Grundprinzip von Tetris?
Übersicht

![]() |
TravisBetreff: Grundprinzip von Tetris? |
![]() Antworten mit Zitat ![]() |
---|---|---|
Zum Spiel Tetris hätte ich mal eine Frage an alle, die das schon einmal programmiert haben.
Bei meinem Versuch habe ich jetzt die Spielblöcke aus einzelnen kleineren quadraten zusammengesetzt. Das habe ich gemacht, weil ich ja einzelne Zeilen (also Blockteile) löschen muss, wenn eine Reihe voll ist. Jetzt kann ich die Blöcke aber nicht mehr drehen, weil sie ja aus mehreren Einzelbildern bestehen. Und wenn ich für jeden Block ein einzelnes Bild nehmen würde, kann ich sie zwar prima drehen, aber nicht mehr teilweise löschen. Ihr versteht was ich meine? Wie habt ihr eure Tetrisvarianten aufgebaut? |
||
www.funforge.org
Ich hasse WASD-Steuerung. Man kann alles sagen, man muss es nur vernünftig begründen können. |
Dreamora |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Warum kannst du den block nicht mehr drehen?
wenn du das tetris feld als 2 dimensionalen Array anlegst und dir einfach merkst, welcher block wo liegt (wenns farbig is) oder besetzt / nicht besetzt, dann kannst du auch die steine drehen, musst dir nur das muster beim drehen merken und gucken ob eine entsprechende drehung möglich is ![]() |
||
![]() |
Travis |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich kann ihn nicht drehen, weil dieser Block ja aus mehreren einzelnen Teilen zusammengesetzt ist.
Diese Einzelteile, werden dann beim Erstellen so angeordnet, dass eine bestimmte Form entsteht (Tetrisblock). Die einzelnen Teile werden für jeden Block mit einer eigenen ID gekennzeichnet, damit mann weis welche Teile zu einem Block zusammengefasst sind. Diese Aufteilung der Blöcke halte ich für nötig da ich ja später, wenn eine vollständige Reihe aufgebaut ist, einige Blöcke nur Teilweise löschen muss. Und da ich jetzt den ganzen Block in eigenständige Objekte zerölegt habe, weis ich nicht, wie ich das Gesamtobjekt drehen soll. Vielleicht bin ich mit diesem Prinzip ja auch auf dem Holzweg und es gibt eine bessere Lösung. Ich bitte um eure Hilfe. |
||
www.funforge.org
Ich hasse WASD-Steuerung. Man kann alles sagen, man muss es nur vernünftig begründen können. |
Dreamora |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Die Form dieser Blöcke (T, Linie, Z etc) speicherst du eifach als ein Muster, welches du dann jeweils um 90 Grad drehst ... und wenn du das ganze Feld als Array anlegst, wird es kein allzugrosses Problem diese zu "drehen"
du drehst keine Grafiken dabei sondern die positionen der Grafiken. |
||
![]() |
BladeRunnerModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Also vom Grundprinzip würde ich das so machen, dass ich für den aktuell fallenden Stein ein Array füllen würde.
Code: [AUSKLAPPEN] dim akt_stein(3,3)
Wieso 4*4 Felder ? Weil das grösste Teil das Lange gerade ist, vier lang, eins Breit, und dass muss ja in allen Richtungen darzustellen sein. Nun wird dieses Feld bestückt, je nach Teil dass fällt, z.B.: Code: [AUSKLAPPEN] .L_Stein_re data 0,0,0,0 data 1,0,0,0 data 1,0,0,0 data 1,1,0,0 . . . if teil=1 then ;angenommen 1 stünde für L-re restore L_Stein_re for y = 0 to 3 for x = 0 to 3 read teil_gesetzt akt_teil(x,y)=teil_gesetzt next next Du könntest sogar (theoretisch) alle Steine schon in allen Ausrichtungen definieren, aber eine rotate_teil()-Funktion wird es genauso tun. Wichtig: im Sinne der Fairness für den Spieler (und damit das Teil nicht "springt"') sollte das rotate so ausgelegt werden, dass immer das Ergebnis Links und Unten bündig liegt, Bsp.: Zitat: Falsch: 0010 1110 0000 0000 Richtig: 0000 0000 0010 1110 Ein Entwurf für das rotate_teil() [nicht geprüft, bin auf der Arbeit und hab das zwischen Tür und Angel zusammengeschraubt]: Code: [AUSKLAPPEN] dim rotate_speicher(3,3) Function rotate_teil(wie_oft) for wieder = 1 to wie_oft for y = 0 to 3 for x = 0 to 3 rotate_speicher(y,(3-x))=akt_teil(x,y) ;90° links drehen next next for x=0 to 3 for y= 0 to 3 akt_teil(x,y)=rotate_speicher(x,y) ;übertragen in Teilspeicher next next .upschieb status=0 for x= 0 to 3 if akt_teil(x,3)=1 then Status=1 ;ist ein Teil in der untersten Zeile? next if status =0 then ;wenn nein schiebe die oberen runter: for y=2 to 0 step -1 for x = 0 to 3 akt_teil(x,y+1)=akt_teil(x,y) next next for i=0 to 3: akt_teil(i,0)=0:next ;oberste Zeile "säubern" goto upschieb end if status=0 .leftschieb for y= 0 to 3 if akt_teil(0,y)=1 then Status=1 ;ist ein Teil in der linken Spalte? next if status =0 then ;wenn nein schiebe die rechten nach: for x=1 to 3 for y = 0 to 3 akt_teil(x-1,y)=akt_teil(x,y) next next for i=0 to 3: akt_teil(3,i)=0:next goto leftschieb end if next end function mit rotate_teil(x) wird das Teil nun x*90° links gedreht. Fallen lässt du die Teile etwas anders: du weist akt_teil eine x und y Koordinate zu. x ändert sich durch Eingaben des Spielers, Y auch durch die Zeit (Alle xyz Millisecs() wird y erhöht). Dabei prüfst du für alle Felder von akt_teil, ob die Neue Koordinate schon belegt wäre, wenn ja, liegt das Teil auf und das nächste Teil kann starten. Wie prüfst du das ? Ich empfehle ein Feld Code: [AUSKLAPPEN] Dim Spielfeld (11,39) Du kannst jetzt also jedes Dieser Felder belegen und Auch Überschneidungen testen. Hier lass ich mal deine Kreativität zum Zug kommen - es ist aber im Grunde nix andres als ne Tilemap. hoffe ich konnte helfen, muß jetzt weiterarbeiten.... ![]() |
||
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3 Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64 B3D BMax MaxGUI Stolzer Gewinner des BAC#48, #52 & #92 |
- Zuletzt bearbeitet von BladeRunner am Do, März 18, 2004 6:59, insgesamt einmal bearbeitet
![]() |
soli |
![]() Antworten mit Zitat ![]() |
---|---|---|
.....im letzten Forum hatten wir ein gut funktionierendes Tetris im Code-Archiv.
Code: [AUSKLAPPEN] ;============================================================== ;Game : Text-Tetris in Blitzbasic ;Version: 1.0 ;Author : Patrick Mächler aka Valio ;Email : valio@visionsinteractive.ch ;Legal : (c) 2003 by Patrick Mächler ; Free use for educational purposes ; I coded this in about an hour, 'cause I was bored. ; ;Control: Shift Block Left - Left Arrow ; Shift Block Right - Right Arrow ; Turn Block Left - Up Arrow ; Turn Block Right - Down Arrow ; Shift Block Down - Space ; Pause/Resume - Enter ; End Game - Esc ; ;Note : There's no Gameover. You maybe just can't move the ; blocks to somwhere anymore. ; The speedformula is quite simple, so on Level 20 it ; will be impossible to play. ;============================================================== Const Fall$="#" Const Full$="" Const Free$=" " Const Wall$="¦" Const Floor$="-" Const Erase$="+" Const FieldX=11 Const FieldY=13 Dim GameField(FieldX,FieldY) Dim Block(4,4) Dim NBlock(4,4) Global OriginX=40 Global OriginY=40 Global BlockX, BlockY Global BlockTime, Level=1, Score=0, Speed=1000, Pause=False SetBuffer BackBuffer() SeedRnd MilliSecs() Fillfield() NewBlock() NewBlock() While Not(KeyHit(1)) Cls DrawField() If Pause=False Then MoveBlock() If KeyHit(28) Then If Pause=False Then Pause = True BlockTime = BlockTime - MilliSecs() Else BlockTime = BlockTime + MilliSecs() Pause = False EndIf EndIf DrawBlock() DrawGUI() Flip Wend End ;============================================================== ;Called at the beginnig, puts walls and floor in the GameField ;array. ;============================================================== Function Fillfield() Local x For x=0 To FieldY GameField(0,x)=2 ;2=wall GameField(FieldX,x)=2 ;2=wall Next For x=1 To FieldX-1 GameField(x,FieldY)=3 ;3 =floor Next End Function ;============================================================== ;This swaps the data in the NBlock (next block) array to the ;Block array and fills NBlock with data of another randomly ;chosen block. ;============================================================== Function NewBlock() Local x,y,r BlockTime=MilliSecs() BlockX=5 BlockY=-2 r=Rand(5) Select r Case 1: Restore Block1 Case 2: Restore Block2 Case 3: Restore Block3 Case 4: Restore Block4 Case 5: Restore Block5 End Select For y=0 To 4 For x=0 To 4 Block(x,y) = NBlock(x,y) Read NBlock(x,y) Next Next End Function ;============================================================== ;Analyze all game related userinputs and controls the moving ;block. ;============================================================== Function MoveBlock() Local t If KeyHit(203) Then BlockX=BlockX-1 If Collide() Then BlockX=BlockX+1 EndIf If KeyHit(205) Then BlockX=BlockX+1 If Collide() Then BlockX=BlockX-1 EndIf If KeyHit(200) Then RotateLeft() If Collide() Then RotateRight() EndIf If KeyHit(208) Then RotateRight() If Collide() Then RotateLeft() EndIf If KeyDown(57) Then BlockTime = BlockTime - Speed/3 t=MilliSecs() If t>BlockTime Then BlockY = BlockY+1 BlockTime = BlockTime + Speed If Collide() Then BlockY = BlockY-1: SetBlock(): LineCheck(): NewBlock() EndIf End Function ;============================================================== ;Transfers the data in the Block array to the GameField array. ;============================================================== Function SetBlock() Local x,y For x = 0 To 4 For y = 0 To 4 SetField(x,y) Next Next End Function ;--------------------------------- ;Helpfunction for SetBlock(). ;--------------------------------- Function SetField(x,y) Local tx,ty tx = BlockX+x ty = BlockY+y If tx<0 Or tx>FieldX Or ty<0 Or ty>FieldY Then Return If Block(x,y)<>0 Then GameField(tx,ty)=1 Return False End Function ;============================================================== ;Checks if one or some rows in the game field are upfilled and ;if so, calls EraseLine() to delete the rows. ;============================================================== Function LineCheck() Local x,y,l,e For y=0 To FieldY-1 l=0 For x=0 To FieldX If GameField(x,y)<>0 Then l=l+1 Next If l=FieldX+1 Then e = e + 1 Else EraseLine(y,e) e = 0 EndIf Next EraseLine(y,e) End Function ;============================================================== ;Erases the e rows over row y, with some blinky effects and ;calls AddScore to add some score for the well done job. ;============================================================== Function EraseLine(y,e) Local t,m,x If e=0 Then Return m=0 t = MilliSecs() For x=1 To e ChangeLine(y-x,1,-1) Next Repeat If MilliSecs()-t>300 Then For x=1 To e If (m Mod 2)=0 Then ChangeLine(y-x,-1,0) Else ChangeLine(y-x,0,-1) EndIf Next t = MilliSecs() m=m+1 EndIf Cls DrawField() DrawGUI() Flip Until m=9 For m=y-1 To e Step -1 For x=0 To FieldX GameField(x,m)=GameField(x,m-e) Next Next For m=m To 0 Step -1 ChangeLine(m,1,0) Next AddScore(e) End Function ;--------------------------------- ;Helpfunction for EraseLine(). ;--------------------------------- Function ChangeLine(y,f,t) Local x For x=0 To FieldX If GameField(x,y)=f Then GameField(x,y)=t Next End Function ;============================================================== ;Adds score for the l erased rows and updates speed and level. ;============================================================== Function AddScore(l) Score = Score + 10*(l^2) Level = 1 + Score/100 Speed = 2200 - Level*200 End Function ;============================================================== ;Checks if the block array currently collides with the game ;field. ;============================================================== Function Collide() Local x,y For x = 0 To 4 For y=0 To 4 If CollideField(x,y) Then Return True Next Next Return False End Function ;--------------------------------- ;Helpfunction for Collide(). ;--------------------------------- Function CollideField(x,y) Local tx,ty tx = BlockX+x ty = BlockY+y If tx<0 Or tx>FieldX Or ty<0 Or ty>FieldY Then Return False If Block(x,y)<>0 And GameField(tx,ty)<>0 Then Return True Return False End Function ;============================================================== ;Rotates the data in the Block array counter clockwise. ;============================================================== Function RotateLeft() Local x,y,swap For x=0 To 1 For y=0 To 1 swap=Block(x,y) Block(x,y)=Block(4-y,x) Block(4-y,x)=Block(4-y,4-x) Block(4-y,4-x)=Block(y,4-x) Block(y,4-x)=swap Next swap=Block(x,2) Block(x,2)=Block(2,x) Block(2,x)=Block(4-x,2) Block(4-x,2)=Block(2,4-x) Block(2,4-x)=swap Next End Function ;============================================================== ;Rotates the data in the Block array clockwise. ;============================================================== Function RotateRight() Local x,y,swap For x=0 To 1 For y=0 To 1 swap=Block(y,4-x) Block(y,4-x)=Block(4-y,4-x) Block(4-y,4-x)=Block(4-y,x) Block(4-y,x)=Block(x,y) Block(x,y)=swap Next swap=Block(2,4-x) Block(2,4-x)=Block(4-x,2) Block(4-x,2)=Block(2,x) Block(2,x)=Block(x,2) Block(x,2)=swap Next End Function ;============================================================== ;Draws the graphical user interface (GUI). ;============================================================== Function DrawGUI() Local p$ ;Locate OriginX+200,OriginY ;print "Score : "+Score Text OriginX+200,OriginY,"Score: "+Score ;Locate OriginX+200,OriginY+20 ;print "Level: "+Level Text OriginX+200,OriginY+20,"Level: "+Level ;Locate OriginX+200,OriginY+40 Text OriginX+200,OriginY+40,"Speed: "+Speed ;print "Speed: "+Speed ;Locate OriginX+200,OriginY+80 Text OriginX+200,OriginY+80,"Next Block:" ;print "Next Block:" DrawNextBlock(OriginX+200,OriginY+100) p$ = "PAUSE +++++ " If Pause Then Text (-MilliSecs()/12 Mod StringWidth(p$)), 280, String(p$,10) End Function ;--------------------------------- ;Helpfunction for DrawGUI(). ;--------------------------------- Function DrawNextBlock(OX,OY) Local s$,x,y For y=0 To 4 s$ = "" For x=0 To 4 If NBlock(x,y)=1 Then s$ = s$ + full Else s$ = s$ + free Next ;Locate OX,OY+y*FontHeight() ;Print s$ Text OX,OY+y*FontHeight(),s$ Next End Function ;============================================================== ;Draw the data in the Block array. ;============================================================== Function DrawBlock() Local s$,x,y For y=0 To 4 s$ = "" For x=0 To 4 If Block(x,y)=1 Then s$ = s$ + fall Else s$ = s$ + free Next ;Locate OriginX+BlockX*FontWidth(),OriginY+(y+BlockY)*FontHeight() ;Print s$ Text OriginX+BlockX*FontWidth(),OriginY+(y+BlockY)*FontHeight(),s$ Next End Function ;============================================================== ;Draw the game field (data in the GameField array). ;============================================================== Function DrawField() Local x,y,s$ For y=0 To FieldY s$="" For x=0 To FieldX Select GameField(x,y) Case 1: s$ = s$ + full Case 2: s$ = s$ + wall Case 3: s$ = s$ + Floor Case -1: s$ = s$ + Erase Default: s$ = s$ + free End Select Next ;Locate OriginX,OriginY+y*FontHeight() ;Print s$ Text OriginX,OriginY+y*FontHeight(),s$ Next End Function ;============================================================== ;Data for blocks to fill in the Block array. ;============================================================== .Block1 Data 0,0,1,0,0 Data 0,0,1,0,0 Data 0,0,1,0,0 Data 0,0,1,0,0 Data 0,0,0,0,0 .Block2 Data 0,0,1,0,0 Data 0,0,1,0,0 Data 0,0,1,1,0 Data 0,0,0,0,0 Data 0,0,0,0,0 .Block3 Data 0,0,1,0,0 Data 0,0,1,0,0 Data 0,1,1,0,0 Data 0,0,0,0,0 Data 0,0,0,0,0 .Block4 Data 0,0,0,0,0 Data 0,0,1,0,0 Data 0,1,1,1,0 Data 0,0,0,0,0 Data 0,0,0,0,0 .Block5 Data 0,0,0,0,0 Data 0,1,1,0,0 Data 0,1,1,0,0 Data 0,0,0,0,0 Data 0,0,0,0,0 Vielleicht hilft dir das weiter |
||
solitaire |
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group