fix bugs
parent
109a452179
commit
f154d6c2b9
146
tetris.py
146
tetris.py
|
@ -77,26 +77,17 @@ BOARD_HEIGHT = 17
|
|||
GAME_WINDOW_WIDTH = 2 * BOARD_WIDTH + 2
|
||||
GAME_WINDOW_HEIGHT = BOARD_HEIGHT + 2
|
||||
|
||||
HELP_WINDOW_WIDTH = 18
|
||||
HELP_WINDOW_HEIGHT = 8
|
||||
HELP_WINDOW_WIDTH = 19
|
||||
HELP_WINDOW_HEIGHT = 7
|
||||
|
||||
STATUS_WINDOW_WIDTH = 18
|
||||
STATUS_WINDOW_HEIGHT = 10
|
||||
STATUS_WINDOW_HEIGHT = 12
|
||||
STATUS_WINDOW_WIDTH = HELP_WINDOW_WIDTH
|
||||
|
||||
TITLE_HEIGHT = 6
|
||||
|
||||
LEFT_MARGIN = 3
|
||||
|
||||
def init_screen():
|
||||
screen = curses.initscr()
|
||||
curses.beep()
|
||||
curses.noecho()
|
||||
curses.cbreak()
|
||||
curses.start_color()
|
||||
curses.curs_set(0)
|
||||
|
||||
init_colors()
|
||||
|
||||
return screen
|
||||
TITLE_WIDTH = FOOTER_WIDTH = 50
|
||||
|
||||
|
||||
def init_colors():
|
||||
|
@ -106,6 +97,7 @@ def init_colors():
|
|||
curses.init_pair(98, curses.COLOR_CYAN, curses.COLOR_BLACK)
|
||||
curses.init_pair(97, curses.COLOR_RED, curses.COLOR_BLACK)
|
||||
curses.init_pair(96, curses.COLOR_BLACK, curses.COLOR_CYAN)
|
||||
curses.init_pair(95, curses.COLOR_BLACK, curses.COLOR_WHITE)
|
||||
|
||||
curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_BLUE)
|
||||
curses.init_pair(2, curses.COLOR_BLACK, curses.COLOR_RED)
|
||||
|
@ -117,7 +109,7 @@ def init_colors():
|
|||
def init_game_window():
|
||||
"""Create and return game window"""
|
||||
|
||||
window = curses.newwin(GAME_WINDOW_HEIGHT, GAME_WINDOW_WIDTH, TITLE_HEIGHT, 3)
|
||||
window = curses.newwin(GAME_WINDOW_HEIGHT, GAME_WINDOW_WIDTH, TITLE_HEIGHT, LEFT_MARGIN)
|
||||
# window.nodelay(True)
|
||||
window.keypad(1)
|
||||
|
||||
|
@ -127,7 +119,7 @@ def init_game_window():
|
|||
def init_help_window():
|
||||
"""Create and return help window"""
|
||||
|
||||
window = curses.newwin(HELP_WINDOW_HEIGHT, HELP_WINDOW_WIDTH, TITLE_HEIGHT + STATUS_WINDOW_HEIGHT + 1,
|
||||
window = curses.newwin(HELP_WINDOW_HEIGHT, HELP_WINDOW_WIDTH, TITLE_HEIGHT + STATUS_WINDOW_HEIGHT,
|
||||
GAME_WINDOW_WIDTH + 5)
|
||||
return window
|
||||
|
||||
|
@ -140,15 +132,10 @@ def init_status_window():
|
|||
|
||||
|
||||
def draw_game_window(window):
|
||||
"""Draw game widnow"""
|
||||
"""Draw game window"""
|
||||
|
||||
window.border()
|
||||
|
||||
# draw dots
|
||||
for row in range(1, GAME_WINDOW_HEIGHT - 1, 2):
|
||||
for col in range(1, GAME_WINDOW_WIDTH - 2, 2):
|
||||
window.addstr(row, col, ".", curses.color_pair(99))
|
||||
|
||||
# draw board
|
||||
for a in range(BOARD_HEIGHT):
|
||||
for b in range(BOARD_WIDTH):
|
||||
|
@ -156,7 +143,7 @@ def draw_game_window(window):
|
|||
window.addstr(a + 1, 2 * b + 1, " ", curses.color_pair(96))
|
||||
else:
|
||||
# hack: to avoid clearing
|
||||
window.addstr(a + 1, 2 * b + 1, " ")
|
||||
window.addstr(a + 1, 2 * b + 1, " .", curses.color_pair(99))
|
||||
|
||||
# draw current block
|
||||
for a in range(board.current_block.size[0]):
|
||||
|
@ -166,12 +153,22 @@ def draw_game_window(window):
|
|||
y = board.current_block_pos[0] + a + 1
|
||||
window.addstr(y, x, " ", curses.color_pair(board.current_block.color))
|
||||
|
||||
if board.is_game_over():
|
||||
go_title = " Game Over "
|
||||
ag_title = " Enter - play again "
|
||||
|
||||
window.addstr(int(GAME_WINDOW_HEIGHT*.4), (GAME_WINDOW_WIDTH - len(go_title)) // 2, go_title, curses.color_pair(95))
|
||||
window.addstr(int(GAME_WINDOW_HEIGHT*.5), (GAME_WINDOW_WIDTH - len(ag_title)) // 2, ag_title, curses.color_pair(95))
|
||||
|
||||
window.refresh()
|
||||
|
||||
|
||||
def draw_status_window(window):
|
||||
"""Draw status window"""
|
||||
|
||||
if board.is_game_over():
|
||||
return
|
||||
|
||||
# hack: avoid clearing (blinking)
|
||||
for row in range(1, STATUS_WINDOW_HEIGHT - 1):
|
||||
window.addstr(row, 2, "".rjust(STATUS_WINDOW_WIDTH - 3, " "))
|
||||
|
@ -181,14 +178,16 @@ def draw_status_window(window):
|
|||
score = random.randint(1, 3000)
|
||||
|
||||
window.addstr(1, 2, f"Score: {score}")
|
||||
window.addstr(2, 2, "Next block:")
|
||||
window.addstr(2, 2, "Lines: 300")
|
||||
window.addstr(3, 2, "Speed: 2")
|
||||
window.addstr(4, 2, "Best Score: 2000")
|
||||
|
||||
start_col = int(STATUS_WINDOW_WIDTH / 2 - board.next_block.size[1])
|
||||
|
||||
for row in range(board.next_block.size[0]):
|
||||
for col in range(board.next_block.size[1]):
|
||||
if board.next_block.shape[row][col] == 1:
|
||||
window.addstr(4 + row, start_col + 2 * col, " ", curses.color_pair(board.next_block.color))
|
||||
window.addstr(6 + row, start_col + 2 * col, " ", curses.color_pair(board.next_block.color))
|
||||
|
||||
window.refresh()
|
||||
|
||||
|
@ -197,8 +196,6 @@ def draw_help_window(window):
|
|||
"""Draw help window"""
|
||||
|
||||
window.border()
|
||||
title = "Controls"
|
||||
window.addstr(0, int(HELP_WINDOW_WIDTH / 2 - len(title) / 2), title)
|
||||
|
||||
window.addstr(1, 2, "Move - ← ↓ →")
|
||||
window.addstr(2, 2, "Drop - space")
|
||||
|
@ -212,7 +209,7 @@ def draw_help_window(window):
|
|||
def draw_title():
|
||||
"""Draw title"""
|
||||
|
||||
window = curses.newwin(TITLE_HEIGHT, 50, 1, 3)
|
||||
window = curses.newwin(TITLE_HEIGHT, TITLE_WIDTH, 1, LEFT_MARGIN)
|
||||
window.addstr(0, 4, "##### #### ##### ### # ####", curses.color_pair(98))
|
||||
window.addstr(1, 4, " # # # # # #", curses.color_pair(98))
|
||||
window.addstr(2, 4, " # ### # # # # ###", curses.color_pair(98))
|
||||
|
@ -226,9 +223,11 @@ def draw_title():
|
|||
|
||||
|
||||
def draw_footer():
|
||||
window = curses.newwin(1, 50, TITLE_HEIGHT + GAME_WINDOW_HEIGHT + 1, 10)
|
||||
window.addstr(0, 9, "Made with", curses.color_pair(98))
|
||||
window.addstr(0, 19, "❤", curses.color_pair(97))
|
||||
title = "Made with"
|
||||
window = curses.newwin(1, FOOTER_WIDTH, TITLE_HEIGHT + GAME_WINDOW_HEIGHT + 1, LEFT_MARGIN)
|
||||
col_pos = int((GAME_WINDOW_WIDTH + STATUS_WINDOW_WIDTH - len(title) + 1) / 2)
|
||||
window.addstr(0, col_pos, title, curses.color_pair(98))
|
||||
window.addstr(0, col_pos + len(title) + 1, "❤", curses.color_pair(97))
|
||||
|
||||
window.refresh()
|
||||
|
||||
|
@ -248,7 +247,7 @@ block_shapes = [
|
|||
[[1, 1],
|
||||
[1, 1]],
|
||||
# i block
|
||||
[[1, 1, 1, 1]]
|
||||
[[1], [1], [1], [1]]
|
||||
]
|
||||
|
||||
|
||||
|
@ -258,20 +257,36 @@ class Board:
|
|||
def __init__(self, height, width):
|
||||
self.height = height
|
||||
self.width = width
|
||||
self.board = [[0 for _ in range(width)] for _ in range(height)]
|
||||
self.board = self._get_new_board()
|
||||
|
||||
self.current_block_pos = None
|
||||
self.current_block = None
|
||||
self.next_block = None
|
||||
|
||||
self.game_over = False
|
||||
|
||||
def _get_new_board(self):
|
||||
return [[0 for _ in range(self.width)] for _ in range(self.height)]
|
||||
|
||||
def start(self):
|
||||
"""Start game"""
|
||||
|
||||
self.board = self._get_new_board()
|
||||
|
||||
self.current_block_pos = None
|
||||
self.current_block = None
|
||||
self.next_block = None
|
||||
|
||||
self.game_over = False
|
||||
|
||||
self.place_new_block()
|
||||
|
||||
def place_new_block(self):
|
||||
"""Place new block and generate the next one"""
|
||||
|
||||
if self.is_game_over():
|
||||
raise Exception("game is over")
|
||||
|
||||
if self.next_block is None:
|
||||
self.current_block = self._generate_block()
|
||||
self.next_block = self._generate_block()
|
||||
|
@ -282,6 +297,9 @@ class Board:
|
|||
col_pos = math.ceil((self.width - self.current_block.size[1]) / 2)
|
||||
self.current_block_pos = [0, col_pos]
|
||||
|
||||
if self._check_overlapping(self.current_block_pos):
|
||||
self.game_over = True
|
||||
|
||||
def _land_block(self):
|
||||
"""Put block to the board and generate a new one"""
|
||||
|
||||
|
@ -292,8 +310,8 @@ class Board:
|
|||
|
||||
self.place_new_block()
|
||||
|
||||
def check_game_over(self):
|
||||
pass
|
||||
def is_game_over(self):
|
||||
return self.game_over
|
||||
|
||||
def move_block(self, direction):
|
||||
"""Try to move block"""
|
||||
|
@ -333,6 +351,14 @@ class Board:
|
|||
for r in range(row, 0, -1):
|
||||
self.board[r] = self.board[r-1]
|
||||
|
||||
def _check_overlapping(self, pos):
|
||||
for row in range(self.current_block.size[0]):
|
||||
for col in range(self.current_block.size[1]):
|
||||
if self.current_block.shape[row][col] == 1:
|
||||
if self.board[pos[0] + row][pos[1] + col] == 1:
|
||||
return True
|
||||
return False
|
||||
|
||||
def _can_move(self, to_pos):
|
||||
"""Check if move is possible"""
|
||||
|
||||
|
@ -340,12 +366,7 @@ class Board:
|
|||
or to_pos[0] + self.current_block.size[0] > BOARD_HEIGHT:
|
||||
return False
|
||||
|
||||
for row in range(self.current_block.size[0]):
|
||||
for col in range(self.current_block.size[1]):
|
||||
if self.current_block.shape[row][col] == 1:
|
||||
if self.board[to_pos[0] + row][to_pos[1] + col] == 1:
|
||||
return False
|
||||
return True
|
||||
return not self._check_overlapping(to_pos)
|
||||
|
||||
@staticmethod
|
||||
def _generate_block():
|
||||
|
@ -383,7 +404,14 @@ board.start()
|
|||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
screen = init_screen()
|
||||
scr = curses.initscr()
|
||||
curses.beep()
|
||||
curses.noecho()
|
||||
curses.cbreak()
|
||||
curses.start_color()
|
||||
curses.curs_set(0)
|
||||
|
||||
init_colors()
|
||||
|
||||
draw_title()
|
||||
draw_footer()
|
||||
|
@ -405,20 +433,26 @@ if __name__ == "__main__":
|
|||
|
||||
key_event = game_window.getch()
|
||||
|
||||
if key_event == curses.KEY_UP:
|
||||
board.current_block.rotate()
|
||||
elif key_event == curses.KEY_DOWN:
|
||||
board.move_block("down")
|
||||
elif key_event == curses.KEY_LEFT:
|
||||
board.move_block("left")
|
||||
elif key_event == curses.KEY_RIGHT:
|
||||
board.move_block("right")
|
||||
elif key_event == ord(" "):
|
||||
board.drop()
|
||||
elif key_event == ord("q"):
|
||||
if key_event == ord("q"):
|
||||
quit_game = True
|
||||
elif key_event == ord("p"):
|
||||
pass
|
||||
|
||||
if not board.is_game_over():
|
||||
if key_event == curses.KEY_UP:
|
||||
board.current_block.rotate()
|
||||
elif key_event == curses.KEY_DOWN:
|
||||
board.move_block("down")
|
||||
elif key_event == curses.KEY_LEFT:
|
||||
board.move_block("left")
|
||||
elif key_event == curses.KEY_RIGHT:
|
||||
board.move_block("right")
|
||||
elif key_event == ord(" "):
|
||||
board.drop()
|
||||
elif key_event == ord("p"):
|
||||
pass
|
||||
else:
|
||||
curses.beep()
|
||||
if key_event == ord("\n"):
|
||||
board.start()
|
||||
|
||||
draw_game_window(game_window)
|
||||
|
||||
|
|
Loading…
Reference in New Issue