add app_root_dir helper function. integrate with all examples

This commit is contained in:
Gered 2024-09-03 00:00:07 -04:00
parent 74d7f2b22c
commit 0cbd5366fd
8 changed files with 92 additions and 38 deletions

View file

@ -58,11 +58,11 @@ fn main() -> Result<()> {
let mut volume = 1.0;
let sounds = [
load_and_convert_wav(Path::new("./assets/pickup-coin.wav"), system.res.audio.spec())?,
load_and_convert_wav(Path::new("./assets/powerup.wav"), system.res.audio.spec())?,
load_and_convert_wav(Path::new("./assets/explosion.wav"), system.res.audio.spec())?,
load_and_convert_wav(Path::new("./assets/jump.wav"), 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/pickup-coin.wav").as_path(), 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(system.app_root_dir.join("./assets/explosion.wav").as_path(), 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(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];

View file

@ -1,5 +1,3 @@
use std::path::Path;
use anyhow::Result;
use ggdt::prelude::*;
@ -26,7 +24,8 @@ fn main() -> Result<()> {
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();
let mut sprites = Vec::<IndexedBitmap>::new();

View file

@ -25,7 +25,8 @@ impl Game {
pub fn new(mut system: System<DosLike>) -> Result<Self> {
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();
let mut sprites = Vec::new();

View file

@ -1,5 +1,4 @@
use std::collections::HashMap;
use std::path::Path;
use std::rc::Rc;
use anyhow::Result;
@ -91,17 +90,20 @@ impl AppContext<Standard> for GameContext {
impl GameContext {
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 small_font = load_font(Path::new("./assets/small.fnt"))?;
let font = load_font(system.app_root_dir.join("./assets/dp.fnt").as_path())?;
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 green_slime = Rc::new(load_bitmap_atlas_autogrid(Path::new("./assets/green_slime.pcx"))?);
let blue_slime = Rc::new(load_bitmap_atlas_autogrid(Path::new("./assets/blue_slime.pcx"))?);
let orange_slime = Rc::new(load_bitmap_atlas_autogrid(Path::new("./assets/orange_slime.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(system.app_root_dir.join("./assets/green_slime.pcx").as_path())?);
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 component_systems = ComponentSystems::new();

View file

@ -1,7 +1,6 @@
extern crate core;
use std::collections::HashMap;
use std::path::Path;
use std::rc::Rc;
use anyhow::{Context, Result};
@ -108,30 +107,36 @@ impl AppContext<DosLike> for Game {
impl Game {
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();
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 hero_male = Rc::new(load_bitmap_atlas_autogrid(Path::new("./assets/hero_male.pcx"))?);
let hero_female = Rc::new(load_bitmap_atlas_autogrid(Path::new("./assets/hero_female.pcx"))?);
let green_slime = Rc::new(load_bitmap_atlas_autogrid(Path::new("./assets/green_slime.pcx"))?);
let blue_slime = Rc::new(load_bitmap_atlas_autogrid(Path::new("./assets/blue_slime.pcx"))?);
let orange_slime = Rc::new(load_bitmap_atlas_autogrid(Path::new("./assets/orange_slime.pcx"))?);
let fist = Rc::new(load_bitmap_atlas_autogrid(Path::new("./assets/fist.pcx"))?);
let sword = Rc::new(load_bitmap_atlas_autogrid(Path::new("./assets/sword.pcx"))?);
let particles = Rc::new(load_bitmap_atlas_autogrid(Path::new("./assets/particles.pcx"))?);
let items = Rc::new(load_bitmap_atlas_autogrid(Path::new("./assets/items.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(system.app_root_dir.join("./assets/hero_male.pcx").as_path())?);
let hero_female =
Rc::new(load_bitmap_atlas_autogrid(system.app_root_dir.join("./assets/hero_female.pcx").as_path())?);
let green_slime =
Rc::new(load_bitmap_atlas_autogrid(system.app_root_dir.join("./assets/green_slime.pcx").as_path())?);
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 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(16, 0, 16, 16))?;
for i in 0..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 component_systems = ComponentSystems::new();

View file

@ -1,5 +1,3 @@
use std::path::Path;
use ggdt::prelude::*;
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) {
match new_state {
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 => {
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) {
match new_state {
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);
}
State::TransitionIn => {

View file

@ -1,6 +1,7 @@
use thiserror::Error;
use crate::audio::AudioError;
use crate::utils::app_root_dir;
mod event;
mod framebuffer;
@ -51,6 +52,9 @@ pub enum SystemError {
#[error("SystemResources error: {0}")]
SystemResourcesError(#[from] SystemResourcesError),
#[error("System I/O error")]
IOError(#[from] std::io::Error),
}
/// Builder for configuring and constructing an instance of [`System`].
@ -195,6 +199,8 @@ impl SystemBuilder {
let event_pump = SystemEventPump::from(sdl_event_pump);
let app_root_dir = app_root_dir()?;
Ok(System {
sdl_context,
sdl_audio_subsystem,
@ -202,6 +208,7 @@ impl SystemBuilder {
sdl_timer_subsystem,
res: system_resources,
event_pump,
app_root_dir,
vsync: self.vsync,
target_framerate: self.target_framerate,
target_framerate_delta: None,
@ -231,6 +238,8 @@ where
pub res: SystemResType,
pub event_pump: SystemEventPump,
pub app_root_dir: std::path::PathBuf,
}
impl<SystemResType> std::fmt::Debug for System<SystemResType>

View file

@ -1,5 +1,8 @@
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
/// 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>;
}
/// 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()
}