Bild flimmert bei Bewegung, Probleme beim Löschen von Elementen



  • Hallo,

    ich habe vor Ikaruga(für Leute, die das nicht kennen: das ist ein shoot-em-up in 2D Perspektive) nachzumachen. Ich benutze Borland Builder 6 und hab das Spiel bisher damit programmiert.
    Bisher gab es Probleme beim Schießen. Wenn ungefähr 100 Schuss abgegeben wurde, fängt das Spiel an zu hängen und wird immer schlimmer, je mehr ich schieße, was natürlich klar ist. Mein Gedanke war es eigentlich , dass alle Schusselemente gelöscht werden, wenn man sie nicht mehr sieht, bisher habe ich es nur hingekriegt, dass die Schüsse nicht mehr sichtbar gemacht werden und sich auch nicht mehr bewegen. Diese Lösung verzögert nur das Hängen im Spiel.

    Quellcode

    in Header wurde

    TShape *shoot;

    deklariert

    Schüsse werden so hergestellt:
    global deklariert:
    int schuesse=0;

    shoot=new TShape(this);
    shoot->Parent=this;
    shoot->Name="shoot"+IntToStr(shoot+1);
    shoot->Brush->Color=clBlue;
    shoot->Pen->Color=clWhite;
    shoot->Shape=stEllipse;
    shoot->Height=25;
    shoot->Width=9;
    shoot->Top=Shape1->Top;
    shoot->Left=Shape1->Left+7;
    schuesse++;

    bisher habe ich folgendes als vorläufige Lösung genommen

    for (int i = schuesse; i>=1; i--)
    {
    if(static_cast<TShape*>(FindComponent("shoot"+IntToStr(i)))->Top>-20)
    {
    static_cast<TShape*>(FindComponent("shoot"+IntToStr(i)))->Top=static_cast<TShape*>(FindComponent("shoot"+IntToStr(i)))->Top-10;
    }
    else
    {
    static_cast<TShape*>(FindComponent("shoot"+IntToStr(i)))->Visible=false;
    }
    /*if(static_cast<TShape*>(FindComponent("shoot"+IntToStr(i)))->Visible==false)
    {
    delete static_cast<TShape*>(FindComponent("shoot"+IntToStr(i)));
    shot++;
    }*/

    geplant habe ich anstatt der Lösung folgendes:
    int schuesse=0, geschossen=1;
    for (int i = schuesse; i>=geschossen; i--)
    {
    if(static_cast<TShape*>(FindComponent("shoot"+IntToStr(i)))->Top>-20)
    {
    static_cast<TShape*>(FindComponent("shoot"+IntToStr(i)))->Top=static_cast<TShape*>(FindComponent("shoot"+IntToStr(i)))->Top-10;
    }
    else
    {
    static_cast<TShape*>(FindComponent("shoot"+IntToStr(i)))->Visible=false;
    }
    if(static_cast<TShape*>(FindComponent("shoot"+IntToStr(i)))->Visible==false)
    {
    delete static_cast<TShape*>(FindComponent("shoot"+IntToStr(i)));
    geschossen++;
    }

    Mein zweites Problem ist ist folgendes: ich habe ein Bild für den Hintergrund in das Programm eingefügt und es soll sich regelmäßig nach unten bewegen, sodass vorkommt, dass man nach vorne fliegt. Bis dahin funktioniert das, in bestimmten Zeilen ist das Bild bei der Bewegung nicht sichtbar.
    Ich hab mir gedacht, dass das ein VSync Problem ist, aber ich hab keine Ahnung wie ich das Lösen kann. Ich habe mir gedacht, dass man da etwas mit opengl machen muss aber ich hab bisher noch nicht wirklich kapiert, wie man da eine Library ein das Programm einfügt.

    Ein drittes Problem ist der Sound. Mit
    PlaySound("sound1.wav",NULL,SND_FILENAME|SND_ASYNC); kann ich Sounds abspielen, aber wenn in der Zeit wo ein Sound abgespielt wird ein anderer Sound(kann auch der gleiche Sound sein) abgespielt wereden soll, wird die Wiedergabe vom ersten Sound abgebrochen.

    Ich dachte ich könnte das Problem mit der SDL Library lösen, aber damit habe ich Probleme und selbst die Seite von SDL hat mir nicht weitergeholfen(http://www.libsdl.org/faq.php?action=listentries&category=4#46). Damit denke ich mal, dass das Problem gelöst wird aber ich habe es nicht hinbekommen, die Library herzustellen

    Mal ganz nebenbei: Ich mache das Spiel als Schulprojekt und will damit eine möglichst gute Note bekommen. Ich habe das Programm bisher in C++ geschrieben aber ein Freund von meinen Bruder hat gefragt, ob ich auch den Game Maker benutzen dürfte. Was haltet ihr eigentlich von dem Game Mak, wenn ich das Fragen dürfte.



  • Also, ich kann hier nicht Helfen mit deinen Problemen ^^

    Aber:

    Game Maker = Anwenderprogramm
    C++ = Programmiersprache

    Ausserdem würde ich dir empfehlen mal einen Blick auf die SMFL Library zu werfen, falls dir SDL nicht weiterhelfen konnte (ausserdem ist diese ja in C++ geschrieben und nicht wie SDL, in C)



  • Mit C++Builder hab ich auch angefangen und habe dann dutzende TImages über den Bildschirm geschoben und mit über hundert Timern den Ablauf geregelt. Deswegen kann ich dir auch sagen, dass das so nichts wird 🙂
    Da SetPixel so unglaublich langsam ist, bin ich dazu übergegangen, mir meine Pixel selbst in einem Buffer zurechtzurücken und den dann nur noch auf die Form zu blitten.
    Die Arbeit kannst du dir aber sparen, indem du gleich SFML benutzt. Hardwarebeschleunigung bekommst du dann sogar noch gratis dazu (glaube ich jedenfalls).

    Edit: eine Zwischenstufe gibt's noch: mit CopyRect alle deine Grafiken auf EINE Zeichenfläche kopieren und dann den Hintergrund an den transparenten Stellen wiederherstellen (oder auch nicht). Dann hast du zumindest das Geflacker nicht mehr.



  • Also wenn du wirklich ein Spiel machen willst, dann würde ich dir zu so etwas, wie SFML raten, oder HGE. Was beides Plattformen sind, mit welchem man recht leicht einfache Multimediaanwendungen schreiben kann. (Also Grafik, Sound, Input).

    Das mit den Schüssen würde ich so lösen, dass du welche erstellst und diese dann in einer Liste oder so speicherst. Dann gehst du in jedem Frame (oder wenn du die halt bewegen willst) die gesamte Liste durch und bewegst die Schüsse. Gleichzeitig kannst du noch checken, ob sie in einer gewissen Entfernung sind und wenn ja, dann zerstörst du ihn wieder.

    #include <list>
    ...
    typedef std::list<Shoot> shots_container;
    shots_container shots;
    ...
    shots.push_back ( Shoot (/*parameter*/) );
    ..
    
    // updaten und ggf. löschen der Schüsse
    for (shots_container::iterator it = shots.begin (),end = shots.end(); it != end;)
    {
      // update jedes element
    
      if ( /* ist der schuss zu weit entfernt?*/ )
        it = shots.erase ( it );
      else
        ++it;
    }
    

    In etwa so.

    Was den Sound anbelangt, würde ich eben etwas externes empfehlen. Da kannst du dann auch mehrere Sounds gleichzeitig abspielen.



  • Na ja ich habe anfangs auch Spiele mit dem Borland C++ Builder geschrieben, für ganz simple Sachen kann man das auch machen.. (hab sogar mal ein Rennspiel gemaacht ;))
    Zu deinem Problem mit den Schüssen:
    Das mit Shapes zumachen ist schonmal keine gute Idee. Besser ist, du zeichnest im Grunde alles selbst, und zwar auf das Canvas des Forms. Quasi jeden Frame alles mit Weiß übermalen und dann die Schüsse raufzeichnen. (Entweder als einfache Kreise, oder du lädst vorher eine Grafik in ein TBitmap-Objekt und zeichnest das einfach per Canvas-Draw() auf das Form, ebenso geht das mit dem Hintergrundbild).
    Und ansonsten wäre es besser, ein festes Array von Schüssen anzulegen (bspw. 500 Stück groß). Du speicherst bei jedem Schuss davon, ob er sichtbar ist. Wenn du dann einen neuen Schuss abgibst, nimmst du den ersten nicht sichtbaren Schuss, setzt ihn auf sichtbar und setzt die Werte (Position etc), wenn dann ein Schuss aus dem Feld fliegt, setzt du ihn einfach auf nicht sichtbar. Rendern brauchst nur alle sichtbaren Schüsse.

    Das so zuu machen (also mit dem Zeichnen) ist zwar nicht gerade das Gelbe vom Ei, aber um erstmal einen Einstieg zu finden bzw. was zu testen reicht es eigentlich aus, da man keinen allzu großen Aufwand hat.

    Edit:
    Mist da war jemand schneller.^^ Die Schüsse in eine Liste zu packen ist quasi noch besser, nur wenn Hunderte Schüsse werden sollten, die jeden Frame neu erstellt und gelöscht werden müssen, wird es langsam ; )



  • Powerpaule schrieb:

    Die Schüsse in eine Liste zu packen ist quasi noch besser, nur wenn Hunderte Schüsse werden sollten, die jeden Frame neu erstellt und gelöscht werden müssen, wird es langsam ; )

    1. Meine Erfahrungen haben mir gezeigt, dass die STL nicht der Knacknpunkt ist, wenn man viele Objekte erzeugt und wieder löscht. Auch nicht sehr viele. Ich habe ein Partikelsystem, welches praktisch nix anderes macht und ich habe da keinen Engpass feststellen können. Zeichnen, updaten usw. ist einiges aufwändiger, als das erstellen oder durchiterieren.

    2. Gehe ich davon aus, dass std::list einen ähnlichen Mechanismus, wie den deinigen implementiert hat und da nicht wirklich jedes mal neuen Speicher anfordert, respektive zerstört. Dazu habe ich aber noch die Flexibilität, dass ich dennoch beliebig viele Objekte Speichern kann und nicht auf einen Wert beschränkt bin.



  • drakon schrieb:

    1. Meine Erfahrungen haben mir gezeigt, dass die STL nicht der Knacknpunkt ist, wenn man viele Objekte erzeugt und wieder löscht. Auch nicht sehr viele. Ich habe ein Partikelsystem, welches praktisch nix anderes macht und ich habe da keinen Engpass feststellen können. Zeichnen, updaten usw. ist einiges aufwändiger, als das erstellen oder durchiterieren.

    2. Gehe ich davon aus, dass std::list einen ähnlichen Mechanismus, wie den deinigen implementiert hat und da nicht wirklich jedes mal neuen Speicher anfordert, respektive zerstört. Dazu habe ich aber noch die Flexibilität, dass ich dennoch beliebig viele Objekte Speichern kann und nicht auf einen Wert beschränkt bin.

    Na ja ich hatte ebenfalls mal ein Partikelsystem mit einer std:list geschrieben, und das hat jedenfalls zu erheblichen Performance-Einbußen geführt, pro Sekunde wurden im Schnitt einige Hundert Objekte erzeugt/entfernt, dann hab ich's mit der oben beschrieben Methode gemacht, und es war um Welten besser... deswegen meinte ich das. Hatte mich ehrlich gesagt auch etwas gewundert, aber vielleicht war auch noch irgendwas anderes Hemmendes dabei..



  • also momentan versteh ich jetzt nicht unbedingt alles was ihr jetzt gesagt habt, aber ich werde mal mein bestes versuchen das erstmal so hinzukriegen, dass es besser läuft.

    btw. war es eigentlich eine gute idee mit c++ ein SPiel zu programmieren oder eher eine schlechte? Gibt es eventuell Programmierprachen womit man leichter Spiele programmieren kann?



  • Powerpaule schrieb:

    Na ja ich hatte ebenfalls mal ein Partikelsystem mit einer std:list geschrieben, und das hat jedenfalls zu erheblichen Performance-Einbußen geführt, pro Sekunde wurden im Schnitt einige Hundert Objekte erzeugt/entfernt, dann hab ich's mit der oben beschrieben Methode gemacht, und es war um Welten besser... deswegen meinte ich das. Hatte mich ehrlich gesagt auch etwas gewundert, aber vielleicht war auch noch irgendwas anderes Hemmendes dabei..

    Kann ich mir nicht vorstellen. Du hast aber schon im Release Modus getestet, oder? Ansonsten ist es schon kein Wunder..

    btw. war es eigentlich eine gute idee mit c++ ein SPiel zu programmieren oder eher eine schlechte? Gibt es eventuell Programmierprachen womit man leichter Spiele programmieren kann?

    Auf jeden Fall gibt es einfachere Sprachen. Die Frage ist aber eher wo du die Grenzen ziehen willst zwischen selber machen und schon fertiges benutzen. Z.b kannst du ja auch einen Game Builder nehmen. Kommen auch gute Sachen bei raus. Afaik bietet Blitzbasic einen recht einfachen (aber halt auch limitierten) Einstieg in Spieleprogrammierung.

    Das schöne an C++ ist halt, dass du an keine Grenzen stossen wirst, an welche du mit anderen Sprachen nicht schon früher gestossen wärst.



  • Ich denk mal ich bleibe mal bei c++, weil dies zudem die einzige Programiersprache ist, die ich kenne. Dennoch sind mir gewisse Sachen unbekannt.
    Das ist zwar ein Schulprojekt, dennoch ,öchte ich gerne alles ausreizen Zum Beispiel wollte ich das mit dem canvas machen, aber ich weiß absolut nicht, was das jetzt genau ist und was man damit machen kann. Ich weiß zwar das ein canvas eine Leinwand ist, aber ich weiß absolut keine Befehle, wie man das ausführt. Kann man an bestimmten Stellen im Kanvas ein Bild einfügen? Wenn ja, dann müsste ich erstmal herausfinden, wie die Befehle sind.



  • Gib mal im C++Builder-Editor irgendwo TCanvas ein und drücke F1. Damit hast du alle Informationen auf einen Schlag.
    TForm, TImage und so weiter haben alle ein Canvas-Objekt, auf dem du nach Belieben herumzeichnen kannst.



  • Ich habe ein paar von meinen Schulfreunden gefragt und die meinten, dass C++ zu langsam ist, um Spiele gut zu programmieren. Ein anderer meint, dass C++ keine richtige reale Zeit bestimmten kann, da die Zeit nur real ist, solange das Programm keine Engpässe enthält.



  • Ich glaube deine Schulkameraden sollten lieber ihre Mäuler halten :xmas1:



  • Deine Schulkameraden ver*****en dich. Sollte dir aber spätestens beim zweiten Punkt aufgefallen sein. Klingt mehr nach Philosophie als sonst irgendwas 🙂



  • es war mir schon klar, dass sie mich für dumm verkaufen wollen. Ich hab mir aber eher gedacht, dass sie sich mit C++ weniger auskennen.

    PS. Ein anderer hat gemeint, dass beim Spiel die Hardware mitspielen soll und nicht nur die Software. Also ich finde das ist schon eher ein Tipp, jedoch habe ich spätestens dann keine Ahnung, wie man das schreiben soll. Ich probier das Programm erstmal mit der SFML zu schreiben, da es mir so scheint, dass eigentlich alles da ist, was ich für die Spieleprogrammierung brauche. (und laut Features hat es sogar Hardwarebeschleunigung^^). Es muss ja kein Spiel sein, was für heutige Verhältnisse gut verkaufbar ist^^.



  • Ja, klar spielt die Hardware eine wichtige Rolle. Aber wenn du jetzt nicht gerade hochperformanten und speziell für eine Hardware angepasste Code schreibebn willst, dann spielt das mal keine Rolle. Und es gilt: Je teurer und neuere Teile verbaut sind, desto besser läufts. (natürlich nur Grundsätzlich und bei einem Vertraunswürdigen Verkäufter)

    Aber im Hobbybereich spielt das so gut, wie keine Rolle in heutigen Zeiten. 😉



  • Leider besitze ich einen Rechner der vor etwas mehr als 5 Jahren aktuell war. Ich hab schon gemerkt, dass das Programm auf schnelleren PCs besser läuft. Leider ist mein PC schon sehr veraltet und ich hab auch kein Geld mir einen neuen zu kaufen.



  • xbruceleex schrieb:

    Leider besitze ich einen Rechner der vor etwas mehr als 5 Jahren aktuell war. Ich hab schon gemerkt, dass das Programm auf schnelleren PCs besser läuft. Leider ist mein PC schon sehr veraltet und ich hab auch kein Geld mir einen neuen zu kaufen.

    Das würd ich jetzt nicht unbedingt als alt einstufen.
    Höchstwahrscheinlich wird der Takt deines Prozessors schon in GHz angegeben. Das reicht locker wenn du es "ordentlich" machst, d.h. für jedes Frame alles immer wieder neu mit Draw/CopyRect alles auf eine Zeichenfläche schiebst oder wenn du es mit SFML machst - selbst ohne Hardwarebeschleunigung.
    So ähnliche Spiele wie du gerade eins bastelst liefen auch schon auf nem 486er mit <50 MHz (da aber wohl nur mit Hardwarebeschleunigung).



  • Also ich kann mit SFML nicht arbeiten, da es immerwieder Linker Probleme gibt bzw. irgendwie die Library nicht erkennt. jedenfalls kompiliert der VC++ nicht.

    Einich komme mit Draw/CopyRect nicht klar. Kann mir jemand ein Beispiel geben, womit es funktioniert? Google hat mir da nicht wirklich weitergeholfen.



  • Du musst die Library auch dem Projekt hinzufügen etc.

    Na ja also auf meinem Rechner mit 2,1 Ghz (Athlon XP) geht das mit dem Canvas auf jeden Fall ausreichend für ganz simple Spiele, selbst in hohen Auflösungen (quasi Fullscreen).

    Ein ganz simples Beispiel:

    // Den Hintergrund weiß malen
    Form1->Canvas->Brush->Color = clWhite;
    Form1->Canvas->Brush->Style = bsSolid;
    Form1->Canvas->Pen->Color = clWhite;
    Form1->Canvas->Rectangle(0, 0, Form1->Width, Form1->Height);
    
    // Bild laden
    Graphics::TBitmap* bitmap = new Graphics::TBitmap;
    bitmap->LoadFromFile("bild.bmp");
    
    // Auf Form zeichnen an Position 10|10
    Form1->Canvas->Draw(10, 10, bitmap);
    
    [..]
    
    delete bitmap;
    

    Das ist natürlich sehr simpel, du musst das dann schon noch ausbauen, dass Bilder zum Beispiel natürlich nur einmal zu Beginn geladen werden und das Ganze alles in einer Schleife läuft (notfalls geht auch TTimer..) und immer wieder neu gezeichnet wird und die Bewegungen der Objekte etc.
    Kannst natürlich auch alles (erstmal) nur durch einfache Kreise zeichnen, die Funktionen dafür findest du in BCB-Hilfe.



  • Wieso denn auf einmal VC++, ich dachte, du benutzt C++Builder? 😕
    Du musst einfach nur die Include-Files in (d)einen Include-Ordner schieben und die SFML-Libs dazulinken.


Anmelden zum Antworten