Войти
Box2DФорумОбщее

Перемещение персонажа

Страницы: 1 2 Следующая »
#0
15:09, 5 ноя. 2013

По идее замусоленная тема, но видимо я гуглить не умею. В общем нужно организовать перемещение персонажа(пусть будет марио-стайл). Вполне ожидаемо, что если по нажатию клавиш делать applyForce или applyLinearImpulse, то при отпускании клавиш персонаж продолжит движение. Вопрос в том как сделать так, чтобы персонаж останавливался при отпускании клавиши движения. Применять к нему обратный импульс/силу или же сбрасывать скорость или еще что-то?

п.с. я конечно нагуглил кое что интересное, но хотелось бы узнать, а нет ли более простого решения, которое позволит сделать это силами Box2d, без добавления своей логики.


#1
15:42, 5 ноя. 2013

angru
> Применять к нему обратный импульс/силу или же сбрасывать скорость или еще что-то?
Ничего не применять, пусть трение его тормозит.

#2
15:49, 5 ноя. 2013

хм, совсем забыл про этот вариант, поэтому решил, что можно в описании задачи упростить до "марио стайл", но у меня TDS, так что персонажу тереться не обо что. прошу прощения, что ввел в заблуждение.

#3
16:08, 5 ноя. 2013

angru
> но у меня TDS,
Tower defense?
Можешь прикладывать с обратным знаком силу,  пропорциональную текущей скорости. Будет влобно реализованное трение.
Ну или да, как в том примере прикладываешь некоторую силу, которая изменит текущую скорость в сторону желаемой, не превышая каких-то ускорений.

#4
16:30, 5 ноя. 2013

RPGman
> Tower defense?
Top Down Shooter

> Можешь прикладывать с обратным знаком силу, пропорциональную текущей скорости. Будет влобно реализованное трение.
т.е. это лучше чем просто обнулить скорость?

еще один вопрос: стоит ли использовать в моем случае Box2d или лучше реализовать свой велосипед? т.к по сути у меня будет всего лишь проверка столкновений: прямоугольник/точка, прямоугольник-прямоугольник, причем стороны всегда параллельны осям координат.


Использую love2d, игровая механика примерно такая

#5
16:33, 5 ноя. 2013

спрашиваю потому, что в доках love2d.physics предостерегают:
> love.physics is not lightweight, and not even remotely simple to use. It's a ten-ton hammer designed for heavy-lifting. If you are just trying to make a character jump around on blocks or the likes, then move along, nothing to see here.

#6
17:15, 5 ноя. 2013

angru
> т.е. это лучше чем просто обнулить скорость?
Это не лучше. Это если нужно, чтобы персонаж "правдоподобно" замедлялся.

> игровая механика примерно такая
Ну, тут физика вроде и не нужна.
Но бокс2д всё ещё можно использовать только для коллизий, без физической симуляции.
А-ля: http://www.raywenderlich.com/606/box2d-tutorial-for-ios-how-to-us… ocos2d-iphone
Но мне кажется, проще будет свалить всё на бокс2д, и рулить только скоростями.

#7
18:02, 5 ноя. 2013

Спасибо, проглядел статью, как мне кажется при таком подходе теряется очень вкусная фича Box2d: когда происходит коллизия двух тел, он просто не дает им проникнуть друг в друга, а тут используется setTransform, есть вероятность положить один обьект в другой. Для меня это как раз главная проблема, из-за которой я отказался от своего велосипеда: детектировать коллизию - детский сад, а вот расположить после этого их так, чтобы они соприкасались, но не пересекались - не сдюжил.

п.с. obj-c - ужс)))

#8
18:34, 5 ноя. 2013

angru
> детектировать коллизию - детский сад, а вот расположить после этого их так,
> чтобы они соприкасались, но не пересекались - не сдюжил.
Потому в предыдущем посте последнее предложение - "проще всё свалить на бокс2д" :)

#9
18:38, 5 ноя. 2013

Ну в общем я так и сделал, после того как сам не справился, хотя конечно же обидно, что такую вроде бы простую вещь не осилил, там ведь даже физики никакой и не надо.

Как бы то ни было, спасибо за помощь.

#10
22:19, 5 ноя. 2013

