最近偶然看到一个Go语言库,口号喊出“一个超级简单(dead simple)的2D游戏引擎”,好奇点开了它的官网。

官网上已经有很多可以在线体验的小游戏了(利用WASM技术)。例如曾经风靡一时的2048:
当然只要安装了Go,我们也键入下面的命令本地运行这个游戏:
$ go run -tags=example github.com/hajimehoshi/ebiten/v2/examples/2048@latest
还有童年《俄罗斯方块》:

有14年左右让无数人疯狂的《Flappy Bird》(或许称为Flappy Gopher更贴切一点😀):
这些瞬间让我产生了极大的兴趣。简单浏览一下文档,整体感觉下来,虽然与成熟的游戏引擎(如Cocos2dx,DirectX,Unity3d等)相比,ebiten功能还不算丰富。但是麻雀虽小,五脏俱全。ebiten的API设计比较简单,使用也很方便,即使对于新手也可以在1-2个小时内掌握,并开发出一款简单的游戏。更妙的是,Go语言让ebitengine实现了跨平台!
接下来的3篇文章,我会介绍ebitengine这个库。对于游戏引擎来说,只介绍它的API用法似乎有点纸上谈兵。恰好我想起之前看到一个《外星人入侵》的小游戏,刚好可以拿来练手。那请大家坐稳扶好,我们出发咯。
ebitengine 要求Go版本 >= 1.15。使用go module下载这个包:
$ go get -u github.com/hajimehoshi/ebiten/v2
游戏开发第一步是将游戏窗口显示出来,并且能在窗口上显示一些文字。先看代码:
- package main
-
- import (
- "log"
-
- "github.com/hajimehoshi/ebiten/v2"
- "github.com/hajimehoshi/ebiten/v2/ebitenutil"
- )
-
- type Game struct{}
-
- func (g *Game) Update() error {
- return nil
- }
-
- func (g *Game) Draw(screen *ebiten.Image) {
- ebitenutil.DebugPrint(screen, "Hello, World")
- }
-
- func (g *Game) Layout(outsideWidth, outsideHeight int) (screenWidth, screenHeight int) {
- return 320, 240
- }
-
- func main() {
- ebiten.SetWindowSize(640, 480)
- ebiten.SetWindowTitle("外星人入侵")
- if err := ebiten.RunGame(&Game{}); err != nil {
- log.Fatal(err)
- }
- }
使用命令go run运行该程序:
$ go run main.go
我们会看到一个窗口,标题为外星人入侵,并且左上角显示了文字Hello,World:
现在我们来分析使用ebiten开发的游戏程序的结构。
首先,ebiten引擎运行时要求传入一个游戏对象,该对象的必须实现ebiten.Game这个接口:
- // Game defines necessary functions for a game.
- type Game interface {
- Update() error
- Draw(screen *Image)
- Layout(outsideWidth, outsideHeight int) (screenWidth, screenHeight int)
- }
ebiten.Game接口定义了ebiten游戏需要的3个方法:Update,Draw和Layout。
Update:每个tick都会被调用。tick是引擎更新的一个时间单位,默认为1/60s。tick的倒数我们一般称为帧,即游戏的更新频率。默认ebiten游戏是60帧,即每秒更新60次。该方法主要用来更新游戏的逻辑状态,