background image

PushButton Engine Basics

So I am starting to use the PushButton Engine at work and right now I am just learning the architecture in order to teach the rest of the flash developers here how to use it. So far it seems like a great engine it is definitely lacking in ‘guided’ documentation on how to get up to speed. Most of the examples/documentation is there you just need to find it across the PushButton website, Google Code Wiki, PushButton API, PushButton forums, and searching through other blog posts. I will try to include all the resources here so that it is easier for others who are new to the engine to start and help you not avoid the same mistakes I Made.

The first thing you need to do is check out the documentation and follow each step of the lessons. It is also very helpful if you watch the video talks and at least skim all the reference material on this page. The main thing to take note of here is the xml. I would say it is the core of what makes the PushButton Engine so powerful.

So now that you are up to speed with the basics, you want to actually start modularizing the code and going beyond what was in the lessons. This was a sticking point for me as I had a complete misunderstanding of how the PBE was supposed to be used. As I started trying to break up the code from the lesson, I immediately moved the ‘createHero’ function into its own class. As I learned from a long chat on the PushButton IRC channel, this is not the correct way. You need to use Templates in Level Xml or
Templates. Since I am just prototyping at this point I chose to use a template as a function. I moved the ‘createHero’ code from out of my class (which should have never been used) into a static factory class where I will create/initialize all entities. As this is a prototype I don’t feel too bad for doing this although for any large project, using xml templates
is definitely the way to go. For this prototype I will be making a simple platform game with mouse navigation.

So now without further ado, we have some code :).  Here is the main function.

public function Main():void
{
    PBE.startup(this);

    var sceneView:SceneView = new SceneView();
    sceneView.width = 700;
    sceneView.height = 400;
    PBE.initializeScene(sceneView);

    PBE.defineEntityByFunction("Hero", EntityFactory.CreateHero);

    PBE.makeEntity("Hero");
}

As you can see, it is very similar to what was in the PushButton example. The only difference here is that instead of calling EntityFactore. CreateHero explicitly, we call PBE.makeEntity which resolves the correct function (I am assuming using a dictionary but I didn’t look at the source). This is a much cleaner solution because it allows us to swap out the CreateHero function with something else if we really need to throughout the prototype — although if it gets that involved then perhaps it is time to start using xml templates.

The next bit of code is the EntityFactory.CreateHero

public static function CreateHero():IEntity
{
    var entity:IEntity = PBE.allocateEntity();
    entity.initialize("Hero");

    var positionProperty:PropertyReference = new PropertyReference("@Spatial.position");

    var spatial:SimpleSpatialComponent = new SimpleSpatialComponent();
    var render:MovieClipRenderer = new MovieClipRenderer();
    var controller:MouseControllerComponent = new MouseControllerComponent();

    spatial.position = new Point(0, 0);
    spatial.size = new Point(50, 90);
    spatial.spatialManager = PBE.spatialManager;

    render.clip = new Static(); // Something my art guy gave me
    render.frameRate = 60;
    render.loop = true;
    render.positionOffset = new Point(-50, -90);
    render.positionProperty = positionProperty;
    render.rotationProperty = new PropertyReference("@Spatial.rotation");
    render.scene = PBE.scene;

    controller.PositionProperty = positionProperty;

    entity.addComponent(spatial, "Spatial");
    entity.addComponent(render, "Render");
    entity.addComponent(controller, "Controller");

    return entity;
}

Take note of the line entity.initialize(“Hero”). The identifier “Hero” can only be used once. PBE uses this identifier in PropertyReferences in order to find component properties of entities. Since I named the entity “Hero” I can get to its spatial ‘position’ property by using the string “#Hero.Spatial.position” in the property reference. You can see an example of this later on in the post. I use a MovieClipRenderer to render an animation for my character. In the future I will be changing this to use an AnimatorComponent but that is for a later post. Also, I have not created a physics component which I will need to do later. For now I am just trying to get things animating

So for my prototype I am making a character which uses the mouse for navigation. I am replacing the mouse cursor with an arrow graphic that always points away from the character and grows/shrinks depending on the distance from the character.

So now I add two lines to the main function to create this arrow.

public function Main():void
{
    PBE.startup(this);

    var sceneView:SceneView = new SceneView();
    sceneView.width = 700;
    sceneView.height = 400;
    PBE.initializeScene(sceneView);

    PBE.defineEntityByFunction("Hero", EntityFactory.CreateHero);
    PBE.defineEntityByFunction("Arrow", EntityFactory.CreateArrow);

    PBE.makeEntity("Hero");
    PBE.makeEntity("Arrow");
}

So I bind the EntityFactore.CreateArrow function and then make the entity. Here is the code for EntityFactory.CreateArrow.

