logo
468x60-2-495


  • Home
  • Privacy Policy
  • About
search
Apr 22, 2012 Posted on Apr 22, 2012 in Hints and Tips | 10 comments

An ImpactJS Overview: Introduction

Impact is an incredibly powerful HTML5 game framework which takes advantage of modern browser’s canvas element and can also run on mobile or be compile into a native iOS app. In this video I will go over the framework, how to set up a project, some background into how to create classes in it and finally go over the core classes that make up the framework. This is a high level overview which will give you a general sense for how things work.


Watch the Screencast

You can also download the video to watch later.


More Info and Links

To learn more about Impact visit http://ImpactJS.com and check out a copy of my book on Impact called Introducing HTML5 Game Development, published by O’Reilly.

  • Conner Petzol’s nodejs module for Impact: https://github.com/cpetzold/node-impact
  • Mike Hamtilon’s ImpactJS-IIS-.NET-API project: http://code.google.com/p/impactjs-iis-backend/
  • Chris Darroch’s Sinatra backend for Impact: https://github.com/chrisdarroch/impactrb
  • John Resig’s Simple JavaScript Inheritance: http://ejohn.org/blog/simple-javascript-inheritance/
  • There are three more videos in this mini-series, and we’ll be posting them all this week, so come back later for more!



    View full post on Activetuts+

Feb 13, 2012 Posted on Feb 13, 2012 in Hints and Tips | 10 comments

Number Systems: An Introduction to Binary, Hexadecimal, and More

Ever see crazy binary numbers and wonder what they meant? Ever see numbers with letters mixed in and wonder what is going on? You’ll find out all of this and more in this article. Hexadecimal doesn’t have to be scary.

(Thanks to the ReBoot Wiki for the thumbnail image.)


Introduction: What is a Number System?

You probably already know what a number system is – ever hear of binary numbers or hexadecimal numbers? Simply put, a number system is a way to represent numbers. We are used to using the base-10 number system, which is also called decimal. Other common number systems include base-16 (hexadecimal), base-8 (octal), and base-2 (binary).

In this article, I’ll explain what these different systems are, how to work with them, and why knowing about them will help you.


Activity

Before we get started, let’s try a little activity for fun. There are many different ways to represent a color, but one of the most common is the RGB color model. Using this model, every color is made up of a combination of different amounts of red, green, and blue.

You may be wondering how colors relate to number systems. In short, on a computer, any color is stored as a large number: a combination of red, green, and blue. (We’ll go into more detail on this later.) Because it’s just a number, it can be represented in multiple ways using different number systems.

Your job is to guess how much red, green, and blue is in the background color of the activity below. The values for red, green, and blue can range from 0 to 255.

Feel free to use the various hints provided to help you out. If you don’t understand the numerical hints yet, no problem! You can see what your guess looks like using the View Guess button. Right now, it may seem tricky, but hopefully by the end of the article, it will seem easy.


Looking at Base-10

0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11… You’ve counted in base-10 all of your life. Quick, what is 7+5? If you answered 12, you are thinking in base-10. Let’s take a closer look at what you’ve been doing all these years without ever thinking about it.

Let’s take a quick look at counting. First, you go through all the digits: 0, 1, 2… Once you hit 9, you have no more digits to represent the next number. So, you change it back to 0, and add 1 to the tens digit, giving you 10. The process repeats over and over, and eventually you get to 99, where you can’t make any larger numbers with two digits, so you add another, giving you 100.

Although that’s all very basic, you shouldn’t overlook what is going on. The right-most digit represents the number of ones, the next digit represents the number of tens, the next the number of hundreds, etc.


Visualizing Base-10

Confused by these descriptions? No problem – below is a demo to help you out. Simply enter a number in the text box and click draw. Try entering a large number, like 2347. You’ll see 2 groups of one thousand, 3 groups of one hundred, 4 groups of ten, and 7 individual blocks.


Base-10 Mathematically

You may have noticed a pattern by now. Let’s look at what is going on mathematically, using 2347 as an example.

  • As you saw, there are 2 groups of a thousand. Not coincidentally, 1000 = 10*10*10 which can also be written as 103.
  • There are 3 groups of a hundred. Again, not coincidentally, 100 = 10*10 or 102.
  • There are 4 groups of ten, and, 10 = 101.
  • Finally, there are 7 groups of one, and 1 = 100. (That may seem strange, but any number to the power of 0 equals 1, by definition.)

This is essentially the definition of base-10. To get a value of a number in base-10, we simply follow that pattern. Here are a few more examples:

  • 892 = 8*102+9*101+2*100
  • 1147 = 1*103+1*102+4*101+7*100
  • 53 = 5*101+3*100

Admittedly, this all seems a little silly. We all know what value a base-10 number is because we always use base-10, and it comes naturally to us. As we’ll see soon, though, if we understand the patterns in the background of base-10, we can understand other bases better.


Base-8

On to base-8, also called octal. Base-8 means just what is sounds like: the system is based on the number eight (as opposed to ten). Remember how in base-10 we had ten digits? Now, in base-8, we are limited to only eight digits: 0, 1, 2, 3, 4, 5, 6, and 7. There’s no such thing as 8 or 9.

We count the same way as we normally would, except with only eight digits. Instead of a lengthy explanation, simply try out the demo below by clicking “Count Up 1″ to see how counting in base-8 works.

You should notice a similar pattern to before; after we get to 7, we run out of different digits for any higher number. We need a way to represent eight of something. So we add another digit, change the 7 back to 0, and end up with 10. Our answer of 10 in base-8 now represents what we would normally think of as 8 in base-10.

Talking about numbers written in multiple bases can be confusing. For example, as we have just seen, 10 in base-8 is not the same as 10 in base-10. So, from this point on, I’ll use a standard notation where a subscript denotes the base of numbers if needed. For example, our base-8 version of 10 now looks like 108.

(Editor’s note: I find it a lot easier to understand this if I change the way I read these numbers in my head, too. For example, for 108, I read “octal one-oh” or “one-oh in base-eight”. For 1010 I read “decimal one-oh” or “one-oh in base-ten”.)

Great, so we know 108 represents eight items. (Always feel free to plug a number into the first tool for a visualization.) What’s the next number after 778? If you said 1008, you’re correct. We know from what we’ve learned so far that the first 7 in 778 represents groups of 8, and the second 7 represents induvidual items. If we add these all up, we have 7*8 + 7*1 = 63. So we have a total of 6310. So 778=6310. We all know 6410 comes after 6310.


Converting From Base-8 to Base-10

Let’s look at a wordier example now. John offers to give you 478 cookies, and Jane offers to give you 4310 cookies. Whose offer do you take? If you want, go ahead and generate the graphic for 478 graphic with the first tool. Let’s figure out its base-10 value so we can make the best decision!

As we saw when counting, the four in 478 represents the number of groups of eight. This makes sense – we are in base-8. So, in total, we have four groups of eight and seven groups of one. If we add these all up, we get 4*8 + 7*1 = 3910. So, 478 cookies is the exact same as 3910 cookies. Jane’s offer seems like the best one now!

The pattern we saw before with base-10 holds true here also. We’ll look at 5238. There are five groups of 82, two groups of 81 and three groups of 80 (remember, 80=1). If we add these all up, 5*82 + 2*81 + 3*80 = 5*64+2*8+3 = 339, we get 33910 which is our final answer. The diagram below shows the same thing visually:

Converting 523 from base-8 to base-10

Here are a couple more examples:

  • 1118 = 1*82+1*81+1*80 = 64+8+1 = 7310
  • 438 = 4*81+3*80 = 32+3 = 3510
  • 61238 = 6*83+1*82+2*81+3*80 = 3072+64+16+3 = 315510

Converting from Base-10 to Base-8

Converting from base-10 to base-8 is a little trickier, but still straightforward. We basically have to reverse the process from above. Let's start with an example: 15010.

We first find the largest power of 8 that is smaller than our number. Here, this is 82 or 64 (83 is 512). We count how many groups of 64 we can take from 150. This is 2, so the first digit in our base-8 number is 2. We have now accounted for 128 out of 150, so we have 22 left over.

The largest power of 8 that is smaller than 22 is 81 (that is, 8). How many groups of 8 can we take from 22? Two groups again, and thus our second digit is 2.

Finally, we are left with 6, and can obviously take 6 groups of one from this, our final digit. We end up with 2268.

In fact, we can make this process a touch clearer with math. Here are the steps:

  1. 150/82 = 2 remainder 22
  2. 22/81 = 2 remainder 6
  3. 6/80 = 6

Our final answer is then all of our non-remainder digits, or 226. Notice that we still start by dividing by the highest power of 8 that is less that our number.


Dealing with any Base

It's important to be able to apply the concepts we've learned about base-8 and base-10 to any base. Just as base-8 had eight digits and base-10 had ten digits, any base has the same number of digits as its base. So base-5 has five digits (0-4), base-7 has seven digits (0-6), etc.

Now let's see how to find the base-10 value of any number in any base. Say we are working in base-b, where b can be any positive integer. We have a number d4d3d2d1d0 where each d is a digit in a number. (The subscripts here don't refer to the base of the number but simply differentiate each digit.) Our base-10 value is simply d4*b4 + d3*b3 + d2*b2 + d1*b1 + d0*b0.

Here's an example: we have the number 32311 in base-4. Notice how our number only has digits from zero to three since base-4 only has four total digits. Our base-10 value is 3*44 + 2*43 + 3*42 + 1*41 + 1*40 = 3*256 + 2*64 + 3*16 + 1*4 + 1*1 = 949. We could, or course, follow this pattern with any amount of digits in our number.


Base-16

Base-16 is also called hexadecimal. It's commonly used in computer programming, so it's very important to understand. Let's start with counting in hexadecimal to make sure we can apply what we've learned about other bases so far.

Since we are working with base-16, we have 16 digits. So, we have 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ... and yikes! We've run out of digits, but we still need six more. Perhaps we could use something like a circled 10?

The truth is, we could, but this would be a pain to type. Instead, we simply use letters of the alphabet, starting with A and continuing to F. Here's a table with all the digits of base-16:

Base-16 digits

Other than these extra digits, hexadecimal is just like any other base. For example, let's convert 3D16 to base-10. Following our previous rules, we have: 3D16 = 3*161 + 13*160 = 48 + 13 = 61. So 3D16 is equal to 6110. Notice how we use D's value of 13 in our calculation.

We can convert from base-10 to base-16 similar to the way we did with base-8. Let's convert 69610 to base-16. First, we find the largest power of 16 that is less than 69610. This is 162, or 296. Then:

  1. 696/162 = 2 remainder 184
  2. 184/161 = 11 remainder 8
  3. 8/161 = 8 remainder 0

We have to replace 11 with its digit representation B, and we get 2B816.

Feel free to try some more conversions for practice. You can use the application below to check your answers:


Binary! (Base-2)

On to the famous base-2, also called binary. While everyone knows binary is made up of 0s and 1s, it is important to understand that it is no different mathematically than any other base. There's an old joke that goes like this:

binary shirt

Can you figure out what it means?

Let's try a few conversions with base-2. First, we'll convert 1011002 to base-10. We have: 101100 = 1*25 + 1*23 + 1*22 = 32 + 8 + 4 = 4410.

Now let's convert 65 to binary. 27 is the highest power of 2 less than 65, so:

  1. 65/27 = 1 remainder 1
  2. 1/26 = 0 remainder 1
  3. 1/25 = 0 remainder 1
  4. 1/24 = 0 remainder 1
  5. 1/23 = 0 remainder 1
  6. 1/22 = 0 remainder 1
  7. 1/21 = 0 remainder 1
  8. 1/20 = 1 remainder 0

And thus we get our binary number, 10000001.

Understanding binary is super important. I've included a table below to point out digits' values.

Powers of Two

For example, the value of 10001 is 17, which is the sum of the values of the two 1 digits (16+1). This is nothing different than we have done before, its just presented in an easy to read way.


Tricks and Tips

Normally, when converting between two bases that aren't base-10, you would do something like this:

  1. Convert number to base-10
  2. Convert result to desired base

However, there's a trick that will let you convert between binary and hexadecimal quickly. First, take any binary number and divide its digits into groups of four. So, say we have the number 10111012. Divided up we have 0101 1101. Notice how we can just add extra zeroes to the front of the first group to make even groups of 4. We now find the value for each group as if it was its own separate number, which gives us 5 and 13. Finally, we simply use the corresponding hexadecimal digits to write out base-16 number, 5D16.

We can go the other direction also, by converting each hexadecimal digit into four binary digits. Try converting B716 to binary. You should get 101101112.

This trick works because 16 is a power of 2. What this means is that we use similar trick for base-8, which is also a power of 2:

Base-8 to Binary

Of course, you can reverse the process to go from base-8 to binary also.


Conclusion

Let's go all the way back and revisit the color guessing game.

In Flash, colors are stored as a single number. When converted to hexadecimal, the first two digits represent the amount of red, the next two the amount of green, and the final two the amount of blue. So, if our color is 17FF1816 we can easily tell that our red component is 1716 or 2310. Our green component is FF16, or 25510. Finally our blue component is 1816 or 2410. If we are given the base-10 version of our color, 157263210, we need to convert it to hexadecimal before we can tell anything about it.

Try the game again, and see how much better you can do!

Understanding different number systems is extremely useful in many computer-related fields. Binary and hexadecimal are very common, and I encourage you to become very familiar with them. Thanks for reading - I hope you've learned a lot from this article! Feel free to grab the source code from any of the demos. Also, if you have any questions, please ask them below.



View full post on Activetuts+

Jan 22, 2012 Posted on Jan 22, 2012 in Hints and Tips | 10 comments

An Introduction to the HTML5 Gamepad API

As HTML games begin to gradually increase in popularity, vendors are starting to introduce some exciting new APIs to make gaming that little bit sweeter for both us developers and our end players. One of these is the GamepadAPI, which allows you to connect your good old console gamepad into your computer and use it for browser based games, plug and play style. Let’s dive in!


Introduction: What Is the Gamepad API?

In a nutshell, the Gamepad API allows you to interact with your browser using a video game console controller, AKA a gamepad. This doesn’t require a special driver or plugin to work, it’s as simple as plug and play!

Being a console gamer rather than a desktop gamer myself, I much prefer to interact with games using a gamepad, and with the upcoming rise of HTML and JavaScript based games, this is going to become a really useful tool in making games more easily accessible for your users.

The Gamepad API is not readily available for public release, but we can start using it for ourselves with preview versions of Firefox. So before we get stuck in, we need a few things.


What You’ll Need

As I mentioned, the Gamepad API isn’t available for public release just yet so you will need to first get yourself a Nightly build of Firefox and make sure you have the Firebug add-on installed (for debugging purposes only).

Also, you can’t forget a gamepad! I’m going to be using a PlayStation 3 controller for this tutorial but an Xbox controller will do just fine.

  • Nightly – Downloads for Windows, Mac and Linux
  • Firebug – Download
  • A gamepad – PlayStation or Xbox controller will do
  • A USB cable to connect your controller to your computer

Once you have installed Nightly and added on Firebug you are ready to go!

(NB. Recent builds of Chromium have Gamepad API support as well, but this tutorial has not been tested against them.)


Step 1: Connecting a Gamepad to Your Browser

Let’s start with a basic HTML file (index.html), sourcing “gamepad.js” (a blank JavaScript file).

index.html

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Introduction to the Gamepad API</title>
  </head>
  <body>
    <h1>Gamepad API</h1>

    <script src="gamepad.js"></script>
  </body>
</html>

The connection of a gamepad is detected with a simple JavaScript event listener, the event fired is called “MozGamepadConnected”. So the first thing we need to do is add an event listener to the window to detect that event.

I’m also adding a callback function that will log the details of the event to Firebug’s console. This is the information we are most interested in and what will actually let us know that we have connected a gamepad successfully.

function gamepadConnected(evt)
{
  console.log(evt);
}
window.addEventListener('MozGamepadConnected', gamepadConnected);

Run your index.html in Nightly and open up Firebug’s console, here we’ll be able to see the logging of the event from our callback function.

Make sure your controller is turned off and not connected wirelessly to a games console. Plug it in to your computer via USB and power on the controller, watching the event log in the console.

The logged event of connecting a gamepad

Great, we have a gamepad connecting to a browser, no extra plugins or drivers required!


Step 2: Disconnecting a Gamepad

It’s just as important to know whether a gamepad has been disconnected as well, so let’s look at the event, “MozGamepadDisconnected”.

Similarly to step one, add an event listener for a disconnect event and a callback function to log the event details.

function gamepadDisconnected(evt)
{
  console.log(evt);
}
window.addEventListener('MozGamepadDisconnected', gamepadDisconnected);

If you’re gamepad is still connected, refresh your page (which you’ll see connected event be logged) and then disconnect your gamepad by ejecting it from the USB port. You should get an event log like this one.

The logged event of disconnecting a gamepad

Now we know when a gamepad has been connected and disconnected, it’s probably a good idea to record the state inside a variable and get ready to detect button events!

var gamepadActive = false;

function gamepadConnected(evt)
{
  console.log(evt);
  gamepadActive = true;
}
function gamepadDisconnected(evt)
{
  console.log(evt);
  gamepadActive = false;
}

window.addEventListener('MozGamepadConnected', gamepadConnected);
window.addEventListener('MozGamepadDisconnected', gamepadDisconnected);

Step 3: Detecting Button Presses

Button presses, again, use an event listener and callback function with two events, “MozGamepadButtonDown” and “MozGamepadButtonUp”.

I would suggest logging the entire event from the button press yourself to see what is going on, but the key piece of information we need to get from this event is evt.button. This is the numerical id of the button that was pressed.

The callback function this time takes a second parameter, a boolean value to test if the button was pressed or released. We set this ourselves in the callback functions of the event listeners.

function buttonPressed(evt, pressed)
{
  console.log(evt.button, pressed);
}
window.addEventListener("MozGamepadButtonDown", function(evt) { buttonPressed(evt, true); } );
window.addEventListener("MozGamepadButtonUp", function(evt) { buttonPressed(evt, false); } );

This should now output the IDs of the buttons that are pressed and whether they were pressed or released (true for button down, false for button up).

The logged button id's

Next we’ll create an array with all the PlayStation 3 buttons in. The indices of the array will map to the IDs used on this gamepad, with the values being the name of the button.

var gamepadActive = false,
    ps3Buttons = new Array();

ps3Buttons[12]  = 'triangle',
ps3Buttons[15]  = 'square',
ps3Buttons[14]  = 'cross',
ps3Buttons[13]  = 'circle',
ps3Buttons[4]   = 'up',
ps3Buttons[7]   = 'left',
ps3Buttons[6]   = 'down',
ps3Buttons[5]   = 'right',
ps3Buttons[10]  = 'L1',
ps3Buttons[8]   = 'L2',
ps3Buttons[11]  = 'R1',
ps3Buttons[9]   = 'R2',
ps3Buttons[1]   = 'L3',
ps3Buttons[2]   = 'R3',
ps3Buttons[16]  = 'PS',
ps3Buttons[0]   = 'select',
ps3Buttons[3]   = 'start';

