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

接上文 游戏编程入门(5):使用键盘和鼠标控制游戏

这个游戏是记忆游戏,将隐藏的方块配对。即点击一下方块,就会翻转出图片页,然后记忆几秒,回归成方块,要将相同图片的方块进行配对。

本章内容包括:

  • 如果构思一个新游戏的概念
  • 如何将游戏的概念转变为一个游戏设计
  • 如何使用游戏引擎和游戏设计从头开发一个游戏

Brainiac 游戏的玩法

Brainiac 游戏的思路是,显示一个由成对的方块组成的网格。更具体的说,一个4*4的网格包括16个方块,将8对方块随机放在这个网格中。

每对方块都包含一个独特的图像,在游戏过程中,玩家使用这个图像将方块配对。当游戏开始时,方块上面的图像是隐藏的,只有在单击方块并尝试将它们配对的时候才会显示出来。当方块不匹配时,将看到一个公共的方块图像,从而无法辨认不同的方块。

这里写图片描述

这个游戏允许玩家选择一个方块,然后选择另一个方块。如果这两个方块是相同的,那么它们将保持可见的状态,玩家尝试继续找出另外两个相同的方块。如果两个方块不同,它们将再次翻转,从而再次隐藏。玩家的任务就是讲它们翻开时记住不同的方块的位置,以便将所有方块配对。这个游戏记录使所有方块都配对经过了多少次尝试,并在完成这个游戏时报告这个总数。

设计Brainiac 游戏

因为游戏设计为4*4的方块网格,所以首先需要的是位图的一个二维数组,这些位图是对每个方块显示的方块图像。另外,还需要另一个二维数组来记录两个方块是否相同。
此外,我们还需要注意用户目前选定的两个方块,这样才能正确地显示并测试他们是否相同。如果两个方块相同,那么只需要在方块状态数组中更新它们的状态,使他们保持是翻开的。如果两个方块不同,则确保它们返回到隐藏的状态。

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

  • 方块位图的二维数组(4*4)
  • 方块状态的二维数组(4*4)
  • 用户选择的可能配对的方块
  • 配对的数量
  • 尝试的次数

开发 Brainiac 游戏

在上面各章中,我们已经了解到,到目前为止开发的游戏引擎(GameEngine)和位图类(Bitmap)使得我们可以专注于游戏本身功能开发,使得使用相对较少的代码开发一个有趣的程序成为可能。

接下来将介绍Brainiac 游戏源码,GameEngine 和 Bitmap文件代码与上节UFO游戏中一致。

Brainiac 游戏结构和效果图

Brainiac 游戏结构:

这里写图片描述

Brainiac 效果图:

这里写图片描述

这里写图片描述

这里写图片描述

Brainiac 游戏源码

Resource.h 源代码

//-----------------------------------------------------------------
// Brainiac Resource Identifiers
// C++ Header - Resource.h
//-----------------------------------------------------------------

//-----------------------------------------------------------------
// Icons                    Range : 1000 - 1999
//-----------------------------------------------------------------
#define IDI_BRAINIAC        1000
#define IDI_BRAINIAC_SM     1001

//-----------------------------------------------------------------
// Bitmaps                  Range : 2000 - 2999
//-----------------------------------------------------------------
#define IDB_TILEBLANK       2000
#define IDB_TILE1           2001
#define IDB_TILE2           2002
#define IDB_TILE3           2003
#define IDB_TILE4           2004
#define IDB_TILE5           2005
#define IDB_TILE6           2006
#define IDB_TILE7           2007
#define IDB_TILE8           2008

Brainiac.h 源代码

#pragma once

//-----------------------------------------------------------------
// 包含文件
//-----------------------------------------------------------------
#include <windows.h>
#include "Resource.h"
#include "GameEngine.h"
#include "Bitmap.h"

//-----------------------------------------------------------------
// 全局变量
//-----------------------------------------------------------------
HINSTANCE   g_hInstance;          //程序实例句柄
GameEngine* g_pGame;              //游戏引擎指针
Bitmap*     g_pTiles[9];          //方块图像,第9个图像是空白的方块(表示背面的方块)
BOOL        g_bTileStates[4][4];  //方块状态,true则已配对
int         g_iTiles[4][4];       //存储方块位图的整数索引1~9
POINT       g_ptTile1, g_ptTile2; //两个方块的选择
int         g_iMatches, g_iTries; //配对的数量和尝试配对的次数

Brainiac.cpp

//-----------------------------------------------------------------
// 包含的文件
//-----------------------------------------------------------------
#include "Brainiac.h"

//-----------------------------------------------------------------
// 游戏事件函数
//-----------------------------------------------------------------

//初始化游戏
BOOL GameInitialize(HINSTANCE hInstance)
{
  // 创建游戏引擎
  g_pGame = new GameEngine(hInstance, TEXT("Brainiac"),
    TEXT("Brainiac"), IDI_BRAINIAC, IDI_BRAINIAC_SM, 528, 512);
  if (g_pGame == NULL)
    return FALSE;

  // 设帧频
  g_pGame->SetFrameRate(1); //帧频对基于事件的使用很重要,对基于回合则没用处

  // 存储句柄
  g_hInstance = hInstance;

  return TRUE;
}

