Skip to content

Commit 34040fd

Browse files
committed
添加 life 例子
1 parent 595a6f3 commit 34040fd

File tree

6 files changed

+194
-0
lines changed

6 files changed

+194
-0
lines changed

waroot/examples/life-game/.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/output/*.wasm
2+
/output/*.wat

waroot/examples/life-game/README.md

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# 凹语言生命游戏的例子
2+
3+
- 安装凹语言编译器
4+
- 在当前目录执行 `wa run` 命令
5+
6+
## Life简介
7+
8+
Life——全称“Conway's Game of Life”,是一个自运行的小游戏,它模拟了一种虚拟的二维栅格生命,栅格中的每个网格被称为一个细胞,每个细胞有活/死两种状态,并且细胞状态按照以下规则演变:
9+
10+
- 如果一个活细胞周围的活细胞少于2个,那么下一代它将死掉
11+
- 如果一个活细胞周围的活细胞数量为2个或3个,那么它将继续活至下一代
12+
- 如果一个活细胞周围的活细胞数量超过3个,那么下一代它将死掉
13+
- 如果一个死细胞周围的活细胞数量为3个,那么下一代它将复活
14+
15+
这里“周围”的含义是与该细胞邻接的8个细胞,并且代与代之间的状态是整体隔离的,也就是说每个细胞的状态仅取决于它周围的细胞在上一代的状态,游戏的更多详细信息可参阅维基百科:https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life。
16+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<!DOCTYPE html>
2+
3+
<title>凹语言生命游戏</title>
4+
5+
<div style="text-align: center;">
6+
<canvas id="canvas" width="400" height="400"></canvas>
7+
<div>R键:重置; 空格键:暂停</div>
8+
</div>
9+
10+
<script type="text/javascript" src="./life.js"></script>
11+
12+
<script>
13+
let app = new WaApp();
14+
15+
window.onload = () => {
16+
app.init().then((result) => {
17+
app.main();
18+
19+
let keyPausing = false;
20+
let preTimeStamp = 1;
21+
22+
// 初始化
23+
app.LifeInit(400, 400, preTimeStamp);
24+
25+
document.addEventListener('keyup', (event) => {
26+
switch (event.key) {
27+
case ' ':
28+
keyPausing = !keyPausing;
29+
app.LifePausing()
30+
break;
31+
case 'r':
32+
app.LifeInit(400, 400, preTimeStamp);
33+
break;
34+
}
35+
});
36+
37+
let stepAnima = function (timeStamp) {
38+
app.LifeStep();
39+
preTimeStamp = timeStamp;
40+
window.requestAnimationFrame(stepAnima);
41+
}
42+
window.requestAnimationFrame(stepAnima);
43+
})
44+
};
45+
</script>

waroot/examples/life-game/src/life.wa

+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
// 版权 @2023 life 作者。保留所有权利。
2+
3+
import (
4+
"image"
5+
"image/color"
6+
"js/canvas"
7+
"math/rand"
8+
)
9+
10+
global (
11+
width :int = 0
12+
height :int = 0
13+
14+
randSeed :int = 0
15+
pausing :bool = false
16+
17+
cells0 :*image.Gray = nil
18+
cells1 :*image.Gray = nil
19+
cellsRGBA :*image.RGBA = nil
20+
21+
ctxCanvas :canvas.Context2D
22+
)
23+
24+
func LifeInit(w, h, s: int) {
25+
width = w
26+
height = h
27+
randSeed = s
28+
29+
cells0 = image.NewGray(w, h)
30+
cells1 = image.NewGray(w, h)
31+
cellsRGBA = image.NewRGBA(w, h)
32+
33+
rand.Seed(i64(s))
34+
for i := 0; i < width*height; i++ {
35+
if (rand.Int() % 2) != 0 {
36+
cells0.Pix[i] = color.Gray(1)
37+
} else {
38+
cells0.Pix[i] = color.Gray(0)
39+
}
40+
}
41+
}
42+
43+
type DIR struct {
44+
x: int
45+
y: int
46+
}
47+
48+
global dirs = [...]DIR{
49+
{-1, -1}, {0, -1}, {1, -1}, {-1, 0}, {1, 0}, {-1, 1}, {0, 1}, {1, 1},
50+
}
51+
52+
// 生命进化
53+
func lifeEvolve {
54+
for y := 0; y < height; y++ {
55+
for x := 0; x < width; x++ {
56+
live_count := 0
57+
for i := 0; i < 8; i++ {
58+
nx := (x + dirs[i].x + width) % width
59+
ny := (y + dirs[i].y + height) % height
60+
if cells0.Pix[ny*width+nx] != 0 {
61+
live_count++
62+
}
63+
}
64+
65+
if cells0.Pix[y*width+x] != 0 {
66+
switch live_count {
67+
case 2, 3:
68+
cells1.Pix[y*width+x] = color.Gray(1)
69+
default:
70+
cells1.Pix[y*width+x] = color.Gray(0)
71+
}
72+
} else {
73+
switch live_count {
74+
case 3:
75+
cells1.Pix[y*width+x] = color.Gray(1)
76+
default:
77+
cells1.Pix[y*width+x] = color.Gray(0)
78+
}
79+
}
80+
}
81+
}
82+
83+
// 交换 cells0 和 cells1
84+
cells0, cells1 = cells1, cells0
85+
}
86+
87+
func LifeStep {
88+
if cellsRGBA == nil {
89+
return
90+
}
91+
92+
if !pausing {
93+
lifeEvolve()
94+
}
95+
96+
for x := 0; x < width; x++ {
97+
for y := 0; y < height; y++ {
98+
if cells0.Pix[y*width+x] != 0 {
99+
cellsRGBA.SetRGBA(x, y, 0xFF0000FF)
100+
} else {
101+
cellsRGBA.SetRGBA(x, y, 0xFFFFFFFF)
102+
}
103+
}
104+
}
105+
106+
// 绘制到 Canvas
107+
ctxCanvas.PutImageData(
108+
raw(cellsRGBA.Pix), 0, 0, 0, 0,
109+
f32(width), f32(height),
110+
)
111+
}
112+
113+
func LifePausing {
114+
println("pausing:", pausing)
115+
pausing = !pausing
116+
}

waroot/examples/life-game/src/main.wa

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// 版权 @2023 life 作者。保留所有权利。
2+
3+
import "js/canvas"
4+
5+
func main {
6+
println("你好,凹语言!")
7+
8+
c, _ := canvas.QueryCanvas("canvas")
9+
ctx, _ := c.GetContext2D()
10+
ctxCanvas = ctx
11+
}

waroot/examples/life-game/wa.mod

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# 版权 @2023 hello 作者。保留所有权利。
2+
3+
name = "life"
4+
pkgpath = "myapp"

0 commit comments

Comments
 (0)