2015-01-06 10 views
2

저는 2D 게임을 SFML로 만들고 있는데 타일 맵에서 타일과 충돌하는 방법을 찾으려고합니다. 몇 가지 코드를 작성했지만 문제는 아래 그림에서 볼 수있는 것처럼 충돌하는 타일에 달라 붙는 것입니다. 어떤 방향으로도 이동할 수 없으며 플레이어의 약 5 픽셀이 벽에 있습니다. enter image description hereSFML 타일 맵 충돌

이 내 충돌/이동 코드

void Player::update(float delta, std::vector<Tile>& tiles) { 
    canMove = true; 

    for (int i = 0; i < tiles.size(); i++) { 
     if (Collision::PixelPerfectTest(sprite, tiles[i].sprite) && tiles[i].collision) { 
      canMove = false; 
     } 
    } 

    if (canMove) { 
     move(delta); 
    } 
} 

void Player::move(float delta) { 
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::W) || sf::Keyboard::isKeyPressed(sf::Keyboard::Up) || sf::Joystick::getAxisPosition(0, sf::Joystick::Y) < -20) { 
     movement.y -= speed * delta; 
    } 
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::A) || sf::Keyboard::isKeyPressed(sf::Keyboard::Left) || sf::Joystick::getAxisPosition(0, sf::Joystick::X) < -20) { 
     movement.x -= speed * delta; 
    } 
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::S) || sf::Keyboard::isKeyPressed(sf::Keyboard::Down) || sf::Joystick::getAxisPosition(0, sf::Joystick::Y) > 20) { 
     movement.y += speed * delta; 
    } 
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::D) || sf::Keyboard::isKeyPressed(sf::Keyboard::Right) || sf::Joystick::getAxisPosition(0, sf::Joystick::X) > 20) { 
     movement.x += speed * delta; 
    } 

    sprite.setPosition(movement); 
} 

이다이있는 PixelPerfectTest 기능 (이 광산이 아니다)

bool PixelPerfectTest(const sf::Sprite& Object1, const sf::Sprite& Object2, sf::Uint8 AlphaLimit) { 
     sf::FloatRect Intersection; 
     if (Object1.getGlobalBounds().intersects(Object2.getGlobalBounds(), Intersection)) { 
      sf::IntRect O1SubRect = Object1.getTextureRect(); 
      sf::IntRect O2SubRect = Object2.getTextureRect(); 

      sf::Uint8* mask1 = Bitmasks.GetMask(Object1.getTexture()); 
      sf::Uint8* mask2 = Bitmasks.GetMask(Object2.getTexture()); 

      // Loop through our pixels 
      for (int i = Intersection.left; i < Intersection.left + Intersection.width; i++) { 
       for (int j = Intersection.top; j < Intersection.top + Intersection.height; j++) { 

        sf::Vector2f o1v = Object1.getInverseTransform().transformPoint(i, j); 
        sf::Vector2f o2v = Object2.getInverseTransform().transformPoint(i, j); 

        // Make sure pixels fall within the sprite's subrect 
        if (o1v.x > 0 && o1v.y > 0 && o2v.x > 0 && o2v.y > 0 && 
         o1v.x < O1SubRect.width && o1v.y < O1SubRect.height && 
         o2v.x < O2SubRect.width && o2v.y < O2SubRect.height) { 

         if (Bitmasks.GetPixel(mask1, Object1.getTexture(), (int)(o1v.x) + O1SubRect.left, (int)(o1v.y) + O1SubRect.top) > AlphaLimit && 
          Bitmasks.GetPixel(mask2, Object2.getTexture(), (int)(o2v.x) + O2SubRect.left, (int)(o2v.y) + O2SubRect.top) > AlphaLimit) 
          return true; 

        } 
       } 
      } 
     } 
     return false; 
    } 

편집 : 나는 그것에서 경우의 사람에서 일하고있어 방법이있다 미래가 도움이 필요합니다

void Player::update(float delta, std::vector<Tile>& tiles) { 
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::W) || sf::Keyboard::isKeyPressed(sf::Keyboard::Up) || sf::Joystick::getAxisPosition(0, sf::Joystick::Y) < -20) { 
     newPos.y -= speed * delta; 
    } 
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::A) || sf::Keyboard::isKeyPressed(sf::Keyboard::Left) || sf::Joystick::getAxisPosition(0, sf::Joystick::X) < -20) { 
     newPos.x -= speed * delta; 
    } 
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::S) || sf::Keyboard::isKeyPressed(sf::Keyboard::Down) || sf::Joystick::getAxisPosition(0, sf::Joystick::Y) > 20) { 
     newPos.y += speed * delta; 
    } 
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::D) || sf::Keyboard::isKeyPressed(sf::Keyboard::Right) || sf::Joystick::getAxisPosition(0, sf::Joystick::X) > 20) { 
     newPos.x += speed * delta; 
    } 

    sf::Vector2f oldPos = sprite.getPosition(); 
    sprite.setPosition(newPos); 

    for (int i = 0; i < tiles.size(); i++) { 
     if (Collision::PixelPerfectTest(sprite, tiles[i].sprite) && tiles[i].collision) { 
      sprite.setPosition(oldPos); 
      newPos = oldPos; 
     } 
    } 
} 

답변

3

귀하의 문제 본질적으로 다음과 같습니다.

플레이어가 벽에 이 아니고이 아닌 경우 어떤 방향 으로든 이동할 수 있습니다. 여기에는 그를 벽에 넣을 움직임이 포함됩니다. 플레이어의 이 벽에 인 경우 그는 전혀 움직일 수 없습니다. 그래서 그가 벽으로 들어간다면 (그렇게하도록 허용했기 때문에) 결코 빠져 나올 수 없습니다.

그래서 가장 확실한 해결 방법은 플레이어가 벽 안으로 들어 가지 못하게하는 것입니다. 한 가지 간단한 방법은 플레이어를 이동 한 다음 벽과의 충돌을 확인하는 것입니다. 충돌이 발생하면 플레이어를 원래 위치로 다시 이동하십시오.

벽에 갇히는 기본 문제를 해결해야합니다. 벽 옆에 바로 올라갈 수없는 것과 같은 다른 문제가 생길 수도 있습니다. 이를 위해, 충돌이 일어 났을 때 벽이 어디에 있는지를 정확히 확인하고 플레이어를 오른쪽으로 움직입니다.

+0

오전 3시에 시작했기 때문에 시작하는 데 문제가 있습니다. 어쩌면 의사 코드를 작성할 수 있습니까? – Wahoozel

+0

@Wahoozel : 의사 코드를 작성했습니다. * "플레이어를 움직여 벽과의 충돌을 확인하십시오 충돌이 발생하면 플레이어를 원래 위치로 다시 이동하십시오."* –

+0

고마워요. 그러나 내가 동시에 걷는다면, 벽을 따라 미끄러 져 움직일 수 없습니다. 나는 단지 갇히게되고, 내가 나올 때까지 움직일 수 없다. – Wahoozel

0

EDIT : 충돌 감지가 false를 반환하면 이전 위치를 저장합니다. 캐릭터와 개체가 충돌 할 때 수행해야 할 일은 이전의 비 충돌 위치를 복원하는 것입니다.

void Player::update(float delta, std::vector<Tile>& tiles) { 
for (int i = 0; i < tiles.size(); i++) 
    Collision::PixelPerfectTest(sprite, tiles[i].sprite) && tiles[i].collision) ? canMove = false : prevpos = sprite.getPosition(); 

if (canMove) { 
    move(delta); 
} 
else 
{ 
sprite.setPosition(prevpos); 
canMove = true; 
} 
} 

그런 것.