Compare commits

...

33 Commits
v0.1.0 ... main

Author SHA1 Message Date
github-actions[bot]
b69cb4d9ff chore(build): auto-build pdf 2024-01-17 12:32:24 +00:00
Kristofers Solo
f7b0bc8da4 fix: typo 2024-01-17 14:31:57 +02:00
Kristofers Solo
8298aef8b4 docs: update install instructions 2024-01-17 14:26:05 +02:00
github-actions[bot]
e9ee2e31fb chore(build): auto-build pdf 2024-01-16 21:53:11 +00:00
Kristofers Solo
3299732976 docs: remove WIP from pdf 2024-01-16 23:50:22 +02:00
Kristofers Solo
1631ff8894 chore: bump up the version 2024-01-16 23:46:59 +02:00
Kristofers Solo
ac2e568a26 docs: remove WIP
docs: remove WIP from readme
2024-01-16 20:55:29 +02:00
github-actions[bot]
714c145316 chore(build): auto-build pdf 2024-01-16 18:37:26 +00:00
Kristofers Solo
782bf70531 fix(game): drop key 2024-01-16 20:37:06 +02:00
github-actions[bot]
c3358a7295 chore(build): auto-build pdf 2024-01-16 18:03:53 +00:00
Kristofers Solo
f8b18f60fe Merge branch 'main' of github.com:kristoferssolo/Tetris 2024-01-16 20:03:14 +02:00
Kristofers Solo
c0e998b882 chore: bump up the version 2024-01-16 20:02:50 +02:00
github-actions[bot]
5a78d14c41 chore(build): auto-build pdf 2024-01-16 18:02:28 +00:00
Kristofers Solo
63fdf72cc8
Merge pull request #7 from kristoferssolo/feature/pause
Implement pause feature
2024-01-16 20:02:09 +02:00
Kristofers Solo
280c6be84d feat(game): add pause screen 2024-01-16 19:55:22 +02:00
Kristofers Solo
a136a6ebf7 feat(game): disable movement while paused 2024-01-16 19:07:25 +02:00
Kristofers Solo
36edbacbbc chore(game): adjust block speed 2024-01-15 22:39:57 +02:00
Kristofers Solo
4eed4a18e9 refactor(game): pause 2024-01-15 22:39:39 +02:00
Kristofers Solo
68452de415 refacor(game): add separate _get_keys function 2024-01-15 09:17:58 +02:00
Kristofers Solo
b8604f41c3 feat(game): add pause method
fix: `pause`
2024-01-15 09:08:39 +02:00
Kristofers Solo
ae5b2fc0df chore(game): adjust speed increase 2024-01-15 07:37:49 +02:00
github-actions[bot]
c35f4798e9 chore(build): auto-build pdf 2024-01-15 05:03:24 +00:00
Kristofers Solo
79e6fd3a07 chore: bump up the version 2024-01-15 07:02:59 +02:00
Kristofers Solo
a8748a69a2 Merge branch 'preview' 2024-01-15 07:01:51 +02:00
Kristofers Solo
38301b0688 refactor(game): use attrs 2024-01-15 07:00:16 +02:00
Kristofers Solo
75d873d1eb style(game): rename FigureConfig to FigureParams
fix
2024-01-15 06:58:23 +02:00
Kristofers Solo
5200a1458e feat(game): update preview tetromino color
Preview color is dependant on chosen colorscheme in `settings.toml`.
2024-01-15 06:52:57 +02:00
github-actions[bot]
ef3dbad2d2 chore(build): auto-build pdf 2024-01-15 04:24:09 +00:00
Kristofers Solo
9e47d1bf2d refactor(game): block colors depend on settings 2024-01-15 06:23:31 +02:00
Kristofers Solo
a578731b65 refactor(game): add image property 2024-01-15 06:23:31 +02:00
github-actions[bot]
822dd60bc1 chore(build): auto-build pdf 2024-01-09 17:42:34 +00:00
Kristofers Solo
3ae98435c2
Merge pull request #3 from kristoferssolo/kristoferssolo-patch-1
Delete .github/workflows/release.yml
2024-01-09 19:40:40 +02:00
Kristofers Solo
040a879868
Delete .github/workflows/release.yml 2024-01-09 19:40:20 +02:00
22 changed files with 289 additions and 155 deletions

