Travels

Monday, March 23, 2009

Metamorphosis Game Demo: A Study in Bitmap Collision Detection

It's been a while since I mentioned Bitmap Collision Detection and I thought a game demo was in order. As I mentioned earlier Bitmap Collision Detection works by taking a small sample area and seeing if it contains certain colors or if it's colors reach a set threshold. Below is a demo of a game I'm working on called Metamorphosis (inspired by Kafka's work of the same name). To play you simply make your way through the maze of dark objects without touching any of them.

So far this game runs very well. The only problem I've found with it is that if you move the mouse very quickly you are sometimes able to skip over dark sections. This is more due to sample rate rather than the type of the detection. Regardless of it's shortcomings, Bitmap Collision Detection has worked very well in my tests and it has the benefit of creating new levels with minimal code. In the Metamorphosis demo adding a new level is a simple matter of adding a reference to the movie clip containing the level art to an array which keeps track of the levels. The game plays through the level and once it is passed, moves on to the next level on the list without any additional collision detection code.

Tuesday, September 30, 2008

A couple small tips

Recently I had a problem with tweens not completing their animations. I did some testing and found the reason that my tweens were stopping was that they were prematurely garbage collected. The way to fix this is to store a reference to them in a global variable (I used a dictionary). Since the dictionary is a global variable it is not garbage collected, there is always a reference to the tween so it is not garbage collected.

Another small problem I've encountered involves using movie clips as buttons. In order to get the hand icon to appear when the cursor mouses over the movie clip be sure to set the move clip's buttonMode=true.

Wednesday, August 6, 2008

Bitmap Collision Detection


Since I got into bitmap data manipulation I've been coming up with some pretty strange ideas of what to do with it. Bitmap collision detection was something I thought up a couple months ago and was curious to see if it was possible.

The basic idea is that you are taking a snapshot of the screen on every frame (or whenever you want to detect collisions) and then using a very small sample area you check for colors or a range of colors. If you find the colors, then a collision occurs.

I made a basic demo of the idea for you to play with here: http://www.sizzlepopboom.com/toys/bitmap_collision_demo.html

Draw some lines by dragging the circles around. When you mouse over red, green, or blue, it will display a hit detected result. The sample area used for detection is a 12x12 pixel square centered on the mouse. This square is displayed in the demo at the top left.

This demo shows how you can detect not only collisions but colors of collisions. Taking the example of a sidescroller, you could set red to mean fire, blue to mean water, and use green for walls. When a character traveling through the sidescroller encounters one of these colors they could respond by burning up, drowning, or coming to rest after a jump or fall.

The best part about using bitmap collision detection in this sidescroller example is that to create a new level, you could just make new art and not do additional programming. Also as demonstrated in the demo, you can draw new collision areas during runtime.

In order to make the levels look nicer another trick could be used. First you create the final art for the level, then using that as guide to draw a piece of art the same size draw in the collision areas. Then when you play move the two pieces together but detect collision only on the hidden piece. This way you can use any colors you want for the final art and still have the ease of drawing in collision areas.

Bitmap collision detection also has the benefit being independent from the shape of the object being detected. Because there is no need to worry about bounding boxes, complex shapes (spiral) and simple shapes (rectangle) are detected using the same technique.

Using bitmap detection it would be possible to make a sidescroller template that would allow users to add their own custom artwork and make it playable without any coding on the user's part. Bitmap Detection so far hasn't been too processor intensive but should it prove to be a problem, things could be made more efficient by checking every other pixel in the 12x12 sample area.

Tuesday, July 22, 2008

Acessibility in AS3

I've recently finished up a batch of Flash projects that were written using AS3 and needed to be 508 compliant (government-mandated accessibility). Since virtually everything I make at work must be accessible, I made a class to make adding accessibility much easier. Over the past couple of months I've been using it and refining it to handle all the problems I've come across. Now in hopes of encouraging accessibility and simplifying the process of learning how to do it, I'm making my accessibility class open source (GNUv3 license). You can download the accessibility class at:
http://code.google.com/p/accessible/

I've also included some great links are there for finding most anything you might need to know about accessibility. Documentation is also available on the wiki and as a .pdf in the download.

You can see my earlier post on Accessibility for some information on doing accessibility in As2.

