QuickBox2D groupIndex Platforms

Actionscript:
  1. import com.actionsnippet.qbox.*;
  2. import Box2D.Common.Math.*;
  3. import Box2D.Collision.Shapes.*;
  4.  
  5. [SWF(width = 800, height = 600, backgroundColor = 0x000000)]
  6.  
  7. var sim:QuickBox2D = new QuickBox2D(this);
  8.  
  9. sim.createStageWalls();
  10.  
  11. var boxNum:int = 8;
  12. var boxes:Array = [];
  13. var xp:Number, yp:Number, w:Number;
  14. for (var i:int = 0; i<boxNum; i++){
  15.     xp = 3 + Math.random() * 10;
  16.     yp = 4 + i * 2;
  17.     w = 2 + Math.random() * 3;
  18.     boxes.push(sim.addBox({x: xp, y: yp, width: w, height: 0.5, density:0, groupIndex:-1, fillColor:0xFF6532}));
  19. }
  20.  
  21. var char:QuickObject = sim.addBox({x:2, y:18, width:1, height:2, allowSleep:false, groupIndex:-1, fillColor:0x0099CC});
  22.  
  23. sim.start();
  24.  
  25. var charVel:b2Vec2;
  26. var charVelAng:Number;
  27.  
  28. addEventListener(Event.ENTER_FRAME, onLoop);
  29. function onLoop(evt:Event):void {
  30.      
  31.     charVel = char.body.GetLinearVelocity();
  32.     charVelAng =  char.body.GetAngularVelocity();
  33.     var filter:b2FilterData;
  34.    
  35.     if (key[Keyboard.RIGHT]){
  36.         charVel.x += 1
  37.         char.body.SetLinearVelocity(charVel);
  38.         charVelAng += 1;
  39.         char.body.SetAngularVelocity(charVelAng);
  40.     }
  41.     if (key[Keyboard.LEFT]){
  42.         charVel.x -=1;
  43.         char.body.SetLinearVelocity(charVel);
  44.         charVelAng -= 1;
  45.         char.body.SetAngularVelocity(charVelAng);
  46.     }
  47.     if (key[Keyboard.UP] && sim.w.GetContactCount()> 0){
  48.          charVel.y = -10;
  49.          trace(charVel.y);
  50.          char.body.SetLinearVelocity(charVel);
  51.          charVelAng *= 0.8;
  52.          char.body.SetAngularVelocity(charVelAng);
  53.     }
  54.     for (var i:int = 0; i<boxes.length; i++){
  55.         var rect:Rectangle = char.userData.getRect(this);
  56.         if (rect.bottom / 30 <boxes[i].y){
  57.             filter = boxes[i].shape.GetFilterData();
  58.             filter.groupIndex = 1;
  59.             boxes[i].shape.SetFilterData(filter);
  60.         }else{
  61.             filter = boxes[i].shape.GetFilterData();
  62.             if (filter.groupIndex != -1){
  63.                 filter.groupIndex = -1;
  64.                 boxes[i].shape.SetFilterData(filter);
  65.             }
  66.         }
  67.     }
  68. }
  69.  
  70. var key:Object = new Object();
  71. stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyPressed);
  72. stage.addEventListener(KeyboardEvent.KEY_UP, onKeyReleased);
  73. function onKeyPressed(evt:KeyboardEvent):void{ key[evt.keyCode] = true; }
  74. function onKeyReleased(evt:KeyboardEvent):void{ key[evt.keyCode] = false; }

NOTE: This requires the QuickBox2D mini-library

This snippet shows how to use groupIndex to create simple platforms for a character to jump on. A few people have asked me about this so I figured I'd post about it. It works by altering the groupIndex of each platform based on the characters position - if the character is below a platform, both the character and the platform have groupIndex -1 (meaning they will not collide). As soon as the character is above a platform, the platforms groupIndex is set to 1 (allowing the character to walk on the platform despite having just passed through it.


Have a look at the swf...


It's also worth noting that I'm using b2World.GetContactCount() to make sure it's ok to jump... if there were more going on in the demo you'd need to check a specific contact point(s), but since the only collision that could happen involves the character this works nicely...

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

