Du bist nicht angemeldet.
Ok, so der Fehler war folgendes:
Die fehlerhafte Zeile(n):
cardSlots[i][0] = 50 + (i Mod slotsPerRow) * slotsWidth
cardSlots[i][1] = 50 + (i / slotsPerRow) * slotsHeight
Die hatten sich darauf verlassen, dass "cardSlots[x]" ein Array mit mindestens 2 Eintraegen waere...
Leider habe ich weiter oben (Zeile 123) einen Fehler gemacht:
cardSlots[i].Resize(2)
Ich hatte da angenommen, dass es einfach den "cardSlots[x]"-Array auf die Laenge 2 setzt... dabei gibt "Resize(2)" aber einfach einen neuen Array mit der Groesse "2" zurueck ...
Loesung: austauschen mit
cardSlots[i] = cardSlots[i].Resize(2) '[0] = x und [1] = y
'oder
cardSlots[i] = New Int[2] '[0] = x und [1] = y
Nun sollte Deinen weiteren Experimenten nichts mehr im Wege stehen :-)
bye
Ron
Resize ist eine Methode der Arrays ... in BlitzMax wuerde man
sets = sets[... setsAmount]
schreiben
@arrayerror
Habe den hier nicht, aber das "GLFW2"-Target hat wohl Probleme mit meinem mehrdimensionalen Array (cardSlots[][]) - wenn ich da cardSlots[1][0] ueberschreibe - also "slot2-x", dann ueberschreibt es das fuer alles).
Schau ich mir nach Mittwoch an (Uni moechte gern ein paar Seiten von mir gedruckt sehen...).
bye
Ron
heyho,
habe mir das ganze jetzt nochmal angeschaut, und ich denke das ich das meiste eigentlich verstanden habe *lach*
Zeile 113 ..
setsAmount = 6
'Platz schaffen fuer alle Array-Eintraege
sets = sets.Resize(setsAmount)
Resize bestimmt die Größe (Länge - Length() ) des Arrays? das Resize kann man für alle Arrays einfach aufrufen? ist demnach eine Methode eines Arrays ?
(ich habe nämlich danach gesucht und nicht gefunden *lach*)
Wenn ich versuche das bsp. zum laufen zu bringen, gibts ne fehlermeldung mit "Array index out of range" bei Zeile 169 ?
und ich verstehe nicht so genau wieso *hehe*
auf jedenfall läßt sich der quellcode für mich nun nicht ganz so einfach lesen da ich ihn ja nicht selber geschrieben habe :-) kommen auch oft die Worte "card", "slots", "set", als bezeichner von variablen vor in unterschiedlicher kombination so das ich dann manchmal schauen muss was denn nun was ist - und wo was definiert ist*g* - bin halt ungeübt.
~s~
Ja ... du meinst eine Art "Assoziationsmemory"
Messer, Gabel, Loeffel
Hund, Katze, Maus
Regenwolke, Blitz, Schnee
... Wenn man das machen will, dann sollte man weg vom "TMemoryCardSet".
Jede "TMemoryCard" bekommt eine "typeID" - also eine Kennung die fuer alle "gleichartigen" Karten gleich ist.
Das Spiel zaehlt dann die offenen Karten (max 2) und reagiert auf "2 ungleiche typeID" und "2 gleiche typeID".
Ist nicht sonderlich schwer - bringt aber das in das Spiel, was ich "Twist" nennen wuerde.
Schroeder Kohl Merkel
Roster Steak und (schwer!) Grill-Maiskolben ;-)
bye
Ron
Gedanke der die Herangehensweise nochmals verändern könnte:
Ein Memory kann ja auch aus zwei Bildern bestehen – ein Hund in [Schrift] und ein Hund als [Bild] – eine „schwarze Katze“ als Schrift und Bild usw. Prinzip sollte klar sein, könnte man auch mit Geometrischen Figuren oder anderem machen – also Paare Bilden.
~s~
hmmmm,
als ich gestern abend nach hause kam, hatte ich mir deinen Quellcode noch angeschaut, aber gegen ende hin meinte dann mein Hirn wohl, das es schon spät ist und der Tag lang war
muss ich mir nochmal anschauen, und dann sind da bestimmt einige fragen.
gruß
~s~
Ok .. kurze Erklaerung: Diesen Thread gab es schon mal, ich habe aber gerade bei einer Korrektur am neuen Server ausversehen die Datenbank vom alten Server nochmal "ruebergeholt" ... weil ich urtuemlich der Annahme war, dass das Forum noch Verbindung zur alten DB aufnahm ... naja und bevor ich jetzt das Backup von heute Nacht 0 Uhr zurueckhole ... kann ich auch einfach unser Gequatsche um "Monkey X" und "Tutoriale" ein wenig aus dem Google-Cache fischen:
http://webcache.googleusercontent.com/search?q=cache:aenoAcJm6icJ:www.gamezworld.de/phpforum/viewtopic.php%3Fid%3D13584
SushiTV:
---------------
hehe,
ich habe gerade etwas anderes angefangen, die Idee hatte ich letzte Woche einfach spontan - ein Memory programmieren - da hatte ich hier noch nicht in's Forum geschaut.
Erstaunlicher weisse habe ich jetzt in recht kurzer zeit etwas geschafft mit Monkey-X *g*
hier jetzt posten macht in sofern wenig sinn denke ich, da die Bilder dann fehlen also man das nicht Kopieren kann und ausprobieren, würde ja fehlermeldungen bringen. (anhänge hier im Forum gehen ja nicht oder?)
gruß
~s~
---------------
In einem weiteren Post von SushiTV kam sein erster Code:
Import mojo
' ****** Klasse TMemory welches 1 Paar beinhaltet
Class TMemory
Field x1, y1, w1, h1:Int '****** Koordinaten für 1. Bild des Paares
Field x2, y2, w2, h2:Int '****** Koordinaten für 2. Bild des Paares
Field img:Image '****** Bild des Memorys
Field imgb:Image '****** Deckblatt / Rückseite (kann man vielleicht anders machen da man das ja nur einmal bräuchte
Field Visible1 = False '****** Aufgedeckt Bild 1, ja oder nein
Field Visible2 = False '****** Aufgedeckt Bild 2, ja oder nein
Method New(bild1:String, bildback:String, a1:Int,a2:Int,a3:Int,a4:Int,b1:Int,b2:Int,b3:Int,b4:Int) '****** Methode New der die ganzen Parameter übergeben werden, Koordinaten sollten dann halt per Random generiert werden
Self.x1 = a1 '****** oder Umgekehrt, die Bilder zufällig verteilt, da habe ich noch keinen plan
Self.y1 = a2
Self.w1 = a3
Self.h1 = a4
Self.x2 = b1
Self.y2 = b2
Self.w2 = b3
Self.h2 = b4
Self.img = LoadImage (bild1)
Self.imgb = LoadImage (bildback)
End Method
Method OnCreate()
End Method
Method OnUpdate() '***** in der OnUpdate wird für jedes Paar überprüft ob die Maus auf dem Bild ist und geklickt wurde, je nachdem wird aktuell einfach der Zustand verändert ob Bild oder Deckblatt sichtbar ist
If Visible1 = False Then
If MouseX > x1 And MouseX < x1+w1 And MouseY > y1 And MouseY < y1+h1 And MouseHit > 0 Then Visible1 = True
Else If MouseX > x1 And MouseX < x1+w1 And MouseY > y1 And MouseY < y1+h1 And MouseHit > 0 Then Visible1 = False
End If
If Visible2 = False Then
If MouseX > x2 And MouseX < x2+w2 And MouseY > y2 And MouseY < y2+h2 And MouseHit > 0 Then Visible2 = True
Else If MouseX > x2 And MouseX < x2+w2 And MouseY > y2 And MouseY < y2+h2 And MouseHit > 0 Then Visible2 = False
End If
End Method
Method OnDraw()
If Visible1 = True Then DrawImage (img, x1,y1)
If Visible1 = False Then DrawImage (imgb, x1,y1)
If Visible2 = True Then DrawImage (img, x2,y2)
If Visible2 = False Then DrawImage (imgb, x2,y2)
End Method
End Class
Class MyApp Extends App
Field m01:TMemory, m02:TMemory, m03:TMemory, m04:TMemory
Method OnCreate()
'wird aufgerufen sobald die App fertiggeladen hat
'Setzt die UpdateRate auf 15 Hertz.
'15x pro Sekunde wird dadurch OnUpdate() aufgerufen
'Diese muss unbedingt gesetzt werden, sonst passiert nix
SetUpdateRate(15)
m01 = New TMemory("Monkey001.png","Monkeyback.png", 20,20,100,100,130,20,100,100) '****** Koordinaten sind halt jetzt hier einfach hardcore per hand vergeben ;)
m02 = New TMemory("Monkey002.png","Monkeyback.png", 20,130,100,100,130,130,100,100)
m03 = New TMemory("Monkey003.png","Monkeyback.png", 20,240,100,100,130,240,100,100)
m04 = New TMemory("Monkey004.png","Monkeyback.png", 20,350,100,100,130,350,100,100)
End Method
Method OnRender()
'Bildschirm leeren, einfarbige Flaeche
Cls
'Farbe setzen
SetColor(255, 255, 255)
m01.OnDraw()
m02.OnDraw()
m03.OnDraw()
m04.OnDraw()
End Method
Method OnUpdate()
'wird aller "UpdateRate"-Hertz aufgerufen
'(in unserem Fall aller 15x pro Sek)
'pro UpdateRate erhoehen wir um 1, macht 15 Pixel pro Sekunde
m01.OnUpdate()
m02.OnUpdate()
m03.OnUpdate()
m04.OnUpdate()
End Method
End Class
Function Main()
New MyApp
End Function
Es folgten noch ein paar Beispielcodes und Hinweise meinerseits.
Am Ende versprach ich, dass ich mal einen etwas umfangreicheren Code um seinen Ansatz herumstricke.
Hier nun noch folgend der letzte Code (ein erweitertes Beispielprogramm von mir).
Import mojo
'Das "drumherum" unseres Spiels
Class MemoryApp Extends App
Field game:TGame 'unser derzeitiges Spiel
Method OnCreate()
'wird aufgerufen sobald die App fertiggeladen hat
'Setzt die UpdateRate auf 15 Hertz.
'15x pro Sekunde wird dadurch OnUpdate() aufgerufen
'Diese muss unbedingt gesetzt werden, sonst passiert nix
SetUpdateRate(15)
'Erstellen des TGame-Objektes (dem eigentlichen Spiel)
'TMemoryGame basiert auf "TGame" - das erlaubt uns einen
'schicken Wechsel des Spiels ohne diesen "Wrapper" hier
'veraendern zu muessen
game = new TMemoryGame()
'initialisieren des Spiels (Zeug laden)
game.Init()
End
Method OnRender()
'Einsprungspunkt für alle Darstellungen (zeichnen)
'Spiel-"Grafik" darstellen
game.Render()
End
Method OnUpdate()
'wird aller "UpdateRate"-Hertz aufgerufen
'(in unserem Fall aller 15x pro Sek)
'Spiel-"Logik" aktualisieren
game.Update()
End
End
'die Main() wird automatisch aufgerufen - hier definieren wir was
'beim Ausfuehren des Programmes gemacht wird
'"App" definiert, dass OnRender/OnUpdate usw ausgefuehrt werden - da
'wir unsere MemoryApp von "App" erweitern, uebernehmen wir dieses Verhalten
Function Main()
New MemoryApp
End Function
'=== Game-Basisklasse ("Vorlage" fuer alle verschiedenen Spiele) ===
Class TGame
'abstract-Methoden muessen von jedem "TGame"-Abkoemmling
'"gefuellt" werden
Method Init:Void() Abstract
Method Reset:Void() Abstract
Method InitDone:Bool() Abstract 'fertig mit Init-Vorgang?
Method Update:Void() Abstract
Method Render:Void() Abstract
End Class
'=== MemoryGame ===
Class TMemoryGame Extends TGame
'Dinge wie "Fields/Const" kann man schoen am Kopf der Klasse definieren
'gaenge aber auch zwischen den Funktionen oder am Ende ... aber Uebersicht
'und so...
Field sets:TMemoryCardSet[]
'wieviele Sets gleichzeitig im Spiel?
Field setsAmount:Int = 12
'jedes Spiel hat verschiedene Slots/Plaetze fuer die Karten, da es ja abhaengig
'von "setsAmount" ist
'"array of arrays": jede Zeile des ersten Arrays enthaelt zwei weitere Arrays
'-> cardSlots[1][0] greift auf die 2. Zeile ("0" waere die erste)
' zu - und dann auf die erste Zeile des weiteren Arrays
' -> in diesen speichern wir "x", in einer weiteren "y" der Slots ab.
' -> alternativ koennten wir auch "Punkte" speichern (und "Punkte" als Klasse
' muesste dann "Field x:int, y:int" besitzen).
' -> "Global cardSlots:TPoint[12]" und Zugriff: cardSlots[1].x
Global cardSlots:Int[][]
'alle MemoryGames haetten die gleichen Grafiken ...
'...da nehmen wir "Global", dann haben alle "bla:TMemoryGame" die
' gleichen Bilder
' man koennte auch mehr Bilder anbieten als im Spiel vorhanden (mehr
' Abwechslung)
Global cardImages:Image[6]
Global coverImage:Image
Global resourcesRequested:Bool = False
Method Init:Void()
'wenn wir noch nicht mit dem Laden der Bilder begonnen haben
If Not resourcesRequested
'fuer jedes "cardImage" versuche eine Karte einzuladen
'Hinweis "to" versus "until":
' waehrend for "0 to 2" [0,1,2] beinhaltet, ist bei "until" nur [0,1] drin
' hier also von 0 bis 5... was 6 Elemente sind, genau soviel passen in
' obigen Array
For Local i:Int = 0 Until cardImages.Length()
cardImages[i] = LoadImage("karte"+i+".png")
Next
coverImage = LoadImage("cover.png")
resourcesRequested = True
Endif
'wir wollen 6*2 Karten = 6 Sets
setsAmount = 6
'Platz schaffen fuer alle Array-Eintraege
sets = sets.Resize(setsAmount)
'Kartenslots definieren (kaum Rechenaufwand, also ruhig erstmal bei
'jedem Init()
'jedes Set enthaelt 2 Karten - also brauchen wir "setsAmount * 2"
'Plaetze fuer die Karten
cardSlots = cardSlots.Resize(setsAmount * 2)
'jeder Slot braucht noch "x" und "y", leider laesst sich das nicht
'"leichter" in einem Rutsch initialisieren ...
For Local i:Int = 0 Until cardSlots.Length()
cardSlots[i].Resize(2) '[0] = x und [1] = y
Next
'nun enthaelt:
'cardSlots[0][0]: "Slot1:x"
'cardSlots[0][1]: "Slot1:y"
'Dies nennt sich "zero based" (0 als erste Zeile)
'nun braucht jeder Slot seinen eigentlichen Platz
'dies koennten wir per "Algorithmus" machen - oder aber per Hand
'...der Algorithmus ist nicht sonderlich schwer
' ("%" -> modulo und "/" -> Division)
' er erlaubt auch ein einfacheres Anpassen der Set-Menge
' Sinn waere: "Slots pro Zeile" ausrechnen und diesen Wert als
' Modulo-Faktor in einer "Iteration" ueber alle Slots
' nutzen. Ergebnis ist die X-Slot-Position.
' Nutzt man "/" und rundet, erhaelt man die X-Slot-Position
' -> Slot 5, 4 Slots pro Zeile
' x = 5 mod 4 = 1
' y = 5 / 4 = 1 (ganzzahlig)
' -> Slot 5 waere also in der zweiten Zeile ("Zeile 0" ist erste)
' und dort in der 1. Spalte
' -> ist in etwa wie "abzaehlen" (einfach im Kopf durchgehen)
'Variante A
#rem
cardSlots[ 0] = [ 50, 50]
cardSlots[ 1] = [100, 50]
cardSlots[ 2] = [150, 50]
cardSlots[ 3] = [200, 50]
cardSlots[ 4] = [ 50,100]
cardSlots[ 5] = [100,100]
cardSlots[ 6] = [150,100]
cardSlots[ 7] = [200,100]
cardSlots[ 8] = [200,150]
cardSlots[ 9] = [200,150]
cardSlots[10] = [200,150]
cardSlots[11] = [200,150]
#end
'Variante B
Local slotsPerRow:Int = 4
Local slotsWidth:Int = 50, slotsHeight:Int = 50
'wir fangen bei "50,50" an - weswegen wir die 50 immer schoen addieren muessen
For Local i:Int = 0 Until cardSlots.Length()
cardSlots[i][0] = 50 + (i Mod slotsPerRow) * slotsWidth
cardSlots[i][1] = 50 + (i / slotsPerRow) * slotsHeight
Next
'-> wir haben nun alle Slots festgelegt
'damit kein Kartenbild mehrfach genommen wird, muessen wir eine Tabelle
'bereitstellen, die alle moeglichen Bilder beinhaltet, wird eines davon
'ausgewaehlt, steht es den weiteren Karten nicht mehr zur Verfuegung
Local availableCardImages:Int[cardImages.Length()]
For Local i:Int = 0 Until cardImages.Length()
availableCardImages[i] = i
Next
'availableCardImages nun [0,1, ..., Laenge-1)
'gleiches tun wir fuer die moeglichen Positionen der Karten,
'wir brauchen hier aber nur die Positionsnummer - nicht die Koordinaten
Local availableCardSlots:Int[cardSlots.Length()]
For Local i:Int = 0 Until cardSlots.Length()
availableCardSlots[i] = i
Next
'nun mischen wir die Kartenslots durcheinander - dadurch koennen wir
'nachfolgend einfach eine nach der anderen erstellen und von "oben"
'Kartenslots abrufen.
'Dafuer nutzen wir eine kleine Hilfsfunktion die einen "Mischalgorithmus"
'nutzt
availableCardSlots = ShuffleIntArray( availableCardSlots )
'availableCardSlots nun also [1,5,11,...,3]
For Local i:Int = 0 Until sets.Length()
'Das bild nehmen, was an der Stelle liegt, die von der ersten
'Zeile in "availableCardImages" definiert wird
Local img:Image = cardImages[availableCardImages[0]]
'Diese Zeile entfernen ... nun liegt andere Zeile an oberster
'Stelle
availableCardImages = availableCardImages[1..]
'obersten Kartenslot
Local cardSlot1:Int = availableCardSlots[0]
'obersten Kartenslot entfernen
availableCardSlots = availableCardSlots[1..]
'wieder obersten Kartenslot
Local cardSlot2:Int = availableCardSlots[0]
'obersten Kartenslot entfernen
availableCardSlots = availableCardSlots[1..]
'Karten anlegen - mit ihren jeweiligen Koordinaten
'Dimensionen sind 40x40 - damit haben wir einen kleinen Rand bei den "50x50" Slots
Local card1 := New TMemoryCard( cardSlots[cardSlot1][0], cardSlots[cardSlot1][1], 40, 40, i, img)
Local card2 := New TMemoryCard( cardSlots[cardSlot2][0], cardSlots[cardSlot2][1], 40, 40, i, img)
'beide Karten als ein Set speichern
sets[i] = New TMemoryCardSet(i, card1, card2)
Print "Kartenset "+i+" initialisiert."
Next
Print "Initialisierung beendet."
End Method
Method Reset:Void()
'bis jetzt machen wir noch nix, aber eigentlich Karten
'zuruecksetzen
End Method
Method InitDone:Bool()
'Bei Zielen wie "Html5" bedeutet "LoadImage", dass die Anfrage
'an den Server gestellt wird, doch bitte das Bild zu laden.
'In dem Moment ist es noch nicht da ... das passiert dann
'irgendwann spaeter
'Aus diesem Grund ueberpruefen wir einfach jede Resource, ob
'sie schon fertiggeladen ist ("nicht Null").
'Hinweis: Eine fehlende Resource wuerde aber auch "null" sein.
'noch nicht mal angefangen mit laden?
if not resourcesRequested then return False
'cover fehlt noch
if not coverImage then return False
'eine der Karten noch nicht geladen?
for local i:int = 0 until cardImages.Length()
if not cardImages[i] then return False
Next
'.... weitere Resourcen ueberpruefen
Return True
End Method
Method Update:Void()
For local i:int = 0 until sets.Length()
sets[i].Update()
Next
End Method
Method Render:Void()
DrawText("render", 0,0)
For Local i:Int = 0 Until sets.Length()
sets[i].Render()
Next
End Method
'Kleiner Helfer um Zahlenarrays "zu mischen"
'(Fisher-Yates Shuffle algorithm)
Function ShuffleIntArray:Int[](arr:Int[])
'2-10x durchmischen
For Local r:Int = 0 To Rnd(2, 10)
For Local i:Int = arr.Length-1 To 0 Step -1
Local index:Int = Int(Rnd (0, i))
'array-zeilen vertauschen
Local tmp:Int = arr[index]
arr[index] = arr[i]
arr[i] = tmp
Next
Next
Return arr
End Function
End Class
'Eine einzelne Karte
Class TMemoryCard
Field x:Int, y:Int 'Koordinaten
Field w:Int, h:Int 'Dimensionen
Field img:Image 'Bild des Memorys
Field flipped:Bool = False 'aufgedeckt, ja oder nein
Field setNumber:Int = -1
Method New(x:Int, y:Int, w:Int, h:Int, setNumber:Int, img:Image)
Self.x = x
Self.y = y
Self.w = w
Self.h = h
Self.setNumber = setNumber
Self.img = img
End Method
Method Reset:Void()
flipped = False
End Method
Method Update:Void()
'check ob maus drin
If MouseX() >= x And MouseX() < x + w And MouseY() >= y And MouseY() < y + h
'wenn ja und Maus geklickt... "flipped" umtauschen
if MouseHit() then flipped = not flipped
EndIf
End Method
Method Render:Void()
If flipped
If img
DrawImage (img, x,y)
Else
'Farbe des Ersatzbildes ist einfach abhaengig von der
'Setnummer
SetColor 70*(setNumber Mod 2),90*(setNumber Mod 3),80*(setNumber Mod 4)
DrawRect(x,y,w,h)
'Farbe zuruecksetzen
SetColor 255,255,255
Endif
Else
'hier greifen wir auf das in TMemoryGame als global definierte
'coverBild zurueck - man koennte auch ein eigenes darstellen...
If TMemoryGame.coverImage
DrawImage (TMemoryGame.coverImage, x,y)
Else
'Deckblatt ist "grau"
SetColor 100,100,100
DrawRect(x,y,w,h)
'Farbe zuruecksetzen
SetColor 255,255,255
Endif
Endif
DrawText(setNumber, x,y)
End Method
End Class
'Die zusammengehoerigen Karten
Class TMemoryCardSet
Field card1:TMemoryCard
Field card2:TMemoryCard
Field setNumber:Int
Method New(setNumber:Int, card1:TMemoryCard, card2:TMemoryCard)
Self.card1 = card1
Self.card2 = card2
Self.setNumber = setNumber
End Method
'gibt "True" zurueck, wenn beide Karten aufgedeckt sind,
'ansonsten "False"
Method IsSolved:Bool()
return card1.flipped and card2.flipped
End Method
'alle enthaltenen Karten aktualisieren
Method Update:Void()
'jede Karte schaut fuer sich selbst, ob sie aufgedeckt ist
'oder nicht usw.
card1.Update()
card2.Update()
End Method
Method Render:Void()
card1.Render()
card2.Render()
End Method
End Class
bye
Ron