Position and Speed Variables

Dec 27, 2010

The impression of spatial continuity – that an object exists at some location, and stays there until it moves to an adjacent position – is not assumed by a computer. This seemingly natural behavior has to be described in code by the programmer.

Fortunately, there is a pattern for this.

It can seem obtuse the first time or two it’s seen – it did for me – though once used a few times its workings become clear.

Side Note Regarding Flash Programming

ActionScript 3 supports a variation of this, by drawing to BitmapData as the Everyone’s Platformer engine does. Otherwise, the Sprite and addChild system commonly used in AS3 (example) bypasses redraw details described in this article.

Overview

What follows assumes very little prior experience, so there’s plenty of text in an effort to be thorough. There are only a few points, though:

  1. Create number variables to store the position of the thing to be drawn.
  2. Use those variables as coordinates when drawing the image for that thing.
  3. Change those variables to move it.
  4. Create additional number variables – to treat as speed for horizontal and vertical movement – and add those to the position variables every frame.

Drawing at Coordinates

Independent of the programming language and library, there’s a function to draw a specified shape or image to the screen at some coordinate.

As mentioned in General Concepts for Beginning Developers, the screen is a 2D plane, often measured in pixels as distance horizontally and vertically from the top-left corner.

Typical draw functions range from plotting a single pixel, to drawing a circle or rectangle, to copying a loaded image file to the screen.

For example purposes, we’ll refer to the image drawing function in this form:

copyBitmapToPosition(10,15,goblin);

…to signify drawing the image pointed to by the variable named “goblin” with its top-left corner 10 pixels from the left side of the screen, and 15 pixels from the top of the screen. To be clear, that’s a fictional, pseudo-code notation – actual function name and order of values vary by programming language and graphics library.

Loading the Image

Before that example line could be used in code to draw a goblin, we would need to declare that there’s an image we’re referring to in code by the label “goblin”, as well as specifying which filename to load into that label. Example code:

Image goblin; // declares 'goblin' a label for an Image

...skipping unrelated code...

goblin = load_png("monster.png"); // loads this image into 'goblin'

