| helpQLODhelp
Registriert seit: Feb 2002 Ort: Köln
Beiträge: 8.505
|
Damit die Antwort auf diesen Thread http://www.flashforum.de/forum/showt...726#post838726
nicht untergeht, habe ich einen extra Stuff Thread draus gemacht.
Solche Sachen sind einfacher, wenn du ein abstraktes Datenmodell für dein Spiel benutzt, das du dann im Speicher ändern kannst. Die Grafik zeigt dann praktisch nur die Änderungen deiner Daten an.
Im Fall von Solitaire ist ein zweidimensionales Array gut geeignet. Wir machen uns ein Array der Groesse 9x9 und tragen in jedes Feld ein, ob es leer ist, ob es besetzt ist oder ob es ausserhalb des kreuzförmigen Spielfelds ist. Dieses "Spielfeld" kann man dann sehr einfach modifizieren, ohne sich gross Gedanken über MovieClips usw. machen zu müssen. Das macht man dann erst zum Schluss in der Anzeige-Routine.
Ich habe dir hier mal ein Beispiel gemacht. Ein Solitaire, das von alleine spielt. ActionScript: /** * Erstelle ein neues Spiel */ function neuesSpiel(){ //trace("neuesSpiel"); var board = [ [2,2,2,1,1,1,2,2,2], [2,2,2,1,1,1,2,2,2], [2,2,2,1,1,1,2,2,2], [1,1,1,1,1,1,1,1,1], [1,1,1,1,3,1,1,1,1], [1,1,1,1,1,1,1,1,1], [2,2,2,1,1,1,2,2,2], [2,2,2,1,1,1,2,2,2], [2,2,2,1,1,1,2,2,2]]; return board; } /** * Ein paar Konstanten die die Art * eines Feldes beschreiben */ POS_AUSSERHALB = 2; POS_BESETZT = 1; POS_LEER = 3; /** * Liefere true, wenn die Position leer ist */ function posLeer( board, hPos, vPos){ return (board[ hPos][ vPos] == POS_LEER) } /** * Liefere true, wenn die Position besetzt ist */ function posBesetzt( board, hPos, vPos){ return (board[ hPos][ vPos] == POS_BESETZT) } /** * Liefere true, wenn die Position dazwischen besetzt ist * Die Position auf halber Strecke muss besetzt sein * Da hOffset und vOffset immer -2, 2, oder 0 sind, ergibt sich * beim Teilen durch 2 immer -1, 1 oder 0, also genau die * gewünschte Position */ function steinDazwischen( board, hPos, vPos, hOffset, vOffset){ return (board[ hPos + hOffset/2][ vPos + vOffset/2] == POS_BESETZT) } /** * Liefere true, wenn die Position innerhalb des Spielfelds ist */ function posInnerhalb( board, hPos, vPos){ return hPos >= 0 && hPos < board.length && vPos >= 0 && vPos < board[0].length && board[ hPos][ vPos] != POS_AUSSERHALB } /** * Besetze ein Feld */ function setzeStein( board, hPos, vPos){ board[hPos][vPos] = POS_BESETZT; } /** * Raeume ein Feld */ function loescheStein( board, hPos, vPos){ board[hPos][vPos] = POS_LEER; } /** * Liefere ein Array mit dem Zug, wenn dieser Zug erlaubt ist. * Wenn nicht, liefere null */ function liefereZugVonNach( board, hPos, vPos, hOffset, vOffset){ var h = hPos + hOffset; var v = vPos + vOffset; if( posInnerhalb( board, h, v)){ if( posLeer( board, h, v)){ if( steinDazwischen( board, hPos, vPos, hOffset, vOffset)){ return new Array(hPos, vPos, hOffset, vOffset); } } } return null; } /** * Liefere alle Zuege, zu denen ich von * hPos,vPos aus ziehen kann. Das sind alle * Zuege, die im Umkreis von 2 Feldern * leer sind, und zwischen Ursprung und Zielfeld * einen Stein haben. * Die Zuege haben die Form eines Arrays und * bestehen aus Ursprungsposition und dem * Offset zur Zielposition. Durch Addieren von * Ursprungsposition und Offset bekommt man * die Zielposition heraus. */ function erlaubteZuegeVon( board, hPos, vPos){ var zuege = new Array(); // Wir laufen im Kreis durch alle // Positionen im Abstand 2 for( var i= -2; i<=2; i+= 2){ for( var j= -2; j<=2; j+= 2){ var zug = liefereZugVonNach( board, hPos, vPos, i, j); if( zug != null){ zuege.push( zug); } } } //trace("erlaubteZuegeVon " + zuege.length); return zuege } /** * Liefere alle erlaubten Zuege, die im Moment * möglich sind. */ function erlaubteZuege( board){ var zuege = new Array(); // Wir laufen durch alle Positionen des Arrays // Da die Felder ausserhalb des Spiels nicht // als besetzt gelten, werden sie automatisch // nicht beachtet. for( var i=0; i<board.length; i++){ for( var j=0; j<board[i].length; j++){ if( posBesetzt( board, i, j)){ zuege = zuege.concat( erlaubteZuegeVon( board, i, j)); } } } //trace("erlaubteZuege " + [zuege.length]); return zuege } /** * Mache einen erlaubten Zug */ function ziehe( board, hPos, vPos, offsetH, offsetV){ //trace("ziehe " + [hPos, vPos, offsetH, offsetV]); // Alte Position loeschen loescheStein( board, hPos, vPos); // Neue Position besetzen setzeStein( board, hPos + offsetH, vPos + offsetV); // Uebersprungenen Stein loeschen loescheStein( board, hPos + offsetH/2, vPos + offsetV/2); } /** * Zeige das Brett */ function zeigeSpiel( board){ //trace("zeigeSpiel"); // _root.clear(); _root.lineStyle(20); // // Laufe durch alle Positionen des Arrays // und zeige die Felder an, die besetzt sind. for( var i=0; i<board.length; i++){ var bi = board[i]; for( var j=0; j<bi.length; j++){ if( posBesetzt( solitair, i, j)){ _root.moveTo(i*25, j*25); _root.lineTo(i*25+1, j*25); } } } } /** * Zum Testen unseres Datenmodells lassen wir den Rechner * in einer Frameschleife solange ziehen, bis keine Zuege mehr * möglich sind. Dann beginnt das Spiel von vorne. */ var solitaire = neuesSpiel(); _root.onEnterFrame = function(){ // welche zuege sind moeglich var zuege = erlaubteZuege( solitaire); // keine mehr, also neues Spiel if( zuege.length == 0){ // neues spiel erzeugen solitaire = neuesSpiel() } else { // per zufall einen moeglichen zug auswaehlen var zufallsIndex = random( zuege.length); zug = zuege[zufallsIndex]; // ziehen ziehe( solitaire, zug[0], zug[1], zug[2], zug[3]); } // zeige die aenderungen an zeigeSpiel(solitaire); }
Zum Ausprobieren musst du nur das Script in den ersten Frame eines leeren Films kopieren und starten.
Kleine Aufgabe fuer OOP-Einsteiger: Wie koennte das Script aussehen, wenn man es objektorientiert schreiben würde.
mfg r.
|