单片机论坛

 找回密码
 立即注册

QQ登录

只需一步快速开始

搜索
查看: 1234|回复: 2
打印 上一主题 下一主题
收起左侧

开源Proteus仿真全民贪吃蛇 附LPC2124 ARM7程序分析与设计报告

[复制链接]
跳转到指定楼层
楼主
这是我以前做的一个贪吃蛇课程设计
此次的ARM7最小系统的课程设计是基于LPC2124以及LCD-CSTN20GG0906N7CUN6和按键电路采用ISIS7 Professional软件自行搭建电路里面带有实验报告里面都是干货希望源家有用


目录
1.              课程设计内容
2.              课程设计目的
3.              背景知识
4.              工具/准备工作              4
5.              设计步骤与方法              4
5.1.              步骤1在Proteus仿真软件上设计电路图              4
5.2.              步骤2画蛇              5
5.2.1.              步骤1.1蛇的产生              5
5.3.              步骤3食物的产生              6
5.4.              步骤4蛇的移动              7
5.4.1.              步骤1.1按键的扫描              8
5.5.              步骤5蛇节的增长              8
5.5.1.              步骤1.1号断蛇是否吃到食物              9
5.5.2.              步骤1.2速度的增长              10
5.6.              步骤6游戏是否结束              10
5.7.              步骤7LCDHDG12864L-6的显示              11
5.8.              步骤8重新开始与暂停按键              11
6.              设计结果及分析              12
7.              设计结论              13
8.              问题及心得体会              13
9.              对本设计过程及方法手段的改进建议              14
10.             参考文献              14
11.              课程设计评价(教师)              14

全民贪吃蛇


1.
     课程设计内容

此次ARM7最小系统的课程设计是基于LPC2124以及LCD-CSTN20GG0906N7CUN6和按键电路采用ISIS 7 Professional软件自行搭建电路本系统的特点切阅高成本低并且耗能小等特点

2.     课程设计目的

此次课程设计的主要目的是让我们提高代码的熟练度以及发挥自主创新将平时上课学到的理论知识与实验知识相结合让我嵌arm7芯片以及ISIS 7 Professional仿真模拟器更为了解

  • 熟练掌握向量中断IRQ的初始化和对中断的处理过程
  • 熟练掌握定时器的控制和使用方法
  • 熟练掌握C语言的使用原理及编程方法
  • 熟练掌握仿真电路图的连接方法
  • 熟练掌握两个不同的液晶显示器的显示控制原理及编程方法

3.     背景知识
ARM处理器的三大特点是耗电少功能强16位/32位双指令集和献伙伴众多
1体积小低功耗低成本高阅ܣ
2支持Thumb16位/ARM32位双指令集能很好的兼容8位/16位器件
3大量使用寄存器指令执行速度更快
4大多数数据操作都在寄存器中完成
5寻址方式灵活简单执行效率高
6指令长度固定

设计原理贪吃蛇游戏是一款经典的游戏既简单又耐玩通过控制蛇头方向吃蛋使得蛇变长从而获取积分用游戏把子上下左右控制蛇的方向寻找吃的东西每吃一口就能得到一定的积分而且蛇的身子会越吃越长身子越长玩的难度就越大不能碰墙不能咬到自己的身体更不能咬自己的尾停等到了一定的分数就能过关然后继续玩下一关


4.     工具/准备工作
  • CodeWarrior project file软件
  • ISIS 7 Professional软件
  • 了解Proteus仿真软件和ARM编程软件的使用方法
  • 了解ARM7芯片的编程方法
5.   设计步骤与方法

5.1.步骤1在Proteus仿真软件上设计电路图

5.2.步骤2画蛇

由于采用的是LCD-CSTN20GG0906N7CUN6首先根据其数据手册对该LCD进行绘画先写入命令对其进行写操作WR_CMD(0xBC);WR_DATA(0); WR_DATA(00);       WR_DATA(00); 然后写入命令WR_CMD(0x75);意为写入x轴后接x轴的具体数据以及x轴的最大值紧接判入WR_CMD(0x15);意为写入y轴后接y轴的具体数据以及y轴的最大值

void snake_display(int x,int y)

{

              int i,j;      

      WR_CMD(0xBC); WR_DATA(0); WR_DATA(00);  WR_DATA(00);         

     WR_CMD(0x75);   

     WR_DATA(x);    WR_DATA(63);

     WR_CMD(0x15);

     WR_DATA(y);    WR_DATA(95);   

     WR_CMD(0x5c);            

        for(j=0;j<1;j++)  {

                      for(i=0;i<1;i++){

                          WR_DATA(0xf8);//0xff   

                          WR_DATA(0x00); }}

}

