Example #1
0
    def apply_explosion_effects(self,
                                explosion_center,
                                damage_at_center=100,
                                blast_radius=200,
                                pushback_force_at_center=500,
                                pushback_radius=300):
        # play explosion sound
        registry.global_controllers.assets_controller.explosion_sound.play()
        enemies_to_remove = []
        for enemy in self.enemies:
            # get the distance to the explosion
            distance_to_explosion = enemy.position.distance(explosion_center)

            # if within pushback radius...
            if distance_to_explosion <= pushback_radius:
                # calculate pushback value, the further from the center, the smaller it is
                pushback_force_val = pushback_force_at_center * (
                    1 - (distance_to_explosion / pushback_radius))
                # apply the pushback force by resetting enemy velocity
                enemy.velocity = (enemy.position - explosion_center
                                  ).normalize() * pushback_force_val

            # if within blast radius...
            if distance_to_explosion <= blast_radius:
                # calculate damage, the further from the center, the smaller it is
                damage = damage_at_center * (
                    1 - (distance_to_explosion / blast_radius))
                # apply damage
                enemy.hp -= int(damage)
                # add the blood splatter animation over the enemy
                self.scene.root.add_child(
                    Node(z_index=900,
                         transition=NodeSpriteTransition(
                             registry.global_controllers.assets_controller.
                             blood_splatter_frames,
                             duration=140),
                         position=enemy.position,
                         rotation=(enemy.position -
                                   explosion_center).to_angle() + math.pi,
                         lifetime=140))

                if enemy.hp < 0:  # IZ DED!
                    # show the death animation (pick random sprite from few animations we have loaded from one png file)
                    self.scene.root.add_child(
                        Node(z_index=1,
                             transition=NodeSpriteTransition(random.choice(
                                 registry.global_controllers.assets_controller.
                                 enemy_death_frames),
                                                             duration=450),
                             position=enemy.position,
                             rotation=enemy.rotation,
                             origin_alignment=Alignment.right,
                             lifetime=random.randint(10000, 20000)))
                    # mark enemy for removal:
                    enemies_to_remove.append(enemy)

        # removed killed enemies
        for dead_enemy in enemies_to_remove:
            self.remove_enemy(dead_enemy)
    def on_collision_mg_bullet_enemy(self, arbiter, mg_bullet_pair,
                                     enemy_pair):
        print(
            "Detected a collision between MG bullet object {} hitbox {} and Enemy object {} hitbox {}"
            .format(mg_bullet_pair.body, mg_bullet_pair.hitbox,
                    enemy_pair.body, enemy_pair.hitbox))

        if arbiter.phase == CollisionPhase.begin:
            enemy = enemy_pair.body
            enemy.hp -= 10
            # add the blood splatter animation to the scene
            self.scene.root.add_child(
                Node(z_index=900,
                     transition=NodeSpriteTransition(
                         registry.global_controllers.assets_controller.
                         blood_splatter_frames,
                         duration=140),
                     position=enemy.position,
                     rotation=mg_bullet_pair.body.rotation + math.pi,
                     lifetime=140))
            # add a random bloodstain - make smaller ones more likely since it's a small arms hit :)
            self.scene.root.add_child(
                Node(z_index=1,
                     sprite=random.choices(registry.global_controllers.
                                           assets_controller.bloodstain_imgs,
                                           weights=[5, 3, 1, 0.5])[0],
                     position=enemy.position,
                     rotation=mg_bullet_pair.body.rotation + math.pi,
                     lifetime=random.randint(20000, 40000)))
            if enemy.hp <= 0:
                # show death animation
                self.scene.root.add_child(
                    Node(z_index=1,
                         transition=NodeSpriteTransition(random.choice(
                             registry.global_controllers.assets_controller.
                             enemy_death_frames),
                                                         duration=450),
                         position=enemy.position,
                         rotation=enemy.rotation,
                         origin_alignment=Alignment.right,
                         lifetime=random.randint(10000, 20000)))
                # remove enemy node from the scene
                self.scene.enemies_controller.remove_enemy(enemy)
            else:
                enemy.stagger()

            mg_bullet_pair.body.delete()  # remove the bullet from the scene
            return 0
Example #3
0
    def __init__(self, position, hp=100, *args, **kwargs):
        # node's properties
        super().__init__(body_type=BodyNodeType.dynamic, mass=1,
                         z_index=10, position=position,
                         transition=NodeSpriteTransition(registry.global_controllers.assets_controller.enemy_frames,
                                                         duration=max(200, random.gauss(400, 100)), loops=0),
                         *args, **kwargs)
        # create a hitbox and add it as a child node to the Enemy
        self.add_child(HitboxNode(
            shape=Polygon([Vector(-8, -19), Vector(8, -19), Vector(8, 19), Vector(-8, 19), Vector(-8, -19)]),
            mask=HitboxMask.enemy,
            collision_mask=HitboxMask.all,
            trigger_id=settings.COLLISION_TRIGGER_ENEMY,
        ))
        # custom properties
        self.hp = hp
        self.stagger_time_left = 0

        # 75% enemies will move towards player and 25% will move randomly
        if random.randint(0, 100) < 75:
            self.movement_mode = EnemyMovementMode.MoveToPlayer
        else:
            self.movement_mode = EnemyMovementMode.MoveToWaypoint
        self.current_waypoint = None  # for those which move to a waypoint, we'll keep its corrdinates here
        self.randomize_new_waypoint()  # and randomize new waypoint

        self.acceleration_per_second = 300  # how fast will enemy accelerate
        self.max_velocity = random.randint(75, 125)  # we'll make enemy stop accelerating if velocity is above this value
