Generative Background and Keyboard Mapping

posted by : CarBari Sunday, April 6, 2008

In celebration of our little vector contest I thought I would unofficially submit my own entry.

I made this animation using our Spring Time vector pack. It’s about 360Kbs, but once it’s loaded click Play to get it started, then you can press the Left or Right arrows to control the little bunny.

I’ll walk you through the process I went through to create this here game/animation.

My first step was to get the vector pack that I wanted to use. Then I imported it into Flash CS3.

Importing Dialogue Box

You can just go ahead and import everything. Then just delete anything you don’t need. I only unchecked a few groups and paths that I knew weren’t needed.

Once all the groups are imported to the stage you can go into them by double clicking on them and remove or edit them how you like. For example I got rid of the dirt path on the ground.

When everything was more or less how I wanted it, I started making MovieClip symbols out of some of the more important groups and the rest I either deleted or just left as background on the stage.

Before I wrote any code I thought it would be fun to animate the sun a little and work out how the bunny was going to hop.

For the sun I separated the face and the orange halo behind its head and over the span of 6 frames I rotated the halo just a little bit so that it would loop and look like it was always turning.

Animating the Bunny

With a little thinking ahead I setup the bunny’s animation and on the first frame I added a quick 3 lines of code to let me stop it from looping if I wanted.

With all the prep done we are finally able to focus on the code. I started off with my symbol class files (i.e. tree.as, clouds.as, and rabbit.as).

There is very little in the rabbit class. Just a boolean property called “moving” so that the small bit of code on frame one will work.

The clouds class is a different story. I wanted to be able to create a new cloud and not have to worry about what type of cloud it was or how fast it would move. So, I made my clouds class randomly child one of my four types of clouds:

public class clouds extends Sprite {

public var vel:Number;
private var c:Number;

public function clouds() {
c = Math.random();
if(c > .85){ //15%
this.y = 140;
addChild(new cloudMad());
}else if(c > .55){ //30%
this.y = 135;
addChild(new cloudCry());
}else if(c > .3){ //25%
this.y = 80;
addChild(new cloudWhistle());
}else { //30%
this.y = 100;
addChild(new cloudSmile());
}

vel = 1 + Math.random();
addEventListener(Event.ENTER_FRAME, doNext);
}

private function doNext(event:Event):void {
this.x += vel;

if(this.x > 700) {
removeEventListener(Event.ENTER_FRAME, doNext);
removeChildAt(0);
dispatchEvent(new Event(Event.COMPLETE));
}
}
}

Notice the variable vel being randomly set to a number between 1 and 2. Every frame the cloud will move to the right by vel pixels. Since the stage is only 550 pixels long I wanted to delete the cloud once it’s definitely clear of the screen. So I remove the child and the event listener and then dispatch a “complete” event so I can finish cleaning up somewhere else in my code.

The tree class is very similar to the cloud class in the respect that it handles it’s own movement. But, there is an added complexity to the trees because 1.) I want to recycle them instead of delete them (actually it’s easier then deleting them), and 2.) The trees don’t move in a straight line across the screen like the clouds do.

public class tree extends Sprite {

private var posY:Number;

public function tree(posY:Number) {
vel = 0;
this.y = this.posY = posY;
addEventListener(Event.ENTER_FRAME, doNext);
}

private function doNext(event:Event):void {
this.x += vel*(this.scaleX);

if(this.x > 700) {
this.x = -150;
}
if(this.x < -150) {
this.x = 700;
}

this.y = posY + 925 - Math.sqrt(925*925 - Math.pow(this.x-275, 2));
this.rotation = (this.x - 275)/18;
}
}

Multiplying the velocity (vel) by the scale (scaleX) will add to the illusion of depth.

In order to move my trees along the curvature of the land I first needed to find out the equation of that curve. To me the curve looked a lot like a segment of a circle, so I just needed to find the radius of that circle. To do that I zoomed out really far, drew a circle and then played around resizing it till it approximately fit the curve. In the end I got a radius of 925 (which is actually slightly too big, but it’s close enough).
Knowing that the equation of a circle is (X+xOffset)^2 + (Y+yOffset)^2 = R^2. Then the equation breaks down to Y = -yOffset + sqrt(R^2 - (X+xOffset)^2) and that’s pretty much what you see near the bottom of my code. The operator signs (+/-) are different because in flash our coordinate plane is flipped vertically.

