Esempio n. 1
0
    def update(self, dt):
        sent = False

        for event in self.event_bus.get_events():
            if event.ty == EventType.COLLISION:
                player = None
                if event.data['first'] == self.entity:
                    player = event.data['second']
                elif event.data['second'] == self.entity:
                    player = event.data['first']

                if player != None and self.world.has_component(
                        player,
                        Tag) and "player" in self.world.component_for_entity(
                            player, Tag).tags:
                    self.event_bus.send.append(
                        Event(
                            {
                                'type': ActionEventType.SET_INFO,
                                'id': self.entity,
                                'text': "Descend",
                                'callback': self.descend,
                                'timeout': 0.2
                            }, EventType.ACTION))
                    sent = True

        if not sent:
            return
            self.event_bus.send.append(
                Event({
                    'type': ActionEventType.DELETE_INFO,
                    'id': self.entity
                }, EventType.ACTION))
    def spawn_bomb(self):
        if self.player.bomb_timer <= 0 and self.player.data.bombs > 0:
            original = self.player.data.bombs
            self.player.data.bombs -= 1
            self.player.event_bus.send.append(
                Event(
                    {
                        'type': PlayerEventType.BOMBS_CHANGED,
                        'original': original,
                        'amount': -1,
                        'new': self.player.data.bombs
                    }, EventType.PLAYER))

            self.player.bomb_timer = constants.BOMB_COOLDOWN
            bomb = self.player.world.create_entity_with(
                *loader.load("entity", "bomb")[0])

            transform = self.player.world.component_for_entity(bomb, Transform)
            transform.position.x = self.player.transform.position.x
            transform.position.y = self.player.transform.position.y

            script = self.player.world.component_for_entity(
                bomb, ScriptComponent).script
            script.damage_data = self.player.data.get_explosion_damage(
                transform.position)
    def hurt(self, amount, knockback):
        if self.hurt_cooldown > 0:
            return
        self.hurt_cooldown = constants.HURT_COOLDOWN

        original = self.data.health

        self.data.health -= amount
        if self.data.health <= 0:
            gameover = self.world.create_entity_with(
                *loader.load("entity", "gameover")[0])

            script = self.world.component_for_entity(gameover,
                                                     ScriptComponent).script
            script.player_pos = self.transform.position

            self.data = PlayerData()
        else:
            self.collision.velocity.x += knockback.x
            self.collision.velocity.y += knockback.y

            self.sound_hurt.play()

        self.event_bus.send.append(
            Event(
                {
                    'type': PlayerEventType.HEALTH_CHANGED,
                    'original': original,
                    'amount': amount,
                    'new': self.data.health
                }, EventType.PLAYER))
    def update(self, dt):
        for event in self.event_bus.get_events():
            if event.ty == EventType.PLAYER:
                if event.data['type'] == PlayerEventType.XP_ADDED:
                    original_level = PlayerData.level_from_xp(
                        event.data['original'])
                    new_level = PlayerData.level_from_xp(event.data['new'])

                    if original_level != new_level:
                        self.event_bus.send.append(
                            Event(
                                {
                                    'type': NotifyEventType.NOTIFY,
                                    'time': 2,
                                    'title': "Level Up",
                                    'text': "Upgrades Available",
                                    'sound_path': "player/level_up.wav"
                                }, EventType.NOTIFY))

                    self.world.remove_component(self.entity, self.sprite)
                    self.sprite = Sprite.new_text("Level " + str(new_level),
                                                  (255, 255, 255), 14)
                    self.world.add_component(self.entity, self.sprite)
                    self.sprite._redraw = True
                    self.transform.x = constants.WIDTH / 2 - self.sprite.bounds.width / 2
 def start(self):
     self.player.event_bus.send.append(
         Event(
             {
                 'type': CameraEventType.FOLLOW,
                 'pos': self.player.transform.position,
                 'offset': pygame.math.Vector2(320 - 16, 200 - 16)
             }, EventType.CAMERA))
    def update(self, dt):
        for ev in pygame.event.get():
            if ev.type == pygame.QUIT:
                self.should_quit = True

            for entity, [event_component
                         ] in self.world.get_components(EventComponent):
                if EventType.PYGAME in event_component.listen:
                    event_component.send.append(Event(ev, EventType.PYGAME))
    def start(self, entity, world):
        self.animation = world.component_for_entity(entity, AnimationSets)
        self.collision = world.component_for_entity(entity, CollisionComponent)
        self.event_bus = world.component_for_entity(entity, EventComponent)
        self.sprite = world.component_for_entity(entity, Sprite)
        self.transform = world.component_for_entity(entity, Transform)

        self.entity = entity
        self.world = world

        self.data.load()

        self.world.add_close_listener(entity, lambda: self.data.save())

        self.event_bus.send.append(
            Event(
                {
                    'type': PlayerEventType.XP_ADDED,
                    'original': self.data.xp,
                    'amount': 0,
                    'new': self.data.xp
                }, EventType.PLAYER))

        self.event_bus.send.append(
            Event(
                {
                    'type': PlayerEventType.HEALTH_CHANGED,
                    'original': self.data.health,
                    'amount': 0,
                    'new': self.data.health
                }, EventType.PLAYER))

        self.event_bus.send.append(
            Event(
                {
                    'type': PlayerEventType.ARROWS_CHANGED,
                    'original': self.data.arrows,
                    'amount': 0,
                    'new': self.data.arrows
                }, EventType.PLAYER))

        self.set_state(NeutralState(self))
    def update(self, dt):
        if not self.waited:
            self.wait_counter += dt

            if self.wait_counter >= constants.GAMEOVER_DELAY + constants.GAMEOVER_SPIN + 1:
                self.waited = True
                self.event_bus.send.append(
                    Event(
                        {
                            'type': MusicEventType.PLAY,
                            'path': "gameover/gameover",
                            'id': constants.MUSIC_GAMEOVER
                        }, EventType.MUSIC))
