save
This commit is contained in:
parent
895b56c326
commit
ee8799c324
8 changed files with 177 additions and 38 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
use std::{f32::consts::TAU, fmt::Debug};
|
use std::f32::consts::TAU;
|
||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
@ -8,10 +8,11 @@ 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)]
|
#[require(Sprite, PhysicsBody, DensityObject, Life, DamageDealer, SphereCollider)]
|
||||||
pub struct Bubble {
|
pub struct Bubble {
|
||||||
move_force: f32,
|
move_force: f32,
|
||||||
}
|
}
|
||||||
|
|
@ -27,10 +28,11 @@ 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() },
|
||||||
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 },
|
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)),
|
||||||
Life::new(10.0),
|
Life::new(10.0),
|
||||||
DamageDealer::new(0.5),
|
DamageDealer::new(0.5),
|
||||||
|
SphereCollider::new(20.0),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -55,3 +57,11 @@ 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,51 @@
|
||||||
|
use std::f32::consts::TAU;
|
||||||
|
|
||||||
use bevy::{prelude::*, render::renderer};
|
use bevy::{prelude::*, render::renderer};
|
||||||
|
|
||||||
pub fn spawn_camera(mut commands: Commands) {
|
use crate::counter::KirbyHitCountThisFrame;
|
||||||
commands.spawn(Camera2d);
|
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct MyCamera {
|
||||||
|
shaking_intensity_factor: f32,
|
||||||
|
shaking_reset_speed: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn spawn_camera(mut commands: Commands) {
|
||||||
|
let mycam = commands
|
||||||
|
.spawn((
|
||||||
|
MyCamera { shaking_intensity_factor: 10.0, shaking_reset_speed: 0.1 },
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
51
src/counter.rs
Normal file
51
src/counter.rs
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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>) {
|
pub fn density_grid_update(mut density_grid: ResMut<DensityGrid>, query: Query<&Transform, With<DensityObject>>) {
|
||||||
density_grid.grid.fill(0);
|
density_grid.grid.fill(0);
|
||||||
|
|
||||||
for transform in &query {
|
for transform in &query {
|
||||||
|
|
@ -86,3 +86,13 @@ 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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
29
src/kirby.rs
29
src/kirby.rs
|
|
@ -26,7 +26,6 @@ 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
|
||||||
|
|
@ -38,22 +37,21 @@ pub fn kirby_spawn(
|
||||||
texture,
|
texture,
|
||||||
TextureAtlas { layout: texture_atlas_layout, index: animation_indices.first },
|
TextureAtlas { layout: texture_atlas_layout, index: animation_indices.first },
|
||||||
),
|
),
|
||||||
Transform::from_scale(Vec3::splat(KIRBY_SCALE)),
|
PhysicsBody { mass: 10.0, force: Vec2::ZERO, velocity: Vec2::ZERO, drag: 0.05 },
|
||||||
|
SphereCollider::new(20.0),
|
||||||
animation_indices,
|
animation_indices,
|
||||||
AnimationTimer(Timer::from_seconds(0.1, TimerMode::Repeating)),
|
AnimationTimer(Timer::from_seconds(0.1, TimerMode::Repeating)),
|
||||||
body,
|
Life::new(1000.0),
|
||||||
SphereCollider::new(50.0),
|
Transform::from_scale(Vec3::splat(KIRBY_SCALE)),
|
||||||
))
|
))
|
||||||
.id();
|
.id();
|
||||||
|
|
||||||
commands.entity(kirby_entity).with_children(|parent| {
|
commands.entity(kirby_entity).with_child((
|
||||||
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 {
|
||||||
|
|
@ -106,3 +104,10 @@ 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
24
src/life.rs
24
src/life.rs
|
|
@ -2,6 +2,7 @@ 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,
|
||||||
};
|
};
|
||||||
|
|
@ -55,7 +56,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)>,
|
||||||
|
|
@ -74,6 +75,7 @@ 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -82,14 +84,22 @@ pub fn bubble_receive_damage(
|
||||||
|
|
||||||
// Considerating allies are ponctual
|
// Considerating allies are ponctual
|
||||||
pub fn kirby_receive_damage(
|
pub fn kirby_receive_damage(
|
||||||
mut ally_query: Query<(&GlobalTransform, &mut Life), With<Kirby>>,
|
mut bubble_exploded: ResMut<BubbleExplodedCountThisFrame>,
|
||||||
mut enemy_query: Query<(&GlobalTransform, &SphereCollider, &DamageDealer, &mut Life), With<Bubble>>,
|
mut kirby_hit: ResMut<KirbyHitCountThisFrame>,
|
||||||
|
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 (ally_transform, mut ally_life) in &mut ally_query {
|
for (kirby_transform, mut kirby_life) in &mut kirby_query {
|
||||||
for (enemy_transform, enemy_sphere_collider, enemy_damage_dealer, mut bubble_life) in &mut enemy_query {
|
for (bubble_transform, bubble_sphere_collider, bubble_damage_dealer, mut bubble_life) in &mut bubble_query {
|
||||||
if enemy_sphere_collider.point_inside(ally_transform.translation(), enemy_transform.translation()) {
|
if bubble_sphere_collider.point_inside(kirby_transform.translation(), bubble_transform.translation()) {
|
||||||
ally_life.damage(enemy_damage_dealer.damage_strength);
|
kirby_life.damage(bubble_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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
27
src/main.rs
27
src/main.rs
|
|
@ -3,16 +3,21 @@ 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::integrate;
|
use physics_body::physics_integrate;
|
||||||
|
|
||||||
use crate::life::bubble_receive_damage;
|
use crate::bubble::BubblePlugin;
|
||||||
|
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;
|
||||||
|
|
@ -24,19 +29,17 @@ 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, integrate)
|
.add_systems(FixedPostUpdate, physics_integrate)
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,11 @@ impl Default for PhysicsBody {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn integrate(bounds: Res<MapBounds>, mut query: Query<(&mut Transform, &mut PhysicsBody)>, time: Res<Time<Fixed>>) {
|
pub fn physics_integrate(
|
||||||
|
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;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue