如何使用SFML库使用Manager类在C ++中管理角色及其动画 [英] How to use a Manager class to manage Characters and their animations in C++ using the SFML library

查看:72
本文介绍了如何使用SFML库使用Manager类在C ++中管理角色及其动画的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个2D侧滑迷你游戏。目前,我只有一个带有精灵和一个动画的角色,我正尝试使用向左/向右箭头移动。最初,我只有一个Character类,用于存储角色的精灵及其运行的动画。而且有效。但是现在,我试图添加一个CharacterManager类,该类将创建所有字符以避免在主体中这样做,并且将管理它们的移动并绘制它们。



它不再起作用了。我认为我的问题出在我实际上并不熟悉指针的使用上。



以下是我正在使用的不同类: / p>

Animation.h:

  #pragma一次
#包括< vector>
#include< SFML / Graphics.hpp>
#include< stdexcept>
#include< ctime>
#include Constants.h

class动画{
public:
Animation();
〜Animation();

void SetFrames(std :: vector< sf :: IntRect>框架){m_frames =框架; }
sf :: IntRect Play();

私有:
std :: vector< sf :: IntRect> m_frames;
unsigned int m_currentFrame;
float m_updateTime;
float m_timeSinceLastFrame;
float m_lastCallTimestamp;
float m_currentTimestamp;
bool m_firstCall;
};

Animation.cpp:

  #include Animation.h 

Animation :: Animation(){
m_currentFrame = 0;

m_updateTime = 1.0f / ANIMATION_SPEED;
m_timeSinceLastFrame = 0.0f;
m_firstCall = true;
}

Animation ::〜Animation(){

}

sf :: IntRect Animation :: Play(){
if(m_frames.size()== 0){
throw std :: length_error(帧向量为空);
}

//提前时间并将经过的时间添加到timeSinceLastFrame
m_currentTimestamp = std :: clock();

//如果第一次调用
,如果(m_firstCall){
m_timeSinceLastFrame = 0.0f;
m_lastCallTimestamp = m_currentTimestamp;
m_firstCall = false; //不先调用
}
else {
m_timeSinceLastFrame + =(m_currentTimestamp-m_lastCallTimestamp)/ CLOCKS_PER_SEC;
m_lastCallTimestamp = m_currentTimestamp;
}

//如果(m_timeSinceLastFrame> = m_updateTime){
m_currentFrame ++;
m_timeSinceLastFrame = 0;

//检查动画结尾
是否(m_currentFrame> = m_frames.size()){
m_currentFrame = 0; //重置帧进度
m_firstCall = true; //下一段将是新动画

/ * TODO的第一个调用:返回某些内容以提醒动画
结束(例如特定的rectint或将变量设置为true和* /
}
}

return m_frames [m_currentFrame];
}

Character.h:

  #pragma一次

#include< string>
#include< iostream>
#include< SFML / Graphics.hpp>
#include< vector>
#include< map>
#include Constants.h
#include Animation.h

class字符:public sf :: Drawable {
public:
字符();
Character(std :: string name);
〜Character();

void Move(浮点值);

//设置者
void SetTexture(std :: string filename);
void SetPosition(sf :: Vector2f pos){m_position = pos; };
void SetAnimations(std :: map< std :: string,Animation *>动画){m_animations =动画; };

受保护:
虚拟虚空绘制(sf :: RenderTarget& target,sf :: RenderStates国家)const;

std :: string m_name;
unsigned int m_orientation; // 0(默认)=右| 1 =左
std :: map< std :: string,Animation *> m_animations;
动画runningAnimation;
sf :: Vector2f m_position;
sf :: Texture m_texture;
sf :: Sprite m_sprite;
};

Character.cpp:

  #include Character.h 

Character :: Character(){}

Character :: Character(std :: string name){
m_name =名称;
m_orientation = 0;

runningAnimation = Animation();
}

Character ::〜Character(){
}

void Character :: draw(sf :: RenderTarget&target,sf :: RenderStates States)const {
target.draw(m_sprite,States);
}

void Character :: Move(float value){
m_sprite.setTextureRect(runningAnimation.Play());
m_position.x + =值;
m_sprite.setPosition(m_position);
}