//开始游戏
void GameStart(HWND hWindow)
{
  // 生成随机数种子
  srand(GetTickCount());

  // 创建并加载方块位图
  HDC hDC = GetDC(hWindow);
  g_pTiles[0] = new Bitmap(hDC, IDB_TILEBLANK, g_hInstance); 
  g_pTiles[1] = new Bitmap(hDC, IDB_TILE1, g_hInstance);
  g_pTiles[2] = new Bitmap(hDC, IDB_TILE2, g_hInstance);
  g_pTiles[3] = new Bitmap(hDC, IDB_TILE3, g_hInstance);
  g_pTiles[4] = new Bitmap(hDC, IDB_TILE4, g_hInstance);
  g_pTiles[5] = new Bitmap(hDC, IDB_TILE5, g_hInstance);
  g_pTiles[6] = new Bitmap(hDC, IDB_TILE6, g_hInstance);
  g_pTiles[7] = new Bitmap(hDC, IDB_TILE7, g_hInstance);
  g_pTiles[8] = new Bitmap(hDC, IDB_TILE8, g_hInstance);

  // 清空方块状态和图像
  for (int i = 0; i < 4; i++)
    for (int j = 0; j < 4; j++)
    {
      g_bTileStates[i][j] = FALSE; 
      g_iTiles[i][j] = 0;
    }

  // 随机初始化方块图像  这段代码使用1~9之间成对的整数索引随机填充方块数组
  for (i = 0; i < 2; i++)
    for (int j = 1; j < 9; j++)
    {
      int x = rand() % 4;
      int y = rand() % 4;
      while (g_iTiles[x][y] != 0)
      {
        x = rand() % 4;
        y = rand() % 4;
      }
      g_iTiles[x][y] = j;
    }

  // 初始化方块选择和配对/尝试计数
  g_ptTile1.x = g_ptTile1.y = -1;  //-1代表当前没有选定的方块
  g_ptTile2.x = g_ptTile2.y = -1;
  g_iMatches = g_iTries = 0;
}

void GameEnd()
{
  // 清空方块位图
  for (int i = 0; i < 9; i++)
    delete g_pTiles[i];

  // 清理游戏引擎
  delete g_pGame;
}

void GameActivate(HWND hWindow)
{
}

void GameDeactivate(HWND hWindow)
{
}

//绘制游戏(根据方块状态来绘制游戏的方块)
void GamePaint(HDC hDC)
{
  // 绘制方块
  int iTileWidth = g_pTiles[0]->GetWidth();
  int iTileHeight = g_pTiles[0]->GetHeight();
  for (int i = 0; i < 4; i++)
    for (int j = 0; j < 4; j++)
      if (g_bTileStates[i][j] || ((i == g_ptTile1.x) && (j == g_ptTile1.y)) ||
        ((i == g_ptTile2.x) && (j == g_ptTile2.y)))
        g_pTiles[g_iTiles[i][j]]->Draw(hDC, i * iTileWidth, j * iTileHeight,
          TRUE);
      else //如果方块不相同或没有选定,则显示空白方块图像
        g_pTiles[0]->Draw(hDC, i * iTileWidth, j * iTileHeight, TRUE);
}

void GameCycle()
{
}

void HandleKeys()
{
}

//按下鼠标事件
void MouseButtonDown(int x, int y, BOOL bLeft)
{
  // 确定单击了哪一个方块
  int iTileX = x / g_pTiles[0]->GetWidth();
  int iTileY = y / g_pTiles[0]->GetHeight();

  // 确保还没有将这个方块配对
  if (!g_bTileStates[iTileX][iTileY])
  {
    // 查看这是否是选定的第一个方块
    if (g_ptTile1.x == -1)
    {
      // 设置第一个方块选择
      g_ptTile1.x = iTileX;
      g_ptTile1.y = iTileY;
    }
    else if ((iTileX != g_ptTile1.x) || (iTileY != g_ptTile1.y))
    {
      if (g_ptTile2.x == -1)
      {
        // 增加尝试次数
        g_iTries++;

        // 设置第二个方块选择
        g_ptTile2.x = iTileX;
        g_ptTile2.y = iTileY;

        // 查看是否相同
        if (g_iTiles[g_ptTile1.x][g_ptTile1.y] == g_iTiles[g_ptTile2.x][g_ptTile2.y])
        {
          // 设置方块状态,指出配对成功
          g_bTileStates[g_ptTile1.x][g_ptTile1.y] = TRUE;
          g_bTileStates[g_ptTile2.x][g_ptTile2.y] = TRUE;

          // 清空方块选择
          g_ptTile1.x = g_ptTile1.y = g_ptTile2.x = g_ptTile2.y = -1;

          // 更新配对次数并检查是否获胜
          if (++g_iMatches == 8)
          {
            TCHAR szText[64];
            wsprintf(szText, "You won in %d tries.", g_iTries);
            MessageBox(g_pGame->GetWindow(), szText, TEXT("Brainiac"), MB_OK);
          }
        }
      }
      else
      {
        // 清空方块选择
        g_ptTile1.x = g_ptTile1.y = g_ptTile2.x = g_ptTile2.y = -1;
      }
    }

    // 强制重新绘制,更新方块
    InvalidateRect(g_pGame->GetWindow(), NULL, FALSE);
  }
}

void MouseButtonUp(int x, int y, BOOL bLeft)
{
}

void MouseMove(int x, int y)
{
}

源代码 下载

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

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值