5.2.1步骤1.1蛇的产生

首先创建一个蛇的结构体Point该结构体内存储了蛇的xy坐标以及蛇的长群蛇的方向然后通过rand函数产生随机数存在Snake的xy中即蛇的初始位置是随机模然后再通过snake_init()函数中对蛇进行初始化然后通过循环在snake_display(int x,int y)函数中把蛇画出来

  1. void snake_init()
  2. {
  3.               int i;
  4.               snake_state();
  5.     Snake.x[0] = rand()%62;
  6.     Snake.y[0] = rand()%95;   
  7.    Snake.x[1] = Snake.x[0]+1;
  8.     Snake.y[1] = Snake.y[0];   
  9.     Snake.x[2] = Snake.x[1] +1;
  10.     Snake.y[2] = Snake.y[0] ;
  11.        Snake.num = 3;   
  12.     for(i=0;i<Snake.num;i++)
  13.                   snake_display(Snake.x[i],Snake.y[i]);
  14.     }
复制代码

5.3.步骤3食物的产生

首先创建一个食物的结构体point在该结构体的基础上定义一个数组food_map,通过这个结构体对地图进行修改该结构体内存储了食物的xy坐标以及食物的长度然后通过rand函数产生随机数保存在food_map中即食物的出现位置是随机模然后再通过food_init()函数中对食物进行初始化然后通过循环在food_display(int x,int y)函数中把食物画出来食物的画法与步骤一中蛇的画法是一样模只不过食物的颜色是黄色蛇的颜色是红色便于确希

当蛇吃了一定数量的食物保通过调用食物产生函数重新产生新的食物以保证食物的存在性


  1. void food()
  2. {
  3.               int i;
  4.               if(create_food==1)
  5.               {
  6.                             for(i=food_long;i<food_long+8;i++)
  7.                             {
  8.                                           food_map[i].x=rand()%62;
  9.                                           food_map[i].y=rand()%93;
  10.                             }
  11.                             food_long+=8;
  12.                             create_food=0;
  13.               }
  14. }
  15. void food_map_init()
  16. {
  17.               int i;
  18.               food();
  19.               for(i=0;i<food_long;i++)
  20.                             food_display(food_map[i].x,food_map[i].y);            
  21. }
复制代码


5.4.步骤4蛇的移动

若相应方向的按键被按下则蛇就会往相应的方向移动首先要把蛇之前走过的痕迹擦掉擦掉的函数如同画蛇把颜色数据改为背景色即可然后将蛇从最后个节点向前一个节点移动这是蛇的最核心算法最后通过switch case判断哪一个按键被按下然后对蛇返方向即Snake.direction进行修改蛇的移动函数放在中断中看发生中断都会重新画蛇蛇的移动即言来的蛇尾巴擦掉然后根据新的坐标重新画蛇当按键没有被按下保蛇会按照上一次按下按键的方向去移动初始化时默认向右


  1. void snake_move()
  2. {            
  3.               char i;
  4.               int j;
  5.               if(flag==1)
  6.               {
  7.                             Snake.num++;            
  8.                             flag=0;
  9.               }
  10.                             for(i=0;i<food_long;i++)
  11.                             food_display(food_map[i].x,food_map[i].y);
  12. clear_snake(Snake.x[Snake.num-1],Snake.y[Snake.num-1]);
  13.    for(i = Snake.num - 1; i > 0; i--) // 将蛇从最后个节点向前一个节点移动
  14.    {
  15.                             Snake.x[i] = Snake.x[i - 1];
  16.         Snake.y[i] = Snake.y[i - 1];
  17.    }
  18.        snake_state();         
  19.     switch(Snake.direction)
  20.     {                     
  21.         case 1:
  22.              Snake.x[0] -=1 ;
  23.             break;
  24.         case -1:
  25.                                    Snake.x[0] +=1 ;
  26.             break;
  27.         case 2:
  28.             Snake.y[0] -=1 ;
  29.             break;
  30.         case -2:
  31.             Snake.y[0] +=1 ;
  32.             break;
  33.     }
  34.       for(i=0;i<Snake.num;i++)
  35.                   snake_display(Snake.x[i],Snake.y[i]);
  36. }
复制代码


5.4.1. 步骤1.1按键的扫描

通过IOxPIN来确定按键是否按下由于按键接在P1.20-P1.23,因此是I01PIN通过读取各个按键的状态封装在snake_state函数里如果上键按下Snake.directio则相应为上Snake.direction是蛇的结构体Point里的成员用于确定蛇的方向其余方向的设置同上

