Archive

Archive for the ‘as3’ Category

Box2Dwrapper – More Examples with Joints

April 1st, 2009

Hi!

Here are a few examples on how to set up joints using Box2Dwrapper. More to come! Remember, you can grab the wrapper source here : https://box2dwrapper.googlecode.com/svn/trunk I’ll be posting more complex examples soon so stay tuned ;)

Prismatic Joint Example

package
{
    import Box2D.Common.Math.b2Vec2;
   
    import com.box2dwrapper.math.Vec;
    import com.box2dwrapper.object.Box;
    import com.box2dwrapper.object.Joint;
    import com.box2dwrapper.view.Box2DView;

    public class PrismaticJointExample extends Box2DView
    {
        public function PrismaticJointExample()
        {
            super();
            initialize();
        }
       
        private function initialize():void
        {
            createBoundingWalls();
            showDebug = true;
            allowDragging = true;
                       
            createObjects();
           
            startPhysicsRender();
        }
       
        private function createObjects():void
        {
            var plank:Box = new Box();
            plank.scale(100, 20);
            plank.position(stage.stageWidth * 0.5, stage.stageHeight * 0.5);
            plank.type = "dynamic";
            addBody(plank);
           
            var joint:Joint = new Joint(Joint.PRISMATIC);
            joint.initialize(world.GetGroundBody(), plank.body, plank.body.GetWorldCenter(), new b2Vec2(1, 0));
            joint.lowerTranslation = -3;
            joint.upperTranslation = 3
            joint.enableLimit = true;          
           
            joint.maxMotorForce = 100;
            joint.motorSpeed = 4.0;
            joint.enableMotor = true;          
           
            addJoint(joint);
        }
       
    }
}

Revolute Joint Example

package
{
    import com.box2dwrapper.math.Vec;
    import com.box2dwrapper.object.Box;
    import com.box2dwrapper.object.Circle;
    import com.box2dwrapper.object.Joint;
    import com.box2dwrapper.view.Box2DView;

    public class RevoluteJointExample extends Box2DView
    {
        public function RevoluteJointExample()
        {
            super();
            initialize();
        }
       
        private function initialize():void
        {
            createBoundingWalls();
            showDebug = true;
            allowDragging = true;
                       
            createObjects();
           
            startPhysicsRender();
        }
       
        private function createObjects():void
        {
            var pivot:Circle = new Circle();
            pivot.radius = 10;
            pivot.position(stage.stageWidth * 0.5, stage.stageHeight * 0.5);
            pivot.type = "static";
            addBody(pivot);
           
            var plank:Box = new Box();
            plank.scale(20, 100);
            plank.position(pivot.x, pivot.y + 35);
            plank.type = "dynamic";
            addBody(plank);
           
            var tac:Joint = new Joint(Joint.REVOLUTE);
            tac.initialize(pivot.body, plank.body, pivot.body.GetWorldCenter());
           
            tac.enableMotor = true;
            tac.motorSpeed = 2;
            tac.maxMotorTorque = 50;
           
            addJoint(tac);
        }
       
    }
}

Gear Joint Example

package
{
    import Box2D.Dynamics.Joints.b2GearJoint;
    import Box2D.Dynamics.Joints.b2GearJointDef;
   
    import com.box2dwrapper.object.Circle;
    import com.box2dwrapper.object.Joint;
    import com.box2dwrapper.view.Box2DView;

    public class GearJointExample extends Box2DView
    {
        public function GearJointExample()
        {
            super();
            showDebug = true;
            allowDragging = true;
            initialize();
            startPhysicsRender();
        }
       
        private function initialize():void
        {
            var gear1:Circle = new Circle();
            gear1.radius = 40;
            gear1.density = 2;
            gear1.position(stage.stageWidth * 0.45, stage.stageHeight * 0.5);
            gear1.type = "dynamic";
            addBody(gear1);
           
            var gear2:Circle = new Circle();
            gear2.radius = 60;
            gear2.density = 3;
            gear2.position(stage.stageWidth * 0.65, stage.stageHeight * 0.5);
            gear2.type = "dynamic";
            addBody(gear2);
           
            var joint1:Joint = new Joint(Joint.REVOLUTE);
            joint1.initialize(world.GetGroundBody(), gear1.body, gear1.body.GetWorldCenter());
            addJoint(joint1);
           
            var joint2:Joint = new Joint(Joint.REVOLUTE);
            joint2.initialize(world.GetGroundBody(), gear2.body, gear2.body.GetWorldCenter());
            addJoint(joint2);
           
            var gearJoint:Joint = new Joint(Joint.GEAR);
            gearJoint.body1 = gear1.body;
            gearJoint.body2 = gear2.body;
            gearJoint.joint1 = joint1.joint;
            gearJoint.joint2 = joint2.joint;
            gearJoint.ratio = 1;
            addJoint(gearJoint);               
        }      
    }
}

