logo
468x60-2-495


  • Home
  • Privacy Policy
  • About
search
top
Jun 1, 2012 Posted on Jun 1, 2012 in Hints and Tips | 10 comments

Citrus-Powered Platformer – Tuts+ Premium

No, this game isn’t powered by oranges and lemons; it’s built using the Citrus Engine, a scalable Flash game engine that takes a lot of the tedious work out of coding a game. In this Premium tutorial, aimed at keen beginners, you’ll learn how to use it to build a simple platformer.


Premium Preview

Let’s take a look at the result we will be working towards:

Ever wanted to make a platformer, but not too keen on writing all the code from scratch? The Citrus Engine doesn’t eliminate code entirely, but it makes it much simpler, with plenty of useful 2D game features built right in. In this tutorial, we’ll use it to build a simple platform game.

Read the Full Tutorial

Premium members can access the full tutorial right away!

If you’re not yet a Premium member, you can still read the first few steps for free.


Tuts+ Premium Membership

We run a Premium membership system which periodically gives members access to extra tutorials, like this one, from across the whole Tuts+ network. If you’re a Premium member, you can log in and read the tutorial. If you’re not a member, you can of course join today!

Also, don’t forget to follow @envatoactive on twitter, circle us on Google+, like us on Facebook, and grab the Activetuts+ RSS Feed to stay up to date with the latest tutorials and articles.



View full post on Activetuts+

banner ad

