def enter(self): UIEnabledState.enter(self) self.panel = HelpPanel(V2(0,0)) self.panel.add_all_to_group(self.scene.ui_group) self.panel.pos = V2(game.RES[0] /2 - self.panel.width / 2, game.RES[1] / 2 - self.panel.height / 2) self.panel._reposition_children() self.scene.paused = True
def __init__(self, planet): super().__init__(V2(0, 0)) self.planet = planet self._num_ships = 0 self._generate_image() self.visible = False self.pos = planet.pos + V2(3, 3)
def _generate_frame(self, border = False): radius = self.size + 8 padding = 8 cx,cy = radius + padding, radius + padding self._width = radius * 2 + padding * 2 self._height = radius * 2 + padding * 2 frame = pygame.Surface((self._width, self._height), pygame.SRCALPHA) border_radius = 2 if border else 1 color = self.owning_civ.color if self.owning_civ else PICO_YELLOW # Border pygame.draw.circle(frame, color, (cx,cy), radius + border_radius) for building in self.buildings: offset = V2.from_angle(building['angle'] + self.base_angle) * radius + V2(cx, cy) building['building'].draw_outline(frame, color, offset, building['angle'] + self.base_angle,expand=border) # Foreground #pygame.draw.circle(frame, PICO_GREYPURPLE, (cx,cy), radius) rotated = pygame.transform.rotate(self.art, 0) frame.blit(rotated, (cx - rotated.get_width() // 2, cy - rotated.get_height() // 2)) for building in self.buildings: offset = V2.from_angle(building['angle'] + self.base_angle) * radius + V2(cx, cy) building['building'].draw_foreground(frame, offset, building['angle'] + self.base_angle) return frame
def _generate_image(self): r = 13 color_by_angles = [] angle_so_far = 0 for color, value in self.data.items(): a1 = angle_so_far a2 = angle_so_far + value / 100.0 * 6.2818 color_by_angles.append((a1, a2, color)) angle_so_far = a2 self.image = pygame.Surface((r * 2, r * 2), pygame.SRCALPHA) center = V2(r - 0.5, r - 0.5) for x in range(r * 2): for y in range(r * 2): pt = V2(x, y) delta = (pt - center) if delta.sqr_magnitude() < r**2: angle = math.atan2(delta.y, delta.x) + 3.1415 / 2 if angle < 0: angle += 6.2818 color = PICO_BLACK for angle1, angle2, anglecolor in color_by_angles: if angle >= angle1 and angle < angle2: color = anglecolor self.image.set_at((pt.x, pt.y), color) self._width = self.image.get_width() self._height = self.image.get_width() self._recalc_rect()
def get_fleet_target_vector(self): target_vector = V2(0, 0) our_ships = self.scene.get_civ_ships(self.owning_civ) fleet_ships = [ s for s in our_ships if (s.pos - self.pos).sqr_magnitude() <= FLEET_RADIUS**2 ] fleet_ships.remove(self) # Separation for ship in fleet_ships: delta = ship.pos - self.pos sm = delta.sqr_magnitude() if sm < FLEET_SEPARATION_MAX**2: target_vector -= ( delta.normalized() * (FLEET_SEPARATION_DEGRADE / sm)) * FLEET_SEPARATION_POWER # Proximity center = V2(0, 0) for ship in fleet_ships: center += ship.pos / len(fleet_ships) delta = center - self.pos target_vector += delta.normalized() * FLEET_PROXIMITY_POWER return target_vector
def __init__(self, scene, pos, owning_civ, sheet): AnimRotSprite.__init__(self, pos, sheet, 12) self.base_speed = 7 self.scene = scene self.owning_civ = owning_civ self.target = None self.offset = (0.5, 0.5) self.speed_t = random.random() * 6.2818 self._layer = 2 self.velocity = V2(0, 0) self.push_velocity = V2(0, 0) self.orbits = True self.collidable = True self.collision_radius = 1 self.thrust_particle_time = 0 self._recalc_rect() self.warp_drive_countdown = 0 self.warp_drive_t = 0 self.base_health = BASE_HEALTH self.size = 2 Healthy.__init__(self, self.scene, (14, 3))
def add_ship(self, type): if type in self.ships: self.ships[type] += 1 else: self.ships[type] = 1 if self.owning_civ == self.scene.my_civ: it = IconText(self.pos, "assets/i-%s.png" % type, "+1", PICO_PINK) it.pos = self.pos - V2(it.width, it.height) * 0.5 + V2(random.random(), random.random()) * 15 self.scene.ui_group.add(it) self.needs_panel_update = True
def _generate_image(self): self.image = pygame.Surface((9, 9), pygame.SRCALPHA) vn = self.vel.normalized() p1 = V2(4, 4) p2 = V2(4, 4) + vn * 2 pygame.draw.line(self.image, PICO_BLUE, p1.tuple(), p2.tuple(), 1) self._width = 9 self._height = 9 self._recalc_rect()
def draw_outline(self, surface, color, offset, angle, expand=False): for points, _ in self.shapes: self.draw_shape(surface, points, color, offset + V2(-1, 0), angle, expand) self.draw_shape(surface, points, color, offset + V2(+1, 0), angle, expand) self.draw_shape(surface, points, color, offset + V2(0, -1), angle, expand) self.draw_shape(surface, points, color, offset + V2(0, +1), angle, expand)
def run(self): clock = pygame.time.Clock() running = True self.scene.start() while running: for event in pygame.event.get(): if event.type == sound.MUSIC_ENDEVENT: sound.end_of_music() if event.type == pygame.QUIT: running = False if event.type == pygame.KEYDOWN: if event.key == pygame.K_LEFT: self.scene.take_input("left", event) elif event.key == pygame.K_RIGHT: self.scene.take_input("right", event) elif event.key == pygame.K_UP: self.scene.take_input("up", event) elif event.key == pygame.K_DOWN: self.scene.take_input("down", event) elif event.key == pygame.K_SPACE: self.scene.take_input("action", event) elif event.key == pygame.K_ESCAPE: self.scene.take_input("back", event) self.scene = levelscene.LevelScene(self, sys.argv[1]) self.scene.start() else: self.scene.take_input("other", event) if event.type == pygame.MOUSEBUTTONDOWN: event.gpos = V2(event.pos[0] / SCALE, event.pos[1] / SCALE) if event.button == 1: self.scene.take_input("click", event) if event.button == 3: self.scene.take_input("rightclick", event) if event.type == pygame.MOUSEBUTTONUP: event.gpos = V2(event.pos[0] / SCALE, event.pos[1] / SCALE) if event.button == 1: self.scene.take_input("unclick", event) if event.button == 3: self.scene.take_input("unrightclick", event) if event.type == pygame.MOUSEMOTION: event.gpos = V2(event.pos[0] / SCALE, event.pos[1] / SCALE) if event.buttons[0]: self.scene.take_input("mouse_drag", event) else: self.scene.take_input("mouse_move", event) dt = clock.tick() / 1000.0 self.scene.update(dt) self.render()
def __init__(self): Building.__init__(self) self.shapes = [ ([V2(-1, -3), V2(6, -3), V2(6, 0), V2(3, 0), V2(3, 3), V2(-1, 3)], PICO_GREYPURPLE), ([V2(-1, -3), V2(0, -3), V2(0, 3), V2(-1, 3)], PICO_LIGHTGRAY) ]
def _generate_image(self): delta = self.pt2 - self.pt1 w = max(abs(delta.x), 1) h = max(abs(delta.y), 1) pt1 = V2(0, 0 if delta.y > 0 else -delta.y) pt2 = V2(w, delta.y if delta.y > 0 else 0) self.image = pygame.Surface((w, h), pygame.SRCALPHA) pygame.draw.line(self.image, self.color, pt1.tuple(), pt2.tuple(), 1) self._width = w self._height = h self._recalc_rect()
def __init__(self): Building.__init__(self) self.shapes = [([V2(-1, -4), V2(2, -2), V2(5, 0), V2(2, 2), V2(-1, 4)], PICO_BLUE), ([V2(-1, -4), V2(0, -4), V2(0, 4), V2(-1, 4)], PICO_LIGHTGRAY)]
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 debug_render(screen, scene): surf = pygame.Surface(screen.get_size(), pygame.SRCALPHA) for ship in scene.get_ships(): if ship.target: pygame.draw.line(surf, (255,128,255, 120), ship.pos.tuple(), ship.target.pos.tuple()) if hasattr(ship, "state"): text.FONTS['tiny'].render_to(surf, (ship.pos + V2(5,5)).tuple(), ship.state, (255,128,255,120)) if hasattr(ship, "current_dogfight_target") and ship.current_dogfight_target: pygame.draw.line(surf, (255,0,0, 120), ship.pos.tuple(), ship.current_dogfight_target.pos.tuple()) for planet in scene.get_civ_planets(scene.enemy.civ): text.FONTS['tiny'].render_to(surf, (planet.pos + V2(-15,15)).tuple(), str(planet.ships['alien-fighter']) + " fighters", (255,128,255,120)) #surf.set_alpha(50) screen.blit(surf, (0,0))
def enter(self): self.scene.paused = True self.panel = UpgradePanel(V2(0,0), self.scene.my_civ.upgrades[0], self.on_select) self.panel.add_all_to_group(self.scene.ui_group) self.panel.position_nicely(self.scene) self.hover_filter = self.filter_only_panel_ui super().enter()
def assault(self, target, dt): threats = self.get_threats() if threats: target = random.choice(threats) self.fire_time += dt fleet_target_vector = self.get_fleet_target_vector() if fleet_target_vector.sqr_magnitude() > 2**2: self.state = "traveling" self.force_travel_time = 0.125 towards = (target.pos - self.pos).normalized() cross = self.turn_towards(towards, dt) rate = FIRE_RATE / (1 + self.owning_civ.upgrade_stats['fire_rate']) if abs(cross) < 0.1 and self.fire_time >= rate: self.fire_time = 0 b = Bullet(self.pos, target, self, {}) self.scene.game_group.add(b) self.velocity += -towards * 1 #self.pos += -towards * 1 self.thrust_particle_time = THRUST_PARTICLE_RATE for i in range(10): pvel = (towards + V2(random.random() * 0.75, random.random() * 0.75) ).normalized() * 30 * (random.random() + 0.25) p = Particle([ PICO_WHITE, PICO_WHITE, PICO_BLUE, PICO_DARKBLUE, PICO_DARKBLUE ], 1, self.pos + towards * 4, 0.2 + random.random() * 0.15, pvel) self.scene.game_group.add(p)
def setup(self, start_planet, end, end_planet=None): thickness = 6 ht = thickness / 2 color = PICO_LIGHTGRAY end_offset = 0 start_offset = 20 if end_planet: end = end_planet.pos color = PICO_WHITE end_offset = 20 pt1 = start_planet.pos pt2 = end delta = pt2 - pt1 if delta.sqr_magnitude() < 25**2: self.visible = False return self.visible = True w = game.RES[0] h = game.RES[1] forward = delta.normalized() side = V2(forward.y, -forward.x) pt1 += forward * start_offset pt2 += forward * -end_offset points = [] points.append(pt1 + side * -ht) points.append(pt1 + side * ht) points.append(pt2 + side * ht + forward * -15) points.append(pt2 + side * 15 + forward * -15) points.append(pt2) points.append(pt2 + side * -15 + forward * -15) points.append(pt2 + side * -ht + forward * -15) points = [p.tuple() for p in points] arrow1 = pt2 + forward * -10 + side * 10 arrow2 = pt2 + forward * -10 + side * -10 self.image = pygame.Surface((w, h), pygame.SRCALPHA) pygame.draw.polygon(self.image, color, points, 0) self._width = w self._height = h self.pos = V2(0, 0) self._recalc_rect()
def __init__(self, pos, panel_for): spritebase.SpriteBase.__init__(self, pos) self.panel_for = panel_for self._controls = [] self.padding = 6 self._background_offset = V2(0,0) self.tab = None
def push_from_planets(self, dt): for planet in self.scene.get_planets(): dist = (planet.pos - self.pos).sqr_magnitude() if dist < (planet.get_radius() + 5)**2: delta = (self.pos - planet.pos) dir = delta.normalized() mag = abs((planet.get_radius() + 5) - delta.magnitude()) fwd = V2.from_angle(self._angle) self.push_velocity = dir * mag w = fwd.cross(dir) if w > 0: self._angle += 5 * dt self.push_velocity += V2(dir.y, -dir.x) * 2 else: self._angle -= 5 * dt self.push_velocity -= V2(dir.y, -dir.x) * 2 self.push_velocity *= 0.9
def __init__(self, planet, scene, pos): super().__init__(pos, "assets/warning.png", 19) self.planet = planet self.scene = scene self.wt = WARNINGTIME self.text = text.Text(str(WARNINGTIME), "small", self.pos + V2(7,6), PICO_RED) self.scene.ui_group.add(self.text) self._recalc_rect()
def update(self, dt): self.color_index += dt self.color = COLORS[int(self.color_index * 12) % len(COLORS)] self.pos = V2(self.pos.x, self.pos.y - 10 / (self.color_index + 0.5) * dt) self.update_image() if self.color_index >= 2.5: self.kill()
def update(self, dt): if self.can_land(self.target): self.orbits = False else: self.orbits = True self.default_update(dt) self.num_label.pos = self.pos + V2(7, -7) return super().update(dt)
def update(self, dt): self.health_bar.pos = self.pos + V2(0, -self.height / 2) if self.health <= 0: self.kill() self.warp_drive_countdown -= dt self.push_from_planets(dt) AnimRotSprite.update(self, dt)
def __init__(self, scene, meter_size = (30,4)): self._health = self.get_max_health() self.health_bar = Meter(V2(self.x, self.y - self._height / 2), meter_size[0], meter_size[1], PICO_RED, self.get_max_health()) self.health_bar.value = self.health self.health_bar.offset = (0.5,1) self.health_bar.stay = False self.health_bar.visible = 0 self.health_bar._recalc_rect() scene.ui_group.add(self.health_bar)
def enter(self): UIEnabledState.enter(self) self.hover_filter = self.filter_only_panel_ui self.panel = OrderPanel(V2(0,0), self.planet_from, self.planet_to, self.on_order) self.panel.position_nicely(self.scene) self.panel.add_all_to_group(self.scene.ui_group) self.arrow = OrderArrow() self.scene.ui_group.add(self.arrow) self.arrow.setup(self.planet_from, None, self.planet_to)
def position_nicely(self, scene): x = self.panel_for.x - self._width / 2 y = self.panel_for.y - self._height / 2 if x > game.RES[0] / 2: x = self.panel_for.x - self.panel_for._width / 2 - self._width - 10 else: x = self.panel_for.x + self.panel_for._width / 2 + 10 y = clamp(y, 2, game.RES[1] - self._height - 2 - 40) self.pos = V2(x,y) self._reposition_children()
def __init__(self, text, target=None): self.color_index = 0 size = "big" if target: size = "small" super().__init__(text.upper(), size, V2(0, 0), color=COLORS[0], border=False, multiline_width=game.RES[0], shadow=PICO_BLACK) self.pos = V2(game.RES[0] / 2, game.RES[1] / 2) if target: self.pos = V2( clamp(target.pos.x, self.width / 2, game.RES[0] - self.width / 2), clamp(target.pos.y, self.height / 2, game.RES[1] - self.height / 2)) self.offset = (0.5, 0.5) self._recalc_rect()
def enter(self): scores = save.SAVE_OBJ.add_highscore(self.scene.score) self.scene.game_group.empty() self.scene.ui_group.empty() save.SAVE_OBJ.save() picked_one = False self.scene.ui_group.add(text.Text("- High Scores -", "big", V2(170, 60), PICO_BLUE, multiline_width=200)) places = ['1st', '2nd', '3rd', '4th', '5th', '6th', '7th', '8th', '9th', '10th'] for i, score in enumerate(save.SAVE_OBJ.get_highscores()): color = PICO_WHITE if score == int(self.scene.score) and not picked_one: color = PICO_BLUE picked_one = True t1 = text.Text(places[i], "big", V2(240, i * 18 + 90), color) t1.offset = (1, 0) t1._recalc_rect() t2 = text.Text("%d" % score, "big", V2(250, i * 18 + 90), color) self.scene.ui_group.add(t1) self.scene.ui_group.add(t2) return super().enter()
def __init__(self, pos, planet_from, planet_to, on_order): super().__init__(pos, planet_from) self.planet_from = planet_from self.planet_to = planet_to self.on_order = on_order self.tab = {'text': "Send Ships", 'color': PICO_PINK} ships = {**self.planet_from.ships} ships['colonist'] = self.planet_from.population y = 0 self.sliders = {} for ship in ships.keys(): if ships[ship]: if ship == "colonist": name = "Worker" else: name = ship.title() self.add(SimpleSprite((0, 0), 'assets/i-%s.png' % ship), V2(0, y)) self.add( Text("%ss" % name, "small", (0, 0), PICO_WHITE, False), V2(14, y + 2)) slider = Slider(V2(0, 0), 80, 0, ships[ship]) self.add(slider, V2(0, y + 12)) self.sliders[ship] = slider y += 45 self.add(Button(V2(0, 0), "LAUNCH", "small", self.on_launch_click), V2(20, y)) self.redraw()