为这个程序花了我三天(当然不是24小时拉呵呵),由于很久没有编程了,所以拿这个小游戏练习一下,让大家见笑了,我觉得自己在程序逻辑方面处理的还可以,但是结构上由于经验不足还是有很多不足之处,而且由于是简单的利用windows api来编程,画面效果可想而知了。我敢于把这个程序贴出来,就算是为了自己开博放个炮仗吧,虽然“声音”小了点。。。
还是来说说我的程序,编程前我试着写了个游戏文档,算是用来指导一下自己的后续行动吧,具体如下:
贪吃蛇游戏文档
1. 游戏描述:该游戏属于既可以单人游戏也可以双人对战的动作游戏。
2. 单人游戏规则:
1) 移动规则:蛇可以向四个方向移动,但是方向不能瞬间移动到相反的方向。
2) 米的出现规则:米在随机在场景中生成。
3) 增长长度规则:蛇一旦吃到米,就增长长度。
4) 失败条件:蛇一旦碰到场景的墙壁,或者蛇头碰到蛇身即告死亡。
5) 胜利条件:吃米吃到一定程度就可以胜利。
3. 双人游戏规则:
1) 移动规则:与单人游戏相同。
2) 米的出现规则:与单人游戏相同。
3) 增长长度规则:与单人游戏相同。
4) 失败条件:蛇一旦碰到场景的墙壁,或者蛇头碰到蛇身即告死亡,己方蛇头碰到对方蛇身也告死亡。
5) 胜利条件:一方吃米比另一方先到某一程度就可以胜利。
4.设计进程
a.单人游戏设计
1)场景的设计
为了方便实现,我采用蛇与场景网格匹配的设计,也就是以蛇的单节size为单位来对场景进行分割。我设计场景大小为400*300,蛇的size为10*10,也就是说场景被分割成40*30=1200格。而蛇的行动一次行进一格。
2)蛇的建模
首先我设计蛇的前进为以格子为单位的前进方式,而蛇的单节大小也与格子匹配,那么我就设计一个队列来作为蛇的模型,而蛇的前进方式也是以队列进出的方式来实现,这是很好理解的,因为每一次渲染都是依次读取蛇的每一节并绘图,那么当蛇行进到下一步时,必然是最后一格的蛇尾消失,而蛇头根据既定方向来到下一格的位置上,正好可以将蛇头作为队尾,蛇头作为队头,进行头进尾出操作。
3)蛇的渲染
其余诸如米与场景的渲染比较简单,所以这里就单论蛇的渲染,从上文可知我把蛇的设计成为一个队列,而蛇的运动通过队列的出入队来实现,队列的入队操作负责控制整个蛇身的运动方向,同时也可以将蛇头的运动轨迹依次传送到蛇尾,而出队操作则负责蛇的长度显示。
蛇的绘图则可以通过依次读取蛇身所在格子的左上坐标来实现。
4)米的生成
米的大小与蛇的单节大小相同,米的生成应有一定的随机性质,那么可以使用rand()函数产生两个随机数字作为长和宽的坐标再用求余进行范围的限定。
5)蛇吃米后的操作
在这里主要是考虑是将增加后的节点以怎样的方式入队以让蛇的变化符合人的逻辑习惯,首先,蛇吃米的判定在蛇头完全覆盖米后立刻生效(因为逻辑行动总在渲染之前),那么可以选择立刻把吃米后蛇的变化表现出来,也可以选择让蛇消化一段时间然后再在蛇尾上增加(即把增加点的坐标设为蛇头,在经历一条蛇身的长度后才显示蛇的长度变化)我选择后者,毕竟什么动物都需要消化嘛
6) 失败的判定
首先,最简单的是碰壁失败,只需设计一段边界碰撞检测代码即可(用if语句实现),而蛇身的碰撞就需要花些心思,因为如果仅仅判断蛇头是否与蛇身体各个部分重合,必然要与吃米冲突,因为吃米我首先将在蛇头插入一个与蛇头坐标一样的新蛇头(为了实现消化的效果),那么在失败判定时必然会产生误判,解决方案可以有两个,一个是在碰身体的判断中忽略前三节,因为,蛇头绝对不可能与前三节产生碰撞,另一个方案是在遍历蛇身的同时考虑到蛇头仅仅不与它的第二节进行比较,我用了后一个方案,因为它实现起来不罗嗦。
7) 胜利的判定
很简单,只要在场景类中添加一个分数成员,吃一次米即增加,然后每一游戏循环都检验它的值。
8) 类的设计
考虑到游戏需要在大局上可能有诸如时间,分数,胜负判断等要求,我首先确定设计一个场景类来封装相关参数与操作。其次,蛇的操作与属性都很多,必然需要用一个类来封装(双人游戏时要考虑用接口类来实现)。最后,米也需要一定的操作(如定位和显示),也应封装为一类。综上所述,我准备用3个类来实现最后的单人游戏设计,这样一旦想到什么就可以根据类别来添加,比较方便。
b.双人游戏设计
1)类的设计
可以从一个类中定义两个实体,即一个甲蛇一个乙蛇。两条蛇共享同样的操作,但是却有着各自的属性。
2)胜利的判定
为每个蛇都单独设置一个吃米值,谁先到达一定值谁就获得胜利。
3)失败的判定
与单人游戏设计唯一增加的一条规则是:当双方蛇头对碰时,打平,蛇头撞对方蛇身或墙体时,失败。
根据以上的文档算是写出来了这么个小游戏,虽然结构上很不完善,但是本着向高手学习的目的,也就顾不得这么多了,说实话,在大学这几年我一直没有培养出好的编程素养与习惯,老师吗也仅仅能在理论上帮助我,一直很希望能得到真正高手的指导,如果有这样GGJJ愿意赐教,小弟先在这里谢过了。
以下是游戏代码,在VC6.0环境下编写:
/*操作指南
单人游戏
W 上
S 下
A 左
D 右
Ctrl 确定开始
双人游戏
方向键对应方向
Ctrl 确定开始
*/
#include "windows.h"
#include <stdio.h>
#include <stdlib.h>
/*---------0.以下为定义区--------------*/
#define UP 0 //方向定义
#define DOWN 1
#define LEFT 2
#define RIGHT 3
#define SNK_SIZE 10 //蛇的形态相关数据
#define SNK_INIT_LENGHT 5
#define FDSHOW 1 //食物的状态
#define FDHIDE 0
#define WINSCORE 10 //胜利的最终得分
#define FORONEPLAYER 1 //游戏模式的分类
#define FORTWOPLAYER 2
#define PLAY_1 1 //不同游戏玩家的代号
#define PLAY_2 2
#define PLAY_1_DEAD 1 //不同游戏玩家死亡的状态分类
#define PLAY_2_DEAD 2
#define STARTSCENE 0 //游戏进程的分类
#define BEFOREGAMESCENE 1
#define GAMESCENE 2
#define WINSCENE 3
#define LOSESCENE 4
#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0) //用来判断是否按下键盘上的特定键的宏定义
#define KEYUP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1) //用来判断是否释放键盘上的特定键的宏定义
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM); //窗口过程,用来初始化以及运行窗口
struct node //节点结构体,用来构成链式队列
{
POINT s_p;
node* next;
};
struct queue_snake //队列结构体
{
node* front;
node* rear;
}*QUEUE;
class Food; //将Food以及Scene的类优先声明是因为在snake类中存在前两个类的友员函数
class Scene;
class snake //snake类主要用来存放蛇的属性以及相关操作,比如蛇的初始化,蛇的移动,蛇的死亡等
{
private:
int snakelength; //蛇的长度,用来标识蛇的节点构成数
int snakevelocity; //蛇的移动速度
int snakedirection; //蛇的移动方向
POINT start_pos; //蛇的起始位置(在这里要声明的是,本程序默认将10*10的方块作为游戏的地图单元,因此这里给出方块左
//上角的坐标,通过该坐标来确定具体是哪个方块)
POINT current_pos; //蛇的当前位置
queue_snake s; //蛇的队列,相当重要,是最基本的数据结构
int snknum; //蛇的编号,是在双人模式中用来确定具体实体对象是玩家1还是玩家2的标志
int snkeatnum; //蛇的吃食物的数量
COLORREF color; //蛇的颜色
public:
snake(); //蛇的构造函数
snake(int, int, int, int,COLORREF);//蛇的重载构造函数,专为了实现双人模式而设计
~snake(); //蛇的析构函数
void Insert_queue(POINT); //插入节点入蛇队列(可以不放在蛇的类中,仅仅是一个工具函数)
POINT Delete_queue(); //删除节点出队列(同上)
void SNKDraw(HDC); //蛇的画面表现
int SNKGetDirection(); //蛇的方向设置
void SNKSetDirection(int);
int SNKGeteatnum(); //蛇的进食数量设置
void SNKSeteatnum(int);
int SNKGetVelocity(); //蛇的速度设置
void SNKSetVelocity(int);
COLORREF SNKGetcolor(); //蛇的颜色设置
void SNKSetcolor(COLORREF);
int SNKDead(); //蛇的死亡判定逻辑
void SNKMove(); //蛇的移动判定逻辑
void SNKEat(Food&, Scene&);//蛇的进食判定逻辑
};
class Food //Food类用来定义Food的属性与操作
{
private:
POINT fdposition; //食物的出现位置
int fdstate; //食物的显示状态
int fdflashflag; //食物的闪烁,有色与透明的切换
public:
Food(); //食物的构造函数
void FDposinit(); //食物的位置初始化
void FDSetpos(POINT); //食物位置属性的设置(用于当前食物被吃后新食物的生成)
void FDDraw(HDC); //食物的图像显示
friend void snake::SNKEat(Food&, Scene&);//设置友员函数,具体看snake类中相关实现
};
class Scene //场景类,用来宏观的控制整个游戏的进程,比如纪录得分,判断游戏的成败,设置场景的表现等,
//同时也开以获取如FPS等信息
{
private:
int scnscore; //记录比赛得分
COLORREF scntextcolor; //文字颜色
int scnloop; //通过循环次数的控制来改变蛇的速度
int scnplaymode; //游戏模式的标志
int scngamestep; //当前游戏状态
int scndeadflag; //用来判定是双人模式是哪个玩家死亡
//以下属性用来测试fps
int scnframe;
int scnfps;
DWORD scnpretime;
DWORD scnnowtime;
public:
Scene(); //场景类
void SCNShowstartsceen(HDC);//用来显示起始场景
void SCNBeforestart(HDC); //用来显示预备场景
void SCNGamescene(HDC); //用来显示主游戏场景
void SCNWaitstart(HDC); //。。。
int SCNWinandrestart(HDC); //判定游戏胜利结束,玩家1胜利返回1,玩家2胜利返回2,否则返回0
int SCNLoseandrestart(HDC); //判定游戏以失败结束,失败返回1,否则返回0(用于单人游戏)
void SCNaddscore(); //用来增加分数(仅用于单人模式)
int SCNGetscore(); //获取分数
void SCNDraw(HDC); //背景的图像显示
void SCNlevel(snake&); //场景的等级判定
void SCNSetmode(int); //场景的模式设置
int SCNGetmode();
void SCNSetstepflg(int); //游戏进程的模式设置
int SCNGetstepflg();
void SCNSetdeadflg(int); //游戏胜利者的设置
int SCNGetdeadflg();
void SCNfpsdraw(HDC , DWORD); //用来显示游戏的fps
friend void snake::SNKEat(Food&, Scene&); //...
};
void Manipulation(WPARAM); //游戏键盘设置
/*---------1.以下为主程序区域--------------*/
snake snkmain(RIGHT, 200, 150, PLAY_1, RGB(255, 255, 0));
snake snksec(RIGHT, 200, 440, PLAY_2, RGB(0, 255, 255));
Food fdmain;
Scene scnmain;
HPEN hPen_snake;
HBRUSH hBrush_snake[3];
char scoreBoard[5];
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )
{
/*------------1.1以下为窗口的初始化与建立-----------------------*/
static TCHAR szAppName[] = TEXT("HelloWIn");
HWND hwnd;
HDC hdc;
MSG msg;
WNDCLASS wndclass;
wndclass.hInstance = hInstance;
wndclass.lpfnWndProc = WndProc;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(hInstance, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
if(!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("Failed!"), szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName
,TEXT("The hello Program")
,WS_OVERLAPPEDWINDOW
,0
,0
,800
,600
,NULL
,NULL
,hInstance
,NULL);
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
/*--------------------1.2以下为蛇的数据初始化区---------------------------------*/
hPen_snake = CreatePen(PS_SOLID, 1 ,RGB(0, 0, 0));
hBrush_snake[0] = CreateSolidBrush(RGB(0, 0, 0));
hBrush_snake[1] = CreateSolidBrush(RGB(255, 255, 255));
hBrush_snake[2] = CreateSolidBrush(RGB(255, 255, 0));
while (TRUE)
{
DWORD start_time = GetTickCount(); //初始化开始时间
if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
else
{
hdc = GetDC(hwnd);
scnmain.SCNfpsdraw(hdc, start_time);
switch(scnmain.SCNGetstepflg()) //总的游戏控制
{
case STARTSCENE:
scnmain.SCNShowstartsceen(hdc);
break;
case BEFOREGAMESCENE:
scnmain.SCNBeforestart(hdc);
break;
case GAMESCENE:
scnmain.SCNGamescene(hdc);
break;
case WINSCENE:
scnmain.SCNWinandrestart(hdc);
break;
case LOSESCENE:
scnmain.SCNLoseandrestart(hdc);
break;
default:
break;
}
ReleaseDC(hwnd, hdc);
}
scnmain.SCNlevel(snkmain);
while((GetTickCount() - start_time) < 30); //通过控制开始时间与当前时间的差来控制游戏显示fps
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
switch(message)
{
case WM_CREATE:
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps);
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_KEYDOWN:
if(wParam == VK_ESCAPE)
SendMessage(hwnd, WM_CLOSE, 0, 0);
Manipulation(wParam);
return 0;
case WM_DESTROY:
DeleteObject(hPen_snake);
for(int j = 0;j < 2; j++)
{
DeleteObject(hBrush_snake[j]);
}
snkmain.~snake();
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
snake::snake(int snkdir, int snkposx, int snkposy, int snkplaynum, COLORREF rgb)
{
this->snknum = snkplaynum;
this->snakedirection = snkdir;
this->snakelength = 0;
this->snakevelocity = 1;
this->start_pos.x = snkposx;
this->start_pos.y = snkposy;
this->s.front = this->s.rear = NULL;
this->color = rgb;
int i;
POINT temp;
for(i = 0; i < SNK_INIT_LENGHT; i++)
{
temp.x = this->start_pos.x + SNK_SIZE * i;
temp.y = this->start_pos.y;
Insert_queue(temp);
}
this->current_pos.x = this->s.rear->s_p.x;
this->current_pos.y = this->s.rear->s_p.y;
}
snake::snake()
{
this->snknum = PLAY_1;
this->snakedirection = RIGHT;
this->snakelength = 0;
this->snakevelocity = 1;
this->start_pos.x = 200;
this->start_pos.y = 150;
this->s.front = this->s.rear = NULL;
this->snkeatnum = 0;
int i;
POINT temp;
for(i = 0; i < SNK_INIT_LENGHT; i++)
{
temp.x = this->start_pos.x + SNK_SIZE * i;
temp.y = this->start_pos.y;
Insert_queue(temp);
}
this->current_pos.x = this->s.rear->s_p.x;
this->current_pos.y = this->s.rear->s_p.y;
}
void snake::Insert_queue(POINT p)
{
node* temp;
if(this->snakelength == 0 && this->s.front == NULL)
{
temp = new node;
temp->s_p.x = p.x;
temp->s_p.y = p.y;
this->s.front = this->s.rear = temp;
this->snakelength++;
}
else
{
temp = new node;
temp->s_p.x = p.x;
temp->s_p.y = p.y;
this->s.rear->next = temp;
this->s.rear = temp;
this->snakelength++;
}
}
snake::~snake()
{
int i;
node* temp;
for(i = 0; i < this->snakelength; i++)
{
// temp = this->s.front;
// this->s.front = this->s.front->next;
// delete temp;
}
}
POINT snake::Delete_queue()
{
POINT temp;
node* t;
if(this->s.front == this->s.rear)
{
temp.x = this->s.front->s_p.x;
temp.y = this->s.front->s_p.y;
delete this->s.front;
}
else
{
temp.x = this->s.front->s_p.x;
temp.y = this->s.front->s_p.y;
t = this->s.front;
this->s.front = this->s.front->next;
delete t;
}
this->snakelength--;
return temp;
}
void snake::SNKDraw(HDC hdc)
{
int i;
i = 0;
hBrush_snake[2] = CreateSolidBrush(this->color);
node* temp;
temp = this->s.front;
for(i = 0; i < this->snakelength; i++)
{
SelectObject(hdc, hBrush_snake[i % 2 + 1]);
SelectObject(hdc, hPen_snake);
Rectangle(hdc, temp->s_p.x, temp->s_p.y, temp->s_p.x + SNK_SIZE, temp->s_p.y + SNK_SIZE);
temp = temp->next;
}
}
void snake::SNKMove()
{
int i;
i = 0;
POINT temp;
switch(this->snakedirection)
{
case UP:
this->Delete_queue();
temp.x = this->s.rear->s_p.x;
temp.y = this->s.rear->s_p.y;
temp.y -= SNK_SIZE * this->snakevelocity;
Insert_queue(temp);
break;
case DOWN:
this->Delete_queue();
temp.x = this->s.rear->s_p.x;
temp.y = this->s.rear->s_p.y;
temp.y += SNK_SIZE * this->snakevelocity;
Insert_queue(temp);
break;
case LEFT:
this->Delete_queue();
temp.x = this->s.rear->s_p.x;
temp.y = this->s.rear->s_p.y;
temp.x -= SNK_SIZE * this->snakevelocity;
Insert_queue(temp);
break;
case RIGHT:
this->Delete_queue();
temp.x = this->s.rear->s_p.x;
temp.y = this->s.rear->s_p.y;
temp.x += SNK_SIZE * this->snakevelocity;
Insert_queue(temp);
break;
default:
break;
}
this->current_pos.x = this->s.rear->s_p.x;
this->current_pos.y = this->s.rear->s_p.y;
}
int snake::SNKDead()
{
node* temp;
if(scnmain.SCNGetmode() == FORTWOPLAYER)
{
if(this->snknum == PLAY_1)
{
temp = this->s.front;
if( this->current_pos.x < 200 || this->current_pos.x > 600 - SNK_SIZE
|| this->current_pos.y < 150 || this->current_pos.y > 450 - SNK_SIZE)
return PLAY_1_DEAD;
while(temp != this->s.rear)
{
if(temp->s_p.x == this->s.rear->s_p.x
&& temp->s_p.y == this->s.rear->s_p.y
&& temp->next != this->s.rear)//pay attention
return PLAY_1_DEAD;
temp = temp->next;
}
temp = snksec.s.front;
while(temp != snksec.s.rear)
{
if(temp->s_p.x == this->s.rear->s_p.x
&& temp->s_p.y == this->s.rear->s_p.y
&& temp->next != this->s.rear)//pay attention
return PLAY_1_DEAD;
temp = temp->next;
}
}
else
{
temp = this->s.front;
if( this->current_pos.x < 200 || this->current_pos.x > 600 - SNK_SIZE
|| this->current_pos.y < 150 || this->current_pos.y > 450 - SNK_SIZE)
return PLAY_2_DEAD;
while(temp != this->s.rear)
{
if(temp->s_p.x == this->s.rear->s_p.x
&& temp->s_p.y == this->s.rear->s_p.y
&& temp->next != this->s.rear)//pay attention
return PLAY_2_DEAD;
temp = temp->next;
}
temp = snkmain.s.front;
while(temp != snkmain.s.rear)
{
if(temp->s_p.x == this->s.rear->s_p.x
&& temp->s_p.y == this->s.rear->s_p.y
&& temp->next != this->s.rear)//pay attention
return PLAY_2_DEAD;
temp = temp->next;
}
}
}
else
{
temp = this->s.front;
if( this->current_pos.x < 200 || this->current_pos.x > 600 - SNK_SIZE
|| this->current_pos.y < 150 || this->current_pos.y > 450 - SNK_SIZE)
return PLAY_1_DEAD;
while(temp != this->s.rear)
{
if(temp->s_p.x == this->s.rear->s_p.x
&& temp->s_p.y == this->s.rear->s_p.y
&& temp->next != this->s.rear)//pay attention
return PLAY_1_DEAD;
temp = temp->next;
}
}
return 0;
}
int snake::SNKGetDirection()
{
return this->snakedirection;
}
void snake::SNKSetDirection(int dir)
{
this->snakedirection = dir;
}
COLORREF snake::SNKGetcolor()
{
return this->color;
}
void snake::SNKSetcolor(COLORREF rgb)
{
this->color = rgb;
}
int snake::SNKGeteatnum()
{
return this->snkeatnum;
}
void snake::SNKSeteatnum(int num)
{
this->snkeatnum = num;
}
void snake::SNKEat(Food& food, Scene& scene)
{
int f_x, f_y;
f_x = food.fdposition.x;
f_y = food.fdposition.y;
if(this->s.rear->s_p.x == f_x && this->s.rear->s_p.y == f_y)
{
this->Insert_queue(this->s.rear->s_p);
if(scene.SCNGetmode() == FORONEPLAYER)
scene.scnscore++;
else
this->snkeatnum++;
food.FDposinit();
}
}
//-------------------------------------------Food
Food::Food()
{
this->FDposinit();
this->fdstate = FDSHOW;
this->fdflashflag = 0;
}
void Food::FDposinit()
{
int p_x, p_y;
int temp;
do
{
temp = rand();
p_x = temp % 600 - temp % 10;
} while(p_x < 200);
this->fdposition.x = p_x;
do
{
temp = rand();
p_y = temp % 450 - temp % 10;
} while(p_y < 150);
this->fdposition.x = p_x;
this->fdposition.y = p_y;
}
void Food::FDDraw(HDC hdc)
{
if(this->fdflashflag == 0)
{
SelectObject(hdc, hBrush_snake[2]);
SelectObject(hdc, hPen_snake);
}
else
{
SelectObject(hdc, hBrush_snake[1]);
SelectObject(hdc, hPen_snake);
}
Rectangle(hdc, this->fdposition.x, this->fdposition.y, this->fdposition.x + SNK_SIZE, this->fdposition.y + SNK_SIZE);
this->fdflashflag += 1;
this->fdflashflag %= 10;
}
//-------------------------------------------------Scene
Scene::Scene()
{
this->scnscore = 0;
this->scntextcolor = RGB(0, 0, 0);
this->scnloop = 0;
this->scnplaymode = FORTWOPLAYER;
this->scndeadflag = 0;
this->scnframe = 0;
this->scnfps = 0;
this->scnpretime = 0;
this->scnnowtime = 0;
}
void Scene::SCNDraw(HDC hdc)
{
// LOGFONT ifont;
// ifont.lfHeight = 25;
// ifont.lfWidth = 15;
// CreateFontIndirect(&ifont);
// SelectObject(hdc, &ifont);
SelectObject(hdc, hBrush_snake[1]);
SelectObject(hdc, hPen_snake);
Rectangle(hdc, 200, 150,600, 450);
SetTextColor(hdc,this->scntextcolor);
TextOut(hdc, 200, 50, "Till now your score is:", strlen("Till now your score is:"));
if(this->scnscore < 10)
sprintf(scoreBoard, "00%d", this->scnscore);
else if(this->scnscore < 100)
sprintf(scoreBoard, "0%d", this->scnscore);
else
sprintf(scoreBoard, "%d", this->scnscore);
TextOut(hdc, 370, 50, scoreBoard, strlen(scoreBoard));
}
void Scene::SCNaddscore()
{
this->scnscore++;
}
int Scene::SCNGetscore()
{
return this->scnscore;
}
void Scene::SCNlevel(snake& snk)
{
if(this->scnscore < 10)
{
while(this->scnloop < 10000000)
{
this->scnloop++;
}
this->scnloop = 0;
}
else if(this->scnscore < 20)
{
while(this->scnloop < 5000000)
{
this->scnloop++;
}
this->scnloop = 0;
}
else if(this->scnloop < 30)
{
while(this->scnloop < 2500000)
{
this->scnloop++;
}
this->scnloop = 0;
}
else
{
this->scnloop = 0;
}
}
void Scene::SCNWaitstart(HDC)
{
}
void Scene::SCNSetmode(int mode)
{
this->scnplaymode = mode;
}
int Scene::SCNGetmode()
{
return this->scnplaymode;
}
void Scene::SCNSetstepflg(int start)
{
this->scngamestep = start;
}
int Scene::SCNGetstepflg()
{
return this->scngamestep;
}
void Scene::SCNSetdeadflg(int dead)
{
this->scndeadflag = dead;
}
int Scene::SCNGetdeadflg()
{
return this->scndeadflag;
}
void Scene::SCNShowstartsceen(HDC hdc)
{
SelectObject(hdc, hBrush_snake[1]);
SelectObject(hdc, hPen_snake);
Rectangle(hdc, 200, 150,600, 450);
TextOut(hdc, 370, 200, "贪吃蛇",
strlen("贪吃蛇"));
if(KEYDOWN(VK_SPACE))
{
if(this->scnplaymode == FORONEPLAYER)
this->scnplaymode = FORTWOPLAYER;
else
this->scnplaymode = FORONEPLAYER;
}
if(this->scnplaymode == FORONEPLAYER)
{
SetTextColor(hdc,RGB(255, 0, 0));
TextOut(hdc, 350, 270, "1 player mode",
strlen("1 player mode"));
SetTextColor(hdc,RGB(0, 0, 0));
TextOut(hdc, 350, 320, "2 players mode",
strlen("2 players mode"));
}
else
{
SetTextColor(hdc,RGB(0, 0, 0));
TextOut(hdc, 350, 270, "1 player mode",
strlen("1 player mode"));
SetTextColor(hdc,RGB(255, 0, 0));
TextOut(hdc, 350, 320, "2 players mode",
strlen("2 players mode"));
}
if(KEYDOWN(VK_CONTROL))
{
this->SCNSetstepflg(BEFOREGAMESCENE);
}
}
void Scene::SCNBeforestart(HDC hdc)
{
scnmain.SCNDraw(hdc);
fdmain.FDDraw(hdc);
if(this->SCNGetmode() == FORONEPLAYER)
{
snkmain.SNKDraw(hdc);
}
else
{
snkmain.SNKDraw(hdc);
snksec.SNKDraw(hdc);
}
TextOut(hdc, 350, 300, "Press space to start", strlen("Press space to start"));
if(KEYDOWN(VK_SPACE))
{
scnmain.SCNSetstepflg(GAMESCENE);
}
}
void Scene::SCNGamescene(HDC hdc)
{
if(this->SCNGetmode() == FORONEPLAYER)
{
snkmain.SNKMove();
snkmain.SNKEat(fdmain, scnmain);
scnmain.SCNDraw(hdc);
fdmain.FDDraw(hdc);
snkmain.SNKDraw(hdc);
if(scnmain.SCNWinandrestart(hdc))
{
scnmain.SCNSetstepflg(WINSCENE);
}
if(scnmain.SCNLoseandrestart(hdc))
{
scnmain.SCNSetstepflg(LOSESCENE);
}
}
else
{
snkmain.SNKMove();
snksec.SNKMove();
snkmain.SNKEat(fdmain, scnmain);
snksec.SNKEat(fdmain, scnmain);
scnmain.SCNDraw(hdc);
fdmain.FDDraw(hdc);
snkmain.SNKDraw(hdc);
snksec.SNKDraw(hdc);
if(scnmain.SCNWinandrestart(hdc))
{
scnmain.SCNSetstepflg(WINSCENE);
}
}
}
int Scene::SCNWinandrestart(HDC hdc)
{
if(this->SCNGetmode() == FORONEPLAYER)
{
if(this->SCNGetscore() == WINSCORE)
{
this->SCNDraw(hdc);
SelectObject(hdc, hPen_snake);
SetTextColor(hdc,RGB(255, 0, 0));
TextOut(hdc, 200, 150, "You Win!!!Press Ctrl to restart game", strlen("You Win!!!Press Ctrl to restart game"));
this->SCNSetstepflg(WINSCENE);
return 1;
}
return 0;
}
else
{
this->SCNSetdeadflg(snksec.SNKDead());
if(snkmain.SNKGeteatnum() == WINSCORE || this->SCNGetdeadflg() == PLAY_2_DEAD)
{
this->SCNDraw(hdc);
SelectObject(hdc, hPen_snake);
SetTextColor(hdc,RGB(255, 0, 0));
TextOut(hdc, 200, 150, "Play 1 Win!!!Press Ctrl to restart game", strlen("Play 1 Win!!!Press Ctrl to restart game"));
this->SCNSetstepflg(WINSCENE);
return 1;
}
this->SCNSetdeadflg(snkmain.SNKDead());
if(snksec.SNKGeteatnum() == WINSCORE || this->SCNGetdeadflg() == PLAY_1_DEAD)
{
this->SCNDraw(hdc);
SelectObject(hdc, hPen_snake);
SetTextColor(hdc,RGB(255, 0, 0));
TextOut(hdc, 200, 150, "Play 2 Win!!!Press Ctrl to restart game", strlen("Play 2 Win!!!Press Ctrl to restart game"));
this->SCNSetstepflg(WINSCENE);
return 1;
}
return 0;
}
}
int Scene::SCNLoseandrestart(HDC hdc)
{
if(snkmain.SNKDead())
{
this->SCNDraw(hdc);
SelectObject(hdc, hPen_snake);
SetTextColor(hdc,RGB(255, 0, 0));
TextOut(hdc, 200, 150, "You lose!!!Press Ctrl to restart game", strlen("You lose!!!Press Ctrl to restart game"));
this->SCNSetstepflg(LOSESCENE);
return 1;
}
else
return 0;
}
void Scene::SCNfpsdraw(HDC hdc,DWORD now)
{
char tmp[40];
if(this->scnnowtime == 0)
this->scnnowtime = now;
this->scnframe++;
if((now - this->scnnowtime) > 1000)
{
this->scnfps = this->scnframe;
this->scnframe = 0;
this->scnnowtime = now;
}
sprintf(tmp, "每秒显示%d个画面", this->scnfps);
TextOut(hdc, 0, 0, tmp,strlen(tmp));
}
//-------------------------------------------------Globe
void Manipulation(WPARAM wParam)
{
switch(wParam)
{
case VK_UP:
if(snkmain.SNKGetDirection() == LEFT)
{
snkmain.SNKSetDirection(UP);
}
else if(snkmain.SNKGetDirection() == RIGHT)
{
snkmain.SNKSetDirection(UP);
}
else
{
//
}
break;
case VK_DOWN:
if(snkmain.SNKGetDirection() == LEFT)
{
snkmain.SNKSetDirection(DOWN);
}
else if(snkmain.SNKGetDirection() == RIGHT)
{
snkmain.SNKSetDirection(DOWN);
}
else
{
//
}
break;
case VK_LEFT:
if(snkmain.SNKGetDirection() == UP)
{
snkmain.SNKSetDirection(LEFT);
}
else if(snkmain.SNKGetDirection() == DOWN)
{
snkmain.SNKSetDirection(LEFT);
}
else
{
//
}
break;
case VK_RIGHT:
if(snkmain.SNKGetDirection() == UP)
{
snkmain.SNKSetDirection(RIGHT);
}
else if(snkmain.SNKGetDirection() == DOWN)
{
snkmain.SNKSetDirection(RIGHT);
}
else
{
//
}
break;
case 'W':
if(snksec.SNKGetDirection() == LEFT)
{
snksec.SNKSetDirection(UP);
}
else if(snksec.SNKGetDirection() == RIGHT)
{
snksec.SNKSetDirection(UP);
}
else
{
//
}
break;
case 'S':
if(snksec.SNKGetDirection() == LEFT)
{
snksec.SNKSetDirection(DOWN);
}
else if(snksec.SNKGetDirection() == RIGHT)
{
snksec.SNKSetDirection(DOWN);
}
else
{
//
}
break;
case 'A':
if(snksec.SNKGetDirection() == UP)
{
snksec.SNKSetDirection(LEFT);
}
else if(snksec.SNKGetDirection() == DOWN)
{
snksec.SNKSetDirection(LEFT);
}
else
{
//
}
break;
case 'D':
if(snksec.SNKGetDirection() == UP)
{
snksec.SNKSetDirection(RIGHT);
}
else if(snksec.SNKGetDirection() == DOWN)
{
snksec.SNKSetDirection(RIGHT);
}
else
{
//
}
break;
default:
break;
}
}