10 Responses to “Citrus-Powered Platformer – Tuts+ Premium”

  1. Carlos Yanez says:
    June 1, 2012 at 1:18 am

    No, this game isn’t powered by oranges and lemons; it’s built using the Citrus Engine, a scalable Flash game engine that takes a lot of the tedious work out of coding a game. In this Premium tutorial, aimed at keen beginners, you’ll learn how to use it to build a simple platformer.


    Premium Preview

    Let’s take a look at the result we will be working towards:

    Ever wanted to make a platformer, but not too keen on writing all the code from scratch? The Citrus Engine doesn’t eliminate code entirely, but it makes it much simpler, with plenty of useful 2D game features built right in. In this tutorial, we’ll use it to build a simple platform game.

    Read the Full Tutorial

    Premium members can access the full tutorial right away!

    If you’re not yet a Premium member, you can still read the first few steps for free.


    Tuts+ Premium Membership

    We run a Premium membership system which periodically gives members access to extra tutorials, like this one, from across the whole Tuts+ network. If you’re a Premium member, you can log in and read the tutorial. If you’re not a member, you can of course join today!

    Also, don’t forget to follow @envatoactive on twitter, circle us on Google+, like us on Facebook, and grab the Activetuts+ RSS Feed to stay up to date with the latest tutorials and articles.


  2. Michael James Williams says:
    June 1, 2012 at 1:30 am

    It’s a pain to have to change the parameters of a function; you have to change every other call to that function in order to avoid errors. But you can get around this by using just one parameter: a configuration object.


    What It Looks Like

    Here’s a silly example of a function for creating a robot:

    
    
    function generateRobot(arms:int, personality:String):Robot {
    	var robot:Robot = new Robot();
    
    	for (var i:int = 0; i < arms; i++) {
    		//create arm and add it to robot
    	}
    
    	if (personality == "evil") {
    		robot.commands = "Destroy mankind.";
    	}
    	else {
    		robot.commands = "Bake cookies."
    	}
    	return robot;
    }
    
    generateRobot(2, "evil");
    

    Now, here’s the same example, using a configuration object:

    
    
    function generateRobot(conf:Object):Robot {
    	var robot:Robot = new Robot();
    
    	for (var i:int = 0; i < conf.arms; i++) {
    		//create arm and add it to robot
    	}
    
    	if (conf.personality == "evil") {
    		robot.commands = "Destroy mankind.";
    	}
    	else {
    		robot.commands = "Bake cookies."
    	}
    	return robot;
    }
    
    generateRobot({arms:2, personality:"evil"});
    

    I’ve highlighted the lines that require changing; you can see that there’s not much difference.


    Why Bother?

    So if there’s hardly any difference, why would we bother doing it the second way? After all, it actually makes the function a little harder to use; whereas before our IDE would be able to give us this information about the parameters the function expected:

    …now it can only give us this:

    Suppose you want to add a couple more parameters: one specifying the material to use and another to specify what color its laser should be. That’s not too hard, in either case:

    
    
    function generateRobot(arms:int, personality:String, material:String, laserColor:String):Robot {
    	var robot:Robot = new Robot();
    
    	for (var i:int = 0; i < arms; i++) {
    		//create arm and add it to robot
    	}
    
    	if (personality == "evil") {
    		robot.commands = "Destroy mankind.";
    	}
    	else {
    		robot.commands = "Bake cookies."
    	}
    
    	switch (material) {
    		case "wood":
    			//wooden robot
    		break;
    		case "steel":
    		default:
    			//steel robot
    		break;
    	}
    
    	robot.laser = new Laser();
    	robot.laser.color = laserColor;
    
    	return robot;
    }
    
    generateRobot(2, "evil", "steel", "red");
    
    
    
    function generateRobot(conf:Object):Robot {
    	var robot:Robot = new Robot();
    
    	for (var i:int = 0; i < conf.arms; i++) {
    		//create arm and add it to robot
    	}
    
    	if (conf.personality == "evil") {
    		robot.commands = "Destroy mankind.";
    	}
    	else {
    		robot.commands = "Bake cookies."
    	}
    
    	switch (conf.material) {
    		case "wood":
    			//wooden robot
    		break;
    		case "steel":
    		default:
    			//steel robot
    		break;
    	}
    
    	robot.laser = new Laser();
    	robot.laser.color = conf.laserColor;
    
    	return robot;
    }
    
    generateRobot({arms:2, personality:"evil", material:"steel", laserColor:"red"});
    

    So far, still not much of a difference. What if you want your robots to all have red lasers by default? Simple again. Without a configuration object, you just need to change the method signature (the function line), and then you can remove the last argument from the function call:

    
    
    function generateRobot(arms:int, personality:String, material:String, laserColor:String = "red"):Robot {
        //this is all the same
    }
    
    generateRobot(2, true, "steel");    //I removed the last argument
    

    With a configuration object, it’s a little trickier – though not much:

    
    
    function generateRobot(conf:Object):Robot {
    	if (!conf.laserColor) {
    		conf.laserColor = "red";
    	}
    
    	var robot:Robot = new Robot();
    
    	for (var i:int = 0; i < conf.arms; i++) {
    		//create arm and add it to robot
    	}
    
    	if (conf.personality == "evil") {
    		robot.commands = "Destroy mankind.";
    	}
    	else {
    		robot.commands = "Bake cookies."
    	}
    
    	switch (conf.material) {
    		case "wood":
    			//wooden robot
    		break;
    		case "steel":
    		default:
    			//steel robot
    		break;
    	}
    
    	robot.laser = new Laser();
    	robot.laser.color = conf.laserColor;
    
    	return robot;
    }
    
    generateRobot({arms:2, personality:"evil", material:"steel"});   //I removed the last argument
    

    Okay. Now suppose you find that you’re setting almost all of your robots to be evil (I mean, why not?), so it’s actually kind of a pain to write “evil” as a parameter every time. Naturally, you want to set “evil” as the default – but you don’t want to set a default material.

    The only way you can do this, with a regular set of function parameters, is to switch the order of the personality and material parameters:

    
    
    function generateRobot(arms:int, material:String, personality:String = "evil", laserColor:String = "red"):Robot {
    

    Ah, but now you have to switch the order of the arguments round on every single function call!

    
    
    generateRobot(2, "evil", "steel");    //no longer works
    

    A configuration object doesn’t give you this problem. Check it out:

    
    
    function generateRobot(conf:Object):Robot {
    	if (!conf.laserColor) {
    		conf.laserColor = "red";
    	}
    	if (!conf.personality) {
    		conf.personality = "evil"
    	}
    
    	//this is all the same
    }
    
    generateRobot({arms:2, material:"steel"});  //no "personality" parameter? no problem!
    

    Neat! All your old generateRobot() function calls will continue to work, but you can create new calls that don’t bother specifying personality.

    You can even decide to get rid of the personality parameter altogether:

    
    
    function generateRobot(conf:Object):Robot {
    	if (!conf.laserColor) {
    		conf.laserColor = "red";
    	}
    	if (!conf.personality) {
    		conf.personality = "evil"
    	}
    
    	var robot:Robot = new Robot();
    
    	for (var i:int = 0; i < conf.arms; i++) {
    		//create arm and add it to robot
    	}
    
    	robot.commands = "Destroy mankind.";
    
    	switch (conf.material) {
    		case "wood":
    			//wooden robot
    		break;
    		case "steel":
    		default:
    			//steel robot
    		break;
    	}
    
    	robot.laser = new Laser();
    	robot.laser.color = conf.laserColor;
    
    	return robot;
    }
    

    The above version of the function doesn’t refer to conf.personality at all – but you won’t get an error if you still have calls like this:

    
    
    generateRobot({arms:2, personality:"evil", material:"steel"});
    

    Of course, you might get a few confused users if you have calls like this:

    
    
    generateRobot({arms:2, personality:"good", material:"steel"});
    

    …since all robots are now evil. But at least the code will compile.

    For the same reason, you can change the order of the arguments without it mattering at all, and even add in new parameters that don’t do anything yet:

    
    
    generateRobot({material:"steel", laserColor:"green", arms:2, voice:"Mr. T"});
    

    Making It Easier to Set Defaults

    The code for setting the defaults is easy to understand so far, but is going to be very annoying to extend if we need to have lots of parameters:

    
    
    	if (!conf.laserColor) {
    		conf.laserColor = "red";
    	}
    	if (!conf.personality) {
    		conf.personality = "evil"
    	}
    

    Let’s write some more general code to cope with it:

    
    
    	var defaults:Object = {
    		laserColor:red,
    		personality: "evil"
    	}
    
    	for (var key:String in defaults){
    		if (!conf[key]) {
    			conf[key] = defaults[key];
    		}
    	}
    

    That for loop may be a little confusing, so I’ll break it down. First, look at this:

    
    
    	for (var key:String in defaults){
    		trace(key);
    	}
    

    This is a for...in loop, which will output the names of the keys inside the default object:

    
    
    laserColor
    personality
    

    Next, look at this line:

    
    
    trace(defaults["laserColor"]);
    

    This will output red – it’s the same as writing trace(defaults.laserColor).

    Following on from that, look at this example:

    
    
    var example:Object = { demo: "test" };
    trace(example["demo"]);
    trace(example["foo"]);
    

    What do you think this will output?

    Well, example["demo"] is the same as example.demo, which equals "test". But example.foo does not exist, so example["foo"] will return null. This means that !example["foo"] (note the exclamation mark) will be equivalent to true.

    Put that all together, and you should be able to understand why this code works:

    
    
    	var defaults:Object = {
    		laserColor:red,
    		personality: "evil"
    	}
    
    	for (var key:String in defaults){
    		if (!conf[key]) {
    			conf[key] = defaults[key];
    		}
    	}
    

    Give me a shout in the comments if you need a hand!

    I Want More!

    For an even quicker version, try this:

    
    
    function generateRobot(conf:Object = null):Robot {
    	var conf:Object = conf || {};
    	var defaults:Object = {
    		laserColor:red,
    		personality: "evil"
    	}
    
    	for (var key:String in defaults){
    		conf[key] = conf[key] || defaults[key];
    	}
    

    The change in Line 1 (and new Line 2) means that even the conf object itself is optional, so you can just call generateRobot(). (Of course, you’ll need to change the code to deal with the values that don’t currently have defaults.)


    Helping the IDE Help You

    As I mentioned above, the IDE can’t give you any tips about what parameters a function is expecting, if that function uses a configuration object. This is a major drawback, as it can make your code really hard to use; you have to remember which parameters go in the conf object, as well as all of their names and types.

    But we can still display this information to the coder when it’s needed; we just have to do so manually, like so:

    
    
    			/**
    			 * Generate a robot, based on the parameters given.
    			 * @param	conf	Configuration object. Expects:
    				 * arms 		(int)		Number of arms robot should have.
    				 * personality 	(String)	Personality of robot. Can be "evil" or "good". Defaults to "evil".
    				 * material		(String)	What the robot should be made out of. Can be "steel" or "wood" at this time.
    				 * laserColor	(String)	Color of the robot's laser. Defaults to "red".
    				 * voice		(String)	Vocal stylings of robot. Currently not implemented.
    			 * @return	The finished robot.
    			 */
    			function generateRobot(conf:Object):Robot {
    				//
    			}
    

    Now, if I start to write a call to this function in FlashDevelop (my IDE of choice), I see this:

    Sure, it’s a bit of a pain to keep this manually updated, but in many cases it’s worth it.


    Conclusion

    I’m not claiming that you should use a configuration object for every single function you create from now on; just think of it as another useful tool in your arsenal.

    Personally, I find it a particularly useful pattern whenever I’m building the first draft of some set of classes that all need to work together. The added flexibility of a conf gives me so much more flexibility, freeing me up to zip around all the different functions and changing how they call one another, without worrying about breaking the code by inserting or removing a parameter.

    Remember the benefits:

    • It’s easy to add and remove parameters (at either end).
    • It’s easy to set default values.
    • You don’t have to worry about the order of the parameters.

    There are drawbacks to using simple objects like I have, though – especially if you do so in a project that’s past the prototyping stage. Check out the great comments below for more details!


  3. Porter says:
    June 1, 2012 at 2:14 am

    In today’s game critique, Matt Porter takes a look at the new hit tower defense game, Keeper of the Grove, developed by BooblyC.


    Overview

    Tower Defense games have always been a popular genre, especially for the casual / web demographic. This popularity has lead me to playing some pretty amazing Tower Defense games, as well as some horridly bland ones (with more of the latter, unfortunately). I love any game that’s easy to play but hard to master, and a good Tower Defense game is just that. Needless to say, when a well developed TD game comes along, I’m all for it.


    Play the Game

    You can play the game at its full size here.


    Gameplay

    While many Tower Defense games look great, the majority of the non-amazing ones fall flat on their faces due to bland gameplay. It appears to be a popular recipe to use the absolute basic form of a Tower Defense game, and to then polish the hell out of it. Unfortunately, gameplay has, and always will make a game, so extreme polish alone can’t do even this genre any justice.

    Keeper of the Grove critique

    Fortunately, Keeper of the Grove is not only extremely polished, but also pretty well stacked in the gameplay department. It has some serious balancing flaws, in my opinion, but it builds well upon the basic recipe of a Tower Defense game.

    Skills and Upgrades

    Units can be upgraded, and can even branch off into new units as you progress throughout the game. The game uses a “Wisdom Tree” upgrade system, which is where you must first pay to unlock the ability to have each specific higher level unit (within each map, not just once). To my knowledge, this was first seen in the hit Android game “Jelly Wars”, although it could quite possibly have existed long before.

    This system creates a level of complexity where players must balance spending between getting higher level units right off, or taking a slow and steady approach. In addition to the upgrading of units, each stage awards up to three skill points, and unlocking achievements grants additional skill points. These can be spent as you please on upgrading the different types of units, and can even be reset if you’d like.

    Keeper of the Grove critique

    One potential flaw to this, is that players can reset and customize their skills for each stage, which detracts from the developer’s balancing of the map. It’s not a horrible flaw, and it’s one that doesn’t necessarily always get spotted and abused, but it’s definitely something to consider when developing similar systems in your own games.

    Flaws

    There are three major flaws with Keeper of the Grove, in my opinion.

    The first is that there’s a little too much luck involved for a game that should be obsessively balanced and rely mostly on strategy. Keeper of the Grove includes a magic system that allows you to use spells on foes – a nice addition one would think. While these magic spells are very neat, and fun to look at, they severely hurt the balancing of the game. Spells are dropped at random when enemies are defeated, and what spell you get is random as well.

    The spells are actually quite powerful, so having one is a game changer. Perhaps you want to pull off a poison tower within the first few waves (an upgraded, rather expensive unit). Quite often, this won’t work – that is, unless you get an item that helps throw the odds in your favor. Once this happens, you’ve got an early powerhouse setup, and there’s really no way for you to lose.

    To emphasize this as a weakness, even the official video walkthrough shows the player using magic spells early on in levels, thus giving them an advantage that viewers could not replicate without extreme luck.

    I like the magic system; I just think it should be less up to luck, and more controlled. A possible solution would be to show the player how to achieve getting a magic spell, such as by killing X enemies, or surviving Y rounds without losing a crystal. These sub goals would make gameplay interesting, and ensure that magical spells are still in the game, but in a controlled manner. I came up with this system literally as I typed this, so there are obviously better ways to handle the magic system than what made it into the game.

    Keeper of the Grove critique

    The second flaw, in my opinion, is the design of the tutorial levels. The first few levels introduce new units, and don’t allow you to upgrade many. This is fine, as introducing new elements slowly is highly encouraged in game design, but I dislike the way they go about it.

    I’m forced to use Unit X in a level, but the level isn’t really set up in a way that’s perfectly clear about how this new unit is beneficial to me, and in what scenarios. If you’re going to limit the player to using certain units, for the sake of a tutorial level, it should be very clear (especially to a veteran of Tower Defense Games) how that unit should be used in that level, and what its role is.

    I also found the number of waves for the tutorial levels to be a bit high. I don’t want the game to be short, but 20 waves on level four – a tutorial level – seems a bit too long. You want to speed things up at first, and show the player what awesome features your game has to offer. Slow things down too soon, and they may never experience what could have been your hook.

    Keeper of the Grove critique

    The last major flaw in my opinion, is the difficulty curve. Myself and many others reported that the difficulty spikes up pretty early, and out of nowhere. I personally found that the difficulty jumps greatly in level four. It wasn’t unbeatable, but there were new elements and units introduced, and perfecting it seemed nearly impossible (without getting upgrades and returning later) compared to the previous three levels.

    With so much more of the game yet to be exposed to players, I think it’s extremely important to be careful about easing players in. I hadn’t even seen all of my units yet, and I was already faced with something I found to be pretty challenging, and slightly unfair (due to getting magic spells or not).

    Polish

    As far as gameplay polish goes, there’s a lot. The game builds far beyond the original recipe of Tower Defense games, and gives the player a lot to work towards. There’s a nice collection of awards to unlock (achievements), all of which also grant bonus skill points when achieved. In addition, the game also awards a final level that is only obtained by getting all the achievements. Tying these all together is an absolutely fantastic idea, as the player now has incentive to gain achievements.

    Keeper of the Grove critique

    The game becomes potentially easier through the awarded bonus skill points (a chance for struggling players to catch a break), and the average play time of each player is likely increased as they attempt to collect all these achievements to unlock that final level. The game also offers a hard mode from the start, which will likely provide any Tower Defense veteran with a nice challenge. Last but not least, there’s a nice looking bestiary for you to slowly unlock with tower stats, enemy stats, and so on – all viewable from the pause menu: a very nice addition.


    Graphics

    The graphics in Keeper of the Grove are absolutely perfect. No shortcuts were taken in the making of the graphics for this game. They’re cute and casual, extremely polished, and full of charm. Menus are simple and clean as far as navigation goes, but they too are on par with the high quality seen throughout the game. Particle effects add great value to many of the animations, but aren’t overdone. Everything that should be animated is, including interfaces and screen transitions.

    Keeper of the Grove critique

    While the cute style may not be for everyone, there really is little room for improvement graphically. As far as casual web or mobile games go, this is the level of visual polish that developers should strive for.


    Audio

    Much like the graphics in Keeper of the Grove, the audio is extremely well done. It’s clear that the music was professionally made, specifically for this game, and not just grabbed from a random stock music site.

    The music compliments the mood of the game by being quirky, charming, and upbeat. It’s exactly what the developers were looking for, and that’s exactly what you get when you hire a professional to do this kind of work. Many people skip out on professionally done music, but I know from personal experience that it more than pays off, assuming the rest of your game is of a quality that warrants such a thing.

    The sounds effects are of equal quality and style. Everything has a sound, and the project as a whole feels very audio-complete. It’s clear to me that the developers know how to polish a game, and the audio backs this thought up.


    Conclusion

    While Keeper of the Grove isn’t going to break any records or earn too many hardcore fans, it is indeed a perfect example of a remarkably polished game. The game is visually and audibly exactly what players and sponsors alike want, which is a very good thing to take note of if you plan on pleasing both parties any time soon. The gameplay isn’t groundbreaking, but it is well done, and enjoyable.

    All in all, it’s far above your average web game, and that’s not due to luck, so do yourself a favor and take note of what worked here and what didn’t.

    On another note, it might be worth debating whether a game like this is worth polishing to the extreme, or if an original game idea would be a far better use of the effort that went into these amazing graphical and audio assets; what do you think?


  4. Sebastian Bratu says:
    June 1, 2012 at 2:53 am

    In this second part of this mini-series of Premium tutorials, you’ll learn how to use Flash to build a Facebook Graph API application that can create slideshows for your public pages. This second part covers loading album information, and generating and displaying the embed code.


    Premium Preview

    Click to try the app on Facebook.

    Welcome back to our Facebook Flash application tutorial! In this part, we’re going to continue building the Flash interface for building the Facebook slider. The interface will handle choosing an album for displaying in a Facebook tab.

    This application allows you to select a Facebook album or event list from one of your public pages (not your personal profile) and turn it into a slideshow for your page tab. When the users enter your page, they will see photos from your chosen album, with your photo title and description, or event name, date and invites (for the Event tab).

    In future parts of this series, we’ll create the actual Flash slider that does just that; meanwhile we’ll create the generator for the embed code that will reside at the Facebook application URL.

    You’ll need to be logged in to Facebook in order to see this demo: https://apps.facebook.com/activetuts_tabmaker/


    Read the Full Tutorial

    Premium members can access the full tutorial right away!

    If you’re not yet a Premium member, you can still read the first few steps for free.


    Tuts+ Premium Membership

    We run a Premium membership system which periodically gives members access to extra tutorials, like this one, from across the whole Tuts+ network. If you’re a Premium member, you can log in and read the tutorial. If you’re not a member, you can of course join today!

    Also, don’t forget to follow @envatoactive on twitter, circle us on Google+, like us on Facebook, and grab the Activetuts+ RSS Feed to stay up to date with the latest tutorials and articles.


  5. Michael James Williams says:
    June 1, 2012 at 3:52 am

    Got 15 minutes to spare? Watch Martin Jonasson and Petri Purho explain how to use the concept of “juiciness” to turn a boring old Breakout clone into something way more exciting.


    Watch the Video

    Martin Jonasson runs Grapefrukt, where he posts a selection of his games, webbfarbror, where you can contact him to do work on commission, and prototyprally, a blog about rapid prototyping games using Flash.

    Petri Purho created Crayon Physics Deluxe, and runs the blog Kloonigames, where he keeps an archive of games, each of which he made within seven days.

    The term “juice” was coined in How to Prototype a Game in Under 7 Days:

    “Juice” was our wet little term for constant and bountiful user feedback. A juicy game element will bounce and wiggle and squirt and make a little noise when you touch it. A juicy game feels alive and responds to everything you do – tons of cascading action and response for minimal user input. It makes the player feel powerful and in control of the world, and it coaches them through the rules of the game by constantly letting them know on a per-interaction basis how they are doing.


    More Resources

    You can play the game itself here, but I recommend you watch the video first. The source is available on GitHub.

    There are plenty of additional links on the YouTube page for the video as well:

    • Robert Penner’s Easing Equations
    • Game Feel, a book by Steve Swink
    • How to Prototype a Game in Under 7 Days
    • Make It Juicy! by Emily Short
    • Principles of Animation
    • The Art of Diablo III
    • GUI Design and Easing Functions
    • Transitions: The Importance of Curves
    • Tim Groleau’s Easing Function Generator

    Big thanks to Christer Kaitila for bringing this video to my attention!


  6. Abel Toy says:
    June 1, 2012 at 4:06 am
    This entry is part 2 of 2 in the series FlashPunk UI Components

    In this tutorial we’ll finish what we started in the first part of this UI with FlashPunk mini-series. We’ll learn how to customize the graphics of our components, and make a few adjustments to make our UI perfect.


    Final Result Preview

    Let’s take a look at the final result we will be working towards:

    Make sure you click everything to see how it responds!


    Section 1: How to Draw

    Step 1.1: Open Your Existing Project

    If you don’t already have it, be sure to download the source code from part one. Open the project file in FlashDevelop (info here) and get ready to upgrade your UI!


    Step 1.2: Drawing Stuff

    The next step we need to do to be able to extensively customize the graphic side of our UI is learn how to draw the graphic stuff directly with code. At the momment we needed an image for each state of our UI (button normal, button hover, checkbox normal unselected, checkbox normal selected, etc.), so we needed a large ammount of Images. Now, let’s say you want a different color for each button, or even a different shape for each one, and selected randomly… we can’t afford to have millions of images: too work to make them and they consume too much memory.

    But before starting to draw the components itself, we must first learn how to draw stuff using code in FlashPunk.


    Step 1.3: Preparing a Drawing Test World

    First of all, we need a new World to test the Drawing stuff. Create a new World class, called DrawWorld, and tell Main to go there when starting the game.

    DrawWorld.as:

    
    
    package
    {
    	import net.flashpunk.World;
    
    	public class DrawWorld extends World
    	{
    		public function DrawWorld()
    		{
    
    		}
    	}
    }
    

    Step 1.4: Using the FlashPunk Drawing Utils

    The FlashPunk Engine has a few utils which lets us Draw things to the screen or to a BitmapData.

    These functions are: line, linePlus, rect, rectPlus, circle, circlePlus and curve (the other ones are used to draw other kinds of stuff). The ‘plus’ versions come with more options and give better results (using antialiasing) but are more CPU intensive.

    Using them is easy; override the render method of your World or an Entity and call those functions, like this overriden render function for our DrawWorld, which draws some shapes:

    
    
    		override public function render():void
    		{
    			super.render();
    
    			Draw.line(10, 10, 100, 100, 0x00FF00);
    			Draw.rectPlus(120, 120, 200, 200, 0x9999FF, 1, true, 2, 10);
    			Draw.circle(100, 100, 50, 0xFF0000);
    			Draw.curve(100, 100, 140, 90, 122, 122, 0x00FFFF, 1, 3);
    		}
    

    Step 1.5: That’s Slow!

    The problem with that method is, it’s really slow. We’re drawing the same stuff over and over again, for no reason, to the screen. This would be OK if things were changing EVERY frame, but if they are not, it’s a complete waste of resources.

    What we’re going to do instead is, create a bitmapData to store our drawings, then draw them there once or just every time they change. Then we just need to render that bitmapData to the screen using copyPixels, which is a much faster way of doing it… or we’ll add a Stamp, which is a FlashPunk graphic that does exactly that: draw a bitmapData to the screen.

    To make Draw do the drawing to a custom bitmapData instead of using the screen, we can use its setTarget function. Draw.resetTarget will make it draw future commands to the screen again.

    Here’s our DrawWorld code now. If you test it, the result should be exactly the same as before.

    
    
    package
    {
    	import flash.display.BitmapData;
    	import net.flashpunk.graphics.Stamp;
    	import net.flashpunk.utils.Draw;
    	import net.flashpunk.World;
    
    	public class DrawWorld extends World
    	{
    		override public function begin():void
    		{
    			super.begin();
    
    			var picture:BitmapData = new BitmapData(300, 300, true, 0);
    			Draw.setTarget(picture);
    
    			Draw.line(10, 10, 100, 100, 0x00FF00);
    			Draw.rectPlus(120, 120, 200, 200, 0x9999FF, 0.5, true, 2, 10);
    			Draw.circle(100, 100, 50, 0xFF0000);
    			Draw.curve(100, 100, 140, 90, 122, 122, 0x00FFFF, 1, 3);
    
    			addGraphic(new Stamp(picture));
    		}
    	}
    }
    

    Step 1.6: Advanced Drawing

    Okay. We know how to draw some circles, lines, squares, and so on to the screen and to a BitmapData now. Thing is, I want to make a good-looking button, not a lame button made of a simple square and a circle! That’s why we need advanced drawing.

    Advanced drawing is just some concept I made up to refer to using the AS3 Drawing API directly (you know, when you draw using the graphics of a Sprite, Shape, etc.). The process is, basically: First, create a Sprite so we can get a Graphics class. Then, we draw what we need to the Sprite graphics. Finally, we render the Sprite to a BitmapData. Done!

    Using this process, we can draw advanced shapes and use advanced fills, like making some awesome-looking gradient buttons. Yay!

    I’m not going to explain each individual method of the Draw API, as explaining it isn’t the scope of this tutorial, but there are plenty of resources on the net if you don’t know how it works.

    The Drawing API is used on the Graphics class. But you can’t create a Graphics class on-the-fly, and you wouldn’t be able to “draw” it anywhere. Instead, we can create a Sprite and use its graphics property for drawing. Then, to use that Sprite as a FlashPunk graphic, we simply render it to a BitmapData.

    Here’s some example code, in which I draw a gradiented rectangle:

    
    
    package
    {
    	import flash.display.BitmapData;
    	import flash.display.Graphics;
    	import flash.display.Sprite;
    	import flash.geom.Matrix;
    	import net.flashpunk.FP;
    	import net.flashpunk.graphics.Stamp;
    	import net.flashpunk.World;
    
    	public class DrawWorld extends World
    	{
    		override public function begin():void
    		{
    			super.begin();
    
    			var sprite:Sprite = new Sprite;
    			var g:Graphics = sprite.graphics;
    
    			var gradientMatrix:Matrix = new Matrix();
    			gradientMatrix.createGradientBox(200, 50, 270 * FP.RAD, 0, 0);
    			g.beginGradientFill("linear", [0x6ACFFF, 0x005F8C], [1, 1], [0, 255], gradientMatrix);
    			g.drawRoundRect(0, 0, 200, 50, 20);
    			g.endFill();
    
    			var bd:BitmapData = new BitmapData(200, 50, true, 0);
    			bd.draw(sprite);
    
    			addGraphic(new Stamp(bd), 0, 100, 50);
    		}
    	}
    }
    • Lines 17-18: We create a Sprite to use its graphics property for drawing, and we store its graphics to a variable named g for less typing.
    • Lines 20-21: We create a gradient matrix, which is required to have a gradient fill. We provide it the size of our rectangle, and a rotation in radians (we convert 270 degrees to radians by multiplying by FP.RAD). As the rectangle will be drawn at (0,0), we set tx and ty properties to 0.
    • Lines 22-24: We draw the rounded rect with the gradient fill to the sprite graphics.
    • Lines 26-27: We create a BitmapData the size of the graphic, and render the sprite to it.
    • Line 29: We create a Stamp, providing our BitmapData which has the sprite rendered, and add it to the World at (100, 50).

    Result:


    Step 1.7: Filters!

    We’re now ready to draw gorgeous buttons… but we can step it up a bit and make them look even better! To do that, on top of the graphics itself, we can add filters to them. With Flash, we can add drop shadow filters, glow filters, bevel filters, and so on, easily.

    To add filters, we simply need to populate the sprite’s filter array with our filters – or if we want to use BitmapFilters, we use bd.applyFilter() after we’ve drawn the sprite.

    Let’s add an inner glow filter and a drop shadow filter to our rectangle, and also change the color of the screen, so we can preview it better. Code here:

    
    
    		override public function begin():void
    		{
    			FP.screen.color = 0xD9F2FF;
    
    			super.begin();
    
    			var sprite:Sprite = new Sprite;
    			var g:Graphics = sprite.graphics;
    
    			var gradientMatrix:Matrix = new Matrix();
    			gradientMatrix.createGradientBox(200, 50, 270 * FP.RAD, 0, 0);
    			g.beginGradientFill("linear", [0x6ACFFF, 0x005F8C], [1, 1], [0, 255], gradientMatrix);
    			g.drawRoundRect(0, 0, 200, 50, 20);
    			g.endFill();
    
    			sprite.filters = [new GlowFilter(0xFFFFFF, 1, 10, 10, 1, 3, true), new DropShadowFilter(8, 45, 0, 0.8, 10, 10, 1, 3)];
    
    			var bd:BitmapData = new BitmapData(200, 50, true, 0);
    			bd.draw(sprite);
    
    			addGraphic(new Stamp(bd), 0, 100, 50);
    		}
    

    If you preview the current code, you’ll see the filters look somewhat… cropped.

    Let’s fix that!


    Step 1.8: Quick Fix for the Filter Crop

    First of all… why does it look cropped? Basically, the problem is our BitmapData is the size of the button, but the shadow is bigger than the button. So, when rendering the sprite to the bitmapdata, as the shadow doesn’t fit the BitmapData, it gets cropped.

    The easiest way to solve that is simply to enlarge the BitmapData. We’ll also have to give the sprite some x and y offset, as the shadow is slightly on top and left of the button as well.

    
    
    			//[...]
    
    			sprite.filters = [new GlowFilter(0xFFFFFF, 1, 10, 10, 1, 3, true), new DropShadowFilter(8, 45, 0, 0.8, 10, 10, 1, 3)];
    
    			var bd:BitmapData = new BitmapData(250, 100, true, 0);
    			var m:Matrix = new Matrix;
    			m.tx = 20;
    			m.ty = 20;
    			bd.draw(sprite, m);
    
    			var stamp:Stamp = new Stamp(bd);
    			stamp.x = -m.tx;
    			stamp.y = -m.ty;
    			addGraphic(stamp, 0, 100, 50);
    

    We also offset the stamp’s x and y to the negative offset of the bitmap drawing. This way, the button coordinates (100, 50) originate from the rounded rectangle and not from the shadow, and it’s in the same place as before.


    Step 1.9: Endless Possibilities!

    As you can see, combining the AS3 Drawing API and its filters can lead to impressive results. The possibilities are endless, if you know well how it works, so it might be worth reading a few things about the Drawing API and filters.

    For example, here you have a pack of AS3 filter setups, with amazing results: Flash Effects Pack. And a cool static distortion filter: Static Distortion Effect using the DisplacementMapFilter.

    There are thousands more of tutorials and effects using flash filters and the drawing API spread all over the web, which you could apply to your UI set. Even better: if you have the knowledge, you can create those amazing effects by yourself.


    Section 2: Preparing Our UI

    Step 2.1: Refactoring the UI Code

    Let’s implement all those drawing stuff to our UI. First of all, as having to write all the code needed to go from a Sprite to a BitmapData for each element we need to draw is a bit silly, we’ll just create a helper function that will do that for us every time we need it. This way we don’t repeat code over and over again.

    We’ll place this helper function in a base class all the UI elements will extend. Let’s call it Component, place it in the ui folder, and make it extend Entity:

    
    
    package ui
    {
    	import net.flashpunk.Entity;
    
    	public class Component extends Entity
    	{
    		public function Component(x:Number = 0, y:Number = 0)
    		{
    			super(x, y);
    		}
    	}
    }

    Now we need to change our ui classes to extend this instead of Entity. We’ll only need to change Button and TextInput, as Checkbox extends Button so it will extend Component indirectly, and RadioButton extends Checkbox so the same happens.


    Step 2.2: Helper Function

    Taking as a base the code we made for drawing our cool gradient-y button, we’ll build this helper function. Here’s how stuff will work:

    Component will have a protected sprite and g variables. This way, you can add filters to Sprite and draw stuff on graphics. They will be kept alive forever, so it’s your job to clean them if you’re going to draw multiple stuff on the same component, and destroy them completely when they aren’t needed anymore.

    Then, when calling this function, it will generate a BitmapData of the specified size and draw the sprite to it. Then it will return a Stamp containing that BitmapData, ready to use!

    Even though there’s already a graphic and sprite properties which can be cleant and used multiple times, if you really need to use a different sprite, the function will be able to get it through a parameter. By default, the parameters will point to the sprite member of the class.

    
    
    package ui
    {
    	import flash.display.BitmapData;
    	import flash.display.DisplayObject;
    	import flash.display.Graphics;
    	import flash.display.Sprite;
    	import flash.geom.Matrix;
    	import net.flashpunk.Entity;
    	import net.flashpunk.graphics.Stamp;
    
    	public class Component extends Entity
    	{
    		protected var sprite:Sprite;
    		protected var g:Graphics;
    
    		public function Component(x:Number = 0, y:Number = 0)
    		{
    			super(x, y);
    
    			sprite = new Sprite;
    			g = sprite.graphics;
    
    			_m = new Matrix();
    		}
    
    		private var _m:Matrix;
    
    		protected function drawStamp(width:Number, height:Number, offsetX:Number = 0, offsetY:Number = 0, sprite:DisplayObject = null):Stamp
    		{
    			if (sprite == null) sprite = this.sprite;
    
    			var bd:BitmapData = new BitmapData(width, height, true, 0);
    			_m.tx = offsetX;
    			_m.ty = offsetY;
    			bd.draw(sprite, _m);
    
    			return new Stamp(bd, -offsetX, -offsetY);
    		}
    	}
    }

    Step 2.3: Removing Graphics From UI

    We will take a different approach for skinning now. The base components (Button, Checkbox, etc.) will only hold the behaviour itself, without the graphics. Then we can extend them (to MenuButton, GameButton, MuteButton, etc.) to include the specific graphic behaviour.

    So first of all, we must remove the graphic rendering of our components. We’ll also make the player input the size of the components.


    Step 2.3a: Removing Graphics From Button

    For the button, first of all, we need to remove the graphic creation, and the variables for it. We’ll also replace the label:Text property with a string property called text. And we’ll require a width and height for setting the hitbox.

    
    
    	public class Button extends Component
    	{
    		protected const NORMAL:int = 0;
    		protected const HOVER:int = 1;
    		protected const DOWN:int = 2;
    
    		public var clicked:Boolean = false;
    
    		protected var text:String;
    		public var callback:Function;
    		public var params:Object;
    
    		public function Button(x:Number=0, y:Number=0, text:String = "", width:Number = 150, height:Number = 50, callback:Function = null, params:Object = null)
    		{
    			super(x, y);
    
    			this.callback = callback;
    			this.params = params;
    			this.text = text;
    
    			setHitbox(width, height);
    		}
    
    		//[...]
    	}
    

    Then, we remove the renderGraphic function and place it in Component instead. We empty the changeState function, because it will be handled on the skinning classes. The render override will also be removed, because we don’t have a label to render. So, after the update function, which we don’t need to change, all we have is this:

    
    
    		protected function changeState(state:int = 0):void
    		{
    		}
    
    		protected function click():void
    		{
    			if (callback != null)
    			{
    				if (params != null) callback(params);
    				else callback();
    			}
    		}
    

    We also could add a lastState variable, and set it on the changeState function, in case our skins need it. Remember, as lastState will be set in the changeState function, when overriding it we will place the new behaviour first and do the super call at the end.

    
    
    		protected var lastState:int = 0;
    
    		protected function changeState(state:int = 0):void
    		{
    			lastState = state;
    		}
    

    Step 2.3b: Removing Graphics From RadioButton

    For the checkbox, we’ll need to remove the changeState override and all the graphic creation in the constructor. For the radio button, we’ll just need to remove the graphic creation in the constructor. We’ll also add the width and height parameters on both classes.

    New Checkbox:

    
    
    package ui
    {
    	public class Checkbox extends Button
    	{
    		public var checked:Boolean = false;
    
    		public function Checkbox(x:Number=0, y:Number=0, text:String = "", width:Number = 150, height:Number = 150, callback:Function = null, params:Object = null, checked:Boolean = false)
    		{
    			super(x, y, text, width, height, callback, params);
    
    			this.checked = checked;
    		}
    
    		override protected function click():void
    		{
    			checked = !checked;
    
    			if (callback != null)
    			{
    				if (params != null) callback(checked, params);
    				else callback(checked);
    			}
    		}
    	}
    }
    

    New RadioButton:

    
    
    package ui
    {
    	public class RadioButton extends Checkbox
    	{
    		internal var group:RadioButtonGroup;
    
    		public function RadioButton(x:Number=0, y:Number=0, group:RadioButtonGroup = null, text:String = "", width:Number = 150, height:Number = 50, params:Object = null, checked:Boolean = false)
    		{
    			super(x, y, text, width, height, null, params, checked);
    
    			if (group) group.add(this);
    		}
    
    		override protected function click():void
    		{
    			group.click(this, params);
    		}
    
    		override public function removed():void
    		{
    			super.removed();
    
    			group.remove(this);
    		}
    	}
    }
    

    Step 2.3c: Removing Graphics From TextInput

    For the text input, all we need to remove is the textGraphic property, and its creation. We’ll also add an onFocus function so we can handle graphic changes for focus on the skin.

    
    
    package ui
    {
    	import flash.events.KeyboardEvent;
    	import net.flashpunk.FP;
    	import net.flashpunk.utils.Input;
    	import net.flashpunk.utils.Key;
    
    	public class TextInput extends Component
    	{
    		protected var _text:String = "";
    
    		protected var multiline:Boolean = false;
    
    		public static var focus:TextInput;
    		private var _focused:Boolean = false;
    
    		public function TextInput(x:Number=0, y:Number=0, text:String = "", multiline:Boolean = false, width:Number = 150, height:Number = 30)
    		{
    			super(x, y);
    
    			this.multiline = multiline;
    
    			this.text = text;
    
    			type = "uiTextInput";
    
    			setHitbox(width, height);
    		}
    
    		override public function added():void
    		{
    			super.added();
    
    			FP.stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
    		}
    
    		protected function onKeyDown(e:KeyboardEvent):void
    		{
    			if (world != FP.world) return;
    			if (TextInput.focus != this) return;
    
    			if (e.keyCode == Key.BACKSPACE) text = _text.substr(0, _text.length - 1);
    			else if (e.keyCode == Key.ENTER && multiline) text += "\n";
    		}
    
    		override public function removed():void
    		{
    			super.removed();
    
    			FP.stage.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
    		}
    
    		protected function onFocus(focused:Boolean):void
    		{
    
    		}
    
    		override public function update():void
    		{
    			super.update();
    
    			if (TextInput.focus == this)
    			{
    				if (!_focused)
    				{
    					onFocus(true);
    					_focused = true;
    				}
    			}
    			else if (_focused)
    			{
    				onFocus(false);
    				_focused = false;
    			}
    
    			if (Input.mousePressed)
    			{
    				if (collidePoint(x, y, world.mouseX, world.mouseY))
    				{
    					TextInput.focus = this;
    					Input.keyString = "";
    				}
    				else if (!world.collidePoint("uiTextInput", world.mouseX, world.mouseY)) TextInput.focus = null;
    			}
    
    			if (TextInput.focus == this && Input.keyString != "")
    			{
    				text += Input.keyString;
    				Input.keyString = "";
    			}
    		}
    
    		public function get text():String
    		{
    			return _text;
    		}
    
    		public function set text(value:String):void
    		{
    			_text = value;
    		}
    	}
    }
    

    Step 2.4: Preparing to Test

    Everything’s prepared to begin building our skins! But first, we need to point to our TestWorld again. To do that, change the line in the Main class which points to the DrawWorld, and make it point to TestWorld.

    If you test it now, you’ll see a blank world. That’s to be expected; we removed all the graphics from our components. Don’t worry, though, we’ll begin the skinning now!


    Section 3: Skinning a Component

    Step 3.1: Skinning the Button

    Now we’re going to go through, step by step, the whole process of skinning a component, taking as an example the button. We will see the most common techniques you will need when skinning your own components: drawing the graphics, adding some fancy animations, some cool sound effects, particle eye-candy, and even some pixel-perfect collision techniques and changing the mouse icon to a hand when hovering over the component.

    This should basically prepare you to be able to skin any component you want with your own style and without any problem. We will then apply the knowledge we gained with the button to skin the checkbox and radio button, we’ll learn how to skin a more complex and different button like the text input, and then we’ll build an extra component and skin it.


    Step 3.2: Normal Graphic

    First of all we’ll make a button show its normal graphic. We’ll use the same cool graphic we used in the Draw World. So, basically, we copy what we used there and then call the drawStamp function to make the Sprite be transformed into a Stamp, and we’ll set it to our button’s graphic.

    Before that, though, we need to actually have a button! Create a blue folder inside the src folder. This is where we’ll place all our skinned components. We’ll make them blue, as you can guess by the name. This is just for us to keep things organised. In your game, you’d probably want to put different folders with different skins in your ui folder, and call them something like menu, game, etc.

    Then, make a BlueButton class which extends Button in the blue folder:

    
    
    package blue
    {
    	import ui.Button;
    
    	public class BlueButton extends Button
    	{
    		public function BlueButton(x:Number=0, y:Number=0, text:String="", width:Number=150, height:Number=50, callback:Function=null, params:Object=null)
    		{
    			super(x, y, text, width, height, callback, params);
    
    		}
    	}
    }
    

    Now, we’ll place the drawing code in the constructor:

    
    
    		public function BlueButton(x:Number=0, y:Number=0, text:String="", width:Number=150, height:Number=50, callback:Function=null, params:Object=null)
    		{
    			super(x, y, text, width, height, callback, params);
    
    			var gradientMatrix:Matrix = new Matrix();
    			gradientMatrix.createGradientBox(200, 50, 270 * FP.RAD, 0, 0);
    			g.beginGradientFill("linear", [0x6ACFFF, 0x005F8C], [1, 1], [0, 255], gradientMatrix);
    			g.drawRoundRect(0, 0, 200, 50, 20);
    			g.endFill();
    
    			sprite.filters = [new GlowFilter(0xFFFFFF, 1, 10, 10, 1, 3, true), new DropShadowFilter(8, 45, 0, 0.8, 10, 10, 1, 3)];
    
    			graphic = drawStamp(220, 70, 5, 5);
    		}
    

    To test it, we need to create the button in TestWorld. So, comment or remove all the components created there, and place a new BlueButton instead. Also, change the background color to a lighter one. Here’s my TestWorld begin function:

    
    
    		override public function begin():void
    		{
    			super.begin();
    
    			FP.screen.color = 0xD9F2FF;
    
    			add(new BlueButton(200, 10, "Blue button!"));
    
    			add(new BlueButton(20, 100, "Fat button", 500, 200));
    		}
    

    If you test the project, you’ll see the buttons are being drawn! However, they all are the same size, even though we specified the fat button to be very big. Let’s give the button some cake.


    Step 3.3: Button Graphic Size

    First of all, I’d like to move the function which draws the button’s graphic into a helper function of BlueButton. Keeps stuff cleaner.

    
    
    	public class BlueButton extends Button
    	{
    		public function BlueButton(x:Number=0, y:Number=0, text:String="", width:Number=150, height:Number=50, callback:Function=null, params:Object=null)
    		{
    			super(x, y, text, width, height, callback, params);
    
    			graphic = drawButton(width, height);
    		}
    
    		protected function drawButton(width:Number, height:Number):Stamp
    		{
    			var gradientMatrix:Matrix = new Matrix();
    			gradientMatrix.createGradientBox(200, 50, 270 * FP.RAD, 0, 0);
    			g.beginGradientFill("linear", [0x6ACFFF, 0x005F8C], [1, 1], [0, 255], gradientMatrix);
    			g.drawRoundRect(0, 0, 200, 50, 20);
    			g.endFill();
    
    			sprite.filters = [new GlowFilter(0xFFFFFF, 1, 10, 10, 1, 3, true), new DropShadowFilter(8, 45, 0, 0.8, 10, 10, 1, 3)];
    
    			return drawStamp(220, 70, 5, 5);
    		}
    	}
    

    All we did is move the button draw stuff from the constructor to a helper function. This helper function returns the Stamp, and asks for a width and a height. We set our graphic to the Stamp returned. Now we need to make it actually use the width and height provided.

    All the changes we need to do are in the matrix gradient box, the round rect drawing and in the stamp creation. The stamp creation needs to have a bigger size, because of the filters. Here’s the final code:

    
    
    		protected function drawButton(width:Number, height:Number):Stamp
    		{
    			var gradientMatrix:Matrix = new Matrix();
    			gradientMatrix.createGradientBox(width, height, 270 * FP.RAD, 0, 0);
    			g.beginGradientFill("linear", [0x6ACFFF, 0x005F8C], [1, 1], [0, 255], gradientMatrix);
    			g.drawRoundRect(0, 0, width, height, 20);
    			g.endFill();
    
    			sprite.filters = [new GlowFilter(0xFFFFFF, 1, 10, 10, 1, 3, true), new DropShadowFilter(8, 45, 0, 0.8, 10, 10, 1, 3)];
    
    			return drawStamp(width + 20, height + 20, 5, 5);
    		}
    

    And here’s the result! They don’t do anything when you click them, but they’re actual buttons!


    Step 3.4: Glare and Border

    Let’s make our button a bit better by adding a border and a glare to it.

    Adding a border is very easy. We could do two things: apply a line style to the button graphics before drawing the round rect, or use a filter. The former would make our button look weird, though, as the inner glow will also cover the border, so let’s go for the filter approach.

    Even though there’s no specific BorderFilter in Flash, the effect can easily be achieved with a glow filter that has high strength and low blur. We’ll add this filter between the glow filter and the shadow filter, like this:

    
    
    		protected function drawButton(width:Number, height:Number):Stamp
    		{
    			var gradientMatrix:Matrix = new Matrix();
    			gradientMatrix.createGradientBox(width, height, 270 * FP.RAD, 0, 0);
    			g.beginGradientFill("linear", [0x6ACFFF, 0x005F8C], [1, 1], [0, 255], gradientMatrix);
    			g.drawRoundRect(0, 0, width, height, 20);
    			g.endFill();
    
    			sprite.filters = [new GlowFilter(0xFFFFFF, 1, 10, 10, 1, 3, true), new GlowFilter(0x00456A, 0.6, 2, 2, 6, 2), new DropShadowFilter(8, 45, 0, 0.8, 10, 10, 1, 3)];
    
    			return drawStamp(width + 20, height + 20, 5, 5);
    		}
    

    The glare will be a little more complicated, but will introduce us to a new concept you will probably need for your own components: multiple graphics. As of now, the skin only consists of a single graphic. But what if we need to add more to it, like a glare?

    We can take two approaches: using a Graphiclist, or using the renderGraphic function our components have. We’ll use the renderGraphic function because our button graphic will change for the hover function, while the glare will remain the same. This way we don’t have to bother updating the graphiclist.

    To draw the glare, all we got to do is draw a semi-transparent big white ellipse, covering the button. Then, to avoid the glare covering everything in the world, we can mask the glare sprite using our button’s graphic. Here’s the code:

    
    
    		protected var glare:Stamp;
    
    		public function BlueButton(x:Number=0, y:Number=0, text:String="", width:Number=150, height:Number=50, callback:Function=null, params:Object=null)
    		{
    			super(x, y, text, width, height, callback, params);
    
    			graphic = drawButton(width, height);
    
    			drawGlare();
    		}
    
    		protected function drawGlare():void
    		{
    			var mask:Sprite = new Sprite;
    			mask.graphics.copyFrom(g);
    
    			sprite.filters = [];
    			g.clear();
    			g.beginFill(0xFFFFFF, 0.25);
    			g.drawEllipse( -width * 0.25, -height * 0.6, width * 1.5, height);
    			sprite.mask = mask;
    
    			glare = drawStamp(width, height * 0.4);
    		}
    

    And the rendering:

    
    
    		override public function render():void
    		{
    			super.render();
    
    			renderGraphic(glare);
    		}
    

    Here’s the end result. Beautiful, isn’t it?


    Step 3.5: Hover Graphic

    To make the hover graphic, we’ll use the same drawButton function but we’ll make the button red-orangish. To do that, we’ll need to ask for some color parameters on that function.

    
    
    		protected function drawButton(width:Number, height:Number, topColor:uint, bottomColor:uint, borderColor:uint):Stamp
    		{
    			var gradientMatrix:Matrix = new Matrix();
    			gradientMatrix.createGradientBox(width, height, 270 * FP.RAD, 0, 0);
    			g.beginGradientFill("linear", [topColor, bottomColor], [1, 1], [0, 255], gradientMatrix);
    			g.drawRoundRect(0, 0, width, height, 20);
    			g.endFill();
    
    			sprite.filters = [new GlowFilter(0xFFFFFF, 1, 10, 10, 1, 3, true), new GlowFilter(borderColor, 0.6, 2, 2, 6, 2), new DropShadowFilter(8, 45, 0, 0.8, 10, 10, 1, 3)];
    
    			return drawStamp(width + 20, height + 20, 5, 5);
    		}
    

    Now, our normal graphic needs the same colors!

    
    
    		public function BlueButton(x:Number=0, y:Number=0, text:String="", width:Number=150, height:Number=50, callback:Function=null, params:Object=null)
    		{
    			super(x, y, text, width, height, callback, params);
    
    			graphic = drawButton(width, height, 0x6ACFFF, 0x005F8C, 0x00456A);
    
    			drawGlare();
    		}
    

    To make the normal / hover switch, we’ll store each graphic and make the correspondent switch in the changeState function. So first, let’s make a variable for each graphic and populate it:

    
    
    		protected var glare:Stamp;
    
    		protected var normal:Stamp;
    		protected var hover:Stamp;
    
    		public function BlueButton(x:Number=0, y:Number=0, text:String="", width:Number=150, height:Number=50, callback:Function=null, params:Object=null)
    		{
    			super(x, y, text, width, height, callback, params);
    
    			normal = drawButton(width, height, 0x6ACFFF, 0x005F8C, 0x00456A);
    			hover = drawButton(width, height, 0xFF8C66, 0xDD0500, 0x550000);
    			graphic = normal;
    
    			drawGlare();
    		}
    

    Now we switch to the correspondent graphic on the changeState function:

    
    
    		override protected function changeState(state:int = 0):void
    		{
    			if (state == lastState) return;
    
    			switch(state)
    			{
    				case NORMAL:
    					graphic = normal;
    					break;
    				case HOVER:
    					graphic = hover;
    					break;
    			}
    
    			super.changeState(state);
    		}
    

    And here’s the result! Finally, interactive buttons! (…which do nothing)


    Step 3.6: Hover Animation Preparation

    Let’s say we want to add a tween for the hover graphic, instead of changing the graphic immediately on hover.

    To be able to do that, we need to make a change first. As creating a new Stamp and a new BitmapData each frame would be a waste of resources, we’ll adapt the drawButton function to draw to a given BitmapData instead. Then, we will simply use that BitmapData for a permanent Stamp in our button.

    
    
    		protected function drawButton(bitmap:BitmapData, width:Number, height:Number, topColor:uint, bottomColor:uint, borderColor:uint):void
    		{
    			g.clear();
    			var gradientMatrix:Matrix = new Matrix();
    			gradientMatrix.createGradientBox(width, height, 270 * FP.RAD, 0, 0);
    			g.beginGradientFill("linear", [topColor, bottomColor], [1, 1], [0, 255], gradientMatrix);
    			g.drawRoundRect(0, 0, width, height, 20);
    			g.endFill();
    
    			sprite.filters = [new GlowFilter(0xFFFFFF, 1, 10, 10, 1, 3, true), new GlowFilter(borderColor, 0.6, 2, 2, 6, 2), new DropShadowFilter(8, 45, 0, 0.8, 10, 10, 1, 3)];
    
    			_m.tx = 5;
    			_m.ty = 5;
    			bitmap.draw(sprite, _m);
    		}
    		private var _m:Matrix = new Matrix;
    

    Now we create the Stamp which will hold it. First, we’ll remove the current stamps we’ve got for the separate states, and use this one instead.

    
    
    		protected var buttonBmp:BitmapData;
    		protected var buttonGraphic:Stamp;
    
    		public function BlueButton(x:Number=0, y:Number=0, text:String="", width:Number=150, height:Number=50, callback:Function=null, params:Object=null)
    		{
    			super(x, y, text, width, height, callback, params);
    
    			buttonBmp = new BitmapData(width + 20, height + 20, true, 0);
    			drawButton(buttonBmp, width, height, 0x6ACFFF, 0x005F8C, 0x00456A);
    
    			buttonGraphic = new Stamp(buttonBmp, -5, -5);
    			graphic = buttonGraphic;
    
    			drawGlare();
    		}
    

    Time to tween!


    Step 3.7: Tweening Button Colors

    To tween the colors for the hover and normal states of our button, we will use the TweenLite library. How to use it is outside the scope of this tutorial, but there are plenty of resources on the net and here on Activetuts+.

    (We could also use any other tweening library, or even FlashPunk’s own tweening. But TweenLite is more extensive than FlashPunk Tweening, is the library which I know better and it’s one of the best tweening libraries for AS3.)

    So, go download TweenLite and add it to your code. As I use FlashDevelop, I got the SWC, placed it in the lib folder and right-clicked it to add it to my project library.

    First of all, we’ll create all the variables we need to tween on our button. In our case, it’s just three colours, but it can be whatever you want! They need to be public, so TweenLite can access them.

    
    
    		public var topColor:uint = 0x6ACFFF;
    		public var bottomColor:uint = 0x005F8C;
    		public var borderColor:uint = 0x00456A;
    

    We also need to activate a plugin in TweenLite so we can tween colors. Place this in Main:

    
    
    TweenPlugin.activate([HexColorsPlugin]);
    

    All we need to do now is tween those properties in the changeState function:

    
    
    		override protected function changeState(state:int = 0):void
    		{
    			if (state == lastState) return;
    
    			switch(state)
    			{
    				case NORMAL:
    					TweenLite.to(this, 0.25, { hexColors: { topColor: 0x6ACFFF, bottomColor: 0x005F8C, borderColor: 0x00456A }, onUpdate: updateGraphic } );
    					break;
    				case HOVER:
    					TweenLite.to(this, 0.25, { hexColors: { topColor: 0xFF8C66, bottomColor: 0xDD0500, borderColor: 0x550000 }, onUpdate: updateGraphic } );
    					break;
    			}
    
    			super.changeState(state);
    		}
    

    We could do a lot of fancy stuff, like easing or using other TweenLite features, but we’ll keep it simple for this example. Remember, you can use whatever you want for your skins.

    As you can see, we also added an onUpdate parameter. That’s so the graphic can be updated according to the tween values, and we actually see it. Here’s the function:

    
    
    		protected function updateGraphic():void
    		{
    			buttonBmp.fillRect(buttonBmp.rect, 0);
    			drawButton(buttonBmp, width, height, topColor, bottomColor, borderColor);
    		}
    

    And here’s the result!


    Step 3.8: Down State

    For the down state, we’ll simply quickly tween the button to black. You already know how to do this, just add another case with the tween parameters.

    
    
    				case DOWN:
    					TweenLite.to(this, 0.1, { hexColors: { topColor: 0x5B5B5B, bottomColor: 0x2D2D2D, borderColor: 0x151515 }, onUpdate: updateGraphic } );
    					break;
    

    The only problem with this is, when going from down to another state, the transition is, in my opinion, too slow. Let’s make it faster. As we want two different durations, the regular one and the “from down” one, we’ll make an extra variable in that function. This variable will check the state we come from, and set the duration depending on that. Then, the NORMAL and HOVER transitions will take into account this variable.

    Here’s the function:

    
    
    		override protected function changeState(state:int = 0):void
    		{
    			if (state == lastState) return;
    
    			var duration:Number = 0.25;
    			if (lastState == DOWN) duration = 0.15;
    
    			switch(state)
    			{
    				case NORMAL:
    					TweenLite.to(this, duration, { hexColors: { topColor: 0x6ACFFF, bottomColor: 0x005F8C, borderColor: 0x00456A }, onUpdate: updateGraphic } );
    					break;
    				case HOVER:
    					TweenLite.to(this, duration, { hexColors: { topColor: 0xFF8C66, bottomColor: 0xDD0500, borderColor: 0x550000 }, onUpdate: updateGraphic } );
    					break;
    				case DOWN:
    					TweenLite.to(this, 0.1, { hexColors: { topColor: 0x5B5B5B, bottomColor: 0x2D2D2D, borderColor: 0x151515 }, onUpdate: updateGraphic } );
    					break;
    			}
    
    			super.changeState(state);
    		}
    

    And here’s the final result. Click our buttons!


    Step 3.9: The Label

    Our button has all the graphics, animations and behaviours. But it needs a very important thing, so the user knows the purpose of each button: a label.

    We are already sending some text parameters to our button, so the only thing we need to do is create a label graphic with that text property. We could use FlashPunk’s Text class with the renderGraphic function on the render override, but I would like to add some filters to our label, so we’ll create the text field directly, and use a Stamp.

    First of all, we’ll prepare the Stamp, its creation and its render, and we’ll use a function called renderLabel which will render that label into the stamp. We’ll code the function later.

    We create the label property which will hold our label Stamp:

    
    
    	public class BlueButton extends Button
    	{
    		protected var glare:Stamp;
    		protected var label:Stamp;
    		//[...]
    

    The end of the constructor, where we call the drawLabel function after the drawGlare one:

    
    
    			//[...]
    			drawGlare();
    			drawLabel(text);
    		}
    

    The drawLabel function, which is empty at the moment:

    
    
    		protected function drawLabel(text:String):void
    		{
    		}
    

    And our render function, rendering the label right after the glare, so it’s the top-most element of the button:

    
    
    		override public function render():void
    		{
    			super.render();
    
    			renderGraphic(glare);
    			renderGraphic(label);
    		}
    

    This process is basically what we’d do if we wanted to add additional elements to our button. Another strategy is to have a Graphiclist property instead of a Stamp, and add the custom graphics there. Then we can do the renderGraphic call with that Graphiclist.

    The only thing left to do now is to populate the drawLabel function. This function will basically create a text field, set some format to it (font size: 20, custom font, white text, center alignment), set the text to it and apply a Glow Filter. Then it draws the label to a stamp, and centers the stamp vertically in our button.

    
    
    		protected function drawLabel(text:String):void
    		{
    			var t:TextField = new TextField();
    
    			var tf:TextFormat = new TextFormat("Comfortaa", 20, 0xFFFFFF);
    			tf.align = "center";
    
    			t.defaultTextFormat = tf;
    			t.width = width;
    			t.height = height;
    			t.embedFonts = true;
    			t.text = text;
    			t.filters = [new GlowFilter(0x6ACFFF, 0.75, 7, 7, 2, 3)];
    
    			label = drawStamp(width + 10, t.textHeight + 10, 5, 5, t);
    			label.y = (height - t.textHeight) * 0.5 - 8;
    		}
    

    We also need to embed the font. I used the bold version of the Comfortaa font face, which you can get for free here: Comfortaa at DaFont.com. After saving it in the fonts folder of our assets folder, we embed it from our Main class (the document class, the one which extends FlashPunk’s Engine):

    
    
    	public class Main extends Engine
    	{
    		[Embed(source = "../assets/fonts/Comfortaa-Bold.ttf", fontFamily="Comfortaa", embedAsCFF="false")] public static var COMFORTAA:Class;
    
    		public function Main():void
    		{
    			super(550, 400);
    		}
    
    		//[...]
    	}
    

    And here’s the end result!


    Step 3.10: Sound Effects

    This one isn’t recommended for all of your UI elements, as it might get quite annoying to the player, but it could work in some cases. I’m talking about sound effects. Basically, we’re going to learn how to play a sound effect for specific case changes. To play the sound effects, we’ll use FlashPunk’s SFX class, which makes it really easy.

    First of all, download the sfx. They are not that good, but they are OK for learning purposes. I made them using as3sfxr. Save them to the sfx folder of our assets folder, using right-click > “Save as…”

    • click.mp3
    • over.mp3
    • out.mp3

    Then we need to embed them, in our Assets class.

    
    
    		[Embed(source = "../assets/sfx/click.mp3")] public static const CLICK:Class;
    		[Embed(source = "../assets/sfx/out.mp3")] public static const OUT:Class;
    		[Embed(source = "../assets/sfx/over.mp3")] public static const OVER:Class;
    

    In order to determine when to play those SFX, we’ll use the changeState function. We can add them inside the state switch statement.

    
    
    			switch(state)
    			{
    				case NORMAL:
    					TweenLite.to(this, duration, { hexColors: { topColor: 0x6ACFFF, bottomColor: 0x005F8C, borderColor: 0x00456A }, onUpdate: updateGraphic } );
    					if (lastState == HOVER) new Sfx(Assets.OUT).play();
    					break;
    				case HOVER:
    					TweenLite.to(this, duration, { hexColors: { topColor: 0xFF8C66, bottomColor: 0xDD0500, borderColor: 0x550000 }, onUpdate: updateGraphic } );
    					if (lastState == NORMAL) new Sfx(Assets.OVER).play();
    					break;
    				case DOWN:
    					TweenLite.to(this, 0.1, { hexColors: { topColor: 0x5B5B5B, bottomColor: 0x2D2D2D, borderColor: 0x151515 }, onUpdate: updateGraphic } );
    					new Sfx(Assets.CLICK).play();
    					break;
    			}
    

    As you can see in the normal and hover states, we can also check the last (previous) state. This is useful if, for example, we want our OVER sound to just play when we’re over the button. If that check wasn’t there, every time we clicked the button it’d also sound.

    Here’s the result:


    Step 3.11: More Effects!

    The possibilites are endless. We could add extra animations, particle candy, and all sorts of things to make our UI more fancy. Unimaginable ammounts of crazy features. Unfortunately, it’d be too long to cover all of them, and at this point you already know how to do stuff with our UI buttons and make it work with the skin. So, now it wouldn’t be a matter of “how to make x work with the buttons”, but just simply “how to make x thing” (like how to make particles), and that’s outside the scope of this tutorial.

    Despite that, the example and the source include a variety of skins which introduce different techniques. You are free, and encouraged, to take a look at the commented source for each skin. This way you can learn more specific techniques. We’ll talk more about the source at the end of the tutorial.


    Step 3.12: Pixel-Perfect Detection

    Even though I mentioned that I already explained enough effects and graphical techniques, there are still two behaviours you need to know. The first one is pixel-perfect detection.

    That isn’t really noticeable now, but let’s make a test. Let’s change the radius of our button. It’ll look ugly, but it’s just for testing purposes.

    
    
    		protected function drawButton(bitmap:BitmapData, width:Number, height:Number, topColor:uint, bottomColor:uint, borderColor:uint):void
    		{
    			var gradientMatrix:Matrix = new Matrix();
    			gradientMatrix.createGradientBox(width, height, 270 * FP.RAD, 0, 0);
    			g.beginGradientFill("linear", [topColor, bottomColor], [1, 1], [0, 255], gradientMatrix);
    			g.drawRoundRect(0, 0, width, height, 100);
    			g.endFill();
    
    			sprite.filters = [new GlowFilter(0xFFFFFF, 1, 10, 10, 1, 3, true), new GlowFilter(borderColor, 0.6, 2, 2, 6, 2), new DropShadowFilter(8, 45, 0, 0.8, 10, 10, 1, 3)];
    
    			_m.tx = 5;
    			_m.ty = 5;
    			bitmap.draw(sprite, _m);
    		}
    

    We changed the radius of our button from 20 to 100. Let’s see how it looks, and more importantly, how our button behaves.

    Hitbox collision.

    Everything, appart from the obvious hideousness of our button, looks normal. There’s one thing, though. Go place your mouse at the corners of our buttons. If you pay attention, you’ll see the mouse is detected even if it’s not over the button. That’s because we’re using hitboxes, so the graphic of the button isn’t taken into account – just its bounding box. And, of course, the mouse is inside that bounding box.

    A way to solve that is to use FlashPunk’s Pixelmask. The pixelmask works like this for detecting collisions: first, it checks whether it’s inside the bounding box, just like the hitbox we’ve been using. If it’s not, okay, it’s fine. But, if it is, then it checks with pixel-precision whether it’s colliding with a graphic we provided. This way, we can make holes and rounded corners and all kinds of artefacts in our graphics, and it will only react to the cursor when it’s actually over the button.

    There’s one thing, though. Imagine a button which only displays its border and the text, but is empty inside. We’d still want to detect the mouse when it’s inside the button, even if it’s on an “empty” part of it. Or, let’s say, as it happens with our case, that we have outter effects in our button, like a shadow. We don’t want to detect if the mouse is over those!

    So, usually, a pixelmask is a different graphic than the button itself. In our case, the pixelmask would be just the rounded rectangle.

    This will be easy to do. For the pixelmask, we’ll draw a black rounded rect. Then, we draw it on a BitmapData, and finally set our button mask to a Pixelmask of that BitmapData. Like this:

    
    
    		protected function drawMask():void
    		{
    			g.clear();
    			g.beginFill(0x000000);
    			g.drawRoundRect(0, 0, width, height, 100);
    			g.endFill();
    
    			var bd:BitmapData = new BitmapData(width, height, true, 0);
    			bd.draw(sprite);
    
    			mask = new Pixelmask(bd);
    		}
    

    Remember to call the drawMask method in the constructor of the button! This technique will work with all your skins, just remember to draw the basic shape there.

    Here’s how it looks:

    Pixel perfect collision.

    And here’s the pixelmask but with our 20 pixel radius. It’s barely noticeable, but the pixel-perfect collision is there!

    Pixel perfect with normal radius


    Step 3.13: Mouse Change

    Another important thing to do is to change the mouse cursor. That’s important feedback for the user. The ideal behavior is to have a normal arrow cursor by default, but then have a hand cursor when hovering over a button. This way, the user knows that element is clickable. That’s almost always a recommended feedback (except for games like spot-the-difference, some kinds of graphic adventures, and so on).

    To do that, we can use a FlashPunk property in the Input class: mouseCursor. It’s a string, and you can change it as often as you want without any glitches occurring, as the property makes sure only one change is made to AS3 at the end of the frame.

    To achieve the effect, we need to set the cursor to “normal” first, and then set it to “hand” when the button detects it’s over it. Unfortunately, the only way we can do that is add a line to our World. If you don’t feel like adding that line to every world you create, you can either (a) modify FlashPunk or (b) create a BaseWorld class which extends World, add that line and make every world you create extend BaseWorld.

    This is what we’ve got to do, in our update, before the super.update:

    
    
    		override public function update():void
    		{
    			Input.mouseCursor = MouseCursor.AUTO;
    
    			super.update();
    		}
    

    Now this needs to go on Button update. I repeat, on Button update, not on the button skin, which is BlueButton.

    
    
    		override public function update():void
    		{
    			super.update();
    
    			if (collidePoint(x, y, world.mouseX, world.mouseY))
    			{
    				Input.mouseCursor = MouseCursor.BUTTON;
    
    				if (Input.mousePressed) clicked = true;
    
    				if (clicked) changeState(DOWN);
    				else changeState(HOVER);
    
    				if (clicked && Input.mouseReleased) click();
    			}
    			else
    			{
    				if (clicked) changeState(HOVER);
    				else changeState(NORMAL);
    			}
    
    			if (Input.mouseReleased) clicked = false;
    		}
    

    Here’s the result:


    Step 3.14: That’s It!

    Finally. We finished our first skin, a button skin, with complete animation and other handy techniques! Now you’re ready to skin all the buttons you want! But we must learn how to apply our knowledge to other components like checkboxes and radio buttons first…


    Section 4: Checkboxes and Radio Buttons

    Step 4.1: Skin the Checkbox

    Before we introduce the new things we will have to consider for the checkbox, let’s apply what we know about the button to the checkbox.

    As I would have to explain everything again, and I don’t want to repeat myself too much, here’s our BlueCheckbox code, with comments when I think it’s needed to explain something. Also, I didn’t add the sound effects, as I find the ones I made too annoying:

    
    
    package blue
    {
    	import com.greensock.TweenLite;
    	import flash.display.BitmapData;
    	import flash.display.Sprite;
    	import flash.filters.BevelFilter;
    	import flash.filters.DropShadowFilter;
    	import flash.filters.GlowFilter;
    	import flash.geom.Matrix;
    	import flash.text.TextField;
    	import flash.text.TextFormat;
    	import net.flashpunk.FP;
    	import net.flashpunk.graphics.Image;
    	import net.flashpunk.graphics.Stamp;
    	import net.flashpunk.masks.Pixelmask;
    	import ui.Checkbox;
    
    	public class BlueCheckbox extends Checkbox
    	{
    		protected var glare:Stamp;
    		protected var label:Stamp;
    
    		protected var buttonBmp:BitmapData;
    
    		public var topColor:uint = 0x6ACFFF;
    		public var bottomColor:uint = 0x005F8C;
    		public var borderColor:uint = 0x00456A;
    
    		public function BlueCheckbox(x:Number = 0, y:Number = 0, text:String = "", width:Number = 200, height:Number = 50, callback:Function = null, params:Object = null, checked:Boolean = false)
    		{
    			//we need width to always be larger or the same as height, because of the check square.
    			if (height > width) width = height;
    
    			super(x, y, text, width, height, callback, params, checked);
    
    			buttonBmp = new BitmapData(width + 20, height + 20, true, 0);
    			drawButton(buttonBmp, width, height);
    
    			drawGlare();
    			drawLabel(text);
    
    			graphic = new Stamp(buttonBmp, -5, -5);
    
    			drawMask();
    		}
    
    		protected function drawMask():void
    		{
    			//the mask is basically the check square + a square the size of the text.
    			sprite.mask = null;
    
    			g.clear();
    			g.beginFill(0x000000);
    			g.drawRoundRect(0, 0, height, height, 20);
    			g.endFill();
    			g.beginFill(0);
    			g.drawRect(height, label.y + 5, label.width + 5, label.height - 5);
    			g.endFill();
    
    			var bd:BitmapData = new BitmapData(width, height, true, 0);
    			bd.draw(sprite);
    
    			mask = new Pixelmask(bd);
    		}
    
    		protected function drawLabel(text:String):void
    		{
    			var t:TextField = new TextField();
    
    			var tf:TextFormat = new TextFormat("Comfortaa", 20, 0xFFFFFF);
    
    			t.defaultTextFormat = tf;
    			t.width = width - height - 5; //take text position into account
    			t.height = height;
    			t.embedFonts = true;
    			t.wordWrap = true; //if our checkbox widht is smaller than the text, the text adapts.
    			t.text = text;
    			t.filters = [new GlowFilter(0x333333, 0.6, 6, 6, 4, 2)];
    
    			label = drawStamp(t.textWidth + 10, t.textHeight + 10, 5, 5, t);
    			label.y = (height - t.textHeight) * 0.5 - 8;
    			label.x = height + 5;
    		}
    
    		protected function drawGlare():void
    		{
    			//the same method from blue button, but instead of taking width into account, we use the height for the width of the rectangle,
    			//this way we make it a square. it will be the check square.
    			var mask:Sprite = new Sprite;
    			mask.graphics.copyFrom(g);
    
    			sprite.filters = [];
    			g.clear();
    			g.beginFill(0xFFFFFF, 0.25);
    			g.drawEllipse(-height * 0.25, -height * 0.6, height * 1.5, height);
    			sprite.mask = mask;
    
    			glare = drawStamp(width, height * 0.4);
    		}
    
    		protected function drawButton(bitmap:BitmapData, width:Number, height:Number):void
    		{
    			//the same method from blue button, but instead of taking width into account, we use the height for the width of the rectangle,
    			//this way we make it a square. it will be the check square.
    			g.clear();
    			var gradientMatrix:Matrix = new Matrix();
    			gradientMatrix.createGradientBox(width
  7. Sebastian Bratu says:
    June 1, 2012 at 4:26 am

    In this new mini-series of Premium tutorials, you’ll learn how to use Flash to build a Facebook Graph API application that can create slideshows for your public pages. This first part covers getting set up with the Facebook AS3 SDK, loading API info into Flash with JSON, and designing the app with Flash Professional.


    Premium Preview

    Click to try the app on Facebook.

    This application allows you to select a Facebook album or event list from one of your public pages (not your personal profile) and turn it into a slideshow for your page tab. When the users enter your page, they will see photos from your chosen album, with your photo title and description, or event name, date and invites (for the Event tab).

    In future parts of this series, we’ll create the actual Flash slider that does just that; meanwhile we’ll create the generator for the embed code that will reside at the Facebook application URL.

    You’ll need to be logged in to Facebook in order to see this demo: https://apps.facebook.com/activetuts_tabmaker/


    Read the Full Tutorial

    Premium members can access the full tutorial right away!

    If you’re not yet a Premium member, you can still read the first few steps for free.


    Tuts+ Premium Membership

    We run a Premium membership system which periodically gives members access to extra tutorials, like this one, from across the whole Tuts+ network. If you’re a Premium member, you can log in and read the tutorial. If you’re not a member, you can of course join today!

    Also, don’t forget to follow @envatoactive on twitter, circle us on Google+, like us on Facebook, and grab the Activetuts+ RSS Feed to stay up to date with the latest tutorials and articles.


  8. Ashish Bogawat says:
    June 1, 2012 at 4:35 am

    In this week’s critique, Ashish Bogawat gives us a detailed rundown of Google Calendar – specifically, its web-based front end.


    Introduction

    When it comes to web based calendar apps, pretty much the only name worth mentioning is Google Calendar. A number of contenders have taken a swipe at this category of apps over the years, but they have all either died off or metamorphosed into broader roles like project management or event planning. Google Calendar, meanwhile, has held on to its roots as a dedicated calendar app and has prospered into a ubiquitous web app – with some help from Gmail and Android. Its direct integration with the popular smartphone operating system and email service means it will continue to hold its top position for a while to come.

    But what I want to discuss today is purely the web-based front end of Google Calendar. If you have been using it for a while, you will no doubt have realized that the app hasn’t changed much over the years. In times when design trends and standards are changing at a breakneck pace and everyone is feeling the heat to stay ahead of the curve design-wise – including Basecamp and a whole bunch of industry leading web apps – Google Calendar has stagnated as far as its UI goes. Let’s take a look then at how (and whether) it manages to stay relevant.


    Intrinsically Google

    The Google Calendar interface is not unlike most other Google apps – minimal, flat, low on visual hierarchy and decidedly under-designed. This is a good thing in some cases, bad in others. On a positive note, the interface brings pretty much everything you expect to see in your calendar right on to the surface.

    To the left is a mini month calendar, a list of your calendars, and a pretty visible button to add an event. A predominant portion of the rest of the space is taken up by the actual calendar with events neatly marked out on dates or time slots depending on the view you choose. Flipping between a day, week, month or agenda view is simple and straightforward.

    Hitting the arrow next to the “Create” button brings up an input field to quickly add an event with natural language meta data. So typing in “Meeting with john@doe.com at Central Park next Monday 4 pm” actually adds an event for the meeting with John Doe as an invitee, Central Park as the venue and 4 pm the next Monday as the time and date.

    This can be a huge time saver, if you do use the web interface to add events. A big chunk of users don’t. Thanks to its integration with all kinds of apps and platforms, there are numerous ways in which events can go into Google Calendar, so I usually use it only as a dashboard of what my days look like time-wise. There are some nice touches on that front as well. Click an empty part of an event box on the calendar and a popup will appear with some more details. Hit the event text instead and you are taken to the event page with everything you might want to know or edit about the event.


    Built for the Savvy

    Google Calendar’s all inclusive, flat interface also proves to be its biggest flaw, depending on what type of user you are. Although the app can feel extremely intuitive to regular, savvy users, it can actually feel extremely overwhelming for first timers. There is simply too much on the screen with little differentiation and visual hierarchy built in to segregate important elements from secondary ones. The virtual lack of icons also doesn’t help here.

    The interface is also not always very self-explanatory. Here’s an example: when creating an event, there is an input field labeled “Where”. It is not immediately apparent what the ideal contents of this field should be. It was only when I once entered a US address in the field that I realized that Calendar will automatically add a link to the map of the venue when it recognizes the content. Till that point, I used to simply type “conference room” or “skype” in the field oblivious of it true potential.

    Google’s new header doesn’t help matters much either. Sure, you might search for events in your calendar once in a while, but the huge emphasis on the search bar blocking off a big chunk of real estate is not going to make you use it every time. In my 8-10 years of using Calendar, I don’t for once remember searching for a task. I typically need to look at what’s coming up in the next few days and the work week view is always enough for that. For longer term goals, there is always the month view.

    Then there are the minor UI niggles that abound in all Google web apps. The “Save” button when adding an event is at the top, which means I need to scroll all the way up after finishing entering my details in order to save the event. The sidebar in an events detail page is super confusing with little clarity on list of attendees, adding people, etc.


    Wrapping Up

    In the end, Google Calendar is a one-of-its-kind-surviving web app that gets the job done pretty well. Sure, you need some getting used to is and often an engineer’s degree to figure out everything the app can do for you, but it is usually simple enough for new users who are willing to give it some time to understand the basics. If you don’t like the flat UI, you might want to give Helvetical a try to try and spruce up the look a bit. As of now though, I wait for the day when Google will finally give some love to this semi-forgotten app of theirs and give it a much needed experience overhaul.


    Your Turn

    What do you think of Google Calendar? Leave your constructive criticism in the comments.

    And if you’ve built a web app that you’d like the Activetuts+ community to do a critique on, submit it here. We’re looking forward to seeing what you’ve made.


  9. Kah Shiu Chong says:
    June 1, 2012 at 4:57 am

    We see lines used in a lot of scenarios. Curves are also used, although perhaps not as frequently – but that doesn’t undermine their importance! In this tutorial we shall take a closer look at curves, particularly the quadratic and cubic curve, along with some of their commonly used mathematical features.


    Final Result Preview

    Let’s take a look at the final result we will be working towards. Drag the red dots and see the gradients change in position.

    And here’s another demo, using cubic curves, without the gradients:


    Step 1: Curves

    Quadratic and cubic will be featured in each of these sections. So let’s first look at the equation of curves. These equations are written in polynomial form, starting with the term of highest degree. The first one is quadratic equation (highest degree is 2); the second is cubic equation (highest degree is 3).
    \[f(x) = Ax^2 + Bx + C\ ... (eq\ 1)\]
    \[g(x) = Ax^3 + Bx^2 + Cx + D\ ... (eq\ 2)\]

    Note that A, B, C and D are real numbers. So now that we are aquainted with it, let’s try to visualise it. Graphing curves will be our next attempt.


    Step 2: Graphing Curves

    First, let’s graph a quadratic curve. I’m sure all readers have graphed quadratic curve in high school math class, but just to refresh your memory, I present graphs below. They are placed side by side to ease comparison.

    • Left graph is using Cartesian coordinate space
    • Right graph is using Flash coordinate space
    Graphing onto Cartesian and Flash coordinate spaces.

    The obvious difference is the inverted y-axis on Flash coordinate space. They look simple overall, right? Okay, now we’re ready to plot onto Flash coordinate space.


    Step 3: Quadratic Coefficients

    To position quadratic curves at the right spot, we need to understand their corresponding equations. The curve drawn is really dependant on the equation’s coefficients (for the case of quadratic, those are A, B and C).

    I’ve included a Flash presentation below so you can easily tweak these coefficients and get immediate feedback.

    To study the effects of individual coefficients on the overall curve, I suggest following the steps below to experiment with the Flash presentation above.

    1. While setting A and B to 0, tweak the value of C to both positive and negative values. You’ll see the line’s height change.
    2. Now tweak the value of B between positive and negative values. Observe what happens to gradient of line.
    3. Now tweak the value of A between positive and negative values, and compare the results.
    4. Then tweak B between being positive and negative again. Observe the curve’s always cutting through the origin.
    5. Finally tweak C. Observe the whole curve shift along the y-axis.

    Another interesting observation is that throughout the second and third steps of the above, the point of inflection (i.e. the turning point) stays at the same point on the y-axis.


    Step 4: Alternative Equation One

    You quickly see that positioning a curve is somewhat difficult. The equation used is impractical if we want to, say, locate the coordinates of the lowest point on a curve.

    Solution? We’ll rewrite the equation into a desired form. Check out the following equation:

    \[f(x) = P(x+Q)^2+R\]

    It’s still a quadratic equation, but it’s taken another form. Now we can easily control the minimum and maximum points on the curve. In the previous Flash presentation, click on button “Approach 1″ on the top right and play with the new values.

    Here’s a brief explanation of the coefficients’ roles:

    Coefficient Role
    P Control the curve’s steepness.
    Q Control displacement of curve’s turning point along x-axis.
    R Control displacement of curve’s turning point along y-axis.

    Nonetheless, it’s still a difficult task to make the curve pass through a given set of points. We’d have to rigorously pre-calculate on paper before translating it to code.

    Fortunately, there is a better solution. But before going through it, let’s have a look at the ActionScript implementation as of now.


    Step 5: ActionScript Implementation

    Here are the equations written as ActionScript functions (check Graphing.as in the source download).

    
    
    private function quadratic1(x:Number, A:Number, B:Number, C:Number):Number {
        //y = A(x^2) + B(x) + C
        return A*x*x+ B*x + C
    }
    
    private function quadratic2(x:Number, P:Number, Q:Number, R:Number):Number {
        // y = P * (x + Q)^2 + R
        return P*(x+Q)*(x+Q) + R
    }
    

    And here’s an implementation of the drawing method using Graphics.drawPath(). Just a note that all curves in this article are drawn in similar fashion.

    First the variables…

    
    
    private var points:Vector.<Number> = new Vector.<Number>;
    private	var drawCommand:Vector.<int> = new Vector.<int>;
    

    Now the y-positions, calculated based on the x-positions and the given coefficients.

    
    
    private function redraw(A:Number, B:Number, C:Number):void {
        for (var i:int = 0; i < 400; i++) {
            var x:Number = i - 200;
            points[i * 2] = x * 10 + stage.stageWidth >> 1;
            if (isApproach1) {
                points[i * 2 + 1] = quadratic1(x, A, B, C) + stage.stageHeight >> 1
            }
            else {
                points[i * 2 + 1] = quadratic2(x, A, B, C) + stage.stageHeight >> 1
            }
    
            if (i == 0) drawCommand[i] = 1;
            else drawCommand[i] = 2;
        }
        graphics.clear();
        graphics.lineStyle(1);
        graphics.drawPath(drawCommand, points);
    }
    

    (Confused about the >> operator? Take a look at this tutorial.)


    Step 6: Alternative Equation Two

    Suppose we’re given three points that the quadratic curve must cross through; how do we form the corresponding equation? More specifically, how can we determine the coefficient values of the equation? Linear algebra comes to the rescue. Let’s analyse this problem.

    We know that quadratic equations always take form as written in eq. 1 in Step 1.

    \[f(x) = Ax^2 + Bx + C\ ... (eq\ 1)\]

    Since all three coordinates given are lying on the same curve, they must each satisfy this equation, with the same coefficients as the equation of the curve that we are looking for. Let’s write this down in equation form.

    Given three coodinates:

    • \(S\ \left(S_x,\ S_y\right)\)
    • \(T\ \left(T_x,\ T_y\right)\)
    • \(U\ \left(U_x,\ U_y\right)\)

    Substitute these values into (eq 1). Note that A, B, C are unknowns at the moment.

    \[f(x) = Ax^2 + Bx + C\ ... (eq\ 1)\]

    • \(S_y = A\left(S_x\right)^2 + B\left(S_x\right) + C\ \)
    • \(T_y = A\left(T_x\right)^2 + B\left(T_x\right) + C\ \)
    • \(U_y = A\left(U_x\right)^2 + B\left(U_x\right) + C\ \)

    Now, rewrite in matrix form. Take note that A, B, C are the unknowns we are solving for.

    \(
    \begin{bmatrix}S_y \\T_y \\U_y\end{bmatrix} =
    \begin{bmatrix}
    \left(S_x\right)^2 & \left(S_x\right) & 1\\
    \left(T_x\right)^2 & \left(T_x\right) & 1\\
    \left(U_x\right)^2 & \left(U_x\right) & 1\end{bmatrix}
    \begin{bmatrix}A \\B \\C\end{bmatrix} \\
    \)
    \(
    \begin{bmatrix}
    \left(S_x\right)^2 & \left(S_x\right) & 1\\
    \left(T_x\right)^2 & \left(T_x\right) & 1\\
    \left(U_x\right)^2 & \left(U_x\right) & 1\end{bmatrix}^{-1}
    \begin{bmatrix}S_y \\T_y \\U_y\end{bmatrix} =
    \begin{bmatrix}
    \left(S_x\right)^2 & \left(S_x\right) & 1\\
    \left(T_x\right)^2 & \left(T_x\right) & 1\\
    \left(U_x\right)^2 & \left(U_x\right) & 1\end{bmatrix}^{-1}
    \begin{bmatrix}
    \left(S_x\right)^2 & \left(S_x\right) & 1\\
    \left(T_x\right)^2 & \left(T_x\right) & 1\\
    \left(U_x\right)^2 & \left(U_x\right) & 1\end{bmatrix}
    \begin{bmatrix}A \\B \\C\end{bmatrix} \\
    \)
    \(
    \begin{bmatrix}
    \left(S_x\right)^2 & \left(S_x\right) & 1\\
    \left(T_x\right)^2 & \left(T_x\right) & 1\\
    \left(U_x\right)^2 & \left(U_x\right) & 1\end{bmatrix}^{-1}
    \begin{bmatrix}S_y \\T_y \\U_y\end{bmatrix}
    = I
    \begin{bmatrix}A \\B \\C\end{bmatrix}
    \\
    K^{-1}J = L
    \)

    Of course we can use simultaneous equations instead, but I prefer using matrices because it’s simpler. (Editor’s note: as long as you understand matrices, that is!)

    We’ll get the inverse of K and multiply by the J matrix to get L. After we have successfully solved for A, B, C, we’ll just substitute into the quadratic equation. Thus, we’ll have a quadratic curve that passes through all three points.


    Step 7: Importing Coral

    As mentioned in the previous step, we need to perform a 3×3 matrix inversion and multiplication. ActionScript’s flash.geom.matrix class won’t be able to help in this. Of course, we have a choice to utilise flash.geom.Matrix3D, class but I prefer the Coral library because I can pry into these custom classes and examine what’s happening under the hood. I personally find this very useful whenever at doubt on proper use of commands even after reading the API documentation.

    So download and place the unzipped Coral files into your project source folder.

    Download Coral
    Coral integrated with source folder

    Step 8: ActionScript Implementation

    Here’s a sample of the result. Try to reposition the red dots and see the quadratic curve redrawn to cross through all three points.


    Step 9: Implementation Explained

    You can find the full script in Draw_curve.as. The following ActionScript is just to enable mouse controls on the little dots.

    
    
    public function Draw_Curve()
    {
        //setting up controls
        c1 = new Circle(0xFF0000); addChild(c1); c1.x = stage.stageWidth * 0.2; c1.y = stage.stageHeight >> 1;
        c2 = new Circle(0xFF0000); addChild(c2); c2.x = stage.stageWidth * 0.5; c2.y = stage.stageHeight >> 1;
        c3 = new Circle(0xFF0000); addChild(c3); c3.x = stage.stageWidth * 0.8; c3.y = stage.stageHeight >> 1;
    
        c1.addEventListener(MouseEvent.MOUSE_DOWN, move);
        c1.addEventListener(MouseEvent.MOUSE_UP, move);
        c2.addEventListener(MouseEvent.MOUSE_DOWN, move);
        c2.addEventListener(MouseEvent.MOUSE_UP, move);
        c3.addEventListener(MouseEvent.MOUSE_DOWN, move);
        c3.addEventListener(MouseEvent.MOUSE_UP, move);
        redraw()
    }
    
    private function move(e:MouseEvent):void {
        if (e.type == "mouseDown") {
            e.target.startDrag()
            e.target.addEventListener(MouseEvent.MOUSE_MOVE, update);
        }
        else if (e.type == "mouseUp") {
            e.target.stopDrag();
            e.target.removeEventListener(MouseEvent.MOUSE_MOVE, update);
        }
    }
    
    private function update(e:MouseEvent):void {
        redraw();
    }
    

    The core lies in the redraw function. I’ve highlighted the matrix operations and the quadratic function for the redraw process.

    
    
    private function redraw():void
    {
        K = new Matrix3d(	c1.x * c1.x, 	c1.x, 	1, 	0,
                            c2.x * c2.x, 	c2.x, 	1, 	0,
                            c3.x * c3.x, 	c3.x, 	1, 	0,
                                      0,       0,	0, 	1);
        K.invert()
        L = new Matrix3d(	c1.y, 	0, 	0, 	0,
                            c2.y, 	0, 	0, 	0,
                            c3.y, 	0, 	0, 	0,
                               0, 	0, 	0, 	0);
        L.append(K);
    
        graphics.clear();
        var points:Vector.<Number> = new Vector.<Number>;
        var cmd:Vector.<int> = new Vector.<int>;
        for (var i:int = 0; i < 200; i++) {
            //current x
            var x:Number = i * 2;
    
            //f(x) = A (x^2) + B (x) + C
            var y:Number = L.n11* x* x + L.n21 * x + L.n31 ;
    
            points.push(x, y);
            if (i == 0) cmd.push(1);
            else cmd.push(2);
        }
        graphics.lineStyle(1);
        graphics.drawPath(cmd, points);
    }
    

    So you can see that the matrix K was initialised and inverted before being appended onto matrix J.

    The append() function multiplies the current matrix, J, with the input matrix, K, placed to its left. Another noteworthy detail is that we don’t utilise all the rows and columns in K and J matrices. However since matrix inversion can only happen with a square matrix, we need to fill in the 4th row, 4th column element of K with 1. (There’s no need to do this for J because we don’t need its inversion in our calculation.) Thus, you can see all the other elements are 0 except for the first column.


    Step 10: Graphing Cubic Curve

    So that’s all for drawing quadratic curves. Let’s move on to cubic curves.

    Again, we’ll have a little revision of graphing these curves. Check out the following image:

    Cubic graphed on Cartesian and Flash coordinate space.

    When you compare this curve to that of quadratic, you will notice that it is steeper, and that a portion of the curve is below the x-axis. One half is mirrored vertically, compared to a quadratic.


    Step 11: Cubic Coefficients

    I’ve included the following Flash presentation to let you experiment with the coefficients of a cubic equation. Try tweaking the value of A from positive to negative and observe the difference in the curve produced.


    Step 12: ActionScript Implementation

    Here’s the important section of the implementation of the graphing above:

    
    
    private function redraw(A:Number, B:Number, C:Number, D:Number):void {
        for (var i:int = 0; i < 400; i++) {
            var x:Number = i - 200;
            points[i * 2] = x * 10 + stage.stageWidth >> 1;
            points[i * 2 + 1] = cubic1(x, A, B, C, D) + stage.stageHeight >> 1
    
            if (i == 0) drawCommand[i] = 1;
            else drawCommand[i] = 2;
        }
        graphics.clear();
        graphics.lineStyle(1);
        graphics.drawPath(drawCommand, points);
    }
    
    private function cubic1(x:Number, A:Number, B:Number, C:Number, D:Number):Number {
        //y = A(x^3) + B(x^2) + C(x) + D
        return A*x*x*x+ B*x*x + C*x +D
    }
    

    Again, it’s difficult to position the cubic curve according to a set of points it crosses through. Once again, we refer to linear algebra for an alternative.


    Step 13: Alternative Method

    We know from Step 6 that the coefficients of a quadratic equation can be calculated based on three given points, and the curve drawn from it will cross through those points. A similar approach can be performed with any four given points to obtain a cubic equation:

    • \(S\ \left(S_x,\ S_y\right)\)
    • \(T\ \left(T_x,\ T_y\right)\)
    • \(U\ \left(U_x,\ U_y\right)\)
    • \(V\ \left(V_x,\ V_y\right)\)

    Substitute these coordinates into (eq 2). Note that A, B, C, D are unknowns.

    \[g(x) = Ax^3 + Bx^2 + Cx + D\ ... (eq\ 2)\]

    • \(S_y = A\left(S_x\right)^3 + B\left(S_x\right)^2 + C\left(S_x\right) + D\)
    • \(T_y = A\left(T_x\right)^3 + B\left(T_x\right)^2 + C\left(T_x\right) + D\)
    • \(U_y = A\left(U_x\right)^3 + B\left(U_x\right)^2 + C\left(U_x\right) + D\)
    • \(V_y = A\left(V_x\right)^3 + B\left(V_x\right)^2 + C\left(V_x\right) + D\)

    But now we’ll deal with a 4×4 matrix instead of 3×3 matrix:

    \(
    \begin{bmatrix}S_y \\T_y \\U_y \\V_y\end{bmatrix} =
    \begin{bmatrix}
    \left(S_x\right)^3 & \left(S_x\right)^2 & \left(S_x\right) & 1\\
    \left(T_x\right)^3 & \left(T_x\right)^2 & \left(T_x\right) & 1\\
    \left(U_x\right)^3 & \left(U_x\right)^2 & \left(U_x\right) & 1\\
    \left(V_x\right)^3 & \left(V_x\right)^2 & \left(V_x\right) & 1\end{bmatrix}
    \begin{bmatrix}A \\B \\C \\D\end{bmatrix} \\
    P = QR \\
    Q^{-1}P = Q^{-1}QR \\
    Q^{-1}P = IR\\
    Q^{-1}P = R
    \)

    Now we will utilise all elements in the 4×4 matrix for Q and the whole first column for P. Then Q is inversed and applied to P.


    Step 14: ActionScript Implementation

    Again, we set up the mouse controls to allow dragging of those points. When any of those points are being dragged, recalculation and redrawing of the curve constantly happen.

    
    
    public function Draw_Curve2()
    {
        //setting up controls
        c1 = new Circle(0xFF0000); addChild(c1); c1.x = stage.stageWidth * 0.2; c1.y = stage.stageHeight >> 1;
        c2 = new Circle(0xFF0000); addChild(c2); c2.x = stage.stageWidth * 0.4; c2.y = stage.stageHeight >> 1;
        c3 = new Circle(0xFF0000); addChild(c3); c3.x = stage.stageWidth * 0.6; c3.y = stage.stageHeight >> 1;
        c4 = new Circle(0xFF0000); addChild(c4); c4.x = stage.stageWidth * 0.8; c4.y = stage.stageHeight >> 1;
    
        c1.addEventListener(MouseEvent.MOUSE_DOWN, move);
        c1.addEventListener(MouseEvent.MOUSE_UP, move);
        c2.addEventListener(MouseEvent.MOUSE_DOWN, move);
        c2.addEventListener(MouseEvent.MOUSE_UP, move);
        c3.addEventListener(MouseEvent.MOUSE_DOWN, move);
        c3.addEventListener(MouseEvent.MOUSE_UP, move);
        c4.addEventListener(MouseEvent.MOUSE_DOWN, move);
        c4.addEventListener(MouseEvent.MOUSE_UP, move);
    
        redraw();
    }
    private function move(e:MouseEvent):void {
        if (e.type == "mouseDown") {
            e.target.startDrag()
            e.target.addEventListener(MouseEvent.MOUSE_MOVE, update);
        }
        else if (e.type == "mouseUp") {
            e.target.stopDrag();
            e.target.removeEventListener(MouseEvent.MOUSE_MOVE, update);
        }
    }
    
    private function update(e:MouseEvent):void {
        redraw();
    }
    

    redraw is the crucial function where everything happened.

    
    
    private function redraw():void
    {
        var left:Matrix3d = new Matrix3d(c1.x * c1.x* c1.x, 	c1.x* c1.x, 	c1.x , 	1,
                                         c2.x * c2.x * c2.x, 	c2.x* c2.x, 	c2.x , 	1,
                                         c3.x * c3.x * c3.x, 	c3.x* c3.x, 	c3.x , 	1,
                                         c4.x * c4.x * c4.x, 	c4.x* c4.x, 	c4.x , 	1);
        left.invert()
        var right:Matrix3d = new Matrix3d(c1.y, 	0, 	0, 	0,
                                          c2.y, 	0, 	0, 	0,
                                          c3.y, 	0, 	0, 	0,
                                          c4.y, 	0, 	0, 	0);
        right.append(left);
    
        //f(x) = A(x^3) + B (x^2) +C (x) + D
        graphics.clear();
        var points:Vector.<Number> = new Vector.<Number>;
        var cmd:Vector.<int> = new Vector.<int>;
        for (var i:int = 0; i < 200; i++) {
            var x:Number = i * 2;
            var y:Number = right.n11 * x * x * x+
                           right.n21 * x * x+
                           right.n31 * x +
                           right.n41;
    
            points.push(x, y);
            if (i == 0) cmd.push(1);
            else cmd.push(2);
        }
        graphics.lineStyle(1);
        graphics.drawPath(cmd, points);
    }
    

    Finally, let’s look at the product. Click and move the red dots to see cubic curve drawn to pass through all those points.


    Step 15: Polynomials of Higher Degree

    We just gone through drawing polynomials of degree 2 and 3 (quadratic and cubic). From our experience, we can predict that calculation for polynomial of degree 4 (quintic) will require five points, which will require 5×5 matrix, and so on for polynomials of even higher degrees.

    Unfortunately, Coral and flash.geom.Matrix3D only allow for 4×4 matrices, so you’ll have write your own class if the need does come. It’s seldom required in games, though.


    Step 16: Dividing Regions

    Let’s try to apply our knowledge to divide regions on our stage. This requires some revision of equation inequalities. Check out the image below.

    Division of regions

    This image above shows a curve dividing the regions into two:

    • Blue region on top, where for each point y is greater than the equation of the curve.
    • Red region at bottom, where for each point y is less than the equation of the curve.

    It’s not hard to grasp this concept. In fact, you have already experimented on this in Step 11 as you tweaked the coefficients of the cubic formula. Imagine, in the coordinate system, that there is an infinite number of curves, all differentiated by just a slight change in D:

    Infinite curves drawn on graph

    Step 17: ActionScript Implementation

    So here’s the sample of output for quadratic curve. You can try to move the red dot around and see the regions coloured.

    Here’s the important ActionScript snippet. Check out the full script in Region_Curve.as

    
    
    private function redraw():void {
        var left:Matrix3d = new Matrix3d(c1.x * c1.x, 	c1.x, 	1, 	0,
                                         c2.x * c2.x, 	c2.x, 	1, 	0,
                                         c3.x * c3.x, 	c3.x, 	1, 	0,
                                         0, 			0, 		0, 	1);
        left.invert()
        var right:Matrix3d = new Matrix3d(c1.y, 	0, 	0, 	0,
                                          c2.y, 	0, 	0, 	0,
                                          c3.y, 	0, 	0, 	0,
                                          0, 	0, 	0, 	0);
        right.append(left);
    
        //D = A (x^2)+ B (x) +C
        for each (var item: Circle in background) {
            var D:Number = right.n11* item.x * item.x + right.n21 * item.x + right.n31 ;
            //trace(background[i].y);
            if (item.y > D) item.color = 0;
            else item.color = 0xAAAAAA;
        }
    }
    

    Here’s the sample with regard to cubic curve.

    And the implementation that comes with it. Again, full script’s in Region_Curve2.as

    
    
    //D = A + B (x) +C (x^2)
    for each (var item: Circle in background) {
        var D:Number = right.n11 * item.x * item.x * item.x;+
                                    right.n21 * item.x * item.x +
                                    right.n31 * item.x +
                                    right.n41
        //trace(background[i].y);
        if (item.y > D) item.color = 0;
        else item.color = 0xAAAAAA;
    }
    

    Step 18: Variations

    How about some tweaks to change the color across different curves? Again, mouse click on the red dots and see the gradient changes across the screen.


    Step 19: ActionScript Implementation

    Here’s the important ActionScript snippet extracted from Region_Curve3.as. First of all we’ll want to find out the maximum and minimum offset from the original curve.

    
    
    var max:Number = 0;
    var min:Number = 0;
    var Ds:Vector.<Number> = new Vector.<Number>;
    
    //D = A(x^2) + B (x) +C
    for each (var item: Circle in background) {
        var D:Number = right.n11 * item.x * item.x + right.n21 * item.x + right.n31;
        var offset:Number = item.y - D;
        Ds.push(offset);
    
        if (item.y > D && offset > max) max = offset;
        else if (item.y < D && offset < min) min = offset;
    }
    

    Once done, we’ll apply it to colouring the individual dots.

    
    
    //color variations based on the offset
    var color:Number
    for (var i:int = 0; i < background.length; i++) {
        if (Ds[i] > 0) {
            color = Ds[i] / max * 255							//calculating color to slot in
            background[i].color = color<<16 | color<<8 | color;	//define a grayscale
        }
        else if (Ds[i] < 0)	{
            color = Ds[i] / min * 255;
            background[i].color = color<<16;	//define a gradient of red
        }
    }
    

    Conclusion

    So that all for the drawing of curves. Next up, finding roots of a quadratic and cubic curve. Thanks for reading. Do share if you see some real life applications that takes advantage of this tutorial.


  10. Michael James Williams says:
    June 1, 2012 at 5:47 am

    Interested in game design? This weekend, we feature a set of four interactive lectures: games that are about game design, by Pixelate.


    Play the Games

    Bub and Bob, two little 8-bit guys, will talk you through the basic concepts of video games. The games themselves are more like interactive tutorials, with smaller games interspersed throughout to help make certain points, and great chiptunes throughout.

    Episode 1

    Weekend Lecture: Understanding Games

    Click to play.

    The first episode deals with rules, interactivity, representation, and simulation in games.

    Episode 2

    Weekend Lecture: Understanding Games

    Click to play.

    The second episode is about motivating the player to stay in the game, and making sure they have fun.

    Episode 3

    Weekend Lecture: Understanding Games

    Click to play.

    The third episode looks at one of my favourite topics: learning in video games.

    Episode 4

    Weekend Lecture: Understanding Games

    Click to play.

    Finally, the fourth episode is about identification.


Leave a Reply

Click here to cancel reply.

search search search search search
Find an Article
Categories
  • Flash Video Training
  • Hints and Tips
  • Recommended
Please Support Our Sponsors
Recent Posts
  • Tuts+ Community Meetup in New York!
  • HTML5 Canvas Optimization: A Practical Example
  • Recreate the Cover Flow Effect Using Flash and AS3
  • Drawing Activetuts+ to a Close
  • Intro to Dart: Creating a Marquee
Tag Cloud
2011 ActionScript Active Activetuts+ Adobe animation Basic Basix Best Build Button Character Code Create Creating Critique Custom design Effect Effects Files Flash from Game Guide HTML5 Introduction Macromedia Motion Muzzle part Player Premium Professional Quick Silverlight Simple Text Tool Tutorial Tuts+ Using Video website Workshop
About Our Site:

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!

Go Back In Time
May 2013
M T W T F S S
« Jul    
 12345
6789101112
13141516171819
20212223242526
2728293031  
Pretty Blank Box
top

Blogroll

  • Development Blog
  • Documentation
  • Plugins
  • Suggest Ideas
  • Support Forum
  • Themes
  • WordPress Planet

Meta

  • Log in
  • Entries RSS
  • Comments RSS
  • WordPress.org

Archives

  • July 2012
  • June 2012
  • May 2012
  • April 2012
  • March 2012
  • February 2012
  • January 2012
  • December 2011
  • November 2011
  • October 2011
  • September 2011
  • August 2011
  • July 2011
  • June 2011
  • May 2011
  • April 2011
  • March 2011
  • February 2011
  • January 2011
  • December 2010
  • November 2010
  • October 2010
  • September 2010
  • August 2010
  • July 2010
  • June 2010
  • May 2010
  • April 2010
Powered by WordPress  |  Designed by Elegant Themes  |  Lightning Fast Hosting by Site 5 Hosting