Как захватить b2Body и перемещать его по экрану? (кокос2д, бокс2д, айфон)

Я хочу перемещать любое b2body, к которому прикасаются на экране, по экрану. Я что-то слышал о мышиных суставах..

Я обнаружил, что: http://iphonedev.net/2009/08/05/how-to-grab-a-sprite-with-cocos2d-and-box2d/

но я просто получаю много ошибок, если просто скопирую методы ccTouch в новый проект (конечно, переменные в заголовке тоже). Например. мир->Запрос ‹- УЧАСТНИК НЕ НАЙДЕН

Может кто-нибудь сделать tut/новый проект и загрузить его сюда. Или есть лучший способ?


person cocos2dbeginner    schedule 12.03.2011    source источник


Ответы (1)


Сначала вам нужно создать подкласс b2QueryCallback:

class QueryCallback : public b2QueryCallback
{
public:
    QueryCallback(const b2Vec2& point)
    {
        m_point = point;
        m_object = nil;
    }

    bool ReportFixture(b2Fixture* fixture)
    {
        if (fixture->IsSensor()) return true; //ignore sensors

        bool inside = fixture->TestPoint(m_point);
        if (inside)
        {
             // We are done, terminate the query.
             m_object = fixture->GetBody();
                 return false;
        }

        // Continue the query.
        return true;
    }

    b2Vec2  m_point;
    b2Body* m_object;
};

Затем в вашем методе touchBegan:

    b2Vec2 pos = yourTouchPos;
// Make a small box.
b2AABB aabb;
b2Vec2 d;
d.Set(0.001f, 0.001f);
aabb.lowerBound = pos - d;
aabb.upperBound = pos + d;

// Query the world for overlapping shapes.
QueryCallback callback(pos);
world_->QueryAABB(&callback, aabb);         

b2Body *body = callback.m_object;
if (body)
    {
        //pick the body
    }

Я вижу два способа управлять выбранным телом. Первый, как вы заметили, - создать mouseJoint, а второй - сделать ваше тело кинематическим и контролировать его скорость (не положение! - это обеспечит нефизическое поведение при столкновении, потому что скорость будет равна нулю). В первом случае, если вы будете перемещать свои объекты очень быстро, при перемещении будет некоторая задержка. Второй способ я сам не пробовал, потому что в этом случае тело не будет сталкиваться с другими кинематическими и статическими телами.

Также вы можете захотеть заблокировать вращение тела при движении.

person Andrew    schedule 12.03.2011
comment
+1 попробую позже, потому что сейчас у меня нет Mac - person cocos2dbeginner; 12.03.2011
comment
@cocos: b2World хранит все указатели на тела. Таким образом, вы можете перебирать их и делать их тип кинематическим. В пункте 6.2 руководства box2d говорится, что статические тела никогда не сталкиваются, но ничего не говорится о кинематике. На самом деле я не знаю, но я предполагаю, что они не могут, потому что физическое поведение не определено. Но вы можете создать свой собственный класс, который будет привязывать динамическое тело (на самом деле датчик) к вашей кинематике (с той же формой) и проверять, сталкиваются ли эти тела. Не уверен, что это лучший способ - person Andrew; 12.03.2011
comment
@cocos: я не могу. Это просто идея. Я никогда не пробовал это сам. Я бы попытался установить скорость тела как vel = cft*diff(fingerPos, bodyPos) - person Andrew; 12.03.2011
comment
@cocos: mouseJoint (или любой другой) не будет работать с кинематическими или статическими телами, потому что при решении используются силы. Но силы нельзя прикладывать к нединамическим телам - person Andrew; 12.03.2011
comment
поэтому я пробую это: pastie.org/1663732, но проблема в том, что после перемещения нет гравитации тело.. - person cocos2dbeginner; 12.03.2011
comment
@cocos: вы должны сделать свое тело динамичным после того, как освободите его от прикосновения. Гравитация — это сила, и она также применяется только к динамическим телам. - person Andrew; 12.03.2011
comment
@Andrew Есть только одна проблема (после этого все будет работать нормально (надеюсь): как вы знаете из кода на pasteie.org, я использую набор преобразований для перемещения тел. Это означает, что каждый раз, когда я касаюсь тела ( скажем в левом нижнем углу корпуса) якорная точка его моментально переходит на мое касание.. хм.. не здорово. Вы такой добрый и не могли бы изменить код, чтобы он работал лучше. (вы что-то сказали со скоростью..setlinearvelocity ??).Спасибо!И напоследок: Вы гений, спасибо, что помогли разобраться, как двигать тело (кинематическое....). СПАСИБО! :) - person cocos2dbeginner; 12.03.2011
comment
@cocos: Если вы будете перемещать тело с помощью setTransform для box2d, его скорость все равно будет равна нулю. А при столкновении с ним другие тела будут отскакивать некорректно (как от статичного тела (с нулевой скоростью)). Если вы будете контролировать скорость вместо позиции, физика будет работать нормально. Насчет точки привязки - единственный способ - держать точку первого касания пальцем относительно тела и использовать при управлении. anchorPoint = fingerPosition - bodyPosition. Затем, когда ваше касание перемещается, обновите его pos: anchoredTouch = touch + anchorPoint - person Andrew; 12.03.2011
comment
Можете ли вы показать мне код? Как сделать так, чтобы касанием пальца относительно тела?? Извините, я знаю, что вы думаете. Какой глупый парень!?... Я новичок.. - person cocos2dbeginner; 12.03.2011
comment
@Andrew pastie.org/1663923 это странно....если я пошевелю пальцем :/ Знаете что неправильный? - person cocos2dbeginner; 12.03.2011
comment
@cocos: вы снова оцениваете anchorPoint в своем коде touchMoves. Тебе не следует. Вы должны оценить это один раз, когда касаетесь тела (это точка на теле, к которой прикоснулись). Вы должны сделать что-то вроде этого: newLocation = location + anchorPoint (или минус, возможно - попробуйте) - person Andrew; 12.03.2011
comment
ОК ... я также нашел опечатку .. теперь все работает отлично !! Спасибо Андрей! Я так рад - person cocos2dbeginner; 12.03.2011