基于ARM硬件平台的贪吃蛇游戏设计.docx

上传人:b****6 文档编号:5868786 上传时间:2023-01-01 格式:DOCX 页数:15 大小:121.49KB
下载 相关 举报
基于ARM硬件平台的贪吃蛇游戏设计.docx_第1页
第1页 / 共15页
基于ARM硬件平台的贪吃蛇游戏设计.docx_第2页
第2页 / 共15页
基于ARM硬件平台的贪吃蛇游戏设计.docx_第3页
第3页 / 共15页
基于ARM硬件平台的贪吃蛇游戏设计.docx_第4页
第4页 / 共15页
基于ARM硬件平台的贪吃蛇游戏设计.docx_第5页
第5页 / 共15页
点击查看更多>>
下载资源
资源描述

基于ARM硬件平台的贪吃蛇游戏设计.docx

《基于ARM硬件平台的贪吃蛇游戏设计.docx》由会员分享,可在线阅读,更多相关《基于ARM硬件平台的贪吃蛇游戏设计.docx(15页珍藏版)》请在冰豆网上搜索。

基于ARM硬件平台的贪吃蛇游戏设计.docx

基于ARM硬件平台的贪吃蛇游戏设计

设计报告书

——基于ARM硬件平台的贪吃蛇游戏

一、设计题目:

贪吃蛇游戏

二、设计要求:

在LCD屏幕上模拟贪吃蛇游戏。

1.基本要求

(1)起初贪吃蛇蛇身为1节,贪吃蛇按照原来的方向行进直到通过按键改变贪吃蛇的行进方向。

(2)在教学实验箱上的LCD上绘制贪吃蛇,在他们的四周绘制四面墙,蛇身在行进的过程中不能碰到墙壁,碰到则游戏结束,提示是否重新开始,按确认键重新开始。

若能保持不碰墙超过1分钟则完成游戏,提示游戏是否重新开始,按确认键则重新开始。

2.扩展内容

(1)实现贪吃蛇吃食物,食物跟1节蛇身一样大小,其位置随机产生。

在行进的过程中遇到产生的食物会将食物吃掉,蛇身便长一节继续行进。

当蛇身长到6节便提示游戏完成,屏幕显示祝贺,同时整个过程中8段数码管会显示蛇身的长度。

(2)可用键盘按键选择游戏难度,难度通过设定蛇身的行进速度和游戏完成时蛇身的长度确定。

三、设计思路:

(1)验所需硬件:

Embest仿真器,EmbestS3CEV40实验箱,PC机。

(2)本次实验所需用到的硬件模块:

①LCD(用来显示蛇的移动以及吃食物、撞墙等过程);②键盘(用来控制贪吃蛇的上下左右移动以及游戏中的难度,蛇游动的快慢和蛇身体长度的设定);③LED七段数码管(用于显示现阶段蛇身体的节数,初始为一节)。

(3)因为本次实验要使LCD显示,并通过键盘产生中断控制贪吃蛇的运动状态和速度,所以本次实验主要同到的.c文件主要是keyboard.c、lcd.c、8led.c和main.c,主要在这几个文件上进行编程。

本次实验的关键是如何在LCD中显示蛇并且需要实现蛇的移动,以及蛇吃到食物之后如何实现蛇身增长一段以及如何用键盘产生中断控制蛇的移动方向、速度以及蛇身节数的上限值。

四、软件实现:

本次设计主要是考察我们对于LCD模块以及键盘中断的认识程度,刚开始的设想是本次贪吃蛇的设计需要创建两个流程任务,一个是键盘按下控制蛇的移动另一个是键盘没有按下贪吃蛇按照初始状态移动。

任务流程和任务状态切换如下图。

具体的任务流程和任务所要完成的功能如下:

在系统启动后,同时创建两个任务,任务一和任务二。

任务一主要功能是等待键盘消息,有键盘消息的时候判断是什么键盘,并对相应的变量重新赋值。

任务二主要功能是控制并在屏幕上显示蛇的移动,并完成对游戏等级和其他相关参数的记录和显示。

