⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tetris.c

📁 一个传统的俄罗斯方块小游戏
💻 C
📖 第 1 页 / 共 2 页
字号:
	yy=Line;
	for(xx=4;xx<(xGrids-4);xx++)
	{
			
			if(pBuf[i++])
			{
				SetMapDot(pMap,xx,yy);
			}
			else
			{
				ClrMapDot(pMap,xx,yy);
			}
	
	}

}

//检测一行是否已满

int	MapLineIsFull(U8 *pMap,int Line)
{

	int xx,yy;
	////
	yy=Line;
	///
	for(xx=4;xx<(xGrids-4-1);xx++)
	{
		if(!GetMapDot(pMap,xx,yy))	return 0;	//如果此行有任意一点为0,则表示此行没有满.
	
	}
	return 1;

}

/*============================================================================*/

int	CheckTetris(struct TETRIS *pTetris)
{
	int	i,j,xx,yy;
	int	states;
	////
	states=0;
st:
	for(yy=(yGrids-4-1);yy>0;yy--)	//从最后一行开始检测
	{
		if(MapLineIsFull(pTetris->Map,yy))
		{
			//如果此行已满.
			
			//pTetris->Point=(2*xGrids);
			
			states=1;
			for(i=yy;i>0;i--)
			{
				U8	buf[xGrids];
				////
				GetMapLine(pTetris->Map,i-1,buf);	//读上一行
				PutMapLine(pTetris->Map,i,buf);		//写到本行.	
				
			}
			
			goto st;					//重新开始检测
			
		}

		
	}
	
	return states;
}

/*============================================================================*/

//初始化背景

void	TetrisMapInit(U8 *pBuf)
{
	int xx,yy;
	////
	
	for(yy=0;yy<yGrids;yy++)
	{
		for(xx=0;xx<xGrids;xx++)
		{
			
			if(xx<4)
			{
				SetMapDot(pBuf,xx,yy);
				continue;
			}
			////
			if(xx>(xGrids-4-1))
			{
				SetMapDot(pBuf,xx,yy);
				continue;
			}
			////
			if(yy>(yGrids-4-1))
			{
				SetMapDot(pBuf,xx,yy);
				continue;
			}
			////
			
			ClrMapDot(pBuf,xx,yy);
			
			
			
		}
	
	}

}

/*============================================================================*/

/*============================================================================*/


/*============================================================================*/

void	ShowMap(U8 *pMap,int x,int y,int FrColor,int BkColor,int BorderColor)
{
	int xx,yy,dx,dy,x_offset,y_step;
	////
	
	dx			=((xGrids-(4*2))*7)+1;
	dy			=((yGrids-(1*4))*7)+1;
	x_offset	=((1*4)*7);
	y_step		=dy>>2;
	////
	
	
	GUI_FillRectangle(x,y,dx,dy,BkColor);
	
	////////
	
	for(yy=0;yy<(yGrids-4);yy++)
	{
		for(xx=4;xx<(xGrids-4);xx++)
		{
			
 			if(GetMapDot(pMap,xx,yy))
			{
				DrawBlockDot(x+(xx*7)-x_offset,y+(yy*7),FrColor);
			
			}
		
		}
	
	}
	////////
	
	GUI_Rectangle(x,y,dx,dy,BorderColor);
	////
	
}


/*============================================================================*/

/*============================================================================*/

void	GetNewBlock(struct BLOCK *block)
{
	
	block->Index	=(GUI_RandVal()%(16))*4;	//方块索引(随机生成)
	block->Rotate	=GUI_RandVal()%4;			//方块方向(随机生成)
				
}

/*============================================================================*/
/*============================================================================*/
/*============================================================================*/

/*============================================================================*/
/*============================================================================*/
/*============================================================================*/

#define	GAME_NEXT_BLOCK		USER_MSG+1
#define	GAME_RUN		USER_MSG+2
#define	GAME_PAUSE		USER_MSG+3
#define	GAME_OVER		USER_MSG+4


struct	TetrisExData
{
	struct	TETRIS TempTetris,Tetris;
	int states;
	

};

