use texture, import from, black

This commit is contained in:
Adrien MALINGREY 2019-10-02 11:54:50 +02:00
parent df8257c4da
commit b95478ea8d
16 changed files with 85 additions and 136 deletions

View File

@ -12,13 +12,15 @@ except ImportError:
try: try:
import arcade import arcade
except ImportError as e: except ImportError as e:
sys.exit(str(e) + """ sys.exit(
str(e)
+ """
This game require arcade library. This game require arcade library.
You can install it with: You can install it with:
python -m pip install --user arcade""" python -m pip install --user arcade"""
) )
import tetrislogic from tetrislogic import TetrisLogic, Color, State
# Constants # Constants
@ -28,7 +30,6 @@ WINDOW_HEIGHT = 600
WINDOW_MIN_WIDTH = 517 WINDOW_MIN_WIDTH = 517
WINDOW_MIN_HEIGHT = 388 WINDOW_MIN_HEIGHT = 388
WINDOW_TITLE = "TETRARCADE" WINDOW_TITLE = "TETRARCADE"
MINO_SIZE = 20
BG_COLOR = (7, 11, 21) BG_COLOR = (7, 11, 21)
# Delays (seconds) # Delays (seconds)
@ -46,26 +47,30 @@ WINDOW_BG_PATH = "res/bg.jpg"
MATRIX_BG_PATH = "res/matrix.png" MATRIX_BG_PATH = "res/matrix.png"
HELD_BG_PATH = "res/held.png" HELD_BG_PATH = "res/held.png"
NEXT_BG_PATH = "res/next.png" NEXT_BG_PATH = "res/next.png"
MINOES_SPRITES_PATHS = { MINOES_SPRITES_PATH = "res/minoes.png"
"orange": "res/orange_mino.png", Color.PRELOCKED = 7
"blue": "res/blue_mino.png", MINOES_COLOR_ID = {
"yellow": "res/yellow_mino.png", Color.BLUE: 0,
"cyan": "res/cyan_mino.png", Color.CYAN: 1,
"green": "res/green_mino.png", Color.GREEN: 2,
"red": "res/red_mino.png", Color.MAGENTA: 3,
"magenta": "res/magenta_mino.png", Color.ORANGE: 4,
"held": "res/held_mino.png" Color.RED: 5,
Color.YELLOW: 6,
Color.PRELOCKED: 7,
} }
MINO_SIZE = 20
MINO_SPRITE_SIZE = 21
TEXTURES = arcade.load_textures(
MINOES_SPRITES_PATH, ((i * MINO_SPRITE_SIZE, 0, MINO_SPRITE_SIZE, MINO_SPRITE_SIZE) for i in range(8))
)
TEXTURES = {color: TEXTURES[i] for color, i in MINOES_COLOR_ID.items()}
# User profile path # User profile path
if sys.platform == "win32": if sys.platform == "win32":
USER_PROFILE_DIR = os.environ.get( USER_PROFILE_DIR = os.environ.get("appdata", os.path.expanduser("~\Appdata\Roaming"))
"appdata", os.path.expanduser("~\Appdata\Roaming")
)
else: else:
USER_PROFILE_DIR = os.environ.get( USER_PROFILE_DIR = os.environ.get("XDG_DATA_HOME", os.path.expanduser("~/.local/share"))
"XDG_DATA_HOME", os.path.expanduser("~/.local/share")
)
USER_PROFILE_DIR = os.path.join(USER_PROFILE_DIR, "TetrArcade") USER_PROFILE_DIR = os.path.join(USER_PROFILE_DIR, "TetrArcade")
HIGH_SCORE_PATH = os.path.join(USER_PROFILE_DIR, ".high_score") HIGH_SCORE_PATH = os.path.join(USER_PROFILE_DIR, ".high_score")
CONF_PATH = os.path.join(USER_PROFILE_DIR, "TetrArcade.ini") CONF_PATH = os.path.join(USER_PROFILE_DIR, "TetrArcade.ini")
@ -83,15 +88,17 @@ HIGHLIGHT_TEXT_SIZE = 20
class MinoSprite(arcade.Sprite): class MinoSprite(arcade.Sprite):
def __init__(self, mino, window, alpha): def __init__(self, mino, window, alpha):
super().__init__() super().__init__()
self.append_texture(MINOES_SPRITES_PATHS[mino.color])
self.append_texture(MINOES_SPRITES_PATHS["held"])
self.alpha = alpha self.alpha = alpha
self.window = window self.window = window
self.append_texture(TEXTURES[mino.color])
self.append_texture(TEXTURES[Color.PRELOCKED])
self.set_texture(0)
def set_position(self, x, y): def refresh(self, x, y, prelocked=False):
size = MINO_SIZE * self.scale size = MINO_SIZE * self.scale
self.left = self.window.matrix_bg.left + x * size self.left = self.window.matrix_bg.left + x * size
self.bottom = self.window.matrix_bg.bottom + y * size self.bottom = self.window.matrix_bg.bottom + y * size
self.set_texture(prelocked)
class MinoesSprites(arcade.SpriteList): class MinoesSprites(arcade.SpriteList):
@ -104,10 +111,6 @@ class MinoesSprites(arcade.SpriteList):
class TetrominoSprites(MinoesSprites): class TetrominoSprites(MinoesSprites):
def __init__(self, tetromino, window, alpha=NORMAL_ALPHA): def __init__(self, tetromino, window, alpha=NORMAL_ALPHA):
super().__init__() super().__init__()
self.preload_textures([
MINOES_SPRITES_PATHS[tetromino.MINOES_COLOR],
MINOES_SPRITES_PATHS["held"]
])
self.tetromino = tetromino self.tetromino = tetromino
self.alpha = alpha self.alpha = alpha
for mino in tetromino: for mino in tetromino:
@ -115,14 +118,9 @@ class TetrominoSprites(MinoesSprites):
self.append(mino.sprite) self.append(mino.sprite)
def refresh(self): def refresh(self):
if self.tetromino.prelocked:
texture = 1
else:
texture = 0
for mino in self.tetromino: for mino in self.tetromino:
coord = mino.coord + self.tetromino.coord coord = mino.coord + self.tetromino.coord
mino.sprite.set_position(coord.x, coord.y) mino.sprite.refresh(coord.x, coord.y, self.tetromino.prelocked)
mino.sprite.set_texture(texture)
class MatrixSprites(MinoesSprites): class MatrixSprites(MinoesSprites):
@ -135,11 +133,11 @@ class MatrixSprites(MinoesSprites):
for y, line in enumerate(self.matrix): for y, line in enumerate(self.matrix):
for x, mino in enumerate(line): for x, mino in enumerate(line):
if mino: if mino:
mino.sprite.set_position(x, y) mino.sprite.refresh(x, y)
self.append(mino.sprite) self.append(mino.sprite)
class TetrArcade(tetrislogic.TetrisLogic, arcade.Window): class TetrArcade(TetrisLogic, arcade.Window):
def __init__(self): def __init__(self):
locale.setlocale(locale.LC_ALL, "") locale.setlocale(locale.LC_ALL, "")
self.highlight_texts = [] self.highlight_texts = []
@ -180,11 +178,7 @@ class TetrArcade(tetrislogic.TetrisLogic, arcade.Window):
self.on_resize(self.init_width, self.init_height) self.on_resize(self.init_width, self.init_height)
def new_conf(self): def new_conf(self):
self.conf["WINDOW"] = { self.conf["WINDOW"] = {"width": WINDOW_WIDTH, "height": WINDOW_HEIGHT, "fullscreen": False}
"width": WINDOW_WIDTH,
"height": WINDOW_HEIGHT,
"fullscreen": False,
}
self.conf["KEYBOARD"] = { self.conf["KEYBOARD"] = {
"start": "ENTER", "start": "ENTER",
"move left": "LEFT", "move left": "LEFT",
@ -197,10 +191,7 @@ class TetrArcade(tetrislogic.TetrisLogic, arcade.Window):
"pause": "ESCAPE", "pause": "ESCAPE",
"fullscreen": "F11", "fullscreen": "F11",
} }
self.conf["AUTO-REPEAT"] = { self.conf["AUTO-REPEAT"] = {"delay": 0.3, "period": 0.01}
"delay": 0.3,
"period": 0.01
}
self.load_conf() self.load_conf()
if not os.path.exists(USER_PROFILE_DIR): if not os.path.exists(USER_PROFILE_DIR):
os.makedirs(USER_PROFILE_DIR) os.makedirs(USER_PROFILE_DIR)
@ -213,42 +204,28 @@ class TetrArcade(tetrislogic.TetrisLogic, arcade.Window):
self.init_fullscreen = self.conf["WINDOW"].getboolean("fullscreen") self.init_fullscreen = self.conf["WINDOW"].getboolean("fullscreen")
self.key_map = { self.key_map = {
tetrislogic.State.STARTING: { State.STARTING: {
getattr(arcade.key, self.conf["KEYBOARD"]["start"]): self.new_game, getattr(arcade.key, self.conf["KEYBOARD"]["start"]): self.new_game,
getattr( getattr(arcade.key, self.conf["KEYBOARD"]["fullscreen"]): self.toggle_fullscreen,
arcade.key, self.conf["KEYBOARD"]["fullscreen"]
): self.toggle_fullscreen,
}, },
tetrislogic.State.PLAYING: { State.PLAYING: {
getattr(arcade.key, self.conf["KEYBOARD"]["move left"]): self.move_left, getattr(arcade.key, self.conf["KEYBOARD"]["move left"]): self.move_left,
getattr( getattr(arcade.key, self.conf["KEYBOARD"]["move right"]): self.move_right,
arcade.key, self.conf["KEYBOARD"]["move right"]
): self.move_right,
getattr(arcade.key, self.conf["KEYBOARD"]["soft drop"]): self.soft_drop, getattr(arcade.key, self.conf["KEYBOARD"]["soft drop"]): self.soft_drop,
getattr(arcade.key, self.conf["KEYBOARD"]["hard drop"]): self.hard_drop, getattr(arcade.key, self.conf["KEYBOARD"]["hard drop"]): self.hard_drop,
getattr( getattr(arcade.key, self.conf["KEYBOARD"]["rotate clockwise"]): self.rotate_clockwise,
arcade.key, self.conf["KEYBOARD"]["rotate clockwise"] getattr(arcade.key, self.conf["KEYBOARD"]["rotate counter"]): self.rotate_counter,
): self.rotate_clockwise,
getattr(
arcade.key, self.conf["KEYBOARD"]["rotate counter"]
): self.rotate_counter,
getattr(arcade.key, self.conf["KEYBOARD"]["hold"]): self.swap, getattr(arcade.key, self.conf["KEYBOARD"]["hold"]): self.swap,
getattr(arcade.key, self.conf["KEYBOARD"]["pause"]): self.pause, getattr(arcade.key, self.conf["KEYBOARD"]["pause"]): self.pause,
getattr( getattr(arcade.key, self.conf["KEYBOARD"]["fullscreen"]): self.toggle_fullscreen,
arcade.key, self.conf["KEYBOARD"]["fullscreen"]
): self.toggle_fullscreen,
}, },
tetrislogic.State.PAUSED: { State.PAUSED: {
getattr(arcade.key, self.conf["KEYBOARD"]["pause"]): self.resume, getattr(arcade.key, self.conf["KEYBOARD"]["pause"]): self.resume,
getattr( getattr(arcade.key, self.conf["KEYBOARD"]["fullscreen"]): self.toggle_fullscreen,
arcade.key, self.conf["KEYBOARD"]["fullscreen"]
): self.toggle_fullscreen,
}, },
tetrislogic.State.OVER: { State.OVER: {
getattr(arcade.key, self.conf["KEYBOARD"]["start"]): self.new_game, getattr(arcade.key, self.conf["KEYBOARD"]["start"]): self.new_game,
getattr( getattr(arcade.key, self.conf["KEYBOARD"]["fullscreen"]): self.toggle_fullscreen,
arcade.key, self.conf["KEYBOARD"]["fullscreen"]
): self.toggle_fullscreen,
}, },
} }
@ -259,21 +236,12 @@ class TetrArcade(tetrislogic.TetrisLogic, arcade.Window):
"\n\n\nCONTROLS\n\n" "\n\n\nCONTROLS\n\n"
+ "\n".join( + "\n".join(
"{:<16s}{:>6s}".format(key, action) "{:<16s}{:>6s}".format(key, action)
for key, action in tuple(self.conf["KEYBOARD"].items()) for key, action in tuple(self.conf["KEYBOARD"].items()) + (("QUIT", "ALT+F4"),)
+ (("QUIT", "ALT+F4"),)
) )
+ "\n\n\n" + "\n\n\n"
) )
self.start_text = ( self.start_text = "TETRARCADE" + controls_text + "PRESS [{}] TO START".format(self.conf["KEYBOARD"]["start"])
"TETRARCADE" self.pause_text = "PAUSE" + controls_text + "PRESS [{}] TO RESUME".format(self.conf["KEYBOARD"]["pause"])
+ controls_text
+ "PRESS [{}] TO START".format(self.conf["KEYBOARD"]["start"])
)
self.pause_text = (
"PAUSE"
+ controls_text
+ "PRESS [{}] TO RESUME".format(self.conf["KEYBOARD"]["pause"])
)
self.game_over_text = """GAME self.game_over_text = """GAME
OVER OVER
@ -358,7 +326,7 @@ AGAIN""".format(
arcade.start_render() arcade.start_render()
self.bg.draw() self.bg.draw()
if self.state in (tetrislogic.State.PLAYING, tetrislogic.State.OVER): if self.state in (State.PLAYING, State.OVER):
self.matrix_bg.draw() self.matrix_bg.draw()
self.held_bg.draw() self.held_bg.draw()
self.next_bg.draw() self.next_bg.draw()
@ -370,13 +338,10 @@ AGAIN""".format(
t = time.localtime(self.time) t = time.localtime(self.time)
font_size = STATS_TEXT_SIZE * self.scale font_size = STATS_TEXT_SIZE * self.scale
for y, text in enumerate( for y, text in enumerate(("TIME", "LINES", "GOAL", "LEVEL", "HIGH SCORE", "SCORE")):
("TIME", "LINES", "GOAL", "LEVEL", "HIGH SCORE", "SCORE")
):
arcade.draw_text( arcade.draw_text(
text=text, text=text,
start_x=self.matrix_bg.left start_x=self.matrix_bg.left - self.scale * (STATS_TEXT_MARGIN + STATS_TEXT_WIDTH),
- self.scale * (STATS_TEXT_MARGIN + STATS_TEXT_WIDTH),
start_y=self.matrix_bg.bottom + 1.5 * (2 * y + 1) * font_size, start_y=self.matrix_bg.bottom + 1.5 * (2 * y + 1) * font_size,
color=TEXT_COLOR, color=TEXT_COLOR,
font_size=font_size, font_size=font_size,
@ -406,12 +371,10 @@ AGAIN""".format(
) )
highlight_text = { highlight_text = {
tetrislogic.State.STARTING: self.start_text, State.STARTING: self.start_text,
tetrislogic.State.PLAYING: self.highlight_texts[0] State.PLAYING: self.highlight_texts[0] if self.highlight_texts else "",
if self.highlight_texts State.PAUSED: self.pause_text,
else "", State.OVER: self.game_over_text,
tetrislogic.State.PAUSED: self.pause_text,
tetrislogic.State.OVER: self.game_over_text,
}.get(self.state, "") }.get(self.state, "")
if highlight_text: if highlight_text:
arcade.draw_text( arcade.draw_text(

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 151 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 167 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 B

BIN
res/minoes.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 143 B

View File

@ -14,17 +14,13 @@ setup(
version="0.1", version="0.1",
description="Tetris clone", description="Tetris clone",
author="adrienmalin", author="adrienmalin",
executables=[Executable( executables=[Executable(script="TetrArcade.py", icon=icon, base=base)],
script="TetrArcade.py",
icon=icon,
base=base
)],
options={ options={
"build_exe": { "build_exe": {
"packages": ["arcade", "pyglet"], "packages": ["arcade", "pyglet"],
"excludes": ["tkinter", "PyQt4", "PyQt5", "PySide", "PySide2"], "excludes": ["tkinter", "PyQt4", "PyQt5", "PySide", "PySide2"],
"include_files": "res", "include_files": "res",
"silent": True "silent": True,
} }
}, },
) )

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from TetrArcade import TetrArcade, tetrislogic from TetrArcade import TetrArcade, State
game = TetrArcade() game = TetrArcade()
game.new_game() game.new_game()
@ -11,5 +11,5 @@ game.rotate_counter()
for i in range(12): for i in range(12):
game.soft_drop() game.soft_drop()
game.on_draw() game.on_draw()
while game.state != tetrislogic.State.OVER: while game.state != State.OVER:
game.hard_drop() game.hard_drop()

View File

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from .consts import NB_LINES, NB_COLS, NB_NEXT from .consts import NB_LINES, NB_COLS, NB_NEXT
from .utils import Movement, Rotation from .utils import Movement, Rotation, Color
from .tetromino import Mino, Tetromino from .tetromino import Mino, Tetromino
from .tetrislogic import TetrisLogic, State, Matrix from .tetrislogic import TetrisLogic, State, Matrix

View File

@ -2,7 +2,7 @@
import random import random
import pickle import pickle
from .utils import Coord, Movement, Rotation, T_Spin, Line from .utils import Coord, Movement, Rotation, T_Spin
from .tetromino import Tetromino, T, I from .tetromino import Tetromino, T, I
from .consts import ( from .consts import (
NB_LINES, NB_LINES,
@ -102,7 +102,7 @@ class TetrisLogic:
return self.random_bag.pop()() return self.random_bag.pop()()
def append_new_line_to_matrix(self): def append_new_line_to_matrix(self):
self.matrix.append(Line(None for x in range(self.NB_COLS))) self.matrix.append([None for x in range(self.NB_COLS)])
def new_level(self): def new_level(self):
self.level += 1 self.level += 1
@ -145,9 +145,7 @@ class TetrisLogic:
self.ghost.coord = self.current.coord self.ghost.coord = self.current.coord
for ghost_mino, current_mino in zip(self.ghost, self.current): for ghost_mino, current_mino in zip(self.ghost, self.current):
ghost_mino.coord = current_mino.coord ghost_mino.coord = current_mino.coord
while self.can_move( while self.can_move(self.ghost.coord + Movement.DOWN, (mino.coord for mino in self.ghost)):
self.ghost.coord + Movement.DOWN, (mino.coord for mino in self.ghost)
):
self.ghost.coord += Movement.DOWN self.ghost.coord += Movement.DOWN
def soft_drop(self): def soft_drop(self):
@ -181,13 +179,8 @@ class TetrisLogic:
return False return False
def rotate(self, rotation): def rotate(self, rotation):
rotated_coords = tuple( rotated_coords = tuple(Coord(rotation * mino.coord.y, -rotation * mino.coord.x) for mino in self.current)
Coord(rotation * mino.coord.y, -rotation * mino.coord.x) for rotation_point, liberty_degree in enumerate(self.current.SRS[rotation][self.current.orientation], start=1):
for mino in self.current
)
for rotation_point, liberty_degree in enumerate(
self.current.SRS[rotation][self.current.orientation], start=1
):
potential_coord = self.current.coord + liberty_degree potential_coord = self.current.coord + liberty_degree
if self.can_move(potential_coord, rotated_coords): if self.can_move(potential_coord, rotated_coords):
if self.current.prelocked: if self.current.prelocked:
@ -215,16 +208,11 @@ class TetrisLogic:
self.stop(self.lock) self.stop(self.lock)
# Piece unlocked # Piece unlocked
if self.can_move( if self.can_move(self.current.coord + Movement.DOWN, (mino.coord for mino in self.current)):
self.current.coord + Movement.DOWN, (mino.coord for mino in self.current)
):
return return
# Game over # Game over
if all( if all((mino.coord + self.current.coord).y >= self.NB_LINES for mino in self.current):
(mino.coord + self.current.coord).y >= self.NB_LINES
for mino in self.current
):
self.game_over() self.game_over()
return return
@ -296,17 +284,12 @@ class TetrisLogic:
self.new_current() self.new_current()
def can_move(self, potential_coord, minoes_coords): def can_move(self, potential_coord, minoes_coords):
return all( return all(self.matrix.cell_is_free(potential_coord + mino_coord) for mino_coord in minoes_coords)
self.matrix.cell_is_free(potential_coord + mino_coord)
for mino_coord in minoes_coords
)
T_SLOT_COORDS = (Coord(-1, 1), Coord(1, 1), Coord(-1, 1), Coord(-1, -1)) T_SLOT_COORDS = (Coord(-1, 1), Coord(1, 1), Coord(-1, 1), Coord(-1, -1))
def is_t_slot(self, n): def is_t_slot(self, n):
t_slot_coord = ( t_slot_coord = self.current.coord + self.T_SLOT_COORDS[(self.current.orientation + n) % 4]
self.current.coord + self.T_SLOT_COORDS[(self.current.orientation + n) % 4]
)
return not self.matrix.cell_is_free(t_slot_coord) return not self.matrix.cell_is_free(t_slot_coord)
def swap(self): def swap(self):

View File

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from .utils import Coord, Rotation from .utils import Coord, Rotation, Color
class Mino: class Mino:
@ -51,7 +51,7 @@ class O(Tetromino, metaclass=MetaTetromino):
Rotation.COUNTER: (tuple(), tuple(), tuple(), tuple()), Rotation.COUNTER: (tuple(), tuple(), tuple(), tuple()),
} }
MINOES_COORDS = (Coord(0, 0), Coord(1, 0), Coord(0, 1), Coord(1, 1)) MINOES_COORDS = (Coord(0, 0), Coord(1, 0), Coord(0, 1), Coord(1, 1))
MINOES_COLOR = "yellow" MINOES_COLOR = Color.YELLOW
def rotate(self, direction): def rotate(self, direction):
return False return False
@ -74,34 +74,34 @@ class I(Tetromino, metaclass=MetaTetromino):
), ),
} }
MINOES_COORDS = (Coord(-1, 0), Coord(0, 0), Coord(1, 0), Coord(2, 0)) MINOES_COORDS = (Coord(-1, 0), Coord(0, 0), Coord(1, 0), Coord(2, 0))
MINOES_COLOR = "cyan" MINOES_COLOR = Color.CYAN
class T(Tetromino, metaclass=MetaTetromino): class T(Tetromino, metaclass=MetaTetromino):
MINOES_COORDS = (Coord(-1, 0), Coord(0, 0), Coord(0, 1), Coord(1, 0)) MINOES_COORDS = (Coord(-1, 0), Coord(0, 0), Coord(0, 1), Coord(1, 0))
MINOES_COLOR = "magenta" MINOES_COLOR = Color.MAGENTA
class L(Tetromino, metaclass=MetaTetromino): class L(Tetromino, metaclass=MetaTetromino):
MINOES_COORDS = (Coord(-1, 0), Coord(0, 0), Coord(1, 0), Coord(1, 1)) MINOES_COORDS = (Coord(-1, 0), Coord(0, 0), Coord(1, 0), Coord(1, 1))
MINOES_COLOR = "orange" MINOES_COLOR = Color.ORANGE
class J(Tetromino, metaclass=MetaTetromino): class J(Tetromino, metaclass=MetaTetromino):
MINOES_COORDS = (Coord(-1, 1), Coord(-1, 0), Coord(0, 0), Coord(1, 0)) MINOES_COORDS = (Coord(-1, 1), Coord(-1, 0), Coord(0, 0), Coord(1, 0))
MINOES_COLOR = "blue" MINOES_COLOR = Color.BLUE
class S(Tetromino, metaclass=MetaTetromino): class S(Tetromino, metaclass=MetaTetromino):
MINOES_COORDS = (Coord(-1, 0), Coord(0, 0), Coord(0, 1), Coord(1, 1)) MINOES_COORDS = (Coord(-1, 0), Coord(0, 0), Coord(0, 1), Coord(1, 1))
MINOES_COLOR = "green" MINOES_COLOR = Color.GREEN
class Z(Tetromino, metaclass=MetaTetromino): class Z(Tetromino, metaclass=MetaTetromino):
MINOES_COORDS = (Coord(-1, 1), Coord(0, 1), Coord(0, 0), Coord(1, 0)) MINOES_COORDS = (Coord(-1, 1), Coord(0, 1), Coord(0, 0), Coord(1, 0))
MINOES_COLOR = "red" MINOES_COLOR = Color.RED

View File

@ -28,5 +28,12 @@ class T_Spin:
T_SPIN = "T-SPIN" T_SPIN = "T-SPIN"
class Line(list): class Color:
pass
BLUE = 0
CYAN = 1
GREEN = 2
MAGENTA = 3
ORANGE = 4
RED = 5
YELLOW = 6