2014-05-17 19 views
0

스페이스 바를 누르면 상대적으로 간단한 프로그램을 작성하여 움직이는 캐릭터로부터 작은 발사체를 만듭니다.SFML - 벡터에서 스프라이트를 그릴 때 프로그램이 충돌 함

프로그램을 오류없이 컴파일 (코드 블록)하고 스페이스 바를 누를 때까지 실행됩니다. 발사체를 발사하는 대신 프로그램이 즉시 충돌합니다.

저는 스크린에 발사체를 그려 넣은 선으로 충돌을 격리 할 수 ​​있다고 생각합니다 (83 번). 전후에 줄에 cout 문을 사용했는데 두 번째 문은 표시되지 않았습니다.

for (int ii = 0; ii < inMotion.size(); ii++) 
{ 
    window.draw(inMotion[ii].bulletSprite); 
} 

나는이 모든 문제를 해결하기 위해 모든 코드를 필요로하므로 모든 코드를 게시했습니다.

#include <iostream> 
#include <SFML/Graphics.hpp> 
#include <string.h> 
#include <math.h> 
#include <vector> 

using namespace std; 
class Projectile 
{ 
public: 
    Projectile(int, string); 
    void moveBullet(); 
    sf::Sprite bulletSprite; 
private: 
    sf::Texture bulletTexture; 
    int speed; 
    string bulletTextureString; 
}; 

Projectile::Projectile(int s, string t) 
{ 
    speed = s; 
    bulletTextureString = t; 
    if(!bulletTexture.loadFromFile((bulletTextureString).c_str())) 
    { 
     cout << "error"; 
    } 
    bulletSprite.setTexture(bulletTexture); 
} 
void Projectile::moveBullet() 
{ 
    bulletSprite.move(speed, 0); 
} 

class thePlayer 
{ 
public: 
    void Fire(sf::Time); 
    void Walk(); 
    void Draw(sf::RenderWindow&); 
    void Create(string); 
    sf::Time lastShot; 
private: 
    vector<Projectile> inMotion; 
    sf::Texture playerTexture; 
    sf::Sprite playerSprite; 
    string playerTextureString; 
    int moveSpeed = 5; 

}; 

void thePlayer::Create(string s) 
{ 
    playerTextureString = s; 

    if(!playerTexture.loadFromFile((playerTextureString).c_str())) 
    { 
     cout << "error"; 
    } 
    playerSprite.setTexture(playerTexture); 
} 
void thePlayer::Fire(sf::Time time) 
{ 
    sf::Time shotDelay = sf::milliseconds(100); 
    if(time - lastShot >= shotDelay) 
    { 
     if(sf::Keyboard::isKeyPressed(sf::Keyboard::Space)) 
     { 
      Projectile bullet(15, "fireball.png"); 
      bullet.bulletSprite.setPosition(playerSprite.getPosition()); 
      inMotion.push_back(bullet); 
     } 
    } 
    for(int ii = 0; ii < inMotion.size(); ii++) 
    { 
     inMotion[ii].moveBullet(); 
    } 
} 
void thePlayer::Draw(sf::RenderWindow& window) 
{ 
    for (int ii = 0; ii < inMotion.size(); ii++) 
    { 
     window.draw(inMotion[ii].bulletSprite); 
    } 
    window.draw(playerSprite); 
} 
void thePlayer::Walk()//awsd standart movement 
{ 
    int x = 0; 
    int y = 0; 
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::A)) 
    { 
     x-= moveSpeed; 
    } 
    else if(sf::Keyboard::isKeyPressed(sf::Keyboard::D)) 
    { 
     x+= moveSpeed; 
    } 
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::W)) 
    { 
     y-= moveSpeed; 
    } 
    else if(sf::Keyboard::isKeyPressed(sf::Keyboard::S)) 
    { 
     y+= moveSpeed; 
    } 
    playerSprite.move(x, y); 
} 

class Game 
{ 
public: 
    void Update(sf::RenderWindow&, sf::Time); 
    void Start(sf::Time); 
    sf::Clock clock; 
    thePlayer player; 

private: 

}; 

void Game::Start(sf::Time time) 
{ 
    player.Create("block.png"); 
    player.lastShot = time; 
} 
void Game::Update(sf::RenderWindow& window, sf::Time time) 
{ 
    player.Fire(time); 
    player.Walk(); 
    player.Draw(window); 
} 