U32	TetrisWinProc(HWND wnd,U32 msg,U32 param0,U32 param1)
{
	struct	WINDOW			*pWin;
	struct	TetrisExData	*pExData;
	struct	BUTTON			*pBN;
	int	states,i;
	////
	
	pWin	=(void*)wnd;
	pExData	=(void*)pWin->ExData;
	////
	
	switch(msg)
	{
			
			case	MSG_INIT:
			
					TetrisMapInit(pExData->Tetris.Map);
		
					pExData->Tetris.Point	=0;
					pExData->Tetris.Count	=0;
					
				
					pExData->Tetris.xgrd	=xGrids>>1;			//x
					pExData->Tetris.ygrd	=0;					//y
					pExData->Tetris.xoffset	=0;					//水平偏移
					
					pExData->states			=GAME_RUN;
					
					GetNewBlock(&pExData->Tetris.CurBlock);		//当前方块
					GetNewBlock(&pExData->Tetris.NextBlock);	//下一个方块

					pBN	=GUI_WindowGetItem(pWin,102);
					
					if(pExData->states==GAME_PAUSE)
					{
						pBN->Text	="开始";
					}
					else
					{
						pBN->Text	="暂停";
					}

					break;
					
				/////////////
				
			case	GAME_NEXT_BLOCK:	//下一个方块.
					
					
					pExData->Tetris.xgrd	=(GUI_RandVal()%(xGrids-(2*4)));
					if(pExData->Tetris.xgrd<4)	pExData->Tetris.xgrd=4;
					
					pExData->Tetris.ygrd	=0;
					pExData->Tetris.xoffset	=0; 
						
						
					pExData->Tetris.Count++;
							
					pExData->Tetris.CurBlock.Index		=pExData->Tetris.NextBlock.Index;
					pExData->Tetris.CurBlock.Rotate		=pExData->Tetris.NextBlock.Rotate;
							
					GetNewBlock(&pExData->Tetris.NextBlock);
							
					memcpy(pExData->Tetris.Map,pExData->TempTetris.Map,(xGrids*yGrids));			
					////////
					
					Uart_Puts(0,"Next Block!\n");
					
					break;
					
				/////////////
			
			case	MSG_KEY:	
			case	MSG_COMMAND:
			
					if(pExData->states==GAME_OVER)
					{
						SendMessageX(wnd,MSG_INIT,0,0);	//重新开始游戏.
						break;
					}
					////
					
					switch(param0)
					{

					
						case	KEY_ID_ESC:
						
								SendMessageX(wnd,MSG_PAINT,0,0);
								while(pGUI_TS->IsDown());
								return MSG_QUIT;
								
								///////////////////
						
						case	'p':
						case	'P':
								if(pExData->states==GAME_OVER)	break;
								////
								
								TS_Disable();
								Key_Disable();

								pBN	=GUI_WindowGetItem(pWin,102);
								////
								
								if(pExData->states==GAME_PAUSE)
								{
									pExData->states=GAME_RUN;
									pBN->Text	="暂停";
									
								
								}
								else
								{
									pExData->states=GAME_PAUSE;
									pBN->Text	="开始";
									
								}
								pBN->Hdr.Draw(pBN);
								
								SendMessageX(wnd,MSG_PAINT,0,0);
								///////////////////
									
						case	KEY_ID_LEFT:
						case	'a':
						case	'A':
								
								if(pExData->states==GAME_OVER)	break;
								////
								if(CheckBlockInTray(pExData->Tetris.Map,pExData->Tetris.xgrd+pExData->Tetris.xoffset-1,pExData->Tetris.ygrd,pExData->Tetris.CurBlock.Index+pExData->Tetris.CurBlock.Rotate))
								{
									pExData->Tetris.xoffset--;			
								}
								SendMessageX(wnd,MSG_PAINT,0,0);
								break;
								
								///////////////////
								
						case	KEY_ID_RIGHT:
						case	'd':
						case	'D':
						
								if(pExData->states==GAME_OVER)	break;
								////
								if(CheckBlockInTray(pExData->Tetris.Map,pExData->Tetris.xgrd+pExData->Tetris.xoffset+1,pExData->Tetris.ygrd,pExData->Tetris.CurBlock.Index+pExData->Tetris.CurBlock.Rotate))
								{
									pExData->Tetris.xoffset++;
								}
								SendMessageX(wnd,MSG_PAINT,0,0);
								break;
								
								///////////////////
						
						case	KEY_ID_UP:
						
								if(pExData->states==GAME_OVER)	break;
								////
								TS_Disable();
							
								i=pExData->Tetris.CurBlock.Rotate;	//保存旧的方块方向.
								
								pExData->Tetris.CurBlock.Rotate++;
								if(pExData->Tetris.CurBlock.Rotate>=4)
								{
									pExData->Tetris.CurBlock.Rotate=0;
								}
								////

								if(!CheckBlockInTray(pExData->Tetris.Map,pExData->Tetris.xgrd+pExData->Tetris.xoffset,pExData->Tetris.ygrd,pExData->Tetris.CurBlock.Index+pExData->Tetris.CurBlock.Rotate))
								{
									////旋转后不能放下该方块
									pExData->Tetris.CurBlock.Rotate=i;		//恢复旧的方块方向.
								}
								
								SendMessageX(wnd,MSG_PAINT,0,0);
								break;
								
								///////////////////
								
						case	KEY_ID_DOWN:
						
								if(pExData->states==GAME_OVER)	break;
								////
								if(CheckBlockInTray(pExData->Tetris.Map,pExData->Tetris.xgrd+pExData->Tetris.xoffset,pExData->Tetris.ygrd+1,pExData->Tetris.CurBlock.Index+pExData->Tetris.CurBlock.Rotate))
								{									
									//如果下一行可以放下该方块:
									pExData->Tetris.ygrd++;									
								}
								
								SendMessageX(wnd,MSG_PAINT,0,0);
								break;
								
								///////////////////
								
							
						default:
								SendMessageX(wnd,MSG_PAINT,0,0);
						
					}
						
					break;
					//////////////////
					
			case	MSG_TIMER:
			
					switch(param0)
					{
					
						case	500:		//定时器500mS
						
								if(!CheckBlockInTray(pExData->Tetris.Map,pExData->Tetris.xgrd+pExData->Tetris.xoffset,pExData->Tetris.ygrd+1,pExData->Tetris.CurBlock.Index+pExData->Tetris.CurBlock.Rotate))
								{
								
									//如果下一行不能放下该方块:
									if(pExData->Tetris.ygrd==0)
									{
										//如果是第一行不能放下该方块.
										pExData->states	=GAME_OVER;				//游戏结束.
										Uart_Puts(0,"Game Over!\r\n");
										
										TS_Disable();
										Key_Disable();
									
									}
									else
									{
										if(CheckTetris(&pExData->TempTetris))	//检测是否有满的行
										{
											pExData->Tetris.Point	+=2*xGrids;
											Uart_Printf(0,"User Point=%d\n",pExData->Tetris.Point);
										}
									}
									////////
									SendMessageX(wnd,GAME_NEXT_BLOCK,0,0);	
													
								}
								else
								{
									//如果下一行可以放下该方块:
									
									if(pExData->states==GAME_RUN)	
									{
										//如果游戏在运行状态.
										pExData->Tetris.ygrd++;
									}
									
								}
								
								break;
								////////
								
						default:	return DefaultMessage(wnd,msg,param0,param1);
								
					}
					
					SendMessageX(wnd,MSG_PAINT,0,0);
					break;
					//////////////////
					
			case	MSG_PAINT:
			
					GUI_PutWallpaper();
					
					memcpy(pExData->TempTetris.Map,pExData->Tetris.Map,(xGrids*yGrids));	//复制数据到TempTetris.Map中.	
					
					DrawBlockInMap(pExData->TempTetris.Map,pExData->Tetris.xgrd+pExData->Tetris.xoffset,pExData->Tetris.ygrd,pExData->Tetris.CurBlock.Index+pExData->Tetris.CurBlock.Rotate);
					
					ShowMap(pExData->TempTetris.Map,20,20,RGB565(00,00,00),TRGB888(200,255,255,255),RGB565(00,00,00));	
					
					////////
					
					DrawBlock(GUI_XSIZE-96,64,RGB565(24,00,00),pExData->Tetris.NextBlock.Index+pExData->Tetris.NextBlock.Rotate);	//显示下一个方块	
					
					GUI_LabelPrintf(GUI_XSIZE-96,96,96,28,RGB565(31,63,00),TRGB565(160,00,00,00),RGB565(10,20,10),LEFT,FONT(ASCII8x16,HZ16x16),"方块数:%d",pExData->Tetris.Count);
					GUI_LabelPrintf(GUI_XSIZE-96,96+32,96,28,RGB565(31,63,00),TRGB565(160,00,00,00),RGB565(10,20,10),LEFT,FONT(ASCII8x16,HZ16x16),"得分数:");
					GUI_LabelPrintf(GUI_XSIZE-96,96+32+28,96,64,TRGB565(128,31,00,00),TRGB565(240,31,63,31),RGB565(10,20,10),CENTER,FONT(ASCII24x48_DT,HZ16x16),"%d",pExData->Tetris.Point);

					////
					
					GUI_ObjectDraw(pWin);
					
					if(pExData->states==GAME_OVER)
					{			
						GUI_LabelPrintf(GUI_XSIZE>>2,GUI_YSIZE>>1,GUI_XSIZE>>1,32,RGB565(31,00,00),RGB_TRANS,RGB_TRANS,CENTER,FONT(ASCII12x24,HZ16x16),"Game Over");
					}

					GUI_DisplayUpdate(pWin->Hdr.x,pWin->Hdr.y,pWin->Hdr.dx,pWin->Hdr.dy);
					break;
					
					////////////////
					
					
			default:	
					return DefaultMessage(wnd,msg,param0,param1);
					break;
					
					////////////////
						
	}
	
	////
	return MSG_NULL;

}

