With the year 2011 at a close, it is time to reflect upon some of the major industry events of the year. A lot happened… we’ll pick out some of the bits and pieces that will be most interesting to browser app and game developers from the world of industry, web, runtimes, operating systems, mobile, and more!
Early in the Year…
In the first part of this year, we saw the release of Android 3.0 “Honeycomb” – a tablet-specific version of the popular mobile operating system. One of the items that this version of the OS was faulted for was its initial lack of Flash Player support. This would later be remedied, but not before a lot of negativity was expressed over the omission. Now that the year is almost at its end, we have a greater understanding of what may have contributed to this delay… and it is a sad reminder that even for large enterprises, resources are far from limitless.
The year was still relatively young when March brought us more interesting developments. Adobe released a project on Labs, code-named “Wallaby”, an AIR application that converts specific FLA files to HTML-based output to perform animations in the browser when Flash is not supported (iOS/WP7), or when HTML output is desired. With Adobe now talking about HTML output directly from Flash Professional, one wonders whether that may be the end result of this prototype? The same month also brought us AIR 2.6 and Flash Player 10.2 for Android, which finally provided Honeycomb tablets with mobile Flash Player.
At this same time, Unity came out with a huge surprise announcement: future versions of the platform tools would be able to compile to SWF in order to support Stage3D in the Flash Player. This announcement opened up a whole lot of existing 3D tooling for Flash developers (especially since Adobe basically has no 3D tooling support for games), and a wider distribution market for current Unity developers as well. Both camps benefit! This was also a clear demonstration of Adobe’s initial strategy around Stage3D: allowing tooling providers and framework engineers to build higher-level components around the core Stage3D APIs.
We also saw an interesting move from Microsoft during this time, with a public effort by the company to convince users of IE6 to upgrade their browser through the ie6countdown.com website. When even Microsoft is running a campaign to get users to upgrade from IE6… well… need I say any more? The website is actually an informative little resource that tracks the decline of the much-despised browser. Here’s looking forward to 0%!
Springtime Advances…
A number of major announcements from Adobe occurred in the Spring, and seemed to center around the 360|Flex conference in Denver. First, Adobe announced Creative Suite 5.5 and an entirely revised release schedule: instead of a new version of the Creative Suite every 18 months, Adobe would be releasing a new version every year to keep tooling relevant in light of the rapid changes taking place on the web and through mobile devices. The announcement was followed a few weeks later by the availability of CS5.5 alongside major updates to Flash Builder, Flash Professional, and the Flex framework.
During 360|Flex, the Adobe Flex team took the stage to make another important announcement: the founding of a new relationship between Adobe and the community in the form of the Spoon project. While Flex had actually been an open source framework for years at this point, there was no organized way in which the community could actually contribute patches and changes in an acceptable fashion. The Spoon project would establish a modified fork (or spoon [oh, now I get it - Ed]) of the codebase that would be community driven. Patches from this fork would then be accepted and integrated into Adobe’s version of Flex as need be. Now that we sit at the close of this year, we can see how vitally important this announcement was to the current situation…
In other Adobe news, Flash Player 10.3 was released and Adobe demonstrated Flash Media Server 4.5 and the implementation of HTTP Live Streaming (HLS) – a form of streaming technology that chunks data into tiny packets for transport over the normal HTTP protocol while also allowing multi-bitrate support for varying devices and connection speeds. This enables FMS to stream video to iOS using the HTML <video> tag. Cool.
One of the bigger announcements that came out of the Google I/O conference this year was the Google Chromebook. The Chromebook is a netbook-class device that is meant to run only browser-based applications, resulting in super-fast startup times and persistent storage in the cloud. Google also announced a new update to Google TV built on Honeycomb. With this, not only would every user get the benefits of an updated Android OS, but the Android Market would be enabled on Google TV devices, allowing developers to target these systems alongside smartphones and tablets. (The lack of Market access on the original Google TV was a huge oversight, in the opinion of many developers.)
One last notable item for Spring was the release of the BlackBerry Playbook. This was a long time coming and provided customers looking for a powerful tablet device an alternative to iOS and Android, since the Blackberry Tablet OS is built upon QNX – known for its stability and overall reliability. Unfortunately, the tablet hasn’t really taken off since the device still doesn’t have a native email client, calendar, or Angry Birds*.
*Yes, I am kidding about Angry Birds. Mostly.
Summer…
A lot happened over the summer months. Flash Builder 4.5.1 was released by Adobe, adding full Flex mobile support for Android, iOS and Playbook. Prior to this, developers needed to use all sorts of tricks to compile applications for all these devices; with 4.5.1, it could all be done through the application GUI. At the same time, Adobe also released AIR 2.7 and mysteriously dropped support for AIR on Linux Desktop with the allowance that Open Screen Partner members may adopt the responsibility to get future versions of the AIR runtime on Linux distributions… although, at the time of writing, nothing has yet come of this. (What’s going on, Adobe?)
In Apple’s world, Mac OSX 10.7 Lion was released – marking what may be the first signs of iOS influence within the desktop operating system with an integrated app store and advanced gesture support. Many were taken aback by the integration of mobile-like elements and concepts into a desktop OS… but since then, Windows appears to be taking a similar path, so this is probably not going to be an isolated idea.
Google took a cue from Adobe’s “Wallaby” project and released their own Flash to HTML conversion tool called Swiffy. This tool differed from “Wallaby” in that it converted SWF files instead of FLA files, and used an entirely different output. Still, the spirit and limitations of both tools are shared: convert old Flash-based content (AS2, limited capability graphics) to something that can be read natively through web browsers.
In July Sony made news due to their joining the Open Screen Project, as well as their release of some interesting Android-based tablets. They also announced the “Adobe AIR App Challenge” to get developers interested in targeting their tablets using AIR 3 betas along with ActionScript Native Extensions (ANE) which targeted specific features of their hardware. With Adobe’s recent new focus on gaming, this was an attractive contest for developers to participate in and it gave users exposure to new possibilities with ANEs in AIR 3.
In strange tablet news, the HP TouchPad with WebOS was released – and then discontinued merely weeks later. This was notable for Flash developers since it was long expected that Adobe was working closely with Palm and then HP to get mobile Flash Player on PalmOS/WebOS devices. Obviously this was never to be. Since that time, users have been able to get Android running on the system, giving the tablet a certain post-mortem desirability.
Anyone who was at Adobe MAX last year will remember a prototype that was shown during the Sneaks called “Project EDGE” – which demonstrated an animation platform targeting HTML5, JavaScript, and CSS3. Adobe Edge Preview 1 was made available for download on Adobe Labs over the Summer and received a rather impressive number of downloads over the first week. While Edge Preview 1 was limited in functionality, it showed great promise.
Around the same time that Edge first saw the light of day, Adobe also launched a new beta resource website, called The Expressive Web. This is a project which Adobe has put together with the goal of creating both a resource and a showcase for some of the most creative and expressive features being added to the web. In addition to highlighting and providing information on 12 new HTML5 and CSS3 features, the site itself makes extensive use of new features such as CSS3 Transitions, CSS3 Transform, Web Storage and more to provide a visually compelling resource for learning about HTML5 and CSS3.
Summer also marked the end of the Adobe AIR Marketplace. The service existed for three years and was a good distribution channel for AIR applications at the time. Since then, a number of other markets have emerged on both mobile and desktop, making Adobe’s offering a bit redundant. One of the most unfortunate things about this closure is that a lot of people had links to the AIR Marketplace for app downloads… these all went dead on August 31st.
Autumn…
A few weeks before Adobe MAX, Microsoft held their BUILD conference at which they released a developer preview of Windows 8. This was the first hands-on of the new Metro interface borrowed from Windows Phone 7, and it was given mixed reviews by the press. The most startling revelation about Metro, though, was that Internet Explorer 10 running in Metro would have no support for browser plugins. Zero. No Flash Player, no Silverlight, no Java… nothing but HTML, CSS, and JavaScript. If a user wants to use any of these plugins, they must exit out of the Metro interface to bring up the “classic” version of IE10 within which plugins like Flash Player would function just as normal.
So now we have two major players in mobile – Apple and Microsoft – saying “no” to mobile Flash Player in favor of a pure HTML experience. (Unfortunately, this goes against the HTML5 spec, since the spec actually now allows <embed> as a valid element!) Even more shocking were the increased rumors that Microsoft may be scaling back hard on Sliverlight moving forward. A rough time for Silverlight developers, indeed.
October brought us Adobe MAX, at which Adobe revealed their new cloud platform, the Creative Cloud, and also a series of touch apps for tablets that aim to bring creative expression to tablet devices. While tablets are commonly seen more as consumer tools, Adobe wants to change that perspective and these tablet applications go some way toward that goal. The Creative Cloud also includes a subscription service to the Creative Suite for about $50 a license. Not too bad – but not everyone wants to be bound to a subscription model. We’ll see what the details are once this is all finalized next year.
There were also a number of new releases timed around Adobe MAX, including Flash Player 11, AIR 3, and Edge Preview 3. The Flash Runtimes included many great new features, among which is Stage3D (formerly Molehill) which allows full GPU-accelerated 3D rendering in the browser. In fact, during the Day 2 keynote, Adobe was able to show off the full Unreal engine (ported to AS3 using Alchemy) running in Flash Player 11. Pretty spectacular. It is also worth noting that practically all of the new touch apps were built with AIR 3.
Even with all of the great announcements for Flash developers, many who left MAX did so with a sense of foreboding… Adobe seemed to be talking up HTML a lot more than Flash – and if you didn’t go to any of the Flex futures sessions, you probably came away with a rather empty feeling. This would play out in the weeks ahead as Adobe made some rather dramatic decisions around the future of the platform.
Winter Falls… Hard
On November 9th, Adobe was scheduled to have its regular analyst meeting to talk about how things were going for the company and lay some groundwork for the direction of the year ahead. Also, as has become custom, everyone expected there to be a bit of restructuring and associated layoffs around the same time. What actually happened is something the industry is still reeling from.
Reports began spreading the evening before that Adobe was set to announce the end of the mobile Flash Player. There were also rumors that the entire Flash Professional team was laid off. Now, rumors are often just that and do not ever actually see the light of day. Many in the community thought that with Adobe being so strong on mobile Flash Player with so many successes that this had to be just another ugly rumor and could not possibly be true.
Unfortunately, this time, the rumor was 100% accurate. A press release and blog post the next morning confirmed that Adobe did intend to drop all future work on mobile Flash Player! Even more alarming was that statements around the dismissal of mobile Flash Player were always framed by statements declaring full support for HTML – even going so far as to point to HTML as the superior technology. This rightly upset a good number of Adobe’s strongest supporters in the Flash and Flex community. In addition, many well-known public figures at Adobe were part of a 750+ company-wide layoff. That’s 10% of the company’s total workforce. Ouch. For more information, I suggest reading Mike Chamber’s post about the situation. Fortunately, the rumor about the Flash Professional team has been declared false.
Later that week Adobe posted more information about their plans for Flex and revealed that the SDK would be contributed to the Apache Foundation and maintained by Spoon, Adobe, and the community at large. Spoon, if you recall, is an organization established in April of this year which had the goal of working with Adobe to open the Flex SDK up for greater community involvement. This is the next logical step in that process. Keep in mind that Flex has actually been open source since 2006… so this has been a lengthy process. Having all of these projects (including PhoneGap) now under Apache is a good move; the Apache Foundation is respected and established. Not only has Adobe contributed the Flex SDK, but also the new generation Falcon compiler (and an experimental version of the compiler called Flacon JS), BlazeDS, and an internal set of testing tools. Flex will not shrivel and die there – Adobe has now made some truly AWESOME contributions to the open source community!
To recap:
Adobe is halting development on the mobile web browser version of Flash Player for Android. This effectively places future versions of Android on the same level as iOS regarding Flash Player.
They are doing this as part of a massive reorg to shift resources to mobile AIR on Android and iOS. They are also focusing on tooling and contributions to open web standards. This is a good thing, overall.
IMPORTANT: Flash through mobile AIR on iOS, Android, Blackberry is going nowhere and is being given more resources. Again, this is what most developers have been working with – not mobile Flash Player in the browser.
Mobile Flash Player 11 is not going away on Android – but if Android handsets want to continue with new versions, they must license the source and compile it for their customers. It will remain available for download and use in the meantime.
Mobile Flash Player source is being licensed to those who wish to compile for their own platforms (like Blackberry does now). So mobile Flash Player may not be going away at all. It depends on the partners.
Adobe is also furthering efforts in HTML through projects like Dreamweaver, jQuery and WebKit contributions, Apache CallBack (PhoneGap), and notably their HTML/CSS/JS motion and interactivity solution Adobe Edge.
Flex is being placed under the Apache Foundation (where PhoneGap will also reside) and will recieve continued (hopefully envigorated) support by the Spoon project, Adobe itself, and possibly other corporate contributors.
An update for mobile Flash Player 11 will be provided for users of Android 4.0 (ICS) and Adobe will continue to support the runtime through security patches and bug fixes.
A mix of good and bad news – the good was absolutely ruined by the way the bad was communicated.
Android 4.0 “Ice Cream Sandwich” was finally released in November. One of the great things about this announcement is that Google has released the source to both ICS and Honeycomb! All of the Android tablet manufacturers out there can finally take advantage of this resource. Even though Flash Player does not currently function with ICS, Adobe has committed to providing an update on Android that will get this working on the new OS.
In Flash runtimes news, a lot of Stage3D resources and demos have been popping up on the web. For a good resource on using Stage3D for games, I would recommend having a look at Adobe Flash 11 Stage3D (Molehill) Game Programming Beginner’s Guide by Christer Kaitila. Amazingly enough, even renounced console publishers such as Square-Enix are having a serious look at Stage3D and have begun demonstrating some games built with these technologies. Flash Player 11.1 and AIR 3.1 were released as well. For those who want a concise, FREE resource to what is new in each of these runtimes; I suggest you check out a set of books published by O’Reilly as part of the Adobe Developer Library: What’s New in Flash Player 11 and What’s New in Adobe AIR 3. (Okay, yes, I am the author of these books but I do not get any royalties from them since they are free!)
The web standards community set up movethewebforward.org which aims to get individuals involved in learning and contributing to standard web technologies in their own way. It’s a particularly good resource for those who may need some guidance along the current web landscape, though it does look like there’s something for everyone here.
In a surprise move by HP, WebOS is going to be contributed to the open source community. It appears that the OS is far from dead, and HP hasn’t ruled out the manufacture of new devices which utilize the WebOS platform. Never count anyone out.
Adobe hosted a small “Flex Community Summit” in San Francisco with 20 Flex developers from the community to discuss the future of the Flex framework. The stated goal of the Summit is to “fix the confusion, provide clarification, and rebuild trust.” Some of the most important takeaways from this discussion include:
There were robust apologies from Adobe executives around how the messaging was handled.
“For years to come Flex is going to be the best way to make applications for the web and desktop.” -Danny Winokur (Adobe)
Adobe’s involvement in future Flex will include “dozens of people”.
Apache Flex will target release runtimes.
AIR, Flex, and Flash Player (non-mobile) will continue to be supported.
“Flash isn’t just focused on gaming and video. Gaming helps push the envelop, but everyone can benefit from the improvements.”
“Adobe is committed to building applications with both Flex and HTML5, not just HTML5.”
“We have every interest that our runtime technology [Flash/AIR] is supported across as many platforms possible.”
Flash Catalyst has been discontinued. Design View in Flash Builder is slated for removal.
The new “Falcon” compiler will be ready for AS3 compilation in 2012. MXML compilation may be 2013.
Falcon is built to allow many back-end compilers such as FalconJS – the idea being that a developer can write in AS3/MXML and compile the code using Falcon, then cross-compile the output for JavaScript or other languages.
There was a great overview of the Apache Software Foundation process by Roy Fielding, an ASF founder.
Adobe will no longer sign RSLs, this will be done through Apache.
Proposal for Apache incubator is almost ready.
A Flex whitepaper will be published in January.
There is still much to be done, but it is a good thing that things are moving forward in a positive way. 2012 will be an interesting year for sure.
We close the year with rumors that Silverlight 5 will most likely be the final version of that runtime. While Silverlight never caught on the way Microsoft originally positioned it (as a “Flash killer”), it is sad that so many developers who invested their time in the technology could be left with an abandoned runtime. Silverlight did much to spur Adobe to action – ramping up development efforts for the runtimes and tooling. Without competing technologies, there is always the possibility of complacency… and that’s good for no one.
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.
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:
Distance between turret and enemy is less than radius.
Angle from turret's line of sight to enemy is less than 30°.
Step 3: Define Field of View Using Vector
We shall use vector math to help us. In this case, the vectors in consideration are vLine2 and vLine3. We can:
Compare magnitudes of vLine2 and vLine3 to validate Condition 1 from Step 2.
Compare angle sandwiched between vLine2 and vLine3 to validate Condition 2 from Step 2.
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.as from 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.as to 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.
private var river:Sprite;
private var troops:Vector.<Ball>;
private var troopVelo:Vector.<Vector2D>;
private var turret:Sprite;
private var fieldOfView:Sprite;
private var lineOfSight:Vector2D = new Vector2D (0, -300); //line of sight facing north
private var sectorOfSight:Number = 20 //Actually half of sector, in degrees
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 center and the spacing between troops through xApart and yApart. Note that troops and its corresponding troopVelo share 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:
Implement a field of view for enemies.
Implement more turrets.
Introduce variation to the field of view as explained in Step 9.
…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.
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:
From everyone at Envato we want to wish you a Happy Holidays and look forward to seeing you all refreshed and ready for another big year in 2012! From Envato HQ to the community, we’ve created a little video to share the holiday cheer. Enjoy!
Wondering what to buy your fellow geek this Christmas? Never fear! You may have left it it a little late, but our holiday gift guides can still come in handy. Here are a few great places to start:
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:
Business Productivity Bundle Giveaway —Each bundle includes a license to Daylite and Billings Pro – it’s the perfect combination for getting your business organised and making money!
The AppStorm Holiday ’11 Video Game Giveaway — In the spirit of this season we’ve hand picked a few critically acclaimed, and award-winning, games released over this year to give away to our readers!
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!
Hey there and welcome to "Flash Video Training Source", a resource for anybody interested in learning more about Adobe's great tool. We feature educational videos, which will help you master Adobe Flash and help you get to know all of its features. We at "Flash Video Training Source" believe that video training and video... more
Why don't you follow us on Twitter and get the latest video tutorials twitted to your account. Just click on the floating twitter bar to your right!