Quick Tip: Collision Detection Between Circles
Collision detection is a branch of algorithms that checks whether two shapes overlap. If you build physics or action games with ActionScript, you will certainly not escape acquaintance with this topic. This is the first of the series regarding collision detection. In this Quick Tip, we shall look at ActionScript’s built-in collision detection method, hitTestObject(), and write our own to detect overlap between two circles.
Final Result Preview
This is the final SWF we will create in this Quick Tip. Click the blue circle and drag it towards the green one. Once they overlap, the green circle will change its color; if you remove the blue circle again, the other will return to being green.
Step 1: Bounding Box Checks
Those who are aquainted with ActionScript 2.0 will definitely recognise the method, hitTest(). This command checks for overlap between two shapes, or between a shape and a single point. In ActionScript 3.0 it is split into two separate methods: hitTestObject() and hitTestPoint().
We shall look at hitTestObject() first. This commnad generally suits collision detection for box-like shapes (squares, rectangles). A bounding box is drawn around shapes and when these bounding boxes overlap each other, hitTestObject() returns true.
Check out the example below. Drag the blue box towards the green one. As they overlap, the green box’s shade darkens.
I attach here the corresponding ActionScript that generates the above presentation. Box is a custom written class to easily generate square shapes. I’ve included the classes in the source folder; do refer to them. The important script for collision detection is highlighted below.
package
{
import flash.display.Graphics;
import flash.display.Sprite;
import flash.events.MouseEvent;
/**
* Simple hitTest with boxes
* @author Shiu
*/
[SWF(width = 400, height = 300)]
public class Simple extends Sprite
{
private var box1:Box, box2:Box;
public function Simple() {
box1 = new Box(0x0000FF); addChild(box1);
box1.x = 250; box1.y = 250;
box1.addEventListener(MouseEvent.MOUSE_DOWN, start);
box1.addEventListener(MouseEvent.MOUSE_UP, end);
box2 = new Box(0x00FF00); addChild(box2);
box2.x = 100; box2.y = 50;
}
private function start(e:MouseEvent):void {
e.target.startDrag();
e.target.addEventListener(MouseEvent.MOUSE_MOVE, check);
}
private function end(e:MouseEvent):void {
e.target.stopDrag();
e.target.removeEventListener(MouseEvent.MOUSE_MOVE, check);
}
private function check(e:MouseEvent):void {
if (e.target.hitTestObject(box2)) box2.color = 0x00AA00;
else box2.color = 0x00FF00;
}
}
}
Step 2: Shortcomings of Bounding Boxes
However, collision between circles cannot be effectively checked using this command. Check out the presentation below. Drag the blue circle towards the green one. Before the shapes collide, their bounding boxes already overlap and hitTestObject() is true. We need a more accurate solution.
This problem is prevalent not only for collision detection between circles but non-square shapes generally. Observe the diagram below. For organic shapes that are difficult to resolve by polygons, we shall make use of pixel-precise collision detection.

Various inaccurate collision detected through hitTestObject.
Step 3: Distance Between Centers
The solution to this problem is quite simple: we shall measure the distance between the centers of these circles. If the centers get close enough to each other, we shall flag collision as true. But how close is close enough?

Distance between circles.
Observe the diagram above. r1 refers to the radius of circle1 and r2 refers to the radius of circle2. The distance between circles is calculated on every frame. If (and only if) it is equal to or less than the sum of both radii (r1+ r2), then the two circles must be touching or overlapping each other.
Step 4: Circle-Circle Collision Detection
Here are the important ActionScript for the implementation of the concept above:
minDist = circle1.radius + circle2.radius;
private function check(e:MouseEvent):void {
var distance:Number = Math2.Pythagoras(circle1.x, circle1.y, circle2.x, circle2.y);
if (distance <= minDist) circle2.color = 0x00FFAA;
else circle2.color = 0x00FF00;
}
Step 5: Sample Solution
Here is a sample of the solution. Drag the blue circle towards to the green one. As they overlap, you will see green’s color change. It returns to normal when both circles are not colliding.
I have included the ActionScript implementation below.
package
{
import flash.display.Sprite;
import flash.events.MouseEvent;
/**
* Simple collision between 2 circles
* @author Shiu
*/
[SWF(width = 400, height = 300)]
public class Simple3 extends Sprite
{
private var circle1:Circle, circle2:Circle;
private var minDist:Number;
public function Simple3() {
circle1 = new Circle(0x0055AA, 30); addChild(circle1);
circle1.x = 250; circle1.y = 250;
circle1.addEventListener(MouseEvent.MOUSE_DOWN, start);
circle1.addEventListener(MouseEvent.MOUSE_UP, end);
circle2 = new Circle(0x00FF00, 30); addChild(circle2);
circle2.x = 100; circle2.y = 50;
minDist = circle1.radius + circle2.radius;
}
private function start(e:MouseEvent):void {
e.target.startDrag();
e.target.addEventListener(MouseEvent.MOUSE_MOVE, check);
}
private function end(e:MouseEvent):void {
e.target.stopDrag();
e.target.removeEventListener(MouseEvent.MOUSE_MOVE, check);
}
private function check(e:MouseEvent):void {
var distance:Number = Math2.Pythagoras(circle1.x, circle1.y, circle2.x, circle2.y);
if (distance <= minDist) circle2.color = 0x00FFAA;
else circle2.color = 0x00FF00;
}
}
}
Conclusion
As you can see, the general principle of collision detection is to use mathematical formulae to check for overlappings between different shapes. Vector mathematics plays an important role too. Next to come is collision between a circle and a line. Thanks for reading and see you soon.
View full post on Activetuts+

