mirror of
https://github.com/doukutsu-rs/doukutsu-rs
synced 2025-04-11 06:54:17 +00:00
failed refactoring lol
This commit is contained in:
parent
ff5962d97e
commit
ccadb98a8a
|
@ -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" }
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
19
src/frame.rs
19
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;
|
||||
}
|
||||
|
|
101
src/game_state.rs
Normal file
101
src/game_state.rs
Normal 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
38
src/live_debugger.rs
Normal 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(())
|
||||
}
|
||||
}
|
183
src/main.rs
183
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<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(())
|
||||
|
|
|
@ -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)?;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)?;
|
||||
}
|
||||
|
||||
|
|
|
@ -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(()) }
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::io::{Cursor, Read};
|
||||
use std::io::Cursor;
|
||||
|
||||
use ggez::{Context, GameResult};
|
||||
|
||||
|
|
22
src/stage.rs
22
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<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(""))?;
|
||||
|
|
|
@ -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
104
src/ui.rs
Normal 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(())
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue