mirror of
				https://github.com/hajimehoshi/ebiten.git
				synced 2025-10-31 11:46:23 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			169 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			169 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // 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.
 | |
| 
 | |
| 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{}
 | |
| 	// Use a smaller scale than 1 to shrink the image.
 | |
| 	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.KeyArrowLeft) {
 | |
| 		g.gopher.vx = -4 * unit
 | |
| 	} else if ebiten.IsKeyPressed(ebiten.KeyD) || ebiten.IsKeyPressed(ebiten.KeyArrowRight) {
 | |
| 		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.ActualTPS())
 | |
| 	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 (Ebitengine Demo)")
 | |
| 	if err := ebiten.RunGame(&Game{}); err != nil {
 | |
| 		panic(err)
 | |
| 	}
 | |
| }
 | 
