Reduce latency with no updating on ghost hard drop, merge block.py with tetromino.py

This commit is contained in:
adrienmalin 2018-08-12 17:14:19 +02:00
parent 3bd090b38e
commit 095e0ebf62
4 changed files with 139 additions and 146 deletions

View File

@ -21,9 +21,8 @@ import consts
from consts import L, R, CLOCKWISE, COUNTERCLOCKWISE from consts import L, R, CLOCKWISE, COUNTERCLOCKWISE
from qt5 import QtWidgets, QtCore, QtGui, QtMultimedia from qt5 import QtWidgets, QtCore, QtGui, QtMultimedia
from __version__ import __title__, __author__, __version__ from __version__ import __title__, __author__, __version__
from block import Block
from point import Point from point import Point
from tetromino import Tetromino, GhostPiece from tetromino import Block, Tetromino, GhostPiece
class Grid(QtWidgets.QWidget): class Grid(QtWidgets.QWidget):
@ -113,6 +112,7 @@ class Matrix(Grid):
self.setFocusPolicy(QtCore.Qt.StrongFocus) self.setFocusPolicy(QtCore.Qt.StrongFocus)
self.auto_repeat_delay = 0
self.auto_repeat_timer = QtCore.QTimer() self.auto_repeat_timer = QtCore.QTimer()
self.auto_repeat_timer.setTimerType(QtCore.Qt.PreciseTimer) self.auto_repeat_timer.setTimerType(QtCore.Qt.PreciseTimer)
self.auto_repeat_timer.timeout.connect(self.auto_repeat) self.auto_repeat_timer.timeout.connect(self.auto_repeat)
@ -175,8 +175,8 @@ class Matrix(Grid):
self.do(action) self.do(action)
if action in (s.MOVE_LEFT, s.MOVE_RIGHT, s.SOFT_DROP): if action in (s.MOVE_LEFT, s.MOVE_RIGHT, s.SOFT_DROP):
if action not in self.actions_to_repeat: if action not in self.actions_to_repeat:
self.actions_to_repeat.append(action)
self.auto_repeat_wait() self.auto_repeat_wait()
self.actions_to_repeat.append(action)
def keyReleaseEvent(self, event): def keyReleaseEvent(self, event):
if event.isAutoRepeat(): if event.isAutoRepeat():
@ -339,6 +339,7 @@ class Matrix(Grid):
if mino.coord.y() >= 0: if mino.coord.y() >= 0:
self.cells[mino.coord.y()][mino.coord.x()] = mino self.cells[mino.coord.y()][mino.coord.x()] = mino
mino.shine(glowing=2, delay=consts.ANIMATION_DELAY) mino.shine(glowing=2, delay=consts.ANIMATION_DELAY)
QtCore.QTimer.singleShot(consts.ANIMATION_DELAY, self.update)
self.update() self.update()
if all( if all(

130
block.py
View File

@ -1,130 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import consts
from consts import U, D
from point import Point
from qt5 import QtCore, QtGui
class Block:
"""
Mino or block
Mino : A single square-shaped building block of a shape called a Tetrimino.
Four Minos arranged into any of their various connected patterns is known as a Tetrimino
Block : A single block locked in a cell in the Grid
"""
# Colors
BORDER_COLOR = consts.BLOCK_BORDER_COLOR
FILL_COLOR = consts.BLOCK_FILL_COLOR
GLOWING_BORDER_COLOR = consts.BLOCK_GLOWING_BORDER_COLOR
GLOWING_FILL_COLOR = consts.BLOCK_GLOWING_FILL_COLOR
LIGHT_COLOR = consts.BLOCK_LIGHT_COLOR
TRANSPARENT = consts.BLOCK_TRANSPARENT
GLOWING = consts.BLOCK_GLOWING
side = consts.BLOCK_INITIAL_SIDE
def __init__(self, coord, trail=0):
self.coord = coord
self.trail = trail
self.border_color = self.BORDER_COLOR
self.fill_color = self.FILL_COLOR
self.glowing = self.GLOWING
def paint(self, painter, top_left_corner, spotlight):
p = top_left_corner + self.coord * Block.side
block_center = Point(Block.side / 2, Block.side / 2)
self.center = p + block_center
spotlight = top_left_corner + Block.side * spotlight + block_center
self.glint = 0.15 * spotlight + 0.85 * self.center
if self.trail:
start = (
top_left_corner + (self.coord + Point(0, self.trail * U)) * Block.side
)
stop = top_left_corner + (self.coord + Point(0, 2 * D)) * Block.side
fill = QtGui.QLinearGradient(start, stop)
fill.setColorAt(0, self.LIGHT_COLOR)
fill.setColorAt(1, self.GLOWING_FILL_COLOR)
painter.setBrush(fill)
painter.setPen(QtCore.Qt.NoPen)
painter.drawRoundedRect(
start.x(),
start.y(),
Block.side,
Block.side * (1 + self.trail),
20,
20,
QtCore.Qt.RelativeSize,
)
if self.glowing:
fill = QtGui.QRadialGradient(self.center, self.glowing * Block.side)
fill.setColorAt(0, self.TRANSPARENT)
fill.setColorAt(0.5 / self.glowing, self.LIGHT_COLOR)
fill.setColorAt(1, self.TRANSPARENT)
painter.setBrush(QtGui.QBrush(fill))
painter.setPen(QtCore.Qt.NoPen)
painter.drawEllipse(
self.center.x() - self.glowing * Block.side,
self.center.y() - self.glowing * Block.side,
2 * self.glowing * Block.side,
2 * self.glowing * Block.side,
)
painter.setBrush(self.brush())
painter.setPen(self.pen())
painter.drawRoundedRect(
p.x() + 1,
p.y() + 1,
Block.side - 2,
Block.side - 2,
20,
20,
QtCore.Qt.RelativeSize,
)
def brush(self):
if self.fill_color is None:
return QtCore.Qt.NoBrush
fill = QtGui.QRadialGradient(self.glint, 1.5 * Block.side)
fill.setColorAt(0, self.fill_color.lighter())
fill.setColorAt(1, self.fill_color)
return QtGui.QBrush(fill)
def pen(self):
if self.border_color is None:
return QtCore.Qt.NoPen
border = QtGui.QRadialGradient(self.glint, Block.side)
border.setColorAt(0, self.border_color.lighter())
border.setColorAt(1, self.border_color.darker())
return QtGui.QPen(QtGui.QBrush(border), 1, join=QtCore.Qt.RoundJoin)
def shine(self, glowing=2, delay=None):
self.border_color = Block.GLOWING_BORDER_COLOR
self.fill_color = Block.GLOWING_FILL_COLOR
self.glowing = glowing
if delay:
QtCore.QTimer.singleShot(delay, self.fade)
def fade(self):
self.border_color = Block.BORDER_COLOR
self.fill_color = Block.FILL_COLOR
self.glowing = 0
self.trail = 0
class GhostBlock(Block):
"""
Mino of the ghost piece
"""
BORDER_COLOR = consts.GHOST_BLOCK_BORDER_COLOR
FILL_COLOR = consts.GHOST_BLOCK_FILL_COLOR
GLOWING_FILL_COLOR = consts.GHOST_BLOCK_GLOWING_FILL_COLOR
GLOWING = consts.GHOST_BLOCK_GLOWING

View File

@ -32,7 +32,7 @@ L, R, U, D = -1, 1, -1, 1 # Left, Right, Up, Down
CLOCKWISE, COUNTERCLOCKWISE = 1, -1 CLOCKWISE, COUNTERCLOCKWISE = 1, -1
# Delays in milliseconds # Delays in milliseconds
ANIMATION_DELAY = 100 ANIMATION_DELAY = 67
INITIAL_SPEED = 1000 INITIAL_SPEED = 1000
ENTRY_DELAY = 80 ENTRY_DELAY = 80
LINE_CLEAR_DELAY = 80 LINE_CLEAR_DELAY = 80

View File

@ -4,9 +4,132 @@
import random import random
import consts
from consts import L, R, U, D, CLOCKWISE, COUNTERCLOCKWISE from consts import L, R, U, D, CLOCKWISE, COUNTERCLOCKWISE
from point import Point from point import Point
from block import Block, GhostBlock from qt5 import QtCore, QtGui
class Block:
"""
Mino or block
Mino : A single square-shaped building block of a shape called a Tetrimino.
Four Minos arranged into any of their various connected patterns is known as a Tetrimino
Block : A single block locked in a cell in the Grid
"""
# Colors
BORDER_COLOR = consts.BLOCK_BORDER_COLOR
FILL_COLOR = consts.BLOCK_FILL_COLOR
GLOWING_BORDER_COLOR = consts.BLOCK_GLOWING_BORDER_COLOR
GLOWING_FILL_COLOR = consts.BLOCK_GLOWING_FILL_COLOR
LIGHT_COLOR = consts.BLOCK_LIGHT_COLOR
TRANSPARENT = consts.BLOCK_TRANSPARENT
GLOWING = consts.BLOCK_GLOWING
side = consts.BLOCK_INITIAL_SIDE
def __init__(self, coord, trail=0):
self.coord = coord
self.trail = trail
self.border_color = self.BORDER_COLOR
self.fill_color = self.FILL_COLOR
self.glowing = self.GLOWING
def paint(self, painter, top_left_corner, spotlight):
p = top_left_corner + self.coord * Block.side
block_center = Point(Block.side / 2, Block.side / 2)
self.center = p + block_center
spotlight = top_left_corner + Block.side * spotlight + block_center
self.glint = 0.15 * spotlight + 0.85 * self.center
if self.trail:
start = (
top_left_corner + (self.coord + Point(0, self.trail * U)) * Block.side
)
stop = top_left_corner + (self.coord + Point(0, 2 * D)) * Block.side
fill = QtGui.QLinearGradient(start, stop)
fill.setColorAt(0, self.LIGHT_COLOR)
fill.setColorAt(1, self.GLOWING_FILL_COLOR)
painter.setBrush(fill)
painter.setPen(QtCore.Qt.NoPen)
painter.drawRoundedRect(
start.x(),
start.y(),
Block.side,
Block.side * (1 + self.trail),
20,
20,
QtCore.Qt.RelativeSize,
)
if self.glowing:
fill = QtGui.QRadialGradient(self.center, self.glowing * Block.side)
fill.setColorAt(0, self.TRANSPARENT)
fill.setColorAt(0.5 / self.glowing, self.LIGHT_COLOR)
fill.setColorAt(1, self.TRANSPARENT)
painter.setBrush(QtGui.QBrush(fill))
painter.setPen(QtCore.Qt.NoPen)
painter.drawEllipse(
self.center.x() - self.glowing * Block.side,
self.center.y() - self.glowing * Block.side,
2 * self.glowing * Block.side,
2 * self.glowing * Block.side,
)
painter.setBrush(self.brush())
painter.setPen(self.pen())
painter.drawRoundedRect(
p.x() + 1,
p.y() + 1,
Block.side - 2,
Block.side - 2,
20,
20,
QtCore.Qt.RelativeSize,
)
def brush(self):
if self.fill_color is None:
return QtCore.Qt.NoBrush
fill = QtGui.QRadialGradient(self.glint, 1.5 * Block.side)
fill.setColorAt(0, self.fill_color.lighter())
fill.setColorAt(1, self.fill_color)
return QtGui.QBrush(fill)
def pen(self):
if self.border_color is None:
return QtCore.Qt.NoPen
border = QtGui.QRadialGradient(self.glint, Block.side)
border.setColorAt(0, self.border_color.lighter())
border.setColorAt(1, self.border_color.darker())
return QtGui.QPen(QtGui.QBrush(border), 1, join=QtCore.Qt.RoundJoin)
def shine(self, glowing=2, delay=None):
self.border_color = Block.GLOWING_BORDER_COLOR
self.fill_color = Block.GLOWING_FILL_COLOR
self.glowing = glowing
if delay:
QtCore.QTimer.singleShot(delay, self.fade)
def fade(self):
self.border_color = Block.BORDER_COLOR
self.fill_color = Block.FILL_COLOR
self.glowing = 0
self.trail = 0
class GhostBlock(Block):
"""
Mino of the ghost piece
"""
BORDER_COLOR = consts.GHOST_BLOCK_BORDER_COLOR
FILL_COLOR = consts.GHOST_BLOCK_FILL_COLOR
GLOWING_FILL_COLOR = consts.GHOST_BLOCK_GLOWING_FILL_COLOR
GLOWING = consts.GHOST_BLOCK_GLOWING
class MetaTetro(type): class MetaTetro(type):
@ -76,7 +199,7 @@ class Tetromino:
self.matrix = matrix self.matrix = matrix
self.minoes = tuple(Block(Point(*coord) + position) for coord in self.COORDS) self.minoes = tuple(Block(Point(*coord) + position) for coord in self.COORDS)
def _try_movement(self, next_coords_generator, trail=0): def _try_movement(self, next_coords_generator, trail=0, update=True):
""" """
Test if self can fit in the Grid with new coordinates, Test if self can fit in the Grid with new coordinates,
i.e. all cells are empty. i.e. all cells are empty.
@ -93,10 +216,11 @@ class Tetromino:
for block, future_coord in zip(self.minoes, futures_coords): for block, future_coord in zip(self.minoes, futures_coords):
block.coord = future_coord block.coord = future_coord
block.trail = trail block.trail = trail
self.matrix.update() if update:
self.matrix.update()
return True return True
def move(self, horizontally, vertically, trail=0): def move(self, horizontally, vertically, trail=0, update=True):
""" """
Try to translate self horizontally or vertically Try to translate self horizontally or vertically
The Tetrimino in play falls from just above the Skyline one cell at a time, The Tetrimino in play falls from just above the Skyline one cell at a time,
@ -110,6 +234,7 @@ class Tetromino:
return self._try_movement( return self._try_movement(
(block.coord + Point(horizontally, vertically) for block in self.minoes), (block.coord + Point(horizontally, vertically) for block in self.minoes),
trail, trail,
update
) )
def rotate(self, direction=CLOCKWISE): def rotate(self, direction=CLOCKWISE):
@ -141,15 +266,16 @@ class Tetromino:
""" """
return self.move(0, D, trail=1) return self.move(0, D, trail=1)
def hard_drop(self): def hard_drop(self, show_trail=True, update=True):
""" """
Causes the Tetrimino in play to drop straight down instantly from its Causes the Tetrimino in play to drop straight down instantly from its
current location and Lock Down on the first Surface it lands on. current location and Lock Down on the first Surface it lands on.
It does not allow for further player manipulation of the Tetrimino in play. It does not allow for further player manipulation of the Tetrimino in play.
""" """
trail = 0 trail = 0
while self.move(0, D, trail=trail): while self.move(0, D, trail=trail, update=update):
trail += 1 if show_trail:
trail += 1
return trail return trail
@ -293,8 +419,4 @@ class GhostPiece(Tetromino):
self.minoes = tuple( self.minoes = tuple(
GhostBlock(Point(mino.coord.x(), mino.coord.y())) for mino in piece.minoes GhostBlock(Point(mino.coord.x(), mino.coord.y())) for mino in piece.minoes
) )
self.hard_drop() self.hard_drop(show_trail=False, update=False)
def hard_drop(self):
while self.move(0, D):
pass