Saturday, November 6, 2010

Actionscript 3 RTS game tutorial - part 2

Today we will allow multiple unit selection and movement.

If you haven't read RTS-like character movement using mouse tutorial yet (its the first part in the series), do it right now.

Here is the results we will get by the end of this tutorial (click units to select them, click somewhere to movethem; you can select multiple units):


I've edited the previous RTS script found in the previous RTS movement tutorial, and here is the full commented code:

// We turn all the code that handles movement and behavior of one unit
// into a function, through which we can apply the same code to
// multiple units.
function addUnit(mc):void
{
var iswalking = false;
var movespeed = 5;
var dir = "down";
var goX;
var goY;
// the selectedUnit variable is toggled when the unit is being clicked
var selectedUnit = false;

stage.addEventListener(Event.ENTER_FRAME, loop);

function loop(Event)
{
if (iswalking == true)
{
mc.w.play();
}
else
{
mc.w.gotoAndStop(1);
}

mc.gotoAndStop(dir);
if ((goY-movespeed)>mc.y)
{
mc.y +=  movespeed;
dir = "down";
}
else if ((goY+movespeed)<mc.y)
{
mc.y -=  movespeed;
dir = "up";
}
if ((goX-movespeed)>mc.x)
{
mc.x +=  movespeed;
dir = "right";
}
else if ((goX+movespeed)<mc.x)
{
mc.x -=  movespeed;
dir = "left";
}

if ((goY-movespeed)>mc.y || (goY+movespeed)<mc.y || (goX-movespeed)>mc.x || (goX+movespeed)<mc.x)
{
iswalking = true;
}
else
{
iswalking = false;
}

}

// When we click the unit, toggle the selectUnit variable

mc.addEventListener(MouseEvent.CLICK, select);

function select(MouseEvent):void
{
if (selectedUnit == true)
{
selectedUnit = false;
// mc.selectedGfx is a movieclip with a green border graphic
// it is visible on frame 2 and invisible on frame 1
mc.selectedGfx.gotoAndStop(1);
}
else
{
selectedUnit = true;
mc.selectedGfx.gotoAndStop(2);
}
}

// When we click the stage area, move there

stage.addEventListener(MouseEvent.CLICK, setposition);

function setposition(evt:MouseEvent):void
{
// The conditional checks if we click stage (not a unit) and set the position
// of the move marker

if (evt.target == stage && selectedUnit == true)
{
goX = mouseX;
goY = mouseY;
}

}
}

// All units are stored in an array
// char, char2 and char3 - instance names of unit mcs on stage

var units:Array = [char,char2,char3];

for (var i:int=0; i<units.length; i++)
{
addUnit(units[i]);
}

// Here we manage depths

stage.addEventListener(Event.ENTER_FRAME, depthManager);

function depthManager(Event):void
{
// Two loops for two objects (object one hits object 2)
for (var v:int=0; v<units.length; v++)
{
for (var o:int=0; o<units.length; o++)
{
// First we check if object1 and object2 aren't the same unit
// Then we check if they collide
if (v != o && units[v].hitTestObject(units[o]))
{
// Swap depths if needed
if (getChildIndex(units[v]) > getChildIndex(units[o]) && units[v].y < units[o].y)
{
swapChildren(units[v], units[o]);
}
if (getChildIndex(units[v]) < getChildIndex(units[o]) && units[v].y > units[o].y)
{
swapChildren(units[v], units[o]);
}
}
}
}
}

Thanks for reading!

Related:

Actionscript 3 RTS game tutorial part 1
Actionscript 3 RTS game tutorial part 3
Actionscript 3 RTS game tutorial part 4
Actionscript 3 RTS game tutorial part 5

3 comments:

z said...

as a side note to this particular tutorial had a tough time with the 'selectedGfx'

in order to make it work what I had to do was go to the character object, add a layer, and then add the selectedGfx on the new layer. then make it persistent to all the key frames of the character.

JLTF1 said...

Hey,

i dont understand the code :(

"var units:Array = [char,char2,char3];

for (var i:int=0; i<units.length; i++)
{
addUnit(units[i]);
}"

Here you call up the function "addUnit" 3 times, but in this function you declare the same variables 3 times ( e.g. iswalking =false), so
from where does the ENTER_FRAME-loop know, wich mc he has to move etc. when theres only on variable for 3 mcs?

I hope you understand my problem (sorry for my bad english btw)

thank you in advance

Kirill Poletaev said...

The variables are not the same, they only have the same names. They aren't the same entity because they are located inside the addUnit() function.

All variables declared inside a function are only accessible to that function (and the functions inside of it).

This means that we have 3 variables iswalking, 3 ENTER_FRAME listeners, etc.

This is not the most efficient way to do things, there are many ways to improve the code. For example, you can make it OOP way - turn each unit into a class and use a single ENTER_FRAME listener to handle all the units in a parent class.

That's what I would do if I were to remake this today, but this is an old tutorial. It works, though.

Post a Comment