应用前面学到的子画面知识,开发一个小鸡过马路游戏。

接上文 游戏编程入门(8):管理子画面


Henway 游戏的玩法

Henway 游戏的主角是一只小鸡,它急需从一条繁忙的高速公路的一边到达另一边。Henway 的游戏方向是水平的,这意味着小鸡要从屏幕的左边到右边。

Henway 游戏,小鸡的数量是有限的3只。当所有小鸡都死掉时,游戏就结束了。当小鸡成功的穿越了高速公路或者玩家失去了一只小鸡,都会计入积分系统中,最后显示玩家所得的分数。

Henway 游戏,以键盘的上下左右键,控制小鸡。

设计Henway 游戏

Henway 游戏有5个子画面:一个小鸡子画面和4辆汽车子画面,有7个位图图像:1个背景高速公路图像,1个小鸡图像,4个汽车图像,很小的鸡头图像。

很小的鸡头图像显示在右下角,提示玩家还剩下多少只小鸡。在高速公路上损失小鸡时,鸡头就会消失,直到没有剩下任何鸡头位置,这时游戏就结束了。

现在,读者已经对游戏中涉及的图像对象有了一定的了解,下面考虑游戏必须维护的其他数据。首先,很显然需要记录剩余多少个小鸡,还需要维护一个连续的积分,在每次小鸡安全穿过高速公路时都加分,还需要一个布尔变量,用来记录游戏是否结束了。

还有最后一个变量,如果读者没有真正开发这个程序并彻底测试它,那么很难预见到这个变量。我是指一个输入延迟变量,它有助于改变键盘的输入响应,以便改进游戏的可玩性。

如果在每一个游戏循环里都直接响应键盘,那么小鸡在游戏屏幕上的移动就会太快了,这就产生了太多的游戏周期,过多的注意了输入设备。为了稍微放慢输入,可以使用一个延迟变量,每三个游戏循环才检查一次键盘输入。确定合适的延迟是一个不断尝试的过程,因此可以随意修改它并查看最合适的延迟。

总结一下,Henway 游戏的设计使我们了解到游戏必须管理以下信息:

  • 剩下的小鸡数量
  • 得分
  • 确定游戏是否结束的布尔变量
  • 输入延迟变量

开发Henway 游戏

注意:若出现编译错误,请在项目设置->连接->对象/库模块中 加入 msimg32.lib winmm.lib

Henway 目录结构与效果图

Henway 目录结构:

Henway 效果图:

Henway 游戏源代码

Henway.h 源代码

#pragma once//-----------------------------------------------------------------
// 包含的文件
//-----------------------------------------------------------------
#include <windows.h>
#include "Resource.h"
#include "GameEngine.h"
#include "Bitmap.h"
#include "Sprite.h"//-----------------------------------------------------------------
// 全局变量
//-----------------------------------------------------------------
HINSTANCE   g_hInstance;         //程序实例句柄
GameEngine* g_pGame;             //游戏引擎指针
HDC         g_hOffscreenDC;      //屏幕外设备
HBITMAP     g_hOffscreenBitmap;  //屏幕外缓冲区的位图
Bitmap*     g_pHighwayBitmap;    //背景高速公路位图
Bitmap*     g_pChickenBitmap;    //小鸡位图
Bitmap*     g_pCarBitmaps[4];    //4个汽车位图
Bitmap*     g_pChickenHeadBitmap;//鸡头位图
Sprite*     g_pChickenSprite;    //小鸡子画面
int         g_iInputDelay;       //输入延迟
int         g_iNumLives;         //剩下的小鸡
int         g_iScore;            //得分
BOOL        g_bGameOver;         //游戏是否结束//-----------------------------------------------------------------
// 根据用户输入事件移动小鸡子画面
//-----------------------------------------------------------------
void MoveChicken(int iXDistance, int iYDistance);

Henway.cpp 源代码

