QuickBox2D Skinning

Actionscript:
  1. import com.actionsnippet.qbox.*;
  2.  
  3. var sim:QuickBox2D = new QuickBox2D(this);
  4.  
  5. sim.createStageWalls({lineAlpha:0,fillColor:0x000000})
  6. sim.addBox({x:3, y:3, width:3, height:3, skin:BoxSkin});
  7. sim.addCircle({x:3, y:8,radius:1.5,  skin:CircleSkin});
  8. sim.addPoly({x:6, y:3, verts:[[1.5,0,3,3,0,3,1.5,0]], skin:TriangleSkin});
  9.  
  10. sim.addBox({x:6, y:3, width:3, height:3, skin:BoxSkin});
  11. sim.addCircle({x:6, y:8,radius:1.5,  skin:CircleSkin});
  12. sim.addPoly({x:12, y:3, verts:[[1.5,0,3,3,0,3,1.5,0]], skin:TriangleSkin});
  13.  
  14. sim.start();
  15. sim.mouseDrag();

You'll need this fla to run this snippet since the graphics are in the library. This snippet shows how to easily use linkage classes as the graphics for your rigid bodies. This was actually one of the first features I implemented in QuickBox2D.


Take a look at the swf here...

This entry was posted in Box2D, MovieClip, QuickBox2D, motion and tagged , , , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

