Renamed content fields,

reworked texture indexing
master
Mark 2024-01-04 17:17:55 -08:00
parent 10f9776108
commit c382431747
Signed by: Mark
GPG Key ID: C6D63995FE72FD80
25 changed files with 240 additions and 217 deletions

View File

@ -7,8 +7,8 @@ rate = 0.2
# Random rate variation (each cooldown is +- this) # Random rate variation (each cooldown is +- this)
rate_rng = 0.1 rate_rng = 0.1
# TODO: apply force on fire # TODO: apply force to ship on fire
projectile.sprite_texture = "projectile::blaster" projectile.sprite = "projectile::blaster"
# Height of projectile in game units # Height of projectile in game units
projectile.size = 6 projectile.size = 6
projectile.size_rng = 0.0 projectile.size_rng = 0.0
@ -29,13 +29,13 @@ projectile.force = 0.0
projectile.collider.ball.radius = 2.0 projectile.collider.ball.radius = 2.0
projectile.impact.texture = "particle::blaster" projectile.impact.sprite = "particle::explosion"
projectile.impact.lifetime = "inherit" projectile.impact.lifetime = "inherit"
projectile.impact.inherit_velocity = "target" projectile.impact.inherit_velocity = "target"
projectile.impact.size = 3.0 projectile.impact.size = 3.0
projectile.expire.texture = "particle::blaster" projectile.expire.sprite = "particle::blaster"
projectile.expire.lifetime = "inherit" projectile.expire.lifetime = "inherit"
projectile.expire.inherit_velocity = "projectile" projectile.expire.inherit_velocity = "projectile"
projectile.expire.size = 3.0 projectile.expire.size = 3.0

View File

@ -3,5 +3,5 @@
space.engine = 20 space.engine = 20
engine.thrust = 100 engine.thrust = 100
engine.flare_texture = "flare::ion" engine.flare_sprite = "flare::ion"
steering.power = 20 steering.power = 20

View File

@ -1,5 +1,5 @@
[ship."Gypsum"] [ship."Gypsum"]
sprite_texture = "ship::gypsum" sprite = "ship::gypsum"
size = 100 size = 100
mass = 1 mass = 1
hull = 200 hull = 200

View File

