Golang游戏引擎日记(03.电子游戏Pong)

制作一个简单的游戏,直接看代码注释:

game.go:

package engine

import (
	SDL "github.com/veandco/go-sdl2/sdl"
)

const thickness = 15
const paddleH = 100.0

type Vector2 struct {
	X float32
	Y float32
}

type Game struct {
	MWindow     *SDL.Window
	MRenderer   *SDL.Renderer
	MIsRunning  bool
	MPaddlePos  Vector2
	MBallPos    Vector2
	MBallVel    Vector2
	MPaddleDir  int
	MTicksCount uint32
}

//初始化引擎
func (g *Game) Initialize() bool {
	var err error
	//初始化SDL
	if err = SDL.Init(SDL.INIT_VIDEO); err != nil {
		SDL.Log("Unable to initialize SDL: %s", SDL.GetError())
		return false
	}
	//创建窗口
	if g.MWindow, err = SDL.CreateWindow(
		"golang游戏引擎(电子游戏Pong)",
		100,
		100,
		1024,
		768,
		0,
	); err != nil {
		SDL.Log("Failed to create window: %s", SDL.GetError())
		return false
	}
	//创建渲染
	if g.MRenderer, err = SDL.CreateRenderer(
		g.MWindow,
		-1,
		SDL.RENDERER_ACCELERATED|SDL.RENDERER_PRESENTVSYNC,
	); err != nil {
		SDL.Log("Failed to create renderer: %s", SDL.GetError())
		return false
	}
	//初始化参数
	g.MPaddlePos.X = 10.0
	g.MPaddlePos.Y = 768.0 / 2.0
	g.MBallPos.X = 1024.0 / 2.0
	g.MBallPos.Y = 768.0 / 2.0
	g.MBallVel.X = -200.0
	g.MBallVel.Y = 235.0
	//保持运行
	g.MIsRunning = true
	return true
}

//引擎循环
func (g *Game) RunLoop() {
	for {
		g.ProcessInput()
		g.UpdateGame()
		g.GenerateOutput()

		if !g.MIsRunning {
			break
		}
	}
}

func (g *Game) ProcessInput() {
	var event SDL.Event
	for {
		if event = SDL.PollEvent(); event == nil {
			break
		} else {
			switch event.GetType() {
			case SDL.QUIT: //窗口关闭退出
				g.MIsRunning = false
			}
		}
	}

	//获取所有按键状态
	state := SDL.GetKeyboardState()
	//按下ESC退出
	if state[SDL.SCANCODE_ESCAPE] == 1 {
		g.MIsRunning = false
	}

	//检测按键WS
	g.MPaddleDir = 0
	if state[SDL.SCANCODE_W] == 1 {
		g.MPaddleDir -= 1
	}
	if state[SDL.SCANCODE_S] == 1 {
		g.MPaddleDir += 1
	}
}

func (g *Game) UpdateGame() {
	//等待
	for {
		//SDL_TICKS_PASSED(A, B)
		if uint32(SDL.GetTicks64()) > g.MTicksCount+16 {
			break
		}
	}
	//增量时间
	deltaTime := float32((uint32(SDL.GetTicks64()) - g.MTicksCount)) / 1000.0
	if deltaTime > 0.05 {
		deltaTime = 0.05
	}
	//总时间
	g.MTicksCount = uint32(SDL.GetTicks64())
	//更新球拍位置
	if g.MPaddleDir != 0 {
		g.MPaddlePos.Y += float32(g.MPaddleDir) * 300.0 * deltaTime
		if g.MPaddlePos.Y < (paddleH/2.0 + thickness) {
			g.MPaddlePos.Y = paddleH/2.0 + thickness
		} else if g.MPaddlePos.Y > (768.0 - paddleH/2.0 - thickness) {
			g.MPaddlePos.Y = 768.0 - paddleH/2.0 - thickness
		}
	}
	//更新球位置
	g.MBallPos.X += g.MBallVel.X * deltaTime
	g.MBallPos.Y += g.MBallVel.Y * deltaTime

	diff := g.MPaddlePos.Y - g.MBallPos.Y
	if diff < 0 {
		diff = -diff
	}
	//碰墙检测(左边离开屏幕和右边碰撞)
	if diff <= paddleH/2.0 && g.MBallPos.X <= 25.0 && g.MBallPos.X >= 20.0 && g.MBallVel.X < 0.0 {
		g.MBallVel.X *= -1.0
	} else if g.MBallPos.X <= 0.0 {
		g.MIsRunning = false
	} else if g.MBallPos.X >= (1024.0-thickness) && g.MBallVel.X > 0.0 {
		g.MBallVel.X *= -1.0
	}
	//碰墙检测(顶部和底部)
	if g.MBallPos.Y <= thickness && g.MBallVel.Y < 0.0 {
		g.MBallVel.Y *= -1
	} else if g.MBallPos.Y >= (768-thickness) && g.MBallVel.Y > 0.0 {
		g.MBallVel.Y *= -1
	}
}

func (g *Game) GenerateOutput() {
	//背景颜色
	g.MRenderer.SetDrawColor(
		0,   // R
		0,   // G
		255, // B
		255, // A
	)
	//清屏
	g.MRenderer.Clear()

	//墙体颜色
	g.MRenderer.SetDrawColor(
		200, // R
		200, // G
		200, // B
		255, // A
	)
	//顶部墙
	wall := &SDL.Rect{
		X: 0,
		Y: 0,
		W: 1024,
		H: thickness,
	}
	g.MRenderer.FillRect(wall)
	//底部墙
	wall.Y = 768 - thickness
	g.MRenderer.FillRect(wall)
	//右边墙
	wall.X = 1024 - thickness
	wall.Y = 0
	wall.W = thickness
	wall.H = 1024
	g.MRenderer.FillRect(wall)
	//绘制球拍
	paddle := &SDL.Rect{
		X: int32(g.MPaddlePos.X),
		Y: int32(g.MPaddlePos.Y - paddleH/2),
		W: thickness,
		H: int32(paddleH),
	}
	g.MRenderer.FillRect(paddle)
	//绘制球
	ball := &SDL.Rect{
		X: int32(g.MBallPos.X),
		Y: int32(g.MBallPos.Y),
		W: thickness,
		H: thickness,
	}
	g.MRenderer.FillRect(ball)
	//交换缓冲区
	g.MRenderer.Present()
}

//引擎销毁
func (g *Game) Shutdown() {
	g.MRenderer.Destroy()
	g.MWindow.Destroy()
	SDL.Quit()
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值