fix: address issue with colors on opponent side

This commit is contained in:
2021-07-15 20:40:26 -04:00
parent 3021f38cf4
commit 165c9d9c86
3 changed files with 102 additions and 83 deletions

View File

@@ -12,24 +12,23 @@ from tetri5.util import SoundManager
""" """
class Entity: class Entity:
def __init__(self, points: Tuple, color: str, border_color: str = None): def __init__(self, points: Tuple, base_color: str, outer_color: str = None):
self._tile_size = ConfigurationManager.get("engine", "tile-size") self._tile_size = ConfigurationManager.get("engine", "tile-size")
self._points = points self._points = points
self._color = color self._base_color = base_color
self._border_color = border_color self._outer_color = outer_color
self._elapsed_time = 0 self._elapsed_time = 0 # TODO does nothing right now
def update(self, elapsed_time: int) -> None: def update(self, elapsed_time: int) -> None:
self._elapsed_time += elapsed_time self._elapsed_time += elapsed_time
def draw(self, surface: pygame.Surface) -> None: def draw(self, surface: pygame.Surface) -> None:
for square in self._points: for square in self._points:
if self._color is not None: if self._base_color is not None:
square_color = pygame.Color(self._color) square_color = pygame.Color(self._base_color)
square_color.a = 255
pygame.draw.polygon(surface, square_color, square, 0) pygame.draw.polygon(surface, square_color, square, 0)
if self._border_color is not None: if self._outer_color is not None:
pygame.draw.polygon(surface, pygame.Color(self._border_color), square, max(self._tile_size // 6, 1)) pygame.draw.polygon(surface, pygame.Color(self._outer_color), square, max(self._tile_size // 6, 1))
def collide(self, entity: "Entity") -> bool: # TODO figure out how to do type hint for entity param of type Entity def collide(self, entity: "Entity") -> bool: # TODO figure out how to do type hint for entity param of type Entity
for square_one in self._points: for square_one in self._points:
@@ -55,8 +54,8 @@ class Well(Entity):
WIDTH = 10 # standard tetris well width, should not be changed WIDTH = 10 # standard tetris well width, should not be changed
HEIGHT = 20 # standard tetris well height, should not be changed HEIGHT = 20 # standard tetris well height, should not be changed
def __init__(self, position: Tuple, color: str, border_color: str): def __init__(self, position: Tuple, base_color: str, outer_color: str):
super().__init__(Well._get_points(position), color, border_color) super().__init__(Well._get_points(position), base_color, outer_color)
@classmethod @classmethod
def _get_points(cls, position: Tuple) -> List: def _get_points(cls, position: Tuple) -> List:
@@ -84,10 +83,10 @@ class Well(Entity):
''' '''
class Piece(Entity): class Piece(Entity):
def __init__(self, shape: Tuple, position: Tuple, color: str, inner_border_color: str, border_color: str): def __init__(self, shape: Tuple, position: Tuple, base_color: str, inner_color: str, outer_color: str):
super().__init__(Piece._get_points(shape, position), color, border_color) super().__init__(Piece._get_points(shape, position), base_color, outer_color)
self._inner_border_color = inner_border_color self._inner_color = inner_color
self._ghost_piece_color = ConfigurationManager.get("color", "piece-ghost") self._ghost_piece_base_color = ConfigurationManager.get("color", "piece-ghost")
self._center = self._get_center(shape, position) self._center = self._get_center(shape, position)
self._previous_points = None self._previous_points = None
self._previous_center = None self._previous_center = None
@@ -150,29 +149,35 @@ class Piece(Entity):
def draw(self, surface: pygame.Surface, well: Well = None, stack: "Stack" = None, ghost_piece_off: bool = False) -> None: def draw(self, surface: pygame.Surface, well: Well = None, stack: "Stack" = None, ghost_piece_off: bool = False) -> None:
# ghost piece # ghost piece
if well and stack and not ghost_piece_off: if well is not None and stack is not None and not ghost_piece_off:
ghost_piece_points = self._get_ghost_piece_points(well, stack) ghost_piece_points = self._get_ghost_piece_points(well, stack)
if ghost_piece_points is not None: if ghost_piece_points is not None:
for square in ghost_piece_points: for square in ghost_piece_points:
pygame.draw.polygon(surface, pygame.Color(self._ghost_piece_color), square, max(self._tile_size // 6, 1)) # TODO add white to the yaml pygame.draw.polygon(surface, pygame.Color(self._ghost_piece_base_color), square, max(self._tile_size // 6, 1)) # TODO add white to the yaml
super().draw(surface)
# inner border piece
for square in self._points: for square in self._points:
if self._inner_border_color: if self._base_color is not None:
square_color = pygame.Color(ConfigurationManager.get("color", self._base_color))
pygame.draw.polygon(surface, square_color, square, 0)
if self._outer_color is not None:
pygame.draw.polygon(surface, pygame.Color(ConfigurationManager.get("color", self._outer_color)), square, max(self._tile_size // 6, 1))
for square in self._points:
# inner color border piece
if self._inner_color:
vertex_one = (square[0][0] + (self._tile_size // 10), square[0][1] + (self._tile_size // 10)) vertex_one = (square[0][0] + (self._tile_size // 10), square[0][1] + (self._tile_size // 10))
vertex_two = (square[1][0] - (self._tile_size // 10), square[1][1] + (self._tile_size // 10)) vertex_two = (square[1][0] - (self._tile_size // 10), square[1][1] + (self._tile_size // 10))
vertex_three = (square[2][0] - (self._tile_size // 10), square[2][1] - (self._tile_size // 10)) vertex_three = (square[2][0] - (self._tile_size // 10), square[2][1] - (self._tile_size // 10))
vertex_four = (square[3][0] + (self._tile_size // 10), square[3][1] - (self._tile_size // 10)) vertex_four = (square[3][0] + (self._tile_size // 10), square[3][1] - (self._tile_size // 10))
new_square = (vertex_one, vertex_two, vertex_three, vertex_four) new_square = (vertex_one, vertex_two, vertex_three, vertex_four)
pygame.draw.polygon(surface, pygame.Color(self._inner_border_color), new_square, max(self._tile_size // 6, 1)) pygame.draw.polygon(surface, pygame.Color(ConfigurationManager.get("color", self._inner_color)), new_square, max(self._tile_size // 6, 1))
# draw glimmer # draw glimmer
surface.set_at((square[0][0]+3, square[0][1]+3), pygame.Color(255, 255, 255)) surface.set_at((square[0][0]+3, square[0][1]+3), "white")
surface.set_at((square[0][0]+4, square[0][1]+4), pygame.Color(255, 255, 255)) surface.set_at((square[0][0]+4, square[0][1]+4), "white")
surface.set_at((square[0][0]+4, square[0][1]+5), pygame.Color(255, 255, 255)) surface.set_at((square[0][0]+5, square[0][1]+5), "white")
surface.set_at((square[0][0]+5, square[0][1]+4), pygame.Color(255, 255, 255)) surface.set_at((square[0][0]+4, square[0][1]+5), "white")
surface.set_at((square[0][0]+5, square[0][1]+4), "white")
def move(self, vector: Tuple) -> None: def move(self, vector: Tuple) -> None:
self._previous_points = copy.deepcopy(self._points) self._previous_points = copy.deepcopy(self._points)
@@ -339,7 +344,7 @@ class Stack(Entity):
def __init__(self): def __init__(self):
super().__init__([], None, None) super().__init__([], None, None)
self._square_designs = [] self._square_colors = []
self.total_lines = 0 self.total_lines = 0
self.lines_completed_last = 0 self.lines_completed_last = 0
@@ -351,28 +356,29 @@ class Stack(Entity):
def draw(self, surface: pygame.Surface) -> None: def draw(self, surface: pygame.Surface) -> None:
for i in range(len(self._points)): for i in range(len(self._points)):
square = self._points[i] square = self._points[i]
square_design = self._square_designs[i] square_design = self._square_colors[i]
if square_design.base_color is not None: if square_design.base_color is not None:
pygame.draw.polygon(surface, pygame.Color(square_design.base_color), square, 0) pygame.draw.polygon(surface, pygame.Color(ConfigurationManager.get("color", square_design.base_color)), square, 0)
if square_design.outer_color is not None: if square_design.outer_color is not None:
pygame.draw.polygon(surface, pygame.Color(square_design.outer_color), square, max(self._tile_size // 6, 1)) pygame.draw.polygon(surface, pygame.Color(ConfigurationManager.get("color", square_design.outer_color)), square, max(self._tile_size // 6, 1))
if square_design.inner_color is not None: if square_design.inner_color is not None:
vertex_one = (square[0][0] + (self._tile_size // 10), square[0][1] + (self._tile_size // 10)) vertex_one = (square[0][0] + (self._tile_size // 10), square[0][1] + (self._tile_size // 10))
vertex_two = (square[1][0] - (self._tile_size // 10), square[1][1] + (self._tile_size // 10)) vertex_two = (square[1][0] - (self._tile_size // 10), square[1][1] + (self._tile_size // 10))
vertex_three = (square[2][0] - (self._tile_size // 10), square[2][1] - (self._tile_size // 10)) vertex_three = (square[2][0] - (self._tile_size // 10), square[2][1] - (self._tile_size // 10))
vertex_four = (square[3][0] + (self._tile_size // 10), square[3][1] - (self._tile_size // 10)) vertex_four = (square[3][0] + (self._tile_size // 10), square[3][1] - (self._tile_size // 10))
new_square = (vertex_one, vertex_two, vertex_three, vertex_four) new_square = (vertex_one, vertex_two, vertex_three, vertex_four)
pygame.draw.polygon(surface, pygame.Color(square_design.inner_color), new_square, max(self._tile_size // 6, 1)) pygame.draw.polygon(surface, pygame.Color(ConfigurationManager.get("color", square_design.inner_color)), new_square, max(self._tile_size // 6, 1))
# draw square glimmer # draw glimmer
surface.set_at((square[0][0]+3, square[0][1]+3), pygame.Color(255, 255, 255)) surface.set_at((square[0][0]+3, square[0][1]+3), pygame.Color(255, 255, 255))
surface.set_at((square[0][0]+4, square[0][1]+4), pygame.Color(255, 255, 255)) surface.set_at((square[0][0]+4, square[0][1]+4), pygame.Color(255, 255, 255))
surface.set_at((square[0][0]+5, square[0][1]+5), pygame.Color(255, 255, 255))
surface.set_at((square[0][0]+4, square[0][1]+5), pygame.Color(255, 255, 255)) surface.set_at((square[0][0]+4, square[0][1]+5), pygame.Color(255, 255, 255))
surface.set_at((square[0][0]+5, square[0][1]+4), pygame.Color(255, 255, 255)) surface.set_at((square[0][0]+5, square[0][1]+4), pygame.Color(255, 255, 255))
def add_piece(self, piece: Piece) -> None: def add_piece(self, piece: Piece) -> None:
self._points += piece._points self._points += piece._points
self._square_designs += [SquareDesign(piece._color, piece._inner_border_color, piece._border_color) for _ in range(len(piece._points))] self._square_colors += [SquareColor(piece._base_color, piece._inner_color, piece._outer_color) for _ in range(len(piece._points))]
# TODO refactor into multiple functions # TODO refactor into multiple functions
def _complete_rows(self) -> int: def _complete_rows(self) -> int:
@@ -400,7 +406,7 @@ class Stack(Entity):
SoundManager.play_line_complete_sfx() SoundManager.play_line_complete_sfx()
new_points = [] new_points = []
new_square_designs = [] self.new_square_colors = []
for i in range(len(self._points)): for i in range(len(self._points)):
square = self._points[i] square = self._points[i]
if square not in squares_to_exclude: if square not in squares_to_exclude:
@@ -411,16 +417,16 @@ class Stack(Entity):
) )
vertex[1] += self._tile_size * distance_to_move vertex[1] += self._tile_size * distance_to_move
new_points.append(square) new_points.append(square)
new_square_designs.append(self._square_designs[i]) self.new_square_colors.append(self._square_colors[i])
self._points = new_points self._points = new_points
self._square_designs = new_square_designs self._square_colors = self.new_square_colors
return len(rows_completed) return len(rows_completed)
""" """
TODO description TODO description
""" """
class SquareDesign: class SquareColor:
def __init__(self, base_color: str, inner_color: str, outer_color: str): def __init__(self, base_color: str, inner_color: str, outer_color: str):
self.base_color = base_color self.base_color = base_color
self.inner_color = inner_color self.inner_color = inner_color
@@ -438,13 +444,12 @@ class PieceGenerator:
if len(cls._bucket) == 0: if len(cls._bucket) == 0:
cls._generate_bucket(cls._bucket) cls._generate_bucket(cls._bucket)
base_color, inner_border_color, outer_border_color = cls._get_piece_color() base_color, inner_color, outer_color = cls._get_piece_color()
return Piece(cls._get_piece_shape(cls._bucket.pop()), position, base_color, inner_border_color, outer_border_color) return Piece(cls._get_piece_shape(cls._bucket.pop()), position, base_color, inner_color, outer_color)
@classmethod @classmethod
def get_opponent_piece(cls) -> Piece: def get_opponent_piece(cls, base_color: str, inner_color: str, outer_color: str) -> Piece:
base_color, inner_border_color, outer_border_color = cls._get_piece_color(True) return Piece(Piece.Z_SHAPE, (-250, -250), base_color, inner_color, outer_color)
return Piece(Piece.Z_SHAPE, (-250, -250), base_color, inner_border_color, outer_border_color)
@classmethod @classmethod
def _generate_bucket(cls, bucket: List) -> None: def _generate_bucket(cls, bucket: List) -> None:
@@ -473,12 +478,11 @@ class PieceGenerator:
return None return None
@classmethod @classmethod
def _get_piece_color(cls, is_player_two: bool = False) -> Tuple: def _get_piece_color(cls) -> Tuple:
random_number = random.randint(1, 3) random_number = random.randint(1, 3)
player_mod = "player-1" if not is_player_two else "player-2"
base_color = ConfigurationManager.get("color", "piece-" + str(random_number) + "-" + player_mod) base_color = "piece-" + str(random_number) + "-player-1"
inner_border_color = None if random_number != 3 else ConfigurationManager.get("color", "piece-inner-border-1" + "-" + player_mod) inner_color = None if random_number != 3 else "piece-inner-border-1-player-1"
outer_border_color = ConfigurationManager.get("color", "piece-outer-border-1") outer_color = "piece-outer-border-1"
return (base_color, inner_border_color, outer_border_color) return (base_color, inner_color, outer_color)

View File

@@ -157,7 +157,7 @@ class _NetworkConnectionService():
async def _try_receive_message(cls) -> None: async def _try_receive_message(cls) -> None:
try: try:
task = cls._pending_receive_task or asyncio.create_task(cls._websocket.recv()) task = cls._pending_receive_task or asyncio.create_task(cls._websocket.recv())
done, pending = await asyncio.wait({task}, timeout=4e-3) # TODO experiment with the timeout done, pending = await asyncio.wait({task}, timeout=2e-3) # TODO experiment with the timeout
if task in done: if task in done:
json_str = await task json_str = await task
@@ -217,18 +217,22 @@ class _NetworkConnectionService():
# DTOs # DTOs
class PieceDto(): class PieceDto():
def __init__(self, points: List, center: List) -> None: def __init__(self, points: List, center: List, base_color: str, inner_color: str, outer_color: str) -> None:
self.points = points self.points = points
self.center = center self.center = center
self.base_color = base_color
self.inner_color = inner_color
self.outer_color = outer_color
@staticmethod @staticmethod
def create(data: Dict) -> "PieceDto": def create(data: Dict) -> "PieceDto":
return PieceDto(data["points"], data["center"]) return PieceDto(data["points"], data["center"], data["base_color"], data["inner_color"], data["outer_color"])
class StackDto(): class StackDto():
def __init__(self, points: List) -> None: def __init__(self, points: List, square_colors: List[Dict]) -> None:
self.points = points self.points = points
self.square_colors = square_colors
@staticmethod @staticmethod
def create(data: Dict) -> "StackDto": def create(data: Dict) -> "StackDto":
return StackDto(data["points"]) return StackDto(data["points"], data["square_colors"])

View File

@@ -5,7 +5,7 @@ from tetri5.util import ConfigurationManager
from tetri5.util import TextGenerator from tetri5.util import TextGenerator
from tetri5.util import Controller from tetri5.util import Controller
from tetri5.util import SoundManager from tetri5.util import SoundManager
from tetri5.entity import SquareDesign, Well from tetri5.entity import SquareColor, Well
from tetri5.entity import Stack from tetri5.entity import Stack
from tetri5.entity import PieceGenerator from tetri5.entity import PieceGenerator
from tetri5.online import * from tetri5.online import *
@@ -347,28 +347,24 @@ class MultiplayerScene(Scene):
if self._stack_player_one is not None: if self._stack_player_one is not None:
self._stack_player_one.update(elapsed_time) self._stack_player_one.update(elapsed_time)
self._update_stack_player_two()
if self._stack_player_two is not None:
# get opponent stack from server and modify for current client
opponent_stack = MultiplayerService.try_receive_stack()
if opponent_stack is not None:
for square in opponent_stack.points:
for vertex in square:
vertex[0] += 400
if len(opponent_stack.points) > len(self._stack_player_two._points):
for _ in range(len(opponent_stack.points) - len(self._stack_player_two._points)):
self._stack_player_two._square_designs.append(self._last_square_design)
# load opponent stack into game
self._stack_player_two._points = opponent_stack.points
print(opponent_stack)
if self._current_piece_player_one is not None: if self._current_piece_player_one is not None:
MultiplayerService.send_piece(PieceDto(self._current_piece_player_one._points, self._current_piece_player_one._center)) MultiplayerService.send_piece(PieceDto(self._current_piece_player_one._points,\
self._current_piece_player_one._center,\
self._current_piece_player_one._base_color,\
self._current_piece_player_one._inner_color,\
self._current_piece_player_one._outer_color))
if self._stack_player_one is not None: if self._stack_player_one is not None:
MultiplayerService.send_stack(StackDto(self._stack_player_one._points)) MultiplayerService.send_stack(
StackDto(
self._stack_player_one._points,
[
x.__dict__
for x in self._stack_player_one._square_colors
],
)
)
def _update_piece_player_one(self, elapsed_time: int) -> None: def _update_piece_player_one(self, elapsed_time: int) -> None:
if self._current_piece_player_one is not None: if self._current_piece_player_one is not None:
@@ -398,20 +394,35 @@ class MultiplayerScene(Scene):
vertex[0] += 400 vertex[0] += 400
opponent_piece.center[0] += 400 opponent_piece.center[0] += 400
# if it was added to stack then update colors
if opponent_piece.center[1] < self._current_piece_player_two._center[1]:
base_color = self._current_piece_player_two._color
inner_color = self._current_piece_player_two._inner_border_color
outer_color = self._current_piece_player_two._border_color
self._last_square_design = SquareDesign(base_color, inner_color, outer_color)
self._current_piece_player_two = PieceGenerator.get_opponent_piece()
# load opponent piece into game # load opponent piece into game
self._current_piece_player_two._points = opponent_piece.points self._current_piece_player_two._points = opponent_piece.points
self._current_piece_player_two._center = opponent_piece.center self._current_piece_player_two._center = opponent_piece.center
self._current_piece_player_two._base_color = opponent_piece.base_color.replace("player-1", "player-2")
if opponent_piece.inner_color is not None:
self._current_piece_player_two._inner_color = opponent_piece.inner_color.replace("player-1", "player-2")
else:
self._current_piece_player_two._inner_color = None
self._current_piece_player_two._outer_color = opponent_piece.outer_color.replace("player-1", "player-2")
else: else:
self._current_piece_player_two = PieceGenerator.get_opponent_piece() self._current_piece_player_two = PieceGenerator.get_opponent_piece(None, None, None)
def _update_stack_player_two(self) -> None:
if self._stack_player_two is not None:
# get opponent stack from server and modify for current client
opponent_stack = MultiplayerService.try_receive_stack()
if opponent_stack is not None:
for square in opponent_stack.points:
for vertex in square:
vertex[0] += 400
# load opponent stack into game
self._stack_player_two._points = opponent_stack.points
self._stack_player_two._square_colors = [
SquareColor(x["base_color"].replace("player-1", "player-2"),\
x["inner_color"].replace("player-1", "player-2") if x["inner_color"] else None,\
x["outer_color"].replace("player-1", "player-2"))
for x in opponent_stack.square_colors
]
def _get_level_player_one(self) -> int: def _get_level_player_one(self) -> int:
return 0 if self._stack_player_one is None else self._stack_player_one.total_lines // self._lines_per_level return 0 if self._stack_player_one is None else self._stack_player_one.total_lines // self._lines_per_level