Compare commits

..

No commits in common. "329cd173b9d9db0da8002c673be161c0be1e263b" and "895b56c326362be80511e6128ee18583e7a5354d" have entirely different histories.

10 changed files with 37 additions and 178 deletions

1
Cargo.lock generated
View file

@ -328,7 +328,6 @@ name = "bevy-santa"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"bevy", "bevy",
"derive_more",
"rand", "rand",
] ]

View file

@ -5,5 +5,4 @@ edition = "2024"
[dependencies] [dependencies]
bevy = "0.17.3" bevy = "0.17.3"
derive_more = "2.1.1"
rand = "0.9.2" rand = "0.9.2"

View file

@ -1,4 +1,4 @@
use std::f32::consts::TAU; use std::{f32::consts::TAU, fmt::Debug};
use bevy::prelude::*; use bevy::prelude::*;
use rand::Rng; use rand::Rng;
@ -8,11 +8,10 @@ use crate::{
kirby::Kirby, kirby::Kirby,
life::{DamageDealer, Life}, life::{DamageDealer, Life},
physics_body::PhysicsBody, physics_body::PhysicsBody,
sphere_collider::SphereCollider,
}; };
#[derive(Component)] #[derive(Component)]
#[require(Sprite, PhysicsBody, DensityObject, Life, DamageDealer, SphereCollider)] #[require(Sprite, PhysicsBody, DensityObject, Life, DamageDealer)]
pub struct Bubble { pub struct Bubble {
move_force: f32, move_force: f32,
} }
@ -28,11 +27,10 @@ pub fn bubble_spawn(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(( commands.spawn((
Bubble { move_force: 3000.0 }, Bubble { move_force: 3000.0 },
Sprite { image: texture.clone(), ..default() }, Sprite { image: texture.clone(), ..default() },
PhysicsBody { mass: 10.0, force: Vec2::ZERO, velocity: Vec2::ZERO, drag: 0.05 },
Transform::from_translation(pos.extend(0.0)).with_scale(Vec3::splat(1.0)), Transform::from_translation(pos.extend(0.0)).with_scale(Vec3::splat(1.0)),
PhysicsBody { mass: 10.0, force: Vec2::ZERO, velocity: Vec2::ZERO, drag: 0.05 },
Life::new(10.0), Life::new(10.0),
DamageDealer::new(0.5), DamageDealer::new(0.5),
SphereCollider::new(20.0),
)); ));
} }
} }
@ -57,11 +55,3 @@ pub fn bubble_move(
bubble_body.force += dir * bubble.move_force; bubble_body.force += dir * bubble.move_force;
} }
} }
pub struct BubblePlugin;
impl Plugin for BubblePlugin {
fn build(&self, app: &mut App) {
app.add_systems(Startup, bubble_spawn).add_systems(FixedUpdate, bubble_move);
}
}

View file

@ -1,51 +1,5 @@
use std::f32::consts::TAU;
use bevy::{prelude::*, render::renderer}; use bevy::{prelude::*, render::renderer};
use crate::counter::KirbyHitCountThisFrame;
#[derive(Component)]
pub struct MyCamera {
shaking_intensity_factor: f32,
shaking_reset_speed: f32,
}
pub fn spawn_camera(mut commands: Commands) { pub fn spawn_camera(mut commands: Commands) {
let mycam = commands commands.spawn(Camera2d);
.spawn((
MyCamera { shaking_intensity_factor: 10.0, shaking_reset_speed: 100.0 },
Transform::from_translation(Vec3::ZERO),
))
.id();
commands.entity(mycam).with_child((Camera2d, Transform::from_xyz(0.0, 0.0, 0.0)));
}
pub fn camera_shake(
time: Res<Time<Fixed>>,
kirby_hit_count: Res<KirbyHitCountThisFrame>,
parent_query: Query<(&MyCamera, &Children)>,
mut children_query: Query<&mut Transform, With<Camera2d>>,
) {
let (parent, children) = parent_query.single().expect("Expect exactly one MyCamera entity");
let child = children.first().expect("MyCamera must have at least one child Camera2d");
let mut child_transform = children_query.get_mut(*child).expect("Camera child must have a Transform and Camera2d");
let rand_angle = rand::random_range(0.0..TAU);
let rand_vec = Vec2::from_angle(rand_angle);
let shaking_strength = kirby_hit_count.count as f32 * parent.shaking_intensity_factor;
let shaking_vec = rand_vec * shaking_strength;
let mut child_translation = child_transform.translation.clone();
child_translation += shaking_vec.extend(0.0);
child_translation -= child_translation * parent.shaking_reset_speed * time.delta_secs();
child_transform.translation.x = child_translation.x;
child_transform.translation.y = child_translation.y;
println!("{:?}", child_transform.translation);
}
pub struct MyCameraPlugin;
impl Plugin for MyCameraPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Startup, spawn_camera).add_systems(FixedPostUpdate, camera_shake);
}
} }