//-----------------------------------------------------------------
// 包含的文件
//-----------------------------------------------------------------
#include "Henway.h"//-----------------------------------------------------------------
// 游戏事件函数
//-----------------------------------------------------------------// 初始化游戏
BOOL GameInitialize(HINSTANCE hInstance)
{// Create the game engineg_pGame = new GameEngine(hInstance, TEXT("Henway"),TEXT("Henway"), IDI_HENWAY, IDI_HENWAY_SM, 465, 400);if (g_pGame == NULL)return FALSE;// Set the frame rateg_pGame->SetFrameRate(30);// Store the instance handleg_hInstance = hInstance;return TRUE;
}// 开始游戏
void GameStart(HWND hWindow)
{// 生成随机数种子srand(GetTickCount());// 创建屏幕外的设备环境,然后使用它创建一个屏幕外位图g_hOffscreenDC = CreateCompatibleDC(GetDC(hWindow));g_hOffscreenBitmap = CreateCompatibleBitmap(GetDC(hWindow),g_pGame->GetWidth(), g_pGame->GetHeight());SelectObject(g_hOffscreenDC, g_hOffscreenBitmap);// 创建并加载位图HDC hDC = GetDC(hWindow);g_pHighwayBitmap = new Bitmap(hDC, IDB_HIGHWAY, g_hInstance);g_pChickenBitmap = new Bitmap(hDC, IDB_CHICKEN, g_hInstance);g_pCarBitmaps[0] = new Bitmap(hDC, IDB_CAR1, g_hInstance);g_pCarBitmaps[1] = new Bitmap(hDC, IDB_CAR2, g_hInstance);g_pCarBitmaps[2] = new Bitmap(hDC, IDB_CAR3, g_hInstance);g_pCarBitmaps[3] = new Bitmap(hDC, IDB_CAR4, g_hInstance);g_pChickenHeadBitmap = new Bitmap(hDC, IDB_CHICKENHEAD, g_hInstance);// 创建小鸡和汽车的子画面(汽车的z顺序比小鸡高,这样小鸡被汽车压的时候,小鸡显示在车下面)Sprite* pSprite;RECT    rcBounds = { 0, 0, 465, 400 };g_pChickenSprite = new Sprite(g_pChickenBitmap, rcBounds, BA_STOP);g_pChickenSprite->SetPosition(4, 175);g_pChickenSprite->SetVelocity(0, 0);g_pChickenSprite->SetZOrder(1);g_pGame->AddSprite(g_pChickenSprite);pSprite = new Sprite(g_pCarBitmaps[0], rcBounds, BA_WRAP);pSprite->SetPosition(70, 0);pSprite->SetVelocity(0, 7);pSprite->SetZOrder(2);g_pGame->AddSprite(pSprite);pSprite = new Sprite(g_pCarBitmaps[1], rcBounds, BA_WRAP);pSprite->SetPosition(160, 0);pSprite->SetVelocity(0, 3);pSprite->SetZOrder(2);g_pGame->AddSprite(pSprite);pSprite = new Sprite(g_pCarBitmaps[2], rcBounds, BA_WRAP);pSprite->SetPosition(239, 400);pSprite->SetVelocity(0, -5);pSprite->SetZOrder(2);g_pGame->AddSprite(pSprite);pSprite = new Sprite(g_pCarBitmaps[3], rcBounds, BA_WRAP);pSprite->SetPosition(329, 400);pSprite->SetVelocity(0, -10);pSprite->SetZOrder(2);g_pGame->AddSprite(pSprite);// 初始化其余全局变量g_iInputDelay = 0;g_iNumLives = 3;g_iScore = 0;g_bGameOver = FALSE;
}// 结束游戏
void GameEnd()
{// 清除屏幕外设备环境和位图DeleteObject(g_hOffscreenBitmap);DeleteDC(g_hOffscreenDC);  // 清除位图delete g_pHighwayBitmap;delete g_pChickenBitmap;for (int i = 0; i < 4; i++)delete g_pCarBitmaps[i];delete g_pChickenHeadBitmap;// 清除子画面g_pGame->CleanupSprites();// 清除游戏引擎delete g_pGame;
}void GameActivate(HWND hWindow)
{}void GameDeactivate(HWND hWindow)
{}// 绘制游戏
void GamePaint(HDC hDC)
{// 绘制高速公路背景g_pHighwayBitmap->Draw(hDC, 0, 0);// 绘制游戏子画面g_pGame->DrawSprites(hDC);// 绘制剩余小鸡生命的数量for (int i = 0; i < g_iNumLives; i++)g_pChickenHeadBitmap->Draw(hDC,406 + (g_pChickenHeadBitmap->GetWidth() * i), 382, TRUE);
}// 游戏循环
void GameCycle()
{if (!g_bGameOver){// 更新子画面g_pGame->UpdateSprites();// 获得用来绘制游戏的设备环境HWND  hWindow = g_pGame->GetWindow();HDC   hDC = GetDC(hWindow);// 在屏幕外设备环境上绘制游戏GamePaint(g_hOffscreenDC);// 将屏幕外位图位块传送到游戏屏幕BitBlt(hDC, 0, 0, g_pGame->GetWidth(), g_pGame->GetHeight(),g_hOffscreenDC, 0, 0, SRCCOPY);// 清理ReleaseDC(hWindow, hDC);}
}// 键盘响应事件
void HandleKeys()
{if (!g_bGameOver && (++g_iInputDelay > 2)){// 根据按键移动小鸡if (GetAsyncKeyState(VK_LEFT) < 0)MoveChicken(-20, 0);else if (GetAsyncKeyState(VK_RIGHT) < 0)MoveChicken(20, 0);if (GetAsyncKeyState(VK_UP) < 0)MoveChicken(0, -20);else if (GetAsyncKeyState(VK_DOWN) < 0)MoveChicken(0, 20);// 重置输入延迟g_iInputDelay = 0;}
}// 按下鼠标
void MouseButtonDown(int x, int y, BOOL bLeft)
{// 开始一个新游戏if (g_bGameOver){g_iNumLives = 3;g_iScore = 0;g_bGameOver = FALSE;}
}void MouseButtonUp(int x, int y, BOOL bLeft)
{
}void MouseMove(int x, int y)
{
}// 碰撞检测
BOOL SpriteCollision(Sprite* pSpriteHitter, Sprite* pSpriteHittee)
{// 查看是否撞上了小鸡if (pSpriteHittee == g_pChickenSprite){// 将小鸡移回开始位置,给人一种新小鸡开始的错觉g_pChickenSprite->SetPosition(4, 175);// 查看游戏是否结束if (--g_iNumLives > 0)MessageBox(g_pGame->GetWindow(), TEXT("Ouch!"), TEXT("Henway"), MB_OK);else{// 显示游戏结束消息TCHAR szText[64];wsprintf(szText, "Game Over! You scored %d points.", g_iScore);MessageBox(g_pGame->GetWindow(), szText, TEXT("Henway"), MB_OK);g_bGameOver = TRUE;}return FALSE;}return TRUE;
}//-----------------------------------------------------------------
// 移动小鸡子画面
//-----------------------------------------------------------------
void MoveChicken(int iXDistance, int iYDistance)
{// 将小鸡移动到新位置g_pChickenSprite->OffsetPosition(iXDistance, iYDistance);// 查看小鸡是否成功通过if (g_pChickenSprite->GetPosition().left > 400){// 将小鸡移回开始位置并增加得分g_pChickenSprite->SetPosition(4, 175);g_iScore += 150;MessageBox(g_pGame->GetWindow(), TEXT("You made it!"), TEXT("Henway"),MB_OK);}
}

源代码 下载

http://pan.baidu.com/s/1ge2Vzr1

游戏编程入门(9):开发 Henway(小鸡过马路) 游戏相关推荐

  1. 游戏编程入门(3):绘制基本 GDI 图形

    接上文 游戏编程入门(2):创建游戏引擎和使用该引擎制作小游戏 本篇内容包括: 使用Windows图形设备接口绘制图形的基础知识 设备环境是什么以及它为什么对GDI图形如此重要 如何在Windows中 ...

  2. 游戏编程入门(6):开发 Brainiac(记忆对对碰) 游戏

    接上文 游戏编程入门(5):使用键盘和鼠标控制游戏 这个游戏是记忆游戏,将隐藏的方块配对.即点击一下方块,就会翻转出图片页,然后记忆几秒,回归成方块,要将相同图片的方块进行配对. 本章内容包括: 如果 ...

  3. 游戏编程入门(完):开发 Stunt Jumper(摩托车跳跃)游戏

    Stunt Jumper 是一个横向滚动的摩托车跳跃游戏,玩家必须仔细控制摩托车手的速度,以便帮助它越过一排汽车. 本章内容包括: Stunt Jumper 的基本思路 如何设计 Stunt Jump ...

  4. 如何根据自己的需要培养游戏开发技能?又一篇游戏编程入门指南

    对游戏编程感兴趣或是想自己做游戏的人可以参考一下~ 我是一个独立游戏开发者,在一个主机独立游戏开发团队里做主程.大学毕业 10 年,毕业以后就一直在做游戏编程,从一开始的"端游", ...

  5. 游戏编程入门(10):播放数字声音效果

    本章内容包括: 如何使用 Win32 API 播放波形声音 如何将波形声音合并到现有的游戏中 接上文 游戏编程入门(9):开发 Henway(小鸡过马路) 游戏 播放波形声音 Win32 API 提供 ...

  6. 游戏编程入门(11):播放MIDI 音乐

    MIDI音乐是将音乐结合到游戏的最佳方式之一,本章就将介绍究竟如何使用相对较少的代码播放MIDI音乐. 本章内容包括: 如何使用MCI播放MIDI音乐 如何向游戏添加MIDI音乐 接上文 游戏编程入门 ...

  7. python游戏编程入门 免费-python游戏编程入门 python游戏编程入门课

    python游戏编程入门 python游戏编程入门课 什么是python游戏编程入门?首先我们需要认识什么是Python Python既是一个软件工具包,也是一种语言.Python软件包包含了一个名为 ...

  8. 《Python游戏编程入门》——1.2 初识Python

    本节书摘来自异步社区<Python游戏编程入门>一书中的第1章,第1.2节,作者[美]Jonathan S. Harbour ,李强 译,更多章节内容可以访问云栖社区"异步社区& ...

  9. .netframework游戏编程入门——模拟魔兽学院永远的羁绊

    相信有很多和我一样摸索着编游戏的自学者,自学是辛苦的,一没明确的引导,二没正确的工具,我就谈一下自己的经验,也许可以让你少走一点弯路.3D 的先不谈,2D作为基础还是有必要研究,然后把地图模型一换(换 ...

最新文章

  1. java怎么来用urlrewrite伪静态化和urlrewrite的配置
  2. h5调微信支付 unkonw url_聚合支付系统设计(一)
  3. 风控策略和模型的区别_智能风控平台核心之风控决策引擎(二)
  4. 深入理解 KVC\KVO 实现机制 — KVC
  5. leetcode266. 回文排列
  6. 成就优秀程序员的很多因素你知道多少?
  7. bugku——普通的二维码(进制转换)
  8. docker1.13.1的安装与卸载及mysql5.5安装实例
  9. 剑指offer——面试题26:复杂链表的复制
  10. 27. 二叉搜索树与双向链表(C++版本)
  11. docker学习记录 docker 脚本----redis,zookeeper,kafka(三)
  12. cetnos6.4 基础版安装
  13. LENET-5卷积神经网络的深度学习技术
  14. Flutter 桌面应用调研
  15. ReadHub android版
  16. AtCoder abc256全题解(区间合并模板、矩阵快速幂优化dp、线段树……)
  17. UNITY 5.2.1 发行说明 中文版
  18. SQLyog 试用期过的解决办法
  19. 从头到尾创建自己的仿真编译flow
  20. 六、Oracle 同义词

热门文章

  1. 你必须要知道的JavaScript数据结构与面试题解答
  2. JS数组的几种遍历方法
  3. 推荐免费的svn空间(SVN代码托管)
  4. 用unigui来制作网站
  5. svg标签元素的XPATH定位
  6. 2023最新SSM计算机毕业设计选题大全(附源码+LW)之java汽车交易平台w81zb
  7. 文件批量重命名工具.exe
  8. Windows下卸载CUDA10.2
  9. NY8B062D 九齐单片机之ADC芯片
  10. Java 并发编程(二)对象的发布逸出和线程封闭