diff options
Diffstat (limited to 'src/main.rs')
-rw-r--r-- | src/main.rs | 307 |
1 files changed, 298 insertions, 9 deletions
diff --git a/src/main.rs b/src/main.rs index a1fee19..c69d791 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,12 +1,301 @@ -use ggez::event::{self}; -use ggez::{ContextBuilder, GameResult}; +use bevy::math::Vec3; +use bevy::prelude::*; +use gems::cell::{self, Cell, Occupant}; +use gems::constants; +use rand::{thread_rng, Rng}; +use std::time::Duration; -use gems::game::Game; +fn star_spawning(mut commands: Commands, time: Res<Time>, mut q: Query<&mut Timer>) { + for mut timer in q.iter_mut() { + if !timer.repeating() { + timer.tick(time.delta()); + if timer.just_finished() { + timer.set_duration(Duration::new(thread_rng().gen_range(2..5), 0)); + timer.reset(); + commands + .spawn_bundle(SpriteSheetBundle { + sprite: TextureAtlasSprite::new(constants::TILESHEET_STAR1), + transform: Transform { + translation: Vec3::new( + thread_rng().gen_range(-300..300) as f32, + thread_rng().gen_range(-200..300) as f32, + 0.0, + ), + scale: Vec3::splat(thread_rng().gen_range(1..3) as f32), + ..Default::default() + }, + ..Default::default() + }) + .insert(Timer::from_seconds(0.25, true)); + } + } + } +} + +pub fn setup( + mut commands: Commands, + asset_server: Res<AssetServer>, + mut materials: ResMut<Assets<ColorMaterial>>, + mut texture_atlases: ResMut<Assets<TextureAtlas>>, +) { + let background = asset_server.load("background.png"); + let tileset = asset_server.load("tileset.png"); + let title = asset_server.load("title.png"); + + let atlas = TextureAtlas::from_grid( + tileset, + Vec2::new(constants::TILE_SIZE, constants::TILE_SIZE), + 5, + 5, + ); + let atlas_handle = texture_atlases.add(atlas); + + commands.spawn_bundle(OrthographicCameraBundle::new_2d()); + commands.spawn_bundle(SpriteBundle { + material: materials.add(background.into()), + transform: Transform { + translation: Vec3::new(50.0, 0.0, 0.0), + scale: Vec3::splat(constants::TILE_SCALE), + ..Default::default() + }, + ..Default::default() + }); + commands.spawn_bundle(SpriteBundle { + material: materials.add(title.into()), + transform: Transform { + translation: Vec3::new(240.0, 200.0, 0.0), + scale: Vec3::splat(2.0), + ..Default::default() + }, + ..Default::default() + }); + commands.spawn_bundle(SpriteSheetBundle { + sprite: TextureAtlasSprite::new(constants::TILESHEET_COSMONAUT1), + texture_atlas: atlas_handle.clone(), + transform: Transform { + translation: Vec3::new(225.0, -200.0, 0.0), + scale: Vec3::splat(constants::TILE_SCALE), + ..Default::default() + }, + ..Default::default() + }); + commands.spawn_bundle((Timer::from_seconds(1.0, false),)); + commands.spawn_bundle(SpriteSheetBundle { + sprite: TextureAtlasSprite::new(constants::TILESHEET_COSMONAUT2), + texture_atlas: atlas_handle.clone(), + transform: Transform { + translation: Vec3::new( + 225.0, + -200.0 + (-constants::TILE_SIZE) * constants::TILE_SCALE, + 0.0, + ), + scale: Vec3::splat(constants::TILE_SCALE), + ..Default::default() + }, + ..Default::default() + }); + + for i in 0..constants::GRID_SIZE { + for j in 0..constants::GRID_SIZE { + commands + .spawn_bundle(SpriteSheetBundle { + texture_atlas: atlas_handle.clone(), + visible: Visible { + is_visible: false, + is_transparent: true, + }, + transform: Transform { + translation: Vec3::new( + ((i as f32) * constants::TILE_SIZE * constants::TILE_SCALE) - 330.0, + ((j as f32) * constants::TILE_SIZE * constants::TILE_SCALE) - 160.0, + 1.0, + ), + scale: Vec3::splat(constants::TILE_SCALE), + ..Default::default() + }, + ..Default::default() + }) + .insert(Cell::new(i, j)); + } + } +} + +fn animation( + mut commands: Commands, + time: Res<Time>, + mut q: Query<( + Entity, + Option<&mut Cell>, + &mut Timer, + &mut TextureAtlasSprite, + &mut Visible, + )>, +) { + for (entity, cell, mut timer, mut sprite, mut visible) in q.iter_mut() { + timer.tick(time.delta()); + if timer.finished() { + let index = match sprite.index { + constants::TILESHEET_EXPLOSION1 => Some(constants::TILESHEET_EXPLOSION2), + constants::TILESHEET_EXPLOSION2 => Some(constants::TILESHEET_EXPLOSION3), + constants::TILESHEET_EXPLOSION3 => Some(constants::TILESHEET_EXPLOSION4), + constants::TILESHEET_EXPLOSION4 => Some(constants::TILESHEET_EXPLOSION5), + + constants::TILESHEET_VISOR1 => Some(constants::TILESHEET_VISOR2), + constants::TILESHEET_VISOR2 => Some(constants::TILESHEET_VISOR3), + constants::TILESHEET_VISOR3 => Some(constants::TILESHEET_VISOR4), + + constants::TILESHEET_STAR1 => Some(constants::TILESHEET_STAR2), + constants::TILESHEET_STAR2 => Some(constants::TILESHEET_STAR3), + + _ => None, + }; + + if let Some(index) = index { + sprite.index = index; + } else if let Some(mut cell) = cell { + cell.set_occupant(Occupant::None, &mut sprite, &mut visible); + commands.entity(entity).remove::<Timer>(); + } else { + commands.entity(entity).despawn(); + } + } + } +} + +fn cosmonaut_detect( + mut commands: Commands, + windows: Res<Windows>, + mut q: Query<(&Transform, &TextureAtlasSprite)>, +) { + if let Some(mut cursor_position) = windows + .get_primary() + .and_then(|window| window.cursor_position()) + { + cursor_position.x -= + (constants::WINDOW_WIDTH / 2.0) - constants::TILE_SIZE * constants::TILE_SCALE * 0.5; + cursor_position.y -= + (constants::WINDOW_HEIGHT / 2.0) - constants::TILE_SIZE * constants::TILE_SCALE * 0.5; + for (transform, sprite) in q.iter_mut() { + if transform.translation.x < cursor_position.x + && transform.translation.x + constants::TILE_SIZE * constants::TILE_SCALE + > cursor_position.x + && transform.translation.y < cursor_position.y + && transform.translation.y + constants::TILE_SIZE * constants::TILE_SCALE + > cursor_position.y + && sprite.index == constants::TILESHEET_COSMONAUT1 + { + commands + .spawn_bundle(SpriteSheetBundle { + sprite: TextureAtlasSprite::new(constants::TILESHEET_VISOR1), + transform: *transform, + ..Default::default() + }) + .insert(Timer::from_seconds(0.1, true)); + } + } + } +} + +fn mouse( + windows: Res<Windows>, + mut q: Query<(&mut Cell, &mut Transform, &mut TextureAtlasSprite)>, + mouse_button_input: Res<Input<MouseButton>>, +) { + if let Some(mut cursor_position) = windows + .get_primary() + .and_then(|window| window.cursor_position()) + { + cursor_position.x -= + (constants::WINDOW_WIDTH / 2.0) - constants::TILE_SIZE * constants::TILE_SCALE * 0.5; + cursor_position.y -= + (constants::WINDOW_HEIGHT / 2.0) - constants::TILE_SIZE * constants::TILE_SCALE * 0.5; + + for (cell, _, mut sprite) in q.iter_mut() { + if cell.selected { + sprite.color.set_a(0.2); + } else if cell.hovered { + sprite.color.set_a(0.5); + } else { + sprite.color.set_a(1.0); + } + } + + for (mut cell, transform, _) in q.iter_mut() { + if transform.translation.x < cursor_position.x + && transform.translation.x + constants::TILE_SIZE * constants::TILE_SCALE + > cursor_position.x + && transform.translation.y < cursor_position.y + && transform.translation.y + constants::TILE_SIZE * constants::TILE_SCALE + > cursor_position.y + { + cell.hovered = true; + if mouse_button_input.just_pressed(MouseButton::Left) { + cell.selected = true; + } + } else { + cell.hovered = false; + } + } + + if mouse_button_input.just_released(MouseButton::Left) { + let mut cells: Vec<Cell> = Vec::new(); + for (cell, _, _) in q.iter_mut() { + cells.push(*cell); + } + if let Some(mut selected) = cells.clone().iter_mut().find(|c| c.selected) { + if let Some(mut hovered) = cells.iter_mut().find(|c| c.hovered) { + if (selected.x == hovered.x + 1 && selected.y == hovered.y) + || (selected.x == hovered.x.overflowing_sub(1).0 && selected.y == hovered.y) + || (selected.y == hovered.y + 1 && selected.x == hovered.x) + || (selected.y == hovered.y.overflowing_sub(1).0 && selected.x == hovered.x) + { + let tmp = selected.occupant; + selected.occupant = hovered.occupant; + hovered.occupant = tmp; + for (mut cell, _, mut sprite) in q.iter_mut() { + if cell.x == selected.x && cell.y == selected.y { + cell.occupant = selected.occupant; + sprite.index = cell.occupant.to_index(); + } else if cell.x == hovered.x && cell.y == hovered.y { + cell.occupant = hovered.occupant; + sprite.index = cell.occupant.to_index(); + } + } + } + } + } + for (mut cell, _, _) in q.iter_mut() { + cell.selected = false; + } + } + } +} + +pub struct GemsPlugin; +impl Plugin for GemsPlugin { + fn build(&self, app: &mut AppBuilder) { + app.add_startup_system(setup.system()); + app.add_system(cell::insert.system()); + app.add_system(cell::falling.system()); + app.add_system(cell::check.system()); + app.add_system(cell::start_explosion.system()); + app.add_system(mouse.system()); + app.add_system(cosmonaut_detect.system()); + app.add_system(animation.system()); + app.add_system(star_spawning.system()); + } +} -pub fn main() -> GameResult { - let (ref mut context, ref mut event_loop) = ContextBuilder::new("gems", "jw&tb") - .add_resource_path("./resources") - .build()?; - let game = &mut Game::new(context)?; - event::run(context, event_loop, game) +pub fn main() { + App::build() + .insert_resource(WindowDescriptor { + title: "gems".to_string(), + width: constants::WINDOW_WIDTH, + height: constants::WINDOW_HEIGHT, + resizable: false, + ..Default::default() + }) + .add_plugins(DefaultPlugins) + .add_plugin(GemsPlugin) + .run(); } |