october/november 1996

GAME DEVELOPER MAGAZINE GGAMEAEM GAME PLAN

Editorial Director Larry O’Brien [email protected] Senior Editor Alex Dunne [email protected] Whither Delphi? Managing Editor Diane Anderson [email protected] his month’s lead article is the first industry. A few days ago, I had a chance Editorial Assistant Jana Outlaw feature that we’ve ever run about to sit down with people from Stereo- [email protected] Contributing Editors Barbara Hanscome Delphi. Back in April of last year, Graphics, the company that makes the [email protected] editor Larry O’Brien wrote an SimulEyes VR 3D glasses. I’ve never Chris Hecker editorial titled “Delphi is the been bullish on 3D eyewear—they always [email protected] Answer.” He explained the bene- struck me merely as novelty items with- David Sieks fit of using Delphi to access out a future outside a hardcore niche of [email protected] WinG, abstract the Windows game players. This meeting gave me five Web Site Manager Phil Keppeler TAPI, and get more compile-link-debug reasons to rethink my position on stereo [email protected] cycles in than you otherwise could with vision glasses: Cover Photography Carter Dow Photography C/C++. Back then, we thought that Del- 1. The price point of these glasses will Publisher Veronica Costanza phi had a decent shot at becoming a staple soon fall under a hundred bucks (a Group Director Regina Starr Ridley development tool for game developers. magic number for consumers). Special Projects Manager Nicole Freeman The product has made few inroads in 2. It’s simple for consumers to install and [email protected] the game development community, use—you don’t have to pop the top on Advertising Sales Staff though. Because the problems corporate your computer case. You just plug a Western Regional Sales Manager application developers face are significant- dongle into the video port and plug Steve Nikkola (415) 905-2256 ly different than those of game developers, your monitor into that, switch on the [email protected] Delphi has languished and is considered little box, and start up your game. Western Account Manager an almost-ran by most game developers. 3. A number of major game developers, Barbara Wren (415) 356-3362 On top of that, the recent releases of game such as Interplay and Nova Logic, are [email protected] SDKs from Microsoft and Apple have building support for stereo vision in Promotions Manager/Eastern Regional Sales Manager ensured that C/C++ will remain the lin- their upcoming games. Holly Meintzer (212) 615-2275 [email protected] gua franca of game development. That 4. Many major 3D accelerator cards on Eastern Sales Assistant begs the questions, “Whither Delphi? Has the market this holiday season are John Travers (212) 615-2682 Game Developer gone nuts covering this going to have built-in support for [email protected] product?” stereo vision. The difference between In his article “Delphi Does DirectX: viewing a fully texture-mapped game Marketing Manager Susan McDonald Using Encapsulated COM Objects” on in 3D and a rendered game in 3D is Marketing Graphic Designer Azriel Hayes page 22, Charlie Calvert makes a convinc- significant—the higher visual quality Advertising Production Coordinator Denise Temple ing case for the product. Using Delphi’s will entice people to buy into 3D Director of Production Andrew A. Mickus encapsulation features, C and C++ devel- technology. Vice President/Circulation Jerry M. Okabe opers can simplify development by wrap- 5. The technology has received impor- Circulation Director Gina Oh ping DirectX COM objects (in this case tant nods from Microsoft and Apple, Associate Circulation Director Kathy Henry ISpeedDraw) and accessing them as DLLs. who announced they will build stereo Group Circulation Manager Mike Poplardo Encapsulating components in this manner vision support into their respective Assistant Circulation Manager Jamai Deuberry may solve one complaint that I hear fairly game SDKs. Newsstand Manager Debra Caris frequently, that being the complexity of These factors point to a bright Reprints Stella Valdez (916) 729-3633 Microsoft’s Component Object Model. future for companies like StereoGraph- Chairman/CEO Marshall W. Freeman As Calvert explains, a properly designed ics and might even herald a future President/COO Thomas L. Kemp Delphi component is easy to use and where the masses regularly don “game Senior Vice President/CFO Warren “Andy” Ambrose maintain. This is the most compelling use shades.” If you’re interested in finding Senior Vice Presidents David Nussbaum, Darrell of Delphi for game development I’ve seen out more about the technology or sign- Denny, Donald A. Pazour, Wini D. Ragus yet. ing on to the StereoGraphics developer Vice President/Production Andrew A. Mickus program, check out their web site at Vice President/Circulation Jerry Okabe The Future’s So Bright, I http://www.stereographics.com. ■ Vice President/ Gotta Wear Game Shades Software Development Division Regina Starr Ridley One great perk of editing a magazine is Alex Dunne Miller Freeman all the contacts you make within the Senior Editor A United News & Media publication

6 GAME DEVELOPER • OCTOBER/NOVEMBER 1996 http://www.gdmag.com BIT BLASTS

Trick or Treat Diane Anderson

curious trend: developers are for $1,495; the upgrade from 1.75 is $295. assembles and manipulates real-time 3D abandoning game companies A Windows version of StudioPro 2.0 will scenes in a virtual reality environment. to start ventures of their own. be available the first quarter of 1997. Wearing pinch gloves and a 3D head- Sid Meier left MicroProse, ■ Strata mounted display, the SmartScene user Chris Roberts left Origin, and St. George, Utah steps into a virtual workspace and now, perhaps most surprising, (801) 628-5218 becomes the architect of realtime 3D John Romero is leaving id, http://www.strata3d.com worlds with a two-handed interface. which he helped found in SmartScene is available for $30,000. A1991. Don’t worry, Bit Blasts introduces MultiGen also announced GameGen II ★ products to help you have a booming Star Trak for Windows NT, which provides author- business with satisfied employees. Just Realism is a big issue for game developers ing tools for building optimized 3D check out some of these products.... because everyone expects characters to worlds in the OpenFlight data format. move in a lifelike way; very few games The core product, GameGen II Author, actually deliver. Maybe wireless motion will cost $7,500. Two options, Model- mTropolis capture is the answer to your movement Maker and BSPMaker, will cost $2,500 mFactory Inc. is now shipping an update woes. Polhemus announced Star Trak. each. to its mTropolis software, an object-ori- This wireless motion capture system pro- ■ MultiGen ented authoring system for building inter- vides six-degree-of-freedom (position and San Jose, Calif. active multimedia titles and applications orientation) data from up to 32 sensors on (408) 261-4100 for use on MacOS, Windows-based com- multiple characters at up to 120Hz for http://www.multigen.com puters, and the Internet. Version 1.1 of dynamic motion capture situations. Users mTropolis features run-time object get freedom of movement within a 25- cloning, support for Apple’s QuickTime foot-by-25-foot area. The system includes Raving VR, and immediate display update. It a Trak Suit (lycra body suit containing Apple announced version 1.5 of its cross- costs $4,995 to new users but is free to all signal acquisition electronics for up to 16 platform 3D graphics toolkit—Quick- registered customers of mTropolis 1.0. receivers), a motion capture server, Draw 3D. The QuickDraw API is avail- ■ mFactory receivers, transmitter, and calibration fix- able for MacOS, Windows 95, and Win- Burlingame, Calif. ture. January 1997 deliveries are being dows NT. QuickDraw 3D has four com- (415) 548-0600 booked. ponents: a fast 24-bit interactive renderer, http://www.mfactory.com ■ Polhemus system-level handling of 3D components, Colchester, Vt. a new 3D file format standard called (802) 655-3159 3DMF, and user-interface guidelines. Are You a Pro? http://www.polhemus.com Apple also announced availability of its In addition to acquiring VideoShop from QuickDraw 3D RAVE (Rendering Ac- Avid, Strata announced StudioPro 2.0, a celeration Virtual Engine) for the three major upgrade to its modeling, rendering, Make a Scene platforms. 3D Rave supports DirectDraw and animation package. The new version MultiGen announced SmartScene, a new on Windows 95 and render caching for features extruding, lathing, sweeping, immersive assembler that lets a user stand faster manipulation of rendered objects. freeform deformation, and new camera in the scene he or she is creating and ■ Apple controls such as autopan, zoom, dolly, design a realtime 3D world. No need to Cupertino, Calif. pitch, yaw, roll, motion blur, and lens flare. model objects by polygon with a (800) 462-4396 The Power Macintosh version is available mouse and keyboard; the SmartScene user http://www.apple.com

10 GAME DEVELOPER • OCTOBER/NOVEMBER 1996 http://www.gdmag.com BEHIND THE SCREEN

Physics, The Next Frontier

o doubt about it: each year Not by a long shot. High-end was controlling them instead of an ani- games become graphically developers will continue to raise the bar mation loop. Suddenly the gears more realistic. Everybody’s in many different technologies, like become more than just eye candy as one doing (or at least showing graphical complexity, artificial comes off its axle and rolls down the screenshots of) texture- intelligence, and networking. While hall after you, Indiana-Jones style. Or mapped 3D game worlds these are indeed important topics, we imagine shooting a gear with a missile, these days, and, when the can’t really discuss any of them in depth causing it to roll down the hall and hardware people finally get without going into game-specific crush your friend who was about to frag theirN act together, every developer will details. However, there is one generally you from behind! A real physics engine be able to draw zillions of perspectively applicable technology I think will makes situations like these possible. correct textured and shaded per become a key differentiating factor in The physics simulation is also second. Technically speaking, what will the near future: physics. what makes a game world feel solid—it be left to do for high-end games? Will Here’s an example: remember puts the “there” there, if you know what every developer with a copy of “Learn to those huge rotating gears in one of the I mean. All the graphics wizardry in the Use 3D Hardware in 21 Days” be able to early shareware levels of Duke Nukem world won’t help players immerse write an impressive game? 3D? Imagine if a general physics engine themselves in your game if they inter- penetrate each other or the walls of the Figure 1. y=x2 level, or if they don’t feel like they have any mass or momentum. The original animators at Disney discovered that this feeling of mass is a large part of what set apart the believable animation from the bad. According to the epic book Disney Animation: The Illusion of Life (Abbeville Press, 1981), by Frank Thomas and Ollie Johnston, Disney animators even hung a sign around the studio to constantly remind themselves: “Does your drawing have weight, depth, and balance?” But doesn’t almost every game already have a physics engine? Sure, it keeps your car from falling out of the world through the track, it keeps your characters from floating away when they jump, and it knocks your ship to the side when a missile explodes near- by. However, most physics engines in today’s games are pretty weak, doing just enough to keep that car from falling out of the world, but not enough to take the game to the next level of interaction—where a wrecked car’s

12 GAME DEVELOPER • OCTOBER/NOVEMBER 1996 http://www.gdmag.com debris might explode onto the track, in your game, either through extreme careening into the wall and other cars, physical realism or through fanciful but Chris Hecker tires rolling into oncoming traffic. consistent surrealism. Other often ignored physical pos- A word of caution: physics is sibilities include everything from simple math—you can’t separate the two and We‘ve been faking rotational effects induced by being hit still get interesting work done. Before off center, to having the creatures in the this scares people away, let me point out game be self-balancing and motivat- that not only is the math behind physics ing—rather than based on static anima- totally elegant and beautiful, it’s also physics in games for tions—so they can react to new physical applied. That is, it’s not abstract math stimuli. I think most developers ignore for math’s sake. Each equation we use these possibilities because they don’t has real physical meaning. We create the understand the math behind physics equations from the physical model, and a while. Now, and have been too busy writing perspec- in return the equations tell us how that tive texture mappers to learn it. The model behaves over time. onslaught of 3D hardware will take care of the latter issue, and the new series Mass-ive Undertaking technology is I’m starting with this article will try to Physics is a vast field. We’re actually take care of the former. By the time only interested in a small subset of it we’re done, you’ll know enough to write called dynamics, and even more specifi- advancing to the point a physics engine that immerses players cally, rigid body dynamics. Dynamics Figure 2. dv/dt = -v/m where implementing a real physics engine within a game is possible. Hecker‘s new series explores how.

http://www.gdmag.com GAME DEVELOPER • OCTOBER/NOVEMBER 1996 13 BEHIND THE SCREEN

can be defined most easily in terms of a Derivative Work closely related field, kinematics—the This may come as a surprise to you, but study of movement over time. Kinemat- you actually can’t directly move an dr ==vr& (Eq. 1) ics doesn’t concern itself with what’s object by pushing on it. I know, you’re dt causing movement or how things get thinking about proving me wrong by where they are in the first place, it just pushing this magazine into the trash for deals with the actual movement itself. printing such nonsense, but it’s true: On the contrary, if we integrate the Dynamics, on the other hand, is the pushing on the magazine does not velocity vector over time, it tells us how study of forces and masses that cause directly affect its position. In fact, push- the position vector changed over that the kinematic quantities to change as ing doesn’t even directly affect its veloc- time. time progresses. How far a baseball ity. What pushing does directly affect, Acceleration is handled similarly; travels in 10 seconds if it’s traveling 50 however, is the magazine’s acceleration, it’s the derivative of velocity, or the sec- kilometers per hour in a straight line is and this fact is one of the most impor- ond derivative of position: a kinematics problem; how far a base- tant findings in the history of science. ball travels in the earth’s gravitational In order to use this amazing fact to field if I smack it with a bat is a dynam- do anything interesting, we first need to 2 ics problem. talk about the relationship between d r drv& d =====r&& va& The “rigid body” part of rigid body position, velocity, and acceleration. It dt 2 dt dt dynamics refers to constraints we place turns out these quantities are very close- upon the objects we’re simulating. A ly related (as you probably know): (Eq. 2) rigid body’s shape does not change dur- velocity is the rate of change of position ing our simulation—it’s more like wood over time, and acceleration is the rate of or metal than jello. We can still create change of velocity. The primary tool for Integrating the acceleration over articulated figures, such as a human studying these changes in time is calcu- time gives the velocity, and twice inte- being, by building each section of the lus. While you might be able to pick it grating the acceleration gives the position. figure from a rigid body and putting up as we go along, I’ll assume you know These kinematic relationships tell us joints between them, but we won’t some calculus. We’re going to use only that if we can find the acceleration on an account for the flexing of bones under simple scalar and vector calculus (deriv- object, we can integrate it with respect to strain or similar effects. This will let us atives and integrals), but it won’t hurt if time to get its velocity and position. As simplify our equations while still allow- you’re familiar with the subject as a we’ll see, we perform this integration ing for interesting dynamic behavior. whole. For reference, my favorite calcu- numerically in our simulation code and Even with our tight focus, rigid body lus textbook is Calculus with Analytic come out with a new position for our dynamics will take a series of articles to Geometry by Thomas and Finney rigid body each frame. Voila, animation! explain. We’re going to start our journey (Addison-Wesley, 1996). Here’s a short 1D example we can by learning the basics of programming a Position, velocity, and acceleration analytically integrate. Let’s say we want computer to move a 2D rigid body are the kinematic quantities we care to find the change in our position over around under the influence of forces. I about in this article. The position of a the time period from the end of last explicitly say, “program a computer,” rigid body in 2D is obviously an X,Y pair frame to the current time so we can draw because in addition to the equations we’ll denoting the world coordinates of some our current position. Let’s further say we develop for the kinematics and dynamics, known point on the body. The derivative know the acceleration on our rigid body we’ll also learn how to solve these equa- of the position vector is the velocity vec- during this time was a constant 5 tions in our programs using floating-point tor for that point, and it tells us what units/sec2. We’ll use the time since the math, which is a vital subject all to itself. I direction the point is moving (and the end of last frame as the integrating vari- say, “a 2D rigid body,” because we’re body if we ignore rotation, which we are able, t: going to stick with two dimensions for for now) and how fast it’s going. Vector the next article or so. The principles— calculus is just scalar calculus on each va()tdtdttC===+∫∫55 and in fact most of the equations—carry element of the vector, so the derivative across to 3D, but certain things are sim- of the X element of the position is the X (Eq. 3) pler in 2D, so we’ll get comfortable there element of the velocity, and so forth. We before moving up a dimension. In future denote the position vector with r and the The above equation shows us the articles, we’ll learn about handling rota- velocity vector with v or with the “dot- velocity as a function of the time since tional effects, collision detection and ted” position vector (in general, a dot the last frame. We discover the constant response, and of course how to do all this means differentiated with respect to of integration, C, is the initial velocity at in three dimensions. Enough about what time, a double dot means twice differen- the beginning of this integration period we’re going to do, let’s get started! tiated, and so on): by plugging in t=0:

