wip!: add scenes to the game

This commit is contained in:
2021-07-07 14:49:04 -04:00
parent 83d2ddbc6b
commit dbcf18e507
6 changed files with 142 additions and 95 deletions

View File

@@ -10,6 +10,7 @@ sound:
piece-set: "resource/sound/piece_set_3.wav" piece-set: "resource/sound/piece_set_3.wav"
image: image:
title-screen: "resource/image/title_screen.png"
window-icon: "resource/image/tetris_icon.png" window-icon: "resource/image/tetris_icon.png"
font: "resource/image/press-start-2p-font.bmp" font: "resource/image/press-start-2p-font.bmp"

View File

@@ -8,7 +8,7 @@ from tetris.game import Game
from tetris.util import ConfigurationManager from tetris.util import ConfigurationManager
def main() -> None: def main() -> None:
ConfigurationManager.load() ConfigurationManager. init()
game = Game() game = Game()
game.initialize() game.initialize()

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@@ -7,7 +7,9 @@ from tetris.entity import PieceGenerator
from tetris.entity import Well from tetris.entity import Well
from tetris.entity import Stack from tetris.entity import Stack
from tetris.online import MultiplayerService from tetris.online import MultiplayerService
from tetris.scene import TitleScene
# TODO improve game assets https://www.spriters-resource.com/nes/tetris/
# TODO should be a singleton and refactor the whole file? # TODO should be a singleton and refactor the whole file?
class Game: class Game:
@@ -16,15 +18,19 @@ class Game:
self.tile_size = -1 self.tile_size = -1
self.screen = None self.screen = None
self.clock = None self.clock = None
self.main_music = None
self.current_scene = TitleScene()
# In Game #
self.current_piece = None self.current_piece = None
self.next_piece = None self.next_piece = None
self.well = None self.well = None
self.stack = None self.stack = None
self.main_music = None
def initialize(self) -> None: def initialize(self) -> None:
pygame.init() pygame.init()
TextGenerator.load(ConfigurationManager.get("image", "font"), (20, 20)) TextGenerator.init(ConfigurationManager.get("image", "font"), (20, 20))
win_width = ConfigurationManager.get("window", "width") win_width = ConfigurationManager.get("window", "width")
win_height = ConfigurationManager.get("window", "height") win_height = ConfigurationManager.get("window", "height")
@@ -50,25 +56,29 @@ class Game:
# gets called from the games main loop # gets called from the games main loop
def update(self) -> None: def update(self) -> None:
# TODO write not initialized exception
elapsed_time = self.clock.tick(self.fps)
if not self.next_piece: if self.current_scene:
self.next_piece = PieceGenerator.get_piece((620, 160)) self.current_scene.update()
if self.current_piece:
self.current_piece.update(elapsed_time, self)
else: else:
self.current_piece = self.next_piece # TODO write not initialized exception
self.current_piece.move((360 - 620, 100 - 160)) # TODO calculate spawn position correctly elapsed_time = self.clock.tick(self.fps)
self.next_piece = PieceGenerator.get_piece((620, 160)) # (360, 100)
if self.stack and self.current_piece.collide(self.stack): # TODO game over redo
pygame.quit()
MultiplayerService.quit()
sys.exit()
if self.stack: if not self.next_piece:
self.stack.update(elapsed_time, self) self.next_piece = PieceGenerator.get_piece((620, 160))
if self.current_piece:
self.current_piece.update(elapsed_time, self)
else:
self.current_piece = self.next_piece
self.current_piece.move((360 - 620, 100 - 160)) # TODO calculate spawn position correctly
self.next_piece = PieceGenerator.get_piece((620, 160)) # (360, 100)
if self.stack and self.current_piece.collide(self.stack): # TODO game over redo
pygame.quit()
MultiplayerService.quit()
sys.exit()
if self.stack:
self.stack.update(elapsed_time, self)
for event in pygame.event.get(): for event in pygame.event.get():
if event.type == pygame.QUIT: if event.type == pygame.QUIT:
@@ -79,31 +89,34 @@ class Game:
def draw(self) -> None: def draw(self) -> None:
# TODO write not initialized exception # TODO write not initialized exception
# draw window bg if self.current_scene:
bg_color = pygame.Color(ConfigurationManager.get("color", "window-bg")) self.current_scene.draw(self.screen)
self.screen.fill(bg_color) else:
# draw window bg
bg_color = pygame.Color(ConfigurationManager.get("color", "window-bg"))
self.screen.fill(bg_color)
# draw all game objects # draw all game objects
if self.next_piece: if self.next_piece:
self.next_piece.draw(self.screen) self.next_piece.draw(self.screen)
if self.well: if self.well:
self.well.draw(self.screen) self.well.draw(self.screen)
if self.stack: if self.stack:
self.stack.draw(self.screen) self.stack.draw(self.screen)
if self.current_piece: if self.current_piece:
self.current_piece.draw(self.screen, self.well, self.stack) self.current_piece.draw(self.screen, self.well, self.stack)
score = str(self.score).zfill(6) score = str(self.score).zfill(6)
lines = str(self.stack.lines_completed_count).zfill(4) lines = str(self.stack.lines_completed_count).zfill(4)
level = str(self.get_level()).zfill(2) level = str(self.get_level()).zfill(2)
TextGenerator.draw("Top", (80, 120), self.screen) TextGenerator.draw("Top", (80, 120), self.screen)
TextGenerator.draw("000000", (80, 140), self.screen) TextGenerator.draw("000000", (80, 140), self.screen)
TextGenerator.draw("Score", (80, 180), self.screen) TextGenerator.draw("Score", (80, 180), self.screen)
TextGenerator.draw(score, (80, 200), self.screen) TextGenerator.draw(score, (80, 200), self.screen)
TextGenerator.draw("Lines " + lines, (300, 40), self.screen) TextGenerator.draw("Lines " + lines, (300, 40), self.screen)
TextGenerator.draw("Next", (600, 120), self.screen) TextGenerator.draw("Next", (600, 120), self.screen)
TextGenerator.draw("LVL " + level, (600, 220), self.screen) TextGenerator.draw("LVL " + level, (600, 220), self.screen)
# update display # update display
pygame.display.update() pygame.display.update()