无效字符:: SetTexture(std :: string filename){
filename = TEXTURE_FILES_PREFIX + filename;

//如果(!m_texture.loadFromFile(filename))
std :: cout<<则加载整个纹理文件
加载纹理文件时出错:<<文件名<< std :: endl;

//设置纹理(默认情况下,初始化为空闲状态)和位置
std :: vector< sf :: IntRect> runningFrames {
sf :: IntRect(67,45,19,28),
sf :: IntRect(116,46,20,27),
sf :: IntRect(166,48 ,20,25),
sf :: IntRect(217,45,22,28),
sf :: IntRect(266,46,19,27),
sf :: IntRect (316,48,20,25)
};

runningAnimation.SetFrames(runningFrames);
m_sprite.setTexture(m_texture);
m_sprite.setTextureRect(runningAnimation.Play());
m_sprite.setPosition(m_position);
}

CharacterManager.h:

  #pragma一次

#include< vector>
#include< map>
#include< iostream>
#include< SFML\Graphics.hpp>
#include AliveCharacter.h
#include Npc.h
#include Animation.h
#include CharacterStats.h

枚举CharacterType
{
NPC,
活着,
一般
};

//包含字符实体向量的类,并根据数据文件创建这些实体的动画(以后)
class CharacterManager:public sf :: Drawable {
public:
CharacterManager();
〜CharacterManager();

//加载文件并将内容存储在数据字符串中(暂时不使用)
void LoadDataFile(std :: string filename);
//创建一个字符并将其添加到列表中
void CreateCharacter(std :: string name,std :: string textureFilename,CharacterType characterType,sf :: Vector2f pos);
void CreateCharacter(std ::字符串名称,std ::字符串textureFilename,CharacterType characterType,sf :: Vector2f pos,std :: map< std :: string,Animation *>动画);
void CreateCharacter(std :: string name,std :: string textureFilename,CharacterType characterType,sf :: Vector2f pos,std :: map< std :: string,Animation *>动画,CharacterStats统计信息);

void Move(浮点值);

字符* GetCharacter(std :: string name){return m_characters [name]; }

private:
//调用每个存储的Character的draw()函数
virtual void draw(sf :: RenderTarget& target,sf :: RenderStates States)const;

std :: string m_data;
std :: map< std :: string,Character *> m_characters;
};

CharacterManager.cpp:

  #include CharacterManager.h 

CharacterManager :: CharacterManager(){
m_characters = std :: map< std :: string,Character *>( );
}

CharacterManager ::〜CharacterManager(){
//删除m_characters;
}

void CharacterManager :: LoadDataFile(std :: string filename){
// TODO:加载文件内容
}

void CharacterManager :: CreateCharacter(std :: string name,std :: string textureFilename,CharacterType characterType,sf :: Vector2f pos){
字符new_character(name); //创建一个通用字符...

// ...并根据字符类型参数对其进行特殊化
开关(characterType)
{
case NPC :
new_character = Npc(名称);
休息时间;
活着的情况:
new_character = AliveCharacter(name);
休息时间;
默认值:
new_character = Character(name);
休息时间;
}

//设置纹理,位置并添加到字符列表中
new_character.SetTexture(textureFilename);
new_character.SetPosition(pos);
m_characters.insert({name,& new_character});
}

void CharacterManager :: CreateCharacter(std :: string name,std :: string textureFilename,CharacterType characterType,sf :: Vector2f pos,std :: map< std :: string,动画*>动画){
CreateCharacter(textureFilename,name,characterType,pos);
m_characters [name]-> SetAnimations(animations);
}

void CharacterManager :: CreateCharacter(std :: string name,std :: string textureFilename,CharacterType characterType,sf :: Vector2f pos,std :: map< std :: string,动画*>动画,CharacterStats统计信息){
CreateCharacter(textureFilename,name,characterType,pos);
m_characters [name]-> SetAnimations(animations);
// m_characters [name]-> SetStats(stats);
}

void CharacterManager :: Move(float value){
每个(m_characters中的std :: pair< std :: string,Character *>对){ b $ b字符*字符= pair.second;
character-> Move(value);
}
}

void CharacterManager :: draw(sf :: RenderTarget& target,sf :: RenderStates States)const {
每个(std :: pair< ; std :: string,Character *>对m_characters){
Character * character = pair.second;
target.draw(* character);
}
}

最后是Main.cpp,您可以在其中看到在评论中我尝试的尝试没有成功:

  #include Map.h 
#include CharacterManager.h

