Я реализую некоторые базовые физики платформера в C ++ для простого платформера на основе плиток. Я следую алгоритму здесь (https://gamedev.stackexchange.com/questions/18302/2d-platformer-collisions) так точно, как только могу, я все еще получаю странный сбой, когда игрок подпрыгивает на плитке. Я не совсем уверен, что происходит. Код на C ++ с использованием SDL
void Player::update(vector< vector<Tile> > map) {
vector<Tile> collidingTiles;
x += xVel;
y += yVel;
boundingBox = Rect(x,y,16,16);
for(int iy=0;iy<MAPH;iy++) {
for(int ix=0;ix<MAPW;ix++) {
if (map[ix][iy].solid == true) {
if (boundingBox.collide(map[ix][iy].boundingBox)) {
collidingTiles.push_back(map[ix][iy]); // store all colliding tiles, will be used later
Rect intersectingRect = map[ix][iy].boundingBox; // copy the intersecting rect
float xOffset = x-intersectingRect.x; // calculate x-axis offset
float yOffset = y-intersectingRect.y; //calculate y-axis offset
if (abs(xOffset) < abs(yOffset)) {
x += xOffset;
}
else if (abs(xOffset) > abs(yOffset)) {
y += yOffset;
}
boundingBox = Rect(x,y,16,16); // reset bounding box
yVel = 0;
}
}
}
}
if (collidingTiles.size() == 0) {
yVel += gravity;
}
};
if (abs(xOffset) < abs(yOffset)) {
x += xOffset;
}
else if (abs(xOffset) > abs(yOffset)) {
y += yOffset;
}
yVel = 0;
В этом коде, если abs(xOffset) == abs(yOffset)
, ничего не происходит, это означает, что игрок может ввести твердую плитку по диагонали. Удаление второго теста должно устранить проблему и изменить y
если алгоритм должен сделать выбор:
Кроме того, мне интересно, если вы действительно хотите сбросить вертикальную скорость, если происходит горизонтальное столкновение. Это также подразумевает, что гравитация все еще должна применяться, если столкновение было горизонтальным (в противном случае стены и потолок были бы липкими).
int gravityApplies = true;//fix 2a
...
if (abs(xOffset) < abs(yOffset)) {
x += xOffset;
xVel = 0; //fix 2
}
else { //fix 1
y += yOffset;
yVel = 0; //fix 2
if( yOfsset < 0 ){ // fix 2a
gravityApplies = false;
}
}
...
if (gravityApplies) { //fix 2a
yVel += gravity;
}
Если вы хотите упругих столкновений, используйте yVel = -yVel
вместо yVel = 0
(и аналогично для другого направления). Вы даже можете сделать yVel = yVel * rest
где rest
колеблется от -1
в 0
(-0.8
хороший выбор), чтобы получить полуэластичные столкновения.
Других решений пока нет …