9 Comments

  1. Posted September 4, 2009 at 12:00 pm | Permalink

    very cool - nice work.

  2. Posted September 4, 2009 at 12:10 pm | Permalink

    thanks

  3. Posted September 5, 2009 at 3:54 pm | Permalink

    Nice, been wondering how to do this.
    Thanks!

  4. Hugo
    Posted September 20, 2009 at 3:57 am | Permalink

    Hi, first of all great work on QuickBox2D, its a great lib for those starting to play with Box2D.

    I’m having an issue however, with an experiment I’m working on… I have a box that will work like a “zone”, this has density 0 so its stopped and then I have a circle which is moving. When they collide I need to catch that event BUT the catch is that I need the circle to overlap / go through the “zone” box instead of bouncing off of it. Any insight into how I can accomplish this?

    Thanks and keep up the good work.

  5. Posted September 20, 2009 at 9:11 am | Permalink

    Hey Hugo,

    Decided to answer your question with a post… check it out:

    http://actionsnippet.com/?p=2218

  6. Hugo
    Posted September 21, 2009 at 8:39 am | Permalink

    Hi Zevan!

    Thanks a lot for the quick reply, I tried your direction and it does indeed work and I’ll most likely use it in the near future on something else but it doesnt solve this specific problem.

    I appologize if I didnt explain myself better but I’ll try to do so now. Lets imagine a game where there are several balls and also a “Win Zone”, this zone is nothing more then a rectangle which is a space where the balls “might” fall into (and be contained in). Now, the balls can collide with eachother but they cant collide with the “Win Zone” because this is a transparent rectangle.

    First off I tried with the win zone being just a thin layer on the game’s floor but the problem is that the balls that “Win” can stack up on top of each other and therefor prevent new balls from “touching” the ground and triggering the event.

    I think a good analogy would be a cup, lets say that each ping pong ball that you manage to get into the cup awards you a point. You could make the bottom of the cup trigger the score but after a couple balls the bottom of the cup would be unreachable so the win zone should be an imaginary space that represents the cup’s inside.

    Anyway, thanks again for your reply it I’ll try to figure a workaround for this, just thought someone with a way better insight into Box2D then me could know an easy fix.

  7. Hugo
    Posted September 21, 2009 at 9:00 am | Permalink

    Nevermind, I looked at the code for the class you wrote and made a small change.

    Basically the balls dont have a groupIndex set but the “zone” has a groupIndex of -1 and I changed the for loop you wrote to:

    // only difference between default Box2D behavior
    for (var i:int = 0; i < indices.length; i++) {
    var index:int = indices[i];
    if (filter1.groupIndex == -1 || filter2.groupIndex == -1) {
    callbacks[i](shape1, shape2);
    return false;
    }
    }
    // –

    The balls collide themselves but not with the zone and the event still triggers. I know this id probably not the best way around the problem but it works and it wont present any problems somewhere else this specific game since I dont need any other groupindex to be set.

    Thanks once again, love QuickBox2D :)

  8. Andrew
    Posted February 24, 2010 at 2:24 pm | Permalink

    This is very nice, but I’m having some problems. I get an error 1006 with GetFilterData, my code thus far:

    package {
    import flash.display.MovieClip;
    import com.actionsnippet.qbox.*;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import com.greensock.TweenLite;
    import Box2D.Common.Math.*;
    import Box2D.Common.*;
    import Box2D.Collision.Shapes.*;

    public class err extends MovieClip {
    public var myArray:Array;
    public var switcher:Number;
    public var _index:b2FilterData;
    public var sim:QuickBox2D;

    public function err():void {
    sim = new QuickBox2D(this);
    butt.addEventListener(MouseEvent.MOUSE_DOWN, gravitySwitch);
    switcher = 2;
    sim.start();
    sim.mouseDrag();
    init();
    }

    public function init():void {
    myArray = [pic1, pic2, pic3, pic4];
    stage.frameRate = 60;
    sim.createStageWalls({width:1, fillColor:0×000000, lineAlpha:0});

    for each (var i:MovieClip in myArray) {
    sim.addBox( { friction:0.5, skin:i, groupIndex:_index } );
    }
    }

    public function gravitySwitch(e:Event):void {
    if (switcher == 0) {
    switcher = 2;
    sim.gravity.y = switcher;
    collOn();
    sim.stop();
    sim.start();
    TweenLite.to(butt, 0.25, { rotationZ: 0 } );
    }
    else if (switcher == 2) {
    _index = myArray.GetFilterData();
    switcher = 0;
    sim.gravity.y = switcher;
    collOff();
    sim.stop();
    sim.start();
    TweenLite.to(butt, 0.25, { rotationZ: -45 } );
    }
    }

    public function collOn():void {
    _index = myArray.Shape.GetFilterData();
    _index.groupIndex = 0;
    myArray.Shape.SetFilterData(_index);
    }

    public function collOff():void {
    _index = myArray.Shape.GetFilterData();
    myArray.groupIndex = -1;
    myArray.Shape.SetFilterData(_index);
    }

    }
    }

    I basically want to switch collisions on and off at will. :)

  9. Posted January 19, 2011 at 12:11 pm | Permalink

    Hello Zevan, i would like to ask you what we should do to the char(box) dont jump when it collides with the walls.

    Note that you can jump to the highest plataform withou jump in the anothers, only using the wall.

    Thanks a lot. You’re great.

One Trackback

  1. [...] 19. 衝突判定の有無をを動的に切り替える – QuickBox2D groupIndex Platforms [...]

Post a Comment

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

*
*