From ccadb98a8a09d28e5b42cf4ff5e6174e3a0a319b Mon Sep 17 00:00:00 2001 From: Alula Date: Wed, 19 Aug 2020 13:21:40 +0200 Subject: [PATCH] failed refactoring lol --- Cargo.toml | 4 + src/entity.rs | 11 ++- src/frame.rs | 19 ++-- src/game_state.rs | 101 ++++++++++++++++++++ src/live_debugger.rs | 38 ++++++++ src/main.rs | 183 ++++++++++++++++--------------------- src/player.rs | 53 +++++------ src/player_hit.rs | 71 +++++++------- src/scene/game_scene.rs | 160 ++++++++++++++------------------ src/scene/loading_scene.rs | 26 +++--- src/scene/mod.rs | 11 ++- src/sound/mod.rs | 2 +- src/stage.rs | 22 +++++ src/texture_set.rs | 2 +- src/ui.rs | 104 +++++++++++++++++++++ 15 files changed, 518 insertions(+), 289 deletions(-) create mode 100644 src/game_state.rs create mode 100644 src/live_debugger.rs create mode 100644 src/ui.rs diff --git a/Cargo.toml b/Cargo.toml index c8d1bea..b639509 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,9 +10,12 @@ panic = 'abort' [dependencies] byteorder = "1.3" +gfx_device_gl = "0.16" ggez = { git = "https://github.com/ggez/ggez", rev = "4f4bdebff463881c36325c7e10520c9a4fd8f75c" } imgui = "0.4.0" imgui-ext = "0.3.0" +imgui-gfx-renderer = "0.4.0" +imgui-winit-support = {version = "0.4.0", default-features = false, features = ["winit-19"] } image = {version = "0.22", default-features = false, features = ["png_codec", "pnm", "bmp"] } itertools = "0.9.0" lazy_static = "1.4.0" @@ -25,3 +28,4 @@ rodio = { version = "0.11", default-features = false, features = ["flac", "vorbi strum = "0.18.0" strum_macros = "0.18.0" owning_ref = "0.4.1" +winit = { version = "0.19.3" } diff --git a/src/entity.rs b/src/entity.rs index 68313db..b938164 100644 --- a/src/entity.rs +++ b/src/entity.rs @@ -1,10 +1,13 @@ use ggez::{Context, GameResult}; -use crate::frame::Frame; -use crate::SharedGameState; +use crate::engine_constants::EngineConstants; +use crate::game_state::GameState; +use crate::GameContext; pub trait GameEntity { - fn tick(&mut self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult; + fn init(&mut self, _state: &GameState, _game_ctx: &mut GameContext, _ctx: &mut Context) -> GameResult { Ok(()) } - fn draw(&self, state: &mut SharedGameState, ctx: &mut Context, frame: &Frame) -> GameResult; + fn tick(&mut self, state: &GameState, constants: &EngineConstants, ctx: &mut Context) -> GameResult; + + fn draw(&self, state: &GameState, game_ctx: &mut GameContext, ctx: &mut Context) -> GameResult; } diff --git a/src/frame.rs b/src/frame.rs index f5a75a4..b8f22a5 100644 --- a/src/frame.rs +++ b/src/frame.rs @@ -1,6 +1,5 @@ use crate::player::Player; use crate::stage::Stage; -use crate::SharedGameState; pub struct Frame { pub x: isize, @@ -9,32 +8,32 @@ pub struct Frame { } impl Frame { - pub fn update(&mut self, state: &SharedGameState, player: &Player, stage: &Stage) { - if (stage.map.width - 1) * 16 < state.canvas_size.0 as usize { - self.x = -(((state.canvas_size.0 as isize - ((stage.map.width - 1) * 16) as isize) * 0x200) / 2); + pub fn update(&mut self, player: &Player, stage: &Stage, canvas_size: (f32, f32)) { + if (stage.map.width - 1) * 16 < canvas_size.0 as usize { + self.x = -(((canvas_size.0 as isize - ((stage.map.width - 1) * 16) as isize) * 0x200) / 2); } else { - self.x += (player.target_x - (state.canvas_size.0 as isize * 0x200 / 2) - self.x) / self.wait; + self.x += (player.target_x - (canvas_size.0 as isize * 0x200 / 2) - self.x) / self.wait; if self.x < 0 { self.x = 0; } - let max_x = (((stage.map.width as isize - 1) * 16) - state.canvas_size.0 as isize) * 0x200; + let max_x = (((stage.map.width as isize - 1) * 16) - canvas_size.0 as isize) * 0x200; if self.x > max_x { self.x = max_x; } } - if (stage.map.height - 1) * 16 < state.canvas_size.1 as usize { - self.y = -(((state.canvas_size.1 as isize - ((stage.map.height - 1) * 16) as isize) * 0x200) / 2); + if (stage.map.height - 1) * 16 < canvas_size.1 as usize { + self.y = -(((canvas_size.1 as isize - ((stage.map.height - 1) * 16) as isize) * 0x200) / 2); } else { - self.y += (player.target_y - (state.canvas_size.1 as isize * 0x200 / 2) - self.y) / self.wait; + self.y += (player.target_y - (canvas_size.1 as isize * 0x200 / 2) - self.y) / self.wait; if self.y < 0 { self.y = 0; } - let max_y = (((stage.map.height as isize - 1) * 16) - state.canvas_size.1 as isize) * 0x200; + let max_y = (((stage.map.height as isize - 1) * 16) - canvas_size.1 as isize) * 0x200; if self.y > max_y { self.y = max_y; } diff --git a/src/game_state.rs b/src/game_state.rs new file mode 100644 index 0000000..dcd2eb1 --- /dev/null +++ b/src/game_state.rs @@ -0,0 +1,101 @@ +use ggez::{Context, GameResult}; +use log::info; + +use crate::bitfield; +use crate::entity::GameEntity; +use crate::frame::Frame; +use crate::GameContext; +use crate::player::Player; +use crate::scene::game_scene::GameScene; +use crate::stage::Stage; + +bitfield! { + pub struct KeyState(u16); + impl Debug; + pub left, set_left: 0; + pub right, set_right: 1; + pub up, set_up: 2; + pub down, set_down: 3; + pub map, set_map: 4; + pub jump, set_jump: 5; + pub fire, set_fire: 6; + pub weapon_next, set_weapon_next: 7; + pub weapon_prev, set_weapon_prev: 8; +} + +bitfield! { + pub struct GameFlags(u32); + impl Debug; + pub flag_x01, set_flag_x01: 0; + pub control_enabled, set_control_enabled: 1; + pub flag_x04, set_flag_x04: 2; +} + +pub struct GameState { + pub tick: usize, + pub stage: Stage, + pub frame: Frame, + pub flags: GameFlags, + pub key_state: KeyState, + pub key_trigger: KeyState, + player: Player, + key_old: u16, +} + +impl GameState { + pub fn new(game_ctx: &mut GameContext, ctx: &mut Context) -> GameResult { + Ok(Self { + tick: 0, + stage: Stage::empty(), + player: Player::new(&game_ctx.constants, ctx)?, + frame: Frame { + x: 0, + y: 0, + wait: 16, + }, + flags: GameFlags(0), + key_state: KeyState(0), + key_trigger: KeyState(0), + key_old: 0, + }) + } + + pub fn player(&self) -> &Player { + &self.player + } + + pub fn player_mut(&mut self) -> &mut Player { + &mut self.player + } + + pub fn update_key_trigger(&mut self) { + let trigger = self.key_state.0 & (self.key_state.0 ^ self.key_old); + self.key_old = self.key_state.0; + self.key_trigger = KeyState(trigger); + } + + pub fn switch_to_stage(&mut self, id: usize, game_ctx: &mut GameContext, ctx: &mut Context) -> GameResult { + let stage = Stage::load(ctx, &game_ctx.base_path, &game_ctx.stages[id])?; + info!("Loaded stage: {}", stage.data.name); + info!("Map size: {}x{}", stage.map.width, stage.map.height); + + game_ctx.next_scene = Some(Box::new(GameScene::new(self, game_ctx, ctx)?)); + self.stage = stage; + + Ok(()) + } + + pub fn init(&mut self, game_ctx: &mut GameContext, ctx: &mut Context) -> GameResult { + self.tick = 0; + self.player = Player::new(&game_ctx.constants, ctx)?; + + self.player.x = 700 * 0x200; + self.player.y = 1000 * 0x200; + + self.flags.set_flag_x01(true); + self.flags.set_control_enabled(true); + + //game_ctx.sound_manager.play_song(ctx)?; + Ok(()) + } +} diff --git a/src/live_debugger.rs b/src/live_debugger.rs new file mode 100644 index 0000000..355bd7a --- /dev/null +++ b/src/live_debugger.rs @@ -0,0 +1,38 @@ +use ggez::{Context, GameResult}; +use imgui::{Condition, im_str, Window}; + +use crate::game_state::GameState; +use crate::GameContext; + +pub struct LiveDebugger { + selected_item: i32, +} + +impl LiveDebugger { + pub fn new() -> Self { + Self { + selected_item: 0, + } + } + + pub fn run(&mut self, state: &mut GameState, game_ctx: &GameContext, ctx: &mut Context, ui: &mut imgui::Ui) -> GameResult { + Window::new(im_str!("Live Debugger")) + .size([300.0, 100.0], Condition::FirstUseEver) + .build(ui, || { + ui.text(format!( + "Player position: ({:.1},{:.1})", + state.player().x as f32 / 512.0, + state.player().y as f32 / 512.0, + )); + }); + + Window::new(im_str!("Stages")) + .size([240.0, 320.0], Condition::FirstUseEver) + .build(ui, || { + ui.list_box(im_str!("Stage table"), &mut self.selected_item, + &[im_str!("Null"), im_str!("Egg Corridor")], 10); + }); + + Ok(()) + } +} diff --git a/src/main.rs b/src/main.rs index ed5f97a..162cec3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,7 +7,7 @@ use std::path; use ggez::{Context, ContextBuilder, event, filesystem, GameResult}; use ggez::conf::{WindowMode, WindowSetup}; -use ggez::event::{KeyCode, KeyMods}; +use ggez::event::KeyCode; use ggez::event::winit_event::{ElementState, Event, KeyboardInput, WindowEvent}; use ggez::graphics; use ggez::graphics::DrawParam; @@ -18,17 +18,25 @@ use log::*; use pretty_env_logger::env_logger::Env; use crate::engine_constants::EngineConstants; +use crate::entity::GameEntity; +use crate::game_state::GameState; +use crate::game_state::KeyState; +use crate::live_debugger::LiveDebugger; +use crate::scene::game_scene::GameScene; use crate::scene::loading_scene::LoadingScene; use crate::scene::Scene; use crate::sound::SoundManager; -use crate::stage::StageData; +use crate::stage::{Stage, StageData}; use crate::texture_set::TextureSet; +use crate::ui::UI; mod common; mod engine_constants; mod entity; mod enemy; mod frame; +mod game_state; +mod live_debugger; mod map; mod player; mod player_hit; @@ -37,40 +45,18 @@ mod stage; mod sound; mod text_script; mod texture_set; - -bitfield! { - pub struct KeyState(u16); - impl Debug; - left, set_left: 0; - right, set_right: 1; - up, set_up: 2; - down, set_down: 3; - map, set_map: 4; - jump, set_jump: 5; - fire, set_fire: 6; - weapon_next, set_weapon_next: 7; - weapon_prev, set_weapon_prev: 8; -} - -bitfield! { - pub struct GameFlags(u32); - impl Debug; - pub flag_x01, set_flag_x01: 0; - pub control_enabled, set_control_enabled: 1; - pub flag_x04, set_flag_x04: 2; -} +mod ui; struct Game { scene: Option>, - state: SharedGameState, + state: Option, + ctx: GameContext, + ui: UI, scaled_matrix: ColumnMatrix4, def_matrix: ColumnMatrix4, } -pub struct SharedGameState { - pub flags: GameFlags, - pub key_state: KeyState, - pub key_trigger: KeyState, +pub struct GameContext { pub texture_set: TextureSet, pub base_path: String, pub stages: Vec, @@ -80,16 +66,6 @@ pub struct SharedGameState { pub canvas_size: (f32, f32), pub screen_size: (f32, f32), pub next_scene: Option>, - key_old: u16, -} - -impl SharedGameState { - pub fn update_key_trigger(&mut self) { - let mut trigger = self.key_state.0 ^ self.key_old; - trigger = self.key_state.0 & trigger; - self.key_old = self.key_state.0; - self.key_trigger = KeyState(trigger); - } } impl Game { @@ -112,14 +88,8 @@ impl Game { let s = Game { scene: None, - scaled_matrix: DrawParam::new() - .scale(Vector2::new(scale, scale)) - .to_matrix(), - def_matrix: DrawParam::new().to_matrix(), - state: SharedGameState { - flags: GameFlags(0), - key_state: KeyState(0), - key_trigger: KeyState(0), + state: None, + ctx: GameContext { texture_set: TextureSet::new(base_path), base_path: str!(base_path), stages: Vec::new(), @@ -129,16 +99,24 @@ impl Game { screen_size, canvas_size, next_scene: None, - key_old: 0, }, + ui: UI::new(ctx)?, + scaled_matrix: DrawParam::new() + .scale(Vector2::new(scale, scale)) + .to_matrix(), + def_matrix: DrawParam::new().to_matrix(), }; Ok(s) } fn update(&mut self, ctx: &mut Context) -> GameResult { - if self.scene.is_some() { - self.scene.as_mut().unwrap().tick(&mut self.state, ctx)?; + if self.state.is_none() { + self.state = Some(GameState::new(&mut self.ctx, ctx)?); + } + + if self.scene.is_some() && self.state.is_some() { + self.scene.as_mut().unwrap().tick(self.state.as_mut().unwrap(), &mut self.ctx, ctx)?; } Ok(()) } @@ -148,49 +126,52 @@ impl Game { graphics::set_transform(ctx, self.scaled_matrix); graphics::apply_transformations(ctx)?; - if self.scene.is_some() { - self.scene.as_ref().unwrap().draw(&mut self.state, ctx)?; + if let (Some(scene), Some(state)) = (self.scene.as_mut(), self.state.as_mut()) { + scene.draw(state, &mut self.ctx, ctx)?; graphics::set_transform(ctx, self.def_matrix); graphics::apply_transformations(ctx)?; - self.scene.as_ref().unwrap().overlay_draw(&mut self.state, ctx)?; + + self.ui.draw(state, &mut self.ctx, ctx, scene)?; } graphics::present(ctx)?; Ok(()) } - fn key_down_event(&mut self, _ctx: &mut Context, key_code: KeyCode, _key_mod: KeyMods, repeat: bool) { + fn key_down_event(&mut self, _ctx: &mut Context, key_code: KeyCode, repeat: bool) { if repeat { return; } // todo: proper keymaps? - let state = &mut self.state; - match key_code { - KeyCode::Left => { state.key_state.set_left(true) } - KeyCode::Right => { state.key_state.set_right(true) } - KeyCode::Up => { state.key_state.set_up(true) } - KeyCode::Down => { state.key_state.set_down(true) } - KeyCode::Z => { state.key_state.set_jump(true) } - KeyCode::X => { state.key_state.set_fire(true) } - KeyCode::A => { state.key_state.set_weapon_prev(true) } - KeyCode::S => { state.key_state.set_weapon_next(true) } - _ => {} + if let Some(state) = self.state.as_mut() { + match key_code { + KeyCode::Left => { state.key_state.set_left(true) } + KeyCode::Right => { state.key_state.set_right(true) } + KeyCode::Up => { state.key_state.set_up(true) } + KeyCode::Down => { state.key_state.set_down(true) } + KeyCode::Z => { state.key_state.set_jump(true) } + KeyCode::X => { state.key_state.set_fire(true) } + KeyCode::A => { state.key_state.set_weapon_prev(true) } + KeyCode::S => { state.key_state.set_weapon_next(true) } + _ => {} + } } } - fn key_up_event(&mut self, _ctx: &mut Context, key_code: KeyCode, _key_mod: KeyMods) { - let state = &mut self.state; - match key_code { - KeyCode::Left => { state.key_state.set_left(false) } - KeyCode::Right => { state.key_state.set_right(false) } - KeyCode::Up => { state.key_state.set_up(false) } - KeyCode::Down => { state.key_state.set_down(false) } - KeyCode::Z => { state.key_state.set_jump(false) } - KeyCode::X => { state.key_state.set_fire(false) } - KeyCode::A => { state.key_state.set_weapon_prev(false) } - KeyCode::S => { state.key_state.set_weapon_next(false) } - _ => {} + fn key_up_event(&mut self, _ctx: &mut Context, key_code: KeyCode) { + if let Some(state) = self.state.as_mut() { + match key_code { + KeyCode::Left => { state.key_state.set_left(false) } + KeyCode::Right => { state.key_state.set_right(false) } + KeyCode::Up => { state.key_state.set_up(false) } + KeyCode::Down => { state.key_state.set_down(false) } + KeyCode::Z => { state.key_state.set_jump(false) } + KeyCode::X => { state.key_state.set_fire(false) } + KeyCode::A => { state.key_state.set_weapon_prev(false) } + KeyCode::S => { state.key_state.set_weapon_next(false) } + _ => {} + } } } } @@ -215,40 +196,35 @@ pub fn main() -> GameResult { .add_resource_path(resource_dir); let (ctx, event_loop) = &mut cb.build()?; - let state = &mut Game::new(ctx)?; - state.state.next_scene = Some(Box::new(LoadingScene::new())); + let game = &mut Game::new(ctx)?; + game.ctx.next_scene = Some(Box::new(LoadingScene::new())); while ctx.continuing { ctx.timer_context.tick(); event_loop.poll_events(|event| { ctx.process_event(&event); + game.ui.handle_events(ctx, &event); + match event { Event::WindowEvent { event, .. } => match event { WindowEvent::CloseRequested => event::quit(ctx), WindowEvent::KeyboardInput { - input: - KeyboardInput { - state: ElementState::Pressed, + input: KeyboardInput { virtual_keycode: Some(keycode), - modifiers, + state: input_state, .. }, .. } => { - let repeat = keyboard::is_key_repeated(ctx); - state.key_down_event(ctx, keycode, modifiers.into(), repeat); - } - WindowEvent::KeyboardInput { - input: - KeyboardInput { - state: ElementState::Released, - virtual_keycode: Some(keycode), - modifiers, - .. - }, - .. - } => { - state.key_up_event(ctx, keycode, modifiers.into()); + match input_state { + ElementState::Pressed => { + let repeat = keyboard::is_key_repeated(ctx); + game.key_down_event(ctx, keycode, repeat); + } + ElementState::Released => { + game.key_up_event(ctx, keycode); + } + } } _ => {} }, @@ -256,14 +232,13 @@ pub fn main() -> GameResult { } }); - state.update(ctx)?; - state.draw(ctx)?; + game.update(ctx)?; + game.draw(ctx)?; - if state.state.next_scene.is_some() { - mem::swap(&mut state.scene, &mut state.state.next_scene); - state.state.next_scene = None; - - state.scene.as_mut().unwrap().init(&mut state.state, ctx)?; + if game.ctx.next_scene.is_some() && game.state.is_some() { + mem::swap(&mut game.scene, &mut game.ctx.next_scene); + game.ctx.next_scene = None; + game.scene.as_mut().unwrap().init(game.state.as_mut().unwrap(), &mut game.ctx, ctx)?; } } Ok(()) diff --git a/src/player.rs b/src/player.rs index 929d367..9c92aac 100644 --- a/src/player.rs +++ b/src/player.rs @@ -3,10 +3,10 @@ use num_traits::clamp; use crate::bitfield; use crate::common::{Direction, Rect}; -use crate::engine_constants::PhysicsConsts; +use crate::engine_constants::{EngineConstants, PhysicsConsts}; use crate::entity::GameEntity; -use crate::frame::Frame; -use crate::SharedGameState; +use crate::game_state::GameState; +use crate::GameContext; use crate::str; bitfield! { @@ -103,12 +103,8 @@ pub struct Player { } impl Player { - pub fn new(state: &mut SharedGameState, ctx: &mut Context) -> GameResult { - let constants = &state.constants; - + pub fn new(constants: &EngineConstants, ctx: &mut Context) -> GameResult { let tex_player_name = str!("MyChar"); - state.texture_set.ensure_texture_loaded(ctx, constants, &tex_player_name)?; - Ok(Player { x: 0, y: 0, @@ -146,7 +142,7 @@ impl Player { }) } - fn tick_normal(&mut self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult<()> { + fn tick_normal(&mut self, state: &GameState, constants: &EngineConstants) -> GameResult<()> { if self.cond.cond_x02() { return Ok(()); } @@ -224,23 +220,23 @@ impl Player { if state.key_state.up() { self.boost_sw = 2; self.xm = 0; - self.ym = state.constants.booster.b2_0_up; + self.ym = constants.booster.b2_0_up; } else if state.key_state.left() { self.boost_sw = 2; self.xm = 0; - self.ym = state.constants.booster.b2_0_left; + self.ym = constants.booster.b2_0_left; } else if state.key_state.right() { self.boost_sw = 2; self.xm = 0; - self.ym = state.constants.booster.b2_0_right; + self.ym = constants.booster.b2_0_right; } else if state.key_state.down() { self.boost_sw = 2; self.xm = 0; - self.ym = state.constants.booster.b2_0_down; + self.ym = constants.booster.b2_0_down; } else { self.boost_sw = 2; self.xm = 0; - self.ym = state.constants.booster.b2_0_up_nokey; + self.ym = constants.booster.b2_0_up_nokey; } } } @@ -455,11 +451,11 @@ impl Player { Ok(()) } - fn tick_stream(&mut self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult<()> { + fn tick_stream(&mut self, state: &GameState, constants: &EngineConstants) -> GameResult<()> { Ok(()) } - fn tick_animation(&mut self, state: &SharedGameState) { + fn tick_animation(&mut self, state: &GameState, constants: &EngineConstants) { if self.cond.cond_x02() { return; } @@ -524,10 +520,10 @@ impl Player { match self.direction { Direction::Left => { - self.anim_rect = state.constants.my_char.animations_left[self.anim_num]; + self.anim_rect = constants.my_char.animations_left[self.anim_num]; } Direction::Right => { - self.anim_rect = state.constants.my_char.animations_right[self.anim_num]; + self.anim_rect = constants.my_char.animations_right[self.anim_num]; } _ => {} } @@ -537,7 +533,12 @@ impl Player { } impl GameEntity for Player { - fn tick(&mut self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult<()> { + fn init(&mut self, state: &GameState, game_ctx: &mut GameContext, ctx: &mut Context) -> GameResult { + game_ctx.texture_set.ensure_texture_loaded(ctx, &game_ctx.constants, &self.tex_player_name)?; + Ok(()) + } + + fn tick(&mut self, state: &GameState, constants: &EngineConstants, ctx: &mut Context) -> GameResult { if !self.cond.visible() { return Ok(()); } @@ -559,31 +560,31 @@ impl GameEntity for Player { // AirProcess(); // todo } - self.tick_normal(state, ctx)?; + self.tick_normal(state, constants)?; } 1 => { - self.tick_stream(state, ctx)?; + self.tick_stream(state, constants)?; } _ => {} } self.cond.set_cond_x20(false); - self.tick_animation(state); + self.tick_animation(state, constants); Ok(()) } - fn draw(&self, state: &mut SharedGameState, ctx: &mut Context, frame: &Frame) -> GameResult<()> { + fn draw(&self, state: &GameState, game_ctx: &mut GameContext, ctx: &mut Context) -> GameResult { if !self.cond.visible() || self.cond.cond_x02() { return Ok(()); } // todo draw weapon - if let Some(batch) = state.texture_set.tex_map.get_mut(&self.tex_player_name) { + if let Some(batch) = game_ctx.texture_set.tex_map.get_mut(&self.tex_player_name) { batch.add_rect( - (((self.x - self.view.left as isize) / 0x200) - (frame.x / 0x200)) as f32, - (((self.y - self.view.top as isize) / 0x200) - (frame.y / 0x200)) as f32, + (((self.x - self.view.left as isize) / 0x200) - (state.frame.x / 0x200)) as f32, + (((self.y - self.view.top as isize) / 0x200) - (state.frame.y / 0x200)) as f32, &self.anim_rect, ); batch.draw(ctx)?; diff --git a/src/player_hit.rs b/src/player_hit.rs index 522765c..edbfcab 100644 --- a/src/player_hit.rs +++ b/src/player_hit.rs @@ -1,14 +1,13 @@ use num_traits::clamp; +use crate::game_state::GameState; use crate::player::Player; -use crate::stage::Stage; -use crate::SharedGameState; const OFF_X: &[isize; 4] = &[0, 1, 0, 1]; const OFF_Y: &[isize; 4] = &[0, 0, 1, 1]; impl Player { - fn judge_hit_block(&mut self, state: &SharedGameState, x: isize, y: isize) { + fn judge_hit_block(&mut self, x: isize, y: isize, state: &GameState) { // left wall if (self.y - self.hit.top as isize) < (y * 0x10 + 4) * 0x200 && self.y + self.hit.bottom as isize > (y * 0x10 - 4) * 0x200 @@ -82,7 +81,7 @@ impl Player { } } - fn judge_hit_triangle_a(&mut self, state: &SharedGameState, x: isize, y: isize) { + fn judge_hit_triangle_a(&mut self, x: isize, y: isize) { if self.x < (x * 0x10 + 8) * 0x200 && self.x > (x * 0x10 - 8) * 0x200 && (self.y - self.hit.top as isize) < (y * 0x10 * 0x200) - (self.x - x * 0x10 * 0x200) / 2 + 0x800 @@ -101,7 +100,7 @@ impl Player { } } - fn judge_hit_triangle_b(&mut self, state: &SharedGameState, x: isize, y: isize) { + fn judge_hit_triangle_b(&mut self, x: isize, y: isize) { if self.x < (x * 0x10 + 8) * 0x200 && self.x > (x * 0x10 - 8) * 0x200 && (self.y - self.hit.top as isize) < (y * 0x10 * 0x200) - (self.x - x * 0x10 * 0x200) / 2 - 0x800 @@ -120,7 +119,7 @@ impl Player { } } - fn judge_hit_triangle_c(&mut self, state: &SharedGameState, x: isize, y: isize) { + fn judge_hit_triangle_c(&mut self, x: isize, y: isize) { if self.x < (x * 0x10 + 8) * 0x200 && self.x > (x * 0x10 - 8) * 0x200 && (self.y - self.hit.top as isize) < (y * 0x10 * 0x200) + (self.x - x * 0x10 * 0x200) / 2 - 0x800 @@ -139,7 +138,7 @@ impl Player { } } - fn judge_hit_triangle_d(&mut self, state: &SharedGameState, x: isize, y: isize) { + fn judge_hit_triangle_d(&mut self, x: isize, y: isize) { if (self.x < (x * 0x10 + 8) * 0x200) && (self.x > (x * 0x10 - 8) * 0x200) && (self.y - self.hit.top as isize) < (y * 0x10 * 0x200) + (self.x - x * 0x10 * 0x200) / 2 + 0x800 @@ -158,7 +157,7 @@ impl Player { } } - fn judge_hit_triangle_e(&mut self, state: &SharedGameState, x: isize, y: isize) { + fn judge_hit_triangle_e(&mut self, x: isize, y: isize) { self.flags.set_flag_x10000(true); if (self.x < (x * 0x10 + 8) * 0x200) @@ -180,7 +179,7 @@ impl Player { } } - fn judge_hit_triangle_f(&mut self, state: &SharedGameState, x: isize, y: isize) { + fn judge_hit_triangle_f(&mut self, x: isize, y: isize) { self.flags.set_flag_x20000(true); if (self.x < (x * 0x10 + 8) * 0x200) @@ -202,7 +201,7 @@ impl Player { } } - fn judge_hit_triangle_g(&mut self, state: &SharedGameState, x: isize, y: isize) { + fn judge_hit_triangle_g(&mut self, x: isize, y: isize) { self.flags.set_flag_x40000(true); if (self.x < (x * 0x10 + 8) * 0x200) @@ -224,7 +223,7 @@ impl Player { } } - fn judge_hit_triangle_h(&mut self, state: &SharedGameState, x: isize, y: isize) { + fn judge_hit_triangle_h(&mut self, x: isize, y: isize) { self.flags.set_flag_x80000(true); if (self.x < (x * 0x10 + 8) * 0x200) @@ -246,7 +245,7 @@ impl Player { } } - fn judge_hit_water(&mut self, state: &SharedGameState, x: isize, y: isize) { + fn judge_hit_water(&mut self, x: isize, y: isize) { if (self.x - self.hit.right as isize) < (x * 0x10 + 5) * 0x200 && (self.x + self.hit.right as isize) > (x * 0x10 - 5) * 0x200 && (self.y - self.hit.top as isize) < (y * 0x10 + 5) * 0x200 @@ -255,55 +254,55 @@ impl Player { } } - pub fn tick_map_collisions(&mut self, state: &SharedGameState, stage: &Stage) { - let x = clamp(self.x / 0x10 / 0x200, 0, stage.map.width as isize); - let y = clamp(self.y / 0x10 / 0x200, 0, stage.map.height as isize); + pub fn tick_map_collisions(&mut self, state: &GameState) { + let x = clamp(self.x / 0x10 / 0x200, 0, state.stage.map.width as isize); + let y = clamp(self.y / 0x10 / 0x200, 0, state.stage.map.height as isize); for (ox, oy) in OFF_X.iter().zip(OFF_Y) { - let attrib = stage.map.get_attribute((x + *ox) as usize, (y + *oy) as usize); + let attrib = state.stage.map.get_attribute((x + *ox) as usize, (y + *oy) as usize); match attrib { // Block 0x02 | 0x60 => { - self.judge_hit_water(state, x + *ox, y + *oy); + self.judge_hit_water(x + *ox, y + *oy); } 0x05 | 0x41 | 0x43 | 0x46 => { - self.judge_hit_block(state, x + *ox, y + *oy); + self.judge_hit_block(x + *ox, y + *oy, state); } 0x50 | 0x70 => { - self.judge_hit_triangle_a(state, x + *ox, y + *oy); - if attrib & 0x20 != 0 { self.judge_hit_water(state, x + *ox, y + *oy); } + self.judge_hit_triangle_a(x + *ox, y + *oy); + if attrib & 0x20 != 0 { self.judge_hit_water(x + *ox, y + *oy); } } 0x51 | 0x71 => { - self.judge_hit_triangle_b(state, x + *ox, y + *oy); - if attrib & 0x20 != 0 { self.judge_hit_water(state, x + *ox, y + *oy); } + self.judge_hit_triangle_b(x + *ox, y + *oy); + if attrib & 0x20 != 0 { self.judge_hit_water(x + *ox, y + *oy); } } 0x52 | 0x72 => { - self.judge_hit_triangle_c(state, x + *ox, y + *oy); - if attrib & 0x20 != 0 { self.judge_hit_water(state, x + *ox, y + *oy); } + self.judge_hit_triangle_c(x + *ox, y + *oy); + if attrib & 0x20 != 0 { self.judge_hit_water(x + *ox, y + *oy); } } 0x53 | 0x73 => { - self.judge_hit_triangle_d(state, x + *ox, y + *oy); - if attrib & 0x20 != 0 { self.judge_hit_water(state, x + *ox, y + *oy); } + self.judge_hit_triangle_d(x + *ox, y + *oy); + if attrib & 0x20 != 0 { self.judge_hit_water(x + *ox, y + *oy); } } 0x54 | 0x74 => { - self.judge_hit_triangle_e(state, x + *ox, y + *oy); - if attrib & 0x20 != 0 { self.judge_hit_water(state, x + *ox, y + *oy); } + self.judge_hit_triangle_e(x + *ox, y + *oy); + if attrib & 0x20 != 0 { self.judge_hit_water(x + *ox, y + *oy); } } 0x55 | 0x75 => { - self.judge_hit_triangle_f(state, x + *ox, y + *oy); - if attrib & 0x20 != 0 { self.judge_hit_water(state, x + *ox, y + *oy); } + self.judge_hit_triangle_f(x + *ox, y + *oy); + if attrib & 0x20 != 0 { self.judge_hit_water(x + *ox, y + *oy); } } 0x56 | 0x76 => { - self.judge_hit_triangle_g(state, x + *ox, y + *oy); - if attrib & 0x20 != 0 { self.judge_hit_water(state, x + *ox, y + *oy); } + self.judge_hit_triangle_g(x + *ox, y + *oy); + if attrib & 0x20 != 0 { self.judge_hit_water(x + *ox, y + *oy); } } 0x57 | 0x77 => { - self.judge_hit_triangle_h(state, x + *ox, y + *oy); - if attrib & 0x20 != 0 { self.judge_hit_water(state, x + *ox, y + *oy); } + self.judge_hit_triangle_h(x + *ox, y + *oy); + if attrib & 0x20 != 0 { self.judge_hit_water(x + *ox, y + *oy); } } 0x61 => { - self.judge_hit_water(state, x + *ox, y + *oy); - self.judge_hit_block(state, x + *ox, y + *oy); + self.judge_hit_water(x + *ox, y + *oy); + self.judge_hit_block(x + *ox, y + *oy, state); } _ => {} } diff --git a/src/scene/game_scene.rs b/src/scene/game_scene.rs index 4a5b624..506da5d 100644 --- a/src/scene/game_scene.rs +++ b/src/scene/game_scene.rs @@ -1,22 +1,18 @@ use ggez::{Context, GameResult}; +use ggez::GameError::EventLoopError; use ggez::nalgebra::clamp; -use log::info; -use num_traits::abs; use crate::common::Rect; use crate::entity::GameEntity; -use crate::frame::Frame; -use crate::player::Player; +use crate::game_state::GameState; +use crate::GameContext; use crate::scene::Scene; -use crate::SharedGameState; -use crate::stage::{BackgroundType, Stage}; +use crate::stage::BackgroundType; use crate::str; +use crate::live_debugger::LiveDebugger; pub struct GameScene { - pub tick: usize, - pub stage: Stage, - pub frame: Frame, - pub player: Player, + debugger: LiveDebugger, tex_tileset_name: String, tex_background_name: String, tex_hud_name: String, @@ -38,28 +34,17 @@ pub enum Alignment { } impl GameScene { - pub fn new(state: &mut SharedGameState, ctx: &mut Context, id: usize) -> GameResult { - let stage = Stage::load(ctx, &state.base_path, &state.stages[id])?; - info!("Loaded stage: {}", stage.data.name); - info!("Map size: {}x{}", stage.map.width, stage.map.height); - - let tex_tileset_name = ["Stage/", &stage.data.tileset.filename()].join(""); - let tex_background_name = stage.data.background.filename(); + pub fn new(state: &GameState, game_ctx: &mut GameContext, ctx: &mut Context) -> GameResult { + let tex_tileset_name = str!(["Stage/", &state.stage.data.tileset.filename()].join("")); + let tex_background_name = state.stage.data.background.filename(); let tex_hud_name = str!("TextBox"); - state.texture_set.ensure_texture_loaded(ctx, &state.constants, &tex_tileset_name)?; - state.texture_set.ensure_texture_loaded(ctx, &state.constants, &tex_background_name)?; - state.texture_set.ensure_texture_loaded(ctx, &state.constants, &tex_hud_name)?; + game_ctx.texture_set.ensure_texture_loaded(ctx, &game_ctx.constants, &tex_tileset_name)?; + game_ctx.texture_set.ensure_texture_loaded(ctx, &game_ctx.constants, &tex_background_name)?; + game_ctx.texture_set.ensure_texture_loaded(ctx, &game_ctx.constants, &tex_hud_name)?; Ok(Self { - tick: 0, - stage, - player: Player::new(state, ctx)?, - frame: Frame { - x: 0, - y: 0, - wait: 16, - }, + debugger: LiveDebugger::new(), tex_tileset_name, tex_background_name, tex_hud_name, @@ -68,8 +53,8 @@ impl GameScene { }) } - fn draw_number(&self, x: f32, y: f32, val: usize, align: Alignment, state: &mut SharedGameState, ctx: &mut Context) -> GameResult { - let set = state.texture_set.tex_map.get_mut(&self.tex_hud_name); + fn draw_number(&self, x: f32, y: f32, val: usize, align: Alignment, game_ctx: &mut GameContext, ctx: &mut Context) -> GameResult { + let set = game_ctx.texture_set.tex_map.get_mut(&self.tex_hud_name); if set.is_none() { return Ok(()); } @@ -87,12 +72,11 @@ impl GameScene { Ok(()) } - fn draw_hud(&self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult { - let set = state.texture_set.tex_map.get_mut(&self.tex_hud_name); + fn draw_hud(&self, state: &GameState, game_ctx: &mut GameContext, ctx: &mut Context) -> GameResult { + let set = game_ctx.texture_set.tex_map.get_mut(&self.tex_hud_name); if set.is_none() { return Ok(()); } - let batch = set.unwrap(); // todo: max ammo display @@ -114,30 +98,30 @@ impl GameScene { &Rect::::new_size(0, 40, 64, 8)); // bar batch.add_rect(40.0, 40.0, - &Rect::::new_size(0, 32, ((self.life_bar as usize * 40) / self.player.max_life as usize) - 1, 8)); + &Rect::::new_size(0, 32, ((self.life_bar as usize * 40) / state.player().max_life as usize) - 1, 8)); // life batch.add_rect(40.0, 40.0, - &Rect::::new_size(0, 24, ((self.player.life as usize * 40) / self.player.max_life as usize) - 1, 8)); + &Rect::::new_size(0, 24, ((state.player().life as usize * 40) / state.player().max_life as usize) - 1, 8)); batch.draw(ctx)?; - self.draw_number(40.0, 40.0, self.life_bar as usize, Alignment::Right, state, ctx)?; + self.draw_number(40.0, 40.0, self.life_bar as usize, Alignment::Right, game_ctx, ctx)?; Ok(()) } - fn draw_background(&self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult { - let set = state.texture_set.tex_map.get_mut(&self.tex_background_name); + fn draw_background(&self, state: &GameState, game_ctx: &mut GameContext, ctx: &mut Context) -> GameResult { + let set = game_ctx.texture_set.tex_map.get_mut(&self.tex_background_name); if set.is_none() { return Ok(()); } let batch = set.unwrap(); - match self.stage.data.background_type { + match state.stage.data.background_type { BackgroundType::Stationary => { - let count_x = state.canvas_size.0 as usize / batch.width() + 1; - let count_y = state.canvas_size.1 as usize / batch.height() + 1; + let count_x = game_ctx.canvas_size.0 as usize / batch.width() + 1; + let count_y = game_ctx.canvas_size.1 as usize / batch.height() + 1; for y in 0..count_y { for x in 0..count_x { @@ -146,11 +130,11 @@ impl GameScene { } } BackgroundType::MoveDistant => { - let off_x = self.frame.x as usize / 2 % (batch.width() * 0x200); - let off_y = self.frame.y as usize / 2 % (batch.height() * 0x200); + let off_x = state.frame.x as usize / 2 % (batch.width() * 0x200); + let off_y = state.frame.y as usize / 2 % (batch.height() * 0x200); - let count_x = state.canvas_size.0 as usize / batch.width() + 2; - let count_y = state.canvas_size.1 as usize / batch.height() + 2; + let count_x = game_ctx.canvas_size.0 as usize / batch.width() + 2; + let count_y = game_ctx.canvas_size.1 as usize / batch.height() + 2; for y in 0..count_y { for x in 0..count_x { @@ -164,27 +148,27 @@ impl GameScene { BackgroundType::Black => {} BackgroundType::Autoscroll => {} BackgroundType::OutsideWind | BackgroundType::Outside => { - let offset = (self.tick % 640) as isize; + let offset = (state.tick % 640) as isize; - batch.add_rect(((state.canvas_size.0 - 320.0) / 2.0).floor(), 0.0, + batch.add_rect(((game_ctx.canvas_size.0 - 320.0) / 2.0).floor(), 0.0, &Rect::::new_size(0, 0, 320, 88)); - for x in ((-offset / 2)..(state.canvas_size.0 as isize)).step_by(320) { + for x in ((-offset / 2)..(game_ctx.canvas_size.0 as isize)).step_by(320) { batch.add_rect(x as f32, 88.0, &Rect::::new_size(0, 88, 320, 35)); } - for x in ((-offset % 320)..(state.canvas_size.0 as isize)).step_by(320) { + for x in ((-offset % 320)..(game_ctx.canvas_size.0 as isize)).step_by(320) { batch.add_rect(x as f32, 123.0, &Rect::::new_size(0, 123, 320, 23)); } - for x in ((-offset * 2)..(state.canvas_size.0 as isize)).step_by(320) { + for x in ((-offset * 2)..(game_ctx.canvas_size.0 as isize)).step_by(320) { batch.add_rect(x as f32, 146.0, &Rect::::new_size(0, 146, 320, 30)); } - for x in ((-offset * 4)..(state.canvas_size.0 as isize)).step_by(320) { + for x in ((-offset * 4)..(game_ctx.canvas_size.0 as isize)).step_by(320) { batch.add_rect(x as f32, 176.0, &Rect::::new_size(0, 176, 320, 64)); } @@ -196,34 +180,34 @@ impl GameScene { Ok(()) } - fn draw_tiles(&self, state: &mut SharedGameState, ctx: &mut Context, layer: TileLayer) -> GameResult { - if let Some(batch) = state.texture_set.tex_map.get_mut(&self.tex_tileset_name) { + fn draw_tiles(&self, layer: TileLayer, state: &GameState, game_ctx: &mut GameContext, ctx: &mut Context) -> GameResult { + if let Some(batch) = game_ctx.texture_set.tex_map.get_mut(&self.tex_tileset_name) { let mut rect = Rect::::new(0, 0, 16, 16); - let tile_start_x = clamp(self.frame.x / 0x200 / 16, 0, self.stage.map.width as isize) as usize; - let tile_start_y = clamp(self.frame.y / 0x200 / 16, 0, self.stage.map.height as isize) as usize; - let tile_end_x = clamp((self.frame.x / 0x200 + 8 + state.canvas_size.0 as isize) / 16 + 1, 0, self.stage.map.width as isize) as usize; - let tile_end_y = clamp((self.frame.y / 0x200 + 8 + state.canvas_size.1 as isize) / 16 + 1, 0, self.stage.map.height as isize) as usize; + let tile_start_x = clamp(state.frame.x / 0x200 / 16, 0, state.stage.map.width as isize) as usize; + let tile_start_y = clamp(state.frame.y / 0x200 / 16, 0, state.stage.map.height as isize) as usize; + let tile_end_x = clamp((state.frame.x / 0x200 + 8 + game_ctx.canvas_size.0 as isize) / 16 + 1, 0, state.stage.map.width as isize) as usize; + let tile_end_y = clamp((state.frame.y / 0x200 + 8 + game_ctx.canvas_size.1 as isize) / 16 + 1, 0, state.stage.map.height as isize) as usize; for y in tile_start_y..tile_end_y { for x in tile_start_x..tile_end_x { - let tile = *self.stage.map.tiles - .get((y * self.stage.map.width) + x) + let tile = *state.stage.map.tiles + .get((y * state.stage.map.width) + x) .unwrap(); match layer { TileLayer::Background => { - if self.stage.map.attrib[tile as usize] >= 0x20 { + if state.stage.map.attrib[tile as usize] >= 0x20 { continue; } } TileLayer::Foreground => { - let attr = self.stage.map.attrib[tile as usize]; + let attr = state.stage.map.attrib[tile as usize]; if attr < 0x40 || attr >= 0x80 { continue; } } - _ => {} + TileLayer::All => {} } rect.left = (tile as usize % 16) * 16; @@ -231,7 +215,7 @@ impl GameScene { rect.right = rect.left + 16; rect.bottom = rect.top + 16; - batch.add_rect((x as f32 * 16.0 - 8.0) - (self.frame.x / 0x200) as f32, (y as f32 * 16.0 - 8.0) - (self.frame.y / 0x200) as f32, &rect); + batch.add_rect((x as f32 * 16.0 - 8.0) - (state.frame.x / 0x200) as f32, (y as f32 * 16.0 - 8.0) - (state.frame.y / 0x200) as f32, &rect); } } @@ -242,35 +226,30 @@ impl GameScene { } impl Scene for GameScene { - fn init(&mut self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult { - state.sound_manager.play_song(ctx)?; - self.player.x = 700 * 0x200; - self.player.y = 1000 * 0x200; - //self.player.equip.set_booster_2_0(true); - state.flags.set_flag_x01(true); - state.flags.set_control_enabled(true); + fn init(&mut self, state: &mut GameState, game_ctx: &mut GameContext, ctx: &mut Context) -> GameResult { Ok(()) } - fn tick(&mut self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult { + fn tick(&mut self, state: &mut GameState, game_ctx: &mut GameContext, ctx: &mut Context) -> GameResult { state.update_key_trigger(); - if state.flags.flag_x01() { - self.player.tick(state, ctx)?; + /*if state.flags.flag_x01() { + state.player_mut().tick(state, &game_ctx.constants, ctx)?; + state.player_mut().flags.0 = 0; + state.player_mut().tick_map_collisions(state); + state.frame.update(state.player(), &state.stage, game_ctx.canvas_size); + }*/ - self.player.flags.0 = 0; - self.player.tick_map_collisions(state, &self.stage); - - self.frame.update(state, &self.player, &self.stage); - } + state.tick = state.tick.wrapping_add(1); + //state.tick(game_ctx, ctx)?; if state.flags.control_enabled() { // update health bar - if self.life_bar < self.player.life as usize { - self.life_bar = self.player.life as usize; + if self.life_bar < state.player().life as usize { + self.life_bar = state.player().life as usize; } - if self.life_bar > self.player.life as usize { + if self.life_bar > state.player().life as usize { self.life_bar_count += 1; if self.life_bar_count > 30 { self.life_bar -= 1; @@ -280,20 +259,21 @@ impl Scene for GameScene { } } - self.tick = self.tick.wrapping_add(1); Ok(()) } - fn draw(&self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult { - self.draw_background(state, ctx)?; - self.draw_tiles(state, ctx, TileLayer::Background)?; - self.player.draw(state, ctx, &self.frame)?; - self.draw_tiles(state, ctx, TileLayer::Foreground)?; + fn draw(&self, state: &GameState, game_ctx: &mut GameContext, ctx: &mut Context) -> GameResult { + self.draw_background(state, game_ctx, ctx)?; + self.draw_tiles(TileLayer::Background, state, game_ctx, ctx)?; + state.player().draw(state, game_ctx, ctx)?; + self.draw_tiles(TileLayer::Foreground, state, game_ctx, ctx)?; + self.draw_hud(state, game_ctx, ctx)?; - self.draw_hud(state, ctx)?; - self.draw_number(16.0, 50.0, abs(self.player.x) as usize, Alignment::Left, state, ctx)?; - self.draw_number(16.0, 58.0, abs(self.player.y) as usize, Alignment::Left, state, ctx)?; + Ok(()) + } + fn overlay_draw(&mut self, state: &mut GameState, game_ctx: &mut GameContext, ctx: &mut Context, ui: &mut imgui::Ui) -> GameResult { + self.debugger.run(state, game_ctx, ctx, ui)?; Ok(()) } } diff --git a/src/scene/loading_scene.rs b/src/scene/loading_scene.rs index 97a6f12..ab44757 100644 --- a/src/scene/loading_scene.rs +++ b/src/scene/loading_scene.rs @@ -1,8 +1,8 @@ use ggez::{Context, GameResult}; -use crate::scene::game_scene::GameScene; +use crate::game_state::GameState; +use crate::GameContext; use crate::scene::Scene; -use crate::SharedGameState; use crate::stage::StageData; pub struct LoadingScene { @@ -18,30 +18,32 @@ impl LoadingScene { } impl Scene for LoadingScene { - fn init(&mut self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult { - state.texture_set.ensure_texture_loaded(ctx, &state.constants, "Loading")?; + fn init(&mut self, state: &mut GameState, game_ctx: &mut GameContext, ctx: &mut Context) -> GameResult { + game_ctx.texture_set.ensure_texture_loaded(ctx, &game_ctx.constants, "Loading")?; Ok(()) } - fn tick(&mut self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult { + fn tick(&mut self, state: &mut GameState, game_ctx: &mut GameContext, ctx: &mut Context) -> GameResult { // deferred to let the loading image draw if self.tick == 1 { - let stages = StageData::load_stage_table(ctx, &state.base_path)?; - state.stages = stages; - state.next_scene = Some(Box::new(GameScene::new(state, ctx, 53)?)); + let stages = StageData::load_stage_table(ctx, &game_ctx.base_path)?; + game_ctx.stages = stages; + } else if self.tick == 2 { + state.init(game_ctx, ctx)?; + state.switch_to_stage(53, game_ctx, ctx)?; } self.tick += 1; Ok(()) } - fn draw(&self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult { - let loading = state.texture_set.tex_map.get_mut("Loading"); + fn draw(&self, state: &GameState, game_ctx: &mut GameContext, ctx: &mut Context) -> GameResult { + let loading = game_ctx.texture_set.tex_map.get_mut("Loading"); if loading.is_some() { let img = loading.unwrap(); - img.add(((state.canvas_size.0 - img.width() as f32) / 2.0).floor(), - ((state.canvas_size.1 - img.height() as f32) / 2.0).floor()); + img.add(((game_ctx.canvas_size.0 - img.width() as f32) / 2.0).floor(), + ((game_ctx.canvas_size.1 - img.height() as f32) / 2.0).floor()); img.draw(ctx)?; } diff --git a/src/scene/mod.rs b/src/scene/mod.rs index 402f7a2..c8c2bed 100644 --- a/src/scene/mod.rs +++ b/src/scene/mod.rs @@ -1,16 +1,17 @@ use ggez::{Context, GameResult}; -use crate::SharedGameState; +use crate::GameContext; +use crate::game_state::GameState; pub mod game_scene; pub mod loading_scene; pub trait Scene { - fn init(&mut self, _state: &mut SharedGameState, _ctx: &mut Context) -> GameResult { Ok(()) } + fn init(&mut self, _state: &mut GameState, _game_ctx: &mut GameContext, _ctx: &mut Context) -> GameResult { Ok(()) } - fn tick(&mut self, _state: &mut SharedGameState, _ctx: &mut Context) -> GameResult { Ok(()) } + fn tick(&mut self, _state: &mut GameState, _game_ctx: &mut GameContext, _ctx: &mut Context) -> GameResult { Ok(()) } - fn draw(&self, _state: &mut SharedGameState, _ctx: &mut Context) -> GameResult { Ok(()) } + fn draw(&self, _state: &GameState, _game_ctx: &mut GameContext, _ctx: &mut Context) -> GameResult { Ok(()) } - fn overlay_draw(&self, _state: &mut SharedGameState, _ctx: &mut Context) -> GameResult { Ok(()) } + fn overlay_draw(&mut self, _state: &mut GameState, _game_ctx: &mut GameContext, _ctx: &mut Context, _ui: &mut imgui::Ui) -> GameResult { Ok(()) } } diff --git a/src/sound/mod.rs b/src/sound/mod.rs index 02401b7..015e060 100644 --- a/src/sound/mod.rs +++ b/src/sound/mod.rs @@ -1,4 +1,4 @@ -use std::io::{Cursor, Read}; +use std::io::Cursor; use ggez::{Context, GameResult}; diff --git a/src/stage.rs b/src/stage.rs index 444fab6..0bab6c5 100644 --- a/src/stage.rs +++ b/src/stage.rs @@ -8,6 +8,7 @@ use ggez::GameError::ResourceLoadError; use log::info; use crate::map::Map; +use crate::str; #[derive(Debug, PartialEq, Eq, Hash)] pub struct NpcType { @@ -374,6 +375,27 @@ pub struct Stage { } impl Stage { + pub fn empty() -> Self { + Self { + map: Map { + attrib: [0u8; 256], + height: 16, + width: 16, + tiles: vec![0u8; 16 * 16], + }, + data: StageData { + map: str!("0"), + name: str!("Null"), + background: Background::new("bk0"), + background_type: BackgroundType::Black, + tileset: Tileset::new("0"), + boss_no: 0, + npc1: NpcType::new("0"), + npc2: NpcType::new("0"), + }, + } + } + pub fn load(ctx: &mut Context, root: &str, data: &StageData) -> GameResult { let map_file = filesystem::open(ctx, [root, "Stage/", &data.map, ".pxm"].join(""))?; let attrib_file = filesystem::open(ctx, [root, "Stage/", &data.tileset.name, ".pxa"].join(""))?; diff --git a/src/texture_set.rs b/src/texture_set.rs index 460fd89..57b7d1f 100644 --- a/src/texture_set.rs +++ b/src/texture_set.rs @@ -7,7 +7,7 @@ use ggez::graphics::{Drawable, DrawParam, FilterMode, Image, Rect}; use ggez::graphics::spritebatch::SpriteBatch; use ggez::nalgebra::{Point2, Vector2}; use itertools::Itertools; -use log::{debug, info}; +use log::info; use crate::common; use crate::engine_constants::EngineConstants; diff --git a/src/ui.rs b/src/ui.rs new file mode 100644 index 0000000..7c0078f --- /dev/null +++ b/src/ui.rs @@ -0,0 +1,104 @@ +use std::time::Instant; + +use ggez::{Context, GameResult, graphics}; +use ggez::GameError::RenderError; +use imgui::{FontConfig, FontSource}; +use imgui_gfx_renderer::{Renderer, Shaders}; +use imgui_gfx_renderer::gfx::format::Rgba8; +use imgui_gfx_renderer::gfx::handle::RenderTargetView; +use imgui_gfx_renderer::gfx::memory::Typed; +use imgui_winit_support::{HiDpiMode, WinitPlatform}; + +use crate::scene::Scene; +use crate::GameContext; +use crate::game_state::GameState; + +mod types { + pub type Device = gfx_device_gl::Device; + pub type Factory = gfx_device_gl::Factory; + pub type Resources = gfx_device_gl::Resources; +} + +pub struct UI { + pub imgui: imgui::Context, + pub platform: WinitPlatform, + pub renderer: Renderer, + main_color: RenderTargetView, + last_frame: Instant, +} + +impl UI { + pub fn new(ctx: &mut Context) -> GameResult { + let mut imgui = imgui::Context::create(); + imgui.set_ini_filename(None); + imgui.fonts().add_font(&[ + FontSource::DefaultFontData { + config: Some(FontConfig::default()), + }, + ]); + imgui.style_mut().use_dark_colors(); + + let mut platform = WinitPlatform::init(&mut imgui); + platform.attach_window(imgui.io_mut(), graphics::window(ctx), HiDpiMode::Rounded); + + let (factory, dev, _, _, color) = graphics::gfx_objects(ctx); + let shaders = { + let version = dev.get_info().shading_language; + if version.is_embedded { + if version.major >= 3 { + Shaders::GlSlEs300 + } else { + Shaders::GlSlEs100 + } + } else if version.major >= 4 { + Shaders::GlSl400 + } else if version.major >= 3 { + if version.minor >= 2 { + Shaders::GlSl150 + } else { + Shaders::GlSl130 + } + } else { + Shaders::GlSl110 + } + }; + let renderer = Renderer::init(&mut imgui, factory, shaders) + .map_err(|e| RenderError(e.to_string()))?; + + Ok(Self { + imgui, + platform, + renderer, + main_color: RenderTargetView::new(color), + last_frame: Instant::now(), + }) + } + + pub fn handle_events(&mut self, ctx: &mut Context, event: &winit::Event) { + self.platform.handle_event(self.imgui.io_mut(), graphics::window(ctx), &event); + } + + pub fn draw(&mut self, state: &mut GameState, game_ctx: &mut GameContext, ctx: &mut Context, scene: &mut Box) -> GameResult { + { + let io = self.imgui.io_mut(); + self.platform.prepare_frame(io, graphics::window(ctx)).map_err(|e| RenderError(e))?; + + io.update_delta_time(self.last_frame); + self.last_frame = Instant::now(); + } + let mut ui = self.imgui.frame(); + + scene.overlay_draw(state, game_ctx, ctx, &mut ui)?; + + self.platform.prepare_render(&ui, graphics::window(ctx)); + let draw_data = ui.render(); + let (factory, dev, encoder, _, _) = graphics::gfx_objects(ctx); + self.renderer + .render(factory, encoder, &mut self.main_color, draw_data) + .map_err(|e| RenderError(e.to_string()))?; + + encoder.flush(dev); + + Ok(()) + } +}