Sunday, November 7, 2010

Actionscript 3 RTS game tutorial - part 3

Now we will add more features to our existing RTS mechanism.

Firstly, here is the final product we will get with the script.

If you just click on units, you can only select a single unit. To select multiple guys, hold CTRL. Press space to deselect all.


I added a new movie clip inside my unit - its transparent and called selectArea. This should be on top of everything what you might have in your unit movie clip, because this is the area you click on to select the unit.

Here is the commented code, you might want to read it more than once to understand how it works fully. It might look complex, but it consists of small 'bricks' of code that are actually pretty simple.

// 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*2)>mc.y)
{
mc.y +=  movespeed;
dir = "down";
}
else if ((goY+movespeed*2)<mc.y)
{
mc.y -=  movespeed;
dir = "up";
}
if ((goX-movespeed*2)>mc.x)
{
mc.x +=  movespeed;
dir = "right";
}
else if ((goX+movespeed*2)<mc.x)
{
mc.x -=  movespeed;
dir = "left";
}

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

// Check for space key (deselect)
if (isSpace)
{
selectedUnit = false;
mc.selectedGfx.gotoAndStop(1);
}
}

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

mc.selectArea.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);
totalSelected--;
}
else
{
selectedUnit = true;
mc.selectedGfx.gotoAndStop(2);
totalSelected++;
}
}

// 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;
}

// Now we check if we clicked on a unit, but not this one. If we did it without holding
// CTRL, then this unit should be deselected.
// We use the selectArea movieclip (which is invisible) located in each unit to trace clicking

for (var l:int=0; l<units.length; l++)
{
if (evt.target == units[l].selectArea && evt.target != mc.selectArea && isCtrl == false)
{
selectedUnit = false;
mc.selectedGfx.gotoAndStop(1);
}
}

}
}

// 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]);
}
}
}
}
}

// Creating a keyboard manager

stage.addEventListener(KeyboardEvent.KEY_DOWN, kDown);
stage.addEventListener(KeyboardEvent.KEY_UP, kUp);

var isCtrl:Boolean = false;
var isSpace:Boolean = false;
msgText.text = "Hold CTRL to select multiple units. Space to deselect all.";

function kDown(evt:KeyboardEvent):void
{
if (evt.keyCode == 17)
{
isCtrl = true;
msgText.text = "Multiple unit select";
}
if (evt.keyCode == 32)
{
isSpace = true;
msgText.text = "Deselected all";
totalSelected = 0;
}
}

function kUp(evt:KeyboardEvent):void
{
if (evt.keyCode == 17)
{
isCtrl = false;
msgText.text = "Single unit select";
}
if (evt.keyCode == 32)
{
isSpace = false;
}
}

// Selection checker

var totalSelected:Number = 0;

stage.addEventListener(Event.ENTER_FRAME, selectionChecker);

function selectionChecker(Event):void
{
// When no units are selected, totalSelected is set to 0.
// Once a unit is clicked, this number increases by 1 and decreases when unselected.
// This var is changed through the addUnit() function and also Space key event.
msgText2.text = "Total units selected: " + totalSelected.toString();
}

Thanks for reading!

Related:

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

1 comment:

juan perez said...

Is it posible you could post the source code for this section #3?

Thanks a lot

Post a Comment