Introduction Ever
since I started playing games on my very first VIC-20 17
years ago I wanted to know how games worked and over the
last 10 years of my programming career 95% of the
programmers I worked with have all wanted to write games
of one sort or another. As most of us came from a
database application backgrounds, I suppose the grass
always seemed greener on the game development
side. Though I somehow doubt that game programmers
have a yearning for database programming.
In the articles that follow over the coming months I
hope that the journey that takes us to the "other side"
will prove to be both educational, and more importantly,
enjoyable. My plan is to build a prototype isometric
engine ( used in such games as Command and Conquer,
Dark Reign, StarCraft &
Diablo ) using DelphiX
(a free set of DirectX components), that will eventually
incorporate some 3D elements as well. While building
this prototype engine I intend to cover such topics as
collision detection, shortest path algorithms across a
map, unit formations/groupings using boids and animating
your characters.
Our first order of business is to get an overview
of DirectX , followed by some basic
terminology and quickly followed by a DelphiX
overview closely followed by a simple
example in using some DelphiX components to create a
worm-hole effect that looks similar to
this...
DirectX
OverviewTechnically, DirectX is a set
of COM ( Component Object Model ) objects
that implement a number of interfaces that simplify the
communication to video hardware, sound hardware, net
working, input devices and some system services (see Figure
1.) .
It was created to solve the problem of having umpteen
hardware manufactures all coming out with the latest and
greatest 2D/3D accelerator, advanced sound synthesis
hardware, networking hardware and strange input devices.
Under Dos gaming programming you would have had to
probably write your own device drivers for these new
pieces of hardware. Using Windows 95/98/NT, and soon to
be, Windows 2000, most ( if not all ) of the
compatibility issues are supposed to be solved.
Also when using DirectX if you happen to have
hardware acceleration ( such as 3Dfx, Nvidia and the
like ) it will use that instead, thus freeing up the CPU
to do other things. So, the person who spends $500 on
their super duper 128 bit video card gets their money's
worth and the game looks better and runs faster without
additional code. Just FYI ( for your information ),
DirectX 6.1 works with Windows 95 and 98. DirectX
3 works with NT 4 but only with service pack 3.
There is an un-official/un-supported DirectX 5 patch for
NT 4 that can be found here.
I have also got DirectX 6.1 running on NT 5 beta 2,
though Microsoft have said that when NT 5/2000 is
officially released it will support DirectX 7.0.
DirectX is currently made up of the following 7 major
components :-
- DirectDraw
- Allows direct access to display memory and hardware
features, while maintaining compatibility with Windows
based applications.
- DirectInput
- Interface for Input Devices ( Mouse, Keyboards,
Joysticks, Headgear etc... ).
- DirectPlay
- Interface for multi-player type options ( TCP/IP,
Direct Dial, Local Networking ).
- DirectSound
- Interface for sound hardware ( WAV, MIDI files and
the like ).
- DirectSound3D
- Interface to allow you to position sounds anywhere
in three-dimensional space, thus giving you that
Surround Sound feel.
- DirectMusic
- Interface for creating an array of original musical
patterns and instructions that respond to user events.
- Direct3D
- Interface for 3-D hardware ( includes Immediate and
Retained Modes ).
They are all designed to
give the programmer direct hardware access.
[ Figure 1 - DirectX
architecture ]
Terminology Before we start
using the DelphiX components I think we need to cover
some DirectX terminology.
Surfaces - Video memory that is
used to store various bitmaps and offscreen video
butters are all referred to as surfaces in DirectX. The
video memory or surface that is currently displayed on
the screen is referred to as the primary surface.
This surface is as big as the amount of memory needed
for the current display mode. If the display mode is 640
x 480 x 256 colours ( 8 bit per pixel ), then the
primary surface would use 307,200 bytes of video
memory. You usually also create at least one
offscreen surface that is the same size as the primary
surface this offscreen surface is used for
flipping ( this will be covered shortly ).
This means that you need 614,400 bytes of video memory
just to get started, without even loading any bit
maps. When you run out of video memory, your
direct Draw surfaces will be created in system memory (
normal RAM ) thereby losing the benefits of hardware
acceleration. Currently a 2MB video card should be
considered the absolute minimum for getting a fairly
simple game up and running.
Double Buffering - Is a
technique used to achieve fast, smooth animation. It is
usually a separate image buffer that is used to compose
your scene on, before it is visible. This is usually
used with page flipping ( see next explanation ) .
Page Flipping
animation - This term probably goes back to
your school days when you used to entertain yourself by
drawing scenes on consecutive pages at the bottom of
thick books so you could flip the pages and get an
animation effect. If you never did this as a
child, give it a try now, it will help crystalise the
effect we are looking for. Scenes are usually
composed by copying ( also known as blitting ) bitmaps
or sprites
to an offscreen surface ( or buffer ), and when the
scene is complete the video hardware has the ability to
flip to the offscreen surface, thus making the newly
composed scene visible. Page flipping is extremely
fast because there is no memory copying involved.
It is simply a matter of setting a register on the video
card that tells it where to start displaying from
in video memory. There are basically 3
steps in creating page flipping animations.
- Compose the scene on the offscreen surface.
- Flip to the offscreen surface to display it, which
also makes the previously displayed surface the
offscreen surface now.
- Repeat step 1.
Frames Per Second - Is Usually
refered to simply as FPS, and is a term used to describe
how many frames of animation will be displayed on the
screen so that the human eye will think that the
movement it is seeing is smooth enough to appear real.
As a guide, feature films display 24 FPS, while
television usually broadcasts at 25 FPS. As a game
developer, in general these are the sort of figures we
should be aiming for as a minimum, in order for our game
to look half decent. In certain styles of games, such as
RTSs ( Real Time Strategy ), you can sometimes get away
with as little as 15 FPS, but as I mentioned 24-25 FPS
should be our goal.
Tearing
- Most monitors try and "refresh" the display
about 70 times per second ( 70 Hz ), and it normally
refreshes from top to bottom. The problem occurs when
you try to draw a new image on the screen when the
monitor is in the middle of redrawing/refreshing the
current display. When you do this the bottom half of the
screen is drawn using the new image while the top half
still has the old image. This visual effect is called
tearing or shearing. In the dark days of DOS you would
have had to check for a vertical retrace to determine
when the screen was refreshing so that you could
avoiding this tearing from happening. With DirectX this
check is taken care of for you.
Bitmaps and Sprites - Bitmaps
are basically images. Sprites are the same as bitmaps
but usually have transparent areas. The term Sprites, is
also used for animated images within a game. Sprites are
usually made up of several frames of animation, Such as
a man walking or as in this example a space ship
flying...
Notice how each frame depicts
a particular angle of movement. If we were to show all
these images sequentially is would look like
this...
Also
note that the transparency colour of this sprite is
black, hence the white background above shows
through.
Clipping
- Is a technique used to ensure that drawing
routines are only able to draw within a specified (
usually ) rectangular area or region, such as a window.
If you used DirectX without clipping you would be
able to draw anywhere on the screen. This is fine if you
are in full screen mode, but is definitely unacceptable
if your application is windowed.
Colour
theory - Colours under Windows is usually
represented, by the RGB (Red,
Green, Blue) colour model. Using the 3 primary
colours red, green and blue, nearly all possible visible
colours can be produced by combining various proportions
of the three . These are commonly stored as three
bytes - each byte represents the relative intensity of
each primary colour as a value from 0 to 255 inclusive,
thus giving us 256 possible colours. 0 being of lowest
intensity and obviously 255 being the highest.
In Delphi, colours are represented by the TColor class that is defined within
the Graphics unit. You can specify colours
either using the pre-defined constants like clBlue, clLime etc. or for
greater accuracy, specifying the TColor as a specific
4-byte hexadecimal number where the low three bytes
represent RGB colour intensities for blue, green, and
red, respectively. The value $00FF0000 represents full
intensity, pure blue, $0000FF00 is pure green, and
$000000FF is pure red, $00000000 is black, $00FFFFFF is
white and $00FF00FF is purple. I'm sure you get
the idea. A little extract from the VCL help file also
tells us that "If the highest-order byte is zero
($00), the color obtained is the closest matching color
in the system palette. If the highest-order byte is one
($01), the color obtained is the closest matching color
in the currently realized palette. If the highest-order
byte is two ($02), the value is matched with the nearest
color in the logical palette of the current device
context."
There are other colour models, such as HSV (Hue,
Saturation, Luminance), but I will not be covering them
in these articles. The book "Computer Graphics,
principles and practise" by Foley & van Dam (
often referred to as The Computer Graphics Bible )
explains colour models in some detail, and how to
convert between colour models.
|