14 GAME DEVELOPER • OCTOBER/NOVEMBER 1996 http://www.gdmag.com BEHIND THE SCREEN

sum of all the momentums of all the points that make up the v()050=+ () C body (I’m using superscripts to denote which quantities belong to which points): = vC0 (Eq. 4) Tii= (Eq. 7) =+ pv∑m v()ttv5 0 i

Now we’ll integrate our velocity equation to find the posi- We can greatly simplify the dynamic analysis of rigid bod- tion (again solving for the constant of integration): ies by introducing a point called the center of mass (CM). The vector to the center of mass is the linear combination of the vec- 5 rv()t==+=++∫∫ () t dt5 t v dt t2 v t r tors to all the points in the rigid body weighted by their masses, 0 2 00 divided by the total mass of the body, M: ∑ miir (Eq. 5) (Eq. 8) rCM = i So, Eq. 5 says we can calculate the current position under M the given acceleration if we know the initial position and veloci- ty (which we assume we have from the end of the last frame) Using this definition of the center of mass, we can simplify and the time elapsed. We plug in the time, and out pops the Eq. 7 by multiplying both sides of Eq. 8 by M, differentiating current position. We’ll also want to plug the time into Eq. 4 to both sides, and then substituting the result into the Eq. 7: calculate the ending velocity so we can use it as an initial condi- CM i i tion for the next frame. dM()rrdm () ===∑∑miivpT dt dt May The Force Be With You i i Now that we have an idea of how to integrate kinematic equa- (Eq. 9) tions to get animation, we need to determine the right accelera- tions to use in the first place. This is where dynamics comes in. The right hand side of Eq. 9 is just the total momentum by Remember how I said pushing on something only directly definition in the Eq. 7. Now look at the left hand side: it is the affects its acceleration? Well, pushing is just a euphemism for velocity of the center of mass times the mass of the whole body, applying a force—one of the two key quantities in dynamics— so bringing the right hand side across gives us: and we can turn to Newton to see how forces affect accelera- CM tions. Newton’s laws relate force, F, to the derivative of the T dM()r CM p ==Mv (Eq. 10) mass—the second key dynamical quantity—times the velocity. dt The mass times the velocity is called the linear momentum, denoted by p: Eq. 10 says the total linear momentum is equal to the dpvdm() Fp==& = =mmva& = total mass times the velocity of the center of mass, meaning dt dt there’s no need to do the summation in Eq. 7 to find the momentum as long as we know the total mass and the location (Eq. 6) and velocity of the center of mass. For continuous rigid bodies all the finite summations above turn into integrals over the The mass is constant for the speeds we care about, so it body, but the center of mass still exists and simplifies the total drops out of the derivative in Eq. 6, and we get the famous momentum equation down to Eq. 10, so we don’t have to F=ma (although I believe Newton originally stated the defini- care—for the purposes of finding the linear momentum we can tion of force as the derivative of momentum). treat all bodies as a single point mass and velocity. If we were only dealing with single point masses, Eq. 6 Similarly, the total force is the derivative of the total would be all we’d need to do dynamics. For a given applied momentum, so the concept of the center of mass can be used to force, we find the acceleration of the point by dividing the force simplify the force equation in the same way: by the mass. This gives us the acceleration to use in our integra- T T CM CM tion, and so we can solve for the movement as in our example Fp==&&MM v = a (Eq. 11) above. However, we’re dealing with rigid bodies with mass dis- tributed over their area (and volume when we go to 3D), so we In short, Eq. 11 tells us we can treat all the forces acting on need to do a bit more work. our rigid body as if their vector sum is acting on a point at the First, let’s picture our rigid body as a set of point masses. center of mass with the mass of the entire body. We divide a force We define the total momentum, pT, of the rigid body as the (say, gravity) by M to find the acceleration of the center of mass,

16 GAME DEVELOPER • OCTOBER/NOVEMBER 1996 http://www.gdmag.com BEHIND THE SCREEN

and then we integrate that acceleration too complex, so we end up doing what’s example, what if f = -v, meaning the fric- over time to get the velocity and position called numerical integration of ordinary dif- tion force decelerates our body at a rate of our body. Since we’re ignoring rota- ferential equations (ODEs). Wow, now proportional to our velocity? Now we tional effects until the next article, we that sounds like real math! Once you’ve have a problem, because if we solve for now have all the equations we need to do learned this stuff, it’s time to ask for a the acceleration by writing f = ma = -v rigid body dynamics. Note that Eq. 11 raise. Luckily, numerical integration of and then divide through by m, we get doesn’t contain any information about ODEs isn’t quite as complicated as it (remember the acceleration is the deriva- where the forces were applied to the sounds. To figure out what it means, let’s tive of the velocity): body. That information drops out when take the phrase apart from the inside out. dv v dealing with linear momentum and the First, a differential equation is an a ==− center of mass, and we just apply all forces equation where derivatives of the depen- dt m to the CM to find its acceleration. When dent variable appear in the equation in we calculate rotation under forces in the addition to the dependent variable itself (Eq. 12) next article, we’ll see how the force appli- and the independent variable. That’s a This is a differential equation cation position is used. mouthful, but here are some examples: if because the equation for the velocity has we have an equation for a time varying the derivative of the velocity in it. Eq. 12 Ode to Joy 1D force like f = 2t, f is the dependent is called an ordinary differential equation At this point, we could run through variable and t is the independent vari- because it contains only ordinary deriva- another analytical integration example able; f’s value depends on t’s value. How- tives of the dependent variable (as using Eq. 11 to calculate the acceleration ever, what if the equation for the force opposed to partial derivatives, which cre- of our center of mass instead of arbitrarily on our body depends on the velocity of ate PDEs, which we won’t talk about). picking the value 5. However, for non-toy our body? Air friction is a force like Now for the next part of our phrase: problems, analytical integration usually this—the faster the plane goes, the more integration. How do we integrate dv/dt isn’t an option because the integrand is air friction it encounters. Again in a 1D to find v in terms of t when the equation

18 GAME DEVELOPER • OCTOBER/NOVEMBER 1996 http://www.gdmag.com for dv/dt has v in it already? It sounds computer is actually relatively easy to all points—this is the definition of satis- impossible, but actually almost every understand. In the space I have left I’m fying the equation dy/dx = 2x. You equation in physics is a differential equa- going to describe the simplest numerical should also notice that there are a lot of tion, so ODEs have been studied a lot. integrator, Euler’s method, and leave different parabolas that would satisfy the Differential equations pop up in physics improving it to a later article. vector field tangency, each one translated so much because very often the rate of Almost all numerical integrators, on the y axis a bit. Each of these parabo- change of a quantity depends on the but none so blatantly as Euler’s method, las is generated by using a different value value of the quantity. For example, we are based on the plain old calculus defin- for the constant of integration you get already said that the deceleration (the ition of the first derivative as a slope: when you integrate dy/dx = 2x. The rate of change of velocity) induced by the dy/dx defines the slope of y with respect parabola I drew corresponds to a 0 con- force of air friction is dependent on the to x. For example, if we have the linear stant of integration, since y = x2. If I velocity. Other physical examples equation y = 5x, then dy/dx = 5, meaning chose 1 for the constant, I’d get y = x2 + include cooling (the rate of heat loss the slope is a constant 5 for all values of 1, which is an identical parabola translat- depends on the current temperature) and x, as you’d expect for a line. A slightly ed up by 1 unit in y. radioactive decay (the rate of decay more complex example is the parabola y Now think about what would hap- depends on how much radioactive mate- = x2. In this case, dy/dx = 2x, which is a pen if you didn’t know the vector field in rial is present). function defining a new slope at each x Figure 1 defined a parabola, and you just The final word in our phrase, coordinate. I’ve graphed y = x2 in Figure plopped yourself down somewhere on numerical, is our savior. I say this 1. In addition, I’ve also overlayed the the grid. Well, if you are going to satisfy because the theory of analytically inte- vector field of the slopes in Figure 1, by the slope equation, you have to follow grating differential equations, even ordi- drawing the solution to the slope equa- the vector field at each point, so along nary ones, is huge and pretty complicat- tion, dy/dx = 2x, as a short vector at each you go, changing direction as the vector ed. However, by a strange twist of fate, coordinate on the grid. Notice how the field changes direction. Wouldn’t you integrating ODEs numerically on a vector field is tangent to the parabola at know it—after a short bit you’ve traced

http://www.gdmag.com GAME DEVELOPER • OCTOBER/NOVEMBER 1996 19 BEHIND THE SCREEN

out a parabola, or at least part of one, Or, explicitly in terms of our air depending on where you started. You friction equation: may not realize it, but you just integrated − v the equation for the vector field. You vvh≈+ n found a specific parabola (which one nn+1 m depends on where you started, or your initial condition) using only the equation for the derivative (evaluating dy/dx is Obviously, Euler’s method accumu- how you followed the vector field). lates a little error each time it steps, since Doing the same thing for a real the real vector field (and therefore the differential equation is just as easy. For solution curve) is curving away at any a differential equation of the type dy/dx point and Euler’s algorithm is just step- = f(x,y), the definition of the derivative ping along the tangent line. But if the dy/dx as a slope means f(x,y) defines a stepsize, h, is small enough, Euler does slope for each coordinate in the x,y okay. We’ll discuss this error more in the graph. If you graph the vector field future. given by dy/dx = f(x,y) you can follow That’s really all there is to numeri- it, just like you did for the parabola, by cally integrating with Euler’s method. sampling the derivative at each point However, you might be wondering how and going in that direction. Figure 2 we integrate the velocity to get the posi- shows the vector field for Equation 12, tion now that we’re numerically integrat- our air friction equation, with velocity ing the acceleration to get the velocity. as the vertical axis and time as the hori- We just use Euler’s method again to inte- zontal axis (I arbitrarily picked m=1 for grate dr/dt = v at the same time we inte- this graph). It also shows one of many grate dv/dt = a, alternating as we go. We possible solution curves. You can see end up with two coupled ordinary differ- that if you pick an initial position in the ential equations (another good one for graph (which corresponds to an inital that raise): velocity in the equation), as time passes your velocity will decay down towards Fn vvvv+ ≈+hh& =+ zero as friction robs you of speed. You nnnn1 M can also see that the rate at which your velocity is decaying depends on the cur- ≈+ =+ rent value of your velocity: the faster rrrrvnnnnn+1 hh& you’re going, the faster it decays. This makes sense, since we picked Equation This gives us an iterative algorithm 12 to give us exactly this result. for computing the position from some Doing these integrations numeri- arbitrarily wacky force on our object cally is quite similar to doing them on a (which could depend on the velocity as graph. Euler’s algorithm for numerical we’ve seen, or time, or even on the posi- integration simply follows the vector tion of the body and other bodies, or all field from an initial position by evaluat- at once!). Euler’s method doesn’t care ing the derivative equation (-v/m for what the force looks like, as long as you our air friction example) to find the can compute it at each step. Euler treats slope at the current point, and then the value of the force over the mass as a stepping forward in time by a fixed slope, and steps merrily along. amount, h, on that tangent line. It then I’m out of space, so I don’t have evaluates the derivative at the new posi- room to give references. Next time I’ll list tion to get a new slope, and takes some great books, and we’ll get into how another time step: to do rotations with rigid bodies. ■ dy yyh≈+ n Although his body is not quite as rigid nn+1 dx as he’d like, Chris Hecker has a dynamic personality. If forced, he’ll answer e-mail at [email protected].

20 GAME DEVELOPER • OCTOBER/NOVEMBER 1996 http://www.gdmag.com DELPHI DEVELOPMENT

Delphi Does DirectX: Using Encapsulated COM Objects

t’s not always easy to grasp the that properly hides its data, is easy to view a .BMP file stored on disk. First, fill complexity that Microsoft’s Com- use, and is easy to maintain. in the BackgroundFile property with the ponent Object Model (COM) Furthermore, you don’t want to name of the .BMP file you want to view presents. However, since that’s have to worry about programming issues and leave the DllName property blank. exactly what Microsoft’s DirectX while you are exercising the creative part (The TSpeedDraw component also supports is based on, COM must be tack- of your mind. Well-made Delphi com- loading bitmaps from DLLs.) When fill- led. One way to simplify your ponents aid this process because they are ing in the BackgroundFile property, you work is to encapsulate COM much easier to use than raw C++ objects. can use the ellipses in its property editor objectsI as Delphi components. to pop up a dialog that lets you browse This article assumes an understand- Sample Use of a across your hard drive for bitmaps. ing of Delphi, Delphi components, DirectX Component Set the BackOrigX and BackOrigY DirectX, and COM. All the code for the Let’s look at two objects, TSpeedDraw and properties to the place on your form Delphi objects, DLLs, and C/C++ pro- ISpeedDraw. The first object is a Delphi where you want the upper left-hand cor- grams is available on the Game Developer component, while the second is a COM ner of the bitmap to be displayed. TSpeed- web site. interface. Draw insists that your bitmap fit into all or Both objects do little more than some portion of a 640-by-480 window. Well-Made Components display a simple bitmap on a DirectX There will, of course, be times when you Are Easy to Use surface, or allow you to easily draw might want to override this behavior. First, a few points about Delphi compo- directly on the surface of your form. You can do so by overriding the virtual nent design. Delphi components are not They are general purpose objects with a BackgroundBlits or InitObjects methods heavy conglomerations like a VBX or wide range of uses, but little specialized or by toggling the ShowBackBmp property. OCX. Instead, they are merely a special ability to ease any particular task. If you want the TSpeedDraw compo- form of Delphi object. As a result, they Here are step-by-step instructions nent to run in exclusive mode, set the are as small and compact as any C++ how to use the TSpeedDraw component to UseExclusive property to true. When object. It’s a good idea to turn complex objects in a program into components. The act of creating a Delphi component enforces very strict adherence to the best principles of object-oriented design. It helps ensure a robust, reusable object

Figure 1. The Dinosaur Figure 2. The Dinosaur bitmap blitted onto the background bitmap. bitmap.

22 GAME DEVELOPER • OCTOBER/NOVEMBER 1996 http://www.gdmag.com Charlie Calvert debugging your application, you should You can leave the BackgroundMap leave the UseExclusive property with its property blank so long as you have set default value of False so that you can ShowBackBmp to False. step through your code using Delphi’s Turn to the Events page for the Has Delphi finally integrated debugger. TSpeedDraw component and create an Once you have set the properties OnPaintProc event: listed above, you can display the bitmap at run time by calling the Run method of procedure TForm1.SpeedDraw1PaintProc(Sender: TSpeedDraw TObject); . Do this after your form has var become visible to the user. DC: HDC; found a niche for If you set the UseTimer value to true, begin DoFlip SpeedDraw1.BackSurface.GetDC(DC); then a method called will be (DC, 100, 100, 200, 200); called automatically for you at the inter- SpeedDraw1.BackSurface.ReleaseDC(DC); val specified in the TimerInterval proper- end; ty. DoFlip is a wrapper around the IDi- rectDrawSuface.Flip function. This procedure draws a rectangle to That’s all there is to getting started the screen. There is no reason why you itself in the game using the TSpeedDraw component. Here is could not show the bitmap and draw on a quick review of the steps described the screen at the same time. above: When drawing on the back surface, • Set the BackgroundFile property to the you can create animation by setting Use- name of bitmap you want to show. Timer to True and responding to PaintProc • Set BackOrigX and BackOrigY to the events as follows: development world? location in your window where you want the upper left-hand corner of procedure TForm1.SpeedDraw1PaintProc(Sender: TObject); the bitmap to be displayed. var • Call the Run method. DC: HDC; Initializing and running a TSpeedDraw begin SpeedDraw1.BackSurface.GetDC(DC); component is this easy. Trying to write if SpeedDraw1.TimerOdd then Teaming Delphi and the same DirectX code from scratch Rectangle(DC, 100, 100, 200, 200) would be much more difficult. As you else Rectangle(DC, 100, 100, 200, 150); will see in the section on COM, a well SpeedDraw1.BackSurface.ReleaseDC(DC); built object could also greatly simplify the end; use of DirectX, but that object would still not be as easy to use as a component. The TimerOdd property switches between True and False every time a DirectX might be the Specialized Behavior page is flipped. Page flipping will occur from TSpeedDraw each time the timer fires. You can con- To stop showing bitmaps on the screen trol the rate at which the timer fires and start drawing directly on the screen with the TimerInterval property. surface, simply set the SetShowBackBmp You can either leave the back- property to False. ground of the DirectDraw object empty or ticket.

