📄 ch28.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 28 -- Game Programming</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="ch27.htm" tppabs="http://pbs.mcp.com/ebooks/0672310228/ch27.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><A HREF="ch29.htm" tppabs="http://pbs.mcp.com/ebooks/0672310228/ch29.htm"><IMG
SRC="forward.gif" tppabs="http://pbs.mcp.com/ebooks/0672310228/buttonart/forward.gif" WIDTH="40" HEIGHT="40" ALIGN="BOTTOM"
ALT="FORWARD" BORDER="0"
NAME="toc2"></A></P>
<H2 ALIGN="CENTER"><FONT COLOR="#000077">Charlie Calvert's C++ Builder Unleashed</FONT></H2>
<P>
<H1 ALIGN="CENTER"><FONT COLOR="#000077">- 28 -<BR>
Game Programming</FONT></H1>
<H2><FONT
COLOR="#000077">Overview</FONT></H2>
<P>In this chapter and the next, you'll examine multimedia and game objects. In particular,
you will see the following:
<UL>
<LI>A simple two-dimensional graphics engine that uses DirectDraw
<P>
<LI>A simple
game engine
<P>
<LI>Examples of how to use both objects
<P>
<LI>Various comments on object design
<P>
<LI>The opening portions of a strategy game called Byzantium
</UL>
<P>The graphics engine used in this chapter is implemented on disk both in
C++ and
in Object Pascal, and it appears to BCB programmers as a set of simple components.
The game engine, shown in the next chapter, is implemented in C++, and it appears
to the user as a set of objects. In short, the graphics engine consists of
components,
and the game engine consists of simple objects.</P>
<P>You can use all the code found in this book in your own programs, but you cannot
use the art or designs found in this chapter and the next. My objection is to distributing
the art in
your own programs. You are free to use the art in your own home or at
your company, but you cannot distribute it to others in any form. You can use the
game engine to build your own games, but it must be distinct from the game you find
in the next
chapter. The world must be different, and so should the art.</P>
<P>I hope that many readers are specifically interested in developing and using game
engines. If you're not interested in that subject, I still think that you will find
these chapters
among the most interesting in the book. In particular, in these pages
you will see how to create complex sets of objects and use them in real-world programs
that have to perform complex tasks.</P>
<P>The DirectX technology shown in these chapters can
be used in a wide variety of
applications. For example, you can use the graphics engine shown here to create the
following:
<UL>
<LI>Games
<P>
<LI>Simulations
<P>
<LI>Presentations
<P>
<LI>Advanced graphical features of all kinds
</UL>
<P>Besides describing the raw graphics tools in this chapter, I also show you how
to create complex object hierarchies, how to plan and design the functionality of
an object properly, how to divide groups of objects into specific engines, and how
to
get the engines to work together.</P>
<P>The overriding theme of these chapters is the importance of object design. You
have to learn how to create objects that are reusable and how to design object hierarchies
that are simple enough to meet the needs
of real programmers.</P>
<P>In the end, everything comes down to design. If you design the right kinds of
objects, you can accomplish almost anything. Furthermore, as you will see, the judicious
use of objects can help you dig yourself out of almost
any hole. Objects are the
Holy Grail of contemporary programming, and if you understand how to use them correctly,
they will help you complete project after project on time.</P>
<P>Just understanding the basics of object technology is not enough. Just
knowing
about polymorphism, inheritance, and encapsulation is not enough. You also need to
know how to design objects that you can use and that other people can use. This section
of the book is about designing these kinds of objects. Of course, on the
way, you
will also have the chance to engage in a good deal of fun with graphics, games, and
multimedia.
<H2><FONT COLOR="#000077">Game Resources</FONT></H2>
<P>Game programming is more complicated than most standard Windows programming tasks
for many
reasons. The root of this complexity is the need to use special graphics
tools such as DirectX. Another complication that many first-time game programmers
underestimate involves creating art.</P>
<P>Many books are available on game programming and on
producing art for games. Two
that I have found useful are <BR>
<BR>
<I>Tricks of the Game Programming GurusI?</I>, LaMothe, Ratcliff,et al., Sams Publishing<BR>
<BR>
<I>The Ultimate Game Developers Sourcebook</I>, Ben Sawyer, Coriolis Group Books.<BR>
<BR>
You will also need a paint program. I find that the inexpensive shareware program
called Paint Shop Pro meets most of my needs, though many other powerful programs
such as Fractal Paint (<A
HREF="javascript:if(confirm('http://www.fractal.com/ \n\nThis file was not retrieved by Teleport Pro, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?'))window.location='http://www.fractal.com/'" tppabs="http://www.fractal.com/"><TT>www.fractal.com</TT></A>)
are available. Here's the contact information for Paint Shop Pro: <BR>
<BR>
<I>JASC, Inc.</I></P>
<P><I>P.O. Box 44997</I></P>
<P><I>Eden Prairie, MN 55344</I></P>
<P><I>930-9171<BR>
</I><TT><BR>
</TT><A HREF="javascript:if(confirm('http://www.jasc.com/ \n\nThis file was not retrieved by Teleport Pro, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?'))window.location='http://www.jasc.com/'" tppabs="http://www.jasc.com/"><TT>www.jasc.com</TT></A><TT><BR>
<BR>
</TT>Other key paint programs that I use often include TrueSpace (<A HREF="javascript:if(confirm('http://www.caligari.com/ \n\nThis file was not retrieved by Teleport Pro, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?'))window.location='http://www.caligari.com/'" tppabs="http://www.caligari.com/"><TT>www.caligari.com</TT></A>)
and VistaPro from Virtual Reality
Laboratories in San Luis Obispo. TrueSpace allows
you to create three-dimensional objects, and VistaPro allows you to create landscapes.
The background scenes that show rolling hills, mountains, and trees in the figures
for this chapter and the next
were created in VistaPro (Virtual Reality Laboratories
in San Luis Obispo, CA, 805-545-8515, e-mail: <A HREF="mailto:VRLI@aol.com"><TT>VRLI@aol.com</TT></A>,
WWW:<TT> </TT><A HREF="javascript:if(confirm('http://www.romt.com/ \n\nThis file was not retrieved by Teleport Pro, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?'))window.location='http://www.romt.com/'" tppabs="http://www.romt.com/"><TT>http://www.romt.com</TT></A>). (See
the files
called <TT>Backgrd1.bmp</TT> and <TT>Backgrd2.bmp</TT> on the CD that comes
with this book for examples of VistaPro files that have gone through a color reduction
so that they could fit on a 256-color palette.)</P>
<P>You might find additional game
components, links, or code available at these sites:</P>
<PRE><A HREF="javascript:if(confirm('http://www.silvercrk.com/directx/ \n\nThis file was not retrieved by Teleport Pro, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?'))window.location='http://www.silvercrk.com/directx/'" tppabs="http://www.silvercrk.com/directx/">http://www.silvercrk.com/directx/</A><FONT
COLOR="#0066FF">
</FONT><A
HREF="javascript:if(confirm('http://www.spinlogic.com/GameDev/ \n\nThis file was not retrieved by Teleport Pro, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?'))window.location='http://www.spinlogic.com/GameDev/'" tppabs="http://www.spinlogic.com/GameDev/">http://www.spinlogic.com/GameDev/</A><FONT
COLOR="#0066FF">
</FONT><A HREF="javascript:if(confirm('http://users.aol.com/charliecal \n\nThis file was not retrieved by Teleport Pro, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?'))window.location='http://users.aol.com/charliecal'" tppabs="http://users.aol.com/charliecal">http://users.aol.com/charliecal</A><FONT
COLOR="#0066FF">
</FONT></PRE>
<P>Many other Web sites are
of interest to game developers, but you can find links
to most of them from the sites listed here. On CompuServe, type <TT>GO GAMEDEV</TT>
to find the game developers' forum.</P>
<P>As I stated previously, game programming is an extremely complex
undertaking.
The biggest mistake you can make is to try to create your own tools from scratch.
Use the tools included in this book to get some sense of what you can gain from a
graphics engine and a set of gaming tools. Then go out and search the Web
and your
local bookstores for ready-made graphics and game engines. Build your games using
these tools; don't try to create your own tools from scratch unless you're sure,
double-sure, and then triple-sure you know what you're doing and why.</P>
<P>If
you have never built a game before, then don't even consider building one from
scratch. Build your first game with someone else's engine. Then, after you understand
something about the tools that are available, you might finally be in a position
to
consider creating some of your own tools. Even then, however, I would still recommend
turning around and using someone else's tools rather than trying to create your own.
The Ultimate Game Developers Sourcebook, mentioned previously, offers a great
deal
of information on finding third-party game engines.
<H2><FONT COLOR="#000077">Where We're Headed: Object Overview</FONT></H2>
<P>In this part of the book, you'll create two sets of objects. Using the first set
of objects, you can encapsulate
DirectX multimedia functionality inside easy-to-use
components. The second set of objects allows you to create games, simulations, or
multimedia tools using the game engine.</P>
<P>The classic mistake to make in this process is to find or create the
objects that
give you access to the multimedia and DirectX interfaces and to then think you're
ready to create a program. This error is fatal--and very common.</P>
<P>Suppose that you have a set of objects that give you full access to DirectDraw.
The
mistake many programmers make is to assume that they can directly use these objects
when creating a game or simulation. Indeed, in some cases, that may be possible.
However, most of the time you need to create a second set of objects tailored
specifically
for games or simulations. In particular, you need a <TT>TGameEngine</TT> object.
Furthermore, this object is not necessarily a direct descendant of any of your graphics-based
objects. It may use them via aggregation but probably does not
descend directly from
them. The same applies for simulations: You need a <TT>TSimulation</TT> object that
uses your graphics objects but presents a different interface to the user. A game
object, for example, needs items such as <TT>TPlayer</TT>,
<TT>TBoard</TT>, <TT>THero</TT>,
<TT>TScene</TT>, and so on. Your graphic objects don't know anything about those
kinds of objects.</P>
<P>To get a handle on this issue, you need to think in terms of specific problem
domains. One problem domain
involves using DirectDraw to create fast graphics. A
second problem domain involves creating a game engine, and a third problem domain
involves creating a specific game. You need to draw firm lines between these domains
so that the complexity of one
problem domain does not creep into another domain.
As a rule, you should not allow any direct calls to your graphics objects by the
users of your <TT>TGameEngine</TT> object. <TT>TGameEngine</TT> calls the graphics
objects, but it does so via private
interfaces that <TT>TGameEngine</TT> users can
never see.
<BLOCKQUOTE>
<DL>
<DD>
<HR>
<FONT COLOR="#000077"><B>NOTE: </B></FONT>An example might be helpful here. In DirectX,
you can write text to the screen using device contexts. You get the DC
for a device,
copy objects into it, and then use <TT>TextOut</TT> to write to the screen. Having
the game engine use these same objects is probably not wise. Instead, you should
hide the underlying technology and provide a routine with a name such
as <TT>WriteXY</TT>
or <TT>WriteLn</TT> or <TT>printf</TT> or <TT>Say</TT> that will let you write to
the screen. Internally, your implementation of <TT>WriteXY</TT> will use device contexts,
but that fact should be hidden from the user. This will
allow you to switch your
game from Windows to DOS to the Mac without having to change its code. Only the interface
to the graphics engine changes, but your game code remains untouched.
<HR>
</DL>
</BLOCKQUOTE>
<P>One way to help design these
objects correctly is to ensure that a user of <TT>TGameEngine</TT>
would have to do nothing more than recompile if you were to switch your game engine
technology from one set of graphics objects to another. In other words, the users
of
<TT>TGameEngine</TT> should not have to know anything about the tools you use
to create fast graphics. You can tell them, "Hey, I use DirectDraw," or
"I use WinG," but the actual technology involved should not matter to them
in the
sense that their code will still compile if you switch the background engine.
Users of <TT>TGameEngine</TT> should not have to know whether <TT>TGameEngine</TT>
uses DirectDraw or WinG. Users of <TT>TGameEngine</TT> never call the graphics objects
directly, and they don't even have to conceive of the fact that such a thing as an
<TT>IDirectDraw</TT> object exists.</P>
<P>Obviously, one of the important benefits of this system is that you can change
from WinG to DirectDraw without having to
rewrite your game or game engine. But this
capability is not the primary benefit that interests me. What I like about this system
is that it creates domains for problems. If I'm working with the <TT>TGameEngine</TT>
object and find that it's not
drawing things correctly because of some error in the
way I access DirectDraw, then I can put the <TT>TGameEngine</TT> object away, open
the graphics engine, and find out what is wrong. My game engine and my game cannot
be the cause of the problem
because they don't talk to the <TT>IDirectDraw</TT> interface.
They don't know anything about the <TT>IDirectDraw</TT> interface!</P>
<P>Another benefit of this system is that it allows you to improve one part of your
code without affecting existing
parts of your code. For example, I could drastically
rewrite the graphics engine without having to change the way <TT>TGameEngine</TT>
operates. In these situations, rewriting the graphics engine without changing its
interface is best, but even if you
do change it, you can still buffer your game from
these changes because it talks to <TT>TGameEngine</TT>, not to the graphics engine.
However, the best thing to do is to never change a public interface after you create
it.
<BLOCKQUOTE>
<DL>
<DD>
<HR>
<FONT COLOR="#000077"><B>NOTE: </B></FONT>I will concede that some of the theory
I am describing here is a bit idealized. In practice, I rarely achieve precisely
the degree of object independence described in the preceding paragraphs. However,
the closer I can get to it, the better off I am. Aiming as high as possible is always
best, thereby limiting as much as possible the amount of trouble you will have if
your architecture needs to be upgraded.<BR>
<BR>
Furthermore, the process of
learning to design good objects is incremental at best.
The first time I tried to create a complex set of objects, I failed miserably. The
second time, I took to heart some of the ideas I am describing here and came closer
to achieving my goal. The
third time out I made yet fewer gross design errors, and
so on, till finally I was starting to produce complex object hierarchies that could
actually be used and maintained.
<HR>
</DL>
</BLOCKQUOTE>
<H2><FONT COLOR="#000077">Creating Public
Interfaces</FONT></H2>
<P>The last paragraph of the preceding section introduces a second key rule of object-oriented
design. Creating problem domains is the most important step, but a second crucial
condition is creating public interfaces that have
little to do with your underlying
technology.</P>
<P>When you're creating the public interface for the graphics engine, you should
take off your <TT>IDirectDraw</TT> expert hat and put on one that helps you pretend
you are the user of this object.
What will a user of this object want to see? A user
doesn't want to hear about the nitty-gritty of using <TT>IDirectDraw</TT>; instead,
he or she wants to be able to work with broad concepts such as <TT>TBackground</TT>,
<TT>TSprite</TT>, and
<TT>TWindow</TT>.
<H2><FONT COLOR="#000077">Managing Complexity: Create Humble Objects</FONT></H2>
<P>Before going further, I want to talk just a little more about limiting the problem
domain.</P>
<P>One of the most important jobs that objects can do
for you is to help manage complexity.
In the first chapter of this book, I stressed the importance of being humble when
you program. Here, that theme can really start to pay off.</P>
<P>The worst mistake you can make as a programmer is to decide
"Hey, I'm so
smart, so cool, that I can make this object stunningly complex and efficient and
still be able to use it." In the process, you might end up continually collapsing
one object into another and continually finding fast, clever ways
to get tasks done
in the fewest possible moves. All this cleverness is good and well, if you can simultaneously
produce objects that you and others can use and maintain.</P>
<P>Putting all the logic into one set of objects has the following problems:
<UL>
<LI>Any hope of code reuse is obliterated. If one small set of objects forms the
whole game, how can you separate the reusable part of the code for a second game
that has similar characteristics?
<P>
<LI>Maintaining it is a nightmare. If
something goes wrong anywhere in the game,
you have no way of localizing a problem and testing it separately from the rest of
the application. If all you have are a few big, complex objects, when something goes
wrong, all the lines of code in your
program are suspect, and you cannot separate
out the code you need to test and repair. This monumental problem is likely to sink
most projects completely. You have to be able to break down a program into its various
components and test each part
separately.
<P>
<LI>Teaching someone how to work with the code for a game is extremely hard if he
or she has to understand the entire game to be able to work on any part of it. Understanding
one huge, complex object is difficult. The paradigm is
innately complex. You have
a much simpler task getting someone up to speed on some code if you can say, "Here,
we need to make these changes to this 500-line object. Please get to work right away;
time is of the essence." The nightmare
scenario sounds like this: "Welcome
aboard. We have 200,000 lines of code here, and we need to make some changes to it.
Please spend the next six months becoming familiar with our code base, and then I
would like you to make some changes to a
few small portions of it. Tell me when you're
up to speed."
</UL>
<P>Putting all the logic in clearly delineated sets of objects has the following
advantages, which are the converse of the disadvantages laid out in the preceding
three points.
<UL>
<LI>Code reuse is supported. A well-designed graphics engine can be reused in almost
any graphics-based game. A subset of those objects can be used in virtually any multimedia
venture that requires DirectDraw. The same is true with the
<TT>GameEngine</TT> code.
It's all in one place and can be reused. Conversely, the code that is specific to
Byzantium is all in one place.
<P>
<LI>Maintaining it is easy. If something goes wrong in the code, you can isolate
the problem in a few
distinct objects that you can test separately. Problems in one
part of the code don't automatically percolate into other, related domains. Instead,
they are isolated in one section of the code. This problem is like a leak in a submarine:
If one
section of the ship is damaged, you can seal it off from the rest of the ship.
It won't affect the whole program; it is isolated in one area. You can then concentrate
on fixing that area without worrying about the ramifications of those repairs on
the rest of the program.
<P>
<LI>Understanding it is easy. You know exactly what is going on in the graphics engine
components because the problem domain is manageable. You can explain the basic structure
of the program to someone in five minutes
because each part plays a distinct, easy-to-understand
role.
</UL>
<P>The theme underlying all these points is humility. To be a good programmer, you
have to admit that a certain level of complexity simply overwhelms you. Your only
bulwark against
that confusion is to break down the project into manageable chunks
that you can understand.</P>
<P>Humble programmers produce real programs. Hotshots are going to produce fantastic
programs Real Soon Now. I know that's true because those hotshots have
been telling
me about their program ideas for years.
<H2><FONT COLOR="#000077">The DirectX Game Engine</FONT></H2>
<P>In the next few sections of the chapter, I describe a set of components that make
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -