Beispiel #1
0
 def __init__(self, game_grid):
     self.game_grid = game_grid
     self.last_view_size = None
     # create copy of game_grid containing CellViews
     self.cell_view_grid = Grid(
         game_grid.get_size()[0], game_grid.get_size()[1], default_val=lambda x, y: CellView(game_grid.get(x, y))
     )
Beispiel #2
0
class GridView(object):
    """Renderer for the game grid.

    Don't scale/translate using the Cairo matrix since it makes the straight
    lines fuzzy.
    """

    def __init__(self, game_grid):
        self.game_grid = game_grid
        self.last_view_size = None
        # create copy of game_grid containing CellViews
        self.cell_view_grid = Grid(
            game_grid.get_size()[0], game_grid.get_size()[1], default_val=lambda x, y: CellView(game_grid.get(x, y))
        )

    def draw(self, c, size):
        """Draw grid view using given context and size."""
        self.last_view_size = size
        tile_size, left, top = self._get_metrics(self.cell_view_grid.get_size(), size)
        # TODO: less awkward way of drawing rotating cells on top
        top_cells = [(x, y, cell_view) for x, y, cell_view in self.cell_view_grid if cell_view.rotation]
        bottom_cells = [
            (x, y, cell_view) for x, y, cell_view in self.cell_view_grid if (x, y, cell_view) not in top_cells
        ]
        for x, y, cell_view in bottom_cells:
            cell_view.draw(c, (left + x * tile_size, top + y * tile_size), tile_size)
        for x, y, cell_view in top_cells:
            cell_view.draw(c, (left + x * tile_size, top + y * tile_size), tile_size)

    def update(self, elapsed):
        """Update animations by elapsed seconds."""
        for _x, _y, cell_view in self.cell_view_grid:
            cell_view.update(elapsed)

    def _get_metrics(self, grid_size, view_size):
        """Return metrics for rendering the grid.

        Returns tile size, and top left location of the grid so it is as large
        as possible and centered.
        """
        tile_size = min(view_size[0] / grid_size[0], view_size[1] / grid_size[1])
        empty_x = view_size[0] - (grid_size[0] * tile_size)
        empty_y = view_size[1] - (grid_size[1] * tile_size)
        return int(tile_size), empty_x / 2, empty_y / 2

    def get_grid_coord_at(self, pixel_position):
        """Translate pixel coordinates to grid coordinates."""
        pixel_position = (int(pixel_position[0]), int(pixel_position[1]))
        g_w, g_h = self.cell_view_grid.get_size()
        tile_size, left, top = self._get_metrics(self.cell_view_grid.get_size(), self.last_view_size)
        x, y = pixel_position
        g_x, g_y = ((x - left) / tile_size, (y - top) / tile_size)
        if 0 <= g_x < g_w and 0 <= g_y < g_h:
            return g_x, g_y
        else:
            return None

    def toggle_cell_lock(self, grid_pos):
        """Toggle lock for cell at given pos."""
        is_locked = self.cell_view_grid.get(*grid_pos).is_locked
        self.cell_view_grid.get(*grid_pos).is_locked = not is_locked

    def rotate_cell(self, grid_pos, change_callback, callback):
        "Set rotation animation for cell at given pos." ""
        cell = self.cell_view_grid.get(*grid_pos)
        if not cell.is_locked:
            cell.rotation = {
                "time": 0,
                "on_end": lambda: (game.rotate_tile(self.game_grid, *grid_pos), callback(), change_callback()),
            }
        else:
            callback()