Example #4
0
    def __init__(self, *, speed_mod, faded=False, **kwargs):
        assert self.SPRITE_FRAMES
        assert self.TRIGGER_ID

        super().__init__(
            body_type=BodyNodeType.kinematic,
            position=random.choice(LANE_ENEMY_SLOTS),
            velocity=Vector(0, random.uniform(300, 300 + speed_mod)),
            angular_velocity_degrees=random.uniform(-20, 20),
            **kwargs,
        )
        self._is_destroying = False

        self.hitbox = self.add_child(
            HitboxNode(
                trigger_id=self.TRIGGER_ID,
                shape=Circle(48.),
                # color=Color(1., 0., 0., 0.5),
                z_index=100,
            ))

        self.transitions_manager.set(
            'animation',
            NodeSpriteTransition(self.SPRITE_FRAMES,
                                 loops=0,
                                 duration=len(self.SPRITE_FRAMES) *
                                 self.FRAME_DURATION),
        )

        if faded:
            self.color = Color(0.5, 0.5, 0.5, 1.)
Example #5
0
    def __init__(self, **kwargs):
        self.is_moving = False
        self.is_frozen = False
        self.current_lane = 2
        self.soap_fuel = self.soap_fuel_max = 30000

        super().__init__(
            body_type=BodyNodeType.kinematic,
            position=LANE_HERO_SLOTS[self.current_lane],
            scale=Vector.xy(0.7),
            **kwargs,
        )

        self.hitbox = self.add_child(
            HitboxNode(
                trigger_id=CollisionTrigger.soap,
                shape=Polygon.from_box(Vector(138, 330)),
                # color=Color(1., 0., 0., 0.5),
                z_index=100,
            ))

        self.transitions_manager.set(
            'animation',
            NodeSpriteTransition(self.SPRITE_FRAMES,
                                 loops=0,
                                 duration=len(self.SPRITE_FRAMES) *
                                 self.FRAME_DURATION),
        )
    def on_collision_grenade_enemy(self, arbiter, grenade_pair, enemy_pair):

        if arbiter.phase == CollisionPhase.begin:
            # show explosion animation
            self.scene.root.add_child(
                Node(transition=NodeSpriteTransition(
                    registry.global_controllers.assets_controller.
                    explosion_frames,
                    duration=12 * 75),
                     position=grenade_pair.body.position,
                     z_index=1000,
                     lifetime=12 * 75))
            # apply explosion effects to enemies (deal damage & push them back)
            self.scene.enemies_controller.apply_explosion_effects(
                grenade_pair.body.position)

            grenade_pair.body.delete()  # remove the grenade from the scene
            return 0
Example #7
0
File: main.py Project: labuzm/kaa
    def __init__(self):
        self.camera.position = Vector(0., 0.)
        self.python_img = Sprite(PYTHON_IMAGE_PATH)

        self.transition = NodeTransitionsSequence([
            NodePositionTransition(
                Vector(-100., -100.),
                3.,
                advance_method=AttributeTransitionMethod.add,
                loops=3,
                easing=Easing.elastic_in_out),
            NodePositionTransition(
                Vector(100., 0.),
                3.,
                advance_method=AttributeTransitionMethod.add,
                easing=Easing.back_in_out),
            NodeTransitionDelay(1.5),
            NodeTransitionCallback(lambda node: setattr(node, 'sprite', None)),
            NodeTransitionsParallel([
                NodePositionTransition(
                    Vector(-50., 100.),
                    3.,
                    advance_method=AttributeTransitionMethod.add),
                NodeRotationTransition(1., 5.),
                NodeScaleTransition(Vector(2., 2.), 3.),
                NodeColorTransition(Color(0., 1., 0., 0.5), 4.),
            ],
                                    back_and_forth=True),
        ])

        self.custom_transition = NodeCustomTransition(
            prepare_func=lambda node: {
                'positions': [
                    Vector(random.uniform(-100, 100), random.uniform(
                        -100, 100)) for _ in range(10)
                ]
            },
            evaluate_func=lambda state, node, t: setattr(
                node,
                'position',
                state['positions'][min(int(t * 10), 9)],
            ),
            duration=10.,
            loops=5,
        )

        spritesheet_frames = split_spritesheet(
            Sprite(EXPLOSION_IMAGE_PATH),
            Vector(64, 64),
        )
        self.sprite_transition = NodeSpriteTransition(
            spritesheet_frames,
            1.,
            loops=0,
            back_and_forth=True,
            easing=Easing.quartic_out,
        )

        self.space = self.root.add_child(SpaceNode())

        self.obj = self.space.add_child(
            Node(
                position=Vector(50., 50.),
                sprite=self.python_img,
                transition=self.transition,
            ))

        self.custom_obj = self.space.add_child(
            Node(
                color=Color(1., 0., 0.),
                sprite=self.python_img,
                transition=self.custom_transition,
            ))

        self.phys_obj = self.space.add_child(
            BodyNode(
                color=Color(0., 1., 1.),
                position=Vector(-50., 50.),
                sprite=self.python_img,
                velocity=Vector(0., 30.),
                transition=BodyNodeVelocityTransition(Vector(0., -30.), 10.),
            ))

        self.animated_obj = self.space.add_child(
            Node(
                position=Vector(-20., 10.),
                transition=self.sprite_transition,
            ))
Example #8
0
    def recover_from_stagger(self):
        # start using the standard sprite animation again
        self.transition=NodeSpriteTransition(registry.global_controllers.assets_controller.enemy_frames,
                                                         duration=max(200, random.gauss(400, 100)), loops=0)

        self.stagger_time_left = 0