예제 #1
0
    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
예제 #2
0
 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
예제 #3
0
    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()
예제 #4
0
 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)
예제 #5
0
    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
예제 #6
0
    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))
예제 #7
0
 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)
예제 #8
0
 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
예제 #9
0
    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()
예제 #10
0
파일: game.py 프로젝트: angrycaptain19/4x2d
    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()
예제 #11
0
 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)
     ]
예제 #12
0
파일: line.py 프로젝트: angrycaptain19/4x2d
    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()
예제 #13
0
 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)]
예제 #14
0
    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)
예제 #15
0
    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)
예제 #16
0
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))
예제 #17
0
 def sphere_get(offset, planet_pos):
     spherize = 0.25 + pow(planet_pos.magnitude(), 1.75) / 40.0
     dist, angle = planet_pos.to_polar()
     angle += wavy_angle
     p2 = offset + V2.from_angle(angle) * dist * spherize
     color = wavy.get_at((int(p2.x), int(p2.y)))
     return color
예제 #18
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()
예제 #19
0
    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()
예제 #20
0
 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()
예제 #21
0
 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()
예제 #22
0
 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)
예제 #23
0
 def update(self, planet, dt):
     self.fire_time += dt
     threats = planet.get_threats()
     if self.fire_time > self.FIRE_RATE and threats:
         self.fire_time = 0
         for i in range(planet.population):
             angle = random.random() * 6.2818
             b = Bullet(planet.pos +
                        V2.from_angle(angle) * planet.get_radius(),
                        random.choice(threats),
                        planet,
                        vel=V2.from_angle(angle) * 20,
                        mods={
                            'homing': True,
                            "damage_debuff": 0.5
                        })
             planet.scene.game_group.add(b)
예제 #24
0
    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
예제 #25
0
 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
예제 #26
0
 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)
예제 #27
0
 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)
예제 #28
0
    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)
예제 #29
0
 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()
예제 #30
0
    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()