diff --git a/config.yaml b/config.yaml index b41f887..7b325e9 100644 --- a/config.yaml +++ b/config.yaml @@ -1,11 +1,10 @@ window: width: 800 height: 600 - - title: "Tetris" + title: "Tetri5" sound: - main-music: "resource/sound/main_music.wav" + main-music: "resource/sound/main_music.ogg" row-completion: "resource/sound/row_completion.wav" piece-set: "resource/sound/piece_set_3.wav" @@ -14,9 +13,17 @@ image: window-icon: "resource/image/tetris_icon.png" font: "resource/image/press-start-2p-font.bmp" +position: + title-logo: [280, 125] + option-one: [320, 390] + option-two: [320, 440] + cursor-option-one: [300, 399] + cursor-option-two: [300, 449] + engine: fps: 60 tile-size: 20 + cursor-blink-interval: 150 piece-gravity-time: 600 piece-set-time: 600 piece-gravity-increase: 56 @@ -29,7 +36,11 @@ engine: - 1200 # 4 lines color: + # window window-bg: "#000000" + # title screen + cursor: "#FFFFFF" + # in game piece-1: "#1F37EC" piece-2: "#3DBBFC" piece-3: "#FFFFFF" diff --git a/main.py b/main.py index 391a183..19828d3 100644 --- a/main.py +++ b/main.py @@ -4,14 +4,14 @@ https://tetris.com/play-tetris ''' -from tetris.game import Game -from tetris.util import ConfigurationManager +from tetri5.game import Game +from tetri5.util import ConfigurationManager def main() -> None: - ConfigurationManager. init() + ConfigurationManager.init() game = Game() - game.initialize() + game.init() while True: game.update() diff --git a/resource/image/title_screen.png b/resource/image/title_screen.png index c5f0a35..4793c4e 100644 Binary files a/resource/image/title_screen.png and b/resource/image/title_screen.png differ diff --git a/resource/sound/main_music.ogg b/resource/sound/main_music.ogg index 85217fc..755e118 100644 Binary files a/resource/sound/main_music.ogg and b/resource/sound/main_music.ogg differ diff --git a/tetris/__init__.py b/tetri5/__init__.py similarity index 100% rename from tetris/__init__.py rename to tetri5/__init__.py diff --git a/tetris/entity.py b/tetri5/entity.py similarity index 98% rename from tetris/entity.py rename to tetri5/entity.py index e93d765..fab7c74 100644 --- a/tetris/entity.py +++ b/tetri5/entity.py @@ -3,12 +3,12 @@ import random import pygame from typing import List, Tuple from pygame import mixer -from tetris.util import ConfigurationManager -from tetris.util import Controller +from tetri5.util import ConfigurationManager +from tetri5.util import Controller from typing import TYPE_CHECKING if TYPE_CHECKING: - from tetris.game import Game + from tetri5.game import Game """ TODO description @@ -65,11 +65,11 @@ class Well(Entity): shape = [] for i in range(self.WIDTH + 2): for j in range(self.HEIGHT + 2): - if i == 0 or i == self.WIDTH + 1: + if i in [0, self.WIDTH + 1]: shape.append(((i, j), (i + 1, j), (i + 1, j + 1), (i, j + 1))) - elif j == 0 or j == self.HEIGHT + 1: + elif j in [0, self.HEIGHT + 1]: shape.append(((i, j), (i + 1, j), (i + 1, j + 1), (i, j + 1))) - + points = [] for square in shape: sub_points = [] diff --git a/tetris/game.py b/tetri5/game.py similarity index 86% rename from tetris/game.py rename to tetri5/game.py index 8086ccf..d67d0f2 100644 --- a/tetris/game.py +++ b/tetri5/game.py @@ -1,13 +1,13 @@ import sys import pygame from pygame import mixer -from tetris.util import ConfigurationManager -from tetris.util import TextGenerator -from tetris.entity import PieceGenerator -from tetris.entity import Well -from tetris.entity import Stack -from tetris.online import MultiplayerService -from tetris.scene import TitleScene +from tetri5.util import ConfigurationManager +from tetri5.util import TextGenerator +from tetri5.entity import PieceGenerator +from tetri5.entity import Well +from tetri5.entity import Stack +from tetri5.online import MultiplayerService +from tetri5.scene import TitleScene # TODO improve game assets https://www.spriters-resource.com/nes/tetris/ # TODO should be a singleton and refactor the whole file? @@ -18,7 +18,6 @@ class Game: self.tile_size = -1 self.screen = None self.clock = None - self.current_scene = TitleScene() # In Game # @@ -27,8 +26,9 @@ class Game: self.well = None self.stack = None self.main_music = None + self.score = -1 - def initialize(self) -> None: + def init(self) -> None: pygame.init() TextGenerator.init(ConfigurationManager.get("image", "font"), (20, 20)) @@ -41,28 +41,26 @@ class Game: self.tile_size = ConfigurationManager.get("engine", "tile-size") self.screen = pygame.display.set_mode((win_width, win_height)) self.clock = pygame.time.Clock() + pygame.display.set_caption(win_title) + pygame.display.set_icon(pygame.image.load(win_icon)) + + + self.main_music = mixer.Channel(0) self.well = Well((280, 80), ConfigurationManager.get("color", "well-1"), ConfigurationManager.get("color", "well-border-1")) # TODO calculate position later and redo color config for well self.stack = Stack(ConfigurationManager.get("color", "stack-1"), ConfigurationManager.get("color", "stack-border-1")) self.score = 0 - - loaded_icon = pygame.image.load(win_icon) - pygame.display.set_caption(win_title) - pygame.display.set_icon(loaded_icon) - - main_music_file = ConfigurationManager.get("sound", "main-music") self.main_music.set_volume(0.7) # TODO add volume to the config - self.main_music.play(mixer.Sound(main_music_file), -1) + self.main_music.play(ConfigurationManager.get("sound", "main-music"), -1) # gets called from the games main loop def update(self) -> None: + # TODO write not initialized exception + elapsed_time = self.clock.tick(self.fps) if self.current_scene: - self.current_scene.update() + self.current_scene.update(elapsed_time) else: - # TODO write not initialized exception - elapsed_time = self.clock.tick(self.fps) - if not self.next_piece: self.next_piece = PieceGenerator.get_piece((620, 160)) diff --git a/tetris/online.py b/tetri5/online.py similarity index 97% rename from tetris/online.py rename to tetri5/online.py index be9c996..01810b0 100644 --- a/tetris/online.py +++ b/tetri5/online.py @@ -100,7 +100,7 @@ class _NetworkConnectionService(): @classmethod async def _try_receive_message(cls) -> None: try: - task = cls._pending_receive_task if cls._pending_receive_task else asyncio.create_task(cls._websocket.recv()) + task = cls._pending_receive_task or asyncio.create_task(cls._websocket.recv()) done, pending = await asyncio.wait({task}, timeout=8e-3) # TODO experiment with the timeout if task in done: diff --git a/tetri5/scene.py b/tetri5/scene.py new file mode 100644 index 0000000..a9a84b7 --- /dev/null +++ b/tetri5/scene.py @@ -0,0 +1,68 @@ +import pygame +from tetri5.util import ConfigurationManager +from tetri5.util import TextGenerator +from tetri5.util import Controller + +""" + TODO +""" +class TitleScene: + + # Title screen options + ONE_PLAYER = "1 PLAYER" + TWO_PLAYER = "2 PLAYER" + + def __init__(self) -> None: + self._tile_size = ConfigurationManager.get("engine", "tile-size") + self._logo_image = pygame.image.load(ConfigurationManager.get("image", "title-screen")) + self._cursor_position_one = ConfigurationManager.get("position", "cursor-option-one") + self._cursor_position_two = ConfigurationManager.get("position", "cursor-option-two") + self._cursor_position = self._cursor_position_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._background_color = pygame.Color(ConfigurationManager.get("color", "window-bg")) + self._logo_position = ConfigurationManager.get("position", "title-logo") + self._option_one_position = ConfigurationManager.get("position", "option-one") + self._option_two_position = ConfigurationManager.get("position", "option-two") + self._is_multiplayer = False + + def draw(self, surface: pygame.Surface) -> None: + surface.fill(self._background_color) + surface.blit(self._logo_image, self._logo_position) + + TextGenerator.draw(TitleScene.ONE_PLAYER, self._option_one_position, surface) + TextGenerator.draw(TitleScene.TWO_PLAYER, self._option_two_position, surface) + + if self._cursor_off: + pygame.draw.circle(surface, self._cursor_color, self._cursor_position, self._tile_size // 3) + + def update(self, elapsed_time) -> None: + if Controller.key_pressed(pygame.K_UP): + self._cursor_position = self._cursor_position_one + self._is_multiplayer = False + if Controller.key_pressed(pygame.K_DOWN): + self._cursor_position = self._cursor_position_two + self._is_multiplayer = True + + 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 + +""" + TODO +""" +class SinglePlayerScene: + pass + +""" + TODO +""" +class MultiPlayerScene: + pass + + + + \ No newline at end of file diff --git a/tetris/util.py b/tetri5/util.py similarity index 100% rename from tetris/util.py rename to tetri5/util.py diff --git a/tetris/scene.py b/tetris/scene.py deleted file mode 100644 index 55478f3..0000000 --- a/tetris/scene.py +++ /dev/null @@ -1,33 +0,0 @@ -import pygame -from tetris.util import ConfigurationManager -from tetris.util import TextGenerator -from tetris.util import Controller - -""" - TODO -""" -class TitleScene: - - # Title screen options - ONE_PLAYER = "ONE_PLAYER" - TWO_PLAYER = "TWO_PLAYER" - - def __init__(self) -> None: - image_path = ConfigurationManager.get("image", "title-screen") - - self.splash_image = pygame.image.load(image_path) - self.cursor_position = None - self.cursor_flash_timer = 0 - - def draw(self, screen) -> None: - screen.fill(pygame.Color(ConfigurationManager.get("color", "window-bg"))) - screen.blit(self.splash_image, (300, 0)) - - TextGenerator.draw("1 PLAYER", (300, 400), screen) - TextGenerator.draw("2 PLAYER", (300, 450), screen) - - def update(self) -> None: - if Controller.key_pressed(pygame.K_DOWN): - self.current_option = TitleScene.ONE_PLAYER - if Controller.key_pressed(pygame.K_UP): - self.current_option = TitleScene.TWO_PLAYER \ No newline at end of file