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)) )
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()