




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、OpenGL实现俄罗斯方块一、 设计思路本程序采用以C+为基础并利用OpenGl库函数的方式实现俄罗斯方块程序,实现俄罗斯方块中正方形,T形,L形,反L形,直线型,Z字形,反Z字形七种形状的变换操作,七种形状的坐标被存储在一个三维数组中,每次随机选择一个形状生成并下落,在下落过程中监听键盘事件。二、 详细设计说明本程序中主要的函数及其作用说明如下:down:定时下落函数,由glutTimerFunc(1000,down,1);函数设置每隔1000毫秒即调用一次该函数,在函数中将方块的所有纵坐标减一个单位。key: 键盘事件监听函数,当键盘上有按键被触发的时候即调用该函数,函数内部支持w,a,s
2、,d四个键的响应,依次代表方向键上,左,右,下,其中w键是用来控制图形变换的,每次按w键时,图形在现有基础上顺时针变换一次。CheckConflict:冲突检测函数,检测方块下一次将要移动的位置是否会碰到已有的方块或者左右两边的墙壁。CheckDelete:每一次方块落到底部之后,调用该函数检查是否有满行,如果有则调用Delete函数删除该行。myDisplay1:作图函数。Change:变换函数,主要是通过计算变换后的图形与之前图形的坐标关系来实现。三、 源代码#include<GL/glut.h>#include<stdlib.h>#include<iostr
3、eam>#include<time.h>#include<windows.h>using namespace std;#define LEFT 'a'#define RIGHT 'd'#define UP 'w'#define DOWN 's'#define START 0/定义图形的范围#define END 19#define SIZE 25/*初始化七个二维数组,即七个块刚开始产生时出现的位置*这里需要考虑的情况是:刚开始产生时有的方块还只露出来一部分,*如果这个时候按了UP键进行变换应该怎么处
4、理*本程序最初设计并不考虑这个问题,一开始即画出方块的各个部分,以后再考虑完善的事情*另外,记录坐标的顺序为从左至右,从上至下*/GLfloat b53=0.0f,0.9f,0.0f,0.8f,0.0f,0.7f,0.0f,0.6f,/1、记录长条四个坐标-0.1f,0.9f,0.0f,0.9f,-0.1f,0.8f,0.0f,0.8f,/2、记录正方形-0.1f,0.9f,-0.2f,0.8f,-0.1f,0.8f,0.0f,0.8f,/3、T字形-0.1f,0.9f,0.0f,0.9f,0.0f,0.8f,0.1f,0.8f,/4、记录Z字形-0.1f,0.9f,0.0f,0.9f,-0.
5、2f,0.8f,-0.1f,0.8f,/5、记录倒Z字形-0.1f,0.9f,-0.1f,0.8f,-0.1f,0.7f,0.0f,0.7f,/6、记录L字形0.0f,0.9f,0.0f,0.8f,-0.1f,0.7f,0.0f,0.7f,/7、记录倒L字形;GLfloat curLoc53;GLint currentBlock=2;/记录当前正在下落的是第几种方块,顺序如上面所示GLint turn7=0;/应该变换成第几种形态了GLfloat xd=0.0f,yd=0.0f;/*这里定义的over是用来判断方块是否到达了不能再往下降的地方,到了则置其为true,否则就修改为false。其中
6、有这样几种情况需要修改over:1、重新生成了一个方块,修改over=false2、方块到大底部,修改over=true*/bool over=false;/记录游戏是否结束bool end=false;int score=0;/设置一个锁,在下降操作时不允许变换,在变换时不允许下降操作,否则将会产生资源竞争/int lock=1;/*定义一个20*20的矩阵来记录当前整个画面中各个小格子的情况,可用来消除满格行矩阵的存储顺序为从左到右,从下到上,包含下标0BLOCKij中i对应的是纵坐标,j对应的是横坐标(这个有点痛苦),但是在消去满格的时候还是不变,只是在用b数组给其赋值时需要反过来*/G
7、Lint BLOCKSIZESIZE;void down(int id);void InitBLOCK();void Change();void CheckDelete();int CheckConflict(int lef_rig=0);void CreateBlocks();void myDisplay1();void key(unsigned char k,int x,int y);void Delete(bool *empty);void show();void show()int i,j;for(i=0;i<4;i+)/函数调用的顺序对错误有一定的影响for(j=0;j<
8、2;j+)cout<<curLocij<<" "cout<<endl;/*初始化方块矩阵,方块是一个上端开口的长方形*/void InitBLOCK()int i,j;for(i=0;i<SIZE;i+)for(j=0;j<SIZE;j+)BLOCKij=0;for(i=0;i<SIZE;i+)BLOCK0i=1;for(i=0;i<4;i+)for(j=0;j<2;j+)curLocij=bcurrentBlockij;void Change()/将图形做变换,采用顺时针旋转的规律(下面的工作即是填入坐标)
9、GLfloat temp00=curLoc00;GLfloat temp01=curLoc01;GLfloat temp10=curLoc10;GLfloat temp11=curLoc11;GLfloat temp20=curLoc20;GLfloat temp21=curLoc21;GLfloat temp30=curLoc30;GLfloat temp31=curLoc31;switch(currentBlock)case 0:/长条switch(turn0)case 0:curLoc00=temp10-0.1f;curLoc01=temp11;curLoc20=temp10+0.1f;
10、curLoc21=temp11;curLoc30=temp10+0.2f;curLoc31=temp11;break;case 1:curLoc00=temp10;curLoc01=temp11+0.1f;curLoc20=temp10;curLoc21=temp11-0.1f;curLoc30=temp10;curLoc31=temp11-0.2f;break;turn0=(turn0+1)%2;break;case 1:/正方形break;case 2:/T字形/cout<<"turn2="<<turn2<<endl;switch(t
11、urn2)case 0:curLoc10=temp20;curLoc11=temp21;curLoc20=temp30;curLoc21=temp31;curLoc30=temp20;curLoc31=temp21-0.1f;break;case 1:curLoc00=temp10-0.1f;curLoc01=temp11;break;case 2:curLoc00=temp10;curLoc01=temp11+0.1f;curLoc10=temp00;curLoc11=temp01;curLoc20=temp10;curLoc21=temp11;break;case 3:curLoc30=t
12、emp20+0.1f;curLoc31=temp21;break;turn2=(turn2+1)%4;break;case 3:/Z字形switch(turn3)case 0:curLoc00=temp10+0.1f;curLoc01=temp11+0.1f;curLoc20=temp10+0.1f;curLoc21=temp11;curLoc30=temp20;curLoc31=temp21;break;case 1:curLoc00=temp10-0.1f;curLoc01=temp11;curLoc20=temp30;curLoc21=temp31;curLoc30=temp30+0.1
13、f;curLoc31=temp31;break;turn3=(turn3+1)%2;break;case 4:/反Z字形switch(turn4)case 0:curLoc00=temp00-0.1f;curLoc01=temp01+0.1f;curLoc10=temp00-0.1f;curLoc11=temp01;curLoc20=temp00;curLoc21=temp01;curLoc30=temp00;curLoc31=temp01-0.1f;break;case 1:curLoc00=temp20;curLoc01=temp21;curLoc10=temp20+0.1f;curLoc
14、11=temp21;curLoc20=temp10;curLoc21=temp11-0.1f;break;turn4=(turn4+1)%2;break;case 5:/L字形switch(turn5)case 0:curLoc00=temp10;curLoc01=temp11;curLoc10=temp10+0.1f;curLoc11=temp11;curLoc20=temp10+0.2f;curLoc21=temp11;curLoc30=temp20;curLoc31=temp21;break;case 1:curLoc00=temp00;curLoc01=temp01+0.1f;curL
15、oc10=temp10;curLoc11=temp11+0.1f;curLoc20=temp10;curLoc21=temp11;curLoc30=temp10;curLoc31=temp11-0.1f;break;case 2:curLoc00=temp20+0.1f;curLoc01=temp21;curLoc10=temp20-0.1f;curLoc11=temp21-0.1f;curLoc20=temp20;curLoc21=temp21-0.1f;curLoc30=temp20+0.1f;curLoc31=temp21-0.1f;break;case 3:curLoc00=temp1
16、0;curLoc01=temp11+0.2f;curLoc10=temp10;curLoc11=temp11+0.1f;curLoc20=temp10;curLoc21=temp11;curLoc30=temp20;curLoc31=temp21;break;turn5=(turn5+1)%4;break;case 6:/反L字形switch(turn6)case 0:curLoc00=temp20-0.1f;curLoc01=temp21+0.1f;curLoc10=temp20-0.1f;curLoc11=temp21;break;case 1:curLoc00=temp00+0.1f;c
17、urLoc01=temp01+0.1f;curLoc10=temp30;curLoc11=temp31+0.2f;curLoc20=temp00+0.1f;curLoc21=temp01;curLoc30=temp20;curLoc31=temp21;break;case 2:curLoc00=temp00-0.1f;curLoc01=temp01-0.1f;curLoc10=temp20;curLoc11=temp21;curLoc20=temp20+0.1f;curLoc21=temp21;curLoc30=temp30+0.1f;curLoc31=temp31;break;case 3:
18、curLoc00=temp20;curLoc01=temp21+0.1f;curLoc10=temp20;curLoc11=temp21;curLoc20=temp30-0.1f;curLoc21=temp31;curLoc30=temp30;curLoc31=temp31;break;turn6=(turn6+1)%4;break;/如果旋转非法(即旋转时碰到墙壁了),则要恢复原来的状态int ret;ret=CheckConflict();if(ret = 1)curLoc00=temp00;curLoc01=temp01;curLoc10=temp10;curLoc11=temp11;c
19、urLoc20=temp20;curLoc21=temp21;curLoc30=temp30;curLoc31=temp31;/*消除满格的一行,在每次over被修改为true的时候都要检查一遍算法思想是从第0行开始依次判断,如果empty为true则将下面的向上,并不是判断一次就移动所有的,而是只移动最近的,将空出来的那一行的empty标记为true*/void Delete(int *empty)int i,j;int pos;while(1)/将上面非空的行填补到下面的空行中i=1;while(i < 20&&emptyi = 0)/为空或者满,都需要将上面的行移下
20、来填充i+;if(i >= 20)break;j=i+1;while(j < 20&&emptyj = -1)j+;if(j >= 20)break;if(j < 20&&emptyj != -1)for(pos=0;pos<20;pos+)BLOCKipos=BLOCKjpos;emptyi=emptyj;emptyj=-1;for(i=1;i<20;i+)if(emptyi != 0)for(j=0;j<20;j+)BLOCKij=0;/*1、判断新生成的图形是否和原来的图形有冲突,有则不能更改,这个地方比较不好实现
21、*2、判断是否有满格的行,有则调用Delete函数去掉*3、这里似乎还要加上判断是否到大顶部,如果到达顶部则游戏结束(可采用监视方框最上*面一行之上那行里面有没有方格,如果有的话则游戏结束)*结束之后就可以把当前方块存入BLOCK中*empty表示一行中方块的数目,-1表示为空行,0表示部分为空,1表示满行*/void CheckDelete()/目前这个函数还只是实现了一个方块到达终点之后是否有能够被删除的行int i,j;int emptySIZE;bool is_needed=false;int count;for(i=0;i<SIZE;i+)emptyi=-1;for(i=0;i
22、<4;i+)double x=(curLoci0+1)*10+0.5;/此处无需注意取值,因为checkConflict已经解决double y=(curLoci1+1)*10+0.5;BLOCK(int)y(int)x=1;/融合for(i=1;i<20;i+)count=0;for(j=0;j<20;j+)if(BLOCKij=1)count+;if(count=20)emptyi=1;/若满格,则可以删除,置为truescore+;/此处计分is_needed=true;else if(count > 0&&count < 20)emptyi
23、=0;if(is_needed=true)/如果有满行则去删除,否则免之Delete(empty);int CheckConflict(int lef_rig)int i;for(i=0;i<4;i+)double x=(curLoci0+1)*10;/注意取值!double y=(curLoci1+1)*10+0.5;/y方向无需注意x=x>0?(x+0.5):(x-0.5);if(lef_rig = 1)int tmpx=(int)x;if(tmpx > 19|tmpx < 0)break;if(BLOCK(int)y(int)x=1) /判断是否发生冲突break
24、;if(i < 4)return 1;return 0;/*关键部分在这里,主要是要判断方块下一次的移动是否合法,本程序通过对b数组所存储的下标是否在BLOCK数组中已经为1来判断,这样,只需要在BLOCK的最外层加一圈1,就不用通过原来的方式来判断方块是否越界*/void key(unsigned char k,int x,int y)int i,ret;if(over = false)if(k=UP)/此处需要改成调用变换图形样式的函数Change();else if(k=DOWN)/后续还要修改,移动到底部过了一段时间之后就不能左右移动了for(i=0;i<4;i+)/需继续
25、添加以1和-1作为哨兵curLoci1-=0.1f;ret=CheckConflict();if(ret = 1)/发生冲突,则将修改复原for(i=0;i<4;i+)curLoci1+=0.1f;over=true;/并且可以生成下一个方块了else if(k=RIGHT)for(i=0;i<4;i+)curLoci0+=0.1f;ret=CheckConflict(1);if(ret = 1)/发生冲突,则将修改复原for(i=0;i<4;i+)curLoci0-=0.1f;else if(k=LEFT)for(i=0;i<4;i+)curLoci0-=0.1f;r
26、et=CheckConflict(1);if(ret = 1)/发生冲突,则将修改复原for(i=0;i<4;i+)curLoci0+=0.1f;if(over=true)CheckDelete();glutPostRedisplay();/调用这个函数可以重新绘图,每次相应消息之后,所有全部重绘/*让方块定时下降*/void down(int id)int i,ret;if(over!=true)for(i=0;i<4;i+)/需继续添加以1和-1作为哨兵curLoci1-=0.1f;ret=CheckConflict();if(ret = 1)/发生冲突,则将修改复原for(i
27、=0;i<4;i+)curLoci1+=0.1f;if(curLoc01 >= bcurrentBlock01)cout<<"Game over,your score is:"<<score*100<<endl;exit(1);over=true;/并且可以生成下一个方块了if(over=true)CheckDelete();glutPostRedisplay();glutTimerFunc(1000,down,1);/作图函数,要修改,利用BLOCK数组绘图void myDisplay1()int i,j;glClear(G
28、L_COLOR_BUFFER_BIT);/不能使用深度测试,否则画出来的图形很乱for(i=0;i<20;i+)for(j=0;j<20;j+)if(BLOCKij=1)glColor3f(0.0f,1.0f,0.0f);/用蓝色画图glRectf(j/10.0f-1.0f,i/10.0f-1.0f,j/10.0f-1.0f+0.1f,i/10.0f-1.0f+0.1f);glLineWidth(2.0f);glBegin(GL_LINE_LOOP);glColor3f(0.0f,0.0f,0.0f);glVertex2f(j/10.0f-1.0f,i/10.0f-1.0f);glVertex2f(j/10.0f-1.0f+0.1f,i/10.0f-1.0f);glVertex2f(j/10.0f-1.0f+0.1f,i/10.0f-1.0f+0.1f);glVertex2f(j/10.0f-1.0f,i/10.0f-1.0f+0.1f);glEnd();glFlush();if(over = false)for(i=0;i<4;i+)glColor3f(0.0f,1.0
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 手工具产品安全性与风险评估考核试卷
- 船舶拆除工程进度控制与调度管理考核试卷
- 沿海货物运输协同发展考核试卷
- 油气田开发过程中的节能减排措施考核试卷
- 橡胶在电子设备散热中的应用考核试卷
- 电力系统稳定性分析与优化控制考核试卷
- 稀土金属矿选矿厂工艺参数优化与调整考核试卷
- 航天器地面模拟试验与测试考核试卷
- 海外度假别墅租赁及海外旅游服务合同
- 海上石油作业平台应急通信设施租赁与安全保障服务协议
- 《中国海洋大学》课件
- 教育行业媒体宣传服务合同
- 第四单元 资本主义制度的确立 说课课件-高一下学期统编版(2019)必修中外历史纲要下
- 2024-2025学年七年级地理下册 7.4 俄罗斯课时1说课稿 (新版)新人教版
- 【专项训练】相似三角形五大模型+训练(共45题)(原卷版+解析)
- 国家助学贷款还款救助归档材料清单
- 11《杠杆》教学设计-2023-2024学年科学五年级下册人教鄂教版
- 2024版恶性肿瘤患者营养治疗指南解读课件
- 2025届四川省成都市高三上学期毕业班摸底测试(零诊)历史试题(解析版)
- YB 4019-1991 轻烧菱镁矿粉化学分析方法柠檬酸法测定轻烧菱镁矿粉的活性
- 路面工程练习试卷1(共101题)
评论
0/150
提交评论