EatTheBlocks

Präsentation und Organisation von eigenen Projekten
nufan
Wiki-Moderator
Beiträge: 2558
Registriert: Sa Jul 05, 2008 3:21 pm

Re: EatTheBlocks

Beitrag von nufan » Mo Jan 05, 2009 3:38 pm

+Fuss+ hat geschrieben:Hat zufällig einer gerade nen Link?
Wohin? Zu den SDL-Bibliotheken? Einfach über Synaptic. Oder hier. Externe Bibliotheken wie SDL_image finden sicher unter "libraries".

Vielleicht hast du SDL auf dem anderen Rechner "unabsichtlich" als Abhängigkeit zu einem GTK-Paket installiert.

Benutzeravatar
+Fuss+
Beiträge: 385
Registriert: Fr Nov 14, 2008 8:16 pm

Re: EatTheBlocks

Beitrag von +Fuss+ » Mo Jan 05, 2009 3:43 pm

Also GTK+ und so hab ich hier auf dem Rechner auch schon!
Ich wüsste jetzt auch keine andere Anwendung, an der das liegen könnte...
Deswegen wundert wich das ja so.

Welche Pakete sind das denn bei Synaptic? bei GTK+ waren das ja auch mehr als eins...

nufan
Wiki-Moderator
Beiträge: 2558
Registriert: Sa Jul 05, 2008 3:21 pm

Re: EatTheBlocks

Beitrag von nufan » Mo Jan 05, 2009 3:48 pm

+Fuss+ hat geschrieben:Welche Pakete sind das denn bei Synaptic? bei GTK+ waren das ja auch mehr als eins...
Ich hab da auch einige...

libsdl1.2debian
libsdl1.2debian-all
libsdl1.2-dev
libsdl-console
libsdl-gfx1.2-4
libsdl-gfx1.2-dev
libsdl-image1.2
libsdl-mixer1.2
libsdl-net1.2
libsdl-sound1.2
sdl-image
sdl-image-devel

Benutzeravatar
+Fuss+
Beiträge: 385
Registriert: Fr Nov 14, 2008 8:16 pm

Re: EatTheBlocks

Beitrag von +Fuss+ » Mo Jan 05, 2009 4:08 pm

Jo danke jetzt läufts!

MfG Fuss

Benutzeravatar
Kerli
Beiträge: 1456
Registriert: So Jul 06, 2008 10:17 am
Wohnort: Österreich
Kontaktdaten:

Re: EatTheBlocks

Beitrag von Kerli » Mo Jan 05, 2009 5:01 pm

dani93 hat geschrieben: Ich hab da auch einige...
[...]
Du brauchst eigentlich nur zwei Pakete. Alle anderen benötigten werden automatisch installiert:

Code: Alles auswählen

libsdl1.2-dev
libsdl-image1.2-dev
Und die Bibliotheken für Sound und Netzwerk werden bei diesem Spiel auch noch nicht benötigt.
dani93 hat geschrieben: Auch die Bilder hab ich selbst "gegimpt"
Warum speicherst du denn farbige Blöcke in Bilddateien? Fast 2 mb nur für einen schwarzen Hintergrund sind schon heftig. Erstens würde ich ein Bildformat mit einer Kompression verwenden - Die SDL unterstützt auch zb png - und zweitens würde ich einfärbige Bilder einfach mit der SDL direkt mit SDL_FillRect erstellen, bzw. direkt in den Bildbuffer schreiben.
dani93 hat geschrieben: * zufälligere Zufallszahlen ;) (sind immer gleich, keine Ahnung warum)
Ich weiß es schon, 'rand' ist nämlich kein Zufallsgenerator :D Schau dir einmal diesen Thread dazu an...
dani93 hat geschrieben: ** valgrind meldet bei mir einen Speicher-Leak (16 Byte). Ich hab keine Ahnung was das sein könnte. Die Bilder hab ich ja alle freigegeben. Kann es sein, dass das von einer SDL-Lib verursacht wird?
Erstens wird 'fruit_pic' nirgendwo freigegeben und zweitens steigst du an einigen Stellen im Programm mit 'exit' aus, so dass nicht immer alle Codeteile in denen Speicher freigegeben wird aufgerufen werden.
dani93 hat geschrieben: * Kann man ASCII-Zeichen auf ein Surface schreiben?? Oder muss ich dann immer ein Bild erstellen?
Ja, schau dir einmal SDL_ttf an...
dani93 hat geschrieben:
Fuss hat geschrieben:Da hängt man ja schon 3 mal an der Wand bevor man reagieren kann und eine Taste gedrückt hat...
Bei mir dauerts ohne lenken bis zum Crash 3 Sekunden. Sollte doch reichen ;)
Bei mir ist es auch nur so ca 1 Sekunde. Das liegt daran, dass alle Computer unterschiedlich schnell sind und du das nicht bei der Bewegung der Schlange berücksichtigst. Da aber die Schleife auf einem schnelleren Computer auch schneller durchläuft, ist die Schlange dort schneller. Du solltest als die immer die Dauer der Frames messen und diesen Wert als Grundlage für die Bewegung im nächsten Frame verwenden.

Ansonsten funktioniert es ja schon einmal recht gut, zumindest für ein erstes Programm ;)

Zu deinem Stil: Ich find ihn gar nicht einmal so schlecht, du solltest nur versuchen eine gewisse Zeilenbreite einzuhalten. Damit meine ich vor allem die beiden if-Abfragen, die grauenhaft zum Lesen sind :)
"Make it idiot-proof and someone will invent an even better idiot." (programmers wisdom)

OpenGL Tutorials und vieles mehr rund ums Programmieren: http://www.tomprogs.at

nufan
Wiki-Moderator
Beiträge: 2558
Registriert: Sa Jul 05, 2008 3:21 pm

Re: EatTheBlocks

Beitrag von nufan » Mo Jan 05, 2009 5:09 pm

Kerli hat geschrieben:Warum speicherst du denn farbige Blöcke in Bilddateien? Fast 2 mb nur für einen schwarzen Hintergrund sind schon heftig. Erstens würde ich ein Bildformat mit einer Kompression verwenden - Die SDL unterstützt auch zb png - und zweitens würde ich einfärbige Bilder einfach mit der SDL direkt mit SDL_FillRect erstellen, bzw. direkt in den Bildbuffer schreiben.
Wieder was gelernt ;)
Kerli hat geschrieben:Erstens wird 'fruit_pic' nirgendwo freigegeben und zweitens steigst du an einigen Stellen im Programm mit 'exit' aus, so dass nicht immer alle Codeteile in denen Speicher freigegeben wird aufgerufen werden.
Umpf... da hätt ich auch selber drauf kommen können...
Und wie kann ich das Problem lösen? Ohne exit häng ich in der Schleife...
atexit?
Kerli hat geschrieben:Ja, schau dir einmal SDL_ttf an...
Ok, thx.
Kerli hat geschrieben:Du solltest als die immer die Dauer der Frames messen und diesen Wert als Grundlage für die Bewegung im nächsten Frame verwenden.
Aha... etwas genauer bitte :D
Kerli hat geschrieben:Damit meine ich vor allem die beiden if-Abfragen, die grauenhaft zum Lesen sind :)
Ok, da hab ichs wirklich ein bisschen übertrieben ^^

Benutzeravatar
Kerli
Beiträge: 1456
Registriert: So Jul 06, 2008 10:17 am
Wohnort: Österreich
Kontaktdaten:

Re: EatTheBlocks

Beitrag von Kerli » Mo Jan 05, 2009 5:37 pm

dani93 hat geschrieben:Und wie kann ich das Problem lösen? Ohne exit häng ich in der Schleife...
atexit?
Entweder du führst eine Variable ein, von der abhängig ist ob die Schleife noch weiterlaufen soll und setzt diese zum beenden einfach auf 0:

Code: Alles auswählen

int run = 1;
while(run)
{
  //...
  switch(/* ... */)
  {
    // ...
    run = 0;
    // ...
  }
  //...
}
Und die zweite Möglichkeit ist, dass du die Behandlung der Nachrichten in eine Funktion auslagerst, und dort je nach Rückgabewert die Schleife beendest oder nicht.

Was mir jetzt noch aufgefallen ist: Was machst du denn wenn keine neue Nachricht kommt? Dann behandelst du einfach die vorherige noch einmal. Du musst auch überprüfen was SDL_PollEvent zurückgibt. Wenn es NULL zurückgibt, hat es nämlich keinen neuen Event gegeben. Außerdem solltest du in jedem Schleifendurchgang in einer weiteren Schleife solange SDL_PollEvent aufrufen bis du keine Events mehr bekommst, da sich sonst auch Events aufstauen könnten, die sonst nie behandelt werden...

Schau dir dazu doch auch meine Tutorials an. Zumindest den Teil mit der SDL, da siehst du dann auch ein Beispiel wie ich das gemeint habe:

http://www.tomprogs.at/spieleentwicklun ... -sdl.xhtml
http://www.tomprogs.at/spieleentwicklun ... ieck.xhtml
dani93 hat geschrieben:
Kerli hat geschrieben:Du solltest als die immer die Dauer der Frames messen und diesen Wert als Grundlage für die Bewegung im nächsten Frame verwenden.
Aha... etwas genauer bitte :D
Annahme: getMS() liefert die vergangenen Millisekunden seit dem Programmstart.

Code: Alles auswählen

while(1)
{
  time_start = getMS();
  
  renderObject();

  object.x += frame_time * move.x;
  object.y += frame_time * move.y;

  frame_time = getMS() - time_start;
}
Das war jetzt sehr pseudocodemäßig, es dürfte aber das Prinzip etwas deutlicher zeigen :)
Wenn die für ein Frame benötigte Zeit kürzer wird bewegt sich das Objekt auch langsamer...
"Make it idiot-proof and someone will invent an even better idiot." (programmers wisdom)

OpenGL Tutorials und vieles mehr rund ums Programmieren: http://www.tomprogs.at

nufan
Wiki-Moderator
Beiträge: 2558
Registriert: Sa Jul 05, 2008 3:21 pm

Re: EatTheBlocks

Beitrag von nufan » Mo Jan 05, 2009 5:56 pm

Kerli hat geschrieben:Was mir jetzt noch aufgefallen ist: Was machst du denn wenn keine neue Nachricht kommt? Dann behandelst du einfach die vorherige noch einmal. Du musst auch überprüfen was SDL_PollEvent zurückgibt. Wenn es NULL zurückgibt, hat es nämlich keinen neuen Event gegeben. Außerdem solltest du in jedem Schleifendurchgang in einer weiteren Schleife solange SDL_PollEvent aufrufen bis du keine Events mehr bekommst, da sich sonst auch Events aufstauen könnten, die sonst nie behandelt werden...
Ich hab den Teil jetzt geändert:

Code: Alles auswählen

  while (run)
  {
  
    draw_snake (direction, newx, newy);
    
    draw_fruit ();
    
    checkevent = SDL_PollEvent (&event);
  
    while (SDL_PollEvent (&empty) != 0); 
    
    check_border_score (&run);
    
    
    if (checkevent != 0)
    {
    
      switch (event.type)
      {
    
        case SDL_KEYDOWN: check_input (event, &run);
                          break;
                        
        case SDL_QUIT: exit (0);
    
      }
    
    }
    
    
    SDL_FillRect (screen, NULL, black);
    
    move_snake (direction, newx, newy);
  
  }
run wird dann in den Unterprogrammen (wenn nötig) auf 0 gesetzt.
Kerli hat geschrieben:Annahme: getMS() liefert die vergangenen Millisekunden seit dem Programmstart.

Code: Alles auswählen

    while(1)
    {
      time_start = getMS();
     
      renderObject();

      object.x += frame_time * move.x;
      object.y += frame_time * move.y;

      frame_time = getMS() - time_start;
    }
Das war jetzt sehr pseudocodemäßig, es dürfte aber das Prinzip etwas deutlicher zeigen :)
Wenn die für ein Frame benötigte Zeit kürzer wird bewegt sich das Objekt auch langsamer...
Dann verwende ich also "frame_time" als das, was jetzt "speed" ist.
Gibt es die Funktion getMS() bereits oder muss ich die selbst schreiben (thread + delay + counter)?

EDIT: difftime sollte gehen.

srand() will bei mir nicht...

Code: Alles auswählen

void new_fruit ()
{
  
  fruit.x = ((srand () % (screen -> w - 20)) + 5);
  srand (time(NULL));
  
  fruit.y = ((srand () % (screen -> h - 20)) + 5);

}
Und gcc meldet

Code: Alles auswählen

Zu wenige Argumente für Funktion »srand«
EDIT:
Problem mit srand gelöst.
Es muss rand und nicht srand heißen :)

Benutzeravatar
Kerli
Beiträge: 1456
Registriert: So Jul 06, 2008 10:17 am
Wohnort: Österreich
Kontaktdaten:

Re: EatTheBlocks

Beitrag von Kerli » Mo Jan 05, 2009 6:25 pm

dani93 hat geschrieben: Problem mit srand gelöst.
Es muss rand und nicht srand heißen :)
Genau, srand nur am Programmstart zum initialisieren der Zufallsfunktion mit einem Startwert.
dani93 hat geschrieben: Ich hab den Teil jetzt geändert:

Code: Alles auswählen

  while (run)
  {
  
    draw_snake (direction, newx, newy);
    
    draw_fruit ();
    
    checkevent = SDL_PollEvent (&event);
  
    while (SDL_PollEvent (&empty) != 0); 
    
    check_border_score (&run);
    
    
    if (checkevent != 0)
    {
    
      switch (event.type)
      {
    
        case SDL_KEYDOWN: check_input (event, &run);
                          break;
                        
        case SDL_QUIT: exit (0);
    
      }
    
    }
    
    
    SDL_FillRect (screen, NULL, black);
    
    move_snake (direction, newx, newy);
  
  }
