24
Nov/09
0

Quick-Hit: Enunciate

In my most recent work project I was asked to develop a set of middle tier services to allow users to connect to commonly used pieces of data in the organization. As I gathered requirements from different developers that were hoping to utilize these services I found that my standard technology stack would not suffice for a number of reasons. First, the organization I was working with had very strict regulations on technologies which could be used. But most importantly, the vast majority of middle-tier web services I’ve done recently have provided data solely to Flex applications, but in this new project I had a number of different clients wanting to pull data.

I knew immediately that I wanted to write one set of web services but allow access to it via a couple of different gateways: AMF and SOAP. I started by asking around to numerous guys I know to see if they recommended anything that would make the SOAP gateway as easy as possible to write. One article that my coworker Andrew sent me pointed me in the direction of Enunciate.

As I sifted through all of the information in the site, I thought, there’s no way they can provide this much functionality for free, but I have to say, it’s pretty awesome. So what does enunciate do? Well enunciate allows you the ability to write the interfaces and implementations of your web services, add a few choice annotations, and Encunciate will configure all of your SOAP, REST, as well as AMF endpoints. Enunciate does all this via an xml based build script which fits in nicely with both ANT and Maven.

Along with all of the service configurations, Enunciate will also export libraries that different client apps can use to connect to your middle tiers. Enunciate will export a Flash library, Objective C (for you iPhone developers), as well as numerous others. I have not been able to use the swc in my eclipse workspace, but I’ve started exporting the source and modifying it as needed.

Another feature that’s really nice about it enunciate, is that it automatically generates all of the documentation for your web services. It gives detailed information about what is available via REST and SOAP. The AMF documentation is not as detailed as SOAP or REST, which is a little disappointing.

All-in-all this tool has blown my expectations away. My proof of concept was completed in no time at all. I plan to do a full how-to blog entry on Enunciate before the end of the year.

20
Nov/09
0

Box 2D Tutorial

If you were out at Adobe Max this year, you might have seen the huge Max Companion walls. It’s a little bit difficult to see in the video, but tweets relating to Adobe Max would come in, they would be loaded and displayed for a few seconds, then they would fall as if gravity was applied to them. The introduction of physics into this application was done via a framework called Box-2D.

What I plan to show you is how to set up a very basic application that has physics applied to it. Setting up your “physical world” is definitely the most difficult part of using Box2D. Here’s the methods I use to create the Box2D world.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public function createWorld(event:Event = null):void
{
    var ab:b2AABB = new b2AABB();  //the bounds of the physics world
    ab.lowerBound.Set(-200, -200);
    ab.upperBound.Set(200, 200);

    var gravity:b2Vec2 = new b2Vec2(0, 4.0);  //the constant force of gravity

    world = new b2World(ab, gravity, false);  //create the world

    createBorderObject(0, this.height, this.width, 100); //floor
    createBorderObject(0, -this.height, this.width, 100); //ceiling
    createBorderObject(-100, -this.height, 100, 3*this.height); //left
    createBorderObject(this.width + 2, -this.height, 100, 3*this.height); //right

    this.addEventListener( Event.ENTER_FRAME, caluclateWorld );
}

private function createBorderObject(xp:Number, yp:Number, w:Number, h:Number):void
{  //these bodies will prevent objects from getting out of our physics world and being unusable
    var the_box:b2PolygonDef = new b2PolygonDef();
    the_box.SetAsBox(w/physicsScale/2, h/physicsScale/2);
    the_box.density = 0;
    the_box.friction = .4;
    the_box.restitution = 0;

    var gbd:b2BodyDef = new b2BodyDef();
    gbd.position.Set((xp+w/2)/physicsScale, (yp+h/2)/physicsScale);

    var ground:b2Body = world.CreateBody(gbd);
    ground.CreateShape(the_box);
    ground.SetMassFromShapes();

    var rect:Canvas = new Canvas();
    rect.graphics.beginFill(0xFF00FF, 0);
    rect.graphics.drawRect(xp, yp, w, h);
    addChild(rect);
}

