예제 #1
0
    def __init__(self, stdscr, start_pos, dimensions):
        # Very clean and totally maintainable code
        height, width = dimensions
        start_y, start_x = start_pos

        self.win = curses.newwin(height, width, start_y, start_x)
        self.win.box()
        stdscr.refresh()
        self.win.refresh()

        self.dim = [height, width]
        self.start_pos = [start_y, start_x]

        self.status = GameStatus()

        self.shapes = [
            [[1, 1, 1], [0, 0, 1]],
            [[0, 1], [1, 1], [0, 1]],
            [[1, 1], [1, 1]],
            [[0, 0, 1], [1, 1, 1]],
            [[1, 1, 1, 1]],
            [[1, 1, 0], [0, 1, 1]]
        ]

        self.active_block = self.spawn_block()
        self.heap = Heap(1, 1, height - 2, width - 2)
        self.draw()
예제 #2
0
class Board(object):
    """
    The game board. The central object which controls spawning
    and movement of blocks as well as the heap of block remnants.
    """
    def __init__(self, stdscr, start_pos, dimensions):
        # Very clean and totally maintainable code
        height, width = dimensions
        start_y, start_x = start_pos

        self.win = curses.newwin(height, width, start_y, start_x)
        self.win.box()
        stdscr.refresh()
        self.win.refresh()

        self.dim = [height, width]
        self.start_pos = [start_y, start_x]

        self.status = GameStatus()

        self.shapes = [
            [[1, 1, 1], [0, 0, 1]],
            [[0, 1], [1, 1], [0, 1]],
            [[1, 1], [1, 1]],
            [[0, 0, 1], [1, 1, 1]],
            [[1, 1, 1, 1]],
            [[1, 1, 0], [0, 1, 1]]
        ]

        self.active_block = self.spawn_block()
        self.heap = Heap(1, 1, height - 2, width - 2)
        self.draw()

    def random_shape(self):
        """Pick a shape from the presets at random."""
        shape_index = randint(0, len(self.shapes) - 1)
        return self.shapes[shape_index]

    def spawn_block(self):
        """Create and return a new bock with random shape."""
        spawn_y = self.start_pos[0] + 1
        spawn_x = self.start_pos[1] + (self.dim[1] / 2)
        block = Block(self.random_shape(), random_color(), spawn_y, spawn_x)
        return block

    def out_of_bounds(self, coord_y, coord_x):
        """Check if the given location is outside the game board"""
        min_y = self.start_pos[0]
        max_y = self.start_pos[0] + self.dim[0] - 1
        min_x = self.start_pos[1]
        max_x = self.start_pos[1] + self.dim[1] - 1
        return coord_y <= min_y or coord_y >= max_y \
                or coord_x <= min_x or coord_x >= max_x

    def block_movable(self, coord_y, coord_x):
        """
        Return if the active block can be safely moved into
        the specified location.
        """
        for new_y, new_x in self.active_block.gen_coords(coord_y, coord_x):
            if self.out_of_bounds(new_y, new_x):
                return False

            # Blue 'ghost' block moves through the heap
            if self.active_block.color != 3 \
                    and self.heap.collision(new_y, new_x):
                return False
        return True

    def update_game_status(self):
        """Increase the score and check if the game should end."""
        self.status.add_score(self.heap.get_removed())

        coord_y, coord_x = self.active_block.position
        if not self.block_movable(coord_y + 1, coord_x):
            self.status.over = True

    def advance_block(self):
        """
        Move the active block block one square down. If the block cannot be
        moved, it is added to the heap and a new block is spawned. The function
        returns True if the block was moved, False otherwise.
        """
        coord_y, coord_x = self.active_block.position
        if self.block_movable(coord_y + 1, coord_x):
            self.active_block.set_position(coord_y + 1, coord_x)
            return True

        self.heap.add(self.active_block)
        self.active_block = self.spawn_block()
        self.update_game_status()
        return False

    def lshift_block(self):
        """Move the active block on square to the left, if possible."""
        coord_y, coord_x = self.active_block.position
        if self.block_movable(coord_y, coord_x - 1):
            self.active_block.set_position(coord_y, coord_x - 1)

    def rshift_block(self):
        """Move the active block on square to the right, if possible."""
        coord_y, coord_x = self.active_block.position
        if self.block_movable(coord_y, coord_x + 1):
            self.active_block.set_position(coord_y, coord_x + 1)

    def land_block(self):
        """Move the active block all the way down."""
        while self.advance_block():
            pass # wat

    def rotate_block(self):
        """Rotate the active block 90 degrees right"""
        coord_y, coord_x = self.active_block.position
        rotation = self.active_block.gen_rotation()
        for new_y, new_x in \
                self.active_block.gen_coords(coord_y, coord_x, shape=rotation):
            if self.out_of_bounds(new_y, new_x) or \
                    (self.active_block.color != 3 and \
                    self.heap.collision(new_y, new_x)):
                return
        self.active_block.rotate(rot=rotation)

    def draw_active_block(self):
        """Draw the active block on the curses display."""
        color = self.active_block.color
        for coord_y, coord_x in self.active_block.coords():
            curses_draw_spot(self.win, coord_y, coord_x, color)

    def draw_heap(self):
        """Draw the block remnant heap on the curses display."""
        for coord_y, coord_x, color in self.heap.contents():
            curses_draw_spot(self.win, coord_y, coord_x, color)

    def draw(self):
        """Draw all the game elements and refresh the curses window."""
        self.draw_heap()
        self.draw_active_block()
        self.win.refresh()

    def game_over(self):
        """Return the game status, True if game should end, False otherwise."""
        return self.status.over

    def game_speed(self):
        """Return the game step time in ms"""
        return self.status.game_speed()