If you want to get started in accessibility I highly recommend reading Bob Regan's whitepaper.
It covers AS2 but the issues with accessibility are pretty much the same. Then download my Accessible class for AS3 and look through the links on my wiki. Finally if you need to look up something specific try my Flash Developer Search, it only searches sites with Flash related content and is one of my favorite tools as a Flash Developer.

As far as the features I've given the Accessible class, my favorite is automatic assignment and organization of tabIndexes. It also will format text to be read properly by a screen reader and provides tools such as keyTrace which make looking up key codes very simple. I wrote this class to reduce the problem of spaghetti code that often is created by adding accessibility to existing projects. It does a good job of reducing the lines I need to write but always take time to thoroughly test your projects using a screen reader and the keyboard for navigation. Often it is when I turn of my monitor and try to play one of my games I realize how adding simple things like audio cues can make a game much more easy to play.
You can see some of my accessible projects at the MedlinePlus interactive world map and the games for the National Library of Medicine's exhibit "Against the Odds". Without a screen reader you will be able to navigate using a keyboard, and with an active screen reader you will hear audio cues and descriptions to help you play the games.

Friday, July 11, 2008

WeatherBug API Part 2: A lesson in Regular Expressions

Since my last post I've been working on a WeatherBug widget. I had some extra time to work on it so I thought I'd do something cool and make a series of particle behaviors to illustrate different weather patterns. You can see the finished product here: http://www.sizzlepopboom.com/open_source/weatherBug_2.html

This widget animates the weather patterns, allows you to change location by entering in a zip code, links to the forecast page for that area, and in the event of a weather alert, a button will appear which when clicked will open a page for the weather alerts in that area. (I've been using the recent California fires to test the alert system.) This widget is also accessible to the vision and mobility impaired (still testing to ensure ease of use).

Once I created my particles and their behavior patterns, I needed some way to parse through the 176 documented types of weather conditions that were published by WeatherBug and create appropriate behavior for each condition.

I did this by using a series of regular expressions. I made a dictionary set of regular expressions and the results I wanted them to return if there was a positive match. Then I made a function that goes through each expression in a specific order to test the weather. When it tests positive it stops the testing. This is important because changing the order will change which weather pattern is chosen when certain words are searched for. For example if there is a thunderstorm, I want rain and lightning, while if there is a chance of storms I would want rain alone. To make sure thunderstorm is chosen before my rain behavior I put its regular expression before the one for rain. If no matches are found, I default to sunny weather.


Here is a snippet of code:

//tells what type of particles to make
var behavior:String;
//store the search expressions
var tests = new Dictionary();
tests["snowReg"] = /(snow|sleet|freez|frozen|flurr|snowstorm)/i;
tests["snowReg"].result = "snow";
tests["sunReg"] = /(sun|clear|fair)/i;
tests["sunReg"].result = "sunny";
tests["thunderReg"] = /(thunder|lightning)/i;
tests["thunderReg"].result = "thunder";
tests["rainReg"] = /(rain|storm|drizzle|hurricane)/i;
tests["rainReg"].result = "rain";
tests["cloudReg"] = /(cloud|smoke)/i;
tests["cloudReg"].result = "cloudy";
tests["windReg"]= /(wind)/i;
tests["windReg"].result = "windy";
tests["fogReg"] = /(fog)/i;
tests["fogReg"].result = "fog";
tests["hazyReg"] = /(haz)/i;
tests["hazyReg"].result = "hazy";

//store the order you want to test for weather
var testList = new Array("sunReg","thunderReg","rainReg","snowReg","cloudReg","hazyReg","windReg","fogReg");

for (var i = 0; i<testList.length; i++) {
if (tests[testList[i]].exec(condition)!=null) {
behavior = tests[testList[i]].result;
break;
//if no matches then use the default sunny behavior
} else {
behavior = "sunny";
}
}


Here is the list of documented weather conditions.

As I was working on this widget I noticed two things. First there are more weather patterns than what is on this list ("Light Thunderstorms" and "Smoke" are not on the list). Second when you are testing weather patterns, Flash may cache the information so that you don't seem to be getting accurate information. I noticed this when I was working on the widget and a thunderstorm began, but the widget said it was partially cloudy. Restarting Flash solved the problem. Remember this while developing; once the widget is online the weather info will not be cached.


Another thing I did to make the widget cooler was to do another testing of the weather condition to see the magnitude of the weather. I set up three different magnitudes: light, average, and heavy. Then I searched through the weather conditions for words that indicated the amount (heavy, chance, light, etc.). Using this information I changed the number of particles to use for each weather pattern and so the animations change to match both the weather and the amount of precipitation. For a few weather patterns I further manipulated the magnitude to ensure a better looking animation.
Here is the code for determining the magnitude:

//now test the amount of precipitation

var strength:String;
var amount:Dictionary = new Dictionary();
amount["mildReg"] = /(light|chance|scatter|partly)/i;
amount["mildReg"].result ="mild";
amount["midReg"] = /(mostly|increas)/i;
amount["midReg"].result = "average";
amount["heavyReg"] = /(heavy|hurricane|smoke)/i;
amount["heavyReg"].result = "heavy";
var magnitude:Array = new Array("mildReg","midReg","heavyReg");
for (var j = 0; j<magnitude.length; j++) {
if (amount[magnitude[j]].exec(condition)!=null) {
strength = amount[magnitude[j]].result;
break;
} else {
strength = "average";
}
}
//adjust the amount of particles to use

var numParticles:uint;
switch (strength) {
case "mild" :
numParticles = 50;
break;
case "average" :
numParticles = 100;
break;
case "heavy" :
numParticles = 300;
break;
default :
numParticles = 100;
}

A widget and my updated open source WeatherBug class are available here:
http://www.sizzlepopboom.com/open_source/weatherbug.zip

For more information on how to use regular expressions in flash check out Adobe's Regex page: at:
http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/RegExp.html

To learn more about writing regular expressions here is a good reference:
http://www.regular-expressions.info/reference.html

Finally here is an excerpt from an accessibility class I'm working on. This function prepares text for screen readers by stripping out any tags and capitalizing all lone "a"s and "i"s so screen readers will pronounce them correctly.

//remove any html tags from text so the tags will not be read by the screen reader

function stripTags(htmlText:String) {
var parseText = htmlText;
//Capitalize all a and i for screenreader correctness
parseText = parseText.replace(/\sa\s/," A ");
parseText = parseText.replace(/\si\s/," I ");
//strip tags
return parseText.replace(/<.*?>/g,"");

}

Wednesday, June 11, 2008

WeatherBug API: A lesson in XML


Recently I was asked to make a WeatherBug widget for my company's local intranet. Making the widget was easy enough, I wrote a class that connects to WeatherBug and retrieves the current weather conditions. The tricky part was parsing the XML in Flash since it has many levels of nested nodes and some of those nodes use a namespace. Because it took me a while to work through parsing the XML I've decided to make my code open source.

The WeatherBug class and the .fla file I've made which demonstrates its use may be downloaded here: http://sizzlepopboom.com/open_source/weatherbug.zip
You can see the widget in action here:
http://sizzlepopboom.com/open_source/weatherbug.html

Don't forget to register to get you WeatherBugAPI Key and put it in the WeatherBug.as file otherwise it will not work.

Here's a bit of advice on traversing the XML. There are three main issues I encountered in parsing my XML: 1. How do you access nodes within a namespace?, 2. How do you access nodes with names that use restricted characters?, 3. What's an easy way to traverse the XML without having to know the entire heirarchy of a node?

Here are my answers:
1. To access nodes within a namespace make a namespace object for the XML you are using:
ex: var weatherNS:Namespace = new Namespace("http://www.aws.com/aws");

Then use the format:
namespace::nodeName
namespace::@attributeName
ex: var highTemp = weatherXML..weatherNS::["temp-high"];

Here's a tricky one to show you an attribute "hour-24" within the node "hour":
ex: var riseHour = weatherXML..weatherNS::sunrise..weatherNS::["hour"].@["hour-24"];

2. Use brackets when you are trying to access nodes whose names use reserved characters; in fact if you want you can use brackets for regular names to if you want things to look consistent.
ex: var monthlyRain = weatherXML..weatherNS::["rain-month"];
var link = weatherXML..image["link"]; //without a reserved character

3. Use .. to search through the entire XML document without knowing the exact heirarchy; this is similar to the // used in XPath
ex: var link = weatherXML..image["link"];
var monthlyRain = weatherXML..weatherNS::["rain-month"]; //within a namespace

-When you are using .. be sure to check your results, if there are multiple nodes with the same name within an XML document you might end up with the values of several nodes. When there are multiple nodes, be sure to reference the parent of your target node to ensure you get only its value as a result. See the link tag in the example above.

Hopefully this helps you solve any of the tricky problems you may have using WeatherBug's API. If you do have more questions about using XML in Flash look at the source code I've provided and check out these sites:
http://www.kirupa.com/developer/flashcs3/using_xml_as3_pg1.htm
http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/XML.html

plus there is a whole chapter on XML in Colin Moock's excellent book: Essential Actionscript 3


















Now that you know how to get WeatherBug information into Flash, I'd like to suggest some interesting ways you might be able to use the information.


I come from a background of making games so I've been intrigued with the idea of using real-world information in the form of XML feeds (like WeatherBug's) to control and influence elements within a game. The first thing I thought of was getting the current weather conditions and then replicating them within the world of the game. If you are playing on a rainy day, it will be raining in the game world. This becomes more interesting if you have characters, abilities, paths that are effected by the weather. A character could act more depressed if it's raining. Electric shock powers would be more powerful in very dry weather and more conductive in rainy weather. A path over a bridge could be flooded and inaccessible on rainy days.

Weather could also be used to drive a game's economy (especially in agrarian societies). Good weather means higher yield of crops and lower prices. This way you would have realistic variation in your economy without having to make it very intelligent.

Weather patterns can also be used to make cultural assumptions which can be useful in increasing the immersion of a player in the game. For example, if there has been a heavy snow children in a game might be staying at home instead of at school. The children would act happier being able to play all day and the adults would be more stressed from dealing with increased traffic. If the temperature has been exceptionally high characters in the game might go swimming more and as a consequence be tanner or sun-burnt. As you see, many assumptions can be made by analyzing weather patterns. Using these assumptions in a game environment will create much more realistic patterns of behavior with less complex AI. The use of weather information and the assumptions that can be made by analyzing it will greatly increase the sense of immersion in games as well as the overall cool factor of games seeming to know about the real world around it.

If you are interested in parsing weather conditions with WeatherBug's feed here's a link to all the possible weather descriptions:

http://weather.weatherbug.com/corporate/products/API/Cond_Icon_Desc.txt


There are about 178 possible descriptions so here is my suggestion for parsing the information to something more manageable:

Use indexOf to search a string for:
Cloud

Snow
Frozen
Flurry
Sleet

Rain
Storms
Thunder
Showers

Windy

Fog

Hazy

Clear

Searching for these words ought to give you a fair idea of what the weather is doing in most of the 178 different options. You can use sunny as the default weather.

Monday, March 10, 2008

Yahoo Pipes is Awesome!

For anyone who hasn't tried Yahoo Pipes yet check it out. Pipes allows you to create custom RSS feeds. This is very cool for making complex mash-ups. For example, a friend of mine is looking for an audio position in New York City. I created a simple pipe that uses Google's Job Search and the keyword audio and out came a list of job postings that were mostly relevant. After you make a pipe you can save it to your Yahoo or Google homepage, or access it as an RSS feed, etc.

I heard about Yahoo Pipes from an installation artist who was searching news feeds for different words and then applying that data to a device that dripped paint on a canvas depending on the amount of data received. I was really impressed how easy it was for him to parse so much data down to a single feed.

After playing with Pipes, I think it may be a good solution to an experiment I've been wanting to try. The idea is to get all sorts of real-world data into Flash, use that data to make inferences based on culture and psychology and then have it influence an interactive pet's emotion engine. More simply, if I know it's been rainy and there are a lot of negative keywords in the news the pet could be sadder than usual. If it is close to a cultural, religious, federal holiday the pet could be happier. It is my hope that by creating an emotion engine fed by this data, and then creating a personality that reacts to this data in a certain way, much more realistic virtual characters and environments could be created. Best of all if I use Pipes, I can keep most of the complex parsing out of Flash and use a single feed to get all the information I need.