да тут и никакой физический движок не нужен. Банально collision detection по bbox, проще не придумаешь, да и материала вагон.

#11
0:48, 6 ноя. 2013

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

кстати гуглением находится методы такого типа:

if ((obj1.x + obj1.width >= obj2.x) && (obj1.x <= obj2.x + obj2.width)) XColl = true;
if ((obj1.y + obj1.height >= obj2.y) && (obj1.y <= obj2.y + obj2.height)) YColl = true;

хотя я тут посидел, подумал, а есть ли право на жизнь у следующего алгоритма?

// r1, r2  - прямоугольники
// r.pos - позиция прямоугольника, отсчет от центра
// r.hw, r.hh - половина ширины и высоты соответственно

d = r2.pos - r1.pos;
if (r1.hw + r2.hw > abs(d.x)) && (r1.hh + r2.hh > abs(d.y))
    // коллизия

так я хотя бы смогу узнать на сколько мне нужно сместить прямоугольники, чтобы они не пересекались.

#12
10:54, 6 ноя. 2013

если кому интересно, то в конечном итоге получилось как-то так, псевдокод:

// r1, r2  - прямоугольники
// rect.pos - позиция прямоугольника, отсчет от центра
// rect.hw, r.hh - половина ширины и высоты соответственно
// rect.vel - вектор скорости

d = abs(r2.pos - r1.pos);  // абсолютный вектор расстояния между центрами прямоугольников
r = vec2(r1.hw + r2.hw, r1.hh + r2.hh);  // расстояние между прямоугольниками, при котором они не пересекаются
if (d < r)
    // коллизия
    // определяем коэф-т перемещения прямоугольника на основе его скорости
    cond = r1.vel.x < r1.vel.y;
    kx = cond ? r1.vel.x / r1.vel.y : 1;
    ky = cond ? 1 : r1.vel.y / r1.vel.x; 
    
    m = r - d;  // вектор на который надо переместить прямоугольник чтобы он не пересекался со вторым
    r1.pos.x -= m.x * kx * sign(r1.vel.x);
    r1.pos.y -= m.y * ky * sign(r1.vel.y);

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

#13
6:17, 8 ноя. 2013

angru
Используй box2d.
Тело перемещай банально - без физики, прямым заданием координат, а вот пульки - путем задания начальной скорости.
Далее - все разрушаемые объекты делай сенсорами.

И все - что тут сложного то?

#14
10:24, 8 ноя. 2013

если я буду напрямую задавать координаты обьекта - box2d не сможет отследить коллизии, я пробовал, у меня персонаж перемещался сквозь другие обьекты.

а вообще я уже сам справился, без box2d, естественно получилось не идеально и довольно топорно, но вроде работает

// псевдоокод
// r1, r2  - прямоугольники
// rect.pos - позиция прямоугольника, отсчет от центра
// rect.hw, r.hh - половина ширины и высоты соответственно
// new_pos - новая позиция прямоугольника r1

void check_collision(new_pos, r1, r2) {
    d = math.abs(r2.pos - r1.pos); // абсолютный вектор расстояния между центрами прямоугольников
    r = vec2(r1.hw + r2.hw, r1.hh + r2.hh);  // расстояние между прямоугольниками, при котором они не пересекаются
    s = new_pos - r1.pos;  // расстояние пройденное прямоугольником за итерацию
    dir = vec2(math.sign(s.x), math.sign(s.y)); // направление движения

    d.x += math.abs(new_pos.x);
    if (d < r) new_pos_x = resolve_collision(new_pos, dir, (d - r)); // если перемещение по оси x вызывает коллизию, то вычисляем значение х, при котором r1 и r2 все еще не пересекаются

    d.y += math.abs(new_pos.y); 
    if (d < r) new_pos_y = resolve_collision(new_pos, dir, (d - r)); // если перемещение по оси y вызывает коллизию, то вычисляем значение х, при котором r1 и r2 все еще не пересекаются

   r1.pos = vec2(new_pos_x.x, new_pos_y.y);
}

vec2 resolve_collision(pos, dir, r) {    
    x = r.x * dir.x;
    y = r.y * dir.y;
    return (pos - vec2(x, y));
}
Страницы: 1 2 Следующая »
Box2DФорумОбщее

Тема в архиве.