int main()
{
sf :: RenderWindow窗口(sf :: VideoMode(WINDOW_SIZE_X,WINDOW_SIZE_Y),WINDOW_TITLE);
window.setFramerateLimit(WINDOW_FRAMERATE);

地图地图;
int pos = WINDOW_SIZE_X / 2-MAP_SIZE_X / 2;
浮点运动= 0;
map.SetPosition(pos);
map.SetGroundTexture( Foreground / Tileset.png);
map.SetBackgroundTexture( Background / BGFront.png);

CharacterManager charManager;
charManager.CreateCharacter( main, Characters / test-character.png,ALIVE,sf :: Vector2f(400,WINDOW_SIZE_Y-HEIGHT_OF_GROUND-28));

而(window.isOpen())
{
sf :: Event事件;
while(window.pollEvent(event))
{
if(event.type == sf :: Event :: Closed)
window.close();
if(event.type == sf :: Event :: KeyPressed)
{
if(event.key.code == sf :: Keyboard :: Left)
运动= -MOVING_SPEED;
else if(event.key.code == sf :: Keyboard :: Right)
运动= MOVING_SPEED;
}
else if(event.type == sf :: Event :: KeyReleased)
运动= 0;
}

//移动地图
map.Scroll(movement);
//charManager.GetCharacter(\"main)-> Move(移动);
charManager.Move(运动);

window.clear();
window.draw(map);
/ *字符* mainPerso = charManager.GetCharacter( main);
window.draw(* mainPerso); * /
window.draw(charManager);
window.display();
}

返回0;
}

我遇到的错误是返回值Play()函数末尾的Animation.cpp中的m_frames [m_currentFrame] 行。将打开一个弹出窗口,显示:表达式:矢量下标超出范围。该错误仅在代码第二次通过此行时发生。第一次是从Character.cpp( m_sprite.setTextureRect(runningAnimation.Play()))的SetTexture()函数调用的,而该函数本身是从以下函数的CreateCharacter()函数调用的: CharacterManager( new_character.SetTexture(textureFilename)),此时,Animation对象看起来应该是应该的。



但这是第二次从Character( m_sprite.setTextureRect(runningAnimation.Play())的Move()函数中调用),它本身是从CharacterManager(字符-> Move(值))的Move()函数调用的。至此,所有的Animation对象绝对看起来不应该如此。在调试模式下,我可以看到:



调试屏幕截图



正如我之前所说,我认为问题出在指针的使用上。当我尝试删除它们时,代码会运行,但出现白色方形问题。



我试图找到某种有关如何使用这种架构的教程,但是没有找到任何相关的内容。如果您知道一个,我会很乐意看的。

解决方案


之前,我认为问题出在指针的使用上。
当我尝试删除它们时,代码会运行,但出现白色的
方形问题。


是的,当使用纹理 Sprite 时,这是 SFML 的常见问题



让我们看一下 sf :: Sprite :: setTexture 参考:


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


因此,一个类如下所示,使用编译器默认生成的复制操作:

  class Foo {
public:
void setT (){
//生成纹理{t}
s.setTexture(t);
}
sf :: Sprite s;
sf ::纹理t;
};

会给您带来麻烦。因为当 Foo f(otherFoo); 复制时,在 Foo 的新创建实例中的子画面将具有指针到 otherFoo 的纹理-它是指向 sf :: Texture 的指针的浅表副本。删除 otherFoo 将在新构造的对象内创建一个悬空指针。



在这种情况下,您应该实现赋值操作为精灵制作纹理的深层副本。如果您不知道该怎么做,则应将赋值操作标记为已删除

  class Character:public sf :: Drawable {
public:
Character();
Character(std :: string name);
〜Character();

//添加了
Character& operator =(const Character&)= delete;
Character(const Character&)=删除;

void Move(浮点值);

然后,每次尝试复制 Character时,编译器都会给您一个错误实例。



如果已删除复制操作,则应使用指针。尝试失败,因为您存储了指向局部变量的指针。局部变量在函数作用域的末尾被删除,以后再引用它们是未定义的行为。



您必须创建 Character 由运算符 new

  void CharacterManager :: CreateCharacter (std :: string name,std :: string textureFilename,CharacterType characterType,sf :: Vector2f pos){
Character * new_character = new Character(name); //创建通用字符...

// ...
//设置纹理,位置并将其添加到字符列表
new_character-> SetTexture(textureFilename) ;
new_character-> SetPosition(pos);
m_characters.insert({name,new_character});
}


I'm trying to create a 2D sidescroller mini-game. For now, I only have a character with a sprite and one animation, which i'm trying to move using the left/right arrows. At first, I only had a Character class, storing the sprite of the character and its running animation. And it worked. But now, I'm trying to add a CharacterManager class, which will create all the characters to avoid doing it in the main, and which will manage their movements and draw them.

And it doesn't work anymore. I think my problems come from the fact that I have trouble using pointers, which I'm not really familiar with.

Here are the different classes I'm using :

Animation.h :

#pragma once
#include <vector>
#include <SFML/Graphics.hpp>
#include <stdexcept>
#include <ctime>
#include "Constants.h"

class Animation {
public:
    Animation();
    ~Animation();

    void SetFrames(std::vector<sf::IntRect> frames) { m_frames = frames; }
    sf::IntRect Play();

private:
    std::vector<sf::IntRect> m_frames;
    unsigned int m_currentFrame;
    float m_updateTime;
    float m_timeSinceLastFrame;
    float m_lastCallTimestamp;
    float m_currentTimestamp;
    bool m_firstCall;
};

Animation.cpp :

#include "Animation.h"

Animation::Animation() {
    m_currentFrame = 0;

    m_updateTime = 1.0f / ANIMATION_SPEED;
    m_timeSinceLastFrame = 0.0f;
    m_firstCall = true;
}

Animation::~Animation() {

}

sf::IntRect Animation::Play() {
    if (m_frames.size() == 0) {
        throw std::length_error("The frames vector is empty");
    }

    // Advance time and add the elapsed time to timeSinceLastFrame
    m_currentTimestamp = std::clock();

    // Ignore elapsed time if first call
    if (m_firstCall) {
        m_timeSinceLastFrame = 0.0f;
        m_lastCallTimestamp = m_currentTimestamp;
        m_firstCall = false; // Not first call anymore
    }
    else {
        m_timeSinceLastFrame += (m_currentTimestamp - m_lastCallTimestamp) / CLOCKS_PER_SEC;
        m_lastCallTimestamp = m_currentTimestamp;
    }

    // Next frame
    if (m_timeSinceLastFrame >= m_updateTime) {
        m_currentFrame++;
        m_timeSinceLastFrame = 0; 

        // Check animation end
        if (m_currentFrame >= m_frames.size()) {
            m_currentFrame = 0; // Reset frame progression
            m_firstCall = true; // Next passage will be the first call of a new animation

            /* TODO : return something to alert the end of the animation
            (like a specific rectint or set a variable to true and get it on the other side) */
        }
    }

    return m_frames[m_currentFrame];
}

Character.h :

#pragma once

#include<string>
#include<iostream>
#include <SFML/Graphics.hpp>
#include <vector>
#include <map>
#include "Constants.h"
#include "Animation.h"

class Character : public sf::Drawable {
public:
    Character();
    Character(std::string name);
    ~Character();

    void Move(float value);

    // Setters
    void SetTexture(std::string filename);
    void SetPosition(sf::Vector2f pos) { m_position = pos; };
    void SetAnimations(std::map<std::string, Animation*> animations) { m_animations = animations; };

protected:
    virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const;

    std::string m_name;
    unsigned int m_orientation; // 0 (default) = right | 1 = left
    std::map<std::string, Animation*> m_animations; 
    Animation runningAnimation; 
    sf::Vector2f m_position;
    sf::Texture m_texture;
    sf::Sprite m_sprite;
};

Character.cpp :

#include "Character.h"

Character::Character() {}

Character::Character(std::string name) {
    m_name = name;
    m_orientation = 0;

    runningAnimation = Animation();
}

Character::~Character() {
}

void Character::draw(sf::RenderTarget& target, sf::RenderStates states) const {
    target.draw(m_sprite, states);
}

void Character::Move(float value) {
    m_sprite.setTextureRect(runningAnimation.Play());
    m_position.x += value;
    m_sprite.setPosition(m_position);
}

void Character::SetTexture(std::string filename) {
    filename = TEXTURE_FILES_PREFIX + filename;

    // Load the entire texture file
    if (!m_texture.loadFromFile(filename))
        std::cout << "Error loading texture file : " << filename << std::endl;

    // Set the texture (by default, initialize to idle state) and the position
    std::vector<sf::IntRect> runningFrames{
        sf::IntRect(67, 45, 19, 28),
        sf::IntRect(116, 46, 20, 27),
        sf::IntRect(166, 48, 20, 25),
        sf::IntRect(217, 45, 22, 28),
        sf::IntRect(266, 46, 19, 27),
        sf::IntRect(316, 48, 20, 25)
    };

    runningAnimation.SetFrames(runningFrames);
    m_sprite.setTexture(m_texture);
    m_sprite.setTextureRect(runningAnimation.Play());
    m_sprite.setPosition(m_position);
}

CharacterManager.h :

#pragma once

#include <vector>
#include <map>
#include <iostream>
#include <SFML\Graphics.hpp>
#include "AliveCharacter.h"
#include "Npc.h"
#include "Animation.h"
#include "CharacterStats.h"

enum CharacterType
{
    NPC,
    ALIVE,
    GENERAL
};

// Class containing a vector of character entities and creates the animations of these entities from a data file (later)
class CharacterManager : public sf::Drawable {
public :
    CharacterManager();
    ~CharacterManager();

    // Loads the file and stores the content inside data string (not used for now)
    void LoadDataFile(std::string filename); 
    // Create a character and add it to the list
    void CreateCharacter(std::string name, std::string textureFilename, CharacterType characterType, sf::Vector2f pos);
    void CreateCharacter(std::string name, std::string textureFilename, CharacterType characterType, sf::Vector2f pos, std::map<std::string, Animation*> animations);
    void CreateCharacter(std::string name, std::string textureFilename, CharacterType characterType, sf::Vector2f pos, std::map<std::string, Animation*> animations, CharacterStats stats);

    void Move(float value);

    Character* GetCharacter(std::string name) { return m_characters[name]; }

private :
    // Calls the draw() function of each stored Character
    virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const;

    std::string m_data;
    std::map<std::string, Character*> m_characters;
};

CharacterManager.cpp :

#include "CharacterManager.h"

CharacterManager::CharacterManager() {
    m_characters = std::map<std::string, Character*>();
}

CharacterManager::~CharacterManager() {
    //delete m_characters;
}

void CharacterManager::LoadDataFile(std::string filename) {
    // TODO : load file content
}

void CharacterManager::CreateCharacter(std::string name, std::string textureFilename, CharacterType characterType, sf::Vector2f pos) {
    Character new_character(name); // Create a generic character...

    // ... and specialise it depending on the character type param
    switch (characterType)
    {
    case NPC:
        new_character = Npc(name);
        break;
    case ALIVE:
        new_character = AliveCharacter(name);
        break;
    default:
        new_character = Character(name);
        break;
    }

    // Set texture, position and add to the characters list
    new_character.SetTexture(textureFilename);
    new_character.SetPosition(pos);
    m_characters.insert({ name, &new_character });
}

void CharacterManager::CreateCharacter(std::string name, std::string textureFilename, CharacterType characterType, sf::Vector2f pos, std::map<std::string, Animation*> animations) {
    CreateCharacter(textureFilename, name, characterType, pos);
    m_characters[name]->SetAnimations(animations);
}

void CharacterManager::CreateCharacter(std::string name, std::string textureFilename, CharacterType characterType, sf::Vector2f pos, std::map<std::string, Animation*> animations, CharacterStats stats) {
    CreateCharacter(textureFilename, name, characterType, pos);
    m_characters[name]->SetAnimations(animations);
    //m_characters[name]->SetStats(stats);
}

void CharacterManager::Move(float value) {
    for each (std::pair<std::string, Character*> pair in m_characters) {
        Character* character = pair.second;
        character->Move(value);
    }
}

void CharacterManager::draw(sf::RenderTarget& target, sf::RenderStates states) const {
    for each (std::pair<std::string, Character*> pair in m_characters) {
        Character* character = pair.second;
        target.draw(*character);
    }
}

And finally the Main.cpp, where you can see in comments the things I tried without success :

#include "Map.h"
#include "CharacterManager.h"

int main()
{
    sf::RenderWindow window(sf::VideoMode(WINDOW_SIZE_X, WINDOW_SIZE_Y), WINDOW_TITLE);
    window.setFramerateLimit(WINDOW_FRAMERATE);

    Map map;
    int pos = WINDOW_SIZE_X / 2 - MAP_SIZE_X / 2;
    float movement = 0;
    map.SetPosition(pos);
    map.SetGroundTexture("Foreground/Tileset.png");
    map.SetBackgroundTexture("Background/BGFront.png");

    CharacterManager charManager;
    charManager.CreateCharacter("main", "Characters/test-character.png", ALIVE, sf::Vector2f(400, WINDOW_SIZE_Y - HEIGHT_OF_GROUND - 28));

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
            if (event.type == sf::Event::KeyPressed)
            {
                if (event.key.code == sf::Keyboard::Left)
                    movement = -MOVING_SPEED;
                else if (event.key.code == sf::Keyboard::Right)
                    movement = MOVING_SPEED;
            }
            else if (event.type == sf::Event::KeyReleased)
                movement = 0;
        }

        // Move the map
        map.Scroll(movement);
        //charManager.GetCharacter("main")->Move(movement);
        charManager.Move(movement);

        window.clear();
        window.draw(map);
        /*Character* mainPerso = charManager.GetCharacter("main");
        window.draw(*mainPerso);*/
        window.draw(charManager);
        window.display();
    }

    return 0;
}