int main() 
{ 
    sf::RenderWindow window(sf::VideoMode(1000, 1000), "Menu"); 
    window.setFramerateLimit(60); 
    Game theGame; 
    sf::Clock clock; 
    sf::Time startTime = clock.restart(); 
    theGame.Start(startTime); 
    while (window.isOpen()) 
    { 
     sf::Event event; 
     while (window.pollEvent(event)) 
     { 
      if (event.type == sf::Event::Closed) 
       window.close(); 
     } 

     window.clear(sf::Color::White); 
     sf::Time elapsed = clock.getElapsedTime(); 
     theGame.Update(window, elapsed); 
     window.display(); 
    } 
    return 0; 
} 

도움을 주셔서 대단히 감사합니다.

편집 : 디버거를 사용하여 시도했지만 아무것도 알아낼 수 없습니다. 코드 블럭 디버깅에 대한 훌륭한 기사 링크가 좋습니다.

답변

1

이 문제를 직접 해결할 수있었습니다. 나는 포인터로 Bullet 클래스를 참조하고 텍스쳐가 public인지 확인해야한다는 것을 알아 냈다. 나는 또한 생성자를 잘못 사용하고 있었고, 그것들을 제거했다.

대략적인 해결책은 다음과 같습니다.

void thePlayer::Fire(sf::Time time) 
{ 
    sf::Time shotDelay = sf::milliseconds(100); 
    if(time - lastShot >= shotDelay) 
    { 
     if(sf::Keyboard::isKeyPressed(sf::Keyboard::Space)) 
     { 
      Projectile *bullet = new Bullet; 
      bullet->bulletSprite.setPosition(playerSprite.getPosition()); 
      inMotion.push_back(bullet); 
     } 
    } 
    for(int ii = 0; ii < inMotion.size(); ii++) 
    { 
     inMotion[ii]->moveBullet(); 
    } 

는 대답하려고 사람들에게

//... 
vector<Bullet*> Bullets; 
//... 

과 다시 한번 감사 클래스에 벡터 선언을 변경했다.

0

음, 게임을 아주 잘못 코딩하고 있습니다!

내가 제안하는 것 :

  • 당신은 선수와 총알 클래스를 생성한다

  • 렌더링 방법 및 업데이트 방법으로 각 클래스 - 업데이트 방법은 DT있다 (경과 시간 마지막 프레임) 매개 변수까지,

  • 플레이어 클래스는 "이동"과 "불"방법을 가지고

  • 게임 루프에서 입력을 읽고 (필요한 경우 이동 또는 호출 메소드를 호출하고) 모든 객체 (플레이어 및 구분 점 위치)를 업데이트하고 모두 그립니다.

  • 이동 방법은 플레이어에게 속도를 주어야하며,

    화재 방법이 속도로 총알을 만들어야합니다
  • ,

  • (속도와 DT와) 새로운 위치를 계산해야하는 업데이트 방법,

  • 플레이어와 총알 기반의 게임 요소 클래스에서 파생 수 (마녀 계산 위치, 충돌, 등 ...).

+0

답변 해 주셔서 감사합니다. 제 코드가 더 잘 작성 될 수 있다는 것에 동의하지만, 제 질문에 대해서는 대답하지 않습니다. 실제로 프로그램을 중단시키는 원인에 대해 더 깊은 통찰력을 얻었습니다. –

+0

네,하지만 (OSX에서) 코드를 시도했습니다 - 컴파일되고, 키에 따라 플레이어가 움직이지만 총알은 작동하지 않습니다. –

0

당신은 시계를 재설정해야 :

sf::Time elapsed = clock.restart(); 

을 그리고 당신은 한 번만 사물의 질감을로드하고 클래스 발사체의 모든 경우에 사용합니다.

+0

그게 작동하지 않습니다. 클럭을 리셋하는 것은 단순히 발사체가 발사되는 것을 방지하는 것입니다 (따라서 충돌을 일으키는 함수를 호출하지 않음). 아마 당신의 대답 뒤에 다른 아이디어가 있었을까요? –

+0

죄송합니다. '경과'에는 마지막 프레임 이후로 경과 된 시간이 포함되어야한다고 생각했습니다. 지금은 고정 된 시간대를 사용하고 있다는 것을 알고 있습니다 (필자는 권장하지 않습니다). 'lastShot'을 업데이트하지 않고 각 프레임에 투사 체를 만드는 것이 하나의 문제 일 수 있습니다. 83 행에 중단 점을 넣고 벡터에 올바른 데이터가 있으면주의해야합니다. – DarkPhantom

관련 문제