Do you like my tutorials?

Then consider supporting me on Ko-fi

Talking about Sproing game, Flash and Users contributions.

This tutorial is guest blogged by TechnoMono and I am happy I got the permission to post it on my blog. TechnoMono hosts more Flash and Gimp tutorials, so don’t forget to take a look to this blog.

We can define Sproing as a “throw a ball in some way” game, and the tutorial is very well explained. Let’s see it:

—————————

Sproing is a very simple and intuitive Flash game. It’s also rather addictive. The object of the game is to destroy green orbs by hitting them hard enough with a blue orb which is connected to the mouse via a spring force. You’ll have to play the game to see what I mean. In this tutorial I’m going to show you how to make the blue orb spring to the mouse. Obviously, I wont show you how to make the complete game. The demo below shows exactly what we’ll be making:

We’ll be making the demo with ActionScript 3.0, which means you’ll need Flash CS3, Flex Builder or the free Flex SDK. However, I’ll explain how to use the code specifically with Flash CS3. I assume you have at least a basic working knowledge of ActionScript 3.0. If you have experience with ActionScript 2.0, then you shouldn’t find it too difficult to follow through.

Before I begin explaining the code step-by-step, I’d like you to get the demo up and running yourself. The first step is to create a new Flash document, with which we’ll associate the program’s main class. Open up Flash and create a new document (File > New > ActionScript 3.0). Save this .fla file as ‘SproingDemo.fla’ (File > Save As). Bring up the Properties Panel (CTRL+F3), and under Document class, enter ‘SproingDemo’ (the name of the program’s main class). If a warning dialog appears (as shown in the image below), just click OK.

Sproing

Set the frame rate to 30fps, and leave the other document properties at their defaults.

Sproing

That’s all we need to do with the .fla file. Now we will create the main class. This is as simple as saving the class definition in a file called ‘SproingDemo.as’ (note the .as extension). Here’s the main class in it’s entirety:

package {
  import flash.display.Shape;
  import flash.display.Sprite;
  import flash.events.Event;
  import flash.ui.Mouse;
 
  public class SproingDemo extends Sprite {
    private var orb1:Shape;
    private var orb2:Orb;
    private var lineCanvas:Shape;
    private var spring:Number = .1;
    private var damping:Number = .9;
 
    // Constructor
    public function SproingDemo() {
      init();
    }
 
    private function init():void {
      // Set up the small orb
      orb1 = new Shape();
      orb1.graphics.lineStyle(1, 0x6633CC);
      orb1.graphics.beginFill(0x6699CC);
      orb1.graphics.drawCircle(0, 0, 10);      
 
      // Set up the large orb
      orb2 = new Orb(25, 0x00CCFF, 1, 0x0066FF);
 
      // Set up the drawing canvas for the line drawn between the orbs
      lineCanvas = new Shape();      
 
      // Add lineCanvas, orb1 and arb2 to this object's display hierarchy
      addChild(orb2);
      addChild(orb1);
      addChild(lineCanvas);      
 
      // Register for Event.ENTER_FRAME events
      addEventListener(Event.ENTER_FRAME, enterFrameListener);      
 
      // Hide the mouse pointer
      Mouse.hide();
    }
 
    private function enterFrameListener(e:Event):void {
      // Set orb1's position to current mouse position
      orb1.x = mouseX;
      orb1.y = mouseY;    
 
      // Spring orb2 to orb1
      orb2.vx += (orb1.x - orb2.x) * spring;
      orb2.vy += (orb1.y - orb2.y) * spring;
      orb2.vx *= damping;
      orb2.vy *= damping;
      orb2.x += orb2.vx;
      orb2.y += orb2.vy;      
 
      // Draw a line between the two orbs
      drawLine();
    }    
 
    private function drawLine():void {
      with (lineCanvas) {
        graphics.clear();
      	graphics.moveTo(orb1.x, orb1.y);
      	graphics.lineStyle(1, 0x4C59D8);
        graphics.lineTo(orb2.x, orb2.y);
      }
    }
  }
}