Collision detection is a branch of algorithms that checks whether two shapes overlap. If you build physics or action games with ActionScript, you will certainly not escape acquaintance with this topic. This is the first of the series regarding collision detection. In this Quick Tip, we shall look at ActionScript’s built-in collision detection method,
hitTestObject(), and write our own to detect overlap between two circles.Final Result Preview
This is the final SWF we will create in this Quick Tip. Click the blue circle and drag it towards the green one. Once they overlap, the green circle will change its color; if you remove the blue circle again, the other will return to being green.
Step 1: Bounding Box Checks
Those who are aquainted with ActionScript 2.0 will definitely recognise the method,
hitTest(). This command checks for overlap between two shapes, or between a shape and a single point. In ActionScript 3.0 it is split into two separate methods:hitTestObject()andhitTestPoint().We shall look at
hitTestObject()first. This commnad generally suits collision detection for box-like shapes (squares, rectangles). A bounding box is drawn around shapes and when these bounding boxes overlap each other,hitTestObject()returns true.Check out the example below. Drag the blue box towards the green one. As they overlap, the green box’s shade darkens.
I attach here the corresponding ActionScript that generates the above presentation.
Boxis a custom written class to easily generate square shapes. I’ve included the classes in the source folder; do refer to them. The important script for collision detection is highlighted below.package { import flash.display.Graphics; import flash.display.Sprite; import flash.events.MouseEvent; /** * Simple hitTest with boxes * @author Shiu */ [SWF(width = 400, height = 300)] public class Simple extends Sprite { private var box1:Box, box2:Box; public function Simple() { box1 = new Box(0x0000FF); addChild(box1); box1.x = 250; box1.y = 250; box1.addEventListener(MouseEvent.MOUSE_DOWN, start); box1.addEventListener(MouseEvent.MOUSE_UP, end); box2 = new Box(0x00FF00); addChild(box2); box2.x = 100; box2.y = 50; } private function start(e:MouseEvent):void { e.target.startDrag(); e.target.addEventListener(MouseEvent.MOUSE_MOVE, check); } private function end(e:MouseEvent):void { e.target.stopDrag(); e.target.removeEventListener(MouseEvent.MOUSE_MOVE, check); } private function check(e:MouseEvent):void { if (e.target.hitTestObject(box2)) box2.color = 0x00AA00; else box2.color = 0x00FF00; } } }Step 2: Shortcomings of Bounding Boxes
However, collision between circles cannot be effectively checked using this command. Check out the presentation below. Drag the blue circle towards the green one. Before the shapes collide, their bounding boxes already overlap and
hitTestObject()is true. We need a more accurate solution.This problem is prevalent not only for collision detection between circles but non-square shapes generally. Observe the diagram below. For organic shapes that are difficult to resolve by polygons, we shall make use of pixel-precise collision detection.
Various inaccurate collision detected through hitTestObject.
Step 3: Distance Between Centers
The solution to this problem is quite simple: we shall measure the distance between the centers of these circles. If the centers get close enough to each other, we shall flag collision as true. But how close is close enough?
Distance between circles.
Observe the diagram above. r1 refers to the radius of circle1 and r2 refers to the radius of circle2. The distance between circles is calculated on every frame. If (and only if) it is equal to or less than the sum of both radii (r1+ r2), then the two circles must be touching or overlapping each other.
Step 4: Circle-Circle Collision Detection
Here are the important ActionScript for the implementation of the concept above:
private function check(e:MouseEvent):void { var distance:Number = Math2.Pythagoras(circle1.x, circle1.y, circle2.x, circle2.y); if (distance <= minDist) circle2.color = 0x00FFAA; else circle2.color = 0x00FF00; }Step 5: Sample Solution
Here is a sample of the solution. Drag the blue circle towards to the green one. As they overlap, you will see green’s color change. It returns to normal when both circles are not colliding.
I have included the ActionScript implementation below.
package { import flash.display.Sprite; import flash.events.MouseEvent; /** * Simple collision between 2 circles * @author Shiu */ [SWF(width = 400, height = 300)] public class Simple3 extends Sprite { private var circle1:Circle, circle2:Circle; private var minDist:Number; public function Simple3() { circle1 = new Circle(0x0055AA, 30); addChild(circle1); circle1.x = 250; circle1.y = 250; circle1.addEventListener(MouseEvent.MOUSE_DOWN, start); circle1.addEventListener(MouseEvent.MOUSE_UP, end); circle2 = new Circle(0x00FF00, 30); addChild(circle2); circle2.x = 100; circle2.y = 50; minDist = circle1.radius + circle2.radius; } private function start(e:MouseEvent):void { e.target.startDrag(); e.target.addEventListener(MouseEvent.MOUSE_MOVE, check); } private function end(e:MouseEvent):void { e.target.stopDrag(); e.target.removeEventListener(MouseEvent.MOUSE_MOVE, check); } private function check(e:MouseEvent):void { var distance:Number = Math2.Pythagoras(circle1.x, circle1.y, circle2.x, circle2.y); if (distance <= minDist) circle2.color = 0x00FFAA; else circle2.color = 0x00FF00; } } }Conclusion
As you can see, the general principle of collision detection is to use mathematical formulae to check for overlappings between different shapes. Vector mathematics plays an important role too. Next to come is collision between a circle and a line. Thanks for reading and see you soon.
In this tutorial, you will learn how to cast a field of view of a turret guarding a specific location. When an enemy is within the turret's field of view, the turret will shoot at them. Vector math will be used to help in implementing this field of view.
Final Result Preview
Let's take a look at the final result we will be working towards. Click on the turret at the bottom of stage to begin the simulation.
Step 1: Field of View
I’m sure most readers have used cameras. Every camera has a view angle, defined by the type of lens attached. There are narrow and wide view angles. View angles constrain the field of view into a sector. From a top-down position, they look like the diagram below. If you take a picture, eveything within the grayed area will be captured.
The turret's field of view in our simulation is like that of a camera. If there's an enemy within its field of view, a guard will respond (sound an alarm, take aim, shoot, etc).
Step 2: Basic Concept
The diagram above shows the field of view of turret. Usually the angle of view will be equal on both the left and the right. The radius will also be consistent throughout the sector. So to check whether an enemy is within a turret's field of view, these two mathematical conditions can be used:
Step 3: Define Field of View Using Vector
We shall use vector math to help us. In this case, the vectors in consideration are
vLine2andvLine3. We can:Using the formula of dot product between Vectors, we can find the angle sandwiched between two vectors. I have included a Flash presentation above to facilitate your understanding. Click on the buttons at the bottom to scroll through the frames.
Here is the Actionscript in
Vector2D(which I’ve used in previous tutorials, like this one) that does the job. Note that line 257 helps to determine whether the angle is on the negative or positive side. However, this is not going to help us much here as direction is not important. More explanations on this topic in the next part of this series./** * Method to obtain the smaller angle, in radian, sandwiched from current vector to input vector * @param vector2 A vector to bound the angle * @return Angle in radian, positive is clockwise, negative is anti-clockwise */ public function angleBetween(vector2:Vector2D):Number { //get normalised vectors var norm1:Vector2D = this.normalise(); var norm2:Vector2D = vector2.normalise(); //dot product of vectors to find angle var product:Number = norm1.dotProduct(norm2); product = Math.min(1, product); var angle:Number = Math.acos(product); //sides of angle if (this.vectorProduct(vector2) < 0) angle *= -1 return angle; }Step 4: Implementation
I have included a presentation below that implements the concept of field of view. Feel free to click and drag the bigger gray circles around. Observe area covered by the field of view indicated by darker dots.
Step 5: Important ActionScript
If you'd like to see the ActionScript for the presentation above, feel free to open up
AppFan.asfrom the source download – it’s commented to facilitate understanding. I shall only include here the important snippet that checks the conditions.I've highlighted the conditional statement that each of the little dots on the stage is evaluated against it to see if its within the highlighted area.
//Calculate the magnitude and angle var vLine2:Vector2D = new Vector2D(b2.x - b1.x, b2.y - b1.y); var vLine3:Vector2D = new Vector2D(b3.x - b1.x, b3.y - b1.y); var ang:Number = Math.abs(vLine2.angleBetween(vLine3)) //Eliminate directional feature of angle var mag:Number = vLine2.getMagnitude(); for each (var item:Ball in sp) { var vParticle1:Vector2D = new Vector2D(item.x - b1.x, item.y - b1.y); //Checking if falls within sector //Condition: Magnitude less than mag, angle between particle ang vLine2 less than ang if(Math.abs(vLine2.angleBetween(vParticle1)) <ang && mag> vParticle1.getMagnitude()){ item.col = 0x000000; } //if outside of segment, original color else item.col = 0xCCCCCC; item.draw(); }Step 6: Variations
To add variation to the use of field of view, we can implement far and near attenuation. In fact, we just went through far attenuation. For far attenuation, enemies that are further away (further than the far attenuation distance) cannot be seen by the turret. For near attenuation, enemies that are too close (less than near attenuation) cannot be seen by turret. This may sound irrational, but imagine the turret sitting on a high cliff while the enemy sneaks right under the cliff.
Okay, perhaps you are not convinced, so here is another example of different use. A guard carries a short sword, a bow and arrows. When an enemy is too far off, he may just want to keep a close eye on him. When the enemy comes within shooting range, he shoots arrows. When the enemy comes too close, he fights with short sword. You may even implement different types of guards: bowmen and swordsmen. Enemies within shooting range are dealt with by bowmen while those at at close range are dealt with by swordsmen.
By understanding the conditions introduced in Step 2, variations can be introduced into our simulation or game.
Step 7: Define Field of View Conditions
I’ve included a Flash presentation below to showcase different cases and their corresponding set of conditions. Click on the buttons to check out the different cases.
Step 8: Programming Field of View Conditions
The following is a snippet of code for implementing the conditions as laid out in Step 7. You may want to view the whole source code in
Region2.asto check out the whole implementation.//Checking done every frame private function move(e:MouseEvent):void { //Calculate Vector from guard to enemy var g_e:Vector2D = new Vector2D(enemy.x - guard.x, enemy.y - guard.y); var angle:Number = r3.angleBetween(g_e); //Conditions var withinSector:Boolean = Math2.degreeOf(Math.abs(angle)) < sector; var withinR3:Boolean = g_e.getMagnitude() < r3.getMagnitude(); var withinR2:Boolean = g_e.getMagnitude() < r2.getMagnitude(); var withinR1:Boolean = g_e.getMagnitude() < r1.getMagnitude(); //Difference example cases if (example == 0) { if (withinSector && withinR3) { t1.text = "Within FOV" } else t1.text = "Beyond FOV" } else if (example == 1) { if (withinSector && withinR3 && !withinR1) { t1.text = "In between \nfar and near attenuation" } else t1.text = "Beyond FOV" } else if (example == 2) { if (withinSector) { if (withinR1) t1.text ="Sword attack" else if (withinR2) t1.text = "Arrow shoot" else if (withinR3) t1.text = "Keep observe" } else t1.text = "Beyond FOV" } } //Swapping example cases in response to changes in context menu private function swap(e:ContextMenuEvent):void { //swap example if (e.target.caption == "Basic FOV") example = 0; else if (e.target.caption == "Far/Near Attenuation") example = 1; else if (e.target.caption == "Observe/Arrow/Sword") example = 2; //Redraw region indicating detection area drawRegion(); }Step 9: Implementation
Here's an implementation of ideas explained in Step 6. Click on the black circle and drag it aroud the stage to check whether it’s sitting within the visible region. Right-click on stage to pop context menu out, then select from "Basic FOV", "Far/Near Attenuation" and "Observe/Arrow/Sword" to check out the different examples.
Step 10: The Scenario
Now to put into context whatever we have learnt, we are going to create a simulation. Here's the scenario:
A turret is stationed at one end of the stage. Its role is to eliminate as many troops that invade its space as possible. Of course, turret will have to see those troops (within field of view) in order to shoot lasers – and bye-bye troops. Since it can only shoot a beam of laser at any instance, it’s going to choose the closest enemy in sight.
On the other hand, troops will try to successfully cross to the other side. They will have to cross a river and, as they do, they will slow down. Now these troops are going to respawn on top of stage whenever they die or go out of stage.
Step 11: Basic Setup
The implementation of this example will be hard-coded. The basic setup is as below. On initialisation we will draw the graphics of elements (river, troops, turret) and position then nicely. On clicking on the purple turret, animation will start. On every frame we will see them animate according to the behaviours of each element.
public function Scene1() { makeTroops(); makeRiver(); makeTurret(); turret.addEventListener(MouseEvent.MOUSE_DOWN, start); function start ():void { stage.addEventListener(Event.ENTER_FRAME, move); } } private function move(e:Event):void { behaviourTroops(); behaviourTurret(); }Below are the variables of this class.
Step 12: Draw and Position River
Drawing and positioning river. Pretty simple.
private function makeRiver():void { river = new Sprite; addChild(river); //Specify the location & draw graphics of river with (river) { x = 0; y = 150; graphics.beginFill(0x22BBDD, 0.2); graphics.drawRect(0, 0, 500, 50); graphics.endFill(); } }Step 13: Draw and Position Troops
Drawing troops will be simple. However, I wanted a "V" formation on troops. So I position the troop at the bottom of "V" first, followed by troops on both sides of its wing. You may want to adjust its center position through
centerand the spacing between troops throughxApartandyApart. Note thattroopsand its correspondingtroopVeloshare the same index. All troops are heading south.private function makeTroops():void { troops = new Vector.<Ball>; //Initiate troops troopVelo = new Vector.<Vector2D>; //initiate velocity //local variables var center:Vector2D = new Vector2D(stage.stageWidth * 0.5, 150); var xApart:int = 20; var yApart:int = 15; //Locating troops & velocities var a:Ball = new Ball; stage.addChild(a); troops.push(a); a.x = center.x; a.y = center.y; //troops heading south var aV:Vector2D = new Vector2D(0, 1); troopVelo.push(aV); for (var i:int = 1; i < 11; i++) { var b:Ball = new Ball; stage.addChild(b); troops.push(b); b.x = center.x + i * xApart; b.y = center.y - i * yApart; var bV:Vector2D = new Vector2D(0, 1); troopVelo.push(bV); var c:Ball = new Ball; stage.addChild(c); troops.push(c); c.x = center.x - i * xApart; c.y = center.y - i * yApart; var cV:Vector2D = new Vector2D(0, 1); troopVelo.push(cV); } }Step 14: Draw and Position Turret
Here, we shall draw, position, and orient the turret and its field of view to face north towards the enemy. Note that the line of sight is facing north.
private function makeTurret():void { //instantiate, locate, orient turret turret = new Sprite; stage.addChild(turret); turret.x = stage.stageWidth * 0.5, turret.y = stage.stageHeight; turret.rotation = -90; turretRot = 2; //rotation speed //Draw turret graphics var w:int = 30; var h:int = 10; turret.graphics.beginFill(0x9911AA); turret.graphics.lineStyle(2); turret.graphics.moveTo( 0, -h / 2); turret.graphics.lineTo(w, -h / 2); turret.graphics.lineTo(w, h / 2); turret.graphics.lineTo(0, h / 2); turret.graphics.lineTo(0, -h / 2); turret.graphics.endFill(); //Setting data for field of view's graphics var point1:Vector2D = new Vector2D(0, 0); var point2:Vector2D = new Vector2D(1, 0); var point3:Vector2D = new Vector2D(0, 0); point1.polar(lineOfSight.getMagnitude(), Math2.radianOf(sectorOfSight)); point2.setMagnitude(lineOfSight.getMagnitude()/Math.cos(Math2.radianOf(sectorOfSight))); point3.polar(lineOfSight.getMagnitude(), Math2.radianOf(-sectorOfSight)); //instantiate, locate, orient field of view fieldOfView = new Sprite; addChild(fieldOfView); fieldOfView.x = turret.x; fieldOfView.y = turret.y; fieldOfView.rotation = -90; //draw turret's field of view fieldOfView.graphics.beginFill(0xff9933, 0.1); fieldOfView.graphics.lineStyle(1); fieldOfView.graphics.moveTo(0, 0); fieldOfView.graphics.lineTo(point1.x, point1.y); fieldOfView.graphics.curveTo(point2.x, point2.y, point3.x, point3.y); fieldOfView.graphics.lineTo(0, 0); fieldOfView.graphics.endFill(); }A little detail here on the drawing the line of sight. I’ve included image below for clarification:
Step 15: Troops' Behaviour
Troops will be animated across time. Here's their behaviour. Note that the last two lines of code are commented. If you would like dead troops to be removed from animation, you may uncomment them.
//troops' behaviour private function behaviourTroops():void { //for each troop for (var i:int = 0; i < troops.length; i++) { //If troop reach bottom of screen, respawn on top of screen if (troops[i].y > stage.stageHeight) { troops[i].y = 0; troops[i].x = Math.random() * (stage.stageWidth - 100) + 100; } //if wading through river, slow down //else normal speed if (river.hitTestObject(troops[i])) troops[i].y += troopVelo[i].y*0.3; else troops[i].y += troopVelo[i].y //If troop is dead ( alpha < 0.05 ), respawn on top of screen if (troops[i].alpha < 0.05) { troops[i].y = 0; troops[i].x = Math.random() * (stage.stageWidth - 100) + 100; troops[i].col = 0xCCCCCC; troops[i].draw(); troops[i].alpha = 1; //stage.removeChild(troops[i]); troops.splice(i, 1); //troopVelo.splice(i, 1); } } }Step 16: Turret’s Behaviour
The turret will guard its post by panning its field of view around, but within certain angles. Here, I’ve defined the panning angle to be between -135 and -45 (using Flash angles). If there's an enemy within sight, it will attack it. But if there's more than one enemy, it's going to choose the closest to attack.
//turret's behaviour private function behaviourTurret():void { //rotate turret within boundaries of -135 & -45 if (turret.rotation > -45) turretRot = -2 else if (turret.rotation < -135) turretRot = 2 //shoot closest enemy within sight graphics.clear(); if (enemyWithinSight() != null) { //closest enemy in sight var target:Ball = enemyWithinSight(); target.col = 0; target.draw(); //turns to black & target.alpha -= 0.2; //health deteriorates //orient turret towards enemy var turret2Target:Vector2D = new Vector2D(target.x - turret.x, target.y - turret.y); turret.rotation = Math2.degreeOf(turret2Target.getAngle()); //draw laser path to enemy graphics.lineStyle(2); graphics.moveTo(turret.x, turret.y); graphics.lineTo(target.x, target.y); } //no enemy within sight, continue scanning else { turret.rotation += turretRot } //turn field of view and line of sight of turret according to turret's rotation fieldOfView.rotation = turret.rotation; lineOfSight.setAngle(Math2.radianOf(turret.rotation)); }Step 17: Getting Closest Enemy
The turret will locate the closest enemy in its field of view and react by shooting a laser at it. To see how it finds the closest enemy, check out the ActionScript implementation below.
//return the closest enemy within sight private function enemyWithinSight():Ball { var closestEnemy:Ball = null; var closestDistance:Number = lineOfSight.getMagnitude(); for each (var item:Ball in troops) { var turret2Item:Vector2D = new Vector2D(item.x - turret.x, item.y - turret.y); //check if enemy is within sight //1. Within sector of view //2. Within range of view //3. Closer than current closest enemy var c1:Boolean = Math.abs(lineOfSight.angleBetween(turret2Item)) < Math2.radianOf(sectorOfSight) ; var c2:Boolean = turret2Item.getMagnitude() < lineOfSight.getMagnitude(); var c3:Boolean = turret2Item.getMagnitude() < closestDistance; //if all conditions fulfilled, update closestEnemy if (c1 && c2&& c3){ closestDistance = turret2Item.getMagnitude(); closestEnemy = item; } } return closestEnemy; }Step 18: Launching Simulation
You may now press Ctrl + Enter in FlashDevelop and observe this simulation. Click the turret to start the demo below.
Step 19: A Step Further
We can make use of this understanding to:
…and so on.
Hopefully, this will spark some ideas and perhaps help in your next simulation or game.
Conclusion
Thanks for reading. As usual, do drop a comment to let me know if this has been helpful to you. I'll be writing the next tutorial to check out how enemies can stay out of turret's field of view by "hiding" behind obstacles. Stay tuned.
Merry Quizmas! This month, I’m quizzing you on your understanding of two popular formats for data used by web apps: JSON and XML.
Let’s Get Quizzy
Having Trouble?
If you get stuck, take a look at our previous posts: Understanding JSON and AS3 101: XML.
Just So You Know…
This quiz was built with the jQuizzy Quiz Engine by Siddharth, ace reviewer for Envato. jQuizzy is available for purchase over on Codecanyon
Thanks also to Orman Clark and MediaLoot for their graphical contributions to the Activetuts+ Coffee Break Quizzes.
What Would You Like To Be Tested On?
If you’ve got an idea for an Activetuts+-related quiz subject, let us know in the comments!
The holidays are upon us, and we’re feeling festive at Tuts+ this weekend! We’d like to take this opportunity to say a huge Christmas thank you to all our readers, and wish you a very Happy Holiday. Read on for a video message from the HQ team, and a few freebies from around the Tuts+ and Envato network!
A Message from Envato HQ
Although the Tuts+ team is spread over the globe, Envato HQ is where much of the Tuts+ magic happens! It isn’t looking traditionally Christmassy in Melbourne at the moment, but we have a special holiday message from everyone at head office:
Music is Kids Holiday Theme by AudioJungle Author CraigHall
Gift Guides & Freebies!
We also have a couple of exclusive freebies and discounts, just in time for the holidays:
The Christmas Freelance Freedom Comic
The “holiday jingle” comic encapsulates everything that we love and hate about freelancing. Don’t forget to sing along to the “Jungle Bells” theme music as you read it…!
You can also enjoy the whole back catalog of Freelance Freedom comics over at FreelanceSwitch.
AppStorm Giveaways
We have two fantastic competitions running over at the AppStorm network over the holiday period, and there’s still time to get your entry in to stand a chance of winning:
Merry Christmas, and Happy New Year!
All that’s left is to wish you a very happy holiday on behalf of everyone at Tuts+! We hope you’ve enjoyed everything that we’ve had to share this year, and look forward to publishing thousands more top-quality tutorials, articles, freebies, and resources in 2012.
Here’s to another exciting year at Tuts+, and thank you for joining us on the journey!
Twice a month, we revisit some of readers’ favorite posts from throughout the history of Activetuts+. Please enjoy this festive tutorial from Christmas past!
Ever wanted give your Flash design an extra dimension? Using Electric Rain’s brilliant 3D software, this basic tutorial will give you an introduction in using Flash and Swift 3D together to create some fantastic graphics and animations.
Final Result Preview
Let’s take a look at the final result we will be working towards:
Step 1: New Flash File
Create a new Flash file, it doesn’t matter what version of ActionScript you use; we’re only using Flash at the moment to create the graphics to export to Swift 3d.
Step 2: Creating the Graphics
Using whatever tools you feel comfortable with, create the basic shapes of the Santa and his Skidoo. I used the pen and pencil tool to create the basic shapes, the fewer anchor points and detail you use the better. This will speed up the time it takes for Swift 3d to import the objects you have created in Flash, and also make the 3d models easier to modify and render in Swift 3d.
An important thing to know is that Swift doesn’t like gradient fills or strokes created in Flash. So just use single color fills and make sure you delete any strokes/outlines.
Step 3: Exporting Your Graphics
File > Export > Export Image > Adobe Illustrator… I’ve saved my file as “father_xmas.ai”.
Step 4: The Swift 3d Interface
I could produce a whole tutorial on the in’s and out’s of Swift 3d, but just to give you an idea of what Swift 3d is like and how easy it is to use I’ve included an image of the interface. The interface is made up of these main elements …
As this is only a simple beginner’s tutorial we’ll be using most of these tool and functions, but nothing too complicated…
Step 5: Importing Your Graphics
It will take a minute for Swift to import all the graphics and data.
Step 6: Our Imported Graphics
As you can see, our graphics have come in pretty much as we created them in Flash. Swift is good at creating these extrusions on its own using the "Extrusion Editor", but I find it easier to draw in Flash, so I use Flash to create all my Extrusions.
Step 7: Adjusting Our Layout in Swift 3d
First thing we want to do is adjust the size of our layout. In the "Property Tools" change the following settings:
Step 8: Viewing Imported Graphics
The first thing to do is change our first viewport to a "Default Target Camera" View, this allows us to rotate and view our Santa freely in any direction.
These cmd/Ctrl/right-click techniques do take a bit of getting used to, but stick with it and it will soon become second nature to you.
As you can see they are all pretty much the same depth at the moment, we can easily change that, but the first thing to do is name all our objects so we know our arms from our legs!
Step 9: Viewing Objects
I thought it might be worth pointing out how to move your focus point in the "Default Target Camera". This red circle with a green vertical line through it is your camera focus/target point. If you click in the middle of this shape and drag, it will move the target position of your camera.
Step 10: Un-Grouping Imported Graphics
Swift 3d has grouped all our objects and I have 24 objects in my "Hierarchy Menu". First thing to do is "Ungroup" these objects/extrusions. To do this select "Arrange", then "Ungroup". Click anywhere in a viewport and your objects will appear in a list called Extrusion, Extrusion 1, 2, 3 etc…
Step 11: Re-naming Imported Graphics
I know it’s a bit tedious but it will help you later on!
Step 12: Creating Parent and Child Relationships
To parent the foot to the leg for example is easy. Simply drag the RightFoot onto the RightLeg to create the parent child relationship, do the same for the arms, hands and cuffs and the same for the rest of the objects as I’ve done here.
Step 13: Improving the Quality of our Model
This bit is optional but I like to improve the quality of my models. This can increase the file size of the final image or animation, but as ours is relatively simple it shouldn’t matter too much. To do this got to the "Property Tools"
Step 14: Moving and Positioning Objects
You can move your objects into position a number of ways:
Step 15: The Finished 3d Model
This is what I ended up with as my final model in Swift 3D. Father Xmas sitting on a skidoo! I used a couple of the ski supports as handle bars and colored them red. We’re nearly there now, just a few more steps and we’re done.
Step 16: Re-coloring our Model
The files coloring should look pretty much the same as the graphics you created in Flash. However, I tend to re-color them in Swift as I find that they are a bit too glossy for my liking. To change the color of an object..
Do this for all or none of your objects, it’s up to you.
Step 17: Adding a Floor
To add a floor to place your model on you need to create a plane, this will allow the shadows to be cast onto a surface/floor.
Step 18: Lighting
First we want to remove Swift’s default lighting, or if you want you can keep it as is… I just prefer to add my own lighting setup.
Step 19: Adjusting the Lighting
Now we’re ready to create our own lighting. Still in the "Top View":
Step 20: Adding More Lights
OK, we need to create more lights by doing exactly the same as "Step 19". The new light will appear over the top of the light you have just created, so we need to move it to another position.
Make sure the "Lock Spin" button is toggled to "On" This will rotate around a fixed axis.- Make sure you have "Rotation Increment" set to 90 degrees.
- Then simply click drag the second light you’ve created around the trackball.
- Do this 3 times so that you have 4 equal lights around the trackball (Name your lights if you wish …Front, Left, Right, Back).
- Create 1 more light. This will be our top light and will cast the shadows in the scene.
- Make sure the "Lock Vertical" toggle is active and drag it up to the top of the scene.
- With this light you want the "Shadows" to be active.
Step 21: Rendering Santa
If you’re using the trial version you won’t be able to export any of your renderings, but you can screen grab what you have done and save it out as a bitmap and crop it in Photoshop. If you have the full working version, Swift 3d comes with a built in Smart Layer rendering function, which separates our graphics/animations into layers. This means that things like shadows, moving objects and transparency layers are separated onto their own layer to help reduce file sizes and makes editing in Flash easier.
Swift can render to both Vector and Bitmap formats, can export to all the standard .swf, .AI and the .SWFT (Smart Layer) for vector formats and render to .png, .jpeg etc in the bitmap formats.
OK here we go…
Make sure the "Default Target View" is active in the "Scene Editor" (swift will render the active viewport by default).
Step 22: Rendering Santa Continued..
Step 23: Importing Santa into Flash
All done!
Conclusion
In this tutorial I’ve shown you the basics of using Flash and Swift 3d together to add an extra dimension to your Flash design work. There’s certainly a lot to cover with Swift 3D and I hope this gives you an idea of what you can achieve using these two pieces of software together. Once you’ve explored the capabilities of Swift 3D I’m sure, like me, you’ll find you use it all the time.
I hope you liked this tutorial, thanks for reading and have avery merry Christmas!
Sometimes you may find yourself needing to modify the behavior of a component for a user input event. This article will explain how to do so by modifying the event object in-flight, before it’s processed by the component. That’s right, you can lie and cheat. In code.
Example
Suppose we have a List component for the user to select multiple items from. We have set its
allowMultipleSelectionproperty totrue, which would allow it to have more than one selected items (hence the name). However, this still requires that the user holds down the Ctrl key, while clicking, to select multiple items. When a single selected item is the exception, not the rule, it would be better if we didn’t make the user hold the Ctrl key every time!The component determines whether the user is holding the Ctrl key by examining the
ctrlKeyproperty of the MouseEvent event object. In the above example, we’re tricking the component, by making it appear that the Ctrl key is pressed.Let’s look at how this is done…
Step 1: Set Up the Flash Document
If you already know how to create Flash applications (you probably do) you can skip reading this step, but keep in mind that the existence of an instance of a List component is assumed in next steps. Just in case, let’s briefly explain the creation of the project.
Create a new FLA (here named htefExample.fla) and a new document class ActionScript file (here named htefExample.as).
Set the properties of the FLA file and link the document class.
The width of the FLA is set to 300, the height to 200 and the ‘Class’ input field is set to ‘htefExample’”.
Drag a List component from the Components panel to the Library.
In the Library the List symbol and its assets are contained.
Write the document class (htefExample.as).
package{ import flash.display.Sprite; import flash.events.MouseEvent; import fl.controls.List; import fl.data.DataProvider; public class htefExample extends Sprite{ private var list:List; function htefExample(){ // create an instance list = new List(); // and set some properties list.width = 200; list.x = 50; list.y = (200-list.height)/2; // set allowMultipleSelection list.allowMultipleSelection = true; // add data list.dataProvider = new DataProvider([{label:"One", data:1}, {label:"Two", data:2}, {label:"Three", data:3}, {label:"Four", data:4}, {label:"Five", data:5}]); // add to display list this.addChild(list); } } }Step 2: Add an Event Listener to the Capturing Phase
The signature of the addEventListener method is:
addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):voidTo add a listener to the capturing phase, set the third parameter (useCapture) to true.
Step 3: Define the Contents of the Listener Function
In the body of the function, set the
ctrlKeyproperty totrue.private function hackMouseListener(e:MouseEvent):void{ // set ctrlKey property e.ctrlKey = true; }How It Works
Flash Player has a model for dispatching events and calling event listeners called the event flow. For display-related events, the Player doesn’t dispatch the event directly to the target object, but instead injects it at the top-level display object: the stage.
We can visualize the event traveling from the stage down the hierarchy to the target object. This is called the capture phase.
At the target, the event is in the target phase.
Then, the event ‘bubbles up’ back to the stage. This is the bubbling phase.
The Flash Player event flow.
This imaginary trip determines the order in which the listener functions are called. The
useCaptureparameter in theaddEventListenermethod states our desire about which direction we want our function to be activated: on the capturing way down (value:true) or bubbling way up (value:false– the default).What is interesting is the fact that the event object that is passed as an argument to the listener functions is the same one. So, if we change some of its properties, the listeners further down the event flow will get the same object, now modified!
In the example above, when we registered the
hackMouseListenerfunction to use the capture phase, we made sure that we’ll get the event on its “way down”, so to speak. That function will be called before the list’s listeners which are registered to the target/bubbling phase on the component itself. When the list’s code inspects thectrlKeyproperty it will find that it is set totrue, indicating that the user pressed the Ctrl key.Or did he?
Conclusion
You now know how to make a List component multi-select with just a simple event listener. You can use this on other list-based components like DataGrid. Don’t forget to set the
allowMultipleSlectionproperty.More importantly, however, is that (hopefully) you’ve learned something new about the Flash event flow, about the
useCaptureparameter, event phases and how to use this marvelous (and a bit unconventional) method to bend events to your needs.Hope you enjoyed it. Thank you for reading!
When a user first opens up a Flash game, their initial impression is based upon the menu that they see. Unfortunately, many games’ menus are dull, plain and static. This is terrible news! A lot of players will just close the game before even playing it, and move on to another. Don’t let this happen to you!
Final Result Preview
Take a look at the menu we’ll be building:
Obviously, in a full game, the different menu screens would contain different buttons, text, and submenu items!
Introduction: What is a Dynamic Menu?
Before we learn what a dynamic menu is we must first learn what a static menu is.
A static menu can be described by the definitions of the two words it is made up of: “static”, meaning lacking in change, and “menu”, meaning a list of available options or choices. Therefore a static menu has an interface of options or choices that is lacking in change.
Conversely, the word “dynamic” means to continuously cause change within a system or process. So in the simplest terms a dynamic menu continuously updates the interface of given options or choices.
Step 1: Setting Up
The first thing that we are going to need to create is a new Flash File(ActionScript 3.0), set its width to 650px and height to 350px, and set the frames per second to 60. Instead of changing the background color leave it as white; later on in the tutorial we will create a background.
Now that we have the basic Flash File set up we can save it; you can name yours whatever you please. I just named mine MenuAccordion.fla.
In the next section we will create the eight MovieClips required for the menu; here is a list of all the colors and their hexidecimal codes that will be used throughout the tutorial:
#FFFFFF#E8A317#FBB917#1569C7#1389FF#347235#3E8F1B#990000#C10202#222222Step 2: Creating the MovieClips
To start off we need to create one main background color, four “bar” MovieClips (these are the ones that will be clicked on) and four background MovieClips (these will slide out after a bar is clicked).
First, right-click the stage and choose Grid, then select Show Grid – by default it will create a 10px by 10px square grid accross the stage. To make your life easier right-click again and select Snapping > Snap to Grid. Now we are ready to start drawing!
Select the Rectangle tool and draw a Matte Grey background over the whole stage. Name the layer Background and lock it. Next, create a new layer and name it Menu. Your timeline and stage should look something similar to this now:
Next we will create one bar MovieClip; to make things easier we will just duplicate it to form four MovieClips and change the color of each.
Select the rectangle tool once again, and draw a 30px by 350px rectangle with no stroke. Right-click the fill and select Convert to Symbol…. Name it goldBar, make sure the type is MovieClip and the registration point is in the top-left corner. Double-click the MovieClip on the stage to edit it.
Right-click the first keyframe in the timeline and go to actions, type in a simple
stop();command to prevent the MovieClip from cycling through frames. Next, right-click the second frame and select Insert Keyframe. It is up to you what you would like to write in each fill; only thing to remember is that if your are writing on a 90 degree angle the text may appear invisible if you have the text set to dynamic. Personally I just broke apart the text until it became a fill, and I drew an arrow that was pointing opposite directions on each frame:Now that we have one bar completed we can right-click it in the library and select Duplicate Symbol…. Make three copies of it and name them blueBar, greenBar and redBar, respectively. Then just edit their fill colors and change the text. Voila! We have four bar MovieClips.
Now we can begin on the background MovieClips which we will create and duplicate in the same way. Select the rectangle tool again and draw a rectangle of 560x350px. Convert it to a symbol, name it goldBackground, and make sure that the type is a MovieClip and the registration is in the top-left corner. Then just duplicate it three times and name the new MovieClips blueBackground, greenBackground and redBackground respectively.
Your rectangles should look very simple, like this:
There is only one more MovieClip to create, I promise! Go to the Insert menu and select New Symbol; name it menuAccordionMC, set the type to MovieClip and put the registration point in the top-left corner (because our last MovieClips had this too). Next, check the box that says Export for ActionScript: the class name should be MenuAccordionMC with the capital at the beginning.
Step 3: Positioning the MovieClips
In the previous section we created all the MovieClips required, and now we need to position them!
Delete any MovieClips on the stage if they are on still there. Open your menuAccordionMC from the Library, and create seven more layers in its timeline. Now name them in the following order from top to bottom:
Now drag and drop each MovieClip from the library to its corresponding layer. The easiest way to position all of these will be to lock all of the layers besides the one with the MovieClip you are currently positioning.
Start with the goldBar and set its x and y coordinates to (0,0). Next the blueBar with the coordinates (30,0), then the greenBar with (60,0), and finally the redBar with (90,0).
Time for the backgrounds: the goldBackground‘s coordinates are (-530,0), the blueBackground‘s coordinates are (-500,0), the greenBackground‘s coordinates are (-470,0) and the redBackground‘s coordinates are (-440,0).
Your MovieClip should look like this now, and the (0,0) coordinate should be in the top-left corner of the goldBar MovieClip where the white plus is in the image:
Step 4: Identifying the MovieClips
Before we can begin coding there is one more thing we have to do: give the eight inner MovieClips instance names.
Open up the the menuAccordionMC for the final time then select each MovieClip and make its instance name the same as its MovieClip name. So goldBar’s instance name would be goldBar, greenBackground’s instance name would be greenBackground, and so on. After this is done we can begin the coding, which is fairly easy to understand!
Step 5: Setting Up the Classes
Go to your Flash file’s properties and name the document class MenuAccordion. Now create a new ActionScript 3.0 file and put the following code in it and save the file as MenuAccordion:
package { import flash.display.MovieClip; import flash.events.Event; public class MenuAccordion extends MovieClip { public var menuAccordionMC:MenuAccordionMC = new MenuAccordionMC(); public function MenuAccordion() { addChild(menuAccordionMC); } } }Here, we first import what we will need (in this case just the MovieClip and Event classes). Next we add the variable for our menuAccordionMC, then in the constructor we attach the MovieClip to the stage at (0,0).
That is all the code we will need for the document class; now let’s create a new ActionScript 3.0 file for the MovieClip and save it as MenuAccordionMC.as.
To set up the MenuAccordionMC class, input the following code – I will explain the variables and event listeners shortly:
package{ import flash.display.MovieClip; import flash.events.Event; import flash.events.MouseEvent; public class MenuAccordionMC extends MovieClip{ public var activeColor:String = new String(); public var speed:Number = new Number(); public function MenuAccordionMC(){ activeColor = "none"; speed = 10; addEventListener(MouseEvent.CLICK, accordionClick); addEventListener(Event.ENTER_FRAME, accordionMove); } } }First thing to notice is that we have imported the MouseEvent: this is very important because without it our mouse click will have no effect. As for the two new variables: activeColor is just a simple string to tell us which color is currently in use, and speed is how many pixels the backgrounds shift every frame.
The first event listener is for a MouseEvent.CLICK and will call the function accordionClick when our menu is clicked anywhere. The second event listener adds the function accordionMove and will be called every frame.
Now we will create the two functions for the event listeners. Place the following code right after the closing curly brace for the constructor.
public function accordionClick(event:MouseEvent):void { } public function accordionMove(event:Event):void { }The two classes are now set up, so it’s time to start putting code in these functions!
Step 6: The accordionClick Function
This function is relatively easy and only has an if, else statement in it. Begin by writing the following in the function:
if(event.target.currentFrame==1){ }else{ }Many people are unfamiliar with event.target, so I will briefly explain it. In a nutshell, it just directs the code to the target of the the event – so if the blueBar is clicked, event.target is equal to blueBar.
This means that the if statement checks to see whether the bar’s currentFrame is equal to 1, and if so it executes that code; if not, it will execute the code in the second curly brackets. We can continue now and change the if, else statement to the following:
if(event.target.currentFrame==1){ event.target.gotoAndStop(2); activeColor = event.target.name; }else{ event.target.gotoAndStop(1); activeColor = "none"; }The new lines are very basic: the target’s currentFrame is changed to the second or first frame and the activeColor variable is set to the target’s name or it is set to “none”. That is all the code needed for the accordionClick function.
Step 7: The accordionMove Function
Alright, this is where all the magic happens! This is the endgame and its a long stretch to the finish, but if you follow the final instructions correctly you will have a working accordion menu!
First thing we need to add to the function is a switch case, which will eventually include all of the if statements required for this to run smoothly:
switch (activeColor){ case "none": break; case "goldBar": break; case "blueBar": break; case "greenBar": break; case "redBar": break; }This switch case corresponds to the variable activeColor that is set during the accordionClick function. Now let’s start with the easiest part of this case statement, case: none:
if(this.goldBackground.x>=-530){ this.goldBackground.x-=speed; } if(this.blueBackground.x>=-500){ this.blueBackground.x-=speed; } if(this.greenBackground.x>=-470){ this.greenBackground.x-=speed; } if(this.redBackground.x>=-440){ this.redBackground.x-=speed; } if(this.blueBar.x>30){ this.blueBar.x-=speed; } if(this.greenBar.x>60){ this.greenBar.x-=speed; } if(this.redBar.x>90){ this.redBar.x-=speed; }(Editor’s Note: You may argue that this code is not neat enough for practical use. See the comments of the other tutorial in this series for a discussion about this!)
All that the none case does is check whether any of the MovieClips’ x-positions are greater than their original ones, if they are it moves them left until they no longer are greater than their original x positions.
The next case, goldBar, does something similar. It moves all the other bars that are on the right side of it to the right side of the stage and the backgrounds to the bars’ previous x-positions. Then it just switches all the other bars’ currentFrame properties to 1 (so that the arrows point in the opposite direction):
if(this.goldBackground.x<0){ //Moves The Bars & Backgrounds this.goldBackground.x+=speed; if(this.blueBar.x<560){ this.blueBar.x+=speed; } if(this.blueBackground.x<30){ this.blueBackground.x+=speed; } if(this.greenBar.x<590){ this.greenBar.x+=speed; } if(this.greenBackground.x<60){ this.greenBackground.x+=speed; } if(this.redBar.x<620){ this.redBar.x+=speed; } if(this.redBackground.x<90){ this.redBackground.x+=speed; } //Checks if any other bar's currentFrame is 2, if it is it switches it to 1 if(this.blueBar.currentFrame==2){ this.blueBar.gotoAndStop(1); }else if(this.greenBar.currentFrame==2){ this.greenBar.gotoAndStop(1); }else if(this.redBar.currentFrame==2){ this.redBar.gotoAndStop(1); } }All right, we have two out of the five cases complete. The next three cases work the same as the goldBar – with one exception. They move any backgrounds that are open to the left of them back to their original position and shift themselves back to their original position.
Here is the blueBar case:
if(this.blueBackground.x<30){ this.blueBackground.x+=speed; if(this.greenBar.x<590){ this.greenBar.x+=speed; } if(this.greenBackground.x<60){ this.greenBackground.x+=speed; } if(this.redBar.x<620){ this.redBar.x+=speed; } if(this.redBackground.x<90){ this.redBackground.x+=speed; } if(this.goldBar.currentFrame==2){ this.goldBar.gotoAndStop(1); }else if(this.greenBar.currentFrame==2){ this.greenBar.gotoAndStop(1); }else if(this.redBar.currentFrame==2){ this.redBar.gotoAndStop(1); } } if(this.blueBar.x>30){ this.blueBar.x-=speed; if(this.goldBackground.x>-530){ this.goldBackground.x-=speed; } if(this.greenBar.x<590){ this.greenBar.x+=speed; } if(this.greenBackground.x<60){ this.greenBackground.x+=speed; } if(this.redBar.x<620){ this.redBar.x+=speed; } if(this.redBackground.x<90){ this.redBackground.x+=speed; } if(this.goldBar.currentFrame==2){ this.goldBar.gotoAndStop(1); }else if(this.greenBar.currentFrame==2){ this.greenBar.gotoAndStop(1); }else if(this.redBar.currentFrame==2){ this.redBar.gotoAndStop(1); } }The only thing new about this case is the second main if statement; this is for when another background was already open, it performs a check to see which one and then it moves it back just like the “none” case, then it changes the frames on the other bar MovieClips.
The final two cases work in exactly the same way; the only difference between the three of these is the positions where each bar is being moved to and where its background is being moved to.
Here are the final two cases:
if(this.greenBackground.x<60){ this.greenBackground.x+=speed; if(this.redBar.x<620){ this.redBar.x+=speed; } if(this.redBackground.x<90){ this.redBackground.x+=speed; } if(this.goldBar.currentFrame==2){ this.goldBar.gotoAndStop(1); }else if(this.blueBar.currentFrame==2){ this.blueBar.gotoAndStop(1); }else if(this.redBar.currentFrame==2){ this.redBar.gotoAndStop(1); } } if(this.greenBar.x>60){ this.greenBar.x-=speed; if(this.goldBackground.x>-530){ this.goldBackground.x-=speed; } if(this.blueBar.x>30){ this.blueBar.x-=speed; } if(this.blueBackground.x>=-500){ this.blueBackground.x-=speed; } if(this.redBar.x<620){ this.redBar.x+=speed; } if(this.redBackground.x<90){ this.redBackground.x+=speed; } if(this.goldBar.currentFrame==2){ this.goldBar.gotoAndStop(1); }else if(this.blueBar.currentFrame==2){ this.blueBar.gotoAndStop(1); }else if(this.redBar.currentFrame==2){ this.redBar.gotoAndStop(1); } }if(this.redBackground.x<90){ this.redBackground.x+=speed; if(this.goldBar.currentFrame==2){ this.goldBar.gotoAndStop(1); }else if(this.blueBar.currentFrame==2){ this.blueBar.gotoAndStop(1); }else if(this.greenBar.currentFrame==2){ this.greenBar.gotoAndStop(1); } } if(this.redBar.x>90){ this.redBar.x-=speed; if(this.goldBackground.x>-530){ this.goldBackground.x-=speed; } if(this.blueBar.x>30){ this.blueBar.x-=speed; } if(this.blueBackground.x>=-500){ this.blueBackground.x-=speed; } if(this.greenBar.x>60){ this.greenBar.x-=speed; } if(this.greenBackground.x>=-470){ this.greenBackground.x-=speed; } if(this.goldBar.currentFrame==2){ this.goldBar.gotoAndStop(1); }else if(this.blueBar.currentFrame==2){ this.blueBar.gotoAndStop(1); }else if(this.greenBar.currentFrame==2){ this.greenBar.gotoAndStop(1); } }And with that all of the coding is complete for the accordion!
Conclusion
Right now you should be admiring your hard work and its magnificent result, but if you are wondering how to take the accordion to the next level and add more bars, then just remember the following:
Thank you for taking the time to read this article, I hoped you enjoyed it!
Here’s an present for our Facebook fans: a new Facebook Fan Bonus tutorial! In this month’s beginner-level tutorial, you’ll learn how to use the Input.as class to create smooth keyboard-driven movement.
Final Result Preview
Here’s a look at the type of keyboard movement you’ll learn to create in the tutorial:
As Cristian Bote, the author, describes it:
Download This Fan Bonus Now!
All you have to do is Like us…
Not On Facebook?
Don’t worry, the tutorial will be posted on Activetuts+ in a month’s time!
It’s time for another Premium tutorial! In this mammoth post, James Tyner will introduce you to Standing Wave 3, an excellent AS3 library for dynamically generating or manipulating sounds in Flash.
Premium Preview
Let’s take a look at what you’ll be building in this tutorial:
You’ll add each section of the above SWF step by step, learning the main features of Standing Wave 3 as you go. Quoting from the tutorial:
If you’re not yet a Premium member, you can still read the first few steps of the tutorial. Members can, of course, access the full thing right away!
Active Premium Membership
We run a Premium membership system which periodically gives members access to extra tutorials, like this one! You’ll also get access to Psd Premium, Vector Premium, Audio Premium, Net Premium, Ae Premium, Cg Premium, Photo Premium, and the new Mobile Premium too. If you’re a Premium member, you can log in and download the tutorial. If you’re not a member, you can of course join today!
Also, don’t forget to follow @envatoactive on twitter and grab the Activetuts+ RSS Feed to stay up to date with the latest tutorials and articles.
In this tutorial I’ll walk you through the steps required to install and use the TextArea component as an alternative to Flash’s native TextField class, and show you how to detect mouse roll over/out events on hyperlinks. I’ll also talk about how you can call custom functions and pass different data types as arguments.
Background
The native TextField class was the first to support text scripts in Flash projects. With TextField, you could support dynamic and static text, as well as the input type to allow user interactivity. It also supported a (very limited) selection of HTML tags for styling your scripts – but when comparing this narrow availability of HTML support in TextField to what is possible with regular HTML files being used within browsers, Flash developers felt the extreme lack of flexibility when dealing with text.
In 2009 when TLFTextField was introduced, developers were hoping to see some solutions – but these didn’t appear. Today, with the TextArea class, you can do what you always wanted with your text blocks. Functionalities like detecting roll over/out on href links, calling custom functions from text blocks, creating anchor links, loading custom created tags like video players, slideshow, and buttons: these are all now possible with TextArea.
Final Result Preview
The following simple no-frills demo will present how custom functions are called on hyperlinks. This is what you’ll build in the next 30 minutes:
Step 1: Set Up the Environment
TextArea can be used in any IDE that compiles AS3 – like Flash Builder, CS pro versions and FlashDevelop – which means it’ll work across Flash platform (in Flex, AIR and AS3-only web projects). Different IDEs each have a somehow similar but unique approach to how you compile your project, and due to this diversity it’s sometimes frustrating, especially for beginners, to work with AS3 tutorials because the author may prefer Flash Builder while the learner is accustomed to work with the CS IDE.
To solve this problem, I will try to explain the usage of TextArea independent of the IDE. So, the first step is to set up your environment. No matter which IDE you’re using, just open it and create a new AS3 project, then save it somewhere on your computer.
Create a document class, name it Main.as, and add a trace call to output Hello World.
package { import flash.display.MovieClip public class Main extends MovieClip { public function Main():void { trace("Hello World") } } }Step 2: Download TextArea
TextArea is free to download and to use but be sure to read the license agreements here. Head to doitflash.com and find the download button at the bottom of the home page to download TextArea classes.
Extract the zip file you downloaded, TextArea.zip, to your computer, go to the folder TextArea/Src, and copy the com folder then to the same directory as your document class, Main.as.
By copying the com folder to where you have your project document class, you are letting the IDE find TextArea classes only in this specific project. Alternatively, you could copy the classes to your global class path so that it will always be available to all your projects – to find out more, read How To Use an External Library in Your Flash Projects.
Step 3: Initializing TextArea
After downloading and installing the TextArea, it’s time to initialize it. First you need to import the required classes to the Main class.
Then remove the hello world trace function and enter the following instead.
Test your movie and this time instead of outputting hello world, you’ll see a text field (but not a
TextField!) created for you:As you can see, TextArea works exactly like the native TextField class. All the different settings that you could apply to TextField are true for TextArea also; it’s basically an extension to TextField so it will do everything TextField does, plus more. I’ll talk about these extra features in the next sections.
Step 4: Feeding TextArea With an XML File
To make this tutorial as informative as possible and to make it useable for real world practices, let’s try to feed the TextArea instance with data from an external XML file.
This procress will again be similar to how you load XML data into TextField. First, create your XML file and place it where you have the published SWF file from the previous steps. Make the XML look like the below and save it as “data.xml”:
(So that XML contains HTML in a CDATA section.)
Now get back to your Main.as, which should look like the following:
package { import flash.display.MovieClip import com.doitflash.text.TextArea; public class Main extends MovieClip { public function Main():void { var _textArea:TextArea = new TextArea(); _textArea.wordWrap = true; _textArea.multiline = true; _textArea.htmlText = "Initialize TextArea just like you used to initialize TextField."; this.addChild(_textArea); } } }Add the required imports for xml loading process.
Then replace the whole Main() function with this.
public function Main():void { var loader:URLLoader = new URLLoader(); loader.addEventListener(Event.COMPLETE, onXmlLoaded); loader.load(new URLRequest("data.xml")); function onXmlLoaded(e:Event):void { var xml:XML = new XML(e.currentTarget.data); var _textArea:TextArea = new TextArea(); _textArea.wordWrap = true; _textArea.multiline = true; _textArea.width = 400; _textArea.height = 200; _textArea.condenseWhite = true; _textArea.htmlText = xml.text(); addChild(_textArea); } }The above code loads data.xml – there’s no difference from how you would have done it with a TextField so far.
Step 5: Detecting Mouse Rollover/Rollout
To use the specific features of TextArea, you need to specify a few extra settings when initializing it.
The first and the most important thing to remember about using TextArea is that you should use the
fmlTextmethod for sending text scripts into the instance rather than using the classichtmlText. ThefmlTextmethod will parse scripts using a different approach thanhtmlText; it stands for Flash Markup Language Text.So, in your test project, replace
htmlTextwithfmlTextlike below.The next thing to do is create two custom functions in your document class,
Main.as, which will be called when you rollover or rollout a hyperlink (which we will build later in data.xml). For the sake of this tutorial, these two functions will just trace some outputs, but in the real world, you could do anything you want with these functions – like, say, opening a tooltip window.public function funcOnOver():void { trace("rollOver"); } public function funcOnOut():void { trace("rollOut"); }You should also set some settings while initializing the TextArea instance. Add these lines just after you initialize TextArea.
Also add the following line to the beginning of the Main() function.
To make sure you have written the code in Main.as correctly, below is how your file should look up to now.
package { import flash.display.MovieClip import com.doitflash.text.TextArea; import flash.events.Event; import flash.net.URLLoader; import flash.net.URLRequest; public class Main extends MovieClip { public function Main():void { var refToThis:Object = this; var loader:URLLoader = new URLLoader(); loader.addEventListener(Event.COMPLETE, onXmlLoaded); loader.load(new URLRequest("data.xml")); function onXmlLoaded(e:Event):void { var xml:XML = new XML(e.currentTarget.data); var _textArea:TextArea = new TextArea(); _textArea.holder = refToThis; // indicates the location where you are adding TextArea to stage _textArea.client = refToThis; // must be the location where you have your "allowedFunctions" saved _textArea.mouseRollOverEnabled = true; // enables mouse rollover detection _textArea.funcSecurity = true; // makes sure only function names in "allowedFunctions" are accessible _textArea.allowedFunctions(funcOnOver, funcOnOut); _textArea.wordWrap = true; _textArea.multiline = true; _textArea.width = 400; _textArea.height = 200; _textArea.condenseWhite = true; _textArea.fmlText = xml.text(); addChild(_textArea); } } public function funcOnOver():void { trace("rollOver"); } public function funcOnOut():void { trace("rollOut"); } } }That’s pretty much everything you need to do in your .as file; and the rest will be done in the XML but before we go to XML and create a hyperlink, let’s talk a bit about the above settings.
First we have the holder property which is something that you won’t use in this article but when you go deeper into TextArea to create custom html tags you will need this a lot; for the sake of this tutorial, it’s sufficient for you to know that this property saves the location where you are adding the TextArea instance into the stage.
Then we have the client property. This is the location of – or better to say, this is a reference to – a class where you save all your allowed functions. In this example we use Main.as as the client, but if you have a long list of functions that want to give them the permission to be called from your text scripts, you may prefer creating a separate class for that purpose.
We also have the mouseRollOverEnabled property which is set to
falseby default for performance reasons. If you want to detect mouse roll over/out on your hyperlinks, you must make sure you enable this property.Then we have two security properties: allowedFunctions and funcSecurity. These properties will let you restrict the called functions to the specific ones mentioned in the allowedFunctions method.
Okay, to see the magic, get back to data.xml and and add the following line somewhere inside the CDATA section:
As you see you have created two function calls (one on mouse rollover, one on mouse rollout) and you can do whatever you like with these functions inside your AS3 project.
But this is not all! In the next section I’ll talk about how you can call custom functions and pass different types of data as arguments.
Step 6: Pass Arguments to Functions
Up to now, you have learned how to set the TextArea instance ready for accepting function calls from HTML content which can be placed in external sources like XML. Now we’re going to send different types of arguments along with the calls.
We can send array, object and simple string types. Try adding the following hyperlink somewhere inside the CDATA tag in your XML file:
<u><a href='event:func1()'>SIMPLE CALL</a></u>.<br /> <u><a href='event:func2(some string)'>SEND STRING</a></u>.<br /> <u><a href='event:func3([0,1,2,3,4])'>SEND ARRAY</a></u>.<br /> <u><a href='event:func4({var1:val1;var2:val2})'>SEND OBJECT</a></u>.<br /> <u><a href='event:func5(string,[0,1,2],{var1:val1;var2:val2})'>SEND MIXED ARGUMENTS</a></u>.<br />This will create five function calls in your AS3 project; each function demonstrates how you can send different types of arguments. But remember that this will not work until you actually create these functions inside your AS3 project. To do that, simply add these functions along with the
funcOnOver()andfuncOnOut()functions that you had previously:public function func1():void { trace("no arguments sent"); } public function func2($str:String):void { trace("arguments >> " + $str); } public function func3($arr:Array):void { trace("arguments >> " + $arr); } public function func4($obj:Object):void { trace("arguments >> " + $obj); } public function func5($str:String, $arr:Array, $obj:Object):void { trace("arguments >> " + $str); trace("arguments >> " + $arr); trace("arguments >> " + $obj); }Now you have the calls in XML and the functions are also available in the AS3 project; all that’s left is to give the usage permission to the TextArea instance. Modify the allowedFunctions method of TextArea as so:
Now publish and test your project and try clicking the hyperlinks you created.
Congratulations, you have now learned how to enable mouse rollover and rollout in your text fields, and you know how to create custom functions and call them from within your text blocks.
Conclusion
TextArea extends TextField, adds only 6kb to your project, and can be used as an alternative to TextField. In this tutorial you learned how to initialize TextArea to create simple hyperlinks which can call custom functions inside your AS3 project, and you also learned how to enable mouse rollover and rollout detection on hyperlinks that can call custom functions.
There are many things you can do with these features, like open a tooltip when rolling over a certain hyperlink or create links which call a custom function in your project to navigate through your application pages easier.
I hope you find this tutorial (and TextArea itself) useful!