Beispiel #1
0
 def __init__(self, position):
     self.can_climb = False
     self.is_climbing = False
     self.hook_type = HookType.rope
     self.max_hooks = 1
     self.image = pygame.image.load('assets/gfx/Player.png')
     self.sheet_size = Vec2D(self.image.get_width(),
                             self.image.get_height())
     Object2D.__init__(
         self, Vec2D(self.image.get_width() / 4,
                     self.image.get_height() / 2), position)
     self.rect = (0, 0, self.width, self.height)
     self.force = Vec2D()
     self.direction = Vec2D()
     self.frame_left = 0
     self.frame_right = 0
     self.last_direction = 0
     self.last_shooting = 0
     self.can_shoot = True
     self.ladder_span = Vec2D()
     self.invulnerability_timer = 0
     self.invulnerable = False
     self.invulnerability_rect = pygame.Surface((self.width, self.height),
                                                pygame.SRCALPHA, 32)
     self.invulnerability_rect.fill((255, 0, 255, 192))
Beispiel #2
0
 def __init__(self, position, bonus_type):
     self.bonus_type = bonus_type
     Object2D.__init__(self, Vec2D(BONUS_SIZE, BONUS_SIZE), position)
     self.force = Vec2D()
     self.to_kill = False
     self.fall = True
     self.timer = BONUS_DURATION