View file

@ -1,51 +0,0 @@
use bevy::prelude::*;
use derive_more::{Deref, DerefMut};
#[derive(Resource, Default)]
pub struct Counter {
pub count: u32,
}
impl Counter {
pub fn new() -> Self {
Counter { count: 0 }
}
pub fn increase(&mut self, delta: u32) {
self.count += delta;
}
pub fn reset(&mut self) {
self.count = 0;
}
}
#[derive(Resource, Default, Deref, DerefMut)]
pub struct BubbleExplodedCountThisFrame(pub Counter);
#[derive(Resource, Default, Deref, DerefMut)]
pub struct BubbleSuckedCountThisFrame(pub Counter);
#[derive(Resource, Default, Deref, DerefMut)]
pub struct KirbyHitCountThisFrame(pub Counter);
fn reset_frame_counters(
mut bubble_sucked: ResMut<BubbleSuckedCountThisFrame>,
mut bubble_exploded: ResMut<BubbleExplodedCountThisFrame>,
mut kirby_hit: ResMut<KirbyHitCountThisFrame>,
) {
bubble_sucked.reset();
bubble_exploded.reset();
kirby_hit.reset();
}
pub struct CounterPlugin;
impl Plugin for CounterPlugin {
fn build(&self, app: &mut App) {
app.insert_resource(BubbleSuckedCountThisFrame::default())
.insert_resource(BubbleExplodedCountThisFrame::default())
.insert_resource(KirbyHitCountThisFrame::default())
.add_systems(FixedPostUpdate, reset_frame_counters);
}
}

View file

@ -52,7 +52,7 @@ pub fn init_density_object(mut density_grid: ResMut<DensityGrid>, mut query: Que
} }
} }
pub fn density_grid_update(mut density_grid: ResMut<DensityGrid>, query: Query<&Transform, With<DensityObject>>) { pub fn density_grid_update(mut density_grid: ResMut<DensityGrid>, query: Query<&Transform>) {
density_grid.grid.fill(0); density_grid.grid.fill(0);
for transform in &query { for transform in &query {
@ -86,13 +86,3 @@ pub fn density_grid_force(
physics_body.force -= density_gradient * DENSITY_FORCE_SCALE; physics_body.force -= density_gradient * DENSITY_FORCE_SCALE;
} }
} }
pub struct DensityGridPlugin;
impl Plugin for DensityGridPlugin {
fn build(&self, app: &mut App) {
app.insert_resource(DensityGrid::new())
.add_systems(PostStartup, init_density_object)
.add_systems(FixedUpdate, (density_grid_update, density_grid_force).chain());
}
}

View file

@ -26,6 +26,7 @@ pub fn kirby_spawn(
mut texture_atlas_layouts: ResMut<Assets<TextureAtlasLayout>>, mut texture_atlas_layouts: ResMut<Assets<TextureAtlasLayout>>,
) { ) {
let texture: Handle<Image> = asset_server.load("sprites/Sprite_kirby-Sheet.png"); let texture: Handle<Image> = asset_server.load("sprites/Sprite_kirby-Sheet.png");
let body = PhysicsBody { mass: 10.0, force: Vec2::ZERO, velocity: Vec2::ZERO, drag: 0.05 };
let layout = TextureAtlasLayout::from_grid(UVec2::splat(32), 3, 3, None, None); let layout = TextureAtlasLayout::from_grid(UVec2::splat(32), 3, 3, None, None);
let texture_atlas_layout = texture_atlas_layouts.add(layout); let texture_atlas_layout = texture_atlas_layouts.add(layout);
let animation_indices = AnimationIndices { first: 3, last: 5 }; // idle let animation_indices = AnimationIndices { first: 3, last: 5 }; // idle
@ -37,21 +38,22 @@ pub fn kirby_spawn(
texture, texture,
TextureAtlas { layout: texture_atlas_layout, index: animation_indices.first }, TextureAtlas { layout: texture_atlas_layout, index: animation_indices.first },
), ),
PhysicsBody { mass: 10.0, force: Vec2::ZERO, velocity: Vec2::ZERO, drag: 0.05 }, Transform::from_scale(Vec3::splat(KIRBY_SCALE)),
SphereCollider::new(20.0),
animation_indices, animation_indices,
AnimationTimer(Timer::from_seconds(0.1, TimerMode::Repeating)), AnimationTimer(Timer::from_seconds(0.1, TimerMode::Repeating)),
Life::new(1000.0), body,
Transform::from_scale(Vec3::splat(KIRBY_SCALE)), SphereCollider::new(50.0),
)) ))
.id(); .id();
commands.entity(kirby_entity).with_child(( commands.entity(kirby_entity).with_children(|parent| {
parent.spawn((
Transform::from_xyz(40.0, 0.0, 0.0), Transform::from_xyz(40.0, 0.0, 0.0),
SuckArea, SuckArea,
SphereCollider::new(80.0), SphereCollider::new(80.0),
DamageDealer::new(10000.0), DamageDealer::new(10000.0),
)); ));
});
} }
pub fn get_dir(keys: Res<ButtonInput<KeyCode>>) -> Vec2 { pub fn get_dir(keys: Res<ButtonInput<KeyCode>>) -> Vec2 {
@ -104,10 +106,3 @@ pub fn kirby_actions(
} }
} }
} }
pub struct KirbyPlugin;
impl Plugin for KirbyPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Startup, kirby_spawn).add_systems(FixedUpdate, kirby_actions);
}
}