33
tetris/scene.py Normal file
View File

@@ -0,0 +1,33 @@
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

View File

@@ -8,96 +8,96 @@ from typing import KeysView, Tuple
class ConfigurationManager: class ConfigurationManager:
CONFIG_FILE_LOCATION = "config.yaml" CONFIG_FILE_LOCATION = "config.yaml"
configuration = [] _configuration = []
@classmethod @classmethod
def load(cls) -> None: def init(cls) -> None:
with open(cls.CONFIG_FILE_LOCATION, "r") as yaml_file: with open(cls.CONFIG_FILE_LOCATION, "r") as yaml_file:
cls.configuration = yaml.safe_load(yaml_file) cls._configuration = yaml.safe_load(yaml_file)
@classmethod @classmethod
def get(cls, key: str, sub_key: str = None): def get(cls, key: str, sub_key: str = None):
if sub_key: if sub_key:
return cls.configuration[key][sub_key] return cls._configuration[key][sub_key]
else: else:
return cls.configuration[key] return cls._configuration[key]
""" """
TODO description TODO description
""" """
class TextGenerator: class TextGenerator:
sheet = None _sheet = None
glyph_size = (-1, -1) _glyph_size = (-1, -1)
characters = { } _characters = { }
@classmethod @classmethod
def load(cls, file: str, glyph_size: Tuple) -> None: def init(cls, file: str, glyph_size: Tuple) -> None:
cls.sheet = pygame.image.load(file) cls._sheet = pygame.image.load(file)
cls.glyph_size = glyph_size cls._glyph_size = glyph_size
# load character positions in bitmap into the characters dictionary # load character positions in bitmap into the characters dictionary
# letters # letters
cls.characters["A"] = (9 * glyph_size[0], 2 * glyph_size[1]) cls._characters["A"] = (9 * glyph_size[0], 2 * glyph_size[1])
cls.characters["B"] = (10 * glyph_size[0], 2 * glyph_size[1]) cls._characters["B"] = (10 * glyph_size[0], 2 * glyph_size[1])
cls.characters["C"] = (11 * glyph_size[0], 2 * glyph_size[1]) cls._characters["C"] = (11 * glyph_size[0], 2 * glyph_size[1])
cls.characters["D"] = (0 * glyph_size[0], 3 * glyph_size[1]) cls._characters["D"] = (0 * glyph_size[0], 3 * glyph_size[1])
cls.characters["E"] = (1 * glyph_size[0], 3 * glyph_size[1]) cls._characters["E"] = (1 * glyph_size[0], 3 * glyph_size[1])
cls.characters["F"] = (2 * glyph_size[0], 3 * glyph_size[1]) cls._characters["F"] = (2 * glyph_size[0], 3 * glyph_size[1])
cls.characters["G"] = (3 * glyph_size[0], 3 * glyph_size[1]) cls._characters["G"] = (3 * glyph_size[0], 3 * glyph_size[1])
cls.characters["H"] = (4 * glyph_size[0], 3 * glyph_size[1]) cls._characters["H"] = (4 * glyph_size[0], 3 * glyph_size[1])
cls.characters["I"] = (5 * glyph_size[0], 3 * glyph_size[1]) cls._characters["I"] = (5 * glyph_size[0], 3 * glyph_size[1])
cls.characters["J"] = (6 * glyph_size[0], 3 * glyph_size[1]) cls._characters["J"] = (6 * glyph_size[0], 3 * glyph_size[1])
cls.characters["K"] = (7 * glyph_size[0], 3 * glyph_size[1]) cls._characters["K"] = (7 * glyph_size[0], 3 * glyph_size[1])
cls.characters["L"] = (8 * glyph_size[0], 3 * glyph_size[1]) cls._characters["L"] = (8 * glyph_size[0], 3 * glyph_size[1])
cls.characters["M"] = (9 * glyph_size[0], 3 * glyph_size[1]) cls._characters["M"] = (9 * glyph_size[0], 3 * glyph_size[1])
cls.characters["N"] = (10 * glyph_size[0], 3 * glyph_size[1]) cls._characters["N"] = (10 * glyph_size[0], 3 * glyph_size[1])
cls.characters["O"] = (11 * glyph_size[0], 3 * glyph_size[1]) cls._characters["O"] = (11 * glyph_size[0], 3 * glyph_size[1])
cls.characters["P"] = (0 * glyph_size[0], 4 * glyph_size[1]) cls._characters["P"] = (0 * glyph_size[0], 4 * glyph_size[1])
cls.characters["Q"] = (1 * glyph_size[0], 4 * glyph_size[1]) cls._characters["Q"] = (1 * glyph_size[0], 4 * glyph_size[1])
cls.characters["R"] = (2 * glyph_size[0], 4 * glyph_size[1]) cls._characters["R"] = (2 * glyph_size[0], 4 * glyph_size[1])
cls.characters["S"] = (3 * glyph_size[0], 4 * glyph_size[1]) cls._characters["S"] = (3 * glyph_size[0], 4 * glyph_size[1])
cls.characters["T"] = (4 * glyph_size[0], 4 * glyph_size[1]) cls._characters["T"] = (4 * glyph_size[0], 4 * glyph_size[1])
cls.characters["U"] = (5 * glyph_size[0], 4 * glyph_size[1]) cls._characters["U"] = (5 * glyph_size[0], 4 * glyph_size[1])
cls.characters["V"] = (6 * glyph_size[0], 4 * glyph_size[1]) cls._characters["V"] = (6 * glyph_size[0], 4 * glyph_size[1])
cls.characters["W"] = (7 * glyph_size[0], 4 * glyph_size[1]) cls._characters["W"] = (7 * glyph_size[0], 4 * glyph_size[1])
cls.characters["X"] = (8 * glyph_size[0], 4 * glyph_size[1]) cls._characters["X"] = (8 * glyph_size[0], 4 * glyph_size[1])
cls.characters["Y"] = (9 * glyph_size[0], 4 * glyph_size[1]) cls._characters["Y"] = (9 * glyph_size[0], 4 * glyph_size[1])
cls.characters["Z"] = (10 * glyph_size[0], 4 * glyph_size[1]) cls._characters["Z"] = (10 * glyph_size[0], 4 * glyph_size[1])
# numbers # numbers
cls.characters["0"] = (4 * glyph_size[0], 1 * glyph_size[1]) cls._characters["0"] = (4 * glyph_size[0], 1 * glyph_size[1])
cls.characters["1"] = (5 * glyph_size[0], 1 * glyph_size[1]) cls._characters["1"] = (5 * glyph_size[0], 1 * glyph_size[1])
cls.characters["2"] = (6 * glyph_size[0], 1 * glyph_size[1]) cls._characters["2"] = (6 * glyph_size[0], 1 * glyph_size[1])
cls.characters["3"] = (7 * glyph_size[0], 1 * glyph_size[1]) cls._characters["3"] = (7 * glyph_size[0], 1 * glyph_size[1])
cls.characters["4"] = (8 * glyph_size[0], 1 * glyph_size[1]) cls._characters["4"] = (8 * glyph_size[0], 1 * glyph_size[1])
cls.characters["5"] = (9 * glyph_size[0], 1 * glyph_size[1]) cls._characters["5"] = (9 * glyph_size[0], 1 * glyph_size[1])
cls.characters["6"] = (10 * glyph_size[0], 1 * glyph_size[1]) cls._characters["6"] = (10 * glyph_size[0], 1 * glyph_size[1])
cls.characters["7"] = (11 * glyph_size[0], 1 * glyph_size[1]) cls._characters["7"] = (11 * glyph_size[0], 1 * glyph_size[1])
cls.characters["8"] = (0 * glyph_size[0], 2 * glyph_size[1]) cls._characters["8"] = (0 * glyph_size[0], 2 * glyph_size[1])
cls.characters["9"] = (1 * glyph_size[0], 2 * glyph_size[1]) cls._characters["9"] = (1 * glyph_size[0], 2 * glyph_size[1])
@classmethod @classmethod
def draw(cls, text: str, position: Tuple, surface: pygame.Surface) -> None: def draw(cls, text: str, position: Tuple, surface: pygame.Surface) -> None:
x_position = 0 x_position = 0
for char_ in text: for char_ in text:
if not char_.isspace(): if not char_.isspace():
surface.blit(cls.sheet, (position[0] + x_position, position[1]), pygame.Rect(cls.characters[char_.upper()], (cls.glyph_size[0], cls.glyph_size[1]))) surface.blit(cls._sheet, (position[0] + x_position, position[1]), pygame.Rect(cls._characters[char_.upper()], (cls._glyph_size[0], cls._glyph_size[1])))
x_position += cls.glyph_size[0] x_position += cls._glyph_size[0]
""" """
TODO description TODO description
""" """
class Controller: class Controller:
keys_pressed = {} _keys_pressed = {}
@classmethod @classmethod
def key_down(cls, key: int) -> bool: def key_down(cls, key: int) -> bool:
prior_pressed_state = False if key not in cls.keys_pressed else cls.keys_pressed[key] prior_pressed_state = False if key not in cls._keys_pressed else cls._keys_pressed[key]
cls.keys_pressed[key] = pygame.key.get_pressed()[key] cls._keys_pressed[key] = pygame.key.get_pressed()[key]
return cls.keys_pressed[key] and not prior_pressed_state return cls._keys_pressed[key] and not prior_pressed_state
@classmethod @classmethod
def key_pressed(cls, key: int) -> bool: def key_pressed(cls, key: int) -> bool: