Upcoming Events
Unite 2010
11/10 - 11/12 @ Montréal, Canada

GDC China
12/5 - 12/7 @ Shanghai, China

Asia Game Show 2010
12/24 - 12/27  

GDC 2011
2/28 - 3/4 @ San Francisco, CA

More events...
Quick Stats
70 people currently visiting GDNet.
2406 articles in the reference section.

Help us fight cancer!
Join SETI Team GDNet!
Link to us Events 4 Gamers
Intel sponsors gamedev.net search:

Contents
 Introduction
 Character Image
 Files

 Checking for
 Movement

 Collision Detection
 Animation
 NPCs and Random
 Movement

 Ordering Characters

 Printable version
 Discuss this article
 in the forums



The Series
 Beginning Windows
 Programming

 Using Resources
 in Win32 Programs

 Tracking Your
 Window/Using GDI

 Introduction
 to DirectX

 Palettes and Pixels
 in DirectDraw

 Bitmapped Graphics
 in DirectDraw

 Developing the
 Game Structure

 Basic Tile Engines
 Adding Characters
 Tips and Tricks

Character Image Files

To move characters around, I usually suggest a minimum of 12 frames. There are four cardinal directions, and in each direction, there should be one frame of the character standing still (facing that direction), one of him in mid-stride with left foot forward, and one with the right foot forward. That's what I'm using in Terran, and in each character image file, the frames are arranged in a vertical line like you see below. Notice that the leftmost character (frame #0) is facing south, frame #3 faces north, frame #6 faces east, and frame #9 faces west. Now do you see why I assigned the FACE_ constants the values that I did? To find out which frame to use for a character standing still, you just use the move.nFace variable. To get the frame with his right foot forward, you use move.nFace +1. And to get the frame with his left foot forward, you just use move.nFace +2. Convenient, hey? :)

Character Image File

This character, by the way, is one of my current main character graphics from Terran. It'll probably change before the final game comes out. But my point in bringing this up is that all the graphics included for the demo that come with this article are pulled directly from my game; they are there for you to experiment with until you can come up with your own stuff, but when you do end up making a game and distributing it, please don't use my art, since it may appear in Terran as well. I know there's someone out there saying, "But Blayde, your art is so terrible, why would anyone want to steal it?" Well... you're probably right, but still, I thought I'd mention it.

Anyway, matters of copyright aside, this is a convenient way to set up your image files and I recommend you use it, or something like it. Vertical lines work just as well as horizontal ones do; it's just a matter of preference. For my game and for our demo, each character fits inside a 32x64 box, so each character image should be 384x64, and you can easily locate a RECT containing the correct frame by doing this:

RECT rcChar = {0, nFrame << 5, 64, (nFrame << 5) + 32};

The nFrame variable, in this case, is simply the number of the frame you're looking for. We'll do something like this when we get to actually blitting the characters onto the screen. Notice, though, that I have the y-values permanently set to 0 and 64. This only works if you have a separate surface for each character. Generally I don't like to do that; I have one large surface with all my characters on it. So then you'll need some way of computing the y-values. Usually I do this by including a value in the NPC or player character structure that says which "slot" on the surface that character's image is loaded into.

Handling the Camera

Remember back in article #8 when we set up the camera to define what part of the map was being drawn in each frame? Well, now we have to change it just a little. Last time, we set the camera so that it shifted in the appopriate direction anytime the user pressed the arrow keys. But in an actual game, chances are that you're not controlling the camera directly with the arrow keys; rather, you are controlling the character, and the camera follows the character.

The simple method we used in that demo would be fine if the character was always going to be centered on the screen, but generally that is not the case. What happens when the character approaches the very edge of a map? If we centered the camera on him, then there would be an area of the screen with nothing displayed on it, and we don't want that. I'm sure you know what I mean; you've probably played a game that has the character centered on the screen, except when he gets near the edge of a map, at which point the camera remains still and the character moves towards the edge of the screen as well. That way, the whole screen is always occupied by the current map.

So how do we implement this? Actually, it's quite easy. Instead of changing the camera every time the arrow keys are pressed, we'll calculate the camera coordinates during every frame, based on where the character is positioned in the world. Since our screen is 640 pixels wide and our character is 32 pixels wide, we can center the camera horizontally by locating the camera (640 - 32) / 2 = 304 pixels to the left of the character. Similarly, the screen is 480 pixels tall and our character is 64 pixels tall, so the camera should be placed (480 - 64) / 2 = 208 pixels above the character to center it vertically. Then to make sure the camera stops when the character gets near the edge of the screen, all we have to do is make sure the camera's coordinates don't drop below (0, 0), or go above the maximum allowable camera coordinates as defined in the MAPDATA structure we created in article #8. It's that easy! So we can get the camera to follow our character with this simple code:

// center camera on main character
mapdata.xCamera = (player.move.xTile<<5) + player.move.xOffset - 304;
mapdata.yCamera = (player.move.yTile<<5) + player.move.yOffset - 240;

// clip camera to map boundaries
if (mapdata.xCamera < 0)
    mapdata.xCamera = 0;
if (mapdata.yCamera < 0)
    mapdata.yCamera = 0;
if (mapdata.xCamera > mapdata.xMaxCamera)
    mapdata.xCamera = mapdata.xMaxCamera;
if (mapdata.yCamera > mapdata.yMaxCamera)
    mapdata.yCamera = mapdata.yMaxCamera;

It's worth mentioning here that this code should probably be included somewhere other than the map rendering function, because you may not always want to use it. For instance, in game story scenes, you'll almost certainly want to control the camera using a script instead of simply setting it to follow the character. If you think back to the logic diagram I showed you for Terran in article #7, this camera-control code is only used while the World Map game state is active. Story scenes, on the other hand, occur under the Scripts Only state, and so whatever scripts happen to be running at the time can do what they like with the camera.





Next : Checking for Movement