Files
PyGame-Tetris/tetris.py
2025-04-21 20:33:36 +02:00

175 lines
7.4 KiB
Python

import pygame
import pygameControls as PC
import enums
from bricks import Brick, BRICKS, TILE_SIZE
from random import randrange
from dropzone import DropZone
from dropnext import DropNext
from hud import Hud
__version__ = "0.0.1"
# Constants
HAT_REPEAT_DELAY = 0 # milliseconds before first repeat
HAT_REPEAT_INTERVAL = 200 # milliseconds between repeats
RUMBLE_TIMEOUT = 200
class Tetris:
def __init__(self):
self.setup()
self.running = True
while self.running:
self.main_loop()
pygame.quit()
def setup(self):
pygame.init()
pygame.key.set_repeat(200)
self.joystick_count = pygame.joystick.get_count()
self.joysticks = {}
self.screen_width, self.screen_height = (20 * TILE_SIZE), (20 * TILE_SIZE)
self.screen = pygame.display.set_mode((self.screen_width, self.screen_height))
pygame.display.set_caption("Tetris " + __version__)
self.current = Brick(brick = randrange(0, len(BRICKS)), state = enums.BrickState.Current)
print(self.current.layout)
print(self.current.color)
self.next = Brick(brick = randrange(0, len(BRICKS)))
print(self.next.layout)
print(self.next.color)
self.hud = Hud(self.screen_width, self.screen_height, TILE_SIZE)
self.dropzone = DropZone(width = TILE_SIZE * 10, height = TILE_SIZE * 18)
self.dropnext = DropNext(width = TILE_SIZE * 4, height = TILE_SIZE * 4)
self.clock = pygame.time.Clock()
self.rumble_timer = pygame.time.get_ticks()
def main_loop(self):
if self.joysticks:
if pygame.time.get_ticks() - self.rumble_timer > RUMBLE_TIMEOUT:
self.joysticks[self.joy.get_instance_id()].controllers[0].stop_rumble()
self.screen.fill(enums.BrickColor.Cyan.value)
self.hud.draw(self.screen)
self.dropzone.draw(self.screen, TILE_SIZE)
self.dropnext.draw(self.screen, TILE_SIZE)
self.dropnext.draw_block(self.next.brick)
self.handle_input()
pygame.display.flip()
self.clock.tick(60)
def handle_hat_repeat(self):
now = pygame.time.get_ticks()
if self.hat_direction != (0, 0):
if self.hat_first_press:
if now - self.hat_timer >= HAT_REPEAT_DELAY:
self.hat_timer = now
self.hat_first_press = False
self.post_hat_repeat_event()
else:
if now - self.hat_timer >= HAT_REPEAT_INTERVAL:
self.hat_timer = now
self.post_hat_repeat_event()
def post_hat_repeat_event(self):
pygame.event.post(pygame.event.Event(pygame.USEREVENT, {
"type_name": "JOYHATREPEAT",
"value": self.hat_direction
}))
def handle_input(self):
for event in pygame.event.get():
match event.type:
case pygame.QUIT:
self.running = False
case pygame.KEYDOWN:
match event.key:
case pygame.K_RIGHT:
if self.current.direction == enums.BrickDirection.Dropped:
break
self.current.direction = enums.BrickDirection.Right
self.current.move_right()
case pygame.K_LEFT:
if self.current.direction == enums.BrickDirection.Dropped:
break
self.current.direction = enums.BrickDirection.Left
self.current.move_left()
case pygame.K_UP:
if self.current.direction == enums.BrickDirection.Dropped:
break
self.current.rotate()
case pygame.K_DOWN:
if self.current.direction == enums.BrickDirection.Dropped:
break
self.current.drop()
case pygame.JOYHATMOTION:
self.hat_direction = event.value
self.hat_x, self.hat_y = self.hat_direction
self.hat_timer = pygame.time.get_ticks()
self.hat_first_press = True
if self.hat_x == 1:
if self.current.direction == enums.BrickDirection.Dropped:
break
self.current.direction = enums.BrickDirection.Right
self.current.move_right()
elif self.hat_x == -1:
if self.current.direction == enums.BrickDirection.Dropped:
break
self.current.direction = enums.BrickDirection.Left
self.current.move_left()
elif self.hat_y == 1:
if self.current.direction == enums.BrickDirection.Dropped:
break
self.current.rotate()
elif self.hat_y == -1:
if self.current.direction == enums.BrickDirection.Dropped:
break
self.current.drop()
case pygame.USEREVENT:
if event.dict.get("type_name") == "JOYHATREPEAT":
match event.dict['value']:
case (1, 0):
if self.current.direction == enums.BrickDirection.Dropped:
break
self.current.direction = enums.BrickDirection.Right
self.current.move_right()
case (-1, 0):
if self.current.direction == enums.BrickDirection.Dropped:
break
self.current.direction = enums.BrickDirection.Left
self.current.move_left()
case (0, 1):
if self.current.direction == enums.BrickDirection.Dropped:
break
self.current.rotate()
case (0, -1):
if self.current.direction == enums.BrickDirection.Dropped:
break
self.current.drop()
# Handle hotplugging
case pygame.JOYDEVICEADDED:
# This event will be generated when the program starts for every
# joystick, filling up the list without needing to create them manually.
self.joy = pygame.joystick.Joystick(event.device_index)
self.joysticks[self.joy.get_instance_id()] = PC.controller.Controllers(self.joy)
case pygame.JOYDEVICEREMOVED:
del self.joysticks[event.instance_id]
print(f"Joystick {event.instance_id} disconnected")
def exit(self):
self.running = False
if __name__ == "__main__":
game = Tetris()