31 Comments

  1. bart
    Posted June 26, 2009 at 12:20 pm | Permalink

    As a small addition:
    It can happen quite easily that you actually want to ‘draw’ the DisplayObject on runtime outside of Box2D code, and then apply it as a skin to a QuickObject.

    I added the following to BoxObject.as, CircleObject.as, …
    if (p.skin is DisplayObject){
    bodyDef.userData = p.skin;
    } else if (p.skin is Class){

    now I can do something like
    var s:Sprite = new Sprite();
    s.graphics.beginFill(0×000000)
    s.graphics.drawCircle(0,0,5);

    sim.addCircle({x:0, y:0, radius:5, skin:s});

    I thought this to be quite useful.
    FWIW and thanks for the great work!

  2. Posted June 26, 2009 at 12:59 pm | Permalink

    very nice bart! :) I’ll add it to the next release and credit you in the comments. Let me know if you have any other recommendations. The main update in the next release is the ability to add any kind of joint… but I’d like to add other things if people have ideas…

    I know what you have there is just pseudo-code, but you’d need to do the pixel to meters conversion so radius would be (5 / 30)… unless you’ve changed the scale settings to match pixels (which isn’t recommended apparently).

  3. bart
    Posted June 27, 2009 at 12:33 pm | Permalink

    well::: I’m just getting around the whole physics world and am already so excited by it :-)
    Another recommendation I’d have: It’s clear that you’ll often be converting from meters to pixels and vice versa. Why not add a static helper function somewhere to convert values? or even just the put the scale ratio in a static variable. Something like (in QuickBox2D class):
    public static const M2P:Number = 30; // M2P -> Meter2Pixel
    public static const P2M:Number = 1 / M2P;

    and then use the M2P value throughout your code, instead of hardcoding the 30 everywhere….

    then, the pseudo example above would be as easy as:
    var radius:Number = 5;
    var s:Sprite = new Sprite();
    s.graphics.beginFill(0×000000)
    s.graphics.drawCircle(0,0,radius);
    sim.addCircle({x:0, y:0, radius:radius*QuickBox2D .P2M, skin:s});

    when creating your own DisplayObjects, I think it’s fair enough for having the developer be responsible for matching the properties of skin & QuickObject.

    again: FWIW and really looking forward to any updates!

  4. Posted June 27, 2009 at 1:38 pm | Permalink

    That’s not a bad idea… the one annoying thing about static const vars is that they are super slow to read for some reason - where just regular public props are fast. This doesn’t matter really for instantiation… just something worth noting. I’ll probably post this in a snippet at some point but check it out:

    var t:Number;
    var i:int;
    var val:Number;
    var vars:Vars = new Vars();

    t = getTimer();
    for (i = 0; i<1000000; i++){
    val = i * vars.publicValue;
    }
    trace("public: ", getTimer() - t);

    t = getTimer();
    for (i = 0; i<1000000; i++){
    val = i * 30.0;
    }
    trace("hard coded: ", getTimer() - t);

    t = getTimer();
    for (i = 0; i<1000000; i++){
    val = i * Vars.CONST_VALUE;
    }
    trace("static const: ", getTimer() - t);

    /*
    public: 8
    hard coded: 8
    static const: 65
    */

    The Vars class just looks like this:

    package {
    public class Vars {

    public static const CONST_VALUE:Number = 30.0;

    public var publicValue:Number = 30.0;
    }
    }

    Thanks for the suggestions - I'll definitely think more about this ... I need to dig around Box2D to see where exactly the scale is set (forget at the moment)... some additional info here:

    http://www.box2d.org/manual.html#units

  5. Posted June 27, 2009 at 1:47 pm | Permalink

    the thing that makes it slow is the static part… not the const.. a public const seems to have the same read time as a regular public var.

  6. bart
    Posted June 28, 2009 at 12:31 pm | Permalink

    that’s interesting:
    well, in time critical code, you could still do:

    var w:Number = Vars.CONST_VALUE;
    t = getTimer();
    for (i = 0; i<1000000; i++){
    val = i * w;
    }

    Still, I think the numbers aren’t that dramatic, for one-million iterations…

  7. Posted June 28, 2009 at 6:08 pm | Permalink

    your right - it isn’t a huge difference…. it just bugs me - I believe they fixed this problem in haxe with the inline keyword.

    I’ll definitely have some variation on this in the next release…

  8. Posted June 28, 2009 at 8:00 pm | Permalink

    Quick question, how do i change the frame the ’skin’ is on?

    Thanks,
    Thomas Francis

  9. Posted June 28, 2009 at 8:05 pm | Permalink

    Hey Thomas,

    You can do that by using the QuickObject userData property. So given the above example you could do:

    var box:QuickObject = sim.addBox({x:3, y:3, width:3, height:3, skin:BoxSkin});
    box.userData.gotoAndStop(10);

    That should do it :)

  10. Posted June 28, 2009 at 8:13 pm | Permalink

    Great, Thanks.

    Another question/comment, When i skin a group, are the boxes that i drew supposed to stay visible?

  11. Posted June 28, 2009 at 8:30 pm | Permalink

    No prob.

    Looks like you found a bug in the GroupObject.as. I’m working on the library now so I’ll take a look and if its an easy fix I’ll post a link to the .as file here… should know in the next few mins :)

  12. Posted June 28, 2009 at 8:38 pm | Permalink

    Oh, cool. I’ll poke around with the files to see if I can fix it or not. But, i’ll probably grab the file you put up, if you do.

  13. Posted June 28, 2009 at 8:52 pm | Permalink

    Yeah… it was a simple fix. You can download the updated GroupObject.as file here:

    http://www.actionsnippet.com/source/GroupObject.as
    (just replace the old file in com.actionsnippet.qbox.objects)

    …and here is an fla describing how skinning should work with GroupObjects … basically sometimes you want the things your grouping to have individual skins and other times you want to use one skin for the entire group (the latter being what your doing):

    http://www.actionsnippet.com/source/skin_demo_group.fla

    I’ll update the actual zip tomorrow, keeping it as version 107.

  14. Posted June 28, 2009 at 9:02 pm | Permalink

    Wow, this is nice. Thanks. I will be watching this project, real good stuff.

    Is there a way to set a custom “stageWalls’ boundaries? I wanted to have some shapes falling in from the top of the swf, but making stage walls creates around the stage (no surprise there). Is there a way to do it with params in the createStageWalls function? or i do i need to create my own static objects?

    Thanks
    -Thomas

  15. Posted June 28, 2009 at 9:20 pm | Permalink

    you’ll need to create your own stage walls… you can copy the code from QuickBox2D.as and just remove the top box. This could be a cool feature though… something like:

    sim.createStageWalls({top:false});

    I’ll probably add that to the next release.

  16. Posted June 29, 2009 at 8:08 am | Permalink

    When I add multiple groups (through a for.. loop, or through a timer), I occasionally get some grey boxes [that make up the shape of the group, but they are all split apart and independent(as in they don't act as a group)] up at the top corner, in the stage origin. That’s probably a bug. I’ll probably post here if I find more weird things.

  17. Posted June 29, 2009 at 10:16 am | Permalink

    incase anyone is wondeirng… this bug has been resolved - you can either follow the instructions to manually update your QuickBox2D alpha 107 or just re-download the zip from the QuickBox2D page on this site.

  18. Posted July 7, 2009 at 10:38 am | Permalink

    Hi there,

    The current version of Quickbox2d, seems to not work with the current official release of box2D.

    Could you tell me which relesae of box2dflash you are building off of so I can download that version?

    Right now i’m using box2dflash version 2.02

  19. Posted July 7, 2009 at 9:06 pm | Permalink

    QuickBox2D Alpha 107 was done with Box2DFlashAS3 2.0.1… QuickBox2D Alpha 108 will be released in a few days….

  20. Posted July 8, 2009 at 2:00 pm | Permalink

    Hey Mario… i tested QuickBox2D 107 with Box2DFlash AS3 2.0.2 and it worked fine… maybe your classpath isn’t set up properly? What error are you getting… ?

  21. Posted August 6, 2009 at 3:24 pm | Permalink

    hi Zevan,

    first thx for your library QuickBox2d, i played with box2dAs3 few times ago and it wasn’t easy..

    so i test your library and it is very cool but i have just a little question/correction :

    in the ASDoc, you say:
    class QuickBox2D > gravity > “This can be changed during runtime.”

    but this lign doen’t works:
    “sim.gravity = new b2Vec2(0, 0);”

    i have to do:
    “sim.w.SetGravity(new b2Vec2(0, 0));”

  22. Posted August 6, 2009 at 3:27 pm | Permalink

    Thanks for pointing that out bertrand…. I’m going to release QuickBox2D alpha 108 tomorrow or saturday - and I’ll be sure to make sure this issue is taken care of.

  23. Posted August 19, 2009 at 7:37 pm | Permalink

    I’m having trouble having the skin show up on circles, any ideas?

  24. Posted August 20, 2009 at 7:28 am | Permalink

    If you upload your file I can take a look, off hand I can’t think of any reason that the circle skinning wouldn’t work… is your registration point centered?

  25. bbb
    Posted September 4, 2009 at 12:13 am | Permalink

    Hi, cool demo, I downloaded the fla and opened in both cs3 and cs4, in both versions the circles are invisible and dont show the graphic, but they can still be dragged etc…

  26. Posted September 4, 2009 at 10:24 am | Permalink

    @bbb …. oops, looks like I was messing with CircleObject and forgot to remove a comment.. you can fix the fla by going into the CircleObject.as file and changing this:

    if (p.skin is Class){
    /* bodyDef.userData = new p.skin();
    bodyDef.userData.width=p.radius * 60;
    bodyDef.userData.height=p.radius* 60;*/

    to this:

    if (p.skin is Class){
    bodyDef.userData = new p.skin();
    bodyDef.userData.width=p.radius * 60;
    bodyDef.userData.height=p.radius* 60;

    Sorry about that, I’m going to fix it in the zip of Alpha 108 now…

  27. mani
    Posted September 11, 2009 at 4:53 am | Permalink

    Hi - I’m having trouble skinning joints. Specifying a skin as a linked MovieClip in the Library gives me the following error: ReferenceError: Error #1056: Cannot create property startWidth on se.everyone.JointCable. This happens even if I define the joint as a distance joint, as instructed in the docs.
    Very grateful for any ideas! :)

  28. Posted September 11, 2009 at 5:12 am | Permalink

    I assume your skin is assocated with a class “se.everyone.JointCable” simply make the JointCable class dynamic and it should work for distance joints…. basically, because of the way that joints are skinned their skins must be dynamic:

    dynamic public class JointCable

    something like that…
    - this may be fixed/not required in the upcoming release of QuickBox2D… let me know if that helps

  29. mani
    Posted September 11, 2009 at 5:53 am | Permalink

    Thanks Zevan - Brilliant and amazingly fast response, I’m sorry I’d missed the fact it needed to be explicitly defined as dynamic. This now works. :)
    One other thing that may be obvious and which I’ll probably regret asking as I’ll look like a total noob, but I can’t work out how to specify depths for joints. At the moment, all my joints are under all my skinned objects - in other words, objects hanging in front of other objects have joints which are behind those other objects. Can depths be specified for joints just as for other DisplayObjects?
    Thanks again for the help!

  30. Posted September 11, 2009 at 6:01 am | Permalink

    That’s not a noob question, its tricky and something I’m trying to decide how to deal with… I think this should work:

    addChild(myJoint.userData);

    basically bring the joints skin up to the top…. ideally there should be some kind of option for this in the addJoint() method, but I haven’t created it yet… something like:

    var myJoint:QuickObject = sim.addJoint({skinDepth:”top”})… or somethign like that… need to decide what makes the most sense…

  31. mani
    Posted September 16, 2009 at 7:09 am | Permalink

    Hi Zevan - thanks again for all the help and the awesome Lib which is working really well! Great work indeed!
    Unfortunately I haven’t managed to solve this one problem, and I wonder if you have time to expand on what you thought might be a possible solution? I guess a lot of other things may take priority, but it would be neat to get joints that really visibly connect objects.
    Anyway, thanks again for the work so far! It really helps bring Flash to life!

2 Trackbacks

  1. [...] GroupとJointの使い方とかFRIM、任意の形を三角ポリゴンに分けてオブジェクトを作る、表示オブジェクトを切り替えるなどなど、おもしろい機能がたくさんあるので僕の勉強がてら書いていきます。 [...]

  2. [...] 10. リンケージされているテクスチャを貼る – QuickBox2D Skinning [...]

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*