View File

@ -1,25 +0,0 @@
name: Release
on:
push:
tags:
- "v*.*.*"
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v3
with:
python-version: "3.11"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install build
- name: Build package
run: python -m build
- name: Release
uses: softprops/action-gh-release@v1
if: startsWith(github.ref, 'refs/tags/')
with:
files: dist/*.tar.gz

1
.gitignore vendored
View File

@ -162,3 +162,4 @@ debug
.logs/
checkpoints
assets/highscore
typst/*.pdf

View File

@ -40,7 +40,7 @@ cd Tetris
3. Install the required dependencies:
```bash
pip install .
pip install -e .
```
4. Run the game:
@ -54,7 +54,7 @@ python -m tetris
The `settings.toml` file is a configuration file for customizing various aspects of the game.
### General Settings
- `pause`: Defines the keys to pause the game. Currently a work in progress (WIP[^WIP]).
- `pause`: Defines the keys to pause the game. Currently a work in progress.
- `quit`: Defines the key(s) to quit the game.
- `colorscheme`: Specifies the color scheme for the game interface. Options include:
- `tokyonight-night`
@ -72,7 +72,7 @@ The `settings.toml` file is a configuration file for customizing various aspects
- `ccw (counter-clockwise)`: Defines the keys to rotate the tetromino in a counter-clockwise direction.
### Action Settings
- `hold`: Defines the keys to hold the tetromino (WIP).
- `hold`: Defines the keys to hold the tetromino (WIP[^WIP]).
- `drop`: Defines the keys to instantly drop the tetromino.
### Volume Settings

Binary file not shown.

Before

Width:  |  Height:  |  Size: 256 B

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 371 B

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 371 B

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 262 B

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 321 B

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 321 B

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 320 B

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -4,26 +4,26 @@ build-backend = "setuptools.build_meta"
[project]
name = "tetris"
version = "0.1.0"
version = "0.1.3"
description = "Tetris game"
authors = [{ name = "Kristofers Solo", email = "dev@kristofers.xyz" }]
readme = "README.md"
requires-python = ">=3.10"
license = { file = "LICENSE" }
dependencies = [
"attrs==23.1.0",
"loguru==0.7.2",
"numpy==1.26.3",
"pygame-ce==2.4.0",
"toml==0.10.2",
"attrs==23.1.0",
"loguru==0.7.2",
"numpy==1.26.3",
"pygame-ce==2.4.0",
"toml==0.10.2",
]
keywords = ["tetris", "game", "pygame"]
classifiers = [
"Development Status :: 3 - Alpha",
"License :: OSI Approved :: GPLv3 License",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Development Status :: 3 - Alpha",
"License :: OSI Approved :: GPLv3 License",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
]
[project.urls]
@ -45,29 +45,29 @@ warn_unused_configs = true
[tool.ruff]
extend-select = [
"B",
"BLE",
"C4",
"ERA",
"I",
"ICN",
"INP",
"ISC",
"N",
"NPY",
"PGH",
"PIE",
# "PTH",
"Q",
"RET",
"RSE",
"RUF",
"S",
"SIM",
"T20",
"TCH",
"TID",
"YTT",
"B",
"BLE",
"C4",
"ERA",
"I",
"ICN",
"INP",
"ISC",
"N",
"NPY",
"PGH",
"PIE",
# "PTH",
"Q",
"RET",
"RSE",
"RUF",
"S",
"SIM",
"T20",
"TCH",
"TID",
"YTT",
]
ignore = ["E741"]
show-fixes = true

View File

@ -1,5 +1,5 @@
[General]
pause = ["escape", "F1"] # WIP
pause = ["escape", "F1"]
quit = ["q"]
colorscheme = "tokyonight-night" # tokyonight-night / tokyonight-storm / tokyonight-day / tokyonight-moon
@ -11,16 +11,16 @@ down = ["down", "keypad 2"]
[Rotation]
cw = ["x", "up", "keypad 1", "keypad 5", "keypad 9"] # clockwise
ccw = [
"left ctrl",
"right ctrl",
"z",
"keypad 3",
"keypad 7",
"left ctrl",
"right ctrl",
"z",
"keypad 3",
"keypad 7",
] # counter-clockwise
[Action]
hold = ["left shift", "right shift", "c", "keypad 0"] # WIP
drop = ["space", "keypad 5"]
drop = ["space", "keypad 8"]
[Volume.Music]
enabled = true

View File

@ -1,15 +1,17 @@
from typing import Any
import pygame
from loguru import logger
from utils import CONFIG, Figure, GameMode
from .base import BaseScreen
from .base import BaseScreen, SceenElement
from .pause import Pause
from .preview import Preview
from .score import Score
from .tetris import Tetris
class Game(BaseScreen):
class Game(BaseScreen, SceenElement):
"""
Game class.
@ -32,15 +34,16 @@ class Game(BaseScreen):
def __init__(self, game_mode: GameMode, settings: dict[str, Any]) -> None:
self.game_mode = game_mode
self.settings = settings
self._initialize_surface()
self._initialize_rect()
self._initialize_game_components()
self._start_background_music()
self.paused = False
def draw(self) -> None:
"""
Raises:
NotImplementedError: Not implemented yet.
"""
raise NotImplementedError
"""Draw the score on the score surface."""
self._update_display_surface()
self._draw_background()
def update(self) -> None:
"""
@ -51,12 +54,15 @@ class Game(BaseScreen):
def run(self) -> None:
"""Run a single iteration of the game loop."""
self.draw()
self.tetris.run()
self.score.run()
self.preview.update(self.next_figure)
self.preview.run()
if self.paused:
self.pause_screen.draw()
self.clock.tick(CONFIG.game.fps)
def mute(self) -> None:
@ -64,6 +70,19 @@ class Game(BaseScreen):
self.music.set_volume(0)
self.tetris.mute()
def pause(self) -> None:
"""Pause the game."""
if self.paused:
logger.debug("Unpause")
self.paused = False
self.tetris.unfreeze()
self.music.play(-1, fade_ms=100)
else:
logger.debug("Pause")
self.paused = True
self.tetris.freeze()
self.music.fadeout(100)
def _initialize_game_components(self) -> None:
"""Initialize game-related components."""
self.clock = pygame.time.Clock()
@ -72,6 +91,7 @@ class Game(BaseScreen):
self.tetris = Tetris(self._get_next_figure, self._update_score, self.game_mode, self.settings)
self.score = Score(self.game_mode)
self.preview = Preview()
self.pause_screen = Pause()
def _update_score(self, lines: int, score: int, level: int) -> None:
"""
@ -110,3 +130,28 @@ class Game(BaseScreen):
self.music = pygame.mixer.Sound(CONFIG.music.background)
self.music.set_volume(self.settings["Volume"]["Music"]["level"])
self.music.play(-1)
def _initialize_surface(self) -> None:
"""Initialize the pause screen surface."""
self.surface = pygame.Surface(CONFIG.window.size)
self.display_surface = pygame.display.get_surface()
def _initialize_rect(self) -> None:
"""Initialize the score rectangle."""
self.rect = self.surface.get_rect(topleft=(0, 0))
def _draw_background(self) -> None:
"""Draw the background."""
self.surface.fill(CONFIG.colors.bg)
def _update_display_surface(self) -> None:
"""Update the display surface."""
self.display_surface.blit(self.surface, self.rect)
def _draw_border(self) -> None:
"""Draw the border.
Raises:
NotImplementedError: Not implemented yet.
"""
raise NotImplementedError

View File

@ -8,6 +8,7 @@ from utils import CONFIG, GameMode, read_settings
from .base import BaseScreen, SceenElement, TextScreen
from .button import Button
from .game import Game
from .tetris import get_keys
class Main(BaseScreen, SceenElement, TextScreen):
@ -45,8 +46,10 @@ class Main(BaseScreen, SceenElement, TextScreen):
if event.type == pygame.QUIT:
self.exit()
elif event.type == pygame.KEYDOWN:
if event.key in [pygame.key.key_code(key) for key in self.settings["General"]["quit"]]:
if event.key in get_keys(self.settings["General"]["quit"]):
self.exit()
elif event.key in get_keys(self.settings["General"]["pause"]) and self.game:
self.game.pause()
if not self.game:
for button in self.buttons:
@ -60,14 +63,13 @@ class Main(BaseScreen, SceenElement, TextScreen):
def run_game_loop(self) -> None:
"""Run a single iteration of the game loop."""
if not self.game:
if self.game:
self.game.run()
else:
self.draw()
self.handle_events()
if self.game:
self.game.run()
self.update()
def exit(self) -> None:

71
src/game/screens/pause.py Normal file
View File

@ -0,0 +1,71 @@
import pygame
from utils import CONFIG
from .base import BaseScreen, SceenElement, TextScreen
class Pause(BaseScreen, SceenElement, TextScreen):
def __init__(self) -> None:
self._initialize_surface()
self._initialize_rect()
self._initialize_font()
def run(self) -> None:
"""
Raises:
NotImplementedError: Not implemented yet.
"""
raise NotImplementedError
def update(self) -> None:
self._update_display_surface()
def draw(self) -> None:
"""Update the display."""
self.update()
self._draw_background()
self._draw_text()
def _draw_text(self) -> None:
"""Draw the text."""
self._display_text("Paused")
def _display_text(self, text: str) -> None:
"""Display the text."""
text_surface = self.font.render(text, True, CONFIG.colors.fg_float)
text_rect = text_surface.get_rect(center=self.rect.center)
self.text_surface.blit(text_surface, text_rect)
def _draw_background(self) -> None:
"""Draw the background."""
self.surface.fill(CONFIG.colors.bg_float)
self.surface.set_alpha(100)
self.text_surface.set_colorkey("#000000")
self.text_surface.set_alpha(255)
def _initialize_surface(self) -> None:
"""Initialize the pause screen surface."""
self.surface = pygame.Surface(CONFIG.window.size)
self.display_surface = pygame.display.get_surface()
self.text_surface = pygame.Surface(CONFIG.window.size)
def _initialize_rect(self) -> None:
"""Initialize the score rectangle."""
self.rect = self.surface.get_rect(topleft=(0, 0))
def _initialize_font(self) -> None:
"""Initialize the font used to display the text."""
self.font = pygame.font.Font(CONFIG.font.family, CONFIG.font.size * 2)
def _update_display_surface(self) -> None:
"""Update the display surface."""
self.display_surface.blit(self.surface, self.rect)
self.display_surface.blit(self.text_surface, self.rect)
def _draw_border(self) -> None:
"""Draw the border.
Raises:
NotImplementedError: Not implemented yet.
"""
raise NotImplementedError

View File

@ -30,7 +30,7 @@ class Preview(BaseScreen, SceenElement):
Args:
next_figures: Next figure.
"""
self.next_figure = next_figure
self.next_figure: Figure = next_figure
def draw(self) -> None:
"""Draw the preview on the preview surface."""
@ -51,9 +51,10 @@ class Preview(BaseScreen, SceenElement):
def _draw_figure(self) -> None:
"""Draw a single upcoming figure on the preview surface."""
figure_surface = self.next_figure.value.image
figure_surface: pygame.Surface = self.next_figure.value.image()
x = self.surface.get_width() / 2
y = self.surface.get_height() / 2
figure_surface.fill(self.next_figure.value.color, special_flags=pygame.BLEND_RGB_MULT)
rect = figure_surface.get_rect(center=(x, y))
self.surface.blit(figure_surface, rect)

View File

@ -91,12 +91,11 @@ class Tetris(BaseScreen):
def handle_events(self) -> None:
"""Handle player input events."""
keys: pygame.key.ScancodeWrapper = pygame.key.get_pressed()
self._handle_movement_keys(keys)
self._handle_rotation_keys(keys)
self._handle_down_key(keys)
self._handle_drop_key(keys)
if not self.paused:
self._handle_movement_keys()
self._handle_rotation_keys()
self._handle_down_key()
self._handle_drop_key()
def move_down(self) -> bool:
"""
@ -161,6 +160,25 @@ class Tetris(BaseScreen):
"""
return self.tetromino.drop()
def restart(self) -> None:
"""Restart the game."""
logger.info(f"Restarting the game. Score was {self.score}")
self._reset_game_state()
def freeze(self) -> None:
"""Freeze all timers."""
self.timers.freeze()
self.paused = True
def unfreeze(self) -> None:
"""Unfreeze all timers."""
self.timers.unfreeze()
self.paused = False
def mute(self) -> None:
"""Mute the game."""
self.landing_sound.set_volume(0)
def create_new_tetromino(self, shape: Optional[Figure] = None) -> Optional[Tetromino]:
"""Create a new tetromino and perform necessary actions."""
self._play_landing_sound()
@ -204,15 +222,6 @@ class Tetris(BaseScreen):
return True
return False
def restart(self) -> None:
"""Restart the game."""
logger.info(f"Restarting the game. Score was {self.score}")
self._reset_game_state()
def mute(self) -> None:
"""Mute the game."""
self.landing_sound.set_volume(0)
def _draw_grid(self) -> None:
"""Draw the grid on the game surface."""
for col in range(1, CONFIG.game.columns):
@ -299,8 +308,8 @@ class Tetris(BaseScreen):
def _level_up(self) -> None:
"""Level up."""
self.level += 1
self.initial_block_speed *= 0.5
self.increased_block_speed *= 0.5
self.initial_block_speed *= 0.8 # the larger the multiplier, the slower the game
self.increased_block_speed *= 0.8
self.timers.vertical.duration = self.initial_block_speed
def _draw_components(self) -> None:
@ -365,13 +374,14 @@ class Tetris(BaseScreen):
def _initialize_game_state(self) -> None:
"""Initialize the game state."""
self.initial_block_speed = CONFIG.game.initial_speed
self.increased_block_speed = self.initial_block_speed * 0.4
self.increased_block_speed = self.initial_block_speed * 0.5
self.down_pressed = False
self.drop_pressed = False
self.level: int = 1
self.score: int = 0
self.lines: int = 0
self.game_over = False
self.paused = False
def _initialize_sound(self) -> None:
"""Initialize game sounds."""
@ -397,17 +407,17 @@ class Tetris(BaseScreen):
"""Fill the game surface with background color."""
self.surface.fill(CONFIG.colors.bg_float)
def _handle_movement_keys(self, keys: pygame.key.ScancodeWrapper) -> None:
def _handle_movement_keys(self) -> None:
"""
Handle movement keys.
See `settings.toml` for the default key bindings.
"""
right_keys: list[int] = [pygame.key.key_code(key) for key in self.settings["Movement"]["right"]]
right_key_pressed = any(keys[key] for key in right_keys)
right_keys = get_keys(self.settings["Movement"]["right"])
right_key_pressed = is_key_pressed(right_keys)
left_keys: list[int] = [pygame.key.key_code(key) for key in self.settings["Movement"]["left"]]
left_key_pressed = any(keys[key] for key in left_keys)
left_keys = get_keys(self.settings["Movement"]["left"])
left_key_pressed = is_key_pressed(left_keys)
if not self.timers.horizontal.active:
if left_key_pressed:
@ -417,17 +427,18 @@ class Tetris(BaseScreen):
self.move_right()
self.timers.horizontal.activate()
def _handle_rotation_keys(self, keys: pygame.key.ScancodeWrapper) -> None:
def _handle_rotation_keys(self) -> None:
"""
Handle rotation keys.
See `settings.toml` for the default key bindings.
"""
cw_keys: list[int] = [pygame.key.key_code(key) for key in self.settings["Rotation"]["cw"]]
cw_key_pressed = any(keys[key] for key in cw_keys)
ccw_keys: list[int] = [pygame.key.key_code(key) for key in self.settings["Rotation"]["ccw"]]
ccw_key_pressed = any(keys[key] for key in ccw_keys)
cw_keys = get_keys(self.settings["Rotation"]["cw"])
cw_key_pressed = is_key_pressed(cw_keys)
ccw_keys = get_keys(self.settings["Rotation"]["ccw"])
ccw_key_pressed = is_key_pressed(ccw_keys)
if not self.timers.rotation.active:
if cw_key_pressed:
@ -438,14 +449,14 @@ class Tetris(BaseScreen):
self.rotate_reverse()
self.timers.rotation.activate()
def _handle_down_key(self, keys: pygame.key.ScancodeWrapper) -> None:
def _handle_down_key(self) -> None:
"""
Handle the down key.
See `settings.toml` for the default key bindings.
"""
down_keys: list[int] = [pygame.key.key_code(key) for key in self.settings["Movement"]["down"]]
down_key_pressed = any(keys[key] for key in down_keys)
down_keys = get_keys(self.settings["Movement"]["down"])
down_key_pressed = is_key_pressed(down_keys)
if not self.down_pressed and down_key_pressed:
self.down_pressed = True
self.timers.vertical.duration = self.increased_block_speed
@ -454,14 +465,14 @@ class Tetris(BaseScreen):
self.down_pressed = False
self.timers.vertical.duration = self.initial_block_speed
def _handle_drop_key(self, keys: pygame.key.ScancodeWrapper) -> None:
def _handle_drop_key(self) -> None:
"""
Handle the drop key.
See `settings.toml` for the default key bindings.
"""
drop_keys = [pygame.key.key_code(key) for key in self.settings["Action"]["drop"]]
drop_key_pressed = any(keys[key] for key in drop_keys)
drop_keys = get_keys(self.settings["Action"]["drop"])
drop_key_pressed = is_key_pressed(drop_keys)
if not self.timers.drop.active and drop_key_pressed:
self.drop()
@ -494,3 +505,14 @@ class Tetris(BaseScreen):
(self.grid_surface.get_width(), y),
CONFIG.game.line_width,
)
def get_keys(keys: dict[str, str]) -> list[int]:
"""Get the key codes for the specified keys."""
return [pygame.key.key_code(key) for key in keys]
def is_key_pressed(keys: list[int]) -> bool:
"""Check if any of the specified keys is pressed."""
keys_pressed = pygame.key.get_pressed()
return any(keys_pressed[key] for key in keys)

View File

@ -1,4 +1,4 @@
from typing import Any, Callable, NamedTuple, Optional
from typing import Any, Callable, Iterator, Optional
import pygame
from attrs import define, field
@ -55,7 +55,8 @@ class Timer:
self.activate()
class Timers(NamedTuple):
@define
class Timers:
"""
NamedTuple for grouping different timers.
@ -70,3 +71,17 @@ class Timers(NamedTuple):
horizontal: Timer
rotation: Timer
drop: Timer
def __iter__(self) -> Iterator[Timer]:
"""Returns an iterator over the timers."""
return iter((self.vertical, self.horizontal, self.rotation, self.drop))
def freeze(self) -> None:
"""Freezes all timers."""
for timer in self:
timer.deactivate()
def unfreeze(self) -> None:
"""Unfreezes all timers."""
for timer in self:
timer.activate()

View File

@ -1,6 +1,6 @@
from .config import CONFIG
from .enum import Direction, GameMode, Rotation
from .figure import Figure, FigureConfig
from .figure import Figure
from .path import BASE_PATH
from .settings import read_settings, save_settings
from .tuples import Size
@ -10,7 +10,6 @@ __all__ = [
"CONFIG",
"Size",
"Figure",
"FigureConfig",
"Direction",
"Rotation",
"GameMode",

View File

@ -1,30 +1,33 @@
import random
from enum import Enum
from typing import NamedTuple
import pygame
from attrs import define
from pygame import Vector2 as Vec2
from .colors import TokyoNightNight
from .config import CONFIG
from .path import BASE_PATH
class FigureConfig(NamedTuple):
@define
class FigureParams:
"""
Attributes:
shape: The shape of the figure.
color: The color of the figure.
image: The image of the figure.
filename: The filename of the image of the figure.
"""
shape: list[Vec2]
color: str
image: pygame.Surface
filename: str
def _load_image(filename: str) -> pygame.Surface:
return pygame.image.load(BASE_PATH / "assets" / "figures" / filename) # TODO: add `.convert_alpha()``
# TODO: change colors of images
def image(self) -> pygame.Surface:
"""
Returns:
The image of the figure.
"""
return pygame.image.load(BASE_PATH / "assets" / "figures" / self.filename).convert_alpha()
class Figure(Enum):
@ -39,76 +42,76 @@ class Figure(Enum):
L: The L figure.
"""
I = FigureConfig(
I = FigureParams( # type: ignore
[
Vec2(0, 0),
Vec2(0, -1),
Vec2(0, -2),
Vec2(0, 1),
],
TokyoNightNight().cyan,
_load_image("I.png"),
CONFIG.colors.cyan,
"I.png",
)
O = FigureConfig(
O = FigureParams( # type: ignore
[
Vec2(0, 0),
Vec2(0, -1),
Vec2(1, 0),
Vec2(1, -1),
],
TokyoNightNight().yellow,
_load_image("O.png"),
CONFIG.colors.yellow,
"O.png",
)
T = FigureConfig(
T = FigureParams( # type: ignore
[
Vec2(0, 0),
Vec2(-1, 0),
Vec2(1, 0),
Vec2(0, -1),
],
TokyoNightNight().purple,
_load_image("T.png"),
CONFIG.colors.purple,
"T.png",
)
S = FigureConfig(
S = FigureParams( # type: ignore
[
Vec2(0, 0),
Vec2(-1, 0),
Vec2(0, -1),
Vec2(1, -1),
],
TokyoNightNight().green,
_load_image("S.png"),
CONFIG.colors.green,
"S.png",
)
Z = FigureConfig(
Z = FigureParams( # type: ignore
[
Vec2(0, 0),
Vec2(1, 0),
Vec2(0, -1),
Vec2(-1, -1),
],
TokyoNightNight().red,
_load_image("Z.png"),
CONFIG.colors.red,
"Z.png",
)
J = FigureConfig(
J = FigureParams( # type: ignore
[
Vec2(0, 0),
Vec2(0, -1),
Vec2(0, 1),
Vec2(-1, 1),
],
TokyoNightNight().blue,
_load_image("J.png"),
CONFIG.colors.blue,
"J.png",
)
L = FigureConfig(
L = FigureParams( # type: ignore
[
Vec2(0, 0),
Vec2(0, -1),
Vec2(0, 1),
Vec2(1, 1),
],
TokyoNightNight().orange,
_load_image("L.png"),
CONFIG.colors.orange,
"L.png",
)
@classmethod

Binary file not shown.

View File

@ -99,7 +99,7 @@ cd Tetris
3. Instalējiet nepieciešamās atkarības:
```bash
pip install .
pip install -e .
```
4. Palaidiet spēli:
@ -116,7 +116,7 @@ python -m tetris
=== Vispārīgi iestatījumi
#par(first-line-indent: 0cm, [
/ `pause`: definē taustiņu(-s), lai apturētu spēli (WIP #footnote[WIP (Work In Progress) -- nepabeigts darbs: darbs vai produkts, kas ir sākts, bet nav pabeigts vai gatavs.]<WIP>).
/ `pause`: definē taustiņu(-s), lai apturētu spēli.
/ `quit`: definē taustiņu(-s), lai izietu no spēles.
/ `colorscheme`: norāda spēles saskarnes krāsu shēmu. Iespējas ietver:
- `tokyonight-day`
@ -140,7 +140,7 @@ python -m tetris
=== Papildus darbību iestatījumi
#par(first-line-indent: 0cm, [
/ `hold`: definē taustiņu(-s), lai uzglabātu tetromino (WIP @WIP).
/ `hold`: definē taustiņu(-s), lai uzglabātu tetromino (WIP #footnote[WIP (Work In Progress) -- nepabeigts darbs: darbs vai produkts, kas ir sākts, bet nav pabeigts vai gatavs.]<WIP>).
/ `drop`: definē taustiņ(-s), lai nekavējoties nomestu tetromino.
])