Jumpy Square.svg

슬라이드2.SVG

슬라이드3.SVG

동기 최종본.svg

슬라이드4.SVG

슬라이드7.SVG

슬라이드8.SVG

슬라이드7.SVG

package main

import (
	"fmt"
	"image/color"
	"log"
	"math/rand"

	"github.com/hajimehoshi/ebiten/v2"
	"github.com/hajimehoshi/ebiten/v2/ebitenutil"
	"github.com/hajimehoshi/ebiten/v2/inpututil"
	"github.com/hajimehoshi/ebiten/v2/vector"
)

const (
	screenWidth  = 320
	screenHeight = 480
	birdSize     = 32
	gravity      = 0.81
	jumpSpeed    = -10
	pipeGapSize  = 130
	pipeWidth    = 60
	pipeSpeed    = 1.75
	dt           = 1.0 // Time step for Euler's method
)

type Game struct {
	birdY           float64
	birdVelocity    float64
	pipeX           float64
	upperPipeHeight int
	score           int
	gameOver        bool // check if the game is over or not
	passCheck       bool // check if the bird passed the pipe
}

func (g *Game) Update() error {
	// Press space bar to restart the game
	if g.gameOver {
		if inpututil.IsKeyJustPressed(ebiten.KeySpace) {
			g.reset()
		}
		return nil
	}

	// Euler's method for updating bird's position and velocity
	g.birdVelocity += gravity * dt
	g.birdY += g.birdVelocity * dt

	// Press space bar to make the bird to jump
	if inpututil.IsKeyJustPressed(ebiten.KeySpace) {
		g.birdVelocity = jumpSpeed
	}

	//pipe movement setting
	g.pipeX -= pipeSpeed
	if g.pipeX < -pipeWidth {
		g.pipeX = screenWidth
		g.upperPipeHeight = rand.Intn(screenHeight - pipeGapSize)
		g.passCheck = false
	}

	// score goes up by 1 when the bird passes a pipe
	if !g.passCheck && g.pipeX < screenWidth/2-birdSize/2 {
		g.score++
		g.passCheck = true
	}

	//If the bird crashes with pipe or goes outide the game screen, bird dies
	if g.birdY < 0 || g.birdY+birdSize > screenHeight || g.hitPipe() {
		g.gameOver = true
	}

	return nil
}

func (g *Game) Draw(screen *ebiten.Image) {
	screen.Fill(color.RGBA{R: 135, G: 206, B: 235, A: 255}) // blue blue sky(background)

	// Draw pipe
	pipeColor := color.RGBA{R: 0, G: 128, B: 0, A: 255} //green
	vector.DrawFilledRect(screen, float32(g.pipeX), float32(float64(0)), float32(float64(pipeWidth)), float32(float64(g.upperPipeHeight)), color.Color(pipeColor), false)
	vector.DrawFilledRect(screen, float32(g.pipeX), float32(float64(g.upperPipeHeight+pipeGapSize)), float32(float64(pipeWidth)), float32(screenHeight-float64(g.upperPipeHeight+pipeGapSize)), color.Color(pipeColor), false)

	// Draw bird
	birdColor := color.RGBA{R: 255, G: 255, B: 0, A: 255} // yellow
	vector.DrawFilledRect(screen, float32(float64(screenWidth/2-birdSize/2)), float32(g.birdY), float32(float64(birdSize)), float32(float64(birdSize)), color.Color(birdColor), false)

	// display score
	scoreText := fmt.Sprintf("Score: %d", g.score)
	ebitenutil.DebugPrintAt(screen, scoreText, 10, 10)

	//gmaeover message display
	if g.gameOver {
		ebitenutil.DebugPrint(screen, "Game Over! Press Space to Restart")
	}
}

func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
	return screenWidth, screenHeight
}

func (g *Game) hitPipe() bool {
	return (screenWidth/2+birdSize/2 > g.pipeX && screenWidth/2-birdSize/2 < g.pipeX+pipeWidth) && (g.birdY < float64(g.upperPipeHeight) || g.birdY+birdSize > float64(g.upperPipeHeight+pipeGapSize))
} //check whether the bird hit the pipe(go outside the screen) or not

func (g *Game) reset() {
	g.birdY = screenHeight / 2
	g.birdVelocity = 0
	g.pipeX = screenWidth
	g.upperPipeHeight = rand.Intn(screenHeight - pipeGapSize)
	g.score = 0
	g.gameOver = false
	g.passCheck = false
}

func main() {
	game := &Game{}
	game.reset()
	ebiten.SetWindowSize(screenWidth, screenHeight)
	ebiten.SetWindowTitle("Flappy Bird (made with Go(ebiten))")
	if err := ebiten.RunGame(game); err != nil {
		log.Fatal(err)
	}
}

게임화면.png

게임화면 기둥 추돌사.png

게임 화면.png

점피스퀘어시연.svg

슬라이드9.SVG

슬라이드10.SVG