Note: The program’s main class definition must be placed in a text file named after the main class, with a .as extension.

An additional class is used to represent the orb which is sprung to the mouse. Save this class in a file called ‘Orb.as’. Here it is:

package {
  import flash.display.Shape;
 
  public class Orb extends Shape {
    internal var radius:int;
    internal var vx:Number = 0;
    internal var vy:Number = 0;
 
    // Constructor
    public function Orb(radius:int = 20, fillColor:int = 0x00FF00, lineThickness:int = 1, lineColor:int = 0) {
      this.radius = radius;
      graphics.lineStyle(lineThickness, lineColor);
      graphics.beginFill(fillColor);
      graphics.drawCircle(0, 0, radius);
    }
  }
}

You should now have three files: SproingDemo.fla, SproingDemo.as and Orb.as (all placed in the same directory). Open SproingDemo.fla and press CTRL+ENTER to see the demo in action (or Control > Test Movie). Assuming all went well, let’s begin exploring the code (if you encountered problems, make sure you followed the above instructions exactly).

The main class

We’ll be using several built-in classes in this program, so we must import them using the import directive:

import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.ui.Mouse;

In the demo, you’ll notice there are two orbs. The small orb is used to represent the position of the mouse. This orb is created as an instance of the Shape class, which is perfect for such a simple graphical object. I’ve given the large orb a class of it’s own: Orb, a subclass of Shape. Since the large orb is sprung to the mouse, we need to keep track of it’s velocity (it’s speed along the x and y axes). So to the Orb class, I have added two instance variables, vx and vy. Both of which are of type Number (there’ll need to hold fractional values).

The main class extends the Sprite class, so we need to import that. For animation, we’ll use the Event.ENTER_FRAME event, which is why we need the Event class. Finally, the Mouse class is used to hide the mouse pointer.

The main class declares five instance variables. orb1 and orb2 hold references to the small and large orb, respectively. lineCanvas holds a reference to a Shape object in which we’ll draw a line between the two orbs. spring is used to determine the strength of the spring force between the two orbs. The greater this value, the greater the force. To force the large orb to settle down, damping is applied to its velocity (you can think of damping as a kind of frictional force, which works against the spring force).

private var orb1:Shape;
private var orb2:Orb;
private var lineCanvas:Shape;
private var spring:Number = .1;
private var damping:Number = .9;

Following the five instance variables is the main class’s constructor, which simply invokes init().

// Constructor
public function SproingDemo() {
  init();
}

init() takes care of initializing the program. It creates the small orb by assigning a Shape object to orb1, and then invokes drawing methods on the Graphics instance of the Shape object. The first two methods, lineStyle() and beginFill(), set the color of the orb’s stroke and fill, as well as the thickness of the stroke. Feel free to change the arguments passed to these methods to change the appearance of the small orb. The large orb is then created, by assigning an instance of the Orb class to orb2, passing in arguments to the set the orb’s appearance (I’ll explain the Orb class shortly).

// Set up the small orb
orb1 = new Shape();
orb1.graphics.lineStyle(1, 0x6633CC);
orb1.graphics.beginFill(0x6699CC);
orb1.graphics.drawCircle(0, 0, 10);
 
// Set up the large orb
orb2 = new Orb(25, 0x00CCFF, 1, 0x0066FF);

The two orbs are connected visually by a line, which is drawn to lineCanvas. So a Shape object is assigned to lineCanvas.

// Set up the drawing canvas for the line drawn between the orbs
lineCanvas = new Shape();

Now that the three graphical elements of the program have been created, they are added to the display list so that they can be seen on screen.

// Add lineCanvas, orb1 and arb2 to this object's display hierarchy
addChild(orb2);
addChild(orb1);
addChild(lineCanvas);