In order to create the world you need to set up a few things. The first thing you have to set up is the boundaries of the world, which need to extend beyond what you are actually going to use. The reason it needs to be larger than your play area, is because if any objects exit this region, they’ll become unusable to the physics world. Next you’ll need to create gravity, which doesn’t need to go to the bottom of your screen. You could easily set up gravity to go to the top of the screen or to the side to one side. The last part of the constructor is whether or not you want objects at rest to go to sleep. I’ve always set it to false, but I’m by no means an expert on all of the options.

Within my createWorld method I’ve also created four border objects. These are invisible barriers that prevent objects from reaching my physics border. Lastly, I add an ENTER_FRAME event listener so that every time flash begins to redraw this component it will calculate any changes. What follows is my calculateWorld function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
private function updateWorld(e:Event):void
{
    world.Step((1/30),10);
    var bodyPos:b2Vec2;
    var bodyRot:Number;
    var renderers:ArrayCollection = getActors();
     //updates our visual components to coincide with their physics
    for( var i:Number = 0; i < renderers.length; i++ )
    {
        var renderer:Actor = renderers.getItemAt(i) as Actor;
        var body:b2Body = renderer.physicsBody;
        if( body )
        {
            bodyPos = body.GetPosition();
            renderer.rotation=0;

            var m:Matrix=renderer.transform.matrix;
            m.tx =- renderer.width/2;
            m.ty =- renderer.height/2;
            m.rotate( body.GetAngle() );   
            //m.scale(1,1);
            // Now set the position to the world position
            m.tx+=bodyPos.x*physicsScale;
            m.ty+=bodyPos.y*physicsScale;

            // ...and set the whole thing at once via the matrix.
            // ie. Update the sprite.
            renderer.transform.matrix=m;
            renderer.scaleX = 1;
            renderer.scaleY = 1;
        }
    }
}

My updateWorld function has a number of steps. First, I tell Box2D to calculate the changes, by passing in the number of refresh frequency (1/30) as well as the number of iterations to calculate. After Box2D has calculated the changes I have to loop through all of the objects in the “world” and update their renderer. The renderers are visual components that are tied to a physics body, which is necessary because the objects in the Box2D are not visible.

For the purposes of my sample, I’ve created a simple renderer which you can see here.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.softwarejesus.physics
{
    import Box2D.Dynamics.b2Body;
   
    import mx.containers.Canvas;

    public class Actor extends Canvas
    {
        public var physicsBody:b2Body;
        public var shape:String;
        public function Actor() {
           
        }
       
        public function drawShape():void
        {
            if (shape == Physics.SQUARE_SHAPE) {
                this.setStyle("backgroundAlpha", 1);
                this.setStyle("backgroundColor", 0x000000);
            } else {
                this.setStyle("backgroundAlpha", 0);
                graphics.beginFill(0x000000);
                graphics.drawCircle(this.width/2, this.height/2, this.width/2);
            }
        }
    }
}

Now that you’ve seen the definition for my renderers, let’s see how objects get added to the world.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
public function addShape():void
{
    if(this.selectedShape == CIRCLE_SHAPE)
        addBall();
    else
        addBox()
}

public function addBox():void
{
    var newCanvas:Actor = new Actor();
    newCanvas.width = this.diameter;
    newCanvas.height = this.diameter;
    newCanvas.x = Math.random() * ( this.width - this.diameter);
    newCanvas.y = -newCanvas.height;
    newCanvas.shape = this.selectedShape;
    newCanvas.drawShape();

    var b1:b2PolygonDef = new b2PolygonDef();
    b1.SetAsBox((diameter/2)/physicsScale , (diameter/2) / physicsScale);
    b1.density = density;
    b1.friction = friction;
    b1.restitution = restitution;

    var bd:b2BodyDef = new b2BodyDef();
    bd.position.Set( (newCanvas.x+(newCanvas.width/2))/physicsScale, (newCanvas.y+(newCanvas.height/2))/physicsScale );
    bd.angle = 0;

    var physicsBody:b2Body = world.CreateBody(bd);
    physicsBody.CreateShape(b1);
    physicsBody.SetMassFromShapes();
    physicsBody.ApplyImpulse( b2Vec2.Make(Math.floor(Math.random() * (10 -  -10)) + -10,0), b2Vec2.Make(10,5) );

    newCanvas.physicsBody = physicsBody;
    newCanvas.addEventListener(MouseEvent.MOUSE_DOWN, handleMouseDown);
    this.addChild(newCanvas)
}

