📄 ch29.htm
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=iso-8859-1">
<META NAME="Author" Content="Steph Mineart">
<TITLE>Ch 29 -- Game Engines</TITLE>
</HEAD>
<BODY
BACKGROUND="bg1.gif" tppabs="http://pbs.mcp.com/ebooks/0672310228/buttonart/bg1.gif" BGCOLOR="#FFFFFF">
<P ALIGN="CENTER"><IMG SRC="sams.gif" tppabs="http://pbs.mcp.com/ebooks/0672310228/buttonart/sams.gif" WIDTH="75" HEIGHT="24" ALIGN="BOTTOM"
BORDER="0"><BR>
<BR>
<A HREF="index-3.htm" tppabs="http://pbs.mcp.com/ebooks/0672310228/index.htm"><IMG SRC="toc.gif" tppabs="http://pbs.mcp.com/ebooks/0672310228/buttonart/toc.gif" WIDTH="40" HEIGHT="40" ALIGN="BOTTOM"
ALT="TOC" BORDER="0" NAME="toc4"></A><A HREF="ch28.htm" tppabs="http://pbs.mcp.com/ebooks/0672310228/ch28.htm"><IMG SRC="back-1.gif" tppabs="http://pbs.mcp.com/ebooks/0672310228/buttonart/back.gif"
WIDTH="40" HEIGHT="40" ALIGN="BOTTOM" ALT="BACK" BORDER="0" NAME="toc1"></A></P>
<H2 ALIGN="CENTER"><FONT COLOR="#000077">Charlie Calvert's C++ Builder
Unleashed</FONT></H2>
<P>
<H2 ALIGN="CENTER"><A NAME="Heading1"></A><FONT COLOR="#000077">- 29 -</FONT></H2>
<H2 ALIGN="CENTER"><A NAME="Heading2"></A><FONT COLOR="#000077">Game Engines</FONT></H2>
<P>
<H3><A NAME="Heading3"></A><FONT
COLOR="#000077">Overview</FONT></H3>
<P>In this chapter, you will see how to implement the key pieces of a simple strategy
game called Byzantium. In particular, you will see how to define problem domains
that assure that graphics-based problems are
confined to the graphics engine and
that game-based problems are confined to the game engine.</P>
<P>There are no hard and fast rules defining where the lines between problem domains
should be drawn. The particular scope of a problem domain can be
decided only by
the individuals involved in any one project. The key is not necessarily seeking out
the ideal problem domains, but rather creating certain reasonable domains and then
rigorously enforcing their sovereignty.</P>
<P>Unlike the code in
the preceding chapter, all the code in this chapter is written
in C++. In particular, you will see two base objects called <TT>TCharacter</TT> and
<TT>TGame</TT>, each of which can be used in a wide variety of projects. Descending
from these broad,
abstract tools are two classes called <TT>TByzCharacter</TT> and
<TT>TByzGame</TT>. These objects will help to define the character of the particular
game implemented in this chapter.
<H3><A NAME="Heading4"></A><FONT COLOR="#000077">Creating the
Framework for a Simple
Game</FONT></H3>
<P>In the preceding chapter, you learned how to develop a graphics engine. Now you're
ready to go on and create the framework for a simple game. I have not had time to
complete the entire game for this book, but
I can give you the basic tools you need
to start creating it. In other words, I will give you a game engine, but not a complete
game. I hope that you will find this reasonable, because games are plentiful and
game engines are in short supply.</P>
<P>The partially complete game called Byzantium described in this chapter uses all
the elements in the graphics engine you learned about in the preceding chapter. This
game is a rudimentary version of the type of strategy game you find in the old hack
games that used to circulate on the Net, and it is also remotely related to WarCraft,
Heroes of Might and Magic, and Civilization. Byzantium is not nearly as fancy as
those games, but it has some of the same underlying architectural features, albeit
only in nascent form.</P>
<P>The game has three main screens, shown in Figures 29.1 through 29.3. The first
scene is the introduction to the game, the second is the main playing field, and
in the third you can have battles between the hero and various
nefarious opponents.
The hero can find food and medical kits as he wanders around, and the game tracks
his hunger and strength.<BR>
<BR>
<A NAME="Heading5"></A><A HREF="29ebu01.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/29/29ebu01.jpg">FIGURE 29.1.</A><FONT COLOR="#000077">
</FONT><I>The
introductory scene to Byzantium.</I>
<H6></H6>
<P><A NAME="Heading6"></A><A HREF="29ebu02.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/29/29ebu02.jpg">FIGURE 29.2.</A><FONT COLOR="#000077">
</FONT><I>The main playing field for Byzantium. An apple is visible near the top
of the screen, and a medical
kit near the bottom. In the center are the hero and
an opponent.</I>
<H6></H6>
<P><A NAME="Heading7"></A><A HREF="29ebu03.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/29/29ebu03.jpg">FIGURE 29.3.</A><FONT COLOR="#000077">
</FONT><I>A battle occurs between the hero and an evil queen.</I>
<DL>
<DT></DT>
</DL>
<BLOCKQUOTE>
<P>
<HR>
<FONT COLOR="#000077"><B>CAUTION:</B></FONT><B> </B>You are free to play around with
these game elements to whatever degree you want. If you create your own games for
public distribution with these tools,
you must devise your own map, using your own
art. In other words, the world found here, with mountains, grass, and ocean in particular
locations, cannot be used in your own games. You can, however, use the tools provided
with this book to create
your own world, with different mountains, grass, and lakes
and different bitmaps used to depict them. You can use both the graphics engine and
game engine in any way you see fit. It's the art and the world I have created that
I want to reserve for
my own use.
<HR>
</BLOCKQUOTE>
<P>The source for Byzantium is divided into three parts:
<UL>
<LI>The graphics engine, which was explained in the preceding chapter
<P>
<LI>The game engine, which is described in this chapter
<P>
<LI>The game
itself, which consists of a set of objects resting on top of both the
graphics engine and the game engine
</UL>
<P>In Listings 29.1 through 29.9, you will find the source for the game engine in
a set of files called <TT>GameEngine1.cpp</TT> and
<TT>GameEngine1.h</TT>. You can
find the game itself primarily in <TT>ByzEngine.cpp</TT>, <TT>ByzEngine1.h</TT>,
<TT>GameForm1.cpp</TT>, <TT>GameForm1.h</TT>, <TT>FightClass1.cpp</TT>, and <TT>FightClass1.h</TT>.
I have a few other related files, such
as one that contains a set of global constants
and types, but the heart of the game is located in the files described here. Besides
the main form, one global object called <TT>ByzGame</TT> is available to all the
modules of the program. This object
encapsulates the game engine itself.<BR>
<BR>
<A NAME="Heading9"></A><FONT COLOR="#000077"><B>Listing 29.1. The header file for
the game engine.</B></FONT></P>
<PRE><FONT COLOR="#0066FF">///////////////////////////////////////
// File: GameEngine1.h
// Project: GameObjects
// Copyright (c) 1997 by Charlie Calvert
#ifndef GameEngine1H
#define GameEngine1H
#include <vcl\Forms.hpp>
#include "gameform1.h"
#include "creatures1.hpp"
class TGame;
class TCharacter
: public TObject
{
private:
AnsiString Bitmaps;
TGame *FGame;
TCreature *FCreature;
int GetRow(void);
int GetCol(void);
AnsiString GetName(void);
TStringList *FCustomFeatures;
TStringList *GetCustomFeatures(void);
protected:
virtual __fastcall ~TCharacter(void);
public:
virtual __fastcall TCharacter(TGame *AGame);
__property TGame *Game={read=FGame, write=FGame, nodefault};
__property int Row={read=GetRow, nodefault};
__property int Col={read=GetCol,
nodefault};
__property TCreature *Creature={read=FCreature, write=FCreature, nodefault};
__property AnsiString Name={read=GetName, nodefault};
__property TStringList *CustomFeatures={read=GetCustomFeatures, nodefault};
void Move(int Key);
};
class TScoreCard : public TObject
{
};
// typedef void __fastcall (__closure *TSetSceneProc)(int NextScene);
class TGame : public TObject
{
private:
TCreatureList *FCreatureList;
TCharacter *FHero;
TCharacter *FBadGuy;
AnsiString FCreatureFile;
AnsiString FScreenFile;
TGameForm *FCurrentGameForm;
int FCurrentScene;
void SetHero(TCharacter *Hero);
void SetBadGuy(TCharacter *ABadGuy);
protected:
virtual void CreateCharacters(void);
virtual
__fastcall ~TGame(void);
public:
virtual __fastcall TGame(void);
void Initialize(TGameForm *AOwner, TCreatureList *ACreatureList);
void SetScene(TGameForm *AOwner, HANDLE MainHandle);
void UpdateMap();
// properties
__property
TCharacter *Hero=
{read=FHero, write=SetHero, nodefault};
__property TCharacter *BadGuy=
{read=FBadGuy, write=SetBadGuy, nodefault};
__property AnsiString CreatureFile=
{read=FCreatureFile, write =FCreatureFile, nodefault};
__property AnsiString ScreenFile=
{read=FScreenFile, write=FScreenFile};
__property TGameForm *CurrentGameForm=
{read=FCurrentGameForm, write=FCurrentGameForm};
__property int CurrentScene=
{read=FCurrentScene,
write=FCurrentScene, nodefault};
__property TCreatureList *CreatureList=
{read=FCreatureList, write=FCreatureList};
};
#endif
</FONT></PRE>
<H3 ALIGN="CENTER"><FONT COLOR="#0066FF"></FONT></H3>
<P><A NAME="Heading10"></A><FONT
COLOR="#000077"><B>Listing 29.2. The main source
for the game engine.</B></FONT></P>
<PRE><FONT COLOR="#0066FF">///////////////////////////////////////
// File: GameEngine1.cpp
// Project: GameObjects
// Copyright (c) 1997 by Charlie Calvert
//
#include <vcl.h>
#pragma hdrstop
#include "GameEngine1.h"
///////////////////////////////////////
// Constructor
///////////////////////////////////////
__fastcall TGame::TGame(void)
{
FCreatureList = NULL;
FHero = NULL;
FBadGuy = NULL;
}
///////////////////////////////////////
// Destructor
///////////////////////////////////////
__fastcall TGame::~TGame(void)
{
}
///////////////////////////////////////
// Initialize
///////////////////////////////////////
void TGame::Initialize(TGameForm *AOwner, TCreatureList *ACreatureList)
{
if (FCreatureList == NULL)
{
CurrentGameForm = AOwner;
FCreatureList = ACreatureList;
CreateCharacters();
FHero->Creature = FCreatureList->CreatureFromName("Hero");
}
}
void TGame::CreateCharacters(void)
{
FHero = new TCharacter(this);
FBadGuy = new TCharacter(this);
}
///////////////////////////////////////
// SetHero
///////////////////////////////////////
void TGame::SetHero(TCharacter *AHero)
{
FHero = AHero;
FHero->Game = this;
}
void TGame::SetBadGuy(TCharacter *ABadGuy)
{
FBadGuy = ABadGuy;
FBadGuy->Game = this;
}
void
TGame::SetScene(TGameForm *AOwner, HANDLE MainHandle)
{
CurrentGameForm = AOwner;
CurrentScene = AOwner->ShowModal();
PostMessage(MainHandle, WM_NEXTSCENE, 0, 0);
}
void TGame::UpdateMap()
{
FCreatureList->UpdateMap();
}
// ------------------------------------
// -- TCharacter --------------------
// ------------------------------------
///////////////////////////////////////
// Constructor
///////////////////////////////////////
__fastcall
TCharacter::TCharacter(TGame *AGame)
{
FGame = AGame;
FCustomFeatures = new TStringList();
}
__fastcall TCharacter::~TCharacter(void)
{
FCustomFeatures->Free();
}
int TCharacter::GetRow(void)
{
return Creature->TrueRow;
}
int TCharacter::GetCol(void)
{
return Creature->TrueCol;
// return Game->CurrentGameForm->Tiler->Hero->TrueCol;
}
AnsiString TCharacter::GetName(void)
{
if (FCreature)
return FCreature->CreatureName;
else
return "Creature not initialized";
}
TStringList *TCharacter::GetCustomFeatures(void)
{
int i;
FCustomFeatures->Clear();
for (i = 0; i < FCreature->GetCustomCount() - 1; i++)
{
FCustomFeatures->Add(FCreature->GetCustom(i)->ValueName);
}
return FCustomFeatures;
}
void TCharacter::Move(int Key)
{
if (Name == "Hero")
Game->CurrentGameForm->HermesChart1->Move(Key);
}
</FONT></PRE>
<P><A NAME="Heading11"></A><FONT COLOR="#000077"><B>Listing 29.3. The header file
for the game objects specific to Byzantium.</B></FONT></P>
<PRE><FONT COLOR="#0066FF">///////////////////////////////////////
// File: ByzEngine1.h
//
Project: GameObjects
// Copyright (c) 1997 by Charlie Calvert
//
#ifndef ByzEngine1H
#define ByzEngine1H
#include "gameengine1.h"
class TByzCharacter : public TCharacter
{
private:
int FArmor;
int FWeapon;
int FHitPoints;
int FHunger;
int FStrength;
bool FVisible;
int GetArmor(void);
void SetArmor(int Value);
int GetHitPoints(void);
void SetHitPoints(int Value);
int GetHunger(void);
void SetHunger(int Value);
int GetWeapon(void);
void
SetWeapon(int Value);
int GetStrength(void);
void SetStrength(int Value);
protected:
virtual __fastcall ~TByzCharacter(void);
public:
virtual __fastcall TByzCharacter(TGame *AGame);
bool DefendYourself(TByzCharacter *Attacker);
void SetVisible(bool Value);
__property int Armor={read=GetArmor, write=SetArmor, nodefault};
__property int Hunger={read=GetHunger, write=SetHunger, nodefault};
__property int HitPoints={read=GetHitPoints, write=SetHitPoints, nodefault};
__property int Weapon={read=GetWeapon, write=SetWeapon, nodefault};
__property int Strength={read=GetStrength, write=SetStrength, nodefault};
// __property bool Visible={read=FVisible, write=SetVisible, nodefault);
};
class THero : public
TByzCharacter
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -