Pointer class soll sich selbstständig löschen.



  • Ich würde vorschlagen, Du bastelst Dir noch eine ParticleSystem-Klasse. Wenn Du die startest, erzeugt die alle möglichen Partikel. Und die hat dann auch so was wie Update, was die Partikel bewegen lässt. Partikel prüft für jeden Partikel auch, ob er fertig ist. Und wenn er das ist, dann kannst Du ihn von dort aus löschen.

    Das lässt sich z.B. so machen:

    class ParticleSystem
    {
        typedef std::unique_ptr<Particle> ParticlePtr;
        typedef std::vector<ParticlePtr> Particles;
        typedef Particles::iterator ParticleIterator;
    
        Particles particles;
    
    public:
        void Start();
        void Update();
    };
    
    void ParticleSystem::Start()
    {
        // erzeuge Mal 100 Partikel
        for(unsigned int n = 0; n < 100; ++n)
            particles.push_back(new Particle(/* irgendwelche Parameter */)); // weiß gerade nicht, ob unique_ptr-ctor explicit ist
    }
    
    void ParticleSystem::Update()
    {  
        for(ParticleIterator it = particles.begin(); it != particles.end();)
        {
            (*it)->Update(); // (*it)-> verweist auf den Partikel
    
            if((*it)->Finished())
                it = particles.erase(it); // dank unique_ptr wird das automatisch gelöscht
            else
                ++it;
        }
    }
    

    Ungetestet, ist auch nur eine Anregung (und ich bin sicher, da haben ein paar Forenkollegen auch noch einiges dran zu kritisieren ;)). Du kannst auch boost::ptr_vector nehmen, dann hast Du nicht dieses (*it)->

    Vielleicht ist Dir das jetzt auch zu viel, aber die Bestandteile zu lernen würde Dir sicherlich sehr weiterhelfen.



  • Ok dann werde ich mal den ganzen aufbau nochmal überdenken. Danke für die anregung. ABER wäre das erzeugen und löschen von pointer klassen so generel möglich oder ist das voller stuss?



  • Wie, so? Also mit meinem Code wird das Löschen automatisiert, das erzeugt keine Speicherlecks.

    Wenn Du ein Partikel erzeugst, das sich selbst löscht, musst Du jedenfalls ganz schön aufpassen, das kann ich nicht empfehlen. Denn ich schätze Mal, in jedem Frame wird vom Partikel eine Update-Methode oder so aufgerufen? Dann brauchst Du ja sowieso einen Container von Partikeln. Wer auch immer von außen auf das Partikel zugreift, muss das Löschen eben mitkriegen. Und das klappt nicht, wenn sich das Partikel selbst löscht, außer das Löschen wird eben von außen angestoßen und dann nutzt man doch wieder besser Smartpointer...



  • Sicher, dass jedes einzelne Partikel dynamisch angefordert werden soll? Das kann bei vielen kurzlebigen Partikeln zu einem echten Performance-Bottleneck werden.

    Eisflamme, so zu iterieren ist ebenfalls langsam, da vector::erase() alle nachfolgenden Elemente verschiebt. Ich würde eher std::remove_if() verwenden.



  • Ja, das war jetzt nicht groß durchdacht. Man nutzt ja für Partikelsysteme gerne auch Mal eigene Allokatoren oder Pools, das wäre dann wohl besser.

    Auch beim erase hast Du völlig recht.



  • std::remove_if löscht aber die Elemente nicht, sondern schiebt sie nur ans Ende. Um sie wirklich zu löschen wäre ja dann noch immer ein erase notwendig.

    Ist das erase-remove-idiom da wirklich im Vorteil?



  • Ja, weil die Verschiebung der danachfolgenden Elemente der Haupt-Performance-Fresser ist. erase-swap-Idiom (wie auch immer es genau heißt) nutzt eben nur den swap und ein erase mit konstanter Laufzeit.



  • Eisflamme schrieb:

    Man nutzt ja für Partikelsysteme gerne auch Mal eigene Allokatoren oder Pools, das wäre dann wohl besser.

    Man kommt schon mit std::vector<Particle> recht weit. Gerade mit seiner Allokationsstrategie hat man kaum noch Allokationen, nur noch Kopien.

    llllll schrieb:

    Ist das erase-remove-idiom da wirklich im Vorteil?

    Ja, weil das erase() dann einmal am Schluss aufgerufen wird -- die Elemente werden also in linearer Zeit entfernt. Wenn man erase() in jeder Iteration aufruft, hat man quadratische Laufzeit.

    Eisflamme schrieb:

    Ja, weil die Verschiebung der danachfolgenden Elemente der Haupt-Performance-Fresser ist. erase-swap-Idiom (wie auch immer es genau heißt) nutzt eben nur den swap und ein erase mit konstanter Laufzeit.

    Meinst du swap() -and- pop_back() ? Das ist bei Partikelsystemen je nachdem ungünstig, da die Reihenfolge geändert wird. Wenn man keinen Depth-Buffer hat, werden die Partikel also in anderer Reihenfolge gezeichnet, was merkwürdig aussehen kann.



  • Hey, Ich habe mein Problem fürs erste gelöst und bin sehr zufrieden, danke für die tollen Ratschläge.

    Jetzt habe ich noch ne frage, die Sprites sollen sich in die Richtung bewegen in die sie ausgerichtet sind, tun sie aber nicht. Es sieht zwar aus wie eine nette kleine Explosion ^^ aber halt mit verdrehten Bildchen.

    _AllParticle[i]._Position.x += sin(_AllParticle[i]._Sprite.getRotation()) * _AllParticle[i]._Speed;
            _AllParticle[i]._Position.y += cos(_AllParticle[i]._Sprite.getRotation()) * _AllParticle[i]._Speed;
    


  • Bezeichner, die mit Unterstrich und Grossbuchstaben beginnen, sind reserviert. Du darfst diese nicht verwenden!

    Ansonsten, bringst du Grad und Bogenmass durcheinander?



  • Ja ok, ich werde meine Schreibeisse überarbeiten 🙂

    Der Code denn ich gepostet habe ist alles was ich verwende. Keine vorherige berechnung. Rotation ist ein zufallswert zwischen 0 &360.



  • Ja, eben.
    sin und cos brauchen aber Bogenmaß und nicht Gr
    ad.



  • Ok dann schau ich mal. Seit dem ich angefangen habe zu Programmieren fällt mir mein Mathe Defizit erst richtig auf 😕


Anmelden zum Antworten