Files
tetri5/tetris/game.py

106 lines
4.0 KiB
Python

import sys
from typing import Text
import pygame
from pygame import mixer
from tetris.util import ConfigurationManager
from tetris.util import TextGenerator
from tetris.util import Controller
from tetris.entity import PieceGenerator
from tetris.entity import Well
from tetris.entity import Stack
# TODO should be a singleton and refactor the whole file?
class Game:
def __init__(self):
self.fps = -1
self.tile_size = -1
self.screen = None
self.clock = None
self.main_music = None
self.current_piece = None
self.well = None
self.stack = None
def initialize(self) -> None:
pygame.init()
TextGenerator.load(ConfigurationManager.get("image", "font"), (20, 20))
win_width = ConfigurationManager.get("window", "width")
win_height = ConfigurationManager.get("window", "height")
win_title = ConfigurationManager.get("window", "title")
win_icon = ConfigurationManager.get("image", "window-icon")
self.fps = ConfigurationManager.get("engine", "fps")
self.tile_size = ConfigurationManager.get("engine", "tile-size")
self.screen = pygame.display.set_mode((win_width, win_height))
self.clock = pygame.time.Clock()
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)
# 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_piece:
self.current_piece.update(elapsed_time, self)
else:
self.current_piece = PieceGenerator.get_piece((360, 100)) # TODO calculate spawn position
if self.stack and self.current_piece.collide(self.stack): # TODO game over redo
pygame.quit()
sys.exit()
if self.stack:
self.stack.update(elapsed_time, self)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
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)
# draw all game objects
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)
# update display
pygame.display.update()
def get_level(self) -> int:
lines_per_level = ConfigurationManager.get("engine", "lines-per-level")
return 0 if not self.stack else self.stack.lines_completed_count // lines_per_level