summaryrefslogtreecommitdiff
path: root/cameltris/screens/in_game.py
blob: bed8643eada2e3a176396d8edd9f706002a5985a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import contextlib
from functools import partial
import sys
from typing import Callable, NoReturn

import pygame

from ..color import Color
from ..controller import Input, KeyboardController, JoystickController
from .base_screen import Screen
from ..player import Player, WouldCollide
from ..misc import Pause


def handle_input_pressed(instance, players: list[Player], event: pygame.event.Event) -> None:
    for player in players:
        if isinstance(player.controller, instance):
            player.handle_input_pressed(event)


def handle_input_released(instance, players: list[Player], event: pygame.event.Event) -> None:
    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]

right_pane_canvas = pygame.Surface((300, 1000))
right_pane_canvas.fill((255, 255, 255))


class InGame(Screen):
    def __init__(self, players: list[Player], screen: pygame.surface.Surface):
        self.players: list[Player] = players
        self.screen: pygame.surface.Surface = screen
        self.event_handler: dict[int, Callable[[pygame.event.Event], None]] = {}

        def exit(_) -> NoReturn:
            sys.exit()

        self.event_handler[pygame.QUIT] = 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) -> None:
        for player in self.players:
            player.level_canvas.fill(Color.black.value)
            player.score_canvas.fill(Color.black.value)

        if pygame.font:
            score_font = pygame.font.Font(None, 56)

            player.score_canvas.blit(score_font.render(f"{player.score:08d}", True, Color.white.value), (0, 0))
            player.level_canvas.blit(score_font.render(f"{player.level:08d}", True, Color.white.value), (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) -> None:
        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) -> None:
        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()