OK! Now that I have (what tense/perspective was I writing in again?) my trees, clouds, and bunny that all take care of their own movement, it’s time I write the main code that adds everything to the stage.

Ever since I noticed that it was possible I’ve been writing all my code in external .AS files and then associating them with my document.

So, in my main code’s constructor I want to add my bunny and trees to the stage and maybe a new cloud every 5 seconds or so:

public class main extends MovieClip{
public var bunny:MovieClip;
public var treeLayer1:Sprite;
public var treeLayer2:Sprite;
public var treeLayer3:Sprite;
public var myTree:Sprite;
public var myCloud:Sprite;
public var cloudTimer:Timer;

public function main() {
addTrees();
addBunny();

cloudTimer = new Timer(5000); // Every 5 seconds without an end
cloudTimer.addEventListener(TimerEvent.TIMER, addCloud);
cloudTimer.start();

stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
}
}

Of course I need to start to watch for keyboard actions too so I added the event listeners for that.

My addTrees() function has to make 3 layers of trees with different amounts of blur (also to give the illusion of depth):

private function addTrees():void {
treeLayer1 = new Sprite();
treeLayer2 = new Sprite();
treeLayer3 = new Sprite();

stage.addChild(treeLayer1);
stage.addChild(treeLayer2);
stage.addChild(treeLayer3);

var filter:BitmapFilter = new BlurFilter(4, 4, BitmapFilterQuality.LOW);
var myFilters:Array = new Array();
myFilters.push(filter);
treeLayer1.filters = myFilters;

filter = new BlurFilter(2.5, 2.5, BitmapFilterQuality.LOW);
myFilters = new Array();
myFilters.push(filter);
treeLayer2.filters = myFilters;

var i=0;
for(i=0; i<4; i++) {
/*The value sent to tree(value) is the Y value at the hight of it’s curve.*/
myTree = new tree(280);
myTree.scaleX = .8;
myTree.scaleY = .8;
myTree.x = 20 + (200*i);
treeLayer1.addChild(myTree);
}
for(i=0; i<3; i++) {
myTree = new tree(300);
myTree.scaleX = .9;
myTree.scaleY = .9;
myTree.x = -20 + (300*i);
treeLayer2.addChild(myTree);
}
for(i=0; i<2; i++) {
myTree = new tree(320);
myTree.x = 50 + (400*i);
treeLayer3.addChild(myTree);
}
}

Adding the bunny to the stage is also really easy:

private function addBunny():void {
bunny = new rabbit();
bunny.scaleX = .5;
bunny.scaleY = .5;
bunny.x = 275;
bunny.y = 350;
stage.addChild(bunny);
}

Our clouds… since there aren’t ALWAYS clouds in the sky I figured I would only add a new cloud about 30% of the time every 5 seconds.

private function addCloud(event:TimerEvent):void {
if(Math.random() > .7) {
myCloud = new clouds();
myCloud.x = -100;
myCloud.addEventListener(Event.COMPLETE, handleOffScreen);
stage.addChildAt(myCloud, 1);
}
}

private function handleOffScreen(event:Event):void {
stage.removeChild(Sprite(event.currentTarget));
}

Also remembering to take care of the “complete” event that I dispatch from within my cloud object when it goes off stage.

Finally I just have to add my keyboard handling functions, which are really easy:

private function keyDownHandler(event:KeyboardEvent):void {
if(event.keyCode == 39) { //Right
if(!bunny.moving) {
bunny.scaleX = -.5;
bunny.moving = true;
bunny.play();
tree.vel = -4;
}
}
if(event.keyCode == 37) { //Left
if(!bunny.moving) {
bunny.scaleX = .5;
bunny.moving = true;
bunny.play();
tree.vel = 4;
}
}
}

private function keyUpHandler(event:KeyboardEvent):void {
bunny.moving = false;
tree.vel = 0;
}

There it is! I’ve given you almost all the code right there. And if you want more, then download ALL the code here: Springtime Animation Source Code.

http://www.clickpopmedia.com/2008/04/04/spring-animation-with-actionscript-3/


Subscribe to Blog Serba Lengkap.Semuanya Ada Disini ! by Email

0 comments