Skip to content

Commit

Permalink
Remove FreePositions resource
Browse files Browse the repository at this point in the history
  • Loading branch information
tehlers committed Feb 8, 2025
1 parent 420ca69 commit 979a87c
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 162 deletions.
13 changes: 1 addition & 12 deletions src/game.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ pub mod resources;
pub mod systems;

use crate::despawn_screen;
use crate::prelude::*;
use crate::GameState;
use bevy::input::common_conditions::input_just_pressed;
use bevy::prelude::*;
Expand All @@ -29,16 +28,7 @@ pub struct GamePlugin;
impl Plugin for GamePlugin {
fn build(&self, app: &mut App) {
app.add_plugins(ShapePlugin)
.add_systems(
OnEnter(GameState::Game),
(
control::init_diplopod,
control::init_wall,
control::init_food,
control::init_poison,
)
.chain(),
)
.add_systems(OnEnter(GameState::Game), control::setup_game)
.add_systems(
Update,
(
Expand Down Expand Up @@ -92,7 +82,6 @@ impl Plugin for GamePlugin {
.add_systems(OnExit(GameState::Game), despawn_screen::<OnGameScreen>)
.insert_resource(DiplopodSegments::default())
.insert_resource(LastSpecialSpawn::default())
.insert_resource(FreePositions::new(CONSUMABLE_WIDTH, CONSUMABLE_HEIGHT))
.insert_resource(Time::<Fixed>::from_seconds(0.075))
.add_event::<GameOver>()
.add_event::<Growth>()
Expand Down
54 changes: 0 additions & 54 deletions src/game/resources.rs
Original file line number Diff line number Diff line change
@@ -1,62 +1,8 @@
use bevy::prelude::*;
use rand::seq::SliceRandom;
use rand::thread_rng;

use crate::game::components::Position;

#[derive(Default, Resource)]
pub struct DiplopodSegments(pub Vec<Entity>);

#[derive(Clone, Resource)]
pub struct FreePositions {
pub positions: Vec<Position>,
width: i32,
height: i32,
}

impl FreePositions {
pub fn new(width: i32, height: i32) -> Self {
let positions = Self::new_positions(width, height);
Self {
positions,
width,
height,
}
}

fn new_positions(width: i32, height: i32) -> Vec<Position> {
let mut positions = Vec::new();

for x in 0..width {
for y in 0..height {
positions.push(Position { x, y });
}
}

positions.shuffle(&mut thread_rng());

positions
}

pub fn shuffle(&mut self) {
self.positions.shuffle(&mut thread_rng());
}

pub fn remove(&mut self, position: &Position) {
self.positions.retain(|&p| p != *position);
}

pub fn remove_all(&mut self, positions: &Vec<Position>) {
for position in positions {
self.remove(position);
}
}

pub fn reset(&mut self) {
self.positions = Self::new_positions(self.width, self.height);
}
}

#[derive(Default, Resource)]
pub struct LastSpecialSpawn(pub u32);

Expand Down
141 changes: 45 additions & 96 deletions src/game/systems/control.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use rand::seq::SliceRandom;
use rand::{thread_rng, Rng};

use bevy::prelude::*;
Expand Down Expand Up @@ -206,106 +207,73 @@ impl Command for SpawnAntidote {
}
}

pub fn init_diplopod(mut commands: Commands) {
pub fn setup_game(mut commands: Commands) {
commands.queue(SpawnDiplopodSegment);
}

pub fn init_wall(mut commands: Commands, mut free_positions: ResMut<FreePositions>) {
for x in 0..CONSUMABLE_WIDTH + 1 {
let position = Position { x, y: 0 };
commands.queue(SpawnWall { position });
free_positions.remove(&position);

let position = Position {
x,
y: CONSUMABLE_HEIGHT,
};
commands.queue(SpawnWall { position });
free_positions.remove(&position);
}

for y in 1..CONSUMABLE_HEIGHT {
let position = Position { x: 0, y };
commands.queue(SpawnWall { position });
free_positions.remove(&position);

let position = Position {
x: CONSUMABLE_WIDTH,
y,
};
commands.queue(SpawnWall { position });
free_positions.remove(&position);
}
}

pub fn init_food(mut commands: Commands, mut free_positions: ResMut<FreePositions>) {
spawn_food(&mut commands, &mut free_positions);
}
let mut position_candidates: Vec<Position> =
Vec::with_capacity(((CONSUMABLE_WIDTH - 1) * (CONSUMABLE_HEIGHT - 1)) as usize);

fn spawn_food(commands: &mut Commands, free_positions: &mut ResMut<FreePositions>) {
let segment_positions = vec![DiplopodPosition {
for x in 1..CONSUMABLE_WIDTH {
for y in 1..CONSUMABLE_HEIGHT {
position_candidates.push(Position { x, y });
}
}

let segment_position = DiplopodPosition {
x: ARENA_WIDTH / 2,
y: ARENA_HEIGHT / 2,
}
.to_position()];
.to_position();
position_candidates.retain(|&p| p != segment_position);

let mut position_candidates = free_positions.clone();
position_candidates.remove_all(&segment_positions);
position_candidates.shuffle(&mut thread_rng());

spawn_random_food(
AMOUNT_OF_FOOD,
commands,
&mut position_candidates,
free_positions,
);
spawn_random_food(AMOUNT_OF_FOOD, &mut commands, &mut position_candidates);
spawn_random_poison(AMOUNT_OF_POISON, &mut commands, &mut position_candidates);
}

fn spawn_random_food(
amount: u32,
commands: &mut Commands,
position_candidates: &mut FreePositions,
free_positions: &mut ResMut<FreePositions>,
position_candidates: &mut Vec<Position>,
) {
for _ in 0..amount {
if let Some(position) = position_candidates.positions.pop() {
if let Some(position) = position_candidates.pop() {
commands.queue(SpawnFood { position });
free_positions.remove(&position);
}
}
}

pub fn init_poison(mut commands: Commands, mut free_positions: ResMut<FreePositions>) {
spawn_poison(&mut commands, &mut free_positions);
}

fn spawn_poison(commands: &mut Commands, free_positions: &mut ResMut<FreePositions>) {
let segment_positions = vec![DiplopodPosition {
x: ARENA_WIDTH / 2,
y: ARENA_HEIGHT / 2,
}
.to_position()];

let mut position_candidates = free_positions.clone();
position_candidates.remove_all(&segment_positions);

spawn_random_poison(
AMOUNT_OF_POISON,
commands,
&mut position_candidates,
free_positions,
);
}

fn spawn_random_poison(
amount: u32,
commands: &mut Commands,
position_candidates: &mut FreePositions,
free_positions: &mut ResMut<FreePositions>,
position_candidates: &mut Vec<Position>,
) {
for _ in 0..amount {
if let Some(position) = position_candidates.positions.pop() {
if let Some(position) = position_candidates.pop() {
commands.queue(SpawnPoison { position });
free_positions.remove(&position);
}
}
}
Expand All @@ -315,69 +283,61 @@ pub fn spawn_consumables(
mut commands: Commands,
segments: ResMut<DiplopodSegments>,
mut spawn_consumables_reader: EventReader<SpawnConsumables>,
mut diplopod_positions: Query<&mut DiplopodPosition>,
diplopod_positions: Query<&DiplopodPosition>,
positions: Query<&Position>,
superfood: Query<Entity, With<Superfood>>,
antidotes: Query<Entity, With<Antidote>>,
mut free_positions: ResMut<FreePositions>,
mut last_special_spawn: ResMut<LastSpecialSpawn>,
sounds: Res<Sounds>,
) {
if let Some(spawn_event) = spawn_consumables_reader.read().next() {
let segment_positions = segments
.0
.iter()
.map(|e| *diplopod_positions.get_mut(*e).unwrap())
.map(|p| p.to_position())
.collect::<Vec<Position>>();
let mut position_candidates: Vec<Position> =
Vec::with_capacity(((CONSUMABLE_WIDTH - 1) * (CONSUMABLE_HEIGHT - 1)) as usize);

let mut position_candidates = free_positions.clone();
position_candidates.remove_all(&segment_positions);
for x in 1..CONSUMABLE_WIDTH {
for y in 1..CONSUMABLE_HEIGHT {
position_candidates.push(Position { x, y });
}
}

for position in positions.iter() {
position_candidates.retain(|&p| p != *position);
}

for segment in segments.0.iter() {
if let Ok(diplopod_position) = diplopod_positions.get(*segment) {
let position = diplopod_position.to_position();
position_candidates.retain(|&p| p != position);
}
}

position_candidates.shuffle(&mut thread_rng());

if spawn_event.regular {
spawn_random_food(
1,
&mut commands,
&mut position_candidates,
&mut free_positions,
);

spawn_random_poison(
1,
&mut commands,
&mut position_candidates,
&mut free_positions,
);
spawn_random_food(1, &mut commands, &mut position_candidates);
spawn_random_poison(1, &mut commands, &mut position_candidates);
}

let new_size = segments.0.len() as u32 + spawn_event.new_segments as u32;
if new_size - last_special_spawn.0 > SPECIAL_SPAWN_INTERVAL {
last_special_spawn.0 = (new_size / SPECIAL_SPAWN_INTERVAL) * SPECIAL_SPAWN_INTERVAL;

for ent in superfood.iter() {
let position = positions.get(ent).unwrap();
free_positions.positions.push(*position);
commands.entity(ent).despawn();
}
free_positions.shuffle();

if last_special_spawn.0 % (SPECIAL_SPAWN_INTERVAL * 2) == 0 {
for ent in antidotes.iter() {
let position = positions.get(ent).unwrap();
free_positions.positions.push(*position);
commands.entity(ent).despawn();
}
free_positions.shuffle();

if let Some(position) = position_candidates.positions.pop() {
if let Some(position) = position_candidates.pop() {
commands.queue(SpawnAntidote { position });
free_positions.remove(&position);
}
}

if let Some(position) = position_candidates.positions.pop() {
if let Some(position) = position_candidates.pop() {
commands.queue(SpawnSuperfood { position });
free_positions.remove(&position);
}

commands.spawn((
Expand Down Expand Up @@ -433,15 +393,12 @@ pub fn eat(
antidote_positions: Query<(Entity, &Position), With<Antidote>>,
mut heads: Query<(&mut DiplopodHead, &DiplopodPosition)>,
wall_positions: Query<(Entity, &Position), With<Wall>>,
mut free_positions: ResMut<FreePositions>,
sounds: Res<Sounds>,
) {
for (mut head, head_pos) in heads.iter_mut() {
for (ent, food_pos) in food_positions.iter() {
if *food_pos == head_pos.to_position() {
commands.entity(ent).despawn();
free_positions.positions.push(*food_pos);
free_positions.shuffle();
growth_writer.send(Growth(1));

spawn_consumables_writer.send(SpawnConsumables {
Expand All @@ -459,8 +416,6 @@ pub fn eat(
for (ent, superfood_pos) in superfood_positions.iter() {
if *superfood_pos == head_pos.to_position() {
commands.entity(ent).despawn();
free_positions.positions.push(*superfood_pos);
free_positions.shuffle();
let new_segments = thread_rng().gen_range(2..10);
growth_writer.send(Growth(new_segments));

Expand All @@ -484,7 +439,6 @@ pub fn eat(
for (ent, antidote_pos) in antidote_positions.iter() {
if *antidote_pos == head_pos.to_position() {
commands.entity(ent).despawn();
free_positions.positions.push(*antidote_pos);

let remaining = head.immunity.remaining_secs();
head.immunity = Timer::from_seconds(10.0 + remaining, TimerMode::Once);
Expand All @@ -502,8 +456,6 @@ pub fn eat(
if *poison_pos == head_pos.to_position() {
if !head.immunity.finished() {
commands.entity(ent).despawn();
free_positions.positions.push(*poison_pos);
free_positions.shuffle();
growth_writer.send(Growth(1));

commands.spawn((
Expand Down Expand Up @@ -597,7 +549,6 @@ pub fn game_over(
mut commands: Commands,
mut reader: EventReader<GameOver>,
mut segments: ResMut<DiplopodSegments>,
mut free_positions: ResMut<FreePositions>,
mut last_special_spawn: ResMut<LastSpecialSpawn>,
sounds: Res<Sounds>,
mut game_state: ResMut<NextState<GameState>>,
Expand All @@ -616,8 +567,6 @@ pub fn game_over(
highscore.0 = lastscore.0;
}

free_positions.reset();

last_special_spawn.0 = 0;

segments.0 = Vec::new();
Expand Down

0 comments on commit 979a87c

Please sign in to comment.