Gentle Reader: This is the second part of a two-part set of posts. For this one to be useful, please take a look at Part I. Also, I’m not an expert on military operations or organizations; so if there’s any error in a basic infantry platoon, feel free to correct me. I am aware, however, of the 7-1 ratio of Service to Combat units in the modern military, and that this is only a simple component of a far more sophisticated structure—that’s why I selected it!
In the first installment of the Wrong Way Warrior, we saw how an OOP developer put together a simple proof-of-concept using what he thought was a prudent approach to a battle simulation. He’d provide the Warrior with certain characteristics and then subclass those characteristics to concrete warriors that would share the capabilities of the parent class. In addition, the concrete warriors would be given a movie clip representation of the warrior.
After the first design was sent to the customer, the response was less than favorable. It was described as “a children’s game” at best. The military advisor described it as a caveman battle plan where all of the combatants are similarly armed with a club to attack adversaries. The problem was that it was bound to a fairly static design, and it would be impossible to be used for a simulation that had more complex behaviors. However, the other submissions were not much better, and so the customer provided a simple organization within the military to simulate—the basic infantry platoon. After all, they’re paying your company $1.5 million to develop the simulation. (This was news to the developer!) Figure 1 shows the organization in terms of a new set of movie clips:

Figure 1: Movie clip representation of platoon
As you can see, far from being a herd of cavemen with clubs, each of the members of the platoon has a specific role. A lieutenant with the aid of an experienced platoon sergeant runs the show. A radio operator keeps in contact with the higher-level organization (company) and other assets than can be brought to bear (e.g. artillery and air support). Broken down into four squads, 3 rifle squads and a weapons squad, the organization is fairly generic of those in the US Army and is instructive for some more complex (and realistic) applications in Flex and Flash.
What Varies?
To get started, it helps to have some kind of perspective on the problem. If we look at the basic military hierarchy, we can get an idea:
Can the simulation be expanded even to company size? The sample platoon is set up for 38 soldiers, and the Company for between 62-190, depending on specialized assignments. These are only the combat units and do not include such service and support units as medics, transport, military police and other service units.
In looking at Figure 1, we can immediately see that roles vary. Put another way, their behaviors vary. Initially, a single Warrior class was used and subclasses of Red and Blue classes made up two opposing sides. However, other than the appearance of their movie clip icons, they were identical. If we added more and more functions, we’d have to override virtually ever other method. So, we need another way.
For this round of development, we need to think about one of the first principles of design patterns,
Separate what varies from what stays the same and encapsulate what varies.
Since we’ve identified that behaviors vary because of the different roles (not a bunch of undifferentiated cavemen with clubs), we’ll start with the weapons and firing behavior. We’ll put the behaviors into an interface and set up implementations of the different weapons. At the same time, we’ll set up the Warrior class so that they can use the different weapons through composition. That is, each instance of each subclass will have a different weapon to use instead of the weapon and its related behavior as an integral part of the particular Warrior class.
Sound On!
To see where all of this is leading turn up your sound and click the Play button. You will see different organizational options when you press the buttons along the top. When you click on the individual “soldiers”, they will play a sound representing their weapons. In the case of the officer and NCO’s, the entire unit’s weapons fire simultaneously representing commanded fire. Because the anti-armor and machine gun units require two people to use the weapons, clicking either of the two sprites serve to fire the weapon. After you’ve had a look, download the files—only selected few were placed in this post.
![]()
![]()
To kick things off we’ll be looking at a very simplified Warrior class and an interface for firing weapons shown in the following code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | //Warrior abstract class package { import flash.display.Sprite; //Abstract class. Do not instantiate public class Warrior extends Sprite { protected var fire:Fire; //protected var movement:Movement; //protected var comm:Communicate; } } //Encapsulating behaviors package { interface Fire { function fireWeapon():void; } } |
Those two elements should be viewed as structuring elements that help guide the development of the program. The Warrior abstract class includes a reference to the Fire interface and the set of behaviors that will be derived from implementations of that interface. The concrete Warrior classes will not derive their behaviors from the parent class but from the aggregate relationship between the Warrior interface (abstract class) and the Fire interface. (You can see two commented out variables, movement and comm that I’ll be referring to in a later post, but they can be ignored for the rest of this post.)
Different Characters and Behaviors
If you’ve ever been admonished to differentiate between a bad action and a bad person you’ll understand what’s going on here. The person belongs to the Warrior class and the action belongs to the Fire interface. They have the relationship shown in Figure 2:

