PDA

Просмотр полной версии : [Box2D] Как правильно остановить шайбу после гола и переместить ее на исходную позицию


djyamato
26.08.2012, 22:10
Здравствуйте
Есть b2Body (b2CircleShape) это бита. Она управляется зажатой мышкой.
Есть шайба b2Body (b2CircleShape).
При попадании в ворота противника мне нужно остановить и переместить шайбу в центр игрового мира, остановить движение биты (если она по инерции все еще движется).

Для этого мне нужно:
1) остановить world.Step(...) ?
2) как остановить инерционное движение шайбы ?
3) как остановить инерционное движение биты ?
4) переместить шайбу washerBodyDef.position.Set(position) ?
5) запустить заново world.Step(...) ?

Или же будет правильнее эту шайбу удалять и заново создавать ?

caseyryan
26.08.2012, 22:24
Решал я как-то точно такую же задачу, когда делал хоккей на бокс2д.
1) остановить world.Step(...) ?
Нет. Этого делать не нужно вообще. Все просто замрет в том состоянии, в котором было на момент остановки.
Просто остановить шайбу без костылей не получится. Это все-таки физический движок.
Я просто применял к ней импульс противоположный ее скорости. Это останавливало шайбу, но не давало совсем уж нужного эффекта. Еще один способ - поменять на время шага тип тела шайбы на статический. Это ее сразу же остановит. Но и тут есть загвоздка. Это нужно делать перед вызовом Step() так как непосредственно после вызова шага мир будет закрыт до его завершения, и все эти телодвижения будут бессмысленными.

Или же будет правильнее эту шайбу удалять и заново создавать ?
Можно и так. Но на это будет тратиться еще больше ресурсов. Хотя от одной шайбы производительность явно не упадет. Так что, возможно, этот вариант тоже стоит рассмотреть.

djyamato
26.08.2012, 22:47
Нет. Этого делать не нужно вообще. Все просто замрет в том состоянии, в котором было на момент остановки.
Ну, это не проблема, я покажу скрин со счетом, а после выставлю все объекты на исходные позиции

Спасибо, интересные варианты
Как раз думал о удалении, но засада получалась с заново созданной шайбой (ошибка)


// создание шайбы
protected function createWasher():void
{
washerBodyDef = new b2BodyDef();
washerBodyDef.userData="washer";
washerBodyDef.type = b2Body.b2_dynamicBody;

washerShape = new b2CircleShape(30 / physicsModel.pixelsPerMeter);
//var circShape:b2CircleShape = new b2CircleShape(3);
washerFixtureDef = new b2FixtureDef();
washerFixtureDef.shape = washerShape;
washerFixtureDef.density = .1;
washerFixtureDef.friction = .1;
washerFixtureDef.restitution = .6;
washerBodyDef.position.Set(PhysicsHelper.stage.stageWidth/2 / physicsModel.pixelsPerMeter, PhysicsHelper.stage.stageHeight/2 / physicsModel.pixelsPerMeter);
washerBody = world.CreateBody(washerBodyDef);
washerBody.CreateFixture(washerFixtureDef); // строка 208
}
// удаление шайбы
protected function removeWasher():void
{
bodyesToRemove.push(washerBody);

if(pm.mouseJoint)
{
pm.mouseJoint.SetTarget(null);
world.DestroyJoint(pm.mouseJoint);
pm.mouseJoint = null;
}
}

// --- ГОЛ !!!
[EventHandler(event="PhysicsContactEvent.CONTACT_BEGIN",properties="data")]
public function contactBeginHandler(data:String):void
{
switch(data)
{
case "opponentGoal":
trace("ГОЛ ОППОНЕНТУ - нужно удалить шайбу и заново создать");
removeWasher();
createWasher();
break;
case "userGoal":
trace("USER GOAL");

break;
}
}
// обновление мира
private function enterFrameHandler(event:Event = null):void
{
if(bodyesToRemove.length>0)
{
for(i=0;i<bodyesToRemove.length;i++)
{
world.DestroyBody(bodyesToRemove[i]);
}
for(i=0;i<bodyesToRemove.length;i++)
{
bodyesToRemove.pop();
}
}

updateMouseJoint();
world.Step(physicsModel.timestep, physicsModel.velocityIterations, physicsModel.positionIterations);
world.ClearForces();
world.DrawDebugData();

updateAssetsPositions();
}

Вот такая ошибка вылетает

TypeError: Error #1009: Не удается вызвать свойство или метод со ссылкой на объект "null".
at swiz.controllers::PhysicsController/createWasher()[D:\flex 4.6\AeroHockey_2\src\swiz\controllers\PhysicsController.as:208]

При новом создании шайбы она возникает
Возможно, после удаления (в обновлении мира) нужно остановить это самое обновление, создать шайбу и заново запустить обновление ?

Я хотел бы еще один вопрос задать как раз про хоккей.
А как Вы двигали биту, при нажатии или нет ?
Я хотел бы чтобы без нажатия бита двигалась за мышкой моментально.
Это мне просто нужно назначать

pm.mouseXWorldPhys=PhysicsHelper.stage.mouseX/physicsModel.pixelsPerMeter;
pm.mouseYWorldPhys=PhysicsHelper.stage.mouseY/physicsModel.pixelsPerMeter;
var mousePVec:b2Vec2=new b2Vec2(pm.mouseXWorldPhys,pm.mouseYWorldPhys);
userStickBody.SetPosition(mousePVec);

?
или все-таки с джоинтами нужно это делать ?

..............
вот как заработало:
в обновлении мира если есть объекты для уничтожения я удяляю их, останавливаю обновление мира, создаю шайбу и стартую обновление мира

caseyryan
27.08.2012, 07:31
А как Вы двигали биту, при нажатии или нет ?
У меня был настольный хоккей. Там были хоккеисты крутящиеся вокруг своей оси, и управлялись с клавиатуры. Мышкой вариант интересный, но я его не пробовал.
Вот такая ошибка вылетает
У вас типичная ошибка, которую допускают многие. И я на нее натыкался.
Цикл движется в сторону увеличения индекса (второй цикл), а длина массива сокращается. Естественно он быстро наткнется на объект null. Для удаления тел используйте цикл while

while (bodyesToRemove.length) {
world.DestroyBody(bodyesToRemove[0]);
bodyesToRemove.shift();
}

djyamato
27.08.2012, 12:23
ясно, спасибо большое
Правда, ошибка была не при удалении объектов в цикле, а при создании новой биты или шайбы уже после того как все удалено.
Про while это верно, признаться, никогда не использую его, а зря.