Flash Actionscript 3.0 Help! - Pseudo-3D Racing Game

Started by
1 comment, last by Patrick B 9 years, 10 months ago

Hello everyone, I do not post here often, but I am a game developer who does have questions.

I was recently hired to make a simple racing game in Flash Professional CS6.

The plan was to make a pseudo-3D track. I messed with some of the rotation tools etc, however I have not encountered any help on how to manipulate movie clips in 3D space. The picture below shows a doodle car and a 3D track with a cheap background (for now). with a green button as acceleration.

My question is, How can I manipulate the movie clip in 3D space?

I would also appreciate any help in telling me the exact math I would need to make the track stay level with the car, and to rotate differently when turning to make the illusion of a 3D environment. Thanks! (I am using an Accelerometer to detect turning of the car)

CarExample.PNG

Advertisement

I think for your game you could probably get away with Flash's built-in "postcard" 3D system. This is the approach I used for a game named FloorPig (look it up on Google Play store if you're interested). It's not true 3D in that it doesn't do any culling, etc., so you will be limited in what you can do, but it's also the path of least resistance and simple to implement.

To accomplish FloorPig's functionality, I first created the tile "floor" using XML coordinates to map individual tiles. In your case you can probably make the entire track one movieclip. To rotate it into perspective, simply adjust the rotateY property of the movieclip:

currentTrack.rotateY=30;

(you'll have to play with the value to get a satisfactory rotation)

Rotating the track to match the movement of the car is simply a matter of rotating around the Z axis:

currentTrack.rotateZ+=10; //Turn right by 10 degrees

currentTrack.rotateZ-=2; //Turn left by 2 degrees

Most likely you will want to add this to a keyboard or mouse event listener so the player can control the movement. Because the keyboard system introduces a delay between first/subsequent keystrokes, you will want to handle keystrokes more directly; something like this:

import flash.ui.Keyboard;
import flash.events.Event;
import flash.events.KeyboardEvent;
private var _currentKey:uint = 0;
private function frameLoop(eventObj:Event):void {
if (this._currentKey == 0 {
return;
}
if (this._currentKey == Keyboard.LEFT) {
currentTrack.rotationX -= 5;
} else if (this._currentKey == Keyboard.RIGHT) {
currentTrack.rotationX += 5;
}
}
private function keyDownHandler(eventObj:KeyboardEvent):void {
this._currentKey = eventObj.keyCode;
}
private function keyUpHandler(eventObj:KeyboardEvent):void {
this._currentKey = 0;
}
stage.addEventListener(Event.ENTER_FRAME, this.frameLoop);
stage.addEventListener(KeyboardEvent.KEY_DOWN, this.keyDownHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, this.keyUpHandler);

Note that the rotation values are arbitrary -- you can adjust these based on the turning ability of the car, track conditions, etc. In other words, use variables unlike me :)

Now that it's rotated, the track can be placed "beneath" the car using straightforward Flash display depths (setChildIndex, etc.) Create the track and then just center the car on top. Same for any other elements you want to be visible on top of the track.

Moving the car along the track requires you to simply adjust either the X or Y values of the track clip (probably Y but you'll have to test this out). For example:

private var _carSpeed:Number=0;
private function frameLoop(eventObj:Event):void {
if (this._carSpeed>0) {
currentTrack.y+=this._carSpeed;
}
if (this._currentKey == 0 {
return;
}
if (this._currentKey == Keyboard.LEFT) {
currentTrack.rotationX -= 5;
} else if (this._currentKey == Keyboard.RIGHT) {
currentTrack.rotationX += 5;
}
}

If you find that moving along the Y axis works well, you can introduce a little X axis motion for things like drifting or sliding (wet track, for example).

Finally, you'll want to implement some sort of collision detection. The following is far from the best approach but it worked well enough for FloorPig so it may work for you too. I created 3 (or was it 4?) invisible dots (just movieclips with alpha=0) that sit at the virtual "edges" of the character -- in your case, where the corners of the car should be at the chosen perspective. I adjusted these by hand -- no fancy math. On ever frame loop I check to see if the dots are on top of a tile or not by doing a hit test. For example:

private function frameLoop(eventObj:Event):void {
if (currentTrack.hitTestObject(edgePoint1) &&
currentTrack.hitTestObject(edgePoint2) &&
currentTrack.hitTestObject(edgePoint3) &&
currentTrack.hitTestObject(edgePoint4)) {
//Currently on track
} else {
//On ore more wheels is off track
}
if (this._currentKey == 0 {
return;
}
...
This, however, has one major problem - if your track includes both the road and non-road (grass, etc.) in one graphic, the car will always be "on the track" if it's over any part of the clip. To differentiate between different types of terrain, I'd recommend drawing or somehow separating the various elements within your track clip. For example, you could have one movieclip within "currentTrack" that's the road, something like currentTrack.road. Another internal clip would be the grass: currentTrack.grass -- and so on. With this detection in place, you can produce a basic version of what you're looking to do. For example:
private function frameLoop(eventObj:Event):void {
if (currentTrack.road.hitTestObject(edgePoint1) &&
currentTrack.road.hitTestObject(edgePoint2) &&
currentTrack.road.hitTestObject(edgePoint3) &&
currentTrack.road.hitTestObject(edgePoint4)) {
//Currently on track
}
if (currentTrack.grass.hitTestObject(edgePoint1) &&
currentTrack.grass.hitTestObject(edgePoint2) &&
currentTrack.grass.hitTestObject(edgePoint3) &&
currentTrack.grass.hitTestObject(edgePoint4)) {
//Currently on grass
}
...

Using a similar approach you can place additional objects on top of the track as well as additional "edge points" to detect collisions with them.

Since this isn't true 3D, you will most likely be pre-rendering the car (or maybe video capture?) Just be sure to decide on what angle your track will be at up front, otherwise your car will look odd in the context of the scene.

Good luck

I just realized that I missed the part about using the Accelerometer, but the concept will be exactly the same. Only difference is that you won't be using Keyboard or Mouse events to capture the user's intentions.

I also realized that I used a little more nesting to accomplish this effect...the track itself (with the pieces in it), should nested within one more parent clip to allow you to move the X/Y coordinates...

currentTrack.rotateY=30;

currentTrack.container.y+=10;

In the above example, currentTrack contains a "container" clip which itself contains the road, grass, etc. clips. When you rotate the parent, all children are also adjusted. However, adjusting the X/Y properties of the "container" will move the track around within the rotated parent, which is what we want.

This topic is closed to new replies.

Advertisement