Figure 2: Class diagram of Warrior and Fire
As you can see in Figure 2, all of the algorithms for weapons actions are encapsulated in the Fire implementations. The Warrior subclass objects get their behaviors through the Warrior interface through the Fire interface.
Marrying the Warrior to the Action
In bringing together the behavior and character, you’ll be glad to know there’s no bridezilla in the coupling. In fact, to quote another fundamental OOP principle,
Objects should be loosely coupled.
So even better, by having loosely coupled objects, when something changes, there won’t be a collapse in the entire system just in case a particular coupling doesn’t work as planned.
In Part I of The Wrong Way Warrior, the developer used movement with buttons to illustrate how each instance inherited the ability to move on the screen. This time around, the developer is demonstrating how the different types of soldiers carry out a behavior—firing a weapon—that is composed into his object through aggregation. So, instead of shooting up the screen, this time the developer decided to use sound effects of the different weapons. Also, to fire the weapons, instead of having another set of buttons, clicking on individual concrete Warrior objects launches the appropriate sound effects.
As noted above, the concrete Warrior objects are coupled with a Fire implementation, and as you will see, they’re very similar. In that respect they’re interchangeable; and that’s just what we want. Starting off, the following listings show the Rifleman (RifleMn) character and the FireRifle behavior.
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 | //Creates concrete Warrior instance package { import flash.display.Sprite; import flash.events.MouseEvent; public class RifleMn extends Warrior { //Rifleman is movie clip in Library private var rm1:Sprite=new Rifleman(); public function RifleMn(fx:uint,fy:uint):void { rm1.x = fx,rm1.y = fy; rm1.addEventListener(MouseEvent.CLICK, fireNow); addChild(rm1); } private function fireNow(e:MouseEvent):void { fire = new FireRifle(); fire.fireWeapon(); } } } //Implements Fire behavior package { public class FireRifle implements Fire { import flash.media.Sound; import flash.media.SoundChannel; import flash.net.URLRequest; private var url:String = "WeaponSounds/M16.mp3"; private var weapon:SoundChannel; public function fireWeapon():void { var urlReq:URLRequest = new URLRequest(url); var gun:Sound=new Sound(); gun.load(urlReq); weapon = gun.play(); trace("Firing M16--1 shot burst"); } } } |
The concrete Warrior selects a movie clip that represents its character first. Typed as a Sprite, it is used as a clickable event generator. In this case, the MovieClip object is named, Rifleman. The Rifleman instance is event-linked to a function fireNow() which then uses the fire object inherited from the parent class—Warrior. Using the fire object, the program instantiates the particular implementation of the behavior. In this case, it wants an instance of FireRifle. Keep in mind that fire inherited from Warrior is typed as a Fire object—only committing to the interface. This allows any implementation of the interface and its methods.
In looking at the Fire implementation of FireRifle, it basically sets up the sound file that is played. However, it only represents any algorithm that could be placed there instead. For example, it could be used in an algorithm to measure the expenditure of force against a target and keep track of the amount of ammunition a concrete Warrior instance expends and has remaining.
When you download and look at the different classes, you’ll see they’re pretty similar. However, some characters, like the Lieutenant, have a much more robust use of the Fire implementations as you can see in the following listing:
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 55 56 57 58 59 60 61 | package { import flash.display.Sprite; import flash.events.MouseEvent; public class Lieutenant extends Warrior { //Lieut is movie clip in Library private var lt1:Sprite=new Lieut(); public function Lieutenant(fx:uint,fy:uint):void { lt1.x = fx,lt1.y = fy; lt1.addEventListener(MouseEvent.CLICK, fireNow); addChild(lt1); } private function fireNow(e:MouseEvent):void { //Fire Personal Weapon fire = new FireRifle(); fire.fireWeapon(); //PlatoonFire squadFire(); weaponsSquadFire(); squadFire(); squadFire(); } private function squadFire():void { //Fire Team 1 fire.fireWeapon(); fire.fireWeapon(); fire = new FireSAW(); fire.fireWeapon(); fire = new FireGrenade(); fire.fireWeapon(); //Fire Team 2 fire = new FireRifle(); fire.fireWeapon(); fire.fireWeapon(); fire = new FireSAW(); fire.fireWeapon(); fire = new FireGrenade(); fire.fireWeapon(); } private function weaponsSquadFire():void { fire=new FireMG(); fire.fireWeapon(); fire.fireWeapon(); fire=new FireRocket(); fire.fireWeapon(); fire.fireWeapon(); } } } |
As you can see, the Lieutenant fired every weapon in the platoon, as did the Platoon Sergeant. This illustrates how flexible this design is. Because the behaviors are separated from the objects that use them, you can put them in any combination you want.
The Client
If you look at the Client carefully, you’ll see no reference at all to the Fire operations. That’s because the concrete Warrior objects all access Fire behaviors themselves. There’s no reason (nor would you want one!) to implement a concrete Fire object from the Client directly. Client constructor creates buttons used to display different arrangements of the troops. The bigger problem was getting rid of one configuration when another had been placed on the stage. Keith Peters provided a handy algorithm for clearing all children, and so I put it in the piedPiper() function that clears everything—including the buttons! So the piedPiper() method replaces the buttons after blowing them and the rest of the children off the stage.
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 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | package { import flash.display.Sprite; import flash.events.MouseEvent; import fl.controls.Button; public class Client extends Sprite { private var rocketBtn:Button=new Button(); private var mgBtn:Button=new Button(); private var ftBtn:Button=new Button(); private var sqBtn:Button=new Button(); private var hqBtn:Button=new Button(); private var lieut:Warrior; private var platoonSgt:Warrior; private var radio:Warrior; private var sqLdr:Warrior; private var tmLdr:Warrior; private var sawMan:Warrior; private var grenMan:Warrior; private var rifMan:Warrior; private var tmLdr2:Warrior; private var sawMan2:Warrior; private var grenMan2:Warrior; private var rifMan2:Warrior; private var mgunner:Warrior; private var asstMgunner:Warrior; private var rocket:Warrior; private var asstRocket:Warrior; public function Client() { ftBtn.addEventListener(MouseEvent.CLICK, fireTeam); ftBtn.label = "FireTeam"; ftBtn.x = 10,ftBtn.y = 10; addChild(ftBtn); sqBtn.addEventListener(MouseEvent.CLICK, squad); sqBtn.label = "Squad"; sqBtn.x = 120,sqBtn.y = 10; addChild(sqBtn); mgBtn.addEventListener(MouseEvent.CLICK, mgCrew); mgBtn.label = "Machine Gun"; mgBtn.x = 230,mgBtn.y = 10; addChild(mgBtn); rocketBtn.addEventListener(MouseEvent.CLICK, rocketCrew); rocketBtn.label = "Anti Armor"; rocketBtn.x = 340,rocketBtn.y = 10; addChild(rocketBtn); hqBtn.addEventListener(MouseEvent.CLICK, hq); hqBtn.label = "Headquarters"; hqBtn.x = 450,hqBtn.y = 10; addChild(hqBtn); } private function fireTeam(e:MouseEvent) { piedPiper(); tmLdr = new TeamLdr(300,424); addChild(tmLdr); rifMan = new RifleMn(428,338); addChild(rifMan); sawMan = new SAW(480,424); addChild(sawMan); grenMan = new Grenadier(428,512); addChild(grenMan); } private function squad(e:MouseEvent) { piedPiper(); sqLdr = new SquadLdr(82,300); addChild(sqLdr); tmLdr = new TeamLdr(300,424); addChild(tmLdr); rifMan = new RifleMn(428,338); addChild(rifMan); sawMan = new SAW(480,424); addChild(sawMan); grenMan = new Grenadier(428,512); addChild(grenMan); tmLdr2 = new TeamLdr(420,162); addChild(tmLdr2); rifMan2 = new RifleMn(548,76); addChild(rifMan2); sawMan2 = new SAW(600,162); addChild(sawMan2); grenMan2 = new Grenadier(548,250); addChild(grenMan2); } private function mgCrew(e:MouseEvent) { mgunner = new MG(520,500); addChild(mgunner); asstMgunner = new AssistantMG(550,570); addChild(asstMgunner); } private function rocketCrew(e:MouseEvent) { rocket = new RocketMan(650,250); addChild(rocket); asstRocket = new AssistRocket(700,300); addChild(asstRocket); } private function hq(e:MouseEvent) { lieut = new Lieutenant(132,98); addChild(lieut); platoonSgt = new PltSgt(66,188); addChild(platoonSgt); radio = new RadioMan(194,188); addChild(radio); } private function clearFireTeam() { removeChild(tmLdr); removeChild(sawMan); removeChild(grenMan); removeChild(rifMan); } private function clearSquad() { clearFireTeam(); removeChild(sqLdr); removeChild(tmLdr2); removeChild(sawMan2); removeChild(grenMan2); removeChild(rifMan2); } private function piedPiper() { while (numChildren > 0) { removeChildAt(0); } addChild(ftBtn); addChild(sqBtn); addChild(mgBtn); addChild(rocketBtn); addChild(hqBtn); } } } |
If you run the program from within the Flash/Flex IDE, you should be able to see trace statements in the Output window as well to tell you what’s going on—in addition to the sound effects.
The Next Steps
I doubt there’s anyone who’s read this blog who doesn’t recognize the design pattern in use; so I won’t go into that. However, this project is yet to be completed. That will come in future posts. Now that we’re on the right track, we (that means you as well) can envision what other behaviors—or class of behaviors and their accompanying algorithms—could be added to the current set.
If you’re interested in game development, I hope that this little demonstration has shown the practicality of using design patterns and how easy they can make it. This is especially true as your projects become more complex. You might also want to review Chapter 13 of our book where we cover the Symmetric Proxy Pattern. There you will find a solution to the problem of simultaneous movement and multi-person play over the Internet using Flash Media Server. Setting up a platoon or even squad level game using simultaneous movement would be a lot of fun, and you could use several of the design patterns we discussed on this blog and in our book.

The Wrong Way Warrior: Getting Flexibility with Design Patterns—Part II by William B. Sanders, unless otherwise expressly stated, is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.

Bill Sanders
Nice work!! Learning a whole lot here.
Hi Sean,
Chandima and I are glad to hear it. We’re also looking for new ideas. Where do you think this application should go next?
Kindest regards,
Bill
I hope the Lieutenant will learn to shout a command to let his troops fire, instead of firing all by himself.
Hi KKCosma,
Yeah, the Lieutenant sounds like Rambo on steroids. Actually, the sounds from the Team Leaders, Squad Leaders, Platoon Sergeant and Lieutenant represent the unit firing on a command. Of course, we might want to think about the addition of a class that would handle different commands. How would be go about that, and instead of a booming sound of all of the platoon’s weapons going off at once, we’d hear a command to that effect and all of the weapons would then sound off? Something like, “We’re being attacked by Sequential Programmers! Blast ‘em!” — then we’d hear a platoon firing sound.
Cheers,
Bill
Bill, how delighted I was to see the followup article posted so quickly! I’ll have a few suggestions for where the app should go next after I get a chance to soak this all in…
Hi T,
Glad to hear it. As for suggestions, let’s see something a bit more… Maybe you can add a light mortar crew… I realize they’re not part of the platoon TOE, but we’ll pretend that the platoon receive a light mortar crew (3 members) to provide added defense against an attack by hordes of Unencapsulated Code Zombies. (How’s that for motivation?) Check out:
http://www.jhu.edu/rotc/Basic_Army_Knowledge/Military_Symbols.htm
for a military symbol for mortars.
Cheers,
Bill
assuming that this demo game will eventually have two sides (blue vs red, etc.), it would be cool to see the implementation of a new “Spy” class, which would basically extend the Warrior class (and the Warrior class would use composition to assign both FireBehavior and WarriorBehavior).
Hi T,
This is all about extending existing programs; so you can make it anything you want. Why not start with something simple?
Take care,
Bill
Hi,
first of all thank for all of your work ;). Second of all, I just started with OOP in AS3 and flash couple months ago. Ive got several questions. For example, you are putting (and as I understood it, its a good practice) the “sprite” from library, RedWarrior for example, into private var of another class. Why? :) I could probably find the answer somewhere here, so important question. You are positioning this “sprite” inside of the new class. So then, as I usually do, you are not able to keep track of xs and ys of all of yours soldiers. Also using private vars (in Client class) for every soldier seems so clumsy (and it takes so much space), and it seems like you are using it only for removing those soldiers (which could be done, in my opinion, more easily, either with sets of arrays or with holder sprites). I am probably all wrong, but these are the things that came to my mind when I read this.
P.S.: And I totally agree with KKCosmo :).
Be well.
Hi Xixixao,
Most of the questions you’re asking are handled in Chapter 1; so if I miss something, you can probably find it there. In both OOP and Design Patterns, there are no simple explanations that will cover everything; especially the good questions that you are asking, and so I’ll also have some links to other posts on this blog that will help out. If you haven’t done so already, download the AIR app with all of the major design pattern principles. The principles make up the bulk of the “whys”—each of the principles is discussed in detail, and you can find them all in the Index of this blog. The AIR app is just a handy reminder of them that you can put on your desktop.
The simple answer for using the private accessor is to encapsulate properties or functions. In this particular case, the OOP programmer wants to use the MovieClip in the Library. However, he just needs the image aspects of it; so he types it as the parent class, Sprite. Had he needed to use timeline methods, he would have typed it as a MovieClip. His Warrior class provides a set of behaviors (methods) for all warriors; but to have flexibility, the Warrior class does not include images. Therefore, the developer can subclass the Warrior and then add sprites that provide a visual representation—in this case the Red and Blue warriors.
As for keeping track of the x and y values in the positions, you’re right. It doesn’t do that. All this example is doing is setting up a straw man (of sorts) to show how this approach (even though using OOP) will fail as soon as more behaviors are added. In Part II here, you see that there’s no movement at all. Instead, using a Strategy design pattern, the behaviors are encapsulated in a separate set of classes around a common interface (Fire).
However, you will notice that a couple of commented-out statements hint to the possibility of encapsulating both movement and communication. The latest Golden Lunch Bucket Contest also shows these tantalizing possibilities. You can create any kind of movement you want by setting up a Movement interface (either as an abstract class or interface) and then using composition, have your warriors move as you like. As you say, the way to go may be with an array. Why not try it out with your ideas and enter the contest? Later, you and KKCosmo can implement the Communication interface and have the Lieutenant bark orders that will set the platoon in motion! (Give the Lieutenant that redneck accent that Brad Pitt uses in Inglourious Basterds.)
Kindest regards,
Bill