Esempio n. 9
0
    def update(self, dt):
        for event in self.event_bus.get_events():
            if event.ty == EventType.CAVE:
                if event.data['type'] == CaveEventType.DESCEND:
                    self.do_gen()

                    self.event_bus.send.append(
                        Event(
                            {
                                'type': MusicEventType.POP,
                                'id': constants.MUSIC_BG,
                                'fade': True,
                                'fade_time': 1000
                            }, EventType.MUSIC))
Esempio n. 10
0
    def start(self, entity, world):
        self.entity = entity
        self.world = world

        self.event_bus = world.component_for_entity(entity, EventComponent)
        self.transform = world.component_for_entity(entity, Transform)

        self.event_bus.send.append(
            Event(
                {
                    'type': PlayerEventType.SET_POS,
                    'x': self.transform.position.x,
                    'y': self.transform.position.y
                }, EventType.PLAYER))
Esempio n. 11
0
    def die(self):
        if self.enemy._dead:
            return
        
        self.enemy.on_death()
        
        self.enemy._dead = True
        self.enemy.event_bus.send.append(Event({
            'type': PlayerEventType.ADD_XP,
            'amount': self.enemy.xp_amount
        }, EventType.PLAYER, True))

        poof_entity = self.enemy.world.create_entity_with(*loader.load("entity", "poof")[0])
        poof_transform = self.enemy.world.component_for_entity(poof_entity, Transform)

        poof_transform.position = self.enemy.transform.position
