WIP
This commit is contained in:
1633
Cargo.lock
generated
1633
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
12
Cargo.toml
12
Cargo.toml
@@ -4,15 +4,15 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
itertools = "0.10.5"
|
itertools = "0.11.0"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
bevy_editor_pls = "0.3.0"
|
bevy_editor_pls = { git = "https://github.com/jakobhellermann/bevy_editor_pls" }
|
||||||
bevy_tweening = "0.7.0"
|
bevy_tweening = "0.8.0"
|
||||||
leafwing-input-manager = "0.9.0"
|
leafwing-input-manager = "0.10.0"
|
||||||
bevy_asset_loader = "0.15.0"
|
bevy_asset_loader = "0.17.0"
|
||||||
|
|
||||||
[dependencies.bevy]
|
[dependencies.bevy]
|
||||||
version = "0.10"
|
version = "0.11"
|
||||||
features = ["wayland", "wav"]
|
features = ["wayland", "wav"]
|
||||||
|
|
||||||
# [profile.dev.package."*"]
|
# [profile.dev.package."*"]
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ mod tile_light;
|
|||||||
use crate::grid;
|
use crate::grid;
|
||||||
use bevy::{
|
use bevy::{
|
||||||
prelude::*,
|
prelude::*,
|
||||||
reflect::TypeUuid,
|
reflect::{TypeUuid, TypePath},
|
||||||
render::{
|
render::{
|
||||||
render_resource::{encase, AsBindGroup, OwnedBindingResource, ShaderRef, ShaderType},
|
render_resource::{encase, AsBindGroup, OwnedBindingResource, ShaderRef, ShaderType},
|
||||||
renderer::RenderQueue,
|
renderer::RenderQueue,
|
||||||
@@ -19,18 +19,18 @@ pub struct CanvasPlugin;
|
|||||||
|
|
||||||
impl Plugin for CanvasPlugin {
|
impl Plugin for CanvasPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_plugin(Material2dPlugin::<CanvasMaterial>::default())
|
app.add_plugins(Material2dPlugin::<CanvasMaterial>::default())
|
||||||
.add_startup_system(spawn_canvas);
|
.add_systems(Startup, spawn_canvas);
|
||||||
|
|
||||||
app.sub_app_mut(RenderApp)
|
app.sub_app_mut(RenderApp)
|
||||||
.add_system(extract_tile_lights.in_schedule(ExtractSchedule))
|
.add_systems(ExtractSchedule, extract_tile_lights)
|
||||||
.add_system(prepare_canvas_material.in_set(RenderSet::Prepare));
|
.add_systems(Update, prepare_canvas_material.in_set(RenderSet::Prepare));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const CANVAS_COLOR: Color = Color::rgb(0.05, 0.05, 0.05);
|
const CANVAS_COLOR: Color = Color::rgb(0.05, 0.05, 0.05);
|
||||||
|
|
||||||
#[derive(AsBindGroup, TypeUuid, Clone)]
|
#[derive(AsBindGroup, TypeUuid, TypePath, Clone)]
|
||||||
#[uuid = "24f83f6e-e52d-41a6-bf1d-0e46e57a4995"]
|
#[uuid = "24f83f6e-e52d-41a6-bf1d-0e46e57a4995"]
|
||||||
struct CanvasMaterial {
|
struct CanvasMaterial {
|
||||||
#[uniform(0)]
|
#[uniform(0)]
|
||||||
|
|||||||
14
src/fruit.rs
14
src/fruit.rs
@@ -12,13 +12,19 @@ pub struct FruitPlugin;
|
|||||||
impl Plugin for FruitPlugin {
|
impl Plugin for FruitPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_event::<EatenEvent>()
|
app.add_event::<EatenEvent>()
|
||||||
.add_startup_system(spawn_fruit_system)
|
.add_systems(Startup, spawn_fruit_system)
|
||||||
.add_system(eat_fruit_system.in_schedule(CoreSchedule::FixedUpdate))
|
.add_systems(FixedUpdate, eat_fruit_system)
|
||||||
.add_system(despawn_fruit_system)
|
.add_systems(
|
||||||
.add_system(spawn_fruit_system.run_if(eaten_event_sent));
|
Update,
|
||||||
|
(
|
||||||
|
despawn_fruit_system,
|
||||||
|
spawn_fruit_system.run_if(eaten_event_sent),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Event)]
|
||||||
pub struct EatenEvent(Option<Entity>);
|
pub struct EatenEvent(Option<Entity>);
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
|
|||||||
87
src/main.rs
87
src/main.rs
@@ -2,6 +2,7 @@ use crate::{
|
|||||||
canvas::CanvasPlugin,
|
canvas::CanvasPlugin,
|
||||||
fruit::FruitPlugin,
|
fruit::FruitPlugin,
|
||||||
grid::{SEGMENT_SIZE, SIZE},
|
grid::{SEGMENT_SIZE, SIZE},
|
||||||
|
level::{LevelPlugin, LevelState},
|
||||||
snake::SnakePlugin,
|
snake::SnakePlugin,
|
||||||
ui::UiPlugin,
|
ui::UiPlugin,
|
||||||
};
|
};
|
||||||
@@ -17,6 +18,7 @@ mod audio;
|
|||||||
mod canvas;
|
mod canvas;
|
||||||
mod fruit;
|
mod fruit;
|
||||||
mod grid;
|
mod grid;
|
||||||
|
mod level;
|
||||||
mod snake;
|
mod snake;
|
||||||
mod ui;
|
mod ui;
|
||||||
|
|
||||||
@@ -25,23 +27,70 @@ const WINDOW_WIDTH: f32 = WINDOW_HEIGHT * ASPECT_RATIO;
|
|||||||
const WINDOW_HEIGHT: f32 = 720.;
|
const WINDOW_HEIGHT: f32 = 720.;
|
||||||
const TICK_PERIOD: Duration = Duration::from_millis(125);
|
const TICK_PERIOD: Duration = Duration::from_millis(125);
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default, States)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||||
enum GameState {
|
enum AppState {
|
||||||
#[default]
|
MainMenu,
|
||||||
Begin,
|
InGame(LevelState),
|
||||||
InGame,
|
}
|
||||||
End,
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct AppStateIter {
|
||||||
|
current: Option<AppState>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for AppStateIter {
|
||||||
|
type Item = AppState;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
let next_state = match self.current {
|
||||||
|
None => Some(AppState::MainMenu),
|
||||||
|
Some(AppState::MainMenu) => Some(AppState::InGame(LevelState::Begin)),
|
||||||
|
Some(AppState::InGame(level_state)) => match level_state {
|
||||||
|
LevelState::Begin => Some(AppState::InGame(LevelState::InGame)),
|
||||||
|
LevelState::InGame => Some(AppState::InGame(LevelState::End)),
|
||||||
|
LevelState::End => None,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(next_state) = next_state {
|
||||||
|
self.current = Some(next_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
next_state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for AppState {
|
||||||
|
fn default() -> Self {
|
||||||
|
if cfg!(debug_assertions) {
|
||||||
|
Self::InGame(LevelState::Begin)
|
||||||
|
} else {
|
||||||
|
Self::MainMenu
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl States for AppState {
|
||||||
|
type Iter = AppStateIter;
|
||||||
|
|
||||||
|
fn variants() -> Self::Iter {
|
||||||
|
AppStateIter::default()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Resource)]
|
#[derive(Resource)]
|
||||||
struct Score(u32);
|
struct Score(u32);
|
||||||
|
|
||||||
|
#[derive(Resource)]
|
||||||
|
struct Level(u32);
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut app = App::new();
|
let mut app = App::new();
|
||||||
|
|
||||||
app.insert_resource(ClearColor(Color::BLACK))
|
app.insert_resource(ClearColor(Color::BLACK))
|
||||||
.insert_resource(FixedTime::new(TICK_PERIOD))
|
.insert_resource(FixedTime::new(TICK_PERIOD))
|
||||||
.insert_resource(Score(0))
|
.insert_resource(Score(0))
|
||||||
|
.insert_resource(Level(0))
|
||||||
.add_plugins(DefaultPlugins.set(WindowPlugin {
|
.add_plugins(DefaultPlugins.set(WindowPlugin {
|
||||||
primary_window: Some(Window {
|
primary_window: Some(Window {
|
||||||
title: "Bevy-Snake".into(),
|
title: "Bevy-Snake".into(),
|
||||||
@@ -52,26 +101,28 @@ fn main() {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
}))
|
}))
|
||||||
.init_collection::<audio::Assets>()
|
.init_collection::<audio::Assets>()
|
||||||
.add_state::<GameState>()
|
.add_state::<AppState>()
|
||||||
.add_plugin(TweeningPlugin)
|
.add_plugins((
|
||||||
.add_plugin(SnakePlugin)
|
TweeningPlugin,
|
||||||
.add_plugin(FruitPlugin)
|
SnakePlugin,
|
||||||
.add_plugin(CanvasPlugin)
|
FruitPlugin,
|
||||||
.add_plugin(UiPlugin)
|
CanvasPlugin,
|
||||||
.add_startup_system(setup_system)
|
UiPlugin,
|
||||||
.add_system(update_score_system);
|
LevelPlugin,
|
||||||
|
))
|
||||||
|
.add_systems(Startup, setup_camera_system)
|
||||||
|
.add_systems(Update, update_score_system);
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
{
|
{
|
||||||
app.add_plugin(EditorPlugin)
|
app.add_plugins(EditorPlugin::new())
|
||||||
.add_system(bevy::window::close_on_esc)
|
.add_systems(Update, (bevy::window::close_on_esc, pause_system));
|
||||||
.add_system(pause_system);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
app.run();
|
app.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_system(mut commands: Commands) {
|
fn setup_camera_system(mut commands: Commands) {
|
||||||
let grid_dimensions = f32::from(SIZE) * SEGMENT_SIZE * 1.2;
|
let grid_dimensions = f32::from(SIZE) * SEGMENT_SIZE * 1.2;
|
||||||
|
|
||||||
commands
|
commands
|
||||||
|
|||||||
95
src/snake.rs
95
src/snake.rs
@@ -3,7 +3,7 @@ mod bulge;
|
|||||||
mod direction;
|
mod direction;
|
||||||
mod movement;
|
mod movement;
|
||||||
|
|
||||||
use crate::{audio, fruit, grid, GameState};
|
use crate::{audio, fruit, grid, level::LevelState, AppState};
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use direction::Direction;
|
use direction::Direction;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
@@ -20,55 +20,71 @@ pub struct SnakePlugin;
|
|||||||
|
|
||||||
impl Plugin for SnakePlugin {
|
impl Plugin for SnakePlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.configure_set(SystemSet::Movement.after(SystemSet::CollisionDetection));
|
app.configure_set(
|
||||||
|
Update,
|
||||||
|
SystemSet::Movement.after(SystemSet::CollisionDetection),
|
||||||
|
);
|
||||||
|
|
||||||
app.add_plugin(InputManagerPlugin::<direction::Direction>::default())
|
app.add_plugins(InputManagerPlugin::<direction::Direction>::default())
|
||||||
.add_event::<AddTailEvent>()
|
.add_event::<AddTailEvent>()
|
||||||
.insert_resource(bulge::PropagationTimer::default())
|
.insert_resource(bulge::PropagationTimer::default())
|
||||||
.add_startup_system(setup_snake_system)
|
|
||||||
.add_systems(
|
.add_systems(
|
||||||
|
OnEnter(AppState::InGame(LevelState::Begin)),
|
||||||
|
setup_snake_system,
|
||||||
|
)
|
||||||
|
.add_systems(
|
||||||
|
FixedUpdate,
|
||||||
(
|
(
|
||||||
segments_movement_system
|
segments_movement_system
|
||||||
.in_set(SystemSet::Movement)
|
.in_set(SystemSet::Movement)
|
||||||
.run_if(in_state(GameState::InGame))
|
.run_if(in_state(AppState::InGame(LevelState::InGame)))
|
||||||
.after(SystemSet::DirectionFlush),
|
.after(SystemSet::DirectionFlush),
|
||||||
direction::apply_direction_system
|
direction::apply_direction_system
|
||||||
.run_if(in_state(GameState::InGame))
|
.run_if(in_state(AppState::InGame(LevelState::InGame)))
|
||||||
.before(SystemSet::DirectionFlush),
|
.before(SystemSet::DirectionFlush),
|
||||||
apply_system_buffers
|
apply_deferred
|
||||||
.in_set(SystemSet::DirectionFlush)
|
.in_set(SystemSet::DirectionFlush)
|
||||||
.run_if(in_state(GameState::InGame)),
|
.run_if(in_state(AppState::InGame(LevelState::InGame))),
|
||||||
collision_system
|
collision_system
|
||||||
.in_set(SystemSet::CollisionDetection)
|
.in_set(SystemSet::CollisionDetection)
|
||||||
.run_if(in_state(GameState::InGame))
|
.run_if(in_state(AppState::InGame(LevelState::InGame)))
|
||||||
.after(SystemSet::DirectionFlush),
|
.after(SystemSet::DirectionFlush),
|
||||||
game_over_system
|
game_over_system
|
||||||
.in_set(SystemSet::CollisionDetection)
|
.in_set(SystemSet::CollisionDetection)
|
||||||
.run_if(in_state(GameState::InGame))
|
.run_if(in_state(AppState::InGame(LevelState::InGame)))
|
||||||
.after(collision_system)
|
.after(collision_system)
|
||||||
.run_if(about_to_collide),
|
.run_if(about_to_collide),
|
||||||
)
|
),
|
||||||
.in_schedule(CoreSchedule::FixedUpdate),
|
|
||||||
)
|
)
|
||||||
.add_systems((
|
.add_systems(
|
||||||
grid_transform_system.run_if(in_state(GameState::InGame)),
|
Update,
|
||||||
direction::start_game_system.run_if(in_state(GameState::Begin)),
|
(
|
||||||
direction::change_direction_system,
|
grid_transform_system.run_if(in_state(AppState::InGame(LevelState::InGame))),
|
||||||
bulge::add_bulge_system,
|
direction::start_game_system
|
||||||
bulge::propagate_bulge_system,
|
.run_if(in_state(AppState::InGame(LevelState::Begin))),
|
||||||
bulge::animate_bulge_system,
|
direction::change_direction_system.run_if(
|
||||||
add_tail_system,
|
in_state(AppState::InGame(LevelState::Begin))
|
||||||
eaten_event_system,
|
.or_else(in_state(AppState::InGame(LevelState::InGame))),
|
||||||
))
|
),
|
||||||
.add_systems((
|
bulge::add_bulge_system,
|
||||||
collision_sound_system
|
bulge::propagate_bulge_system,
|
||||||
.run_if(in_state(GameState::InGame))
|
bulge::animate_bulge_system,
|
||||||
.run_if(about_to_collide),
|
add_tail_system,
|
||||||
blip_sound_system.run_if(fruit::eaten_event_sent),
|
eaten_event_system,
|
||||||
));
|
),
|
||||||
|
)
|
||||||
|
.add_systems(
|
||||||
|
Update,
|
||||||
|
(
|
||||||
|
collision_sound_system
|
||||||
|
.run_if(in_state(AppState::InGame(LevelState::InGame)))
|
||||||
|
.run_if(about_to_collide),
|
||||||
|
blip_sound_system.run_if(fruit::eaten_event_sent),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
app.add_system(debug::add_tail);
|
app.add_systems(Update, debug::add_tail);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,8 +107,6 @@ struct SnakeBundle {
|
|||||||
snake: Snake,
|
snake: Snake,
|
||||||
collision: Collision,
|
collision: Collision,
|
||||||
segments: Segments,
|
segments: Segments,
|
||||||
|
|
||||||
#[bundle]
|
|
||||||
spatial_bundle: SpatialBundle,
|
spatial_bundle: SpatialBundle,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,6 +115,7 @@ struct Collision {
|
|||||||
about_to_collide: bool,
|
about_to_collide: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Event)]
|
||||||
pub struct AddTailEvent;
|
pub struct AddTailEvent;
|
||||||
|
|
||||||
fn create_snake_segment(
|
fn create_snake_segment(
|
||||||
@@ -246,21 +261,27 @@ fn about_to_collide(query: Query<&Collision, With<Snake>>) -> bool {
|
|||||||
query.get_single().unwrap().about_to_collide
|
query.get_single().unwrap().about_to_collide
|
||||||
}
|
}
|
||||||
|
|
||||||
fn game_over_system(mut next_state: ResMut<NextState<GameState>>) {
|
fn game_over_system(mut next_state: ResMut<NextState<AppState>>) {
|
||||||
next_state.set(GameState::End);
|
next_state.set(AppState::InGame(LevelState::End));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collision_sound_system(audio: Res<Audio>, audio_assets: Res<audio::Assets>) {
|
fn collision_sound_system(mut commands: Commands, audio_assets: Res<audio::Assets>) {
|
||||||
audio.play(audio_assets.collision.clone());
|
commands.spawn(AudioBundle {
|
||||||
|
source: audio_assets.collision.clone(),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn blip_sound_system(
|
fn blip_sound_system(
|
||||||
audio: Res<Audio>,
|
mut commands: Commands,
|
||||||
audio_assets: Res<audio::Assets>,
|
audio_assets: Res<audio::Assets>,
|
||||||
mut eaten_event_reader: EventReader<fruit::EatenEvent>,
|
mut eaten_event_reader: EventReader<fruit::EatenEvent>,
|
||||||
) {
|
) {
|
||||||
for _ in eaten_event_reader.iter() {
|
for _ in eaten_event_reader.iter() {
|
||||||
audio.play(audio_assets.blip.clone());
|
commands.spawn(AudioBundle {
|
||||||
|
source: audio_assets.blip.clone(),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use super::Snake;
|
use super::Snake;
|
||||||
use crate::{audio, GameState};
|
use crate::{audio, level::LevelState, AppState};
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use leafwing_input_manager::prelude::*;
|
use leafwing_input_manager::prelude::*;
|
||||||
|
|
||||||
#[derive(Actionlike, Component, Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Actionlike, Reflect, Component, Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
pub(super) enum Direction {
|
pub(super) enum Direction {
|
||||||
Up,
|
Up,
|
||||||
Down,
|
Down,
|
||||||
@@ -13,35 +13,34 @@ pub(super) enum Direction {
|
|||||||
|
|
||||||
#[derive(Component, Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Component, Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
#[component(storage = "SparseSet")]
|
#[component(storage = "SparseSet")]
|
||||||
pub(super) struct NewDirection(Direction);
|
pub(super) struct NextDirection(Direction);
|
||||||
|
|
||||||
pub(super) fn start_game_system(
|
pub(super) fn start_game_system(
|
||||||
query: Query<&ActionState<Direction>>,
|
query: Query<&ActionState<Direction>>,
|
||||||
mut next_state: ResMut<NextState<GameState>>,
|
mut next_state: ResMut<NextState<AppState>>,
|
||||||
) {
|
) {
|
||||||
let action_state = query.single();
|
let action_state = query.single();
|
||||||
|
|
||||||
if !action_state.get_just_pressed().is_empty() {
|
if !action_state.get_just_pressed().is_empty() {
|
||||||
next_state.set(GameState::InGame);
|
next_state.set(AppState::InGame(LevelState::InGame));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn apply_direction_system(
|
pub(super) fn apply_direction_system(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut query: Query<(Entity, &NewDirection), With<Snake>>,
|
mut query: Query<(Entity, &NextDirection), With<Snake>>,
|
||||||
) {
|
) {
|
||||||
for (snake, new_direction) in query.iter_mut() {
|
for (snake, new_direction) in query.iter_mut() {
|
||||||
commands
|
commands
|
||||||
.entity(snake)
|
.entity(snake)
|
||||||
.insert(new_direction.0)
|
.insert(new_direction.0)
|
||||||
.remove::<NewDirection>();
|
.remove::<NextDirection>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn change_direction_system(
|
pub(super) fn change_direction_system(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut query: Query<(Entity, &ActionState<Direction>, Option<&Direction>), With<Snake>>,
|
mut query: Query<(Entity, &ActionState<Direction>, Option<&Direction>), With<Snake>>,
|
||||||
audio: Res<Audio>,
|
|
||||||
audio_assets: Res<audio::Assets>,
|
audio_assets: Res<audio::Assets>,
|
||||||
) {
|
) {
|
||||||
let (snake, action_state, direction) = query.single_mut();
|
let (snake, action_state, direction) = query.single_mut();
|
||||||
@@ -62,7 +61,10 @@ pub(super) fn change_direction_system(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
commands.entity(snake).insert(NewDirection(new_direction));
|
commands.entity(snake).insert(NextDirection(new_direction));
|
||||||
audio.play(audio_assets.tick.clone());
|
commands.spawn(AudioBundle {
|
||||||
|
source: audio_assets.tick.clone(),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
mod score;
|
mod status;
|
||||||
|
|
||||||
pub struct UiPlugin;
|
pub struct UiPlugin;
|
||||||
|
|
||||||
impl Plugin for UiPlugin {
|
impl Plugin for UiPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_systems((
|
app.add_systems(Startup, status::spawn_status_text)
|
||||||
score::spawn_score_text.on_startup(),
|
.add_systems(Update, status::update_status_text);
|
||||||
score::update_score_text,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,45 +0,0 @@
|
|||||||
use crate::Score;
|
|
||||||
use bevy::prelude::*;
|
|
||||||
|
|
||||||
#[derive(Component)]
|
|
||||||
pub(super) struct ScoreText;
|
|
||||||
|
|
||||||
pub(super) fn spawn_score_text(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|
||||||
let font = asset_server.load("fonts/Audiowide-Regular.ttf");
|
|
||||||
|
|
||||||
commands.spawn((
|
|
||||||
ScoreText,
|
|
||||||
TextBundle::from_sections([
|
|
||||||
TextSection::new(
|
|
||||||
"Score: ",
|
|
||||||
TextStyle {
|
|
||||||
font: font.clone(),
|
|
||||||
font_size: 32.0,
|
|
||||||
color: Color::WHITE,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
TextSection::from_style(TextStyle {
|
|
||||||
font: font,
|
|
||||||
font_size: 32.0,
|
|
||||||
color: Color::WHITE,
|
|
||||||
}),
|
|
||||||
])
|
|
||||||
.with_style(Style {
|
|
||||||
position_type: PositionType::Absolute,
|
|
||||||
position: UiRect {
|
|
||||||
left: Val::Px(10.0),
|
|
||||||
bottom: Val::Px(10.0),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
..Default::default()
|
|
||||||
}),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn update_score_text(mut query: Query<&mut Text, With<ScoreText>>, score: Res<Score>) {
|
|
||||||
let score = score.0;
|
|
||||||
|
|
||||||
for mut text in query.iter_mut() {
|
|
||||||
text.sections[1].value = format!("{score}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user