failed refactoring lol

This commit is contained in:
Alula 2020-08-19 13:21:40 +02:00
parent ff5962d97e
commit ccadb98a8a
No known key found for this signature in database
GPG Key ID: 3E00485503A1D8BA
15 changed files with 518 additions and 289 deletions

View File

@ -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" }

View File

@ -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;
}

View File

@ -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;
}

101
src/game_state.rs Normal file
View File

@ -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<Self> {
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(())
}
}

38
src/live_debugger.rs Normal file
View File

@ -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(())
}
}

View File

@ -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<Box<dyn Scene>>,
state: SharedGameState,
state: Option<GameState>,
ctx: GameContext,
ui: UI,
scaled_matrix: ColumnMatrix4<f32>,
def_matrix: ColumnMatrix4<f32>,
}
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<StageData>,
@ -80,16 +66,6 @@ pub struct SharedGameState {
pub canvas_size: (f32, f32),
pub screen_size: (f32, f32),
pub next_scene: Option<Box<dyn Scene>>,
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(())

View File

@ -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<Player> {
let constants = &state.constants;
pub fn new(constants: &EngineConstants, ctx: &mut Context) -> GameResult<Player> {
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)?;

View File

@ -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);
}
_ => {}
}

View File

@ -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<Self> {
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<Self> {
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::<usize>::new_size(0, 40, 64, 8));
// bar
batch.add_rect(40.0, 40.0,
&Rect::<usize>::new_size(0, 32, ((self.life_bar as usize * 40) / self.player.max_life as usize) - 1, 8));
&Rect::<usize>::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::<usize>::new_size(0, 24, ((self.player.life as usize * 40) / self.player.max_life as usize) - 1, 8));
&Rect::<usize>::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::<usize>::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::<usize>::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::<usize>::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::<usize>::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::<usize>::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::<usize>::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(())
}
}

View File

@ -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)?;
}

View File

@ -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(()) }
}

View File

@ -1,4 +1,4 @@
use std::io::{Cursor, Read};
use std::io::Cursor;
use ggez::{Context, GameResult};

View File

@ -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<Self> {
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(""))?;

View File

@ -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;

104
src/ui.rs Normal file
View File

@ -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<Rgba8, types::Resources>,
main_color: RenderTargetView<types::Resources, Rgba8>,
last_frame: Instant,
}
impl UI {
pub fn new(ctx: &mut Context) -> GameResult<Self> {
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<dyn Scene>) -> 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(())
}
}