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

Checking For Movement

Now we have everything we need in terms of organization and setup, and we're ready to create some sort of mechanism for controlling the character. Since we haven't covered DirectInput and creating a universal input system from multiple devices (such as keyboard and gamepad), we'll just use the Win32 API function GetAsyncKeyState(), which we met back in article #3. As you may recall, we wrapped the function in a macro which masks out the bit we're interested in. Here's the macro again, to refresh your memory:

#define KEYSTATE(n) ((GetAsyncKeyState(n) & 0x8000) ? TRUE: FALSE)

Now what we need is for the character to start moving in the specified direction as soon as an arrow key is pressed. How do we do that? Well, thinking back to the CHARMOVE structure we just set up, there were two member variables called xMove and yMove. For now, all we'll do is set those to their correct values based on the key being pressed, and we'll see how to handle the data when we write the actual animation code in a bit. So, all we do is check each arrow key. If it's being pressed, and the character is not already moving, then we set xMove or yMove appropriately. The other thing we need to do is to adjust xTile and xOffset, or yTile and yOffset, to reflect the character's new location. We don't want the character's position to change suddenly, so when we increase a tile setting by 1, we decrease the corresponding offset by 32 (our tile size). In this way, the character's position remains constant, but represented in a different way, so that the animation code knows to do something with it. Finally, we update nFace so the character turns to face the right direction. In this code, and for the rest of the article, I'll assume we have a PLAYER structure set up called player.

if (KEYSTATE(VK_UP) && (player.move.xMove == 0) && 
                       (player.move.yMove == 0))
{
  player.move.yMove = -1;
  player.move.yTile--;
  player.move.yOffset += 32;
  player.move.nFace = FACE_NORTH;
}
if (KEYSTATE(VK_DOWN) && (player.move.xMove == 0) && 
                         (player.move.yMove == 0))
{
  player.move.yMove = 1;
  player.move.yTile++;
  player.move.yOffset -= 32;
  player.move.nFace = FACE_SOUTH;
}
if (KEYSTATE(VK_LEFT) && (player.move.xMove == 0) && 
                         (player.move.yMove == 0))
{
  player.move.xMove = -1;
  player.move.xTile--;
  player.move.xOffset += 32;
  player.move.nFace = FACE_WEST;
}
if (KEYSTATE(VK_RIGHT) && (player.move.xMove == 0) && 
                          (player.move.yMove == 0))
{
  player.move.xMove = 1;
  player.move.xTile++;
  player.move.xOffset -= 32;
  player.move.nFace = FACE_EAST;
}

That's not so bad, right? Just a few simple lines. Consider this for a minute: what would happen if we didn't check whether or not the player was already moving? And what would happen if, when the player pressed up or down, we only checked vertical movement, not horizontal, before assigning a value to yMove (and similarly for when right or left was pressed)?

The answer to the first question is that keystrokes would build up in a sort of buffered fashion... if your game runs at 30 FPS, and the player were to hold down the up key for one second, the player would move 30 spaces to the north. That's obviously not what we want!

The answer to the second question is something more useful: it would yield eight-directional movement instead of our four-directional system. However, it would allow the character to start moving vertically in the middle of moving horizontally, which means the end destination would not be centered on a tile. This means we'd have a pixel-by-pixel scrolling game instead of pixel-by-tile, which is a bit harder to handle; I'll explain the difference once we come to animation.

Before we get any character animations onscreen, there's one more thing we have to consider. Our movement code as it stands right now will work, but it will let the character go anywhere, even off the edge of the map! And what's the point of having a map if the character can just walk through everything? What we need is a function that performs a series of checks on the intended destination, and tell us whether or not it's allowable to move there.





Next : Collision Detection