Archive for the ‘Tutorials’ category

PBE Series: using SchemaGenerator

January 22nd, 2010

Previously, in PBE Series: dynamically get list of public members, properties and methods of object or class, I noted that

SchemaGenerator.instance.generateSchema();

“dumps all classes and public info to a xml file”.
We’ll, I’ve used it now, and I must admit that was a lie ;)
So here’s how you use it, and what it results in!

First, you need to establish a local connection, and then call generateSchema:

conn = new LocalConnection();
conn.client = this;
conn.allowDomain('*');
try {
	conn.connect("_SchemaConnection");
} catch (error:ArgumentError) {
	trace("Can't connect to _SchemaConnection");
}
 
SchemaGenerator.instance.generateSchema();

SchemaGenerator.instance.generateSchema will then call OnSchemaReceived in your class, so you need to add that. It takes two string arguments: type and data. Type is either “START”, “END”, “ERROR” or “TYPE”. Data is an XML description of the current processed class (internally it uses flash.utils.describeType), which you then can further interact with.
Here’s an example of how OnSchemaReceived could look like:

public function OnSchemaReceived(type:String, data:String):void
{
	switch( type )
	{
		case "START":
		break;
 
		case "END":
		break;
 
		case "ERROR":
		break;
 
		case "TYPE":
		{
			var myXML:XML = new XML(data);
			myXML.ignoreWhite = true;
 
			var xmlList:XMLList = myXML.child("factory");
 
			//Check accessors:
			for each (var acc:XML in xmlList.accessor)
			{
				//DO SOMETHING.
			}
 
			//Check public variables:
			for each (var pVar:XML in xmlList.variable)
			{
				//DO SOMETHING.
			}
		}
		break;
	}
}

That should help you getting started!

PBE Series: clickable component

January 2nd, 2010

Prerequisites:

Today I will show you, how to create a component for PushButton Engine, that registers, if an entity got clicked on or not.

In general, you got two possibilities how to handle this:

  1. per object level
  2. on a global level

Per object level: since it’s flash, you can simply add an event listener to your graphics component, which listens to click events.

I personally don’t like that too much though, so let’s consider variant two: global level.

It’s a component which exists once in the scene, and not per entity. It listens to click events which happen on the main stage, and on each click, it uses the built in functions PBE.scene.getRenderersUnderPoint and/or PBE.spatialManager.getObjectsUnderPoint to determine, which objects got clicked on.

This version only uses the getRenderersUnderPoint, the main stuff is going on in the OnClick method:

package
{
   import com.pblabs.engine.PBE;
   import com.pblabs.engine.debug.Logger;
   import com.pblabs.engine.entity.EntityComponent;
   import com.pblabs.rendering2D.DisplayObjectRenderer;
 
   import flash.events.MouseEvent;
   import flash.geom.Point;
 
	public class ClickComponent extends EntityComponent
	{
		protected override function onAdd():void
		{
			PBE.mainStage.addEventListener(MouseEvent.CLICK, OnClick );
		}
 
		private function OnClick(e:MouseEvent):void
		{
			var results:Array = new Array();
			var point:Point = new Point( PBE.mainStage.mouseX, PBE.mainStage.mouseY );
			var foundRenderers:Boolean = PBE.scene.getRenderersUnderPoint( point, results );
 
			for each( var obj:DisplayObjectRenderer in  results )
			{
				Logger.print( this, obj.name );
			}
		}	  
 
		protected override function onRemove():void
		{
			PBE.mainStage.removeEventListener(MouseEvent.CLICK, OnClick );
		}
	}
}

Now if you want to get the spatial objects, simply use this:

var spatials:Array = new Array();
PBE.spatialManager.getObjectsUnderPoint( PBE.scene.transformScreenToWorld(point), spatials, new ObjectType("Renderable"));
 
for each( var spatialObj:ISpatialObject2D in spatials )
{
	Logger.print( this, spatialObj.position.toString() );
}

The main difference is that getRenderersUnderPoint results in DisplayObjectRenderers, and getObjectsUnderPoint results in ISpatialObject2Ds.

Also, see that you can supply an object mask. Leaving it null will take all objects into consideration.

All in all you can see, how easy this is (for such a complex sounding task)!

PBE Series: dynamically get list of public members, properties and methods of object or class

December 27th, 2009

Now this isn’t necessarily only related to PushButton Engine. Without using the Logger functions, it would also work with “plain” ActionScript. So what do I want to do here? My main problem was, with Level Master 2000, I want to have UI-based component composition. And each component has different properties which should be settable in the editor. And it looks like this is pretty easy to do with ActionScript. All you need to do is get an XML description of your object or class, by using the built in function describeType:

//Produces an XML object that describes the ActionScript
//object named as the parameter of the method:
var varList:XML = flash.utils.describeType( /*INSERT OBJECT OR CLASS*/ );

And then, depending on what you want to access (properties, members or functions), just iterate over your XML and you’re good!

Logger.print(this, "Properties:");
for each (var a:XML in varList.accessor)
{
	Logger.print(this, a.@name+" : "+a.@type);
}
Logger.print(this, "Variables:");
for each (var b:XML in varList.variable)
{
	Logger.print(this, b.@name+" : "+b.@type);
}
Logger.print(this, "Methods:");
for each (var c:XML in varList.method)
{
	Logger.print(this, c.@name+" : "+c.@type);
}

