Monday, March 14, 2011

Beginning Flash and ActionScript Game Programming Part 8: Basic Programming Concepts-Classes-Inheritance

Beginning Flash and ActionScript Game Programming Part 8: Basic Programming Concepts-Classes-Inheritance:

Crysis2 game screen shot

In the previous section, we learned the basics of creating classes, and how to create objects from the classes we made.

In this section, we’ll go into more detail about creating classes, specifically inheritance, which allows you to save time when creating simmilar objects.

What is Inheritance?

The programming concept of ‘inheritance’ is important, and used a lot in object oriented programming (OOP).

The concept is that you create a base class that other classes will inherit from, usually when the other class is a derivative of the base class.

For instance, if you have a orc enemy, a golbin enemy, and a dragon enemy, they can all be based off a basic ‘enemy’ type.

Each enemy will need health, a function to damage the player, have an attack speed, a move speed, and whatever else as enemy might have.

They can all have basic stuff in common, and ‘inherit’ those functions and variables from a base class, but have their own specific variables and functions as well, that the other enemy types might not need.

An example of a base enemy class:

Enemy.as

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
package  
{
 /**
  * ...
  * @author Chris Moeller
  */
 public class Enemy 
 {
  public var name:String;
  public var health:int;
  public var attack_speed:int;
  public var attack_strength:int;
  public var move_speed:int;
 
  public function Enemy(name:String, health:int=100, attack_speed:int=20, attack_strength:int=5, move_speed:int=48) 
  {
   this.name=name;
   this.health=health;
   this.attack_speed=attack_speed;
   this.attack_strength=attack_strength;
   this.move_speed=move_speed;
 
   trace(name+": basic enemy created");
  }
  public function TakeDamage(amount:int):void
  {
   if(health <= 0)
   {
    trace(name+": Stop beating my corpse!");
    return;
   }
 
   health-=amount;
   if(health > 0)
    trace(name+": ouch, you damaged me!(health:"+health+")");
   else
    trace(name+": Eck, you killed me!");
  }
  public function Speak():void
  {
   trace(name+": I am a basic enemy!");
  }
 
 }
 
}

Nothing really new here, we have a constructor that is called on creation where we are required to pass in the enemy name, but all the other variables in the parameters have default values, so we don’t have to pass them in if not needed.
“Speak” if a function that just traces out our basic enemy telling what it is.

Next, lets create some clases that inherit from our base enemy class.

To do this, first right click on the ‘src’ folder in FlashDevelop, and select “Add->New Class”.
Name it “Dragon” in the name field, and this time click on the “Browse” button below, next to “Base Class”.
In the top field type in “Enemy”, and double click on the enemy class, whcih shows up in the window area below.
Next click the check box next to “Generate constructor matching base class” to check it, and click ‘OK’ to create your dragon class.

It should create a new class file that looks like:

Dragon.as

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package
{
 /**
  * ...
  * @author Chris Moeller
  */
 public class Dragon extends Enemy
 {
 
  public function Dragon(name:String, health:int = 100, attack_speed:int = 20, attack_strength:int = 5, move_speed:int = 48)
  {
   super(name, health, attack_speed, attack_strength, move_speed);
 
  }
 
 }
 
}

As you can see, there are a couple additions here that are not in a class that doesn’t have a base class. The first is

line 7: public class Dragon extends Enemy The key here being the keywords ‘extends Enemy’.
This just means that this class will be a sub class of the ‘Enemy’ class, and will inherit all of it’s ‘public’ variables and functions as if we declared them in this class.
So we will have access to all of the ‘Enemy’ class’s functions and variables that we declared in the ‘Enemy.as’ file, as if we also declared it in this file.

line 12: super(name, health, attack_speed, attack_strength, move_speed); The “super” keyword is used to explicitly call a base class’s functions. Here, just using ‘super’ with paranthesis will call the parent/base class’s constructor.
So when a dragon object is created, right now it needs to be created with the same parameters as the ‘Enemy’ class, and it needs to call the ‘Enemy’ class’s constructor in it’s constructor to run the ‘Enemy’ constructor.

Right now, if you created a ‘Dragon’ object, it would be identical to an ‘Enemy’ object, so lets change that to make the Dragon class slightly different.

Dragon.as

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
package
{
 /**
  * ...
  * @author Chris Moeller
  */
 public class Dragon extends Enemy
 {
  public var flight_speed:int;
  public var fire_damage:int;
  public var number_of_heads:int;
 
  public function Dragon(name:String, health:int = 100, flight_speed:int=100, fire_damage:int=50, number_of_heads:int=1)
  {
   //super(name, health, attack_speed, attack_strength, move_speed);
   super(name, health, 20, 10, 50);
   this.flight_speed = flight_speed;
   this.fire_damage = fire_damage;
   this.number_of_heads = number_of_heads;
 
   trace(name + ": dragon created");
  }
  override public function Speak():void
  {
   trace("I used to say:");
   super.Speak();
 
   trace("But now I say: ");
   trace("I am a dragon!");
  }
  public function BlowFire():void
  {
   trace(name+": I'm blowing fire, with fire damage=" + fire_damage + ", from my " + number_of_heads + " heads");
  }
 
 }
 
}

I added some things that a dragon would have, that a generic enemy might not.

Line 9–11: I added a few variables that a dragon would have, that the basic enemy wouldn’t have needed.

Line 13: I created the Dragon constructor with different parameters that are used to create it, but it can be the same as the original Enemy constructor if needed.

Line 16: I call the ‘Enemy’ constructor, and say that all dragons will have an attack speed of 20, attack strength of 10, an a move speed of 50.

Line 23: Here, we use the keyword ‘override’ to override a function that was created in the base class (Enemy), but make it so that when the function for a dragon is called, we run this function instead.

Line 26: Here, we use the ‘super’ keyword and the name of the ‘Speak’ function to call the Dragons parent class (Enemy) Speak function. So even if we override a function, we have access to the base function as well.

Line 31: This is a new function, specific to dragons, which we can call for dragons, but not for basic Enemies.

Now we need to just need to create the objects from the class definitions we just made in our ‘Main.as’ program [...]

No comments:

Post a Comment