ActionScript, PushButton Engine → Angry Explanations #2: Spinning a freaking image with PBE!
Following on from Angry Explanations #1, we will now add some motion to the scene. For kicks and giggles, we’ll cause the image to rotate each frame.
(Note that this information is in reference to PushButton Engine build r625.)
The key takeaway here is that for a component to be tickable, it must implement the ITickedObject interface and then tell the ProcessManager to start and stop calling onTick() every tick.
Oh, there’s one other key takeaway here: how to use PropertyReferences. You get a property of a component by way of the owning entity. You create a PropertyReference instance for each data member that you need to access. In this example, we’re accessing the rotation field on the SpriteRenderer component we added in Angry Explanations #1.
In a bit more detail, the PropertyReference is constructed with a special string: "@Sprite.rotation" (see line 11 in the code below). That means, this is a reference to the component of this entity with the name “Sprite” (recall that we gave it that name when we created the SpriteRenderer component instance), and the field “rotation” of the SpriteRenderer class. It’s quite simple once you realize what it’s doing (but I’m no less angry, mind you!).
I thought that a SpatialComponent might be necessary to alter the sprite’s position, but apparently that component has been removed (since r470, which is the current packaged release). That data seems to now be handled by the renderer component itself.
Add this one line to the end of showLogo() from the previous example:
spriteEntity.addComponent( new SpinController(), "spinner" );
Then add the following new class in a sub-folder (components/controllers/).
package com.yourcompany.yourgame.components.controllers
{
import com.pblabs.engine.core.ITickedObject;
import com.pblabs.engine.core.ProcessManager;
import com.pblabs.engine.entity.EntityComponent;
import com.pblabs.engine.entity.PropertyReference;
public class SpinController extends EntityComponent implements ITickedObject
{
// Cache the PropertyReference instance here to avoid a bunch of temporary allocations.
private var _rotProp:PropertyReference = new PropertyReference( "@Sprite.rotation" );
// Nothing to do in the constructor because this is such a simple example.
public function SpinController()
{
super();
}
// When the component is added to the sprite entity, we want to register to
// get tick updates by the ProcessManager.
protected override function onAdd():void
{
super.onAdd();
ProcessManager.instance.addTickedObject( this );
}
// When the component is removed from the sprite entity, we want to unregister
// from the ProcessManager so tick updates will stop.
protected override function onRemove():void
{
super.onRemove();
ProcessManager.instance.removeTickedObject( this );
}
// Each tick, we just change the rotation of the sprite renderer a little bit.
public function onTick(tickRate:Number):void
{
// Get the current rotation.
var rotation:Number = owner.getProperty( _rotProp ) as Number;
// Add 1 degree to it.
rotation += 1;
// Store the new rotation back in the sprite.
owner.setProperty( _rotProp, rotation );
}
}
}
As an addendum, I should point out that the rotation will probably not be smooth. To fix that, you should have the SpinController implement IAnimatedObject instead of ITickedObject. The registration with the ProcessManager is the same, except you call addAnimatedObject() instead of addTickedObject().
The difference is that IAnimatedObject will update when Flash draws a frame instead of when the ProcessManager ticks, and the motion will appear a lot smoother.
And you’ll want to normalize the rotation based on delta time since the last frame. Er, like this:
public function onFrame( elapsed:Number ):void
{
var rotation:Number = owner.getProperty( _rotProp ) as Number;
// Rotate 15 degrees per second, nice and slow.
rotation += 15 * elapsed;
owner.setProperty( _rotProp, rotation );
}
My first approach was to get around it entirely by encoding all values that require more than 1 byte into hex strings. What a joyful aside that was! (Sarcasm, you see.) I mean, now I know how to encode anything to hex and back and do it sideways, too. But, this wasn’t working so well and it was bloating the nice binary format anyway. (No, I wasn’t really concerned about the size of the packets based on that, but if there’s a better way and it’s more space efficient–why not?)
I like
I’ve noticed the rise of several hosted solutions that intend to make the creation of multiplayer Flash games simpler. I’m all about using middleware. I have no ego or hangups about parts of my game code being “
I’m using Box2d, and for a physics sim, you want every update to use the same delta time. Fluctuations can cause the simulation to get all wigged out and blow up. Lucky for me, on the game I’m working on (not announced yet), I’m mostly only using Box2d for collision detection. There are no stacks of boxes or whatever, so there’s not a lot of simulating happening, and that makes it more tolerant to variable tick durations. Still not ideal, because it can cause weird collision glitches, like tunneling.