OpenGL實(shí)現(xiàn)俄羅斯方塊源代碼.doc
《OpenGL實(shí)現(xiàn)俄羅斯方塊源代碼.doc》由會(huì)員分享,可在線閱讀,更多相關(guān)《OpenGL實(shí)現(xiàn)俄羅斯方塊源代碼.doc(15頁(yè)珍藏版)》請(qǐng)?jiān)谘b配圖網(wǎng)上搜索。
1、 OpenGL實(shí)現(xiàn)俄羅斯方塊 一、 設(shè)計(jì)思路 本程序采用以C++為基礎(chǔ)并利用OpenGl庫(kù)函數(shù)的方式實(shí)現(xiàn)俄羅斯方塊程序,實(shí)現(xiàn)俄羅斯方塊中正方形,T形,L形,反L形,直線型,Z字形,反Z字形七種形狀的變換操作,七種形狀的坐標(biāo)被存儲(chǔ)在一個(gè)三維數(shù)組中,每次隨機(jī)選擇一個(gè)形狀生成并下落,在下落過(guò)程中監(jiān)聽鍵盤事件。 二、 詳細(xì)設(shè)計(jì)說(shuō)明 本程序中主要的函數(shù)及其作用說(shuō)明如下: down:定時(shí)下落函數(shù),由glutTimerFunc(1000,down,1);函數(shù)設(shè)置每隔1000毫秒即調(diào)用一次該函數(shù),在函數(shù)中將方塊的所有縱坐標(biāo)減一個(gè)單位。 key: 鍵盤事件監(jiān)聽函數(shù),當(dāng)鍵盤上有按鍵被觸發(fā)的
2、時(shí)候即調(diào)用該函數(shù),函數(shù)內(nèi)部支持w,a,s,d四個(gè)鍵的響應(yīng),依次代表方向鍵上,左,右,下,其中w鍵是用來(lái)控制圖形變換的,每次按w鍵時(shí),圖形在現(xiàn)有基礎(chǔ)上順時(shí)針變換一次。
CheckConflict:沖突檢測(cè)函數(shù),檢測(cè)方塊下一次將要移動(dòng)的位置是否會(huì)碰到已有的方塊或者左右兩邊的墻壁。
CheckDelete:每一次方塊落到底部之后,調(diào)用該函數(shù)檢查是否有滿行,如果有則調(diào)用Delete函數(shù)刪除該行。
myDisplay1:作圖函數(shù)。
Change:變換函數(shù),主要是通過(guò)計(jì)算變換后的圖形與之前圖形的坐標(biāo)關(guān)系來(lái)實(shí)現(xiàn)。
三、 源代碼
#include 3、dlib.h>
#include 4、P鍵進(jìn)行變換應(yīng)該怎么處理
*本程序最初設(shè)計(jì)并不考慮這個(gè)問(wèn)題,一開始即畫出方塊的各個(gè)部分,以后再考慮完善的事情
*另外,記錄坐標(biāo)的順序?yàn)閺淖笾劣遥瑥纳现料?
*/
GLfloat b[][5][3]={
{{0.0f,0.9f},{0.0f,0.8f},{0.0f,0.7f},{0.0f,0.6f}},//1、記錄長(zhǎng)條四個(gè)坐標(biāo)
{{-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 5、}},//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.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字形
};
GLfloa 6、t curLoc[5][3];
GLint currentBlock=2;//記錄當(dāng)前正在下落的是第幾種方塊,順序如上面所示
GLint turn[7]={0};//應(yīng)該變換成第幾種形態(tài)了
GLfloat xd=0.0f,yd=0.0f;
/*
這里定義的over是用來(lái)判斷方塊是否到達(dá)了不能再往下降的地方,到了則置
其為true,否則就修改為false。
其中有這樣幾種情況需要修改over:
1、重新生成了一個(gè)方塊,修改over=false
2、方塊到大底部,修改over=true
*/
bool over=false;
//記錄游戲是否結(jié)束
bool end 7、=false;
int score=0;
//設(shè)置一個(gè)鎖,在下降操作時(shí)不允許變換,在變換時(shí)不允許下降操作,否則將會(huì)產(chǎn)生資源競(jìng)爭(zhēng)
//int lock=1;
/*
定義一個(gè)20*20的矩陣來(lái)記錄當(dāng)前整個(gè)畫面中各個(gè)小格子的情況,可用來(lái)消除滿格行
矩陣的存儲(chǔ)順序?yàn)閺淖蟮接?,從下到上,包含下?biāo)0
BLOCK[i][j]中i對(duì)應(yīng)的是縱坐標(biāo),j對(duì)應(yīng)的是橫坐標(biāo)(這個(gè)有點(diǎn)痛苦),但是在消去滿格
的時(shí)候還是不變,只是在用b數(shù)組給其賦值時(shí)需要反過(guò)來(lái)
*/
GLint BLOCK[SIZE][SIZE];
void down(int id);
void InitBLOCK() 8、;
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++) //函數(shù)調(diào)用的順序?qū)﹀e(cuò)誤有一定的影響
for(j=0;j<2;j++)
{
cout<< 9、curLoc[i][j]<<" ";
}
cout< 10、hange()//將圖形做變換,采用順時(shí)針旋轉(zhuǎn)的規(guī)律(下面的工作即是填入坐標(biāo))
{
GLfloat temp00=curLoc[0][0];
GLfloat temp01=curLoc[0][1];
GLfloat temp10=curLoc[1][0];
GLfloat temp11=curLoc[1][1];
GLfloat temp20=curLoc[2][0];
GLfloat temp21=curLoc[2][1];
GLfloat temp30=curLoc[3][0];
GLfloat temp31=curLoc[3][1];
switch( 11、currentBlock)
{
case 0://長(zhǎng)條
switch(turn[0])
{
case 0:
curLoc[0][0]=temp10-0.1f;
curLoc[0][1]=temp11;
curLoc[2][0]=temp10+0.1f;
curLoc[2][1]=temp11;
curLoc[3][0]=temp10+0.2f;
curLoc[3][1]=temp11;
break;
case 1:
curLoc[0][0]=temp10;
curLoc[0][1]=temp 12、11+0.1f;
curLoc[2][0]=temp10;
curLoc[2][1]=temp11-0.1f;
curLoc[3][0]=temp10;
curLoc[3][1]=temp11-0.2f;
break;
}
turn[0]=(turn[0]+1)%2;
break;
case 1://正方形
break;
case 2://T字形
//cout<<"turn[2]="< 13、[0]=temp20;
curLoc[1][1]=temp21;
curLoc[2][0]=temp30;
curLoc[2][1]=temp31;
curLoc[3][0]=temp20;
curLoc[3][1]=temp21-0.1f;
break;
case 1:
curLoc[0][0]=temp10-0.1f;
curLoc[0][1]=temp11;
break;
case 2:
curLoc[0][0]=temp10;
curLoc[0][1]=temp11+0.1f;
14、curLoc[1][0]=temp00;
curLoc[1][1]=temp01;
curLoc[2][0]=temp10;
curLoc[2][1]=temp11;
break;
case 3:
curLoc[3][0]=temp20+0.1f;
curLoc[3][1]=temp21;
break;
}
turn[2]=(turn[2]+1)%4;
break;
case 3://Z字形
switch(turn[3])
{
case 0:
curLoc[0][0]=te 15、mp10+0.1f;
curLoc[0][1]=temp11+0.1f;
curLoc[2][0]=temp10+0.1f;
curLoc[2][1]=temp11;
curLoc[3][0]=temp20;
curLoc[3][1]=temp21;
break;
case 1:
curLoc[0][0]=temp10-0.1f;
curLoc[0][1]=temp11;
curLoc[2][0]=temp30;
curLoc[2][1]=temp31;
curLoc[3][0]=temp30+0.1 16、f;
curLoc[3][1]=temp31;
break;
}
turn[3]=(turn[3]+1)%2;
break;
case 4://反Z字形
switch(turn[4])
{
case 0:
curLoc[0][0]=temp00-0.1f;
curLoc[0][1]=temp01+0.1f;
curLoc[1][0]=temp00-0.1f;
curLoc[1][1]=temp01;
curLoc[2][0]=temp00;
curLoc[2][1]=temp01;
17、 curLoc[3][0]=temp00;
curLoc[3][1]=temp01-0.1f;
break;
case 1:
curLoc[0][0]=temp20;
curLoc[0][1]=temp21;
curLoc[1][0]=temp20+0.1f;
curLoc[1][1]=temp21;
curLoc[2][0]=temp10;
curLoc[2][1]=temp11-0.1f;
break;
}
turn[4]=(turn[4]+1)%2;
break;
case 5://L 18、字形
switch(turn[5])
{
case 0:
curLoc[0][0]=temp10;
curLoc[0][1]=temp11;
curLoc[1][0]=temp10+0.1f;
curLoc[1][1]=temp11;
curLoc[2][0]=temp10+0.2f;
curLoc[2][1]=temp11;
curLoc[3][0]=temp20;
curLoc[3][1]=temp21;
break;
case 1:
curLoc[0][0]=temp00;
19、 curLoc[0][1]=temp01+0.1f;
curLoc[1][0]=temp10;
curLoc[1][1]=temp11+0.1f;
curLoc[2][0]=temp10;
curLoc[2][1]=temp11;
curLoc[3][0]=temp10;
curLoc[3][1]=temp11-0.1f;
break;
case 2:
curLoc[0][0]=temp20+0.1f;
curLoc[0][1]=temp21;
curLoc[1][0]=temp20-0.1f;
20、 curLoc[1][1]=temp21-0.1f;
curLoc[2][0]=temp20;
curLoc[2][1]=temp21-0.1f;
curLoc[3][0]=temp20+0.1f;
curLoc[3][1]=temp21-0.1f;
break;
case 3:
curLoc[0][0]=temp10;
curLoc[0][1]=temp11+0.2f;
curLoc[1][0]=temp10;
curLoc[1][1]=temp11+0.1f;
curLoc[2][0]=temp10;
21、 curLoc[2][1]=temp11;
curLoc[3][0]=temp20;
curLoc[3][1]=temp21;
break;
}
turn[5]=(turn[5]+1)%4;
break;
case 6://反L字形
switch(turn[6])
{
case 0:
curLoc[0][0]=temp20-0.1f;
curLoc[0][1]=temp21+0.1f;
curLoc[1][0]=temp20-0.1f;
curLoc[1][1]=temp21;
b 22、reak;
case 1:
curLoc[0][0]=temp00+0.1f;
curLoc[0][1]=temp01+0.1f;
curLoc[1][0]=temp30;
curLoc[1][1]=temp31+0.2f;
curLoc[2][0]=temp00+0.1f;
curLoc[2][1]=temp01;
curLoc[3][0]=temp20;
curLoc[3][1]=temp21;
break;
case 2:
curLoc[0][0]=temp00-0.1f;
curLoc[ 23、0][1]=temp01-0.1f;
curLoc[1][0]=temp20;
curLoc[1][1]=temp21;
curLoc[2][0]=temp20+0.1f;
curLoc[2][1]=temp21;
curLoc[3][0]=temp30+0.1f;
curLoc[3][1]=temp31;
break;
case 3:
curLoc[0][0]=temp20;
curLoc[0][1]=temp21+0.1f;
curLoc[1][0]=temp20;
curLoc[1][1]=te 24、mp21;
curLoc[2][0]=temp30-0.1f;
curLoc[2][1]=temp31;
curLoc[3][0]=temp30;
curLoc[3][1]=temp31;
break;
}
turn[6]=(turn[6]+1)%4;
break;
}
//如果旋轉(zhuǎn)非法(即旋轉(zhuǎn)時(shí)碰到墻壁了),則要恢復(fù)原來(lái)的狀態(tài)
int ret;
ret=CheckConflict();
if(ret == 1)
{
curLoc[0][0]=temp00;
curLoc[0][1]=temp01;
25、
curLoc[1][0]=temp10;
curLoc[1][1]=temp11;
curLoc[2][0]=temp20;
curLoc[2][1]=temp21;
curLoc[3][0]=temp30;
curLoc[3][1]=temp31;
}
}
/*
消除滿格的一行,在每次over被修改為true的時(shí)候都要檢查一遍
算法思想是從第0行開始依次判斷,如果empty為true則將下面的向上,
并不是判斷一次就移動(dòng)所有的,而是只移動(dòng)最近的,將空出來(lái)的
那一行的empty標(biāo)記為true
*/
void Delete(int *emp 26、ty)
{
int i,j;
int pos;
while(1) //將上面非空的行填補(bǔ)到下面的空行中
{
i=1;
while(i < 20&&empty[i] == 0) //為空或者滿,都需要將上面的行移下來(lái)填充
{
i++;
}
if(i >= 20) break;
j=i+1;
while(j < 20&&empty[j] == -1) j++;
if(j >= 20) break;
if(j < 20&&empty[j] != -1)
{
for(pos=0;pos<20;pos++)
27、 BLOCK[i][pos]=BLOCK[j][pos];
empty[i]=empty[j];
empty[j]=-1;
}
}
for(i=1;i<20;i++)
if(empty[i] != 0)
{
for(j=0;j<20;j++)
BLOCK[i][j]=0;
}
}
/*
*1、判斷新生成的圖形是否和原來(lái)的圖形有沖突,有則不能更改,這個(gè)地方比較不好實(shí)現(xiàn)
*2、判斷是否有滿格的行,有則調(diào)用Delete函數(shù)去掉
*3、這里似乎還要加上判斷是否到大頂部,如果到達(dá)頂部則游戲結(jié)束(可采用監(jiān)視方框最上
* 28、面一行之上那行里面有沒(méi)有方格,如果有的話則游戲結(jié)束)
*結(jié)束之后就可以把當(dāng)前方塊存入BLOCK中
*empty表示一行中方塊的數(shù)目,-1表示為空行,0表示部分為空,1表示滿行
*/
void CheckDelete()//目前這個(gè)函數(shù)還只是實(shí)現(xiàn)了一個(gè)方塊到達(dá)終點(diǎn)之后是否有能夠被刪除的行
{
int i,j;
int empty[SIZE];
bool is_needed=false;
int count;
for(i=0;i 29、][0]+1)*10+0.5; //此處無(wú)需注意取值,因?yàn)閏heckConflict已經(jīng)解決
double y=(curLoc[i][1]+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(BLOCK[i][j]==1)
count++;
if(count==20)
{
empty[i]=1; //若滿格,則可以刪除,置為true
score++; //此處計(jì)分
is_n 30、eeded=true;
}
else if(count > 0&&count < 20)
{
empty[i]=0;
}
}
if(is_needed==true)//如果有滿行則去刪除,否則免之
Delete(empty);
}
int CheckConflict(int lef_rig)
{
int i;
for(i=0;i<4;i++)
{
double x=(curLoc[i][0]+1)*10; //注意取值!!!
double y=(curLoc[i][1]+1)*10+0.5; //y方向無(wú)需注意
31、 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) //判斷是否發(fā)生沖突
{
break;
}
}
if(i < 4)
return 1;
return 0;
}
/*
關(guān)鍵部分在這里,主要是要判斷方塊下一次的移動(dòng)是否合法,
本程序通過(guò)對(duì)b數(shù)組所存儲(chǔ)的下標(biāo)是否在BLOCK數(shù)組中已經(jīng)為1
來(lái)判斷,這樣,只需要在BLOCK 32、的最外層加一圈1,就不用通過(guò)
原來(lái)的方式來(lái)判斷方塊是否越界
*/
void key(unsigned char k,int x,int y)
{
int i,ret;
if(over == false)
{
if(k==UP)//此處需要改成調(diào)用變換圖形樣式的函數(shù)
{
Change();
}
else if(k==DOWN)//后續(xù)還要修改,移動(dòng)到底部過(guò)了一段時(shí)間之后就不能左右移動(dòng)了
{
for(i=0;i<4;i++)//需繼續(xù)添加以1和-1作為哨兵
{
curLoc[i][1]-=0.1f;
} 33、
ret=CheckConflict();
if(ret == 1)//發(fā)生沖突,則將修改復(fù)原
{
for(i=0;i<4;i++)
curLoc[i][1]+=0.1f;
over=true;//并且可以生成下一個(gè)方塊了
}
}
else if(k==RIGHT)
{
for(i=0;i<4;i++)
curLoc[i][0]+=0.1f;
ret=CheckConflict(1);
if(ret == 1)//發(fā)生沖突,則將修改復(fù)原
{
for(i=0;i 34、<4;i++)
curLoc[i][0]-=0.1f;
}
}
else if(k==LEFT)
{
for(i=0;i<4;i++)
curLoc[i][0]-=0.1f;
ret=CheckConflict(1);
if(ret == 1)//發(fā)生沖突,則將修改復(fù)原
{
for(i=0;i<4;i++)
curLoc[i][0]+=0.1f;
}
}
}
if(over==true) CheckDelete();
glutPostRedisplay();//調(diào)用這 35、個(gè)函數(shù)可以重新繪圖,每次相應(yīng)消息之后,所有全部重繪
}
/*
讓方塊定時(shí)下降
*/
void down(int id)
{
int i,ret;
if(over!=true)
{
for(i=0;i<4;i++)//需繼續(xù)添加以1和-1作為哨兵
{
curLoc[i][1]-=0.1f;
}
ret=CheckConflict();
if(ret == 1)//發(fā)生沖突,則將修改復(fù)原
{
for(i=0;i<4;i++)
curLoc[i][1]+=0.1f;
if(curLoc[0][1] > 36、= b[currentBlock][0][1])
{
cout<<"Game over,your score is:"< 37、GL_COLOR_BUFFER_BIT); //不能使用深度測(cè)試,否則畫出來(lái)的圖形很亂
for(i=0;i<20;i++)
{
for(j=0;j<20;j++)
{
if(BLOCK[i][j]==1)
{
glColor3f(0.0f,1.0f,0.0f); //用藍(lán)色畫圖
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);
g 38、lColor3f(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= 39、0;i<4;i++)
{
glColor3f(0.0f,1.0f,0.0f); //用藍(lán)色畫圖
glRectf(curLoc[i][0],curLoc[i][1],curLoc[i][0]+0.1f,curLoc[i][1]+0.1f);
glLineWidth(2.0f);
glBegin(GL_LINE_LOOP);
glColor3f(0.0f,0.0f,0.0f);
glVertex2f(curLoc[i][0],curLoc[i][1]);
glVertex2f(curLoc[i][0]+0.1f,curLoc[i][1 40、]);
glVertex2f(curLoc[i][0]+0.1f,curLoc[i][1]+0.1f);
glVertex2f(curLoc[i][0],curLoc[i][1]+0.1f);
glEnd();
glFlush();
}
}
glutSwapBuffers();
}
/*
* 隨機(jī)生成方塊,原理即生成一個(gè)7以內(nèi)的隨機(jī)數(shù),
* 對(duì)應(yīng)的二維數(shù)組即為下一個(gè)產(chǎn)生的方塊
*/
void CreateBlocks()
{
int i,j;
myDisplay1();
if(over)
{
srand(t 41、ime(NULL));
currentBlock=rand()%7;
for(i=0;i<7;i++) //關(guān)鍵之處,每次創(chuàng)建一個(gè)新的方塊后要將變形的記錄清空
turn[i]=0;
for(i=0;i<4;i++)
for(j=0;j<2;j++)
{
curLoc[i][j]=b[currentBlock][i][j];
}
over=false;
glutPostRedisplay();
}
}
void main(int argc ,char **argv)
{
glutInit(&argc,argv 42、);
glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE);
glutInitWindowPosition(400,100);
glutInitWindowSize(600,600);
InitBLOCK();
glutCreateWindow("俄羅斯方塊 author:parkfang");
glutDisplayFunc(&CreateBlocks);
glutTimerFunc(1000,down,1);
glutKeyboardFunc(key);
glClearColor(1.0f,1.0f,1.0f,1.0f);//用白色清除屏幕
glutMainLoop();
}
- 溫馨提示:
1: 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
2: 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
3.本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
5. 裝配圖網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 外研版(一起)英語(yǔ)一年級(jí)上冊(cè)Module-5課件
- 外研版(一起)五上Module-10《Unit-1-You-should-tidy-your課件
- 認(rèn)識(shí)線段課件
- 患者病情評(píng)估培訓(xùn)完整
- 早產(chǎn)兒的護(hù)理教學(xué)
- 我們吃的食物安全嗎
- 鹽酸硫酸—浙教版九級(jí)科學(xué)上冊(cè)課件1
- 人工智能遺傳算法
- 硬質(zhì)景觀的細(xì)部處理龍湖
- 人教版小學(xué)二年級(jí)上冊(cè)數(shù)學(xué)8的乘法口訣
- 郵輪旅游世界郵輪產(chǎn)業(yè)經(jīng)濟(jì)的發(fā)展
- 如何繪制出高品質(zhì)的學(xué)科思維導(dǎo)圖
- 美國(guó)癲癇學(xué)會(huì)驚厥性癲癇持續(xù)狀態(tài)治療指南解讀
- 城市公共空間設(shè)計(jì)理論及方法課件
- (課件)正弦定理公開課