2016-04-26 3 views
0

У меня возникли проблемы с реализацией этой функции.спрайт из сферы действия, потому что он локальный

//Engine.cpp

void Game::createPlayer(sf::Sprite &player) 
{ ///Can't get this to work 
    sf::Texture player_texture; 
    if (!player_texture.loadFromFile("player.png")) 
    { 
     //Error Loading 
    } 
    player.setTexture(player_texture); 
} 

Я хочу, чтобы заменить «создает игрок в ничтожных играх :: бежать, но я понимаю, что Player_texture является локальным для Createplayer и что она не будет существовать, когда функция возвращается.

void Game::run() 
{ 
    sf::RenderWindow window(sf::VideoMode(SCREEN_X, SCREEN_Y), "Shogun Master"); 
    srand((unsigned int)time(NULL)); 
    //Creates Player [Makes into function] 
    sf::Texture player_texture; 
    player_texture.loadFromFile("sprites/player.png"); 
    sf::Sprite player(player_texture); 
    //Creates Enemy [Make into function] 
    sf::Texture enemy_texture; 
    enemy_texture.loadFromFile("sprites/enemy.png"); 
    sf::Sprite enemy[MAX_ENEMIES]; 
    for (int x = 0; x < MAX_ENEMIES; x++) 
    { 
     enemy[x].setTexture(enemy_texture); 
     enemy[x].setPosition(rand_int(100, SCREEN_X - 100), rand_int(100, SCREEN_Y - 100)); //Spawning Point 
    } 
    //Sets Positions 
    player.setPosition(500, 300); 

    while (window.isOpen()) 
    { 
     sf::Event event; 
     while (window.pollEvent(event)) 
     { 
      check_closeWindows(event, window); //Closes Game if Executed 
      player_movement(event);    //Moves Character 
      attack(event);      //Character's attacks 
     } 
     border(player);     //Border so player does not go off screen 
     for (int x = 0; x < total_enemies; x++) 
      border(enemy[x]); 
     movementUpdate(player, enemy); //Player & Enemy Movement Updates 
     collision(player, enemy[0]); 

     window.clear(); 
     window.draw(player); //Draws Player 
     for (int x = 0; x < total_enemies; x++) 
      window.draw(enemy[x]);  //Draws Enemy 
     window.display(); 
    } 
} 

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

//Engine.h

void Game::createPlayer(sf::Sprite &player); 
+1

Возможный дубликат [Спрайт становится белым ящиком, когда я реализую функцию] (http://stackoverflow.com/questions/36852825/sprite-becomes-white-box-when-i-implement-function) – Hiura

+0

Я имею в виду, вы задавая точно такой же вопрос, не принимая во внимание данный ответ в полном объеме ... – Hiura

ответ

2

документация (http://www.sfml-dev.org/documentation/2.0/classsf_1_1Sprite.php#a3729c88d88ac38c19317c18e87242560) для setTexture() метода вы звоните говорит:

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

Один из способов справиться с этим было бы сделать свой собственную структуру или класс, который содержит как Sprite и его структуры:

struct SpriteWithTexture 
{ 
    sf::Texture texture; 
    sf::Sprite sprite; 

    SpriteWithTexture() 
    { 
     sprite.setTexture(texture); 
    } 

    SpriteWithTexture(const SpriteWithTexture& that) 
     : texture(that.texture) 
    { 
     sprite.setTexture(texture); 
    } 

    SpriteWithTexture& operator=(const SpriteWithTexture& that) 
    { 
     texture = that.texture; 
     sprite.setTexture(texture); 
     return *this; 
    } 
}; 

Затем вы можете вернуть это из вашей функции:

SpriteWithTexture Game::createPlayer() 
{ 
    SpriteWithTexture player; 
    if (!player.texture.loadFromFile("player.png")) 
    { 
     //Error Loading 
    } 
    return player; 
} 

Теперь текстура всегда будет жить так долго, как спрайт.

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

struct SpriteWithTexture 
{ 
    std::shared_ptr<sf::Texture> texture; 
    sf::Sprite sprite; 

    SpriteWithTexture(const std::shared_ptr<sf::Texture>& texture_) 
     : texture(texture_) 
    { 
     sprite.setTexture(*texture); 
    } 
}; 

Теперь вы можете использовать его таким образом:

std::shared_ptr<sf::Texture> player_texture(new sf::Texture); 
player_texture->loadFromFile("sprites/player.png"); 
SpriteWithTexture player(player_texture); 

std::shared_ptr<sf::Texture> enemy_texture(new sf::Texture); 
enemy_texture->loadFromFile("sprites/enemy.png"); 
std::vector<SpriteWithTexture> enemies; 
for (int x = 0; x < MAX_ENEMIES; x++) 
{ 
    enemies.emplace_back(enemy_texture); // construct enemy Sprite 
    enemies.back().sprite.setPosition(rand_int(100, SCREEN_X - 100), rand_int(100, SCREEN_Y - 100)); //Spawning Point 
} 

теперь все враги в векторе доли одной текстуры. Возможно, это важно для эффективности.

+1

Первый проект «SpriteWithTexture» является ошибкой: при копировании скопированный спрайт не будет ссылаться на скопированную текстуру, но только для оригинальная текстура. Кроме того, вторая версия кажется мне сложной: лучше использовать диспетчер ресурсов, как было объяснено в [дублированном вопросе OP] (http://stackoverflow.com/a/36855842/520217). Таким образом, сохранение текстуры действительно отдельная задача и хорошо отделяется от остальной части программы. – Hiura

+0

@Hiura: Спасибо, я считаю, что теперь я исправил ошибку, которую вы правильно указали. –

+0

Не совсем на самом деле: вам нужно полностью скопировать спрайт (прежде чем переопределить ссылку на текстуру, конечно), поскольку он имеет другие свойства, а не только ссылку на текстуру. ;-) – Hiura

Смежные вопросы