【问题标题】:Sprite becomes white box when I implement function当我实现功能时,Sprite变成白框
【发布时间】:2016-04-25 23:25:55
【问题描述】:

//Main.c

#include "Engine.h"

int main()
{
    Game app;
    //Menu Class Here
    app.run();
    return 0;
}

//Engine.cpp

#include "Engine.h"

Game::Game() 
{
    DASH = 0, x = 0, y = 0;
    total_enemies = 1;
    p_timer = 0;
    e_timer = 0;
}

Game::~Game()
{
}

void Game::run()
{
    sf::RenderWindow window(sf::VideoMode(SCREEN_X, SCREEN_Y), "Shogun Master");
    srand((unsigned int)time(NULL));

尝试将此处的“创建玩家”替换为位于该文件底部的 void game::createPlayer。

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

void Game::attack(sf::Event event)
{
    if (event.type == sf::Event::KeyPressed)    //Keyboard Commands
    if (event.key.code == sf::Keyboard::X)      //X = Dash Attack
        DASH = ATTK_SPD;
    if (event.type == sf::Event::JoystickButtonPressed) 
    {   ///Controller Action Buttons
        if (event.joystickButton.button == 0)                   //A = Dash Attack
        DASH = ATTK_SPD;
    }
}

void Game::player_movement(sf::Event event)
{
    if (event.type == sf::Event::KeyPressed)
    {       ///Keyboard Commands
        if (event.key.code == sf::Keyboard::W || event.key.code == sf::Keyboard::Up)    // Move Up
            x = 0, y = -P_SPD;
        if (event.key.code == sf::Keyboard::S || event.key.code == sf::Keyboard::Down)  // Move Down
            x = 0, y = P_SPD;
        if (event.key.code == sf::Keyboard::D || event.key.code == sf::Keyboard::Right) // Move Right
            x = P_SPD, y = 0;
        if (event.key.code == sf::Keyboard::A || event.key.code == sf::Keyboard::Left)      // Move Left
            x = -P_SPD, y = 0;
    }
    else if (event.type == sf::Event::JoystickMoved)
    {   ///Controller Directionals
        if (event.joystickMove.axis == sf::Joystick::PovY && event.joystickMove.position == 100)    //Up
            x = 0, y = -P_SPD;
        if (event.joystickMove.axis == sf::Joystick::PovY && event.joystickMove.position == -100)   //Down
            x = 0, y = P_SPD;
        if (event.joystickMove.axis == sf::Joystick::PovX && event.joystickMove.position == 100)    //Right
            x = P_SPD, y = 0;
        if (event.joystickMove.axis == sf::Joystick::PovX && event.joystickMove.position == -100)   //Left
            x = -P_SPD, y = 0;
    }
}

void Game::movementUpdate(sf::Sprite &player, sf::Sprite enemy[])
{
    //Player's Movements
    playerUpdate(player);
    for (int x = 0; x < total_enemies; x++)
    {
        enemyAiUpdate(player, enemy[x]);
    }
}

void Game::playerUpdate(sf::Sprite &player)
{
    if (DASH != 0)
    {   //Dash acts like a timer, speeds up until 0
        player.move(x * 3, y * 3);  //Dash
        --DASH;                     //Counts down
    }
    else
    player.move(x, y);  //Player Movement
}

void Game::enemyAiUpdate(sf::Sprite &player, sf::Sprite &enemy)
{
    double x = 1, y = 1, speed = .08;   //Enemy Movement towards player
    if (enemy.getPosition().x < player.getPosition().x)
        x = speed;      //Moves to right
    else if (enemy.getPosition().x > player.getPosition().x)
        x = -speed;     //Moves to left
    if (enemy.getPosition().y < player.getPosition().y)
        y = speed;      //Moves up
    else if (enemy.getPosition().y > player.getPosition().y)
        y = -speed;     //Moves down
    if (this->x == 0 && this->y == 0)
        x = 0, y = 0;   //Won't move until player moves
    enemy.move(x, y);
}

void Game::collision(sf::Sprite &player, sf::Sprite &enemy)
{
    int collision = 20, dmg = 100;
    //Enemy Collision (Damage Detection)
    if (enemy.getPosition().x > player.getPosition().x - collision && enemy.getPosition().x < player.getPosition().x + collision
        && enemy.getPosition().y > player.getPosition().y - collision && enemy.getPosition().y < player.getPosition().y + collision) 
    {
    if (DASH != 0) 
    {
        enemy.setColor(sf::Color(255, dmg, dmg));   //Enemy Collision [Damage taken, changes Red]
        e_timer = 400;
    } 
    else
    {
        player.setColor(sf::Color(255, dmg, dmg));  //Player Collision [Damage taken, changes Red]
        p_timer = 400;
    }
    }
    if (e_timer != 0)
        e_timer--;
    else
        enemy.setColor(sf::Color(255, 255, 255));
    if (p_timer != 0)
        p_timer--;
    else
        player.setColor(sf::Color(255, 255, 255));
}

void Game::check_closeWindows(sf::Event event, sf::RenderWindow &window)
{
    if (event.type == sf::Event::Closed)
        window.close();
    if (event.type == sf::Event::KeyPressed)
        if (event.key.code == sf::Keyboard::Escape) // Press Esc to Exit
            window.close();
    if (event.type == sf::Event::JoystickButtonPressed)
        if (event.joystickButton.button == 6)   //Press Back to Exit
            window.close();
}

void Game::border(sf::Sprite &player)
{
    if (player.getPosition().x >= SCREEN_X)                     ///If Player goes off screen, spawns on the other side
        player.setPosition(1, player.getPosition().y);              //Right Border
    if (player.getPosition().x <= 0)
        player.setPosition(SCREEN_X - 1, player.getPosition().y);       //Left Border
    if (player.getPosition().y >= SCREEN_Y)
        player.setPosition(player.getPosition().x - 1, 1);          //Top Border
    if (player.getPosition().y <= 0)
        player.setPosition(player.getPosition().x, SCREEN_Y - 1);   //Bottom Border
}

int Game::rand_int(int min, int quantity)
{
    return rand() % quantity + min;
}

这是我在实施时遇到的问题。我试图让它工作,所以我可以使用这个函数来替换 void game::run() 下的“create player”,然后用它来创建一个类,但我不知道是什么原因造成的走出范围。任何有关如何实施这一点的帮助将不胜感激。

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

//Engine.h

#pragma once
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
#include <iostream>
#include <time.h>

#define SCREEN_X 1000   //Size of Memory, can be changed
#define SCREEN_Y 800    //Size of Memory, can be changed
#define ATTK_SPD 250    //Speed of Player Attack
#define P_SPD .2        //Player's Speed
#define MAX_ENEMIES 5

class Game
{
 public:
        Game();
        ~Game();
        void run();
        void attack(sf::Event event);
        void player_movement(sf::Event event);
        void movementUpdate(sf::Sprite &player, sf::Sprite enemy[]);
        void playerUpdate(sf::Sprite &player);
        void enemyAiUpdate(sf::Sprite &player, sf::Sprite &enemy);
        void collision(sf::Sprite &player, sf::Sprite &enemy);
        void check_closeWindows(sf::Event event, sf::RenderWindow &window);
        void border(sf::Sprite &player);
        int rand_int(int min, int quantity);
        //void Game::createPlayer(sf::Sprite &player);
 private:
        int DASH;
        double x, y;
        int total_enemies;
        int p_timer;
        int e_timer;
};

【问题讨论】:

  • Player_texture 对于 Createplayer 是本地的。当函数返回时,它将不再存在。

标签: c++ scope sfml


【解决方案1】:
void Game::createPlayer(sf::Sprite &player)
{   
    // this variable is local.
    // it will only live to the end of the createPlayer method
    sf::Texture player_texture; 

    if (!player_texture.loadFromFile("player.png")) 
    {
        //Error Loading
    }

    player.setTexture(player_texture);
}

您的 player_texture 是一个 本地 变量。当它在方法结束时超出范围时,它将被销毁。现在你的 player_sprite 有一个被破坏的纹理。由于不知道曾经保存在该纹理中的内容,SFMl 会将其绘制为白色。

您需要做的是确保您的 player_texture 变量的生命周期至少与您的 player 变量一样长。

你可以把它放在你的 Game 类中。但是您的玩家似乎不在该类别之外。你很快就会发现,对于所有的精灵,你需要一个类来保存它们。像 TextureManager 或 ResourceHolder 之类的东西。然后您会发现将所有外部资源(文件)访问在一个地方会更实用,例如在 TextureManager.load() 方法中。然后你将需要你的第一个加载屏幕。欢迎来到游戏世界。

【讨论】:

    猜你喜欢
    • 2023-01-11
    • 2020-01-13
    • 1970-01-01
    • 2019-08-07
    • 2021-03-21
    • 2012-08-08
    • 1970-01-01
    • 2020-05-26
    • 1970-01-01
    相关资源
    最近更新 更多