The error I'm getting is on the return m_frames[m_currentFrame] line in Animation.cpp, in the end of the Play() function. A pop-up window opens saying : "Expression: vector subscript out of range". This error only happens the second time the code goes through this line. The first time it's called from the SetTexture() function of Character.cpp (m_sprite.setTextureRect(runningAnimation.Play())), itself called from the CreateCharacter() function of the CharacterManager (new_character.SetTexture(textureFilename)), and at this point the Animation object looks as it should.

But the second time, it's called from the Move() function of Character (m_sprite.setTextureRect(runningAnimation.Play())), itself called from the Move() function of the CharacterManager (character->Move(value)). And at this point, all of the Animation object absolutely doesn't look like it should. In debug mode, I can see this :

Debug screenshot

As I said earlier, I think the problem comes from the use of pointers. When I'm trying to remove them, the code runs, but I get a white square problem.

I tried to find some sort of tutorial on how to use this kind of architecture, but didn't find anything relevant. If you know one, I'll be glad to look at it.

解决方案

As I said earlier, I think the problem comes from the use of pointers. When I'm trying to remove them, the code runs, but I get a white square problem.

yep, it is a common issue for SFML when using Texture and Sprite when shallow copy is used.

Let's look at sf::Sprite::setTexture reference:

The texture argument refers to a texture that must exist as long as the sprite uses it. Indeed, the sprite doesn't store its own copy of the texture, but rather keeps a pointer to the one that you passed to this function. If the source texture is destroyed and the sprite tries to use it, the behavior is undefined.