Esempio n. 12
0
    def spawn_arrow(self):
        if self.player.data.arrows <= 0:
            return

        original = self.player.data.arrows
        self.player.data.arrows -= 1

        self.player.event_bus.send.append(
            Event(
                {
                    'type': PlayerEventType.ARROWS_CHANGED,
                    'original': original,
                    'amount': -1,
                    'new': self.player.data.arrows
                }, EventType.PLAYER))

        arrow_entity = loader.load_entities_into("arrow", self.world)

        animation = self.world.component_for_entity(arrow_entity,
                                                    AnimationSets)
        script = self.world.component_for_entity(arrow_entity, ScriptComponent)
        transform = self.world.component_for_entity(arrow_entity, Transform)

        transform.position.x = self.transform.position.x
        transform.position.y = self.transform.position.y

        animation.current = "down"
        if self.dir == Direction.UP:
            animation.current = "up"
            transform.position.y -= 32
        elif self.dir == Direction.LEFT:
            animation.current = "left"
            transform.position.x -= 32
        elif self.dir == Direction.RIGHT:
            animation.current = "right"
            transform.position.x += 16
        else:
            transform.position.y += 16

        script.script.damage_data = self.damage_data
        script.script.dir = self.dir
        script.script.player = self.player
Esempio n. 13
0
    def on_event(self, event):
        if event.ty == EventType.COLLISION:
            if event.data['first'] == self.enemy.entity or event.data['second'] == self.enemy.entity:
                if event.data['first'] == self.enemy.entity:
                    other_entity = event.data['second']
                else:
                    other_entity = event.data['first']

                tag = self.enemy.world.component_for_entity(other_entity, Tag)

                if tag != None:
                    if "weapon" in tag.tags:
                        self.take_damage(other_entity)
                    
                    if "player" in tag.tags:
                        self.enemy.event_bus.send.append(Event({
                            'type': PlayerEventType.HURT,
                            'amount': self.enemy.attack_amount,
                            'knockback': self.enemy.damage_knockback
                        }, EventType.PLAYER))
    def start(self, entity, world):
        self.entity = entity
        self.world = world

        self.event_bus = world.component_for_entity(entity, EventComponent)

        for all_ent in world.get_all_entities():
            if all_ent == self.entity:
                continue

            if world.has_component(all_ent, Tag):
                tag = world.component_for_entity(all_ent, Tag)
                if not "system" in tag.tags:
                    world.delete_entity(all_ent)
            else:
                world.delete_entity(all_ent)

        self.event_bus.send.append(
            Event({'type': MusicEventType.CLEAR}, EventType.MUSIC))

        self.create_player()
Esempio n. 15
0
    def update(self, dt):
        for event in self.event_bus.get_events():
            if event.ty == EventType.COLLISION:
                other = None
                if event.data['first'] == self.entity:
                    other = event.data['second']
                elif event.data['second'] == self.entity:
                    other = event.data['first']

                if other != None:
                    if self.world.has_component(other, Tag):
                        tag = self.world.component_for_entity(other, Tag)
                        if "player" in tag.tags:
                            if not self.touched:
                                self.touched = True

                                self.event_bus.send.append(
                                    Event(
                                        {
                                            'type': NotifyEventType.NOTIFY,
                                            'time': 2,
                                            'title': "Saved",
                                            'text': "Game Saved"
                                        }, EventType.NOTIFY))