@ -1,40 +1,40 @@
[texture."starfield"] [sprite."starfield"]
file = "starfield.png" file = "starfield.png"
[texture."star::star"] [sprite."star::star"]
file = "star/B-09.png" file = "star/B-09.png"
[texture."flare::ion"] [sprite."flare::ion"]
file = "flare/1.png" file = "flare/1.png"
[texture."planet::earth"] [sprite."planet::earth"]
file = "planet/earth.png" file = "planet/earth.png"
[texture."planet::luna"] [sprite."planet::luna"]
file = "planet/luna.png" file = "planet/luna.png"
[texture."projectile::blaster"] [sprite."projectile::blaster"]
file = "projectile/blaster.png" file = "projectile/blaster.png"
[texture."ship::gypsum"] [sprite."ship::gypsum"]
file = "ship/gypsum.png" file = "ship/gypsum.png"
[texture."ui::radar"] [sprite."ui::radar"]
file = "ui/radar.png" file = "ui/radar.png"
[texture."ui::shipblip"] [sprite."ui::shipblip"]
file = "ui/ship-blip.png" file = "ui/ship-blip.png"
[texture."ui::planetblip"] [sprite."ui::planetblip"]
file = "ui/planet-blip.png" file = "ui/planet-blip.png"
[texture."ui::radarframe"] [sprite."ui::radarframe"]
file = "ui/radarframe.png" file = "ui/radarframe.png"
[texture."ui::centerarrow"] [sprite."ui::centerarrow"]
file = "ui/center-arrow.png" file = "ui/center-arrow.png"
[texture."particle::blaster"] [sprite."particle::blaster"]
duration = 0.15 duration = 0.15
repeat = "once" repeat = "once"
frames = [ frames = [
@ -45,7 +45,7 @@ frames = [
] ]
[texture."particle::explosion"] [sprite."particle::explosion"]
duration = 0.4 duration = 0.4
repeat = "once" repeat = "once"
frames = [ frames = [

View File

@ -1,17 +1,17 @@
[system."12 Autumn Above"] [system."12 Autumn Above"]
object.star.sprite_texture = "star::star" object.star.sprite = "star::star"
object.star.position = [0.0, 0.0, 30.0] object.star.position = [0.0, 0.0, 30.0]
object.star.size = 2000 object.star.size = 2000
object.earth.sprite_texture = "planet::earth" object.earth.sprite = "planet::earth"
object.earth.position.center = "star" object.earth.position.center = "star"
object.earth.position.radius = 4000 object.earth.position.radius = 4000
object.earth.position.angle = 0 object.earth.position.angle = 0
object.earth.position.z = 10.0 object.earth.position.z = 10.0
object.earth.size = 1000 object.earth.size = 1000
object.luna.sprite_texture = "planet::luna" object.luna.sprite = "planet::luna"
object.luna.position.center = "earth" object.luna.position.center = "earth"
object.luna.position.radius = 1600 object.luna.position.radius = 1600
object.luna.position.angle = 135 object.luna.position.angle = 135

View File

@ -35,14 +35,14 @@ pub const STARFIELD_DENSITY: f64 = 0.01;
/// Must fit inside an i32 /// Must fit inside an i32
pub const STARFIELD_COUNT: u64 = (STARFIELD_SIZE as f64 * STARFIELD_DENSITY) as u64; pub const STARFIELD_COUNT: u64 = (STARFIELD_SIZE as f64 * STARFIELD_DENSITY) as u64;
/// Name of starfield texture /// Name of starfield sprite
pub const STARFIELD_TEXTURE_NAME: &'static str = "starfield"; pub const STARFIELD_SPRITE_NAME: &'static str = "starfield";
/// Root directory of game content /// Root directory of game content
pub const CONTENT_ROOT: &'static str = "./content"; pub const CONTENT_ROOT: &'static str = "./content";
/// Root directory of game textures /// Root directory of game images
pub const TEXTURE_ROOT: &'static str = "./assets/render"; pub const IMAGE_ROOT: &'static str = "./assets/render";
/// We can draw at most this many object sprites on the screen. /// We can draw at most this many object sprites on the screen.
pub const OBJECT_SPRITE_INSTANCE_LIMIT: u64 = 500; pub const OBJECT_SPRITE_INSTANCE_LIMIT: u64 = 500;

View File

@ -17,6 +17,8 @@ readme = { workspace = true }
workspace = true workspace = true
[dependencies] [dependencies]
galactica-packer = { workspace = true }
serde = { workspace = true } serde = { workspace = true }
toml = { workspace = true } toml = { workspace = true }
anyhow = { workspace = true } anyhow = { workspace = true }

View File

@ -7,24 +7,24 @@
//! in our code. It's managable, but the approach here is simpler and easier to understand. //! in our code. It's managable, but the approach here is simpler and easier to understand.
use std::{cmp::Eq, hash::Hash}; use std::{cmp::Eq, hash::Hash};
/// A lightweight representation of a /// A lightweight representation of a sprite
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct TextureHandle { pub struct SpriteHandle {
/// The index of this texture in content.textures /// The index of this sprite in content.sprites
pub(crate) index: usize, pub(crate) index: usize,
/// The aspect ratio of this texture (width / height) /// The aspect ratio of this sprite (width / height)
pub aspect: f32, pub aspect: f32,
} }
impl Hash for TextureHandle { impl Hash for SpriteHandle {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) { fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.index.hash(state) self.index.hash(state)
} }
} }
impl Eq for TextureHandle {} impl Eq for SpriteHandle {}
impl PartialEq for TextureHandle { impl PartialEq for SpriteHandle {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.index.eq(&other.index) self.index.eq(&other.index)
} }

View File

@ -8,6 +8,7 @@ mod part;
mod util; mod util;
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use galactica_packer::{SpriteAtlas, SpriteAtlasImage};
use std::{ use std::{
collections::HashMap, collections::HashMap,
fs::File, fs::File,
@ -17,10 +18,10 @@ use std::{
use toml; use toml;
use walkdir::WalkDir; use walkdir::WalkDir;
pub use handle::{FactionHandle, GunHandle, OutfitHandle, ShipHandle, SystemHandle, TextureHandle}; pub use handle::{FactionHandle, GunHandle, OutfitHandle, ShipHandle, SpriteHandle, SystemHandle};
pub use part::{ pub use part::{
EnginePoint, Faction, Gun, GunPoint, ImpactInheritVelocity, Outfit, OutfitSpace, Projectile, EnginePoint, Faction, Gun, GunPoint, ImpactInheritVelocity, Outfit, OutfitSpace, Projectile,
ProjectileCollider, ProjectileParticle, Relationship, RepeatMode, Ship, System, Texture, ProjectileCollider, ProjectileParticle, Relationship, RepeatMode, Ship, Sprite, System,
}; };
mod syntax { mod syntax {
@ -28,7 +29,7 @@ mod syntax {
use serde::Deserialize; use serde::Deserialize;
use std::{collections::HashMap, fmt::Display, hash::Hash}; use std::{collections::HashMap, fmt::Display, hash::Hash};
use crate::part::{faction, gun, outfit, ship, system, texture}; use crate::part::{faction, gun, outfit, ship, sprite, system};
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub struct Root { pub struct Root {
@ -36,7 +37,7 @@ mod syntax {
pub ship: Option<HashMap<String, ship::syntax::Ship>>, pub ship: Option<HashMap<String, ship::syntax::Ship>>,
pub system: Option<HashMap<String, system::syntax::System>>, pub system: Option<HashMap<String, system::syntax::System>>,
pub outfit: Option<HashMap<String, outfit::syntax::Outfit>>, pub outfit: Option<HashMap<String, outfit::syntax::Outfit>>,
pub texture: Option<HashMap<String, texture::syntax::Texture>>, pub sprite: Option<HashMap<String, sprite::syntax::Sprite>>,
pub faction: Option<HashMap<String, faction::syntax::Faction>>, pub faction: Option<HashMap<String, faction::syntax::Faction>>,
} }
@ -72,7 +73,7 @@ mod syntax {
ship: None, ship: None,
system: None, system: None,
outfit: None, outfit: None,
texture: None, sprite: None,
faction: None, faction: None,
} }
} }
@ -84,8 +85,8 @@ mod syntax {
.with_context(|| "while merging systems")?; .with_context(|| "while merging systems")?;
merge_hashmap(&mut self.outfit, other.outfit) merge_hashmap(&mut self.outfit, other.outfit)
.with_context(|| "while merging outfits")?; .with_context(|| "while merging outfits")?;
merge_hashmap(&mut self.texture, other.texture) merge_hashmap(&mut self.sprite, other.sprite)
.with_context(|| "while merging textures")?; .with_context(|| "while merging sprites")?;
merge_hashmap(&mut self.faction, other.faction) merge_hashmap(&mut self.faction, other.faction)
.with_context(|| "while merging factions")?; .with_context(|| "while merging factions")?;
return Ok(()); return Ok(());
@ -94,10 +95,10 @@ mod syntax {
} }
trait Build { trait Build {
type InputSyntax; type InputSyntaxType;
/// Build a processed System struct from raw serde data /// Build a processed System struct from raw serde data
fn build(root: Self::InputSyntax, ct: &mut Content) -> Result<()> fn build(root: Self::InputSyntaxType, ct: &mut Content) -> Result<()>
where where
Self: Sized; Self: Sized;
} }
@ -106,18 +107,21 @@ trait Build {
#[derive(Debug)] #[derive(Debug)]
pub struct Content { pub struct Content {
/* Configuration values */ /* Configuration values */
/// Root directory for textures /// Root directory for image
texture_root: PathBuf, image_root: PathBuf,
/// Name of starfield texture /// Name of starfield sprite
starfield_texture_name: String, starfield_sprite_name: String,
/// Textures /// Sprites
pub textures: Vec<part::texture::Texture>, pub sprites: Vec<part::sprite::Sprite>,
/// Map strings to texture names. /// Map strings to texture names.
/// This is only necessary because we need to hard-code a few texture names for UI elements. /// This is only necessary because we need to hard-code a few texture names for UI elements.
texture_index: HashMap<String, handle::TextureHandle>, sprite_index: HashMap<String, handle::SpriteHandle>,
/// The texture to use for starfield stars /// The texture to use for starfield stars
starfield_handle: Option<handle::TextureHandle>, starfield_handle: Option<handle::SpriteHandle>,
/// Keeps track of which images are in which texture
sprite_atlas: SpriteAtlas,
/// Outfits /// Outfits
outfits: Vec<part::outfit::Outfit>, outfits: Vec<part::outfit::Outfit>,
@ -148,6 +152,7 @@ impl Content {
pub fn load_dir( pub fn load_dir(
path: PathBuf, path: PathBuf,
texture_root: PathBuf, texture_root: PathBuf,
atlas_index: PathBuf,
starfield_texture_name: String, starfield_texture_name: String,
) -> Result<Self> { ) -> Result<Self> {
let mut root = syntax::Root::new(); let mut root = syntax::Root::new();
@ -177,23 +182,32 @@ impl Content {
} }
} }
let atlas: SpriteAtlas = {
let mut file_string = String::new();
let _ = File::open(atlas_index)?.read_to_string(&mut file_string);
let file_string = file_string.trim();
toml::from_str(&file_string)?
};
let mut content = Self { let mut content = Self {
sprite_atlas: atlas,
systems: Vec::new(), systems: Vec::new(),
ships: Vec::new(), ships: Vec::new(),
guns: Vec::new(), guns: Vec::new(),
outfits: Vec::new(), outfits: Vec::new(),
textures: Vec::new(), sprites: Vec::new(),
factions: Vec::new(), factions: Vec::new(),
texture_index: HashMap::new(), sprite_index: HashMap::new(),
starfield_handle: None, starfield_handle: None,
texture_root, image_root: texture_root,
starfield_texture_name, starfield_sprite_name: starfield_texture_name,
}; };
// Order here matters, usually // Order here matters, usually
if root.texture.is_some() { if root.sprite.is_some() {
part::texture::Texture::build(root.texture.take().unwrap(), &mut content)?; part::sprite::Sprite::build(root.sprite.take().unwrap(), &mut content)?;
} }
if root.ship.is_some() { if root.ship.is_some() {
part::ship::Ship::build(root.ship.take().unwrap(), &mut content)?; part::ship::Ship::build(root.ship.take().unwrap(), &mut content)?;
} }
@ -216,27 +230,32 @@ impl Content {
// Access methods // Access methods
impl Content { impl Content {
/// Get the texture handle for the starfield texture /// Get the handle for the starfield sprite
pub fn get_starfield_handle(&self) -> TextureHandle { pub fn get_starfield_handle(&self) -> SpriteHandle {
match self.starfield_handle { match self.starfield_handle {
Some(h) => h, Some(h) => h,
None => unreachable!("Starfield texture hasn't been loaded yet!"), None => unreachable!("Starfield sprite hasn't been loaded yet!"),
} }
} }
/// Get a handle from a texture name /// Get a handle from a sprite name
pub fn get_texture_handle(&self, name: &str) -> TextureHandle { pub fn get_sprite_handle(&self, name: &str) -> SpriteHandle {
return match self.texture_index.get(name) { return match self.sprite_index.get(name) {
Some(s) => *s, Some(s) => *s,
None => unreachable!("get_texture_handle was called with a bad handle!"), None => unreachable!("get_sprite_handle was called with a bad name!"),
}; };
} }
/// Get a texture from a handle /// Get a sprite from a handle
pub fn get_texture(&self, h: TextureHandle) -> &Texture { pub fn get_sprite(&self, h: SpriteHandle) -> &Sprite {
// In theory, this could fail if h has a bad index, but that shouldn't ever happen. // In theory, this could fail if h has a bad index, but that shouldn't ever happen.
// The only TextureHandles that exist should be created by this crate. // The only handles that exist should be created by this crate.
return &self.textures[h.index]; return &self.sprites[h.index];
}
/// Get a sprite from a path
pub fn get_image(&self, p: &Path) -> &SpriteAtlasImage {
self.sprite_atlas.index.get(p).unwrap()
} }
/// Get an outfit from a handle /// Get an outfit from a handle
@ -249,7 +268,7 @@ impl Content {
return &self.guns[h.index]; return &self.guns[h.index];
} }
/// Get a texture from a handle /// Get a ship from a handle
pub fn get_ship(&self, h: ShipHandle) -> &Ship { pub fn get_ship(&self, h: ShipHandle) -> &Ship {
return &self.ships[h.index]; return &self.ships[h.index];
} }

View File

@ -59,9 +59,9 @@ pub struct Faction {
} }
impl crate::Build for Faction { impl crate::Build for Faction {
type InputSyntax = HashMap<String, syntax::Faction>; type InputSyntaxType = HashMap<String, syntax::Faction>;
fn build(factions: Self::InputSyntax, ct: &mut Content) -> Result<()> { fn build(factions: Self::InputSyntaxType, ct: &mut Content) -> Result<()> {
// Keeps track of position in faction array. // Keeps track of position in faction array.
// This lets us build FactionHandles before finishing all factions. // This lets us build FactionHandles before finishing all factions.
let faction_names: Vec<String> = factions.keys().map(|x| x.to_owned()).collect(); let faction_names: Vec<String> = factions.keys().map(|x| x.to_owned()).collect();

View File

@ -3,7 +3,7 @@ use cgmath::Deg;
use serde::Deserialize; use serde::Deserialize;
use std::collections::HashMap; use std::collections::HashMap;
use crate::{handle::TextureHandle, Content}; use crate::{handle::SpriteHandle, Content};
use crate::OutfitSpace; use crate::OutfitSpace;
@ -23,7 +23,7 @@ pub(crate) mod syntax {
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub struct Projectile { pub struct Projectile {
pub sprite_texture: String, pub sprite: String,
pub size: f32, pub size: f32,
pub size_rng: f32, pub size_rng: f32,
pub speed: f32, pub speed: f32,
@ -40,7 +40,7 @@ pub(crate) mod syntax {
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub struct ProjectileParticle { pub struct ProjectileParticle {
pub texture: String, pub sprite: String,
pub lifetime: ParticleLifetime, pub lifetime: ParticleLifetime,
pub inherit_velocity: super::ImpactInheritVelocity, pub inherit_velocity: super::ImpactInheritVelocity,
pub size: f32, pub size: f32,
@ -110,7 +110,7 @@ pub struct Gun {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Projectile { pub struct Projectile {
/// The projectile sprite /// The projectile sprite
pub sprite_texture: TextureHandle, pub sprite: SpriteHandle,
/// The average size of this projectile /// The average size of this projectile
/// (height in game units) /// (height in game units)
@ -155,9 +155,9 @@ pub struct Projectile {
/// The particle a projectile will spawn when it hits something /// The particle a projectile will spawn when it hits something
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ProjectileParticle { pub struct ProjectileParticle {
/// The texture to use for this particle. /// The sprite to use for this particle.
/// This is most likely animated. /// This is most likely animated.
pub texture: TextureHandle, pub sprite: SpriteHandle,
/// How many seconds this particle should live /// How many seconds this particle should live
pub lifetime: f32, pub lifetime: f32,
@ -174,8 +174,8 @@ fn parse_projectile_particle(
p: Option<syntax::ProjectileParticle>, p: Option<syntax::ProjectileParticle>,
) -> Result<Option<ProjectileParticle>> { ) -> Result<Option<ProjectileParticle>> {
if let Some(impact) = p { if let Some(impact) = p {
let impact_texture = match ct.texture_index.get(&impact.texture) { let impact_sprite_handle = match ct.sprite_index.get(&impact.sprite) {
None => bail!("impact texture `{}` doesn't exist", impact.texture), None => bail!("impact sprite `{}` doesn't exist", impact.sprite),
Some(t) => *t, Some(t) => *t,
}; };
@ -183,8 +183,8 @@ fn parse_projectile_particle(
syntax::ParticleLifetime::Seconds(s) => s, syntax::ParticleLifetime::Seconds(s) => s,
syntax::ParticleLifetime::Inherit(s) => { syntax::ParticleLifetime::Inherit(s) => {
if s == "inherit" { if s == "inherit" {
let t = ct.get_texture(impact_texture); let sprite = ct.get_sprite(impact_sprite_handle);
t.fps * t.frames.len() as f32 sprite.fps * sprite.frames.len() as f32
} else { } else {
bail!("bad impact lifetime, must be float or \"inherit\"",) bail!("bad impact lifetime, must be float or \"inherit\"",)
} }
@ -192,7 +192,7 @@ fn parse_projectile_particle(
}; };
Ok(Some(ProjectileParticle { Ok(Some(ProjectileParticle {
texture: impact_texture, sprite: impact_sprite_handle,
lifetime: impact_lifetime, lifetime: impact_lifetime,
inherit_velocity: impact.inherit_velocity, inherit_velocity: impact.inherit_velocity,
size: impact.size, size: impact.size,
@ -203,15 +203,15 @@ fn parse_projectile_particle(
} }
impl crate::Build for Gun { impl crate::Build for Gun {
type InputSyntax = HashMap<String, syntax::Gun>; type InputSyntaxType = HashMap<String, syntax::Gun>;
fn build(gun: Self::InputSyntax, ct: &mut Content) -> Result<()> { fn build(gun: Self::InputSyntaxType, ct: &mut Content) -> Result<()> {
for (gun_name, gun) in gun { for (gun_name, gun) in gun {
let projectile_texture = match ct.texture_index.get(&gun.projectile.sprite_texture) { let projectile_sprite_handle = match ct.sprite_index.get(&gun.projectile.sprite) {
None => bail!( None => bail!(
"In gun `{}`: projectile texture `{}` doesn't exist", "In gun `{}`: projectile sprite `{}` doesn't exist",
gun_name, gun_name,
gun.projectile.sprite_texture gun.projectile.sprite
), ),
Some(t) => *t, Some(t) => *t,
}; };
@ -229,7 +229,7 @@ impl crate::Build for Gun {
rate_rng: gun.rate_rng, rate_rng: gun.rate_rng,
projectile: Projectile { projectile: Projectile {
force: gun.projectile.force, force: gun.projectile.force,
sprite_texture: projectile_texture, sprite: projectile_sprite_handle,
size: gun.projectile.size, size: gun.projectile.size,
size_rng: gun.projectile.size_rng, size_rng: gun.projectile.size_rng,
speed: gun.projectile.speed, speed: gun.projectile.speed,

View File

@ -5,13 +5,13 @@ pub mod gun;
pub mod outfit; pub mod outfit;
mod shared; mod shared;
pub mod ship; pub mod ship;
pub mod sprite;
pub mod system; pub mod system;
pub mod texture;
pub use faction::{Faction, Relationship}; pub use faction::{Faction, Relationship};
pub use gun::{Gun, ImpactInheritVelocity, Projectile, ProjectileCollider, ProjectileParticle}; pub use gun::{Gun, ImpactInheritVelocity, Projectile, ProjectileCollider, ProjectileParticle};
pub use outfit::Outfit; pub use outfit::Outfit;
pub use shared::OutfitSpace; pub use shared::OutfitSpace;
pub use ship::{EnginePoint, GunPoint, Ship}; pub use ship::{EnginePoint, GunPoint, Ship};
pub use sprite::{RepeatMode, Sprite};
pub use system::{Object, System}; pub use system::{Object, System};
pub use texture::{RepeatMode, Texture};

View File

@ -2,7 +2,7 @@ use std::collections::HashMap;
use anyhow::{bail, Result}; use anyhow::{bail, Result};
use crate::{handle::TextureHandle, Content, OutfitSpace}; use crate::{handle::SpriteHandle, Content, OutfitSpace};
pub(crate) mod syntax { pub(crate) mod syntax {
use crate::part::shared; use crate::part::shared;
@ -20,7 +20,7 @@ pub(crate) mod syntax {
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub struct Engine { pub struct Engine {
pub thrust: f32, pub thrust: f32,
pub flare_texture: String, pub flare_sprite: String,
} }
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
@ -44,37 +44,37 @@ pub struct Outfit {
/// The engine flare sprite this outfit creates. /// The engine flare sprite this outfit creates.
/// Its location and size is determined by a ship's /// Its location and size is determined by a ship's
/// engine points. /// engine points.
pub engine_flare_texture: Option<TextureHandle>, pub engine_flare_sprite: Option<SpriteHandle>,
/// How much space this outfit requires /// How much space this outfit requires
pub space: OutfitSpace, pub space: OutfitSpace,
} }
impl crate::Build for Outfit { impl crate::Build for Outfit {
type InputSyntax = HashMap<String, syntax::Outfit>; type InputSyntaxType = HashMap<String, syntax::Outfit>;
fn build(outfits: Self::InputSyntax, ct: &mut Content) -> Result<()> { fn build(outfits: Self::InputSyntaxType, ct: &mut Content) -> Result<()> {
for (outfit_name, outfit) in outfits { for (outfit_name, outfit) in outfits {
let mut o = Self { let mut o = Self {
name: outfit_name.clone(), name: outfit_name.clone(),
engine_thrust: 0.0, engine_thrust: 0.0,
steer_power: 0.0, steer_power: 0.0,
engine_flare_texture: None, engine_flare_sprite: None,
space: OutfitSpace::from(outfit.space), space: OutfitSpace::from(outfit.space),
}; };
// Engine stats // Engine stats
if let Some(engine) = outfit.engine { if let Some(engine) = outfit.engine {
let th = match ct.texture_index.get(&engine.flare_texture) { let th = match ct.sprite_index.get(&engine.flare_sprite) {
None => bail!( None => bail!(
"In outfit `{}`: texture `{}` doesn't exist", "In outfit `{}`: flare sprite `{}` doesn't exist",
outfit_name, outfit_name,
engine.flare_texture engine.flare_sprite
), ),
Some(t) => *t, Some(t) => *t,
}; };
o.engine_thrust = engine.thrust; o.engine_thrust = engine.thrust;
o.engine_flare_texture = Some(th); o.engine_flare_sprite = Some(th);
} }
// Steering stats // Steering stats

View File

@ -4,7 +4,7 @@ use anyhow::{bail, Result};
use cgmath::Point2; use cgmath::Point2;
use nalgebra::{point, Point}; use nalgebra::{point, Point};
use crate::{handle::TextureHandle, Content, OutfitSpace}; use crate::{handle::SpriteHandle, Content, OutfitSpace};
pub(crate) mod syntax { pub(crate) mod syntax {
use crate::part::shared; use crate::part::shared;
@ -15,7 +15,7 @@ pub(crate) mod syntax {
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub struct Ship { pub struct Ship {
pub sprite_texture: String, pub sprite: String,
pub size: f32, pub size: f32,
pub engines: Vec<Engine>, pub engines: Vec<Engine>,
pub guns: Vec<Gun>, pub guns: Vec<Gun>,
@ -57,7 +57,7 @@ pub struct Ship {
pub name: String, pub name: String,
/// This ship's sprite /// This ship's sprite
pub sprite_texture: TextureHandle, pub sprite: SpriteHandle,
/// The size of this ship. /// The size of this ship.
/// Measured as unrotated height, /// Measured as unrotated height,
@ -123,26 +123,26 @@ pub struct GunPoint {
} }
impl crate::Build for Ship { impl crate::Build for Ship {
type InputSyntax = HashMap<String, syntax::Ship>; type InputSyntaxType = HashMap<String, syntax::Ship>;
fn build(ship: Self::InputSyntax, ct: &mut Content) -> Result<()> { fn build(ship: Self::InputSyntaxType, ct: &mut Content) -> Result<()> {
for (ship_name, ship) in ship { for (ship_name, ship) in ship {
let th = match ct.texture_index.get(&ship.sprite_texture) { let handle = match ct.sprite_index.get(&ship.sprite) {
None => bail!( None => bail!(
"In ship `{}`: texture `{}` doesn't exist", "In ship `{}`: sprite `{}` doesn't exist",
ship_name, ship_name,
ship.sprite_texture ship.sprite
), ),
Some(t) => *t, Some(t) => *t,
}; };
let size = ship.size; let size = ship.size;
let aspect = th.aspect; let aspect = ct.get_sprite(handle).aspect;
ct.ships.push(Self { ct.ships.push(Self {
aspect, aspect,
name: ship_name, name: ship_name,
sprite_texture: th, sprite: handle,
mass: ship.mass, mass: ship.mass,
space: OutfitSpace::from(ship.space), space: OutfitSpace::from(ship.space),
angular_drag: ship.angular_drag, angular_drag: ship.angular_drag,

View File

@ -3,7 +3,7 @@ use image::io::Reader;
use serde::Deserialize; use serde::Deserialize;
use std::{collections::HashMap, path::PathBuf}; use std::{collections::HashMap, path::PathBuf};
use crate::{handle::TextureHandle, Content}; use crate::{handle::SpriteHandle, Content};
pub(crate) mod syntax { pub(crate) mod syntax {
use serde::Deserialize; use serde::Deserialize;
@ -16,18 +16,18 @@ pub(crate) mod syntax {
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
#[serde(untagged)] #[serde(untagged)]
pub enum Texture { pub enum Sprite {
Static(StaticTexture), Static(StaticSprite),
Frames(FramesTexture), Frames(FrameSprite),
} }
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub struct StaticTexture { pub struct StaticSprite {
pub file: PathBuf, pub file: PathBuf,
} }
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub struct FramesTexture { pub struct FrameSprite {
pub frames: Vec<PathBuf>, pub frames: Vec<PathBuf>,
pub duration: f32, pub duration: f32,
pub repeat: RepeatMode, pub repeat: RepeatMode,
@ -57,90 +57,94 @@ impl RepeatMode {
} }
} }
/// Represents a texture that may be used in the game. /// Represents a sprite that may be used in the game.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Texture { pub struct Sprite {
/// The name of this texture /// The name of this sprite
pub name: String, pub name: String,
/// The handle for this texture /// This sprite's handle
pub handle: TextureHandle, pub handle: SpriteHandle,
/// The frames of this texture /// The file names of frames of this sprite.
/// (static textures have one frame) /// unanimated sprites have one frame.
pub frames: Vec<PathBuf>, pub frames: Vec<PathBuf>,
/// The speed of this texture's animation /// The speed of this sprite's animation.
/// (static textures have zero fps) /// unanimated sprites have zero fps.
pub fps: f32, pub fps: f32,
/// How to replay this texture's animation /// How to replay this sprite's animation
pub repeat: RepeatMode, pub repeat: RepeatMode,
/// Aspect ratio of this sprite (width / height)
pub aspect: f32,
} }
impl crate::Build for Texture { impl crate::Build for Sprite {
type InputSyntax = HashMap<String, syntax::Texture>; type InputSyntaxType = HashMap<String, syntax::Sprite>;
fn build(texture: Self::InputSyntax, ct: &mut Content) -> Result<()> { fn build(sprites: Self::InputSyntaxType, ct: &mut Content) -> Result<()> {
for (texture_name, t) in texture { for (sprite_name, t) in sprites {
match t { match t {
syntax::Texture::Static(t) => { syntax::Sprite::Static(t) => {
let file = ct.texture_root.join(t.file); let file = ct.image_root.join(&t.file);
let reader = Reader::open(&file).with_context(|| { let reader = Reader::open(&file).with_context(|| {
format!( format!(
"Failed to read texture `{}` from file `{}`", "Failed to read file `{}` in sprite `{}`",
texture_name, file.display(),
file.display() sprite_name,
) )
})?; })?;
let dim = reader.into_dimensions().with_context(|| { let dim = reader.into_dimensions().with_context(|| {
format!( format!(
"Failed to get dimensions of texture `{}` from file `{}`", "Failed to get dimensions of file `{}` in sprite `{}`",
texture_name, file.display(),
file.display() sprite_name,
) )
})?; })?;
let h = TextureHandle { let h = SpriteHandle {
index: ct.textures.len(), index: ct.sprites.len(),
aspect: dim.0 as f32 / dim.1 as f32, aspect: dim.0 as f32 / dim.1 as f32,
}; };
if texture_name == ct.starfield_texture_name { if sprite_name == ct.starfield_sprite_name {
if ct.starfield_handle.is_none() { if ct.starfield_handle.is_none() {
ct.starfield_handle = Some(h) ct.starfield_handle = Some(h)
} else { } else {
// This can't happen, since this is a hashmap. // This can't happen, since this is a hashmap.
unreachable!("Found two starfield textures! Something is very wrong.") unreachable!("Found two starfield sprites! Something is very wrong.")
} }
} }
ct.texture_index.insert(texture_name.clone(), h); ct.sprite_index.insert(sprite_name.clone(), h);
ct.textures.push(Self { ct.sprites.push(Self {
name: texture_name, name: sprite_name,
frames: vec![file], frames: vec![t.file],
fps: 0.0, fps: 0.0,
handle: h, handle: h,
repeat: RepeatMode::Once, repeat: RepeatMode::Once,
aspect: dim.0 as f32 / dim.1 as f32,
}); });
} }
syntax::Texture::Frames(t) => { syntax::Sprite::Frames(t) => {
let mut dim = None; let mut dim = None;
for f in &t.frames { for f in &t.frames {
let file = ct.texture_root.join(f); let file = ct.image_root.join(f);
let reader = Reader::open(&file).with_context(|| { let reader = Reader::open(&file).with_context(|| {
format!( format!(
"Failed to read texture `{}` from file `{}`", "Failed to read file `{}` in sprite `{}`",
texture_name, file.display(),
file.display() sprite_name,
) )
})?; })?;
let d = reader.into_dimensions().with_context(|| { let d = reader.into_dimensions().with_context(|| {
format!( format!(
"Failed to get dimensions of texture `{}` from file `{}`", "Failed to get dimensions of file `{}` in sprite `{}`",
texture_name, file.display(),
file.display() sprite_name,
) )
})?; })?;
match dim { match dim {
@ -148,37 +152,34 @@ impl crate::Build for Texture {
Some(e) => { Some(e) => {
if d != e { if d != e {
bail!( bail!(
"Failed to load frames of texture `{}`. Frames have different sizes `{}`", "Failed to load frames of sprite `{}` because frames have different sizes.",
texture_name, sprite_name,
file.display()
) )
} }
} }
} }
} }
let dim = dim.unwrap();
let h = TextureHandle { let h = SpriteHandle {
index: ct.textures.len(), index: ct.sprites.len(),
aspect: dim.unwrap().0 as f32 / dim.unwrap().1 as f32, aspect: dim.0 as f32 / dim.1 as f32,
}; };
if texture_name == ct.starfield_texture_name { if sprite_name == ct.starfield_sprite_name {
unreachable!("Starfield texture may not be animated") unreachable!("Starfield texture may not be animated")
} }
let fps = t.duration / t.frames.len() as f32; let fps = t.duration / t.frames.len() as f32;
ct.texture_index.insert(texture_name.clone(), h); ct.sprite_index.insert(sprite_name.clone(), h);
ct.textures.push(Self { ct.sprites.push(Self {
name: texture_name, name: sprite_name,
frames: t frames: t.frames,
.frames
.into_iter()
.map(|f| ct.texture_root.join(f))
.collect(),
fps, fps,
handle: h, handle: h,
repeat: t.repeat, repeat: t.repeat,
aspect: dim.0 as f32 / dim.1 as f32,
}); });
} }
} }
@ -187,7 +188,7 @@ impl crate::Build for Texture {
if ct.starfield_handle.is_none() { if ct.starfield_handle.is_none() {
bail!( bail!(
"Could not find a starfield texture (name: `{}`)", "Could not find a starfield texture (name: `{}`)",
ct.starfield_texture_name ct.starfield_sprite_name
) )
} }

View File

@ -2,7 +2,7 @@ use anyhow::{bail, Context, Result};
use cgmath::{Deg, Point3}; use cgmath::{Deg, Point3};
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use crate::{handle::TextureHandle, util::Polar, Content}; use crate::{handle::SpriteHandle, util::Polar, Content};
pub(crate) mod syntax { pub(crate) mod syntax {
use serde::Deserialize; use serde::Deserialize;
@ -17,7 +17,7 @@ pub(crate) mod syntax {
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub struct Object { pub struct Object {
pub sprite_texture: String, pub sprite: String,
pub position: Position, pub position: Position,
pub size: f32, pub size: f32,
@ -94,7 +94,7 @@ pub struct System {
#[derive(Debug)] #[derive(Debug)]
pub struct Object { pub struct Object {
/// This object's sprite /// This object's sprite
pub sprite_texture: TextureHandle, pub sprite: SpriteHandle,
/// This object's size. /// This object's size.
/// Measured as height in game units. /// Measured as height in game units.
@ -175,9 +175,9 @@ fn resolve_position(
} }
impl crate::Build for System { impl crate::Build for System {
type InputSyntax = HashMap<String, syntax::System>; type InputSyntaxType = HashMap<String, syntax::System>;
fn build(system: Self::InputSyntax, ct: &mut Content) -> Result<()> { fn build(system: Self::InputSyntaxType, ct: &mut Content) -> Result<()> {
for (system_name, system) in system { for (system_name, system) in system {
let mut objects = Vec::new(); let mut objects = Vec::new();
@ -185,17 +185,17 @@ impl crate::Build for System {
let mut cycle_detector = HashSet::new(); let mut cycle_detector = HashSet::new();
cycle_detector.insert(label.clone()); cycle_detector.insert(label.clone());
let th = match ct.texture_index.get(&obj.sprite_texture) { let handle = match ct.sprite_index.get(&obj.sprite) {
None => bail!( None => bail!(
"In system `{}`: texture `{}` doesn't exist", "In system `{}`: sprite `{}` doesn't exist",
system_name, system_name,
obj.sprite_texture obj.sprite
), ),
Some(t) => *t, Some(t) => *t,
}; };
objects.push(Object { objects.push(Object {
sprite_texture: th, sprite: handle,
position: resolve_position(&system.object, &obj, cycle_detector) position: resolve_position(&system.object, &obj, cycle_detector)
.with_context(|| format!("In object {:#?}", label))?, .with_context(|| format!("In object {:#?}", label))?,
size: obj.size, size: obj.size,

View File

@ -10,7 +10,7 @@ use galactica_behavior::{behavior, ShipBehavior};
use galactica_constants; use galactica_constants;
use galactica_content as content; use galactica_content as content;
use galactica_gameobject as object; use galactica_gameobject as object;
use galactica_render::{FrameState, ObjectSprite, ParticleBuilder, UiSprite}; use galactica_render::{ObjectSprite, ParticleBuilder, RenderState, UiSprite};
use galactica_ui as ui; use galactica_ui as ui;
use galactica_world::{util, ShipPhysicsHandle, World}; use galactica_world::{util, ShipPhysicsHandle, World};
@ -174,8 +174,8 @@ impl Game {
self.last_update = Instant::now(); self.last_update = Instant::now();
} }
pub fn get_frame_state(&mut self) -> FrameState { pub fn get_frame_state(&mut self) -> RenderState {
FrameState { RenderState {
camera_pos: self.camera.pos, camera_pos: self.camera.pos,
camera_zoom: self.camera.zoom, camera_zoom: self.camera.zoom,
object_sprites: self.get_object_sprites(), object_sprites: self.get_object_sprites(),

View File

@ -17,14 +17,15 @@ fn main() -> Result<()> {
// TODO: error if missing // TODO: error if missing
let content = content::Content::load_dir( let content = content::Content::load_dir(
PathBuf::from(galactica_constants::CONTENT_ROOT), PathBuf::from(galactica_constants::CONTENT_ROOT),
PathBuf::from(galactica_constants::TEXTURE_ROOT), PathBuf::from(galactica_constants::IMAGE_ROOT),
PathBuf::from("spriteatlas.toml"), PathBuf::from("spriteatlas.toml"),
galactica_constants::STARFIELD_TEXTURE_NAME.to_owned(), galactica_constants::STARFIELD_SPRITE_NAME.to_owned(),
)?; )?;
let event_loop = EventLoop::new(); let event_loop = EventLoop::new();
let window = WindowBuilder::new().build(&event_loop).unwrap(); let window = WindowBuilder::new().build(&event_loop).unwrap();
let mut gpu = pollster::block_on(galactica_render::GPUState::new(window, &content))?; let mut gpu = pollster::block_on(galactica_render::GPUState::new(window, &content))?;
gpu.init();
let mut game = game::Game::new(content); let mut game = game::Game::new(content);
gpu.update_starfield_buffer(); gpu.update_starfield_buffer();

View File

@ -33,7 +33,7 @@ impl ShipGun {
pub struct OutfitStatSum { pub struct OutfitStatSum {
pub engine_thrust: f32, pub engine_thrust: f32,
pub steer_power: f32, pub steer_power: f32,
pub engine_flare_textures: Vec<content::TextureHandle>, pub engine_flare_sprites: Vec<content::SpriteHandle>,
} }
impl OutfitStatSum { impl OutfitStatSum {
@ -41,23 +41,23 @@ impl OutfitStatSum {
Self { Self {
engine_thrust: 0.0, engine_thrust: 0.0,
steer_power: 0.0, steer_power: 0.0,
engine_flare_textures: Vec::new(), engine_flare_sprites: Vec::new(),
} }
} }
pub fn add(&mut self, o: &content::Outfit) { pub fn add(&mut self, o: &content::Outfit) {
self.engine_thrust += o.engine_thrust; self.engine_thrust += o.engine_thrust;
if let Some(t) = o.engine_flare_texture { if let Some(t) = o.engine_flare_sprite {
self.engine_flare_textures.push(t); self.engine_flare_sprites.push(t);
}; };
self.steer_power += o.steer_power; self.steer_power += o.steer_power;
} }
pub fn remove(&mut self, o: &content::Outfit) { pub fn remove(&mut self, o: &content::Outfit) {
self.engine_thrust -= o.engine_thrust; self.engine_thrust -= o.engine_thrust;
if let Some(t) = o.engine_flare_texture { if let Some(t) = o.engine_flare_sprite {
self.engine_flare_textures.remove( self.engine_flare_sprites.remove(
self.engine_flare_textures self.engine_flare_sprites
.iter() .iter()
.position(|x| *x == t) .position(|x| *x == t)
.unwrap(), .unwrap(),
@ -185,7 +185,7 @@ impl<'a> OutfitSet {
pub fn update_engine_flares(&mut self) { pub fn update_engine_flares(&mut self) {
// TODO: better way to pick flare texture // TODO: better way to pick flare texture
self.engine_flare_sprites.clear(); self.engine_flare_sprites.clear();
let t = if let Some(e) = self.stats.engine_flare_textures.iter().next() { let s = if let Some(e) = self.stats.engine_flare_sprites.iter().next() {
e e
} else { } else {
return; return;
@ -200,7 +200,7 @@ impl<'a> OutfitSet {
y: p.pos.y, y: p.pos.y,
z: 1.0, z: 1.0,
}, },
texture: *t, sprite: *s,
angle: Deg(0.0), angle: Deg(0.0),
size: p.size, size: p.size,
}) })

View File

@ -18,7 +18,7 @@ impl System {
for o in &sys.objects { for o in &sys.objects {
s.bodies.push(SystemObject { s.bodies.push(SystemObject {
pos: o.position, pos: o.position,
sprite_texture: o.sprite_texture, sprite: o.sprite,
size: o.size, size: o.size,
angle: o.angle, angle: o.angle,
}); });

View File

@ -4,7 +4,7 @@ use galactica_content as content;
use galactica_render::ObjectSprite; use galactica_render::ObjectSprite;
pub struct SystemObject { pub struct SystemObject {
pub sprite_texture: content::TextureHandle, pub sprite: content::SpriteHandle,
pub pos: Point3<f32>, pub pos: Point3<f32>,
pub size: f32, pub size: f32,
pub angle: Deg<f32>, pub angle: Deg<f32>,
@ -13,7 +13,7 @@ pub struct SystemObject {
impl SystemObject { impl SystemObject {
pub(crate) fn get_sprite(&self) -> ObjectSprite { pub(crate) fn get_sprite(&self) -> ObjectSprite {
return ObjectSprite { return ObjectSprite {
texture: self.sprite_texture, sprite: self.sprite,
pos: self.pos, pos: self.pos,
angle: self.angle, angle: self.angle,
size: self.size, size: self.size,

View File

@ -24,12 +24,12 @@ pub fn build_radar(
let (_, player_body) = physics.get_ship_body(player).unwrap(); let (_, player_body) = physics.get_ship_body(player).unwrap();
let player_position = util::rigidbody_position(player_body); let player_position = util::rigidbody_position(player_body);
let planet_texture = ct.get_texture_handle("ui::planetblip"); let planet_sprite = ct.get_sprite_handle("ui::planetblip");
let ship_texture = ct.get_texture_handle("ui::shipblip"); let ship_sprite = ct.get_sprite_handle("ui::shipblip");
let arrow_texture = ct.get_texture_handle("ui::centerarrow"); let arrow_sprite = ct.get_sprite_handle("ui::centerarrow");
out.push(UiSprite { out.push(UiSprite {
texture: ct.get_texture_handle("ui::radar"), sprite: ct.get_sprite_handle("ui::radar"),
pos: AnchoredUiPosition::NwNw(Point2 { x: 10.0, y: -10.0 }), pos: AnchoredUiPosition::NwNw(Point2 { x: 10.0, y: -10.0 }),
dimensions: Point2 { dimensions: Point2 {
x: radar_size, x: radar_size,
@ -57,7 +57,7 @@ pub fn build_radar(
continue; continue;
} }
out.push(UiSprite { out.push(UiSprite {
texture: planet_texture, sprite: planet_sprite,
pos: AnchoredUiPosition::NwC( pos: AnchoredUiPosition::NwC(
Point2 { Point2 {
x: radar_size / 2.0 + 10.0, x: radar_size / 2.0 + 10.0,
@ -65,7 +65,7 @@ pub fn build_radar(
} + (d * (radar_size / 2.0)), } + (d * (radar_size / 2.0)),
), ),
dimensions: Point2 { dimensions: Point2 {
x: planet_texture.aspect, x: planet_sprite.aspect,
y: 1.0, y: 1.0,
} * size, } * size,
angle: o.angle, angle: o.angle,
@ -77,7 +77,7 @@ pub fn build_radar(
// Draw ships // Draw ships
for (s, r) in physics.iter_ship_body() { for (s, r) in physics.iter_ship_body() {
let ship = ct.get_ship(s.ship.handle); let ship = ct.get_ship(s.ship.handle);
let size = (ship.size * ship.sprite_texture.aspect) * ship_scale; let size = (ship.size * ship.sprite.aspect) * ship_scale;
let p = util::rigidbody_position(r); let p = util::rigidbody_position(r);
let d = (p - player_position) / radar_range; let d = (p - player_position) / radar_range;
let m = d.magnitude() + (size / (2.0 * radar_size)); let m = d.magnitude() + (size / (2.0 * radar_size));
@ -92,7 +92,7 @@ pub fn build_radar(
let f = ct.get_faction(s.ship.faction).color; let f = ct.get_faction(s.ship.faction).color;
let f = [f[0], f[1], f[2], 1.0]; let f = [f[0], f[1], f[2], 1.0];
out.push(UiSprite { out.push(UiSprite {
texture: ship_texture, sprite: ship_sprite,
pos: AnchoredUiPosition::NwC( pos: AnchoredUiPosition::NwC(
Point2 { Point2 {
x: radar_size / 2.0 + 10.0, x: radar_size / 2.0 + 10.0,
@ -100,7 +100,7 @@ pub fn build_radar(
} + (d * (radar_size / 2.0)), } + (d * (radar_size / 2.0)),
), ),
dimensions: Point2 { dimensions: Point2 {
x: ship_texture.aspect, x: ship_sprite.aspect,
y: 1.0, y: 1.0,
} * size, } * size,
angle: -angle, angle: -angle,
@ -118,13 +118,13 @@ pub fn build_radar(
let d = d * (radar_size / 2.0); let d = d * (radar_size / 2.0);
let color = Some([0.3, 0.3, 0.3, 1.0]); let color = Some([0.3, 0.3, 0.3, 1.0]);
if m < 0.8 { if m < 0.8 {
let texture = ct.get_texture_handle("ui::radarframe"); let sprite = ct.get_sprite_handle("ui::radarframe");
let dimensions = Point2 { let dimensions = Point2 {
x: texture.aspect, x: sprite.aspect,
y: 1.0, y: 1.0,
} * 7.0f32.min((0.8 - m) * 70.0); } * 7.0f32.min((0.8 - m) * 70.0);
out.push(UiSprite { out.push(UiSprite {
texture, sprite,
pos: AnchoredUiPosition::NwNw(Point2 { pos: AnchoredUiPosition::NwNw(Point2 {
x: (radar_size / 2.0 + 10.0) - d.x, x: (radar_size / 2.0 + 10.0) - d.x,
y: (radar_size / -2.0 - 10.0) + d.y, y: (radar_size / -2.0 - 10.0) + d.y,
@ -135,7 +135,7 @@ pub fn build_radar(
}); });
out.push(UiSprite { out.push(UiSprite {
texture, sprite,
pos: AnchoredUiPosition::NwSw(Point2 { pos: AnchoredUiPosition::NwSw(Point2 {
x: (radar_size / 2.0 + 10.0) - d.x, x: (radar_size / 2.0 + 10.0) - d.x,
y: (radar_size / -2.0 - 10.0) - d.y, y: (radar_size / -2.0 - 10.0) - d.y,
@ -146,7 +146,7 @@ pub fn build_radar(
}); });
out.push(UiSprite { out.push(UiSprite {
texture, sprite,
pos: AnchoredUiPosition::NwSe(Point2 { pos: AnchoredUiPosition::NwSe(Point2 {
x: (radar_size / 2.0 + 10.0) + d.x, x: (radar_size / 2.0 + 10.0) + d.x,
y: (radar_size / -2.0 - 10.0) - d.y, y: (radar_size / -2.0 - 10.0) - d.y,
@ -157,7 +157,7 @@ pub fn build_radar(
}); });
out.push(UiSprite { out.push(UiSprite {
texture, sprite,
pos: AnchoredUiPosition::NwNe(Point2 { pos: AnchoredUiPosition::NwNe(Point2 {
x: (radar_size / 2.0 + 10.0) + d.x, x: (radar_size / 2.0 + 10.0) + d.x,
y: (radar_size / -2.0 - 10.0) + d.y, y: (radar_size / -2.0 - 10.0) + d.y,
@ -174,7 +174,7 @@ pub fn build_radar(
if m > 200.0 { if m > 200.0 {
let player_angle: Deg<f32> = q.angle(Vector2 { x: 0.0, y: 1.0 }).into(); let player_angle: Deg<f32> = q.angle(Vector2 { x: 0.0, y: 1.0 }).into();
out.push(UiSprite { out.push(UiSprite {
texture: arrow_texture, sprite: arrow_sprite,
pos: AnchoredUiPosition::NwC( pos: AnchoredUiPosition::NwC(
Point2 { Point2 {
x: radar_size / 2.0 + 10.0, x: radar_size / 2.0 + 10.0,
@ -182,7 +182,7 @@ pub fn build_radar(
} + ((q.normalize() * 0.865) * (radar_size / 2.0)), } + ((q.normalize() * 0.865) * (radar_size / 2.0)),
), ),
dimensions: Point2 { dimensions: Point2 {
x: arrow_texture.aspect, x: arrow_sprite.aspect,
y: 1.0, y: 1.0,
} * 10.0, } * 10.0,
angle: -player_angle, angle: -player_angle,

View File

@ -44,7 +44,7 @@ impl ProjectileWorldObject {
let ang: Deg<f32> = rot.angle(Vector2 { x: 1.0, y: 0.0 }).into(); let ang: Deg<f32> = rot.angle(Vector2 { x: 1.0, y: 0.0 }).into();
ObjectSprite { ObjectSprite {
texture: self.projectile.content.sprite_texture, sprite: self.projectile.content.sprite,
pos: Point3 { pos: Point3 {
x: pos.x, x: pos.x,
y: pos.y, y: pos.y,

View File

@ -86,7 +86,7 @@ impl ShipWorldObject {
ObjectSprite { ObjectSprite {
pos: (ship_pos.x, ship_pos.y, 1.0).into(), pos: (ship_pos.x, ship_pos.y, 1.0).into(),
texture: s.sprite_texture, sprite: s.sprite,
angle: -ship_ang, angle: -ship_ang,
size: s.size, size: s.size,

View File

@ -189,7 +189,7 @@ impl<'a> World {
} }
}; };
particles.push(ParticleBuilder { particles.push(ParticleBuilder {
texture: x.texture, sprite: x.sprite,
pos: Point2 { x: pos.x, y: pos.y }, pos: Point2 { x: pos.x, y: pos.y },
velocity, velocity,
angle: -angle, angle: -angle,
@ -332,7 +332,7 @@ impl<'a> World {
content::ImpactInheritVelocity::Projectile => util::rigidbody_velocity(&pr), content::ImpactInheritVelocity::Projectile => util::rigidbody_velocity(&pr),
}; };
particles.push(ParticleBuilder { particles.push(ParticleBuilder {
texture: x.texture, sprite: x.sprite,
pos: Point2 { x: pos.x, y: pos.y }, pos: Point2 { x: pos.x, y: pos.y },
velocity, velocity,
angle: -angle, angle: -angle,