Beispiel #3
0
 def split_ball(self, ball):
     self.play_sound('BallPop.wav')
     if ball.radius > MIN_BALL_RADIUS:
         self.balls.append(Ball(ball.radius//2,
                                Vec2D(ball.x - ball.radius//2, ball.y),
                                Vec2D(-abs(ball.force.x), -GRAVITY)))
         self.balls.append(Ball(ball.radius//2,
                                Vec2D(ball.x + ball.radius//2, ball.y),
                                Vec2D(abs(ball.force.x), -GRAVITY)))
     self.spawn_bonus(ball.position)
     self.score += ball.radius
Beispiel #4
0
 def calculate_force(self, force):
     """Function takes as a parameter the Vec2D object returned from the
     collision function and changes the x/y direction if the force isn't 0
     """
     if force.x:
         self.force = Vec2D(-self.force.x, self.force.y)
     if force.y:
         if self.y < self.max_height:
             self.force = Vec2D(self.force.x, 0)
         else:
             if self.falling:
                 self.force = Vec2D(
                     self.force.x, -(abs(
                         (self.y - self.max_height) * 2 * GRAVITY)**.5))
             else:
                 self.force = Vec2D(self.force.x, -self.force.y)
Beispiel #5
0
 def __init__(self, height, position, hook_type):
     self.hook_type = hook_type
     self.to_kill = False
     Object2D.__init__(self, Vec2D(6, height),
                       position)
     self.expand = True
     self.timer = HOOK_DURATION
Beispiel #6
0
 def __init__(self, radius, position, force):
     Object2D.__init__(self, Vec2D(radius * 2, radius * 2), position)
     self.radius = radius
     self.position = position
     self.force = force
     self.falling = True
     if force.y < 0:
         self.falling = False
     self.max_height = SCREEN_HEIGHT - 150 - radius * 4
Beispiel #7
0
 def update(self, time_passed):
     self.force += (0, GRAVITY * time_passed)
     self.position += self.force * time_passed
     if self.x < self.radius or self.x > SCREEN_WIDTH - self.radius:
         self.force = Vec2D(-self.force.x, self.force.y)
         if self.x < self.radius:
             self.position = Vec2D(2 * self.radius - self.x, self.y)
         else:
             self.position = Vec2D(
                 2 * (SCREEN_WIDTH - self.radius) - self.x, self.y)
     if self.y > SCREEN_HEIGHT - self.radius:
         self.position = Vec2D(self.x,
                               2 * (SCREEN_HEIGHT - self.radius) - self.y)
         self.force = Vec2D(
             self.force.x,
             -(((self.y - self.max_height) * 2 * GRAVITY)**.5))
     if self.force.y > 0:
         self.falling = True
     else:
         self.falling = False
Beispiel #8
0
 def update(self, time_passed):
     if not self.fall:
         self.timer -= time_passed
         if self.timer < 0:
             self.to_kill = True
     else:
         self.force += (0, GRAVITY * time_passed)
         self.position += (0, self.force.y * time_passed)
         if self.y > SCREEN_HEIGHT - self.height:
             self.position = Vec2D(self.x, SCREEN_HEIGHT - self.height)
             self.fall = False
Beispiel #9
0
 def player_shoot(self):
     if not self.player.is_climbing and \
        self.player.max_hooks > len(self.hooks) and self.player.can_shoot:
         self.play_sound('HookShoot.wav')
         self.hooks.append(Hook(20, Vec2D(self.player.x +
                                          self.player.width/2,
                                          self.player.y +
                                          self.player.height - 20),
                                self.player.hook_type))
         self.player.last_shooting = HOOK_RELOAD_TIME
         self.player.can_shoot = False
Beispiel #10
0
 def add_option(self, caption, function, arg=None):
     text = self.font.render(caption, True, self.color)
     text_selected = self.font.render('-> ' + caption + ' <-', True,
                                      self.selected_color)
     if arg:
         self.labels[len(self.labels.items())] = (text, text_selected,
                                                  function, arg)
     else:
         self.labels[len(self.labels.items())] = (text, text_selected,
                                                  function)
     if len(self.labels.items()) == 1:
         self.selected_option = 0
     self.positions = []
     items = len(self.labels.items())
     max_height = 0
     if self.title:
         max_height = self.title_text.get_rect().height
         items += 2
     for key, value in self.labels.items():
         text_height = value[0].get_rect().height
         if text_height > max_height:
             max_height = text_height
     current_y_pos = (SCREEN_HEIGHT -
                      (items * max_height +
                       (items - 1) * MENU_LABEL_MARGIN)) // 2
     if self.y_position:
         current_y_pos = self.y_position
     if self.title:
         x_pos = (SCREEN_WIDTH - self.title_text.get_rect().width) // 2
         y_pos = current_y_pos + (max_height -
                                  self.title_text.get_rect().height) // 2
         self.title_position = Vec2D(x_pos, y_pos)
         current_y_pos += 2 * (max_height + MENU_LABEL_MARGIN)
     for key, value in self.labels.items():
         x_pos = (SCREEN_WIDTH - value[0].get_rect().width) // 2
         y_pos = current_y_pos + (max_height -
                                  value[0].get_rect().height) // 2
         position = Vec2D(x_pos, y_pos)
         current_y_pos += max_height + MENU_LABEL_MARGIN
         self.positions.append(position)
Beispiel #11
0
 def __init__(self, title=None, y_position=0):
     self.labels = OrderedDict()
     self.font = pygame.font.SysFont(None, MENU_LABEL_FONT_SIZE)
     self.selected_color = (255, 0, 0)
     self.color = (255, 255, 255)
     self.selected_option = None
     self.title = title
     self.y_position = y_position
     if self.title:
         self.title_text = self.font.render(title, True, self.color)
         self.title_position = Vec2D()
     self.music_path = 'assets/music/Menu.wav'
     self.positions = []
Beispiel #12
0
 def process_event(self, event):
     key = pygame.key.get_pressed()
     direction = Vec2D()
     if key[pygame.K_LEFT]:
         direction -= (1, 0)
     if key[pygame.K_RIGHT]:
         direction += (1, 0)
     if key[pygame.K_UP]:
         direction -= (0, 1)
     if key[pygame.K_DOWN]:
         direction += (0, 1)
     self.player.set_direction(direction)
     if key[pygame.K_SPACE]:
         self.player_shoot()
Beispiel #13
0
 def update(self, time_passed):
     if not self.expand:
         self.timer -= time_passed
         if self.timer < 0:
             self.to_kill = True
     if self.y > 0 and self.expand:
         increment = HOOK_SPEED * time_passed
         self.size += (0, increment)
         self.position -= (0, increment)
     if self.y < 0:
         if self.hook_type == HookType.rope:
             self.to_kill = True
         elif self.hook_type == HookType.chain:
             self.size += (0, self.y)
             self.position = Vec2D(self.x, 0)
             self.expand = False
Beispiel #14
0
    def get_ladder_image(self, string, width, height):
        image_library = self.ladder_cache.get(string)
        size_string = str(width) + 'x' + str(height)
        image = None
        if image_library is None:
            image_library = {}
            self.ladder_cache[string] = image_library

        image = image_library.get(size_string)
        if image is None:
            tile_image = pygame.image.load(string)
            tile = Vec2D(tile_image.get_size())
            image = pygame.Surface([width, height], flags=pygame.SRCALPHA)
            for y in range(0, height + 1, tile.height):
                image.blit(tile_image, (0, y))
            self.ladder_cache[string][size_string] = image
        return image
Beispiel #15
0
    def get_obstacle_image(self, string, width, height):
        image_library = self.obstacle_cache.get(self.obstacle_image)
        size_string = str(width) + 'x' + str(height)
        image = None
        if image_library is None:
            image_library = {}
            self.obstacle_cache[string] = image_library

        image = image_library.get(size_string)
        if image is None:
            tile_image = pygame.image.load(self.obstacle_image)
            tile = Vec2D(tile_image.get_size())
            image = pygame.Surface([width, height])
            for x in range(0, width + 1, tile.width):
                for y in range(0, height + 1, tile.height):
                    image.blit(tile_image, (x, y))
            self.obstacle_cache[string][size_string] = image
        return image
Beispiel #16
0
def box_to_box(box1, box2, player=False, bonus=False, hook=False):
    """Separating Axis Theorem used for AABB collision and different fixations
    based on parameters. If one of the flags is set to True, the first object
    should be movable and the second static.
    """
    if (abs(box1.x + box1.width / 2 - (box2.x + box2.width / 2)) >=
        (box1.width / 2 + box2.width / 2)):
        return False

    if (abs(box1.y + box1.height / 2 - (box2.y + box2.height / 2)) >=
        (box1.height / 2 + box2.height / 2)):
        return False

    if player:
        if int(box1.y + box1.height) in range(int(box2.y + 10)):
            box1.position = Vec2D(box1.x, box2.y - box1.height)
            box1.force = Vec2D(box1.force.x, 0)
        else:
            if box1.x + box1.width - box2.x < box2.x + box2.width - box1.x:
                box1.position = Vec2D(box2.x - box1.width, box1.y)
            else:
                box1.position = Vec2D(box2.x + box2.width, box1.y)

    if bonus:
        box1.position = Vec2D(box1.x, box2.y - box1.height)
        box1.force = Vec2D(box1.force.x, 0)
        box1.fall = False

    if hook and box1.y > box2.y:
        if box1.hook_type == HookType.chain:
            fixation = box2.y + box2.height - box1.y
            box1.position += (0, fixation)
            box1.size -= (0, fixation)
            box1.expand = False
        elif box1.hook_type == HookType.rope:
            box1.to_kill = True

    return True
Beispiel #17
0
    def check_collisions(self):
        for ball in self.balls:
            for obstacle in self.obstacles:
                result = ball_to_box(ball, obstacle, True)
                if result:
                    ball.calculate_force(result)

        if self.player.invulnerable:
            for ball in self.balls:
                result = ball_to_box(ball, self.player, True)
                if result:
                    ball.calculate_force(result)

        self.player.can_climb = False
        for ladder in self.ladders:
            if player_to_ladder(self.player, ladder):
                self.player.can_climb = True
                self.player.ladder_span = Vec2D(ladder.y, ladder.y +
                                                ladder.height)

        if not self.player.is_climbing:
            for obstacle in self.obstacles:
                box_to_box(self.player, obstacle, player=True)

        for hook in self.hooks:
            for obstacle in self.obstacles:
                if box_to_box(hook, obstacle, hook=True):
                    break

        for hook_index in range(len(self.hooks) - 1, -1, -1):
            hook = self.hooks[hook_index]
            if hook.to_kill:
                del self.hooks[hook_index]
            else:
                for ball_index in range(len(self.balls) - 1, -1, -1):
                    ball = self.balls[ball_index]
                    if ball_to_box(ball, hook):
                        self.split_ball(ball)
                        del self.balls[ball_index]
                        del self.hooks[hook_index]
                        break

        for bonus_index in range(len(self.bonuses) - 1, -1, -1):
            bonus = self.bonuses[bonus_index]
            if bonus.to_kill:
                del self.bonuses[bonus_index]
            elif box_to_box(bonus, self.player):
                self.activate_bonus(bonus)
                del self.bonuses[bonus_index]

        for bonus_index in range(len(self.bonuses) - 1, -1, -1):
            bonus = self.bonuses[bonus_index]
            for obstacle in self.obstacles:
                box_to_box(bonus, obstacle, bonus=True)

        for ball in self.balls:
            if ball_to_box(ball, self.player):
                self.lives -= 1
                if self.lives:
                    self.load_level(self.current_level)
                    break
                else:
                    self.game_over = True
                    break
Beispiel #18
0
 def load_game(self, file_name):
     file_path = 'assets/save/' + str(file_name) + '.save'
     if not os.path.isfile(file_path):
         return None
     file = open(file_path, 'r')
     lines = file.readlines()
     lines = list(map(str.rstrip, lines))
     match = re.match(r'level (\d+)', lines[0])
     level_id = list(map(int, match.groups()))[0]
     self.load_level(level_id, scene_only=True, keep_score=False)
     ball_regex = (r'ball radius (\d+) pos (\d+), ' +
                   '(\d+) force (-?\d+), (-?\d+)')
     player_regex = (r'player pos (\d+), (\d+) hooktype (\d+) maxhooks ' +
                     '(\d+) force (-?\d+), (-?\d+)')
     bonus_regex = (r'bonus pos (\d+), (\d+) bonustype (\d+) duration ' +
                    '(\d+.\d+|\d+) force (-?\d+), (-?\d+) fall (\d+) ' +
                    'tokill (\d+)')
     hook_regex = (r'hook pos (\d+), (\d+) hooktype (\d+) height (\d+) ' +
                   'duration (\d+.\d+|\d+) expand (\d+) tokill (\d+)')
     world_regex = r'world ballstimer (\d+.\d+|\d+) score (\d+) lives (\d+)'
     for line in lines[1:]:
         if re.match(ball_regex, line):
             match = re.match(ball_regex, line)
             radius, x, y, force_x, force_y = list(map(int, match.groups()))
             self.balls.append(Ball(radius, Vec2D(x, y),
                                    Vec2D(force_x, force_y)))
         elif re.match(player_regex, line):
             match = re.match(player_regex, line)
             pos_x = int(match.group(1))
             pos_y = int(match.group(2))
             hook_type = int(match.group(3))
             max_hooks = int(match.group(4))
             force_x = int(match.group(5))
             force_y = int(match.group(6))
             self.player = Player(Vec2D(pos_x, pos_y))
             self.player.hook_type = hook_type
             self.player.max_hooks = max_hooks
             self.player.force = Vec2D(force_x, force_y)
         elif re.match(bonus_regex, line):
             match = re.match(bonus_regex, line)
             pos_x = int(match.group(1))
             pos_y = int(match.group(2))
             bonus_type = int(match.group(3))
             duration = float(match.group(4))
             force_x = int(match.group(5))
             force_y = int(match.group(6))
             fall = bool(int(match.group(7)))
             to_kill = bool(int(match.group(8)))
             bonus = Bonus(Vec2D(pos_x, pos_y), bonus_type)
             bonus.timer = duration
             bonus.force = Vec2D(force_x, force_y)
             bonus.fall = fall
             bonus.to_kill = to_kill
             self.bonuses.append(bonus)
         elif re.match(hook_regex, line):
             match = re.match(hook_regex, line)
             pos_x = int(match.group(1))
             pos_y = int(match.group(2))
             hook_type = int(match.group(3))
             height = int(match.group(4))
             duration = float(match.group(5))
             expand = bool(int(match.group(6)))
             to_kill = bool(int(match.group(7)))
             hook = Hook(height, Vec2D(pos_x, pos_y), hook_type)
             hook.timer = duration
             hook.expand = expand
             hook.to_kill = to_kill
             self.hooks.append(hook)
         elif re.match(world_regex, line):
             match = re.match(world_regex, line)
             balls_timer, score, lives = list(map(float, match.groups()))
             self.balls_timer = balls_timer
             if balls_timer > 0:
                 self.balls_paused = True
             else:
                 self.balls_paused = False
             self.score = int(score)
             self.lives = int(lives)
Beispiel #19
0
 def load_level(self, level_index, scene_only=False, keep_score=True):
     self.active = True
     file_path = 'assets/levels/' + str(level_index) + '.pang'
     if not os.path.isfile(file_path):
         return None
     self.balls = []
     self.bonuses = []
     self.hooks = []
     self.obstacles = []
     self.ladders = []
     self.sound_library = {}
     self.text_cache = {}
     self.balls_paused = False
     self.balls_timer = 0
     if not keep_score:
         self.score = 0
     self.current_level = level_index
     self.level_pause = True
     self.pause_remaining = PAUSE_ON_LEVEL_LOAD
     file = open(file_path, 'r')
     lines = file.readlines()
     lines = list(map(str.rstrip, lines))
     match = re.match(r'background (\S+)', lines[0])
     background = list(map(str, match.groups()))[0]
     self.background = pygame.image.load('assets/gfx/' + background)
     tile_name = ''
     ball_regex = (r'ball radius (\d+) pos (\d+), ' +
                   '(\d+) force (-?\d+), (-?\d+)')
     obstacle_regex = r'obstacle size (\d+), (\d+) pos (\d+), (\d+)'
     for line in lines[1:]:
         if not scene_only and re.match(ball_regex, line):
             match = re.match(ball_regex, line)
             radius, x, y, force_x, force_y = list(map(int, match.groups()))
             self.balls.append(Ball(radius, Vec2D(x, y),
                                    Vec2D(force_x, force_y)))
         elif re.match(obstacle_regex, line):
             match = re.match(obstacle_regex, line)
             width, height, x, y = list(map(int, match.groups()))
             self.obstacles.append(Obstacle(Vec2D(width, height),
                                            Vec2D(x, y)))
         elif not scene_only and re.match(r'player pos (\d+), (\d+)', line):
             match = re.match(r'player pos (\d+), (\d+)', line)
             point_x, point_y = list(map(int, match.groups()))
             point = Vec2D(point_x, point_y)
             self.player = Player(point)
         elif re.match(r'ladder height (\d+) pos (\d+), (\d+)', line):
             match = re.match(r'ladder height (\d+) pos (\d+), (\d+)', line)
             height, point_x, point_y = list(map(int, match.groups()))
             point = Vec2D(point_x, point_y)
             self.ladders.append(Ladder(height, point))
         elif re.match(r'music (\S+)', line):
             match = re.match(r'music (\S+)', line)
             music = list(map(str, match.groups()))[0]
             self.music_path = 'assets/music/' + music
             pygame.mixer.music.load(self.music_path)
             pygame.mixer.music.play(-1)
         elif re.match(r'bricktile (\S+)', line):
             match = re.match(r'bricktile (\S+)', line)
             tile_name = list(map(str, match.groups()))[0]
             self.gui_drawer.obstacle_image = 'assets/gfx/' + tile_name
     return True
Beispiel #20
0
 def setUp(self):
     self.box = Obstacle(Vec2D(200, 200), Vec2D(200, 200))
     self.test_boxes = []
     self.test_boxes.append(Obstacle(Vec2D(400, 100), Vec2D(100, 250)))
     self.test_boxes.append(Obstacle(Vec2D(100, 400), Vec2D(250, 100)))
     self.test_boxes.append(Obstacle(Vec2D(100, 200), Vec2D(250, 100)))
     self.test_boxes.append(Obstacle(Vec2D(100, 200), Vec2D(250, 300)))
     self.test_boxes.append(Obstacle(Vec2D(200, 100), Vec2D(100, 250)))
     self.test_boxes.append(Obstacle(Vec2D(200, 100), Vec2D(300, 250)))
     self.test_boxes.append(Obstacle(Vec2D(200, 200), Vec2D(300, 100)))
     self.test_boxes.append(Obstacle(Vec2D(200, 200), Vec2D(100, 100)))
     self.test_boxes.append(Obstacle(Vec2D(200, 200), Vec2D(100, 300)))
     self.test_boxes.append(Obstacle(Vec2D(200, 200), Vec2D(300, 300)))
     self.test_boxes.append(Obstacle(Vec2D(200, 200), Vec2D(300, -50)))
     self.test_boxes.append(Obstacle(Vec2D(200, 200), Vec2D(500, 500)))
     self.test_boxes.append(Obstacle(Vec2D(200, 200), Vec2D(500, 300)))
     self.test_boxes.append(Obstacle(Vec2D(200, 200), Vec2D(400, 200)))
     self.test_boxes.append(Obstacle(Vec2D(200, 200), Vec2D(200, 0)))
     self.player_results = []
     self.test_boxes.append(Obstacle(Vec2D(80, 100), Vec2D(200, 105)))
     self.player_results.append(Vec2D(200, 100))
     self.test_boxes.append(Obstacle(Vec2D(80, 100), Vec2D(350, 115)))
     self.player_results.append(Vec2D(400, 115))
     self.test_boxes.append(Obstacle(Vec2D(80, 100), Vec2D(250, 115)))
     self.player_results.append(Vec2D(120, 115))
Beispiel #21
0
    def update(self, time_passed):
        if self.invulnerable:
            self.invulnerability_timer -= time_passed
            if self.invulnerability_timer <= 0:
                self.invulnerability_timer = 0
                self.invulnerable = False

        if not self.is_climbing:
            if self.y < SCREEN_HEIGHT - self.height:
                self.force += (0, GRAVITY * time_passed)
                self.position += (0, self.force.y * time_passed)
            if self.direction.x:
                self.position += ((self.direction.x * time_passed *
                                   PLAYER_SPEED), 0)
                if self.direction.x > 0:
                    self.frame_right += time_passed
                    self.frame_left = 0
                else:
                    self.frame_left += time_passed
                    self.frame_right = 0
            else:
                self.frame_right = 0
                self.frame_left = 0
            if self.x < 0:
                self.position = Vec2D(0, self.y)
            elif self.x > SCREEN_WIDTH - self.width:
                self.position = Vec2D(SCREEN_WIDTH - self.width, self.y)
        else:
            self.force = Vec2D(self.force.x, 0)

        if self.can_climb:
            if self.direction.y:
                self.position += (0, (self.direction.y * time_passed *
                                      PLAYER_SPEED))
                self.is_climbing = True
                if self.y + self.height <= self.ladder_span[0]:
                    self.position = Vec2D(self.x,
                                          self.ladder_span[0] - self.height)
                    self.can_climb = True
                    self.is_climbing = False
                elif self.y + self.height >= self.ladder_span[1]:
                    self.position = Vec2D(self.x,
                                          self.ladder_span[1] - self.height)
                    self.can_climb = True
                    self.is_climbing = False
                self.frame_right = 0
                self.frame_left = 0
        else:
            self.is_climbing = False
        if self.y > SCREEN_HEIGHT - self.height:
            self.position = Vec2D(self.x, SCREEN_HEIGHT - self.height)
            self.is_climbing = False

        #calculate animation to display
        update_speed = 1. / PLAYER_ANIM_SPEED * GAME_SPEED
        if self.frame_right:
            self.frame_right %= 4 * update_speed
            frame = int(self.frame_right / update_speed) % 4
            self.rect = (frame * self.width, 0, self.width, self.height)
        elif self.frame_left:
            self.frame_left %= 4 * update_speed
            frame = int(self.frame_left / update_speed) % 4
            self.rect = (frame * self.width, self.height, self.width,
                         self.height)
        else:
            if self.last_direction == -1:
                self.rect = (0, self.height, self.width, self.height)
            else:
                self.rect = (0, 0, self.width, self.height)

        if not self.can_shoot:
            self.last_shooting -= time_passed
            if self.last_shooting <= 0:
                self.can_shoot = True
Beispiel #22
0
 def setUp(self):
     self.balls = []
     self.results = []
     self.box = Obstacle(Vec2D(200, 200), Vec2D(200, 200))
     self.balls.append(Ball(150, Vec2D(200, 100), Vec2D(50, 50)))
     self.results.append((Vec2D(200, 0), Vec2D(0, -1)))
     self.balls.append(Ball(150, Vec2D(200, 100), Vec2D(-50, 50)))
     self.results.append((Vec2D(200, 0), Vec2D(0, -1)))
     self.balls.append(Ball(150, Vec2D(400, 100), Vec2D(50, 50)))
     self.results.append((Vec2D(400, 0), Vec2D(0, -1)))
     self.balls.append(Ball(150, Vec2D(400, 100), Vec2D(-50, 50)))
     self.results.append((Vec2D(400, 0), Vec2D(0, -1)))
     self.balls.append(
         Ball(150, Vec2D(450, 200 - 50 * (3**.5)), Vec2D(50, 50)))
     self.results.append((Vec2D(450, 3.76), Vec2D(0, -1)))
     self.balls.append(
         Ball(150, Vec2D(450, 200 - 50 * (3**.5)), Vec2D(-50, 50)))
     self.results.append((Vec2D(450, 3.76), Vec2D(0, -1)))
     self.balls.append(
         Ball(150, Vec2D(400 + 50 * (3**.5), 150), Vec2D(-50, 50)))
     self.results.append((Vec2D(596.24, 150), Vec2D(-1, 0)))
     self.balls.append(
         Ball(150, Vec2D(400 + 50 * (3**.5), 150), Vec2D(-50, -50)))
     self.results.append((Vec2D(596.24, 150), Vec2D(-1, 0)))
     self.balls.append(Ball(150, Vec2D(500, 200), Vec2D(-50, 50)))
     self.results.append((Vec2D(600, 200), Vec2D(-1, 0)))
     self.balls.append(Ball(150, Vec2D(500, 200), Vec2D(-50, -50)))
     self.results.append((Vec2D(600, 200), Vec2D(-1, 0)))
     self.balls.append(Ball(150, Vec2D(500, 400), Vec2D(-50, 50)))
     self.results.append((Vec2D(600, 400), Vec2D(-1, 0)))
     self.balls.append(Ball(150, Vec2D(500, 400), Vec2D(-50, -50)))
     self.results.append((Vec2D(600, 400), Vec2D(-1, 0)))
     self.balls.append(
         Ball(150, Vec2D(400 + 50 * (3**.5), 450), Vec2D(-50, 50)))
     self.results.append((Vec2D(596.24, 450), Vec2D(-1, 0)))
     self.balls.append(
         Ball(150, Vec2D(400 + 50 * (3**.5), 450), Vec2D(-50, -50)))
     self.results.append((Vec2D(596.24, 450), Vec2D(-1, 0)))
     self.balls.append(
         Ball(150, Vec2D(450, 400 + 50 * (3**.5)), Vec2D(50, -50)))
     self.results.append((Vec2D(450, 596.24), Vec2D(0, -1)))
     self.balls.append(
         Ball(150, Vec2D(450, 400 + 50 * (3**.5)), Vec2D(-50, -50)))
     self.results.append((Vec2D(450, 596.24), Vec2D(0, -1)))
     self.balls.append(Ball(150, Vec2D(400, 500), Vec2D(50, -50)))
     self.results.append((Vec2D(400, 600), Vec2D(0, -1)))
     self.balls.append(Ball(150, Vec2D(400, 500), Vec2D(-50, -50)))
     self.results.append((Vec2D(400, 600), Vec2D(0, -1)))
     self.balls.append(Ball(150, Vec2D(200, 500), Vec2D(50, -50)))
     self.results.append((Vec2D(200, 600), Vec2D(0, -1)))
     self.balls.append(Ball(150, Vec2D(200, 500), Vec2D(-50, -50)))
     self.results.append((Vec2D(200, 600), Vec2D(0, -1)))
     self.balls.append(
         Ball(150, Vec2D(150, 400 + 50 * (3**.5)), Vec2D(50, -50)))
     self.results.append((Vec2D(150, 596.24), Vec2D(0, -1)))
     self.balls.append(
         Ball(150, Vec2D(150, 400 + 50 * (3**.5)), Vec2D(-50, -50)))
     self.results.append((Vec2D(150, 596.24), Vec2D(0, -1)))
     self.balls.append(
         Ball(150, Vec2D(200 - 50 * (3**.5), 450), Vec2D(50, -50)))
     self.results.append((Vec2D(3.76, 450), Vec2D(-1, 0)))
     self.balls.append(
         Ball(150, Vec2D(200 - 50 * (3**.5), 450), Vec2D(50, 50)))
     self.results.append((Vec2D(3.76, 450), Vec2D(-1, 0)))
     self.balls.append(Ball(150, Vec2D(100, 400), Vec2D(50, -50)))
     self.results.append((Vec2D(0, 400), Vec2D(-1, 0)))
     self.balls.append(Ball(150, Vec2D(100, 400), Vec2D(50, 50)))
     self.results.append((Vec2D(0, 400), Vec2D(-1, 0)))
     self.balls.append(Ball(150, Vec2D(100, 200), Vec2D(50, -50)))
     self.results.append((Vec2D(0, 200), Vec2D(-1, 0)))
     self.balls.append(Ball(150, Vec2D(100, 200), Vec2D(50, 50)))
     self.results.append((Vec2D(0, 200), Vec2D(-1, 0)))
     self.balls.append(
         Ball(150, Vec2D(200 - 50 * (3**.5), 150), Vec2D(50, -50)))
     self.results.append((Vec2D(3.76, 150), Vec2D(-1, 0)))
     self.balls.append(
         Ball(150, Vec2D(200 - 50 * (3**.5), 150), Vec2D(50, 50)))
     self.results.append((Vec2D(3.76, 150), Vec2D(-1, 0)))
     self.balls.append(
         Ball(150, Vec2D(150, 200 - 50 * (3**.5)), Vec2D(50, 50)))
     self.results.append((Vec2D(150, 3.76), Vec2D(0, -1)))
     self.balls.append(
         Ball(150, Vec2D(150, 200 - 50 * (3**.5)), Vec2D(-50, 50)))
     self.results.append((Vec2D(150, 3.76), Vec2D(0, -1)))
     self.balls.append(Ball(150, Vec2D(300, 100), Vec2D(50, 50)))
     self.results.append((Vec2D(300, 0), Vec2D(0, -1)))
     self.balls.append(Ball(150, Vec2D(300, 100), Vec2D(-50, 50)))
     self.results.append((Vec2D(300, 0), Vec2D(0, -1)))
     self.balls.append(Ball(150, Vec2D(450, 100), Vec2D(50, 50)))
     self.results.append((Vec2D(450, 17.16), Vec2D(0, -1)))
     self.balls.append(Ball(150, Vec2D(450, 100), Vec2D(-50, 50)))
     self.results.append((Vec2D(450, 17.16), Vec2D(0, -1)))
     self.balls.append(Ball(150, Vec2D(450, 150), Vec2D(50, 50)))
     self.results.append((Vec2D(450, -32.84), Vec2D(0, -1)))
     self.balls.append(Ball(150, Vec2D(450, 150), Vec2D(-50, 50)))
     self.results.append((Vec2D(337.87, 37.87), Vec2D(-1, -1)))
     self.balls.append(Ball(150, Vec2D(450, 150), Vec2D(-50, -50)))
     self.results.append((Vec2D(632.84, 150), Vec2D(-1, 0)))
     self.balls.append(Ball(150, Vec2D(500, 150), Vec2D(-50, 50)))
     self.results.append((Vec2D(582.84, 150), Vec2D(-1, 0)))
     self.balls.append(Ball(150, Vec2D(500, 150), Vec2D(-50, -50)))
     self.results.append((Vec2D(582.84, 150), Vec2D(-1, 0)))
     self.balls.append(Ball(150, Vec2D(500, 300), Vec2D(-50, 50)))
     self.results.append((Vec2D(600, 300), Vec2D(-1, 0)))
     self.balls.append(Ball(150, Vec2D(500, 300), Vec2D(-50, -50)))
     self.results.append((Vec2D(600, 300), Vec2D(-1, 0)))
     self.balls.append(Ball(150, Vec2D(500, 450), Vec2D(-50, 50)))
     self.results.append((Vec2D(582.84, 450), Vec2D(-1, 0)))
     self.balls.append(Ball(150, Vec2D(500, 450), Vec2D(-50, -50)))
     self.results.append((Vec2D(582.84, 450), Vec2D(-1, 0)))
     self.balls.append(Ball(150, Vec2D(450, 450), Vec2D(-50, 50)))
     self.results.append((Vec2D(632.84, 450), Vec2D(-1, 0)))
     self.balls.append(Ball(150, Vec2D(450, 450), Vec2D(-50, -50)))
     self.results.append((Vec2D(562.13, 562.13), Vec2D(-1, -1)))
     self.balls.append(Ball(150, Vec2D(450, 450), Vec2D(50, -50)))
     self.results.append((Vec2D(450, 632.84), Vec2D(0, -1)))
     self.balls.append(Ball(150, Vec2D(450, 500), Vec2D(-50, -50)))
     self.results.append((Vec2D(450, 582.84), Vec2D(0, -1)))
     self.balls.append(Ball(150, Vec2D(450, 500), Vec2D(50, -50)))
     self.results.append((Vec2D(450, 582.84), Vec2D(0, -1)))
     self.balls.append(Ball(150, Vec2D(300, 500), Vec2D(-50, -50)))
     self.results.append((Vec2D(300, 600), Vec2D(0, -1)))
     self.balls.append(Ball(150, Vec2D(300, 500), Vec2D(50, -50)))
     self.results.append((Vec2D(300, 600), Vec2D(0, -1)))
     self.balls.append(Ball(150, Vec2D(150, 500), Vec2D(-50, -50)))
     self.results.append((Vec2D(150, 582.84), Vec2D(0, -1)))
     self.balls.append(Ball(150, Vec2D(150, 500), Vec2D(50, -50)))
     self.results.append((Vec2D(150, 582.84), Vec2D(0, -1)))
     self.balls.append(Ball(150, Vec2D(150, 450), Vec2D(-50, -50)))
     self.results.append((Vec2D(150, 632.84), Vec2D(0, -1)))
     self.balls.append(Ball(150, Vec2D(150, 450), Vec2D(50, -50)))
     self.results.append((Vec2D(262.13, 562.13), Vec2D(-1, -1)))
     self.balls.append(Ball(150, Vec2D(150, 450), Vec2D(50, 50)))
     self.results.append((Vec2D(-32.84, 450), Vec2D(-1, 0)))
     self.balls.append(Ball(150, Vec2D(100, 450), Vec2D(50, -50)))
     self.results.append((Vec2D(17.16, 450), Vec2D(-1, 0)))
     self.balls.append(Ball(150, Vec2D(100, 450), Vec2D(50, 50)))
     self.results.append((Vec2D(17.16, 450), Vec2D(-1, 0)))
     self.balls.append(Ball(150, Vec2D(100, 300), Vec2D(50, -50)))
     self.results.append((Vec2D(0, 300), Vec2D(-1, 0)))
     self.balls.append(Ball(150, Vec2D(100, 300), Vec2D(50, 50)))
     self.results.append((Vec2D(0, 300), Vec2D(-1, 0)))
     self.balls.append(Ball(150, Vec2D(100, 150), Vec2D(50, -50)))
     self.results.append((Vec2D(17.16, 150), Vec2D(-1, 0)))
     self.balls.append(Ball(150, Vec2D(100, 150), Vec2D(50, 50)))
     self.results.append((Vec2D(17.16, 150), Vec2D(-1, 0)))
     self.balls.append(Ball(150, Vec2D(150, 150), Vec2D(50, -50)))
     self.results.append((Vec2D(-32.84, 150), Vec2D(-1, 0)))
     self.balls.append(Ball(150, Vec2D(150, 150), Vec2D(50, 50)))
     self.results.append((Vec2D(37.87, 37.87), Vec2D(-1, -1)))
     self.balls.append(Ball(150, Vec2D(150, 150), Vec2D(-50, 50)))
     self.results.append((Vec2D(150, -32.84), Vec2D(0, -1)))
     self.balls.append(Ball(150, Vec2D(150, 100), Vec2D(50, 50)))
     self.results.append((Vec2D(150, 17.16), Vec2D(0, -1)))
     self.balls.append(Ball(150, Vec2D(150, 100), Vec2D(-50, 50)))
     self.results.append((Vec2D(150, 17.16), Vec2D(0, -1)))
     self.balls.append(Ball(150, Vec2D(0, 0), Vec2D(50, 0)))
     self.results.append((Vec2D(0, 0), None))
Beispiel #23
0
 def test_angle(self):
     self.assertAlmostEqual(0, calc_angle(Vec2D(1, 0)))
     self.assertAlmostEqual(30, calc_angle(Vec2D((3**.5) / 2, .5)))
     self.assertAlmostEqual(30, calc_angle(Vec2D((3**.5) / 2, -.5)))
     self.assertAlmostEqual(45, calc_angle(Vec2D(1, 1)))
     self.assertAlmostEqual(45, calc_angle(Vec2D(1, -1)))
     self.assertAlmostEqual(60, calc_angle(Vec2D(.5, (3**.5) / 2)))
     self.assertAlmostEqual(60, calc_angle(Vec2D(.5, -(3**.5) / 2)))
     self.assertAlmostEqual(90, calc_angle(Vec2D(0, 1)))
     self.assertAlmostEqual(90, calc_angle(Vec2D(0, -1)))
     self.assertAlmostEqual(120, calc_angle(Vec2D(-.5, (3**.5) / 2)))
     self.assertAlmostEqual(120, calc_angle(Vec2D(-.5, -(3**.5) / 2)))
     self.assertAlmostEqual(135, calc_angle(Vec2D(-1, 1)))
     self.assertAlmostEqual(135, calc_angle(Vec2D(-1, -1)))
     self.assertAlmostEqual(150, calc_angle(Vec2D(-(3**.5) / 2, .5)))
     self.assertAlmostEqual(150, calc_angle(Vec2D(-(3**.5) / 2, -.5)))
     self.assertAlmostEqual(180, calc_angle(Vec2D(-1, 0)))
Beispiel #24
0
 def __init__(self, height, position):
     Object2D.__init__(self, Vec2D(LADDER_WIDTH, height), position)
Beispiel #25
0
def ball_to_box(ball, box, solid=False):
    """Ball to box collision detection algorithm using voronoi regions.
    Calculates which region the ball is in based on this map:
    1|2|3
    4|0|5
    6|7|8
    Fixates the ball's position so that the objects no longer collide if solid
    is set to True and returns a Vec2D object representing the directions
    which the ball needs to change.
    """
    radius = ball.radius
    region = -1
    box_x_edge = 0
    box_y_edge = 0
    force_x = 0
    force_y = 0
    ball_x_fixate = 0
    ball_y_fixate = 0
    if ball.x > box.x + box.width:  # 3 or 5 or 8
        if ball.y > box.y + box.height:  # 8
            box_x_edge = box.x + box.width
            box_y_edge = box.y + box.height
            if (ball.x - box_x_edge)**2 + (ball.y - box_y_edge)**2 < radius**2:
                region = 8
        elif ball.y < box.y:  # 3
            box_x_edge = box.x + box.width
            box_y_edge = box.y
            if (ball.x - box_x_edge)**2 + (ball.y - box_y_edge)**2 < radius**2:
                region = 3
        else:  # 5
            if box.x + box.width >= ball.x - radius:
                region = 5
                ball_x_fixate = 2 * (box.x + box.width - (ball.x - radius))
                force_x = -1
    elif ball.x < box.x:  # 1 or 4 or 6
        if ball.y > box.y + box.height:  # 6
            box_x_edge = box.x
            box_y_edge = box.y + box.height
            if (ball.x - box_x_edge)**2 + (ball.y - box_y_edge)**2 < radius**2:
                region = 6
        elif ball.y < box.y:  # 1
            box_x_edge = box.x
            box_y_edge = box.y
            if (ball.x - box_x_edge)**2 + (ball.y - box_y_edge)**2 < radius**2:
                region = 1
        else:  # 4
            if box.x <= ball.x + radius:
                region = 4
                ball_x_fixate = 2 * (box.x - (ball.x + radius))
                force_x = -1
    else:  # 2 or 7 or 0
        if ball.y >= box.y + box.height:  # 7
            if box.y + box.height >= ball.y - radius:
                region = 7
                ball_y_fixate = 2 * (box.y + box.height - (ball.y - radius))
                force_y = -1
        elif ball.y <= box.y:  # 2
            if box.y <= ball.y + radius:
                region = 2
                ball_y_fixate = 2 * (box.y - (ball.y + radius))
                force_y = -1
        else:  # 0
            region = 0
            if ball.force.y >= 0:  # this is actually the same as 2
                ball_y_fixate = 2 * (box.y - (ball.y + radius))
                force_y = -1
            else:  # this is actually the same as 7
                ball_y_fixate = 2 * (box.y + box.height - (ball.y - radius))
                force_y = -1
    if solid:
        if region in [1, 3, 6, 8]:

            delta_x = ball.x - box_x_edge
            delta_y = ball.y - box_y_edge

            if region in [1, 6]:
                if ball.force.x > 0:
                    force_x = -1
            else:
                if ball.force.x < 0:
                    force_x = -1

            if region in [1, 3]:
                if ball.force.y > 0:
                    force_y = -1
            else:
                if ball.force.y < 0:
                    force_y = -1

            angle = calc_angle(Vec2D(delta_x, delta_y))
            if angle > 90.5:
                angle %= 90

            if region in [1, 6]:
                if angle <= 31:
                    force_x = 0
                elif angle >= 59:
                    force_y = 0
            else:
                if angle <= 31:
                    force_y = 0
                elif angle >= 59:
                    force_x = 0

            if force_x and force_y:
                force_length = ((delta_x)**2 + (delta_y)**2)**.5
                lengthen_y = radius / force_length - 1
                lengthen_x = lengthen_y * ball.force.x / ball.force.y
                ball_x_fixate = 2 * delta_x * lengthen_x
                ball_y_fixate = 2 * delta_y * lengthen_y
            elif force_x:
                x_pos = (radius**2 - (box_y_edge - ball.y)**2)**.5
                if ball.x > box_x_edge:
                    x_pos = ball.x - x_pos
                    ball_x_fixate = 2 * (box_x_edge - x_pos)
                else:
                    x_pos += ball.x
                    ball_x_fixate = 2 * (box_x_edge - x_pos)
            elif force_y:
                y_pos = (radius**2 - (box_x_edge - ball.x)**2)**.5
                if ball.y > box_y_edge:
                    y_pos = ball.y - y_pos
                    ball_y_fixate = 2 * (box_y_edge - y_pos)
                else:
                    y_pos += ball.y
                    ball_y_fixate = 2 * (box_y_edge - y_pos)

            ball.position += (ball_x_fixate, ball_y_fixate)

        elif region in [0, 2, 4, 5, 7]:
            ball.position += (ball_x_fixate, ball_y_fixate)

    if region != -1:
        return Vec2D(force_x, force_y)