任务一为主任务,在创建任务的时候,赋给它的优先级别比任务二高,所以任务一优先运行,任务二处于就绪状态,因为任务一主要是等待键盘消息,在无键盘消息的时候,任务一被挂起,这时候任务二进入运行状态。

这就是本次设计的主要框架。

程序主流程图:

主任务流程图:

——主要功能是等待键盘消息,有键盘消息的时候判断是那个键按下来控制方向、难度、重启并对相应的变量重新赋值。

 

 

任务二流程图:

——主要功能是控制并在屏幕上显示蛇的移动,并完判定蛇是否撞墙或者撞到自身和其他相关参数的记录和显示。

五、模块功能:

(1)主函数以及初始化:

voidMain(void)

{

sys_init();    /*Initial44B0X'sInterrupt,PortandUART*/

_Link();     /*PrintMiscinfo*/

Test_Keyboard();/*初始化*/

Lcd_Test();

mysnake.life=0;                /*活着*/

mysnake.direction=1;              /*方向往右*/

mysnake.x[0]=100;mysnake.y[0]=100;       /*蛇头坐标*/

mysnake.x[1]=110;mysnake.y[1]=100;

mysnake.node=2;/*蛇身初始为两节*/

myfood.x=50;/*食物初始坐标*/

myfood.y=150;

DrawK();        /*开始画面画围墙生成小蛇*/

GamePlay();       /*玩游戏具体过程*/

}

(2)子程序画围墙:

voidDrawK(void)

{

Lcd_Draw_Box(10,10,310,230,GREEN);/*画围墙*/

}

(3)游戏过程:

voidGamePlay(void)

