예제 #1
0
    def __init__(self,
                 board: Board,
                 surface: Surface,
                 image_list: List[Surface] = None):
        Sprite.__init__(self)
        self.image = surface
        self.rect = surface.get_rect()
        self.board = board

        width, height = self.rect.width, self.rect.height
        self.board_row_count, self.board_column_count = board.get_board().shape
        self.block_size = Vector2()
        self.block_size.x = width / board.get_board().shape[0]
        self.block_size.y = height / board.get_board().shape[1]

        if image_list is None:
            block_images = [
                self.get_default_image(number)
                for number in range(board.block_kind_count)
            ]
        else:
            block_images = image_list.copy()
            if len(block_images) < board.block_kind_count:
                more_images = [
                    self.get_default_image(number) for number in range(
                        len(image_list), board.block_kind_count)
                ]
                block_images.extend(more_images)
        self.block_images = block_images

        self.new_blocks = []
        self.blocks = []
        self.sync_board()

        self.timeline = Timeline(0)
예제 #2
0
    def test_update_3(self):
        board_obj = Board(4, 4, 4)
        board_obj.board = numpy.array([[0, 0, 0, 0], [1, 1, 2, 1],
                                       [2, 2, 2, 2], [3, 3, 2, 3]])
        to_remove = [(2, 0), (2, 1), (1, 2), (2, 2), (3, 2), (2, 3)]
        to_remove.reverse()
        diff = board_obj.update(to_remove)
        test_indices = [(1, 0), (1, 1), (1, 3), (2, 0), (2, 1), (2, 3), (3, 0),
                        (3, 1), (3, 2), (3, 3)]
        expected = [0, 0, 0, 1, 1, 1, 3, 3, 0, 3]
        for i, e in zip(test_indices, expected):
            self.assertEqual(board_obj.board[i[0], i[1]], e)
        value, count = numpy.unique(board_obj.board, return_counts=True)
        count_dict = dict(zip(value, count))
        self.assertRaises(KeyError, lambda: count_dict[-1])
        self.assertTrue(-1 < numpy.amax(board_obj.board) < 4)

        expected_animations = [(2, 0, -1, -1), (2, 1, -1, -1), (1, 2, -1, -1),
                               (2, 2, -1, -1), (3, 2, -1, -1), (2, 3, -1, -1),
                               (1, 0, 2, 0), (0, 0, 1, 0), (-1, 0, 0, 0),
                               (1, 1, 2, 1), (0, 1, 1, 1), (-1, 1, 0, 1),
                               (0, 2, 3, 2), (-1, 2, 2, 2), (-2, 2, 1, 2),
                               (-3, 2, 0, 2), (1, 3, 2, 3), (0, 3, 1, 3),
                               (-1, 3, 0, 3)]
        self.assertCountEqual(diff, expected_animations)
예제 #3
0
    def __init__(self, context: Context):
        Scene.__init__(self, context)
        self.rows = 8
        self.columns = 8
        self.kinds_of_blocks = 6

        self.board = Board(self.rows, self.columns, self.kinds_of_blocks)
        self.board_position = pygame.Vector2(0, 200)
        self.board_size = pygame.Vector2(400, 400)
        board_size_int = int(self.board_size.x), int(self.board_size.y)
        board_region = pygame.Surface(board_size_int)
        board_region.blit(self.context.assets["board_image"], (0, 0, 400, 400))
        self.board_sprite = BoardSprite(self.board, board_region,
                                        context.assets["icon_list"])

        self.selected = []
        self.selecting = False
        self.path_sprite = PathSprite(self.board_position, self.board_size,
                                      self.board_sprite.get_block_size())

        play_position = pygame.Vector2(0, 50)
        self.play = self.context.data["play"]
        self.play_sprite = PlaySprite(context.data["play"],
                                      context.assets["play_image"],
                                      play_position)
        self.animation_playing = [False, False]
