def __init__(self): super().__init__() xform_state = p3d.TransformState.make_pos(p3d.LVector3f(0, 0, 0.9)) shape = bullet.BulletBoxShape(p3d.LVector3f(0.25, 0.25, 0.8)) self.physics_node = bullet.BulletGhostNode('HitBox') self.physics_node.add_shape(shape, xform_state) self.physics_node.set_python_tag('component', self)
def __init__(self, chassis, mesh=None): super().__init__() self.movement = p3d.LVector3f(0, 0, 0) self.mesh_name = mesh self.level = 1 with open(os.path.join('chassis', chassis) + '.json') as f: self._chassis = json.load(f) self.action_set = set() for t in ['track_one', 'track_two', 'track_three', 'track_four']: with open(os.path.join('tracks', t) + '.json') as f: track_data = json.load(f) track_entity = base.ecsmanager.create_entity() for component_data in track_data['components']: component = getattr(effects, component_data['name'] + 'EffectComponent')(component_data['args']) track_entity.add_component(component) setattr(self, t, track_entity) self.current_health = self.health if self._chassis else None self.recoil_duration = 0.35 self.recoil_timer = self.recoil_duration + 1.0
def __init__(self, geom, offset=p3d.LVector3f(0, 0, 0)): super().__init__() mesh = bullet.BulletTriangleMesh() for i in range(geom.node().get_num_geoms()): mesh.add_geom(geom.node().get_geom(i)) shape = bullet.BulletTriangleMeshShape(mesh, dynamic=False) self.physics_node = bullet.BulletRigidBodyNode('StaticMesh') xform_state = p3d.TransformState.make_pos(offset) self.physics_node.add_shape(shape, xform_state) self.physics_node.set_python_tag('component', self)
def init_components(self, dt, components): for hit_box in components.get('PHY_HITBOX', []): np_component = hit_box.entity.get_component('NODEPATH') np_component.nodepath.attach_new_node(hit_box.physics_node) self.physics_world.attach(hit_box.physics_node) for static_mesh in components.get('PHY_STATICMESH', []): np_component = static_mesh.entity.get_component('NODEPATH') np_component.nodepath.attach_new_node(static_mesh.physics_node) self.physics_world.attach(static_mesh.physics_node) for character in components.get('PHY_CHARACTER', []): np = character.entity.get_component('NODEPATH').nodepath char_np = np.get_parent().attach_new_node(character.physics_node) char_np.set_pos(np.get_pos()) np.reparent_to(char_np) np.set_pos(p3d.LVector3f(0, 0, -0.9)) self.physics_world.attach(character.physics_node)
def update(self, dt, components): for char in components['CHARACTER']: nodepath = char.entity.get_component('NODEPATH').nodepath actor = None if char.entity.has_component('ACTOR'): actor = char.entity.get_component('ACTOR').actor if actor: actor.disableBlend() actor.pose('idle', 0) # Position ms = char.move_speed * dt / 2 char_speed = p3d.LVector3f(ms, 0, 0.0) delta = char.movement delta.componentwise_mult(char_speed) phys = char.entity.get_component('PHY_CHARACTER') phys.physics_node.set_linear_movement(delta, is_local=False) if char.movement.length_squared() > 0.0: if char.movement.get_x() > 0: nodepath.set_h(-90) elif char.movement.get_x() < 0: nodepath.set_h(90) char.action_set.discard('ATTACK_MOVE') if 'JUMP' in char.action_set: phys.physics_node.do_jump() char.action_set.discard('JUMP') # Resolve attacks for attack in self._attack_queues[char.entity.guid]: char.current_health -= attack.damage char.recoil_timer = 0.0 self._attack_queues[char.entity.guid].clear() if 'ATTACK' in char.action_set: if base.ecsmanager.has_system('PhysicsSystem'): physics = base.ecsmanager.get_system('PhysicsSystem') to_vec = base.render.get_relative_vector( nodepath, p3d.LVector3f(0, 1, 0)) from_pos = nodepath.get_pos() + p3d.LVector3f(0, 0, 0.5) to_pos = from_pos + to_vec * 1000 hits = physics.ray_cast(from_pos, to_pos, all_hits=True) if hits: hit = min(hits, key=lambda h: h.t) char.attack_move_target = hit.position char.target_entity_guid = hit.component.entity.guid char.action_set.add('ATTACK_MOVE') char.action_set.remove('ATTACK') if 'ATTACK_MOVE' in char.action_set: if char.entity.has_component('WEAPON'): weapon = char.entity.get_component('WEAPON') vec_to = char.attack_move_target - nodepath.get_pos() distance = vec_to.length() if distance < weapon.range: anim_control = weapon.actor.getAnimControl('attack') if not anim_control.is_playing(): if weapon.has_hit: weapon.has_hit = False char.action_set.discard('ATTACK_MOVE') else: weapon.actor.play('attack', fromFrame=1, toFrame=21) if not weapon.has_hit and anim_control.get_frame( ) >= 18: weapon.has_hit = True self._attack_queues[ char.target_entity_guid].append(Attack(1)) else: vec_to.normalize() vec_to.componentwiseMult(char_speed) new_pos = nodepath.get_pos() + vec_to nodepath.set_pos(new_pos) for track in [ 'TRACK_ONE', 'TRACK_TWO', 'TRACK_THREE', 'TRACK_FOUR' ]: if track in char.action_set: for component in getattr( char, track.lower()).get_components('EFFECT'): component.cmd_queue.add('ACTIVATE') char.action_set.remove(track) # Resolve health and dying # TODO make the player invincible for now if char.current_health <= 0 and not char.entity.has_component( 'PLAYER'): char.entity.remove_component( char.entity.get_component('PHY_HITBOX')) base.ecsmanager.remove_entity(char.entity) # Resolve recoil if char.recoil_timer < char.recoil_duration: char.recoil_timer += dt if actor: t = min(char.recoil_timer / char.recoil_duration, 1.0) mid_p = 0.33 if t > mid_p: t = (t - mid_p) / (1.0 - mid_p) t = 1.0 - t else: t /= mid_p actor.enableBlend() actor.setControlEffect('idle', 1 - t) actor.setControlEffect('hit', t) actor.pose('idle', 0) actor.pose('hit', 0)