box2d: Как помешать персонажу прыгать в воздухе? - PullRequest
1 голос
/ 18 апреля 2011

Итак, я играл с box2d на iOS (думал, что этот вопрос не ограничивается iOS), и у меня есть небольшая демонстрация, где персонаж игрока прыгает, когда пользователь нажимает на экран через ApplyLinearImpulse.

По большей части это работает.За исключением случаев, когда я нажимаю, когда игрок находится в воздухе, снова вызывается ApplyLinearImpulse, и игрок снова «прыгает», но в воздухе.Теперь было бы неплохо сделать это в реальной жизни, но вы не можете, и я бы предпочел, чтобы мой игрок тоже не смог этого сделать.

Так что я пытался прийтиприличный способ предотвратить прыжки, когда игрок уже прыгает, и я не уверен, куда идти дальше - моя лучшая мысль - попробовать что-то вроде этого:

  • Прикрепите тело, котороеэто просто датчик в нижней части моего игрока с фиксированным соединением.
  • Когда игрок прыгает, отключайте прыжки, пока вышеупомянутый датчик не обнаружит столкновение (то есть, когда игрок "приземляется" на что-то, что может илиможет не быть землей).
  • Как только столкновение будет обнаружено, включите прыжки.

Я не уверен, насколько мне нравится эта идея, например, яЯ не уверен, что прикрепление датчика к нижней части моего плеера - это «самый умный» способ обнаружения столкновений в нижней части спрайта моего плеера.Я еще не попробовал, вместо этого я хотел получить информацию от SO и посмотреть, сможет ли кто-нибудь предложить лучшую альтернативу.Есть идеи?

Редактировать: У mafutrct было хорошее предложение: попробуйте какой-нибудь тест на попадание вниз, используя луч прямо вниз от тела моего игрока, и посмотрите, пересекает ли этот луч другой объект внутрина небольшом расстоянии (т. е. прямо под моим плеером) - возможен ли такой тип проверки попадания лучей с box2d?

Ответы [ 3 ]

5 голосов
/ 14 июля 2011

Мой голос идет по методу «датчик у ног игрока». Если вы действительно хотите проверить тип луча, вы можете сделать сенсорным прибором ребро, но в целом я думаю, что более полезно иметь возможность указывать область, особенно если ваш персонаж сможет стоять на нескольких предметах одновременно, и если вы заинтересованы в ведении актуального списка того, что стоит на. Если вы создаете тело игрока в графическом редакторе, то будет также более интуитивно понятно разместить и посмотреть на датчик, вместо того, чтобы запускать его все программно с помощью радиопередач. Я полагаю, что метод датчика стопы также требует меньших затрат на процессор и меньше работы, чем самостоятельная проверка с помощью raycast. Я написал подробный урок об этом, надеюсь, он будет полезен: http://www.iforce2d.net/b2dtut/jumpability

3 голосов
/ 18 апреля 2011

Вам нужно проверить, касаются ли ступни земли в момент прыжка.

В зависимости от модели измерьте расстояние между ногами и землей. Либо примените вектор из центра модели и проверьте наличие вершины, либо (более сложный) проверьте наличие первого вертикального удара многоугольника, описывающего область ваших ног с землей.

Простая проверка на любое столкновение не удалась, так как вы можете прыгнуть на стену, которая все еще считается воздушной (если вы не играете в Unreal Tournament, в котором это прыжок на стену).

Хотя я не знаком с вашим программным обеспечением, так что это всего лишь идея - было бы здорово, если бы это действительно помогло. Удачи:)

2 голосов
/ 13 мая 2011

Способ решения этой проблемы заключается в создании класса, который реализует ContactListener, а затем, когда вы создаете World, вы .setContactListener () для своего класса.Теперь ваш класс будет уведомлен обо всех столкновениях.Оттуда вы создаете флаг, если игрок контактирует с какими-либо наземными объектами.

Предположим, что вы установили userData фигур для соответствующих GameObjects (shapeDef.userData = this; в конструкторе GameObject).Предположим, у вас есть enum, который определяет типы GameObject в вашей игре, а затем у вас есть контактный слушатель по следующим направлениям:

import org.jbox2d.dynamics.ContactListener;
import org.jbox2d.dynamics.contacts.ContactPoint;
import org.jbox2d.dynamics.contacts.ContactResult;
import android.util.Log;

import GameObject.GAME_OBJECT_TYPE;

public class CollisionChecker implements ContactListener {

    private boolean groundCollision = false;

    @Override
    public void add(ContactPoint arg0) {
        // Called when a contact point is added. This includes the geometry and the forces.
    }

    @Override
    public void persist(ContactPoint arg0) {
        // Called when a contact point persists. This includes the geometry and the forces.
    }

    @Override
    public void remove(ContactPoint arg0) {
        // Called when a contact point is removed. This includes the last computed geometry and forces.
    }

    @Override
    public void result(ContactResult arg0) {
        // This is called once the collision has been resolved 

        GAME_OBJECT_TYPE a = ((GameObject) arg0.shape1.getUserData()).getType();
        GAME_OBJECT_TYPE b = ((GameObject) arg0.shape2.getUserData()).getType();
        //check for ground
        groundCollision = check(a, b, GAME_OBJECT_TYPE.ground);
    }

    private boolean check(GAME_OBJECT_TYPE a, GAME_OBJECT_TYPE b, GAME_OBJECT_TYPE test){
        if (a == test && b == GAME_OBJECT_TYPE.player){
            return true;
        }
        else if (a == GAME_OBJECT_TYPE.player && b == test){
            return true;
        }
        return false;
    }

    public boolean isGroundCollision(){
        return groundCollision;
    }

    public void step() {
        /*
        if (groundCollision)
            Log.d("COLLSN", "We have a collision with ground");*/
        //after logic, reset the state variables
        reset();
    }

    private void reset(){
        groundCollision = false;
    }
}

Теперь вы создаете логический переход в вашем плеере.Когда он прыгает, установите его в true.Он больше не может прыгать, когда флаг верен.Проверьте каждый кадр на столкновение с землей с помощью collisionChecker.isGroundCollision ().Когда происходит столкновение, снова установите player.jump = false.

Здесь есть проблема, заключающаяся в том, что если у вас вертикальное основание, игрок сможет прыгнуть через стену.Если игрок ударит его головой о землю, он также сможет прыгать больше.Для решения этих проблем вы проверяете «arg0.position», чтобы узнать, где была точка контакта относительно объекта игрока.Если контакт не находится под игроком, то он бьет себя по голове или бьет по стене.

...