add app_root_dir helper function. integrate with all examples
This commit is contained in:
parent
74d7f2b22c
commit
0cbd5366fd
|
@ -58,11 +58,11 @@ fn main() -> Result<()> {
|
||||||
let mut volume = 1.0;
|
let mut volume = 1.0;
|
||||||
|
|
||||||
let sounds = [
|
let sounds = [
|
||||||
load_and_convert_wav(Path::new("./assets/pickup-coin.wav"), system.res.audio.spec())?,
|
load_and_convert_wav(system.app_root_dir.join("./assets/pickup-coin.wav").as_path(), system.res.audio.spec())?,
|
||||||
load_and_convert_wav(Path::new("./assets/powerup.wav"), system.res.audio.spec())?,
|
load_and_convert_wav(system.app_root_dir.join("./assets/powerup.wav").as_path(), system.res.audio.spec())?,
|
||||||
load_and_convert_wav(Path::new("./assets/explosion.wav"), system.res.audio.spec())?,
|
load_and_convert_wav(system.app_root_dir.join("./assets/explosion.wav").as_path(), system.res.audio.spec())?,
|
||||||
load_and_convert_wav(Path::new("./assets/jump.wav"), system.res.audio.spec())?,
|
load_and_convert_wav(system.app_root_dir.join("./assets/jump.wav").as_path(), system.res.audio.spec())?,
|
||||||
load_and_convert_wav(Path::new("./assets/laser-shoot.wav"), system.res.audio.spec())?,
|
load_and_convert_wav(system.app_root_dir.join("./assets/laser-shoot.wav").as_path(), system.res.audio.spec())?,
|
||||||
];
|
];
|
||||||
|
|
||||||
let mut statuses = [AudioChannelStatus { size: 0, position: 0, playing: false }; NUM_CHANNELS];
|
let mut statuses = [AudioChannelStatus { size: 0, position: 0, playing: false }; NUM_CHANNELS];
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
use std::path::Path;
|
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
use ggdt::prelude::*;
|
use ggdt::prelude::*;
|
||||||
|
@ -26,7 +24,8 @@ fn main() -> Result<()> {
|
||||||
|
|
||||||
let font = BitmaskFont::new_vga_font()?;
|
let font = BitmaskFont::new_vga_font()?;
|
||||||
|
|
||||||
let (balls_bmp, balls_palette) = IndexedBitmap::load_pcx_file(Path::new("./assets/balls.pcx"))?;
|
let (balls_bmp, balls_palette) =
|
||||||
|
IndexedBitmap::load_pcx_file(system.app_root_dir.join("./assets/balls.pcx").as_path())?;
|
||||||
system.res.palette = balls_palette.clone();
|
system.res.palette = balls_palette.clone();
|
||||||
|
|
||||||
let mut sprites = Vec::<IndexedBitmap>::new();
|
let mut sprites = Vec::<IndexedBitmap>::new();
|
||||||
|
|
|
@ -25,7 +25,8 @@ impl Game {
|
||||||
pub fn new(mut system: System<DosLike>) -> Result<Self> {
|
pub fn new(mut system: System<DosLike>) -> Result<Self> {
|
||||||
let font = BitmaskFont::new_vga_font()?;
|
let font = BitmaskFont::new_vga_font()?;
|
||||||
|
|
||||||
let (balls_bmp, balls_palette) = IndexedBitmap::load_pcx_file(Path::new("./assets/balls.pcx"))?;
|
let (balls_bmp, balls_palette) =
|
||||||
|
IndexedBitmap::load_pcx_file(system.app_root_dir.join("./assets/balls.pcx").as_path())?;
|
||||||
system.res.palette = balls_palette.clone();
|
system.res.palette = balls_palette.clone();
|
||||||
|
|
||||||
let mut sprites = Vec::new();
|
let mut sprites = Vec::new();
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::path::Path;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
@ -91,17 +90,20 @@ impl AppContext<Standard> for GameContext {
|
||||||
|
|
||||||
impl GameContext {
|
impl GameContext {
|
||||||
pub fn new(system: System<Standard>) -> Result<Self> {
|
pub fn new(system: System<Standard>) -> Result<Self> {
|
||||||
let palette = load_palette(Path::new("./assets/db16.pal"))?;
|
let palette = load_palette(system.app_root_dir.join("./assets/db16.pal").as_path())?;
|
||||||
|
|
||||||
let font = load_font(Path::new("./assets/dp.fnt"))?;
|
let font = load_font(system.app_root_dir.join("./assets/dp.fnt").as_path())?;
|
||||||
let small_font = load_font(Path::new("./assets/small.fnt"))?;
|
let small_font = load_font(system.app_root_dir.join("./assets/small.fnt").as_path())?;
|
||||||
|
|
||||||
let tiles = Rc::new(load_bitmap_atlas_autogrid(Path::new("./assets/tiles.pcx"))?);
|
let tiles = Rc::new(load_bitmap_atlas_autogrid(system.app_root_dir.join("./assets/tiles.pcx").as_path())?);
|
||||||
let green_slime = Rc::new(load_bitmap_atlas_autogrid(Path::new("./assets/green_slime.pcx"))?);
|
let green_slime =
|
||||||
let blue_slime = Rc::new(load_bitmap_atlas_autogrid(Path::new("./assets/blue_slime.pcx"))?);
|
Rc::new(load_bitmap_atlas_autogrid(system.app_root_dir.join("./assets/green_slime.pcx").as_path())?);
|
||||||
let orange_slime = Rc::new(load_bitmap_atlas_autogrid(Path::new("./assets/orange_slime.pcx"))?);
|
let blue_slime =
|
||||||
|
Rc::new(load_bitmap_atlas_autogrid(system.app_root_dir.join("./assets/blue_slime.pcx").as_path())?);
|
||||||
|
let orange_slime =
|
||||||
|
Rc::new(load_bitmap_atlas_autogrid(system.app_root_dir.join("./assets/orange_slime.pcx").as_path())?);
|
||||||
|
|
||||||
let tilemap = TileMap::load_from(Path::new("./assets/arena.map.json"))?;
|
let tilemap = TileMap::load_from(system.app_root_dir.join("./assets/arena.map.json").as_path())?;
|
||||||
|
|
||||||
let entities = Entities::new();
|
let entities = Entities::new();
|
||||||
let component_systems = ComponentSystems::new();
|
let component_systems = ComponentSystems::new();
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
extern crate core;
|
extern crate core;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::path::Path;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
|
@ -108,30 +107,36 @@ impl AppContext<DosLike> for Game {
|
||||||
|
|
||||||
impl Game {
|
impl Game {
|
||||||
pub fn new(mut system: System<DosLike>) -> Result<Self> {
|
pub fn new(mut system: System<DosLike>) -> Result<Self> {
|
||||||
let palette = load_palette(Path::new("./assets/db16.pal"))?;
|
let palette = load_palette(system.app_root_dir.join("./assets/db16.pal").as_path())?;
|
||||||
system.res.palette = palette.clone();
|
system.res.palette = palette.clone();
|
||||||
|
|
||||||
let font = load_font(Path::new("./assets/dp.fnt"))?;
|
let font = load_font(system.app_root_dir.join("./assets/dp.fnt").as_path())?;
|
||||||
|
|
||||||
let tiles = Rc::new(load_bitmap_atlas_autogrid(Path::new("./assets/tiles.pcx"))?);
|
let tiles = Rc::new(load_bitmap_atlas_autogrid(system.app_root_dir.join("./assets/tiles.pcx").as_path())?);
|
||||||
let hero_male = Rc::new(load_bitmap_atlas_autogrid(Path::new("./assets/hero_male.pcx"))?);
|
let hero_male =
|
||||||
let hero_female = Rc::new(load_bitmap_atlas_autogrid(Path::new("./assets/hero_female.pcx"))?);
|
Rc::new(load_bitmap_atlas_autogrid(system.app_root_dir.join("./assets/hero_male.pcx").as_path())?);
|
||||||
let green_slime = Rc::new(load_bitmap_atlas_autogrid(Path::new("./assets/green_slime.pcx"))?);
|
let hero_female =
|
||||||
let blue_slime = Rc::new(load_bitmap_atlas_autogrid(Path::new("./assets/blue_slime.pcx"))?);
|
Rc::new(load_bitmap_atlas_autogrid(system.app_root_dir.join("./assets/hero_female.pcx").as_path())?);
|
||||||
let orange_slime = Rc::new(load_bitmap_atlas_autogrid(Path::new("./assets/orange_slime.pcx"))?);
|
let green_slime =
|
||||||
let fist = Rc::new(load_bitmap_atlas_autogrid(Path::new("./assets/fist.pcx"))?);
|
Rc::new(load_bitmap_atlas_autogrid(system.app_root_dir.join("./assets/green_slime.pcx").as_path())?);
|
||||||
let sword = Rc::new(load_bitmap_atlas_autogrid(Path::new("./assets/sword.pcx"))?);
|
let blue_slime =
|
||||||
let particles = Rc::new(load_bitmap_atlas_autogrid(Path::new("./assets/particles.pcx"))?);
|
Rc::new(load_bitmap_atlas_autogrid(system.app_root_dir.join("./assets/blue_slime.pcx").as_path())?);
|
||||||
let items = Rc::new(load_bitmap_atlas_autogrid(Path::new("./assets/items.pcx"))?);
|
let orange_slime =
|
||||||
|
Rc::new(load_bitmap_atlas_autogrid(system.app_root_dir.join("./assets/orange_slime.pcx").as_path())?);
|
||||||
|
let fist = Rc::new(load_bitmap_atlas_autogrid(system.app_root_dir.join("./assets/fist.pcx").as_path())?);
|
||||||
|
let sword = Rc::new(load_bitmap_atlas_autogrid(system.app_root_dir.join("./assets/sword.pcx").as_path())?);
|
||||||
|
let particles =
|
||||||
|
Rc::new(load_bitmap_atlas_autogrid(system.app_root_dir.join("./assets/particles.pcx").as_path())?);
|
||||||
|
let items = Rc::new(load_bitmap_atlas_autogrid(system.app_root_dir.join("./assets/items.pcx").as_path())?);
|
||||||
|
|
||||||
let mut ui = load_bitmap_atlas(Path::new("./assets/ui.pcx"))?;
|
let mut ui = load_bitmap_atlas(system.app_root_dir.join("./assets/ui.pcx").as_path())?;
|
||||||
ui.add(Rect::new(0, 0, 16, 16))?;
|
ui.add(Rect::new(0, 0, 16, 16))?;
|
||||||
ui.add(Rect::new(16, 0, 16, 16))?;
|
ui.add(Rect::new(16, 0, 16, 16))?;
|
||||||
for i in 0..8 {
|
for i in 0..8 {
|
||||||
ui.add(Rect::new(i * 8, 16, 8, 8))?;
|
ui.add(Rect::new(i * 8, 16, 8, 8))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let tilemap = TileMap::load_from(Path::new("./assets/title_screen.map.json"))?;
|
let tilemap = TileMap::load_from(system.app_root_dir.join("./assets/title_screen.map.json").as_path())?;
|
||||||
|
|
||||||
let entities = Entities::new();
|
let entities = Entities::new();
|
||||||
let component_systems = ComponentSystems::new();
|
let component_systems = ComponentSystems::new();
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
use std::path::Path;
|
|
||||||
|
|
||||||
use ggdt::prelude::*;
|
use ggdt::prelude::*;
|
||||||
|
|
||||||
use crate::entities::*;
|
use crate::entities::*;
|
||||||
|
@ -88,7 +86,13 @@ impl AppState<Game> for MainMenuState {
|
||||||
fn state_change(&mut self, new_state: State, old_state: State, context: &mut Game) {
|
fn state_change(&mut self, new_state: State, old_state: State, context: &mut Game) {
|
||||||
match new_state {
|
match new_state {
|
||||||
State::Pending | State::Resume => {
|
State::Pending | State::Resume => {
|
||||||
init_everything(context, Path::new("./assets/title_screen.map.json"), 0.2, 1.0, 32);
|
init_everything(
|
||||||
|
context,
|
||||||
|
context.core.system.app_root_dir.join("./assets/title_screen.map.json").as_path(),
|
||||||
|
0.2,
|
||||||
|
1.0,
|
||||||
|
32,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
State::TransitionIn => {
|
State::TransitionIn => {
|
||||||
self.fade = 0.0;
|
self.fade = 0.0;
|
||||||
|
@ -219,7 +223,13 @@ impl AppState<Game> for GamePlayState {
|
||||||
fn state_change(&mut self, new_state: State, old_state: State, context: &mut Game) {
|
fn state_change(&mut self, new_state: State, old_state: State, context: &mut Game) {
|
||||||
match new_state {
|
match new_state {
|
||||||
State::Pending => {
|
State::Pending => {
|
||||||
init_everything(context, Path::new("./assets/arena.map.json"), 0.5, 2.0, 100);
|
init_everything(
|
||||||
|
context,
|
||||||
|
context.core.system.app_root_dir.join("./assets/arena.map.json").as_path(),
|
||||||
|
0.5,
|
||||||
|
2.0,
|
||||||
|
100,
|
||||||
|
);
|
||||||
spawn_player_randomly(&mut context.core);
|
spawn_player_randomly(&mut context.core);
|
||||||
}
|
}
|
||||||
State::TransitionIn => {
|
State::TransitionIn => {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::audio::AudioError;
|
use crate::audio::AudioError;
|
||||||
|
use crate::utils::app_root_dir;
|
||||||
|
|
||||||
mod event;
|
mod event;
|
||||||
mod framebuffer;
|
mod framebuffer;
|
||||||
|
@ -51,6 +52,9 @@ pub enum SystemError {
|
||||||
|
|
||||||
#[error("SystemResources error: {0}")]
|
#[error("SystemResources error: {0}")]
|
||||||
SystemResourcesError(#[from] SystemResourcesError),
|
SystemResourcesError(#[from] SystemResourcesError),
|
||||||
|
|
||||||
|
#[error("System I/O error")]
|
||||||
|
IOError(#[from] std::io::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builder for configuring and constructing an instance of [`System`].
|
/// Builder for configuring and constructing an instance of [`System`].
|
||||||
|
@ -195,6 +199,8 @@ impl SystemBuilder {
|
||||||
|
|
||||||
let event_pump = SystemEventPump::from(sdl_event_pump);
|
let event_pump = SystemEventPump::from(sdl_event_pump);
|
||||||
|
|
||||||
|
let app_root_dir = app_root_dir()?;
|
||||||
|
|
||||||
Ok(System {
|
Ok(System {
|
||||||
sdl_context,
|
sdl_context,
|
||||||
sdl_audio_subsystem,
|
sdl_audio_subsystem,
|
||||||
|
@ -202,6 +208,7 @@ impl SystemBuilder {
|
||||||
sdl_timer_subsystem,
|
sdl_timer_subsystem,
|
||||||
res: system_resources,
|
res: system_resources,
|
||||||
event_pump,
|
event_pump,
|
||||||
|
app_root_dir,
|
||||||
vsync: self.vsync,
|
vsync: self.vsync,
|
||||||
target_framerate: self.target_framerate,
|
target_framerate: self.target_framerate,
|
||||||
target_framerate_delta: None,
|
target_framerate_delta: None,
|
||||||
|
@ -231,6 +238,8 @@ where
|
||||||
pub res: SystemResType,
|
pub res: SystemResType,
|
||||||
|
|
||||||
pub event_pump: SystemEventPump,
|
pub event_pump: SystemEventPump,
|
||||||
|
|
||||||
|
pub app_root_dir: std::path::PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<SystemResType> std::fmt::Debug for System<SystemResType>
|
impl<SystemResType> std::fmt::Debug for System<SystemResType>
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
use byteorder::{ReadBytesExt, WriteBytesExt};
|
use byteorder::{ReadBytesExt, WriteBytesExt};
|
||||||
use std::io::{Error, SeekFrom};
|
use std::{
|
||||||
|
io::{Error, SeekFrom},
|
||||||
|
path::PathBuf,
|
||||||
|
};
|
||||||
|
|
||||||
/// Provides a convenience method for determining the total size of a stream. This is provided
|
/// Provides a convenience method for determining the total size of a stream. This is provided
|
||||||
/// as a temporary alternative to [std::io::Seek::stream_len] which is currently marked unstable.
|
/// as a temporary alternative to [std::io::Seek::stream_len] which is currently marked unstable.
|
||||||
|
@ -34,3 +37,28 @@ pub trait WriteType {
|
||||||
|
|
||||||
fn write<T: WriteBytesExt>(&self, writer: &mut T) -> Result<(), Self::ErrorType>;
|
fn write<T: WriteBytesExt>(&self, writer: &mut T) -> Result<(), Self::ErrorType>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the application root directory (the directory that the application executable is
|
||||||
|
/// located in).
|
||||||
|
///
|
||||||
|
/// First tries to automatically detect this from the `CARGO_MANIFEST_DIR` environment variable,
|
||||||
|
/// if present, to catch scenarios where the application is running from a Cargo workspace as a
|
||||||
|
/// sub-project/binary within that workspace. In such a case, the application root directory is
|
||||||
|
/// the same as that sub-project/binary's `Cargo.toml`.
|
||||||
|
///
|
||||||
|
/// If `CARGO_MANIFEST_DIR` is not present, then an attempt is made to determine the application
|
||||||
|
/// root directory from the running executable's location.
|
||||||
|
///
|
||||||
|
/// If this fails for some reason, then this returns the current working directory.
|
||||||
|
pub fn app_root_dir() -> Result<PathBuf, Error> {
|
||||||
|
if let Some(manifest_path) = std::env::var_os("CARGO_MANIFEST_DIR") {
|
||||||
|
return Ok(PathBuf::from(manifest_path));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut exe_path = std::env::current_exe()?.canonicalize()?;
|
||||||
|
if exe_path.pop() {
|
||||||
|
return Ok(exe_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::env::current_dir()
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue