Students
Students get a Tuts+ subscription for just $45! Hurry limited offer.
Advertisement

Creating "Flux": A Simple Flash Game With a Gravity Mechanic

by

In this tutorial, I'll explain the major steps and workflow for creating a simple space survival game, based on the gravity mechanic explained in a previous tutorial. This game is written in AS3 using FlashDevelop.


Play the Game

Use the left and right arrow keys to manoeuvre your ship, the up and down arrow keys to increase or reduce the size of the magnetic field it produces, and the space bar to reverse the polarity. Collect the white crystals to increase your fuel supply - but avoid the red ones, because they use it up. Don't hit a rock, or it's game over!

In this tutorial, we won't actually create the full game displayed above; we'll just get started on it, by making a very simple version with primitive graphics and just one type of object. However, by the end, you should have learned enough to be able to add the other features yourself!

The game itself is very simple in its current state - take a look at this critique for tips on how you can take it from a simple demo to a full game!


Let's Get Started!

Set up a new AS3 project in FlashDevelop, and set its dimensions to 550x600px.


Step 1: Identifying the Game Objects

There are six objects in particle that you can identify from playing the game above:

  • Energy supply - represented by an white oval shape object
  • Asteroid - represented by a rock-like object
  • Energy consumer - represented by a red star bounded with green light.
  • Stars - the background
  • Range indicator - represented by a white circle
  • Ship - player object

Of course you can add in any other object to make the game more interactive or add a new feature. For this tutorial we'll just make


Step 2: The Energy Class

From the objects we identified, four of them actually work in exactly the same way: by falling from top to bottom.

They are:

  • Stars
  • Energy supply
  • Energy consumer
  • Asteroid

In this tutorial, we're only going to make the "energy supply" objects, out of the four above. So let’s begin by creating these objects and making them fall down, with a random spawning position and speed.

Start by creating an Energy class:


Step 3: The GameScreen Class

This class will eventually control most of the aspects of our game, including the player movement and the game loop.

Create the class:

That's all we need for now.


Step 4: Update The Main Class

We'll now create an instance of GameScreen within Main:

Why bother? Well, this way, it'll be easier to add extra screens later if we want to (like a preloader, a title screen, a game over screen...).


Step 5: Introducing a Manager Class

To avoid the GameScreen class becoming too much of a mess, we'll use separate classes to manage each object.

Each manager class will contain all the functions that relate to, and interact with, a particular object. Here's the EnergyManager class:

Note that we require a reference to the GameScreen to be passed to the constructor, and we store this reference in a private variable. We also set up a Vector to store references to all the energy objects.

So far the class contain no other functions; we will add them in later.


Step 6: Creating Energy

Add the below function for creating energy, this is just a function; we will call the function later from GameScreen Class:

We create a new energy supply with a speed of 4, add it to the display list (via the GameScreen), add it to the Vector of all energy objects that we just created, and set its position to a random point within certain bounds.

The Calculation.generateRandomValue(#, #) is a static function we haven't written yet, so let's do that now. Create a new class called Calculation and add this function:

This function will generate a random number between the two values passed to it. For more information on how it works, see this Quick Tip. Since this is a static function, we don't need to create an instance of Calculation in order to call it.

Now, what's that addEnergyToScreen() function? We haven't defined that yet, so let's do it now. Add this to GameScreen:

It just adds the passed instance of energy to the display list. Let's also make a corresponding function to remove a given energy object from the screen:


Step 7: Spawning Energy

Let's set a timer that defines the interval for each spawning. This code goes in GameScreen's constructor function:

So, every three seconds, the timer will call spawnEnergy(). Let's write that function now:


Step 8: Creating Player

Let's use another, bigger circle to represent the player. Feel free to import an image to use instead:

Add this code to GameScreen to add the player to the screen:

So far we should have a few energy supplies falling few seconds, and the player appearing in the middle of the screen:

playerandenergy.

Step 9: Moving the Player

There are basically two ways to apply movement:

  1. Using Boolean (true/false) values - true = moving, false = not moving. When the right arrow key is pressed, the value for "moving right" will change to true. In each frame update, "moving right" is true, we increase the object's x-value.
  2. Using direct update each frame - when the right arrow key is pressed, an object is told to move right immediately, by increasing its x-value.

The second method does not lead to smooth movement when the key is continuously pressed, but the first method does - so we shall use the first method.

There are three simple steps to doing this:

  1. Create two Boolean variables, one for moving right and one for moving left.
  2. Toggle the Boolean when keys are pressed or released:
  3. Based on these Booleans, actually move the player every frame:

    Don't forget to first create a function listen from the enter frame event, "updating" :

    Keep the player within the bounds of the screen:

Here's how all that looks, in place:


Step 10: Move the Energy Supplies

At the moment, the energy supplies are spawning but not moving. We'll use the GameScreen.update() function to make them move, since it runs every frame.

Add this code to GameScreen.update():

Now of course we need to make the EnergyManager.moveAll() function, so add this to EnergyManager.as:


Step 10: Collision Detection

We will need to check for collisions between each energy object and the player. (If you develop the game further, you'll need to check this for asteroids and energy consumers, but not for stars.)

The best place to handle these checks is inside the EnergyManager, triggered every frame by the GameScreen.

One thing to consider: the collision checks will be between two circles, so hitTestObject() is not ideal. Instead, we'll be using the method explained in this tutorial.

We can write the function as below:

  • Line 32: note that we pass in a reference to the player, so that we can access its position.
  • Line 38: EnergyS is short for Energy Supply.
  • Line 40 & 41: finding the difference in x- and y-coordinates between the player and the energy supply we are currently checking.
  • Line 43: calculate the distance between the objects via Pythagoras.
  • Line 45: check for collision; 28 is the sum of the two objects' radii (player radius is 20, energy radius is 8).
  • Line 46 & 47: remove energy supply from screen and from Vector.
  • Line 51: add a maximum of one unit of energy per frame.

You could alter Line 51 to energyTransfer += 1, to allow the player to absorb more than one energy object at once. It's up to you - try it out and see how it affects the game.


Step 11: Call Collision Detection Routine

We need to check for collisions every frame, so we should call the function we just wrote from GameScreen.update().

First, we need to create an integer variable to store the energy transfer value from the collision detection function. We'll use this value for increasing the ship's energy and adding to the player's score.


Step 12: Newton's Law of Gravitation

Before we go into creating the game mechanic for the ‘Push’ and ‘Pull’ function of the ship, I would like to introduce the physics concept on which the mechanic is based.

The idea is to attract the object towards the player by means of a force. Newton’s Law of Universal Gravitation gives us a great (and simple) mathematical formula we can use for this, where the force is of course the gravitational force:

G is just a number, and we can set it to whatever we like. Similarly, we can set the masses of each object in the game to any values that we like. Gravity occurs across infinite distances, but in our game, we'll have a cut-off point (denoted by the white circle in the demo from the start of the tutorial).

The two most important things to note about this formula are:

  • The strength of the force depends on the square of the distance between the two objects (so if the objects are twice as far away, the force is one-quarter as strong).
  • The direction of the force is along the direct line connecting the two objects through space.

Step 13: Revising Math Concepts

Before we start coding the game mechanics for the 'Push' and 'Pull' function, let's be clear on what we want it to do:

frameWork

Essentially, we want A (the player) to exert a certain force on B (a crystal), and move B towards A based on that force.

We should revise a few concepts:

  • Flash works in radians rather than degrees.
  • Flash's coordinate system has its y-axis reversed: going down means an increase in y.
  • We can get the angle of the line connecting A to B using Math.atan2(B.y - A.y, B.x - A.x).
  • We can use trigonometry to figure out how much we need to move B along each axis, based on this angle and the force:
    • B.x += (Force*Math.cos(angle));
    • B.y += (Force*Math.sin(angle));
  • We can use Pythagoras's theorem to figure out the distance between the two objects:

For more information, see the tutorials Gravity in Action and Trigonometry for Flash Game Developers.


Step 14: Implementing Push and Pull

Based on the previous explanation, we can come up with an outline for our code that attracts each crystal to the ship:

  1. Find the difference in x and y between the ship and a given crystal.
  2. Find the angle between them, in radians.
  3. Find the distance between them, using Pythagoras.
  4. Check whether object is within the ship's gravitational field.
  5. If so, calculate the gravitational force, and...
  6. ...apply the force, changing the x and y values of the crystal.

Sample Code:

  • Line 53: get a reference to the player.
  • Line 55: we loop through each energy object.
  • Line 61: find the angle between the ship and the energy.
  • Line 63: find the distance between them, too.
  • Line 65: check whether the energy is within the ship's force field.
  • Line 67: use the formula:
    • 4 = G, the "gravitational constant" I've chosen.
    • 50 = m1, the mass of the ship player.
    • 10 = m2, the mass of the energy object.
  • Line 69: apply movement.

Here's a timelapse showing how this looks:

Note that the energy moves faster the closer it gets to the ship, thanks to the r-squared term.

We can implement the pushing function just by making the force negative:

Here the object moves more slowly as it gets further away from the player, since the force gets weaker.


Step 15: Apply the Mechanic

Of course that you will need this function to be run each frame by GameScreen - but before that, we will need to use a Boolean function to toggle between the two functions:

We are going to use true for 'Push' and false for 'Pull'.

Inside KeyDownHandler():

Afterwards, you will have to check the Boolean each frame. Add this to update():


Step 16: Modification

You might find that the movement doesn't look so nice. This could be because the force is not quite ideal, or because of the r-squared term.

I'd like to alter the formula like so:

As you can see, I've reduced the value of "G" to 0.8, and changed the force to depend simply on the distance between the objects, rather than the distance squared.

Try it out and see if you enjoy the change. You can always alter it however you like.


Step 17: The Text Class

We will need to show some text on the screen, for showing the score and the ship's remaining power.

For this purpose, we'll build a new class, Text:

It's very simple; it's basically a MovieClip with a text field inside.


Step 18: Adding Power for Player

To give the game some challenge, we'll make the ship's power get used up slowly, so that the player has to collect energy objects in order to recharge.

To make the ship's power appear on the ship itself, we can simply add an instance of Text to the ship object's display list.

Declare these variables within the Ship class:

We'll need to keep the amount of power (both stored and displayed) updated every frame, so add this new function to Player:

First, in the constructor:

And then...

The power will decrease every frame by 1/24th of a unit, meaning it'll decrease by one full unit every second.

We need to make this run every frame, so add this line to GameScreen.update():


Step 19: Make Energy Increase Power

When the ship collides with an energy object, we want it to increase its power.

In GameScreen.update(), add the highlighted line:

Remember you can alter how much power is returned in the EnergyManager.checkCollision() function.


Step 20: Setting Up the Score

Again, we will need the text class. This time, we'll display “Score” and then the value.

Here, we will need three more variables:

  • The "Score" text.
  • The score value text.
  • A variable to store the actual score.

Declare these in GameScreen class:

In the constructor, add this code:

Now, in the update() function, add this:

That's it - we've created a basic version of the above game!

Take a look (you may need to reload the page):


Extra Features and Polishing

Space Background

Maybe you would also like a background with an embedded image and stars. Add this to your Main class:

Now create the Star class:

In the Main() constructor, add this to create the stars:

Here's the actual createStars() function:

With random alpha, size, position, and speed, a pseudo-3D background can be generated.

Range indicator

A range indicator circle can be made by simply creating another circle and adding it to the ship's display list, just like how you added the power indicator text. Make sure the circle is centred on the ship, and has a radius equal to the ship's push/pull range.

Add transparancy (alpha value) to the circle with the below code:

Try adding extra controls that make the range increase or decrease when the up and down arrow keys are pressed.


Conclusion

I hope you enjoyed this tutorial! Please do leave your comments.

Next: Read this critique for a guide to taking Flux from a simple demo to a full game!

Advertisement