Seite 1 von 2

Erstes Spiel//unvollständig

Verfasst: 10.11.2007 22:56
von Milchshake
Hi,
habe mir mal vorgenommen, ein Samus ähnliches Spiel (aber nicht so Komplex usw.) zu Programmieren.
Hier einmal der Downloadlink
http://rapidshare.com/files/68824043/Ju ... e.zip.html
Der Sourcecode liegt bei.
Open for Feed-Back :mrgreen:

Nur da ich mich schon Öfters in Tile-Engines probiert habe,
bräuchte ich eure hilfe.
Wenn ich etwas mit AddElement Aufrufe, kommt es ja unentlich oft
in einer Schleife. (Also es überlappt sich, der Counter schiest in die Höhe, das Programm wird langsamer)
Wie kann ich das Verhindern, ohne sowas wie ClearList() zu benutzen?

lg Milchshake

Verfasst: 10.11.2007 23:17
von ZeHa
Milchshake hat geschrieben:Wenn ich etwas mit AddElement Aufrufe, kommt es ja unentlich oft
in einer Schleife. (Also es überlappt sich, der Counter schiest in die Höhe, das Programm wird langsamer)
Wie kann ich das Verhindern, ohne sowas wie ClearList() zu benutzen?
Kann es grad nicht runterladen, muß laut rapidshare 110 Minuten warten :(

Aber vielleicht kannst Du den Code ja hier posten, aus Deiner Erklärung kann ich mir leider überhaupt nicht vorstellen, worum es bei Dir geht und was genau das Problem ist. Vielleicht kannst Du ja auch einfach nochmal genauer erklären, also den konkreten Sinn und Zweck, wo Du das mit der Liste einsetzt.

Verfasst: 10.11.2007 23:24
von Milchshake
Erstens:
Tut mir leid wegen dem Dummen Rapidshare, meine HP ist gerade down, hätte es nämlich sonst dort hochgeladen.

Zweitens:
Wenn ich jetzt eine Structur,List und eine Procedure (AddElement(blabalbal)usw.)
erstelle, und dann die Proceture benutze, steig die Linked List (die ich via CountList() ) gezählt habe, in das unentliche, und führt somit zur unspielbarkeit.
Habe ich das jetzt besser erklärt?

Verfasst: 10.11.2007 23:38
von ZeHa
Ehrlich gesagt nicht - es fehlt nämlich der Grund, weshalb Du das eigentlich tust. Erstellst Du dauernd neue Elemente (z.B. Gegner)? Fügst Du alles, was Du rendern willst, in eine Liste ein? Oder wofür ist die Liste gedacht?

Ohne diese Informationen kann Dir hier wahrscheinlich keiner weiterhelfen ;)

Verfasst: 11.11.2007 00:09
von AND51
> Wenn ich etwas mit AddElement Aufrufe, kommt es ja unentlich oft in einer Schleife
Du kannst nichts mit AddElement() "aufrufen". Diesen Ausdruck gibt es überhaupt nicht!
Mit AddElement() kannst du höchstens etwas in einer LinkedList speichern. Das meinst du sicherlich.

> steig die Linked List (die ich via CountList() ) gezählt habe, in das unentliche, und führt somit zur unspielbarkeit.
> Habe ich das jetzt besser erklärt?
Leider nein.
Es kommt auf die Art und Weise an, wie der Programmier codet bzw. der Coder programmiert. :lol:

Lange Rede, kurzer Sinn: Alles, was du jemals einer LinkedList hinzufügst, wirst du irgendwann löschen!

Als Beispiel mal die Sache mit den Schüssen: Du musst Schüsse nur so lange berechnen, bis sie außerhalb des Bildschirms sind. Dann kannst du sie mit DeleteElement() doch aus der Liste rausschmeißen, oder etwa nicht? Also steigt deine Anzahl doch nicht ins unendliche. :wink:
Speziell bei der Sache mit den Schüssen kannst du sogar eine Limitierung einbauen, sodass der Spieler nicht mehr als 3 Schüsse auf einmal abfeuern kann:

Code: Alles auswählen

If CountList(schuss()) <= 3
    ; Füge neuen Schuss hinzu