예제 #4
0
 def test_create(self):
     board_obj = Board(8, 8, 3)
     board = board_obj.get_board()
     self.assertEqual(board.shape[0] * board.shape[1], 8 * 8)
     self.assertTrue(isinstance(board[4, 2], numpy.int8))
     count = board_obj.get_count()
     self.assertEqual(len(count), 3)
     self.assertEqual(sum(count), 8 * 8)
예제 #5
0
 def test_render(self):
     board = Board(8, 8, 2)
     board.board = numpy.zeros([8, 8], numpy.int8)
     board.board[4][2] = 1
     board_surface = Surface((400, 400))
     image_list = [Surface((50, 50)), Surface((50, 50))]
     image_list[0].fill(Color(200, 0, 0))
     image_list[1].fill(Color(0, 200, 0))
     board_sprite = BoardSprite(board, board_surface, image_list)
     screen = Surface((400, 600))
     position = Vector2(0, 100)
     board_sprite.render(screen, position, [])
     self.assertEqual(screen.get_at((125, 325)), Color(0, 200, 0))
     self.assertEqual(screen.get_at((225, 225)), Color(200, 0, 0))
예제 #6
0
 def test_create(self):
     board = Board(8, 8, 3)
     board_surface = Surface((400, 400))
     board_sprite = BoardSprite(board, board_surface)
     self.assertEqual(board_sprite.block_size, Vector2(400 / 8, 400 / 8))
     self.assertEqual(len(board_sprite.blocks), 8 * 8)
     self.assertEqual(len(board_sprite.block_images), 3)
     self.assertTrue(isinstance(board_sprite.block_images[2], Surface))
예제 #7
0
 def setUp(self) -> None:
     global scene
     scene = MainScene(context)
     scene.board = Board(4, 4, 4)
     scene.board.board = board.copy()
     scene.board_region = pygame.Surface((400, 400))
     scene.board_position = pygame.Vector2(0, 100)
     scene.board_sprite = BoardSprite(scene.board, scene.board_region)
예제 #8
0
 def test_shuffle(self):
     board = Board(4, 4, 3)
     board.board = numpy.array([[0, 1, 0, 0], [0, 2, 2, 1], [1, 1, 0, 1],
                                [2, 0, 2, 2]])
     prev_count = [6, 5, 5]
     board.count = prev_count.copy()
     board.shuffle()
     new_count = board.count
     self.assertTrue(board.is_possible_to_move())
     self.assertEqual(prev_count, new_count)
