// Copyright 2017 The Ebiten Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // +build example package main import ( "bytes" "fmt" "image" _ "image/png" "github.com/hajimehoshi/ebiten/v2" "github.com/hajimehoshi/ebiten/v2/ebitenutil" rplatformer "github.com/hajimehoshi/ebiten/v2/examples/resources/images/platformer" "github.com/hajimehoshi/ebiten/v2/inpututil" ) const ( // Settings screenWidth = 960 screenHeight = 540 ) var ( leftSprite *ebiten.Image rightSprite *ebiten.Image idleSprite *ebiten.Image backgroundImage *ebiten.Image ) func init() { // Preload images img, _, err := image.Decode(bytes.NewReader(rplatformer.Right_png)) if err != nil { panic(err) } rightSprite = ebiten.NewImageFromImage(img) img, _, err = image.Decode(bytes.NewReader(rplatformer.Left_png)) if err != nil { panic(err) } leftSprite = ebiten.NewImageFromImage(img) img, _, err = image.Decode(bytes.NewReader(rplatformer.MainChar_png)) if err != nil { panic(err) } idleSprite = ebiten.NewImageFromImage(img) img, _, err = image.Decode(bytes.NewReader(rplatformer.Background_png)) if err != nil { panic(err) } backgroundImage = ebiten.NewImageFromImage(img) } const ( unit = 16 groundY = 380 ) type char struct { x int y int vx int vy int } func (c *char) tryJump() { // Now the character can jump anytime, even when the character is not on the ground. // If you want to restrict the character to jump only when it is on the ground, you can add an 'if' clause: // // if gopher.y == groundY * unit { // ... c.vy = -10 * unit } func (c *char) update() { c.x += c.vx c.y += c.vy if c.y > groundY*unit { c.y = groundY * unit } if c.vx > 0 { c.vx -= 4 } else if c.vx < 0 { c.vx += 4 } if c.vy < 20*unit { c.vy += 8 } } func (c *char) draw(screen *ebiten.Image) { s := idleSprite switch { case c.vx > 0: s = rightSprite case c.vx < 0: s = leftSprite } op := &ebiten.DrawImageOptions{} op.GeoM.Scale(0.5, 0.5) op.GeoM.Translate(float64(c.x)/unit, float64(c.y)/unit) screen.DrawImage(s, op) } type Game struct { gopher *char } func (g *Game) Update() error { if g.gopher == nil { g.gopher = &char{x: 50 * unit, y: groundY * unit} } // Controls if ebiten.IsKeyPressed(ebiten.KeyA) || ebiten.IsKeyPressed(ebiten.KeyLeft) { g.gopher.vx = -4 * unit } else if ebiten.IsKeyPressed(ebiten.KeyD) || ebiten.IsKeyPressed(ebiten.KeyRight) { g.gopher.vx = 4 * unit } if inpututil.IsKeyJustPressed(ebiten.KeySpace) { g.gopher.tryJump() } g.gopher.update() return nil } func (g *Game) Draw(screen *ebiten.Image) { // Draws Background Image op := &ebiten.DrawImageOptions{} op.GeoM.Scale(0.5, 0.5) screen.DrawImage(backgroundImage, op) // Draws the Gopher g.gopher.draw(screen) // Show the message msg := fmt.Sprintf("TPS: %0.2f\nPress the space key to jump.", ebiten.CurrentTPS()) ebitenutil.DebugPrint(screen, msg) } func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) { return screenWidth, screenHeight } func main() { ebiten.SetWindowSize(screenWidth, screenHeight) ebiten.SetWindowTitle("Platformer (Ebiten Demo)") if err := ebiten.RunGame(&Game{}); err != nil { panic(err) } }