def update_speed(self): """Update camera and game speed.""" # Get distance lst = [float("inf")] for i in (1, 2): j = 2 if i == 1 else 1 pos_1 = xytuple(*self.players[i].legs.center) if not any(pos_1): continue pos_2 = xytuple(*self.players[j].head.center) pos_3 = xytuple(*self.players[j].body.center) lst.append(abs(pos_1 - pos_2)) lst.append(abs(pos_1 - pos_3)) # Reset speed and camera if not self.colliding and min(lst) > float(self.threshold): if self.time_speed: self.time_speed = 1.0 self.parent.reset_camera() return # Set speed if self.time_speed: self.time_speed = self.slow_ratio # Set camera new_zoom = not self.parent.is_camera_set area = self.players[1].rect.union(self.players[2].rect) center = area.center area.h = max(area.h, self.rect.h / 2) area.w = max(area.w, self.rect.w / 2) area.center = center self.parent.set_camera(area.clamp(self.rect)) # Break the update if new zoom detected return new_zoom
def update_speed(self): """Update camera and game speed.""" # Get distance lst = [float("inf")] for i in (1, 2): j = 2 if i == 1 else 1 pos_1 = xytuple(*self.players[i].legs.center) if not any(pos_1): continue pos_2 = xytuple(*self.players[j].head.center) pos_3 = xytuple(*self.players[j].body.center) lst.append(abs(pos_1-pos_2)) lst.append(abs(pos_1-pos_3)) # Reset speed and camera if not self.colliding and min(lst) > float(self.threshold): if self.time_speed: self.time_speed = 1.0 self.parent.reset_camera() return # Set speed if self.time_speed: self.time_speed = self.slow_ratio # Set camera new_zoom = not self.parent.is_camera_set area = self.players[1].rect.union(self.players[2].rect) center = area.center area.h = max(area.h, self.rect.h/2) area.w = max(area.w, self.rect.w/2) area.center = center self.parent.set_camera(area.clamp(self.rect)) # Break the update if new zoom detected return new_zoom
def compute_basesize(self): width = float(self.settings.width) / self.max_tile_x coresponding_height = width / (3**0.5) height = float(self.settings.height) / self.max_tile_y if height > coresponding_height: return xytuple(width, coresponding_height) coresponding_width = height * (3**0.5) return xytuple(coresponding_width, height)
def perfect_collide(rect1, img1, pos1, rect2, img2, pos2): """Perform a pixel-perfect collision test using transparency. It takes the inner rectangle, image and position for both elements. """ rect = rect1.clip(rect2) if not rect: return False flag = pygame.BLEND_RGBA_MIN pos1, pos2 = xytuple(pos1), xytuple(pos2) surf = pygame.Surface(rect.size).convert_alpha() surf.blit(img1, (0, 0), area=rect.move(-pos1), special_flags=flag) surf.blit(img2, (0, 0), area=rect.move(-pos2), special_flags=flag) return any(flatten(pygame.PixelArray(surf)))
def size(self): if self.rect.size != (0, 0): return self.rect.size if self.raw_ratio is None: return xytuple(0, 0) size = self.basesize * (1, self.raw_ratio * 3**0.5) return size.map(ceil).map(int)
def get_rect_from_dir(self, direction): """Compute a hitbox inside the player in a given direction.""" size = xytuple(*self.size) * ((self.hitbox_ratio,) * 2) attr = Dir.DIR_TO_ATTR[direction] rect = Rect((0, 0), size) value = getattr(self.rect, attr) setattr(rect, attr, value) return rect
def get_rect_from_dir(self, direction): """Compute a hitbox inside the player in a given direction.""" size = xytuple(*self.size) * ((self.hitbox_ratio,)*2) attr = Dir.DIR_TO_ATTR[direction] rect = Rect((0, 0), size) value = getattr(self.rect, attr) setattr(rect, attr, value) return rect
def pos(self): if not self.is_busy: return xytuple(*self.real_pos) if self.is_dying: ratio = self.dying_timer.get(normalized=True) return self.round_pos + (ratio * 0.8,) * 2 ratio = self.moving_timer.get(normalized=True) return self.round_pos + self.dir * (ratio, ratio)
def pos(self): if not self.is_busy: return xytuple(*self.real_pos) if self.is_dying: ratio = self.dying_timer.get(normalized=True) return self.round_pos + (ratio * 0.8, ) * 2 ratio = self.moving_timer.get(normalized=True) return self.round_pos + self.dir * (ratio, ratio)
def current_dir(self): """Current direction with x and y in (-1, 0, 1).""" # Static case if self.fixed: if not any(self.save_dir) or sum(self.save_dir * self.pos) > 0: return xytuple(0, 0) current_dir = self.save_dir - self.pos sign = lambda arg: (arg > 0) - (arg < 0) return current_dir.map(sign) # Dynamic case return Dir.closest_dir(self.speed)
def init(self): # Build the board and tiles self.player_dct = {} self.goal_dct = {} self.resource_lst = list(self.control.resource.map) try: self.board = self.resource_lst[self.level] except IndexError: self.load_next_board() self.tile_dct = self.build_tiles(self.board) # Useful attributes self.max_coordinate = xytuple(*max(self.tile_dct)) self.nb_line = self.max_coordinate.x + 1 self.nb_column = self.max_coordinate.x + 1
def current_dir(self): """Current direction with x and y in (-1, 0, 1).""" # Static case if self.fixed: if not any(self.save_dir) or \ sum(self.save_dir*self.pos) > 0: return xytuple(0, 0) current_dir = self.save_dir - self.pos sign = lambda arg: cmp(arg, 0) return current_dir.map(sign) # Dynamic case return Dir.closest_dir(self.speed)
def init(self, pos, pid): super(PlayerModel, self).init(pos) # Create timers self.timer = Timer(self, stop=self.period, periodic=True) self.transform_timer = Timer(self, stop=self.transfrom_period, callback=self.transform_callback) self.moving_timer = Timer(self, stop=self.moving_period, callback=self.moving_callback) self.dying_timer = Timer(self, stop=self.dying_period, callback=self.dying_callback) self.timer.start() # Set attributes self.id = pid self.dir = xytuple(0, 1) self.activedir = False self.is_dead = False
def init(self, pid): """Initialize the player.""" # Attributes self.id = pid self.border = self.parent.border self.resource = self.control.resource # Player rectangle self.size = self.resource.image.get(self.ref)[0].get_size() self.rect = Rect((0, 0), self.size) if pid == 1: self.rect.bottomleft = self.border.rect.bottomleft else: self.rect.bottomright = self.border.rect.bottomright # Player state self.speed = self.remainder = xytuple(0.0, 0.0) self.control_dir = Dir.NONE self.save_dir = Dir.NONE self.pos = Dir.DOWN self.fixed = True self.ko = False self.steps = [self.rect] # Animation timer self.timer = Timer(self, stop=self.period, periodic=True).start() # Loading timer self.loading_timer = Timer(self, start=self.init_speed, stop=self.max_loading_speed) # Delay timer self.delay_timer = Timer(self, stop=self.pre_jump, callback=self.delay_callback) # Dying timer self.blinking_timer = Timer(self.parent.parent, stop=self.blinking_period, periodic=True) # Debug if self.control.settings.debug_mode: RectModel(self, "head", Color("red")) RectModel(self, "body", Color("green")) RectModel(self, "legs", Color("blue"))
def update_collision(self): """Handle wall collisions.""" collide_dct = dict(list(self.collide_dct.items())) # Loop over changes while not self.border.rect.contains(self.rect): self.fixed = True self.save_dir = self.control_dir dct = {} # Test against the 4 directions. for direc, attr in list(collide_dct.items()): rect = self.rect.copy() value = getattr(self.border.rect, attr) setattr(rect, attr, value) distance = abs(xytuple(*rect.topleft) - self.rect.topleft) dct[distance] = rect, direc, attr # Aply the smallest change self.rect, self.pos, _ = dct[min(dct)] del collide_dct[self.pos] # Do not grab the wall when KO if self.ko and self.pos != Dir.DOWN: self.fixed = False
def init(self, pos, pid): super(PlayerModel, self).init(pos) # Create timers self.timer = Timer(self, stop=self.period, periodic=True) self.transform_timer = Timer(self, stop=self.transfrom_period, callback=self.transform_callback) self.moving_timer = Timer(self, stop=self.moving_period, callback=self.moving_callback) self.dying_timer = Timer(self, stop=self.dying_period, callback=self.dying_callback) self.timer.start() # Set attributes self.id = pid self.dir = xytuple(0,1) self.activedir = False self.is_dead = False
def update_collision(self): """Handle wall collisions.""" collide_dct = dict(self.collide_dct.items()) # Loop over changes while not self.border.rect.contains(self.rect): self.fixed = True self.save_dir = self.control_dir dct = {} # Test against the 4 directions. for direc, attr in collide_dct.items(): rect = self.rect.copy() value = getattr(self.border.rect, attr) setattr(rect, attr, value) distance = abs(xytuple(*rect.topleft) - self.rect.topleft) dct[distance] = rect, direc, attr # Aply the smallest change self.rect, self.pos, _ = dct[min(dct)] del collide_dct[self.pos] # Do not grab the wall when KO if self.ko and self.pos != Dir.DOWN: self.fixed = False
def init(self, pid): """Initialize the player.""" # Attributes self.id = pid self.border = self.parent.border self.resource = self.control.resource # Player rectangle self.size = self.resource.image.get(self.ref)[0].get_size() self.rect = Rect((0, 0), self.size) if pid == 1: self.rect.bottomleft = self.border.rect.bottomleft else: self.rect.bottomright = self.border.rect.bottomright # Player state self.speed = self.remainder = xytuple(0.0, 0.0) self.control_dir = Dir.NONE self.save_dir = Dir.NONE self.pos = Dir.DOWN self.fixed = True self.ko = False self.steps = [self.rect] # Animation timer self.timer = Timer(self, stop=self.period, periodic=True).start() # Loading timer self.loading_timer = Timer( self, start=self.init_speed, stop=self.max_loading_speed ) # Delay timer self.delay_timer = Timer(self, stop=self.pre_jump, callback=self.delay_callback) # Dying timer self.blinking_timer = Timer( self.parent.parent, stop=self.blinking_period, periodic=True ) # Debug if self.control.settings.debug_mode: RectModel(self, "head", Color("red")) RectModel(self, "body", Color("green")) RectModel(self, "legs", Color("blue"))
def pos(self, value): self.real_pos = xytuple(*value).map(int)
def pos(self, value): self._pos = xytuple(*value)
def pos(self): return xytuple(*self._pos)
def register_direction(self, dirx, diry): if self.is_busy: return self.activedir = True self.dir = xytuple(dirx,diry)
def delta_tuple(self): """Delta time as an xytuple.""" return xytuple(self.delta, self.delta)
def size(self): """Size of the screen.""" return xytuple(self.width, self.height)
def init(self): self.low = xytuple(0,0).map(float) self.high = xytuple(*self.size_ratio).map(float) - (1,1)
def pos(self): """Position for the center of the control panels.""" size = xytuple(*self.model.rect.bottomright) return (size * self.pos_dct[self.player]).map(round)
def pos(self): """Position for the center of the reset text.""" size = xytuple(*self.model.rect.bottomright) return (size * self.relative_pos).map(round)
def isoconvert(self, pos): pos = xytuple(pos.y - pos.x, pos.x + pos.y) pos *= self.basesize * (0.5, 0.5) return pos.map(round).map(int)
def register_direction(self, dirx, diry): if self.is_busy: return self.activedir = True self.dir = xytuple(dirx, diry)
def step(self): # Return default value return -xytuple(*self.speed_ratio)