Read Foundation Game Design with ActionScript 3.0, Second Edition Online
Authors: Rex van der Spuy
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
[SWF(width="550", height="400",
backgroundColor="#FFFFFF", frameRate="60")]
public class Jumping extends Sprite
{
private var _character:Character = new Character();;
public function Jumping()
{
//Add the character to the stage
stage.addChild(_character);
_character.x = 250;
_character.y = 175;
//Add the event listeners
stage.addEventListener
(KeyboardEvent.KEY_DOWN, keyDownHandler);
stage.addEventListener
(KeyboardEvent.KEY_UP, keyUpHandler);
stage.addEventListener
(Event.ENTER_FRAME, enterFrameHandler);
}
public function keyDownHandler(event:KeyboardEvent):void
{
if (event.keyCode == Keyboard.LEFT)
{
_character.accelerationX = -0.2;
}
else if (event.keyCode == Keyboard.RIGHT)
{
_character.accelerationX = 0.2;
}
else if (event.keyCode == Keyboard.UP
|| event.keyCode == Keyboard.SPACE)
{
if(_character.isOnGround)
{
_character.vy += _character.jumpForce;
_character.isOnGround = false;
}
}
}
public function keyUpHandler(event:KeyboardEvent):void
{
if (event.keyCode == Keyboard.LEFT
|| event.keyCode == Keyboard.RIGHT)
{
_character.accelerationX = 0;
}
}
public function enterFrameHandler(event:Event):void
{
//Apply acceleration
_character.vx += _character.accelerationX;
//Apply friction
_character.vx *= _character.friction;
//Apply gravity
_character.vy += _character.gravity;
//Limit the speed, except when the character
//is moving upwards
if (_character.vx > _character.speedLimit)
{
_character.vx = _character.speedLimit;
}
if (_character.vx < -_character.speedLimit)
{
_character.vx = -_character.speedLimit;
}
if (_character.vy > _character.speedLimit * 2)
{
_character.vy = _character.speedLimit * 2;
}
//Force the velocity to zero
//after it falls below 0.1
if (Math.abs(_character.vx) < 0.1)
{
_character.vx = 0;
}
if (Math.abs(_character.vy) < 0.1)
{
_character.vy = 0;
}
//Move the character
_character.x += _character.vx;
_character.y += _character.vy;
//Check stage boundaries
if (_character.x < 0)
{
_character.vx = 0;
_character.x = 0;
}
if (_character.y < 0)
{
_character.vy = 0;
_character.y = 0;
}
if (_character.x + _character.width > stage.stageWidth)
{
_character.vx = 0;
_character.x = stage.stageWidth - _character.width;
}
if (_character.y + _character.height > stage.stageHeight)
{
_character.vy = 0;
_character.y = stage.stageHeight - _character.height;
_character.isOnGround = true;
}
}
}
}
You now have a nice, bouncing, jumping game character. Wouldn't it be great to add a sound effect each time it jumps? Playing sounds in game is not difficult at all, and I'll show you how in this section.
Open the PlayingSounds project folder in the chapter's source file. Along with the usual folders, you'll find a new folder called sounds. It contains an MP3 file called bounce.mp3 (
Figure 9-8
). This MP3 file is going to be embedded into the application class in exactly the same way you've been embedding images.
Figure 9-8.
Keep your game sounds in a sounds folder with the rest of the project files.
Run the SWF file and press the space key. You'll hear a “bounce” sound, typical of the kind made by jumping game characters
Here's the entirePlayingSounds
class. I've highlighted all the code that embeds the sound, creates the sound objects, and plays the sound.
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
//Classes needed to play sounds
import flash.media.Sound;
import flash.media.SoundChannel;
[SWF(width="550", height="400",
backgroundColor="#FFFFFF", frameRate="60")]
public class PlayingSounds extends Sprite
{
//Embed the sound
[Embed(source="../sounds/bounce.mp3")]
private var Bounce:Class;
//Create the Sound and Sound channel
//objects for the sound
private var _bounce:Sound = new Bounce();
private var _bounceChannel:SoundChannel = new SoundChannel();
public function PlayingSounds()
{
stage.addEventListener
(KeyboardEvent.KEY_DOWN, keyDownHandler);
}
public function keyDownHandler(event:KeyboardEvent):void
{
if (event.keyCode == Keyboard.SPACE)
{
//Tell the bounce sound channel
//to play the bounce sound
_bounceChannel = _bounce.play();
}
}
}
}
To use sounds in a game, you need to import two classes:Sound
andSoundChannel
.
import flash.media.Sound;
import flash.media.SoundChannel;
You then embed the MP3 file in the class definition in exactly the same way that you embed an image.
[Embed(source="../sounds/bounce.mp3")]
private var Bounce:Class;
You then need to create two objects to help you play the sound.
private var _bounce:Sound = new Bounce();
private var _bounceChannel:SoundChannel = new SoundChannel();
You need to use both objects together to play sounds. You can think of theSound
class as a CD and aSoundChannel
as the CD player that actually loads and plays it.
TheSoundChannel
object can then play theSound
whenever it's called on to do so. In this case, it happens when you press the space key.
_bounceChannel = _bounce.play();
And that's really all there is to it. Keep this format in mind and you can't go wrong.
To see how to integrate sound effects into the context of a real game, open the JumpingWithSounds projects folder. Run the SWF, turn up the sound on your computer, and you'll now hear a bounce sound each time the character jumps. This is accomplished by playing the bounce sound each time the player presses the up or space key, which happens by running this directive:
_bounceChannel = _bounce.play();
There's a sounds folder in the project folder that contains the bounce.mp3 file. Here's the new code in theJumpingWithSounds
application class that embeds and plays the sound. First, theSound
andSoundChannel
classes are imported along with all the other classes needed in this example.
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
//Classes needed to play sounds
import flash.media.Sound;
import flash.media.SoundChannel;
Next, the MP3 file is embedded and the sound objects are created in the class definition.
public class JumpingWithSound extends Sprite
{
//Embed the sound
[Embed(source="../sounds/bounce.mp3")]
private var Bounce:Class;
//Create the Sound and Sound channel
//objects for the sound
private var _bounce:Sound = new Bounce();
private var _bounceChannel:SoundChannel = new SoundChannel();
private var _character:Character = new Character();
Finally, the sound is played by thekeyDownHandler
when the player presses the up or space keys.
else if (event.keyCode == Keyboard.UP
|| event.keyCode == Keyboard.SPACE)
{
if(_character.isOnGround)
{
_bounceChannel = _bounce.play();
_character.vy += _character.jumpForce;
_character.isOnGround = false;
}
}
Adding sound effects to games like this is just a matter of choosing the right place to call the sound'splay
method. Most of your game sound effects will be short like this, but if you ever need to stop any of them, call the sound object'sstop
method, like this:
_bounceChannel = _bounce.
stop();
If you're using longer sounds that you need to loop, the next section will show you how to do this.
You'll likely have music in your games that you'll need to loop over and over again during the course of the game. And you might also need to control the volume levels of sounds and balance sounds between the left and right speakers. The next sections cover some simple techniques to help you do this.
Here's the format you need to use to loop a sound when you play it:
_soundChannel = _sound.play(startPosition, timesToPlay);
ThestartPosition
is a number in milliseconds. Note that 0 is the very start of the sound and 1000 would be one second into the start of the sound.timesToPlay
is the number of times you want a sound to play. So if you want to start a sound from the beginning and repeat it ten times, your code could look like this:
_soundChannel = _sound.play(0, 10);
If you want sound to repeat from the 5 second mark very time it repeats, use 5000 as the first argument:
_soundChannel = _sound.play(5000, 10);
To make a sound repeat infinitely (or almost infinitely) you need to use a little trick. Set the second argument, the times to loop, to the maximum possible number that AS3.0 knows. That's actually stored as a property of the integer class that you can access like this:
int.MAX_VALUE
int.MAX_VALUE
is the highest possible value that an integer can be: 2,147,483,647. It means the sound won't loop forever, but it will loop long enough for the player to finish the game—and possibly even continue to loop a few decades well beyond that. Here's how you can use it to make a sound loop “forever”:
_soundChannel = _sound.play(0, int.MAX_VALUE);
If you loop continuous sounds that don't have a discernible start or end, you might hear a moment of silence before the sound plays again. This is because some MP3 formats store the ID3 tag information (the name of the song, name of the artist, and so on) at the beginning or end of the file. That's the silence you hear. If this proves to be a problem, make sure that you export the MP3 file from your audio software without the ID3 information. Most sound editors have this as an option. If you don't have access to the original uncompressed sound file, use a dedicated audio editor, like Audacity, to trim the few milliseconds of silence from the beginning or end of the file. You can download Audacity from
http://audacity.sourceforge.net/download/
You'll also need to download and install the LAME MP3 encoder so that Audacity can export the finished MP3 file. You can find a link to the LAME download site at
http://audacity.sourceforge.net/help/faq?s=install&item=lame-mp3
You can also sometimes get around the few milliseconds delay between loops by starting the sound at a start position other than zero. You'll need to experiment a bit to find the right amount, but 30 is often a good place to start.
_soundChannel = _sound.play(30, int.MAX_VALUE);
This will skip the first 30 milliseconds, which is roughly where the sound gap ends.
On occasions where you need a bit more flexibility and control, you can create a loop using aSOUND_COMPLETE
event. First, add aSOUND_COMPLETE
event handler to theSoundChannel
object when you play the sound.