/*============================================================================*/

int	Tetris(void *pdata)
{

	
	struct	TetrisExData	ExData;

	struct	BUTTON	*pBN;
	struct	WINDOW	*Wnd;
	struct	MESSAGE msg;
	struct	RECT Rect[6];
	
	////////////////////////
	////
	char	*s_Name[]={"Tetris(For Window)","方块游戏(窗口版)","???"};
	
	/////////////	
	if(pdata)
	{
		struct	PGM_INFO *pInfo	=pdata;
		pInfo->Name		=(char*)GUI_Language(s_Name);
		pInfo->pIcon		=0;
		pInfo->pSmallIcon	=0;
		pInfo->ExtraInfo	="Version:1.1";
		return	1;
	
	}
	/////////////

	Wnd=GUI_WindowCreate(	
							
							0,0,LCD_XSIZE-0,LCD_YSIZE-0,
							
							0,
							RGB565(20,40,20),0,
							(U32)&ExData,
							TetrisWinProc,
							(char*)GUI_Language);
	////////
	
	GUI_MatrixRectangle((GUI_XSIZE-160),GUI_YSIZE-96,160,90,3,2,8,8,Rect);
	
pBN	=GUI_ButtonCreate(Wnd,100,	GUI_XSIZE-64,8,56,48,RGB565(31,00,00),TRGB565(128,26,52,26),RGB565(10,20,10),BN_3D,	KEY_ID_ESC,		FONT(ASCII8x16,GBK16),"退出");
	GUI_ButtonCreate(Wnd,101,	Rect[1].x,Rect[1].y,Rect[1].dx,Rect[1].dy,RGB565(00,00,00),TRGB565(128,26,52,26),RGB565(10,20,10),BN_3D,	KEY_ID_UP,		FONT(ASCII8x16,GBK16),"∧");
	GUI_ButtonCreate(Wnd,102,	Rect[2].x,Rect[2].y,Rect[2].dx,Rect[2].dy,RGB565(00,00,00),TRGB565(128,26,52,26),RGB565(10,20,10),BN_3D,	'p'	,			FONT(ASCII8x16,GBK16),"暂停");
	GUI_ButtonCreate(Wnd,103,	Rect[3].x,Rect[3].y,Rect[3].dx,Rect[3].dy,RGB565(00,00,00),TRGB565(128,26,52,26),RGB565(10,20,10),BN_3D,	KEY_ID_LEFT,	FONT(ASCII8x16,GBK16),"<");
	GUI_ButtonCreate(Wnd,104,	Rect[4].x,Rect[4].y,Rect[4].dx,Rect[4].dy,RGB565(00,00,00),TRGB565(128,26,52,26),RGB565(10,20,10),BN_3D,	KEY_ID_DOWN,	FONT(ASCII8x16,GBK16),"∨");
	GUI_ButtonCreate(Wnd,105,	Rect[5].x,Rect[5].y,Rect[5].dx,Rect[5].dy,RGB565(00,00,00),TRGB565(128,26,52,26),RGB565(10,20,10),BN_3D,	KEY_ID_RIGHT,	FONT(ASCII8x16,GBK16),">");
	
	GUI_TimerCreate(Wnd,120,500);	//创建定时器 时间为500mS.
	GUI_ObjectSetFocused(pBN);
	////
	SendMessageX(Wnd,MSG_INIT,0,0);
	SendMessageX(Wnd,MSG_PAINT,0,0);
	////
	while(GetMessageX(&msg,Wnd))
	{
	
	}
	
	GUI_ObjectDestroy(Wnd);
	TS_Disable();
	Key_Disable();
	
}
/*============================================================================*/
/*============================================================================*/
/*============================================================================*/
/*============================================================================*/
/*============================================================================*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -