256 lines
7.1 KiB
Rust
256 lines
7.1 KiB
Rust
use crate::util::Vector2I;
|
|
|
|
use super::TexelID;
|
|
use bevy::prelude::*;
|
|
use lazy_static::lazy_static;
|
|
use std::{borrow::Cow, collections::HashMap};
|
|
|
|
lazy_static! {
|
|
static ref ID_MAP: HashMap<TexelID, TexelBehaviour2D> = {
|
|
let mut result = HashMap::new();
|
|
|
|
result.insert(
|
|
1,
|
|
TexelBehaviour2D {
|
|
name: Cow::Borrowed("loose sand"),
|
|
color: Color::rgb(0.61, 0.49, 0.38),
|
|
gravity: Some(TexelGravity::Down(200)),
|
|
has_collision: true,
|
|
..default()
|
|
},
|
|
);
|
|
|
|
result.insert(
|
|
2,
|
|
TexelBehaviour2D {
|
|
name: Cow::Borrowed("loose stone"),
|
|
color: Color::rgb(0.21, 0.19, 0.17),
|
|
gravity: Some(TexelGravity::Down(200)),
|
|
has_collision: true,
|
|
..default()
|
|
},
|
|
);
|
|
|
|
result.insert(
|
|
3,
|
|
TexelBehaviour2D {
|
|
name: Cow::Borrowed("loose sturdy stone"),
|
|
color: Color::rgb(0.11, 0.11, 0.11),
|
|
gravity: Some(TexelGravity::Down(200)),
|
|
has_collision: true,
|
|
..default()
|
|
},
|
|
);
|
|
|
|
result.insert(
|
|
4,
|
|
TexelBehaviour2D {
|
|
name: Cow::Borrowed("water"),
|
|
color: Color::rgba(0.0, 0.0, 1.0, 0.5),
|
|
form: TexelForm::Liquid,
|
|
gravity: Some(TexelGravity::Down(50)),
|
|
..default()
|
|
},
|
|
);
|
|
|
|
result.insert(
|
|
5,
|
|
TexelBehaviour2D {
|
|
name: Cow::Borrowed("oil"),
|
|
color: Color::rgba(0.5, 0.5, 0.25, 0.5),
|
|
form: TexelForm::Liquid,
|
|
gravity: Some(TexelGravity::Down(20)),
|
|
..default()
|
|
},
|
|
);
|
|
|
|
result.insert(
|
|
6,
|
|
TexelBehaviour2D {
|
|
name: Cow::Borrowed("light gas"),
|
|
color: Color::rgba(0.0, 1.0, 0.0, 0.5),
|
|
form: TexelForm::Gas,
|
|
gravity: Some(TexelGravity::Up(160)),
|
|
..default()
|
|
},
|
|
);
|
|
|
|
result.insert(
|
|
7,
|
|
TexelBehaviour2D {
|
|
name: Cow::Borrowed("heavy gas"),
|
|
color: Color::rgba(1.0, 0.5, 0.5, 0.5),
|
|
form: TexelForm::Gas,
|
|
gravity: Some(TexelGravity::Down(60)),
|
|
..default()
|
|
},
|
|
);
|
|
|
|
result.insert(
|
|
8,
|
|
TexelBehaviour2D {
|
|
name: Cow::Borrowed("oxygen"),
|
|
color: Color::rgba(0.5, 0.5, 0.5, 0.5),
|
|
form: TexelForm::Gas,
|
|
..default()
|
|
},
|
|
);
|
|
|
|
result.insert(
|
|
11,
|
|
TexelBehaviour2D {
|
|
name: Cow::Borrowed("sand"),
|
|
color: Color::rgb(0.61, 0.49, 0.38),
|
|
has_collision: true,
|
|
..default()
|
|
},
|
|
);
|
|
|
|
result.insert(
|
|
12,
|
|
TexelBehaviour2D {
|
|
name: Cow::Borrowed("stone"),
|
|
color: Color::rgb(0.21, 0.19, 0.17),
|
|
has_collision: true,
|
|
..default()
|
|
},
|
|
);
|
|
|
|
result.insert(
|
|
13,
|
|
TexelBehaviour2D {
|
|
name: Cow::Borrowed("sturdy stone"),
|
|
color: Color::rgb(0.11, 0.11, 0.11),
|
|
has_collision: true,
|
|
..default()
|
|
},
|
|
);
|
|
|
|
result
|
|
};
|
|
static ref FORM_DISPLACEMENT_PRIORITY: HashMap<TexelForm, u8> = {
|
|
let mut result = HashMap::new();
|
|
result.insert(TexelForm::Gas, 0);
|
|
result.insert(TexelForm::Liquid, 1);
|
|
result.insert(TexelForm::Solid, 2);
|
|
result
|
|
};
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
|
|
pub enum TexelForm {
|
|
#[default]
|
|
// Solid materials, when affected by gravity, create pyramid-like piles
|
|
Solid,
|
|
// Liquid materials, when affected by gravity, act like solids but also try to stabilise the surface level by traveling flat surfaces
|
|
Liquid,
|
|
// Gas materials act like liquids, but also have density/pressure that causes them to disperse
|
|
Gas,
|
|
}
|
|
|
|
impl TexelForm {
|
|
fn priority(&self) -> u8 {
|
|
FORM_DISPLACEMENT_PRIORITY
|
|
.get(self)
|
|
.cloned()
|
|
.unwrap_or_default()
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
pub enum TexelGravity {
|
|
Down(u8),
|
|
Up(u8),
|
|
}
|
|
|
|
impl From<TexelGravity> for Vector2I {
|
|
fn from(gravity: TexelGravity) -> Self {
|
|
match gravity {
|
|
TexelGravity::Down(_) => Vector2I::DOWN,
|
|
TexelGravity::Up(_) => Vector2I::UP,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TexelGravity {
|
|
pub fn abs(&self) -> u8 {
|
|
match self {
|
|
TexelGravity::Down(grav) => *grav,
|
|
TexelGravity::Up(grav) => *grav,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub struct TexelBehaviour2D {
|
|
pub name: Cow<'static, str>,
|
|
pub color: Color,
|
|
pub form: TexelForm,
|
|
pub has_collision: bool,
|
|
pub gravity: Option<TexelGravity>,
|
|
pub toughness: Option<f32>,
|
|
}
|
|
|
|
impl Default for TexelBehaviour2D {
|
|
fn default() -> Self {
|
|
TexelBehaviour2D {
|
|
name: Cow::Borrowed("Unnamed material"),
|
|
color: Color::PINK,
|
|
form: TexelForm::Solid,
|
|
has_collision: false,
|
|
gravity: None,
|
|
toughness: None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TexelBehaviour2D {
|
|
pub const OUT_OF_BOUNDS: Self = TexelBehaviour2D {
|
|
name: Cow::Borrowed(":)"),
|
|
color: Color::BLACK,
|
|
has_collision: true,
|
|
form: TexelForm::Solid,
|
|
gravity: None,
|
|
toughness: None,
|
|
};
|
|
|
|
pub fn from_id(id: &TexelID) -> Option<Self> {
|
|
ID_MAP.get(id).cloned()
|
|
}
|
|
|
|
pub fn is_empty(id: &TexelID) -> bool {
|
|
ID_MAP.get(id).is_none()
|
|
}
|
|
|
|
pub fn has_collision(id: &TexelID) -> bool {
|
|
ID_MAP.get(id).map_or(false, |b| b.has_collision)
|
|
}
|
|
|
|
/// Can this type of material displace another?
|
|
pub fn can_displace(from: &TexelBehaviour2D, to: &Option<TexelBehaviour2D>) -> bool {
|
|
let to = if let Some(to) = to { to } else { return true };
|
|
|
|
match (from.form, to.form) {
|
|
(from_form, to_form) => {
|
|
if from_form.priority() != to_form.priority() {
|
|
return from_form.priority() > to_form.priority();
|
|
}
|
|
if let (Some(from_grav), Some(to_grav)) = (from.gravity, to.gravity) {
|
|
match (from_grav, to_grav) {
|
|
(TexelGravity::Down(from_grav), TexelGravity::Down(to_grav)) => {
|
|
from_grav > to_grav
|
|
}
|
|
(TexelGravity::Up(from_grav), TexelGravity::Up(to_grav)) => {
|
|
from_grav > to_grav
|
|
}
|
|
(_, _) => true,
|
|
}
|
|
} else {
|
|
// Solids can also be displaced, but only if the other material has gravity
|
|
to_form != TexelForm::Solid
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|