def update(self, inputs, t, dt, collision_detector): # move to new position direction = Vector(inputs.leftright, inputs.updown) self._set_move_dir(inputs.leftright, inputs.updown) direction = direction.normalized() * 140.0 super(GirlCharacter, self).update(inputs, t, dt, direction, collision_detector) # activate abilities new_objs = list() if self.ability_one and inputs.one: self.ability_one.activate(t, dt, collision_detector, self, new_objs) if self.ability_two and inputs.two: self.ability_two.activate(t, dt, collision_detector, self, new_objs) if self.ability_three and inputs.three: self.ability_three.activate(t, dt, collision_detector, self, new_objs) if self.ability_four and inputs.four: self.ability_four.activate(t, dt, collision_detector, self, new_objs) # regen health if t - self.last_hit > self.regen_delay: self.health += self.regen_rate * dt self.health = min(self.max_health, self.health) return new_objs
def __init__(self, filename, collision_detector): with open(filename) as f: json_level = json.load(f) tiles = _get_tileset(filename, json_level['tilesets'][0]['image']) width = json_level['layers'][0]['width'] height = json_level['layers'][0]['height'] self.filename = filename for layer in json_level['layers']: if not layer['visible']: continue for i,tile in enumerate(layer['data']): if tile == 0: continue tile = tile & ~tileset.FLIP_MASK if not tiles.collides(tile): continue x = 32 * (i % width) y = 32 * (height - i / width) center = Vector(x + 16, y + 16) tl = Vector(-16, -16) br = Vector(16, 16) token = '{}_{}_{}'.format(filename, x, y) c = kidgine.collision.rectangle.Rectangle(None, tl, br, center = center) c.tags = set([kidgine.collision.shape.tags.IMPEEDS_MOVEMENT, Tags.ENVIRONMENT]) collision_detector.update_collidable(token, c)
def __init__(self, position): self.position = position tl = Vector(-16, -16) br = Vector(16, 16) self.token = 'spike{}'.format(Spike.counter) Spike.counter += 1 self.collidable = kidgine.collision.rectangle.Rectangle(self, tl, br) self.collidable.tags = set([collision.Tags.ENVIRONMENT])
def apply(self, t, dt, c): p1 = c.shape1.owner.position p2 = c.shape2.owner.position start_vector = Vector(p2.x - p1.x, p2.y - p1.y) eject_mag = self.force / (start_vector.magnitude() / self.size ) eject_vector = start_vector.normalized().rotate((random.random() - 0.5) * self.spread) eject_vector *= (eject_mag * dt) c.shape2.owner.apply_force(eject_vector) try: c.shape2.owner.slow(t, self.slow, self) except AttributeError: pass
def __init__(self, parent, collision_detector): super(Windblast, self).__init__() self.parent = parent self.position = parent.position + Vector(0, 16) tl = Vector(-self.size, -self.size) br = Vector(self.size, self.size) self.collidable = kidgine.collision.rectangle.Rectangle(self, tl, br) self.token = 'windblast' collision_detector.update_collidable(self.token, self.collidable)
def apply(self, t, dt, c): p1 = c.shape1.owner.position p2 = c.shape2.owner.position start_vector = Vector(p2.x - p1.x, p2.y - p1.y) eject_mag = self.force / (start_vector.magnitude() / self.size) eject_vector = start_vector.normalized().rotate( (random.random() - 0.5) * self.spread) eject_vector *= (eject_mag * dt) c.shape2.owner.apply_force(eject_vector) try: c.shape2.owner.slow(t, self.slow, self) except AttributeError: pass
def __init__(self, position, throw_vector): self.position = position self.forces = throw_vector self.forced = False self.time_left = self.time tl = Vector(-20, -20) br = Vector(20, 20) self.token = 'spear{}'.format(Spear.counter) Spear.counter += 1 self.collidable = kidgine.collision.rectangle.Rectangle(self, tl, br) self.collidable.tags = set([collision.Tags.PUSHABLE])
def __init__(self, position): super(CollidableCharacter, self).__init__(position) tl = Vector(-16, 0) br = Vector(16, 32) self.token = 'character{}'.format(CollidableCharacter.counter) CollidableCharacter.counter += 1 self.collidable = kidgine.collision.rectangle.Rectangle(self, tl, br) self.collidable.tags = set( [kidgine.collision.shape.tags.IMPEEDS_MOVEMENT]) self.forces = Vector()
def __init__(self, parent, collision_detector): super(Earthquake, self).__init__() self.position = parent.position + Vector(0, 16) tl = Vector(-self.size, -self.size) br = Vector(self.size, self.size) self.collidable = kidgine.collision.rectangle.Rectangle(self, tl, br) self.token = 'earthquake' #self.collidable = kidgine.collision.circle.Circle(self, self.position, self.size) collision_detector.update_collidable(self.token, self.collidable)
def update(self, inputs, t, dt, collision_detector): self.first_spawn_delay = max(self.first_spawn_delay - dt, 0) direction = Vector(0.0, 0.0) if self.target: # Adjusting position, preparing to charge. target_vector = self.target.position - self.position direction = self.target.position - self.position if abs(direction.x) > abs(direction.y): direction.x = 0 else: direction.y = 0 if self.charging or (direction.magnitude() < 30.0 and self.first_spawn_delay == 0.0): # Currently charging OR beginning a charge. direction *= 0 if not self.charging: self.charging = t elif t - (self.charge_delay + self.charge_length + self.charge_rest) > self.charging: # Done resting. self.charging = None self.charge_direction = None self.speed = self.normal_speed elif t - (self.charge_delay + self.charge_length) > self.charging: # Resting from a charge. pass elif t - self.charge_delay > self.charging: # Waited a full second, charging now. if not self.charge_direction: if abs(target_vector.x) > abs(target_vector.y): direction.x = math.copysign(1, target_vector.x) else: direction.y = math.copysign(1, target_vector.y) self.charge_direction = direction.normalized() else: direction = self.charge_direction.normalized() self.speed = self.charge_speed else: direction = kidgine.math.vector.constant_zero direction = direction.normalized() direction *= self.speed * self.slow_factor collision_info = collision_detector.collides( token=self.token, filters=self.player_filter) if collision_info is not None: self.do_damage(t, collision_info) super(MeleeEnemy, self).update(inputs, t, dt, direction, collision_detector) self.reset_slow(t)
def update(self, inputs, t, dt, collision_detector): self.time_left -= dt self.position = self.position + self.forces all = collision_detector.collides(token=self.token, filters=self.environment_filters) if len(all) > 0: normal = Vector() for c in all: if normal.dot(c.translation_vector) == 0: normal += c.translation_vector self.position += normal collision_detector.update_collidable(self.token, self.collidable)
def apply(self, t, dt, c): self.last_trigger_time = t try: # Pull is at a 45 degree slant, getting straighter and weaker toward the middle. # Slow is weak, getting stronger toward the middle. p1 = c.shape1.owner.position p2 = c.shape2.owner.position start_vector = Vector(p1.x - p2.x, p1.y - p2.y) svmag = start_vector.magnitude() pull_mag = svmag * self.force_mult * self.pulse_rate pull_vector = start_vector.normalized().rotate(math.radians(-(45*(1-(self.size / (self.size + svmag)))))) pull_vector *= pull_mag**0.5 c.shape2.owner.apply_force(pull_vector) c.shape2.owner.slow(t, min(self.min_slow, self.min_slow / (pull_mag * self.slow_scale)), self) except AttributeError: pass
def update(self, inputs, t, dt, direction, collision_detector): super(CollidableCharacter, self).update(t, dt, direction) self.position = self.position + direction * dt + self.forces all = collision_detector.collides(token=self.token, filters=self.environment_filters) if len(all) > 0: normal = Vector() for c in all: if normal.dot(c.translation_vector) == 0: normal += c.translation_vector self.position += normal collision_detector.update_collidable(self.token, self.collidable) self.reset_force()
def update(self, inputs, t, dt, collision_detector): spear = None direction = Vector(0.0, 0.0) if self.target: target_vector = self.target.position - self.position if target_vector.shorter_than(128): # move away from target direction = -target_vector.normalized() elif target_vector.shorter_than( 256) and t - self.last_damage_time > self.throw_delay: self.last_damage_time = t # throw spear spear = updatable.Spear( self.position, target_vector.normalized() * self.spear_speed) elif target_vector.shorter_than(512): # move toward target direction = target_vector.normalized() direction *= self.speed * self.slow_factor super(MeleeEnemy, self).update(inputs, t, dt, direction, collision_detector) self.reset_slow(t) if spear: return [spear] else: return []
def __init__(self, parent, collision_detector): super(Firebolt, self).__init__() self.rotation = parent.move_direction * 45.0 offset = kidgine.math.vector.from_radians(math.radians( self.rotation)) * 48 offset.y = -offset.y self.position = (parent.position + offset + Vector(0, 16)) self.token = 'firebolt' tl = Vector(-48, -48) br = Vector(48, 48) self.collidable = kidgine.collision.rectangle.Rectangle(self, tl, br) self.collidable.rotation = self.rotation collision_detector.update_collidable(self.token, self.collidable)
def __init__(self, parent, collision_detector): super(Whirlpool, self).__init__() self.rotation = parent.move_direction * 45 offset = kidgine.math.vector.from_radians(math.radians( self.rotation)) * 132 offset.y = -offset.y self.position = (parent.position + offset) tl = Vector(-self.size, -self.size) br = Vector(self.size, self.size) self.collidable = kidgine.collision.rectangle.Rectangle(self, tl, br) self.token = 'whirlpool' collision_detector.update_collidable(self.token, self.collidable)
def __init__(self, position, throw_vector): self.position = position self.forces = throw_vector self.time_left = self.time self.explosion_time_left = self.explosion_time self.explosion_triggered = False tl = Vector(-32, -32) br = Vector(32, 32) self.token = 'bomb{}'.format(Bomb.counter) Bomb.counter += 1 self.collidable = kidgine.collision.rectangle.Rectangle(self, tl, br) self.collidable.tags = set([ collision.Tags.PROJECTILE, collision.Tags.PUSHABLE, collision.Tags.NOT_SLOWED ])
def create_wave(self, position, enemy_type, num_enemies, spread): all = list() for i in xrange(num_enemies): p = position + Vector(random.uniform(-spread, spread), random.uniform(-spread, spread)) enemy = enemy_type(p, self.player_character) all.append(enemy) return all
def __init__(self, player, width): self.player = player def anchor_fn(): if self.player is not None: return self.player.position return Vector() super(PlayerCamera, self).__init__(anchor_fn, Vector(width))
def apply(self, t, dt, c): self.last_trigger_time = t try: # Pull is at a 45 degree slant, getting straighter and weaker toward the middle. # Slow is weak, getting stronger toward the middle. p1 = c.shape1.owner.position p2 = c.shape2.owner.position start_vector = Vector(p1.x - p2.x, p1.y - p2.y) svmag = start_vector.magnitude() pull_mag = svmag * self.force_mult * self.pulse_rate pull_vector = start_vector.normalized().rotate( math.radians(-(45 * (1 - (self.size / (self.size + svmag)))))) pull_vector *= pull_mag**0.5 c.shape2.owner.apply_force(pull_vector) c.shape2.owner.slow( t, min(self.min_slow, self.min_slow / (pull_mag * self.slow_scale)), self) except AttributeError: pass
def __init__(self, anchor, center_x, width, min_y): self._min_y = min_y self._anchor = anchor self._x = center_x self._last = 0 def anchor_fn(): if self._anchor is not None: self._last = self._anchor.position.y if self._last < self._min_y: self._last = self._min_y return Vector(self._x, self._last) super(VerticalPanningCamera, self).__init__(anchor_fn, Vector(width))
def update(self, inputs, t, dt, collision_detector): if not self.explosion_triggered: self.time_left -= dt if self.time_left <= 0.0: self._trigger() self.position = self.position + self.forces * self.slow_factor all = collision_detector.collides(token=self.token, filters=self.environment_filters) if len(all) > 0: normal = Vector() for c in all: if normal.dot(c.translation_vector) == 0: normal += c.translation_vector self.position += normal collision_detector.update_collidable(self.token, self.collidable) else: self.explosion_time_left -= dt self.reset_slow(t)
def update(self, inputs, t, dt, collision_detector): self.position = self.parent.position + Vector(0, 16) collision_detector.update_collidable(self.token, self.collidable) super(Windblast, self).update(inputs, t, dt, collision_detector)
class Character(object): tags = set() idle_delay = 3.0 idle_delay_two = 4.0 last = Vector() """represents a character, player controlled or otherwise. has position and a facing""" def __init__(self, position): self.facing = Facing.left self.position = position self.moving = False self.time_to_idle = self.idle_delay self.idle = False self.idle_time = data.animations.animation_duration( self.renderable_type.sprite_name + '_idle') if isinstance(self, GirlCharacter): self.health = self.max_health else: self.health = self.max_health * health_scaling self.last_hit = 0 def update(self, t, dt, direction): if direction.magnitude_sqr() > 0.1: self.last = direction self.moving = True if math.fabs(direction.x) > math.fabs(direction.y): if direction.x > 0: self.facing = Facing.right else: self.facing = Facing.left else: if direction.y > 0: self.facing = Facing.top else: self.facing = Facing.bottom else: self.moving = False self.update_idle(t, dt) def damage(self, t, amount): self.last_hit = t self.health = max(0, self.health - amount) def alive(self): return self.health > 0.0 def collides(self, t, shape): pass def get_tags(self): return self.tags def update_idle(self, t, dt): if self.moving: self.time_to_idle = self.idle_delay self.idle = False else: self.time_to_idle -= dt if self.time_to_idle <= 0.0: if self.idle: self.idle = False self.time_to_idle = self.idle_delay_two else: self.idle = True self.time_to_idle = self.idle_time def is_ui(self): return False def create_renderable(self): def wrapped(batch, group): self.renderable = self.renderable_type(batch, group, self) return self.renderable return wrapped
def __init__(self): super(ActTwo, self).__init__('data/levels/act_two.json') self.hermited = False # create player self.player_character = character.GirlCharacter( Vector(32 * 20, 32 * 10)) self.player_character.ability_one = None self.add_updatable(self.player_character) self.hermit = character.HermitCharacter(Vector(32 * 18 + 16, 32 * 52)) self.add_updatable(self.hermit) self.hermit.facing = character.Facing.left # set camera self.set_camera(camera.PlayerCamera(self.player_character, 32 * 20)) # create some enemies self.add_updatables( self.create_wave(Vector(32 * 13, 32 * 18), character.BombEnemy, 3, 96)) self.add_updatables( self.create_wave(Vector(32 * 27, 32 * 18), character.BombEnemy, 3, 96)) # start by fading from black self.add_updatable(updatable.fade_from_black(1.0)) # set up some triggers # lose when the player dies self.add_trigger( trigger.trigger(self, 'is_player_dead'), action.action_list([ action.action(self, 'play_dialog', 'data/dialog/death_dialog.json'), action.action(self, 'end_with', game.SceneState.failed, updatable.fade_to_black(0.5)) ])) self.add_trigger( trigger.trigger(self, 'should_start_hermit'), action.action_list([ action.add_updatables( self.create_wave(Vector(32 * 25, 32 * 40), character.BombEnemy, 2, 48)), action.add_updatables( self.create_wave(Vector(32 * 15, 32 * 40), character.BombEnemy, 2, 48)), action.action(self, 'do_hermit') ])) self.add_trigger( trigger.trigger(self, 'should_spawn_wave'), action.action_list([ action.add_updatables( self.create_wave(Vector(32 * 25, 32 * 30), character.BombEnemy, 2, 48)), action.add_updatables( self.create_wave(Vector(32 * 15, 32 * 30), character.BombEnemy, 2, 48)) ])) self.add_trigger(trigger.trigger(self, 'victory'), action.action(self, 'do_victory'))
def update(self, inputs, t, dt, collision_detector): super(HermitCharacter, self).update(t, dt, Vector(0, 0))
def reset_force(self): self.forces = Vector()
def __init__(self): super(ActThree, self).__init__('data/levels/act_three.json') # create player self.player_character = character.GirlCharacter( Vector(32 * 10, 32 * 10)) self.player_character.ability_one = None self.player_character.ability_two = None self.add_updatable(self.player_character) self.set_camera( camera.VerticalPanningCamera( self.player_character, 32 * 10, # center x 32 * 20, # width 32 * 7)) # min_y #self.add_blocking_event(updatable.fade_from_black(1.0)) self.boss = character.ChieftainBoss( Vector(random.uniform(32 * 5, 32 * 15), 32 * 20), self.player_character) self.add_updatable(self.boss) self.add_updatable(updatable.Spike(Vector(32 * 7, 32 * 18))) self.add_updatable(updatable.Spike(Vector(32 * 14, 32 * 26))) self.add_updatable(updatable.Spike(Vector(32 * 5, 32 * 32))) self.add_updatable(updatable.Spike(Vector(32 * 15, 32 * 30))) self.add_updatable(updatable.Spike(Vector(32 * 17, 32 * 20))) self.play_dialog('data/dialog/act_three_chieftan_1.json') self.add_updatables( self.create_wave(Vector(32 * 5, 32 * 10), character.SpearEnemy, 4, 64)) self.add_updatables( self.create_wave(Vector(32 * 16, 32 * 16), character.SpearEnemy, 3, 64)) # lose when the player dies self.add_trigger( trigger.trigger(self, 'is_player_dead'), action.action_list([ action.action(self, 'play_dialog', 'data/dialog/death_dialog.json'), action.action(self, 'end_with', game.SceneState.failed, updatable.fade_to_black(0.5)) ])) # self.add_trigger( # trigger.trigger(self, 'should_spawn_wave'), # action.add_updatables(self.create_wave(Vector( # random.uniform(5*32,15*32), # random.uniform(5*32,25*32)), character.SpearEnemy, 4, 64)), True) self.add_trigger(trigger.trigger(self, 'should_do_dialog_one'), action.action(self, 'dialog_one')) self.add_trigger(trigger.trigger(self, 'should_do_dialog_two'), action.action(self, 'dialog_two')) self.add_trigger(trigger.trigger(self, 'should_do_dialog_final'), action.action(self, 'dialog_final'))
def __init__(self): super(ActOne, self).__init__('data/levels/act_one.json') # create player self.player_character = character.GirlCharacter(Vector( 32 * 10, 32 * 3)) self.player_character.facing = character.Facing.top self.add_updatable(self.player_character) # set camera self.set_camera( camera.VerticalPanningCamera( self.player_character, 32 * 11, # center x 32 * 20, # width 32 * 8)) # min_y # create some enemies self.add_updatables( self.create_wave(Vector(4 * 32, 8 * 32), character.MeleeEnemy, 2, 48)) self.add_updatables( self.create_wave(Vector(13 * 32, 9 * 32), character.MeleeEnemy, 3, 48)) # fade from black self.add_blocking_event(updatable.fade_from_black(1.0)) # play some dialog self.play_dialog('data/dialog/act_one_intro.json') # set up some triggers # lose when the player dies self.add_trigger( trigger.trigger(self, 'is_player_dead'), action.action_list([ action.action(self, 'play_dialog', 'data/dialog/death_dialog.json'), action.action(self, 'end_with', game.SceneState.failed, updatable.fade_to_black(0.5)) ])) # enemy waves self.add_trigger( trigger.trigger(self, 'should_spawn_wave_2'), action.action_list([ action.add_updatables( self.create_wave(Vector(3 * 32, 21 * 32), character.MeleeEnemy, 4, 48)), action.add_updatables( self.create_wave(Vector(17 * 32, 24 * 32), character.MeleeEnemy, 3, 48)) ])) self.add_trigger( trigger.trigger(self, 'should_spawn_wave_3'), action.action_list([ action.add_updatables( self.create_wave(Vector(2 * 32, 33 * 32), character.MeleeEnemy, 4, 48)), action.add_updatables( self.create_wave(Vector(12 * 32, 36 * 32), character.MeleeEnemy, 5, 64)) ])) # boss, dialog, win when all enemies are dead self.add_trigger( trigger.trigger(self, 'should_spawn_boss'), action.action_list([ action.add_updatable( character.WarlordBoss( Vector(random.uniform(32 * 5, 32 * 15), 32 * 48 - 8), self.player_character)), action.add_trigger( self, trigger.trigger(self, 'all_enemies_dead'), action.action_list([ action.action(self, 'play_dialog', 'data/dialog/act_one_warlord_1.json'), action.action(self, 'girl_points'), action.action(self, 'play_dialog', 'data/dialog/act_one_warlord_2.json'), action.action(self, 'end_with', game.SceneState.succeeded, updatable.fade_to_black(0.5)) ])) ]))
def anchor_fn(): if self._anchor is not None: self._last = self._anchor.position.y if self._last < self._min_y: self._last = self._min_y return Vector(self._x, self._last)
def anchor_fn(): if self.player is not None: return self.player.position return Vector()