diff --git a/assets/image/entity/1-bit/Clothing.png b/assets/image/entity/1-bit/Clothing.png new file mode 100644 index 0000000..3558943 Binary files /dev/null and b/assets/image/entity/1-bit/Clothing.png differ diff --git a/assets/image/entity/1-bit/Creatures.png b/assets/image/entity/1-bit/Creatures.png new file mode 100644 index 0000000..97d64e7 Binary files /dev/null and b/assets/image/entity/1-bit/Creatures.png differ diff --git a/assets/image/entity/1-bit/Food.png b/assets/image/entity/1-bit/Food.png new file mode 100644 index 0000000..a682f39 Binary files /dev/null and b/assets/image/entity/1-bit/Food.png differ diff --git a/assets/image/entity/1-bit/Gems-Jewels-and-Money.png b/assets/image/entity/1-bit/Gems-Jewels-and-Money.png new file mode 100644 index 0000000..b3e43ce Binary files /dev/null and b/assets/image/entity/1-bit/Gems-Jewels-and-Money.png differ diff --git a/assets/image/entity/1-bit/Instruments.png b/assets/image/entity/1-bit/Instruments.png new file mode 100644 index 0000000..fdc18da Binary files /dev/null and b/assets/image/entity/1-bit/Instruments.png differ diff --git a/assets/image/entity/1-bit/Jewelry.png b/assets/image/entity/1-bit/Jewelry.png new file mode 100644 index 0000000..1cd3e56 Binary files /dev/null and b/assets/image/entity/1-bit/Jewelry.png differ diff --git a/assets/image/entity/1-bit/Misc-Future.png b/assets/image/entity/1-bit/Misc-Future.png new file mode 100644 index 0000000..e8c42da Binary files /dev/null and b/assets/image/entity/1-bit/Misc-Future.png differ diff --git a/assets/image/entity/1-bit/Misc.png b/assets/image/entity/1-bit/Misc.png new file mode 100644 index 0000000..2065c25 Binary files /dev/null and b/assets/image/entity/1-bit/Misc.png differ diff --git a/assets/image/entity/1-bit/People.png b/assets/image/entity/1-bit/People.png new file mode 100644 index 0000000..33e6b85 Binary files /dev/null and b/assets/image/entity/1-bit/People.png differ diff --git a/assets/image/entity/1-bit/Potions.png b/assets/image/entity/1-bit/Potions.png new file mode 100644 index 0000000..e0113cf Binary files /dev/null and b/assets/image/entity/1-bit/Potions.png differ diff --git a/assets/image/entity/1-bit/Tools.png b/assets/image/entity/1-bit/Tools.png new file mode 100644 index 0000000..f0319e8 Binary files /dev/null and b/assets/image/entity/1-bit/Tools.png differ diff --git a/assets/image/entity/1-bit/UI.png b/assets/image/entity/1-bit/UI.png new file mode 100644 index 0000000..905db24 Binary files /dev/null and b/assets/image/entity/1-bit/UI.png differ diff --git a/assets/image/entity/1-bit/Weapons.png b/assets/image/entity/1-bit/Weapons.png new file mode 100644 index 0000000..6c1683b Binary files /dev/null and b/assets/image/entity/1-bit/Weapons.png differ diff --git a/src/simulation.rs b/src/simulation.rs index d26a280..1855596 100644 --- a/src/simulation.rs +++ b/src/simulation.rs @@ -1,11 +1,13 @@ +mod sprite_pack; + use std::f32::consts::TAU; -use bevy::math::vec2; use bevy::prelude::*; -use rand::seq::SliceRandom; use rand::Rng; use crate::physics::Velocity; +pub use crate::simulation::sprite_pack::SpritePack; +pub use crate::simulation::sprite_pack::SpritePackAssets; use crate::state::editor_screen::SceneViewBounds; use crate::state::editor_screen::WrapWithinSceneView; use crate::state::AppState; @@ -22,6 +24,7 @@ impl Plugin for SimulationPlugin { fn build(&self, app: &mut App) { app.register_type::() .register_type::() + .add_plugins(sprite_pack::SpritePackPlugin) .add_event::() .init_resource::() .init_resource::() @@ -46,10 +49,9 @@ pub struct Simulation { pub lines: f64, pub entities: f64, pub tech_debt: f64, - - /// Fun factor, determines the score. + /// Fun score, affects the submission's results. pub fun_score: f64, - /// Presentation factor, determines the score. + /// Presentation factor, affects the submissions' results. pub presentation_score: f64, /// Minimum size for new entities. @@ -58,6 +60,8 @@ pub struct Simulation { pub entity_size_max: f32, /// List of colors that the new entities can have. pub entity_colors: Vec, + /// The sprite pack to use. + pub sprite_pack: SpritePack, /// Minimum offset distance for entities on spawn. pub spawn_offset_min: f32, @@ -74,12 +78,15 @@ impl Default for Simulation { tech_debt: 0.0, fun_score: 0.0, presentation_score: 0.0, + entity_size_min: 8.0, entity_size_max: 8.0, entity_colors: vec![ Color::rgba(0.0, 0.0, 0.0, 1.0), Color::rgba(1.0, 1.0, 1.0, 1.0), ], + sprite_pack: default(), + spawn_offset_min: 0.0, spawn_offset_max: 2.0, } @@ -99,8 +106,9 @@ fn spawn_entities( mut commands: Commands, mut events: EventReader, root: Res, - mut entity_cap_query: Query<&mut OverflowDespawnQueue, With>, mut simulation: ResMut, + sprite_pack_assets: Res, + mut entity_cap_query: Query<&mut OverflowDespawnQueue, With>, ) { let mut rng = rand::thread_rng(); for event in events.read() { @@ -119,24 +127,24 @@ fn spawn_entities( let position = (event.position + offset).extend(0.0); let size = rng.gen_range(simulation.entity_size_min..=simulation.entity_size_max); + let size = Vec2::splat(size); let entity = commands .spawn(( Name::new("Entity"), - SpriteBundle { - sprite: Sprite { - color: *simulation.entity_colors.choose(&mut rng).unwrap(), - custom_size: Some(vec2(size, size)), - ..default() - }, - transform: Transform::from_translation(position), - ..default() - }, + SpatialBundle::from_transform(Transform::from_translation(position)), Velocity(velocity), WrapWithinSceneView, )) .set_parent(root.world) .id(); + simulation.sprite_pack.apply( + &mut commands, + entity, + &sprite_pack_assets, + size, + &mut rng, + ); for mut despawn_queue in &mut entity_cap_query { despawn_queue.push(entity); diff --git a/src/simulation/sprite_pack.rs b/src/simulation/sprite_pack.rs new file mode 100644 index 0000000..9695494 --- /dev/null +++ b/src/simulation/sprite_pack.rs @@ -0,0 +1,89 @@ +use bevy::prelude::*; +use bevy_asset_loader::prelude::*; +use rand::seq::SliceRandom; +use rand::Rng; + +pub struct SpritePackPlugin; + +impl Plugin for SpritePackPlugin { + fn build(&self, app: &mut App) { + app.register_type::() + .init_collection::(); + } +} + +pub enum SpritePack { + None(Vec), + OneBit(Vec<(Color, usize)>), +} + +impl Default for SpritePack { + fn default() -> Self { + Self::None(vec![Color::BLACK, Color::WHITE]) + } +} + +impl SpritePack { + pub fn add_skin(&mut self, mut rng: impl Rng) { + let color = Color::Rgba { + red: rng.gen_range(0.0..1.0), + green: rng.gen_range(0.0..1.0), + blue: rng.gen_range(0.0..1.0), + alpha: 1.0, + }; + match self { + Self::None(colors) => { + colors.push(color); + }, + // TODO: Curate the tiles. + // FIXME: Prevent duplicates. + Self::OneBit(tiles) => tiles.push((color, rng.gen_range(0..=5))), + } + } + + pub fn apply( + &self, + commands: &mut Commands, + entity: Entity, + assets: &SpritePackAssets, + size: Vec2, + mut rng: impl Rng, + ) { + let (color, index) = match self { + Self::None(colors) => { + commands.entity(entity).insert(Sprite { + color: *colors.choose(&mut rng).unwrap(), + custom_size: Some(size), + ..default() + }); + return; + }, + Self::OneBit(tiles) => *tiles.choose(&mut rng).unwrap(), + }; + let handle = match self { + Self::None(..) => unreachable!(), + Self::OneBit(..) => assets.one_bit_food.clone(), + }; + + commands.entity(entity).insert(( + TextureAtlasSprite { + color, + index, + custom_size: Some(size), + ..default() + }, + handle, + )); + } +} + +#[derive(AssetCollection, Resource, Reflect, Default)] +#[reflect(Resource)] +pub struct SpritePackAssets { + #[asset(texture_atlas(tile_size_x = 10.0, tile_size_y = 10.0, rows = 5, columns = 17))] + #[asset(path = "image/entity/1-bit/Food.png")] + pub one_bit_food: Handle, + #[asset(texture_atlas(tile_size_x = 10.0, tile_size_y = 10.0, rows = 11, columns = 13))] + #[asset(path = "image/entity/1-bit/Weapons.png")] + pub one_bit_weapons: Handle, +} diff --git a/src/state/loading_screen.rs b/src/state/loading_screen.rs index 1bc9399..59d79d7 100644 --- a/src/state/loading_screen.rs +++ b/src/state/loading_screen.rs @@ -7,6 +7,7 @@ use serde::Deserialize; use serde::Serialize; use crate::config::Config; +use crate::simulation::SpritePackAssets; use crate::state::editor_screen::EditorScreenAssets; use crate::state::AppState::*; use crate::ui::FontSize; @@ -20,6 +21,7 @@ impl Plugin for LoadingScreenStatePlugin { app.register_type::() .add_loading_state(LoadingState::new(LoadingScreen)) .add_collection_to_loading_state::<_, EditorScreenAssets>(LoadingScreen) + .add_collection_to_loading_state::<_, SpritePackAssets>(LoadingScreen) .add_plugins(ProgressPlugin::new(LoadingScreen).continue_to(EditorScreen)) .add_systems(OnEnter(LoadingScreen), enter_loading) .add_systems(OnExit(LoadingScreen), exit_loading) diff --git a/src/state/title_screen.rs b/src/state/title_screen.rs index 0be0e3b..82436a8 100644 --- a/src/state/title_screen.rs +++ b/src/state/title_screen.rs @@ -7,6 +7,7 @@ use serde::Deserialize; use serde::Serialize; use crate::config::Config; +use crate::simulation::SpritePackAssets; use crate::state::editor_screen::EditorScreenAssets; use crate::state::AppState::*; use crate::ui::FontSize; @@ -24,6 +25,7 @@ impl Plugin for TitleScreenStatePlugin { .init_collection::() .add_loading_state(LoadingState::new(TitleScreen)) .add_collection_to_loading_state::<_, EditorScreenAssets>(TitleScreen) + .add_collection_to_loading_state::<_, SpritePackAssets>(TitleScreen) .add_plugins(ProgressPlugin::new(TitleScreen)) .add_systems(OnEnter(TitleScreen), enter_title_screen) .add_systems(OnExit(TitleScreen), exit_title_screen); diff --git a/src/upgrade.rs b/src/upgrade.rs index 82c5dcd..e413415 100644 --- a/src/upgrade.rs +++ b/src/upgrade.rs @@ -6,7 +6,6 @@ use bevy::ecs::system::SystemId; use bevy::prelude::*; use rand::seq::SliceRandom; use rand::thread_rng; -use rand::Rng; use strum::EnumCount; use crate::config::Config; @@ -16,6 +15,7 @@ use crate::simulation::PassiveCodeTyper; use crate::simulation::PassiveEntitySpawner; use crate::simulation::Simulation; use crate::simulation::SpawnEvent; +use crate::simulation::SpritePack; use crate::state::editor_screen::spawn_editor_screen; use crate::state::editor_screen::SceneView; use crate::state::editor_screen::SceneViewBounds; @@ -293,7 +293,7 @@ fn load_upgrade_sequence(mut commands: Commands) { vec![Inspiration], vec![VelocityPlugin], vec![ImportLibrary, SplashOfLifePlugin], - vec![Coffee], + vec![Coffee, OneBitSpritePack], vec![Brainstorm], ])); } @@ -339,27 +339,30 @@ generate_upgrade_list!( // Presentation score + OneBitSpritePack: Upgrade { + name: "1-bit Sprite Pack".to_string(), + desc: "Downloads a 1-bit sprite pack for your entities. Makes your game prettier.".to_string(), + presentation_score: 10.0, + base_cost: 25.0, + install: Some(world.register_system(| + mut simulation: ResMut + | { + simulation.sprite_pack = SpritePack::OneBit(vec![]); + simulation.sprite_pack.add_skin(&mut thread_rng()); + })), + ..default() + }, EntitySkinPlugin: Upgrade { name: "EntitySkinPlugin".to_string(), desc: "Introduces a new entity skin with a random color. Makes your game prettier.".to_string(), - presentation_score: 5.0, + presentation_score: 4.0, base_cost: 10.0, cost_scale_factor: 1.2, weight: 1.0, remaining: 5, - install: Some( - world.register_system(|mut simulation: ResMut| { - let mut rng = rand::thread_rng(); - simulation.entity_colors.push( - Color::Rgba { - red: rng.gen_range(0.0..1.0), - green: rng.gen_range(0.0..1.0), - blue: rng.gen_range(0.0..1.0), - alpha: 1.0, - } - ); - }), - ), + install: Some(world.register_system(|mut simulation: ResMut| { + simulation.sprite_pack.add_skin(&mut thread_rng()); + })), ..default() }, EntitySizePlugin: Upgrade { @@ -370,11 +373,9 @@ generate_upgrade_list!( cost_scale_factor: 1.2, weight: 1.0, remaining: 2, - install: Some( - world.register_system(|mut simulation: ResMut| { - simulation.entity_size_max += 4.0; - }), - ), + install: Some(world.register_system(|mut simulation: ResMut| { + simulation.entity_size_max += 4.0; + })), ..default() }, @@ -674,11 +675,9 @@ generate_upgrade_list!( name: "Brainstorm".to_string(), desc: "Adds 1 extra upgrade slot.".to_string(), tech_debt: 0.0, - install: Some( - world.register_system(|mut sequence: ResMut| { - sequence.slots += 1; - }), - ), + install: Some(world.register_system(|mut sequence: ResMut| { + sequence.slots += 1; + })), ..default() }, DesignDocument: Upgrade { @@ -688,11 +687,9 @@ generate_upgrade_list!( base_cost: 20.0, upgrade_min: 7, weight: 2.5, - install: Some( - world.register_system(|mut sequence: ResMut| { - sequence.slots += 1; - }), - ), + install: Some(world.register_system(|mut sequence: ResMut| { + sequence.slots += 1; + })), ..default() }, );