Porting a game in ActionScript 2 to ActionScript 3

Yesterday I blogged about a post on Emanuele Feronato’s blog. Today he put on is blog some code on an artillery game. It is nice code, but it is in ActionScript 2. I thought it would be fun to try to make the same thing in ActionScript 3. Here is the code from is post

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
Mouse.hide();
gravity = 2;
attachMovie("crosshair", "crosshair", 1);
attachMovie("tank", "tank", 2, {_x:230, _y:350});
crosshair.onEnterFrame = function() {
  this._x = _xmouse;
  this._y = _ymouse;
};
tank.onEnterFrame = function() {
  mousex = _xmouse-this._x;
  mousey = (_ymouse-this._y)*-1;
  angle = Math.atan(mousey/mousex)/(Math.PI/180);
  if (mousex<0) {
    angle += 180;
  }
  if (mousex>=0 && mousey>0) {
    angle += 360;
  }
  if (angle<160) {
    angle = 160;
  }
  if (angle<20) {
    angle = 20;
  }
  firepower = Math.sqrt(mousex*mousex+mousey*mousey);
  if (firepower>200) {
    firepower = 200;
  }
  this.cannon._rotation = angle*-1;
};
function onMouseDown() {
  angle = tank.cannon._rotation-1;
  start_ball_x = tank._x+48*Math.cos(angle*Math.PI/180);
  start_ball_y = tank._y+48*Math.sin(angle*Math.PI/180);
  cannonball_fired = attachMovie("cannonball", "cannonball_"+_root.getNextHighestDepth(), _root.getNextHighestDepth(), {_x:start_ball_x, _y:start_ball_y});
  cannonball_fired.dirx = Math.cos(angle*Math.PI/180)*firepower;
  cannonball_fired.diry = Math.sin(angle*Math.PI/180)*firepower;
  cannonball_fired.onEnterFrame = function() {
    this.diry += gravity;
    this._x += this.dirx/50;
    this._y += this.diry/50;
    if (this._y+this._height/2>350) {
      this._y = 350-this._height/2;
      this.diry = -this.diry*.3;
    }
  };
}

This code is on the first frame of the fla file. To transfer this in ActionScript 3 and in an object oriented way (I am just starting to learn object oriented programming so if you see way I could improve the code just tell me so). In order to do so I divided his code into 4 classes. One class for the document class, one class for the crosshair (I don’t think I needed to make this as a class but it seemed like a good way to divide things), one class for the tank and one class for the cannonball. Here is the code for the document class saved in a file called artillery9AS3.as since my fla is named artillery9AS3.fla:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
 
package{
  import flash.display.Sprite;
  import flash.ui.Mouse;
  import flash.events.*;
  import artillery.*;
  public class artillery9AS3 extends Sprite{
    private var gravity:int;
    private var firepower:Number;
    var crosshair:Crosshair;
    var tank:Tank;
    public function artillery9AS3(){
      Mouse.hide();
      gravity = 2;
      crosshair = new Crosshair();
      addChild(crosshair);
      tank = new Tank(230, 350);
      addChild (tank);
      stage.addEventListener(Event.ENTER_FRAME, doEnterFrame);
      stage.addEventListener(MouseEvent.MOUSE_DOWN, doMouseDown);
    }
    private function doEnterFrame(e:Event){
      crosshair.setPos(mouseX, mouseY);
      var newMousex:Number = mouseX-tank.x;
      var newMousey:Number = (mouseY-tank.y)*-1;
      var newAngle:Number = Math.atan(newMousey/newMousex)/(Math.PI/180);
      if (newMousex<0) {
         newAngle += 180;
      }
      if (newMousex>=0 && newMousey>0) {
        newAngle += 360;
      }
      if (newAngle>160) {
         newAngle = 160;
      }
      if (newAngle<20) {
        newAngle = 20;
      }
      tank.setAngle(newAngle);
      firepower = Math.sqrt(newMousex*newMousex+newMousey*newMousey);
      if (firepower>200) {
        firepower = 200;
      }
    }
    private function doMouseDown(e:MouseEvent){
      var angle:Number = tank.getAngle() - 1;
      var start_ball_x:Number = tank.x + 48*Math.cos(angle*Math.PI/180);
      var start_ball_y:Number = tank.y + 48*Math.sin(angle*Math.PI/180);
      var dirX:Number = Math.cos(angle*Math.PI/180)*firepower;
      var dirY:Number = Math.sin(angle*Math.PI/180)*firepower;
      addChild(new Cannonball(start_ball_x, start_ball_y, dirX, dirY, gravity));
    }
  }
}