Experiment, Lab, as3

Exploring a Papervision3D class – Sound3D

February 4th, 2009

So, this weekend I was working on a project; I use Flex Builder to code and as I was casting a class, I noticed “Sound3D” in the code completion and immediately got intrigued. I have heard of that class being buried deep in the Papervision packages before, but really didn’t pay much attention to it, till now.

Before we jump into anything, check out the example below. It uses the FirstPersonCamera3D class so you can move around and get a sense of what the Sound3D class does.

How cool is that?! I recently developed a game in which that would have worked out pretty well. No complaints though :) One thing about the Sound3D class in the Papervision3D packages is that it does not have the ability to load sounds, it only accepts a sound object as a parameter in the constructor, so, I decided to to add the functionality in there myself by creating an EnhancedSound3D class which extends the Sound3D, and here it is:

package
{
    import flash.events.Event;
    import flash.events.ProgressEvent;
    import flash.media.Sound;
    import flash.media.SoundLoaderContext;
    import flash.net.URLRequest;
   
    import org.papervision3d.objects.special.Sound3D;

    public class EnhancedSound3D extends Sound3D
    {
       
        private var soundObjectParams:Object = {};
       
        public function EnhancedSound3D(soundObj:Sound = null)
        {
            super(soundObj);
        }
       
        public function load(soundPath:String, startTime:Number = 0, loops:int = 0, soundTransform:SoundTransform = null):void{
            var soundRequest:URLRequest = new URLRequest(soundPath);
            sound = new Sound();
            sound.load(soundRequest, new SoundLoaderContext());
            sound.addEventListener(Event.COMPLETE, handleSoundLoaded);
            sound.addEventListener(ProgressEvent.PROGRESS, handleLoadProgress);
            soundObjectParams = {startTime:startTime, loops:loops, soundTransform:soundTransform}
        }
       
        private function handleSoundLoaded(e:Event):void
        {
            sound.removeEventListener(ProgressEvent.PROGRESS, handleLoadProgress);
            sound.removeEventListener(Event.COMPLETE, handleSoundLoaded);
            play(soundObjectParams.startTime, soundObjectParams.loops, soundObjectParams.soundTransform);
            dispatchEvent(e.clone());
        }
       
        private function handleLoadProgress(e:ProgressEvent):void
        {
            dispatchEvent(e.clone());
        }
       
    }
}

The Sound3D class extends DisplayObject3D, so it inherits all its properties such as x, y and z so you can basically place the sound anywhere you like in 3D space. A few added properties are maxSoundDistance and soundDistance. “maxSoundDistance” determines the maximum distance the sound can travel and “soundDistance” is used to control the volume. It puts out values ranging from -1 to 1 where 0 to -1 represent the sound being behind the camera.

You can basically attach your sound to anything, a car, a plane an enemy walking behind in your first person shooter game [wink, wink].

Below is the code I used for the example you just saw. Remember that you’ll need to grab the FirstPersonCamera3D class if you don’t have it yet.

