第一次真正意义上的用VC++实现的一个完整的Win32程序。 //Block.h //------------------------------------------------------------------------------------------------- /* 定义每个方块的结构 */
#if !defined _BLOCK_H_ #define _BLOCK_H_ #define BLOCK_VERSION &H01000000 //主版本号、辅版本、附加版本、附加2 #define BLOCK_SIZE 6 //存储到文件时占用的字节数 #define BLOCK_HEADER_SIZE 8 //存储文件头信息的大小 struct _Block {//注意:这些字段对于存储文件来说是有先后之分的。 unsigned int ID:8; unsigned int NextID:8; int Width:4; int Height:4; int OffsetY:4; int OffsetX:4; unsigned int Elements; //方块的各位是否为实体 };
typedef _Block BLOCK; #endif //------------------------------------------------------------------------------------------------- //CustomGDI.h //------------------------------------------------------------------------------------------------- #pragma once #include "windows.h" //#include "d3d9.h"
#define BORDER_STYLE_NONE 0 #define BORDER_STYLE_FLAT 1 //为简单起见,目前只提供FLAT //#define BORDER_STYLE_FIXED3D 2 //#define BORDER_STYLE_INNER3D 4 #define BORDER_STYLE_DEFAULT BORDER_STYLE_NONE
#define INNER_STYLE_EMPTY 0 #define INNER_STYLE_SOLID 1 #define INNER_STYLE_DEFAULT INNER_STYLE_EMPTY
#define TRANSPARENT_COLOR RGB(0,0,0) #define BACKGROUND_DEFAULT_COLOR RGB(0,0,0)
typedef int INNER_STYLE; typedef int BORDER_STYLE; typedef DWORD GDI_COLOR;
class CCustomGDI { public: //CCustomGDI(void); CCustomGDI(HWND hWnd); ~CCustomGDI(void); void TextOut(int x, int y,const char* lpString, int cbString); void Drawbox(PRECT prect, BORDER_STYLE bstyle=BORDER_STYLE_DEFAULT, INNER_STYLE istyle=INNER_STYLE_DEFAULT); void Drawbox(int x, int y, int height, int width, BORDER_STYLE bstyle=BORDER_STYLE_DEFAULT, INNER_STYLE istyle=INNER_STYLE_DEFAULT); void DrawPic(int x, int y, int height, int width, const char* file); void DrawPic(PRECT prect, const char* file); void Clear(void); void Clear(PRECT prect); void Clear(GDI_COLOR color); void Clear(PRECT prect, GDI_COLOR color); void Clear(int x, int y, int height, int width, GDI_COLOR color); void SetBkColor(GDI_COLOR color); //设置背景色 void SetColor(GDI_COLOR color); //设置前景色 void Set3DColor(GDI_COLOR ul_color, GDI_COLOR rb_color); //设置绘制3D时左上角与右下角的颜色 void SetBorderColor(GDI_COLOR color); void SetBorderSize(int size); protected: //LPDIRECT3D9 m_pD3D; //LPDIRECT3DDEVICE9 m_pd3dDevice; //HDC m_hdc; HWND m_hwnd; //HBRUSH m_hbrBkgnd; GDI_COLOR m_background; int m_bordersize; GDI_COLOR m_bordercolor; GDI_COLOR m_color; }; //------------------------------------------------------------------------------------------------- //CustomGDI.cpp //------------------------------------------------------------------------------------------------- #include ".\customgdi.h" // //CCustomGDI::CCustomGDI(void) //{ //} // CCustomGDI::CCustomGDI(HWND hWnd) { //初始化图形设备 m_hwnd=hWnd; //m_hdc=GetDC(hWnd);
m_background=BACKGROUND_DEFAULT_COLOR; m_bordersize=1; m_bordercolor=RGB(0x80,0x80,0x80); //gray m_color=RGB(0xFF,0xFF,0xFF); //white }
CCustomGDI::~CCustomGDI(void) { //ReleaseDC(m_hwnd, m_hdc); }
void CCustomGDI::TextOut(int x, int y,const char* lpString, int cbString) { HDC hdc=GetDC(m_hwnd); ::TextOut(hdc,x,y,lpString,cbString); ReleaseDC(m_hwnd,hdc); }
void CCustomGDI::Drawbox(PRECT prect, BORDER_STYLE bstyle, INNER_STYLE istyle) { HBRUSH hbr; HDC hdc;
hdc=GetDC(m_hwnd);
RECT rect; rect.top=prect->top; rect.bottom=prect->bottom; rect.left=prect->left; rect.right=prect->right;
if(bstyle==BORDER_STYLE_FLAT) { //如果为BORDER_STYLE_FLAT hbr=CreateSolidBrush(m_bordercolor); FrameRect(hdc, &rect, hbr); //这里不知道如何画线,呵呵。
DeleteObject(hbr);
rect.left+=m_bordersize; rect.right-=m_bordersize; rect.top+=m_bordersize; rect.bottom-=m_bordersize;
}
if(istyle==INNER_STYLE_SOLID) { hbr=CreateSolidBrush(m_color); FillRect(hdc, &rect, hbr); DeleteObject(hbr); }
ReleaseDC(m_hwnd,hdc); }
void CCustomGDI::Drawbox(int x, int y, int height, int width, BORDER_STYLE bstyle, INNER_STYLE istyle) { RECT rect; rect.top=y; rect.left=x; rect.bottom=y+height-1; rect.right=x+width-1; Drawbox(&rect,bstyle,istyle); }
void CCustomGDI::DrawPic(int x, int y, int height, int width, const char* file) { }
void CCustomGDI::DrawPic(PRECT prect, const char* file) { }
void CCustomGDI::Clear(void) { //清除屏幕 RECT rect; GetClientRect(m_hwnd,&rect); Clear(&rect, m_background); }
void CCustomGDI::Clear(PRECT prect) { Clear(prect, m_background); }
void CCustomGDI::Clear(GDI_COLOR color) { RECT rect; GetClientRect(m_hwnd,&rect); Clear(&rect, color); }
void CCustomGDI::Clear(PRECT prect, GDI_COLOR color) { HDC hdc; hdc=GetDC(m_hwnd);
HBRUSH hbr=CreateSolidBrush(color); FillRect(hdc, prect, hbr); DeleteObject(hbr);
ReleaseDC(m_hwnd,hdc); }
void CCustomGDI::Clear(int x, int y, int height, int width, GDI_COLOR color) { RECT rect; rect.left=x; rect.top=y; rect.right=x+height-1; rect.bottom=y+width-1; Clear(&rect,color); }
void CCustomGDI::SetBkColor(GDI_COLOR color) { m_background=color; }
void CCustomGDI::SetColor(GDI_COLOR color) { m_color=color; }
void CCustomGDI::Set3DColor(GDI_COLOR ul_color, GDI_COLOR rb_color) { }
void CCustomGDI::SetBorderSize(int size) { }
void CCustomGDI::SetBorderColor(GDI_COLOR color) { } //-------------------------------------------------------------------------------------------------- //Els.h //------------------------------------------------------------------------------------------------- #include <windows.h> //#include <d3d9.h> #include <stdio.h> #include <direct.h> #include <time.h> #include "Block.h" #include "CustomGDI.h"
#define PLAYAREA_HEIGHT 24 #define PLAYAREA_WIDTH 12 #define PLAYAREA_EMPTY_COLOR RGB(0,0,0)
#define IDT_PLAY 2005
#define GAME_STATUS_STOPPED 0 #define GAME_STATUS_RUNNING 1 #define GAME_STATUS_PAUSED -1
#define PLAYER_DEFAULT_NAME "<Player>" #define PLAYER_MAX_LEVEL 12 #define PLAYER_MAX_SCORE 999999999 struct _PLAYER { char Name[50]; int Power; //爆了几次 int Score; //得分,最大为999999999 };
struct _ELSSYS { int Level; //当前游戏级别 int ClientHeight; //当前客户区域高度 int ClientWidth; //当前客户区域宽度 int PlayAreaX; //游戏区域X坐标(注意:不包含游戏区域外的边框等) int PlayAreaY; //游戏区域Y坐标(注意:不包含游戏区域外的边框等) int SingleHeight; //单个格的高度 int SingleWidth; //单个格的宽度 int BorderSize; //边框大小 int Spacing; //格与格之间的间隔 int NextX; //下一个方块显示区域的X坐标 int NextY; //下一个方块显示区域的Y坐标 bool IsNextShown; //下一个方块是否显示 };
typedef _PLAYER PLAYER; typedef _ELSSYS EVIRONMENT; //--------------------------------------------------------------------------------------------------- //Els.cpp //--------------------------------------------------------------------------------------------------- #include "Els.h" //Direct3D Object //LPDIRECT3D9 g_pD3D = NULL;
//Direct3D Device //LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;
//窗体的HWND HWND g_hwnd;
int g_Status=GAME_STATUS_STOPPED; //存储游戏的状态 //当前的时间间隔 //int g_Interval=1000;
//游戏区域,存放每个格的颜色值,如果为0,表示当前格没有占用,否则已占用。 GDI_COLOR g_PlayArea[PLAYAREA_HEIGHT][PLAYAREA_WIDTH];
//当前行、列 int g_CurRow=0; int g_CurCol=0;
//当前方块的索引 int g_CurBlock;
//当前方块的颜色 GDI_COLOR g_CurBlockColor;
//下一个方块的索引 int g_NextBlock;
GDI_COLOR g_NextBlockColor;
//存放所有的方块 BLOCK* Blocks=NULL;
//方块的个数 int g_BlockCount=0;
//当前级别 int g_Level=0; int g_NextLevelPower=0; int g_NextLevelScore=1000;
//环境信息 EVIRONMENT g_Env;
//用户的信息 PLAYER g_Player={"Player",0,0};
//声明自己的GDI对象 CCustomGDI* g_GDI;
//所有函数定义 extern void CaculateEnv(void); //计算界面环境信息 extern void Render(void); //绘制界面
extern HRESULT LoadBlocks(void); //载入方块 extern void ClearBlocks(void); //清除所有方块所占内存
extern void _Bottom(void); //方块置底后的处理过程 extern void Bottom(void); //方块置底的处理过程 extern void Down(void); //方块下落 extern void MapCurBlockToPlayArea(void); //把当前方块影射到游戏区域
// //void ShowDebugMsg(const char* sMsg, int x=100, int y=100) //{ // HDC hdc; // hdc=GetDC(g_hwnd); // TextOut(hdc,x,y, sMsg, (int)strlen(sMsg)); //} // //清除释放所有方块所占内存 void ClearBlocks() { if(Blocks!=NULL) { free(Blocks); } }
//从文件中调入所有的方块 HRESULT LoadBlocks() { int i; FILE* fp; char sPath[_MAX_PATH]; char Header[BLOCK_HEADER_SIZE]; //char sMsg[255];
if(Blocks!=NULL) { ClearBlocks(); }
_getcwd(sPath, _MAX_PATH); //这里不判断了
strcat(sPath, "\\Turn.Right.blk"); fp=fopen(sPath, "rb");
if(fp==NULL) { //存在错误。 return E_FAIL; }
fread(Header,1,BLOCK_HEADER_SIZE,fp); //这里不再判断这个文件是否正确了,同时没有判断版本信息。 //0-2字节为:BLK //3-6字节为:版本信息 //7字节为方块个数。 g_BlockCount=(unsigned int)Header[BLOCK_HEADER_SIZE-1];
//然后申请g_BlockCount大小的方块数组 Blocks=(BLOCK *)malloc(sizeof(BLOCK)*g_BlockCount);
for(i=0;i<g_BlockCount;i++) { fread(&Blocks[i], sizeof(BLOCK), 1, fp); //测试载入的小片段 //sprintf(sMsg, "ID:%d;Next:%d.",Blocks[i].ID,Blocks[i].NextID); //ShowDebugMsg(sMsg, 0, 24*i); //MessageBox(g_hwnd, sMsg, "test",MB_OK); }
fclose(fp);
return S_OK;
}
//_Drawbox: //在俄罗斯方块区域以颜色color绘制第r行,第c列的单元格方块。 void _Drawbox(int r, int c, GDI_COLOR color) { int x,y; x=g_Env.PlayAreaX + g_Env.BorderSize + (c+1)*g_Env.Spacing + c*g_Env.SingleWidth; y=g_Env.PlayAreaY + g_Env.BorderSize + (r+1)*g_Env.Spacing + r*g_Env.SingleHeight;
g_GDI->SetColor(color); //g_GDI->Set3DColor(WHITE,BLACK); if(color==PLAYAREA_EMPTY_COLOR) { g_GDI->Drawbox(x,y,g_Env.SingleHeight,g_Env.SingleWidth,BORDER_STYLE_NONE,INNER_STYLE_SOLID); } else { g_GDI->Drawbox(x,y,g_Env.SingleHeight,g_Env.SingleWidth,BORDER_STYLE_FLAT,INNER_STYLE_SOLID); } }
void HideCurBlock() { //清除屏幕上当前方块的显示 int row,col; for(row=0;row<=Blocks[g_CurBlock].Height;row++) { if(g_CurRow+row<0) continue; for(col=0;col<=Blocks[g_CurBlock].Width;col++) { if(((Blocks[g_CurBlock].Elements) & (1<<(row*(Blocks[g_CurBlock].Width+1)+col)))!=0) { _Drawbox(g_CurRow+row,g_CurCol+col,PLAYAREA_EMPTY_COLOR); } } } }
void ShowCurBlock() { //在屏幕上显示当前方块 int row,col; for(row=0;row<=Blocks[g_CurBlock].Height;row++) { if(g_CurRow+row<0) continue;
for(col=0;col<=Blocks[g_CurBlock].Width;col++) { if(((Blocks[g_CurBlock].Elements) & (1<<(row*(Blocks[g_CurBlock].Width+1)+col)))!=0) { _Drawbox(g_CurRow+row,g_CurCol+col,g_CurBlockColor); //注意g_CurBlockColor值是否设置 } } }
//char s[200]; //sprintf(s,"Block:%d,%2x;SIZE:%d.",g_CurBlock, Blocks[g_CurBlock].Elements,sizeof(BLOCK)); //g_GDI->Drawbox(0,g_Env.ClientHeight-35,30,g_Env.ClientWidth*3/10-10,BORDER_STYLE_FLAT,INNER_STYLE_SOLID); //g_GDI->TextOut(10,g_Env.ClientHeight-30,s,(int)strlen(s)); }
void ShowNextBlock() { //在下一个方块的显示框中显示下一个方块 int row,col; int blkRow,blkCol;
blkRow=(3-Blocks[g_NextBlock].Height)/2; blkCol=(3-Blocks[g_NextBlock].Width)/2;
g_GDI->SetColor(PLAYAREA_EMPTY_COLOR); g_GDI->Drawbox(g_Env.NextX,g_Env.NextY,((g_Env.SingleHeight+g_Env.Spacing)<<2)+g_Env.Spacing+(g_Env.BorderSize<<1),((g_Env.SingleWidth+g_Env.Spacing)<<2)+g_Env.Spacing+(g_Env.BorderSize<<1),BORDER_STYLE_FLAT,INNER_STYLE_SOLID);
for(row=0;row<4;row++) { for(col=0;col<4;col++) { if(row>=blkRow && row<=blkRow+Blocks[g_NextBlock].Height && col>=blkCol && col<=blkCol+Blocks[g_NextBlock].Width) { if((Blocks[g_NextBlock].Elements & (1<<((row-blkRow)*(Blocks[g_NextBlock].Width+1)+(col-blkCol))))!=0) { g_GDI->SetColor(g_NextBlockColor); g_GDI->Drawbox(g_Env.NextX+g_Env.BorderSize+g_Env.Spacing+(g_Env.SingleWidth+g_Env.Spacing)*col, g_Env.NextY+g_Env.BorderSize+g_Env.Spacing+(g_Env.SingleHeight+g_Env.Spacing)*row,g_Env.SingleHeight,g_Env.SingleWidth,BORDER_STYLE_FLAT,INNER_STYLE_SOLID); continue; } } g_GDI->SetColor(PLAYAREA_EMPTY_COLOR); g_GDI->Drawbox(g_Env.NextX+g_Env.BorderSize+g_Env.Spacing+(g_Env.SingleWidth+g_Env.Spacing)*col, g_Env.NextY+g_Env.BorderSize+g_Env.Spacing+(g_Env.SingleHeight+g_Env.Spacing)*row,g_Env.SingleHeight,g_Env.SingleWidth,BORDER_STYLE_FLAT,INNER_STYLE_SOLID); } } }
void ShowGameInfo() { char s[200]; //显示游戏数据信息 if(g_Status==GAME_STATUS_STOPPED) { strcpy(s,"Game Status: Stopped."); }
if(g_Status==GAME_STATUS_RUNNING) { strcpy(s,"Game Status: Running."); }
if(g_Status==GAME_STATUS_PAUSED) { strcpy(s,"GameStatus: Paused."); }
g_GDI->TextOut(g_Env.ClientWidth*3/4,g_Env.ClientHeight-30," ",30); g_GDI->TextOut(g_Env.ClientWidth*3/4,g_Env.ClientHeight-30,s,(int)strlen(s));
//用户得分、当前级别 sprintf(s,"Score: %d",g_Player.Score);
g_GDI->TextOut(g_Env.ClientWidth*3/4,g_Env.ClientHeight/2-50," ",30); g_GDI->TextOut(g_Env.ClientWidth*3/4,g_Env.ClientHeight/2-50,s,(int)strlen(s)); sprintf(s,"Level: %d",g_Level); g_GDI->TextOut(g_Env.ClientWidth*3/4,g_Env.ClientHeight/2-30," ",30); g_GDI->TextOut(g_Env.ClientWidth*3/4,g_Env.ClientHeight/2-30,s,(int)strlen(s));
}
BOOL CanMoveDown() { int row,col;
if(Blocks==NULL) return FALSE; if(g_BlockCount<=0) return FALSE; if(g_CurBlock<0||g_CurBlock>=g_BlockCount) return FALSE; //如果已经到达最下面一行,不能再向下移了。 if((g_CurRow+Blocks[g_CurBlock].Height+1)>=PLAYAREA_HEIGHT) return FALSE;
for(col=0;col<=Blocks[g_CurBlock].Width;col++) { for(row=Blocks[g_CurBlock].Height;row>=0;row--) { //找到最下的非空 if(((Blocks[g_CurBlock].Elements) & (1<<(row*(Blocks[g_CurBlock].Width+1)+col)))!=0) { //如果游戏区域的下一行相应位置不空,则也不能再向下移动了。 if(g_PlayArea[g_CurRow+row+1][g_CurCol+col]!=PLAYAREA_EMPTY_COLOR) { return FALSE; } } } }
return TRUE; }
BOOL CanMoveLeft() { int row,col;
if(Blocks==NULL) return FALSE; if(g_BlockCount<=0) return FALSE; if(g_CurBlock<0||g_CurBlock>=g_BlockCount) return FALSE; //如果已经到达最左一列,不能再左移了。 if(g_CurCol<=0) return FALSE;
for(row=0;row<=Blocks[g_CurBlock].Height;row++) { for(col=0;col<=Blocks[g_CurBlock].Width;col++) { //找到最左的非空 if(((Blocks[g_CurBlock].Elements) & (1<<(row*(Blocks[g_CurBlock].Width+1)+col)))!=0) { //如果游戏区域的左位置不空,则也不能再左移动了。 if(g_PlayArea[g_CurRow+row][g_CurCol+col-1]!=PLAYAREA_EMPTY_COLOR) { return FALSE; } } } }
return TRUE; }
BOOL CanMoveRight() { if(Blocks==NULL) return FALSE; if(g_BlockCount<=0) return FALSE; if(g_CurBlock<0||g_CurBlock>=g_BlockCount) return FALSE; //如果已经到达最右一列,不能再右移了。 if(g_CurCol+Blocks[g_CurBlock].Width+1>=PLAYAREA_WIDTH) return FALSE; int row,col; for(row=0;row<=Blocks[g_CurBlock].Height;row++) { for(col=Blocks[g_CurBlock].Width;col>=0;col--) { //找到最右的非空 if(((Blocks[g_CurBlock].Elements) & (1<<(row*(Blocks[g_CurBlock].Width+1)+col)))!=0) { //如果游戏区域的右位置不空,则也不能再右移动了。 if(g_PlayArea[g_CurRow+row][g_CurCol+col+1]!=PLAYAREA_EMPTY_COLOR) { return FALSE; } } } }
return TRUE; }
BOOL CanTurn() { int row,col; int ARow,ACol; BLOCK* next;
if(Blocks==NULL) return FALSE; if(g_BlockCount<=0) return FALSE; if(g_CurBlock<0||g_CurBlock>=g_BlockCount) return FALSE; if(Blocks[g_CurBlock].NextID<0||Blocks[g_CurBlock].NextID>=(unsigned int)g_BlockCount) return FALSE; //说明原数据文件有错误,需更正
next=&Blocks[Blocks[g_CurBlock].NextID];
//这里的OffsetY、OffsetX,应该是由当前Block提供。 ARow=g_CurRow + Blocks[g_CurBlock].OffsetY; ACol=g_CurCol + Blocks[g_CurBlock].OffsetX; //如果超过高度了,应该不允许变换了,要不,一直按变换键,可能就永远落不了地了。 if(ARow+next->Height+1>PLAYAREA_HEIGHT) return FALSE; //如果列超出游戏区域,可以处理一下。 if(ACol<0) ACol=0; if(ACol+next->Width+1>=PLAYAREA_WIDTH) { ACol=PLAYAREA_WIDTH-next->Width-1; }
//实现CanTurn时,突然想到,当前方块所占的空,不要在g_PlayArea中记录 for(row=0;row<=next->Height;row++) { for(col=0;col<=next->Width;col++) { if(((next->Elements) & (1<<(row*next->Width+col+1)))!=0) { //如果下一个变换的相应位置非空的话 if(g_PlayArea[ARow+row][ACol+col]!=PLAYAREA_EMPTY_COLOR) { //如果游戏区域也非空 return FALSE; } } } }
return TRUE; }
void _Turn() { g_CurRow = g_CurRow + Blocks[g_CurBlock].OffsetY; g_CurCol = g_CurCol + Blocks[g_CurBlock].OffsetX;
g_CurBlock = Blocks[g_CurBlock].NextID;
//关于列的超范围值,变换应该同CanTurn中的算法相同。 if(g_CurCol<0) g_CurCol=0; if(g_CurCol + Blocks[g_CurBlock].Width+1>=PLAYAREA_WIDTH) { g_CurCol = PLAYAREA_WIDTH-Blocks[g_CurBlock].Width-1; } //变换完毕 }
void Turn() { if(g_Status!=GAME_STATUS_RUNNING) return; if(CanTurn()==TRUE) { HideCurBlock(); _Turn(); ShowCurBlock(); } }
void _MoveLeft() { g_CurCol--; }
void MoveLeft() { if(g_Status!=GAME_STATUS_RUNNING) return; if(CanMoveLeft()==TRUE) { HideCurBlock(); _MoveLeft(); ShowCurBlock(); } }
void _MoveRight() { g_CurCol++; }
void MoveRight() { if(g_Status!=GAME_STATUS_RUNNING) return; if(CanMoveRight()==TRUE) { HideCurBlock(); _MoveRight(); ShowCurBlock(); } }
void _Down() { g_CurRow++; }
void MapCurBlockToPlayArea() { int row,col; row=0; col=0; for(row=0;row<=Blocks[g_CurBlock].Height;row++) { for(col=0;col<=Blocks[g_CurBlock].Width;col++) { if((Blocks[g_CurBlock].Elements & (1<<(row*(Blocks[g_CurBlock].Width+1)+col)))!=0) { g_PlayArea[g_CurRow+row][g_CurCol+col]=g_CurBlockColor; } } } }
void Gain() { int row,col; int gain=0; BOOL full; //当前行是否全部填满 for(row=0;row<=Blocks[g_CurBlock].Height;row++) { full=TRUE; for(col=0;col<PLAYAREA_WIDTH;col++) { if(g_PlayArea[g_CurRow+row][col]==PLAYAREA_EMPTY_COLOR) { full=FALSE; break; } } if(full==TRUE) { //消当前行的动画效果 //消当前行 int tmpRow,tmpCol; for(tmpRow=g_CurRow+row;tmpRow>0;tmpRow--) { for(tmpCol=0;tmpCol<PLAYAREA_WIDTH;tmpCol++) { g_PlayArea[tmpRow][tmpCol]=g_PlayArea[tmpRow-1][tmpCol]; _Drawbox(tmpRow,tmpCol,g_PlayArea[tmpRow][tmpCol]); } }
for(tmpCol=0;tmpCol<PLAYAREA_WIDTH;tmpCol++) { g_PlayArea[0][tmpCol]=PLAYAREA_EMPTY_COLOR; _Drawbox(tmpRow,tmpCol,PLAYAREA_EMPTY_COLOR); }
gain++; } }
//变更用户的相关情况 if(gain>0) { g_Player.Score+=(100*(gain*gain-gain+1)); //1:100;2:300;3:700;4:1300; if(g_Player.Score>PLAYER_MAX_SCORE) { g_Player.Power++; g_Player.Score %= (PLAYER_MAX_SCORE+1); }
ShowGameInfo(); } }
void UpdateSys() { //变更系统相关情况 if(g_Player.Power==g_NextLevelPower) { if(g_Player.Score>=g_NextLevelScore) { //变更级别 g_Level++; g_Level %= PLAYER_MAX_LEVEL; g_NextLevelScore+=(100*(g_Level*g_Level)+1000); if(g_NextLevelScore>PLAYER_MAX_SCORE) { g_NextLevelPower++; g_NextLevelScore%=(PLAYER_MAX_SCORE+1); }
//变更系统速度 KillTimer(g_hwnd,IDT_PLAY); SetTimer(g_hwnd, IDT_PLAY,1000/(g_Level+1),NULL);
} } }
BOOL NextBlock() { g_CurBlock=g_NextBlock; g_CurBlockColor=g_NextBlockColor; g_CurRow=0; g_CurCol=(PLAYAREA_WIDTH-Blocks[g_CurBlock].Width)/2; srand((unsigned)time(NULL)); g_NextBlock=rand()%g_BlockCount; g_NextBlockColor=RGB((rand()%4)*64+63,(rand()%4)*64+63,(rand()%4)*64+63); ShowNextBlock(); ShowCurBlock();
int row,col; for(row=0;row<=Blocks[g_CurBlock].Height;row++) { for(col=0;col<=Blocks[g_CurBlock].Width;col++) { if((Blocks[g_CurBlock].Elements & (1<<(row*(Blocks[g_CurBlock].Width+1)+col)))!=0) { if(g_PlayArea[g_CurRow+row][g_CurCol+col]!=PLAYAREA_EMPTY_COLOR) //如果所在位置已经不为空则Game Over。 { return FALSE; } } } }
return TRUE; }
void Stop() { if(g_Status!=GAME_STATUS_RUNNING) return; KillTimer(g_hwnd,IDT_PLAY); g_Status=GAME_STATUS_STOPPED; ShowGameInfo(); }
void Down() { if(g_Status!=GAME_STATUS_RUNNING) return;
//g_GDI->Drawbox(0,g_Env.ClientHeight,60,20,BORDER_STYLE_FLAT,INNER_STYLE_SOLID); //g_GDI->TextOut(10, g_Env.ClientHeight-30,"Downning!",9); if(CanMoveDown()==TRUE) { //BeginPaint(g_hwnd,NULL); HideCurBlock(); _Down(); ShowCurBlock(); //ValidateRect(g_hwnd,NULL); //UpdateWindow(g_hwnd); } else { _Bottom(); } }
void _Bottom() {
//把当前方块映射到游戏区域中 MapCurBlockToPlayArea(); //检查是否有可消行,变更用户得分 Gain(); //检查游戏级别是否需要提高 UpdateSys(); //设置当前方块为下一个方块,并重新产生一个下一方块 if(NextBlock()==FALSE) { //如果下一个方块顶死应该Game Over。 Stop(); //首先停止游戏。 //然后检查最高分,记录到排行榜。 } ShowGameInfo();
}
void Bottom() { if(g_Status!=GAME_STATUS_RUNNING) return; while(CanMoveDown()==TRUE) { HideCurBlock(); _Down(); ShowCurBlock(); } _Bottom(); }
void Pause() { if(g_Status!=GAME_STATUS_RUNNING) return; //clear timer. KillTimer(g_hwnd, IDT_PLAY); g_Status=GAME_STATUS_PAUSED; ShowGameInfo(); }
//写到Resume,觉得应该引入一个变量,用来标识游戏是否已经开始,是否是继续游戏,而Start()只能算作重新从头开始。 void Resume() { if(g_Status!=GAME_STATUS_PAUSED) return; SetTimer(g_hwnd, IDT_PLAY,1000/(g_Level+1),NULL); g_Status=GAME_STATUS_RUNNING; ShowGameInfo();
}
void Start() { if(g_Status!=GAME_STATUS_STOPPED) return;
int row,col;
for(row=0;row<PLAYAREA_HEIGHT;row++) { for(col=0;col<PLAYAREA_WIDTH;col++) { g_PlayArea[row][col]=PLAYAREA_EMPTY_COLOR; } }
//产生当前方块及下一个方块 srand((unsigned)time(NULL)); g_CurBlock=rand()%g_BlockCount; g_CurBlockColor=RGB((rand()%4)*64+63,(rand()%4)*64+63,(rand()%4)*64+63);
g_NextBlock=rand()%g_BlockCount; g_NextBlockColor=RGB((rand()%4)*64+63,(rand()%4)*64+63,(rand()%4)*64+63);
//决定当前方块的位置 g_CurRow=0; g_CurCol=(PLAYAREA_WIDTH-Blocks[g_CurBlock].Width)/2;
//初始化系统信息 g_Level=0; //将来可以通过用户定制现在级别 g_NextLevelPower=0; g_NextLevelScore=1000;
//初始化用户信息 strcpy(g_Player.Name, PLAYER_DEFAULT_NAME); g_Player.Power=0; g_Player.Score=0;
//然后开始游戏 Render(); //重新绘制界面
g_Status=GAME_STATUS_RUNNING; SetTimer(g_hwnd, IDT_PLAY,(10-g_Level)*100,NULL); ShowNextBlock(); ShowCurBlock(); ShowGameInfo(); }
void CaculateEnv() { RECT rect;
GetClientRect(g_hwnd, &rect); //得到当前窗口的大小 //更改环境变量 g_Env.ClientHeight=rect.bottom-rect.top+1; g_Env.ClientWidth=rect.right-rect.left+1;
g_Env.BorderSize=3; g_Env.Spacing=1; g_Env.IsNextShown=true;
//得到各区域坐标 //游戏区域 g_Env.PlayAreaX=g_Env.ClientWidth*3/10+g_Env.BorderSize; g_Env.PlayAreaY=g_Env.BorderSize;
g_Env.SingleHeight = (g_Env.ClientHeight-g_Env.PlayAreaY*2-g_Env.BorderSize*2-g_Env.Spacing)/PLAYAREA_HEIGHT-g_Env.Spacing; g_Env.SingleWidth = (g_Env.ClientWidth - g_Env.PlayAreaX*2-g_Env.BorderSize*2-g_Env.Spacing)/PLAYAREA_WIDTH-g_Env.Spacing;
//下一个区域 g_Env.NextX = g_Env.ClientWidth*17/20-g_Env.BorderSize-g_Env.Spacing*5/2-g_Env.SingleWidth*2; g_Env.NextY = g_Env.BorderSize*2;
//UpdateWindow(g_hwnd);
}
VOID Render() { //绘制整个界面 char s[200];
//清除所有 g_GDI->Clear(RGB(0x80,0x80,0x80));
//绘制图片 //g_GDI->DrawPic(g_Env.BorderSize*2,g_Env.BorderSize*2, g_Env.ClientWidth/5-g_Env.BorderSize*5,g_Env.ClientWidth/5-g_Env.BorderSize*5, "mydaughter.bmp"); //绘制Logo //g_GDI->DrawPic(g_Env.BorderSize*2,rect.bottom-g_Env.BorderSize*2,100,100, "logo.bmp");
//绘制游戏区域 g_GDI->SetColor(0); g_GDI->Drawbox(g_Env.PlayAreaX,g_Env.PlayAreaY,(g_Env.SingleHeight+g_Env.Spacing)*PLAYAREA_HEIGHT+g_Env.Spacing+g_Env.BorderSize*2,(g_Env.SingleWidth+g_Env.Spacing)*PLAYAREA_WIDTH+g_Env.Spacing+g_Env.BorderSize*2,BORDER_STYLE_FLAT,INNER_STYLE_SOLID);
int row,col; for(row=0;row<PLAYAREA_HEIGHT;row++) { for(col=0;col<PLAYAREA_WIDTH;col++) { if(g_PlayArea[row][col]!=PLAYAREA_EMPTY_COLOR) { _Drawbox(row,col,g_PlayArea[row][col]); } } } //绘制当前方块 if(g_Status!=GAME_STATUS_STOPPED) { ShowNextBlock(); ShowCurBlock(); } //绘制Next
//绘制各按钮 strcpy(s,"[Enter]: Start/Resume"); g_GDI->TextOut(g_Env.ClientWidth*3/4,g_Env.ClientHeight/2,s,(int)strlen(s)); strcpy(s,"[Pause]: Pause"); g_GDI->TextOut(g_Env.ClientWidth*3/4,g_Env.ClientHeight/2+20,s,(int)strlen(s)); strcpy(s,"↑: 翻转方块"); g_GDI->TextOut(g_Env.ClientWidth*3/4,g_Env.ClientHeight/2+40,s,(int)strlen(s)); strcpy(s,"↓: 向下落一格"); g_GDI->TextOut(g_Env.ClientWidth*3/4,g_Env.ClientHeight/2+60,s,(int)strlen(s)); strcpy(s,"←: 左移"); g_GDI->TextOut(g_Env.ClientWidth*3/4,g_Env.ClientHeight/2+80,s,(int)strlen(s)); strcpy(s,"→: 右移"); g_GDI->TextOut(g_Env.ClientWidth*3/4,g_Env.ClientHeight/2+100,s,(int)strlen(s)); strcpy(s,"[Space]: 置底"); g_GDI->TextOut(g_Env.ClientWidth*3/4,g_Env.ClientHeight/2+120,s,(int)strlen(s)); strcpy(s,"[ESC]: Stop Game"); g_GDI->TextOut(g_Env.ClientWidth*3/4,g_Env.ClientHeight/2+140,s,(int)strlen(s));
//绘制当前状态 ShowGameInfo();
//以下为调试信息 //sprintf(s,"ClientWidth:%d",g_Env.ClientWidth); //g_GDI->TextOut(0,0,s,(int)strlen(s)); //sprintf(s,"ClientHeight:%d",g_Env.ClientHeight); //g_GDI->TextOut(0,20,s,(int)strlen(s)); //sprintf(s,"PlayAreaX:%d",g_Env.PlayAreaX); //g_GDI->TextOut(0,40,s,(int)strlen(s)); //sprintf(s,"PlayAreaY:%d",g_Env.PlayAreaY); //g_GDI->TextOut(0,60,s,(int)strlen(s)); //sprintf(s,"SingleHeight:%d",g_Env.SingleHeight); //g_GDI->TextOut(0,80,s,(int)strlen(s)); //sprintf(s,"SingleWidth:%d",g_Env.SingleWidth); //g_GDI->TextOut(0,100,s,(int)strlen(s)); }
LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_TIMER: Down(); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; case WM_ACTIVATE: if(wParam==WA_INACTIVE) { Pause(); } break; case WM_SIZE: if(wParam!=SIZE_MINIMIZED) { CaculateEnv(); if(wParam==SIZE_RESTORED) { Render(); } //UpdateWindow(hWnd); } return 0; case WM_PAINT: Render(); ValidateRect(hWnd, NULL); //呵呵,目前还不能去掉该行 return 0; //case WM_SYSKEYDOWN: case WM_KEYDOWN: switch(wParam) { case VK_UP: Turn(); break; case VK_DOWN: Down(); break; case VK_LEFT: MoveLeft(); break; case VK_RIGHT: MoveRight(); break; case VK_SPACE: Bottom(); break; case VK_RETURN: if(g_Status==GAME_STATUS_PAUSED) { Resume(); } else { Start(); } break; case VK_PAUSE: Pause(); break; //case VK_END: case VK_ESCAPE: Stop(); break; } } return DefWindowProc(hWnd,msg,wParam,lParam); }
//系统初始化 HRESULT Initialize() { //绑定当前窗口到自己的GDI g_GDI=new CCustomGDI(g_hwnd);
if(SUCCEEDED(LoadBlocks())) { return S_OK; }
return E_FAIL; }
//释放系统资源 void Cleanup() { //释放方块资源 ClearBlocks();
//释放GDI delete g_GDI; }
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { //创建窗体 WNDCLASS wndclass={0, MsgProc, 0L, 0L, hInstance, NULL,NULL,NULL,NULL,"Els"}; RegisterClass(&wndclass); g_hwnd=CreateWindow("Els","Els v1.0.0.0", WS_OVERLAPPEDWINDOW,100,100,640,480,GetDesktopWindow(),NULL,wndclass.hInstance,NULL);
//初始化 if(SUCCEEDED(Initialize())) { ShowWindow(g_hwnd,SW_SHOWDEFAULT); UpdateWindow(g_hwnd);
//进入Window消息循环 MSG msg; while(GetMessage(&msg,NULL,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); } }
Cleanup();
UnregisterClass("Els", wndclass.hInstance); return 0; } //-------------------------------------------------------------------------------------------------------- 
|