Mostly what I am doing here is three things, I create the tank and the crosshair, I add the ENTER_FRAME and the MOUSE_DOWN listeners and I handle these events. In the ENTER_FRAME handler I give the new position to the crosshair, and the new angle to the tank. In the MOUSE_DOWN handler, I create a new cannonball and I give it its parameters so that it can update itself alone.

The code for the crosshair and the tank is pretty straight forward so I won’t paste it here, but download the zip file if you want to see it.

Here is the code for the cannonball

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 
package artillery{
  import flash.display.Sprite;
  import flash.events.*;
  public class Cannonball extends Sprite{
  private var dirX:Number;
  private var dirY:Number;
  private var gravity:Number;
  public function Cannonball(xpos:Number, ypos:Number, newDirX:Number, newDirY:Number, newGravity:Number){
    x = xpos;
    y = ypos;
    dirX = newDirX;
    dirY = newDirY;
    gravity = newGravity;
    addEventListener(Event.ENTER_FRAME, doEnterFrame);
  }
  private function doEnterFrame(e:Event):void{
    dirY += gravity;
    x += dirX/50;
    y += dirY/50;
    if (y+ height/2 >350) {
      y = 350- height/2;
      dirY = - dirY * .3;
    }
    if (x < 0)
    {
       removeEventListener(Event.ENTER_FRAME, doEnterFrame);
       this.parent.removeChild(this);
    }
    }
  }
}

This code is saved in a file named Cannonball.as in the folder artillery. Basically it updates its position based on the direction it had was it was created. I modified one thing in this code. When the cannonball x position is less than, I remove the ENTER_FRAME listener and I remove this cannonball from the display list. I do this because, for one the cannonball is not visible anymore so we should not calculate its position. Also, with the previous code, all the cannonballs that you had shot would continue to use up memory, so if you played for a long time, you would eventually run out of memory. By removing the listener and the display object, the garbage collector will remove the unused cannonballs thereby freeing memory.

Also, I mostly used Sprites since there was no timelines involved (the cannon is still a MovieClip, I didn’t take the time to convert it). This is good for the crosshair and the tank, but I think the cannonballs should have stayed a MovieClips since eventually you will want these cannonballs to explode and use a timeline in order to animate the explosions.

Well that is about it for now, feel free to download the files to look at the source code.

Source of the artillery game

, ,

  1. #1 by Robert - January 6th, 2008 at 22:38

    Thank you so much for doing this! I’m trying to teach myself actionscript 3 so I can finally create some game designs I’ve had sitting on a shelf for a long time. Anyway, I’m trying to avoid AS2 so I don’t mess myself up, so seeing Emanuele’s tutorial converted is immensely useful.

    I can follow most of what you did here, but I hit a snag trying to make some changes on my own. I want the turret in the middle of the screen, and able to rotate in 360 degrees to shoot in any direction. If you get a chance, would you give me a tip or two to get started or post a snippet change?

    Thank you again!

  2. #2 by Flanture - February 27th, 2010 at 11:02

    Hello,

    I know this post is 2+ years old but still it’s great for us trying to learn AS3 everywhere we can :) I see you’ve done this porting in a hurry, there are few things redundant like gravity inside main class (only needed in cannonball).

    Those who are about to make theirs first AS3 game (like me) can benefit from this code even more than trying to learn entire framework like let’s say Fixel or something similar.

    So, once again thanks for the port and feel free to check my blog in few days to see how I’m doing with this new game :)

    Good luck with your future projects,
    Flanture
    [Flash Adventure]

(will not be published)
Subscribe to comments feed
  1. No trackbacks yet.