public static function CreateArrow():IEntity
{
    var entity:IEntity = PBE.allocateEntity();
    entity.initialize();

    var positionProperty:PropertyReference = new PropertyReference("@Spatial.position");
    var rotationProperty:PropertyReference = new PropertyReference("@Spatial.rotation");

    var spatial:SimpleSpatialComponent = new SimpleSpatialComponent();
    var render:MovieClipRenderer = new MovieClipRenderer();
    var controller:ArrowControllerComponent = new ArrowControllerComponent();

    spatial.position = new Point(0, 0);
    spatial.size = new Point(40, 50);
    spatial.spatialManager = PBE.spatialManager;

    render.clip = new Default(); // Default arrow
    render.frameRate = 60;
    render.loop = true;
    render.positionProperty = positionProperty;
    render.rotationProperty = rotationProperty;
    render.scene = PBE.scene;

    controller.PositionProperty = positionProperty;
    controller.RotationProperty = rotationProperty;
    controller.ScaleProperty = new PropertyReference("@Render.scale");

    entity.addComponent(spatial, "Spatial");
    entity.addComponent(render, "Render");
    entity.addComponent(controller, "Controller");

    return entity;
}

As you can see, this time when I call entity.initialize I do not pass in an identifier. In this case I do no really need an identifier but if you were doing something such as creating bullet entities where you would have more than one created at a time, you would need to do this since the identifier would clash and PBE would complain. Other than that, this function is very similar to the EntityFactory.CreateHero function.

The next thing I have to worry about is actually moving the arrow with the mouse. For that I created the ArrowControllerComponent.

public class ArrowControllerComponent extends TickedComponent
{
    public var PositionProperty:PropertyReference;
    public var RotationProperty:PropertyReference;
    public var ScaleProperty:PropertyReference;

    private var _heroSpatialProperty:PropertyReference = new PropertyReference("#Hero.Spatial.position");

    public static const MINDISTANCE:Number = 200;
    public static const MAXDISTANCE:Number = 300;

    override public function onTick(deltaTime:Number):void
    {
        owner.setProperty(
            PositionProperty,
                new Point(
                    PBE.mainStage.mouseX - .5 * PBE.scene.sceneView.width,
                    PBE.mainStage.mouseY - .5 * PBE.scene.sceneView.height));

        var position:Point = owner.getProperty(PositionProperty) as Point;

        var charPosition:Point = owner.getProperty(_heroSpatialProperty) as Point;
        var difference:Point = position.subtract(charPosition);

        var scale:Number = 1 + Math.max((Math.min(difference.length, MAXDISTANCE) - MINDISTANCE) / (MAXDISTANCE - MINDISTANCE), 0);
        trace(scale);
        owner.setProperty(
            ScaleProperty,
                new Point(1, scale));

        owner.setProperty(
        RotationProperty,
        Math.atan2(difference.y, difference.x) * 57.32 + 90);
    }
}

So in this class I have four PropertyReferences. The first three are instantiated by the EntityFactory.CreateArrow function when creating that entity. The private _heroSpatialProperty is set and cached so it does not have to find the property each time onTick is called. Doing this is crucial when using PBE because the PropertyReference class is a beast. I looked through the source code a bit and if you do not use the PropertyReference correctly, your project will definitely take a huge performance hit. Anyways, as you can see I use the “#Hero.Spatial.position” to resolve the hero’s position not “#Hero.@Spatial.position” which was a mistake I made and took a while to figure out. The next bits of code is just doing math stuff in order to properly position the arrow at the correct cordinates — mouseX is using the flash coordinates where (0,0) is in the top left while the rest of PBE assumes (0,0) is in the center of the stage/box. I am assuming this is to make integration with Box2D make more sense…

Well, that is all for now. I will be posting the entire source of this prototype when I am finished with everything. I will keep posting updates as I move along. Next up the
AnimatorComponent and SpriteSheets (or however I figure out how to render movie clips with a state machine).



5 views shared on this article. Join in...

  1. Dan says:

    Hi,

    I am new to pbe and I wanted to know if there any option to make gotoAndStop command to the movieclip that are rendered

    Thanks :) your post helped me allot!!

    • John Kalberer says:

      It’s been a while since I worked with PBE so I am sure that there have been some changes to the codebase. I know they were working on a 2.0 of the framework (PBE Next) when I wrote this.

      Anyway, I know you can cast some member of the MovieClipRenderer into a movie clip so it would have the gotoAndStop functionality. After more experience with the engine, I would recommend using spritesheets using the PBE renderer instead of rendering the movie clips. You can use the MultiSpriteSheetHelper or the SWFSpriteSheetComponent to accomplish this.

  2. Junak says:

    Could you please contact me I’m looking for Pushbutton tutorials or any ways from where I could learn PBEngine. Since official forum no longer exists It’ reallly hard to find anything. Thank you very much.

    Kind regards
    Junak

    • As far as I know, the PBEngine is not being worked on any more as Flash is being replaced with HTML5/javascript. If you want to work on Flash-like games, I recommend looking into ImpactJS. It has a very nice system and is one of the more mature javascript game libraries.



Pings to this post

  1. booker t and the msgs…

    […]listed below are several listings to online sites we link to because we feel they’re definitely worth browsing[…]…


Leave a Reply

Your email address will not be published. Required fields are marked *

Comment

You may use these tags : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>