Esempio n. 16
0
    def update(self, dt):
        for event in self.event_bus.get_events():
            if event.ty == EventType.MUSIC:
                if event.data['type'] == MusicEventType.PLAY:
                    if self.cur_slot == None or event.data[
                            'id'] != self.cur_slot.id:
                        info = loader.load("music", event.data['path'])
                        self.cur_slot = MusicSlot(
                            event.data['id'], info,
                            event.data.get('lifetime', None))
                        self.cur_slot.play()
                    elif self.cur_slot != None and event.data[
                            'id'] == self.cur_slot.id:
                        if event.data.get('lifetime', None) != None:
                            self.cur_slot.lifetime = event.data.get(
                                'lifetime', None)

                elif event.data['type'] == MusicEventType.PUSH:
                    if self.cur_slot == None or event.data[
                            'id'] != self.cur_slot.id:
                        info = loader.load("music", event.data['path'])
                        if self.cur_slot != None:
                            self.cur_slot.stamp = pygame.mixer.music.get_pos()

                        self.cur_slot = MusicSlot(
                            event.data['id'], info,
                            event.data.get('lifetime', None), self.cur_slot)
                        self.cur_slot.play()
                    elif self.cur_slot != None and event.data[
                            'id'] == self.cur_slot.id:
                        if event.data.get('lifetime', None) != None:
                            self.cur_slot.lifetime = event.data.get(
                                'lifetime', None)

                elif event.data['type'] == MusicEventType.POP:
                    self.stopping = True
                    if event.data.get('fade', False):
                        pygame.mixer.music.fadeout(event.data['fade_time'])
                    else:
                        pygame.mixer.music.stop()

                    if self.cur_slot != None:
                        self.cur_slot = self.cur_slot.prev
                        if self.cur_slot != None:
                            self.cur_slot.play()

                            if self.cur_slot.stamp != None:
                                pygame.mixer.music.rewind()
                                pygame.mixer.music.set_pos(
                                    self.cur_slot.stamp / 1000)

                elif event.data['type'] == MusicEventType.CLEAR:
                    pygame.mixer.music.stop()
                    self.cur_slot = None

            elif event.ty == EventType.PYGAME:
                if event.data.type == 32:
                    if self.cur_slot != None and not self.stopping:
                        self.cur_slot.next()
                        self.cur_slot.play()

        if self.stopping:
            self.stop_counter -= dt
            if self.stop_counter <= 0:
                self.stopping = False
                self.stop_counter = 1
        else:
            self.stop_counter = 1

        if self.cur_slot != None and self.cur_slot.lifetime != None:
            self.cur_slot.lifetime -= dt

            if self.cur_slot.lifetime <= 0:
                self.event_bus.send.append(
                    Event({
                        'type': MusicEventType.POP,
                        'id': self.cur_slot.id
                    }, EventType.MUSIC))
Esempio n. 17
0
    def e_update(self, dt):
        for event in self.event_bus.get_events():
            if event.ty == EventType.PLAYER:
                if event.data['type'] == PlayerEventType.PLAYER_MOVED:
                    x = event.data['x']
                    y = event.data['y']

                    self.tracking = False

                    self.tracking_x = x
                    self.tracking_y = y
            elif event.ty == EventType.COLLISION:
                if event.data['first'] == self.entity or event.data[
                        'second'] == self.entity:
                    self.max_dir_counter = 0

        if not self.tracking:
            self_x = self.transform.position.x
            self_y = self.transform.position.y
            x = self.tracking_x
            y = self.tracking_y

            if self_x > x - constants.MINIMOLDORM_RANGE and self_x < x + constants.MINIMOLDORM_RANGE and self_y > y - constants.MINIMOLDORM_RANGE and self_y < y + constants.MINIMOLDORM_RANGE:
                self.tracking = True

                self.event_bus.send.append(
                    Event(
                        {
                            'type': MusicEventType.PUSH,
                            'path': 'encounter/encounter',
                            'id': constants.MUSIC_ENCOUNTER,
                            'lifetime': 1
                        }, EventType.MUSIC))

        if self.tracking:
            x = self.tracking_x
            y = self.tracking_y
            self_x = self.transform.position.x
            self_y = self.transform.position.y

            self.event_bus.send.append(
                Event(
                    {
                        'type': MusicEventType.PUSH,
                        'path': 'encounter/encounter',
                        'id': constants.MUSIC_ENCOUNTER,
                        'lifetime': 3
                    }, EventType.MUSIC))

            self.max_dir_counter = 0

            if self_x > x + 4:
                self.dir_x = Direction.LEFT
            elif self_x < x - 4:
                self.dir_x = Direction.RIGHT
            else:
                self.dir_x = None

            if self_y > y + 4:
                self.dir_y = Direction.UP
            elif self_y < y - 4:
                self.dir_y = Direction.DOWN
            else:
                self.dir_y = None

        self.dir_counter += dt
        if self.dir_counter >= self.max_dir_counter:
            self.max_dir_counter = random.uniform(
                constants.MINIMOLDORM_ROTATE_MIN,
                constants.MINIMOLDORM_ROTATE_MAX)
            self.dir_counter = 0
            if not self.tracking:
                self.dir_x = random.choice(
                    [None, Direction(random.randrange(2, 4))])
                self.dir_y = random.choice(
                    [None, Direction(random.randrange(0, 2))])

            aname = None
            if self.dir_y == None:
                if self.dir_x == Direction.LEFT:
                    aname = "west"
                elif self.dir_x == Direction.RIGHT:
                    aname = "east"
            elif self.dir_y == Direction.UP:
                if self.dir_x == None:
                    aname = "north"
                elif self.dir_x == Direction.LEFT:
                    aname = "northwest"
                elif self.dir_x == Direction.RIGHT:
                    aname = "northeast"
            elif self.dir_y == Direction.DOWN:
                if self.dir_x == None:
                    aname = "south"
                elif self.dir_x == Direction.LEFT:
                    aname = "southwest"
                elif self.dir_x == Direction.RIGHT:
                    aname = "southeast"

            if aname != None:
                self.animation.current = aname

        if self.dir_x != None and self.dir_y != None:
            self.damage_knockback = pygame.math.Vector2(
                self.dir_x.to_vector(constants.MINIMOLDORM_SPEED).x * 10,
                self.dir_y.to_vector(constants.MINIMOLDORM_SPEED).y * 10)

        if self.dir_x != None:
            self.collision.velocity.x += self.dir_x.to_vector(
                constants.MINIMOLDORM_SPEED).x
        if self.dir_y != None:
            self.collision.velocity.y += self.dir_y.to_vector(
                constants.MINIMOLDORM_SPEED).y