예제 #9
0
class MainScene(Scene):
    def __init__(self, context: Context):
        Scene.__init__(self, context)
        self.rows = 8
        self.columns = 8
        self.kinds_of_blocks = 6

        self.board = Board(self.rows, self.columns, self.kinds_of_blocks)
        self.board_position = pygame.Vector2(0, 200)
        self.board_size = pygame.Vector2(400, 400)
        board_size_int = int(self.board_size.x), int(self.board_size.y)
        board_region = pygame.Surface(board_size_int)
        board_region.blit(self.context.assets["board_image"], (0, 0, 400, 400))
        self.board_sprite = BoardSprite(self.board, board_region,
                                        context.assets["icon_list"])

        self.selected = []
        self.selecting = False
        self.path_sprite = PathSprite(self.board_position, self.board_size,
                                      self.board_sprite.get_block_size())

        play_position = pygame.Vector2(0, 50)
        self.play = self.context.data["play"]
        self.play_sprite = PlaySprite(context.data["play"],
                                      context.assets["play_image"],
                                      play_position)
        self.animation_playing = [False, False]

    def on_create(self, context: Context):
        pass

    def on_mouse_down(self, button: Tuple, position: Tuple):
        if not any(self.animation_playing):
            if button[0]:
                block = mouse_row, mouse_col = self.mouse_on_which_block(
                    position)
                if mouse_row > -1 and mouse_col > -1:
                    self.selecting = True
                    self.selected.append(block)

    def on_mouse_move(self, position: Tuple):
        if not any(self.animation_playing):
            if self.selecting:
                board = self.board.get_board()
                mouse = mouse_row, mouse_col = self.mouse_on_which_block(
                    position)
                last_row, last_col = self.selected[-1]
                backtrack = len(
                    self.selected) > 1 and mouse == self.selected[-2]
                if backtrack:
                    self.selected.pop()
                    return
                on_screen = mouse_row > -1 and mouse_col > -1
                is_neighbour = abs(mouse_row - last_row) < 2 and abs(
                    mouse_col - last_col) < 2
                same_colour = board[mouse_row][mouse_col] == board[last_row][
                    last_col]
                not_same = not (mouse_row == last_row
                                and mouse_col == last_col)
                no_cross = self.selected.count((mouse_row, mouse_col)) == 0
                correct = all(
                    [on_screen, is_neighbour, same_colour, not_same, no_cross])
                if correct:
                    self.selected.append(mouse)

    def on_mouse_up(self, button: Tuple, position: Tuple):
        if not any(self.animation_playing):
            if len(self.selected) > 2:
                board = self.board.get_board()
                row, col = self.selected[0]
                update_kind = board[row, col]
                update_count = len(self.selected)
                self.play.update(update_kind, update_count)
                diff = self.board.update(self.selected)

                self.board_sprite.add_animation(diff)
                self.board_sprite.play_animation(pygame.time.get_ticks())
                self.play_sprite.add_animation(update_kind, update_count)
                self.play_sprite.play_animation(pygame.time.get_ticks())
            self.selected = []
            self.selecting = False

    def on_animation_begin(self, timeline_id: int):
        self.animation_playing[timeline_id] = True

    def on_animation_end(self, timeline_id: int):
        self.animation_playing[timeline_id] = False
        if timeline_id == 0:
            self.board_sprite.on_animation_end()
        elif timeline_id == 1:
            self.play_sprite.on_animation_end()

        if not any(self.animation_playing):
            if not self.board.is_possible_to_move():
                diff = self.board.shuffle()
                self.board_sprite.add_animation(diff)
                self.board_sprite.play_animation(pygame.time.get_ticks())

    def update(self, ticks: int):
        if self.animation_playing[0]:
            self.board_sprite.update(ticks)
        if self.animation_playing[1]:
            self.play_sprite.update(ticks)

    def render(self):
        self.board_sprite.render(self.context.screen, self.board_position,
                                 self.selected)
        self.path_sprite.render(self.context.screen, self.selected)
        self.play_sprite.render(self.context.screen,
                                self.board_sprite.block_images)

    def mouse_on_which_block(self, position: Tuple) -> Tuple:
        block_size = self.board_sprite.get_block_size()
        mouse_position = pygame.Vector2(position)
        offset = mouse_position - self.board_position
        column_index, column_remain = divmod(offset.x, block_size.x)
        row_index, row_remain = divmod(offset.y, block_size.y)
        column_index = column_index if -1 < column_index < self.columns else -1
        row_index = row_index if -1 < row_index < self.rows else -1

        row_col = int(row_index), int(column_index)
        touch_ratio = 0.8
        touch_low, touch_high = 0.5 - touch_ratio / 2, 0.5 + touch_ratio / 2
        column_in_touch = touch_low < column_remain / block_size.x < touch_high
        row_in_touch = touch_low < row_remain / block_size.y < touch_high
        if column_in_touch and row_in_touch:
            return row_col
        else:
            return -1, -1
예제 #10
0
 def test_check_if_possible_1(self):
     board = Board(4, 4, 3)
     board.board = numpy.array([[1, 0, 0, 1], [0, 2, 2, 0], [0, 1, 0, 1],
                                [2, 0, 2, 2]])
     self.assertTrue(board.is_possible_to_move())