凹语言开发案例分享: Pong 游戏

查看 28|回复 1
作者:chai2010   
WASM-4 是一款使用 WebAssembly 实现的复古风格游戏机。凹语言作为国内首个面向 WebAssembly 设计的通用编程语言在 syscall/wasm4 内置标准库对 WASM4 平台提供了支持,从而为使用凹语言开发小游戏的用户提供最佳体验。
我们以一个简单的乒乓球游戏作为例子,看看如何开发 WASM4 游戏。

配置环境
安装凹语言 v0.15 以上的版本,或者通过以下 Go 命令安装最新的 wa 命令行:
$ go install wa-lang.org/wa@master
然后通过以下命令创建一个 hello 新目录工程:
$ wa init -wasm4
$ tree hello/
hello/
├── README.md
├── src
│   └── main.wa
└── wa.mod
2 directories, 3 files
命令行环境进入 hello 目录后,输入wa run可以在浏览器打开查看效果。
程序整体骨架
直接修改src/main.wa文件:
import (
        "math/rand"
        "strconv"
        "syscall/wasm4"
)
const (
        width  = 5
        height = 15
        ballSize   = 5
        screenSize = int(wasm4.SCREEN_SIZE)
)
// 玩家 1(右边): 上下方向键
// 玩家 2(左边): ED 键对应上下键, 左右方向键盘控制
global game = NewPongGame(true) // 双人游戏
#wa:export update
func Update {
        game.Input()
        game.Update()
        game.Draw()
}
Update 函数会以每秒 60 帧的频率被调用,其中分布出来游戏的输入、更新游戏状态并显示。
定义游戏对象
在对象中保存的游戏状态:
// 游戏的状态
type PongGame :struct {
        isMultiplayer: bool // 多人游戏
        ballX:         int  // 球的水平位置
        ballY:         int  // 球的竖直位置
        dirX:          int  // 球的方向
        dirY:          int  // 球的方向
        y1:            int  // 左边挡板位置
        y2:            int  // 右边挡板位置
        score1:        int  // 玩家分数
        score2:        int  // 玩家分数
}
// 构建一个新游戏对象
func NewPongGame(enableMultiplayer: bool) => *PongGame {
        return &PongGame{
                isMultiplayer: enableMultiplayer,
                ballX:         screenSize / 2,
                ballY:         screenSize / 2,
                dirX:          1,
                dirY:          1,
                y1:            screenSize / 2,
                y2:            screenSize / 2,
                score1:        0,
                score2:        0,
        }
}
主要是乒乓球、挡板等位置和方向信息。
处理输入键
通过不同方向键盘分别控制 2 个挡板的移动。
func PongGame.Input {
        // 第 1 个玩家
        if pad := wasm4.GetGamePad1(); pad&wasm4.BUTTON_UP != 0 && this.y1 > 0 {
                this.y1 -= 2
        } else if pad&wasm4.BUTTON_DOWN != 0 && this.y1+height  0 {
                        this.y2 -= 2
                } else if pad&wasm4.BUTTON_RIGHT != 0 && this.y2+height  0 {
                        this.y2 -= 2
                } else if pad&wasm4.BUTTON_DOWN != 0 && this.y2+height
根据键盘更新挡板的位置信息。
更新游戏的状态
每秒钟 60 帧的速度更新状态:
func PongGame.Update {
        // 更新球的方向
        if dirNow := this.paddleCollision(); dirNow != 0 {
                wasm4.Tone(2000, 5, 100, wasm4.TONE_PULSE2|wasm4.TONE_MODE2)
                if rand.Int()%2 != 0 {
                        this.dirX = dirNow
                        this.dirY = -1
                } else {
                        this.dirX = dirNow
                        this.dirY = 1
                }
        }
        // 更新球的位置
        this.ballX += this.dirX
        this.ballY += this.dirY
        // 检查球是否反弹
        if this.ballY > screenSize || this.ballY  screenSize {
                wasm4.Tone(1000, 5, 100, wasm4.TONE_PULSE2|wasm4.TONE_MODE2)
                if this.ballX  screenSize {
                        this.score1 += 1 // 右边玩家失球
                }
                // 重置球位置
                this.ballX = screenSize / 2
                this.ballY = screenSize / 2
                this.dirX = -this.dirX
        }
}
同时判断失球和得分情况。以下是碰撞判断:
func PongGame.paddleCollision => int {
        if this.ballX  this.y2 {
                return 1
        }
        if this.ballX+ballSize > screenSize-width &&
                this.ballY  this.y1 {
                return -1
        }
        return 0
}
球碰到和超出边界表示失球得分。
如何画乒乓球和挡板
WASM4 的调色板寄存器一次只能存储 4 种颜色,可以通过更改这一寄存器来引入新的颜色。以下是 WASM4 默认的配色表:

WASM4 内置的绘图函数不直接访问这个颜色表寄存器,而是访问同样能够存储 4 个颜色的 DRAW_COLORS 寄存器来指定对应的颜色表索引。可以通过wasm4.SetDrawColors函数完成。
绘制场景的代码:
func PongGame.Draw {
        wasm4.SetDrawColors(0, 4)
        wasm4.SetDrawColors(1, 0)
        wasm4.Text(strconv.Itoa(this.score1), 85, 0)
        wasm4.Text(strconv.Itoa(this.score2), 70, 0)
        wasm4.Rect(screenSize/2, 0, 2, screenSize)
        wasm4.SetDrawColors(0, 2)
        wasm4.SetDrawColors(1, 3)
        wasm4.Oval(this.ballX, this.ballY, ballSize, ballSize)
        wasm4.Rect(0, this.y2, width, height)
        wasm4.Rect(screenSize-width, this.y1, width, height)
}
到此乒乓球游戏就完成了。
完整代码
完整代码大约 150 行: https://github.com/wa-lang/wa/tree/master/waroot/examples/w4-pong
在线体验地址: https://wa-lang.org/wa/w4-pong/
如果你也是游戏爱好者,也可以试试用凹语言开发自己的游戏了。
Borch   
乍一看以为是 rust...
您需要登录后才可以回帖 登录 | 立即注册

返回顶部