Двухмерные проблемы обнаружения столкновений на основе плитки - PullRequest
0 голосов
/ 11 февраля 2011

Я пытаюсь следовать этому уроку http://www.tonypa.pri.ee/tbw/tut05.html для реализации столкновений в реальном времени в мире на основе тайлов.

Я нахожу координаты центра моих объектов благодаря этим свойствам:

public float CenterX
{
    get { return X + Width / 2f; }
    set { X = value - Width / 2f; }
}
public float CenterY
{
    get { return Y + Height / 2f; }
    set { Y = value - Height / 2f; }
}

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

public override void Update()
{
    base.Update();

    int downY = (int)Math.Floor((CenterY + Height / 2f - 1) / 16f);
    int upY = (int)Math.Floor((CenterY - Height / 2f) / 16f);
    int leftX =     (int)Math.Floor((CenterX + Speed * NextX - Width / 2f) / 16f);
    int rightX = (int)Math.Floor((CenterX + Speed * NextX + Width / 2f - 1) / 16f);

    bool upleft = Game.CurrentMap[leftX, upY] != 1;
    bool downleft = Game.CurrentMap[leftX, downY] != 1;
    bool upright = Game.CurrentMap[rightX, upY] != 1;
    bool downright = Game.CurrentMap[rightX, downY] != 1;

    if(NextX == 1)
    {
        if (upright && downright)
           CenterX += Speed;
        else
           CenterX = (Game.GetCellX(CenterX) + 1)*16 - Width / 2f;
    }
 }

downY, upY, leftX и rightX должны соответственно найти самую низкую позицию Y, самую высокую позицию Y, крайнюю левую позицию X и крайнюю правую позицию X. Я добавляю + Speed ​​* NextX, потому что в учебнике вызывается функция getMyCorners со следующими параметрами:

getMyCorners (ob.x+ob.speed*dirx, ob.y, ob);

Методы GetCellX и GetCellY:

public int GetCellX(float mX)
{
    return (int)Math.Floor(mX / SGame.Camera.TileSize); 
}
public int GetCellY(float mY)
{
    return (int)Math.Floor(mY / SGame.Camera.TileSize); 
}

Проблема заключается в том, что игрок «мерцает» при ударе о стену, и обнаружение углов даже не работает должным образом, поскольку оно может перекрывать стены, которые поражают только один из углов. Я не понимаю, что не так. В учебнике поля ob.x и ob.y должны быть такими же, как мои свойства CenterX и CenterY, а ob.width и ob.height должны совпадать с Width / 2f и Height / 2f. Однако это все еще не работает.

Спасибо за вашу помощь.

Ответы [ 2 ]

1 голос
/ 11 февраля 2011

РЕДАКТИРОВАТЬ - Ой, ты прав.CenterX - это пиксельная координата, которую GetCellX преобразует в координату тайла, поэтому код эквивалентен.За ним действительно особенно трудно следить.

В этот момент я начинаю думать, что у нас недостаточно информации, чтобы ответить на ваш вопрос.Вот несколько идей:

Является ли скорость целым числом?Ваши координаты целые числа?Похоже, что можно передать 0,5 пикселя в стену без столкновения, но когда вы передадите 1,0 пикселя, вы вернетесь назад.Если скорость и координаты - это целые числа, которые не произойдут, как я предполагаю, что учебник работает, но если какие-то дроби попадают в него, то вы можете увидеть некоторое дрожание.()?Когда происходит рендеринг?Перемещает ли что-нибудь плеер между вызовами в Update ()?

Как отображается карта и игрок?Возможно ли, что они случайно оказываются в неправильном месте относительно друг друга?Я не думаю, что это может вызвать проблемы с мерцанием, но это может усугубить проблему обнаружения столкновений, иногда пропуская вас.сам по себе: довольно сложно понять, что он должен делать.Там, где у вас есть (Game.GetCellX(CenterX) + 1)*16 - Width / 2f, учебник имеет (ob.xtile+1)*game.tileW-ob.width.Это разные.Учебник берет индекс плитки, добавляет один, чтобы переместить следующую плитку, затем преобразует в координату x.Ваш код берет индекс плитки, преобразует в координату х, а затем добавляет один пиксель.Это, по крайней мере, частично ответственно за ваше мерцание.

1 голос
/ 11 февраля 2011

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

   if(input == "right" && !(Tile.right.collidable))
    {
        //vector.speed = {1, 0, 0};
    }
else
{
//vector.speed = {0, 0, 0};
}


Возможно, не совсем так, но я надеюсь, что это поможет. Приветствия ~

...