main.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. // Copyright 2017 The Ebiten Authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package main
  15. import (
  16. "bytes"
  17. "fmt"
  18. "image"
  19. _ "image/png"
  20. "github.com/hajimehoshi/ebiten/v2"
  21. "github.com/hajimehoshi/ebiten/v2/ebitenutil"
  22. rplatformer "github.com/hajimehoshi/ebiten/v2/examples/resources/images/platformer"
  23. "github.com/hajimehoshi/ebiten/v2/inpututil"
  24. )
  25. const (
  26. // Settings
  27. screenWidth = 960
  28. screenHeight = 540
  29. )
  30. var (
  31. leftSprite *ebiten.Image
  32. rightSprite *ebiten.Image
  33. idleSprite *ebiten.Image
  34. backgroundImage *ebiten.Image
  35. )
  36. func init() {
  37. // Preload images
  38. img, _, err := image.Decode(bytes.NewReader(rplatformer.Right_png))
  39. if err != nil {
  40. panic(err)
  41. }
  42. rightSprite = ebiten.NewImageFromImage(img)
  43. img, _, err = image.Decode(bytes.NewReader(rplatformer.Left_png))
  44. if err != nil {
  45. panic(err)
  46. }
  47. leftSprite = ebiten.NewImageFromImage(img)
  48. img, _, err = image.Decode(bytes.NewReader(rplatformer.MainChar_png))
  49. if err != nil {
  50. panic(err)
  51. }
  52. idleSprite = ebiten.NewImageFromImage(img)
  53. img, _, err = image.Decode(bytes.NewReader(rplatformer.Background_png))
  54. if err != nil {
  55. panic(err)
  56. }
  57. backgroundImage = ebiten.NewImageFromImage(img)
  58. }
  59. const (
  60. unit = 16
  61. groundY = 380
  62. )
  63. type char struct {
  64. x int
  65. y int
  66. vx int
  67. vy int
  68. }
  69. func (c *char) tryJump() {
  70. // Now the character can jump anytime, even when the character is not on the ground.
  71. // If you want to restrict the character to jump only when it is on the ground, you can add an 'if' clause:
  72. //
  73. // if gopher.y == groundY * unit {
  74. // ...
  75. c.vy = -10 * unit
  76. }
  77. func (c *char) update() {
  78. c.x += c.vx
  79. c.y += c.vy
  80. if c.y > groundY*unit {
  81. c.y = groundY * unit
  82. }
  83. if c.vx > 0 {
  84. c.vx -= 4
  85. } else if c.vx < 0 {
  86. c.vx += 4
  87. }
  88. if c.vy < 20*unit {
  89. c.vy += 8
  90. }
  91. }
  92. func (c *char) draw(screen *ebiten.Image) {
  93. s := idleSprite
  94. switch {
  95. case c.vx > 0:
  96. s = rightSprite
  97. case c.vx < 0:
  98. s = leftSprite
  99. }
  100. op := &ebiten.DrawImageOptions{}
  101. // Use a smaller scale than 1 to shrink the image.
  102. op.GeoM.Scale(0.5, 0.5)
  103. op.GeoM.Translate(float64(c.x)/unit, float64(c.y)/unit)
  104. screen.DrawImage(s, op)
  105. }
  106. type Game struct {
  107. gopher *char
  108. }
  109. func (g *Game) Update() error {
  110. if g.gopher == nil {
  111. g.gopher = &char{x: 50 * unit, y: groundY * unit}
  112. }
  113. // Controls
  114. if ebiten.IsKeyPressed(ebiten.KeyA) || ebiten.IsKeyPressed(ebiten.KeyArrowLeft) {
  115. g.gopher.vx = -4 * unit
  116. } else if ebiten.IsKeyPressed(ebiten.KeyD) || ebiten.IsKeyPressed(ebiten.KeyArrowRight) {
  117. g.gopher.vx = 4 * unit
  118. }
  119. if inpututil.IsKeyJustPressed(ebiten.KeySpace) {
  120. g.gopher.tryJump()
  121. }
  122. g.gopher.update()
  123. return nil
  124. }
  125. func (g *Game) Draw(screen *ebiten.Image) {
  126. // Draws Background Image.
  127. op := &ebiten.DrawImageOptions{}
  128. op.GeoM.Scale(0.5, 0.5)
  129. screen.DrawImage(backgroundImage, op)
  130. // Draws the Gopher.
  131. g.gopher.draw(screen)
  132. // Show the message.
  133. msg := fmt.Sprintf("TPS: %0.2f\nPress the space key to jump.", ebiten.ActualTPS())
  134. ebitenutil.DebugPrint(screen, msg)
  135. }
  136. func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
  137. return screenWidth, screenHeight
  138. }
  139. func main() {
  140. ebiten.SetWindowSize(screenWidth, screenHeight)
  141. ebiten.SetWindowTitle("Platformer (Ebitengine Demo)")
  142. if err := ebiten.RunGame(&Game{}); err != nil {
  143. panic(err)
  144. }
  145. }