Talking about Flex.
October, 23rd update: Part 2 released
With the increasing performances of Actionscript and modern computers, now we have enough power to simulate physics in a Flash movie.
All we need is… let’s say… an huge knowledge of physics, constraints, integrations and so on. With all those things to think about, we cannot focus on the main goal: produce our game/application.
Someone should develop an Actionscript physics engine… APE (Actionscript Physics Engine) is a free AS3 open source 2D physics engine for use in Flash and Flex, released under the MIT License.
I started playing with it yesterday, and results are really amazing. While I need much more time for some experiments, I want to share with you my first steps.
The documentation about this project is very poor (some kind of API without examples, one tutorial and two demos….) so this tutorial could be a bit unclear, but I am doing my best.
Moreover, it’s my first time with APE and my first time with Flex… two new tools to learn quickly, but I am a geek and I am a PROgrammer, so that’s no problem!
First, download the alpha version (yes… just an alpha…).
Now, we need Flex. Let’s say Flex 2. From its official site: “Adobe® Flexâ„¢ 2 is a cross-platform development framework for creating rich Internet applications (RIAs). Flex enables you to create expressive, high-performance applications that run identically on all major browsers and operating systems.”
If it’s your first time with Flex, you can download a complete 30 days evaluation version from this page.
When you have Flex installed on your computer the unzipped APE folder, you are ready to go.
Launch Flex and create a new ActionScript project
Call you project “ape” (you can call it as you want, but later in the code you will have to use this name, so if it’s your first time call it “ape”), don’t click on “Finish” but go to “Next >”.
Seletc “Library Path” and click on “Add SWC…”
Now in the dialog box select the ape.swc file, normally located in the bin directory of your APE package, then click OK and Finish.
You should have an actionscript window with this content:
package {
import flash.display.Sprite;
public class ape extends Sprite
{
public function ape()
{
}
}
}
The public class ape
and public function ape
are called in this way because I named the project ape
.
Now it’s time to show you what can I do in less than 40 lines
package {
import org.cove.ape.*;
import flash.events.Event;
import flash.display.Sprite;
[SWF(width='500',height='400',backgroundColor='0xFFFFFF',frameRate='30')]
public class ape extends Sprite {
public function ape() {
addEventListener(Event.ENTER_FRAME, run);
APEngine.init(1/4);
APEngine.container = this;
APEngine.addMasslessForce(new Vector(0,2));
var defaultGroup:Group = new Group();
defaultGroup.collideInternal = true;
var cp:CircleParticle = new CircleParticle(250,10,5);
defaultGroup.addParticle(cp);
var wp:WheelParticle = new WheelParticle(280,10,5,false,1,0.3,0.1,1);
defaultGroup.addParticle(wp);
var rp:RectangleParticle = new RectangleParticle(250,300,200,10,-0.52,true);
defaultGroup.addParticle(rp);
var rp2:RectangleParticle = new RectangleParticle(150,200,200,10,0.52,true);
defaultGroup.addParticle(rp2);
var rp3:RectangleParticle = new RectangleParticle(250,50,200,10,-0.52,true);
defaultGroup.addParticle(rp3);
var wa: WheelParticle = new WheelParticle(160,20,10,false,2);
defaultGroup.addParticle(wa);
var wb: WheelParticle = new WheelParticle(200,20,10,false,2)
defaultGroup.addParticle(wb);
var wc:SpringConstraint = new SpringConstraint(wa, wb, 0.5, true, 3);
defaultGroup.addConstraint(wc);
APEngine.addGroup(defaultGroup);
}
private function run(evt:Event):void {
APEngine.step();
APEngine.paint();
}
}
}
Lines 2-4: Importing necessary libraries
Line 5: Setting width, height, bgcolor and framerate of the movie we are going to create. This is the way you have to define attributes in pure actionscript projects.
Note: Width and height must be specified in pixels. You are not allowed to use percentage values such as 50%.
Line 6: Definining the ape class as an extension of the built in Sprite class.
The Sprite class is new in ActionScript 3.0 A Sprite object is similar to a movie clip, but does not have a timeline.
Line 7: Declaring the main function
Line 8: Adding an event listener. Since the on(event)
syntax is no longer supported in ActionScript 3.0, we need to use addEventListener
to trig for some events. In our case, the event is ENTER_FRAME
. So it’s basically an onEnterFrame = function(){}
coded in AS3, where the “function” is run
(the function defined at lines 32-35).
Line 9: Initializing the APE engine. The parameter 1/4 (0.25) is used to set the speed of the simulation. Typical values are 1/3 or 1/4. Lower values result in slower, but more accurate simulations, and higher ones result in faster, less accurate ones.
Line 10: Definining the default container used by the default painting methods of the particles and constraints. In other words, the area where the simulation takes place.
Line 11: Adding a “massless” force to the system. What is a “massless” force? It’s a force that acts on all particles in the same way even if they have different masses… such as gravity. Particles with larger masses are affected by gravity same as those with smaller masses. The Vector
represents the… vector of the force, splitted in fx
and fy
. fx
is the horizontal component of the force, while fy is the vertical component of the force. In our case, we have a force that does not have horizontal force, but only a vertical one (like gravity). Changing the vector values will result in different gravity types (reverse, horizontal, and so on).
Line 12: Creating a group called defaultGroup
. The Group class can contain Particles, Constraints, and Composites. Groups can be assigned to be checked for collision with other Groups or internally. This means that I can have a group of particles that can collide only with particles of another group, or a group of particles that are checked for collision one with each other. As you can see from Line 13, I want my particles inside defaultGroup
to collide, and I specify it with the collideInternal
property
Line 14: Creating a circle haped particle. The CircleParticle
has some interesting parameters:
x:Number: The initial x position of this particle.
y:Number: The initial y position of this particle.
radius:Number: The radius of this particle.
fixed:Boolean (default = false): Determines if the particle is fixed or not. Fixed particles are not affected by forces or collisions and are good to use as surfaces. Non-fixed particles move freely in response to collision and forces.
mass:Number (default = 1): The mass of the particle.
elasticity:Number (default = 0.3): The elasticity of the particle. Higher values mean more elasticity or “bounciness”.
friction:Number (default = 0): The surface friction of the particle
So in my case I have a circle particle located at (250,10) with a radius of 5 pixels, that is not fixed (it will fall, bounce, etc), with a mass equal to 1 and an elasticity equal to 0.3 and no friction.
Line 15: Adding the circle particle to the group defined at line 12
Line 16: Introducing the most interesting particle of the engine, in my opinion: the wheel particle. A wheel particle is… a particle that simulates the behavior of a wheel.
Let’s see its parameters:
x:Number: The initial x position.
y:Number: The initial y position.
radius:Number: The radius of this particle.
fixed:Boolean (default = false): Determines if the particle is fixed or not. Fixed particles are not affected by forces or collisions and are good to use as surfaces. Non-fixed particles move freely in response to collision and forces.
mass:Number (default = 1): The mass of the particle
elasticity:Number (default = 0.3): The elasticity of the particle. Higher values mean more elasticity.
friction:Number (default = 0): The surface friction of the particle.
traction:Number (default = 1): The surface traction of the particle.
So basically a wheel is a circle that can rotate and with a traction
Line 17: Adding the wheel particle to the group
Line 18: Another particle… this time a rectangle particle. Look at the parameters:
x:Number: The initial x position.
y:Number: The initial y position.
width:Number: The width of this particle.
height:Number: The height of this particle.
rotation:Number (default = 0): The rotation of this particle in radians. Read carefully! RADIANS!!
fixed:Boolean (default = false): Determines if the particle is fixed or not. Fixed particles are not affected by forces or collisions and are good to use as surfaces. Non-fixed particles move freely in response to collision and forces.
mass:Number (default = 1): The mass of the particle
elasticity:Number (default = 0.3): The elasticity of the particle. Higher values mean more elasticity.
friction:Number (default = 0): The surface friction of the particle.
Line 19: Adding the rectangle particle to the group
Lines 20-23: Adding two more rectangle particles
Lines 24-27: Adding two more wheel particles
Line 28: The feature I love: the spring constraint. The spring constraint is a spring-like constraint that connects two particles. If you need more information about constraints, refer to Creation of a Ragdoll with Flash part 2: Constraints.
I am going to connect the last two wheels I created with a constraint. This means I am going to create a car. Look at the parameters:
p1:AbstractParticle: The first particle this constraint is connected to.
p2:AbstractParticle: The second particle this constraint is connected to.
stiffness:Number (default = 0.5): The strength of the spring. Valid values are between 0 and 1. Lower values result in softer springs. Higher values result in stiffer, stronger springs.
collidable:Boolean (default = false): Determines if the constraint will be checked for collision
rectHeight:Number (default = 1): If the constraint is collidable, the height of the collidable area can be set in pixels. The height is perpendicular to the two attached particles.
rectScale:Number (default = 1): If the constraint is collidable, the scale of the collidable area can be set in value from 0 to 1. The scale is percentage of the distance between the the two attached particles.
scaleToLength:Boolean (default = false): If the constraint is collidable and this value is true, the collidable area will scale based on changes in the distance of the two particles.
In my case, I am connecting the last two wheels with a semi-strong collidable spring, with an height of 3 pixels.
Line 29: Adding the constraint to the group
Line 30: Adding the group to the engine
Line 32: Beginning of the function to be executed at every frame, like declared at line 8
Line 33: The main step function of the engine. This method should be called continously to advance the simulation. The faster this method is called, the faster the simulation will run. Usually you would call this in your main program loop.
Line 34: Calling this method will in turn call each particle and constraint’s paint method. Generally you would call this method after stepping the engine in the main program cycle.
The last two lines advance the simulation and display the result.
And this is what I got with this simple script (you may need to reload the page to see the movie work properly)
As you can see, results are really exciting. The ball, the wheel and the car go down the slope bouncing and moving in a very realistic way. I am sure I will be able to create a “Moster Truck” game in a few hours.
And I’ll publish it as soon as it create it.
Meanwhile, download the entire project and give me feeback. Then, move to part 2
Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.