Files
tetri5/tetri5/scene.py

234 lines
10 KiB
Python

import sys
import pygame
from types import FunctionType
from tetri5.util import ConfigurationManager
from tetri5.util import TextGenerator
from tetri5.util import Controller
from tetri5.util import SoundManager
from tetri5.entity import Well
from tetri5.entity import Stack
from tetri5.entity import PieceGenerator
from tetri5.online import MultiplayerService
"""
TODO
"""
class Scene:
pass
"""
TODO
"""
class TitleScene(Scene):
# Title screen options
ONE_PLAYER = "1 PLAYER"
TWO_PLAYER = "2 PLAYER"
def __init__(self, change_scene: FunctionType) -> None:
self._tile_size = ConfigurationManager.get("engine", "tile-size")
self._background_color = pygame.Color(ConfigurationManager.get("color", "window-bg"))
self._logo_image = pygame.image.load(ConfigurationManager.get("image", "title-screen"))
self._cursor_pos_one = ConfigurationManager.get("position", "cursor-option-one")
self._cursor_pos_two = ConfigurationManager.get("position", "cursor-option-two")
self._cursor_pos = self._cursor_pos_one
self._cursor_blink_interval = ConfigurationManager.get("engine", "cursor-blink-interval")
self._cursor_blink_time = 0
self._cursor_color = pygame.Color(ConfigurationManager.get("color", "cursor"))
self._cursor_off = False
self._logo_pos = ConfigurationManager.get("position", "title-logo")
self._option_one_pos = ConfigurationManager.get("position", "option-one")
self._option_two_pos = ConfigurationManager.get("position", "option-two")
self._is_multiplayer = False
self._change_scence = change_scene
def draw(self, surface: pygame.Surface) -> None:
surface.fill(self._background_color)
surface.blit(self._logo_image, self._logo_pos)
TextGenerator.draw(TitleScene.ONE_PLAYER, self._option_one_pos, surface)
TextGenerator.draw(TitleScene.TWO_PLAYER, self._option_two_pos, surface)
if self._cursor_off:
pygame.draw.circle(surface, self._cursor_color, self._cursor_pos, self._tile_size // 3)
def update(self, elapsed_time: int) -> None:
option_change = False
if Controller.key_pressed(pygame.K_UP) and self._is_multiplayer:
self._cursor_pos = self._cursor_pos_one
self._is_multiplayer = False
option_change = True
if Controller.key_pressed(pygame.K_DOWN) and not self._is_multiplayer:
self._cursor_pos = self._cursor_pos_two
self._is_multiplayer = True
option_change = True
if option_change:
SoundManager.play_option_change_sfx() # TODO add cool down
self._cursor_blink_time += elapsed_time
if self._cursor_blink_time >= self._cursor_blink_interval:
self._cursor_blink_time = 0
self._cursor_off = not self._cursor_off
if Controller.key_pressed(pygame.K_RETURN):
self._change_scence(SinglePlayerScene(self._change_scence) if not self._is_multiplayer else MultiPlayerScene(self._change_scence))
"""
TODO
"""
class SinglePlayerScene(Scene):
def __init__(self, change_scene: FunctionType) -> None:
self._top_label_pos = ConfigurationManager.get("position", "top-label")
self._top_value_pos = ConfigurationManager.get("position", "top-value")
self._score_label_pos = ConfigurationManager.get("position", "score-label")
self._score_value_pos = ConfigurationManager.get("position", "score-value")
self._lines_label_pos = ConfigurationManager.get("position", "lines-label")
self._next_label_pos = ConfigurationManager.get("position", "next-label")
self._level_label_pos = ConfigurationManager.get("position", "level-label")
self._next_piece_pos = ConfigurationManager.get("position", "next-piece")
self._spawn_piece_shift = ConfigurationManager.get("position", "spawn-piece")
self._tile_size = ConfigurationManager.get("engine", "tile-size")
self._background_color = pygame.Color(ConfigurationManager.get("color", "window-bg"))
self._points_table = ConfigurationManager.get("engine", "points-table")
self._lines_per_level = ConfigurationManager.get("engine", "lines-per-level")
self._score = 0
self._previous_level = 0
self._current_piece = None
self._next_piece = PieceGenerator.get_piece(self._next_piece_pos)
self._well = Well(ConfigurationManager.get("position", "well"),\
ConfigurationManager.get("color", "well-1"),\
ConfigurationManager.get("color", "well-border-1"))
self._stack = Stack()
self._change_scence = change_scene
SoundManager.play_theme_music()
def draw(self, surface: pygame.Surface) -> None:
surface.fill(self._background_color)
if self._next_piece:
self._next_piece.draw(surface)
if self._well:
self._well.draw(surface)
if self._stack:
self._stack.draw(surface)
if self._current_piece:
self._current_piece.draw(surface, self._well, self._stack)
score = str(self._score).zfill(6)
lines = str(self._stack.total_lines).zfill(4)
level = str(self._get_level()).zfill(2)
TextGenerator.draw("Top", self._top_label_pos, surface)
TextGenerator.draw("000000", self._top_value_pos, surface)
TextGenerator.draw("Score", self._score_label_pos, surface)
TextGenerator.draw(score, self._score_value_pos, surface)
TextGenerator.draw("Lines " + lines, self._lines_label_pos, surface)
TextGenerator.draw("Next", self._next_label_pos, surface)
TextGenerator.draw("LVL " + level, self._level_label_pos, surface)
def update(self, elapsed_time: int) -> None:
if self._current_piece:
self._current_piece.update(elapsed_time,\
self._well,\
self._stack,\
self._get_level(),\
self._clear_current_piece)
else:
self._current_piece = self._next_piece
self._current_piece.move(self._spawn_piece_shift)
self._next_piece = PieceGenerator.get_piece(self._next_piece_pos)
# TODO create game over scene
if self._stack and self._current_piece.collide(self._stack):
pygame.quit()
sys.exit()
if self._stack:
self._stack.update(elapsed_time)
self._score += self._points_table[self._stack.lines_completed_last] * (self._get_level() + 1)
if self._previous_level != self._get_level():
self._previous_level = self._get_level()
SoundManager.play_level_up_sfx()
def _get_level(self) -> int:
return 0 if not self._stack else self._stack.total_lines // self._lines_per_level
def _clear_current_piece(self) -> None:
self._current_piece = None
"""
TODO
"""
class MultiPlayerScene(Scene):
def __init__(self, change_scene: FunctionType) -> None:
self._tile_size = ConfigurationManager.get("engine", "tile-size")
self._background_color = pygame.Color(ConfigurationManager.get("color", "window-bg"))
# wells init
self._well_player_one = Well(ConfigurationManager.get("position", "well-player-1"),\
ConfigurationManager.get("color", "well-1"),\
ConfigurationManager.get("color", "well-border-1"))
self._well_player_two = Well(ConfigurationManager.get("position", "well-player-2"),\
ConfigurationManager.get("color", "well-1"),\
ConfigurationManager.get("color", "well-border-1"))
# stacks init
self._stack_player_one = Stack()
self._stack_player_two = Stack()
# score positions
self.score_label_player_one_pos = ConfigurationManager.get("position", "score-label-player-1")
self.score_label_player_two_pos = ConfigurationManager.get("position", "score-label-player-2")
self.score_value_player_one_pos = ConfigurationManager.get("position", "score-value-player-1")
self.score_value_player_two_pos = ConfigurationManager.get("position", "score-value-player-2")
# lines positions
self.lines_label_player_one_pos = ConfigurationManager.get("position", "lines-label-player-1")
self.lines_label_player_two_pos = ConfigurationManager.get("position", "lines-label-player-2")
# next positions
self.next_label_player_one_pos = ConfigurationManager.get("position", "next-label-player-1")
self.next_label_player_two_pos = ConfigurationManager.get("position", "next-label-player-2")
self._change_scence = change_scene
MultiplayerService.init()
def draw(self, surface: pygame.Surface) -> None:
surface.fill(self._background_color)
# wells
if self._well_player_one:
self._well_player_one.draw(surface)
if self._well_player_two:
self._well_player_two.draw(surface)
# stacks
if self._stack_player_one:
self._stack_player_one.draw(surface)
if self._stack_player_two:
self._stack_player_two.draw(surface)
# scores
TextGenerator.draw("Score", self.score_label_player_one_pos, surface)
TextGenerator.draw("000000", self.score_value_player_one_pos, surface)
TextGenerator.draw("Score", self.score_label_player_two_pos, surface)
TextGenerator.draw("000000", self.score_value_player_two_pos, surface)
# lines
TextGenerator.draw("Lines 0000", self.lines_label_player_one_pos, surface)
TextGenerator.draw("Lines 0000", self.lines_label_player_two_pos, surface)
# next
TextGenerator.draw("P1 NXT", self.next_label_player_one_pos, surface)
TextGenerator.draw("P2 NXT", self.next_label_player_two_pos, surface)
def update(self, elapsed_time: int) -> None:
pass