查看: 3901|回复: 2

【RT1052】千行代码完成坦克大战

[复制链接]
  • TA的每日心情
    开心
    前天 00:29
  • 签到天数: 1187 天

    连续签到: 8 天

    [LV.10]以坛为家III

    25

    主题

    1万

    帖子

    4

    金牌会员

    Rank: 6Rank: 6

    积分
    14305
    最后登录
    2025-9-6
    发表于 2018-12-11 21:18:44 | 显示全部楼层 |阅读模式
    本帖最后由 tobot 于 2018-12-16 19:36 编辑

    发贴要审核,好麻烦。。。不如重新开个帖子
    坦克游戏暂时就到这里,反正活动结束了,我的拖沓症又可以犯了,坦克游戏的最终版本视频:
    http://v.qq.com/x/page/c0813swgdt3.html
    含5个地图,已调整难度,我方坦克炮速为5,敌方炮速为2,坦克速度统一为1,修改了若干bug。项目其实是可以结贴了,但本帖的内容还没完,目前写到了如何画图、坦克如何操作,但坦克的行进原理、子弹的碰撞,胜负的判断等都还没写,有时间再写吧,现在开始下一个游戏开发了。。。




    今天白天有时间,把那个游戏终于做完成了,代码打包放出来。
    昨天在社区里面发了开篇的帖子,本来准备接楼的,结果发现楼层太高,估计也没人想爬,在重新开一贴吧,这个帖子可能会有干货,请大家别插楼。。。
    https://www.nxpic.org.cn/module/forum/thread-615758-1-1.html
    https://www.nxpic.org.cn/module/forum/thread-615763-1-1.html

    mars4zhu兄提到这个游戏的代码是哪里来的,自然是从例程里面ctrl-cctrl-v得来的啊。
    首先,我们要明确要做什么?比如我做的这个游戏:坦克大战。
    1、敌我双方
    对抗的双方都是坦克,其中我方首先得有一个可控的坦克,和一个需要保护的建筑(司令部或者叫做hawk塔)。我方的坦克可以有三次复生的机会,司令部不能移动,且只有一条命(被炮弹打中就game over),但是可以被碾压(这是最早坦克大战的一个bug,不过我觉得很有意思就保留了),我方坦克生命耗尽或者司令部被破坏则游戏失败。
    对方有多辆坦克,随游戏的进展从固定的三个军营逐步出现,我方消灭一定数量的坦克(不一定是全部消灭完),就能过关(我这个游戏就是取胜)。
    2、地形
    地形包括子弹可以经过,但坦克车不能行进的“水面”,可以通过子弹破坏的“砖墙”,不可破坏的“精钢”(这个今天改掉了,后面叙述)。
    昨天设计的地形发现难度太高,敌方坦克出来就是一炮,把砖墙轰开,司令部就敞亮了。今天增加了一个可以反复破坏的元素(昨天的设计是不可破坏的金属块,已改)。
    好吧,说了这么多,和nxp有毛关系?我们话归正题。我这里用的是一个nxp作为主mcu和一块LCD屏作为输出,输入我采用的是串口,由笔记本电脑的键盘作为输入。
    那么回到mars4zhu兄的问题:怎么从例程中取得需要的元素?
    刚才说到,我们想做的事情:
    1、点亮LCD
    2、串口输入
    3、定时动作
    一步步来分析,点亮LCD屏的代码有吗?当然有:
    OK1052-C_32M_sdram\boards\evkbimxrt1050\driver_examples\elcdif\rgb”里面就是,初始化那些东西都不用动,我们要改就只是
    使用1.png
    至于s_frameBuffer[frameBufferIndex]自己想怎么改就怎么改,当然自己灌图的话要考虑空间大小。
    接下来串口输入,我们可以直接使用getchar吗?想也知道不行,在公元2000年以前的古老战棋游戏,由于是轮流进行的(包括比较新一点的英雄无敌),那么用getchar是没问题的,因为对方会等待你的输入,而坦克大战不行,必须是在你操作你坦克的同时,对方坦克也会有动作,那么就需要——中断,OK,串口中断代码有吗?当然也有:
    OK1052-C_32M_sdram\boards\evkbimxrt1050\driver_examples\lpuart\interrupt”,继续拿出我们想要的
    使用2.png

    使用3.png
    好吧,把while里面的东西都拿走,我们用不上串口中断输出,直接用printf就行了;void DEMO_LPUART_IRQHandler(void)也可以只留个壳子,里面掏空,灌点我们自己想要东西进去。
    定时动作,这个就是重头戏了,坦克要前行,子弹要发出,自然是需要定时更新的,那么用什么呢?“OK1052-C_32M_sdram\boards\evkbimxrt1050\driver_examples\pit”来帮忙。
    使用4.png
    老规矩if里面掏空,灌私货。
    这么说了一堆,是不是很简单呢?
    等下再新开一贴,讲游戏结构。

    tank.rar

    235.91 KB, 下载次数: 4, 下载积分: 威望 1

    tank5_Fin(含五个地图).rar

    86.27 KB, 下载次数: 2, 下载积分: 威望 1

    哎...今天够累的,签到来了~
    回复

    使用道具 举报

  • TA的每日心情
    开心
    前天 00:29
  • 签到天数: 1187 天

    连续签到: 8 天

    [LV.10]以坛为家III

    25

    主题

    1万

    帖子

    4

    金牌会员

    Rank: 6Rank: 6

    积分
    14305
    最后登录
    2025-9-6
     楼主| 发表于 2018-12-15 23:12:09 | 显示全部楼层
    接上文
    定义好地形之后
    就开始定义坦克,坦克虽然可以平滑运动,但其实是有固定要求的,也就说当坦克在到达整数格子之前是不能够拐弯、倒车、停止的,定义坦克的状态使用了如下结构:
    typedef struct struct_tank{
            int tankNo;
            uint8_t direct;
            int speed;
            int pos_x;
            int pos_y;
            uint8_t map_x;
            uint8_t map_y;
            bool exist;
            bool ismoving;
            int step;
    }tank;
    其中tankNo表示坦克车的类型,实际上包含了坦克的外观(用另外一个数组定义),direct表示方向,只有上下左右四个,在这里坦克炮口的方向始终和行进方向一致;speed好理解,就是坦克行进的速度,实际上,这也是可以在游戏中接到道具后,进行修改,增加游戏的趣味性,int pos_x、int pos_y,坦克实际位置,这个是没有优化的,其实应该可以用16位整形表示就可以了;uint8_t map_x、uint8_t map_y坦克“实际”应该所处的位置,这里定义行进到整数地图前都还在原位,exist表示坦克是否存在,这是为了消灭敌方坦克时,防止出现“幽灵坦克”而设置的参数,“ismoving”有二义性定义,对于我方坦克来说,就是这个坦克是否正在开动,如之前介绍,行动过程中不允许转弯;如果该值为false,那么可以进一步修改下一步的行动方向,即direct的数值;step是临时记录坦克是否走到正确的位置,其实是可以通过pos_x,pos_y和map_x、map_y计算出来,这里只是为了化简运算,留下多的一个数值,今后优化时是可以去掉的。
    所有的坦克有五个动作:上、下、左、右、开炮,其中开炮是可以在行进过程中进行,所以对于敌方坦克来说,动作始终是流畅的;而对于我方坦克来说,行进过程中的操作实际上是被屏蔽得只剩下开炮了,这也是为什么我们在拍摄游戏动画时,我方坦克操作起来“呆呆”的原因。
    哎...今天够累的,签到来了~
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2025-9-8 17:00 , Processed in 0.091149 second(s), 20 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表