The large orb needs to be below both the small orb and the connecting line, so it’s added first, followed by the small orb and then the connecting line (which appears on top).

enterFrameListener() registers with the main class instance to receive Event.ENTER_FRAME notifications, so that it is executed repeatedly, each time the screen is about to be updated. It is in this listener that we place the animation code.

// Register for Event.ENTER_FRAME events
addEventListener(Event.ENTER_FRAME, enterFrameListener);

Finally, the mouse pointer is hidden by invoking the hide() method of the Mouse class.

// Hide the mouse pointer
Mouse.hide();

The enterFrameListener() method is the heart of the program. It is executed on every frame. First it sets the small orb’s position equal to the mouse’s position, as retrieved from the DisplayObject class’s instance variables, mouseX and mouseY. This causes the small orb to follow the mouse. Next, the large orb is moved a little closer to the small orb, as determined by a simple spring formula. The difference between the orbs positions along both axes is multiplied by spring. The resulting value is the amount by which the large orb should be accelerated towards the small orb on this frame. As the distance between the two orbs decreases, so does the acceleration. However, the large orb is moving at greatest speed when it has reached the small orb, which it passes, causing the spring force to pull it back towards the small orb. The acceleration along the x and y axes is applied by adding to vx and vy, respectively. Damping is achieved by applying damping to vx and vy, which reduces the orbs velocity on every frame. The large orb’s position is finally updated by adding vx and vy to the orb’s x and y properties, respectively.

private function enterFrameListener(e:Event):void {
  // Set orb1's position to current mouse position
  orb1.x = mouseX;
  orb1.y = mouseY;
 
  // Spring orb2 to orb1
  orb2.vx += (orb1.x - orb2.x) * spring;
  orb2.vy += (orb1.y - orb2.y) * spring;
  orb2.vx *= damping;
  orb2.vy *= damping;
  orb2.x += orb2.vx;
  orb2.y += orb2.vy;
 
  // Draw a line between the two orbs
  drawLine();
}

Last but not least, drawLine() is invoked. It draws a line between the two orbs.

private function drawLine():void {
  with (lineCanvas) {
    graphics.clear();
    graphics.moveTo(orb1.x, orb1.y);
    graphics.lineStyle(1, 0x4C59D8);
    graphics.lineTo(orb2.x, orb2.y);
  }
}

The Orb class

This class is very simple. It consists of just three instance variables. We’ve met both vx and vy. radius simply holds the orbs radius. Although radius is not used in this program, it can be convenient to have access to this property, such as when performing collision detection. The constructor has four parameters, all of which are optional (since default values are supplied). However, if you supply a value for a parameter, you must supply values for all preceding parameters. These parameters are used to set the orb’s radius, fill color, stroke thickness, and stroke color. The constructor sets radius equal to the parameter with the same name. The radius variable and radius parameter are disambiguated by using the this keyword (which refers to the current object). A circle is then drawn in the center of the Orb object using drawCircle().

package {
  import flash.display.Shape;
 
  public class Orb extends Shape {
    internal var radius:int;
    internal var vx:Number = 0;
    internal var vy:Number = 0;
 
    // Constructor
    public function Orb(radius:int = 20, fillColor:int = 0x00FF00, lineThickness:int = 1, lineColor:int = 0) {
      this.radius = radius;
      graphics.lineStyle(lineThickness, lineColor);
      graphics.beginFill(fillColor);
      graphics.drawCircle(0, 0, radius);
    }
  }
}

Notice that radius, vx, and vy are defined using the internal access-control modifier: this is to make them accessible within the main class. That’s all there is to it.

I hope you’ve enjoyed working through this tutorial, and I’m sure you’ll take the program a lot further. If you have any questions, leave a comment.

—————————

That’s all. I included the source code as of the movie I made following this tutorial. Remember to visit TechnoMono because it’s a tutorial blog that you cannot miss.

Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.