Advanced Sprite Programming: Alpha Channel Transparency and Angular Motion This chapter covers two advanced topics in sprite programming that will give your games a serious edge over the competition. First, you’ll learn how to create sprite images that use an alpha channel instead of a color key for transparency. This advanced technique produces much higher quality sprites than a color keyed sprite (which uses a specific color for pixel-level transparency). Next, you’ll learn an advanced technique to move a sprite using angular motion. This type of sprite control produces a realistic simulation of momentum which looks great in a space-based game. To demonstrate how these two advanced topics work, this chapter provides a hands-on tutorial and an example game. Specifically, in this chapter you’ll learn about n Alpha channel transparency n Angular motion Alpha Channel Transparency In the previous chapters on sprite programming, you learned a technique for drawing transparent sprites using a color key. The color key of an image is a specific color that is defined as the transparent color, so that when the image is drawn, you can see through the transparent pixels in the image and the back- ground will show. This is a reasonable way to draw transparent sprites, but it has 385 chapter 16
28
Embed
Advanced Sprite Programming: Alpha Channel Transparency ... · PDF fileAdvanced Sprite Programming: Alpha Channel Transparency and Angular Motion This chapter covers two advanced topics
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
This chapter covers two advanced topics in sprite programming that will give
your games a serious edge over the competition. First, you’ll learn how to create
sprite images that use an alpha channel instead of a color key for transparency.
This advanced technique produces much higher quality sprites than a color
keyed sprite (which uses a specific color for pixel-level transparency). Next, you’ll
learn an advanced technique to move a sprite using angular motion. This type of
sprite control produces a realistic simulation of momentum which looks great in
a space-based game. To demonstrate how these two advanced topics work, this
chapter provides a hands-on tutorial and an example game. Specifically, in this
chapter you’ll learn about
n Alpha channel transparency
n Angular motion
Alpha Channel TransparencyIn the previous chapters on sprite programming, you learned a technique for
drawing transparent sprites using a color key. The color key of an image is a
specific color that is defined as the transparent color, so that when the image is
drawn, you can see through the transparent pixels in the image and the back-
ground will show. This is a reasonable way to draw transparent sprites, but it has
385
chapter 16
some disadvantages. For one thing, you have to know the color key of a sprite,
and unless you use the set image colorkey command for any images that have a
different transparent color, some of your sprites won’t render transparently.
(This problem is lessened if you choose a standard color key.)
Comparing Color Key and Alpha Channel Transparency
Figure 16.1 shows a sprite loaded up in Paint Shop Pro with a white color key.
No t e
The spaceship sprite featured in this chapter was drawn by artist Levi Bath (http://www.levibath.com). The alien UFO ship featured later on, as well as the background and bullet images,were drawn by Reiner Prokein (http://www.reinerstileset.de).
You can use any color for the color key of an image, such as the white color key in
the previous figure, although this is an unusual color. Most color keys are either
black (0,0,0) or magenta (255,0,255), which looks more like pink to me. For the
386 Chapter 16 n Advanced Sprite Programming
Figure 16.1This sprite image has no alpha channel, but rather uses a color key.
white color in the previous figure, you could use set image colorkey 255,255,255
to set white as the transparent color.
Now let’s take a look at an image that uses an alpha channel instead of a color key.
Figure 16.2 shows the same spaceship image in Paint Shop Pro that now has an
alpha channel. You can tell that an alpha channel is in use in graphic editors
(such as Paint Shop Pro and Photoshop) because the background will show a
checkerboard pattern. This pattern shows you exactly what the image will look
like when drawn over a background in a game.
Alpha channel transparency is a more advanced way to draw an image with
transparency. The alpha channel refers to a color channel in a 32-bit image that
represents a mask that filters out a portion of the image. An alpha channel can
cause an image to blend with the background (making it partially see-through),
or it can render certain pixels of the image with 100 percent transparency.
Alpha Channel Transparency 387
Figure 16.2This sprite does have an alpha channel.
Figure 16.3 shows the two versions of the sprite side by side so you can see the
difference at a glance.
Artists tend to prefer alpha channel transparency over color key because it is very
obvious how the image will look in the game. DarkBASIC supports 32-bit images
with an alpha channel in the PNG (Portable Network Graphics) file format. All
popular graphic editors support the PNG format, so it is easy to convert from
BMP to PNG.
Creating an Alpha Channel in an Image
Let’s look at the steps involved in creating an alpha channel. You can take an
existing image with a color keyed background color and add an alpha channel to
the image using most graphic editors. For the purpose of this tutorial, I will be
using Paint Shop Pro 8, though later versions have similar functionality.
388 Chapter 16 n Advanced Sprite Programming
Figure 16.3Two versions of the spaceship sprite, one with color key and the other with alpha channel transparency.
Let’s start with an animated sprite. Figure 16.4 shows an explosion sprite with 16
frames of animation that will work well for this tutorial. All modern graphic editors
come with a tool called Magic Wand. You can look for this tool on the toolbar of
your graphic editor, which is usually found with the other standard tools like Pen
and Flood Fill. Now, using the Magic Wand, click somewhere on the background of
the image, which in this example is any of the black portion of the image. The Magic
Wand tool will locate the edges of the animation frames as shown in Figure 16.5.
Next, you want to zoom in to the image and add any additional transparent
regions that are located inside the image, where the Magic Wand did not
penetrate. By using the Shift key and clicking these additional pixels, you can add
those regions to the existing selection, as you can see in Figure 16.6.
When you finally have the transparent regions all highlighted, the next step is to
invert the selection. This will cause the selection to shift from the transparent
Alpha Channel Transparency 389
Figure 16.4An alpha channel will be added to this animated explosion image.
region to the actual image that you want to show up. By doing this, you will be
able to erase the transparent portion from the image by creating a mask (or alpha
channel) layer. The Invert option in Paint Shop Pro 8 can be found in the
Selections menu as shown in Figure 16.7.
After the invert process is done, the resulting selection will look like that shown in
Figure 16.8. Note that now only the true portions of the sprite frames are selected,
and the background (or transparent) portion of the image is not selected. We will
create the alpha channel using this selection so that the background color key will
be removed from the image.
To create a mask layer, which will be the alpha channel, open the Layers menu
and choose New Mask Layer, and then Show Selection, as shown in Figure 16.9.
The new alpha channel will be added and the image will look like the one in
Figure 16.10. You can now see the checkerboard pattern behind the image, which
tells you that the alpha channel is working.
390 Chapter 16 n Advanced Sprite Programming
Figure 16.5Using the Magic Wand tool to highlight the color keyed background color.
Now for saving the new image. You can’t just save a 32-bit image with an alpha
channel back to a BMP file, because that format doesn’t support an alpha
channel. Instead, we need to save the file as a PNG. Open the file menu and
choose Save As, as shown in Figure 16.11. This will bring up the Save As dialog
box. Using the Save As Type drop-down list, look for the file type called Portable
Network Graphics (*.png), as shown in Figure 16.12. Type a name for the file and
then click Save.
Angular MotionAngular motion is an interesting technique for moving sprites in a realistic
manner on the screen. Traditional methods of sprite movement, where the
Angular Motion 391
Figure 16.6Adding additional selections with the Magic Wand tool by using the Shift key.
position of the sprite is updated based on a fixed velocity, tend to produce games
with a very limited and unrealistic level of gameplay. Typically, sprites that do not
use angular motion are limited to only eight directions of travel. Figure 16.13
shows an example of an airplane with this limitation.
Another example is the tank sprite shown in Figure 16.14, which also has eight
directions of travel, but it is oriented and numbered to give you a better idea of
how it will move in a game.
Fixed Angles of Travel
Not only are these sprites limited in their range of movements, but they require a
lot of hard-coded values to be inserted into the game, and each direction has an
associated X and Y velocity that is fixed. The result is a very jerky-looking game
with a very unrealistic sense of movement. In addition, firing a bullet or other
392 Chapter 16 n Advanced Sprite Programming
Figure 16.7Inverting the selections.
weapon, as is usually required in most games, requires that the bullets also
conform to this limited range of movement.
For instance, somewhere in your game loop is the code to update the sprite’s
position on the screen based on its velocity:
inc X, SpeedXinc Y, SpeedY
The SpeedX and SpeedY variables are set to specific values such as 1, 2, or more.
These represent the number of pixels that the sprite will move by in a single
iteration of the game loop. One solution to improve realism is to add a delay
value for both X and Y, so that a game sprite will move more realistically:
inc CounterX, 1if (CounterX > DelayX)
Angular Motion 393
Figure 16.8The selected portion of the image has been inverted.
CounterX = 0inc X, SpeedX
endif
The trick, then, is to fine-tune DelayX and SpeedX to values appropriate for the
object you are trying to animate in the game. Take the direction that is due east,
for example. As you can see in Figure 16.15, due east is 90 degrees from due
north. Thus, the velocity for X should be positive, while the velocity for Y should
be zero.
In a game that uses eight directions, each of the directions has an associated and
fixed velocity that causes the sprite to move in that general direction. You must
also have the eight different rotated images of the sprite, unless you plan to rotate
them using the rotate sprite command, in which case you only need the north-
facing sprite.
394 Chapter 16 n Advanced Sprite Programming
Figure 16.9Adding a new mask layer to the image based on the image selection.
Free Angles of Travel
Instead of limiting your game to just a handful of directions of travel, why
not give your game objects the ability to move in any direction around the full
360 degrees? Yes, this is possible, and can be applied to any sprite with just a little
bit of setup. I call this technique angular motion because the movement of a sprite
is based on the angle it must travel.
A far better solution is to calculate the SpeedX and SpeedY values instead of setting
them manually. What if SpeedX and SpeedY are floating-point instead of integer
based? By switching to a float or double, you can use values such as:
SpeedX = 2.3455SpeedY = 0.0023
These values might be small, even fractional, but keep in mind a game runs
upwards of 60 frames per second. When iterated through a loop many times in a
Angular Motion 395
Figure 16.10The new alpha channel has been added to the image.
second, a sprite with these types of values will move! The problem is figuring out
which fractional values to assign to SpeedX and SpeedY to account for many
directions of travel.
Programming Angular Motion
You could do that manually by playtesting to figure out which SpeedX and SpeedY
values result in proper motion at a given angle, but this is tedious and imprecise.
A better method is to calculate these values! Let me introduce you to two lovely
functions that can help.
function calcVelocityX(angle as float)‘calculate X velocity based on direction anglevalue# = sin(angle)
endfunction (value#)
396 Chapter 16 n Advanced Sprite Programming
Figure 16.11Opening the File menu to save the file as a PNG.
function calcVelocityY(angle#)‘calculate Y velocity based on direction anglevalue# = -cos(angle#)
endfunction value#
These two functions, calcVelocityX and calcVelocityY, make it possible to
assign a floating-point value to the velocity of a sprite. To calculate a partial-pixel
velocity for X, you calculate the sine of the angle. For the velocity of Y, you
calculate the cosine of an angle. We multiply the cosine value by �1 because sine
and cosine produce results that are based on the Cartesian coordinate system
Angular Motion 397
Figure 16.12Saving the image as a PNG.
Figure 16.13A sprite with only eight directions of movement is very limited.
(remember basic geometry?), and the vertical orientation is inverted from the
computer monitor. Then, instead of moving a sprite by a fixed 1 or 2 pixel per
frame rate of speed, the sprite is moving at partial-pixel rates. What you want to
do is choose a direction angle (as a double or float) and then call calcAngleMoveX
and calcAngleMoveY, pass the angle to these functions, and then you are given a
velocity value for X and Y.
This is quite different from the previous technique of forcing a sprite to move at a
specific angle, with only 45 degrees of precision. Using angular motion, your
sprite can move at 1 degree or 258 degrees or any other value from 0 to 359.
Figure 16.16 shows a screenshot of the game that you will learn to create to
demonstrate angular motion. Notice how the sprites are not only moving at
arbitrary angles, but they’re firing weapons along those trajectories as well!
Pay close attention to the values being printed at the top of the screen in this
figure. See the first value at the upper left labeled ‘‘Vel’’? These are the velocity X
and Y values, which are, respectively, 1.030 and 0.543 in this example. The ‘‘Face’’
and ‘‘Move’’ values represent the angles that the ship is facing, which is not the
398 Chapter 16 n Advanced Sprite Programming
Figure 16.14This tank sprite is also limited to eight directions of movement.
same as the move angle. The ship can move in one direction, and then rotate and
fire in a different direction without affecting the movement direction. This works
great for a space-based game that must follow Newtonian physics. Remember
Newton’s first law of motion? It states ‘‘Every object in a state of uniform motion
tends to remain in that state of motion unless an external force is applied to it.’’
Testing Angular Motion
I’ve written a simple demonstration program that will give you a good oppor-
tunity to play around with angular motion. This game is called Astro Gunner,
and it is little more than a game of target practice, since the alien ship does not
fire back. This program might be a good basis for an entire game if you add more
functionality to it, such as enemies that shoot back, some other objects like
asteroids, and possibly weapon upgrades, shields, and other features. At this
stage, the game was intended solely to demonstrate angular motion, and as such
Angular Motion 399
Figure 16.15Each of the eight directions of travel require a specific velocity for X and Y.
the code has been kept as lightweight and simple as possible. The alien UFO
sprite is shown in Figure 16.17.
Defining Constants Used by the Game
Let’s get started on the source code for the game, which I will explain in detail so
you will have a solid grasp of how the game works. First up we have the usual
constants used by the program. I like to use variables as constants so that the
game doesn’t have any image or sprite numbers used directly in the game’s
source code—which is very difficult to modify because you have to keep track of
all the sprite and image numbers. It’s far easier to use variables like SPR_SHIP
instead.
‘set screen to manual updatesync on
400 Chapter 16 n Advanced Sprite Programming
Figure 16.16This game features sprites that are moved using angular motion calculations.
sync rate 60hide mouse
‘define all sprite #’sglobal IMG_BG as integer = 1global SPR_SHIP as integer = 2global SPR_UFO as integer = 3global SPR_EXPLOSION as integer = 4global IMG_BULLET as integer = 20global SPR_BULLET as integer = 200
‘ship constantsglobal ROTATIONRATE as float = 2.0global ACCELERATION as float = 0.04global TOPSPEED as float = 2.0
Angular Motion 401
Figure 16.17The alien UFO spaceship is a 32-bit image with an alpha channel.
‘bullet constantsglobal FIRINGRATE as integer = 4 ‘per secondglobal BULLETSPEED as float = 5.0
Defining the Sprite Structure
You have seen a rudimentary version of this sprite structure (a custom data type)
in prior chapters, but now it has grown quite a bit and includes a lot of
new features. Most notably, there are two new properties called imagenum and
spritenum. These make it possible to assign a number to the sprite’s structure
variable for the image and sprite number, and then just use these properties any
time you need to draw the sprite. This significantly cleans up the code and makes
it possible to build a more complex game with many sprites.
‘define a custom sprite datatypetype mySPRITE
alive as bytex as floaty as floatvelx as floatvely as floatfaceangle as integermoveangle as integervelocity as floatanimframe as integeranimcount as integeranimdelay as integerimagenum as integerspritenum as integer
endtype
The Sprite Variables
After defining the sprite structure, which is called mySPRITE, next comes the sprite
variables used in the game. The only sprites this simple game needs are the player,
alien, and explosion, in addition to the bullets.
‘define the spritesglobal player as mySPRITEglobal NUMBULLETS as integer = 10dim bullets(10) as mySPRITEglobal ufo as mySPRITEglobal expl as mySPRITE
402 Chapter 16 n Advanced Sprite Programming
Getting the Game Rolling
Next up is some code that initializes the game and prepares it to run. Think of
this code as the pre-launch checklist before the Space Shuttle is fired off into
space.
‘framerate variablesglobal fps as integerglobal ticks as integerglobal start as integer = timer()
‘use manual timing for bulletsglobal firestart as integer = timer()
‘load the game graphicsloadGraphics()
‘make sure all drawing now goes to the screenset current bitmap 0
The Game Loop
Now we have come to the most important part of the program, the game loop.
This game loop uses the do . . . loop instead of repeat or while because in this
particular example, we don’t need any condition to exit out of the loop. The
game loop calls on numerous support functions to get things happening on the
screen, such as checkInput() and updateSprites().
do‘draw the backgroundpaste image IMG_BG, 0, 0‘move the player’s shipcheckInput()‘update all spritesupdateSprites()‘test for collisionstestCollisions()‘display status infoprintInfo()‘calculate frame rateticks = ticks þ 1