deltaluca / nape

Haxe/AS3 Physics Engine
http://napephys.com
Other
542 stars 77 forks source link

Space clear() don't clear compounds? #90

Open T1mL3arn opened 9 years ago

T1mL3arn commented 9 years ago

I make a car that consist from several bodies, suspensions(distance and line joints) and motors added in one compound. In game process suspensions can be broken down and I need to reset the level. So I clear space and rebuild level. But here we go! If all bodies is sleep before clearing, I get null-errors sometimes , sometimes I get "assert("+"cbsets.empty()"+") :: "+("space cleared, called setmanager clear(), and tree was non-empty. wuh" and other asserts (with NAPE_ASSERT flag).

I tried to isolate error and make a demo. I have two bodies added into one compound and this compound added into space. After the bodies were asleep I clearing space and adding compound to it again. And I got the error:

TypeError: Error #1009: Cannot access a property or method of a null object reference.
    at zpp_nape.space::ZPP_DynAABBPhase/broadphase()[C:\HaxeToolkit\nape\2,0,16\zpp_nape\space\DynAABBPhase.hx:1841]
    at zpp_nape.space::ZPP_Space/step()[C:\HaxeToolkit\nape\2,0,16\zpp_nape\space\Space.hx:3029]
    at nape.space::Space/step()[C:\HaxeToolkit\nape\2,0,16\nape\space\Space.hx:508]
    at Main/onFrame()[C:\prog_projs\haxe\Openfl_Bug_fixes\NapeSpaceClearBugDemo\src\Main.hx:227]

If I clear the space before the bodies were asleep no errors is happening. And if I make compound.space = null before space.clear() no errors is happening.

Sample code:

function init() 
{
    space = new Space(Vec2.weak(0, 450));
    debug = new ShapeDebug(stage.stageWidth, stage.stageHeight);
    debug.drawBodies = true;
    debug.drawConstraints = true;
    this.addChild(debug.display);

    compound = new Compound();
    stage.addEventListener(Event.ENTER_FRAME, onFrame);
    stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
}
private function onKeyUp(e:KeyboardEvent):Void 
{
    if (e.keyCode == Keyboard.NUMBER_3)
        compound.space = null;

    space.clear();
    space.gravity.setxy(0, 450);

    var w = stage.stageWidth;
    var h = stage.stageHeight;

    createRectBody(0, 0, 1, h, BodyType.STATIC).space = space;  // left
    createRectBody(0, 0, w, 1, BodyType.STATIC).space = space;  // top
    createRectBody(w, 0, 1, h, BodyType.STATIC).space = space;  // right
    createRectBody(0, h, w, 1, BodyType.STATIC).space = space;  // bottom

    if (e.keyCode == Keyboard.NUMBER_1)
    {
        compound = new Compound();

        var body = createRectBody(w / 2, h / 2, 50, 50, BodyType.DYNAMIC).align();
        body.compound = compound;

        var wheel = createRectBody(w / 2, h / 2+60, 40, 40, BodyType.DYNAMIC).align();
        wheel.compound = compound;

        compound.space = space;
    }
    else if (e.keyCode == Keyboard.NUMBER_2 || e.keyCode == Keyboard.NUMBER_3)
    {
        compound.space = space;
        compound.translate(Vec2.weak(0, -50));
    }
}
function createRectBody(x:Float, y:Float, w:Float, h:Float, type:BodyType):Body
{
    var body = new Body(type);
    body.shapes.push(new Polygon(Polygon.rect(x, y, w, h, true)));
    return body;
}
private function onFrame(e:Event):Void 
{
    space.step(1 / 60, 25, 25);

    debug.clear();
    debug.draw(space);
    debug.flush();
}

Press 1 to create objects, press 2 after the bodies were asleep to simulate error, and press 3 to avoid error.

And maybe I don't understand how the compound works? And it is normal that I need to manually iterate over all compounds in the space to set their space property to null ?

PS: sorry for my English.