2017-02-05 30 views
1

私は思ったコードでは苦労しています...非常に簡単なはずです。しかし、私はなぜ、私はそれを正しく行う方法を理解していないのか分からない。描画するアイテムを含むクラスを作成する(segフォールト)

sf::Drawableのすべてのインスタンスをstd::vectorに保存しようとしています。 問題は、sf::Drawableクラスは抽象クラスなので、ポインタを使用する必要があります。私はそれが正しいことを知っています。

私はstd::vector<std::vector<sf::Drawable*>>を使用していますので、アイテムを部分的にレンダリングしようとしています。それよりも優れたものを作る方法が分かっていれば、喜んで受け入れるでしょう。ベクトル、それは危険に大きく見え、私はそれが3つの部分を最大に保つことを試みる多くのメモリを使用すると確信しています。

問題は、スプライトがスコープから外れた場合(通常の場合)、ページクラスにポインタを追加すると(描画可能なオブジェクトへのポインタをすべて格納する)、セグメンテーションが発生します。問題は、スプライトやテキストを保持するために私のメインクラス(Gameという名前)を必要としないので、スプライトを削除できないようにする方法がわかりません。

ここにコードがあります、それは明確にする必要があります:

Page.cpp:

#include "Page.h" 

void Page::AddSprite(int coat, sf::Drawable* sprite) { 

    if (coat < m_sprites.size()) 
     m_sprites[coat].push_back(sprite); 

    else 
     m_sprites.push_back(std::vector<sf::Drawable*>(1, sprite)); 
} 

std::vector<std::vector<sf::Drawable*>>* Page::GetSprites() { 
    return &m_sprites; 
} 

Page.h:

#ifndef PAGE_H 
#define PAGE_H 

#include <SFML/Graphics.hpp> 
#include <vector> 
#include <memory> 

class Page 
{ 
    public: 
     Page(); 

     void AddSprite(int coat, sf::Drawable* sprite); 

     std::vector<std::vector<sf::Drawable*>>* GetSprites(); 

    protected: 
     std::vector<std::vector<sf::Drawable*>> m_sprites; 
    private: 
}; 

#endif // PAGE_H 

Game.cpp:

Game::Game() : m_numberItems(20) {} 

void Game::Run() { 
    sf::RenderWindow window(sf::VideoMode(SCREEN_WIDTH, SCREEN_HEIGHT), "Lost Items | Items remaining : " + std::to_string(m_numberItems)); 

    LoadSprites(); 

    while (window.isOpen()) { 
     sf::Event event; 

     while (window.pollEvent(event)) { 
      if (event.type == sf::Event::Closed) 
       window.close(); 
     } 

     window.clear(sf::Color::White); 

     std::vector<std::vector<sf::Drawable*>>* pageSprites = m_page.GetSprites(); 
     for (int i = 0; i < pageSprites->size(); i++) { 
      for (int j = 0; j < pageSprites->at(i).size(); j++) { 
       window.draw((*(pageSprites->at(i)[j]))); 
      } 
     } 

     window.display(); 
    } 
} 

void Game::LoadSprites() { 
    int CASE_LEN = CASE_LENGTH; // It was after a copy paste from another class, and I didn't want to change all the CASE_LEN to CASE_LENGTH 
    for (short i = 0; i < m_numberItems; i++) { 
     int x = rand() % ((SCREEN_WIDTH - CASE_LEN)/CASE_LEN); 
     int y = rand() % ((SCREEN_HEIGHT - CASE_LEN)/CASE_LEN); 
     sf::Sprite sprite(m_graphics.GetTilesTexture()); 
     sprite.setTextureRect(sf::IntRect(ITEM_X, ITEM_Y, CASE_LEN, CASE_LEN)); 
     sprite.setPosition(x * CASE_LEN, y * CASE_LEN); 
     m_page.AddSprite(0, &sprite); 
    } 
} 

Game.h:

#ifndef GAME_H 
#define GAME_H 

#include <SFML/Graphics.hpp> 
#include "Page.h" 

class Game 
{ 
    public: 
     Game(); 
     void Run(); 
     void LoadSprites(); 

     /** @brief The window width.*/ 
     static const unsigned short SCREEN_WIDTH = 1280; 

     /** @brief The window height */ 
     static const unsigned short SCREEN_HEIGHT = 736; 

     /** @brief The case length. */ 
     static const unsigned short CASE_LENGTH = 32; 

    protected: 

     unsigned char m_numberItems; 
     Page m_page; 

#endif // GAME_H 

私は十分に明らかにされてきた願っています、そしてあなたの答えをありがとう!

P.S.私はユニークなポインタ(std::unique_ptr<sf::Drawable>)を使用することができると思ったが、sf::Drawableという抽象化のためにstd::make_unique<sf::Drawable>を使用することができないため、それらを使用する方法がわからない。

+0

使用smartpointers、:: shared_ptrの – LeDYoM

+0

のstd :: shared_ptrのといないのはstd :: unique_ptrをなぜ(スマートポインタを使用して)のような何かを行うことができますか?私はそれらの違いを確信していません... ^^ 'また、どのように初期化するのですか?なぜなら私は抽象クラスでこれをやったことがないからです:c – FeelZoR

+0

'page.GetSprites()'は 'std :: vector >>'を返すことができます。そして、あなたは別の質問 - 「unique_ptrの使い方」を聞くことができます。 'shared_ptr'を使う - スプライトのライフサイクルに依存する – rustyx

答えて

1

{ 
    sf::Sprite sprite(m_graphics.GetTilesTexture()); 

    // ... 
    m_page.AddSprite(0, &sprite); 
} 

を使用すると、ローカル変数を格納し、その範囲の終わりのダングリング参照を持っています。

あなたは、あなたのケースのSTDで

{ 
    auto sprite = std::make_unique<sf::Sprite>(m_graphics.GetTilesTexture()); 

    // ... 
    m_page.AddSprite(0, std::move(sprite)); 
} 
+0

ありがとう!それはあなたのコメント(正確にはうまくいきました)で言ったこととはちょっと違いますが、私はその解決策にも挑戦します。本当に良いようです^^もう一度、ありがとう! – FeelZoR

関連する問題