summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xcameltris.py322
-rw-r--r--pycameltris/controller.py3
-rw-r--r--pycameltris/misc.py6
-rw-r--r--pycameltris/screens/InGame.py321
-rw-r--r--pycameltris/screens/Pause.py34
5 files changed, 378 insertions, 308 deletions
diff --git a/cameltris.py b/cameltris.py
index 5d80cad..b454db2 100755
--- a/cameltris.py
+++ b/cameltris.py
@@ -1,258 +1,13 @@
#!/usr/bin/env python3
import argparse
-import contextlib
-from functools import partial
-import random
-import sys
import pygame
-from pycameltris.controller import KeyboardController, JoystickController, Input
-from pycameltris.piece import *
-
-
-class WouldCollide(Exception):
- pass
-
-
-class PlayerQuit(Exception):
- pass
-
-
-def refresh_right_pane_canvas():
- for player in players:
- player.level_canvas.fill(black)
- player.score_canvas.fill(black)
-
- if pygame.font:
- score_font = pygame.font.Font(None, 56)
-
- player.score_canvas.blit(score_font.render(f"{player.score:08d}", True, white), (0, 0))
- player.level_canvas.blit(score_font.render(f"{player.level:08d}", True, white), (0, 0))
- right_pane_canvas.blit(player.score_canvas, (2, 10))
- right_pane_canvas.blit(player.level_canvas, (2, 70))
-
- right_pane_canvas.blit(player.piece_preview_canvas, (50, 200))
-
-
-def refresh_screen():
- for player in players:
- player.refresh_grid_canvas()
- screen.blit(player.grid_canvas, (0, 0))
- refresh_right_pane_canvas()
- screen.blit(right_pane_canvas, (501, 0))
-
-
-class Player:
- def __init__(self, controller):
- self.controller = controller
- self.grid = [[None for _ in range(10)] for _ in range(20)]
-
- self.current_piece, self.current_piece_position = self.generate_piece()
- self.next_piece, self.next_piece_position = self.generate_piece()
-
- self.level = self.starting_level = ARGS["starting_level"]
- self.score = 0
-
- self.lines_burnt = 0
-
- self.das = 0
- self.pressing_down_countdown = None
-
- self.piece_drop_frames = 0
-
- self.grid_canvas = pygame.Surface((500, 1000))
- self.piece_preview_canvas = pygame.Surface((200, 200))
- self.score_canvas = pygame.Surface((296, 50))
- self.level_canvas = pygame.Surface((296, 50))
-
-
- def generate_piece(self):
- # We may want to make this a function outside the class
- piece = random.choice((TPiece, SPiece, IPiece, ZPiece, SquarePiece, LPiece, JPiece))()
-
- for row_id, row in enumerate(piece.elements):
- if list(filter(lambda x: x is not None, row)):
- break
-
- initial_y_position = -row_id
- initial_x_position = (len(self.grid[0]) // 2) - (len(piece.elements[0]) // 2)
-
- return (piece, [initial_y_position, initial_x_position])
-
- def burn_rows(self):
- rows_to_burn = list()
-
- for row in self.grid:
- if all(map(lambda element: element is not None, row)):
- rows_to_burn.append(row)
-
- for row in rows_to_burn:
- self.grid.insert(0, [None for _ in range(10)])
- self.grid.remove(row)
-
- return len(rows_to_burn)
-
- def lock_piece(self):
- if self.has_collision(self.current_piece_position[0], self.current_piece_position[1]):
- raise WouldCollide()
-
- for row_id, row in enumerate(self.current_piece.elements):
- for col_id, element in enumerate(row):
- if element is None:
- continue
- self.grid[row_id + self.current_piece_position[0]][col_id + self.current_piece_position[1]] = element
-
- count = self.burn_rows()
-
- if count == 1:
- print("Single")
- rate = 1
- elif count == 2:
- print("Double")
- rate = 2.5
- elif count == 3:
- print("Triple")
- rate = 7.5
- elif count == 4:
- print("Tetris!")
- rate = 30
- else:
- rate = 0
-
- self.lines_burnt += count
-
- self.score += int(self.level * 40 * rate)
-
- if self.lines_burnt >= self.level * 10:
- self.level += 1
- self.current_piece, self.current_piece_position = self.next_piece, self.next_piece_position
- self.next_piece, self.next_piece_position = self.generate_piece()
- self.refresh_piece_preview_canvas()
-
- def has_collision(self, y: int, x: int) -> bool:
- try:
- for row_id, row in enumerate(self.current_piece.elements):
- for col_id, element in enumerate(row):
- if element is None:
- continue
-
- if row_id + y < 0:
- continue
-
- if col_id + x < 0:
- return True
-
- if self.grid[row_id + y][col_id + x] is not None:
- return True
-
- except IndexError:
- return True
-
- return False
-
- def move_piece_down(self):
- if not self.has_collision(self.current_piece_position[0] + 1, self.current_piece_position[1]):
- self.current_piece_position[0] += 1
- else:
- raise WouldCollide()
-
- def move_piece_up(self):
- if not self.has_collision(self.current_piece_position[0] - 1, self.current_piece_position[1]):
- self.current_piece_position[0] -= 1
- else:
- raise WouldCollide()
-
- def move_piece_left(self):
- if not self.has_collision(self.current_piece_position[0], self.current_piece_position[1] - 1):
- self.current_piece_position[1] -= 1
- else:
- raise WouldCollide()
-
- def move_piece_right(self):
- if not self.has_collision(self.current_piece_position[0], self.current_piece_position[1] + 1):
- self.current_piece_position[1] += 1
- else:
- raise WouldCollide()
-
- def rotate_piece_counter_clockwise(self):
- self.current_piece.rotate_counter_clockwise()
-
- if self.has_collision(self.current_piece_position[0], self.current_piece_position[1]):
- self.current_piece.rotate_clockwise()
- raise WouldCollide()
-
- def rotate_piece_clockwise(self):
- self.current_piece.rotate_clockwise()
-
- if self.has_collision(self.current_piece_position[0], self.current_piece_position[1]):
- self.current_piece.rotate_counter_clockwise()
- raise WouldCollide()
-
- def handle_input_pressed(self, event):
- if self.controller.get_input_down(event) == Input.QUIT:
- raise PlayerQuit()
-
- with contextlib.suppress(WouldCollide):
- if self.controller.get_input_down(event) == Input.MOVE_RIGHT:
- self.move_piece_right()
- self.das = 0
- if self.controller.get_input_down(event) == Input.MOVE_LEFT:
- self.move_piece_left()
- self.das = 0
- if self.controller.get_input_down(event) == Input.ROTATE_CLOCKWISE:
- self.rotate_piece_clockwise()
- if self.controller.get_input_down(event) == Input.ROTATE_COUNTER_CLOCKWISE:
- self.rotate_piece_counter_clockwise()
- if self.controller.get_input_down(event) == Input.MOVE_DOWN:
- self.piece_drop_frames = 0
- self.pressing_down_countdown = 3
- try:
- self.move_piece_down()
- except WouldCollide:
- self.lock_piece()
-
- def handle_input_released(self, event):
- if self.controller.get_input_up(event) == Input.MOVE_DOWN:
- self.pressing_down_countdown = None
-
- def refresh_piece_preview_canvas(self):
- self.piece_preview_canvas.fill(black)
-
- non_empty_rows = list()
- for row in self.next_piece.elements:
- if any(map(lambda element: element is not None, row)):
- non_empty_rows.append(row)
-
- non_empty_cols = set()
- for row in self.next_piece.elements:
- for col_id, element in enumerate(row):
- if element is not None:
- non_empty_cols.add(col_id)
-
- y_offset = (4 - len(non_empty_rows)) / 2
- x_offset = (4 - len(non_empty_cols)) / 2
-
- # Display the next piece
- for row_idx, row in enumerate(non_empty_rows):
- for col_idx, element in enumerate(row):
- if element is not None:
- self.piece_preview_canvas.blit(element, ((col_idx + x_offset) * 50 + 1, (row_idx + y_offset) * 50 + 1))
-
- def refresh_grid_canvas(self):
- self.grid_canvas.fill(black)
-
- for row_idx, row in enumerate(self.grid):
- for col_idx, element in enumerate(row):
- if element is not None:
- self.grid_canvas.blit(element, (col_idx * 50 + 1, row_idx * 50 + 1))
-
- # Display the current piece
- for row_idx, row in enumerate(self.current_piece.elements):
- for col_idx, element in enumerate(row):
- if element is not None:
- self.grid_canvas.blit(element, ((col_idx + self.current_piece_position[1]) * 50 + 1, (row_idx + self.current_piece_position[0]) * 50 + 1))
+from pycameltris.controller import KeyboardController, JoystickController
+from pycameltris.screens.InGame import InGame as InGameScreen, Player
+from pycameltris.screens.Pause import Pause as PauseScreen
+from pycameltris.misc import Pause, UnPause
PARSER = argparse.ArgumentParser()
@@ -268,10 +23,6 @@ pygame.init()
screen = pygame.display.set_mode((801, 1000))
-right_pane_canvas = pygame.Surface((300, 1000))
-right_pane_canvas.fill((255, 255, 255))
-
-
if ARGS["joystick_id"] is not None:
joystick = pygame.joystick.Joystick(ARGS["joystick_id"])
joystick.init()
@@ -280,69 +31,24 @@ else:
controller = KeyboardController(pygame.key)
# Just one player
-players = [Player(controller)]
+players = [Player(controller, ARGS["starting_level"])]
for player in players:
player.refresh_piece_preview_canvas()
-# Number of frames
-frames_per_gridcell = [48, 43, 38, 33, 28, 23, 18, 13, 8, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1]
-
clock = pygame.time.Clock()
-def handle_input_pressed(instance, event):
- for player in players:
- if isinstance(player.controller, instance):
- player.handle_input_pressed(event)
-
-
-def handle_input_released(instance, event):
- for player in players:
- if isinstance(player.controller, instance):
- player.handle_input_released(event)
-
-event_handler = dict()
-event_handler[pygame.QUIT] = lambda _: sys.exit()
-event_handler[pygame.KEYDOWN] = partial(handle_input_pressed, KeyboardController)
-event_handler[pygame.KEYUP] = partial(handle_input_released, KeyboardController)
-event_handler[pygame.JOYBUTTONDOWN] = partial(handle_input_pressed, JoystickController)
-event_handler[pygame.JOYBUTTONUP] = partial(handle_input_released, JoystickController)
+current_screen = ingame_screen = InGameScreen(players, screen)
while True:
- for player in players:
- player.piece_drop_frames += 1
-
- for event in pygame.event.get():
- with contextlib.suppress(KeyError):
- event_handler[event.type](event)
-
- for player in players:
- player.das += 1
- if player.das == 16:
- with contextlib.suppress(WouldCollide):
- if controller.is_pressed(Input.MOVE_RIGHT):
- player.move_piece_right()
- if controller.is_pressed(Input.MOVE_LEFT):
- player.move_piece_left()
- player.das = 10
-
- if player.pressing_down_countdown == 0:
- try:
- player.move_piece_down()
- except WouldCollide:
- player.lock_piece()
- player.pressing_down_countdown = 2
- elif player.pressing_down_countdown is not None:
- player.pressing_down_countdown -= 1
-
- if player.piece_drop_frames >= frames_per_gridcell[player.level - 1]:
- player.piece_drop_frames = 0
- try:
- player.move_piece_down()
- except WouldCollide:
- player.lock_piece()
-
- refresh_screen()
+ try:
+ current_screen.oneframe()
+ except Pause:
+ current_screen = PauseScreen(screen)
+ except UnPause:
+ current_screen = ingame_screen
+
+ current_screen.refresh()
pygame.display.update()
clock.tick(60)
diff --git a/pycameltris/controller.py b/pycameltris/controller.py
index 3532fd9..9878536 100644
--- a/pycameltris/controller.py
+++ b/pycameltris/controller.py
@@ -20,6 +20,7 @@ class JoystickController:
CIRCLE = 1
TRIANGLE = 2
SQUARE = 3
+ START = 9
DOWN = 14
LEFT = 15
RIGHT = 16
@@ -32,6 +33,7 @@ class JoystickController:
Input.MOVE_LEFT: JoystickController.PS3Controller.LEFT,
Input.MOVE_RIGHT: JoystickController.PS3Controller.RIGHT,
Input.MOVE_DOWN: JoystickController.PS3Controller.DOWN,
+ Input.PAUSE: JoystickController.PS3Controller.START,
}
self.downevent = pygame.JOYBUTTONDOWN
self.upevent = pygame.JOYBUTTONUP
@@ -65,6 +67,7 @@ class KeyboardController:
Input.MOVE_RIGHT: pygame.K_l,
Input.MOVE_DOWN: pygame.K_j,
Input.QUIT: pygame.K_q,
+ Input.PAUSE: pygame.K_RETURN,
}
self.downevent = pygame.KEYDOWN
self.upevent = pygame.KEYUP
diff --git a/pycameltris/misc.py b/pycameltris/misc.py
new file mode 100644
index 0000000..11c2358
--- /dev/null
+++ b/pycameltris/misc.py
@@ -0,0 +1,6 @@
+class Pause(Exception):
+ pass
+
+class UnPause(Exception):
+ pass
+
diff --git a/pycameltris/screens/InGame.py b/pycameltris/screens/InGame.py
new file mode 100644
index 0000000..f865c77
--- /dev/null
+++ b/pycameltris/screens/InGame.py
@@ -0,0 +1,321 @@
+import contextlib
+from functools import partial
+import random
+import sys
+
+import pygame
+
+from ..piece import *
+from ..controller import Input, KeyboardController, JoystickController
+from ..misc import Pause
+
+
+class WouldCollide(Exception):
+ pass
+
+class PlayerQuit(Exception):
+ pass
+
+right_pane_canvas = pygame.Surface((300, 1000))
+right_pane_canvas.fill((255, 255, 255))
+
+class Player:
+ def __init__(self, controller, starting_level):
+ self.controller = controller
+ self.grid = [[None for _ in range(10)] for _ in range(20)]
+
+ self.current_piece, self.current_piece_position = self.generate_piece()
+ self.next_piece, self.next_piece_position = self.generate_piece()
+
+ self.level = self.starting_level = starting_level
+ self.score = 0
+
+ self.lines_burnt = 0
+
+ self.das = 0
+ self.pressing_down_countdown = None
+
+ self.piece_drop_frames = 0
+
+ self.grid_canvas = pygame.Surface((500, 1000))
+ self.piece_preview_canvas = pygame.Surface((200, 200))
+ self.score_canvas = pygame.Surface((296, 50))
+ self.level_canvas = pygame.Surface((296, 50))
+
+
+ def generate_piece(self):
+ # We may want to make this a function outside the class
+ piece = random.choice((TPiece, SPiece, IPiece, ZPiece, SquarePiece, LPiece, JPiece))()
+
+ for row_id, row in enumerate(piece.elements):
+ if list(filter(lambda x: x is not None, row)):
+ break
+
+ initial_y_position = -row_id
+ initial_x_position = (len(self.grid[0]) // 2) - (len(piece.elements[0]) // 2)
+
+ return (piece, [initial_y_position, initial_x_position])
+
+ def burn_rows(self):
+ rows_to_burn = list()
+
+ for row in self.grid:
+ if all(map(lambda element: element is not None, row)):
+ rows_to_burn.append(row)
+
+ for row in rows_to_burn:
+ self.grid.insert(0, [None for _ in range(10)])
+ self.grid.remove(row)
+
+ return len(rows_to_burn)
+
+ def lock_piece(self):
+ if self.has_collision(self.current_piece_position[0], self.current_piece_position[1]):
+ raise WouldCollide()
+
+ for row_id, row in enumerate(self.current_piece.elements):
+ for col_id, element in enumerate(row):
+ if element is None:
+ continue
+ self.grid[row_id + self.current_piece_position[0]][col_id + self.current_piece_position[1]] = element
+
+ count = self.burn_rows()
+
+ if count == 1:
+ print("Single")
+ rate = 1
+ elif count == 2:
+ print("Double")
+ rate = 2.5
+ elif count == 3:
+ print("Triple")
+ rate = 7.5
+ elif count == 4:
+ print("Tetris!")
+ rate = 30
+ else:
+ rate = 0
+
+ self.lines_burnt += count
+
+ self.score += int(self.level * 40 * rate)
+
+ if self.lines_burnt >= self.level * 10:
+ self.level += 1
+ self.current_piece, self.current_piece_position = self.next_piece, self.next_piece_position
+ self.next_piece, self.next_piece_position = self.generate_piece()
+ self.refresh_piece_preview_canvas()
+
+ def has_collision(self, y: int, x: int) -> bool:
+ try:
+ for row_id, row in enumerate(self.current_piece.elements):
+ for col_id, element in enumerate(row):
+ if element is None:
+ continue
+
+ if row_id + y < 0:
+ continue
+
+ if col_id + x < 0:
+ return True
+
+ if self.grid[row_id + y][col_id + x] is not None:
+ return True
+
+ except IndexError:
+ return True
+
+ return False
+
+ def move_piece_down(self):
+ if not self.has_collision(self.current_piece_position[0] + 1, self.current_piece_position[1]):
+ self.current_piece_position[0] += 1
+ else:
+ raise WouldCollide()
+
+ def move_piece_up(self):
+ if not self.has_collision(self.current_piece_position[0] - 1, self.current_piece_position[1]):
+ self.current_piece_position[0] -= 1
+ else:
+ raise WouldCollide()
+
+ def move_piece_left(self):
+ if not self.has_collision(self.current_piece_position[0], self.current_piece_position[1] - 1):
+ self.current_piece_position[1] -= 1
+ else:
+ raise WouldCollide()
+
+ def move_piece_right(self):
+ if not self.has_collision(self.current_piece_position[0], self.current_piece_position[1] + 1):
+ self.current_piece_position[1] += 1
+ else:
+ raise WouldCollide()
+
+ def rotate_piece_counter_clockwise(self):
+ self.current_piece.rotate_counter_clockwise()
+
+ if self.has_collision(self.current_piece_position[0], self.current_piece_position[1]):
+ self.current_piece.rotate_clockwise()
+ raise WouldCollide()
+
+ def rotate_piece_clockwise(self):
+ self.current_piece.rotate_clockwise()
+
+ if self.has_collision(self.current_piece_position[0], self.current_piece_position[1]):
+ self.current_piece.rotate_counter_clockwise()
+ raise WouldCollide()
+
+ def handle_input_pressed(self, event):
+ if self.controller.get_input_down(event) == Input.QUIT:
+ raise PlayerQuit()
+
+ if self.controller.get_input_down(event) == Input.PAUSE:
+ raise Pause()
+
+ with contextlib.suppress(WouldCollide):
+ if self.controller.get_input_down(event) == Input.MOVE_RIGHT:
+ self.move_piece_right()
+ self.das = 0
+ if self.controller.get_input_down(event) == Input.MOVE_LEFT:
+ self.move_piece_left()
+ self.das = 0
+ if self.controller.get_input_down(event) == Input.ROTATE_CLOCKWISE:
+ self.rotate_piece_clockwise()
+ if self.controller.get_input_down(event) == Input.ROTATE_COUNTER_CLOCKWISE:
+ self.rotate_piece_counter_clockwise()
+ if self.controller.get_input_down(event) == Input.MOVE_DOWN:
+ self.piece_drop_frames = 0
+ self.pressing_down_countdown = 3
+ try:
+ self.move_piece_down()
+ except WouldCollide:
+ self.lock_piece()
+
+ def handle_input_released(self, event):
+ if self.controller.get_input_up(event) == Input.MOVE_DOWN:
+ self.pressing_down_countdown = None
+
+ def refresh_piece_preview_canvas(self):
+ self.piece_preview_canvas.fill(black)
+
+ non_empty_rows = list()
+ for row in self.next_piece.elements:
+ if any(map(lambda element: element is not None, row)):
+ non_empty_rows.append(row)
+
+ non_empty_cols = set()
+ for row in self.next_piece.elements:
+ for col_id, element in enumerate(row):
+ if element is not None:
+ non_empty_cols.add(col_id)
+
+ y_offset = (4 - len(non_empty_rows)) / 2
+ x_offset = (4 - len(non_empty_cols)) / 2
+
+ # Display the next piece
+ for row_idx, row in enumerate(non_empty_rows):
+ for col_idx, element in enumerate(row):
+ if element is not None:
+ self.piece_preview_canvas.blit(element, ((col_idx + x_offset) * 50 + 1, (row_idx + y_offset) * 50 + 1))
+
+ def refresh_grid_canvas(self):
+ self.grid_canvas.fill(black)
+
+ for row_idx, row in enumerate(self.grid):
+ for col_idx, element in enumerate(row):
+ if element is not None:
+ self.grid_canvas.blit(element, (col_idx * 50 + 1, row_idx * 50 + 1))
+
+ # Display the current piece
+ for row_idx, row in enumerate(self.current_piece.elements):
+ for col_idx, element in enumerate(row):
+ if element is not None:
+ self.grid_canvas.blit(element, ((col_idx + self.current_piece_position[1]) * 50 + 1, (row_idx + self.current_piece_position[0]) * 50 + 1))
+
+def handle_input_pressed(instance, players, event):
+ for player in players:
+ if isinstance(player.controller, instance):
+ player.handle_input_pressed(event)
+
+
+def handle_input_released(instance, players, event):
+ for player in players:
+ if isinstance(player.controller, instance):
+ player.handle_input_released(event)
+
+# Number of frames
+frames_per_gridcell = [48, 43, 38, 33, 28, 23, 18, 13, 8, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1]
+
+
+class InGame:
+ def __init__(self, players, screen):
+ self.players = players
+ self.screen = screen
+ self.event_handler = dict()
+
+ self.event_handler[pygame.QUIT] = lambda _: sys.exit()
+ self.event_handler[pygame.KEYDOWN] = partial(handle_input_pressed, KeyboardController, self.players)
+ self.event_handler[pygame.KEYUP] = partial(handle_input_released, KeyboardController, self.players)
+ self.event_handler[pygame.JOYBUTTONDOWN] = partial(handle_input_pressed, JoystickController, self.players)
+ self.event_handler[pygame.JOYBUTTONUP] = partial(handle_input_released, JoystickController, self.players)
+
+ def refresh_right_pane_canvas(self):
+ for player in self.players:
+ player.level_canvas.fill(black)
+ player.score_canvas.fill(black)
+
+ if pygame.font:
+ score_font = pygame.font.Font(None, 56)
+
+ player.score_canvas.blit(score_font.render(f"{player.score:08d}", True, white), (0, 0))
+ player.level_canvas.blit(score_font.render(f"{player.level:08d}", True, white), (0, 0))
+ right_pane_canvas.blit(player.score_canvas, (2, 10))
+ right_pane_canvas.blit(player.level_canvas, (2, 70))
+
+ right_pane_canvas.blit(player.piece_preview_canvas, (50, 200))
+
+
+ def refresh(self):
+ for player in self.players:
+ player.refresh_grid_canvas()
+ self.screen.blit(player.grid_canvas, (0, 0))
+ self.refresh_right_pane_canvas()
+ self.screen.blit(right_pane_canvas, (501, 0))
+
+ def oneframe(self):
+ for player in self.players:
+ player.piece_drop_frames += 1
+
+ try:
+ for event in pygame.event.get():
+ with contextlib.suppress(KeyError):
+ self.event_handler[event.type](event)
+ except Pause:
+ pygame.event.clear()
+ raise
+
+ for player in self.players:
+ player.das += 1
+ if player.das == 16:
+ with contextlib.suppress(WouldCollide):
+ if player.controller.is_pressed(Input.MOVE_RIGHT):
+ player.move_piece_right()
+ if player.controller.is_pressed(Input.MOVE_LEFT):
+ player.move_piece_left()
+ player.das = 10
+
+ if player.pressing_down_countdown == 0:
+ try:
+ player.move_piece_down()
+ except WouldCollide:
+ player.lock_piece()
+ player.pressing_down_countdown = 2
+ elif player.pressing_down_countdown is not None:
+ player.pressing_down_countdown -= 1
+
+ if player.piece_drop_frames >= frames_per_gridcell[player.level - 1]:
+ player.piece_drop_frames = 0
+ try:
+ player.move_piece_down()
+ except WouldCollide:
+ player.lock_piece()
diff --git a/pycameltris/screens/Pause.py b/pycameltris/screens/Pause.py
new file mode 100644
index 0000000..f9f8859
--- /dev/null
+++ b/pycameltris/screens/Pause.py
@@ -0,0 +1,34 @@
+import contextlib
+import sys
+
+import pygame
+
+from ..controller import KeyboardController, JoystickController, Input
+from ..misc import UnPause
+
+
+def handle_input_pressed(controller, event):
+ if controller.get_input_down(event) == Input.PAUSE:
+ raise UnPause()
+
+
+class Pause:
+ def __init__(self, screen):
+ self.event_handler = dict()
+
+ self.event_handler[pygame.QUIT] = lambda _: sys.exit()
+ self.event_handler[pygame.JOYBUTTONDOWN] = lambda evt: handle_input_pressed(JoystickController(evt.joy), evt)
+ self.event_handler[pygame.KEYDOWN] = lambda evt: handle_input_pressed(KeyboardController(pygame.key), evt)
+
+
+ def refresh(self):
+ pass
+
+ def oneframe(self):
+ try:
+ for event in pygame.event.get():
+ with contextlib.suppress(KeyError):
+ self.event_handler[event.type](event)
+ except UnPause:
+ pygame.event.clear()
+ raise