课程设计报告
俄罗斯方块游戏设计
班 级 : 20090612
学 号 : 2009061222
姓 名 : 白磊磊
教师评语:
教师签名:
2012 年 10 月
课程设计题目
俄罗斯方块游戏设计
本次课程设计的主要内容是通过前 7 次小实验中完成的任务和
实现的功能,综合前面的设计方法,利用学到的 LCD 接口控制、
中断控制以及所学的 I/O 控制的知识等完成本次所选课设实验题
目,最后实现方块的移动、变形、随机出现下一个方块、触屏控
制、停止、嵌套、消行、计分等功能。同时通过这次课设的体会
应该总结到自己在实践中的不足和欠缺的知识,及时的补充和完
善个人能力,争取学到更多的知识和实践技能。
主要内容
1.ADS1.2开发环境
2.博创UP-NETARM3000 嵌入式开发平台
3.配置Windows XP系统的PC
4.串口线
采用的工具方法
2012.9.4 - 2012.9.11
系统需求分析与总体设计、模块设计
进度安排
2012.9.13-2012.9.27
系统模块具体编码实现
2012.10.11
系统测试
1、 武俊鹏、张国印、姚爱红、赵国冬,基于 ARM 的嵌入式系
统设计实验与实践教程,清华大学出版社 2011
参考资料
2、 吴学智,基于 ARM 的嵌入式系统设计与开发,人民邮电出
版社 2007
1. 题目
俄罗斯方块游戏设计
2. 系统简介
2.1 基于对游戏的理解,这款游戏的设计基本要求有:
1、游戏界面友好、合理。
2、按指定的键开始游戏,随机产生方块并自动下移。
3、按指定的键可以暂停游戏,再次按指定键可重新开始游戏。
4、用指定键变换方块角度。
5、用指定键实现左右移动方块,一个键实现左移,另一个键实现右移。
6、用指定键实现方块快速下移。
7、系统能正确判断满行,并对已填充满的行进行消行、加分。
2.2 系统的功能要求如下按:
1、按“Numlock”开始游戏,随机产生方块并自动下移。
2、按“/”键可以暂停游戏,再次按键可以重新开始游戏。
3、按“8”键可以转换方块角度。
4、按“7”,“9”键实现向左移动和向右移动。
5、按“5”键实现方块加速下移。
3. 系统设计
3.1 设计思路
1、整个游戏界面的设计和控制:设计一个左边是 10X15 带有框格的游戏界面。右边为
控制和显示的界面,控制自然是绘制按键图案通过触屏控制来实现。显示的内容有下一
个、得分、等级。
2、方块的移动:通过定时器 1,改变方块左右移动的地址来实现。
3、方块的变形:可通过运用三维数组储存 7 个基本方块形状,采用线性代数转置的思
路改变数组的值并设定一个缓冲区储存变形数组,从而达到变形的效果。
4、方块的碰边处理:可设定一个二维数组储存整个游戏界面的最新状态,有方块为 1,
没有则为 0,并在游戏界面周围填入 1,通过方块地址和数组位置的转换判定数组中的
值,为 0 说明可走,为 1 则不能通过,从而实现碰边处理。
5、方块的嵌套:与碰边原理相似,可将之前停止在界面上的方块位置对应数组中的值
赋 1,再判断当前方块每一列的最后一行下是否有方块,实现方块嵌套。
6、方块的随机出现:当方块到达最后一行或嵌套成功后停止,然后将出现下一个方块,
- 1 -
可通过定时器取出末尾三位实现随机性。并在右边显示下一个方块的形状。
7、消行处理:可通过处理界面的数组判断某一行是否都为 1,若为 1 就执行将上一行赋
给下一行,并将第一行赋为 0。
8、分数的计算:当方块到达最后一行或嵌套成功后停止分数加 1 分。
3.2 程序流程图
- 2 -
4. 系统实现
4.1 游戏界面函数
本实验设计了一个左边是 10X15 附有框图的游戏界面。右边为控制和显示的界面,
分别有显示下一个方块、开始、结束、暂停、变形、向左、向右、向下、得分、等级等,
//设定背景颜色 API
//填充底色
Set_Color (GUI_BLACK);
Draw_VLine(10+i*32, 15, 480);//竖线
Draw_HLine(15+j*30, 10, 10+11*32); //横线
Set_Color (GUI_WHITE);
//填充白色
Fill_Rect(10+i*32+1, 15+j*30+1,10+(i+1)*32-1,15+(j+1)*30-1);//填充
并且大部分都是通过触屏控制达到相应效果。
void InitGame ()
{
U16 i,j;
Set_Color(GUI_BLACK);
Fill_Rect(0,0,639,479);
for(i=0;i<10;i++) //10x15 格游戏界面
for(j=0;j<15;j++)
{
}
}
(&CHINESE_FONT16);
Set_Color(GUI_GREEN);
Set_Font
Disp_String (CN_start"下一个"CN_end,9*40-20,27);
Disp_String (CN_start"得分"CN_end,9*40-10,5*40+10);
Disp_String (CN_start"等级"CN_end,13*40-10,5*40+10);
Set_Color(GUI_YELLOW);
Fill_Rect(14*40-20,20,15*40,60);//开始、结束、暂停
Fill_Rect(14*40-20,80,15*40,120);
Fill_Rect(14*40-20,140,15*40,180);
Fill_Circle(12*40,7*40+20,40);//变形、左、右、下
Fill_Circle(10*40,9*40+10,40);
Fill_Circle(14*40,9*40+10,40);
Fill_Circle(12*40,11*40-10,40);
Set_BkColor(GUI_YELLOW);
Set_Color(GUI_RED);
Disp_String (CN_start"开始"CN_end,14*40-5,35);
Disp_String (CN_start"结束"CN_end,14*40-5,95);
Disp_String (CN_start"暂停"CN_end,14*40-5,155);
Disp_String (CN_start"变形"CN_end,12*40-15,8*40-30);
Disp_String (CN_start"向左"CN_end,10*40-15,9*40);
Disp_String (CN_start"向右"CN_end,14*40-15,9*40);
Disp_String (CN_start"向下"CN_end,12*40-15,11*40-20);
- 3 -
4.2 绘制方块
本实验设计了一个三维数组储存 7 个基本方块形状,通过数组里的数将方块绘制出
来。
void Drawblock(U16 x,U16 y,U16 z)
{
U16 i,j;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
{
if(block[z][j][i]==1)
Set_Color (GUI_BLACK);
//边框黑色
Draw_VLine(x+i*32+1, y+j*30+1, y+(j+1)*30-1);//竖线
Draw_VLine(x+(i+1)*32-1, y+j*30+1, y+(j+1)*30-1);
Draw_HLine(y+j*30+1, x+i*32+1, x+(i+1)*32-1); //横线
Draw_HLine(y+(j+1)*30-1, x+i*32+1, x+(i+1)*32-1);
Set_Color (GUI_BLUE);
Fill_Rect(x+i*32+2, y+j*30+2,x+(i+1)*32-2,y+(j+1)*30-2);//填充
//填充蓝色
{
}
}
}
4.3 随机生成一个方块
通过取出定时器 1 的后三位值产生随机值,为了避免取值时间几乎相同随机值相近
的概率比较高,所以采用当前时刻取出的值与之前相加达到更加随机的效果。并且在右
侧下一个中显示出来。
void Creatblock()
{
U16 i,j;
s=rTCNTO1&0x0007+s;//取随机值 &0x0007 取后三位
for(i=0;i<4;i++)
for(j=0;j<4;j++)
{
if(block[ZZ][j][i]==1)
{
Set_Color (GUI_BLACK);
Fill_Rect(9*40+i*32+1, 40+j*30+1,9*40+(i+1)*32-1,40+(j+1)*30-1);
//填充黑色
}
}
k=s&0x0007;
Drawblock(9*40,40,k);
Delay(50);
}
- 4 -
4.4 左移函数
当触屏界面的左移按键被按下后,方块首地址的列坐标将会减去 32 像素达到左移
一格的效果。根据取出的最左列坐标判断方块是否到达游戏界面最左侧,若不是继续左
移,若是则不再左移。右移、下降同理,下面不再赘述。
void Goleft()
{
U16 m,n,k;
k=getL(); m=k/10;n=k%10;
//time1 stop
rTCON=(0<<8);
if(oldblock[(m*30+i*30+YY)/30][((n+1)*32+XX)/32-1]==1);
else
{
}
}
4.5 变形函数
Eraseblock(XX,i*30+YY,ZZ);
XX=XX-32;//左移
Drawblock(XX,i*30+YY,ZZ);
//擦除
rTCON=(1<<11)|(0<<9)|(1<<8);//time1 start
利用转置的原理,达到方块变形的效果。先将当前数组的值赋给缓冲区,然后再将
缓冲区转置变形后的值再赋给原来的数组。
void Changeblock(U16 z)
{
U16 a,b;
rTCON
Eraseblock(XX,i*30+YY,ZZ);
for(a=0;a<4;a++)
=(0<<8);
//time1 stop
//擦除
for(b=0;b<4;b++)
{
block[7][a][b]=block[z][a][b];//赋值缓冲区
}
for(a=0;a<4;a++)
for(b=0;b<4;b++)
{
block[z][a][b]=block[7][3-b][a];//装置变形
}
rTCON=(1<<11)|(0<<9)|(1<<8);//time1 start
Drawblock(XX,i*30+YY,ZZ);
//画出新方块
}
4.6 消行函数
- 5 -
当游戏界面数组的某一行全为 1 时,则进入消行,分数加 10 并将上一行赋给下一
行,第一行清 0。若有 n 行全为 1 时,分数加 10*n 并将上 n 行赋给下 n 行,第一行到第
n 行清 0。
void ok(U8
{
//y:要判断的行的坐标
y)
U16 i,j,n,temp1=1,temp2=0;
U8 flag_H;
for(i=4;i>0;i--)
{
for(j=1;j<11;j++)
{
temp1=temp1&&oldblock[y-i][j];//检测是否可以消行
temp2=temp2||oldblock[0][j];//检测是否到第一行
if(temp1==1)
}
{
n++;//可以消的行数
flag_H=1;//进入消行标志位
}
if(temp2==1) Gameover(); //游戏结束
}
if(flag_H==1)//进入消行
{
flag_H=0;
for(j=0;j<4;j++)
for(i=1;i<11;i++)
{oldblock[y-j][i]=oldblock[y-j-n][i];//把上一行赋给下一行
oldblock[n-j][i]=0;
fen=fen+10*n;}
}
5. 实验成果截图
游戏界面图(截图 1)
- 6 -