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"
image:
title-screen: "resource/image/title_screen.png"
window-icon: "resource/image/tetris_icon.png"
font: "resource/image/press-start-2p-font.bmp"

View File

@@ -8,7 +8,7 @@ from tetris.game import Game
from tetris.util import ConfigurationManager
def main() -> None:
ConfigurationManager.load()
ConfigurationManager. init()
game = Game()
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 Stack
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?
class Game:
@@ -16,15 +18,19 @@ class Game:
self.tile_size = -1
self.screen = None
self.clock = None
self.main_music = None
self.current_scene = TitleScene()
# In Game #
self.current_piece = None
self.next_piece = None
self.well = None
self.stack = None
self.main_music = None
def initialize(self) -> None:
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_height = ConfigurationManager.get("window", "height")
@@ -50,25 +56,29 @@ class Game:
# gets called from the games main loop
def update(self) -> None:
# 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))
if self.current_piece:
self.current_piece.update(elapsed_time, self)
if self.current_scene:
self.current_scene.update()
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()
# TODO write not initialized exception
elapsed_time = self.clock.tick(self.fps)
if self.stack:
self.stack.update(elapsed_time, self)
if not self.next_piece:
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():
if event.type == pygame.QUIT:
@@ -79,31 +89,34 @@ class Game:
def draw(self) -> None:
# TODO write not initialized exception
# draw window bg
bg_color = pygame.Color(ConfigurationManager.get("color", "window-bg"))
self.screen.fill(bg_color)
if self.current_scene:
self.current_scene.draw(self.screen)
else:
# draw window bg
bg_color = pygame.Color(ConfigurationManager.get("color", "window-bg"))
self.screen.fill(bg_color)
# draw all game objects
if self.next_piece:
self.next_piece.draw(self.screen)
if self.well:
self.well.draw(self.screen)
if self.stack:
self.stack.draw(self.screen)
if self.current_piece:
self.current_piece.draw(self.screen, self.well, self.stack)
score = str(self.score).zfill(6)
lines = str(self.stack.lines_completed_count).zfill(4)
level = str(self.get_level()).zfill(2)
# draw all game objects
if self.next_piece:
self.next_piece.draw(self.screen)
if self.well:
self.well.draw(self.screen)
if self.stack:
self.stack.draw(self.screen)
if self.current_piece:
self.current_piece.draw(self.screen, self.well, self.stack)
score = str(self.score).zfill(6)
lines = str(self.stack.lines_completed_count).zfill(4)
level = str(self.get_level()).zfill(2)
TextGenerator.draw("Top", (80, 120), self.screen)
TextGenerator.draw("000000", (80, 140), self.screen)
TextGenerator.draw("Score", (80, 180), self.screen)
TextGenerator.draw(score, (80, 200), self.screen)
TextGenerator.draw("Lines " + lines, (300, 40), self.screen)
TextGenerator.draw("Next", (600, 120), self.screen)
TextGenerator.draw("LVL " + level, (600, 220), self.screen)
TextGenerator.draw("Top", (80, 120), self.screen)
TextGenerator.draw("000000", (80, 140), self.screen)
TextGenerator.draw("Score", (80, 180), self.screen)
TextGenerator.draw(score, (80, 200), self.screen)
TextGenerator.draw("Lines " + lines, (300, 40), self.screen)
TextGenerator.draw("Next", (600, 120), self.screen)
TextGenerator.draw("LVL " + level, (600, 220), self.screen)
# update display
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:
CONFIG_FILE_LOCATION = "config.yaml"
configuration = []
_configuration = []
@classmethod
def load(cls) -> None:
def init(cls) -> None:
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
def get(cls, key: str, sub_key: str = None):
if sub_key:
return cls.configuration[key][sub_key]
return cls._configuration[key][sub_key]
else:
return cls.configuration[key]
return cls._configuration[key]
"""
TODO description
"""
class TextGenerator:
sheet = None
glyph_size = (-1, -1)
characters = { }
_sheet = None
_glyph_size = (-1, -1)
_characters = { }
@classmethod
def load(cls, file: str, glyph_size: Tuple) -> None:
cls.sheet = pygame.image.load(file)
cls.glyph_size = glyph_size
def init(cls, file: str, glyph_size: Tuple) -> None:
cls._sheet = pygame.image.load(file)
cls._glyph_size = glyph_size
# load character positions in bitmap into the characters dictionary
# letters
cls.characters["A"] = (9 * 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["D"] = (0 * 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["G"] = (3 * 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["J"] = (6 * 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["M"] = (9 * 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["P"] = (0 * 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["S"] = (3 * 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["V"] = (6 * 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["Y"] = (9 * glyph_size[0], 4 * glyph_size[1])
cls.characters["Z"] = (10 * glyph_size[0], 4 * 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["C"] = (11 * glyph_size[0], 2 * 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["F"] = (2 * 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["I"] = (5 * 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["L"] = (8 * 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["O"] = (11 * glyph_size[0], 3 * 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["R"] = (2 * 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["U"] = (5 * 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["X"] = (8 * 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])
# numbers
cls.characters["0"] = (4 * 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["3"] = (7 * 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["6"] = (10 * 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["9"] = (1 * glyph_size[0], 2 * 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["2"] = (6 * 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["5"] = (9 * 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["8"] = (0 * glyph_size[0], 2 * glyph_size[1])
cls._characters["9"] = (1 * glyph_size[0], 2 * glyph_size[1])
@classmethod
def draw(cls, text: str, position: Tuple, surface: pygame.Surface) -> None:
x_position = 0
for char_ in text:
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])))
x_position += cls.glyph_size[0]
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]
"""
TODO description
"""
class Controller:
keys_pressed = {}
_keys_pressed = {}
@classmethod
def key_down(cls, key: int) -> bool:
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]
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]
return cls.keys_pressed[key] and not prior_pressed_state
return cls._keys_pressed[key] and not prior_pressed_state
@classmethod
def key_pressed(cls, key: int) -> bool: