[GELÖST] Array wird nicht richtig ausgelesen?

Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Neue Antwort erstellen

 

sackboy

Betreff: [GELÖST] Array wird nicht richtig ausgelesen?

BeitragMi, März 16, 2016 23:15
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich versuche mich gerade an einem Bejeweled Spiel und stehe vor einem Problem, was ich irgendwie nicht verstehe. Ich habe angefangen einen Code zu schreiben, welcher für jeden Stein auf dem Spielfeld prüft, ob in der Horizontalen benachbarte Steine mit gleicher Farbe existieren, und falls es mehr als zwei sind, dann sollen diese markiert werden. Hier mal der entsprechende Codeabschnitt:

Methode im Type für die Steine:
Code: [AUSKLAPPEN]
   Method CheckCombination()
      
      Local counter:Int = 1
      Local combi:Int
      Local marker:Int
      
      ColorCheck[Self.gridposX, Self.gridposY] = Self.color 'Farbe in Matrix speichern
      DrawText ColorCheck[Self.gridposX, Self.gridposY], 50 + (Self.gridposX * 15), 300 + (Self.gridposY * 15) 'Debug: zeichnet oberste Matrix
      
      For combi = 1 To combicheck 'combicheck ist global definiert mit 4
         
         If Self.gridposX + combi < dimx Then 'Wenn nächster Stein, der geprüft wird innerhalb des Spielfelds ist
            
            If marker = 0 Then 'Zählmodus
               
               If ColorCheck[Self.gridposX, Self.gridposY] = ColorCheck[Self.gridposX + combi, Self.gridposY] Then counter = counter + 1 'Wenn gleiche Farben horizontal nebeneinander
               If ColorCheck[Self.gridposX, Self.gridposY] <> ColorCheck[Self.gridposX + combi, Self.gridposY] Then counter = 0; combi = combicheck 'Wenn ungleiche Farbe, dann nicht auf Kombination prüfen
               If ColorCheck[Self.gridposX, Self.gridposY] = - 1 Then counter = 0; combi = combicheck 'Wenn kein farbiger Stein, dann nicht auf Kombination prüfen
               
               If counter = combimin Then 'Wenn mindestesn drei nebeneinanderliegende Steine gefunden
                  
                  counter = 1 'Zähler zurücksetzen
                  combi = 0 'Kombinationen zurücksetzen
                  marker = 1 'Markieren für Streichung aktivieren
                  
                  Mark[Self.gridposX, Self.gridposY] = 1 'Stein zum streichen markieren
                  
               EndIf
               
            ElseIf marker = 1 Then 'Markiermodus
               
               If ColorCheck[Self.gridposX, Self.gridposY] = ColorCheck[Self.gridposX + combi, Self.gridposY] Then 'Wenn gleiche Farben horizontal nebeneinander
                  
                  Mark[Self.gridposX + combi, Self.gridposY] = 1 'Nachbarstein zum streichen markieren
                  
               Else
                  
                  combi = combicheck 'Kombination zuende, Abbruch
                  
               EndIf
               
            EndIf
            
         ElseIf Self.gridposX + combi = dimx Then 'Wenn rechter Spielfeldrand
            
            combi = combicheck 'Kombination zuende, Abbruch
            
         EndIf
         
      Next
      
      DrawText Mark[Self.gridposX, Self.gridposY], 50 + (Self.gridposX * 15), 450 + (Self.gridposY * 15) 'Debug: zeichnet mitlere Matrix

      Self.marked = Mark[Self.gridposX, Self.gridposY] 'Überträgt Markierung vom Array auf das Objekt
      Mark[Self.gridposX, Self.gridposY] = 0 'Markierung im Array zurücksetzen
      
   End Method


Code in der Hauptschleife:
Code: [AUSKLAPPEN]
   For Gems = EachIn gemlist 'Jeder Stein auf dem Feld

         Gems.Draw() 'Steine zeichnen

      If Gems.gridposY >= 0 Then
         
         Gems.CheckCombination() 'Methode von oben
         
      EndIf
      
      If Gems.marked = 1 Then
      
         DrawText Gems.marked, 50 + (Gems.gridposX * 15), 600 + (Gems.gridposY * 15) 'Debug: zeichnet unterste Matrix
         
         Gems.imagetop = stone 'Markiert die zu streichenden Steine grafisch
         
      EndIf
      
   Next


Die Arrays sind alle global definiert. Wenn ich den Code laufen lasse, bekomme ich folgendes, beispielhaftes Ergebnis:

user posted image

Die Matrix links oben gibt die Farben auf dem Spielfeld wieder, die Matrix links in der Mitte gibt den Array "Mark" (speichert die zu markierenden Steine an der jeweiligen Position) wieder, bevor er zurückgesetzt wird und die unterste Matrix gibt im Prinzip den Zustand unmittelbar vor der grafischen Markierung wieder (wobei hier nur die Werte der Objekte (also nicht mehr des Arrays "Mark") ausgegeben werden, die markiert werden sollen).
Jede Matrix wird korrekt angezeigt und zeigt das gewünschte Ergebnis, nur wenn ich eine Grafik in Abhängigkeit von der Markierung festlege (direkt nachdem die Matrix gezeichnet wurde, ohne Zwischenbefehle), sind scheinbar willkürlich auch andere Steine davon betroffen (tatsächlich mal mehr, mal weniger). Ich habe keinen blassen Schimmer woran das liegen könnte, hat jemand eine Idee?
  • Zuletzt bearbeitet von sackboy am Sa, März 19, 2016 0:36, insgesamt einmal bearbeitet

Holzchopf

Meisterpacker

BeitragMi, März 16, 2016 23:38
Antworten mit Zitat
Benutzer-Profile anzeigen
Der Code von Gems.Draw() wäre noch hilfreich. Und du setzt Gems.imagetop = stone, aber ich sehe nirgends, dass du es mal wieder zurücksetzen würdest.

mfG
Holzchopf
Erledige alles Schritt um Schritt - erledige alles. - Holzchopf
CC BYBinaryBorn - Yogurt ♫ (31.10.2018)
Im Kopf da knackt's und knistert's sturm - 's ist kein Gedanke, nur ein Wurm
 

sackboy

BeitragDo, März 17, 2016 1:07
Antworten mit Zitat
Benutzer-Profile anzeigen
Gems.Draw():
Code: [AUSKLAPPEN]
Method Draw()
      
      Self.gridposX = (Self.posX - gridstartX) / TGems.gemwidth 'X-Gridposition ermitteln
      Self.gridposY = (Self.posY - gridstartY) / TGems.gemheight 'Y-Gridposition ermitteln
      
      If Self.image <> Null Then DrawImage(Self.image, Self.posX, Self.posY) 'Grafik an aktueller Position zeichnen
      If Self.imagetop <> Null Then DrawImage(Self.imagetop, Self.posX, Self.posY) 'Grafik an aktueller Position zeichnen
      
   End Method


Ist noch nicht wirklich viel drin. Die Zeile "Gems.imagetop = stone" wollte ich, wenn alles funktioniert, mit "ListRemove(gemlist, Gems)" ersetzen. Hab das auch schon mal testweise gemacht, aber es verschwindet eben immer zu viel, daher wollte ich mir das mal grafisch anschauen.

Thunder

BeitragDo, März 17, 2016 21:25
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich glaube ehrlich gesagt, dass es was mit der ColorCheck-Matrix zu tun hat. Viel kann ich nicht dazu sagen, ich kann ja nix testen - aber ich sehe es als problematisch, dass du die Liste durchgehst und währenddessen die Farben der benachbarten Steine checkst, wo aber die ColorCheck-Matrix noch nicht geupdatet ist, weil die Schleife noch nicht komplett durchlief.

Vielleicht ist es nicht genau ColorCheck, aber ich bin mir sicher, dass du irgend so ein Abhängigkeitsproblem hast (also wo du annimmst, dass eine Variable schon aktuelle Daten hält, obwohl sie erst in den nächsten Schleifendurchläufen zugewiesen werden würden). Solche, die du kriegst, wenn du ein Brettspiel in einer Schleife updaten und zeichnen willst.

Ich schlage ein Redesign vor. Das Markieren der zu entfernenden Steine sollte komplett aus der Schleife zum Zeichnen ausgelagert werden. Ich würde eine zweite Schleife unter die zum Zeichnen setzen. Wenn der Programmfluss dort ist, ist ColorCheck sicher vollständig geupdatet, weil in der Zeichenschleife nichts geändert wurde. Dann kann man in der zweiten Schleife in einer Operation alle Steine zum Löschen markieren oder entfernen. Ist auch Cache-freundlicher!
Meine Sachen: https://bitbucket.org/chtisgit https://github.com/chtisgit
 

sackboy

BeitragDo, März 17, 2016 22:57
Antworten mit Zitat
Benutzer-Profile anzeigen
Habe vorhin mal erfolglos versucht die Schleifen zu trennen, aber egal wo ich den ColorCheck platziert habe, irgendwie kam dasselbe Ergebnis raus.
Habe mal den ganzen Code hier hochgeladen: https://www.mediafire.com/?c5vj6kfdlt60puz

Xeres

Moderator

BeitragFr, März 18, 2016 21:23
Antworten mit Zitat
Benutzer-Profile anzeigen
Du kannst deinen Code auch hier im Forum unter Archiv hochladen.
Aber was mir so auffällt:
- Die Trennung von Zuständigkeiten sollte verbessert werden. GameLoop() sollte keinen extra Schalter brauchen, um beim Start das Spielfeld zu erstellen. Das kann man in in eine extra Funktion stecken, die in Reset() aufgerufen wird - anstatt da den Schalter zurück zu setzen.
- Der Globale Namensraum könnte sauberer sein. Wenn du etwas Objektorientierter programmieren wolltest, könntest du die ganzen Konstanten in ein Game-Objekt verpacken. Aber selbst wenn du eher beim Funktionalem Stil bleiben willst: Types können globale Variablen enthalten: TGems.gemlist wäre z.B. hübscher. Funktionen können globalen Variablen enthalten - falls du den Wert beim nächsten Funktionsaufruf wieder benötigst.
- Kommentare sind da nötig, wo es um komplizierteren Code geht, der einfach nicht selbsterklärend ist.
Gute Kommentare, die erklären mehr, als schon da steht:
Code: [AUSKLAPPEN]
ElseIf x = dimx - 1 Then 'Wenn rechter Spielfeldrand
Gems.imagetop = stone 'Markiert die zu streichenden Steine grafisch

Kommentare die dich Zeit kosten aber nichts aussagen:
Code: [AUSKLAPPEN]
Graphics 1024, 768, 0 'Auflösung setzen
gemcounter = gemcounter + 1 'Steine auf dem Spielfeld zählen
DrawThickLine(2, x, y) 'Linie rechts zeichnen
Local a:Int 'Lokalen Zähler definieren

Was passiert, steht im Code - Dokumentiere Warum etwas passiert.

So weit erst mal meine Tirade Wink
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)

Thunder

BeitragFr, März 18, 2016 22:53
Antworten mit Zitat
Benutzer-Profile anzeigen
Mit dem ganzen Code ist es viel einfacher! Danke

Ich bin dem Problem anscheinend auf die Schliche gekommen. Versuche folgendes:

Die Zeile
Code: [AUSKLAPPEN]
ColorCheck[Self.gridposX, Self.gridposY] = Self.color 'Farbe in Matrix speichern

kommt in die Methode Draw()

Und CheckCombinations wird in eine eigene Schleife ausgelagert:
BlitzBasic: [AUSKLAPPEN]
		For Gems = EachIn gemlist 'Jeder Stein auf dem Feld

Gems.Draw() 'Steine zeichnen und fallen lassen
gemcounter = gemcounter + 1 'Steine auf dem Spielfeld zählen


If Gems.marked = 1 Then

DrawText Gems.marked, 50 + (Gems.gridposX * 15), 600 + (Gems.gridposY * 15) 'Debug

Gems.imagetop = stone 'Markiert die zu streichenden Steine grafisch

EndIf

Next

For Gems = EachIn gemlist
If Gems.gridposY >= 0 Then

Gems.CheckCombination()

EndIf
Next


Nun scheint alles zu klappen!
Meine Sachen: https://bitbucket.org/chtisgit https://github.com/chtisgit
 

sackboy

BeitragSa, März 19, 2016 0:35
Antworten mit Zitat
Benutzer-Profile anzeigen
Super, vielen Dank Euch beiden! Very Happy

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group