If you’re using a different controller, take the time to figure out which index goes with which button, and store that info in a similar array.

If we now modify the buttonPressed() function ever so slightly, we can easily tell which button on the controller has been pressed.

function buttonPressed(evt, pressed)
{
  console.log(ps3Buttons[evt.button] + ' was pressed');
}

Give it a go! Pressing buttons on your controller should now log the name of buttons being pressed. This will be a lot easier to understand than “button 5″ (which, in my case, is on the D-pad).


Step 4: Detecting Axis Events

Detecting axis events is basically keeping track of where the left and right analog sticks on the gamepad are positioned using the “MozGamepadAxisMove” event.

Add the new event handler and callback function.

function moveAnalogSticks(evt) {
  console.log(evt.axis, evt.value);
}
window.addEventListener("MozGamepadAxisMove", moveAnalogSticks);

This is what we get – confusing, right?

The logged button id's

There is only one event fired by both analog sticks; each event gives us one of four possible axis and a value between -1.0 and +1.0. Axis 0 and 1 belong to left analog stick and axis 2 and 3 belong to the right.

The logged button id's

In the diagram above you’ll see axis 0 and 2 correspond to the x axis, and 1 and 3 correspond to the y axis. By using both the x and y axis for each individual analog stick, you can figure out which way the analog stick is facing!

On different gamepads, you may have other axes. For instance, the shoulder triggers on an Xbox controller are also analog.


Step 5: Putting It Into Practice

That covers all of the events that we can currently take from a gamepad, so let’s put what we’ve learnt into practice.

Now, I don’t want to go too heavily into the game development side of things, as we are focusing on what we use to control games themselves. One of the key things to look at, though, is switching control schemes. As not everyone will have a gamepad ready to hand, we need to make sure we provide controls for both the keyboard and gamepad.


Step 6: Setting Up Your Canvas

To get a small demo up and running, create a canvas element in your html file with an id of “game” and set the width to 600 and height to 540. As you may know, the canvas element is commonly used to render HTML games on.

You will also want to copy the “ship.png” and “space.jpg” images from the source download to your working folder as these are what we’ll be rendering to the canvas. Alternatively, find some graphics of your own to have a play with!

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Introduction to the Gamepad API</title>
  </head>
  <body>
    <h1>Gamepad API</h1>
    <canvas id="game" width="600" height="540"></canvas>
    <script src="gamepad.js"></script>
  </body>
</html>

Step 7: Creating the Game Loop

Now that the canvas element is in our DOM, we want to create a game loop to render our game.

I’m using a shim for “requestAnimationFrame” by Paul Irish that will be the base for our loop. Next, we get the 2D context of the canvas which we’ll use to draw on and create two new image objects, one for the background and one for our spaceship.

// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
window.requestAnimFrame = (function(){
  return  window.requestAnimationFrame       ||
          window.webkitRequestAnimationFrame ||
          window.mozRequestAnimationFrame    ||
          window.oRequestAnimationFrame      ||
          window.msRequestAnimationFrame     ||
          function(/* function */ callback, /* DOMElement */ element){
            window.setTimeout(callback, 1000 / 60);
          };
})();

var canvas  = document.getElementById('game'),
    ctx     = canvas.getContext('2d'),
    ship    = new Image(),
    space   = new Image();

space.src = "space.jpg";
ship.src  = "ship.png";

Next, the player object. It has x and y coordinates which keep track of where it should appear on the canvas; four direction states (up, down, left and right) so we can know which way the ship is moving; a render() function, which first calls updatePosition() and then draws the image of the ship onto the canvas based on the x and y coordinates, and finally the updatePosition() function itself, which tests to see which way the ship is set to move and updates its position accordingly.

var player = {
  x: 200,
  y: 250,
  up: false,
  down: false,
  left: false,
  right: false,
  render: function() {
    this.updatePosition();
    ctx.drawImage(ship,this.x,this.y);
  },
  updatePosition: function() {
    this.up     ? this.y-- : false;
    this.down   ? this.y++ : false;
    this.left   ? this.x-- : false;
    this.right  ? this.x++ : false;
  }
}

After that we have our “renderGame” function which draws the space background image onto the canvas first, then draws our spaceship on top of that.

And finally, our loop. This function calls itself again and again, each time calling our “renderGame” function.

function renderGame()
{
  ctx.drawImage(space,0,0);
  player.render();
}

;(function animloop(){
  requestAnimFrame(animloop);
  renderGame();
})();

Your canvas should now have a nice space looking background with a spaceship sat in the middle of it – not too exciting, I know. So let’s add some controls!


Step 8: Hooking Up the Ship’s Controls

In our player code we named the four buttons which we want to control our ship with. These match up to the names of the buttons inside the ps3Buttons[] array. So, all we have to do is modify our buttonPressed() function ever so slightly and we’ll be moving.

var player = {
  ...
  up: false,
  down: false,
  left: false,
  right: false,
  ...
}

Now when a gamepad button is pressed or released it will set its state within the player object, so when the “up” button is pressed, player.up = true/false will be set.

function buttonPressed(evt, pressed)
{
  console.log(evt.button, pressed);
  player[ps3Buttons[evt.button]] = pressed ? true : false;
}

Head back over to your demo and you should be able to move your ship around!


Step 9: Adding a Keyboard Fallback

As not everyone playing your game will have a gamepad, you’ll probably still want to allow them to play the game with a keyboard.

Lets first create a new keys[] array, and map the keyboard’s arrow keys’ keyCode properties to the equivalent buttons on the gamepad. This will allow us to reuse buttonPressed() function that the gamepad utilises.

var gamepadActive = false,
    ps3Buttons    = new Array(),
    keys          = new Array();

ps3Buttons[12]  = 'triangle',
ps3Buttons[15]  = 'square',
ps3Buttons[14]  = 'cross',
ps3Buttons[13]  = 'circle',
ps3Buttons[4]   = 'up',
ps3Buttons[7]   = 'left',
ps3Buttons[6]   = 'down',
ps3Buttons[5]   = 'right',
ps3Buttons[10]  = 'L1',
ps3Buttons[8]   = 'L2',
ps3Buttons[11]  = 'R1',
ps3Buttons[9]   = 'R2',
ps3Buttons[1]   = 'L3',
ps3Buttons[2]   = 'R3',
ps3Buttons[16]  = 'PS',
ps3Buttons[0]   = 'select',
ps3Buttons[3]   = 'start';

keys[38] = 4;
keys[37] = 7;
keys[40] = 6;
keys[39] = 5;

Now we need a “onkeyup” and “onkeydown” event listener for the arrow keys. When a key is pressed or released, we make sure that a gamepad is not in use. Then we prevent the arrow key from doing its usual task (scrolling the browser window up or down in this case) and then call the same buttonPressed() function that the gamepad calls.

To do this, a fake event object is passed with the key’s “keyCode” mapped to an item in the keys[] array, which in turn, passes the corresponding gamepad button ID.

window.onkeydown = function(evt)
  {
    if (gamepadActive == false)
    {
      evt.preventDefault();
      buttonPressed({ button: keys[evt.keyCode] }, true);
    }
  }
window.onkeyup = function(evt)
  {
    if (gamepadActive == false)
    {
      evt.preventDefault();
      buttonPressed({ button: keys[evt.keyCode] }, false);
    }
  }

This should now let you use the arrow keys for controlling the ship when a gamepad isn’t plugged in, while still letting the gamepad take over when it’s present.


Conclusion

So we’ve covered the basics of connecting a gamepad to your computer, learnt how to hook into the events that the gamepad fires, and then use them in practice. Not forgetting, the crucial fall-back support for the keyboard!

A quick challenge for those of you with a controller other than a PS3 Dual Shock: adjust the button mapping based on whichever controller is plugged in.

Thank you for taking the time to learn about the Gamepad API. If you have any questions, please leave them in the comments.



View full post on Activetuts+

Nov 17, 2011 Posted on Nov 17, 2011 in Hints and Tips | 10 comments

An Introduction to FlashPunk: Creating a Spaceship Shoot-’Em-Up

This entry is part 2 of 2 in the series An Introduction to FlashPunk

In the last tutorial, we introduced FlashPunk and its capabilities. Now it’s time to build a game with it! We’ll build a top-down, mouse-controlled shoot-’em-up, with a title screen and a game over screen. Read on to learn more…


Final Result Preview

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


Step 1: The Player Ship

As always, first we need a clean project. Grab the latest FlashPunk build from the official site. Create a new AS3 project in FlashDevelop and put FlashPunk’s source in the source folder of the project. The game will have the following dimensions: 400×500 px.

We will begin our game by adding a ship – the player ship – on the screen. For that, we will need a new world, called GameWorld, and an image:

Player Ship Image

The player ship will be an entity. Create one, embed the image in it and put it on the screen. If you’re feeling lost, below is the code for the player ship (if you’re really feeling lost, I recommend reading the first tutorial again). I think that creating the world won’t be a problem for you.

package
{
	import net.flashpunk.Entity;
	import net.flashpunk.graphics.Image;

	public class PlayerShip extends Entity
	{
		[Embed(source = '../img/PlayerShipImage.png')]
		private const IMAGE:Class;

		public function PlayerShip()
		{
			graphic = new Image(IMAGE);

			graphic.x = -27.5;
			graphic.y = -30;

			x = 200;
			y = 400;
		}

	}

}

Add the player ship into the world and make it the current world when FlashPunk’s Engine starts. You’ll get the following:

The player ship in game

Step 2: Movement

With the player ship on the screen, we need to make it move. Just like every shoot-’em-up game, the player ship will be able to move across all the screen. There’s one thing left to decide before coding the movement: we will be using frame-based movement (the reason for this is in the next step). That means changing (if needed) the super() call to FlashPunk’s Engine and NOT using the FP.elapsed property.

The code for the player ship movement is below. The movement is mouse-based:

		private var _currentDistanceX:Number;
		private var _currentDistanceY:Number;

		private const SPEED:int = 3;

		override public function update():void
		{
			calculateDistances();

			if ((_currentDistanceX * _currentDistanceX) + (_currentDistanceY * _currentDistanceY) < SPEED * SPEED)
			{
				x = Input.mouseX;
				y = Input.mouseY;
			}
			else
			{
				x += Math.cos(Math.atan2(_currentDistanceY, _currentDistanceX)) * SPEED;
				y += Math.sin(Math.atan2(_currentDistanceY, _currentDistanceX)) * SPEED;
			}
		}

		private function calculateDistances():void
		{
			_currentDistanceX = Input.mouseX - x;
			_currentDistanceY = Input.mouseY - y;
		}

You will need to import net.flashpunk.utils.Input in the player ship class. Also, don’t forget to enable FlashPunk’s console. After compiling the project, you will see the player ship following the mouse:


Step 3: Enemies

Time to add something fun: enemies. Enemies need to spawn randomly (based on waves) and need to have a controlled movement. They also have a different image:

Image of the enemy

The code for creating the enemy class and adding the image to it shouldn’t be a problem. What we need to focus on is how to make enemies follow a path. The idea is this: we create a wave of enemies and pass them a path to follow, and when to spawn. After that, they will be responsible for showing themselves on the screen and moving along the path.

What is a good representation for a path? A Vector of points seems good enough. Also, we need to define a distance between each point. That way, we can be sure of one important thing: if we define the distance between two points of the path to be the distance that the enemy moves during 1 frame, we won’t need the enemy to process too much information, and we will be able to define after how many frames the enemy will leave the screen by just counting the number of points in the vector. That way, it’s very easy to define when a wave will end.

See it in action: the code below only makes enemies follow a path already given to them, and on the time passed to them (which will be counted in frames). When the enemy is created, a counter that starts on a given number begins decreasing after each elapsed frame, and when it reaches zero, the enemy will put itself on screen and begin following its path.

package
{
	import flash.geom.Point;
	import net.flashpunk.Entity;
	import net.flashpunk.FP;
	import net.flashpunk.graphics.Image;
	import net.flashpunk.World;

	public class Enemy extends Entity
	{
		[Embed(source = '../img/EnemyImage.png')]
		private const IMAGE:Class;

		private var _timeToAct:uint;
		private var _pathToFollow:Vector.<Point>;

		private var _currentPoint:uint;

		private var _myWorld:World;
		private var _added:Boolean;

		public function Enemy(timeToAct:uint, pathToFollow:Vector.<Point>, worldToBeAdded:World)
		{
			graphic = new Image(IMAGE);

			graphic.x = -15;
			graphic.y = -8;

			_timeToAct = timeToAct;

			_pathToFollow = pathToFollow;

			_currentPoint = 0;

			_myWorld = worldToBeAdded;
			_added = false;
		}

		override public function update():void
		{
			if (_timeToAct > 0)
			{
				_timeToAct--;
			}
			else
			{
				if (!_added)
				{
					_myWorld.add(this);

					_added = true;
				}

				x = _pathToFollow[_currentPoint].x;
				y = _pathToFollow[_currentPoint].y;

				_currentPoint++;

				if (_currentPoint == _pathToFollow.length)
				{
					_myWorld.remove(this);

					_added = false;

					destroy();
				}
			}
		}

		public function destroy():void
		{
			graphic = null;
		}

	}

}

From the code above, you can see that we always move a fixed distance from point to point by just positioning the enemy on its current point. It is because of this that we are able to determine when an enemy wave will end. You can also see that the enemy takes care of everything: adding itself in the world, moving through the world and removing itself from the world. With that, it’s very simple to create enemies in the game.


Step 4: Adding Enemies to the Screen

Our base Enemy class is done. Now it’s time to modify GameWorld a bit to add enemies. The first task is to generate paths for the enemies. For the purposes of this tutorial, we will only create a straight line, but feel free to try creating any kind of wave path. This is the function that creates a straight line:

		private function generateEnemyPath(distanceBetweenPoints:Number):Vector.<Point>
		{
			var i:Number;

			var vec:Vector.<Point> = new Vector.<Point>();

			var xPos:Number = Math.random() * 360 + 20;

			for (i = -20; i < 520; i += distanceBetweenPoints)
			{
				vec.push(new Point(xPos, i));
			}

			return vec;
		}

With that, we can already give to an enemy a path to follow. The next step is to actually create the enemy:

		private var _enemy:Enemy;

		public function GameWorld()
		{
			_playerShip = new PlayerShip();

			add(_playerShip);

			_enemy = new Enemy(0, generateEnemyPath(1), this);
		}

		override public function update():void
		{
			super.update();

			if (_enemy)
				_enemy.update();
		}

Compile and run the game. You’ll probably get the following error:

[Fault] exception, information=RangeError: Error #1125: The index 540 is out of range 540.

That happens because even after the enemy deletes itself from the world, we are still calling the update() function of it, because our code didn’t detect when the enemy removed itself. Let’s fix that by overriding the current remove() method:

		override public function remove(e:Entity):Entity
		{
			if (e is Enemy)
			{
				_enemy = new Enemy(0, generateEnemyPath(1), this);
			}

			return super.remove(e);
		}

Now compile the project and you’ll see this:

This is what that function does: every time the enemy removes itself from the world, we detect that through our overriden function and then just create another enemy to “replace” the old one. That’s it! We now have enemies moving across the screen!


Step 5: Shooting With the Player Ship

A shoot-’em-up game wouldn’t be fun without cool ways of shooting bullets out of your ship, would it? In this step we’ll see a great way of organizing bullet patterns in order to shoot them. If you tried to take a guess, you are probably correct: we’re going to use Vectors of Points. However, this time the points will have dynamic beginnings and ends, because your ship won’t always be at the same place every time you shoot, but don’t worry, it’s not as hard as it sounds!

The strategy here is to generate a bullet pattern around a fixed x- and y-axis, and then sum the player ship’s position to the points from the pattern, thus relocating the axis to a new position, giving the impression that the bullets are coming out of the player ship. The bullet image we are going to use is this:

Player bullet

Everything gets simpler when you look at the code. We are basically doing something very similar to the enemy path:

package
{
	import flash.geom.Point;
	import net.flashpunk.Entity;
	import net.flashpunk.graphics.Image;

	public class PlayerBullet extends Entity
	{
		[Embed(source = '../img/BulletImage.png')]
		private const IMAGE:Class;

		private var _pathToFollow:Vector.<Point>;

		private var _xPos:Number;
		private var _yPos:Number;

		public function PlayerBullet(pathToFollow:Vector.<Point>, xPos:Number, yPos:Number)
		{
			graphic = new Image(IMAGE);

			graphic.x = graphic.y = -3.5;

			_pathToFollow = pathToFollow;

			_xPos = xPos;
			_yPos = yPos;
		}

		override public function update():void
		{
			x = _xPos + _pathToFollow[0].x;
			y = _yPos + _pathToFollow[0].y;

			_pathToFollow.shift();

			if (_pathToFollow.length == 0)
			{
				world.remove(this);

				destroy();
			}
		}

		public function destroy():void
		{
			_pathToFollow = null;

			graphic = null;
		}

	}

}

Notice that we don’t really create the bullet patterns in here: they’re always passed as parameters, just like the enemies. The only difference is that the bullets are always added right away in the world and we keep the initial position of the bullet.

Let’s try adding a bullet when the player clicks with the mouse. In PlayerShip.as:

		override public function update():void
		{
			calculateDistances();

			if ((_currentDistanceX * _currentDistanceX) + (_currentDistanceY * _currentDistanceY) < SPEED * SPEED)
			{
				x = Input.mouseX;
				y = Input.mouseY;
			}
			else
			{
				x += Math.cos(Math.atan2(_currentDistanceY, _currentDistanceX)) * SPEED;
				y += Math.sin(Math.atan2(_currentDistanceY, _currentDistanceX)) * SPEED;
			}

			if (Input.mousePressed)
			{
				world.add(new PlayerBullet(GameWorld(world).generateBulletPath(3), x, y));
			}
		}

Now we need to create the bullet path. We are going to create a straight line, just like for the enemy, but you can do any kind of path! In GameWorld.as, let’s create the generateBulletPath() function:

		public function generateBulletPath(distanceBetweenPoints:Number):Vector.<Point>
		{
			var i:Number;

			var vec:Vector.<Point> = new Vector.<Point>();

			for (i = 0; i > -500; i -= distanceBetweenPoints)
			{
				vec.push(new Point(0, i));
			}

			return vec;
		}

With that, hit the compile and run button and this is what you get:


Step 6: Collision Detection (Using Masks)

We have now the basics of the game running: a player ship that shoots and enemies that go down the screen. Time to add collision detection!

The first step to add the collision detection is to give each entity a type. I’ll leave that to you: give the “Player” type to PlayerShip, “Enemy” to Enemy and “PlayerBullet” to PlayerBullet.

We will be using pixel-perfect collision in this game, so it might be useful to talk about masks. Masks are elements used by FlashPunk for collision detection. They are basically like hitboxes, but they can have a different form (pixel level). We need to set up masks for the player ship, enemies and bullets. The image used by the mask is the same image of the entity. Look at the code for the PlayerShip, Enemy and PlayerBullet, respectively:

		public function PlayerShip()
		{
			graphic = new Image(IMAGE);

			graphic.x = -27.5;
			graphic.y = -30;

			mask = new Pixelmask(IMAGE, -27.5, -30);

			x = 200;
			y = 400;

			type = "Player";
		}
		public function Enemy(timeToAct:uint, pathToFollow:Vector.<Point>, worldToBeAdded:World)
		{
			graphic = new Image(IMAGE);

			graphic.x = -15;
			graphic.y = -8;

			mask = new Pixelmask(IMAGE, -15, -8);

			_timeToAct = timeToAct;

			_pathToFollow = pathToFollow;

			_currentPoint = 0;

			_myWorld = worldToBeAdded;
			_added = false;

			type = "Enemy";
		}
		public function PlayerBullet(pathToFollow:Vector.<Point>, xPos:Number, yPos:Number)
		{
			graphic = new Image(IMAGE);

			graphic.x = graphic.y = -3.5;

			mask = new Pixelmask(IMAGE, -3.5, -3.5);

			_pathToFollow = pathToFollow;

			_xPos = xPos;
			_yPos = yPos;

			type = "PlayerBullet";
		}

As you can see, this is very simple: we create a new Pixelmask, pass the source to use as a mask (just like with the graphic) and then pass both x and y offsets (in case you want to center the mask somewhere). Now, in GameWorld.as:

		private var _bulletList:Vector.<PlayerBullet>;

		override public function update():void
		{
			super.update();

			if (_enemy)
				_enemy.update();

			_bulletList = new Vector.<PlayerBullet>();

			getType("PlayerBullet", _bulletList);

			for each (var bullet:PlayerBullet in _bulletList)
			{
				if (bullet.collideWith(_enemy, bullet.x, bullet.y))
				{
					_enemy.takeDamage();

					remove(bullet);

					bullet.destroy();
				}
			}
		}

Notice that we could have simply used _enemy.collide("PlayerBullet", _enemy.x, _enemy.y) to check for collisions, but the method above is better when we have many bullets on the screen and there is a possibility that two bullets hit the same enemy at the same time. We have called the takeDamage() function of the Enemy class, but at the moment there is none. (Create an empty function for now. In the next step we will make the enemy take damage and explode when necessary.) Compile the project and you’ll get this:


Step 7: Enemy Death

We have made bullets hit our enemies. In this step we will play an explosion animation every time an enemy dies and remove it from the game. The explosion animation sprite sheet is below:

Explosion after enemy death

The approach we will take to do this is by decreasing the enemy’s health in the takeDamage() function, and if the health gets below zero, we will destroy it and put the animation in the screen. The code for decreasing the health is below:

		private var _health:int = 100;

		public function takeDamage():void
		{
			_health -= 50;

			if (_health <= 0)
			{
				addExplosion();

				_myWorld.remove(this);

				_added = false;

				destroy();
			}
		}

The code is very simple. There’s only one thing unknown about it: the addExplosion() function. This function will create an instance of Explosion and add it to the world. The Explosion class will just play and remove itself from the world after that. It’s a simple class:

package
{
	import net.flashpunk.Entity;
	import net.flashpunk.graphics.Spritemap;

	public class Explosion extends Entity
	{
		[Embed(source = '../img/ExplosionAnimation.png')]
		private const ANIMATION:Class;

		public function Explosion(xPos:Number, yPos:Number)
		{
			graphic = new Spritemap(ANIMATION, 50, 46, onAnimationEnd);

			graphic.x = -25;
			graphic.y = -23;

			x = xPos;
			y = yPos;

			Spritemap(graphic).add("Explode", [0, 1, 2, 3, 4], 25/60, false);

			Spritemap(graphic).play("Explode");
		}

		private function onAnimationEnd():void
		{
			world.remove(this);

			destroy();
		}

		public function destroy():void
		{
			graphic = null;
		}

	}

}

The trick here is using the callback parameter of the Spritemap class: when the animation ends, that function will be called, and then it removes itself from the world.

Now, back to Enemy.as to finish that function!

		private function addExplosion():void
		{
			world.add(new Explosion(x, y));
		}

Easy, isn’t it? Compile the game and destroy some enemies!


Step 8: Score

The next logical step after making enemies die is to add a score in the game! We will do that using FlashPunk’s Text class. Start by creating a GameScore class, which will hold the score of the game. Since Text is a Graphic, we will make GameScore an Entity and add its text as a graphic. Look at the code:

package
{
	import net.flashpunk.Entity;
	import net.flashpunk.graphics.Text;

	public class GameScore extends Entity
	{
		private var _score:int;

		public function GameScore()
		{
			graphic = new Text("Score: 0");

			_score = 0;
		}

		public function addScore(points:int):void
		{
			_score += points;

			Text(graphic).text = "Score: " + _score.toString();
		}

		public function destroy():void
		{
			graphic = null;
		}

	}

}

As you can see, we will call the addScore() function to add points to the game’s score. First, we need to add it to the world. In GameWorld.as:

		private var _score:GameScore;

		public function GameWorld()
		{
			_playerShip = new PlayerShip();

			add(_playerShip);

			_enemy = new Enemy(0, generateEnemyPath(1), this);

			_score = new GameScore();

			_score.x = 300;
			_score.y = 470;

			add(_score);
		}

		public function get score():GameScore
		{
			return _score;
		}

		public function get score():int
		{
			return _score;
		}

If we hit compile, we get just a static score on the bottom of the screen:

The game score

We need to add something to the score every time an enemy is killed. In Enemy.as:

		public function takeDamage():void
		{
			_health -= 50;

			if (_health <= 0)
			{
				addExplosion();

				GameWorld(world).score.addScore(1);

				_myWorld.remove(this);

				_added = false;

				destroy();
			}
		}

Hit compile now and the score will always increase when an enemy is killed!


Step 9: Upgrades

Time to add upgrades! We will not have a nice screen to choose upgrades. Instead, we will create upgrades based on the score: each time the score goes up by 5 (up to 45), the player’s speed will increase a bit. When the score reaches 25, the player will be able to shoot two shots on every click. We will make the score 50 be the end of the game.

Let’s begin by coding the player speed upgrade. For that, we will need to add a multiplier to the speed. In PlayerShip.as:

		public var speedMultiplier:Number = 1;

		override public function update():void
		{
			calculateDistances();

			if ((_currentDistanceX * _currentDistanceX) + (_currentDistanceY * _currentDistanceY) < SPEED * SPEED * speedMultiplier * speedMultiplier)
			{
				x = Input.mouseX;
				y = Input.mouseY;
			}
			else
			{
				x += Math.cos(Math.atan2(_currentDistanceY, _currentDistanceX)) * SPEED * speedMultiplier;
				y += Math.sin(Math.atan2(_currentDistanceY, _currentDistanceX)) * SPEED * speedMultiplier;
			}

			if (Input.mousePressed)
			{
				world.add(new PlayerBullet(GameWorld(world).generateBulletPath(3), x, y));
			}
		}

Now it’s all about changing the multiplier in GameWorld.as:

		private var _speedUpgradeNumber:int = 0;

		override public function update():void
		{
			super.update();

			if (_enemy)
				_enemy.update();

			_bulletList = new Vector.<PlayerBullet>();

			getType("PlayerBullet", _bulletList);

			for each (var bullet:PlayerBullet in _bulletList)
			{
				if (bullet.collideWith(_enemy, bullet.x, bullet.y))
				{
					_enemy.takeDamage();

					remove(bullet);

					bullet.destroy();
				}
			}

			if ((_score.score % 5) == 0 && _score.score > (_speedUpgradeNumber * 5))
			{
				_playerShip.speedMultiplier += 0.1;

				_speedUpgradeNumber++;
			}
		}

Done! Now, every 5 enemy deaths the player will receive a 10% increase in moving speed!

For the double bullet upgrade, we will make a boolean in the PlayerShip class indicating whether or not the ship has the upgrade. Then we will check that when shooting. Here is it:

		public var hasDoubleShoot:Boolean = false;

		override public function update():void
		{
			calculateDistances();

			if ((_currentDistanceX * _currentDistanceX) + (_currentDistanceY * _currentDistanceY) < SPEED * SPEED * speedMultiplier * speedMultiplier)
			{
				x = Input.mouseX;
				y = Input.mouseY;
			}
			else
			{
				x += Math.cos(Math.atan2(_currentDistanceY, _currentDistanceX)) * SPEED * speedMultiplier;
				y += Math.sin(Math.atan2(_currentDistanceY, _currentDistanceX)) * SPEED * speedMultiplier;
			}

			if (Input.mousePressed)
			{
				if (hasDoubleShoot)
				{
					world.add(new PlayerBullet(GameWorld(world).generateBulletPath(3), x - 5, y));
					world.add(new PlayerBullet(GameWorld(world).generateBulletPath(3), x + 5, y));
				}
				else
				{
					world.add(new PlayerBullet(GameWorld(world).generateBulletPath(3), x, y));
				}
			}
		}

Now, let’s do the same as we did for the speed in GameWorld.as:

		override public function update():void
		{
			super.update();

			if (_enemy)
				_enemy.update();

			_bulletList = new Vector.<PlayerBullet>();

			getType("PlayerBullet", _bulletList);

			for each (var bullet:PlayerBullet in _bulletList)
			{
				if (bullet.collideWith(_enemy, bullet.x, bullet.y))
				{
					_enemy.takeDamage();

					remove(bullet);

					bullet.destroy();
				}
			}

			if ((_score.score % 5) == 0 && _score.score > (_speedUpgradeNumber * 5))
			{
				_playerShip.speedMultiplier += 0.1;

				_speedUpgradeNumber++;
			}

			if (_score.score >= 25)
			{
				_playerShip.hasDoubleShoot = true;
			}
		}

And that’s it! Hit compile and your game will have upgrades!


Step 10: Increasing the Difficulty

If you played the game until getting the double shot upgrade in the last step, you may have noticed that the game is too easy right now. What do you think of increasing its difficulty based on the player’s score?

That’s the idea: the game will now be able to put on the screen more than one enemy. And for each kill the player gets, we decrease the timer of spawning a new enemy. Interesting, isn’t it? But that’s not the only thing. What about increasing the enemies’ healths and decreasing the damage they take from the player? Now we’re getting somewhere!

Let’s jump to the coding: first we will make the health increase and damage decrease every kill. They will be just like the upgrades on the player ships, but this time we will need to change our approach as to where to keep the multipliers. In Enemy.as:

		private var _health:int;

		public static var healthMultiplier:Number = 1;
		public static var damageMultiplier:Number = 1;

		public function Enemy(timeToAct:uint, pathToFollow:Vector.<Point>, worldToBeAdded:World)
		{
			graphic = new Image(IMAGE);

			graphic.x = -15;
			graphic.y = -8;

			mask = new Pixelmask(IMAGE, -15, -8);

			_timeToAct = timeToAct;

			_pathToFollow = pathToFollow;

			_currentPoint = 0;

			_myWorld = worldToBeAdded;
			_added = false;

			type = "Enemy";

			health = 100 * Enemy.healthMultiplier;
		}

		public function takeDamage():void
		{
			_health -= 50 * Enemy.damageMultiplier;

			if (_health <= 0)
			{
				addExplosion();

				GameWorld(world).score.addScore(1);

				_myWorld.remove(this);

				_added = false;

				destroy();
			}
		}

And now, in GameWorld.as:

		private var _enemyUpgradeNumber:int = 0;

		override public function update():void
		{
			super.update();

			if (_enemy)
				_enemy.update();

			_bulletList = new Vector.<PlayerBullet>();

			getType("PlayerBullet", _bulletList);

			for each (var bullet:PlayerBullet in _bulletList)
			{
				if (bullet.collideWith(_enemy, bullet.x, bullet.y))
				{
					_enemy.takeDamage();

					remove(bullet);

					bullet.destroy();
				}
			}

			if ((_score.score % 5) == 0 && _score.score > (_speedUpgradeNumber * 5))
			{
				_playerShip.speedMultiplier += 0.1;

				_speedUpgradeNumber++;
			}

			if (_score.score >= 25)
			{
				_playerShip.hasDoubleShoot = true;
			}

			if (_score.score > _enemyUpgradeNumber)
			{
				Enemy.damageMultiplier -= 0.015;
				Enemy.healthMultiplier += 0.02;

				_enemyUpgradeNumber++;
			}
		}

And now our enemies are getting stronger after each kill! Take that, evil player!

Now we need to modify GameWorld in order to spawn enemies based on time. It’s a simple thing: we will just need a timer and a spawn interval. Here’s all the modified code:

		private var _enemyList:Vector.<Enemy>;

		private var _enemySpawnInterval:int = 5000;
		private var _enemySpawnTimer:int;

		public function GameWorld()
		{
			_playerShip = new PlayerShip();

			add(_playerShip);

			_enemyList = new Vector.<Enemy>();

			_score = new GameScore();

			_score.x = 300;
			_score.y = 470;

			add(_score);

			_enemySpawnTimer = 0;
		}

		override public function update():void
		{
			super.update();

			_enemySpawnTimer--;

			if (_enemySpawnTimer <= 0)
			{
				_enemySpawnTimer = _enemySpawnInterval;

				_enemyList.push(new Enemy(uint(Math.random() * 30), generateEnemyPath(2), this));

				add(_enemyList[_enemyList.length - 1]);
			}

			_bulletList = new Vector.<PlayerBullet>();

			getType("PlayerBullet", _bulletList);

			for each (var bullet:PlayerBullet in _bulletList)
			{
				for each (var enemy:Enemy in _enemyList)
				{
					if (bullet.collideWith(enemy, bullet.x, bullet.y))
					{
						enemy.takeDamage();

						remove(bullet);

						bullet.destroy();
					}
				}
			}

			if ((_score.score % 5) == 0 && _score.score > (_speedUpgradeNumber * 5))
			{
				_playerShip.speedMultiplier += 0.1;

				_speedUpgradeNumber++;
			}

			if (_score.score >= 25)
			{
				_playerShip.hasDoubleShoot = true;
			}

			if (_score.score > _enemyUpgradeNumber)
			{
				Enemy.damageMultiplier -= 0.015;
				Enemy.healthMultiplier += 0.02;

				_enemyUpgradeNumber++;
			}
		}

		override public function remove(e:Entity):Entity
		{
			if (e is Enemy)
			{
				_enemyList.splice(_enemyList.indexOf(e), 1);
			}

			return super.remove(e);
		}

Notice that I gave the enemies a few random frames of “wait time” before appearing. That will make their appearance unpredictable. Now all that’s left is to decrease the spawn interval after every kill:

		override public function update():void
		{
			super.update();

			_enemySpawnTimer--;

			if (_enemySpawnTimer <= 0)
			{
				_enemySpawnTimer = _enemySpawnInterval;

				_enemyList.push(new Enemy(uint(Math.random() * 30), generateEnemyPath(2), this));

				add(_enemyList[_enemyList.length - 1]);
			}

			_bulletList = new Vector.<PlayerBullet>();

			getType("PlayerBullet", _bulletList);

			for each (var bullet:PlayerBullet in _bulletList)
			{
				for each (var enemy:Enemy in _enemyList)
				{
					if (bullet.collideWith(enemy, bullet.x, bullet.y))
					{
						enemy.takeDamage();

						remove(bullet);

						bullet.destroy();
					}
				}
			}

			if ((_score.score % 5) == 0 && _score.score > (_speedUpgradeNumber * 5))
			{
				_playerShip.speedMultiplier += 0.1;

				_speedUpgradeNumber++;
			}

			if (_score.score >= 25)
			{
				_playerShip.hasDoubleShoot = true;
			}

			if (_score.score > _enemyUpgradeNumber)
			{
				Enemy.damageMultiplier -= 0.015;
				Enemy.healthMultiplier += 0.02;

				_enemySpawnInterval -= 3;

				_enemyUpgradeNumber++;
			}
		}

With that, we basically have everything done in the game world!


Step 11: The Main Menu World

I think we have everything finished in the game world. The game’s surprisingly difficult with the tougher enemies! What do you think of making a nice main menu now? I created a nice background for it:

The main menu screen

Create the MainMenuWorld class, which extends from net.flashpunk.World, and add the background in it. I’ll leave the code for you. We will need a play button, which I also created:

The play button

In order to create the play button, we are going to use the Button class created in the first part of this tutorial series. Here’s the code for the button in MainMenuWorld.as:

		[Embed(source = '../img/PlayGameButton.png')]
		private const PLAYBUTTON:Class;

		private var _playButton:Button;

		public function MainMenuWorld()
		{
			addGraphic(new Image(TITLE));

			_playButton = new Button(playTheGame, null, 48, 395);

			_playButton.setSpritemap(PLAYBUTTON, 312, 22);

			add(_playButton);
		}

		private function playTheGame():void
		{
			FP.world = new GameWorld();

			destroy();
		}

		public function destroy():void
		{
			removeAll();

			_playButton = null;
		}

Don’t forget to change the Main class as well!

		override public function init():void
		{
			FP.world = new MainMenuWorld();

			FP.console.enable();
		}

Hit compile and… Yes! Our shiny main menu world works! Now to the game over world!


Step 12: The Game Over World

The game over world is going to be very simple. I have created two images: one for when the player dies and one for when the player wins the game. There will be a Quit button that will return the player to the main menu. It’s basically the same thing as the main menu world. Here are the two images and the button:

Game over image when player loses
Game over image when player wins
The quit button

I will leave the coding to you. The only thing that will change in this class is that it will need an argument passed to the constructor, telling whether or not the player destroyed the enemies. Here’s the code for the constructor:

		public function GameOverWorld(hasLost:Boolean)
		{
			if (hasLost)
			{
				addGraphic(new Image(BACKGROUNDLOST));
			}
			else
			{
				addGraphic(new Image(BACKGROUNDWON));
			}

			_quitButton = new Button(quitToMain, null, 166, 395);

			_quitButton.setSpritemap(QUITBUTTON, 69, 19);

			add(_quitButton);
		}

Step 13: The Boss – Movement

Finally, the moment everyone was waiting for. Every shoot-’em-up needs a boss, and this is ours!

The boss! Kill him!

What we need now is code it. First, the movements. And then, the bullets. This step is for the movements.

As you may have guessed, our boss won’t go directly down the screen. Instead, it will move randomly around the top of the screen, to give the player a bit of difficulty defeating it. What we will need to do is a movement very similar to the player’s. The only difference is that it will follow a point chosen randomly in the top of the screen, and not the mouse. Here’s the full code for the Boss class!

