#include "Game.h"
CGame::CGame()
{
}
CGame::~CGame()
{
}
/**
* @brief 对游戏进行初始化。
* 创建窗口,加载背景图片,初始化地平线、恐龙、仙人掌。
*/
void CGame::InitGame()//初始化
{
///白底背景
background = cvLoadImage("background.png");
copybk = cvCreateImage(cvGetSize(background), background->depth, background->nChannels);
///黑底背景
bbackground = cvLoadImage("bbackground.png");
copybbk = cvCreateImage(cvGetSize(bbackground), bbackground->depth, bbackground->nChannels);
///游戏结束图片
m_end = cvLoadImage("gameover.png");
///地平线初始化
skyline.Initialize();
///恐龙初始化
dinosaur.Initialize();
///仙人掌1初始化
for (int i = 0; i < 6; ++i)
cactus1[i].Initialize();
///仙人掌2初始化
for (int i = 0; i < 6; ++i)
cactus2[i].Initialize();
///仙人掌序号
no_1 = rand() % 6;
no_2 = rand() % 6;
count = 0;
///daytime=1时为白天,-1则为黑夜
daytime = 1;
m_state = 1;
m_score = 0;
m_high_score = 0;
cvNamedWindow("DinoRun");
}
/**
* @brief 运行游戏。
* 循环显示帧,接收空格输入控制恐龙跳起进行游戏,并记录分数;如果碰到仙人掌,则游戏结束。
*/
void CGame::Run()
{
while (true)
{
ShowFrame();
///接收键盘输入ASCII码
int key = cvWaitKey(10);
///ESC退出
if (key == 27)
break;
///空格开始游戏
if (m_state == 1 && key == 32)
{
m_state = 2;
}
///gameover后空格重新开始
if (m_state == 3 && key == 32)
{
/**
* 先release掉,再initialize
*/
for (int i = 0; i < 6; ++i)
cactus1[i].Release();
for (int i = 0; i < 6; ++i)
cactus2[i].Release();
for (int i = 0; i < 6; ++i)
cactus1[i].Initialize();
for (int i = 0; i < 6; ++i)
cactus2[i].Initialize();
/**
* 重新设初始值
*/
no_1 = rand() % 6;
no_2 = rand() % 6;
count = 0;
daytime = 1;
m_state = 2;
dinosaur.m_speed = 5;
m_score = 0;
continue;
}
///如果在跑的状态下输入为空格,恐龙改变状态,设置向上速度
if (key == 32 && dinosaur.m_isRun)
{
//PlaySound(TEXT("jump.wav"), NULL, SND_FILENAME | SND_SYNC);
dinosaur.m_isJump = true;
dinosaur.m_isRun = false;
dinosaur.m_speed_up = 17;
}
///只有在跑的时候才能跳起来,无法在空中进行连续跳
if (dinosaur.m_isJump && !dinosaur.m_isRun)
{
dinosaur.Jump();
}
///碰撞检测
if (dinosaur.isCollide(cactus1[no_1]) || dinosaur.isCollide(cactus2[no_2]))
{
m_state = 3;
}
else
{
if (dinosaur.m_posx > cactus1[no_1].m_posx + cactus1[no_1].m_cactus->width)
{
///通过仙人掌1,准备下一个仙人掌1
if (cactus1[no_1].isPass())
no_1 = rand() % 6;
}
if (dinosaur.m_posx > cactus2[no_2].m_posx + cactus2[no_2].m_cactus->width)
{
///通过仙人掌2,准备下一个仙人掌2
if (cactus2[no_2].isPass())
no_2 = rand() % 6;
}
}
}
}
/**
* @brief 销毁游戏窗口,释放背景图片资源,释放地平线、恐龙、仙人掌资源
*/
void CGame::ReleaseGame()
{
cvDestroyWindow("DinoRun");
cvReleaseImage(&background);
cvReleaseImage(©bk);
cvReleaseImage(&bbackground);
cvReleaseImage(©bbk);
skyline.Release();
dinosaur.Release();
for (int i = 0; i < 6; ++i)
cactus1[i].Release();
for (int i = 0; i < 6; ++i)
cactus2[i].Release();
}
/**
* @brief 显示帧
*/
void CGame::ShowFrame()
{
///复制背景板准备画图,白天画白板,夜晚画黑板
cvCopy(background, copybk);
cvCopy(bbackground, copybbk);
///画地平线
skyline.DrawToBk(copybk, copybbk, daytime);
///画仙人掌1
cactus1[no_1].DrawToBk(copybk, copybbk, daytime);
///画仙人掌2
cactus2[no_2].DrawToBk(copybk, copybbk, daytime);
///画恐龙
dinosaur.DrawToBk(copybk, copybbk, daytime);
/** 初始状态 */
if (m_state == 1)
{
/*cvCopy(background, copybk);//复制背景板准备画图
cvCopy(bbackground, copybbk);
skyline.DrawToBk(copybk, copybbk, daytime);//画地平线
cactus1[no_1].DrawToBk(copybk, copybbk, daytime);//画仙人掌1
cactus2[no_2].DrawToBk(copybk, copybbk, daytime);//画仙人掌2
dinosaur.DrawToBk(copybk, copybbk, daytime);//画恐龙*/
/*count++;//计数
count %= 500;
if (count % 500 == 0 && dinosaur.m_speed < 6)//每过10s速度+1,最高为12
{
dinosaur.m_speed++;
}
if (count % 500 == 0 && dinosaur.m_speed == 6)//达到最大速度后每过20s白底黑底切换
{
daytime = 0 - daytime;//daytime = -1,1,-1,1...
}*/
}
/** 游戏进行中 */
if (m_state == 2)
{
/** 移动更新 */
skyline.Move(dinosaur.m_speed);
cactus1[no_1].Move(dinosaur.m_speed);
cactus2[no_2].Move(dinosaur.m_speed);
dinosaur.m_frameid = (dinosaur.m_frameid + 1) % 8 + 1;
/**
* 计数,每刷新300次速度+1,最高为10
* 达到最大速度后每刷新300次切换昼夜
* 切换昼夜daytime = -1,1,-1,1...
*/
count++;
count %= 300;
if (count % 300 == 0 && dinosaur.m_speed < 10)
{
dinosaur.m_speed++;
}
if (count % 300 == 0 && dinosaur.m_speed == 10)
{
daytime = 0 - daytime;
}
}
/** 游戏结束 */
else if(m_state == 3)
{
dinosaur.m_frameid = 9;
/** draw game over字样 */
if (copybk != 0 && copybbk != 0 && m_end != 0)
{
for (int i = 0; i < m_end->height; ++i)
{
for (int j = 0; j < m_end->width; ++j)
{
int B = CV_IMAGE_ELEM(m_end, uchar, i, j * 3 + 0);
int G = CV_IMAGE_ELEM(m_end, uchar, i, j * 3 + 1);
int R = CV_IMAGE_ELEM(m_end, uchar, i, j * 3 + 2);
if (R >= 240 && G >= 240 && B >= 240)
continue;
if (daytime == 1)
{
CV_IMAGE_ELEM(copybk, uchar, i + 80, (j + 380) * 3 + 0) = B;
CV_IMAGE_ELEM(copybk, uchar, i + 80, (j + 380) * 3 + 1) = G;
CV_IMAGE_ELEM(copybk, uchar, i + 80, (j + 380) * 3 + 2) = R;
}
else
{
CV_IMAGE_ELEM(copybbk, uchar, i + 80, (j + 380) * 3 + 0) = 255 - B;
CV_IMAGE_ELEM(copybbk, uchar, i + 80, (j + 380) * 3 + 1) = 255 - G;
CV_IMAGE_ELEM(copybbk, uchar, i + 80, (j + 380) * 3 + 2) = 255 - R;
}
}
}
}
}
///显示分数
ShowScore(count);
if (daytime == 1)
///白天显示白底图像
cvShowImage("DinoRun", copybk);
else
///夜晚显示黑底图像
cvShowImage("DinoRun", copybbk);
}
/**
* @brief 显示分数
* @param 传入一个整型变量计数值,根据这个值来计算分数
*/
void CGame::ShowScore(int count)
{
if (m_state != 1)
{
if (count % 10 == 0)
m_score++;
char score[10] = { 0 };
_itoa(m_score, score, 10);
CvPoint point1 = cvPoint(830, 20);
CvScalar color1 = cvScalar(128, 128, 128);
CvFont font;
cvInitFont(&font, CV_FONT_HERSHEY_COMPLEX_SMALL, 1.0, 1.0, 0);
cvPutText(copybk, score, point1, &font, color1);
cvPutText(copybbk, score, point1, &font, color1);
if (m_score > m_high_score)
///当当前分数大于最高分数时,最高分数=当前分数
m_high_score = m_score;
char high_score[10] = { 0 };
_itoa(m_high_score, high_score, 10);
CvPoint point2 = cvPoint(750, 20);
CvScalar color2 = cvScalar(192, 192, 192);
cvPutText(copybk, high_score, point2, &font, color2);
cvPutText(copybbk, high_score, point2, &font, color2);
CvPoint point3 = cvPoint(700, 20);
cvPutText(copybk, "HI", point3, &font, color2);
cvPutText(copybbk, "HI", point3, &font, color2);
}
}