Compare commits
11
Commits
0.2
..
f013a061b2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f013a061b2 | ||
|
|
f025ad5fd8 | ||
|
|
9a7aead918 | ||
|
|
b173b6ff73 | ||
|
|
ddf7ea0f4e | ||
|
|
d308618556 | ||
|
|
9c77096bfb | ||
|
|
093264c351 | ||
|
|
5b3e6ec931 | ||
|
|
0970e1f6df | ||
|
|
f48f1fc000 |
No files matched your search
+112
-77
@@ -1,26 +1,42 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import sys
|
import sys
|
||||||
import locale
|
|
||||||
import time
|
|
||||||
import os
|
|
||||||
|
|
||||||
import configparser
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import arcade
|
import arcade
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
sys.exit(
|
sys.exit(
|
||||||
str(e)
|
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 pyglet
|
||||||
|
|
||||||
from tetrislogic import TetrisLogic, Color, State
|
import locale
|
||||||
|
import time
|
||||||
|
import os
|
||||||
|
import itertools
|
||||||
|
import configparser
|
||||||
|
|
||||||
|
from tetrislogic import TetrisLogic, Color, State, Coord
|
||||||
|
|
||||||
|
|
||||||
# Constants
|
# Constants
|
||||||
|
# Matrix
|
||||||
|
NB_LINES = 20
|
||||||
|
NB_COLS = 10
|
||||||
|
NB_NEXT = 5
|
||||||
|
|
||||||
|
# Delays (seconds)
|
||||||
|
LOCK_DELAY = 0.5
|
||||||
|
FALL_DELAY = 1
|
||||||
|
AUTOREPEAT_DELAY = 0.300
|
||||||
|
AUTOREPEAT_PERIOD = 0.010
|
||||||
|
|
||||||
|
# Piece init coord
|
||||||
|
MATRIX_PIECE_COORD = Coord(4, NB_LINES)
|
||||||
|
NEXT_PIECE_COORDS = [Coord(NB_COLS + 4, NB_LINES - 4 * n - 3) for n in range(NB_NEXT)]
|
||||||
|
HELD_PIECE_COORD = Coord(-5, NB_LINES - 3)
|
||||||
|
|
||||||
# Window
|
# Window
|
||||||
WINDOW_WIDTH = 800
|
WINDOW_WIDTH = 800
|
||||||
WINDOW_HEIGHT = 600
|
WINDOW_HEIGHT = 600
|
||||||
@@ -45,19 +61,19 @@ MINO_SPRITE_SIZE = 21
|
|||||||
|
|
||||||
if getattr(sys, 'frozen', False):
|
if getattr(sys, 'frozen', False):
|
||||||
# The application is frozen
|
# The application is frozen
|
||||||
DATA_DIR = os.path.dirname(sys.executable)
|
PROGRAM_DIR = os.path.dirname(sys.executable)
|
||||||
else:
|
else:
|
||||||
# The application is not frozen
|
# The application is not frozen
|
||||||
# Change this bit to match where you store your data files:
|
PROGRAM_DIR = os.path.dirname(__file__)
|
||||||
DATA_DIR = os.path.dirname(__file__)
|
RESOURCES_DIR = os.path.join(PROGRAM_DIR, "resources")
|
||||||
DATA_DIR = os.path.join(DATA_DIR, "res")
|
|
||||||
|
|
||||||
# Sprites
|
# Sprites
|
||||||
WINDOW_BG_PATH = os.path.join(DATA_DIR, "bg.jpg")
|
IMAGES_DIR = os.path.join(RESOURCES_DIR, "images")
|
||||||
MATRIX_BG_PATH = os.path.join(DATA_DIR, "matrix.png")
|
WINDOW_BG_PATH = os.path.join(IMAGES_DIR, "bg.jpg")
|
||||||
HELD_BG_PATH = os.path.join(DATA_DIR, "held.png")
|
MATRIX_BG_PATH = os.path.join(IMAGES_DIR, "matrix.png")
|
||||||
NEXT_BG_PATH = os.path.join(DATA_DIR, "next.png")
|
HELD_BG_PATH = os.path.join(IMAGES_DIR, "held.png")
|
||||||
MINOES_SPRITES_PATH = os.path.join(DATA_DIR, "minoes.png")
|
NEXT_BG_PATH = os.path.join(IMAGES_DIR, "next.png")
|
||||||
|
MINOES_SPRITES_PATH = os.path.join(IMAGES_DIR, "minoes.png")
|
||||||
Color.PRELOCKED = 7
|
Color.PRELOCKED = 7
|
||||||
MINOES_COLOR_ID = {
|
MINOES_COLOR_ID = {
|
||||||
Color.BLUE: 0,
|
Color.BLUE: 0,
|
||||||
@@ -74,6 +90,19 @@ TEXTURES = arcade.load_textures(
|
|||||||
)
|
)
|
||||||
TEXTURES = {color: TEXTURES[i] for color, i in MINOES_COLOR_ID.items()}
|
TEXTURES = {color: TEXTURES[i] for color, i in MINOES_COLOR_ID.items()}
|
||||||
|
|
||||||
|
# Music
|
||||||
|
MUSIC_DIR = os.path.join(RESOURCES_DIR, "musics")
|
||||||
|
MUSICS_PATHS = (entry.path for entry in os.scandir(MUSIC_DIR))
|
||||||
|
|
||||||
|
# Text
|
||||||
|
TEXT_COLOR = arcade.color.BUBBLES
|
||||||
|
FONT_NAME = os.path.join(RESOURCES_DIR, "fonts/joystix monospace.ttf")
|
||||||
|
STATS_TEXT_MARGIN = 40
|
||||||
|
STATS_TEXT_SIZE = 14
|
||||||
|
STATS_TEXT_WIDTH = 150
|
||||||
|
HIGHLIGHT_TEXT_COLOR = arcade.color.BUBBLES
|
||||||
|
HIGHLIGHT_TEXT_SIZE = 20
|
||||||
|
|
||||||
# User profile path
|
# User profile path
|
||||||
if sys.platform == "win32":
|
if sys.platform == "win32":
|
||||||
USER_PROFILE_DIR = os.environ.get("appdata", os.path.expanduser("~\Appdata\Roaming"))
|
USER_PROFILE_DIR = os.environ.get("appdata", os.path.expanduser("~\Appdata\Roaming"))
|
||||||
@@ -83,20 +112,9 @@ 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")
|
||||||
|
|
||||||
# Text
|
|
||||||
TEXT_COLOR = arcade.color.BUBBLES
|
|
||||||
FONT_NAME = os.path.join(DATA_DIR, "joystix monospace.ttf")
|
|
||||||
STATS_TEXT_MARGIN = 40
|
|
||||||
STATS_TEXT_SIZE = 14
|
|
||||||
STATS_TEXT_WIDTH = 150
|
|
||||||
HIGHLIGHT_TEXT_COLOR = arcade.color.BUBBLES
|
|
||||||
HIGHLIGHT_TEXT_SIZE = 20
|
|
||||||
|
|
||||||
# Music
|
|
||||||
MUSIC_PATH = os.path.join(DATA_DIR, "Tetris - Song A.mp3")
|
|
||||||
|
|
||||||
|
|
||||||
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.alpha = alpha
|
self.alpha = alpha
|
||||||
@@ -114,6 +132,7 @@ class MinoSprite(arcade.Sprite):
|
|||||||
|
|
||||||
|
|
||||||
class MinoesSprites(arcade.SpriteList):
|
class MinoesSprites(arcade.SpriteList):
|
||||||
|
|
||||||
def resize(self, scale):
|
def resize(self, scale):
|
||||||
for sprite in self:
|
for sprite in self:
|
||||||
sprite.scale = scale
|
sprite.scale = scale
|
||||||
@@ -121,6 +140,7 @@ 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.tetromino = tetromino
|
self.tetromino = tetromino
|
||||||
@@ -136,6 +156,7 @@ class TetrominoSprites(MinoesSprites):
|
|||||||
|
|
||||||
|
|
||||||
class MatrixSprites(MinoesSprites):
|
class MatrixSprites(MinoesSprites):
|
||||||
|
|
||||||
def __init__(self, matrix):
|
def __init__(self, matrix):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.matrix = matrix
|
self.matrix = matrix
|
||||||
@@ -146,10 +167,15 @@ class MatrixSprites(MinoesSprites):
|
|||||||
for x, mino in enumerate(line):
|
for x, mino in enumerate(line):
|
||||||
if mino:
|
if mino:
|
||||||
mino.sprite.refresh(x, y)
|
mino.sprite.refresh(x, y)
|
||||||
self.append(mino.sprite)
|
|
||||||
|
def remove_line(self, y):
|
||||||
|
for mino in self.matrix[y]:
|
||||||
|
if mino:
|
||||||
|
self.remove(mino.sprite)
|
||||||
|
|
||||||
|
|
||||||
class TetrArcade(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 = []
|
||||||
@@ -166,7 +192,7 @@ class TetrArcade(TetrisLogic, arcade.Window):
|
|||||||
self.new_conf()
|
self.new_conf()
|
||||||
self.load_conf()
|
self.load_conf()
|
||||||
|
|
||||||
super().__init__()
|
super().__init__(NB_LINES, NB_COLS, NB_NEXT)
|
||||||
arcade.Window.__init__(
|
arcade.Window.__init__(
|
||||||
self,
|
self,
|
||||||
width=self.init_width,
|
width=self.init_width,
|
||||||
@@ -188,9 +214,18 @@ class TetrArcade(TetrisLogic, arcade.Window):
|
|||||||
self.next.bg.alpha = BAR_ALPHA
|
self.next.bg.alpha = BAR_ALPHA
|
||||||
self.matrix.sprites = MatrixSprites(self.matrix)
|
self.matrix.sprites = MatrixSprites(self.matrix)
|
||||||
self.on_resize(self.init_width, self.init_height)
|
self.on_resize(self.init_width, self.init_height)
|
||||||
|
|
||||||
if self.play_music:
|
if self.play_music:
|
||||||
self.music = arcade.Sound(MUSIC_PATH)
|
try:
|
||||||
self.music_player = None
|
self.music = pyglet.media.Player()
|
||||||
|
playlist = itertools.cycle(
|
||||||
|
pyglet.media.load(path)
|
||||||
|
for path in MUSICS_PATHS
|
||||||
|
)
|
||||||
|
self.music.queue(playlist)
|
||||||
|
except:
|
||||||
|
Warning("Can't play music.")
|
||||||
|
self.play_music = False
|
||||||
|
|
||||||
def new_conf(self):
|
def new_conf(self):
|
||||||
self.conf["WINDOW"] = {"width": WINDOW_WIDTH, "height": WINDOW_HEIGHT, "fullscreen": False}
|
self.conf["WINDOW"] = {"width": WINDOW_WIDTH, "height": WINDOW_HEIGHT, "fullscreen": False}
|
||||||
@@ -274,42 +309,47 @@ AGAIN""".format(
|
|||||||
|
|
||||||
self.play_music = self.conf["MUSIC"].getboolean("play")
|
self.play_music = self.conf["MUSIC"].getboolean("play")
|
||||||
|
|
||||||
def new_game(self):
|
def on_new_game(self):
|
||||||
self.highlight_texts = []
|
self.highlight_texts = []
|
||||||
super().new_game()
|
|
||||||
if self.play_music:
|
|
||||||
if self.music_player:
|
|
||||||
self.music_player.seek(0)
|
|
||||||
self.music_player.play()
|
|
||||||
else:
|
|
||||||
self.music_player = self.music.player.play()
|
|
||||||
self.music_player.loop = True
|
|
||||||
|
|
||||||
def new_tetromino(self):
|
|
||||||
tetromino = super().new_tetromino()
|
|
||||||
tetromino.sprites = TetrominoSprites(tetromino, self)
|
|
||||||
return tetromino
|
|
||||||
|
|
||||||
def new_matrix_piece(self):
|
|
||||||
self.matrix.sprites = MatrixSprites(self.matrix)
|
self.matrix.sprites = MatrixSprites(self.matrix)
|
||||||
super().new_matrix_piece()
|
if self.play_music:
|
||||||
|
self.music.seek(0)
|
||||||
|
self.music.play()
|
||||||
|
|
||||||
|
def on_new_piece(self, piece):
|
||||||
|
piece.sprites = TetrominoSprites(piece, self)
|
||||||
|
|
||||||
|
def on_new_level(self, level):
|
||||||
|
self.show_text("LEVEL\n{:n}".format(level))
|
||||||
|
|
||||||
|
def on_generation_phase(self, piece):
|
||||||
|
self.matrix.sprites.refresh()
|
||||||
self.matrix.ghost.sprites = TetrominoSprites(self.matrix.ghost, self, GHOST_ALPHA)
|
self.matrix.ghost.sprites = TetrominoSprites(self.matrix.ghost, self, GHOST_ALPHA)
|
||||||
for tetromino in [self.matrix.piece, self.matrix.ghost] + self.next.pieces:
|
for tetromino in [self.matrix.piece, self.matrix.ghost] + self.next.pieces:
|
||||||
tetromino.sprites.refresh()
|
tetromino.sprites.refresh()
|
||||||
|
|
||||||
def move(self, movement, prelock=True):
|
def on_falling_phase(self):
|
||||||
moved = super().move(movement, prelock)
|
|
||||||
self.matrix.piece.sprites.refresh()
|
self.matrix.piece.sprites.refresh()
|
||||||
if moved:
|
|
||||||
self.matrix.ghost.sprites.refresh()
|
|
||||||
return moved
|
|
||||||
|
|
||||||
def rotate(self, rotation):
|
def on_moved(self, moved):
|
||||||
rotated = super().rotate(rotation)
|
self.matrix.piece.sprites.refresh()
|
||||||
if rotated:
|
self.matrix.ghost.sprites.refresh()
|
||||||
for tetromino in (self.matrix.piece, self.matrix.ghost):
|
|
||||||
tetromino.sprites.refresh()
|
def on_rotated(self, direction):
|
||||||
return rotated
|
for tetromino in (self.matrix.piece, self.matrix.ghost):
|
||||||
|
tetromino.sprites.refresh()
|
||||||
|
|
||||||
|
def on_lock_phase(self):
|
||||||
|
self.matrix.piece.sprites.refresh()
|
||||||
|
self.matrix.sprites.refresh()
|
||||||
|
|
||||||
|
def on_locked(self, piece):
|
||||||
|
piece.sprites.refresh()
|
||||||
|
for mino in piece:
|
||||||
|
self.matrix.sprites.append(mino.sprite)
|
||||||
|
|
||||||
|
def on_line_remove(self, y):
|
||||||
|
self.matrix.sprites.remove_line(y)
|
||||||
|
|
||||||
def swap(self):
|
def swap(self):
|
||||||
super().swap()
|
super().swap()
|
||||||
@@ -318,25 +358,20 @@ AGAIN""".format(
|
|||||||
if tetromino:
|
if tetromino:
|
||||||
tetromino.sprites.refresh()
|
tetromino.sprites.refresh()
|
||||||
|
|
||||||
def lock(self):
|
|
||||||
self.matrix.piece.prelocked = False
|
|
||||||
self.matrix.piece.sprites.refresh()
|
|
||||||
super().lock()
|
|
||||||
|
|
||||||
def pause(self):
|
def pause(self):
|
||||||
super().pause()
|
super().pause()
|
||||||
if self.play_music:
|
if self.play_music:
|
||||||
self.music_player.pause()
|
self.music.pause()
|
||||||
|
|
||||||
def resume(self):
|
def resume(self):
|
||||||
super().resume()
|
super().resume()
|
||||||
if self.play_music:
|
if self.play_music:
|
||||||
self.music_player.play()
|
self.music.play()
|
||||||
|
|
||||||
def game_over(self):
|
def game_over(self):
|
||||||
super().game_over()
|
super().game_over()
|
||||||
if self.play_music:
|
if self.play_music:
|
||||||
self.music_player.pause()
|
self.music.pause()
|
||||||
|
|
||||||
def on_key_press(self, key, modifiers):
|
def on_key_press(self, key, modifiers):
|
||||||
for key_or_modifier in (key, modifiers):
|
for key_or_modifier in (key, modifiers):
|
||||||
@@ -380,7 +415,7 @@ AGAIN""".format(
|
|||||||
if tetromino:
|
if tetromino:
|
||||||
tetromino.sprites.draw()
|
tetromino.sprites.draw()
|
||||||
|
|
||||||
t = time.localtime(self.time)
|
t = time.localtime(self.stats.time)
|
||||||
font_size = STATS_TEXT_SIZE * self.scale
|
font_size = STATS_TEXT_SIZE * self.scale
|
||||||
for y, text in enumerate(("TIME", "LINES", "GOAL", "LEVEL", "HIGH SCORE", "SCORE")):
|
for y, text in enumerate(("TIME", "LINES", "GOAL", "LEVEL", "HIGH SCORE", "SCORE")):
|
||||||
arcade.draw_text(
|
arcade.draw_text(
|
||||||
@@ -396,11 +431,11 @@ AGAIN""".format(
|
|||||||
for y, text in enumerate(
|
for y, text in enumerate(
|
||||||
(
|
(
|
||||||
"{:02d}:{:02d}:{:02d}".format(t.tm_hour - 1, t.tm_min, t.tm_sec),
|
"{:02d}:{:02d}:{:02d}".format(t.tm_hour - 1, t.tm_min, t.tm_sec),
|
||||||
"{:n}".format(self.nb_lines_cleared),
|
"{:n}".format(self.stats.lines_cleared),
|
||||||
"{:n}".format(self.goal),
|
"{:n}".format(self.stats.goal),
|
||||||
"{:n}".format(self.level),
|
"{:n}".format(self.stats.level),
|
||||||
"{:n}".format(self.high_score),
|
"{:n}".format(self.stats.high_score),
|
||||||
"{:n}".format(self.score),
|
"{:n}".format(self.stats.score),
|
||||||
)
|
)
|
||||||
):
|
):
|
||||||
arcade.draw_text(
|
arcade.draw_text(
|
||||||
@@ -521,7 +556,7 @@ High score could not be saved:
|
|||||||
def on_close(self):
|
def on_close(self):
|
||||||
self.save_high_score()
|
self.save_high_score()
|
||||||
if self.play_music:
|
if self.play_music:
|
||||||
self.music_player.pause()
|
self.music.pause()
|
||||||
super().on_close()
|
super().on_close()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -29,13 +29,13 @@ options = {
|
|||||||
"build_exe": {
|
"build_exe": {
|
||||||
"packages": ["arcade", "pyglet"],
|
"packages": ["arcade", "pyglet"],
|
||||||
"excludes": excludes,
|
"excludes": excludes,
|
||||||
"include_files": "res",
|
"include_files": "resources",
|
||||||
"silent": True
|
"silent": True
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setup(
|
setup(
|
||||||
name = "TetrArcade",
|
name = "TetrArcade",
|
||||||
version = "0.2",
|
version = "0.3",
|
||||||
description = "Tetris clone",
|
description = "Tetris clone",
|
||||||
author = "AdrienMalin",
|
author = "AdrienMalin",
|
||||||
executables = [executable],
|
executables = [executable],
|
||||||
|
|||||||
@@ -1,16 +1,25 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from TetrArcade import TetrArcade, State
|
from TetrArcade import TetrArcade, State, MinoSprite
|
||||||
|
from tetrislogic import Mino, Color, Coord
|
||||||
|
|
||||||
game = TetrArcade()
|
game = TetrArcade()
|
||||||
game.new_game()
|
game.new_game()
|
||||||
|
for x in range(game.matrix.collumns):
|
||||||
|
mino = Mino(Color.ORANGE, Coord(x, 0))
|
||||||
|
mino.sprite = MinoSprite(mino, game, 200)
|
||||||
|
game.matrix[0][x] = mino
|
||||||
|
game.matrix.sprites.append(mino.sprite)
|
||||||
game.move_left()
|
game.move_left()
|
||||||
|
game.pause()
|
||||||
|
game.resume()
|
||||||
game.move_right()
|
game.move_right()
|
||||||
game.swap()
|
game.swap()
|
||||||
game.rotate_clockwise()
|
game.rotate_clockwise()
|
||||||
game.rotate_counter()
|
game.rotate_counter()
|
||||||
for i in range(12):
|
for i in range(12):
|
||||||
game.soft_drop()
|
game.soft_drop()
|
||||||
|
game.matrix.sprites.refresh()
|
||||||
game.on_draw()
|
game.on_draw()
|
||||||
while game.state != State.OVER:
|
while game.state != State.OVER:
|
||||||
game.hard_drop()
|
game.hard_drop()
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from .consts import NB_LINES, NB_COLS, NB_NEXT
|
from .consts import LINES, COLLUMNS, NEXT_PIECES
|
||||||
from .utils import Movement, Rotation, Color
|
from .utils import Movement, Rotation, Color, Coord
|
||||||
from .tetromino import Mino, Tetromino
|
from .tetromino import Mino, Tetromino
|
||||||
from .tetrislogic import TetrisLogic, State, Matrix
|
from .tetrislogic import TetrisLogic, State, Matrix
|
||||||
@@ -3,18 +3,17 @@ from .utils import Coord
|
|||||||
|
|
||||||
|
|
||||||
# Matrix
|
# Matrix
|
||||||
NB_LINES = 20
|
LINES = 20
|
||||||
NB_COLS = 10
|
COLLUMNS = 10
|
||||||
NB_NEXT = 5
|
NEXT_PIECES = 5
|
||||||
|
|
||||||
# Delays (seconds)
|
# Delays (seconds)
|
||||||
LOCK_DELAY = 0.5
|
LOCK_DELAY = 0.5
|
||||||
FALL_DELAY = 1
|
FALL_DELAY = 1
|
||||||
AUTOREPEAT_DELAY = 0.200 # Official : 0.300
|
AUTOREPEAT_DELAY = 0.300 # Official : 0.300 s
|
||||||
AUTOREPEAT_PERIOD = 0.010 # Official : 0.010
|
AUTOREPEAT_PERIOD = 0.010 # Official : 0.010 s
|
||||||
|
|
||||||
|
|
||||||
# Piece init coord
|
# Piece init coord
|
||||||
CURRENT_COORD = Coord(4, NB_LINES)
|
MATRIX_PIECE_COORD = Coord(4, LINES)
|
||||||
NEXT_COORDS = [Coord(NB_COLS + 4, NB_LINES - 4 * n - 3) for n in range(NB_NEXT)]
|
NEXT_PIECE_COORDS = [Coord(COLLUMNS + 4, LINES - 4 * n - 3) for n in range(NEXT_PIECES)]
|
||||||
HELD_COORD = Coord(-5, NB_LINES - 3)
|
HELD_PIECE_COORD = Coord(-5, LINES - 3)
|
||||||
+191
-120
@@ -5,16 +5,16 @@ import pickle
|
|||||||
from .utils import Coord, Movement, Rotation, T_Spin
|
from .utils import Coord, Movement, Rotation, T_Spin
|
||||||
from .tetromino import Tetromino, T_Tetrimino, I_Tetrimino
|
from .tetromino import Tetromino, T_Tetrimino, I_Tetrimino
|
||||||
from .consts import (
|
from .consts import (
|
||||||
NB_LINES,
|
LINES,
|
||||||
NB_COLS,
|
COLLUMNS,
|
||||||
NB_NEXT,
|
NEXT_PIECES,
|
||||||
LOCK_DELAY,
|
LOCK_DELAY,
|
||||||
FALL_DELAY,
|
FALL_DELAY,
|
||||||
AUTOREPEAT_DELAY,
|
AUTOREPEAT_DELAY,
|
||||||
AUTOREPEAT_PERIOD,
|
AUTOREPEAT_PERIOD,
|
||||||
CURRENT_COORD,
|
MATRIX_PIECE_COORD,
|
||||||
NEXT_COORDS,
|
NEXT_PIECE_COORDS,
|
||||||
HELD_COORD,
|
HELD_PIECE_COORD,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -42,88 +42,58 @@ class HoldQueue(PieceContainer):
|
|||||||
|
|
||||||
class Matrix(list, PieceContainer):
|
class Matrix(list, PieceContainer):
|
||||||
|
|
||||||
def __init__(self, *args, **kargs):
|
def __init__(self, lines, collumns):
|
||||||
list.__init__(self, *args, **kargs)
|
list.__init__(self)
|
||||||
PieceContainer.__init__(self)
|
PieceContainer.__init__(self)
|
||||||
|
self.lines = lines
|
||||||
|
self.collumns = collumns
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
self.clear()
|
||||||
|
for y in range(self.lines + 3):
|
||||||
|
self.append_new_line()
|
||||||
|
|
||||||
|
def append_new_line(self):
|
||||||
|
self.append([None for x in range(self.collumns)])
|
||||||
|
|
||||||
def cell_is_free(self, coord):
|
def cell_is_free(self, coord):
|
||||||
return 0 <= coord.x < NB_COLS and 0 <= coord.y and not self[coord.y][coord.x]
|
return 0 <= coord.x < self.collumns and 0 <= coord.y and not self[coord.y][coord.x]
|
||||||
|
|
||||||
|
|
||||||
class NextQueue(PieceContainer):
|
class NextQueue(PieceContainer):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, nb_pieces):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
self.nb_pieces = nb_pieces
|
||||||
self.pieces = []
|
self.pieces = []
|
||||||
|
|
||||||
|
|
||||||
class TetrisLogic:
|
class Stats:
|
||||||
|
|
||||||
NB_LINES = NB_LINES
|
def _get_score(self):
|
||||||
NB_COLS = NB_COLS
|
|
||||||
NB_NEXT = NB_NEXT
|
|
||||||
LOCK_DELAY = LOCK_DELAY
|
|
||||||
FALL_DELAY = FALL_DELAY
|
|
||||||
AUTOREPEAT_DELAY = AUTOREPEAT_DELAY
|
|
||||||
AUTOREPEAT_PERIOD = AUTOREPEAT_PERIOD
|
|
||||||
CURRENT_COORD = CURRENT_COORD
|
|
||||||
NEXT_COORDS = NEXT_COORDS
|
|
||||||
HELD_COORD = HELD_COORD
|
|
||||||
random_bag = []
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.load_high_score()
|
|
||||||
self.state = State.STARTING
|
|
||||||
self.held = HoldQueue()
|
|
||||||
self.matrix = Matrix()
|
|
||||||
self.matrix.ghost = None
|
|
||||||
self.next = NextQueue()
|
|
||||||
self.time = 0
|
|
||||||
self.autorepeatable_actions = (self.move_left, self.move_right, self.soft_drop)
|
|
||||||
self.pressed_actions = []
|
|
||||||
self._score = 0
|
|
||||||
|
|
||||||
def get_score(self):
|
|
||||||
return self._score
|
return self._score
|
||||||
|
|
||||||
def set_score(self, new_score):
|
def _set_score(self, new_score):
|
||||||
self._score = new_score
|
self._score = new_score
|
||||||
if self._score > self.high_score:
|
if self._score > self.high_score:
|
||||||
self.high_score = self._score
|
self.high_score = self._score
|
||||||
|
|
||||||
score = property(get_score, set_score)
|
score = property(_get_score, _set_score)
|
||||||
|
|
||||||
def new_game(self):
|
def __init__(self):
|
||||||
self.level = 0
|
self._score = 0
|
||||||
self.score = 0
|
|
||||||
self.nb_lines_cleared = 0
|
|
||||||
self.goal = 0
|
|
||||||
self.time = 0
|
self.time = 0
|
||||||
|
|
||||||
self.pressed_actions = []
|
def new_game(self, level):
|
||||||
self.auto_repeat = False
|
self.level = level - 1
|
||||||
|
self.score = 0
|
||||||
|
self.lines_cleared = 0
|
||||||
|
self.goal = 0
|
||||||
|
self.time = 0
|
||||||
|
self.combo = -1
|
||||||
|
|
||||||
self.lock_delay = self.LOCK_DELAY
|
self.lock_delay = LOCK_DELAY
|
||||||
self.fall_delay = self.FALL_DELAY
|
self.fall_delay = FALL_DELAY
|
||||||
|
|
||||||
self.matrix.clear()
|
|
||||||
for y in range(self.NB_LINES + 3):
|
|
||||||
self.append_new_line_to_matrix()
|
|
||||||
self.next.pieces = [self.new_tetromino() for n in range(self.NB_NEXT)]
|
|
||||||
self.held.piece = None
|
|
||||||
self.state = State.PLAYING
|
|
||||||
self.start(self.update_time, 1)
|
|
||||||
|
|
||||||
self.new_level()
|
|
||||||
|
|
||||||
def new_tetromino(self):
|
|
||||||
if not self.random_bag:
|
|
||||||
self.random_bag = list(Tetromino.shapes)
|
|
||||||
random.shuffle(self.random_bag)
|
|
||||||
return self.random_bag.pop()()
|
|
||||||
|
|
||||||
def append_new_line_to_matrix(self):
|
|
||||||
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
|
||||||
@@ -132,23 +102,102 @@ class TetrisLogic:
|
|||||||
self.fall_delay = pow(0.8 - ((self.level - 1) * 0.007), self.level - 1)
|
self.fall_delay = pow(0.8 - ((self.level - 1) * 0.007), self.level - 1)
|
||||||
if self.level > 15:
|
if self.level > 15:
|
||||||
self.lock_delay = 0.5 * pow(0.9, self.level - 15)
|
self.lock_delay = 0.5 * pow(0.9, self.level - 15)
|
||||||
self.show_text("LEVEL\n{:n}".format(self.level))
|
|
||||||
self.restart(self.fall, self.fall_delay)
|
|
||||||
self.new_matrix_piece()
|
|
||||||
|
|
||||||
def new_matrix_piece(self):
|
def update_time(self):
|
||||||
|
self.time += 1
|
||||||
|
|
||||||
|
|
||||||
|
class TetrisLogic:
|
||||||
|
|
||||||
|
LINES = LINES
|
||||||
|
COLLUMNS = COLLUMNS
|
||||||
|
NEXT_PIECES = NEXT_PIECES
|
||||||
|
AUTOREPEAT_DELAY = AUTOREPEAT_DELAY
|
||||||
|
AUTOREPEAT_PERIOD = AUTOREPEAT_PERIOD
|
||||||
|
MATRIX_PIECE_COORD = MATRIX_PIECE_COORD
|
||||||
|
NEXT_PIECE_COORDS = NEXT_PIECE_COORDS
|
||||||
|
HELD_PIECE_COORD = HELD_PIECE_COORD
|
||||||
|
random_bag = []
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
lines=LINES,
|
||||||
|
collumns=COLLUMNS,
|
||||||
|
next_pieces=NEXT_PIECES,
|
||||||
|
):
|
||||||
|
self.stats = Stats()
|
||||||
|
self.load_high_score()
|
||||||
|
self.state = State.STARTING
|
||||||
|
self.held = HoldQueue()
|
||||||
|
self.matrix = Matrix(lines, collumns)
|
||||||
|
self.matrix.ghost = None
|
||||||
|
self.next = NextQueue(next_pieces)
|
||||||
|
self.autorepeatable_actions = (self.move_left, self.move_right, self.soft_drop)
|
||||||
|
self.pressed_actions = []
|
||||||
|
|
||||||
|
def new_game(self, level=1):
|
||||||
|
self.stats.new_game(level)
|
||||||
|
|
||||||
|
self.pressed_actions = []
|
||||||
|
self.auto_repeat = False
|
||||||
|
|
||||||
|
self.matrix.reset()
|
||||||
|
self.next.pieces = [self.new_piece() for n in range(self.next.nb_pieces)]
|
||||||
|
self.held.piece = None
|
||||||
|
self.state = State.PLAYING
|
||||||
|
self.start(self.stats.update_time, 1)
|
||||||
|
|
||||||
|
self.on_new_game()
|
||||||
|
|
||||||
|
self.new_level()
|
||||||
|
|
||||||
|
def on_new_game(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def new_piece(self):
|
||||||
|
if not self.random_bag:
|
||||||
|
self.random_bag = list(Tetromino.shapes)
|
||||||
|
random.shuffle(self.random_bag)
|
||||||
|
piece = self.random_bag.pop()()
|
||||||
|
self.on_new_piece(piece)
|
||||||
|
return piece
|
||||||
|
|
||||||
|
def on_new_piece(self, piece):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def new_level(self):
|
||||||
|
self.stats.new_level()
|
||||||
|
self.restart(self.fall, self.stats.fall_delay)
|
||||||
|
|
||||||
|
self.on_new_level(self.stats.level)
|
||||||
|
|
||||||
|
self.generation_phase()
|
||||||
|
|
||||||
|
def on_new_level(self, level):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def generation_phase(self):
|
||||||
self.matrix.piece = self.next.pieces.pop(0)
|
self.matrix.piece = self.next.pieces.pop(0)
|
||||||
self.matrix.piece.coord = self.CURRENT_COORD
|
self.matrix.piece.coord = self.MATRIX_PIECE_COORD
|
||||||
self.matrix.ghost = self.matrix.piece.ghost()
|
self.matrix.ghost = self.matrix.piece.ghost()
|
||||||
self.move_ghost()
|
self.move_ghost()
|
||||||
self.next.pieces.append(self.new_tetromino())
|
self.next.pieces.append(self.new_piece())
|
||||||
self.next.pieces[-1].coord = self.NEXT_COORDS[-1]
|
self.next.pieces[-1].coord = self.NEXT_PIECE_COORDS[-1]
|
||||||
for tetromino, coord in zip(self.next.pieces, self.NEXT_COORDS):
|
for tetromino, coord in zip(self.next.pieces, self.NEXT_PIECE_COORDS):
|
||||||
tetromino.coord = coord
|
tetromino.coord = coord
|
||||||
|
|
||||||
|
self.on_generation_phase(self.matrix.piece)
|
||||||
|
self.on_falling_phase()
|
||||||
|
|
||||||
if not self.can_move(self.matrix.piece.coord, (mino.coord for mino in self.matrix.piece)):
|
if not self.can_move(self.matrix.piece.coord, (mino.coord for mino in self.matrix.piece)):
|
||||||
self.game_over()
|
self.game_over()
|
||||||
|
|
||||||
|
def on_generation_phase(self, piece):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def on_falling_phase(self):
|
||||||
|
pass
|
||||||
|
|
||||||
def move_left(self):
|
def move_left(self):
|
||||||
self.move(Movement.LEFT)
|
self.move(Movement.LEFT)
|
||||||
|
|
||||||
@@ -171,12 +220,12 @@ class TetrisLogic:
|
|||||||
def soft_drop(self):
|
def soft_drop(self):
|
||||||
moved = self.move(Movement.DOWN)
|
moved = self.move(Movement.DOWN)
|
||||||
if moved:
|
if moved:
|
||||||
self.score += 1
|
self.stats.score += 1
|
||||||
return moved
|
return moved
|
||||||
|
|
||||||
def hard_drop(self):
|
def hard_drop(self):
|
||||||
while self.move(Movement.DOWN, prelock=False):
|
while self.move(Movement.DOWN, prelock=False):
|
||||||
self.score += 2
|
self.stats.score += 2
|
||||||
self.lock()
|
self.lock()
|
||||||
|
|
||||||
def fall(self):
|
def fall(self):
|
||||||
@@ -186,35 +235,47 @@ class TetrisLogic:
|
|||||||
potential_coord = self.matrix.piece.coord + movement
|
potential_coord = self.matrix.piece.coord + movement
|
||||||
if self.can_move(potential_coord, (mino.coord for mino in self.matrix.piece)):
|
if self.can_move(potential_coord, (mino.coord for mino in self.matrix.piece)):
|
||||||
if self.matrix.piece.prelocked:
|
if self.matrix.piece.prelocked:
|
||||||
self.restart(self.lock, self.lock_delay)
|
self.restart(self.lock, self.stats.lock_delay)
|
||||||
self.matrix.piece.coord = potential_coord
|
self.matrix.piece.coord = potential_coord
|
||||||
if not movement == Movement.DOWN:
|
if not movement == Movement.DOWN:
|
||||||
self.matrix.piece.last_rotation_point = None
|
self.matrix.piece.last_rotation_point = None
|
||||||
self.move_ghost()
|
self.move_ghost()
|
||||||
|
self.on_moved(movement)
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
if prelock and not self.matrix.piece.prelocked and movement == Movement.DOWN:
|
if prelock and not self.matrix.piece.prelocked and movement == Movement.DOWN:
|
||||||
self.matrix.piece.prelocked = True
|
self.matrix.piece.prelocked = True
|
||||||
self.start(self.lock, self.lock_delay)
|
self.start(self.lock, self.stats.lock_delay)
|
||||||
|
self.on_lock_phase()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def on_moved(self, movement):
|
||||||
|
pass
|
||||||
|
|
||||||
def rotate(self, rotation):
|
def rotate(self, rotation):
|
||||||
rotated_coords = tuple(Coord(rotation * mino.coord.y, -rotation * mino.coord.x) for mino in self.matrix.piece)
|
rotated_coords = tuple(Coord(rotation * mino.coord.y, -rotation * mino.coord.x) for mino in self.matrix.piece)
|
||||||
for rotation_point, liberty_degree in enumerate(self.matrix.piece.SRS[rotation][self.matrix.piece.orientation], start=1):
|
for rotation_point, liberty_degree in enumerate(self.matrix.piece.SRS[rotation][self.matrix.piece.orientation], start=1):
|
||||||
potential_coord = self.matrix.piece.coord + liberty_degree
|
potential_coord = self.matrix.piece.coord + liberty_degree
|
||||||
if self.can_move(potential_coord, rotated_coords):
|
if self.can_move(potential_coord, rotated_coords):
|
||||||
if self.matrix.piece.prelocked:
|
if self.matrix.piece.prelocked:
|
||||||
self.restart(self.lock, self.lock_delay)
|
self.restart(self.lock, self.stats.lock_delay)
|
||||||
self.matrix.piece.coord = potential_coord
|
self.matrix.piece.coord = potential_coord
|
||||||
for mino, coord in zip(self.matrix.piece, rotated_coords):
|
for mino, coord in zip(self.matrix.piece, rotated_coords):
|
||||||
mino.coord = coord
|
mino.coord = coord
|
||||||
self.matrix.piece.orientation = (self.matrix.piece.orientation + rotation) % 4
|
self.matrix.piece.orientation = (self.matrix.piece.orientation + rotation) % 4
|
||||||
self.matrix.piece.last_rotation_point = rotation_point
|
self.matrix.piece.last_rotation_point = rotation_point
|
||||||
self.move_ghost()
|
self.move_ghost()
|
||||||
|
self.on_rotated(rotation)
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def on_rotated(self, direction):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def on_lock_phase(self):
|
||||||
|
pass
|
||||||
|
|
||||||
SCORES = (
|
SCORES = (
|
||||||
{LINES_CLEAR_NAME: "", T_Spin.NONE: 0, T_Spin.MINI: 1, T_Spin.T_SPIN: 4},
|
{LINES_CLEAR_NAME: "", T_Spin.NONE: 0, T_Spin.MINI: 1, T_Spin.T_SPIN: 4},
|
||||||
{LINES_CLEAR_NAME: "SINGLE", T_Spin.NONE: 1, T_Spin.MINI: 2, T_Spin.T_SPIN: 8},
|
{LINES_CLEAR_NAME: "SINGLE", T_Spin.NONE: 1, T_Spin.MINI: 2, T_Spin.T_SPIN: 8},
|
||||||
@@ -232,14 +293,23 @@ class TetrisLogic:
|
|||||||
return
|
return
|
||||||
|
|
||||||
# Game over
|
# Game over
|
||||||
if all((mino.coord + self.matrix.piece.coord).y >= self.NB_LINES for mino in self.matrix.piece):
|
if all((mino.coord + self.matrix.piece.coord).y >= self.matrix.lines for mino in self.matrix.piece):
|
||||||
self.game_over()
|
self.game_over()
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.pressed_actions:
|
if self.pressed_actions:
|
||||||
self.auto_repeat = False
|
self.auto_repeat = False
|
||||||
self.restart(self.repeat_action, self.AUTOREPEAT_DELAY)
|
self.stop(self.repeat_action)
|
||||||
|
|
||||||
|
for mino in self.matrix.piece:
|
||||||
|
coord = mino.coord + self.matrix.piece.coord
|
||||||
|
if coord.y <= self.matrix.lines + 3:
|
||||||
|
self.matrix[coord.y][coord.x] = mino
|
||||||
|
self.on_locked(self.matrix.piece)
|
||||||
|
|
||||||
|
self.pattern_phase()
|
||||||
|
|
||||||
|
def pattern_phase(self):
|
||||||
# T-Spin
|
# T-Spin
|
||||||
if type(self.matrix.piece) == T_Tetrimino and self.matrix.piece.last_rotation_point is not None:
|
if type(self.matrix.piece) == T_Tetrimino and self.matrix.piece.last_rotation_point is not None:
|
||||||
a = self.is_t_slot(0)
|
a = self.is_t_slot(0)
|
||||||
@@ -255,21 +325,16 @@ class TetrisLogic:
|
|||||||
else:
|
else:
|
||||||
t_spin = T_Spin.NONE
|
t_spin = T_Spin.NONE
|
||||||
|
|
||||||
for mino in self.matrix.piece:
|
|
||||||
coord = mino.coord + self.matrix.piece.coord
|
|
||||||
del mino.coord
|
|
||||||
if coord.y <= self.NB_LINES + 3:
|
|
||||||
self.matrix[coord.y][coord.x] = mino
|
|
||||||
|
|
||||||
# Clear complete lines
|
# Clear complete lines
|
||||||
nb_lines_cleared = 0
|
lines_cleared = 0
|
||||||
for y, line in reversed(list(enumerate(self.matrix))):
|
for y, line in reversed(list(enumerate(self.matrix))):
|
||||||
if all(mino for mino in line):
|
if all(mino for mino in line):
|
||||||
nb_lines_cleared += 1
|
lines_cleared += 1
|
||||||
|
self.on_line_remove(y)
|
||||||
self.matrix.pop(y)
|
self.matrix.pop(y)
|
||||||
self.append_new_line_to_matrix()
|
self.matrix.append_new_line()
|
||||||
if nb_lines_cleared:
|
if lines_cleared:
|
||||||
self.nb_lines_cleared += nb_lines_cleared
|
self.stats.lines_cleared += lines_cleared
|
||||||
|
|
||||||
# Scoring
|
# Scoring
|
||||||
lock_strings = []
|
lock_strings = []
|
||||||
@@ -277,31 +342,40 @@ class TetrisLogic:
|
|||||||
|
|
||||||
if t_spin:
|
if t_spin:
|
||||||
lock_strings.append(t_spin)
|
lock_strings.append(t_spin)
|
||||||
if nb_lines_cleared:
|
if lines_cleared:
|
||||||
lock_strings.append(self.SCORES[nb_lines_cleared][LINES_CLEAR_NAME])
|
lock_strings.append(self.SCORES[lines_cleared][LINES_CLEAR_NAME])
|
||||||
self.combo += 1
|
self.stats.combo += 1
|
||||||
else:
|
else:
|
||||||
self.combo = -1
|
self.stats.combo = -1
|
||||||
|
|
||||||
if nb_lines_cleared or t_spin:
|
if lines_cleared or t_spin:
|
||||||
ds = self.SCORES[nb_lines_cleared][t_spin]
|
ds = self.SCORES[lines_cleared][t_spin]
|
||||||
self.goal -= ds
|
self.stats.goal -= ds
|
||||||
ds *= 100 * self.level
|
ds *= 100 * self.stats.level
|
||||||
lock_score += ds
|
lock_score += ds
|
||||||
lock_strings.append(str(ds))
|
lock_strings.append(str(ds))
|
||||||
self.show_text("\n".join(lock_strings))
|
self.show_text("\n".join(lock_strings))
|
||||||
|
|
||||||
if self.combo >= 1:
|
if self.stats.combo >= 1:
|
||||||
ds = (20 if nb_lines_cleared == 1 else 50) * self.combo * self.level
|
ds = (20 if lines_cleared == 1 else 50) * self.stats.combo * self.stats.level
|
||||||
lock_score += ds
|
lock_score += ds
|
||||||
self.show_text("COMBO x{:n}\n{:n}".format(self.combo, ds))
|
self.show_text("COMBO x{:n}\n{:n}".format(self.stats.combo, ds))
|
||||||
|
|
||||||
self.score += lock_score
|
self.stats.score += lock_score
|
||||||
|
|
||||||
if self.goal <= 0:
|
if self.stats.goal <= 0:
|
||||||
self.new_level()
|
self.new_level()
|
||||||
else:
|
else:
|
||||||
self.new_matrix_piece()
|
self.generation_phase()
|
||||||
|
|
||||||
|
if self.pressed_actions:
|
||||||
|
self.start(self.repeat_action, self.AUTOREPEAT_DELAY)
|
||||||
|
|
||||||
|
def on_locked(piece):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def on_line_remove(self, y):
|
||||||
|
pass
|
||||||
|
|
||||||
def can_move(self, potential_coord, minoes_coords):
|
def can_move(self, potential_coord, minoes_coords):
|
||||||
return all(self.matrix.cell_is_free(potential_coord + mino_coord) for mino_coord in minoes_coords)
|
return all(self.matrix.cell_is_free(potential_coord + mino_coord) for mino_coord in minoes_coords)
|
||||||
@@ -318,18 +392,18 @@ class TetrisLogic:
|
|||||||
self.matrix.piece.prelocked = False
|
self.matrix.piece.prelocked = False
|
||||||
self.stop(self.lock)
|
self.stop(self.lock)
|
||||||
self.matrix.piece, self.held.piece = self.held.piece, self.matrix.piece
|
self.matrix.piece, self.held.piece = self.held.piece, self.matrix.piece
|
||||||
self.held.piece.coord = self.HELD_COORD
|
self.held.piece.coord = self.HELD_PIECE_COORD
|
||||||
if type(self.held.piece) == I_Tetrimino:
|
if type(self.held.piece) == I_Tetrimino:
|
||||||
self.held.piece.coord += Movement.LEFT
|
self.held.piece.coord += Movement.LEFT
|
||||||
for mino, coord in zip(self.held.piece, self.held.piece.MINOES_COORDS):
|
for mino, coord in zip(self.held.piece, self.held.piece.MINOES_COORDS):
|
||||||
mino.coord = coord
|
mino.coord = coord
|
||||||
|
|
||||||
if self.matrix.piece:
|
if self.matrix.piece:
|
||||||
self.matrix.piece.coord = self.CURRENT_COORD
|
self.matrix.piece.coord = self.MATRIX_PIECE_COORD
|
||||||
self.matrix.ghost = self.matrix.piece.ghost()
|
self.matrix.ghost = self.matrix.piece.ghost()
|
||||||
self.move_ghost()
|
self.move_ghost()
|
||||||
else:
|
else:
|
||||||
self.new_matrix_piece()
|
self.generation_phase()
|
||||||
|
|
||||||
def pause(self):
|
def pause(self):
|
||||||
self.state = State.PAUSED
|
self.state = State.PAUSED
|
||||||
@@ -340,10 +414,10 @@ class TetrisLogic:
|
|||||||
|
|
||||||
def resume(self):
|
def resume(self):
|
||||||
self.state = State.PLAYING
|
self.state = State.PLAYING
|
||||||
self.start(self.fall, self.fall_delay)
|
self.start(self.fall, self.stats.fall_delay)
|
||||||
if self.matrix.piece.prelocked:
|
if self.matrix.piece.prelocked:
|
||||||
self.start(self.lock, self.lock_delay)
|
self.start(self.lock, self.stats.lock_delay)
|
||||||
self.start(self.update_time, 1)
|
self.start(self.stats.update_time, 1)
|
||||||
|
|
||||||
def game_over(self):
|
def game_over(self):
|
||||||
self.state = State.OVER
|
self.state = State.OVER
|
||||||
@@ -353,10 +427,7 @@ class TetrisLogic:
|
|||||||
def stop_all(self):
|
def stop_all(self):
|
||||||
self.stop(self.fall)
|
self.stop(self.fall)
|
||||||
self.stop(self.lock)
|
self.stop(self.lock)
|
||||||
self.stop(self.update_time)
|
self.stop(self.stats.update_time)
|
||||||
|
|
||||||
def update_time(self):
|
|
||||||
self.time += 1
|
|
||||||
|
|
||||||
def do_action(self, action):
|
def do_action(self, action):
|
||||||
action()
|
action()
|
||||||
@@ -364,7 +435,7 @@ class TetrisLogic:
|
|||||||
self.auto_repeat = False
|
self.auto_repeat = False
|
||||||
self.pressed_actions.append(action)
|
self.pressed_actions.append(action)
|
||||||
if action == self.soft_drop:
|
if action == self.soft_drop:
|
||||||
delay = self.fall_delay / 20
|
delay = self.stats.fall_delay / 20
|
||||||
else:
|
else:
|
||||||
delay = self.AUTOREPEAT_DELAY
|
delay = self.AUTOREPEAT_DELAY
|
||||||
self.restart(self.repeat_action, delay)
|
self.restart(self.repeat_action, delay)
|
||||||
@@ -393,16 +464,16 @@ class TetrisLogic:
|
|||||||
def load_high_score(self, crypted_high_score=None):
|
def load_high_score(self, crypted_high_score=None):
|
||||||
if crypted_high_score:
|
if crypted_high_score:
|
||||||
crypted_high_score = int(pickle.loads(crypted_high_score))
|
crypted_high_score = int(pickle.loads(crypted_high_score))
|
||||||
self.high_score = crypted_high_score ^ CRYPT_KEY
|
self.stats.high_score = crypted_high_score ^ CRYPT_KEY
|
||||||
else:
|
else:
|
||||||
raise Warning(
|
raise Warning(
|
||||||
"""TetrisLogic.load_high_score not implemented.
|
"""TetrisLogic.load_high_score not implemented.
|
||||||
High score is set to 0"""
|
High score is set to 0"""
|
||||||
)
|
)
|
||||||
self.high_score = 0
|
self.stats.high_score = 0
|
||||||
|
|
||||||
def save_high_score(self):
|
def save_high_score(self):
|
||||||
crypted_high_score = self.high_score ^ CRYPT_KEY
|
crypted_high_score = self.stats.high_score ^ CRYPT_KEY
|
||||||
crypted_high_score = pickle.dumps(crypted_high_score)
|
crypted_high_score = pickle.dumps(crypted_high_score)
|
||||||
return crypted_high_score
|
return crypted_high_score
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user