package
{
	import flash.geom.Point;
	import net.flashpunk.Entity;
	import net.flashpunk.graphics.Image;
	import net.flashpunk.masks.Pixelmask;

	public class Boss extends Entity
	{
		[Embed(source = '../img/BossImage.png')]
		private const IMAGE:Class;

		private var _currentDistanceX:Number;
		private var _currentDistanceY:Number;

		private var _randomPoint:Point;

		private const SPEED:int = 3;

		public var speedMultiplier:Number = 1;

		public function Boss()
		{
			graphic = new Image(IMAGE);

			graphic.x = -38;
			graphic.y = -35;

			mask = new Pixelmask(IMAGE, -38, -35);

			type = "BossEnemy";

			getRandomPoint();
		}

		private function getRandomPoint():void
		{
			_randomPoint = new Point();

			_randomPoint.x = Math.random() * 400;
			_randomPoint.y = 38 + (Math.random() * 100);
		}

		override public function update():void
		{
			calculateDistances();

			if ((_currentDistanceX * _currentDistanceX) + (_currentDistanceY * _currentDistanceY) < SPEED * SPEED * speedMultiplier * speedMultiplier)
			{
				x = _randomPoint.x;
				y = _randomPoint.y;

				getRandomPoint();
			}
			else
			{
				x += Math.cos(Math.atan2(_currentDistanceY, _currentDistanceX)) * SPEED * speedMultiplier;
				y += Math.sin(Math.atan2(_currentDistanceY, _currentDistanceX)) * SPEED * speedMultiplier;
			}
		}

		private function calculateDistances():void
		{
			_currentDistanceX = _randomPoint.x - x;
			_currentDistanceY = _randomPoint.y - y;
		}

	}

}

We are basically using the same movement code from PlayerShip. Notice that we have kept the speed multipliers, because there will be a really fun thing in the end!

We need now to come up with a way to test this movement. Running the game and getting 50 kills is too much time to wait until we can see the boss (and end up realizing there’s a bug and we will need to do it all again and again!). Let’s just add the boss on the screen when the game begins (yes, with the other enemies going down the screen!) and check the movement! In GameWorld.as:

		private var _boss:Boss;

		public function GameWorld()
		{
			_playerShip = new PlayerShip();

			add(_playerShip);

			_enemyList = new Vector.<Enemy>();

			_score = new GameScore();

			_score.x = 300;
			_score.y = 470;

			add(_score);

			_enemySpawnTimer = 0;

			_boss = new Boss();

			add(_boss);
		}

Hit compile and test the game! Our boss is moving nicely, isn’t it? It’s going to be hard to kill it!


Step 14: The Boss – Shooting

Time for the really evil boss bullets! Here is their image:

Boss bullet

But there is something really bothering me: they will have exactly the same behavior as the player bullet, but instead they will just follow the same enemy downward path, and will have a different FlashPunk type, but I don’t want to copy and paste the same code in their class. What do you think about using some Object-Oriented Design and make an inheritance? Take all the code (yes, all the code) of PlayerBullet and copy it to a new class called Bullet. Remove the code related to the bullet’s image, and this is what you get:

package
{
	import flash.geom.Point;
	import net.flashpunk.Entity;

	public class Bullet extends Entity
	{
		private var _pathToFollow:Vector.<Point>;

		private var _xPos:Number;
		private var _yPos:Number;

		public function Bullet(pathToFollow:Vector.<Point>, xPos:Number, yPos:Number)
		{
			_pathToFollow = pathToFollow;

			_xPos = xPos;
			_yPos = yPos;
		}

		override public function update():void
		{
			x = _xPos + _pathToFollow[0].x;
			y = _yPos + _pathToFollow[0].y;

			_pathToFollow.shift();

			if (_pathToFollow.length == 0)
			{
				world.remove(this);

				destroy();
			}
		}

		public function destroy():void
		{
			_pathToFollow = null;

			graphic = null;
		}

	}

}

That’s the basic behavior of the bullet. Now, what do we do with the PlayerBullet class? Put only the things related to the bullet image in there, and remove the rest. And also make it inherit from Bullet:

package
{
	import flash.geom.Point;
	import net.flashpunk.graphics.Image;
	import net.flashpunk.masks.Pixelmask;

	public class PlayerBullet extends Bullet
	{
		[Embed(source = '../img/BulletImage.png')]
		private const IMAGE:Class;

		public function PlayerBullet(pathToFollow:Vector.<Point>, xPos:Number, yPos:Number)
		{
			super(pathToFollow, xPos, yPos);

			graphic = new Image(IMAGE);

			graphic.x = graphic.y = -3.5;

			mask = new Pixelmask(IMAGE, -3.5, -3.5);

			type = "PlayerBullet";
		}

	}

}

Do you mind making the same thing for the BossBullet class too? The only difference is that it will have a type of “BossBullet”. I’ll leave the code to you. Check the tutorial source if you need help!

We could have done the same for the boss and the enemies, but we would need to change more things, because the movement of the enemies isn’t the same as the movement of the boss. It’s better to leave it that way. And now, for the boss shooting. We will use the same timer strategy that we used for the enemy spawning. Here’s the code:

		private var _shootingInterval:int = 75;
		private var _shootingTimer:int = 0;

		override public function update():void
		{
			calculateDistances();

			if ((_currentDistanceX * _currentDistanceX) + (_currentDistanceY * _currentDistanceY) < SPEED * SPEED * speedMultiplier * speedMultiplier)
			{
				x = _randomPoint.x;
				y = _randomPoint.y;

				getRandomPoint();
			}
			else
			{
				x += Math.cos(Math.atan2(_currentDistanceY, _currentDistanceX)) * SPEED * speedMultiplier;
				y += Math.sin(Math.atan2(_currentDistanceY, _currentDistanceX)) * SPEED * speedMultiplier;
			}

			_shootingTimer--;

			if (_shootingTimer <= 0)
			{
				_shootingTimer = _shootingInterval;

				world.add(new BossBullet(GameWorld(world).generateBossBulletPath(1.5), x - 10, y));
				world.add(new BossBullet(GameWorld(world).generateBossBulletPath(1.5), x + 10, y));
				world.add(new BossBullet(GameWorld(world).generateBossBulletPath(1.5), x, y + 5));
			}
		}

Compile and run the code and now you have a boss shooting bullets and flying around! Time to make the last battle happen in the next step :)


Step 15: Final Touches

You may have noticed that the boss’s bullets don’t hit the player ship, and the player’s bullets don’t hit the boss. That’s because we haven’t coded them to hit their enemies. That’s what we are going to do now. We will also make the boss only appear when the score reaches 50, and check for when the player loses the game.

The first task: to make the boss only appear when the score reaches 50. We will do that by checking for the score in GameWorld.as, just like we did with the enemy and player upgrades.

		private var _bossAppeared:Boolean = false;

		public function GameWorld()
		{
			_playerShip = new PlayerShip();

			add(_playerShip);

			_enemyList = new Vector.<Enemy>();

			_score = new GameScore();

			_score.x = 300;
			_score.y = 470;

			add(_score);

			_enemySpawnTimer = 0;

			_boss = new Boss();

			// Not adding the boss in the game this time
		}

		override public function update():void
		{
			super.update();

			_enemySpawnTimer--;

			if (_enemySpawnTimer <= 0 && !_bossAppeared)
			{
				_enemySpawnTimer = _enemySpawnInterval;

				_enemyList.push(new Enemy(uint(Math.random() * 30), generateEnemyPath(2), this));

				add(_enemyList[_enemyList.length - 1]);
			}

			_bulletList = new Vector.<PlayerBullet>();

			getType("PlayerBullet", _bulletList);

			for each (var bullet:PlayerBullet in _bulletList)
			{
				for each (var enemy:Enemy in _enemyList)
				{
					if (bullet.collideWith(enemy, bullet.x, bullet.y))
					{
						enemy.takeDamage();

						remove(bullet);

						bullet.destroy();
					}
				}
			}

			if ((_score.score % 5) == 0 && _score.score > (_speedUpgradeNumber * 5))
			{
				_playerShip.speedMultiplier += 0.1;

				_speedUpgradeNumber++;
			}

			if (_score.score >= 25)
			{
				_playerShip.hasDoubleShoot = true;
			}

			if (_score.score > _enemyUpgradeNumber)
			{
				Enemy.damageMultiplier -= 0.015;
				Enemy.healthMultiplier += 0.02;

				_enemySpawnInterval -= 3;

				_enemyUpgradeNumber++;
			}

			if (_score.score == 50 && !_bossAppeared)
			{
				add(_boss);

				_bossAppeared = true;
			}
		}

First task done. Notice that we also changed the block that spawned new enemies. That way, when the boss appears, no more enemies will spawn.

Second task: make boss bullets hit the player and player bullets hit the boss. This is also done in GameWorld.as. Take a look at the code:

		private var _bulletList:Vector.<Bullet>;

		override public function update():void
		{
			super.update();

			_enemySpawnTimer--;

			if (_enemySpawnTimer <= 0 && !_bossAppeared)
			{
				_enemySpawnTimer = _enemySpawnInterval;

				_enemyList.push(new Enemy(uint(Math.random() * 30), generateEnemyPath(2), this));

				add(_enemyList[_enemyList.length - 1]);
			}

			_bulletList = new Vector.<Bullet>();

			getType("PlayerBullet", _bulletList);

			for each (var bullet:PlayerBullet in _bulletList)
			{
				for each (var enemy:Enemy in _enemyList)
				{
					if (bullet.collideWith(enemy, bullet.x, bullet.y))
					{
						enemy.takeDamage();

						remove(bullet);

						bullet.destroy();
					}
				}

				if (_bossAppeared)
				{
					if (bullet.collideWith(_boss, bullet.x, bullet.y))
					{
						_boss.takeDamage();

						if (!_boss)
						{
							endTheGame();

							return;
						}

						remove(bullet);

						bullet.destroy();
					}
				}
			}

			_bulletList = new Vector.<Bullet>();

			getType("BossBullet", _bulletList);

			for each (var bossBullet:BossBullet in _bulletList)
			{
				if (bossBullet.collideWith(_playerShip, bossBullet.x, bossBullet.y))
				{
					endTheGame();

					return;
				}
			} 

			if ((_score.score % 5) == 0 && _score.score > (_speedUpgradeNumber * 5))
			{
				_playerShip.speedMultiplier += 0.1;

				_speedUpgradeNumber++;
			}

			if (_score.score >= 25)
			{
				_playerShip.hasDoubleShoot = true;
			}

			if (_score.score > _enemyUpgradeNumber)
			{
				Enemy.damageMultiplier -= 0.015;
				Enemy.healthMultiplier += 0.02;

				_enemySpawnInterval -= 3;

				_enemyUpgradeNumber++;
			}

			if (_score.score == 50 && !_bossAppeared)
			{
				add(_boss);

				_bossAppeared = true;
			}
		}

In the first part of the code, we check for a collision between the player’s bullets and the boss. If there is a collision, we call the takeDamage() function from the boss, which is below. After checking the player’s bullets, we check for the boss’s bullets, and if we find a collision between any of them and the player, we end the game. This function is also below.

Now, for the takeDamage() function of the boss. We want the boss to have a lot of health, and we will make it fly faster after each hit. In Boss.as:

		private var _health:int = 1000;

		public function takeDamage():void
		{
			_health -= 50;

			speedMultiplier += 0.05;

			if (_health <= 0)
			{
				world.remove(this);

				destroy();
			}
		}

		public function destroy():void
		{
			graphic = null;

			mask = null;

			_randomPoint = null;
		}

Our boss battle is complete! It will die after 20 hits from the player, getting faster after each hit.

Now, the only thing remaining is to end the game and show the screen when the boss is killed, and also make the player lose before the boss battle if an enemy goes down the screen. For the end of the game, we need to check when the boss is killed and create the endTheGame() function in GameWorld.as. This function will basically remove every bullet from the screen, remove the player and boss and then add the game over screen. In GameWorld.as:

		override public function remove(e:Entity):Entity
		{
			if (e is Enemy)
			{
				_enemyList.splice(_enemyList.indexOf(e), 1);
			}

			if (e is Boss)
			{
				_boss = null;
			}

			return super.remove(e);
		}

		public function endTheGame():void
		{
			removeAll();

			while (_bulletList.length > 0)
			{
				_bulletList[0].destroy();

				_bulletList.shift();
			}

			while (_enemyList.length > 0)
			{
				_enemyList[0].destroy();

				_enemyList.shift();
			}

			_bulletList = null;
			_enemyList = null;
			_playerShip = null;
			_score = null;

			if (_boss)
			{
				FP.world = new GameOverWorld(true);
			}
			else
			{
				FP.world = new GameOverWorld(false);
			}

			_boss = null;
		}

And that’s it! The endTheGame() function is basically the same as a destroy() function. It just cleans every reference in the game world.

The last part: making the player lose the game if an enemy has reached the end of the screen. For this one we’re going to remember that an enemy only reaches the bottom of the screen if it still has health. So, in the remove() function of GameWorld.as:

		private var _gameEnded:Boolean = false;

		override public function remove(e:Entity):Entity
		{
			if (e is Enemy)
			{
				if (Enemy(e).health > 0)
				{
					endTheGame();

					return e;
				}

				_enemyList.splice(_enemyList.indexOf(e), 1);
			}

			if (e is Boss)
			{
				_boss = null;
			}

			return super.remove(e);
		}

		override public function update():void
		{
			super.update();

			if (_gameEnded)
			{
				return;
			}

			_enemySpawnTimer--;

			if (_enemySpawnTimer <= 0 && !_bossAppeared)
			{
				_enemySpawnTimer = _enemySpawnInterval;

				_enemyList.push(new Enemy(uint(Math.random() * 30), generateEnemyPath(2), this));

				add(_enemyList[_enemyList.length - 1]);
			}

			_bulletList = new Vector.<Bullet>();

			getType("PlayerBullet", _bulletList);

			for each (var bullet:PlayerBullet in _bulletList)
			{
				for each (var enemy:Enemy in _enemyList)
				{
					if (bullet.collideWith(enemy, bullet.x, bullet.y))
					{
						enemy.takeDamage();

						remove(bullet);

						bullet.destroy();
					}
				}

				if (_bossAppeared)
				{
					if (bullet.collideWith(_boss, bullet.x, bullet.y))
					{
						_boss.takeDamage();

						if (!_boss)
						{
							endTheGame();

							return;
						}

						remove(bullet);

						bullet.destroy();
					}
				}
			}

			_bulletList = new Vector.<Bullet>();

			getType("BossBullet", _bulletList);

			for each (var bossBullet:BossBullet in _bulletList)
			{
				if (bossBullet.collideWith(_playerShip, bossBullet.x, bossBullet.y))
				{
					endTheGame();

					return;
				}
			}

			if ((_score.score % 5) == 0 && _score.score > (_speedUpgradeNumber * 5))
			{
				_playerShip.speedMultiplier += 0.1;

				_speedUpgradeNumber++;
			}

			if (_score.score >= 25)
			{
				_playerShip.hasDoubleShoot = true;
			}

			if (_score.score > _enemyUpgradeNumber)
			{
				Enemy.damageMultiplier -= 0.015;
				Enemy.healthMultiplier += 0.02;

				_enemySpawnInterval -= 3;

				_enemyUpgradeNumber++;
			}

			if (_score.score == 50 && !_bossAppeared)
			{
				add(_boss);

				_bossAppeared = true;
			}
		}

		public function endTheGame():void
		{
			removeAll();

			while (_bulletList.length > 0)
			{
				_bulletList[0].destroy();

				_bulletList.shift();
			}

			while (_enemyList.length > 0)
			{
				_enemyList[0].destroy();

				_enemyList.shift();
			}

			_bulletList = null;
			_enemyList = null;
			_playerShip = null;
			_score = null;

			if (_boss)
			{
				FP.world = new GameOverWorld(true);
			}
			else
			{
				FP.world = new GameOverWorld(false);
			}

			_boss = null;

			_gameEnded = true;
		}

This code will only end the game when an enemy reaches the end (is destroyed) with a health above 0. If the enemy dies, this function is also called, but then the enemy health will be below (or equal to) 0, skipping the code to end the game. We have also created the _gameEnded boolean because when an enemy reaches the end of the screen and gets removed, the world is still updating its entities. Only when it finished updating them (after the super.update() call in the class) is that we can end the game.

After all these lines and lines of code changed, remove the FlashPunk console, hit compile and test the game. It’s finally done, your very first game entirely done in FlashPunk! Congratulations!


Step 16: Conclusion

Congratulations, you have created your first FlashPunk game! You have used pretty much all of FlashPunk’s features for a very basic game, which means you are ready to create more FlashPunk games and spread the word! What do you think of improving this game? It could have different enemies, enemies that also shoot bullets, levels, more bosses, more upgrades and a lot of other things! Are you up to the challenge?



View full post on Activetuts+

Nov 9, 2011 Posted on Nov 9, 2011 in Hints and Tips | 10 comments

TimelineLite Ultimate Starter Guide: Introduction

This entry is part 1 of 1 in the series TimelineLite Ultimate Starter Guide

TimelineLite is the ultimate tool for creating elaborate and precise sequences of scripted animation. It is an integral part of the GreenSock Tweening Platform that allows you to make the most of TweenLite and TweenMax. This series of screencasts will walk you step by step through everything you need to know to take your AS3 tweening skills to the next level.


Basic Features of TimelineLite

  • Create a sequence of TweenLite/Max tweens
  • Play and pause any sequence
  • Reverse any sequence
  • Adjust the overall speed of the sequence
  • Jump-to any part of the sequence
  • Add labels for easy navigation
  • Scrub through any animation

Along the way we will be diving into TimelineMax which extends the power of TimelinLite with even more features. Everything you learn how to do in TimelineLite will also apply to TimelineMax.

Also, although this guide was produced solely with AS3, TimelineLite and TimelineMax have the exact same features in AS2, and use identical syntax!


Meet TimelineLite

In this first introductory video I’m going to explain exactly what TimelineLite is and what it can do. I’ll walk you through some inspiring examples of TimelineLite that highlight its many features. Along the way I’ll show you a few resources that are going to help you get the most out of your TimelineLite training. Once you see how concise and flexible TimelineLite code can be, you’ll never tween without it.

Sit back and relax as I set the groundwork for all the amazing things we will be covering in this series.

Don’t like ads? Download the screencast, or subscribe to Activetuts+ screencasts via iTunes!


TimelineLite in Action


Resources Mentioned in this Video

In this series of videos I am going to be referring to the TimelineLite documentation many times. I strongly suggest you visit and bookmark the following:

  • GreenSock.com to learn more about TimelineLite and get the complete GreenSock Tweening Platform code library.
  • Official TimelineLite Documentation get ahead of the class and see the tremendous amount of properties and methods available.

To get the most out of TimelineLite its imperative that you have a basic understanding of TweenLite and TweenMax. For a quick crash course please read GreenSock’s Getting Started Tweening article.

Come back tomorrow for the next video in the series, where we’ll be looking at basic methods and properties of TimelineLite.



View full post on Activetuts+

Page 1 of 712345...»Last »
search search search search search
Find an Article
Categories
  • Flash Video Training
  • Hints and Tips
  • Recommended
Please Support Our Sponsors
Recent Posts
  • The Math and ActionScript of Curves: Drawing Quadratic and Cubic Curves
  • Weekend Lecture: Understanding Games, a Flash Game About Game Design
  • Weekend Lecture: Understanding Games, a Flash Game About Game Design
  • Workshop Coding Challenge: Fix This Breakout Game
  • Enable the Latest AIR SDK in Flash Professional CS5.5+
Tag Cloud
2011 ActionScript Active Activetuts+ Adobe animation Basic Basix Best Build Button Character 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+ Tween 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 2012
M T W T F S S
« Apr    
 123456
78910111213
14151617181920
21222324252627
28293031  
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

  • 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