经过了前面10章漫长的旅程,我们终于要达成我们的目标了:在一个完全由自己实现的计算机平台上运行一个小游戏。这个小游戏要经过编写、编译、转换虚拟机字节码、汇编、生成机器代码等步骤,最终运行在自己搭建的虚拟计算机上。在游戏的运行过程中,每一条指令都是我们亲手编写,每一个细节我们都了如指掌,是我们完完全全地创造了它(虽然需要基于一个硬件虚拟机),这确实是一件非常有意思的事情。
骑手快跑
我这里编写了一个非常简单的小游戏:骑手快跑。在屏幕上会位置随机地出现食物和房子,我们扮演骑手,通过上下左右键控制骑手的行动。骑手需要先取到食物装到车上,然后运送到房子处并领取奖励金,完成配送后骑手又可以继续配送下一单,当奖励金达到一定数额后游戏通关🙄。





实现
main() 先创建游戏实例,然后运行游戏,游戏结束后调用 dispose() 回收内存
1
2
3
4
5
6
7
8
9
10
11
12
13
class Main {
function void main() {
var RunnerGame game;
do RunnerGame.newInstance();
let game = RunnerGame.getInstance();
do game.run();
do game.dispose();
return;
}
}
RunnerGame类是游戏的核心控制类。负责创建骑手、食物、房子等对象;然后监听用户键盘输入、控制游戏逻辑、调整游戏状态、控制屏幕刷新。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
class RunnerGame {
static RunnerGame instance; // 游戏单例
field Runner runner; // 骑手
field Food food; // 食物
field House house; // 配送地点
field int runnerX, runnerY; // 骑手当前位置
field int foodX, foodY; // 食物当前位置
field int houseX, houseY; // 房屋当前位置
field boolean picked; // 是否取到货
field int score; // 挣到的钱
field boolean exit; // 游戏结束
constructor RunnerGame new() {
do Screen.clearScreen();
let runnerX = 230;
let runnerY = 120;
let foodX = 100;
let foodY = 200;
let houseX = 400;
let houseY = 50;
let runner = Runner.new(runnerX, runnerY);
let house = House.new(houseX, houseY);
let food = Food.new(foodX, foodY);
let picked = false;
let score = 0;
let exit = false;
// 底部分数分数记录区
do Screen.drawRectangle(0, 238, 511, 240);
do Output.moveCursor(22,0);
do Output.printString("money: 0");
return this;
}
method void dispose() {
do runner.dispose();
do food.dispose();
do house.dispose();
do Memory.deAlloc(this);
return;
}
function void newInstance() {
let instance = RunnerGame.new();
return;
}
function RunnerGame getInstance() {
return instance;
}
// 开始游戏。用键盘控制骑手位置,先取货,再送货,然后获得奖励
method void run() {
var char key;
while (~exit) {
// 等待按下按键
while ((key = 0) & (~exit)) {
let key = Keyboard.keyPressed();
do Sys.wait(50);
}
do moveRunner(key);
// 等待按键松开
while ((~(key = 0)) & (~exit)) {
let key = Keyboard.keyPressed();
do Sys.wait(50);
}
do updateStatus();
do reDraw();
}
if (exit) {
do Output.moveCursor(1,23);
do Output.printString("Congratulations!");
}
return;
}
method void moveRunner(int key) {
// 左 = 130,上 = 131,右 = 132,下 = 133
if (key = 130) {
let runnerX = runnerX - 20;
} else {
if (key = 131) {
let runnerY = runnerY - 20;
} else {
if (key = 132) {
let runnerX = runnerX + 20;
} else {
if (key = 133) {
let runnerY = runnerY + 20;
}
}
}
}
// 防止越界
if (runnerX > 490) {
let runnerX = 490;
}
if (runnerX < 0) {
let runnerX = 0;
}
if (runnerY > 236) {
let runnerY = 236;
}
if (runnerY < 0) {
let runnerY = 0;
}
do runner.moveTo(runnerX, runnerY);
return;
}
method void updateStatus() {
// 取到食物
if ((Math.abs(foodX - runnerX) < 20) & (Math.abs(foodY - runnerY) < 20)) {
let picked = true;
do runner.setPicked(picked);
}
// 送到食物
if (picked & ((Math.abs(houseX - runnerX) < 20) & (Math.abs(houseY - runnerY) < 20))) {
let score = score + 30;
if (score > 100) {
let exit = true;
}
let picked = false;
do runner.setPicked(picked);
do newRound();
}
return;
}
// 完成一次配送,更新食物和房屋的位置
method void newRound() {
// 更新位置
let foodX = mod(foodX + houseX , 490);
let foodY = mod(foodY + houseY , 236);
let houseX = mod(foodY + houseX , 490);
let houseY = mod(houseX + foodY , 236);
do food.moveTo(foodX, foodY);
do house.moveTo(houseX, houseY);
return;
}
// 重新绘制
method void reDraw() {
do runner.show();
do house.show();
if (picked) {
do food.hide();
} else {
do food.show();
}
do Output.moveCursor(22,7);
do Output.printInt(score);
return;
}
// 补充一个取模的方法
method int mod(int x, int y) {
var int q;
let q = Math.divide(x, y);
return x - (q*y);
}
}
Runner,House,Food类负责表示个字的对象,维护对象位置信息,状态信息,并负责绘制自己的图形。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
class Runner {
field int x, y; // 骑手位置
field int width, height; // 骑手宽高 20*20
field boolen picked; // 是否已取货
// 新创建一个骑手
constructor Runner new(int Ax, int Ay) {
let x = Ax;
let y = Ay;
let width = 20;
let height = 20;
let picked = false;
do show();
return this;
}
method void dispose() {
do Memory.deAlloc(this);
return;
}
// 在screen上展示骑手
method void show() {
do Screen.setColor(true);
do draw();
return;
}
// 抹掉当前在screen上展示的骑手
method void hide() {
do Screen.setColor(false);
do draw();
return;
}
/** 绘制房屋 */
method void draw() {
do Screen.drawRectangle(x, y + 9, x + 19, y + 10);
do Screen.drawCircle(x + 5, y + 15, 4);
do Screen.drawCircle(x + 15, y + 15, 4);
do Screen.drawLine(x + 15, y + 9, x + 15, y + 4);
do Screen.drawLine(x + 11, y + 4, x + 19, y + 4);
if (picked) {
do Screen.drawCircle(x + 4, y + 4, 3);
}
return;
}
method void setPicked(boolean Apicked) {
let picked = Apicked;
return;
}
method void moveTo(int Ax, int Ay) {
do hide(); //先抹掉当前骑手
let x = Ax;
let y = Ay;
do draw(); // 重新画骑手
return;
}
}
class Food {
field int x, y; // 食物位置
field int width, height; // 食物宽高 15*15
// 新创建一个食物
constructor Food new(int Ax, int Ay) {
let x = Ax;
let y = Ay;
let width = 15;
let height = 15;
do show();
return this;
}
method void dispose() {
...
}
// 在screen上展示食物
method void show() {
...
}
// 抹掉当前在screen上展示的食物
method void hide() {
...
}
/** 绘制食物 */
method void draw() {
...
}
method void moveTo(int Ax, int Ay) {
...
}
}
class House {
field int x, y; // 房屋位置
field int width, height; // 房屋宽高 20*20
// 新创建一个房屋
constructor House new(int Ax, int Ay) {
let x = Ax;
let y = Ay;
let width = 20;
let height = 20;
do show();
return this;
}
method void dispose() {
...
}
// 在screen上展示房屋
method void show() {
...
}
// 抹掉当前在screen上展示的房屋
method void hide() {
...
}
/** 绘制房屋 */
method void draw() {
...
}
method void moveTo(int Ax, int Ay) {
...
}
}
广告
