|
Has the
age of so-called "2D" programming drawn to a close? Certainly
for some genres the twilight has come -- a designer suggesting a side-scrolling
adventure game would likely have just recovered from a long coma. But
for other categories, a 3D environment is not an easy fit. Titles such
as Sid Meier's Alpha Centauri (and his Civilization series),
the Age of Empires games, Talonsoft's Operational Art of War
series, and the entire Red Alert series all use a 2D interface
and map to good effect. That is not to say everything must look flat,
for instance Age of Empires 2 and Red Alert 2 make use of
detailed graphics for units, buildings, and landscape that have the appearance
of depth. However, this does not change the fact that they are still 2D
game engines. More than that, it can be strongly argued that a move to
a "full 3D" environment would reduce the quality of gameplay
on these products. For instance, Sierra's Ground Control could
be considered the 3D evolution of the RTS concept, yet it was Red Alert
2 that beat it out to win IGN's recent Readers Choice Award for Best
Strategy Game of 2000.
Having determined
that the opportunities for a 2D engine are still alive and well, PC programmers
are currently facing three problems: first, Microsoft's recently released
DirectX update has focused all its new API development into the area of
3D support; next, game players are clamoring for higher graphics quality
and special effects; and finally, there is a substantial learning curve
for a 2D programmer to move to the world of 3D graphics APIs such as Direct3D
and OpenGL. Yet the newest release of Microsoft's DirectX, version 8,
offers some features to help make the transition a bit easier.
A Brief Overview
of Traditional 2D Methods
The king
of 2D graphics concepts is the sprite. At its very simplest, a 2D engine
is capable of drawing a background image and then drawing individual graphic
objects -- sprites -- onto that image. The use of color-keying allows
a specific color in a sprite to be considered transparent, which allows
sprites to be any irregular shape. And the use of a series of sprites
to represent an object, for instance a number of different facings of
a unit, allow the simulation of animation and action when they are drawn
in sequence. The fundamental programming process for 2D graphics is the
blit -- bit block transfer -- which is used to move the bit image of a
sprite onto the display area. Finally, to provide a smooth transition
of the display from frame to frame, graphics operations (primarily blits)
are usually done to a back buffer, which is basically a working copy of
the screen area. Once the frame is complete, the back buffer is flipped
to the display area (front buffer), and the next frame begins from scratch.
Almost everything else in 2D graphics is built on these base concepts.
In DirectX,
Microsoft provided a capable (but sometimes limited) interface for 2D
graphics which they called DirectDraw. This API provided all the basics
that a 2D engine required. A DIRECTDRAWSURFACE
is used to represent both raw-data graphic surfaces (filled with background
images or sprites) and the primary display surface (front and back buffers).
Most of these surfaces could be in either video memory or system memory
(with the exception of the active front buffer of the display, which is
of course always in video memory). The DirectDraw
Blt() command is used to move images or portions of images around
between surfaces. While there is not any specific support for sprites
as a unique object in DirectX, it is a trivial matter to create a library
to split one large surface into an array of rectangular cells for use
as sprite objects. Take a look at some of the data files on disk used
by many commercial games and you'll find these graphic "template"
files of object sprites.
The
DirectDraw Blt() function
handles color keying and also provides support for a few more advanced
options such as mirroring, stretching, and shrinking of bitmaps. These
features, however, are often driver-dependent and are supported to different
extents on different video hardware, providing inconsistent results if
used. A simplified code snippet of drawing a frame in DirectDraw is provided
in Listing 1.
Changes in DirectX
8
With the
release of DirectX 8, Microsoft made some significanet changes in the
design and implementation of the graphics engine. They replaced the separate
DirectDraw and Direct3D components of DirectX 7 with a new component officially
called "DirectX Graphics." It does not take long, however, to
notice that all the focus in this new component is on 3D functionality,
and DirectX Graphics is often interchangeably called "Direct3D 8."
The interfaces of DirectX Graphics are not derived from the interfaces
of previous DirectX versions, but are an entirely new design. As in all
releases of DirectX, older interfaces are available -- meaning that you
can install DirectX 8 but still program for the older version 7 (or earlier)
functions. And this is, in fact, the oft-suggested solution when DirectDraw
programmers take a look at the new API in version 8. To quote from Microsoft's
DirectX FAQ, posted February 1, 2001:
"What happened to DirectDraw? Much of the functionality
of DirectDraw has now been subsumed into the new Direct3D 8 interfaces.
Developers working on purely 2D applications may wish to continue using
the old DirectX 7 interfaces. Developers working on 3D applications with
some 2D elements are encouraged to use Direct3D alternatives (point sprites
and billboard textures, for example) as this will result in improved performance
and flexibility."
While this
is the official line, there are a few problems with this answer that cause
confusion among 2D programmers looking to port their code to the latest
API. First, it is misleading to say that "much of the functionality
of DirectDraw" has been included in the new Direct3D 8 (possibly
explaining their use of the uncommon word "subsumed"). Most
significantly, there is no longer a blit command or equivalent function.
Early in the beta process of DirectX 8, developers looked at new functions
such as CopyRects()
to provide some blit features but these lack necessary support for important
capabilities such as color keying. Point Sprites, a new feature in DirectX
8, are technically quite limited and do not provide required functionality.
That leaves "billboard textures," a concept with little information
in the DirectX SDK and no provided examples for a 2D programmer to follow.
There is,
however, the carrot at the end of the stick: "improved performance
and flexibility." Clearly DirectX 8 is designed to get the most out
of modern video cards, utilizing all the hardware acceleration available.
Scaling, rotation, and most importantly alpha blending are all standard
features with 3D graphics, and all hardware-supported. Alpha blending
was defined in the DirectDraw
Blt() function, but listed as "Feature Unsupported in DirectX
7," leaving programmers wishing to use this feature quite unsatisfied.
So, how can a 2D programmer take advantage of these DirectX 8 features?
|
I'll see if I can dig up the listings and post them somewhere again. Of course DX8 was replaced by DX9 and the more recent incarnations, though for people looking to do basic 2D work on DX9 the concepts (and most of the code) are still valid.