add sound effects
This commit is contained in:
parent
86f2345667
commit
587b902e79
39 changed files with 234 additions and 40 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
|
@ -1628,6 +1628,7 @@ dependencies = [
|
|||
"bevy",
|
||||
"combat",
|
||||
"input",
|
||||
"rand",
|
||||
"resources",
|
||||
"state",
|
||||
"ui_health_bar",
|
||||
|
|
@ -5376,6 +5377,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"bevy",
|
||||
"bevy_egui",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -5410,6 +5412,7 @@ dependencies = [
|
|||
"input",
|
||||
"resources",
|
||||
"state",
|
||||
"ui",
|
||||
"ui_state",
|
||||
"upgrade",
|
||||
]
|
||||
|
|
@ -5423,6 +5426,7 @@ dependencies = [
|
|||
"combat",
|
||||
"music",
|
||||
"state",
|
||||
"ui",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
(
|
||||
map: {
|
||||
MouseButton(Middle): [
|
||||
CameraOrbitEnable,
|
||||
KeyCode(ShiftLeft): [
|
||||
MultiPlaceTower,
|
||||
],
|
||||
MouseButton(Right): [
|
||||
PlaceTower,
|
||||
|
|
@ -9,8 +9,8 @@
|
|||
MouseButton(Left): [
|
||||
CameraPanEnable,
|
||||
],
|
||||
KeyCode(ShiftLeft): [
|
||||
MultiPlaceTower,
|
||||
MouseButton(Middle): [
|
||||
CameraOrbitEnable,
|
||||
],
|
||||
MouseScroll: [
|
||||
CameraZoom,
|
||||
|
|
|
|||
BIN
assets/sounds/boom1.ogg
Normal file
BIN
assets/sounds/boom1.ogg
Normal file
Binary file not shown.
BIN
assets/sounds/click1.ogg
Normal file
BIN
assets/sounds/click1.ogg
Normal file
Binary file not shown.
BIN
assets/sounds/gasp1.ogg
Normal file
BIN
assets/sounds/gasp1.ogg
Normal file
Binary file not shown.
BIN
assets/sounds/gasp2.ogg
Normal file
BIN
assets/sounds/gasp2.ogg
Normal file
Binary file not shown.
BIN
assets/sounds/gasp3.ogg
Normal file
BIN
assets/sounds/gasp3.ogg
Normal file
Binary file not shown.
BIN
assets/sounds/gust1.ogg
Normal file
BIN
assets/sounds/gust1.ogg
Normal file
Binary file not shown.
BIN
assets/sounds/gust2.ogg
Normal file
BIN
assets/sounds/gust2.ogg
Normal file
Binary file not shown.
BIN
assets/sounds/megathump.ogg
Normal file
BIN
assets/sounds/megathump.ogg
Normal file
Binary file not shown.
BIN
assets/sounds/megathump2.ogg
Normal file
BIN
assets/sounds/megathump2.ogg
Normal file
Binary file not shown.
BIN
assets/sounds/pop1.ogg
Normal file
BIN
assets/sounds/pop1.ogg
Normal file
Binary file not shown.
BIN
assets/sounds/pop2.ogg
Normal file
BIN
assets/sounds/pop2.ogg
Normal file
Binary file not shown.
BIN
assets/sounds/pop3.ogg
Normal file
BIN
assets/sounds/pop3.ogg
Normal file
Binary file not shown.
BIN
assets/sounds/revthump1.ogg
Normal file
BIN
assets/sounds/revthump1.ogg
Normal file
Binary file not shown.
BIN
assets/sounds/revthump2.ogg
Normal file
BIN
assets/sounds/revthump2.ogg
Normal file
Binary file not shown.
BIN
assets/sounds/thump1.ogg
Normal file
BIN
assets/sounds/thump1.ogg
Normal file
Binary file not shown.
BIN
assets/sounds/thump2.ogg
Normal file
BIN
assets/sounds/thump2.ogg
Normal file
Binary file not shown.
BIN
assets/sounds/weird1.ogg
Normal file
BIN
assets/sounds/weird1.ogg
Normal file
Binary file not shown.
|
|
@ -6,6 +6,7 @@ edition = "2024"
|
|||
[dependencies]
|
||||
bevy = { workspace = true }
|
||||
avian3d = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
combat = { path = "../combat" }
|
||||
state = { path = "../state" }
|
||||
resources = { path = "../resources" }
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ use bevy::{
|
|||
};
|
||||
use combat::{Defense, Health, Range, Team};
|
||||
use input::Selectable;
|
||||
use rand::{Rng, thread_rng};
|
||||
use resources::{Cost, Resources};
|
||||
use state::GameSystemSet;
|
||||
use ui_health_bar::BarSettings;
|
||||
|
|
@ -45,6 +46,7 @@ pub struct BuildingInfo {
|
|||
pub preview: Entity,
|
||||
pub size: UVec3,
|
||||
pub unlocked: bool,
|
||||
pub place_sound: Handle<AudioSource>,
|
||||
}
|
||||
|
||||
impl BuildingInfo {
|
||||
|
|
@ -189,6 +191,16 @@ fn place_building(
|
|||
continue;
|
||||
}
|
||||
|
||||
commands.spawn((
|
||||
AudioPlayer(info.place_sound.clone()),
|
||||
PlaybackSettings {
|
||||
mode: bevy::audio::PlaybackMode::Despawn,
|
||||
speed: thread_rng().gen_range(0.8..1.2),
|
||||
spatial: false,
|
||||
..default()
|
||||
},
|
||||
Transform::from_translation(position),
|
||||
));
|
||||
let mut ec = commands.spawn((
|
||||
// adjust model up slightly so base of all towers are aligned
|
||||
Transform::from_translation(position),
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use avian3d::prelude::{Collider, LinearVelocity, RigidBody};
|
|||
use bevy::prelude::*;
|
||||
use building::{BuildingInfo, BuildingPreview, PREVIEW_ALPHA, PopulatePlacedBuilding};
|
||||
use combat::{
|
||||
Defense, Health, Range,
|
||||
DeathAudio, Defense, Health, Range,
|
||||
projectiles::{Fire, Projectile, ProjectileLauncher, get_shotgun_launch_vectors},
|
||||
};
|
||||
use combat_damagers::ContactDamage;
|
||||
|
|
@ -36,6 +36,8 @@ struct BuildingResources {
|
|||
projectile_material: Handle<StandardMaterial>,
|
||||
projectile_collider: Collider,
|
||||
info_entity: Entity,
|
||||
death_audio: Handle<AudioSource>,
|
||||
shoot_audio: Handle<AudioSource>,
|
||||
}
|
||||
|
||||
const SIZE: UVec3 = UVec3::splat(2);
|
||||
|
|
@ -45,6 +47,7 @@ fn register(
|
|||
mut commands: Commands,
|
||||
mut meshes: ResMut<Assets<Mesh>>,
|
||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||
assets: Res<AssetServer>,
|
||||
) {
|
||||
let mesh = meshes.add(Cuboid::from_length(2.0));
|
||||
let base_material = StandardMaterial {
|
||||
|
|
@ -149,6 +152,7 @@ fn register(
|
|||
preview,
|
||||
size: SIZE,
|
||||
unlocked: true,
|
||||
place_sound: assets.load("sounds/thump1.ogg"),
|
||||
},
|
||||
Range(10.0),
|
||||
Health::new(20.0),
|
||||
|
|
@ -167,6 +171,8 @@ fn register(
|
|||
projectile_mesh: meshes.add(Cuboid::from_size(PROJ_SIZE)),
|
||||
projectile_collider: Collider::cuboid(PROJ_SIZE.x, PROJ_SIZE.y, PROJ_SIZE.z),
|
||||
info_entity: info,
|
||||
death_audio: assets.load("sounds/thump1.ogg"),
|
||||
shoot_audio: assets.load("sounds/pop1.ogg"),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -185,12 +191,14 @@ fn populate(
|
|||
projectile_count: 5,
|
||||
},
|
||||
ContactDamage::new(2.0),
|
||||
DeathAudio(res.death_audio.clone()),
|
||||
ProjectileLauncher::new(
|
||||
Duration::from_secs(1),
|
||||
5.0,
|
||||
Vec3::Y * (SIZE.y as f32 + 0.5),
|
||||
Duration::from_secs(10),
|
||||
10.0_f32.to_radians(),
|
||||
res.shoot_audio.clone(),
|
||||
),
|
||||
Mesh3d(res.mesh.clone()),
|
||||
MeshMaterial3d(res.material.clone()),
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
use bevy::prelude::*;
|
||||
use building::{BuildingInfo, BuildingPreview, Core, PREVIEW_ALPHA, PopulatePlacedBuilding};
|
||||
use combat::{Defense, Died, Health, Range};
|
||||
use combat::{DeathAudio, Defense, Died, Health, Range};
|
||||
use resources::{AvailableWorkers, Quantity};
|
||||
use state::{CoreState, GameState};
|
||||
use ui_range_indicator::CustomRangeIndicator;
|
||||
|
|
@ -23,6 +23,7 @@ struct CoreResources {
|
|||
mesh: Handle<Mesh>,
|
||||
material: Handle<StandardMaterial>,
|
||||
info_entity: Entity,
|
||||
death_sound: Handle<AudioSource>,
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
|
|
@ -34,6 +35,7 @@ fn register(
|
|||
mut commands: Commands,
|
||||
mut meshes: ResMut<Assets<Mesh>>,
|
||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||
assets: Res<AssetServer>,
|
||||
) {
|
||||
let mesh = meshes.add(Cuboid::from_length(2.0));
|
||||
let base_material = StandardMaterial {
|
||||
|
|
@ -65,6 +67,7 @@ fn register(
|
|||
preview,
|
||||
size: SIZE,
|
||||
unlocked: false,
|
||||
place_sound: assets.load("sounds/megathump.ogg"),
|
||||
},
|
||||
UpgradeTree { upgrades },
|
||||
Name::new("Core"),
|
||||
|
|
@ -76,6 +79,7 @@ fn register(
|
|||
mesh: mesh,
|
||||
material: material,
|
||||
info_entity: info,
|
||||
death_sound: assets.load("sounds/megathump2.ogg"),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -157,6 +161,7 @@ fn populate(
|
|||
Core,
|
||||
Mesh3d(res.mesh.clone()),
|
||||
MeshMaterial3d(res.material.clone()),
|
||||
DeathAudio(res.death_sound.clone()),
|
||||
CustomRangeIndicator::new(materials.add(StandardMaterial {
|
||||
alpha_mode: AlphaMode::Blend,
|
||||
base_color: Color::srgba(0.6, 0.2, 0.2, 0.4),
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
use bevy::prelude::*;
|
||||
use building::{BuildingInfo, BuildingPreview, PREVIEW_ALPHA, PopulatePlacedBuilding};
|
||||
use combat::{Defense, Health};
|
||||
use combat::{DeathAudio, Defense, Health};
|
||||
use combat_damagers::ContactDamage;
|
||||
use resources::{Cost, Quantity};
|
||||
use upgrade::{Upgrade, UpgradeApplied, UpgradeTree};
|
||||
|
|
@ -25,6 +25,7 @@ struct ImpalerResources {
|
|||
mesh: Handle<Mesh>,
|
||||
material: Handle<StandardMaterial>,
|
||||
info_entity: Entity,
|
||||
death_audio: Handle<AudioSource>,
|
||||
}
|
||||
|
||||
const SIZE: UVec3 = UVec3::ONE;
|
||||
|
|
@ -33,6 +34,7 @@ fn register(
|
|||
mut commands: Commands,
|
||||
mut meshes: ResMut<Assets<Mesh>>,
|
||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||
assets: Res<AssetServer>,
|
||||
) {
|
||||
let mesh = meshes.add(Cuboid::from_length(1.0));
|
||||
let base_material = StandardMaterial {
|
||||
|
|
@ -143,6 +145,7 @@ fn register(
|
|||
preview,
|
||||
size: SIZE,
|
||||
unlocked: true,
|
||||
place_sound: assets.load("sounds/thump1.ogg"),
|
||||
},
|
||||
UpgradeTree { upgrades },
|
||||
Cost(Quantity { souls: 5, bones: 0 }),
|
||||
|
|
@ -153,6 +156,7 @@ fn register(
|
|||
mesh: mesh,
|
||||
material: material,
|
||||
info_entity: info,
|
||||
death_audio: assets.load("sounds/pop3.ogg"),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -168,6 +172,7 @@ fn populate(
|
|||
Impaler,
|
||||
ContactDamage::new(5.0),
|
||||
Mesh3d(res.mesh.clone()),
|
||||
DeathAudio(res.death_audio.clone()),
|
||||
MeshMaterial3d(res.material.clone()),
|
||||
));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use avian3d::prelude::{Collider, GravityScale, LinearVelocity, RigidBody};
|
|||
use bevy::prelude::*;
|
||||
use building::{BuildingInfo, BuildingPreview, PREVIEW_ALPHA, PopulatePlacedBuilding};
|
||||
use combat::{
|
||||
Defense, Health, Range, Team,
|
||||
DeathAudio, Defense, Health, Range, Team,
|
||||
projectiles::{Fire, Projectile, ProjectileLauncher},
|
||||
};
|
||||
use combat_damagers::ContactDamage;
|
||||
|
|
@ -38,6 +38,8 @@ struct BuildingResources {
|
|||
projectile_material: Handle<StandardMaterial>,
|
||||
projectile_collider: Collider,
|
||||
info_entity: Entity,
|
||||
death_audio: Handle<AudioSource>,
|
||||
shoot_audio: Handle<AudioSource>,
|
||||
}
|
||||
|
||||
const SIZE: UVec3 = UVec3::new(1, 4, 1);
|
||||
|
|
@ -47,6 +49,7 @@ fn register(
|
|||
mut commands: Commands,
|
||||
mut meshes: ResMut<Assets<Mesh>>,
|
||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||
assets: Res<AssetServer>,
|
||||
) {
|
||||
let mesh = meshes.add(Cuboid::from_size(SIZE.as_vec3()));
|
||||
let base_material = StandardMaterial {
|
||||
|
|
@ -157,6 +160,7 @@ fn register(
|
|||
preview,
|
||||
size: SIZE,
|
||||
unlocked: true,
|
||||
place_sound: assets.load("sounds/thump1.ogg"),
|
||||
},
|
||||
Range(10.0),
|
||||
Health::new(10.0),
|
||||
|
|
@ -175,6 +179,8 @@ fn register(
|
|||
projectile_mesh: meshes.add(Cuboid::from_size(PROJ_SIZE)),
|
||||
projectile_collider: Collider::cuboid(PROJ_SIZE.x, PROJ_SIZE.y, PROJ_SIZE.z),
|
||||
info_entity: info,
|
||||
death_audio: assets.load("sounds/revthump1.ogg"),
|
||||
shoot_audio: assets.load("sounds/pop2.ogg"),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -194,6 +200,7 @@ fn populate(
|
|||
shot_velocity: 20.,
|
||||
},
|
||||
ContactDamage::new(2.0),
|
||||
DeathAudio(res.death_audio.clone()),
|
||||
ProjectileLauncher {
|
||||
custom_targeting: true,
|
||||
..ProjectileLauncher::new(
|
||||
|
|
@ -202,6 +209,7 @@ fn populate(
|
|||
Vec3::Y * (SIZE.y as f32 + 0.5),
|
||||
Duration::from_secs(10),
|
||||
0.,
|
||||
res.shoot_audio.clone(),
|
||||
)
|
||||
},
|
||||
Mesh3d(res.mesh.clone()),
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use avian3d::prelude::*;
|
|||
use bevy::prelude::*;
|
||||
use building::{BuildingInfo, BuildingPreview, PREVIEW_ALPHA, PopulatePlacedBuilding};
|
||||
use combat::{
|
||||
Attacked, Defense, Died, Health, Range, Team,
|
||||
Attacked, DeathAudio, Defense, Died, Health, Range, Team,
|
||||
projectiles::{Fire, Projectile, ProjectileLauncher, get_launch_vector},
|
||||
};
|
||||
use combat_damagers::ContactDamage;
|
||||
|
|
@ -47,6 +47,9 @@ struct BuildingResources {
|
|||
projectile_material: Handle<StandardMaterial>,
|
||||
projectile_collider: Collider,
|
||||
info_entity: Entity,
|
||||
death_audio: Handle<AudioSource>,
|
||||
shoot_audio: Handle<AudioSource>,
|
||||
explosion_audio: Handle<AudioSource>,
|
||||
}
|
||||
|
||||
const SIZE: UVec3 = UVec3::new(3, 1, 3);
|
||||
|
|
@ -56,6 +59,7 @@ fn register(
|
|||
mut commands: Commands,
|
||||
mut meshes: ResMut<Assets<Mesh>>,
|
||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||
assets: Res<AssetServer>,
|
||||
) {
|
||||
let mesh = meshes.add(Cuboid::from_size(SIZE.as_vec3()));
|
||||
let base_material = StandardMaterial {
|
||||
|
|
@ -178,6 +182,7 @@ fn register(
|
|||
preview,
|
||||
size: SIZE,
|
||||
unlocked: true,
|
||||
place_sound: assets.load("sounds/thump2.ogg"),
|
||||
},
|
||||
Range(20.0),
|
||||
Health::new(50.0),
|
||||
|
|
@ -196,6 +201,9 @@ fn register(
|
|||
projectile_mesh: meshes.add(Cuboid::from_size(PROJ_SIZE)),
|
||||
projectile_collider: Collider::cuboid(PROJ_SIZE.x, PROJ_SIZE.y, PROJ_SIZE.z),
|
||||
info_entity: info,
|
||||
death_audio: assets.load("sounds/revthump2.ogg"),
|
||||
shoot_audio: assets.load("sounds/gust2.ogg"),
|
||||
explosion_audio: assets.load("sounds/boom1.ogg"),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -218,6 +226,7 @@ fn populate(
|
|||
pellet_damage: 10.,
|
||||
pellet_speed: 50.,
|
||||
},
|
||||
DeathAudio(res.death_audio.clone()),
|
||||
ContactDamage::new(2.0),
|
||||
ProjectileLauncher::new(
|
||||
Duration::from_secs(3),
|
||||
|
|
@ -225,6 +234,7 @@ fn populate(
|
|||
Vec3::Y * (SIZE.y as f32 + 0.5),
|
||||
Duration::from_secs(10),
|
||||
0.,
|
||||
res.shoot_audio.clone(),
|
||||
),
|
||||
Mesh3d(res.mesh.clone()),
|
||||
MeshMaterial3d(res.material.clone()),
|
||||
|
|
@ -256,6 +266,7 @@ fn on_fire(
|
|||
Transform::from_translation(trigger.event().spawn_pos),
|
||||
Projectile::from(&trigger.event().launcher),
|
||||
Projectile::collision_layers(trigger.event().team),
|
||||
DeathAudio(res.explosion_audio.clone()),
|
||||
SuncannonProjectile(suncannon.clone()),
|
||||
LinearVelocity(v),
|
||||
res.projectile_collider.clone(),
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ use std::time::Duration;
|
|||
use avian3d::prelude::*;
|
||||
use bevy::prelude::*;
|
||||
use physics::PhysicsLayers;
|
||||
use rand::{Rng, thread_rng};
|
||||
use resources::{Drops, Resources};
|
||||
use state::GameSystemSet;
|
||||
|
||||
|
|
@ -96,6 +97,9 @@ pub struct Health {
|
|||
pub current: f32,
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct DeathAudio(pub Handle<AudioSource>);
|
||||
|
||||
impl Health {
|
||||
pub fn new(health: f32) -> Self {
|
||||
Self {
|
||||
|
|
@ -245,13 +249,26 @@ fn on_attack(
|
|||
fn on_die(
|
||||
trigger: Trigger<Died>,
|
||||
names: Query<&Name>,
|
||||
drops: Query<&Drops>,
|
||||
dying_query: Query<(&Drops, &GlobalTransform, Option<&DeathAudio>)>,
|
||||
mut resources: ResMut<Resources>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
if let Ok(drop) = drops.get(trigger.target()) {
|
||||
if let Ok((drop, gtf, opt_audio)) = dying_query.get(trigger.target()) {
|
||||
resources.0 = resources.0 + drop.0;
|
||||
if let Some(audio) = opt_audio {
|
||||
commands.spawn((
|
||||
AudioPlayer(audio.0.clone()),
|
||||
PlaybackSettings {
|
||||
mode: bevy::audio::PlaybackMode::Despawn,
|
||||
speed: thread_rng().gen_range(0.8..1.2),
|
||||
spatial: false,
|
||||
..default()
|
||||
},
|
||||
Transform::from_translation(gtf.translation()),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(mut ec) = commands.get_entity(trigger.target()) {
|
||||
info!(
|
||||
"{:?} killed {:?}!",
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ pub struct ProjectileLauncher {
|
|||
pub damage: f32,
|
||||
/// will set fields in the fire event to be defaults, responsiblity of the building to set them up
|
||||
pub custom_targeting: bool,
|
||||
pub shoot_sound: Handle<AudioSource>,
|
||||
}
|
||||
|
||||
impl ProjectileLauncher {
|
||||
|
|
@ -70,6 +71,7 @@ impl ProjectileLauncher {
|
|||
fire_offset: Vec3,
|
||||
lifetime: Duration,
|
||||
spread: f32,
|
||||
shoot_sound: Handle<AudioSource>,
|
||||
) -> Self {
|
||||
Self {
|
||||
fire_timer: Timer::new(fire_interval, TimerMode::Once),
|
||||
|
|
@ -78,6 +80,7 @@ impl ProjectileLauncher {
|
|||
fire_offset,
|
||||
lifetime,
|
||||
custom_targeting: false,
|
||||
shoot_sound: shoot_sound.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -142,6 +145,16 @@ fn fire_launcher(
|
|||
},
|
||||
[launcher_entity],
|
||||
);
|
||||
commands.spawn((
|
||||
AudioPlayer(launcher.shoot_sound.clone()),
|
||||
PlaybackSettings {
|
||||
mode: bevy::audio::PlaybackMode::Despawn,
|
||||
speed: thread_rng().gen_range(0.8..1.2),
|
||||
spatial: false,
|
||||
..default()
|
||||
},
|
||||
Transform::from_translation(gtf.translation()),
|
||||
));
|
||||
continue;
|
||||
}
|
||||
let Some((closest_enemy, enemy_pos)) = enemies
|
||||
|
|
@ -180,6 +193,16 @@ fn fire_launcher(
|
|||
},
|
||||
[launcher_entity],
|
||||
);
|
||||
commands.spawn((
|
||||
AudioPlayer(launcher.shoot_sound.clone()),
|
||||
PlaybackSettings {
|
||||
mode: bevy::audio::PlaybackMode::Despawn,
|
||||
speed: thread_rng().gen_range(0.8..1.2),
|
||||
spatial: false,
|
||||
..default()
|
||||
},
|
||||
Transform::from_translation(gtf.translation()),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
use avian3d::prelude::*;
|
||||
use bevy::prelude::*;
|
||||
use building::Core;
|
||||
use combat::{GaveDamage, Health, Team};
|
||||
use combat::{DeathAudio, GaveDamage, Health, Team};
|
||||
use combat_damagers::ContactDamage;
|
||||
use inhabitant::Inhabitant;
|
||||
use state::{BasePhaseState, GameSystemSet};
|
||||
|
|
@ -35,12 +35,14 @@ struct CoranthResources {
|
|||
material: Handle<StandardMaterial>,
|
||||
mesh: Handle<Mesh>,
|
||||
charge_timer: Timer,
|
||||
death_sound: Handle<AudioSource>,
|
||||
}
|
||||
|
||||
fn init(
|
||||
mut commands: Commands,
|
||||
mut meshes: ResMut<Assets<Mesh>>,
|
||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||
assets: Res<AssetServer>,
|
||||
) {
|
||||
commands.insert_resource(CoranthResources {
|
||||
material: materials.add(StandardMaterial {
|
||||
|
|
@ -51,6 +53,7 @@ fn init(
|
|||
}),
|
||||
mesh: meshes.add(Sphere::new(0.25)),
|
||||
charge_timer: Timer::from_seconds(1.5, TimerMode::Repeating),
|
||||
death_sound: assets.load("sounds/gasp1.ogg"),
|
||||
});
|
||||
}
|
||||
fn spawn(
|
||||
|
|
@ -69,6 +72,7 @@ fn spawn(
|
|||
MeshMaterial3d(res.material.clone()),
|
||||
MaxLinearSpeed(25.),
|
||||
Coranth,
|
||||
DeathAudio(res.death_sound.clone()),
|
||||
transform.clone(),
|
||||
Health::new(1.0 + phase as f32),
|
||||
ContactDamage::new(if phase < 8 { 4.0 } else { 5.0 }),
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
use avian3d::prelude::*;
|
||||
use bevy::prelude::*;
|
||||
use building::Core;
|
||||
use combat::{Defense, Health, Team};
|
||||
use combat::{DeathAudio, Defense, Health, Team};
|
||||
use combat_damagers::ContactDamage;
|
||||
use inhabitant::Inhabitant;
|
||||
use inhabitant_simbert::SpawnSimbert;
|
||||
|
|
@ -40,6 +40,7 @@ pub struct SpawnEndrake {
|
|||
struct EndrakeResources {
|
||||
material: Handle<StandardMaterial>,
|
||||
mesh: Handle<Mesh>,
|
||||
death_sound: Handle<AudioSource>,
|
||||
}
|
||||
|
||||
const BASE_RADIUS: f32 = 3.;
|
||||
|
|
@ -50,6 +51,7 @@ fn init(
|
|||
mut commands: Commands,
|
||||
mut meshes: ResMut<Assets<Mesh>>,
|
||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||
assets: Res<AssetServer>,
|
||||
) {
|
||||
commands.insert_resource(EndrakeResources {
|
||||
material: materials.add(StandardMaterial {
|
||||
|
|
@ -64,6 +66,7 @@ fn init(
|
|||
radius_bottom: BASE_RADIUS,
|
||||
height: HEIGHT,
|
||||
}),
|
||||
death_sound: assets.load("sounds/weird1.ogg"),
|
||||
});
|
||||
}
|
||||
fn spawn(
|
||||
|
|
@ -74,20 +77,23 @@ fn spawn(
|
|||
) {
|
||||
for SpawnEndrake { transform } in reader.read() {
|
||||
commands.spawn((
|
||||
RigidBody::Dynamic,
|
||||
Collider::cuboid(TOP_RADIUS * 2., HEIGHT, TOP_RADIUS * 2.),
|
||||
Mesh3d(res.mesh.clone()),
|
||||
MeshMaterial3d(res.material.clone()),
|
||||
MaxLinearSpeed(0.5),
|
||||
Mass(10.),
|
||||
Endrake {
|
||||
spawn_timer: Timer::from_seconds(2.0, TimerMode::Repeating),
|
||||
spawn_count: 10,
|
||||
},
|
||||
Drops(Quantity {
|
||||
souls: 50,
|
||||
bones: 25,
|
||||
}),
|
||||
(
|
||||
RigidBody::Dynamic,
|
||||
Collider::cuboid(TOP_RADIUS * 2., HEIGHT, TOP_RADIUS * 2.),
|
||||
Mesh3d(res.mesh.clone()),
|
||||
MeshMaterial3d(res.material.clone()),
|
||||
MaxLinearSpeed(0.5),
|
||||
Mass(10.),
|
||||
Endrake {
|
||||
spawn_timer: Timer::from_seconds(2.0, TimerMode::Repeating),
|
||||
spawn_count: 10,
|
||||
},
|
||||
Drops(Quantity {
|
||||
souls: 50,
|
||||
bones: 25,
|
||||
}),
|
||||
),
|
||||
DeathAudio(res.death_sound.clone()),
|
||||
transform.clone(),
|
||||
Health::new(2000.0 + 100. * phase.get().phase_count() as f32),
|
||||
Defense::new(5.),
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
use avian3d::prelude::*;
|
||||
use bevy::prelude::*;
|
||||
use building::Building;
|
||||
use combat::{GaveDamage, Health, Team};
|
||||
use combat::{DeathAudio, GaveDamage, Health, Team};
|
||||
use combat_damagers::ContactDamage;
|
||||
use inhabitant::Inhabitant;
|
||||
use resources::{Drops, Quantity};
|
||||
|
|
@ -38,12 +38,14 @@ struct SimbertResources {
|
|||
mesh: Handle<Mesh>,
|
||||
mega_material: Handle<StandardMaterial>,
|
||||
mega_scale: f32,
|
||||
death_sound: Handle<AudioSource>,
|
||||
}
|
||||
|
||||
fn init(
|
||||
mut commands: Commands,
|
||||
mut meshes: ResMut<Assets<Mesh>>,
|
||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||
assets: Res<AssetServer>,
|
||||
) {
|
||||
commands.insert_resource(SimbertResources {
|
||||
material: materials.add(StandardMaterial {
|
||||
|
|
@ -60,6 +62,7 @@ fn init(
|
|||
..default()
|
||||
}),
|
||||
mega_scale: 1.3,
|
||||
death_sound: assets.load("sounds/gasp3.ogg"),
|
||||
});
|
||||
}
|
||||
fn spawn(
|
||||
|
|
@ -93,6 +96,7 @@ fn spawn(
|
|||
Mesh3d(res.mesh.clone()),
|
||||
MeshMaterial3d(material),
|
||||
MaxLinearSpeed(25.),
|
||||
DeathAudio(res.death_sound.clone()),
|
||||
Simbert,
|
||||
drops,
|
||||
transform,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#![allow(clippy::type_complexity)]
|
||||
#![allow(clippy::too_many_arguments)]
|
||||
|
||||
use bevy::prelude::*;
|
||||
use bevy::{audio::Volume, prelude::*};
|
||||
use rand::{Rng, thread_rng};
|
||||
use state::AppState;
|
||||
|
||||
|
|
@ -21,6 +21,7 @@ impl Plugin for MusicPlugin {
|
|||
pub struct BackgroundMusicPlayer {
|
||||
menu_music: Vec<Handle<AudioSource>>,
|
||||
game_music: Vec<Handle<AudioSource>>,
|
||||
pub settings: PlaybackSettings,
|
||||
track_index: usize,
|
||||
}
|
||||
|
||||
|
|
@ -35,6 +36,7 @@ fn init(mut commands: Commands, assets: Res<AssetServer>) {
|
|||
assets.load("music/Egmont Overture.ogg"),
|
||||
assets.load("music/Ghost Dance.ogg"),
|
||||
],
|
||||
settings: PlaybackSettings::default().with_volume(Volume::Linear(0.25)),
|
||||
track_index: 0,
|
||||
});
|
||||
}
|
||||
|
|
@ -48,7 +50,10 @@ fn play_menu_music(
|
|||
commands
|
||||
.entity(player_entity)
|
||||
.remove::<AudioSink>()
|
||||
.insert(AudioPlayer(player.menu_music[player.track_index].clone()));
|
||||
.insert((
|
||||
AudioPlayer(player.menu_music[player.track_index].clone()),
|
||||
player.settings.clone(),
|
||||
));
|
||||
}
|
||||
|
||||
fn play_game_music(
|
||||
|
|
@ -60,7 +65,10 @@ fn play_game_music(
|
|||
commands
|
||||
.entity(player_entity)
|
||||
.remove::<AudioSink>()
|
||||
.insert(AudioPlayer(player.game_music[player.track_index].clone()));
|
||||
.insert((
|
||||
AudioPlayer(player.game_music[player.track_index].clone()),
|
||||
player.settings.clone(),
|
||||
));
|
||||
}
|
||||
|
||||
fn update_track(
|
||||
|
|
@ -88,6 +96,6 @@ fn update_track(
|
|||
commands
|
||||
.entity(entity)
|
||||
.remove::<AudioSink>()
|
||||
.insert(AudioPlayer(next_track));
|
||||
.insert((AudioPlayer(next_track), background_player.settings.clone()));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ edition = "2024"
|
|||
[dependencies]
|
||||
bevy = { workspace = true }
|
||||
bevy_egui = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
|
|
|||
|
|
@ -4,11 +4,48 @@
|
|||
|
||||
use bevy::prelude::*;
|
||||
use bevy_egui::EguiPlugin;
|
||||
use rand::{Rng, thread_rng};
|
||||
|
||||
pub struct UiPlugin;
|
||||
|
||||
impl Plugin for UiPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_plugins(EguiPlugin::default());
|
||||
app.add_plugins(EguiPlugin::default())
|
||||
.add_event::<PlayClickSound>()
|
||||
.add_systems(Update, play_click_sound)
|
||||
.add_systems(Startup, init);
|
||||
}
|
||||
}
|
||||
|
||||
fn init(assets: Res<AssetServer>, mut commands: Commands) {
|
||||
commands.insert_resource(UIResources {
|
||||
click_audio: assets.load("sounds/click1.ogg"),
|
||||
});
|
||||
}
|
||||
|
||||
#[derive(Resource)]
|
||||
struct UIResources {
|
||||
click_audio: Handle<AudioSource>,
|
||||
}
|
||||
|
||||
#[derive(Event)]
|
||||
pub struct PlayClickSound;
|
||||
|
||||
fn play_click_sound(
|
||||
mut reader: EventReader<PlayClickSound>,
|
||||
mut commands: Commands,
|
||||
res: Res<UIResources>,
|
||||
) {
|
||||
if reader.is_empty() {
|
||||
return;
|
||||
}
|
||||
reader.clear();
|
||||
commands.spawn((
|
||||
AudioPlayer(res.click_audio.clone()),
|
||||
PlaybackSettings {
|
||||
mode: bevy::audio::PlaybackMode::Despawn,
|
||||
speed: thread_rng().gen_range(0.9..1.1),
|
||||
..default()
|
||||
},
|
||||
));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ building_placement = { path = "../building_placement" }
|
|||
building_core = { path = "../building_core" }
|
||||
upgrade = { path = "../upgrade" }
|
||||
combat = { path = "../combat" }
|
||||
ui = { path = "../ui" }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ use resources::{
|
|||
AvailableWorkers, Cost, Quantity, ResourceDeposit, Resources, WorkedResourceDeposit,
|
||||
};
|
||||
use state::{BasePhaseState, CoreState, GameState, Phase};
|
||||
use ui::PlayClickSound;
|
||||
use ui_state::GameUIState;
|
||||
use upgrade::{UnlockUpgrade, Upgradable, Upgrade};
|
||||
|
||||
|
|
@ -80,6 +81,7 @@ fn plan_ui(
|
|||
mut contexts: EguiContexts,
|
||||
curr_phase: Res<State<BasePhaseState>>,
|
||||
mut next_phase: ResMut<NextState<BasePhaseState>>,
|
||||
mut writer: EventWriter<PlayClickSound>,
|
||||
) {
|
||||
let ctx = contexts.ctx_mut().unwrap();
|
||||
egui::Window::new("PlanUI")
|
||||
|
|
@ -92,6 +94,7 @@ fn plan_ui(
|
|||
.button(RichText::new("EXECUTE").size(VERY_LARGE_FONT_SIZE))
|
||||
.clicked()
|
||||
{
|
||||
writer.write(PlayClickSound);
|
||||
next_phase.set(BasePhaseState::Execute {
|
||||
phase: curr_phase.get().phase_count(),
|
||||
});
|
||||
|
|
@ -202,6 +205,7 @@ fn side_panel(
|
|||
)>,
|
||||
mut selected_preview_writer: EventWriter<SelectBuildingPreview>,
|
||||
mut select_writer: EventWriter<SelectEntity>,
|
||||
mut writer: EventWriter<PlayClickSound>,
|
||||
) {
|
||||
let ctx = contexts.ctx_mut().unwrap();
|
||||
egui::Window::new("Resources")
|
||||
|
|
@ -214,6 +218,7 @@ fn side_panel(
|
|||
if let Ok((selected, selected_name)) = selected.single() {
|
||||
if ui.button("x").clicked() {
|
||||
select_writer.write(SelectEntity(None));
|
||||
writer.write(PlayClickSound);
|
||||
}
|
||||
|
||||
ui.heading(selected_name.as_str());
|
||||
|
|
@ -246,6 +251,7 @@ fn side_panel(
|
|||
ui.add_enabled(false, egui::Button::new("Maximum workers reached"));
|
||||
} else {
|
||||
if ui.button("Add worker").clicked() {
|
||||
writer.write(PlayClickSound);
|
||||
available_workers.0 = available_workers.0.saturating_sub(1);
|
||||
if let Some(ref mut worked) = opt_worked {
|
||||
worked.workers = worked.workers.saturating_add(1);
|
||||
|
|
@ -264,6 +270,7 @@ fn side_panel(
|
|||
// remove
|
||||
if let Some(ref mut worked) = opt_worked {
|
||||
if ui.button("Remove worker").clicked() {
|
||||
writer.write(PlayClickSound);
|
||||
worked.workers = worked.workers.saturating_sub(1);
|
||||
available_workers.0 = available_workers.0.saturating_add(1);
|
||||
if worked.workers == 0 {
|
||||
|
|
@ -305,6 +312,7 @@ fn side_panel(
|
|||
RichText::new(upgrade_name.as_str()).size(LARGE_FONT_SIZE);
|
||||
if resources.0.can_buy(upgrade.cost) {
|
||||
if ui.button(button_text).clicked() {
|
||||
writer.write(PlayClickSound);
|
||||
resources.0 = resources.0 - upgrade.cost;
|
||||
commands.trigger_targets(
|
||||
UnlockUpgrade { building: selected },
|
||||
|
|
@ -341,6 +349,7 @@ fn side_panel(
|
|||
.clicked()
|
||||
{
|
||||
commands.entity(selected).despawn();
|
||||
writer.write(PlayClickSound);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
|
@ -361,6 +370,7 @@ fn side_panel(
|
|||
RichText::new(format!("{} - {}", name, cost.0.to_string())).size(FONT_SIZE);
|
||||
if resources.can_buy(cost.0) {
|
||||
if ui.button(button_text).clicked() {
|
||||
writer.write(PlayClickSound);
|
||||
selected_preview_writer.write(SelectBuildingPreview(Some(info.preview)));
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ bevy_egui = { workspace = true }
|
|||
state = { path = "../state" }
|
||||
combat = { path = "../combat" }
|
||||
music = { path = "../music" }
|
||||
ui = { path = "../ui" }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ use bevy_egui::{
|
|||
use combat::Difficulty;
|
||||
use music::BackgroundMusicPlayer;
|
||||
use state::AppState;
|
||||
use ui::PlayClickSound;
|
||||
|
||||
pub struct UiMenuPlugin;
|
||||
|
||||
|
|
@ -57,7 +58,11 @@ fn setup_menu(mut commands: Commands) {
|
|||
));
|
||||
}
|
||||
|
||||
fn main_screen(mut contexts: EguiContexts, mut next_screen: ResMut<NextState<MenuScreen>>) {
|
||||
fn main_screen(
|
||||
mut contexts: EguiContexts,
|
||||
mut next_screen: ResMut<NextState<MenuScreen>>,
|
||||
mut writer: EventWriter<PlayClickSound>,
|
||||
) {
|
||||
let ctx = contexts.ctx_mut().unwrap();
|
||||
egui::Window::new("Title")
|
||||
.resizable(false)
|
||||
|
|
@ -81,6 +86,7 @@ fn main_screen(mut contexts: EguiContexts, mut next_screen: ResMut<NextState<Men
|
|||
.clicked()
|
||||
{
|
||||
next_screen.set(MenuScreen::Difficulty);
|
||||
writer.write(PlayClickSound);
|
||||
}
|
||||
});
|
||||
ui.centered_and_justified(|ui| {
|
||||
|
|
@ -89,6 +95,7 @@ fn main_screen(mut contexts: EguiContexts, mut next_screen: ResMut<NextState<Men
|
|||
.clicked()
|
||||
{
|
||||
next_screen.set(MenuScreen::Info);
|
||||
writer.write(PlayClickSound);
|
||||
}
|
||||
});
|
||||
ui.centered_and_justified(|ui| {
|
||||
|
|
@ -97,6 +104,7 @@ fn main_screen(mut contexts: EguiContexts, mut next_screen: ResMut<NextState<Men
|
|||
.clicked()
|
||||
{
|
||||
next_screen.set(MenuScreen::Settings);
|
||||
writer.write(PlayClickSound);
|
||||
}
|
||||
});
|
||||
ui.centered_and_justified(|ui| {
|
||||
|
|
@ -105,6 +113,7 @@ fn main_screen(mut contexts: EguiContexts, mut next_screen: ResMut<NextState<Men
|
|||
.clicked()
|
||||
{
|
||||
next_screen.set(MenuScreen::Credits);
|
||||
writer.write(PlayClickSound);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
@ -115,6 +124,7 @@ fn difficulty_screen(
|
|||
mut next_screen: ResMut<NextState<MenuScreen>>,
|
||||
mut next_state: ResMut<NextState<AppState>>,
|
||||
mut difficulty: ResMut<Difficulty>,
|
||||
mut writer: EventWriter<PlayClickSound>,
|
||||
) {
|
||||
let ctx = contexts.ctx_mut().unwrap();
|
||||
egui::Window::new("DifficultyScreen")
|
||||
|
|
@ -131,6 +141,7 @@ fn difficulty_screen(
|
|||
{
|
||||
*difficulty = Difficulty::Standard;
|
||||
next_state.set(AppState::Game);
|
||||
writer.write(PlayClickSound);
|
||||
}
|
||||
columns[1].label("The intended experience, which is quite difficult.")
|
||||
});
|
||||
|
|
@ -145,6 +156,7 @@ fn difficulty_screen(
|
|||
{
|
||||
*difficulty = Difficulty::Chill;
|
||||
next_state.set(AppState::Game);
|
||||
writer.write(PlayClickSound);
|
||||
}
|
||||
columns[1].label(
|
||||
"Enemies deal significantly less damage. Good to chill and check out the game!",
|
||||
|
|
@ -157,6 +169,7 @@ fn difficulty_screen(
|
|||
{
|
||||
*difficulty = Difficulty::Casual;
|
||||
next_state.set(AppState::Game);
|
||||
writer.write(PlayClickSound);
|
||||
}
|
||||
columns[1].label(
|
||||
"Enemies deal less damage. Good for players who don't want to sweat as much.",
|
||||
|
|
@ -169,6 +182,7 @@ fn difficulty_screen(
|
|||
{
|
||||
*difficulty = Difficulty::Intense;
|
||||
next_state.set(AppState::Game);
|
||||
writer.write(PlayClickSound);
|
||||
}
|
||||
columns[1].label("Enemies deal more damage. Significantly harder.")
|
||||
});
|
||||
|
|
@ -184,11 +198,16 @@ fn difficulty_screen(
|
|||
.clicked()
|
||||
{
|
||||
next_screen.set(MenuScreen::Main);
|
||||
writer.write(PlayClickSound);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn info_screen(mut contexts: EguiContexts, mut next_screen: ResMut<NextState<MenuScreen>>) {
|
||||
fn info_screen(
|
||||
mut contexts: EguiContexts,
|
||||
mut next_screen: ResMut<NextState<MenuScreen>>,
|
||||
mut writer: EventWriter<PlayClickSound>,
|
||||
) {
|
||||
let ctx = contexts.ctx_mut().unwrap();
|
||||
egui::Window::new("InfoScreen")
|
||||
.resizable(false)
|
||||
|
|
@ -215,6 +234,7 @@ fn info_screen(mut contexts: EguiContexts, mut next_screen: ResMut<NextState<Men
|
|||
.clicked()
|
||||
{
|
||||
next_screen.set(MenuScreen::Main);
|
||||
writer.write(PlayClickSound);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -223,7 +243,8 @@ fn settings_screen(
|
|||
mut contexts: EguiContexts,
|
||||
mut next_screen: ResMut<NextState<MenuScreen>>,
|
||||
mut global_volume: ResMut<GlobalVolume>,
|
||||
mut music_query: Query<&mut AudioSink, With<BackgroundMusicPlayer>>,
|
||||
mut music_query: Query<(&mut AudioSink, &BackgroundMusicPlayer)>,
|
||||
mut writer: EventWriter<PlayClickSound>,
|
||||
mut volume: Local<f32>,
|
||||
mut init: Local<bool>,
|
||||
) {
|
||||
|
|
@ -242,8 +263,9 @@ fn settings_screen(
|
|||
ui.label(RichText::new("Volume").size(FONT_SIZE));
|
||||
ui.add(egui::Slider::new(&mut *volume, 0.0..=100.));
|
||||
global_volume.volume = Volume::Linear(*volume / 100.);
|
||||
if let Ok(mut sink) = music_query.single_mut() {
|
||||
sink.set_volume(Volume::Linear(*volume / 100.));
|
||||
if let Ok((mut sink, player)) = music_query.single_mut() {
|
||||
let player_volume = player.settings.volume.to_linear();
|
||||
sink.set_volume(Volume::Linear(*volume / 100. * player_volume));
|
||||
}
|
||||
});
|
||||
egui::Window::new("SettingsBack")
|
||||
|
|
@ -257,11 +279,16 @@ fn settings_screen(
|
|||
.clicked()
|
||||
{
|
||||
next_screen.set(MenuScreen::Main);
|
||||
writer.write(PlayClickSound);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn credits_screen(mut contexts: EguiContexts, mut next_screen: ResMut<NextState<MenuScreen>>) {
|
||||
fn credits_screen(
|
||||
mut contexts: EguiContexts,
|
||||
mut writer: EventWriter<PlayClickSound>,
|
||||
mut next_screen: ResMut<NextState<MenuScreen>>,
|
||||
) {
|
||||
let ctx = contexts.ctx_mut().unwrap();
|
||||
egui::Window::new("SettingsScreen")
|
||||
.resizable(false)
|
||||
|
|
@ -325,6 +352,7 @@ fn credits_screen(mut contexts: EguiContexts, mut next_screen: ResMut<NextState<
|
|||
.clicked()
|
||||
{
|
||||
next_screen.set(MenuScreen::Main);
|
||||
writer.write(PlayClickSound);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
2
todo.txt
2
todo.txt
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
--- VERY IMPORTANT ---
|
||||
- sound
|
||||
- music
|
||||
x music
|
||||
x limit workers per resource deposit
|
||||
x main menu
|
||||
x improve enemy AI
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue