Skip to content

Commit

Permalink
game over screen; decouple main.py from tetris game draw/update logic
Browse files Browse the repository at this point in the history
  • Loading branch information
richardso21 committed Apr 29, 2024
1 parent 24f0909 commit 2a8015c
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 26 deletions.
25 changes: 16 additions & 9 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import pyxel

from ttris.board import Board
from ttris.constants import DISPLAY_SCALE, FPS, WINDOW_HEIGHT, WINDOW_WIDTH
from ttris.main import TtrisGame

# constants for pyxel.init
WINDOW_HEIGHT = 200
WINDOW_WIDTH = 180
DISPLAY_SCALE = 8
FPS = 60

class TtrisGame:

class TtrisMenu:
def __init__(self) -> None:
pyxel.init(
WINDOW_WIDTH,
Expand All @@ -15,16 +20,18 @@ def __init__(self) -> None:
)
pyxel.screen_mode(2)
pyxel.load("assets/ttris.pyxres")
self.board = Board(10, 1, 5)
pyxel.run(self.update, self.draw)
self.runGame()

def update(self) -> None:
self.board.update()
pass

def draw(self) -> None:
pyxel.cls(0)
self.board.draw()
pass

def runGame(self) -> None:
self.game = TtrisGame()
self.game.run()
pyxel.run(self.update, self.draw)


TtrisGame()
TtrisMenu()
47 changes: 39 additions & 8 deletions ttris/board.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def __init__(self, das: int, arr: int, lookahead: int):
self.hard_drop_tick: bool = False
self.score: int = 0
self.previous_tspin: TSpinType = TSpinType.NONE
self.game_over: bool = False

@property
def curr_lc_goal_level(self) -> int:
Expand All @@ -54,6 +55,8 @@ def soft_drop_timer(self) -> int:
return LEVEL_GRAVITY_FRAMES[self.level - 1]

def update(self) -> None:
if self.game_over:
return
self.hard_drop_tick = False
# check controls
self.controller.checkControls()
Expand All @@ -73,6 +76,24 @@ def update(self) -> None:
self.clearLines()

def draw(self) -> None:
# draw board elements
self.drawBoard(self.game_over)

# draw current/falling piece
self.drawCurrPiece(self.game_over)

# draw hold and queue pieces & elements
self.drawHold()
self.drawQueue()

# update score and other game info besides board
Score.draw(self)

if self.game_over:
pyxel.rect(BOARD_X + 15, BOARD_Y + 95, 45, 15, 8)
pyxel.text(BOARD_X + 20, BOARD_Y + 100, "GAME OVER", 7)

def drawBoard(self, game_over: bool) -> None:
# draw the bounding box up to the 20th block
pyxel.rectb(
BOARD_X - 1,
Expand All @@ -89,8 +110,9 @@ def draw(self) -> None:
1,
0,
)

# draw existing pieces on the board if a piece has dropped
if game_over:
pyxel.dither(0.5)
# draw existing blocks
for i, row in enumerate(self.board_arr):
for j, block in enumerate(row):
if block == MinoType.NO_MINO:
Expand All @@ -99,17 +121,25 @@ def draw(self) -> None:
y = i * BLOCK_SIZE + BOARD_Y
u = (block.value - 1) * BLOCK_SIZE
pyxel.blt(x, y, 1, u, 0, BLOCK_SIZE, BLOCK_SIZE)
pyxel.dither(1)

self.curr_piece.drawOnBoard(hint=True) # draw hint first, then the actual piece
def drawCurrPiece(self, game_over: bool) -> None:
if game_over:
pyxel.dither(0.5)
if not game_over:
self.curr_piece.drawOnBoard(
hint=True
) # draw hint first, then the actual piece
self.curr_piece.drawOnBoard()

# draw locking status of current piece
self.curr_piece.drawLockDelayMeter(
BOARD_X - 1,
BOARD_Y + (BLOCK_SIZE * (BOARD_HEIGHT)),
BLOCK_SIZE * BOARD_WIDTH + 1,
)
pyxel.dither(1)

def drawHold(self) -> None:
# draw holding piece
pyxel.rectb(
BOARD_X - 48, BOARD_Y + (BLOCK_SIZE * OVERFLOW_HEIGHT) - 10, 48, 32, 13
Expand All @@ -130,6 +160,7 @@ def draw(self) -> None:
)
pyxel.dither(1)

def drawQueue(self) -> None:
# draw minos/pieces in queue
pyxel.rectb(
BOARD_X + (BLOCK_SIZE * BOARD_WIDTH),
Expand All @@ -150,9 +181,6 @@ def draw(self) -> None:
15 + (i * 24) - (4 if minoType is MinoType.MINO_I else 0),
)

# update score and other game info besides board
Score.draw(self)

def clearLines(self) -> None:
# check for any line clears and construct new board if necessary
clear_inds = [i for i, row in enumerate(self.board_arr) if all(row)]
Expand Down Expand Up @@ -224,4 +252,7 @@ def hardDropCurrPiece(self) -> None:

def spawnMino(self) -> None:
self.curr_piece = self.mino_provider.fetchMino()
self.curr_piece.updateHint(self.board_arr)
if self.curr_piece.isColliding(self.board_arr):
self.game_over = True
else:
self.curr_piece.updateHint(self.board_arr)
6 changes: 0 additions & 6 deletions ttris/constants.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
# constants for pyxel.init
WINDOW_HEIGHT = 200
WINDOW_WIDTH = 180
DISPLAY_SCALE = 8
FPS = 60

OVERFLOW_HEIGHT = 5 # height (in blocks) of the hidden overflow area
BOARD_HEIGHT = 25 # height (in blocks) of the entire board area (including overflow)
BOARD_WIDTH = 10 # width (in blocks) of the board
Expand Down
19 changes: 19 additions & 0 deletions ttris/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import pyxel

from ttris.board import Board


class TtrisGame:
def __init__(self) -> None:
self.board = Board(10, 1, 5)

def update(self) -> None:
self.board.update()
pass

def draw(self) -> None:
pyxel.cls(0)
self.board.draw()

def run(self) -> None:
pyxel.run(self.update, self.draw)
6 changes: 3 additions & 3 deletions ttris/tetriminos.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,9 +253,9 @@ def updateHint(self, board: List[List[MinoType]]) -> None:

def isValidPosition(self, board: List[List[MinoType]]) -> bool:
# check collision with other minos and out of bounds
return not (self._isOutOfBounds() or self._isColliding(board))
return not (self.isOutOfBounds() or self.isColliding(board))

def _isOutOfBounds(self) -> bool:
def isOutOfBounds(self) -> bool:
# for each block, check if it exceeds the bounds of the board
for i, row in enumerate(self.mino_arr):
for j, el in enumerate(row):
Expand All @@ -269,7 +269,7 @@ def _isOutOfBounds(self) -> bool:
return True
return False

def _isColliding(self, board: List[List[MinoType]]) -> bool:
def isColliding(self, board: List[List[MinoType]]) -> bool:
# for each block, check if it is already occupied by a mino block
for i, row in enumerate(self.mino_arr):
for j, el in enumerate(row):
Expand Down

0 comments on commit 2a8015c

Please sign in to comment.