View file

@ -2,7 +2,6 @@ use bevy::prelude::*;
use crate::{ use crate::{
bubble::Bubble, bubble::Bubble,
counter::{BubbleExplodedCountThisFrame, BubbleSuckedCountThisFrame, KirbyHitCountThisFrame},
kirby::{Kirby, SuckArea}, kirby::{Kirby, SuckArea},
sphere_collider::SphereCollider, sphere_collider::SphereCollider,
}; };
@ -56,7 +55,7 @@ impl DamageDealer {
// Considerating ennemies are ponctual // Considerating ennemies are ponctual
pub fn bubble_receive_damage( pub fn bubble_receive_damage(
time: Res<Time<Fixed>>, time: Res<Time<Fixed>>,
mut bubble_sucked: ResMut<BubbleSuckedCountThisFrame>,
mut enemy_query: Query<(&GlobalTransform, &mut Life), With<Bubble>>, mut enemy_query: Query<(&GlobalTransform, &mut Life), With<Bubble>>,
kirby_query: Query<(&Kirby, &Children)>, kirby_query: Query<(&Kirby, &Children)>,
@ -75,7 +74,6 @@ pub fn bubble_receive_damage(
for (enemy_transform, mut enemy_life) in &mut enemy_query { for (enemy_transform, mut enemy_life) in &mut enemy_query {
if suck_collider.point_inside(suck_transform.translation(), enemy_transform.translation()) { if suck_collider.point_inside(suck_transform.translation(), enemy_transform.translation()) {
enemy_life.damage(suck_damage.damage_strength * time.delta_secs()); enemy_life.damage(suck_damage.damage_strength * time.delta_secs());
bubble_sucked.increase(1);
} }
} }
} }
@ -84,22 +82,14 @@ pub fn bubble_receive_damage(
// Considerating allies are ponctual // Considerating allies are ponctual
pub fn kirby_receive_damage( pub fn kirby_receive_damage(
mut bubble_exploded: ResMut<BubbleExplodedCountThisFrame>, mut ally_query: Query<(&GlobalTransform, &mut Life), With<Kirby>>,
mut kirby_hit: ResMut<KirbyHitCountThisFrame>, mut enemy_query: Query<(&GlobalTransform, &SphereCollider, &DamageDealer, &mut Life), With<Bubble>>,
mut kirby_query: Query<(&GlobalTransform, &mut Life), (With<Kirby>, Without<Bubble>)>,
mut bubble_query: Query<
(&GlobalTransform, &SphereCollider, &DamageDealer, &mut Life),
(With<Bubble>, Without<Kirby>),
>,
) { ) {
for (kirby_transform, mut kirby_life) in &mut kirby_query { for (ally_transform, mut ally_life) in &mut ally_query {
for (bubble_transform, bubble_sphere_collider, bubble_damage_dealer, mut bubble_life) in &mut bubble_query { for (enemy_transform, enemy_sphere_collider, enemy_damage_dealer, mut bubble_life) in &mut enemy_query {
if bubble_sphere_collider.point_inside(kirby_transform.translation(), bubble_transform.translation()) { if enemy_sphere_collider.point_inside(ally_transform.translation(), enemy_transform.translation()) {
kirby_life.damage(bubble_damage_dealer.damage_strength); ally_life.damage(enemy_damage_dealer.damage_strength);
bubble_life.damage(1000000.0); // Bubble explode bubble_life.damage(1000000.0); // Bubble explode
// println!("{:?}", kirby_life.current_life)
bubble_exploded.increase(1);
kirby_hit.increase(1);
} }
} }
} }

View file

@ -3,21 +3,16 @@ use bevy::prelude::*;
use bubble::{bubble_move, bubble_spawn}; use bubble::{bubble_move, bubble_spawn};
use camera::spawn_camera; use camera::spawn_camera;
use density_grid::{DensityGrid, density_grid_force, density_grid_update, init_density_object}; use density_grid::{DensityGrid, density_grid_force, density_grid_update, init_density_object};
use kirby::{kirby_actions, kirby_spawn};
use life::despawn_if_dead; use life::despawn_if_dead;
use life::{bubble_receive_damage, kirby_receive_damage};
use map::MapBounds; use map::MapBounds;
use physics_body::physics_integrate; use physics_body::integrate;
use crate::bubble::BubblePlugin; use crate::life::bubble_receive_damage;
use crate::camera::MyCameraPlugin;
use crate::counter::CounterPlugin;
use crate::density_grid::DensityGridPlugin;
use crate::kirby::KirbyPlugin;
mod animation; mod animation;
mod bubble; mod bubble;
mod camera; mod camera;
mod counter;
mod density_grid; mod density_grid;
mod globals; mod globals;
mod kirby; mod kirby;
@ -29,17 +24,19 @@ mod sphere_collider;
fn main() { fn main() {
App::new() App::new()
.add_plugins(DefaultPlugins.set(ImagePlugin::default_nearest())) .add_plugins(DefaultPlugins.set(ImagePlugin::default_nearest()))
.add_plugins(CounterPlugin)
.add_plugins(KirbyPlugin)
.add_plugins(DensityGridPlugin)
.add_plugins(BubblePlugin)
.add_plugins(MyCameraPlugin)
.insert_resource(Time::<Fixed>::from_seconds(1.0 / 60.0)) .insert_resource(Time::<Fixed>::from_seconds(1.0 / 60.0))
.insert_resource(MapBounds { min: Vec2::ONE * -600.0, max: Vec2::ONE * 600.0 }) .insert_resource(MapBounds { min: Vec2::ONE * -600.0, max: Vec2::ONE * 600.0 })
.insert_resource(DensityGrid::new())
.add_systems(Startup, spawn_camera)
.add_systems(Startup, kirby_spawn)
.add_systems(Startup, bubble_spawn)
.add_systems(PostStartup, init_density_object)
.add_systems(Update, animate_sprite) .add_systems(Update, animate_sprite)
.add_systems(FixedUpdate, (density_grid_update, density_grid_force).chain())
.add_systems(FixedUpdate, kirby_actions)
.add_systems(FixedUpdate, bubble_move)
.add_systems(FixedUpdate, bubble_receive_damage) .add_systems(FixedUpdate, bubble_receive_damage)
.add_systems(FixedUpdate, kirby_receive_damage)
.add_systems(FixedPostUpdate, despawn_if_dead) .add_systems(FixedPostUpdate, despawn_if_dead)
.add_systems(FixedPostUpdate, physics_integrate) .add_systems(FixedPostUpdate, integrate)
.run(); .run();
} }

View file

@ -17,11 +17,7 @@ impl Default for PhysicsBody {
} }
} }
pub fn physics_integrate( pub fn integrate(bounds: Res<MapBounds>, mut query: Query<(&mut Transform, &mut PhysicsBody)>, time: Res<Time<Fixed>>) {
bounds: Res<MapBounds>,
mut query: Query<(&mut Transform, &mut PhysicsBody)>,
time: Res<Time<Fixed>>,
) {
for (mut transform, mut physicsbody) in &mut query { for (mut transform, mut physicsbody) in &mut query {
let force = physicsbody.force; let force = physicsbody.force;
let mass = physicsbody.mass; let mass = physicsbody.mass;