Проблемы столкновения блоков в игре C ++ / SFML Super Mario с блоками - PullRequest
0 голосов
/ 09 мая 2020

Я делал супер-марио-подобную игру на C ++ / SFML, и при попытке написать код для столкновений Марио у меня возникли некоторые проблемы: Персонаж, когда сталкивается с вертикальной стопкой блоков при движении по горизонтальной оси , застрять на одной стороне блоков, как если бы он шел по невидимому блоку. Я попытался изменить функцию столкновения, например, заставить Марио сталкиваться с блоками по горизонтали, только если его положение, связанное с блоками, содержится в координатах блока.

Я включаю некоторый код для движения (keyPressed - это функция, которая возвращает нажата клавиша):

void Player::movement(Time& gameTime) {
    player.move(v * gameTime.asSeconds());
    view.setCenter(player.getPosition().x + 16, 590);

    if (keyPressed(up) && !jumping) {
        jumping = true;
        v.y = jumpSpeed;
    }
    if (v.y > 200) {
        jumping = true;
    }
    else {
        crouch = false;
    }
    if (keyPressed(left)) {
        if (v.x > -moveSpeed) {
            v.x -= 100;
        }
        else {
            v.x = -moveSpeed;
        }
    }
    else if (keyPressed(right)) {
        noKeyPressed = false;
        if (v.x < moveSpeed) {
            v.x += 100;
        }
        else {
            v.x = moveSpeed;
        }
    }
    else {
        if (v.x < -100) {
            v.x += 100;
        }
        else if (v.x > 100) {
            v.x -= 100;
        }
        else {
            v.x = 0;
        }
    }
    gravity();

    if (big) { //Big is a variable that tells me if mario is big or small
        heightValue = 33; //heightValue is a variable that stores the sprite height in pixels
    }
    else {
        heightValue = 16;
    }
}

void Player::gravity() {
    if (!big) {
        if (player.getPosition().y + 32 < 1100) {
            if (v.y < maxSpeed) {
                v.y += 100;
            }
        }
        if (alive) { //This is useful to check if big mario has fallen
            if (player.getPosition().y + 32 >= 1200) {
                player.setPosition(player.getPosition().x, 1200 - 32);
                jumping = false;
                alive = false;
            }
        }
    }
    else {
        if (player.getPosition().y + 64 < 1100) {
            if (v.y < maxSpeed) {
                v.y += 100;
            }
        }
        if (alive) { //This is useful to check if small mario has fallen
            if (player.getPosition().y + 64 >= 1200) {
                player.setPosition(player.getPosition().x, 1200 - 64);
                jumping = false;
                alive = false;
            }
        }
    }
}

И функция столкновения, где класс блока имеет 4 небольших блока вокруг спрайта блока, которые упрощают столкновения:

void Player::collisions(Block* block) {
    if (this->player.getGlobalBounds().intersects(block->up.getGlobalBounds())) {
        if (!big) {
            if (this->player.getPosition().y + heightValue <= block->block.getPosition().y) {
                this->player.setPosition(this->player.getPosition().x, block->up.getPosition().y - 32);
                v.y = 0;
                jumping = false;
                score = 100;    
            }
        }
        else {
            if (this->player.getPosition().y + heightValue <= block->block.getPosition().y) {
                this->player.setPosition(this->player.getPosition().x, block->up.getPosition().y - 64);
                v.y = 0;
                jumping = false;
                score = 100;            
            }
        }
    }
    if (this->player.getGlobalBounds().intersects(block->down.getGlobalBounds())) {
        this->player.setPosition(this->player.getPosition().x, block->down.getPosition().y + 1);
        v.y = 0;
    }
    if (this->player.getGlobalBounds().intersects(block->left.getGlobalBounds()) && v.x > 0) {
        this->player.setPosition(block->left.getPosition().x - 32, this->player.getPosition().y);
    }
    else if (this->player.getGlobalBounds().intersects(block->right.getGlobalBounds()) && v.x < 0) {
        this->player.setPosition(block->right.getPosition().x + 1, this->player.getPosition().y);
    }
}

Надеюсь, я точно объяснил проблему .

1 Ответ

0 голосов
/ 19 мая 2020

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

пример псевдокода:

//X axis
oldPos = position
if(leftKey):
    position.x -= speed
if(rightKey):
    position.x += speed
if(collision):
    position = oldPos

//Y axis
oldPos = position
if(upKey):
    position.y -= speed
if(downKey):
    position.y += speed
if(collision):
    position = oldPos
...