Esempio n. 18
0
    def descend(self):
        self.event_bus.send.append(
            Event({'type': CaveEventType.DESCEND}, EventType.CAVE, True))

        return True
Esempio n. 19
0
    def update(self, dt):
        self.player.collision.velocity += self.player.facer.get_movement()
        self.player.animation.current = self.player.facer.get_animation()

        if self.player.facer.is_moving():
            self.step_timer += dt

            if self.step_timer >= 0.35:
                self.step_timer = 0
                self.step_sound.play()
        else:
            self.step_timer = 0

        if self.player.collision.velocity.x != 0 or self.player.collision.velocity.y != 0:
            self.player.event_bus.send.append(
                Event(
                    {
                        'type': CameraEventType.FOLLOW,
                        'pos': self.player.transform.position,
                        'offset': pygame.math.Vector2(320 - 16, 200 - 16)
                    }, EventType.CAMERA))

            self.player.event_bus.send.append(
                Event(
                    {
                        'type': PlayerEventType.PLAYER_MOVED,
                        'x': self.player.transform.position.x,
                        'y': self.player.transform.position.y
                    }, EventType.PLAYER))

        keys_pressed = pygame.key.get_pressed()

        if keys_pressed[pygame.K_w] or (
                self.player.joystick != None
                and self.player.joystick.get_axis(1) > 0.2):
            if not self.player.facer.contains(Direction.UP):
                self.player.facer.hold(Direction.UP)
        else:
            self.player.facer.release(Direction.UP)

        if keys_pressed[pygame.K_s] or (
                self.player.joystick != None
                and self.player.joystick.get_axis(1) < -0.2):
            if not self.player.facer.contains(Direction.DOWN):
                self.player.facer.hold(Direction.DOWN)
        else:
            self.player.facer.release(Direction.DOWN)

        if keys_pressed[pygame.K_a] or (
                self.player.joystick != None
                and self.player.joystick.get_axis(0) < -0.2):
            if not self.player.facer.contains(Direction.LEFT):
                self.player.facer.hold(Direction.LEFT)
        else:
            self.player.facer.release(Direction.LEFT)

        if keys_pressed[pygame.K_d] or (
                self.player.joystick != None
                and self.player.joystick.get_axis(0) > 0.2):
            if not self.player.facer.contains(Direction.RIGHT):
                self.player.facer.hold(Direction.RIGHT)
        else:
            self.player.facer.release(Direction.RIGHT)
Esempio n. 20
0
    def generate(self):
        # TODO
        gen = Generator(32, 32)
        basicmap = gen.create_dungeon()
        yield
        tilemap = [0 for i in range(len(basicmap))]
        for y in range(0, 32):
            for x in range(0, 32):
                if gen.get_tile(x, y) == 1:
                    tilemap[x + y * 32] = -1
                    continue
                n = gen.get_tile(x, y - 1)
                ne = gen.get_tile(x + 1, y - 1)
                e = gen.get_tile(x + 1, y)
                se = gen.get_tile(x + 1, y + 1)
                s = gen.get_tile(x, y + 1)
                sw = gen.get_tile(x - 1, y + 1)
                w = gen.get_tile(x - 1, y)
                nw = gen.get_tile(x - 1, y - 1)
                sprite_number = 0
                if n == 0:
                    sprite_number += 1
                if ne == 0:
                    sprite_number += 2
                if e == 0:
                    sprite_number += 4
                if se == 0:
                    sprite_number += 8
                if s == 0:
                    sprite_number += 16
                if sw == 0:
                    sprite_number += 32
                if w == 0:
                    sprite_number += 64
                if nw == 0:
                    sprite_number += 128

                tilemap[x + y * 32] = tilemappings.get(sprite_number)

            yield

        populator = Populator(tilemap, 32, 32)
        tilemap = populator.populate(5, True)

        yield

        tile_mappings = loader.load("data", "tiles")

        for y in range(0, 32):
            for x in range(0, 32):
                tile_type = type(tilemap[x + y * 32])
                if tile_type == int:
                    if tilemap[x + y * 32] > -1:
                        collision = CollisionComponent(
                            size=pygame.math.Vector2(16, 16), solid=True)
                        sprite = loader.load("sprite", "bricks")
                        transform = Transform(position=pygame.math.Vector2(
                            x * 16 * 2, y * 16 * 2),
                                              scale=pygame.math.Vector2(2, 2))
                        sprite.start = tilemap[x + y * 32]
                        sprite.end = sprite.start + 1

                        self.world.create_entity_with(collision, sprite,
                                                      transform)
                else:
                    chance_list = tile_mappings[tilemap[x + y * 32]]
                    weights = list(
                        map(lambda x: x.get('chance', 1), chance_list))
                    choice = random.choices(chance_list, weights)
                    entity_path = choice[0]['entity']
                    entities = loader.load("entity", entity_path)

                    for components in entities:
                        for component in components:
                            if type(component) == Transform:
                                component.position.x = x * 16 * 2
                                component.position.y = y * 16 * 2
                                component.scale.x = 2
                                component.scale.y = 2

                        self.world.create_entity_with(*components)

            yield

        floor_sprite = loader.load("sprite", "tiles/floor").repeated(32, 32)
        floor_transform = Transform(scale=pygame.math.Vector2(2, 2), layer=-1)
        self.world.create_entity_with(floor_sprite, floor_transform)

        yield

        self.event_bus.send.append(
            Event(
                {
                    'type': CameraEventType.SET_BOUNDS,
                    'x': 0,
                    'y': 0,
                    'width': 16 * 2 * 32,
                    'height': 16 * 2 * 32 + 80
                }, EventType.CAMERA))

        self.event_bus.send.append(
            Event(
                {
                    'type': MusicEventType.PLAY,
                    'path': "background/background",
                    'id': constants.MUSIC_BG
                }, EventType.MUSIC))

        raise StopIteration
    def update(self, dt):
        import math

        bodies = [
            Body(entity, collision, transform)
            for entity, [collision, transform] in self.world.get_components(
                CollisionComponent, Transform)
        ]
        if len(bodies) < 1:
            return
        quad_tree = QuadTree(bodies, 4)

        for body in bodies:
            body.collision.velocity.x *= body.collision.friction
            body.collision.velocity.y *= body.collision.friction

            if abs(body.collision.velocity.x) < 0.5:
                body.collision.velocity.x = 0
            if abs(body.collision.velocity.y) < 0.5:
                body.collision.velocity.y = 0

            if abs(body.collision.velocity.x) > body.collision.max_speed:
                body.collision.velocity.x = math.copysign(
                    body.collision.max_speed, body.collision.velocity.x)
            if abs(body.collision.velocity.y) > body.collision.max_speed:
                body.collision.velocity.y = math.copysign(
                    body.collision.max_speed, body.collision.velocity.y)

            if body.collision.velocity.x != 0 or body.collision.velocity.y != 0 or body.collision.persistent:
                prev_x = body.transform.position.x
                prev_y = body.transform.position.y

                sent = []

                body.transform.position.x += body.collision.velocity.x * dt

                for other_body in quad_tree.collide(body):
                    self.event_bus.send.append(
                        Event(
                            {
                                'first': body.entity,
                                'second': other_body.entity
                            }, EventType.COLLISION))
                    sent.append(other_body.entity)
                    if body.collision.solid and other_body.collision.solid:
                        body.transform.position.x = prev_x
                        body.collision.velocity.x = 0

                body.transform.position.y += body.collision.velocity.y * dt

                for other_body in quad_tree.collide(body):
                    if not other_body.entity in sent:
                        self.event_bus.send.append(
                            Event(
                                {
                                    'first': body.entity,
                                    'second': other_body.entity
                                }, EventType.COLLISION))
                    if body.collision.solid and other_body.collision.solid:
                        body.transform.position.y = prev_y
                        body.collision.velocity.y = 0
Esempio n. 22
0
    def update(self, dt):
        for event in self.event_bus.get_events():
            if event.ty == EventType.PLAYER:
                if event.data['type'] == PlayerEventType.SET_POS:
                    self.transform.position.x = event.data['x']
                    self.transform.position.y = event.data['y']

                    self.event_bus.send.append(
                        Event(
                            {
                                'type': CameraEventType.FOLLOW,
                                'pos': self.transform.position,
                                'offset': pygame.math.Vector2(
                                    320 - 16, 200 - 16)
                            }, EventType.CAMERA))
                elif event.data['type'] == PlayerEventType.ADD_XP:
                    original = self.data.xp
                    self.data.add_xp(event.data['amount'])

                    self.event_bus.send.append(
                        Event(
                            {
                                'type': PlayerEventType.XP_ADDED,
                                'original': original,
                                'amount': event.data['amount'],
                                'new': self.data.xp
                            }, EventType.PLAYER))
                elif event.data['type'] == PlayerEventType.HURT:
                    self.hurt(
                        event.data['amount'],
                        event.data.get('knockback', pygame.math.Vector2(0, 0)))
            elif event.ty == EventType.COLLISION:
                other = None
                if event.data['first'] == self.entity:
                    other = event.data['second']
                elif event.data['second'] == self.entity:
                    other = event.data['first']

                if other != None:
                    if self.world.has_component(other, Tag):
                        tag = self.world.component_for_entity(other, Tag)
                        if "drop" in tag.tags:
                            script = self.world.component_for_entity(
                                other, ScriptComponent).script
                            drop_info = script.drop

                            if drop_info.ty == DropType.ARROW:
                                amount = drop_info.data['amount']

                                original = self.data.arrows
                                self.data.arrows += amount

                                self.event_bus.send.append(
                                    Event(
                                        {
                                            'type':
                                            PlayerEventType.ARROWS_CHANGED,
                                            'original': original,
                                            'amount': amount,
                                            'new': self.data.arrows
                                        }, EventType.PLAYER))

                                self.sound_pickup_arrow.play()

                                script.collected()

            self.state.on_event(event)

        self.state.update(dt)

        self.hurt_cooldown -= dt
        if self.hurt_cooldown < 0:
            self.hurt_cooldown = 0
            self.sprite.visible = True

        if self.hurt_cooldown > 0:
            self.hurt_blinker += dt
            if self.hurt_blinker >= constants.HURT_BLINK:
                self.hurt_blinker = 0
                self.sprite.visible = not self.sprite.visible

        if self.bomb_timer > 0:
            self.bomb_timer -= dt