http://www.gdmag.com GAME DEVELOPER • OCTOBER/NOVEMBER 1996 23 DELPHI DEVELOPMENT

Listing 1. The InitObjectsProc event triggers the sprite dialog box to report an error. This is

procedure TForm1.SpeedDraw1InitObjectsProc(Sender: TObject); not necessary if you are not in exclusive var mode, but sooner or later, most Direct- SurfaceDesc: TDDSurfaceDesc; Draw applications end up running in hr: HResult; begin exclusive mode, as shown in Listing 3. if not SpeedDraw1.CreateDDSurface(FNewSurface, ‘dino.bmp’, True) then raise EDDError.Create(‘TSpeedDraw.SetupWorkSurface: No WorkSurface’); Implementations Details SurfaceDesc.dwSize := SizeOf(TDDSurfaceDesc); TSpeedDraw hr := FNewSurface.GetSurfaceDesc(SurfaceDesc); Now that you understand ’s if hr <> DD_OK then ease of use and flexibility, you might be raise EDDError.CreateFmt(‘No Surface Desc $%x %s’, [hr, GetOleError(hr)]); interested in seeing some of the code FDinoRect := Rect(0, 0, SurfaceDesc.dwWidth, SurfaceDesc.dwHeight); TSpeedDraw end; that makes the object tick. comes with complete source, but I will not discuss the actual DirectX code fill it in with a color. To choose to fill it The bitmap has a background filled in involved because it is identical to code in with a color, set FillBackground to True with the designated transparent color as you have seen in the many articles pub- and set the BackColor property to the a background. lished on DirectX. Delphi gives you full value you want to use. If you don’t fill in After creating a new DirectDraw access to the Windows API, including the background, you can get garbage on surface for the sprite, the code uses the all the available COM objects on your the screen unless you completely fill up IDirectDrawSurface.GetSurfaceDesc func- system. There is very little difference the window with your own bitmaps or tion to retrieve the dimensions of the between Delphi’s Object Pascal imple- drawings. bitmap. These dimensions are stored in a mentation of DirectX and the types of Be careful that you don’t set the private variable of TForm1 called implementations you would see in a C++ transparent color to one of the key colors FDinoRect, which is of type TRect: object. in your bitmap. One of the most important TSpeed- TForm1 = class(TForm) Draw methods is called InitObjects, which Adding Additional // Standard Delphi code omitted here. private is described in Listing 4. This procedure Bitmaps to the Scene FNewSurface: IDirectDrawSurface; takes care of the following steps: At this point, there are no sprite classes FDinoRect: TRect; • DirectDrawCreate initializes the video for use with TSpeedDraw. However, if you end; card interface, which is also known as want to add additional bitmaps to the The PaintProc event will be called IDirectDraw. scene, you can do so by responding to once when you call Run, and then again • SetCooperativeLevel defines the high- the TSpeedDraw, InitObjectsProc, and every time that DoFlip is called. For level behavior of the interface. PaintProc events. instance, if you set UseTimer to True, • If SetCooperativeLevel is set to Exclu- The InitObjectsProc event is fired then PaintProc would be called every sive; SetDisplayMode defines the video only once at the very beginning of the time an WM_TIMER message is sent, as in mode. life cycle for a TSpeedDraw object. Listing Listing 2. This code simply blits the • CreatePrimary, an ISpeedDraw method, 1 responds to the event by creating a new sprite onto the background at a creates a primary surface. sprite depicting a small dinosaur. Here’s specified location. • SetUpBack, an ISpeedDraw method, cre- how it works: You may notice that I raise excep- ates a flipping surface. The CreateDDSurface method is a tions if errors occur. It is good practice • The local SetupWorkSurface method wrapper around the DirectDraw.Cre- to override the exception handler for sets up the WorkSurface, which holds ateSurface function. This code loads a your application so that you can get out the background bitmap. bitmap with a picture of a dinosaur on it. of exclusive mode before popping up a • The InitObjectsProc event is initiated

Listing 2. Blitting a sprite onto the background Listing 3. Overriding the exception handler

procedure TForm1.SpeedDraw1PaintProc(Sender: TObject); procedure TForm1.FormCreate(Sender: TObject); var begin hr: HResult; Application.OnException := ExceptionHandler; begin end; hr := SpeedDraw1.BackSurface.BltFast(200, 75, FNewSurface, FDinoRect, procedure TForm1.ExceptionHandler(Sender: TObject; E: Exception); DDBLTFAST_WAIT or DDBLTFAST_SRCCOLORKEY); begin if hr <> DD_OK then SpeedDraw1.ErrorEvent(E.Message); raise EDDError.CreateFmt(‘No blit $%x %s’, [hr, GetOleError(hr)]); end; end;

24 GAME DEVELOPER • OCTOBER/NOVEMBER 1996 http://www.gdmag.com if the user has set a WorkSurface up. Listing 4. The InitObjects Method InitObjects Active • The method sets to procedure TSpeedDraw.InitObjects; True. var The methods CreatePrimary, Setup- hr: hResult; Back CreateWorkSurface Flags: DWORD; , and are places to begin initialize the three key IDirectDrawSur- FHandle := TForm(Owner).Handle; face objects used by the component. ASpeedDraw := Self; CreatePri- In Listing 5, you see the DDTest(DirectDrawCreate(nil, FDirectDraw, nil), ‘InitObjects1’); mary method and all the standard coding paraphernalia associated with DirectX. if not FUseExclusive then Flags := DDSCL_NORMAL For instance, notice that the code else attempts to set up a surface that sup- Flags := DDSCL_EXCLUSIVE or DDSCL_FULLSCREEN; ports page flipping only if the program DDTest(FDirectDraw.SetCooperativeLevel(FHandle, Flags), ‘InitObjects2’); if FUseExclusive then begin runs in exclusive mode. Don’t worry hr := FDirectDraw.SetDisplayMode(640, 480, 8); about the details of this implementa- if(hr <> DD_OK) then tion, just remember that these details raise EDDError.CreateFmt(‘TSpeedDraw.InitObjects: %d %s’, [hr, GetOleError(hr)]); end; are hidden from the programmer during the crucial creative periods of develop- CreatePrimary; ment. Conversely, if you find that you SetUpBack; SetUpWorkSurface; must get at the low-level source, then these Delphi components are easily if FUseTimer then opened up and operated upon. As a SetTimer(Handle, Timer1, FTimerInterval, @Timer2Timer); if Assigned(InitObjectsProc) then rule, Delphi’s compile time will often InitObjectsProc(Self); allow you to recompile and test an object in a matter of seconds. FActive := True; end; It’s helpful if components are easy to use. Difficult components can pre- sent a maddeningly opaque face to the component because there are few clues you through its use. The art of compo- user. You find yourself asking questions to get you started. As a result, well- nent building is to create a simple, intu- like, “What properties am I supposed to loved components have an intuitive, itive interface that still lets you get at fill in?” and “How do I get it to run?” easy-to-use interface, or come equipped the advanced features of a particular It’s difficult to figure out a hard-to-use with an expert or wizard that will guide technology.

Using the ISpeedDraw Listing 5. The CreatePrimary method Object in a C++ Program function TSpeedDraw.CreatePrimary: Boolean; The TSpeedDraw object is constructed in var such a way that it can easily be converted SurfaceDesc: TDDSurfaceDesc; hr: HResult; via conditional compilation into a COM begin object that can be used in C++. To con- FillChar(SurfaceDesc, sizeOf(TDDSurfaceDesc), 0); vert the object, you simply need to define SurfaceDesc.dwSize := sizeof(TDDSurfaceDesc); the symbol USECOM. You could then create if not FUseExclusive then begin a simple Object Pascal COM DLL that SurfaceDesc.dwFlags := DDSD_CAPS; serves the object up to any interested SurfaceDesc.ddsCaps.dwCaps := DDSCAPS_PRIMARYSURFACE; end else begin clients. SurfaceDesc.dwFlags := DDSD_CAPS or DDSD_BACKBUFFERCOUNT; For instance, the beginning of the SurfaceDesc.ddsCaps.dwCaps := DDSCAPS_PRIMARYSURFACE or class declaration looks like this: DDSCAPS_FLIP or DDSCAPS_COMPLEX; SurfaceDesc.dwBackBufferCount := 1; {$IFDEF USECOM} end; TSpeedDraw = class(IDrawBase) {$ELSE} hr := FDirectDraw.CreateSurface(SurfaceDesc, FPrimarySurface, nil); TSpeedDraw = class(TComponent) if hr <> DD_OK then {$ENDIF} raise EDDError.CreateFmt(‘TSpeedDraw.CreatePrimary: %d %s’, [hr, GetOleError(hr)]) private else FActive: Boolean; Result := True; FBackColor: TColor; end; // Large chunk of code omitted end;

http://www.gdmag.com GAME DEVELOPER • OCTOBER/NOVEMBER 1996 25 DELPHI DEVELOPMENT

