Skip to content

Commit

Permalink
feat: entities following path 🛣️
Browse files Browse the repository at this point in the history
yaaaaay finally, it was a mess to get set up with every possibility and
not just for the best path, but it covers a lot of variants now,
specially when building/rebuilding new paths. i am sure it can be very
improved upon but for this game jam it is more than enough
  • Loading branch information
eerii committed Dec 4, 2023
1 parent 53921fa commit 836e0f5
Show file tree
Hide file tree
Showing 5 changed files with 196 additions and 68 deletions.
4 changes: 0 additions & 4 deletions src/game.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@ use bevy::{prelude::*, render::view::RenderLayers};

use crate::GameState;

// TODO: Spawn entities, follow pathfinding
// TODO: Collisions between entities (traffic)
// TODO: Multiple spawn points

pub struct CharonPlugin;

impl Plugin for CharonPlugin {
Expand Down
4 changes: 2 additions & 2 deletions src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use bevy::{
use bevy_persistent::Persistent;
use serde::{Deserialize, Serialize};

use crate::config::Keybinds;
use crate::{config::Keybinds, game::GameCam};

// TODO: Mouse movement and gamepad axis

Expand Down Expand Up @@ -123,7 +123,7 @@ fn clear_input(mut input: ResMut<Input<Bind>>) {
}

fn handle_mouse_moved(
camera: Query<(&GlobalTransform, &Camera)>, // TODO: Create game camera and filter it here
camera: Query<(&GlobalTransform, &Camera), With<GameCam>>,
mut events: EventReader<CursorMoved>,
mut mouse: ResMut<MousePosition>,
) {
Expand Down
2 changes: 0 additions & 2 deletions src/menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,8 +339,6 @@ fn layout_keybinds(mut cmd: Commands, node: Entity, style: &UIStyle, keybinds: &
node.with_children(|parent| {
UIText::new(style, "Keybinds").with_title().add(parent);

// TODO: Scrollable section (Requires #8104 to be merged in 0.13)

for (i, value) in keybinds.iter_fields().enumerate() {
let field_name = keybinds.name_at(i).unwrap();
if let Some(value) = value.downcast_ref::<Vec<Bind>>() {
Expand Down
98 changes: 80 additions & 18 deletions src/spirits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use bevy_ecs_tilemap::prelude::*;

use crate::{
load::GameAssets,
tilemap::{get_neighbours, pos_to_tile, tile_to_pos, PathTile, StartTile},
tilemap::{get_neighbours, pos_to_tile, tile_to_pos, EndTile, PathTile, StartTile},
GameState,
};

Expand All @@ -17,7 +17,10 @@ impl Plugin for SpiritPlugin {
fn build(&self, app: &mut App) {
app.insert_resource(SpawnTimer::default())
.insert_resource(MoveTimer::default())
.add_systems(Update, move_spirit.run_if(in_state(GameState::Play)));
.add_systems(
Update,
(spawn_spirit, move_spirit).run_if(in_state(GameState::Play)),
);
}
}

Expand All @@ -39,22 +42,24 @@ struct MoveTimer(Timer);

impl Default for MoveTimer {
fn default() -> Self {
Self(Timer::from_seconds(1.0, TimerMode::Repeating))
Self(Timer::from_seconds(0.5, TimerMode::Repeating))
}
}

// ··········
// Components
// ··········

#[derive(Component)]
pub struct Spirit;
#[derive(Component, Default)]
pub struct Spirit {
prev: Option<TilePos>,
}

// ·······
// Systems
// ·······

fn _spawn_spirit(
fn spawn_spirit(
mut cmd: Commands,
mut timer: ResMut<SpawnTimer>,
time: Res<Time>,
Expand All @@ -80,18 +85,20 @@ fn _spawn_spirit(
transform: Transform::from_translation(pos).with_scale(Vec3::splat(0.3)),
..default()
},
Spirit,
Spirit::default(),
));
}
}
}
}

fn move_spirit(
mut cmd: Commands,
mut timer: ResMut<MoveTimer>,
time: Res<Time>,
mut spirit: Query<&mut Transform, With<Spirit>>,
paths: Query<&TilePos, With<PathTile>>,
mut spirit: Query<(Entity, &mut Transform, &mut Spirit)>,
paths: Query<(&TilePos, &PathTile)>,
end: Query<Entity, With<EndTile>>,
tilemap: Query<
(
&TilemapSize,
Expand All @@ -105,25 +112,80 @@ fn move_spirit(
) {
if timer.0.tick(time.delta()).just_finished() {
if let Ok((map_size, grid_size, map_type, storage, map_trans)) = tilemap.get_single() {
for mut trans in spirit.iter_mut() {
for (spirit_entity, mut trans, mut spirit) in spirit.iter_mut() {
if let Some(tile_pos) = pos_to_tile(
&trans.translation.xy(),
map_size,
grid_size,
map_type,
map_trans,
) {
for neighbour in get_neighbours(&tile_pos, map_size) {
if let Some(entity) = storage.get(&neighbour) {
// TODO: Get neighbours that are paths and get lower
// TODO: Check collisions
if let Ok(path) = paths.get(entity) {
let new_pos = tile_to_pos(&path, grid_size, map_type, map_trans);
trans.translation = new_pos.extend(1.);
break;
let mut curr = std::f32::MAX;
if let Some(entity) = storage.get(&tile_pos) {
if let Ok((_, path)) = paths.get(entity) {
if let Some(i) = path.0 {
curr = i;
}
}
};

let prev = spirit.prev.unwrap_or(tile_pos);

let neighbours = get_neighbours(&tile_pos, map_size);
let next_it = neighbours
.iter()
.filter_map(|pos| storage.get(pos))
.filter_map(|entity| {
if let Ok((pos, path)) = paths.get(entity) {
if pos == &prev {
None
} else if let Some(i) = path.0 {
if i <= curr {
Some((pos, i))
} else {
None
}
} else {
None
}
} else {
None
}
});

// Move to next tile
if let Some((next, _)) =
next_it.min_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap())
{
let new_pos = tile_to_pos(next, grid_size, map_type, map_trans);

// TODO: Check if there is a spirit on the next tile
// I'm going to need to break this down into subsistems to be able to
// borrow the spirit list
// That or register the spirit in the tile is in (but that doesn't let me
// do fancy collisions later
// This needs reworking anyways so that the movement is not tile by tile

trans.translation = new_pos.extend(1.);

// If the next tile has the end as a neighbour, despawn
for neighbour in get_neighbours(next, map_size) {
if let Some(entity) = storage.get(&neighbour) {
if end.get(entity).is_ok() {
cmd.get_entity(spirit_entity).unwrap().despawn_recursive();
}
}
}
} else {
// If there is no next tile and you have been stuck, despawn
if let Some(prev) = spirit.prev {
if prev == tile_pos {
cmd.get_entity(spirit_entity).unwrap().despawn_recursive();
}
}
}

spirit.prev = Some(tile_pos);
}
}
}
Expand Down
Loading

0 comments on commit 836e0f5

Please sign in to comment.