234 lines
11 KiB
Python
234 lines
11 KiB
Python
import pygame
|
|
import pygameControls as PC
|
|
import globals
|
|
globals.init()
|
|
from globals import GRID_WIDTH, GRID_HEIGHT, TILE_SIZE, BRICKS
|
|
import enums
|
|
from bricks import Brick
|
|
import random
|
|
from dropzone import DropZone
|
|
from dropnext import DropNext
|
|
from hud import Hud
|
|
|
|
__version__ = "0.2.0"
|
|
|
|
# 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()
|
|
|
|
if self.joysticks:
|
|
self.joysticks[self.joy.get_instance_id()].controllers[0].close()
|
|
|
|
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.hud = Hud(self.screen_width, self.screen_height)
|
|
self.dropzone = DropZone(GRID_WIDTH, GRID_HEIGHT)
|
|
self.dropnext = DropNext(width = TILE_SIZE * 4, height = TILE_SIZE * 4)
|
|
|
|
self.current = Brick(brick = random.choice(list(BRICKS.keys())), state = enums.BrickState.Current)
|
|
self.next = Brick(brick = random.choice(list(BRICKS.keys())))
|
|
|
|
self.clock = pygame.time.Clock()
|
|
self.rumble_timer = pygame.time.get_ticks()
|
|
self.fall_speed = 1000 # in milliseconds
|
|
self.fall_timer = pygame.USEREVENT + 1
|
|
pygame.time.set_timer(self.fall_timer, self.get_fall_speed(self.hud.level))
|
|
|
|
def get_fall_speed(self, level):
|
|
return max(100, 1000 - (level - 1) * 100)
|
|
|
|
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)
|
|
self.dropzone.draw_brick(self.current.brick, self.current.location)
|
|
self.dropnext.draw(self.screen)
|
|
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:
|
|
#new_pos = pos[:]
|
|
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()
|
|
self.dropzone.draw_brick(self.current.brick, self.current.location)
|
|
case pygame.K_LEFT:
|
|
if self.current.direction == enums.BrickDirection.Dropped:
|
|
break
|
|
self.current.direction = enums.BrickDirection.Left
|
|
self.current.move_left()
|
|
self.dropzone.draw_brick(self.current.brick, self.current.location)
|
|
case pygame.K_SPACE:
|
|
if self.current.direction == enums.BrickDirection.Dropped:
|
|
break
|
|
self.current.rotate()
|
|
self.dropzone.draw_brick(self.current.brick, self.current.location)
|
|
case pygame.K_RETURN:
|
|
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()
|
|
self.dropzone.draw_brick(self.current.brick, self.current.location)
|
|
elif self.hat_x == -1:
|
|
if self.current.direction == enums.BrickDirection.Dropped:
|
|
break
|
|
self.current.direction = enums.BrickDirection.Left
|
|
self.current.move_left()
|
|
self.dropzone.draw_brick(self.current.brick, self.current.location)
|
|
|
|
case pygame.JOYBUTTONDOWN:
|
|
match event.button:
|
|
case self.left_button:
|
|
if self.current.direction == enums.BrickDirection.Dropped:
|
|
break
|
|
self.current.direction = enums.BrickDirection.Left
|
|
self.current.move_left()
|
|
self.dropzone.draw_brick(self.current.brick, self.current.location)
|
|
case self.right_button:
|
|
if self.current.direction == enums.BrickDirection.Dropped:
|
|
break
|
|
self.current.direction = enums.BrickDirection.Right
|
|
self.current.move_right()
|
|
self.dropzone.draw_brick(self.current.brick, self.current.location)
|
|
case self.rotate_button:
|
|
if self.current.direction == enums.BrickDirection.Dropped:
|
|
break
|
|
self.current.rotate()
|
|
self.dropzone.draw_brick(self.current.brick, self.current.location)
|
|
case self.drop_button:
|
|
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()
|
|
|
|
case self.fall_timer:
|
|
if not self.current.update():
|
|
self.dropzone.lock(self.current)
|
|
self.current = self.next
|
|
self.next = Brick(brick = random.choice(list(BRICKS.keys())))
|
|
|
|
# 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)
|
|
|
|
# Get joypad mappings
|
|
if "triangle button" in self.joysticks[self.joy.get_instance_id()].controllers[0].mapping:
|
|
self.rotate_button = self.joysticks[self.joy.get_instance_id()].controllers[0].mapping["triangle button"]
|
|
elif "Y button" in self.joysticks[self.joy.get_instance_id()].controllers[0].mapping:
|
|
self.rotate_button = self.joysticks[self.joy.get_instance_id()].controllers[0].mapping["Y button"]
|
|
print(f"Rotate button :{self.rotate_button}")
|
|
|
|
if "cross button" in self.joysticks[self.joy.get_instance_id()].controllers[0].mapping:
|
|
self.drop_button = self.joysticks[self.joy.get_instance_id()].controllers[0].mapping["cross button"]
|
|
elif "A button" in self.joysticks[self.joy.get_instance_id()].controllers[0].mapping:
|
|
self.drop_button = self.joysticks[self.joy.get_instance_id()].controllers[0].mapping["A button"]
|
|
print(f"Drop button :{self.drop_button}")
|
|
|
|
if "left button" in self.joysticks[self.joy.get_instance_id()].controllers[0].mapping:
|
|
self.left_button = self.joysticks[self.joy.get_instance_id()].controllers[0].mapping["left button"]
|
|
else: self.left_button = None
|
|
|
|
if "right button" in self.joysticks[self.joy.get_instance_id()].controllers[0].mapping:
|
|
self.right_button = self.joysticks[self.joy.get_instance_id()].controllers[0].mapping["right button"]
|
|
else: self.right_button = None
|
|
|
|
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() |