package
{
    import flash.events.Event;
    import flash.events.ProgressEvent;
    import flash.text.TextField;
   
    import org.papervision3d.materials.ColorMaterial;
    import org.papervision3d.materials.WireframeMaterial;
    import org.papervision3d.materials.special.CompositeMaterial;
    import org.papervision3d.materials.utils.MaterialsList;
    import org.papervision3d.objects.primitives.Cube;
    import org.papervision3d.objects.primitives.Plane;
    import org.papervision3d.view.BasicView;

        import FirstPersonCamera3D;
        import EnhancedSound3D;

    public class CameraTest extends BasicView
    {
       
        private var firstPersonCamera:FirstPersonCamera3D;
        private var cubes:Array = [];
        private var sounds:Array = [];
       
        private var SIZE:Number;
        private var DISTANCE:Number;
       
        public function CameraTest()
        {
            super(640, 480, true, false);
            SIZE = 30000;
            DISTANCE = (SIZE * 0.5) - 250;
            setupCamera();
            createObjects3D();
            startRendering()
        }
       
        private function setupCamera():void
        {
            firstPersonCamera = new FirstPersonCamera3D();
            firstPersonCamera.initialize(viewport, 0.8, 0.2);
            firstPersonCamera.mode = "manual";
            firstPersonCamera.y = 750;
            firstPersonCamera.moveBounds = {left:-DISTANCE + 750, right:DISTANCE - 750, front:DISTANCE - 750, back:-DISTANCE + 750};
            firstPersonCamera.mapKeys(FirstPersonCamera3D.WASD_AND_ARROWS);
        }
       
        private function createObjects3D():void
        {
            var positions:Array = [{x:DISTANCE, y:750, z:DISTANCE},
                                   {x:-DISTANCE, y:750, z:DISTANCE},
                                   {x:DISTANCE, y:750, z:-DISTANCE},
                                   {x:-DISTANCE, y:750, z:-DISTANCE}];
           
            var cubeMat:WireframeMaterial = new WireframeMaterial(0xFF0000);
            var colorMat:ColorMaterial = new ColorMaterial(0x00FF00);
            var compMat:CompositeMaterial = new CompositeMaterial();
            compMat.addMaterial(cubeMat);
            compMat.addMaterial(colorMat);
           
            var materialsList:MaterialsList = new MaterialsList({ all:compMat });
           
            for(var a:Number = 0; a<4; a++){
                var cube:Cube = new Cube(materialsList);
                cube.x = positions[a].x;
                cube.y = positions[a].y;
                cube.z = positions[a].z;
                cube.lookAt(firstPersonCamera);
                cubes[a] = cube;
                               
                var sound3D:EnhancedSound3D = new EnhancedSound3D();
                sound3D.load(a+".mp3");
                sound3D.x = positions[a].x;
                sound3D.y = positions[a].y;
                sound3D.z = positions[a].z;
                sound3D.maxSoundDistance = SIZE * 0.75;
                sound3D.addEventListener(ProgressEvent.PROGRESS, handleSoundLoadProgress);
                sounds[a] = {sound:sound3D, tf:TextField(this["soundLoad"+a])};        
               
                scene.addChild(cube);
                scene.addChild(sound3D);
            }
           
            var floor:Plane = new Plane(new WireframeMaterial(0xFFFFFF), SIZE, SIZE, SIZE*0.001, SIZE*0.001);
            floor.rotationX = 90;
            scene.addChild(floor);
        }
       
        private function focusCubesOnCamera():void
        {
            for(var a:Number = 0; a<cubes.length; a++){
                cubes[a].lookAt(firstPersonCamera)
            }
        }
       
        private function handleSoundLoadProgress(e:ProgressEvent):void
        {
            for(var a:Number = 0; a<sounds.length; a++){
                if(e.target == sounds[a].sound){
                    sounds[a].tf.text = "Sound"+a+" -- "+Number(Math.round((e.bytesLoaded/e.bytesTotal)*100))+"% loaded."
                }
            }
        }
       
        override protected function onRenderTick(event:Event=null):void
        {
            firstPersonCamera.look(0.5);
            focusCubesOnCamera();
           
            renderer.renderScene(scene, firstPersonCamera, viewport);
        }
       
    }
}

Lab, as3, papervision3d

Method of removing all event listeners

January 26th, 2009

So over the weekend I was talking to a buddy of mine in regards to different ways of removing event listeners from objects. The way that I usually do it is that everything that requires a listener is placed in a “addListeners” method and and its counter part is placed in a “removeListeners” method. That’s a very simple way of doing it. It works all the time as long as you are on top of every single object that requires having a listener added and you place it on both functions.

Don’t get me wrong, that work around works pretty good but becomes sort of a drag at times (eh, call me lazy) so I came up with a more automated way of doing it! A little disclaimer though, the method that I am about to describe works in 99.9% of my cases because all my classes extend an abstract class of some sort. Anyway, let me show you how I go about it:

What I do is archive all the added listeners and then remove them later in a loop. Everything is done at the abstract class level

private var arrListeners:Array = [];

I then override the “addEventListener” method in order to push references into the array as so:

override public function addEventListener(type:String, listener:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean=false):void
{
        super.addEventListener(type, listener, useCapture, priority, useWeakReference);
        arrListeners.push({type:type, listener:listener});
}

Now that you have a way to reference the added listeners, you would loop through the array to remove the listeners which still exist when needed:

private function clearEvents():void
{
   for(var i:Number = 0; i<arrListeners.length; i++){
      if(this.hasEventListener(arrListeners[i].type){
         this.removeEventListener(arrListeners[i].type, arrListeners[i].listener);
      }
   }
   arrListeners = null
}

That’s basically it. After that, if the object does not extend a class with that method, then I would just use the first method mentioned above.

You can download a quick example here. If you guys have any other ways of doing it, or can enhance the way that I am doing it now, please do let me know. Hope this helps!

Lab, as3