精灵超出范围,因为它是本地的

时间:2016-04-26 01:16:36

标签: c++ scope sfml

我无法实现此功能。

// 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);
}

我希望它替换“在void Game :: run中创建播放器但我意识到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 个答案:

答案 0 :(得分:2)

您呼叫的setTexture()方法的文档(http://www.sfml-dev.org/documentation/2.0/classsf_1_1Sprite.php#a3729c88d88ac38c19317c18e87242560)说:

  

纹理参数指的是只要精灵使用它就必须存在的纹理。实际上,精灵并不存储自己的纹理副本,而是保留指向您传递给该函数的指针。如果源纹理被破坏并且精灵试图使用它,则行为是未定义的。

解决这个问题的一种方法是创建自己的包含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;
}

现在纹理将始终与精灵一样长。

但是请注意,当你构建你的敌人&#34;你为所有这些使用单一纹理。为了在多个精灵之间共享一个纹理,我们可以增强上述功能:

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
}

现在,矢量中的所有敌人都共享一个纹理。也许这对效率很重要。