Listing 6. USECOM is defined; TSpeedDraw properties aren’t compiled app, you should release the object and {$IFDEF USECOM} shut down COM: procedure MakeActive(Value: Boolean); virtual; stdcall; procedure SetTimerOdd(Value: Boolean); virtual; stdcall; void Window1_OnDestroy(HWND hwnd) procedure SetBackOrigin(Value: TPoint); virtual; stdcall; { {$ELSE} P->Release(); property Active: Boolean read fActive write SetActive; property BackOrigin: TPoint read FBackOrigin write FBackOrigin; CoUninitialize; property TimerOdd: Boolean read FTimerOdd write FTimerOdd; PostQuitMessage(0); // Other properties omitted } {$ENDIF}

Encapsulation Is the Key If USECOM is defined, this code will To use this object, you declare a You can encapsulate complex APIs declare a simple instantiation of IUn- global variable of type PISpeedDraw: within an understandable wrapper that known called IDrawBase as the parent of can be used even by the neophytes on TSpeedDraw. If USECOM is not defined, then PISpeedDraw P; your staff. Or, more importantly for TSpeedDraw becomes a descendant of the game writers, you can wrap up the standard Delphi TComponent object, This variable can then be used in details of an operation so that you don’t which gives the object the ability to standard COM code, like the response have to consider them while you are appear on the component palette. to a WM_LBUTTONDOWN message that appears using your creative side. The TSpeedDraw properties are not in Listing 8. Most code in this article is part of compiled if USECOM is defined (see the This code first initializes COM, an ongoing project to develop Delphi code in Listing 6). then calls CoCreateInstance to retrieve gaming components. Other objects, As you can see, some of the key the PISpeedObject from the Delphi DLL such as those for handling tiled sur- properties are replaced by COM-com- in which it resides. faces, are already complete. For addi- patible methods if USECOM is defined. The InitParams method allows you tional information, point your Internet Listing 7 shows the ISpeedDraw to make one call that fills in some of the browser to http://users.aol.com/ object as it is declared for use in a C++ fields which the TSpeedDraw component charliecal. ■ program. The actual ISpeedDraw object has you fill in at design time via the as declared in an Object Pascal DLL is Delphi Object Inspector. To me, the more complex than this, but COM is Delphi Component-based interface is only interested in the virtual methods more elegant than using the InitParams for an object, so other declarations are method, but both techniques get the job Charlie Calvert is the author of Del- omitted in this case. done with a minimum of fuss. phi 2 Unleashed, Teach Yourself Win- After calling PIS- dows 95 Programming in 21 Days, Del- peedDraw.Run, the bit- phi Unleashed, Teach Yourself Win- Listing 7. The ISpeedDraw Object map you asked to see dows Programming, and Turbo Pascal class ISpeedDraw: public IUnknown will be displayed on the Programming 101. He works at Borland { main window of your International as a manager in Developer public: STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID*) PURE; C/C++ application. Relations. You can reach him at STDMETHOD_(ULONG,AddRef) (THIS) PURE; Before closing your [email protected]. STDMETHOD_(ULONG,Release) (THIS) PURE; STDMETHOD_(BOOL, BackgroundBlits) (THIS) PURE; STDMETHOD_(BOOL, Pause) (THIS) PURE; STDMETHOD_(VOID, Restore) (THIS) PURE; Listing 8. Response to a WM_LBUTTONDOWN message STDMETHOD_(VOID, Create) (THIS) PURE; STDMETHOD_(VOID, InitParams)(THIS_ HWND AHandle, void Window1_OnLButtonDown(HWND hwnd, BOOL fDoubleClick, LPSTR BackGroundMapStr, int x, int y, UINT keyFlags) int TransColor, { LPSTR DllName) PURE; HRESULT hr; STDMETHOD_(VOID, Run) (THIS) PURE; STDMETHOD_(VOID, DestroyObjects) (THIS) PURE; CoInitialize(NULL); STDMETHOD_(VOID, DoFlip)(THIS) PURE; hr = CoCreateInstance(CLSID_ISPEEDDRAW, NULL, CLSCTX_INPROC_SERVER, STDMETHOD_(VOID, InitObjects) (THIS) PURE; IID_IUnknown, (VOID**) &P); STDMETHOD_(VOID, Move) (THIS_ int Value) PURE; if (SUCCEEDED(hr)) STDMETHOD_(VOID, MakeActive) (THIS_ BOOL Value) PURE; { STDMETHOD_(VOID, SetTimerOdd) (THIS_ BOOL Value) PURE; P->InitParams(hwnd, “E:\\SRC\\BLAISE\\WINFIRE\\BACKGRD1.BMP”, 254, “”); STDMETHOD_(VOID, SetBackOrigin) (THIS_ POINT Value) PURE; P->Run(); }; } typedef ISpeedDraw *PISpeedDraw; }

26 GAME DEVELOPER • OCTOBER/NOVEMBER 1996 http://www.gdmag.com ARTIFICIAL INTELLIGENCE

Smart Moves: Intelligent Path-Finding

f all the decisions involved in load. The article and demo assume that • Movement in a random direction. If the computer-game AI, the most the playing space is represented with obstacles are all small and convex, the common is probably path- square tiles. You can adapt the concepts entity (shown as a green dot) can finding—looking for a good in the algorithms to other tilings, such as probably get around them by moving a route for moving an entity hexagons; ideas for adapting them to little bit away and trying again, until it from here to there. The entity continuous spaces are discussed at the reaches the goal (shown as a red dot). can be a single person, a vehi- end of the article. Figure 1A shows this strategy at work. cle, or a combat unit; the genre A problem arises with this method if Ocan be an action game, a simulator, a Path-Finding on the Move the obstacles are large or if they are role-playing game, or a strategy game. The typical problem in path-finding is concave, as is seen in Figure 1B—the But any game in which the computer is obstacle avoidance. The simplest entity can get completely stuck, or at responsible for moving things around has approach to the problem is to ignore the least waste a lot of time before it stum- to solve the path-finding problem. obstacles until one bumps into them. The bles onto a way around. One way to And this is not a trivial problem. algorithm would look something like this: avoid this: if a problem is too hard to Questions about path-finding are regular- deal with, alter the game so it never ly seen in online game programming while not at the goal comes up. That is, make sure there are forums, and the entities in several games pick a direction to move toward the goal never any concave obstacles. move in less than intelligent paths. How- if that direction is clear for movement • Tracing around the obstacle. Fortu- ever, although path-finding is not trivial, move there nately, there are other ways to get there are some well-established, solid else around. If the obstacle is large, one algorithms that deserve to be known bet- pick another direction according to can do the equivalent of placing a ter in the game community. an avoidance strategy hand against the wall and following Several path-finding algorithms are the outline of the obstacle until it is not very efficient, but studying them This approach is simple because it skirted. Figure 2A shows how well serves us by introducing concepts incre- makes few demands: all that needs to be this can deal with large obstacles. mentally. We can then understand how known are the relative positions of the The problem with this technique different shortcomings are overcome. entity and its goal, and whether the comes in deciding when to stop trac- To demonstrate the workings of immediate vicinity is blocked. For many ing. A typical heuristic may be: “Stop the algorithms visually, I have developed game situations, this is good enough. tracing when you are heading in the a program in Delphi 2.0 called “PathDe- Different obstacle-avoidance strate- direction you wanted to go when you mo.” It is available for readers to down- gies include: started tracing.” This would work in many situations, but Figure 2B Figure 1A and 1B. Bouncing off in a random direction shows how one may end up con- stantly circling around without find- ing the way out. • Robust tracing. A more robust heuris- tic comes from work on mobile robots: “When blocked, calculate the equation of the line from your current position to the goal. Trace until that line is again crossed. Abort if you end up at the starting position again.”

28 GAME DEVELOPER • OCTOBER/NOVEMBER 1996 http://www.gdmag.com Figure 2A and 2B. Tracing around the obstacle W. Bryan Stout Many a tirade has been launched by

This method is guaranteed to find a passable or even adequate job, there are way around the obstacle if there is situations where the only intelligent one, as is seen in Figure 3A. (If the approach is to plan the entire route game developers original point of blockage is between before the first step is taken. In addition, you and the goal when you cross the these methods do little to handle the line, be sure not to stop tracing, or problem of weighted regions, where the more circling will result.) Figure 3B difficulty is not so much avoiding obsta- about stupid shows the downside of this approach: cles as finding the cheapest path among it will often take more time tracing several choices where the terrain can vary the obstacle than is needed, making it in its cost. look pretty simple-minded—though Fortunately, the fields of Graph computer-controlled not as simple as endless circling. A Theory and conventional AI have several happy compromise would be to com- algorithms that can be used to handle bine both approaches: always use the both difficult obstacles and weighted simpler heuristic for stopping the regions. In the literature, many of these characters. Endowing tracing first, but if circling is detected, algorithms are presented in terms of switch to the robust heuristic. changing between states, or traversing the nodes of a graph. They are often Looking Before You Leap used in solving a variety of problems, your game with some Although the obstacle-skirting tech- including puzzles like the 15-puzzle or niques discussed above can often do a Rubik’s cube, where a state is an Figure 3A and 3B. Robust tracing path-finding smarts will give players a reason to cheer.

http://www.gdmag.com GAME DEVELOPER • OCTOBER/NOVEMBER 1996 29 ARTIFICIAL INTELLIGENCE

Listing 1. Breadth-first search FIFO (first-in-first-out) queue. The priority queue, where the node popped algorithm would go something like is the one with the best score—here, queue Open what is shown in Listing 1. Figure 4 the one with the lowest cost path from shows how the search proceeds. We the start. (See Listing 2.) We see in BreadthFirstSearch can see that it does find its way around Figure 6 that Dijkstra’s algorithm node n, n’, s obstacles, and in fact it is guaranteed adapts well to terrain cost. However, it s.parent = null to find a shortest path—that is, one of still has the weakness of breadth- // s is a node for the start several paths that tie for the shortest in width search in ignoring the direction push s on Open length—if all steps have the same cost. to the goal. while Open is not empty There are a couple of obvious prob- • Depth-first search. This search is the pop node n from Open lems. One is that it fans out in all complement to breadth-first search; if n is a goal node directions equally, instead of directing instead of visiting all a node’s siblings construct path its search towards the goal; the other is before any children, it visits all of a return success that all steps are not equal—at least the node’s descendants before any of its for each successor n’ of n diagonal steps should be longer than siblings. To make sure the search ter- if n’ has been visited the orthogonal ones. minates, we must add a cutoff at already, • Bidirectional breadth-first search. This some depth. We can use the same continue enhances the simple breadth-first code for this search as for breadth- n’.parent = n search by starting two simultaneous first search, if we add a depth para- push n’ on Open breadth-first searches from the start meter to keep track of each node’s return failure // if no path found and the goal nodes and stopping depth and change Open from a FIFO when a node from one end’s search queue to a LIFO (last-in-first-out) finds a neighboring node marked stack. In fact, we can eliminate the arrangement of the tiles or cubes, and from the other end’s search. As seen Open list entirely and instead make neighboring states (or adjacent nodes) in Figure 5, this can save substantial the search a recursive routine, which are visited by sliding one tile or rotating work from simple breadth-first search would save the memory used for one cube face. Applying these algo- (typically by a factor of 2), but it is Open. We need to make sure each rithms to path-finding in geometric still quite inefficient. Tricks like this tile is marked as “visited” on the way space requires a simple adaptation: a are good to remember, though, since out, and is unmarked on the way state or a graph node stands for the enti- they may come in handy elsewhere. back, to avoid generating paths that ty being in a particular tile, and moving • Dijkstra’s algorithm. E. Dijkstra devel- visit the same tile twice. In fact, Fig- to adjacent tiles corresponds to moving oped a classic algorithm for traversing ure 7 shows that we need to do more to the neighboring states, or adjacent graphs with edges of differing weights. than that: the algorithm still can tan- nodes. At each step, it looks at the gle around itself and waste time in a Working from the simplest algo- unprocessed node closest to the start maddening way. For geometric path- rithms to the more robust, we have: node, looks at that node’s neighbors, finding, we can add two enhance- • Breadth-first search. Beginning at the and sets or updates their respective ments. One would be to label each start node, this algorithm first exam- distances from the start. This has two tile with the length of the cheapest ines all immediate neighboring nodes, advantages to the breadth-first search: path found to it yet; the algorithm then all nodes two steps away, then it takes a path’s length or cost into would then never visit it again unless three, and so on, until a goal node is account and updates the goodness of it had a cheaper path, or one just as found. Typically, each node’s unexam- nodes if better paths to them are cheap but searching to a greater ined neighboring nodes are pushed found. To implement this, the Open depth. The second would be to have onto an Open list, which is usually a list is changed from a FIFO queue to a the search always look first at the Figure 4. Breadth-first search Figure 5. Bidirectional search Figure 6. Dijkstra’s search

30 GAME DEVELOPER • OCTOBER/NOVEMBER 1996 http://www.gdmag.com Listing 2. Dijkstra’s search algorithm Listing 3. A* search algorithm

priority queue Open priorityqueue Open list Closed DijkstraSearch node n, n’, s AStarSearch s.cost = 0 s.g = 0 // s is the start node s.parent = null // s is a node for the start s.h = GoalDistEstimate( s ) push s on Open s.f = s.g + s.h while Open is not empty s.parent = null pop node n from Open // n has lowest cost in Open push s on Open if n is a goal node while Open is not empty construct path pop node n from Open // n has the lowest f return success if n is a goal node for each successor n’ of n construct path newcost = n.cost + cost(n,n’) return success if n’ is in Open for each successor n’ of n and n’.cost <= newcost newg = n.g + cost(n,n’) continue if n’ is in Open or Closed, n’.parent = n and n’.g <= newg n’.cost = newcost skip if n’ is not yet in Open n’.parent = n push n’ on Open n’.g = newg return failure // if no path found n’.h = GoalDistEstimate( n’ ) n’.f = n’.g + n’.h if n’ is in Closed children in the direction of the goal. a depth-first search remove it from Closed With these two enhancements with increasing if n’ is not yet in Open checked, one sees that the depth-first depth: first one, push n’ on Open search finds a path quickly. Even then two, and so on push n onto Closed weighted paths can be handled by until the goal is return failure // if no path found making the depth cut-off equal the found. In the path- total accumulated cost rather than the finding domain, we total distance. can enhance this by starting with a In 8A, we see that it does not take into • Iterative-deepening depth-first search. depth equal to the straight-line dis- account the accumulated cost of the Actually, there is still one fly in the tance from the start to the goal. This terrain, plowing straight through a depth-first ointment—picking the search is asymptotically optimal costly area rather than going around it. right depth cutoff. If it is too low, it among brute force searches in both And in 8B, we see that the path it will not reach the goal; if too high, it space and time. finds around the obstacle is not direct, will potentially waste time exploring • Best-first search. This is the first but weaves around it in a manner rem- blind avenues too far, or find a weight- heuristic search considered, meaning iniscent of the hand-tracing tech- ed path which is too costly. These that it takes into account domain niques seen above. problems are solved by doing iterative knowledge to guide its efforts. It is deepening, a technique that carries out similar to Dijkstra’s algorithm, except The Star of the Search that instead of the nodes in Open Algorithms (A* Search) Figure 7. Depth-first search being scored by their distance from the The best-established algorithm for the start, they are scored by an estimate of general searching of optimal paths is A* the distance remaining to the goal. (pronounced “A-star”). This heuristic This cost also does not require possi- search ranks each node by an estimate of ble updating as Dijkstra’s does. Figure the best route that goes through that 8 shows its performance. It is easily node. The typical formula is expressed as: the fastest of the forward-planning searches we have examined so far, f(n) = g(n) + h(n) heading in the most direct manner to where: the goal. We also see its weaknesses. f(n) is the score assigned to node n

http://www.gdmag.com GAME DEVELOPER • OCTOBER/NOVEMBER 1996 31 ARTIFICIAL INTELLIGENCE

Figure 8A and 8B. Best-first search • The estimate is usually the minimum distance between the current node and the goal multiplied by the mini- mum cost between nodes. This guar- antees that h(n) is admissible. (In a map of square tiles where units may only occupy points in the grid, the minimum distance would not be the Euclidean distance, but the minimum number of orthogonal and diagonal moves between the two points.) g(n) is the actual cheapest cost of • The state would often be the tile or • The goal does not have to be a single arriving at n from the start position the entity occupies. But if location but can consist of multiple h(n) is the heuristic estimate of the needed, it can represent orientation locations. The estimate for a node cost to the goal from n and velocity as well (for example, for would then be the minimum of the finding a path for a tank or most any estimate for all possible goals. So it combines the tracking of the vehicle—their turn radius gets worse • Search cutoffs can be included easily, to previous path length of Dijkstra’s algo- the faster they go). cover limits in path cost, path dis- rithm, with the heuristic estimate of the • Neighboring states would vary depend- tance, or both. remaining path from best-first search. ing on the game and the local situa- From my own direct experience, I The algorithm proper is seen in Listing 3. tion. Adjacent positions may be have seen the A* star search work very Since some nodes may be processed more excluded because they are impassable well for finding a variety of types of than once—from finding better paths to or are between the neighbors. Some paths in wargames and strategy games. them later—we use a new list called terrain can be passable for certain Closed to keep track of them. units but not for others; units that The Limitations of A* A* has a couple interesting proper- cannot turn quickly cannot go to all There are situations where A* may not ties. It is guaranteed to find the shortest neighboring tiles. perform very well, for a variety of reasons. path, as long as the heuristic estimate, • The cost of going from one position to The more or less real-time requirements h(n), is admissible—that is, it is never another can represent many things: of games, plus the limitations of the avail- greater than the true remaining distance the simple distance between the posi- able memory and processor time in some to the goal. It makes the most efficient tions; the cost in time or movement of them, may make it hard even for A* to use of the heuristic function: no search points or fuel between them; penalties work well. A large map may require thou- that uses the same heuristic function for traveling through undesirable sands of entries in the Open and Closed h(n) and finds optimal paths will expand places (such as points within range of list, and there may not be room enough fewer nodes than A*, not counting tie- enemy artillery); bonuses for traveling for that. Even if there is enough memory breaking among nodes of equal cost. In through desirable places (such as for them, the algorithms used for manip- Figures 9A through 9C, we see how A* exploring new terrain or imposing ulating them may be inefficient. deals with situations that gave problems control over uncontrolled locations); The quality of A*’s search depends to other search algorithms. and aesthetic considerations—for on the quality of the heuristic estimate example, if diagonal moves are just as h(n). If h is very close to the true cost of How Do I Use A*? cheap as orthogonal moves, you may the remaining path, its efficiency will be A* turns out to be very flexible in prac- still want to make them cost more, so high; on the other hand, if it is too low, tice. Consider the different parts of the that the routes chosen look more its efficiency gets very bad. In fact, algorithm. direct and natural. breadth-first search is an A* search, with Figure 9A, 9B, and 9C. How A* deals with some problematic cases

32 GAME DEVELOPER • OCTOBER/NOVEMBER 1996 http://www.gdmag.com Figure 10A and 10B. inefficient algorithms handling the data structures. Regarding the search, two major data structures are involved. The first is the representation of the playing area. Many questions have to be addressed. How will the playing field be represented? Will the areas accessible from each spot—and the costs of moving there—be represented directly in the map or in a separate structure, or calcu- lated when needed? How will features in h being trivially zero for all nodes—this countries as areas, a hierarchical search the area be represented? Are they direct- certainly underestimates the remaining would first determine that the route ly in the map, or separate structures? path cost, and while it will find the opti- would go from Spain to France to Italy to How can the search algorithm access mum path, it will do so slowly. In Figure Yugoslavia (looking at an old map) to necessary information quickly? There are 10A, we see that while searching in Greece; and then the route through Italy too many variables concerning the type expensive terrain (shaded area), the fron- would only need to connect Italy’s border of game and the hardware and software tier of nodes searched looks similar to with France, to Italy’s border with environment to give much detail about Dijkstra’s algorithm; in 10B, with the Yugoslavia. As another example, routes these questions here. heuristic increased, the search is more from one part of a building to another can The second major structure focused. be broken down into a path of rooms and involved is the node or state of the Let’s look at ways to make the A* hallways to take, and then the paths search, and this can be dealt with more search more efficient in problem areas. between doors in each room. explicitly. At the lower level is the search It is much easier to choose areas in state structure. Fields a developer might Transforming the predefined maps than to have the com- wish to include in it are: Search Space puter figure them out for randomly gen- • The location (coordinates) of the map Perhaps the most important improvement erated maps. Note also that the examples position being considered at this state one can make is to restructure the prob- discussed deal mainly with obstacle avoid- of the search. lem to be solved, making it an easier ance; for weighted regions, it is trickier to • Other relevant attributes of the entity, problem. Macro-operators are sequences of assign useful regions, especially for the such as orientation and velocity. steps that belong together and can be computer (it may not very useful, either). • The cost of the best path from the combined into a single step, making the source to this location. search take bigger steps at a time. For Storing It Better • The length of the path up to this example, airplanes take a series of steps in Even if the A* search is relatively effi- position. order to change their orientation and alti- cient by itself, it can be slowed down by • The estimate of the cost to the goal tude. A common sequence may be used as a single change of state operator, rather Figure 11 A-F than using the smaller steps individually. In addition, search and general problem- solving methods can be greatly simplified if they are reduced to sub-problems, whose individual solutions are fairly simple. In the case of path-finding, a map can be broken down into large contiguous areas whose connectivity is known. One or two border tiles between each pair of adjacent areas are chosen; then the route is first laid out in by a search among adjacent areas, in each of which a route is found from one border point to another. For example, in a strategic map of Europe, a path-finder searching for a land route from Madrid to Athens would probably waste a fair amount of time looking down the boot of Italy. Using

http://www.gdmag.com GAME DEVELOPER • OCTOBER/NOVEMBER 1996 33 ARTIFICIAL INTELLIGENCE

(or closest goal) from this location. large, they may not be worth the over- What if I’m in a • The score of this state, used to pick head they require. Smooth World? the next state to pop off Open. All these search methods have assumed a • A limit for the length of the search Fine-Tuning Your playing area composed of square or path, or its cost, or both, if applicable. Search Engine hexagonal tiles. What if the game play • A reference (pointer or index) to the There are also ways of tweaking the area is continuous? What if the positions parent of this node—that is, the node search algorithm to help get good results of both entities and obstacles are stored that led to this one. while working with limited resources: as floats, and can be as finely determined • Additional references to other nodes, Beam search. One way of dealing as the resolution of the screen? Figure as needed by the data structure used with restricted memory is to limit the 11A shows a sample layout. For answers for storing the Open and Closed lists; number of nodes on the Open list; when to these search conditions, we can look for example, “next” and maybe “previ- it is full and a new node is to be inserted, at the field of robotics and see what sort ous” pointers for linked lists, “right,” simply drop the node with the worst rat- of approaches are used for the path- “left,” and “parent” pointers for binary ing. The Closed list could also be elimi- planning of mobile robots. Not surpris- trees. nated, if each tile stores its best path ingly, many approaches find some way to Another issue to consider is when length. There is no promise of an opti- reduce the continuous space into a few to allocate the memory for these struc- mal path since the node leading to it important discrete choices for considera- tures; the answer depends on the may be dropped, but it may still allow tion. After this, they typically use A* to demands and constraints of the game, finding a reasonable path. search among them for a desirable path. hardware, and operating system. Iterative-deepening A*. The itera- Ways of quantizing the space include: On the higher level are the aggre- tive-deepening technique used for • Tiles. A simple approach is to slap a gate data structures—the Open and depth-first search (IDDFS) as men- tile grid on top of the space. Tiles that Closed lists. Although keeping them as tioned above can also be used for an A* contain all or part of an obstacle are separate structures is typical, it is possi- search. This entirely eliminates the labeled as blocked; a fringe of tiles ble to keep them in the same structure, Open and Closed lists. Do a simple touching the blocked tiles is also with a flag in the node to show if it is recursive search, keep track of the accu- labeled as blocked to allow a buffer of open or not. The sorts of operations that mulated path cost g(n), and cut off the movement without collision. This rep- need to be done in the Closed list are: search when the rating f(n) = g(n) + resentation is also useful for weighted • Insert a new node. h(n) exceeds the limit. Begin the first regions problems. See Figure 11B. • Remove an arbitrary node. iteration with the cutoff equal to • Points of visibility. For obstacle avoid- • Search for a node having certain h(start), and in each succeeding itera- ance problems, you can focus on the attributes (location, speed, direction). tion, make the new cutoff the smallest critical points, namely those near the • Clear the list at the end of the search. f(n) value which exceeded the old cut- vertices of the obstacles (with enough The Open list does all these, and in off. Similar to IDDFS among brute- space away from them to avoid colli- addition will: force searches, IDA* is asymptotically sions), with points being considered • Pop the node with the best score. optimal in space and time usage among connected if they are visible from each • Change the score of a node. heuristic searches. other (that is, with no obstacle The Open list can be thought of as a Inadmissible heuristic h(n). As dis- between them). For any path, the priority queue, where the next item cussed above, if the heuristic estimate search considers only the critical popped off is the one with the highest h(n) of the remaining path cost is too points as intermediate steps between priority—in our case, the best score. low, then A* can be quite inefficient. But start and goal. See Figure 11C. Given the operations listed, there are sev- if the estimate is too high, then the path • Convex polygons. For obstacle avoid- eral possible representations to consider: a found is not guaranteed to be optimal ance, the space not occupied by linear, unordered array; an unordered and may be abysmal. In games where the polygonal obstacles can be broken up linked list; a sorted array; a sorted linked range of terrain cost is wide—from into convex polygons; the intermedi- list; a heap (the structure used in a heap swamps to freeways—you may try exper- ate spots in the search can be the sort); a balanced binary search tree. imenting with various intermediate cost centers of the polygons, or spots on There are several types of binary estimates to find the right balance the borders of the polygons. Schemes search trees: 2-3-4 trees, red-black trees, between the efficiency of the search and for decomposing the space include: height-balanced trees (AVL trees), and the quality of the resulting path. C-Cells (each vertex is connected to weight-balanced trees. There are also other algorithms that the nearest visible vertex; these lines Heaps and balanced search trees are variations of A*. Having toyed with partition the space) and Maximum- have the advantage of logarithmic times some of them in PathDemo, I believe Area decomposition (each convex for insertion, deletion, and search; how- that they are not very useful for the geo- vertex of an obstacle projects the ever, if the number of nodes is rarely metric path-finding domain. edges forming the vertex to the near-

34 GAME DEVELOPER • OCTOBER/NOVEMBER 1996 http://www.gdmag.com est obstacles or walls; between these two segments and the segment join- ing to the nearest visible vertex, the shortest is chosen). See Figure 11D. For weighted regions problems, the space is divided into polygons of homogeneous traversal cost. The points to aim for when crossing boundaries are computed using Snell’s Law of Refraction. This approach avoids the irregular paths found by other means. • Quadtrees. Similar to the convex poly- gons, the space is divided into squares. Each square that isn’t close to being homogenous is divided into four smaller squares, recursively. The centers of these squares are used for searching a path. See Figure 11E. • Generalized cylinders. The space between adjacent obstacles is consid- ered a cylinder whose shape changes along its axis. The axis traversing the space between each adjacent pair of obstacles (including walls) is comput- ed, and the axes are the paths used in the search. See Figure 11F. • Potential fields. An approach that does not quantize the space, nor require complete calculation beforehand, is to consider that each obstacle has a repulsive potential field around it, whose strength is inversely propor- tional to the distance from it; there is also a uniform attractive force to the goal. At close regular time intervals, the sum of the attractive and repulsive vectors is computed, and the entity moves in that direction. A problem with this approach is that it may fall into a local minimum; various ways of moving out of such spots have been devised. For more figures that illustrate con- cepts presented in this article and for a list of references on AI research, data structures, and robotics, check out http://www.gdmag.com. ■

Bryan Stout has done work in “real” AI for Martin Marietta and in computer games for MicroProse. He is preparing a book on computer game AI to be published by Addison-Wesley. He can be contacted at [email protected].

http://www.gdmag.com GAME DEVELOPER • OCTOBER/NOVEMBER 1996 35 COIN-OP

The Four Laws of Coin-Op

f you’ve ever played STAR CASTLE, As with all laws, you can break them STREET FIGHTER II and do pretty well in DEFENDER, MORTAL KOMBAT, or if you wish, and you may even get away the first couple of rounds against the DAYTONA USA, then you’ve experi- with it—but you’re running a nearly computer just by pounding quickly and enced the pulse-pounding rush of 100% risk of failure if you violate these randomly on the buttons. Once they’ve great coin-op game design. As a PC laws without first internalizing them played a few times and have built a desire game developer yourself, you know a completely. to improve, players might read the few good game when you see one. But simple instructions (or simply explore the knowing it’s good and knowing why Brown’s First Law: controls’ behavior) and realize that the Iit’s good are two very different things. Be Simple and Intuitive controls have greater depth. Being able to design a coin-op game A coin-op game’s controls, objectives, The objective of the game is obvious yourself is something else entirely. choices, and reasons for loss must be sim- to even the most casual passersby. Two This article reveals the secrets of the ple and intuitive on the first play. large, tough-looking characters start each coin-op masters. It is based on a series of Nobody reads the instructions in a game facing each other in stances that interviews with some of the most success- coin-op game, at least not until they’ve suggest impending confrontation. Even ful coin-op game designers in the world. played the game and realized that the from the early days of the fighter genre, With high-end PCs emerging as the new controls have greater depth than they first this was more than enough to teach a standard platform for coin-op game imagined (see Law #4, Depth, below). player what he was supposed to do: use design, your experience in PC game Players have to be able to walk up to the his character to beat the crud out of the development and the experts’ experience machine, drop in a coin, start playing, other character. Distinct life energy bars in coin-op game design should produce a and do well enough on the very first play on each player’s side of the screen and a new market for PC-based coin-op games to feel good enough about their perfor- large centralized timer communicate the that can be very profitable to both—and a mance to think that they (and therefore specific objectives—namely, pound your heck of a lot of fun. the game) are pretty darn good. If a game opponent until his life energy is gone, or fails to obey this law, the players will walk at least drive it lower than your own bar It’s the Law away after their first coin—a recipe for before time runs out. We interviewed many stars, such as Ed financial disaster. The primary choice in STREET Logg, designer of CENTIPEDE, GAUNT- Capcom’s phenomenally successful FIGHTER II is which character to use, LET, and STEEL TALONS, Richard Dit- STREET FIGHTER II provides an excellent and this choice is presented in a simple, ton, founder of Incredible Technologies example of this law in action. Its controls obvious manner. Afterwards, the player whose credits include Capcom BOWL- consist of a joystick and six buttons. The chooses which attack to use at which ING and TIME KILLERS, as well as joystick moves your fighter’s body, and time—the basic attacks, character-spe- designers at Williams and Rare (makers the buttons activate kicks and punches. cific attacks, and combo attacks. These of KILLER INSTINCTS). We asked specif- The six buttons are arranged in two rows. decisions can be the result of randomly ic and open-ended questions about what The three upper buttons control punches, pounding the controls or of extremely coin-op games were the best and why— while the three lower buttons control deep (but fast) tactical planning, and what general rules they used when kicks—so there’s a natural mapping depending on the skill level of the play- designing coin-op games. The answers, between upper body (which correlates to er. Each individual attack is easy to while varying widely, uniformly agreed the upper buttons) and lower body learn, and the degree of improvement on the key concepts described below. (which correlates to the lower buttons). resulting from the player’s learning just These, then, are the core design princi- From left to right, the buttons progress one move is significant, encouraging ples—the laws, if you will—of coin-op from faster, lighter blows to slower, heav- players to learn more. The learning game design. ier blows. Anyone can just walk up to curve is smooth, allowing the players to

38 GAME DEVELOPER • OCTOBER/NOVEMBER 1996 http://www.gdmag.com improve their understanding steadily, example of this design law in action. It Jeff Brown and and at their own pace. puts out a flicker-free 60 frames per sec- James Plamondon A cardinal rule of coin-op—almost ond on a 50-inch, high-resolution moni- worthy of its own law—is that when a tor, giving the player very fast, accurate Designing coin-op player loses the game, it must be obvious visual feedback. The high-quality audio to that player why he or she lost, and it system delivers important audio feedback, must appear to be a simple matter to cor- such like squealing sound when the play- rect the mistake and win next time. The er’s car starts to slide. Force feedback games is player has to feel that he or she lost, not “pushes back” on the steering wheel, in that the game won. The failing is with response to the stresses affecting the car him or her, and the player should feel that in the game—from pulling Gs in tight with just a little more practice—“just one turns to bumping against other cars. This more quarter”—he or she can win the multisensory feedback gives the player significantly different game (that is, overcome the specific chal- fast, accurate, detailed, consistent—and lenge that defeated him or her last time). therefore immersive—information about his car and its interaction with other from designing Brown’s Second Law: game elements. As a result, DAYTONA is Deliver Strong Feedback widely regarded as one of the best coin- Strong feedback must be fast, accurate, op games of all time—and it’s been mak- detailed, and consistent—involving the ing money steadily for two years. player’s senses as fully as possible. PC-based games. Of the five senses, three should be Brown’s Third Law: engaged in coin-op games: sight, hearing, Deliver Pace and Rhythm and touch. (The frontiers of smell and A coin-operated video game must deliv- taste are so far unexplored, which—con- er challenges to the player at a fast, Follow these basic sidering the content of fighting games— steadily increasing pace, delivering is just fine with us.) Every player action rhythmic pulses of additional challenges. must be reinforced by visible action—an People play games to be challenged. appropriate sound and, ideally, force- These challenges can be mental, physical, rules, and you will feedback. Force-feedback is best known or both. Mental challenges usually take from driving games, in which the steering time to work out. MYST is a great exam- wheel shakes from the “strain” of a tough ple of a mentally challenging game. It’s turn, or jumps from bumping against also a great example of a game that would other cars, and so on. This multi-sensory flop miserably in coin-op, which is why increase your feedback links the player and avatar—the coin-op games invariably prefer physical vehicle, character, or icon. Through the challenges—challenges of eye-hand coor- avatar, the player is linked to the game dination—to mental challenges, as the environment. Only through fast and core of game play. chances of producing accurate feedback can the player get lost Since such a physical challenge can in the experience the game offers. be presented and overcome in a fraction Sega’s DAYTONA, one of the most of a second, such challenges must be pre- successful driving games ever, is a great sented at a rapid pace. “Tuning” a coin- a hit.

http://www.gdmag.com GAME DEVELOPER • OCTOBER/NOVEMBER 1996 39 COIN-OP

op game means sustaining the right bal- excellent tuning of pace and rhythm. The sity from light (enemies come more or ance between challenge and reward, at all pace of challenges is slow at first, and less one at a time) to heavy (Yikes! points in the game, for the largest group picks up gradually both in the short term They’re all over the place!). Players do of people who might play the game. Tun- (during the course of a single play) as well well enough during light and medium ing has to make both the first-time player as in the long term (over multiple plays, waves to feel good about their abilities and the master player feel challenged and as the player advances farther into the and know that even a small improvement successful, while still defeating them in game). Both the rate at which enemies in skill (“just one more quarter…”) will (generally) one-and-a-half to two-and-a- appear on screen and the speed with get them past the wave that they failed to half minutes per credit. which they shoot at you after they appear shoot their way through last time. Atari’s AREA 51, a recent gun game, are used to increase the pace. Threats has succeeded in large measure to its come in distinct waves, ranging in inten- Brown’s Fourth Law: Offer Depth of Play To continue to draw in coins, a coin- operated video game must engage a play- er’s interest even after repeated play. “Depth” is that characteristic of a game that keeps it interesting and challenging. Depth can be provided through physical challenges or mental challenges. Mental challenges should offer a simple choice between obvious alterna- tives. The three kinds of mental chal- lenges most effectively employed in coin- op game design are set-up options, mid- play options, and hidden elements. Set-up options include things like different teams, racetracks, or characters. In a racing game, a given car may do bet- ter on one track than another; having the player choose both the car (c) and the track (t) creates (c*t) combinations that the player can explore. Similarly, mid-play options give players simple choices during the course of a game. For example, in a racing game, the track may include a long easy stretch and a relatively difficult shortcut, tuned such that only the skilled player would be able to save time by taking the shortcut. Hidden elements are things like secret rooms, secret characters, and so on which generally require that the player know special information. These fre- quently are revealed only by extensive gameplay and word of mouth, creating an “inside group” of which many players will wish to be a part. Physical challenge not only forms the core of coin-op gameplay, but is usu- ally the primary contributor to depth as well. Consider the simple and obvious controls of Capcom’s STREET FIGHTER II. Anyone can walk up, pound away at the buttons, and get at least a few good blows in, by luck alone. But to truly mas-

40 GAME DEVELOPER • OCTOBER/NOVEMBER 1996 http://www.gdmag.com ter the controls—to be able to deliver a the new standard for coin-op video game meets the needs of the coin-op video game specific three-blow combination perfectly deployment. If you’re working on an industry. timed to maximize its effect on the arcade or action-style game, you should opposing character—takes a great deal of be thinking about coin-op—and the Jeff Brown is a freelance game designer physical skill. This skill can be acquired information on our Web site will help and consultant with eight years experience in only through extensive practice, which you get started. ■ coin-op. Mr. Brown previously worked in trains the player’s muscles to perform the the coin-op divisions at Data East and Elec- needed actions smoothly. James Plamondon is a programmer, tronic Arts. He is now a principle of Advent But the separation of mental and author, avid gamer, and technical evange- Game Design in San Jose, Calif. Both physical challenges is not pure, quite the list. Currently the director of coin-op mar- authors can be reached via e-mail at contrary. The pinnacle of mastery is keting at Microsoft, he ensures Windows [email protected]. achieved only when the mental challenge of selecting the ideal action, and the physical challenge of delivering it, merge into a mentally elevated state of being (not to get too Zen-like here), in which you simply are the character, and simply do the right thing. As Miyamoto Musashi, the legendary samurai duelist, wrote in his Book of Five Rings (1643): “First of all, when you take up the sword, in any case the idea is to kill an opponent. Even though you may catch, hit, or block an opponent’s slashing sword, or tie it up or obstruct it, all of these moves are opportunities for cutting the opponent down. This must be under- stood. If you think of catching, think of hitting, think of blocking, think of tying up, or think of obstructing, you will thereby become unable to make the kill.” The game designer’s challenge is to create a game that is sufficiently com- pelling, that the player is stimulated to play again and again, in order to reach and enjoy this level of mastery.

Learning By Example This brief overview of the Laws of Coin- Op is now complete. To understand these laws fully, however, it would be useful to discuss how the Laws would be applied to existing PC games in the main coin-op genres, to turn them into potentially successful coin-op games. Space does not allow such a discussion here, but you’ll find exactly that discus- sion—plus information on the great guys who contributed their wisdom and experience to the creation of this paper—on Microsoft’s web site. Head for http://www.microsoft. com/devonly, and search for “coin-op.” You’ll find these examples and a lot of other information on the emergence of the high-end PC as

http://www.gdmag.com GAME DEVELOPER • OCTOBER/NOVEMBER 1996 41 BSP TREES

Advanced Binary Space Partition Techniques

arge, complex worlds com- must draw the two polygons in three BSP algorithm stores polygons in a posed of thousands of poly- steps: first, the farthest portion of the given order, correctly handles overlap- gons often create problems piercing polygon is drawn, then the ping or penetrated polygons, and pro- for game developers. It’s not pierced polygon is drawn, and finally vides ways to tailor the algorithm to the easy to display every polygon the portion of the piercing polygon in performance requirements of the most correctly. In order to reduce front of the pierced polygon is drawn. demanding applications. The BSP algo- the number of polygons you Whether the scene is static (where rithm does have some disadvantages have to display, consider polygons are fixed in 3D space) or however, which I’ll cover in a moment. Lusing techniques based on the binary dynamic (where polygons move from The BSP algorithm can be under- space partition (BSP) to eliminate frame to frame), the 3D game engine stood when broken down into its basic polygons that aren’t visible from the has to draw the polygons in such a components: the storage component, player’s perspective. manner that the display appears realis- the space partition component, and the The need for the BSP arises from tic and matches the viewer’s expecta- polygon partition component. Each the problems associated with correctly tions of solid objects in a 3D world for component has its own set of optimiza- displaying polygons in a 3D visual envi- all possible combinations of polygons. tions and caveats. ronment. One approach to displaying The storage component stores and polygons, known as the Painter’s algo- Polygon Collision Problem retrieves the polygons in a specified rithm, simply draws each of the poly- Although the Painter’s algorithm solves order. Usually, a binary tree is used as gons from the farthest point in space to some problems associated with correctly the storage component. Other methods the closest until all polygons are drawn. displaying polygons, it does not address (linked lists or octrees) are equally valid. However, this solution doesn’t work if collision detection issues, nor does it The binary tree excels at adding or some of the polygons are pierced by allow for shading, ray tracing, or other removing large numbers of polygons at other polygons. When one polygon illumination effects. This is where the run time because its content can be pierces another, the Painter’s algorithm BSP algorithm becomes valuable. The searched fast. However, when the 3D

Figure 1. The partitioning polygon’s plane splits the scene into Figure 2. None of the vertices of the test polygon are on the near two sides. side of the partition.

42 GAME DEVELOPER • OCTOBER/NOVEMBER 1996 http://www.gdmag.com Michael game engine does not expect much in titioning polygon defines a partitioning Kelleghan the way of additions and deletions, a plane through the 3D scene. Take each linked list is faster. vertex of the test polygon and determine The space partition component which side of the partitioning plane the The Binary Space determines the position of a given poly- vertex is on. I obtain the normal of the gon relative to another polygon. The vertex to the partitioning plane. The sign objective is to use one polygon to define of the normal indicates which side of the a plane through the 3D space. All other plane the vertex is on (see Figure 1). The Partition algorithm polygons are classified as either being partitioning polygon’s plane splits the on the same side of the plane as the scene into two sides, hence the name viewer or on the far side of the plane binary space partition (we want to know away from the viewer. A polygon can be which side of the partitioning plane the positioned on either side of the plane, test polygon is on). can help correctly on the plane, or pierced by the plane. If The code for this operation is a polygon lies entirely on one side of called the partitioning function. I use it the plane or the other, you pass it to the to determine whether the test polygon storage component. If the polygon is is in contact with the partitioning poly- display polygons in a pierced by the plane, it must be split gon’s plane, and where on the test poly- into two smaller polygons, which must gon the contact occurs. Let’s take a lie on either side of the plane. These closer look at the partitioning function two polygons are then passed into the now. 3D environment, storage component. Here are three conditions to evalu- The polygon partition component ate when writing your partitioning determines how and where to split a function: polygon when it is intersected by 1. If none of the vertices of the test poly- address the problem another polygon or the partitioning gon are on the near side of the parti- plane, which results in two or more tion (from your viewpoint as in Figure child polygons. 2), the test polygon goes on the left node of the binary tree whose root of collision detection, The Initial BSP starts at the partitioning polygon. Keeping the above components in mind, 2. If none of the vertices of the test I’ll outline the steps to build a are on the far side of the par- BSP algorithm. (I’ll use a brute-force tition (from the view point as in Fig- approach for simplicity’s sake, and ure 3), the test polygon goes on the and allow for shading, explore optimizations later.) To illustrate right node of the binary tree whose the process, I’ll build a static BSP algo- root starts at the partitioning rithm, using a binary tree for our storage polygon. method and triangles as our polygons. 3. If some vertices of the test polygon are ray tracing, and other Starting with a world made up of on the near side of the partition and polygons, select any two of them and some are on the far side (as in Figure designate one the partitioning polygon 4), then split the test polygon into two and the other the test polygon. The par- sub-polygons; attach one sub-polygon illumination effects.

http://www.gdmag.com GAME DEVELOPER • OCTOBER/NOVEMBER 1996 43 BSP TREES

Figure 3. None of the vertices of the test polygon are on the far Figure 4. Some of the vertices of the test polygon are on the near side of the partition. side of the partition and some are on the far side.

to the left node, and the other to the the scene. Once you know that, you can 1. The moving polygon optimization. Dur- right node. Make the split where the apply any additional algorithms to the ing the user action stage in the game, partitioning plane intersects the test point of contact such as reflection, flag those polygons that have moved. polygon. You may use any standard refraction, transparency, or luminosity. Before the BSP is accessed to draw polygon intersection algorithm from You repeat the algorithm until all poly- the polygons to the screen, resort only your favorite geometry book. gons have been visited by the ray or the those polygons that have moved. Our binary tree now contains the ray flies off into infinity, and then repeat There is no need to visit polygons that two polygons (or the partitioning poly- again for every ray you want to trace. have not moved. gon and several sub-polygons) in Z- The BSP algorithm can also be used 2. The nearest-neighbors optimization. order. Repeat the three-step process for for collision detection and line-of-sight When testing a polygon against other all other polygons in the scene. (both direct and mirrored) calculations polygons in the tree, test the polygon by modifying the partitioning function in only against its immediate neighbors Illumination Effects the same way that we modified it for illu- in the tree. The polygons that are con- Once we’ve set up our initial BSP, we can mination effects. sidered nearest neighbors are those use it for ray tracing and other illumina- that are within the maximum distance tion effects. Modify the partitioning func- BSP in Dynamic 3D Games that a polygon can travel in a single tion used for the static BSP so that the Although BSPs have been used in static frame. function returns data about the polygon environments, when properly optimized 3. The binary-plane split optimization. instead of adding a polygon to the binary they can be very useful in multi-frame Note that the reason a polygon is split tree. This data tells whether the polygon dynamic environments. The most com- on either side of a binary plane is to intersects any other polygon in the scene mon use is for managing collision detec- allow for illumination effects. If the and where the intersection occurs. tion, line-of-sight calculations, and poly- game does not require run-time illu- Next, select the first ray you wish to gon culling in shoot-’em-up games. mination, you don’t need to split poly- trace. For this example, I will use the tradi- To enable these features, the BSP is gons with the plane of the partitioning tional ray-tracing method of following rays first built with the static methods out- polygon. You only need to split those from the light source through the scene. lined. During run time, the sorted order polygons that are in actual contact (Other methods exist; the use of the BSP is of polygons in the BSP is maintained with other polygons. similar for all.) Consider the ray, which is a between animation frames. (The brute- 4. The backface optimization. Since back- 2D line through the 3D scene, to be a force method would have you resort the faces aren’t visible, performance can be degenerate polygon, with its two endpoints entire BSP every frame of your anima- improved by eliminating backface split- as the three vertices of a triangle. (One of tion.) This approach would be correct ting. Avoid using backfaces as either the endpoints will be equivalent to two of but horribly slow. Assuming a fully sort- test or partitioning polygons. This the vertices of a triangle.) Pass this ray to ed initial BSP, I have listed optimiza- optimization is only valid if you don’t the partitioning function so that it treats tions below that improve the speed dra- use the BSP for illumination effects, the ray as if it were a polygon. matically (keep in mind, though, that and you’ll still need to maintain the Z- The partitioning function should they are designed to produce a fast order of the backface as it may become tell you if the ray contacts a polygon in result—not a perfect one). visible during another frame.

44 GAME DEVELOPER • OCTOBER/NOVEMBER 1996 http://www.gdmag.com 5. The non-penetrating optimization. For 10. The bounding Z-box optimization. have a problem calculating the sign of some applications, such as Doom-style When you have selected two polygons the dot product of a vertex against a games, one polygon may never pene- for penetration testing, check the Z- plane in your partitioning function. If trate another. Thus, you may be able to position of the polygons. If one of the your program freezes, the BSP is proba- dispense with splitting altogether. polygons is fully further in Z than the bly splitting both polygons into multi- 6. The join optimization. Notice that the other polygon, then the polygons are tudes of sub-polygons, trying to get all of BSP leaves several sub-polygons in not in contact. At this point, you can them on both sides of each other’s parti- the tree whenever a polygon is split. exit the partitioning function even if tioning planes. You probably used a “>=” Given enough motion in the poly- one of the polygons has reached the where you meant to use “>”. gons and the resulting polygon splits, partitioning plane of the other. For the second test, rotate the red you will eventually end up with a polygon about any axis in single-degree BSP that has many more polygons Viewing Frustum Culling increments each frame for a full 360 than you started with. In the worst in Dynamic Applications frames. The red polygon should fall away case, every polygon will be split so The BSP can be used to quickly calculate behind the blue polygon, swing around, many times that you may end up which polygons are within the viewing and return to cover the blue polygon. The with a BSP filled with pixel-sized frustum (that portion of your 3D world coordinates of the vertices of the red poly- sub-polygons! The solution lies in visible on the screen). This technique gon should be the same as they were prior going back through the tree, rejoin- can greatly reduce the number of poly- to the rotation. If not, you may be accu- ing all the split polygons after draw- gons your program has to deal with. mulating too many floating-point errors. ing each frame. If you’re flagging Consider the viewing frustum as For the third test, add a few lines of moved polygons as part of a moving polygons making up the sides, base, and code to your BSP so that polygons on the polygon optimization, maintain the top of a truncated pyramid. The sides of left node of the binary tree are colored flag when you join the splits. the frustum should be considered poly- blue and those on the right node are col- 7. Inter-frame coherency optimization. gons in the 3D scene. These polygons ored red. Now, create two polygons; one Instead of maintaining the BSP must have their own flags to uniquely coplanar with the XY plane; the other between each frame of your anima- identify them, and their normals must with the YZ plane. Move the two poly- tion, do the maintenance every other point into the viewing frustum. gons so that they intersect and interpene- frame. If the motion of the polygons Next, build the initial static BSP as trate each other. The motion should take from frame to frame is fast enough, we did in previous sections. (You may several frames. Observe the polygons as the image won’t suffer. In some opt to add another flag to each polygon they intersect. The color of the sub-poly- cases, you can postpone the mainte- indicating whether it’s inside or outside gons created by the split operations nance over several frames. the viewing frustum to simplify polygon should change at the line where the two 8. The linked-list optimization. Store all culling.) Use the moving polygon opti- polygons intersect. When the two poly- your polygons in a linearly linked list mization described. If the polygon gons have completely passed through instead of a binary tree; this removes moves outside the viewing frustum, you each other, they should each consist of a any balancing issues, as well as prob- can discard it. solid color. If they don’t, you have a prob- lems caused by recursion depth. lem in the join optimization. (You’re 9. The viewpoint-translate optimization. Testing Your doing join optimizations, aren’t you?) You can place the viewpoint in the BSP for Errors The binary space partition is an tree (as a pseudo polygon), so that Most errors in BSP implementations extremely flexible and powerful algo- when the viewpoint translates (but are found in the partitioning function rithm. Properly optimized and applied, does not rotate), no polygons are and its handling of comparisons. The it can form the core of the most processed (they have not moved rela- accumulation of floating-point errors demanding 3D applications. By using tive to each other). Process only the makes these errors all the more vexing. well-known components, such as binary viewpoint pseudo polygon by sliding However, you can use a few simple tests trees, linked lists and octrees, a robust it left or right in the tree, drawing to identify the presence of these errors. implementation is easily achieved. This from the furthest leaf node to the First, create two identical polygons well-respected algorithm is a useful viewpoint node. This optimization with identical vertices. Color one red addition to any tool chest. ■ prevents having to balance the tree all and the other blue so they are easily dis- the time. (You have placed the view- tinguished. For the first test, display Mike Kelleghan writes 3D engines for point in the tree as a virtual root, if these two polygons with your BSP code various game companies in Southern Cali- you will.) If there are objects in the and observe them during several frames. fornia. He thrives on pizza, Jolt Cola, and scene behind the viewpoint, you can One of the polygons should occlude the grandkids. You can usually find him in the save even more time by stopping the other at all times. If you notice that the GAMEDEV forum on Compuserve. Con- drawing process at the viewpoint leaf. polygons switch Z-order each frame, you tact him via e-mail at [email protected].

http://www.gdmag.com GAME DEVELOPER • OCTOBER/NOVEMBER 1996 45 DIRECTINPUT

DirectInput: Microsoft’s Peripheral Vision Brian Gosselin

oday’s games are much more es the implementation details of using complex than those just a cou- DirectInput through version 2.0. ple years old. There’s a need, A new generation of therefore, to increase the The DirectInput sophistication of the peripher- Architecture als that control the action, and As shown in Figure 1, the DirectInput Microsoft responded with architecture in Windows 95 provides input devices requires DirectInput. By collecting up two separate data paths for 16- and 32- toT six axes (left/right, up/down, back- bit applications. DirectInput removes wards/forwards, and a barrel roll the burden that polling joysticks and around each of these axes) and 32 but- configuring special controllers place on a next generation API tons of data from a peripheral device, the system and game developer. Vendors DirectInput is a fundamental shift from that make joysticks, flight yokes, control the previous joystick interfaces that pads, or other input devices for Win- supported only three axes of data. It dows 95 games must supply their own to leverage the tech- also leverages the performance increase DirectInput driver to communicate with digital joysticks offer. Finally, DirectIn- VJOYD.VXD, which is the 32-bit dri- put reduces the peripheral coding ver that polls the joystick. The required by game developers to a few VJOYD.VXD then turns the devices’ nology. Microsoft‘s simple functions, and it returns normal- axis data in to DWORDs (an unsigned long ized data that lets you easily configure data type) with values ranging between 0 all kinds of devices. This article discuss- and 65535 and point-of-view (POV) DirectInput is quickly Figure 1. The DirectInput Architecture becoming the industry 16-bit Application 32-bit Application

Thunk standard for Windows MMSYSTEM.DLL (16 bit) WINMM.DLL (32 bit)

MSJSTICK.DRV (16 bit) Input/Output Control (IOCTL) 95 games. Gosselin Thunk

VJOYD.VxD (32 bit)

OEM.VxD shows how it works.

http://www.gdmag.com GAME DEVELOPER • OCTOBER/NOVEMBER 1996 47 DIRECTINPUT

Listing 1. Determining if joystick is attached rently installed joysticks, location of the joystick driver. Listing 2 and joystick capabilities. shows the JOYCAPS structure. MMRESULT joy_error; // Joystick Status/Error By determining the capabilities of LPJOYCAPS joy_cap; // Joystick capabilities structure Getting Started UINT joysizestruct; // Size of Joystick Structure the attached device, you can match your unsigned int joy_num; With DirectInput game’s performance to the capabilities of You can incorporate the attached peripheral. To display a list joy_cap = malloc(joysizestruct=sizeof(*joy_cap)); for(joy_num=0;joy_num<16;joy_num++) DirectInput into your of attached devices as they would appear { application by linking the in the joystick properties control panel, if(!(joy_error=joyGetDevCaps(joy_num,joy_cap,joy WINMM.LIB file and use the function in Listing 3. Just pass sizestruct))) szRegkey { including the MMSYS- the returned value and the asso- /* Found a Joystick Extract Name and axes from TEM.H file with your ciated joystick ID number. registry*/ executable. These files are } Capturing and Configuring } located in the compiler’s library (\lib) and include the Joystick directories, respectively. To capture a joystick, use the joySetCap- data values ranging from 0 to 35900 When your game is launched, it should ture function like this: (measured in angular degrees). (The first determine the number and type of POV data lets a player acting as a pilot input devices present. DirectInput can MMRESULT joySetCapture(HWND hwnd, UINT look around without changing the support up to 16 different joysticks. uJoyID, UINT uPeriod, BOOL fChanged); motion of the ship the player is traveling The MMSYSTEM.H defines two joy- in. A player can look out of a plane stick IDs, JOYSTICKID1 and JOYSTICKID2, If joySetCapture fails to capture the cockpit to the right, left, or behind.) with the remaining joystick ID num- joystick, it will return one of the three New digital devices provide a significant bers to be set by the user using values 2 error messages shown in Table 1. This performance improvement over analog through 15. You might be tempted to capture function must be called for each joysticks because valuable time is not use the function joyGetNumDevs() to joystick individually. wasted by polling for data. retrieve the number of attached joy- When a joystick is captured, the DirectInput 1.0 and 2.0 use the sticks, but under Windows 95 this joySetCapture function configures the Windows 95 registry to store data that function determines how many joy- VJOYD.VXD to perform either event- your game will need to access. This data sticks the present driver can support driven or polling data transfers. Today’s includes device and calibration data, cur- (which is always 16), not how many are digital joysticks produce event-driven attached to the system. You data, which means that applications save can easily determine precious CPU cycles by putting the onus Listing 2. The JOYCAPS Structure whether a joystick is on the joystick to inform the computer attached by looping of a movement or button event. Polling typedef struct { through joystick IDs 0 and event-driven data will be explained WORD wMid; \\ manufacturer identifier through 16 and determin- more thoroughly in the next section. WORD wPid; \\ product identifier CHAR szPname[MAXPNAMELEN]; \\ Driver name ing the capabilities of each The fChanged flag in the joySetCap- UINT wXmin; \\ min. x-coordinate joystick, like the function ture function can either be set to TRUE or UINT wXmax; \\ max. x-coordinate in Listing 1. This function FALSE. A setting of TRUE configures the UINT wYmin; \\ min. y-coordinate UINT wYmax; \\ max. y-coordinate will return capabilities of joystick for event messages, while setting UINT wZmin; \\ min. z-coordinate attached joysticks or an fChanged to FALSE will tell the computer to UINT wZmax; \\ max. z-coordinate error code JOYERR_PARMS. poll the joystick for changes. If polling is UINT wNumButtons; \\ no. of joystick buttons UINT wPeriodMin; \\ minimum supported polling freq. After your application selected, you must set the period between UINT wPeriodMax; \\ Maximum supported polling Freq has detected a joystick, the callback messages (measured in millisec- \\ The following members are not in previous versions of Windows. capabilites structure, JOY- onds). The wPeriodMin and wPeriodMax UINT wRmin; \\ min r-coordinate UINT wRmax; \\ max. r-coordinate CAPS, provides detailed flags from the joystick capabilities struc- UINT wUmin; \\ min u-coordinate information about the ture provide the feasible polling rate UINT wUmax; \\ max. u-coordinate device. The joystick capa- range for your application. Setting uPeri- UINT wVmin; \\ min v-coordinate UINT wVmax; \\ max. v-coordinate bilities structure provides od to 0 results in the minimum polling UINT wCaps; \\ Point of View Capabilities information on the mini- frequency of the attached device. UINT wMaxAxes; \\ max. Axes supported mum and maximum value Setting fChanged for event messages UINT wNumAxes; \\ max. Axes used UINT wMaxButtons; \\ Max buttons on device of each axis, the presence (TRUE) means that a motion event will CHAR szRegKey[MAXPNAMELEN]; \\ Registry key for the msjstick.drv or absence of a POV con- only be sent from the VJOYD.VXD CHAR szOEMVxD[MAXOEMVXD]; \\ Oem’s VXD name trol, the number of buttons when the joystick movement crosses the } JOYCAPS; and axes, and the registry “defined” threshold. Initially, the default

48 GAME DEVELOPER • OCTOBER/NOVEMBER 1996 http://www.gdmag.com Listing 3. Displaying a list of attached devices threshold of an attached device is 0. The value of the threshold is an unsigned inte- /*------*/ ger ranging from 0 to 65535. The thresh- int GetJoystickName(UINT joy_num,BYTE szRegKey[MAX_PATH],BYTE szReturnName[MAX_PATH]) /* old must be set carefully. If it is set too Description : Opens the MediaResources\Joysitick\mjstick.drv\JoystickSettings and high, all movements from a device will be extracts Joystick%dOEMName string eliminated; if it is set too low, the slight- Arguments : joy_num (r/o) - Joystick Number szRegKey (r/o) - Registry Key of the msjstick.drv est touch on the input device will cause a ReturnName (r/w) - Return String for name listed in Control Panel reaction. Altering the threshold of the Returns : 0 for success 1 for failure joystick is important when the joystick is /*------*/ { set for event-driven data collection. BYTE KeyStr[MAX_PATH] = REGSTR_PATH_JOYCONFIG; // found in regstr.h An appropriate threshold prevents BYTE KeyJoySetStr[MAX_PATH] = REGSTR_KEY_JOYSETTINGS; // found in Regstr.h spurious callback message generation. BYTE szOEMName[MAX_PATH]; // OEM name from Current Settings HKEY ConfigKey; The threshold will stabilize the images HKEY JoyConfigKey; // Joystick Configuration on the screen by limiting rendering to HKEY DriverKey; // Joystick Driver Key movements of the defined magnitudes. HKEY OEMPropKey; HKEY PropKey; You can alter the threshold value by call- MMRESULT test; ing the following function: DWORD Length; BYTE Crap[MAX_PATH]; // Opens msjstick.drv MMRESULT joySetThreshold(UINT uJoyID, if( ERROR_SUCCESS != RegOpenKey( HKEY_LOCAL_MACHINE,REGSTR_PATH_JOYCONFIG,&ConfigKey ) ) UINT uThreshold); function { return( 1 ); // It should never get here key received from Caps } Subsequently, you can check the threshold by using the following function: if( ERROR_SUCCESS != RegOpenKey( ConfigKey, szRegKey, &DriverKey ) ) { MMRESULT joyGetThreshold(UINT uJoyID, return( 1 ); // It should never get here key received from Caps } LPUINT puThreshold); function // Open CurrentSettings Key

if( ERROR_SUCCESS != RegOpenKey( DriverKey, REGSTR_KEY_JOYCURR, &JoyConfigKey ) ) It’s important to understand that { the joystick callbacks in DirectInput return( 1 ); // It should never get here always a Current Settings Version 1.0 and 2.0 are generated for } sprintf(KeyStr,REGSTR_VAL_JOYNOEMNAME,joy_num+1); any motion or button event, up to the Length=sizeof(szOEMName); // Get OEMNAME Configuration first four buttons pressed or released. (This is a throwback to the older joy- if( ERROR_SUCCESS != RegQueryValueEx( JoyConfigKey,KeyStr,NULL,NULL,(unsigned char *)&szOEMName,&Length)) { sticks.) The state of the remaining but- return( 1 ); // No OEM name listed return error ton is returned in the dwButton value of } the joystick, but no callback messages RegCloseKey( REGSTR_PATH_JOYCONFIG); // Closes the registry Key will be generated. // Open OEM Properties Key Since Windows 95 is a multitasking if( ERROR_SUCCESS != RegOpenKey(HKEY_LOCAL_MACHINE,REGSTR_PATH_JOYOEM,&PropKey ) ) operating system, it’s important to { return( 1 ); // It should never get here key received from Caps remember that more than one application } can collect data from the joystick at a time. With multiple applications collect- if( ERROR_SUCCESS != RegOpenKey( PropKey, szOEMName, &OEMPropKey ) ) { ing data, the data stream to an application return( 1 ); // It should never get here if device is selected can be interrupted causing data loss— } meaning a player’s motion or button event Length=MAX_PATH; // Get Name as listed in Control Panel might not be registered by the game. One if( ERROR_SUCCESS != RegQueryValueEx( OEMPropKey,REGSTR_VAL_JOYOEMNAME,NULL,NULL,(unsigned char *)szReturn- way to prevent such data loss is to see if Name,&Length))) another application has captured the joy- { return( 1 ); // No OEM name listed return error stick. While an application can request } data from VJOYD.VXD without captur- RegCloseKey( REGSTR_PATH_JOYOEM); // Closes the registry Key ing the joystick, only one application may return 0; capture the joystick at a time. Also beware } /* End GetJoystickName */ that other applications can still interrupt the data flow by calling joyGetPosEx with- out capturing the joystick.

http://www.gdmag.com GAME DEVELOPER • OCTOBER/NOVEMBER 1996 49 DIRECTINPUT

Listing 4. A motion callback Table 1. Joystick Capture Error Messages

LPJOYINFOEX joy_data; MMSYSERR_NODRIVER The joystick driver is not present.

case MM_JOY1MOVE : JOYERR_NOCANDO Cannot capture joystick input because a required service (such as a Win- // I am using polling so I am only dows timer) is unavailable. watching for motion events joy_data->dwFlags = JOY_RETURNALL // Configures for the axis data to return JOYERR_UNPLUGGED The specified joystick is not connected to the system. if((joy_error =joyGetPosEx(JOYSTICKID1,joy_data))) { return (-1); // No Data ward compatibility. The joyGetPosEx application requires only X and Y data, } function extends the collection of data to code it like this: // Process Data for your application six axes, 32 buttons, and a POV. The return(0); dwFlags parameter of the JOYINFOEX struc- joy_data->dwFlags = JOY_RETURNX | ture determines the type and amount of JOY_RETURNY Receiving Data data an application receives from the From the Joystick VJOYD.VXD. The code fragment in Requesting data from only the pertinent Once the joystick is set up, your game Listing 4 is an example of processing a joystick axes in this way will save valuable can begin to retrieve data from it. The motion callback. I have placed the CPU time. A complete list of dwFlags is messages sent to the application consist JOY_RETURNALL flag inside the loop for this listed in your compiler’s help files for the of MM_JOY1MOVE, MM_JOY1BUTTONUP, and example. The returned data structure for JOYINFOEX structure, but I’ve listed some of MM_JOY1BUTTONDOWN. When any button is joyGetPosEx is shown in Listing 5. the common ones in Table 2. pressed, for example, the MM_JOYBUTTON When data from a device is collected There are two return values for but- event is triggered and you have to deci- using the JOY_RETURNALL flag, axis data is ton data. The first one, the dwButton pher what button was actually pressed. standardized between 0 to 65535 (DWORD) field, stores a 32-bit mask for the state of In an application using event-driven and the POV data is standardized the button at the time of the function messaging, the application must process between 0 and 35900 (DWORD). To use this call. The second, dwButtonNumber, stores all messages, while polling applications data, you divide the return value by 100 the number of the lowest button pressed need only to process move messages for the pressed angle on the device. For (meaning if button 1 and 2 are pressed, because the button’s state is stored with- optimum performance, only request the dwButtonNumber will be 1 and dwButton in the position information. A polling desired information from the joystick; will be 3). application can optionally process button event or polling timer loops must be con- A note about processing the data messages too, because these messages are figured for analog joysticks. The need to from peripheral devices. While Direct- still generated from the VJOYD.VXD. request only the desired data is removed Input has standardized to six axes, not To utilize the data from all six axes when the device is purely digital. Because all peripherals have all six axes, nor do available in DirectInput, the joyGetPosEx the dwFlags controls the data returned, they map to the same common move- function must be called instead of the you can request selected axes by passing ment to axes. Many applications allow joyGetPos function from Windows 3.11. an “or-ed” combination of individual axes peripheral vendors to set an axis map The joyGetPos function is supported into the dwFlags prior to calling the for their game. The common conven- under DirectInput, but only for back- joyGetPosEx function. For example, if your tion is a string containing the map. An axis map consists of six letters— XYZRUV. The letters represent the Listing 5. Returned data for joyGetPosEx joysticks data axes 1 through 6. The string can be read from the registry and typedef struct joyinfoex_tag { DWORD dwSize; \\ size, in bytes, of this structure configured within your game. Since the DWORD dwFlags; \\ flags for return data axes of different controllers move in DWORD dwXpos; \\ current x-coordinate different directions, axis data can be DWORD dwYpos; \\ current y-coordinate DWORD dwZpos; \\ current z-coordinate inverted by using lowercase letters. For DWORD dwRpos; \\ Rudder information example “xUZRYV” is the axis map- DWORD dwUpos; \\ current 5th axis position ping for Doom with my company’s DWORD dwVpos; \\ current 6th axis position DWORD dwButtons; \\ mask of the button state input device, the Spaceball Avenger. DWORD dwButtonNumber; \\ lowest button number pressed The first axis is strafe (translate X), the DWORD dwPOV; \\ Point of View position 0 to 35,900 divide number by 100 for angle measurements second is rotation (rotate Y), and the DWORD dwReserved1; \\ reserved; do not use DWORD dwReserved2; \\ reserved; do not use third is move forward (translate Z). } JOYINFOEX; Different controllers may configure Doom differently. For example, the

50 GAME DEVELOPER • OCTOBER/NOVEMBER 1996 http://www.gdmag.com Microsoft Sidewinder would create a Table 2. Common flags in dwFlags map “XRYZUV” where X is strafe (Translate X), R is rotate (the twist on JOY_RETURNALL Return all axis data and POV data = the or of all dwFlags except the top of the controller), and Y is mov- JOY_RETURNPOV Return POV data ing forward (Translate Y). Only the JOY_RETURNRAWDATA Return the raw data from a device prior to normalizing to 0 to 65535 first three axes are used in Doom; the JOY_RETURNBUTTONS Return button information remaining three axes are not used. JOY_RETURNX Return just X axis data

Closing the Joystick Upon completion of your application, the joystick should be released. If the what joysticks are connected, check their about the time this article is published. application does not explicitly release the capabilities, get the manufacturer’s name Version 3.0 will collect data from all capture, the system will release the joy- for the device, set up a polling loop, and types of peripheral devices including stick automatically when the application process joystick 1 messages. mice, keyboards, data gloves, and force- closes. To release the capture of the joy- feedback joysticks. It will also support stick use the following function: The Next Step virtual devices, which will allow unlimit- While DirectInput is presently limited ed axes and buttons. ■ MMRESULT joyReleaseCapture(UINT uJoyID); to Windows 95, it has been suggested that it will be available under Windows Complete Code Sample NT 4.0. The burden of configuring joy- Brian Gosselin is a project leader for The complete code is available on the sticks and setting up polling loops has Spacetec IMC, makers of the Spaceball Game Developer web site. It is a simple been removed from the game. DirectIn- products, including the Spaceball Avenger polling joystick application from the Wnd- put 3.0, which is being developed as I and SpaceOrb360. He can be reached via e- Proc function. The code will check to see write this article, will likely be released mail at [email protected].

http://www.gdmag.com GAME DEVELOPER • OCTOBER/NOVEMBER 1996 51 ARTIST‘S VIEW

Walk this Way

David Sieks emember the ads for Sea larly breathless copy that preceded the Monkeys in the back pages of release of Character Studio, the new comic books? The illustration figure animation plug-in for 3D Studio Kinetix takes a giant showed these darling little Max. “MUSCLE-BULGING, TENDON- pink people-like creatures: STRETCHING, AND VEIN-POPPING there was the Sea Monkey DETAIL,” it promised in bold capitals. king with his crown, little Sea “JUST PLACE THE FOOTSTEPS INTO Monkey kids, an oddly appeal- YOUR SCENE AND WATCH IT CREATE Ring she-Sea Monkey, and a fantastic Sea 100% BELIEVABLE MOTION RIGHT step toward Monkey castle in the background. The BEFORE YOUR EYES. Make your char- breathless ad copy led one to expect these acters walk up stairs, jump through little charmers would be more fun to hoops, or dance to the beat!” Yeah, watch than Saturday morning cartoons. right, I thought. Just add water! Gazing at the ad, I could picture my per- After spending a couple of weeks sonal Sea Monkey colony going about with a prerelease version of the software, their subaquatic business, skinny pink however, I had to admit this wasn’t hype. revolutionizing figure limbs paddling the crystal clear water, Well, okay, yes it is hype, but in this case every once in a while looking up to smile the product pretty much delivers on the their innocent Sea Monkey smiles at me hype. Of course it isn’t quite as effortless through the squeaky clean glass. as the ad copy makes it sound (what ever I never actually sent away for the is?), but Character Studio gives you truly Sea Monkeys because caring for a fish- amazing figure animation tools that will animation with bowl of little people, smiling and happy help you bring your 3D characters to life and yet so fragile and needy in their tiny in ways you might have dreamt of but pinkness, seemed, the more I thought never thought possible. about it, a crushing responsibility for a Character Studio was developed as a child. I had flushed more than one gold- 3D Studio Max plug-in for Kinetix (the fish by then and buried a few stiff gerbils, Autodesk multimedia division) by Unreal Character Studio, a and I was afraid, frankly, of finding these Pictures Inc. of Palo Alto, Calif. 3D adorable little humanoids belly up in Studio Max, therefore, is a prerequisite their bowl, their endearing smiles twisted for Character Studio, which does not into deathly grimaces. It wasn’t until work as a stand-alone program. Rather, it some years later that I actually saw the adds revolutionary figure animation tools reality of Sea Monkeys: freeze-dried to Max’s already impressive 3D toolkit new plug-in for 3D brine shrimp eggs that resume their rudi- (see the Aug./Sept. issue for more on mentary lives when dumped unceremoni- Max). It also ups the hardware ante ously into water—minuscule aqueous some: whereas a minimum of 32MB bugs with less personality than a dande- RAM is required for Max, 64MB or lion puff, about as much fun to watch as more is recommended for running Char- the bubbles in a glass of soda. acter Studio, though it will run on any I was put in mind of the Sea system capable of running Max. Most Studio Max. Monkeys again when reading the simi- Character Studio features are quite usable

52 GAME DEVELOPER • OCTOBER/NOVEMBER 1996 http://www.gdmag.com with only 32MB RAM, but given the they aren’t—no four-armed Martian war- complexity of character models, animation riors with Biped—and, of course, a biped playback is problematic when memory is can only be two-legged. Also, structure in short supply. parameters are not animatable, so your Character Studio consists of two biped can’t grow a tail mid-animation. major components, Biped and Physique, These limitations only apply to Biped. which fit themselves seamlessly in with Max’s “bones” feature can be used to con- the existing Max toolset and any other struct more freeform armatures. Bones can installed plug-ins. Biped provides a cus- even be linked to a biped to create addi- tomizable, animatable mannequin with tional limbs, but they will not share in built-in character dynamics. Physique Biped’s built-in character dynamics and allows the user to “skin” this biped (or must be carefully set up with their own other “bones” structure) and refine the way inverse kinematics (IK) parameters. this skin moves in tandem with the under- Biped’s character dynamics are a Animate with Biped, then add muscle and lying armature. All of which sounds great dream come true, and combined with the tendon action with Physique. but definitely raises more questions than it revolutionary ease-of-use of “footstep-dri- answers. So let’s take a good look at what ven” animation, they form Character Stu- Because the biped has a built-in sort of hoops the user has to jump through dio’s most immediately impressive feature. understanding of motion dynamics and to make a character do the same. Basically, the user specifies with the click gravity (user-definable, too), the resulting of a button whether the figure is to be movement is surprisingly tasty right out of Biped walking, running, or jumping, and lays out the can. Footsteps can be placed over With a drag of the mouse, Biped lets you the general course of a movement routine uneven ground—to which the biped create a two-legged mannequin. Click, by plotting out steps, like those dance-by- adapts by shifting its center of gravity to drag, and there it is on the screen, wait- the-numbers footprints. Steps can be plot- account for the changing terrain—or at ing to be put through its paces. The ted singly or with the Create Multiple different elevations, so the biped climbs a default is the standard human makeup, Footsteps feature, which lets you indicate stairway or leaps from ledge to ledge. but by typing in new creation parameters which foot goes first, the number of steps, Even this default movement genera- for the biped you can dictate much of its and length of stride. Once these footsteps tion is more satisfactory than much of the basic physiognomy: remove the arms, are activated, the biped walks, runs, or stiff, awkward 3D character animation make the neck or spine more flexible, add jumps along its path as indicated. we’ve all seen. Still, it is rather character- a tail of variable length and flexibility, change the number of fingers or toes, or add an extra joint to the legs. You can then use Max’s usual transformation tools to scale and rotate body parts to arrive at the desired configuration. Two nice Character Studio fea- tures—Symmetrical Tracks and Copy Posture—provide different shortcuts to body symmetry. Symmetrical Tracks allows you to adjust matched body parts (both thighs, for example) simultaneous- ly, while Copy Posture and its helpmate Paste Posture Opposite translate the selected configuration to the other side of the body. You’ll perform these transforms mostly to conform the biped to the dimensions and features of an existing character model, but you can create, modify, and animate a biped without attaching it to any other geometry. Character Studio enables artists to easily swap and splice movement routines for any Biped- Note that these modifications have controlled figure. Here, an alien modeled by Emile Degray of Viewpoint Datalabs dances a cha- their limitations: fingers always have three cha animated by Michael Girard of Unreal Pictures, with additional hand movements added by joints, while a tail can have no more than Robert Lurye of Rhythm & Hues. five segments and arms are either there or

http://www.gdmag.com GAME DEVELOPER • OCTOBER/NOVEMBER 1996 53 ARTIST’S VIEW

Click and drag to create a biped, a figure animation armature with built-in character dynamics. less and is not intended as a final solution, enough to whip its arms and corkscrew its but as a way to let the animator quickly trunk like Greg Louganis twisting off the block out the scene’s action before tweak- high board, but with a little more tweak- ing figure movement by hand. Toward ing, you can fake that pretty well, too, and this end, standard Max transforms can be the embedded IK helps a lot in this. used to manipulate the Biped throughout In combination with Max’s Track the footstep-driven routine, adding small View, which displays and allows for the details—a turn of the head, fidgeting editing of keyframes, a new Biped Play- hands, sashaying hips—or adding major back feature makes for very interactive actions to the existing gait—shooting a real-time motion editing. Biped Play- gun while running or swatting at a cloud back reduces the biped to a glorified of bees while jumping from a cliff. All stick figure and lets you watch the these actions invoke Biped’s built-in IK, motion smoothly regardless of RAM. which helps your hands-on tweaking While watching the looping playback, more readily achieve the desired effect. keys can be dragged in the Track View In addition to manipulating the to easily adjust pacing. body directly, you can manipulate foot- Once you’ve honed your movement steps to add character to a routine: you routine, you save it in a .BIP file. Any A simple cylinder is transformed into an can select and rotate footsteps in or out, .BIP file can be loaded for any Biped arm with Physique’s Cross Section editor, for example, so your character saunters figure, so you can build a repertoire of which deforms the cylinder and controls like a bow-legged cowboy or waddles like movement routines for any and all char- the bulging action of muscles. Veins pop at a duck. Or you can rotate a jumping acters. Footsteps and all associated the wrist and biceps flex. biped’s landing marks 180 degrees, and it movement keys can also be cut, copied, will automatically perform a half twist in and pasted to splice together different Biped can be linked piece by piece to a mid-air so it lands accordingly. It’s not a movement routines. Additional hands- trusty old segmented model for anima- perfect twist, mind you—or rather, it’s on tweaking is usually required to segue tion, but is most powerful and most too perfect, because Biped uses a “quater- smoothly from one routine to the next. promising when attached to a seamless, nion interpolation scheme” for rotational You turn this Biped animation unjointed model using the other half of motions, not a physics-based simulation from a neat conversation piece into a Character Studio, Physique. as it does for horizontal and vertical useful production tool by attaching the dynamics. The biped doesn’t know mannequin to a 3D character model. A Physique Physique associates an object mesh, rep- resenting the outer skin, with an under- lying armature—a Biped or bones struc- ture—which serves as a skeletal frame. Further, it provides a range of tools for controlling how the skin moves with the bones. In these functions, it is similar to an older 3D Studio plug-in with which the reader might be familiar: Animatek’s BonesPro, from Digimation. There are a lot of differences between the use of the two, however—a source of confusion for some BonesPro users picking up Char-

54 GAME DEVELOPER • OCTOBER/NOVEMBER 1996 http://www.gdmag.com acter Studio. Whether you’re familiar Physique, and attach to a biped for ani- where and how to assign the model’s ver- with BonesPro or not, working with mation. It’s a nice solution when you tices to the underlying armature. The Physique is a hands-on process, but it need an animated figure fast. default vertex assignment logic works offers the animator a great amount of Subsequent steps are made immea- well, but can’t be expected to fully match control in defining the movement char- surably easier if the model is positioned your expectations of how the model acteristics of skin and muscle. in a reference pose; typically standing should deform as it moves. Problem areas The Physique process starts with a erect, arms held out straight to the sides. on a biped are the pelvis and armpits. character model—Character Studio does This aids greatly when lining up the The next step then is to edit prob- a lot, but it does not obviate the need for biped or bones armature with the model. lem areas on the vertex level by reassign- a good model. Physique can use any ver- Once you’ve fitted model and skeleton ing links and changing the status of select tex-based mesh, patch, or shape. For together and saved the scene, you apply vertices from flexible to rigid so that, for quick humanoid figures, something I’ve the Physique modifier to the model, example, the character’s face does not found handy is Fractal Design’s Poser. which is then attached to the Biped. stretch and contract as the figure moves. Poser is primarily intended as a digital Care in dimensioning and positioning The biped is returned to its reference pose artist’s model: it lets you pose and the skeleton dictates its effectiveness during these operations. Once you’ve dimension a realistic three-dimensional during the animation. Thanks to Max’s made adjustments, you can run through human figure for static renderings, with Modifier Stack feature, though, changes the animation again to see how well your models of both sexes ranging from infant can later be made to the skeletal struc- vertex reassignments work. to superhero. More to the point, it also ture to correct problems. This is where you want plenty of lets you export the figure as a .DXF file, With a biped skinned with RAM to allow smooth playback of a which Max can then import. This gives Physique, you next load a .BIP file move- complex shaded model. If smooth play- you a quick and easy, mid-res (1,500 ment routine and see how well the char- back isn’t possible on your system, you polygons) 3D human model that you can acter performs. You’ll see some things you can step through the animation using the edit with Max’s tools, skin with don’t like as Physique makes its best guess timeline, but it is harder to spot the

http://www.gdmag.com GAME DEVELOPER • OCTOBER/NOVEMBER 1996 55 ARTIST’S VIEW

smaller, lingering problem areas this way. number of tools to control just how the You can get up and running with Max’s Optimize modifier can be used to skin and bones work together. Link Character Studio’s basics quite quickly, simplify object geometry while you are Parameters affect how vertices deform but a lot of experimentation is required to working, which can help speed playback, around joints: how the skin reacts to understand how best to make use of these but the lower detail of the optimized bending, twisting, and stretching move- advanced Physique features. With prac- model means that it may not deform as ments. Tendons provide links between tice, they can help you create a character accurately as the fully detailed mesh. The bones, so that lifting the arm, for exam- model whose body moves with uncanny real solution is to have a beefy enough ple, causes corresponding movement in verisimilitude in virtually any situation. machine to push all those polygons. the flesh of the side, chest, and back. Physique can even be used as a modeling Aligning the biped and correcting Bulges simulate muscle action by flex- tool to add details that don’t exist in the vertex assignments can be painstaking ing throughout a specified range of object geometry (see screenshots). work, and your first couple of attempts movement. are likely to be less than entirely success- Each feature is optional and can be ful. Nonetheless, if you’re familiar with employed to whatever level of detail you Character Studio the workings of Max, it really doesn’t require. You can simply make a charac- Character Studio take too many hours after first starting ter’s biceps bulge when the arm is bent, or Kinetix—Autodesk Inc. with the plug-in to arrive at a realistically you can build a complete web of muscular 111 McInnis Pkwy. animated, smooth-skinned model. But interactions. Myriad adjustable parame- San Rafael, Calif. 95903 don’t worry, you can spend many more ters provide finegrained control over the Tel: (800) 879-4233 Web: http://www.ktx.com/products/03chrstu/ hours using the rest of Physique’s fea- behavior of muscles and the interplay of Price: $995 tures to bring your character to an even flesh and bone—for example, you can System Requirements: 90 MHz Pentium PC, greater level of realism. cause a muscle bulge to flex evenly over Windows NT 3.51, 32MB RAM, 100MB swap Once the object geometry is linked the course of a movement or to snap sud- space, PCI or VLB graphics card, screen reso- to the armature, Physique provides a denly to full flex at a particular point. lution of 800x600x256 colors, CD-ROM drive.

56 GAME DEVELOPER • OCTOBER/NOVEMBER 1996 http://www.gdmag.com What a Character ious to get started with Character Studio the talent in the box for you, but they’ve Once the initial giddiness wears off, the who aren’t yet familiar with Max will removed many of the barriers that slow one thing almost every Character Studio want to check out 3D Studio Max Fun- your own talent’s migration to the screen user comes around to wishing for is that damentals, a helpful supplement to the or limit the sort of realism you feel you these terrific figure animation tools Max manuals and tutorials by Michael can strive for. included facial expression. Character Todd Peterson (New Riders, 1996), Character Studio is a serious tool Studio Product Manager Phillip Miller which also includes some useful infor- that begs to be played with like a toy. If hints that a facial deformation plug-in mation for those migrating to Windows you don’t have any figure animation pro- and a quadruped animation plug-in are NT for the first time. For that matter, jects you need to work on, you’ll wind up in the works—though no details or pro- anyone using or contemplating the making something up just for fun, like jected release dates are forthcoming. In switch to Max may also want to consider the animation I’m doing of the Sea- the meantime, Max’s own patch model- another Peterson book entitled Windows Monkey king. Now, how do I get him to ing capabilities can be used to create nice NT for Graphics Professionals (New Rid- smile that Sea-Monkey smile? ■ facial animations, and early Character ers, 1996); it’s a handy guide to the OS Studio adopters are experimenting with and the machines that run it, targeted to Sea-Monkey Worship Page bones and tendons to animate a face. our particular needs. users.uniserve.com/~sbarclay/seamonk.htm As usual, the documentation from I have been sufficiently impressed to New Riders Publishing Kinetix provides a great introduction to recommend Max as a powerful and usable www.mcp.com/newriders the software’s basics. I’d like to see the 3D animation tool, but Character Studio Fractal Design coverage go further insofar as some of redefines it as a must-have application for www.fractal.com the more advanced capabilities of the serious computer animator. You can’t Physique, but the Character Studio beat these character animation capabilities David Sieks is a contributing editor to manual is more than sufficient to get on the PC platform, and perhaps not on Game Developer. You can contact him via Max users up and running. Users anx- any platform. Kinetix still hasn’t packaged e-mail at [email protected].

http://www.gdmag.com GAME DEVELOPER • OCTOBER/NOVEMBER 1996 57