(The writing after the // marks implies comments, meaning that text is ignored by the compiler when code is translated into an application. For more information on comments, see Game Programming Fundamentals.)

Clearing Every Frame

Computer games update the screen dozens of times every second.

The first thing to do with every update is to clear the screen, giving backdrop to the object(s) and concealing the previous draw. The two easiest ways to do this (either works, no need to do both):

  1. Draw a filled rectangle, at the top-left corner of the screen, the same dimensions as the screen. (“background color”)
  2. Draw an image, one with the same dimensions as the screen, lining up its top-left corner with the top-left of the screen. (“background image”)

An example of the latter, using our draw function, might look like this:

copyBitmapToPosition(0,0,sky);

That erases whatever the world looked like the previous frame – which is why we do it – but that also means we need to constantly redraw the image at its current position for it to show.

Drawing Every Frame

After the part that clears/resets the screen, we call the function that draws the image:

copyBitmapToPosition(10,15,goblin);

In Processing, that means we’d put the copyBitmapToPosition call in the draw() function, which gets called every frame. In C++ or AS3, the call would go in whichever function we’ve attached to a timer to be called 24-60 times per second, somewhere after the line that draws the background to clear the screen.

Keeping Track of Position

The problem with a call like this one:

copyBitmapToPosition(10,15,goblin);

…is that it always draws the goblin image at the same position on the screen. This is fine for drawing the background every frame to clear the image, but objects like goblins should be able to move.

To support that movement, we’ll create two number variables to store the goblin’s position along each axis:

int gob_x = 10, gob_y = 15; // happens only once in code

...skipping middle code...

copyBitmapToPosition(gob_x, gob_y, goblin); // called every frame

Note that the gob_x and gob_y variables are now used in the copyBitmapToPosition as the position to draw the image, rather than specific numbers. This way, when gob_x is changed, whether dramatically (gob_x = 450) or incrementally (gob_x = gob_x + 2), the position where gob_x is being drawn for future frames will be changed.

Changing the value in gob_y will likewise affect the vertical spot where the goblin image is being drawn.

Small changes – say, adding or subtracting a few every frame – creates the impression of movement. Larger changes, mid-gameplay, suggest teleportation, although setting values at the start of a level is unnoticeable without reference point, and the way to set initial positions.

Constant Movement

Just like the problem with this:

copyBitmapToPosition(10,15,goblin);

…was that the position was always the same (“hard coded”), the problem with this:

int gob_x=10, gob_y=15;

...later in the code...

gob_x = gob_x + 1; // increase by 1 pixel the horizontal position
copyBitmapToPosition(gob_x,gob_y,goblin);

…is that the speed is always the same (1 to the right every frame). Instead, we add another pair of variables, denoting the current horizontal and vertical speed:

int gob_x=10, gob_y=15;
int gob_x_moveAmount=0, gob_y_moveAmount=0;

...and later in the code...

if( keyPressed( RIGHT_ARROW) ) {
  gob_x_moveAmount = 1; // right movement
} else if( keyPressed( LEFT_ARROW) ) {
  gob_x_moveAmount = -1; // left movement
} else { // neither left nor right arrows pressed
  gob_x_moveAmount = 0; // stop moving horizontally
}

if( keyPressed( UP_ARROW) ) {
  gob_y_moveAmount = -1; // upward movement
} else if( keyPressed( DOWN_ARROW) ) {
  gob_y_moveAmount = 1; // downward movement
} else { // neither up nor down arrows pressed
  gob_y_moveAmount = 0; // stop moving vertically
}

// every frame, adjust the position by the current speed
gob_x = gob_x + gob_x_moveAmount;
gob_y = gob_y + gob_y_moveAmount;

copyBitmapToPosition(gob_x,gob_y,goblin);

By keeping horizontal and vertical movement stored separate from position, we can program and reason differently about movement vs position. For example we can now zero – or reverse – speed when the goblin bumps into something. We can adjust speed when the goblin stands on a conveyor belt, adjust speed based on wind vectors, fling the goblin backward from an explosive blast, etc. by modifying the variables for speed.

Smoother Movement

In the example above, even though the code is just pseudo-code (not actual wording for any particular language, just showing the pattern), the common ‘int’/integer type was used for position and speed. Although pixel positions are whole numbers (501, 502, 503…), decimal real values of the float/double/number variety work better for keeping track of position and speed values.

When the speed values are decimal, percentage falloff can be used to slowly decay speed:

float gob_x = 0.0;
float gob_x_moveAmount = 0.0;

...skip positions variables and keyboard code...

// instead of setting to 0.0 when neither left/right is held, decay:
gob_x_moveAmount = gob_x_moveAmount * 0.93; // lose 7%

gob_x += gob_x_moveAmount

With code like this, rather than instantly coming to a halt when no keys are pressed, the object will glide gracefully to a stop.

Code Organization

Classes can be used to better organize the data above. X/Y pairs are often contained in a Point or Vector class. Both vectors are often grouped into a larger class, along with the image used (goblin, in this case), plus the functions used to handle the character’s movement and updates on the screen.

That amount of structure isn’t necessary to get it working, but it’s useful to stay organized and minimize mental overhead while expanding the program to include multiple moving objects. If you’re new to programming, consider this a note which will make more sense in time.

Other Uses of Position Variables

Keeping the position stored in variables is also handy for comparing the character’s location to other values – screen edges, world edges, and most often, the position values used to track other objects. When the distance between the coordinates of one character and another is within some range, a function for handling collision between those characters can be called.

Staying on Screen, Other Details

For more information on position and speed variables, within a working example, refer to the ActionScript 3 – Motion Tutorial.



Learn and practice team game development with Gamkedo Club.
Membership worldwide. Professional support. Proven process.




Subscribe by e-mail to receive weekly updates with Gamkedo.Community interviews and YouTube training videos for game developers!



One Comment

Leave a comment

Comments Form
  • Your email will not be used for any purpose other than to update you in replies to your comments. Your website address will be shown as a link from your name with your comment. Your profile photo is auto-magically provided by Gravatar.

All contents Copyright ©2017 Chris DeLeon.

Site production by Ryan Burrell.