run wird dann in den Unterprogrammen (wenn nötig) auf 0 gesetzt.
So ist es nicht gut :D Wenn du in einem Frame nämlich mehr als ein Event bekommst gehen diese verloren. Besser ist es so:

Code: Alles auswählen

while (run)
{   
  while( SDL_PollEvent (&event) ) // Alle anstehenden Events abarbeiten
  {    
      switch (event.type)
      {
    
        case SDL_KEYDOWN: check_input (event, &run);
                          break;                        
        case SDL_QUIT: run = 0;
                          break;    
      }    
    }
    
    draw_snake (direction, newx, newy);    
    draw_fruit ();   
    
    SDL_FillRect (screen, NULL, black);    

    check_border_score (&run);
    move_snake (direction, newx, newy);
  
  }
Du solltest auch schauen, dass du ein Vermischen von rendern und bewegen vermeidest. Dh. zuerst rendern und dann bewegen...
dani93 hat geschrieben: Dann verwende ich also "frame_time" als das, was jetzt "speed" ist.
Gibt es die Funktion getMS() bereits oder muss ich die selbst schreiben (thread + delay + counter)?
Nein, die gibt es nicht. Ich verwende dafür zb boost::posix_time::microsec_clock::local_time(), das eigentlich sehr genaue Ergebnisse auf allen Platformen liefert. Sonst kannst du es auch mit SDL_GetTicks() versuchen.
"Make it idiot-proof and someone will invent an even better idiot." (programmers wisdom)

OpenGL Tutorials und vieles mehr rund ums Programmieren: http://www.tomprogs.at

Benutzeravatar
fat-lobyte
Beiträge: 1398
Registriert: Sa Jul 05, 2008 12:23 pm
Wohnort: ::1
Kontaktdaten:

Re: EatTheBlocks

Beitrag von fat-lobyte » Di Jan 06, 2009 12:55 am

dani93 hat geschrieben:
+Fuss+ hat geschrieben:Die beiden Pakete sind bei mir schon in der neusten Version vorhanden.
im Ordner /usr/include/SDL gibt es aber SDL_image.h nicht.
Hmmm....
dann das runterladen und mit dem Paket "alien" in ein .deb konvertieren.
Also

Code: Alles auswählen

$ alien SDL_image-1.2.7-1.src.rpm
Und dann einfach Doppelklick auf die .deb-Datei.

EDIT:
wenn das nicht geht, dann dieses
http://www.libsdl.org/projects/SDL_imag ... 1.i386.rpm
und wenn das auch nicht geht, dann das:
http://www.libsdl.org/projects/SDL_imag ... 1.i386.rpm
;)

Ich glaube es ist das erste vom EDIT.
Na du Held? Gratuliere, du hast Fuss' System zerstört! bist du jetzt zufrieden? ;-)
Fuss, kannst dich schon mal bei dani bedanken.

NIEMALS IM SYSTEM HERUMPFUSCHEN WO MAN SICH NICHT AUSKENNT! IMMER DEN PAKETMANAGER MACHEN LASSEN
Hier ein paar "dont's" aus meiner Ratschlagskiste:
  • NIEMALS selbst hand an Systemdateien (dateien, die man nur mit sudo verändern kann) anlegen (sie löschen, verschieben, ersetzen) wenn du nicht WIRKLICH weißt was du tust.
  • Am besten ganz auf RPM konvertierer verzichten
  • Am besten ganz auf heruntergeladene Pakete verzichten
  • Am besten ganz auf inoffizielle Paketquellen verzichten
  • So wenig wie möglich selbst kompilieren. Wenns doch sein muss, sind ein paar dinge zu beachten:
    • Vorher das Readme lesen (oder andere Anleitungen und Dateien die beiliegen, oder die Information von dort, wo du das Paket herhast). WENN DU ES NICHT VERSTEHST, LASS DIE FINGER DAVON!
    • Am besten nur lokal (in deinem /home/$user/ Verzeichnis installieren
    • Wenns das obere nicht geht, dann nur unter /usr/local installieren, und versichern dass das Installerskript nichts wichtiges überschreibt
Ich weiß das war ein bisschen streng. Wer Zeit hat, und das betreffende System kein produktives (und nicht euer einziges) System ist, dem kann ich nur das gelegentliche missachten dieser Regeln empfehlen. ;-)
(Echt jetzt! Man lernt selten so schnell so viel über sein System, wenn man nicht gerade versucht etwas zu reparieren, was man selbst zerstört hat! :-) )
Haters gonna hate, potatoes gonna potate.

Antworten