Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Projectiles - Systems

pub fn projectile_system(projectiles: Query<(Ref<Projectile>, Ref<EntityId>, Ref<Timer>, Ref<Velocity>, Ref<Collider>, Ref<Transform>)>, player_query: Query<(Ref<Transform>, Ref<Player>, Ref<Collider>, Ref<Velocity>)>, enemies: Query<(Ref<Transform>, Ref<Enemy>, Ref<Collider>, Ref<Velocity>)>, engine: Ref<Engine>, frame_constants: Ref<FrameConstants>) {
    for (projectile, entity_id, timer, velocity, collider, transform) in projectiles.iter() {
        if timer.time_remaining <= 0.0 || projectile.number_of_hits >= projectile.max_number_of_hits.unwrap_or(0) {
            //TODO: apply on death effects
            engine.despawn(*entity_id);
        }

        let (can_hit_enemies, can_hit_player) = match projectile.valid_targets {
            Faction::Enemy => (true, false),
            Faction::Player => (false, true),
            Faction::All => (true, true),
        };

        let projectile_mm = Mat4::from_translation(transform.position.extend(0.)).into();
        let options = ShapeCastOptions {
            max_time_of_impact: frame_constants.delta_time,
            ..Default::default()
        };

        if can_hit_enemies {
            let collider_radius = match *collider {
                Collider::Sphere { radius } => radius,
                Collider::Box { size } => (size[0] + size[1]) / 2.0,
                Collider::Capsule { radius, height } => (radius + height) / 2.0,
            };
            
            let check_range = 2.0 * collider_radius 
            + velocity.current_velocity.length() * frame_constants.delta_time * 10.0;

            for (enemy_transform, _, enemy_collider, enemy_velocity) in enemies.iter() {
                let distance = transform.position.distance_squared(enemy_transform.position);
               
                // Check if enemey is close enoough to even consider
                if distance <= check_range * check_range {
                    let enemy_mm = Mat4::from_translation(enemy_transform.position.extend(0.)).into();
                   if physics::cast_shapes(
                    &collider.clone(),
                     &projectile_mm, 
                     &velocity.current_velocity, 
                     &enemy_collider, 
                     &enemy_mm, 
                     &enemy_velocity.current_velocity, 
                     options).is_some() {
                        println!("Hit enemy");
                        engine.despawn(*entity_id);
                   }
                }
            }

        }

        if can_hit_player {
            for (player_transform, _, player_collider, player_velocity) in player_query.iter() {
            let player_mm = Mat4::from_translation(player_transform.position.extend(0.)).into();
            if physics::cast_shapes(
                &collider.clone(),
                &projectile_mm,
                &velocity.current_velocity,
                &player_collider,
                &player_mm,
                &player_velocity.current_velocity,
                options,
            ).is_some() {
                println!("Hit player");
                engine.despawn(*entity_id);
            }
            }
        }
    }
}