📄 tetris.c
字号:
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 + -