brrrrbrrr
This commit is contained in:
commit
250c3a510a
11 changed files with 662 additions and 0 deletions
190
src/cloud.rs
Normal file
190
src/cloud.rs
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
use crate::AppState;
|
||||
use crate::Materials;
|
||||
use bevy::prelude::*;
|
||||
use bevy_rapier2d::prelude::*;
|
||||
extern crate rand;
|
||||
|
||||
pub struct Cloud(Vec2);
|
||||
struct NewCloudTimer(Timer);
|
||||
pub struct Evil;
|
||||
pub struct CloudPlugin;
|
||||
|
||||
impl Plugin for CloudPlugin {
|
||||
fn build(&self, app: &mut AppBuilder) {
|
||||
app.init_resource::<NewCloudTimer>()
|
||||
.add_system_set(
|
||||
SystemSet::on_enter(AppState::InGame)
|
||||
.with_system(cloud_belt.system())
|
||||
.with_system(spawn_earth.system()),
|
||||
)
|
||||
.add_system_set(
|
||||
SystemSet::on_update(AppState::InGame)
|
||||
.with_system(cloud_kinematics.system())
|
||||
.with_system(newcloud_maker.system()),
|
||||
)
|
||||
.add_system_set(
|
||||
SystemSet::on_update(AppState::GameOver)
|
||||
.with_system(cloud_kinematics.system())
|
||||
.with_system(newcloud_maker.system()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for NewCloudTimer {
|
||||
fn default() -> Self {
|
||||
NewCloudTimer(Timer::from_seconds(2., true))
|
||||
}
|
||||
}
|
||||
|
||||
fn newcloud_maker(
|
||||
mut commands: Commands,
|
||||
rapier_config: Res<RapierConfiguration>,
|
||||
materials: Res<Materials>,
|
||||
time: Res<Time>,
|
||||
mut timer: ResMut<NewCloudTimer>,
|
||||
) {
|
||||
if timer.0.tick(time.delta()).just_finished() {
|
||||
use rand::Rng;
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
let nb = 4;
|
||||
for _ in 0..nb {
|
||||
let theta = rng.gen_range(0.0..10000.) * 2. * std::f32::consts::PI / nb as f32;
|
||||
let rho = 1.;
|
||||
let speed = rng.gen_range(1.0..5.0);
|
||||
let pos = Vec2::new(f32::cos(theta), f32::sin(theta)) * rho;
|
||||
let vel = Vec2::new(pos.x, pos.y).normalize() * speed;
|
||||
let is_evil = false;
|
||||
spawn_cloud(&mut commands, &rapier_config, &materials, pos, vel, is_evil);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn cloud_belt(
|
||||
mut commands: Commands,
|
||||
rapier_config: Res<RapierConfiguration>,
|
||||
materials: Res<Materials>,
|
||||
) {
|
||||
use rand::Rng;
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
let nb = 10;
|
||||
for i in 0..nb {
|
||||
let theta = i as f32 * 2. * std::f32::consts::PI / nb as f32;
|
||||
let rho = 10.;
|
||||
let speed = rng.gen_range(0.0..5.0);
|
||||
let pos = Vec2::new(f32::cos(theta), f32::sin(theta)) * rho;
|
||||
let vel = Vec2::new(pos.x, pos.y).normalize() * speed;
|
||||
let is_evil = false;
|
||||
spawn_cloud(&mut commands, &rapier_config, &materials, pos, vel, is_evil);
|
||||
}
|
||||
}
|
||||
|
||||
fn spawn_earth(
|
||||
mut commands: Commands,
|
||||
rapier_config: Res<RapierConfiguration>,
|
||||
materials: Res<Materials>,
|
||||
) {
|
||||
//TODO sapwn mother earth the root of all evil
|
||||
let radius = 60. / rapier_config.scale;
|
||||
let rigid_body = RigidBodyBundle {
|
||||
body_type: RigidBodyType::Static,
|
||||
position: Vec2::new(0., 0.).into(),
|
||||
velocity: RigidBodyVelocity {
|
||||
linvel: Vec2::new(0., 0.).into(),
|
||||
angvel: 0.0,
|
||||
},
|
||||
..Default::default()
|
||||
};
|
||||
let collider = ColliderBundle {
|
||||
shape: ColliderShape::ball(radius),
|
||||
mass_properties: ColliderMassProps::Density(1.0),
|
||||
material: ColliderMaterial {
|
||||
restitution: 1.0,
|
||||
..Default::default()
|
||||
},
|
||||
flags: (ActiveEvents::INTERSECTION_EVENTS | ActiveEvents::CONTACT_EVENTS).into(),
|
||||
..Default::default()
|
||||
};
|
||||
commands
|
||||
.spawn_bundle(rigid_body)
|
||||
.insert_bundle(collider)
|
||||
.insert_bundle(SpriteBundle {
|
||||
material: materials.earth_material.clone(),
|
||||
sprite: Sprite::new(Vec2::new(
|
||||
2. * radius * rapier_config.scale,
|
||||
2. * radius * rapier_config.scale,
|
||||
)),
|
||||
..Default::default()
|
||||
})
|
||||
.insert(RigidBodyPositionSync::Discrete)
|
||||
.insert(Cloud(Vec2::new(0., 0.)))
|
||||
.insert(Evil);
|
||||
}
|
||||
|
||||
fn spawn_cloud(
|
||||
commands: &mut Commands,
|
||||
rapier_config: &Res<RapierConfiguration>,
|
||||
materials: &Res<Materials>,
|
||||
pos: Vec2,
|
||||
vel: Vec2,
|
||||
is_evil: bool,
|
||||
) {
|
||||
//Spawn a cloud
|
||||
let radius = 15. / rapier_config.scale;
|
||||
let rigid_body = RigidBodyBundle {
|
||||
body_type: RigidBodyType::KinematicVelocityBased,
|
||||
position: pos.into(),
|
||||
velocity: RigidBodyVelocity {
|
||||
linvel: vel.into(),
|
||||
angvel: 0.0,
|
||||
},
|
||||
..Default::default()
|
||||
};
|
||||
let collider = ColliderBundle {
|
||||
shape: ColliderShape::ball(radius),
|
||||
mass_properties: ColliderMassProps::Density(1.0),
|
||||
material: ColliderMaterial {
|
||||
restitution: 1.0,
|
||||
..Default::default()
|
||||
},
|
||||
flags: (ActiveEvents::INTERSECTION_EVENTS | ActiveEvents::CONTACT_EVENTS).into(),
|
||||
..Default::default()
|
||||
};
|
||||
if is_evil {
|
||||
commands
|
||||
.spawn_bundle(rigid_body)
|
||||
.insert_bundle(collider)
|
||||
.insert_bundle(SpriteBundle {
|
||||
material: materials.cloud_material.clone(),
|
||||
sprite: Sprite::new(Vec2::new(
|
||||
2. * radius * rapier_config.scale,
|
||||
2. * radius * rapier_config.scale,
|
||||
)),
|
||||
..Default::default()
|
||||
})
|
||||
.insert(RigidBodyPositionSync::Discrete)
|
||||
.insert(Cloud(vel))
|
||||
.insert(Evil);
|
||||
} else {
|
||||
commands
|
||||
.spawn_bundle(rigid_body)
|
||||
.insert_bundle(collider)
|
||||
.insert_bundle(SpriteBundle {
|
||||
material: materials.cloud_material.clone(),
|
||||
sprite: Sprite::new(Vec2::new(
|
||||
2. * radius * rapier_config.scale,
|
||||
2. * radius * rapier_config.scale,
|
||||
)),
|
||||
..Default::default()
|
||||
})
|
||||
.insert(RigidBodyPositionSync::Discrete)
|
||||
.insert(Cloud(vel));
|
||||
}
|
||||
}
|
||||
|
||||
fn cloud_kinematics(mut velocities: Query<(&Cloud, &mut RigidBodyVelocity)>) {
|
||||
for (vel, mut next_vel) in velocities.iter_mut() {
|
||||
next_vel.linvel = vel.0.into();
|
||||
}
|
||||
}
|
||||
66
src/main.rs
Normal file
66
src/main.rs
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
use bevy::prelude::*;
|
||||
use bevy_rapier2d::prelude::*;
|
||||
|
||||
mod cloud;
|
||||
mod montociel;
|
||||
mod score;
|
||||
mod ui;
|
||||
|
||||
use cloud::*;
|
||||
use montociel::*;
|
||||
use score::*;
|
||||
use ui::*;
|
||||
|
||||
struct Materials {
|
||||
//TODO background image or smthing
|
||||
montociel_material: Handle<ColorMaterial>,
|
||||
cloud_material: Handle<ColorMaterial>,
|
||||
earth_material: Handle<ColorMaterial>,
|
||||
}
|
||||
|
||||
impl FromWorld for Materials {
|
||||
fn from_world(world: &mut World) -> Self {
|
||||
let asset_server = world.get_resource::<AssetServer>().unwrap();
|
||||
let montociel_asset = asset_server.load("montociel.png");
|
||||
let cloud_asset = asset_server.load("cloud.png");
|
||||
let earth_asset = asset_server.load("earth.png");
|
||||
let mut materials = world.get_resource_mut::<Assets<ColorMaterial>>().unwrap();
|
||||
let montociel_material = materials.add(montociel_asset.into());
|
||||
let cloud_material = materials.add(cloud_asset.into());
|
||||
let earth_material = materials.add(earth_asset.into());
|
||||
Materials {
|
||||
montociel_material,
|
||||
cloud_material,
|
||||
earth_material,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn setup(mut commands: Commands, mut rapier_config: ResMut<RapierConfiguration>) {
|
||||
rapier_config.scale = 15.;
|
||||
rapier_config.gravity = Vec2::new(0.0, 0.0).into();
|
||||
commands.spawn_bundle(OrthographicCameraBundle::new_2d());
|
||||
commands.spawn_bundle(UiCameraBundle::default());
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||
pub enum AppState {
|
||||
Menu,
|
||||
InGame,
|
||||
GameOver,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
App::build()
|
||||
.add_plugins(DefaultPlugins)
|
||||
.add_plugin(RapierPhysicsPlugin::<NoUserData>::default())
|
||||
.insert_resource(ClearColor(Color::rgb(1.0, 0.714, 0.757)))
|
||||
.init_resource::<Materials>()
|
||||
.add_plugin(MontocielPlugin)
|
||||
.add_plugin(CloudPlugin)
|
||||
.add_plugin(ScorePlugin)
|
||||
.add_plugin(UIPlugin)
|
||||
.add_state(AppState::Menu)
|
||||
.add_system_set(SystemSet::on_enter(AppState::Menu).with_system(setup.system()))
|
||||
.run();
|
||||
}
|
||||
214
src/montociel.rs
Normal file
214
src/montociel.rs
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
use crate::AppState;
|
||||
use crate::Evil;
|
||||
use crate::Materials;
|
||||
use crate::Score;
|
||||
use bevy::prelude::*;
|
||||
use bevy_rapier2d::prelude::*;
|
||||
|
||||
pub struct Montociel;
|
||||
pub struct MontocielPlugin;
|
||||
|
||||
impl Plugin for MontocielPlugin {
|
||||
fn build(&self, app: &mut AppBuilder) {
|
||||
app.add_system_set(
|
||||
SystemSet::on_enter(AppState::InGame).with_system(spawn_montociel.system()),
|
||||
)
|
||||
.add_system_set(
|
||||
SystemSet::on_update(AppState::InGame)
|
||||
.with_system(input_movement.system())
|
||||
.with_system(montociel_aerodynamism.system())
|
||||
.with_system(update_forces.system())
|
||||
.with_system(clamp_velocity.system())
|
||||
.with_system(cloud_collision.system()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn spawn_montociel(
|
||||
mut commands: Commands,
|
||||
rapier_config: ResMut<RapierConfiguration>,
|
||||
materials: Res<Materials>,
|
||||
) {
|
||||
//Spawn Montociel
|
||||
let radius = 30. / rapier_config.scale;
|
||||
let rigid_body = RigidBodyBundle {
|
||||
body_type: RigidBodyType::Dynamic,
|
||||
position: Vec2::new(10., 10.).into(),
|
||||
velocity: RigidBodyVelocity {
|
||||
linvel: Vec2::new(0.0, 0.0).into(),
|
||||
angvel: 0.4,
|
||||
},
|
||||
..Default::default()
|
||||
};
|
||||
let collider = ColliderBundle {
|
||||
//collider_type: ColliderType::Sensor,
|
||||
shape: ColliderShape::ball(radius),
|
||||
mass_properties: ColliderMassProps::Density(1.0),
|
||||
material: ColliderMaterial {
|
||||
restitution: 0.0,
|
||||
..Default::default()
|
||||
},
|
||||
flags: (ActiveEvents::INTERSECTION_EVENTS | ActiveEvents::CONTACT_EVENTS).into(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
commands
|
||||
.spawn_bundle(rigid_body)
|
||||
.insert_bundle(collider)
|
||||
.insert_bundle(SpriteBundle {
|
||||
material: materials.montociel_material.clone(),
|
||||
sprite: Sprite::new(Vec2::new(
|
||||
2. * radius * rapier_config.scale,
|
||||
2. * radius * rapier_config.scale,
|
||||
)),
|
||||
..Default::default()
|
||||
})
|
||||
.insert(RigidBodyPositionSync::Discrete)
|
||||
.insert(Montociel);
|
||||
}
|
||||
|
||||
fn input_movement(
|
||||
mouse_input: Res<Input<MouseButton>>,
|
||||
rapier_parameters: Res<RapierConfiguration>,
|
||||
mut montociel_info: Query<(&Montociel, &mut RigidBodyVelocity, &RigidBodyPosition)>,
|
||||
) {
|
||||
for (_, mut velocity, pos) in montociel_info.iter_mut() {
|
||||
if mouse_input.get_pressed().len() > 0 {
|
||||
let x = pos.position.translation.x;
|
||||
let y = pos.position.translation.y;
|
||||
let theta = std::f32::consts::PI / 2.;
|
||||
let mut move_delta = Vec2::new(
|
||||
-x * f32::cos(theta) + y * f32::sin(theta),
|
||||
-x * f32::sin(theta) - y * f32::cos(theta),
|
||||
);
|
||||
|
||||
if move_delta != Vec2::new(0., 0.) {
|
||||
// Note that the RapierConfiguration::Scale factor is also used here to transform
|
||||
// the move_delta from: 'pixels/second' to 'physics_units/second'
|
||||
move_delta.normalize();
|
||||
move_delta /= rapier_parameters.scale;
|
||||
}
|
||||
|
||||
// Update the velocity on the rigid_body_component,
|
||||
// the bevy_rapier plugin will update the Sprite transform.
|
||||
// cringeee
|
||||
let power = 0.8;
|
||||
let v_x = power * move_delta.x + velocity.linvel.x;
|
||||
let v_y = power * move_delta.y + velocity.linvel.y;
|
||||
velocity.linvel = Vec2::new(v_x, v_y).into();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn montociel_aerodynamism(mut velocities: Query<&mut RigidBodyVelocity, With<Montociel>>) {
|
||||
for mut velocity in velocities.iter_mut() {
|
||||
let v_x = velocity.linvel.x;
|
||||
let v_y = velocity.linvel.y;
|
||||
let velocity_slowed_by_air = 0.95 * Vec2::new(v_x, v_y);
|
||||
velocity.linvel = velocity_slowed_by_air.into();
|
||||
}
|
||||
}
|
||||
|
||||
fn update_forces(
|
||||
mut rigid_bodies: Query<
|
||||
(
|
||||
&mut RigidBodyForces,
|
||||
&RigidBodyPosition,
|
||||
&RigidBodyMassProps,
|
||||
),
|
||||
With<Montociel>,
|
||||
>,
|
||||
) {
|
||||
for (mut rb_forces, rb_pos, rb_mass) in rigid_bodies.iter_mut() {
|
||||
let x = rb_pos.position.translation.x;
|
||||
let y = rb_pos.position.translation.y;
|
||||
let d2 = x * x + y * y;
|
||||
let norm = f32::sqrt(d2);
|
||||
let g = 100.;
|
||||
let eps = 0.0001;
|
||||
let nimp = -g * rb_mass.mass() * 1. / (norm + eps);
|
||||
let gravity = Vec2::new(nimp * x, nimp * y).into();
|
||||
rb_forces.force = gravity;
|
||||
}
|
||||
}
|
||||
|
||||
fn clamp_velocity(
|
||||
mut bodies_info: Query<
|
||||
&mut RigidBodyVelocity, //, With<Montociel>
|
||||
>,
|
||||
) {
|
||||
for mut velocity in bodies_info.iter_mut() {
|
||||
let v_x = velocity.linvel.x;
|
||||
let v_y = velocity.linvel.y;
|
||||
let magnitude = f32::sqrt(v_x * v_x + v_y * v_y);
|
||||
let max_magnitude = 70.;
|
||||
if magnitude > 0.01 {
|
||||
let clamped_velocity =
|
||||
Vec2::new(v_x, v_y) / magnitude * f32::min(magnitude, max_magnitude);
|
||||
velocity.linvel = clamped_velocity.into();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn cloud_collision(
|
||||
mut commands: Commands,
|
||||
mut score: ResMut<Score>,
|
||||
mut state: ResMut<State<AppState>>,
|
||||
mut montociel_info: Query<
|
||||
(Entity, &mut RigidBodyVelocity, &RigidBodyPosition),
|
||||
With<Montociel>,
|
||||
>,
|
||||
mut contact_events: EventReader<ContactEvent>,
|
||||
query: Query<Entity, With<Evil>>,
|
||||
rapier_config: Res<RapierConfiguration>,
|
||||
) {
|
||||
for contact_event in contact_events.iter() {
|
||||
for (montociel_entity, mut vel, pos) in montociel_info.iter_mut() {
|
||||
match contact_event {
|
||||
ContactEvent::Started(collider1, collider2) => {
|
||||
let entity1 = collider1.entity();
|
||||
let entity2 = collider2.entity();
|
||||
if entity1 != montociel_entity && entity2 != montociel_entity {
|
||||
continue;
|
||||
}
|
||||
let entity = if entity1 == montociel_entity {
|
||||
entity2
|
||||
} else {
|
||||
entity1
|
||||
};
|
||||
if query.get(entity).is_ok() {
|
||||
state.set(AppState::GameOver).unwrap();
|
||||
} else {
|
||||
commands.entity(entity).despawn();
|
||||
jump(pos, &mut vel, &rapier_config);
|
||||
//increment score
|
||||
score.incr();
|
||||
}
|
||||
}
|
||||
ContactEvent::Stopped(_collider1, _collider2) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn jump(
|
||||
pos: &RigidBodyPosition,
|
||||
vel: &mut RigidBodyVelocity,
|
||||
rapier_config: &Res<RapierConfiguration>,
|
||||
) {
|
||||
let x = pos.position.translation.x;
|
||||
let y = pos.position.translation.y;
|
||||
let theta = 3. * std::f32::consts::PI / 4.;
|
||||
let mut move_delta = Vec2::new(
|
||||
-x * f32::cos(theta) + y * f32::sin(theta),
|
||||
-x * f32::sin(theta) - y * f32::cos(theta),
|
||||
);
|
||||
if move_delta != Vec2::new(0., 0.) {
|
||||
move_delta.normalize();
|
||||
move_delta /= rapier_config.scale;
|
||||
}
|
||||
let power = 70.;
|
||||
let v_x = power * move_delta.x + vel.linvel.x;
|
||||
let v_y = power * move_delta.y + vel.linvel.y;
|
||||
vel.linvel = Vec2::new(v_x, v_y).into();
|
||||
}
|
||||
85
src/score.rs
Normal file
85
src/score.rs
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
use crate::AppState;
|
||||
use bevy::prelude::*;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Score {
|
||||
score: u32,
|
||||
}
|
||||
struct ScoreUI;
|
||||
|
||||
impl Default for Score {
|
||||
fn default() -> Self {
|
||||
Score { score: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
impl Score {
|
||||
pub fn incr(&mut self) {
|
||||
//TODO incr more for each turn
|
||||
self.score += 1;
|
||||
}
|
||||
pub fn reset(&mut self) {
|
||||
self.score = 0;
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ScorePlugin;
|
||||
|
||||
impl Plugin for ScorePlugin {
|
||||
fn build(&self, app: &mut AppBuilder) {
|
||||
app.init_resource::<Score>()
|
||||
.add_system_set(
|
||||
SystemSet::on_enter(AppState::InGame).with_system(setup_score_ui.system()),
|
||||
)
|
||||
.add_system_set(
|
||||
SystemSet::on_update(AppState::InGame).with_system(update_score_ui.system()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn update_score_ui(score: Res<Score>, mut query: Query<&mut Text, With<ScoreUI>>) {
|
||||
for mut text in query.iter_mut() {
|
||||
text.sections[1].value = format!("{:.2}", score.score);
|
||||
}
|
||||
}
|
||||
|
||||
fn setup_score_ui(
|
||||
mut commands: Commands,
|
||||
mut score: ResMut<Score>,
|
||||
asset_server: Res<AssetServer>,
|
||||
) {
|
||||
//commands.spawn_bundle(UiCameraBundle::default());
|
||||
score.reset();
|
||||
commands
|
||||
.spawn_bundle(TextBundle {
|
||||
style: Style {
|
||||
align_self: AlignSelf::FlexEnd,
|
||||
..Default::default()
|
||||
},
|
||||
// Use `Text` directly
|
||||
text: Text {
|
||||
// Construct a `Vec` of `TextSection`s
|
||||
sections: vec![
|
||||
TextSection {
|
||||
value: "Score: ".to_string(),
|
||||
style: TextStyle {
|
||||
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
|
||||
font_size: 60.0,
|
||||
color: Color::WHITE,
|
||||
},
|
||||
},
|
||||
TextSection {
|
||||
value: "0".to_string(),
|
||||
style: TextStyle {
|
||||
font: asset_server.load("fonts/FiraMono-Medium.ttf"),
|
||||
font_size: 60.0,
|
||||
color: Color::GOLD,
|
||||
},
|
||||
},
|
||||
],
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
})
|
||||
.insert(ScoreUI);
|
||||
}
|
||||
93
src/ui.rs
Normal file
93
src/ui.rs
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
use crate::AppState;
|
||||
use bevy::prelude::*;
|
||||
|
||||
pub struct UIPlugin;
|
||||
|
||||
impl Plugin for UIPlugin {
|
||||
fn build(&self, app: &mut AppBuilder) {
|
||||
app.add_system_set(SystemSet::on_enter(AppState::Menu).with_system(setup_button.system()))
|
||||
.add_system_set(
|
||||
SystemSet::on_enter(AppState::GameOver).with_system(setup_button.system()),
|
||||
)
|
||||
.add_system(button_system.system());
|
||||
}
|
||||
}
|
||||
|
||||
fn button_system(
|
||||
//button_materials: Res<ButtonMaterials>,
|
||||
mut commands: Commands,
|
||||
mut interaction_query: Query<&Interaction, (Changed<Interaction>, With<Button>)>,
|
||||
entities: Query<Entity, Without<bevy::render::camera::Camera>>,
|
||||
button: Query<Entity, With<Button>>,
|
||||
mut state: ResMut<State<AppState>>,
|
||||
) {
|
||||
for interaction in interaction_query.iter_mut() {
|
||||
match *interaction {
|
||||
Interaction::Clicked => {
|
||||
match state.current() {
|
||||
AppState::Menu => {
|
||||
for button in button.iter() {
|
||||
commands.entity(button).despawn_recursive();
|
||||
}
|
||||
state.set(AppState::InGame).unwrap();
|
||||
}
|
||||
AppState::GameOver => {
|
||||
//despawn all entities
|
||||
for entity in entities.iter() {
|
||||
commands.entity(entity).despawn();
|
||||
}
|
||||
for button in button.iter() {
|
||||
commands.entity(button).despawn_recursive();
|
||||
}
|
||||
state.set(AppState::InGame).unwrap();
|
||||
}
|
||||
AppState::InGame => panic!(),
|
||||
}
|
||||
}
|
||||
Interaction::Hovered => {}
|
||||
Interaction::None => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn setup_button(
|
||||
mut commands: Commands,
|
||||
asset_server: Res<AssetServer>,
|
||||
state: Res<State<AppState>>,
|
||||
//button_materials: Res<ButtonMaterials>,
|
||||
) {
|
||||
let text = match state.current() {
|
||||
AppState::Menu => "Play!",
|
||||
AppState::InGame => panic!(),
|
||||
AppState::GameOver => "Revive!",
|
||||
};
|
||||
commands
|
||||
.spawn_bundle(ButtonBundle {
|
||||
style: Style {
|
||||
size: Size::new(Val::Px(150.0), Val::Px(65.0)),
|
||||
// center button
|
||||
margin: Rect::all(Val::Auto),
|
||||
// horizontally center child text
|
||||
justify_content: JustifyContent::Center,
|
||||
// vertically center child text
|
||||
align_items: AlignItems::Center,
|
||||
..Default::default()
|
||||
},
|
||||
//material: button_materials.normal.clone(),
|
||||
..Default::default()
|
||||
})
|
||||
.with_children(|parent| {
|
||||
parent.spawn_bundle(TextBundle {
|
||||
text: Text::with_section(
|
||||
text,
|
||||
TextStyle {
|
||||
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
|
||||
font_size: 40.0,
|
||||
color: Color::rgb(0.9, 0.9, 0.9),
|
||||
},
|
||||
Default::default(),
|
||||
),
|
||||
..Default::default()
|
||||
});
|
||||
});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue