20、再做一个游戏

我不打算用分屏了。一旦屏幕中的敌人和硬币多了以后,游戏就会变慢,屏幕会来回滚动,结果会很糟糕。

不用分屏,不用担心速度变慢(每帧中增加更多的游戏逻辑)

增加背景音乐和音效,游戏中我们在增加敌人和硬币。当和硬币碰撞的时候使用sfx音效,当和敌人碰撞的时候使用噪声音效。

我用yy-chr画了一些简单的敌人,定义了一些metasprite对象。我们使用 nes screen tool这样做非常简单,我从另外一个metasprite复制粘贴到tile里。

原版使用数组方式定义所有内容应该是个很好的选择,但是6502太慢了。快的方法是使用大量小于256字节的char数组,就像下面这样。

#define MAX_COINS 16

unsigned char coin_x [MAX_COINS];

unsigned char coin_y [MAX_COINS];

unsigned char coin_active [MAX_COINS];

unsigned char coin_room [MAX_COINS];

unsigned char coin_actual_x [MAX_COINS];

我优化了对象初始化的代码,每行只放一个数组来让代码的执行速度更快。6502每次只能执行一个指针。如果使用单行的数组的赋值会让执行速度慢5倍。

这样是不推荐的方式

coin_y[index] = pointer[index2];

应该这样做

temp1 = pointer[index2]; //获取1byte的数据

coin_y[index] = temp1;

信不信由你,这样写的话代码的执行效率可以更快。如果我们想要游戏中有多个移动的物体和屏幕滚动,必须要考虑优化代码。

因此,每帧我会检查每个对象是否在屏幕的显示范围内,并将它们标记为活动。只在活动状态时候移动它们,检查碰撞是否有效,并在活动的时候绘制到屏幕上显示。

check_spr_objects() 这个方法用来检查每个对象是否显示再屏幕上,当结果是true标记它们是活动的。

现在,跟移动相关的代码变得简单了,小怪根据主角的位置改变移动方向。后面我会考虑优化这部分。

目前,我使用 y=0xff作为 “不存在”(TRUN_OFF),因此,不显示敌人是通过将它们的Y改为0xff的方式处理的。当然还有其他方式,不过我这么做的。我们不需要敌人从屏幕下方跳进来,就让他能正常运行。

我做的另一件事是添加游戏状态。暂停模式,改变音乐,动作停止,通过修改颜色亮度让屏幕变暗。如果所有的颜色都设置只会让颜色变暗一点点。

color_emphasis(COL_EMP_NORMAL);

color_emphasis(COL_EMP_DARK);

https://github.com/nesdoug/25_Platform5/blob/master/platformer5.c

https://github.com/nesdoug/25_Platform5

https://nesdoug.com/2018/09/11/21-finished-platformer/

好了,现在基本上能工作了,后面要做完整的关卡了。