EndIf
Dieser Code erlaubt dem Spieler nicht mehr als 3 Schüsse. Das gibt's bei alten Spielen, wo damals die Computer/Konsolen noch nicht schnell genug waren um sehr viele Schüsse zu verarbetien, denke ich. Ein weiterer Grund ist, dass der Spieler es mit nur 3 Schuss gleichzeitig schwerer hat; dies erhöht den Schwierigkeitsgrad eines Spiels.

Alles, was du nicht mehr brauchst, sofort weg damit, raus aus der LinkedList! Es spielt auch keine Rolle, ob du irgendwie Structures in Kombination mit LinkedLists benutzt oder sonstwas.
Es liegt, wie gesagt an der Art, wie du programmierst, ob dein Spiel spielbar wird oder das Spiel doch eher als Benchmark-Test für deine CPU durchgeht.

Alles klar? :wink:

Verfasst: 11.11.2007 09:05
von Milchshake
Also, hier mal der Code:

Code: Alles auswählen

InitSprite()
InitKeyboard()

OpenScreen(1024,768,32," ")

Structure Show
  x.w
  y.w
  Width.w
  Height.w
  Image.w
  SpeedX.w
  SpeedY.w
EndStructure

Global NewList Show.Show()
Procedure AddShow(Sprite, x, y, SpeedX, SpeedY)
  AddElement(Show())           
  Show()\x      = x
  Show()\y      = y
  Show()\Width  = SpriteWidth(Sprite)
  Show()\Height = SpriteHeight(Sprite)
  Show()\Image  = Sprite
  Show()\SpeedX = SpeedX
  Show()\SpeedY = SpeedY
EndProcedure
CreateSprite(1, 64, 64)
StartDrawing(SpriteOutput(1))
  Box(0,  16, 32, 32, RGB(192,192,192))
  Box(32, 16, 32, 32, #Gray)
StopDrawing()

Repeat 
FlipBuffers()
ExamineKeyboard()
ClearScreen(0)

 StartDrawing(ScreenOutput())
 DrawingMode(1)
 DrawText(0,0," List :"+Str(CountList(Show())),#White)
 StopDrawing()
 
AddShow(1,500,500,0,0)

  ResetList(Show())
While NextElement(Show())

If Show()\y < 0        
  DeleteElement(Show())
Else
If Show()\x < 0       
  DeleteElement(Show())
Else
If Show()\x > 1024-Show()\Width
  DeleteElement(Show())
Else
If Show()\y > 760
  DeleteElement(Show())
Else
  DisplayTransparentSprite(Show()\Image, Show()\x, Show()\y)   ; Display the bullet
  
  Show()\y + Show()\SpeedY
  Show()\x + Show()\SpeedX
  EndIf
EndIf
EndIf
EndIf  
Wend

Until KeyboardPushed(#PB_Key_Escape) 
Mein Problem ist noch immer noch das Gleiche

Verfasst: 11.11.2007 12:03
von ZeHa
Mein Problem ist noch immer noch das Gleiche
Dann erklär es doch bitte mal!

Dein Code fügt pro Schleifendurchlauf ein neues Element rein, und wenn eins den Bildschirm verläßt (was keines tut, da SpeedX und SpeedY beide = 0 sind), würde er sie wieder aus der Liste entfernen. Passiert aber nie.

Das wird Dich ja nun sicherlich kaum überraschen, denn daß Du laufend Elemente hinzufügst, sie aber nicht löscht, wirst Du sicher selbst wissen.

Nun hast Du aber ein Spiel programmiert, und dort scheint es sich wohl um die Schüsse zu handeln. Diese werden auch in einer Liste verwaltet, aber doch rechtzeitig auch wieder gelöscht, wie ich sehe. Du hast ja sogar oben einen Bullet-Zähler, der irgendwann wieder auf 0 geht. Also kann es doch jetzt kein Problem mehr geben, oder nicht? Zumindest verstehe ich nicht, wo genau das Problem liegen soll, daher wäre es doch sinnvoll, wenn Du es einfach nochmal ein wenig genauer erläuterst. Im momentanen Code gibt es kein Problem, und da man es sowieso nie schafft, mehr als 10 Schüsse auf den Bildschirm zu bringen, kann es auch keine Performance-Probleme geben.


///


Ein Tip noch, hat jetzt nix mit dem eigentlichen Problem zu tun. Die "Clipping-Phasen" solltest Du nicht von hand definieren, das ist viel zu umständlich, sondern Du solltest die errechnen. Du hast ja einen Zähler namens ClippingPhase, den solltest Du ausnutzen. Ordne die Bilder in der Bitmap so an, daß sie alle im selben Raster sind (Deinem Code zufolge ist das leider nicht der Fall), und dann multipliziere ClippingPhase mit der Rasterbreite. Und fang bei x=0 an, und nicht bei x=12. Darüber hinaus ist es am besten, wenn Du die Bilder für "nach rechts laufen" alle in der ersten und die Bilder für "nach links laufen" alle in der zweiten Zeile hast (oder auch umgekehrt), weil Du dann auch die Variable für die Laufrichtung zur Berechnung nutzen kannst. Somit ersparst Du Dir hunderte von Zeilen, in denen Du mühselig von Hand alles berechnen mußt.

Hier mal ein Beispiel:
Bild
Es sind jetzt weniger Phasen wie bei Dir, aber das ist wurscht. Zudem wird bei uns die erste, dann die zweite, dann die erste, und dann die dritte angezeigt, aber das ist egal, stell Dir einfach vor, es wären pro Zeile 4 Figuren.

Der Code hierfür wäre dann z.B. sowas in der Art:

Code: Alles auswählen

#LEFT = 0
#RIGHT = 1
#UP = 2
#DOWN = 3
#DEATH = 4

#PLAYER_WIDTH = 20
#PLAYER_HEIGHT = 20

ClippingPhase = (ElapsedMilliSeconds() % 400) / 4

ClipX = ClippingPhase * #PLAYER_WIDTH
ClipY = Player\Direction * #PLAYER_HEIGHT
ClipSprite(Player\Sprite, ClipX, ClipY)
Deutlich kürzer, wie Du siehst ;)
Wichtig ist halt nur, daß Du auch die Richtung irgendwo speicherst. Vielleicht willst Du lieber die Richtung für X und Y getrennt benutzen, kommt halt aufs Spiel drauf an, aber letztendlich ist das Prinzip das selbe. Immer schön alles rechnen, dafür hat man ja auch 'nen "Rechner" ;)
Stell Dir nur mal vor, Du willst auf einmal größere Sprites verwenden. In meinem Fall genügt es, #PLAYER_WIDTH und #PLAYER_HEIGHT anzupassen, sodaß es mit den neuen Grafiken funktioniert. In Deinem Fall müßtest Du aber wieder von Hand die ganzen Werte ändern, was natürlich nicht nur mühsam, sondern auch fehleranfällig ist.

Verfasst: 11.11.2007 12:42
von Milchshake
Danke, für die Antwort ;)
Und wegen der Idee, ich habe die Sprites nicht selber gemacht (wär schön), desswegen haben diese auch keinen Regelmäßigen abstand, worauf dein Code ja Basiert (soweit ich das richtig verstanden habe)

und ich glaube, das Problem habe ich jetzt auch gelöst, indem ich das so mache:

If Showshow = 0
AddShow(1,500,500,0,0)
AddShow(1,600,500,0,0)
Showshow = 1
EndIf

Dadurch werden die Elemente nur ein mal erstellt, und ich habe keine Probleme mit der List ;)

Für bessere Ideen bin ich immer noch offen.

Verfasst: 11.11.2007 13:14
von AND51
1. Du hast noch nicht auf meinen Post geantwortet
2. Warum nimmst du für AddShow() eine Prozedur? Nimm doch lieber Macros! Ist schneller und hat den Vorteil dass die LinkedList nicht global gemacht werden muss.

Verfasst: 11.11.2007 13:25
von Milchshake
Ich habe mir mal die Macros angeschaut, verstehe aber nicht genau, wie ich
die Macros einbauen soll (kann).
Könntest du mir das netterweise auch mal erklären?
lg Milchshake