tetris stuff

This commit is contained in:
Irmen de Jong 2019-03-07 02:28:01 +01:00
parent 3a6fae4447
commit 9be70bcbe7
2 changed files with 102 additions and 93 deletions

View File

@ -1,8 +1,12 @@
; TehTriz - a Tetris clone. ; TehTriz - a Tetris clone.
; ;
; @todo: hold block.
; @todo: holding a block.
; @todo: show next 2 blocks instead of just 1. ; @todo: show next 2 blocks instead of just 1.
; @todo: how to deal with rotation when block is against a wall or another block ('bump' off the wall?)
; @todo: should not give the same block more than twice in a row?
; @todo: simple sound effects? slight click when moving, swish when rotating/dropping, soft explosion when lines are cleared, buzz at game over
~ main { ~ main {
@ -30,15 +34,88 @@ waitkey:
c64.TIME_LO = 0 c64.TIME_LO = 0
if blocklogic.canMoveDown(xpos, ypos) { if blocklogic.canMoveDown(xpos, ypos) {
; @todo re-enable down movement ; slowly move the block down
;drawBlock(xpos, ypos, 32) drawBlock(xpos, ypos, 32)
;ypos++ ; descend ypos++
;drawBlock(xpos, ypos, 160) drawBlock(xpos, ypos, 160)
} else { } else {
; block can't move further down! ; block can't move further down!
; check if the game area is full, if not, spawn the next block at the top. ; check if the game area is full, if not, spawn the next block at the top.
if blocklogic.isGameOver() { if blocklogic.isGameOver(xpos, ypos) {
game_over()
} else {
spawnNextBlock()
}
}
}
ubyte key=c64.GETIN() ; @todo: joystick support as well. (doesn't joy1 input characters as well?)
if_z goto waitkey
if key>='1' and key<='7' {
; select block type, reset to start pos
; @todo remove this feature it is for testing purposes only
xpos = startXpos
ypos = startYpos
drawBlock(xpos, ypos, 32)
blocklogic.newCurrentBlock(key-'1')
drawBlock(xpos, ypos, 160)
}
else if key==157 or key==',' {
; move left
if blocklogic.canMoveLeft(xpos, ypos) {
drawBlock(xpos, ypos, 32)
xpos--
drawBlock(xpos, ypos, 160)
}
}
else if key==29 or key=='.' {
; move right
if blocklogic.canMoveRight(xpos, ypos) {
drawBlock(xpos, ypos, 32)
xpos++
drawBlock(xpos, ypos, 160)
}
}
else if key==17 or key=='m' {
; move down faster
if blocklogic.canMoveDown(xpos, ypos) {
drawBlock(xpos, ypos, 32)
ypos++
drawBlock(xpos, ypos, 160)
}
}
else if key==145 or key==' ' {
; drop down immediately
drawBlock(xpos, ypos, 32)
ypos = boardOffsetY+boardHeight-4 ; @todo determine proper y position
drawBlock(xpos, ypos, 160)
}
else if key=='z' {
; rotate counter clockwise
if blocklogic.canRotateCCW(xpos, ypos) {
drawBlock(xpos, ypos, 32)
blocklogic.rotateCCW()
drawBlock(xpos, ypos, 160)
}
}
else if key=='x' {
; rotate clockwise
if blocklogic.canRotateCW(xpos, ypos) {
drawBlock(xpos, ypos, 32)
blocklogic.rotateCW()
drawBlock(xpos, ypos, 160)
}
}
; @todo check if line(s) are full -> flash/clear line(s) + add score + move rest down
goto waitkey
}
sub game_over() {
c64scr.PLOT(7, 7) c64scr.PLOT(7, 7)
c64.CHROUT('U') c64.CHROUT('U')
c64scr.print("────────────────────────") c64scr.print("────────────────────────")
@ -49,72 +126,16 @@ waitkey:
c64.CHROUT('J') c64.CHROUT('J')
c64scr.print("────────────────────────") c64scr.print("────────────────────────")
c64.CHROUT('K') c64.CHROUT('K')
} else { while(true) {
spawnNextBlock() ; endless loop
; @todo restart game on pressing F1/firebutton
} }
} }
}
ubyte key=c64.GETIN()
if_z goto waitkey
if key>='1' and key<='7' {
; select block type, reset to start pos
xpos = startXpos
ypos = startYpos
drawBlock(xpos, ypos, 32)
blocklogic.newCurrentBlock(key-'1')
drawBlock(xpos, ypos, 160)
}
else if key==157 or key==',' {
if blocklogic.canMoveLeft(xpos, ypos) {
drawBlock(xpos, ypos, 32)
xpos-- ; move left
drawBlock(xpos, ypos, 160)
}
}
else if key==29 or key=='.' {
if blocklogic.canMoveRight(xpos, ypos) {
drawBlock(xpos, ypos, 32)
xpos++ ; move right
drawBlock(xpos, ypos, 160)
}
}
else if key==17 or key=='m' {
if blocklogic.canMoveDown(xpos, ypos) {
drawBlock(xpos, ypos, 32)
ypos++ ; descend
drawBlock(xpos, ypos, 160)
}
}
else if key==145 or key==' ' {
; drop down immediately
drawBlock(xpos, ypos, 32)
ypos = boardOffsetY+boardHeight-4
drawBlock(xpos, ypos, 160)
}
else if key=='z' {
if blocklogic.canRotateCCW() {
drawBlock(xpos, ypos, 32)
blocklogic.rotateCCW()
drawBlock(xpos, ypos, 160)
}
}
else if key=='x' {
if blocklogic.canRotateCW() {
drawBlock(xpos, ypos, 32)
blocklogic.rotateCW()
drawBlock(xpos, ypos, 160)
}
}
goto waitkey
}
sub spawnNextBlock() { sub spawnNextBlock() {
c64.TIME_LO = 0 c64.TIME_LO = 0
blocklogic.newCurrentBlock(nextBlock) blocklogic.newCurrentBlock(nextBlock)
nextBlock = rnd() % 7 nextBlock = (rnd() + c64.RASTER) % 7
drawNextBlock() drawNextBlock()
xpos = startXpos xpos = startXpos
ypos = startYpos ypos = startYpos
@ -167,9 +188,9 @@ waitkey:
c64scr.setcc(boardOffsetX+boardWidth, i, 84, 11) c64scr.setcc(boardOffsetX+boardWidth, i, 84, 11)
} }
for ubyte b in 7 to 0 step -1 { for i in 7 to 0 step -1 {
blocklogic.newCurrentBlock(b) blocklogic.newCurrentBlock(i)
drawBlock(3, 3+b*3, 102) ; 102 = stipple drawBlock(3, 3+i*3, 102) ; 102 = stipple
} }
drawScore() drawScore()
} }
@ -335,89 +356,73 @@ waitkey:
} }
} }
sub canRotateCW() -> ubyte {
rotateCW()
ubyte okay=true ; TODO determine
rotateCCW()
return okay
}
sub canRotateCCW() -> ubyte {
rotateCCW()
ubyte okay=true ; TODO determine
rotateCW()
return okay
}
; For movement checking it is not needed to clamp the x/y coordinates, ; For movement checking it is not needed to clamp the x/y coordinates,
; because we have to check for brick collisions anyway. ; because we have to check for brick collisions anyway.
; The full play area is bordered by (in)visible characters that will collide. ; The full play area is bordered by (in)visible characters that will collide.
; Collision is determined by reading the screen data directly.
; This means the current position of the block on the screen has to be cleared first,
; and redrawn after the collision result has been determined.
sub canRotateCW(ubyte xpos, ubyte ypos) -> ubyte {
main.drawBlock(xpos, ypos, 32)
rotateCW()
ubyte collision = collides(xpos, ypos)
rotateCCW()
main.drawBlock(xpos, ypos, 160)
return not collision
}
sub canRotateCCW(ubyte xpos, ubyte ypos) -> ubyte {
main.drawBlock(xpos, ypos, 32)
rotateCCW()
ubyte collision = collides(xpos, ypos)
rotateCW()
main.drawBlock(xpos, ypos, 160)
return not collision
}
sub canMoveLeft(ubyte xpos, ubyte ypos) -> ubyte { sub canMoveLeft(ubyte xpos, ubyte ypos) -> ubyte {
main.drawBlock(xpos, ypos, 32) main.drawBlock(xpos, ypos, 32)
ubyte result = canActuallyMoveLeft(xpos, ypos) ubyte collision = collides(xpos-1, ypos)
main.drawBlock(xpos, ypos, 160) main.drawBlock(xpos, ypos, 160)
return result return not collision
sub canActuallyMoveLeft(ubyte xpos, ubyte ypos) -> ubyte {
; @todo make this a generic subroutine that also works to check right and bottom collisions...
return not (currentBlock[0] and c64scr.getchr(xpos-1, ypos)!=32
or currentBlock[1] and c64scr.getchr(xpos, ypos)!=32
or currentBlock[2] and c64scr.getchr(xpos+1, ypos)!=32
or currentBlock[3] and c64scr.getchr(xpos+2, ypos)!=32
or currentBlock[4] and c64scr.getchr(xpos-1, ypos+1)!=32
or currentBlock[5] and c64scr.getchr(xpos, ypos+1)!=32
or currentBlock[6] and c64scr.getchr(xpos+1, ypos+1)!=32
or currentBlock[7] and c64scr.getchr(xpos+2, ypos+1)!=32
or currentBlock[8] and c64scr.getchr(xpos-1, ypos+2)!=32
or currentBlock[9] and c64scr.getchr(xpos, ypos+2)!=32
or currentBlock[10] and c64scr.getchr(xpos+1, ypos+2)!=32
or currentBlock[11] and c64scr.getchr(xpos+2, ypos+2)!=32
or currentBlock[12] and c64scr.getchr(xpos-1, ypos+3)!=32
or currentBlock[13] and c64scr.getchr(xpos, ypos+3)!=32
or currentBlock[14] and c64scr.getchr(xpos+1, ypos+3)!=32
or currentBlock[15] and c64scr.getchr(xpos+2, ypos+3)!=32)
}
} }
sub canMoveRight(ubyte xpos, ubyte ypos) -> ubyte { sub canMoveRight(ubyte xpos, ubyte ypos) -> ubyte {
main.drawBlock(xpos, ypos, 32) main.drawBlock(xpos, ypos, 32)
ubyte result = canActuallyMoveRight(xpos, ypos) ubyte collision = collides(xpos+1, ypos)
main.drawBlock(xpos, ypos, 160) main.drawBlock(xpos, ypos, 160)
return result return not collision
sub canActuallyMoveRight(ubyte xpos, ubyte ypos) -> ubyte {
; @todo use the generic subroutine that also works to check right and bottom collisions...
return not (currentBlock[0] and c64scr.getchr(xpos+1, ypos)!=32
or currentBlock[1] and c64scr.getchr(xpos+2, ypos)!=32
or currentBlock[2] and c64scr.getchr(xpos+3, ypos)!=32
or currentBlock[3] and c64scr.getchr(xpos+4, ypos)!=32
or currentBlock[4] and c64scr.getchr(xpos+1, ypos+1)!=32
or currentBlock[5] and c64scr.getchr(xpos+2, ypos+1)!=32
or currentBlock[6] and c64scr.getchr(xpos+3, ypos+1)!=32
or currentBlock[7] and c64scr.getchr(xpos+4, ypos+1)!=32
or currentBlock[8] and c64scr.getchr(xpos+1, ypos+2)!=32
or currentBlock[9] and c64scr.getchr(xpos+2, ypos+2)!=32
or currentBlock[10] and c64scr.getchr(xpos+3, ypos+2)!=32
or currentBlock[11] and c64scr.getchr(xpos+4, ypos+2)!=32
or currentBlock[12] and c64scr.getchr(xpos+1, ypos+3)!=32
or currentBlock[13] and c64scr.getchr(xpos+2, ypos+3)!=32
or currentBlock[14] and c64scr.getchr(xpos+3, ypos+3)!=32
or currentBlock[15] and c64scr.getchr(xpos+4, ypos+3)!=32)
}
} }
sub canMoveDown(ubyte xpos, ubyte ypos) -> ubyte { sub canMoveDown(ubyte xpos, ubyte ypos) -> ubyte {
return ypos<main.boardOffsetY+main.boardHeight-4 ; TODO deal with actual block/border collision, use generic check routine main.drawBlock(xpos, ypos, 32)
ubyte collision = collides(xpos, ypos+1)
main.drawBlock(xpos, ypos, 160)
return not collision
} }
sub isGameOver() -> ubyte { sub collides(ubyte xpos, ubyte ypos) -> ubyte {
return false ; TODO determine fail state return currentBlock[0] and c64scr.getchr(xpos, ypos)!=32
or currentBlock[1] and c64scr.getchr(xpos+1, ypos)!=32
or currentBlock[2] and c64scr.getchr(xpos+2, ypos)!=32
or currentBlock[3] and c64scr.getchr(xpos+3, ypos)!=32
or currentBlock[4] and c64scr.getchr(xpos, ypos+1)!=32
or currentBlock[5] and c64scr.getchr(xpos+1, ypos+1)!=32
or currentBlock[6] and c64scr.getchr(xpos+2, ypos+1)!=32
or currentBlock[7] and c64scr.getchr(xpos+3, ypos+1)!=32
or currentBlock[8] and c64scr.getchr(xpos, ypos+2)!=32
or currentBlock[9] and c64scr.getchr(xpos+1, ypos+2)!=32
or currentBlock[10] and c64scr.getchr(xpos+2, ypos+2)!=32
or currentBlock[11] and c64scr.getchr(xpos+3, ypos+2)!=32
or currentBlock[12] and c64scr.getchr(xpos, ypos+3)!=32
or currentBlock[13] and c64scr.getchr(xpos+1, ypos+3)!=32
or currentBlock[14] and c64scr.getchr(xpos+2, ypos+3)!=32
or currentBlock[15] and c64scr.getchr(xpos+3, ypos+3)!=32
}
sub isGameOver(ubyte xpos, ubyte ypos) -> ubyte {
return ypos==main.startYpos and not canMoveDown(xpos, ypos)
} }
} }

View File

@ -5,6 +5,10 @@
; @todo see problem in looplabelproblem.p8 ; @todo see problem in looplabelproblem.p8
; @todo when using -noopt, the error "can only push address of string that is a variable on the heap" appears when using strings
sub start() { sub start() {
uword w = 12345 uword w = 12345