def ai(self): pos = game_vars.player_pos() if self.stage == 0: self.v[1] = -15 dx = self.rect.centerx - pos[0] if abs(dx) > 10 * BLOCK_W: self.v[0] = math.copysign(15, -dx) else: self.v[0] = 0 # When we get high enough and close enough, switch modes if self.pos[1] < pos[1] - 10 * BLOCK_W: # 60% chance to go to stage one (diving) if randint(1, 5) > 2: self.start_diving() # 40% chance to go to stage two (shoot fireballs) else: self.time = 0 self.stage = 2 # If we get too far away, switch modes elif self.stage == 1: dx = self.pos[0] - pos[0] dy = self.pos[1] - pos[1] if dy > 10 * BLOCK_W or (dy >= 0 and abs(dx) > 10 * BLOCK_W): self.set_image(self.rising_anim.get_frame()) self.stage = 0 elif self.stage == 2: num_shot_i = int(self.time) self.time += game_vars.dt num_shot_f = int(self.time) # Shoot fire balls! for i in range(num_shot_f - num_shot_i): game_vars.shoot_projectile( self.FireBall(self.rect.center, game_vars.player_pos(False))) if num_shot_f >= 9: self.start_diving() else: # Get distance to 8 blocks above and to the side of the player dy = pos[1] - BLOCK_W * 8 - self.rect.centery dx = pos[0] - self.rect.centerx dx -= math.copysign(BLOCK_W * 8, dx) self.v[0] = math.copysign(7, dx) if dx != 0 else 0 self.v[1] = math.copysign(7, dy) if dy != 0 else 0 # Update animation if self.stage == 0 or self.stage == 2: i = self.rising_anim.idx self.rising_anim.update(game_vars.dt) if i != self.rising_anim.idx: self.set_image(self.rising_anim.get_frame())
def start_diving(self): self.rising_anim.reset() pos = game_vars.player_pos() theta = get_angle(self.rect.center, pos) self.v = [15 * math.cos(theta), 15 * math.sin(theta)] self.set_image(self.attacking_img) self.stage = 1
def ai(self): pos = game_vars.player_pos() if self.stage == 0: # If we aren't launching, move normally if self.hits_blocks: self.time += game_vars.dt # Check if we are switching to jump stage if self.time >= 7.75: self.a = [0, 20] if self.collisions[1] == 1: self.v = [0, 0] if self.time >= 8: self.time = 0 self.stage = 1 self.v[1] = -self.stats.get_stat("max_speed") self.hits_blocks = True else: self.time = 7.75 else: dx = pos[0] - self.rect.centerx if dx != 0: self.a[0] = math.copysign(10, dx) if self.collisions[0] != 0 and self.collisions[1] == 1: self.v[1] = -10 self.jump_count += 1 if self.jump_count > 2: self.launch() # Reset jumps if we aren't hitting something to the side if self.collisions[0] == 0: self.jump_count = 0 else: # If we are in a block, keep launching if game_vars.in_block(self.pos, self.dim): # If we went past out launch target, relaunch angle = get_angle(self.rect.center, self.launch_target) if abs(self.launch_angle - angle) > math.pi // 2: self.launch_target = pos self.launch_angle = get_angle(self.rect.center, pos) self.v[0] = 15 * math.cos(self.launch_angle) self.v[1] = 15 * math.sin(self.launch_angle) # Stop launching else: self.a[1] = 20 self.v[1] = -5 self.hits_blocks = True elif self.stage == 1: if self.v[1] > -3: self.v[1] = 25 if self.collisions[1] == 1: self.stage = 0 self.v[1] = 0 p = self.GroundP(self.pos, -1) p.set_pos(self.rect.centerx - p.dim[0] * BLOCK_W, self.rect.bottom - p.dim[1] * BLOCK_W) game_vars.shoot_projectile(p) p = self.GroundP(self.pos, 1) p.set_pos(self.rect.centerx, self.rect.bottom - p.dim[1] * BLOCK_W) game_vars.shoot_projectile(p)
def launch(self): self.stage = 0 self.a = [0, 0] self.v[0] = 15 * math.cos(self.launch_angle) self.v[1] = 15 * math.sin(self.launch_angle) self.hits_blocks = False self.launch_target = game_vars.player_pos() self.launch_angle = get_angle(self.rect.center, self.launch_target)
def follow_player(entity): # Check if we are standing on the ground if entity.collisions[1]: entity.a[0] = math.copysign( entity.stats.get_stat("acceleration"), game_vars.player_pos()[0] - entity.rect.centerx) # Check if we need to jump if entity.collisions[0] != 0: entity.v[1] = -entity.stats.get_stat("jump_speed")
def fly_follow(entity): # Move towards player when we get to far away from the player pos = game_vars.player_pos() if entity.a[0] == 0 or abs(entity.rect.centerx - pos[0]) >= 5 * BLOCK_W: entity.a[0] = math.copysign(entity.stats.get_stat("acceleration"), pos[0] - entity.rect.centerx) if entity.a[1] == 0 or abs(entity.rect.centery - pos[1]) >= 2 * BLOCK_W: entity.a[1] = math.copysign(entity.stats.get_stat("acceleration"), pos[1] - entity.rect.centery)
def spawn(self): conditions = SpawnConditions() conditions.check_world() player_pos = [i // BLOCK_W for i in game_vars.player_pos()] spawners = game_vars.world.spawners world_dim = game_vars.world_dim() for x in range(max(0, player_pos[0] - 50), min(world_dim[0], player_pos[0] + 50)): if x in spawners.keys(): for y in range(max(0, player_pos[1] - 50, min(world_dim[1], player_pos[1] + 50))): if y in spawners[x].keys(): if randint(1, 10000) == 1: entity = game_vars.tiles[spawners[x][y]].spawn((x, y), conditions) if entity is not None: self.add_entity(entity)
def tick(self, dt): # Check chunk loading/unloading pos = game_vars.player_pos(in_blocks=True) rect = self.get_rect() dx = [pos[0] - rect.x, rect.right - pos[0]] dy = [pos[1] - rect.top, rect.bottom - pos[1]] for i in range(2): # X chunks if dx[i] >= CHUNK_W * 3: for row in self.chunks: row[-i].unload() del row[-i] elif dx[i] <= CHUNK_W * 3 // 2 and ( rect.x >= CHUNK_W if i == 0 else rect.right <= self.world.dim[0] - CHUNK_W): x = self.chunks[0][-i].x + (-CHUNK_W if i == 0 else CHUNK_W) for row in self.chunks: new = Chunk(x, row[0].y, blocks=self.world.blocks) if i == 0: row.insert(0, new) else: row.append(new) # Y chunks if dy[i] >= CHUNK_W * 3: for chunk in self.chunks[-i]: chunk.unload() del self.chunks[-i] elif dy[i] <= CHUNK_W * 3 // 2 and ( rect.y >= CHUNK_W if i == 0 else rect.bottom <= self.world.dim[1] - CHUNK_W): y = self.chunks[0][-i].y + (-CHUNK_W if i == 0 else CHUNK_W) new_row = [ Chunk(c.x, y, blocks=self.world.blocks) for c in self.chunks[0] ] if i == 0: self.chunks.insert(0, new_row) else: self.chunks.append(new_row) # Update chunks for row in self.chunks: for chunk in row: chunk.tick(dt)
def jump(entity, follow): # If we are on the ground, progress our timer and make sure we aren't moving if entity.collisions[1] == 1: entity.a[0], entity.v[0] = 0, 0 entity.time -= game_vars.dt # If we are done waiting, jump if entity.time <= 0: if follow: entity.a[0] = math.copysign( entity.stats.get_stat("acceleration"), game_vars.player_pos()[0] - entity.rect.centerx) else: entity.a[0] = entity.stats.get_stat( "acceleration") * random_sign() entity.v[0] = math.copysign(entity.stats.get_stat("max_speedx"), entity.a[0]) entity.v[1] = -randint(5, entity.stats.get_stat("jump_speed")) entity.time = uniform(1, 2)
def draw_map(self, rect): src_dim = self.source.get_size() dim = rect.size dim = [min(dim[i], src_dim[i] * self.zoom) for i in (0, 1)] # Get map width in terms of blocks block_dim = (dim[0] / self.zoom, dim[1] / self.zoom) half_dim = (block_dim[0] / 2, block_dim[1] / 2) # Calculate top and left of our minimap for i in range(2): if self.center[i] < half_dim[i]: self.center[i] = half_dim[i] elif self.center[i] > src_dim[i] - half_dim[i]: self.center[i] = src_dim[i] - half_dim[i] left, top = self.center[0] - half_dim[0], self.center[1] - half_dim[1] # Get the blocks that will be in our map b_left, b_top = int(left), int(top) b_right, b_bot = math.ceil(left + block_dim[0]), math.ceil(top + block_dim[1]) b_dim = (b_right - b_left, b_bot - b_top) # Draw them onto a surface s = pg.Surface(b_dim) s.blit(self.source, (0, 0), area=((b_left, b_top), b_dim)) s = pg.transform.scale( s, (int(b_dim[0] * self.zoom), int(b_dim[1] * self.zoom))) # Cut off the edges off_x, off_y = int((left - b_left) * self.zoom), int( (top - b_top) * self.zoom) map_rect = pg.Rect((b_left, b_top), b_dim) self.draw_sprite(s, map_rect, game_vars.player.sprite, game_vars.player_pos(in_blocks=True)) for entity in [ e for e in game_vars.handler.entities.values() if e.sprite ]: self.draw_sprite(s, map_rect, entity.sprite, entity.get_block_pos()) pg.display.get_surface().blit( s, (rect.centerx - dim[0] // 2, rect.centery - dim[1] // 2), area=((off_x, off_y), dim))
def tick(self, dt): self.time = (self.time + dt) % c.SEC_PER_DAY # Run auto save self.next_save -= game_vars.dt if self.next_save <= 0: self.save_progress = self.save_world(self.save_progress) if self.save_progress >= 1: self.save_progress = 0 self.next_save = 30 game_vars.player.write() # Update minimap pos = game_vars.player_pos(True) left, top = max(int(pos[0] - 10), 0), max(int(pos[1] - 10), 0) # Go through every row, column pair where the color is black section = pg.surfarray.pixels2d(self.map)[left:math.ceil(pos[0] + 10), top:math.ceil(pos[1] + 10)] for x, y in zip(*np.where(section == 0)): map_color = game_vars.tiles[game_vars.get_block_at( left + x, top + y)].map_color section[x][y] = self.map.map_rgb(map_color) del section self.manager.tick(dt)
def ai(self): jump( self, abs(game_vars.player_pos()[0] - self.rect.centerx) // BLOCK_W <= 10)
def on_break(self, pos): game_vars.spawn_entity(mobs.Dragon(), [ p + randint(10, 20) * BLOCK_W * c.random_sign() for p in game_vars.player_pos() ]) return False
def on_left_click(self): game_vars.spawn_entity(Mobs.MainBoss(), [p + randint(15, 30) * BLOCK_W * random_sign() for p in game_vars.player_pos()])
def on_left_click(self): super().on_left_click() game_vars.shoot_projectile(self.P1(game_vars.player_pos(), game_vars.global_mouse_pos()))