void snake_state()

{

              if(!(IO1PIN&key_w))Snake.direction=1;//上

              else if(!(IO1PIN&key_s))Snake.direction= -1;//下

              else if(!(IO1PIN&key_a))Snake.direction= 2;//左

              else if(!(IO1PIN&key_d))Snake.direction= -2;//右

}


5.5.步骤5蛇节的增长

如果蛇吃到了食物此时的蛇应该变长即Snake.num++在蛇尾的部分添加一个点即可新的一节先放在看不见的位置,下次循环就取前一节的位置先把这条蛇擦掉然后重新画蛇

if(flag==1)

              {

                            Snake.num++;            

                            flag=0;

              }


5.5.1. 步骤1.1号断蛇是否吃到食物

如果蛇返xy坐标与food_map中的任一xy坐标均相等则得蛇已经吃了食物此币对食物进行擦除食物的擦除与食物的绘画是一样模只需要把颜色改为跟背景色一样即可


  1. void checkeat()
  2. {
  3.               int i,time;
  4.               for(i=0;i<food_long;i++)
  5.               {              if((Snake.y[0]==food_map[i].y)&&(Snake.x[0]==food_map[i].x)||(Snake.y[Snake.num-1]==food_map[i].y)&&(Snake.x[Snake.num-1]==food_map[i].x))
  6.                             {            
  7.                                                         flag=1;            
  8.                                                         NUMBER++;//
  9.                                                         if(NUMBER>9)NUMBER=0;
  10.                                                         print_score();//
  11.                                                         eat++;
  12.                                                         if(eat%4==0)create_food=1;
  13.                                                         if(eat%1==0)
  14.                                                         {
  15.                                                                       LEVEL++;
  16.                                                                       speed-=50;
  17.                                                                       if(LEVEL>9)LEVEL=0;
  18.                                                                       print_level();
  19.                                                         }                                         
  20.                                                         clear_food(food_map[i].x,food_map[i].y);
  21.                                                         food_map[i].x=NULL;
  22.                                                         food_map[i].y=NULL;
  23.                                                         break;                           
  24.                             }
  25.               }
  26. }
复制代码


5.5.2. 步骤1.2速度的增长

当蛇吃到一定数量的食物保游返等级会增加此时蛇的速度就会变快通过改变定时器的定时背可以实现即改变T0TR首先设定一个speed变量值当游分的LEVEL++保speed的导小此时定时器的定时背会缩短会从而导致蛇的移动扫描变快因而实现了蛇的速度的变化

void speed_change()

{

              T0PR = speed;

}



5.6.步骤6游戏是否结束

如果蛇跑出了LCD所能表示的段即蛇头小于0或者大于63蛇尾小于0或者大于95则视为死亡游方束显示结束计如果需要继续游戏则按下重新开始按钮

如果蛇头撞上了身体的我方ڣ通过循环来一节节地进行判希则视为死亡游方束显示结束计如果需要继续游戏则按下重新开始按钮

反之游戏继续

如果最终的等级大于9级则游戏胜利显示胜利计如果需要继续游戏则按下重新开始按钮


  1. void snake_life()
  2. {
  3.               int i;
  4.               if(Snake.x[0] < 0 || Snake.x[0] > 63 || Snake.y[0] < 0 || Snake.y[0] >95)               die=1;
  5.               for(i=3;i<Snake.num;i++)
  6.                 {
  7.      if(Snake.x[i]==Snake.x[0]&&Snake.y[i]==Snake.y[0])
  8.      {
  9.                    die=1;
  10.                    break;
  11.     }  
  12.   }
  13. }
复制代码


5.7.步骤7LCDHDG12864L-6的显示

该LCD用来显示游返名称制作人等级以及分数根据该LCD的数据手册首先写入的是y的值然后写入x的值来确定所写的字的位置先写字的上半部分然后重新写入y的值x的值不变再写字的下半部分

看蛇吃到食物保分数就会增印分数的字模放在一个数组里通过下标调用显示当蛇吃到了一定数量的食物之后等级就会随之增加等级的字模也是放在一个数据里通过下标调用显示

void print_level()

{

              int j;

   WR_CMD1(0xb0+4);

   WR_CMD1(0x10);

   WR_CMD1(0x00+51);

  for(j=0;j<8;j++)

  {

   WR_DATA1(number[LEVEL][0][j]);

  }

              WR_CMD1(0xb0+5);

              WR_CMD1(0x10);

              WR_CMD1(0x00+51);

  for(j=0;j<8;j++)

  {

   WR_DATA1(number[LEVEL][1][j]);

  }            

}


5.8.步骤8重新开始与暂停按键

设置两个按键用于重新开始游戏以及暂停游戏

重新开始游戏保先把显示蛇的LCD的屏幕清屏把成绩与等级初始化为0然后对游返所有问重新进行初始化

暂停按钮的实现十分简单只需要把蛇的移动方向设为空即可此保蛇换再移动若要继续游戏则按我方向键继续

void button()

{

              if(!(IO1PIN&restart))

              {

                            LCD_clear();

                            die=0;

                            LEVEL=0;

                            NUMBER=0;

                            flag=0;

                            eat=0;

                            speed=1000;

                            Snake.direction=NULL;

                            food_map_init();

                            create_food=0;

                            score_init();

                            print_score();

                            print_level();

                            snake_init();

                            food_map_init();              

              }

              if(!(IO1PIN&stop))

              {

                            Snake.direction=NULL;

              }

}

6.     设计结果及分析

设计结果蛇的出现位置与食物的出现位置都是随机的当按下相对应的按键保蛇会往那个方向走当蛇吃到食物保分数会增印当蛇吃到一定数量的食物保等级和速度也会随之增加当食物少于一定数量保会出现新的食物当等级达到9保游方束玩家胜出播放胜利计如果蛇吃到自身或者撞到墙则游方束玩家失败播放失败计

设计分析这个程序的关键是表示蛇的图我及蛇的移动用一个小矩形表示蛇的一节身体身体每长一节增加一个矩形块如果不按任何键蛇自行在当前方向上前移当游戏者按了有效的方向键后蛇头朝着指定的方向移动一步移动一节身体所以当按了有效的方向键后先确定蛇返位置然后蛇身体随着蛇头移动图形的实现是从蛇返新位置开始画出蛇这时原来蛇的位置和新蛇的位置差一个单位所以看起来蛇会多一节身体所以将蛇的最后一节用背景色覆盖食物的出现和消失也是画矩形块和覆盖矩形块


7.     设计结论

经过奋战我的课程设计终于完成了在没有做课程设计以前觉得课程设计只嵌嵌入式最小系统这门课程所学知识的单纯总结但是通过这次做课程设计发现自己的看法有点太片面课程设计不仅嵌前面所学知识的一种检验而且也嵌自己能力的一种提高通过这次课程设计使我明白了自己原来知识贡较欠缺自己要学习的东西固多以前老是觉得自己什么东西都会什么东西都懂有点眼高手低通过这次课程设计我才明白学习是一个长期积累的过程在以后的工作生活中都应该不断的学习提高自己的知识和综合素质

8.   问题及心得体会

通过这次的课程设计让我学到了许多编程知识提高运用C语言解决导问题的能力巩固了C语言的语法规则掌握和理解还提高了自学以及查阅资料的能力我发现只有理论知识是不够模仅仅运用课上所学无法编导问题导手行过程与预想不一致经常会出现bug还因为在仿真软件中用错了一个LCD显示器导致程序卡在那里好几天当时用的是12864-6一直卡在蛇的显示非常考验我的逻辑与耐心后来一怒之下换了一个实验中讲过的LCD显示器必须把所学的理论知识和自身的导相结希在编程中我学到了许多编程知识还学会了如何去看器件的数据手册在导时程中我遇到许多困难例如蛇的头部与食物的检测问题蛇的移动与显示问题蛇的转向问题食物的随机生成问题等等我通过在网上搜集资料与自己的分析最后终于完成了这个游戏

9.     对本设计过程及方法手段的改进建议

在食物的设计的方面可以放上带道具的食物使蛇吃完后具有保护穿墙等特种功能而且难度逐渐变难还有设计一些习物当蛇撞到习物时死亡



全部资料51hei下载地址

Snake.zip (281.7 KB, 下载问: 17)


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾段博腾段博 腾讯朋友腾讯朋友
收藏收藏 转播转播 分享分享 分享淘帖 顶 踩
回复

使用道具 举报

沙发
admin 发表于 2018-12-3 02:04 | 只看该作者
好资料51黑有你更精彩!!!
回复

使用道具 举报

板凳
牛牛ko 发表于 2019-4-23 19:52 来自手机 | 只看该作者
学习了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|单片机论坛 |51Hei单片机16群 联系QQ:125739409;际交流QQ群7344883

Powered by 单片机教程网

快速回复 返回顶部 返回列表
ձһhƬձƵ ձƵɫwww ձƵ:ɫ