///////////////////////////////////////////////////////////////////////////////////////////////////
// 程序:Tetris的DirectX版本 //
// 文件:Tetris的游戏逻辑主程序文件 //
// 版本:Version1.0 //
// 作者:游戏人间 //
// 时间:2005年12月11日 //
///////////////////////////////////////////////////////////////////////////////////////////////////
#include "dxtgame.h"
// 全局变量////////////////////////////////////////////////////////////////////////////////////////
// directdraw stuff
LPDIRECTDRAW7 lpdd = NULL; // dd object
LPDIRECTDRAWSURFACE7 lpddsprimary = NULL; // dd primary surface
LPDIRECTDRAWSURFACE7 lpddsback = NULL; // dd back surface
LPDIRECTDRAWPALETTE lpddpal = NULL; // a pointer to the created dd palette
LPDIRECTDRAWCLIPPER lpddclipper = NULL; // dd clipper
DDSURFACEDESC2 ddsd; // a direct draw surface description struct
DDBLTFX ddbltfx; // used to fill
DDSCAPS2 ddscaps; // a direct draw surface capabilities struct
HRESULT ddrval; // result back from dd calls
DWORD g_dwPixelFormat; // 屏幕色彩位数
int g_xClientTopLeft; // 窗口客户区左上角在屏幕的x坐标位置
int g_yClientTopLeft; // 窗口客户区左上角在屏幕的y坐标位置
DWORD g_dwStartClockCount = 0;// 定时
UCHAR * g_pbDoubleBuffer; // 双缓冲
int g_xScreen; // 屏幕宽
int g_yScreen; // 屏幕高
int g_xScreenByte; // 屏幕x方向每行所需字节数
int g_iClientStart; // 窗口客户区在双缓冲中的开始位置
int g_iClientByte; // 窗口客户区每行所需字节数
CDiamondPTR g_pdNow = NULL; // 指向当前的DIAMOND
CDiamondPTR g_pdNext = NULL; // 指向当前DIAMOND执行平移、下移、旋转动作后的DIAMOND
int g_iGridColor; // 小方块显示的颜色值
int g_iInput; // 接收输入
int g_iDifficultTime; // 游戏难度时间等级
bool g_bDrawScreen= false; // 是否应该进行屏幕绘制,只有游戏逻辑被执行后,才对屏幕进行绘制
bool g_bLeftUp = true; // 左方向键被放开
bool g_bRightUp = true; // 右方向键被放开
bool g_bUpUp = true; // 旋转键被放开
int g_iLeftDownTime; // 左移键被按下的时间间隔
int g_iRightDownTime; // 右移键被按下的时间间隔
int g_iMark = 0; // 分数
int g_iaTetris[NUM_GRID_HEIGHT][NUM_GRID_WIDTH];// 整个游戏区域的方块填充数组,从方块左上角开始,若当前位置已有方块
// 填充,相应的数组位置值为1,否则为0
// 全局函数定义 //////////////////////////////////////////////////////////////////////////////////////
int GameMain(void *parms, int num_parms)
{
// 游戏主循环,开始运行
// 若窗口已经被关闭,不应再执行任何屏幕写动作,GameMain立即返回
if(g_bWindowClosed)
return(1);
// 若按下ESC键,发送WM_CLOSE消息,并立即返回
if (KEYDOWN(VK_ESCAPE))
{
SendMessage(main_window_handle,WM_CLOSE,0,0);
g_bWindowClosed=true;
}
// 游戏仅运行于16位、24位或32位颜色深度
if(g_dwPixelFormat<=8)
return(1);
// 若窗口失去焦点,游戏循环暂不再执行下一步计算,进程睡眠一定时间后返回
if(!g_bWinFocus)
{
// 保持每秒60此执行游戏循环
int iIntervalTime=GetTickCount()-g_iSleepTime;
if(iIntervalTime < PER_FRAME_TIME)
{
Sleep(PER_FRAME_TIME-iIntervalTime);
}
return(1);
}
// 若窗口被移动,重新计算窗口位置
if(g_bWinMove)
{
// 初始化以字节计算的窗口客户区在双缓冲中的开始位置
g_iClientStart=g_xScreenByte*g_yClientTopLeft+g_xClientTopLeft*g_dwPixelFormat/8;
}
// 若窗口被移动或曾经失去焦点,
if(g_bWinMove || g_bKillFocus)
{
// 绘制备注信息
if(g_iGameState == GAME_STATE_FREE)
{
DrawScreen();
}
g_bWinMove=false;
g_bKillFocus=false;
}
// 检查键盘输入
CheckInput();
if(g_iGameState == GAME_STATE_START)
{
GameStart();
}
else if(g_iGameState == GAME_STATE_RUN)
{
GameRun();
}
else if(g_iGameState == GAME_STATE_END)
{
GameEnd();
}// 结束if语句
// 所执行了游戏逻辑,即刷新游戏屏幕
if(g_bDrawScreen)
{
if(g_pdNow->bState)
{
LocationDiamond();
}
// 游戏逻辑被执行,清空时间难度,从新计算该时间
g_iDifficultTime=GetTickCount();
DrawScreen();
// 游戏逻辑已经绘制到屏幕,置屏幕标志为已绘制
g_bDrawScreen=false;
}
// 保持每秒60此执行游戏循环
int iIntervalTime=GetTickCount()-g_iSleepTime;
if(iIntervalTime < PER_FRAME_TIME)
{
Sleep(PER_FRAME_TIME-iIntervalTime);
}
// return success or failure or your own return code here
return(0);
} // end Game_Main
////////////////////////////////////////////////////////////
int GameInit(void *parms, int num_parms)
{
// this is called once after the initial window is created and
// before the main event loop is entered, do all your initialization
// here
bWinActive = true;
// create IDirectDraw interface 7.0 object and test for error
if (FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL)))
return(0);
// set cooperation to full screen
if (FAILED(lpdd->SetCooperativeLevel(main_window_handle,DDSCL_NORMAL)))
{
// error
return(1);
} // end if
DD_INIT_STRUCT(ddsd);
// enable valid fields
ddsd.dwFlags = DDSD_CAPS;
// request primary surface
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
// create the primary surface
if (FAILED(lpdd->CreateSurface(&ddsd, &lpddsprimary, NULL)))
{
// error
return(1);
} // end if
DDPIXELFORMAT ddpixelformat;
DD_INIT_STRUCT(ddpixelformat);
//取屏幕像素格式
lpddsprimary->GetPixelFormat(&ddpixelformat);
g_dwPixelFormat=ddpixelformat.dwRGBBitCount;
// 分配双缓冲内存空间
g_xScreen=GetSystemMetrics(SM_CXSCREEN);
g_yScreen=GetSystemMetrics(SM_CYSCREEN);
g_xScreenByte=g_xScreen*g_dwPixelFormat/8;
g_pbDoubleBuffer=new UCHAR[g_xScreen*g_yScreen*g_dwPixelFormat/8];
// 双缓冲分配失败
if(g_pbDoubleBuffer==NULL)
return(1);
// 初始化窗口客户区每行所需字节数
g_iClientByte=g_iTetrisWidth*g_dwPixelFormat/8;
// 初始化以字节计算的窗口客户区在双缓冲中的开始位置
g_iClientStart=g_xScreenByte*g_yClientTopLeft+g_xClientTopLeft*g_dwPixelFormat/8;
// 为当前CDiamond对象,分配内存空间,初始化属性值
g_pdNow=(CDiamondPTR)new CDiamond;
g_pdNow->poly.vlist=(VERTEX2DF_PTR)new VERTEX2DF[NUM_GRID_MAX];
g_pdNow->poly.state=1;
g_pdNow->poly.color=GRID_COLOR;
g_pdNow->poly.xv=0;
g_pdNow->poly.yv=0;
g_pdNow->bState=0;
// 为执行平移、下移、旋转动作后的CDiamond对象,分配内存空间,初始化属性值
g_pdNext=(CDiamondPTR)new CDiamond;
g_pdNext->poly.vlist=(VERTEX2DF_PTR)new VERTEX2DF[NUM_GRID_MAX];
g_pdNext->poly.state=1;
g_pdNext->poly.color=GRID_COLOR;
g_pdNext->poly.xv=0;
g_pdNext->poly.yv=0;
g_pdNext->bState=0;
// 游戏屏幕每个小方块均置未填充状态
for(int row=0;row < NUM_GRID_HEIGHT;row++)
for(int col=0;col < NUM_GRID_WIDTH;col++)
g_iaTetris[row][col]=0;
// 初始化cos和sin值
float rad;
for(int ang=0;ang<360;ang++)
{
rad=(float)ang*3.1415926/180;
g_cosLook[ang]=cos(rad);
g_sinLook[ang]=sin(rad);
} // 结束cos和sin值初始化
// 绘制备注信息
DrawScreen();
// 等待游戏开始
g_iGameState=GAME_STATE_FREE;
// return success or failure or your own return code here
return(0);
} // end Game_Init
/////////////////////////////////////////////////////////////
int GameShutdown(void *parms, int num_parms)
{
// this is called after the game is exited and the main event
// loop while is exited, do all you cleanup and shutdown here
// now the primary surface
// 释放当前CDiadmond对象内存空间
if(!g_pdNow)
{
if(!g_pdNow->poly.vlist)
delete []g_pdNow->poly.vlist;
delete g_pdNow;
}
// 释放执行平移、下移、旋转动作后的CDiadmond对象内存空间
if(!g_pdNext)
{
if(!g_pdN
评论0