8bitrocket.com
27Sep/080

Tutorial: N-way tile-based blit fine scrolling in AS3 (part 2)

Tutorial: N-way tile-based blit fine scrolling in AS3 (part 2)

In this tutorial we will discuss the theory and practice behind 360 degree n-way blit fine scrolling in AS3. What does that mean? N-way scrolling is a means by which you can scroll the screen in any direction based on the angle the main character of the game is facing.  Part 2 covers adding the car to the screen and driving it around the world.

This is a long tutorial, so it has been split into 3 parts:
Part 1 explains the concepts of N-way blit scrolling
Part 2 (this) adds a car and and let you drive it around the screen
Part 3 demonstrates 4-way and 8-way techniques and provide some auxiliary methods and functions that i have used in creating these demos.

Now, how do we move our car?
Our car has also been modeled after the yellow Volkswagen bug from the Super Bug classic arcade game: it has an export name of car_png.

There are many ways to place a car object on the screen. In most cases, if I feel that I am going to have 100's of independent objects moving on the screen, I will go to the trouble of blitting EVERY object to ensure I can keep a constant frame rate. There is no need to do that with this demo, or even a finalized game based on this demo as there are very few moving objects. In this instance, why not use the built in Sprite class that AS3 provides? It will offer us built in rotation and the ability to attach Bitmap object directly to its display list. In any case, it is a speedy way to prototype this engine. If the game started to lag down the line, the car sprite could be swapped out for a blitted sprite.

In the init() function, I set up the car this way: note that I have not created an object to hold all of the car data. In a final game I would probably create a Car class that extended Sprite to do this. It is not needed in this example.

[cc lang="javascript" width="550"]
//car
carPNG=new car_png(31,21)
carSprite=new Sprite();
carBitmap=new Bitmap(carPNG);
carBitmap.x=-15.5;
carBitmap.y=-10.5;
carSprite.addChild(carBitmap);
carSprite.x=110;
carSprite.y=145;
carRotation=-90;
carTurnSpeed=.5;
carMaxSpeed=5;
carAcceleration=.02;
carDeceleration=.03; addChild(carSprite); addChild(carSprite); [/cc]
[/cc]
The car surface is basically a just a 31x21 png that represents the car pointing to the right. We do that because that angle corresponds to the 0 angle that Flash uses for Display Objects. We need to store the car image in a Bitmap object and place it so its center is at .5* width x and .5* height y (-15.5x, -10.5y). We then attach it to the Sprite's display list and place the carSprite roughly in the center of out 240x320 output window (110x,145y).

We set carRotation to -90 to have it start pointing up the screen. The carTurnSpeed is how much to rotate the car in the left or right direction when the arrows keys are hit by the user. We set a max of 5 on our carSpeed. The carSpeed will be increased by our carAcceleration every time the up arrow is pressed and by the carDeceleration when the down arrow is pressed.

Finally, we add out carSprite to the main displayList. (this has to happen AFTER the canvasBD has been added).

Checking key presses
On every frame tick, we will need to check to see which of the arrow keys are still being held down by the user (if any).

In out init() we will need to add these event listeners:
[cc lang="javascript" width="550"]
//key listeners
stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDownListener);
stage.addEventListener(KeyboardEvent.KEY_UP,keyUpListener);
[/cc]

We also need to add in these event methods to correspond to the events:

[cc lang="javascript" width="550"]
private function keyDownListener(e:KeyboardEvent) {

//trace("down e.keyCode=" + e.keyCode);

aKeyPress[e.keyCode]=true;

}

private function keyUpListener(e:KeyboardEvent) {

//trace("up e.keyCode=" + e.keyCode);

aKeyPress[e.keyCode]=false;

}
[/cc]
In our main loop, we will have to call a checkKeys() method every frame tick:
[cc lang="javascript" width="550"]
if (aKeyPress[38]){
trace("up pressed");
carSpeed+=carAcceleration;
if (carSpeed >carMaxSpeed) carSpeed=carMaxSpeed;

}
if (aKeyPress[40]){
trace("down pressed");
carSpeed-=carDeceleration;
if (carSpeed <-carMaxSpeed) carSpeed=-carMaxSpeed;

}
if (aKeyPress[37]){
trace("left pressed");

carRotation-=(carSpeed+.1)*carTurnSpeed;

}
if (aKeyPress[39]){
trace("right pressed");

carRotation+=(carSpeed+.1)*carTurnSpeed;

}

[/cc]

If the up key is pressed we add the carAcceleration to the carSpeed and make sure it doesn't go over our carMaxSpeed. We do the same with the deceleration and 0, For the left and right keys, we update the carRotation value by the carTurnSpeed, but also add in the current speed of the car (plus a little extra). This, according to Gary Rosenzweig will help keep the game from being too frustrating. I used Gary's car physics model because his theory and my theory on car movement are very close, but his is more fun in actual game play. I would usually think that the car would not be able to turn unless the speed is greater than 0, but both Gary, and the original Super Bug programmers seem to think it is ok, and maybe even makes the game less frustrating to play.

The last method we need is the updatePlayer() method. This one is called every frame tick and is used to keep the background moving and the player rotated in the right direction. It also checks for collisions with the bounds of the world.
[cc lang="javascript" width="550"]
carSprite.rotation=carRotation;
var carRadians:Number=(carRotation/360)*(2.0*Math.PI);
carDX=Math.cos(carRadians)*carSpeed;
carDY=Math.sin(carRadians)*carSpeed;

viewXOffset+=carDX;
viewYOffset+=carDY;

if (viewXOffset <0) {
viewXOffset=0;
}else if (viewXOffset > (worldWidth-viewWidth)-1) {
viewXOffset = (worldWidth - viewWidth)-1;
trace("hit end of world width");
}

if (viewYOffset <0) {
viewYOffset=0;
}else if (viewYOffset > (worldHeight-viewHeight)-1) {
viewYOffset = (worldHeight-viewHeight)-1;
trace("hit end of world height");
}

[/cc]
This code is used to find the new dx (a vector value that describes the direction and speed of the movement of the car in the x direction) and the dy value (a vector for the y direction). The carDX and carDYmust be turned into radians from the angle provided by the carRotation value. The viewXOffset, and viewYOffset of our widow copyPixels from our buffer are set to these carDX and carDY values.

The rest of the code keeps the window from trying to scroll passed out last tile on the x any y directions, and also keeps us from trying go passed the first tile in each direction. I have no code in here to let the carSprite move from the middle to the edge of the game world once max widow size has been reached.

Here is the example of this type of n-way scrolling working. Use the up and down to accelerate and decelerate. Use the left and right to steer.

Go on to Part 3

If you enjoyed this post, please consider leaving a comment or subscribing to the RSS feed to have future articles delivered to your feed reader.
Filed under: Tutorials Leave a comment
Comments (0) Trackbacks (0)

No comments yet.


Leave a comment

No trackbacks yet.

This site is protected by Comment SPAM Wiper.