第一次真正意义上的用VC++实现的一个完整的Win32程序-俄罗斯方块

类别:VC语言 点击:0 评论:0 推荐:

 
第一次真正意义上的用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;
}
//--------------------------------------------------------------------------------------------------------

本文地址:http://com.8s8s.com/it/it259.htm