{

while

(1)                

{

if(reset==1)                /*设定重启按键*/

{

Lcd_Test();

mysnake.life=0;                /*活着*/

mysnake.direction=1;            /*方向往右*/

mysnake.x[0]=100;mysnake.y[0]=100;/*蛇头*/

mysnake.x[1]=110;mysnake.y[1]=100;

mysnake.node=2;

myfood.x=50;

myfood.y=150;

reset=0;

flag=0;

DrawK();           /*开始画面画围墙生成小蛇*/

}

while(!

flag)             /*在没有按键的情况下,蛇自己移动身体*/

{

if(mysnake.life==1)          /*以上两种判断以后,如果蛇死就跳出内循环,重新开始*/

break;

if(myfood.yes==1)           /*需要出现新食物*/

{

myfood.x=randomnumber()%250+10;

myfood.y=randomnumber()%180+10;

while(myfood.x%10!

=0)       /*食物随机出现后必须让食物能够在整格内,这样才可以让蛇吃到*/

myfood.x++;

while(myfood.y%10!

=0)

myfood.y++;

myfood.yes=0;           /*画面上有食物了*/

}

if(myfood.yes==0)           /*画面上有食物了就要显示*/

{

Lcd_Draw_Box(myfood.x,myfood.y,myfood.x+10,myfood.y-10,RED);

}

if(mysnake.node==2)

Digit_Led_Test();

for(i=mysnake.node-1;i>0;i--)     /*蛇的每个环节往前移动,也就是贪吃蛇的关键算法*/

{

mysnake.x[i]=mysnake.x[i-1];

mysnake.y[i]=mysnake.y[i-1];

}

/*1,2,3,4表示右,左,上,下四个方向,通过这个判断来移动蛇头*/

switch(mysnake.direction)

{

case1:

mysnake.x[0]+=10;break;

case2:

mysnake.x[0]-=10;break;

case3:

mysnake.y[0]-=10;break;

case4:

mysnake.y[0]+=10;break;

}

/*从蛇的第四节开始判断是否撞到自己了,因为蛇头为两节,第三节不可能拐过来*/

for(i=3;i

{

if(mysnake.x[i]==mysnake.x[0]&&mysnake.y[i]==mysnake.y[0])

{

GameOver();         /*显示失败*/

mysnake.life=1;

break;

}

}

if(mysnake.x[0]<20||mysnake.x[0]>300||mysnake.y[0]<20||mysnake.y[0]>220)   /*蛇是否撞到墙壁*/

{

GameOver();           /*本次游戏结束*/

mysnake.life=1;          /*蛇死*/

}

if(mysnake.life==1)          /*以上两种判断以后,如果蛇死就跳出内循环,重新开始*/

break;

if(mysnake.x[0]==myfood.x&&mysnake.y[0]==myfood.y)/*吃到食物以后*/

{

Lcd_Draw_Box(myfood.x,myfood.y,myfood.x+10,myfood.y-10,WHITE);//消除食物mysnake.x[mysnake.node]=-20;mysnake.y[mysnake.node]=-20;

/*新的一节先放在看不见的位置,下次循环就取前一节的位置*/

mysnake.node++;    /*蛇的身体长一节*/

myfood.yes=1;    /*画面上需要出现新的食物*/

Digit_Led_Test();  /*led灯显示蛇身节数*/

}    

/*实现贪吃蛇的身体增加*/

Lcd_Draw_Box(mysnake.x[mysnake.node-1],mysnake.y[mysnake.node-1],

mysnake.x[mysnake.node-1]+10,mysnake.y[mysnake.node-1]-10,WHITE);

for(i=0;i

Lcd_Draw_Box(mysnake.x[i],mysnake.y[i],mysnake.x[i]+10,mysnake.y[i]-10,GREEN);

}  

Dly_ms(T);     /*控制移动速度*/

count++;   /*控制贪吃蛇时间*/

if(count==1999)

{

Congra();

mysnake.life=1;

}

if(mysnake.life==1)/*以上两种判断以后,如果蛇死就跳出内循环,重新开始*/

break;

if(con==0xf)break;

if(mysnake.node>=L)  /*控制蛇身长度上限*/

{

Congra();

mysnake.life==1;

}          

switch(con)               /*控制运动方向*/

{                

case3:

 //上

if(mysnake.direction!

=4)/*判断是否往相反的方向移动*/

mysnake.direction=3;

break;

case1:

 //左

if(mysnake.direction!

=2)

mysnake.direction=1;

break;

case2:

 //右

if(mysnake.direction!

=1)

mysnake.direction=2;

break;

case4:

 //下

if(mysnake.direction!

=3)

mysnake.direction=4;

break;

}

}

}

}

(4)游戏结束模块:

voidGameOver(void)

{

Lcd_Clr();/*清屏*/

Lcd_DspAscII8x16(140,120,GREEN-55,"GAMEOVER");/*显示*/

if(con==0xf)/*判断是否按下重启键*/

return0;

}

(5)游戏胜利模块:

voidCongra(void)

{

mysnake.life=1;/*蛇死*/

Lcd_Clr();/*清屏*/

Lcd_DspAscII8x16(140,120,GREEN-55,"WIN!

!

!

!

");/*显示*/

}

(6)延时程序:

{

intii,jj;

if(ms<1)ms=1;

for(ii=0;ii

//for(jj=0;jj<1335;jj++); //16MHz--1ms

//for(jj=0;jj<4006;jj++); //48MHz--1ms

for(jj=0;jj<2670;jj++);  //32MHz--1ms 

}

主程序中:

1、移动功能的实现:

这部分功能是游戏的主体,实现蛇移动的方式是首先擦除蛇尾,擦除的方发是用白色的矩形框覆盖画上蛇尾,蛇尾就变成白色底色不可见,然后从蛇尾开始,依次将蛇每一的坐标给下一节。

例如刚开始蛇是5节,这时候依次把第1节的坐标给第2节;把第2节(即蛇头)的坐标给第3节;把第3四节的坐标给第4节;把第5节的坐标给第4节。

擦除蛇尾和转移坐标这两个顺序不能颠倒。

这时候蛇头的坐标需要在原来第一节的坐标上(X+10,Y-10),这时候还需要判断变量snake.direction的值,根据snake.direction的值补画上蛇头。

蛇的每个环节坐标给下一节;

for(i=mysnake.node-1;i>0;i--)     

/*蛇的每个环节往前移动,也就是贪吃蛇的关键算法*/

{

mysnake.x[i]=mysnake.x[i-1];/把前一点的坐标给后一点/

mysnake.y[i]=mysnake.y[i-1];

}

/*1,2,3,4表示右,左,上,下四个方向,通过这个判断来移动蛇头*/

switch(mysnake.direction)

{

case1:

mysnake.x[0]+=10;break;

case2:

mysnake.x[0]-=10;break;

case3:

mysnake.y[0]-=10;break;

case4:

mysnake.y[0]+=10;break;

}

擦除蛇尾:

Lcd_Draw_Box(mysnake.x[mysnake.node-1],mysnake.y[mysnake.node-1],

mysnake.x[mysnake.node-1]+10,mysnake.y[mysnake.node-1]-10,WHITE);

增长蛇身:

for(i=0;i

{

Lcd_Draw_Box(mysnake.x[i],mysnake.y[i],mysnake.x[i]+10,mysnake.y[i]-10,GREEN);

}  

2、食物的产生:

食物的产生主要还是通过坐标画出一个矩形框,本次实验我的通过一个随机算法来产生一个食物的坐标,来产生食物。

食物的产生主要要注意食物产生之前,我们必须要判断画面上面是已经存在食物,如有已经存在食物了,就不再产生食物,如果食物被蛇吃到了,那就要重新画上食物。

本设计是中设置了变量myfood.yes,在每次循环都依次判断myfood.yes的值,通过myfood.yes的值来判断要不要画出食物。

myfood.yes的值为0表示已存在食物,为1表示需要画食物。

在蛇吃到食物后myfood.yes的值要被赋值1,画完食物后重新赋值,0。

另外还要保证食物不能超出蛇的活动界面,并要保证食物能被蛇吃到,所以需要指定食物坐标的范围,被通过舍去食物坐标个位的方法保证食物坐标是整十,这样就能被蛇吃到。

本设计用一个矩形方框来代表食物,所以通过上面介绍的方法产生食物坐标后,对应在该坐标的位置画上一个矩形方框。

if(myfood.yes==1)      /*需要出现新食物*/

{

myfood.x=randomnumber()%250+10;

myfood.y=randomnumber()%180+10;

while(myfood.x%10!

=0)       /*食物随机出现后必须让食物能够在整格内,这样才可以让蛇吃到*/

myfood.x++;

while(myfood.y%10!

=0)

myfood.y++;

myfood.yes=0;       /*画面上有食物了*/

}

if(myfood.yes==0)  /*画面上有食物了就要显示*/

{

Lcd_Draw_Box(myfood.x,myfood.y,myfood.x+10,myfood.y-10,RED);

}

3、判断蛇是否吃到食物:

判断蛇是否吃到食物的方法比较简单,只要判断蛇头的X、Y坐标是否同时和食物的坐标的X、Y一样。

吃到食物后改变响应的游戏参数,并要让蛇的节数多一节,这时候要让变量mysnake.node加1,并且还要对蛇补画上一节,本设计采用补上蛇头的方法,要注意根据此时蛇的运动方向来确定新蛇头的坐标。

另外,要注意,蛇吃完食物后,要把变量myfood.yes赋值1,以后食物产生子程序能够判断食物已经被蛇“吃到”了,要重新产生食物。

if(mysnake.x[0]==myfood.x&&mysnake.y[0]==myfood.y)/*吃到食物以后*/

{

Lcd_Draw_Box(myfood.x,myfood.y,myfood.x+10,myfood.y-10,WHITE);//消除食物mysnake.x[mysnake.node]=-20;mysnake.y[mysnake.node]=-20;

/*新的一节先放在看不见的位置,下次循环就取前一节的位置*/

mysnake.node++;        /*蛇的身体长一节*/

myfood.yes=1;     /*画面上需要出现新的食物*/

Digit_Led_Test();     /*led灯显示蛇身节数*/

}   

4、判断游戏是否结束的功能实现——有两种情况,游戏将结束

(1)蛇头撞到蛇身

判断蛇是否撞到蛇身的方法可以从蛇头开始依次开始判断蛇头的X、Y轴坐标是不是同时和蛇身的坐标相等,但是其实因为从第四节开始蛇身才有可能被蛇头碰到,为了减轻硬件资源开销,只需要从snake.node-3的那一节开始,逐次逐节开始判断蛇身的X、Y坐标是否同时和蛇头的X、Y坐标一样,一样的话即表明蛇撞到蛇身了,此时游戏结束。

for(i=3;i

{

if(mysnake.x[i]==mysnake.x[0]&&mysnake.y[i]==mysnake.y[0])

{

GameOver();         /*显示失败*/

mysnake.life=1;

break;

}

}

(2)蛇头撞到游戏界面边框

判断蛇是否撞到边框的方法,只要比较蛇头的X、Y坐标是不是同时和边框的X、Y坐标一样,一样的话,即表明蛇撞到边框,游戏结束。

例如:

本设计中以(10,10)为坐标原点的情况下,只要保证蛇头的X坐标在0~310之间(像素点为单位),蛇头Y坐标在0~220之间(像素点为单位),即表示蛇没有撞到边框。

if(mysnake.x[0]<20||mysnake.x[0]>300||mysnake.y[0]<20||mysnake.y[0]>220)   /*蛇是否撞到墙壁*/

{

GameOver();        /*本次游戏结束*/

mysnake.life=1;          /*蛇死*/

}

5、监听键盘动作:

任务通过等待消息而处于挂起状态,当任务接到消息以后,则处于就绪状态,然后开始判断所接受到的这个消息是不是需要处理,如果是执行相应的处理函数,最后,删除所接收到的消息,继续挂起等待下一条消息。

switch(mysnake.direction)

{

case1:

mysnake.x[0]+=10;break;

case2:

mysnake.x[0]-=10;break;

case3:

mysnake.y[0]-=10;break;

case4:

mysnake.y[0]+=10;break;

}

switch(con)                /*控制运动方向*/

{                

case3:

 //上

if(mysnake.direction!

=4)      /*判断是否往相反的方向移动*/

mysnake.direction=3;

break;

case1:

 //左

if(mysnake.direction!

=2)

mysnake.direction=1;

break;

case2:

 //右

if(mysnake.direction!

=1)

mysnake.direction=2;

break;

case4:

 //下

if(mysnake.direction!

=3)

mysnake.direction=4;

break;

}

六、软件的调试修改过程出现的问题及解决方法:

⑴在一开始,我对于一个整体工程的概念还不是很清晰,只有一个大概的了解和初步的构思。

当我通过老师给的一个实例工程之后,我尝试将自己之前编写的一段程序放到main.c中运行,但是有100多个报错。

让自己非常灰心。

解决方法:

通过老师的指导我学会了通过一步一步来,先不把所有程序都写出来而是分块,一块一块的完成,先画出围墙,再画出蛇,然后再实现蛇身的移动,再产生食物等等,通过这个一个个步骤完成了程序的初步构架。

⑵在调用按键中断时,因为一开始不知道怎么使用,导致思路混乱,中断进入后无发转换。

解决方法:

用keyboard.c中的一个标志flag来监控我的按键是否按下,flag为0时,没有键按下,为1时,有键按下。

KEYread中选中我需要的按键,在按键中附一个变量来控制方向、速度、难度以及重启。

⑶在各文件中,没有分清全局变量和局部变量,及全局子函数的调用,乱定义,导致了一大串的语法错误。

解决方法:

通过查书,并认真分清各变量,重新整理定义。

七、设计总结:

⑴软件演示的操作方法:

首先打开EmbestIDE软件,打开我编制的工程Keyboard_Test。

编译连接,下载,并运行,观看LCD屏幕,开始可以看到我这次要演示的课题,几秒钟后显示我的学号、姓名和班级,最后跳入演示界面。

用实验箱上的键盘控制贪吃蛇的运动状态和速度以及控制蛇身节数的上限值。

按第1行第3个键,蛇向上移动;按第2行第2个键,蛇向右运动;按第2行第4个键,蛇向左运动;按第3行第3个键,蛇向下运动;按第4行第1个键,游戏重新启动;按第4行第2个键,增加蛇身节数的上限值(初始上限为4);按第4行第4个键,控制蛇移动的速度依次增快(达到最快之后再按键复位到开始速度)。

⑵设计缺点:

贪吃蛇还是过于生硬,不太

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 经管营销 > 人力资源管理

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1