PBE Series: clickable component

January 2nd, 2010 by Christian Leave a reply »

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)!

5 comments

  1. Christian says:

    I updated the code to let it work with PBE 1.0!

  2. ray says:

    Hi there, The spatials object method worked for me.. I managed to find trace an object found under the point when clicked.. however, I am perplexed by how to find the actual entity’s name so that I can perform additional actions, can you provide some insight on how I could find the actual entity that the spatials object belongs to? spatialObj.owner kinds of returns null.. hmm

  3. Christian says:

    Hi!

    It’s been a while, but if I remember correctly, using the spatialmanager.getObjects… returns the Entity itself, not the component.
    So it should do the trick by simply writing spatialObj.name.
    IFF I remember correct… ;)

  4. ray says:

    Hi Christian!
    Thanks for your response!
    Can you help me out with the function –>
    PBE.spatialManager.getObjectsUnderPoint …
    really only gets objects at that “point” and is so precise such that when I click on some part of the object’s picture that is relatively larger.., it does not detect that object any more.. it only works for that precise Point … (which is probably what the function is designed for) ..
    is there a way to do it so that the whole image of that object, is detected when I click on any part of the image.. like if I wanted the object to be destroy()-ed on a click on any part of its image… is there a better way to do this? Thanks!

    - Ray

  5. Christian says:

    PBE.spatialManager.getObjectsUnderPoint gets spatial objects.

    If you want to get display objects, use
    var point:Point = new Point(PBE.mainStage.mouseX, PBE.mainStage.mouseY);

    var objs:Boolean = PBE.scene.getRenderersUnderPoint(point, selectedDisplayObjects);

Leave a Reply