def setup_players(self): # Me self.homeworld = get_nearest(V2(0, game.RES[1]), self.get_civ_planets(self.player_civ))[0] # Alien p = get_nearest(V2(0, game.RES[1]), self.get_civ_planets(self.enemy.civ))[0] self.alien_homeworld = p
def near_enemies(self): obj, dsq = get_nearest(self.pos, self.scene.get_civ_ships(self.scene.player_civ)) if dsq < 30**2: return True obj, dsq = get_nearest( self.pos, self.scene.get_civ_planets(self.scene.player_civ)) if dsq < 50**2: return True return False
def try_warp(self, dt): if self.owning_civ.upgrade_stats['warp_drive'] == 0: return if self.warp_drive_countdown > 0: return towards = (self.target.pos - self.pos).normalized() nearest, dist = helper.get_nearest(self.pos, self.scene.get_planets()) if nearest: if dist < (nearest.get_radius() + WARP_PLANET_MIN_DIST)**2: return if self.warp_drive_t < 0.66: self.velocity = V2(0, 0) self.warp_drive_t += dt if int(self.warp_drive_t * 40) % 2 == 0: pvel = V2(random.random() - 0.5, random.random() - 0.5) * 15 pvel -= towards * 25 p = particle.Particle([PICO_WHITE, PICO_PINK], 1, self.pos, 0.25 + random.random() * 0.25, pvel) self.scene.game_group.add(p) return exit_dist = (self.target.pos - self.pos).magnitude( ) - self.target.get_radius() - WARP_PLANET_MIN_DIST max_dist = self.owning_civ.upgrade_stats['warp_drive'] + 30 dist = min(exit_dist, max_dist) print(dist) for i in range(0, int(dist), 4): p = self.pos + towards * i pvel = V2(random.random() - 0.5, random.random() - 0.5) * 15 pvel += towards * 15 p = particle.Particle([PICO_WHITE, PICO_PINK], 1, p, 0.25 + random.random() * 0.5, pvel) self.scene.game_group.add(p) nearest, d = helper.get_nearest(p, self.scene.get_planets()) if nearest and d < (nearest.get_radius() + WARP_PLANET_MIN_DIST)**2: dist = i break self.warp_drive_t = 0 self.pos = self.pos + towards * dist print(towards, dist, self.pos) self.warp_drive_countdown = WARP_DRIVE_TIME * (dist / max_dist)
def setup_players(self): # Me self.homeworld = get_nearest(V2(0, game.RES[1]), self.get_civ_planets(self.player_civ))[0] self.homeworld.population = 3 + self.game.run_info.bonus_population self.homeworld.ships['fighter'] = 1 + self.game.run_info.bonus_fighters self.radar = Explosion(self.homeworld.pos, [PICO_GREEN], 1.25, self.game.game_resolution.x) self.ui_group.add(self.radar) # Alien p = get_nearest(V2(0, game.RES[1]), self.get_civ_planets(self.enemy.civ))[0] p.population = 5
def joystick_update(self, dt): all_sprites = [] all_sprites.extend( sorted(self.scene.ui_group.sprites()[::], key=lambda x: x.layer, reverse=True)) all_sprites.extend( sorted(self.scene.game_group.sprites()[::], key=lambda x: x.layer, reverse=True)) selectable_sprites = [ s for s in all_sprites if s.selectable and s.visible and self.joy_hover_filter(s) ] if self.joy_controls_state == "default": self.scene.fleet_managers['my'].update_fleet_markers( self.joystick_overlay.cursor_pos) nearest, d = get_nearest(self.joystick_overlay.cursor_pos, selectable_sprites) if d < 40**2: self.joystick_overlay.set_nearest(nearest) else: self.joystick_overlay.set_nearest(None) nearest = None if self.joy_controls_state == "default": if isinstance(nearest, planet.planet.Planet): if nearest.owning_civ == self.scene.player_civ: self.joystick_overlay.set_button_options( ["[*x*] Planet Info", "[*square*] Order Ships"]) else: self.joystick_overlay.set_button_options( ["[*x*] Planet Info"]) else: self.joystick_overlay.set_button_options([]) elif self.joy_controls_state == "arrow": if nearest: self.joystick_overlay.set_button_options( ["[*x*] Select Target", "[*circle*] Cancel"]) else: self.joystick_overlay.set_button_options(["[*circle*] Cancel"]) if self.current_panel and self.current_panel.panel_for != self.joystick_overlay.nearest_obj: self.current_panel.kill() self.current_panel = None if self.current_panel and isinstance(self.current_panel.panel_for, planet.planet.Planet): self.current_panel.update_planet() if self.joy_controls_state == "arrow": if self.joy_arrow_from.owning_civ and self.joy_arrow_from.owning_civ == self.scene.player_civ: self.arrow.setup(self.joy_arrow_from, self.joystick_overlay.cursor_pos, self.joystick_overlay.nearest_obj) else: self.arrow.kill() self.joy_arrow_from = None self.joy_controls_state = "default"
def state_returning(self, dt): if self.fuel_remaining <= 0 and self.turnaround_spr: self.turnaround_time += dt self.turnaround_spr.pos = self.pos + V2(3, -8) if self.turnaround_time < 1: self.turnaround_spr.frame = min(int(self.turnaround_time * 4), 3) else: self.turnaround_spr.frame = int( self.turnaround_time * 4) % 2 + 2 if self.turnaround_time > 8: self.turnaround_spr.kill() self.turnaround_spr = None if self.get_stat("warp_drive"): if self._timers['warp_drive'] > 0: WARP_MIN_PLANET_DIST = 40 _, distsq = helper.get_nearest( self.pos, self.scene.get_planets_in_range(self.pos, WARP_MIN_PLANET_DIST)) if distsq > WARP_MIN_PLANET_DIST**2: self.warp(self.get_stat("warp_drive") * 10 + 20) self._timers['warp_drive'] = -20 if self.effective_target.owning_civ != self.owning_civ: self.set_state(STATE_RETURNING) elif self.effective_target: self.target_velocity = self.scene.flowfield.get_vector( self.pos, self.effective_target, 10) * self.get_cruise_speed() else: self.set_state(STATE_WAITING)
def take_damage(self, damage, origin=None): armor = 0 if self.get_stat("ship_armor_far_from_home"): nearest, dist = helper.get_nearest( self.pos, self.scene.get_civ_planets(self.owning_civ)) if dist > FAR_FROM_HOME_DIST**2: armor = self.get_stat("ship_armor_far_from_home") armor += self.get_stat("ship_armor") if damage > 1 and armor > 0: damage = max(damage - armor, 1) if damage >= self.health: if origin and isinstance( origin, bullet.Bullet) and origin.shooter and hasattr( origin.shooter, "owning_civ"): if origin.shooter.get_stat("hacking"): if self.is_in_deep_space() and random.random() < 0.25: self.health = self.get_max_health() damage = 0 super().take_damage(damage, origin=origin) self.change_owner(origin.shooter.owning_civ) self.set_state("returning") return return super().take_damage(damage, origin=origin)
def __init__(self, scene, pos, owning_civ): super().__init__(scene, pos, owning_civ) self.set_sprite_sheet("assets/warpship.png", 13) self.tethered_to, _ = get_nearest( self.pos, self.scene.get_civ_planets(owning_civ)) self.line1 = line.Line(V2(0, 0), V2(0, 0), PICO_LIGHTGRAY) self.line2 = line.Line(V2(0, 0), V2(0, 0), PICO_RED) self.scene.game_group.add(self.line1) self.scene.game_group.add(self.line2) self.update_lines()
def recall_fleet(self, fleet): nearest, dist = helper.get_nearest(fleet.ships[0].pos, self.scene.get_civ_planets(fleet.ships[0].owning_civ)) any_returned = False if nearest: for ship in fleet.ships: if ship.state != 'returning': any_returned = True ship.set_target(nearest) ship.set_state('returning') if any_returned and fleet.ships[0].owning_civ.is_player: sound.play("recall")
def get_max_shield(self): shield = self.extra_shield if self.get_stat("enclosure_shield") and self.fleet and len( self.fleet.ships) >= 4: shield += self.get_stat("enclosure_shield") if self.get_stat('ship_shield_far_from_home'): _, near_dist = helper.get_nearest( self.pos, self.scene.get_civ_planets(self.owning_civ)) if near_dist > FAR_FROM_HOME_DIST**2: shield += self.get_stat('ship_shield_far_from_home') if self.in_void(): shield *= 2 return shield
def joystick_update(self, dt): all_sprites = [] all_sprites.extend( sorted(self.scene.ui_group.sprites()[::], key=lambda x:x.layer, reverse=True) ) selectable_sprites = [s for s in all_sprites if s.selectable and s.visible and self.hover_filter(s)] nearest, d = get_nearest(self.joystick_overlay.cursor_pos, selectable_sprites) if d < 40 ** 2: self.joystick_overlay.set_nearest(nearest) else: self.joystick_overlay.set_nearest(None) nearest = None self.joystick_overlay.cursor_pos = rect_contain( self.joystick_overlay.cursor_pos, self.panel.x, self.panel.y, self.panel.width, self.panel.height )
def joystick_update(self, dt): if self.pending_upgrade is None: return all_sprites = [] all_sprites.extend( sorted(self.scene.ui_group.sprites()[::], key=lambda x:x.layer, reverse=True) ) all_sprites.extend( sorted(self.scene.game_group.sprites()[::], key=lambda x:x.layer, reverse=True) ) selectable_sprites = [s for s in all_sprites if s.selectable and s.visible and isinstance(s, SpaceObject) and self.hover_filter(s)] nearest, d = get_nearest(self.joystick_overlay.cursor_pos, selectable_sprites) if d < 40 ** 2: self.joystick_overlay.set_nearest(nearest) else: self.joystick_overlay.set_nearest(None)
def _generate_base_grid(self, avoidees): grid = [] for gy in range(self.gh): grid.append([]) for gx in range(self.gw): cell = None center = V2(gx * GRIDSIZE + GRIDSIZE / 2, gy * GRIDSIZE + GRIDSIZE / 2) + self.offset closest, dist = get_nearest(center, avoidees) if closest: extra = EXTRA if isinstance(closest, hazard.Hazard): extra = 6 if dist < (closest.radius + extra) ** 2: #print(center, closest.pos, closest) delta = helper.try_normalize(center - closest.pos) cell = (closest, delta) grid[-1].append(cell) return grid
def state_cruising(self, dt): if not self.chosen_target.is_alive(): self.set_state(STATE_RETURNING) return delta = self.effective_target.pos - self.pos use_path = True if not self.scene.flowfield.has_field( self.effective_target ) or delta.length_squared() < NO_PATH_RANGE**2: use_path = False if use_path: towards_flow = self.scene.flowfield.get_vector( self.pos, self.effective_target, 0) towards_center = towards_flow distance = 1 if self.fleet and len(self.fleet.path) > 2 and len( self.fleet.ships) > 1: distance = (self.fleet.path[2] - self.pos).length() towards_center = helper.try_normalize(self.fleet.path[2] - self.pos) ratio = 0.5 ratio = helper.clamp(20 / (distance + 1), 0, 1) self.debug_ratio = ratio self.target_velocity = (towards_flow * ratio + towards_center * (1 - ratio)) * self.get_cruise_speed() else: self.target_velocity = helper.try_normalize( delta) * self.get_cruise_speed() # Warp if self.get_stat("warp_drive"): if self._timers['warp_drive'] > 0: WARP_MIN_PLANET_DIST = 40 _, distsq = helper.get_nearest( self.pos, self.scene.get_planets_in_range(self.pos, WARP_MIN_PLANET_DIST)) if distsq > WARP_MIN_PLANET_DIST**2: self.warp(self.get_stat("warp_drive") * 10 + 20) self._timers['warp_drive'] = -20
def find_new_target(self): def is_valid(t): return isinstance(t, Asteroid) or (t.owning_civ and t.owning_civ != self.planet.owning_civ and t.health > 0) d = helper.from_angle(self.angle) * 5 steps = 0 p = V2(self.pos + helper.from_angle(self.angle) * 6) self.target = None while (p.x > 0 and p.x < self.scene.game.game_resolution.x) and (p.y > 0 and p.y < self.scene.game.game_resolution.y): p += d steps += 1 possible = [o for o in self.scene.get_objects_in_range(p, 25) if not isinstance(o, bullet.Bullet)] nearest, dsq = helper.get_nearest(p, possible) if not nearest: continue if dsq < (nearest.radius) ** 2: if is_valid(nearest): self.target = nearest break elif dsq < (nearest.radius + steps * 2) ** 2 and is_valid(nearest): self.target = nearest
def update(self, dt): self.time += dt self.health_bar.pos = self.pos + V2(0, -self.height / 2) if self.time > 1.0 and not self.jumped: self.jumped = True bad_location = True i = 0 while bad_location: np = V2( self.scene.game.game_resolution.x * 0.66, self.scene.game.game_resolution.y * 0.4 ) + helper.random_angle() * random.random() * (50 + i * 10) _, dsq = helper.get_nearest(np, self.scene.get_planets()) if dsq > 50**2: bad_location = False i += 1 delta = np - self.pos dn = helper.try_normalize(delta) side = V2(dn.y, -dn.x) for i in range(12): color = random.choice( [PICO_RED, PICO_RED, PICO_ORANGE, PICO_YELLOW, PICO_WHITE]) z = random.randint(-12, 12) l1 = LaserParticle(self.pos + side * z / 2, np - dn * (10 - abs(z)) + side * z, color, random.random()) self.scene.game_group.add(l1) self.pos = np self.frame = int(self.time * 3) % 15 if self.state == self.STATE_CINEMATIC_TRAVELING: self.target_planet, sqdist = helper.get_nearest( self.pos, self.planets_to_revive) if self.target_planet: #delta = self.target_planet.pos - self.pos if sqdist < REVIVING_PLANET_CLOSE_RANGE**2: self.state = self.STATE_CINEMATIC_POPULATING self.emit = ['bosscolonist'] num = 2 if len(self.planets_to_revive) == len(self.ships_on_board): num = 1 if len(self.planets_to_revive) > len(self.ships_on_board): num = 0 for i in range(num): self.emit.append(self.ships_on_board.pop(0)) self.emit_timer = 5.0 if self.target_planet.owning_civ == self.scene.player_civ: possible_evacs = self.scene.get_civ_planets( self.scene.player_civ) possible_evacs.remove(self.target_planet) if possible_evacs: possible_evacs = helper.nearest_order( V2(0, self.scene.game.game_resolution.y // 2), possible_evacs) evac_target = random.choice(possible_evacs[0:3]) for ship, amt in self.target_planet.ships.items(): for i in range(amt): self.target_planet.emit_ship( ship, {"to": evac_target}) if self.target_planet.population: self.target_planet.emit_ship( "colonist", { "to": evac_target, "num": self.target_planet.population }) return towards_planet = self.scene.flowfield.get_vector( self.pos, self.target_planet, 5) self.velocity += towards_planet * dt * ACCEL if self.state == self.STATE_CINEMATIC_POPULATING: self.brake(dt) self.emit_timer -= dt if not self.emit: if self.emit_timer < -3: self.planets_to_revive.remove(self.target_planet) if self.planets_to_revive: self.state = self.STATE_CINEMATIC_TRAVELING else: self.state = self.STATE_GAME_WAITING self.range_indicator = RangeIndicator( self.pos, REINCARNATE_RANGE, PICO_ORANGE, 1, 5) self.scene.ui_group.add(self.range_indicator) else: if self.emit_timer < 0: if self.target_planet.owning_civ == self.scene.player_civ: self.target_planet.change_owner(None) self.emit_timer = 1.0 name = self.emit.pop(0) ctor = SHIPS_BY_NAME[name] ship = ctor(self.scene, self.pos, self.owning_civ) if 'colonist' in name: ship.set_pop(3) ship.set_target(self.target_planet) self.scene.game_group.add(ship) pass if self.state == self.STATE_GAME_WAITING: self.wander(dt) self.wait_time -= dt if self.wait_time < 0: self.state = self.STATE_GAME_TRAVELING self.travel_target = None if self.state == self.STATE_GAME_TRAVELING: if not self.travel_target: # Pick only fleets targeting a neutral or player planet fleets = [ f for f in self.scene.fleet_managers['enemy'].current_fleets if f.target.owning_civ != self.owning_civ and isinstance(f.target, planet.Planet) ] if fleets: self.travel_target = random.choice(fleets).target else: self.state = self.STATE_GAME_WAITING self.wait_time = 5 self.wander_center = V2(self.pos) if self.travel_target: delta = self.travel_target.pos - self.pos if delta.length_squared() > (REINCARNATE_RANGE - 10)**2: accel = self.scene.flowfield.get_vector( self.pos, self.travel_target, 10) * ACCEL self.velocity += accel * dt else: self.state = self.STATE_GAME_WAITING self.wander_center = V2(self.pos) self.wait_time = 30 objs = self.scene.get_planets() + self.scene.get_hazards() nearest, dsq = helper.get_nearest(self.pos, objs) if dsq < 40**2: delta = nearest.pos - self.pos self.velocity += -helper.try_normalize(delta) * ACCEL / 2 * dt if self.velocity.length_squared() > self.max_speed**2: self.velocity = helper.try_normalize( self.velocity) * self.max_speed self.pos += self.velocity * dt if self.range_indicator: self.range_indicator.pos = self.pos if self.state in [self.STATE_GAME_WAITING, self.STATE_GAME_TRAVELING]: self.update_reincarnation() return super().update(dt)
def enter_state_returning(self): nearest, dist = helper.get_nearest( self.pos, self.scene.get_civ_planets(self.owning_civ)) if nearest: self.set_target(nearest)
def update(self, dt): if hasattr(self.get_max_speed, 'cache_clear'): self.get_max_speed.cache_clear() if not self.updated_color: self.update_color() self.updated_color = True self.time += dt if self.health <= 0: e = explosion.Explosion( self.pos, [PICO_WHITE, PICO_LIGHTGRAY, PICO_DARKGRAY], 0.25, 13, scale_fn="log", line_width=1) self.scene.game_group.add(e) self.kill() return self.states[self.state]['update'](dt) # Factor in fleet forces self.fleet_forces = self.get_fleet_forces(dt) * FLEET_POWER if self.fleet_forces.length_squared() > self.fleet_minimum_forces**2: self.target_velocity += self.fleet_forces # Try to get to the target velocity velocity_adjust_total = self.target_velocity - self.velocity # We want to reduce thrust if we're trying to thrust away from our heading angle_thrust_adjust = 1 if velocity_adjust_total.x or velocity_adjust_total.y: velocity_adjust_final = helper.try_normalize(velocity_adjust_total) else: velocity_adjust_final = velocity_adjust_total current_heading_vec = helper.from_angle(self.angle) dp = velocity_adjust_final.dot(current_heading_vec) if dp < 0: # dot product < 0 means that the two vectors are facing away from eachother. angle_thrust_adjust = 0.5 velocity_adjust_frame = velocity_adjust_final * dt * self.get_thrust_accel( ) * angle_thrust_adjust if velocity_adjust_frame.length_squared( ) > velocity_adjust_total.length_squared() * angle_thrust_adjust: self.velocity = self.target_velocity * angle_thrust_adjust else: self.velocity += velocity_adjust_frame if self.velocity.length_squared() > (self.get_max_speed() * angle_thrust_adjust)**2: self.velocity = helper.try_normalize( self.velocity) * self.get_max_speed() * angle_thrust_adjust # Set angle based on velocity if self.target_heading is None: if self.velocity.length_squared() > 0: _, self.angle = self.velocity.as_polar() self.angle *= 3.14159 / 180 else: angle_delta = helper.get_angle_delta(self.angle, self.target_heading) if abs(angle_delta) < ROTATE_SPEED * dt: self.angle = self.target_heading elif angle_delta < 0: self.angle -= ROTATE_SPEED * dt else: self.angle += ROTATE_SPEED * dt if self.velocity.length_squared() > 0: if self._timers['thrust_particle_time'] > THRUST_PARTICLE_RATE: self.emit_thrust_particles() self._timers['thrust_particle_time'] = 0 # Nearest hazard nearest, dsq = helper.get_nearest(self.pos, [ o for o in self.scene.get_objects_in_range(self.pos, 20) if o.collidable and o.stationary ]) if nearest and nearest != self.effective_target: dsf = dsq - nearest.radius**2 delta = helper.try_normalize(nearest.pos - self.pos) near = 20 if dsf > 0 and dsf < near**2: t = 1 - math.sqrt(dsf) / near self.velocity += -delta * t * 5 * dt side = V2(delta.y, -delta.x) fwd = helper.try_normalize(self.velocity) cross = fwd.cross(side) if cross > 0: side = -side self.velocity += side * t * 5 * dt # Stay away from the edges of the world if self.pos.x < 5: self.velocity.x += dt * self.get_thrust_accel() * 2 if self.pos.y < 5: self.velocity.y += dt * self.get_thrust_accel() * 2 if self.pos.x > game.Game.inst.game_resolution.x - 5: self.velocity.x -= dt * self.get_thrust_accel() * 2 if self.pos.y > game.Game.inst.game_resolution.y - 5: self.velocity.y -= dt * self.get_thrust_accel() * 2 # Fuel empty if self.state == STATE_CRUISING: speed_adjust = self.get_max_speed() / self.MAX_SPEED cruise_travel_dist_frame = self.velocity.length( ) * dt / speed_adjust self.fuel_remaining -= cruise_travel_dist_frame if self.fuel_remaining < 0: sound.play("recall") self.set_state(STATE_RETURNING) self.turnaround_spr = FrameSprite( self.pos, "assets/fighterturnaround.png", 6) self.scene.ui_group.add(self.turnaround_spr) self.turnaround_time = 0 # TODO: Error sound self.pos += self.velocity * dt self.health_bar.pos = self.pos + V2(0, -6) self.shield_bar.pos = self.pos + V2(0, -9) self.special_stat_update(dt) if self.scene.game.run_info.o2 <= 0 and self.owning_civ and self.owning_civ.is_player: self.health -= self.get_max_health() / 60 * dt super().update(dt) if self.stealth: if self._sheet != self._stealth_sheet: self.set_stealth_image() self._timers['thrust_particle_time'] = -1 else: if self._unstealth_sheet and self._sheet != self._unstealth_sheet: self._sheet = self._unstealth_sheet
def is_in_deep_space(self): nearest, distsq = helper.get_nearest(self.pos, self.scene.get_planets()) return distsq > DEEP_SPACE_DIST**2