public function addBall():void
{
    var newCanvas:Actor = new Actor();
    newCanvas.width = diameter;
    newCanvas.height = diameter;
    newCanvas.x = Math.random() * ( this.width - diameter);
    newCanvas.y = -newCanvas.height;
    newCanvas.shape = selectedShape;
    newCanvas.drawShape();

    var b1:b2CircleDef = new b2CircleDef();
    b1.radius = (diameter/2)/ physicsScale;
    b1.density = density;
    b1.friction = friction;
    b1.restitution = restitution;

    var bd:b2BodyDef = new b2BodyDef();
    bd.position.Set( (newCanvas.x+(newCanvas.width/2))/physicsScale, (newCanvas.y+(newCanvas.height/2))/physicsScale );
    bd.angle = 0;

    var physicsBody:b2Body = world.CreateBody(bd);
    physicsBody.CreateShape(b1);
    physicsBody.SetMassFromShapes();
    physicsBody.ApplyImpulse( b2Vec2.Make(Math.floor(Math.random() * (10 + 10)) + -10,0), b2Vec2.Make(10,5) );

    newCanvas.physicsBody = physicsBody;
    newCanvas.addEventListener(MouseEvent.MOUSE_DOWN, handleMouseDown);
    this.addChild(newCanvas)
}

I start by creating my renderer. Next, I create the shape that I want to add to the world, for this example I’ve limited the shapes to circles and squares for the sake of simplicity. I set a few options on the shape that determine how the shape interacts with it’s surroundings in our world. Those options are density, friction, restitution (bounciness), and size. You can see the effects of each of these options in my example below.

The last element of my functions for adding my shapes is the addition of a MOUSE_DOWN event listener. The purpose of this is to allow the user to actually interact with the objects in the world. Here’s my mouse event handlers.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public function handleMouseDown(evt:MouseEvent):void
{
    var newX:int = (evt.stageX+15)/physicsScale;
    var newY:int = (evt.stageY+15)/physicsScale;
    var renderer:Actor;
    if (evt.target is Actor) {
        renderer = evt.target as Actor;
    } else {
    }
    if( renderer )
    {
        var body:b2Body = renderer.physicsBody;
        var md:b2MouseJointDef = new b2MouseJointDef();
        md.body1 = world.GetGroundBody();
        md.body2 = body;
        md.target.Set(newX, newY);
        md.maxForce = 5000.0;
        md.timeStep = (1/30);

        var newMouseJoint:b2MouseJoint = world.CreateJoint(md) as b2MouseJoint;
        mouseJoint = newMouseJoint;
        body.WakeUp();
        this.addEventListener(MouseEvent.MOUSE_MOVE, handleMouseMove);
        this.addEventListener(MouseEvent.MOUSE_UP, handleMouseUp);
    }
}

public function handleMouseMove(event:MouseEvent):void
{
    var newX:int = (event.stageX+10)/physicsScale;
    var newY:int = (event.stageY+10)/physicsScale;
    var p2:b2Vec2 = new b2Vec2(newX, newY);

    if(mouseJoint)
        mouseJoint.SetTarget(p2);

}  

public function handleMouseUp(event:MouseEvent):void    
{
    this.removeEventListener(MouseEvent.MOUSE_MOVE, handleMouseMove);
    this.removeEventListener(MouseEvent.MOUSE_UP, handleMouseUp);
    if (mouseJoint) {
        world.DestroyJoint(mouseJoint);
        mouseJoint = null;
    }


}

When the user mouses down on one of the renderers a mouse joint is created and we listen for a mouse move event. A mouse joint is a means for us to apply an external force to our objects.

When you put all this together, you have the goofy little sample below.

Get Adobe Flash player

You can also see it here
Or download this source from here