For me with my editor, I’ll probably do this once at startup and keep the information for all the components stored somewhere. I currently don’t know how performance is, but I guess it’s gonna be better that way. If it turns out to be a wrong approach, I’ll post my conclusion here ;)

Edit – doing it the PushButton way:
Of course there seems to be a much easier way doing it with PushButton Engine. I must admit, I haven’t tried it, but it seems there’s this built in function which sort of dumps all classes and public info to a xml file by just using:

SchemaGenerator.instance.generateSchema();

Nice!

PBE Series: creating spatial objects via ActionScript

December 19th, 2009

Prerequisites:

Today I want to cover how to create spatial positioned objects with PushButton Engine via ActionScript.
With the current build, you got two possibilities:

  1. create a SimpleSpatialComponent or
  2. create a Box2DSpatialComponent.

Remark: if you want to display graphics only (meaning without a spatial component), it’s also possible to position them directly. See PBE Series: quickly displaying sprites via ActionScript for more information about that!

So what’s the difference between those two? In short, Simple-SpatialComponent is not driven by a physics engine. Box2D-SpatialComponent is, as the name might let one guess, bound to Box2D. If your SpatialManager is a Box2D-ManagerComponent (again, see PBE Series: initializing your scene via ActionScript how to setup your scene), you can easily work with both types of objects in your scene, but remember that a Simple-SpatialComponent cannot collide with a Box2D-SpatialComponent. So for everything which needs physical interaction, you want to use Box2D-SpatialComponent.

Anyway, not every game needs physics, so let’s start with the SimpleSpatialComponent:

//Create a new entity:
var myEntity:IEntity = PBE.allocateEntity();
myEntity.initialize("MyEntity");
 
//Create our spatial component
var spatialComp:SimpleSpatialComponent = new SimpleSpatialComponent();
spatialComp.spatialManager = PBE.getSpatialManager();
spatialComp.objectMask = new ObjectType("Renderable");
spatialComp.position = new Point(0, 0);
spatialComp.size = new Point(256,64);         
 
//Add the component to the entity:
myEntity.addComponent( spatialComp, "Spatial" ); 			
 
//Since we want to visualize the entity, we need a simple sprite renderer:
var renderComp:SpriteRenderer = new SpriteRenderer(); 
 
renderComp.scene = PBE.getScene();
renderComp.fileName = "../assets/Images/platform.png";
 
//Bind render component position and rotation to spatial component:
renderComp.positionProperty  = new PropertyReference("@Spatial.position");
renderComp.rotationProperty = new PropertyReference("@Spatial.rotation");
 
//Add the component to the entity:
myEntity.addComponent( renderComp, "Render" );

The most important thing to note, is that the render component’s position and rotation properties are bound to the spatial component.

Now to the Box2DSpatialComponent:

//Create a new entity:
var myEntity:IEntity = PBE.allocateEntity();
myEntity.initialize("MyEntity");
 
//Create our spatial component / body:
var spatialComp:Box2DSpatialComponent = new Box2DSpatialComponent();
spatialComp.manager = (PBE.getSpatialManager() as Box2DManagerComponent);
spatialComp.position = new Point(0, 0);
spatialComp.size = new Point(50, 50);
spatialComp.collisionType = new ObjectType("Something");
spatialComp.collidesWithTypes = new ObjectType("Something", "SomethingDifferent");
 
//We also need a collision shape, which collides with the world (meaning other shapes):
var shape:CircleCollisionShape = new CircleCollisionShape();
shape.radius = 1.0;
shape.density = 20;
 
//Now we add the shape to the spatial component / body:
spatialComp.collisionShapes = new Array();
spatialComp.collisionShapes.push(shape);
spatialComp.buildCollisionShapes(); //don't forget to build the collision shapes!
 
//Add the component to the entity:
myEntity.addComponent( spatialComp, "Spatial" ); 			
 
//Since we want to visualize the entity, we need a simple sprite renderer:
var renderComp:SpriteRenderer = new SpriteRenderer(); 
 
renderComp.scene = PBE.getScene();
renderComp.fileName = "../assets/Images/platform.png";
renderComp.positionProperty  = new PropertyReference("@Spatial.position");
renderComp.rotationProperty = new PropertyReference("@Spatial.rotation");
 
//Add the component to the entity:
myEntity.addComponent( renderComp, "Render" );

I think the code is pretty self-explanatory. The basic work flow is to first create a body (spatial component), then some collision shapes, add those shapes to your body and then build the collision shapes. This is just a start, feel free to play around with all the properties and see how they affect the body’s behaviour!

PBE Series: quickly displaying sprites via ActionScript

December 16th, 2009

Prerequisites:

There’s not much to say. We’ll just create an entity with a sprite render component – and position it in our scene.

//Create a new entity:
var myEntity:IEntity = PBE.allocateEntity();
myEntity.initialize("MyEntity");
 
//Render component:
var renderComp:SpriteRenderer = new SpriteRenderer(); 
 
renderComp.scene = PBE.getScene();
renderComp.fileName = "../assets/Images/platform.png";
renderComp.position = new Point(0, 0);
renderComp.rotation = 0.0;
 
//Add the component to the entity:
myEntity.addComponent( renderComp, "Render" );

That’s the comfortable thing when working with PushButton Engine! You don’t necessary need a spatial component or such, just to display graphics. In case you wonder what a spatial component is: they’ll be covered in the next PBE Series tutorial!