So, a class like below, with default generated copy operation by compiler:

class Foo { 
  public:
    void setT() {
        // generate texture {t}
        s.setTexture(t);
    }
    sf::Sprite s;
    sf::Texture t;
};

will bring troubles to you. Because when a copy is made by Foo f(otherFoo);, sprite in newly created instance of Foo will have pointer to texture of otherFoo - it is shallow copy of pointer to sf::Texture. Deleting otherFoo will make a dangle pointer inside new constructed object.

In this case, you should implement assignment operation which makes deep copy of texture for sprite. If you don't know how to do it, you should mark assignment operations as deleted:

class Character : public sf::Drawable {
public:
    Character();
    Character(std::string name);
    ~Character();

    // added    
    Character& operator=(const Character&) = delete;
    Character(const Character&) = delete;

    void Move(float value);

Then, compiler will give you an error for each attempt of copying of Character instance.

In case of deleted copy operation, you should rely on pointers. Your attempt failed, because you store pointer to local variables. Local variables are deleted at the end of a function scope, and referring to them later is undefined behaviour.

You have to create Character by operator new:

void CharacterManager::CreateCharacter(std::string name, std::string textureFilename, CharacterType characterType, sf::Vector2f pos) {
    Character* new_character = new Character(name); // Create a generic character...

    //...
    // Set texture, position and add to the characters list
    new_character->SetTexture(textureFilename);
    new_character->SetPosition(pos);
    m_characters.insert({ name, new_character });
}

这篇关于如何使用SFML库使用Manager类在C ++中管理角色及其动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