Implement platforms

This commit is contained in:
crumblingstatue 2023-04-08 19:21:07 +02:00
parent 1662857731
commit 47035f1460
5 changed files with 79 additions and 11 deletions

View file

@ -121,6 +121,7 @@ impl App {
self.game.player.vspeed = -10.0;
self.game.player.jumps_left = 0;
}
self.game.player.down_intent = self.input.down(Key::S);
let terminal_velocity = 60.0;
self.game.player.vspeed = self
.game
@ -130,14 +131,22 @@ impl App {
let mut on_screen_tile_ents = Vec::new();
for_each_tile_on_screen(self.game.camera_offset, self.rt.size(), |tp, _sp| {
let tid = self.game.world.tile_at_mut(tp, &self.game.worldgen).mid;
if !self.game.tile_db[tid].solid {
let tdef = &self.game.tile_db[tid];
let Some(bb) = tdef.bb else {
return;
}
let tsize = TILE_SIZE as i32;
};
let x = tp.x as i32 * TILE_SIZE as i32;
let y = tp.y as i32 * TILE_SIZE as i32;
let en = s2dc::Entity::from_rect_corners(x, y, x + tsize, y + tsize);
on_screen_tile_ents.push(en);
let en = s2dc::Entity::from_rect_corners(
x + bb.x as i32,
y + bb.y as i32,
x + bb.w as i32,
y + bb.h as i32,
);
on_screen_tile_ents.push(TileColEn {
col: en,
platform: tdef.platform,
});
});
imm_dbg!(on_screen_tile_ents.len());
self.game
@ -146,7 +155,18 @@ impl App {
.move_y(self.game.player.vspeed, |player_en, off| {
let mut col = false;
for en in &on_screen_tile_ents {
if player_en.would_collide(en, off) {
if player_en.would_collide(&en.col, off) {
if en.platform {
if self.game.player.vspeed < 0. {
continue;
}
// If the player's feet are below the top of the platform,
// collision shouldn't happen
let player_feet = player_en.pos.y + player_en.bb.y;
if player_feet > en.col.pos.y || self.game.player.down_intent {
continue;
}
}
col = true;
if self.game.player.vspeed > 0. {
self.game.player.jumps_left = 1;
@ -162,7 +182,10 @@ impl App {
.move_x(self.game.player.hspeed, |player_en, off| {
let mut col = false;
for en in &on_screen_tile_ents {
if player_en.would_collide(en, off) {
if en.platform {
continue;
}
if player_en.would_collide(&en.col, off) {
col = true;
self.game.player.hspeed = 0.;
}
@ -290,6 +313,12 @@ impl App {
}
}
/// Tile collision entity for doing physics
struct TileColEn {
col: s2dc::Entity,
platform: bool,
}
fn viewport_center_offset(rw_size: Vector2u, rt_size: Vector2u, scale: u8) -> ScreenVec {
let rw_size = rw_size;
let rt_size = rt_size * scale as u32;

View file

@ -13,6 +13,8 @@ pub struct Player {
pub vspeed: f32,
pub hspeed: f32,
pub jumps_left: u8,
/// true if the player wants to jump down from a platform
pub down_intent: bool,
}
fn inspect_mobile_entity(en: &mut MobileEntity, ui: &mut egui::Ui, _id_src: u64) {
@ -32,6 +34,7 @@ impl Player {
vspeed: 0.0,
hspeed: 0.0,
jumps_left: 0,
down_intent: false,
}
}
#[allow(dead_code)]

View file

@ -15,10 +15,27 @@ use crate::{
#[derive(Serialize, Deserialize, Default, Debug, Inspect)]
pub struct TileDef {
pub solid: bool,
pub bb: Option<TileBb>,
/// Whether the tile emits light, and the light source offset
pub light: Option<ScreenVec>,
pub atlas_offset: AtlasOffset,
/// Platform behavior: Horizontally passable, vertically passable upwards
pub platform: bool,
}
const DEFAULT_TILE_BB: TileBb = TileBb {
x: 0,
y: 0,
w: TILE_SIZE,
h: TILE_SIZE,
};
#[derive(Serialize, Deserialize, Debug, Inspect, Clone, Copy)]
pub struct TileBb {
pub x: u8,
pub y: u8,
pub w: u8,
pub h: u8,
}
#[derive(Serialize, Deserialize, Debug, Inspect)]
@ -36,11 +53,12 @@ impl Default for TileDb {
}
const EMPTY: TileDef = TileDef {
solid: false,
bb: None,
light: None,
// Rendering empty tile is actually special cased, and no rendering is done.
// But just in case, put the offset to UNKNOWN
atlas_offset: UNKNOWN_ATLAS_OFF,
platform: false,
};
impl Index<TileId> for TileDb {
@ -76,12 +94,13 @@ impl Default for AtlasOffset {
const UNKNOWN_ATLAS_OFF: AtlasOffset = AtlasOffset { x: 320, y: 0 };
static UNKNOWN_TILE: TileDef = TileDef {
solid: true,
bb: None,
light: Some(ScreenVec {
x: TILE_SIZE as ScreenSc / 2,
y: TILE_SIZE as ScreenSc / 2,
}),
atlas_offset: UNKNOWN_ATLAS_OFF,
platform: false,
};
const PATH: &str = "tiles.dat";

View file

@ -3,7 +3,7 @@ use crate::{
math::TILE_SIZE,
};
use super::TileDb;
use super::{TileDb, DEFAULT_TILE_BB};
pub fn tiledb_edit_ui(ctx: &egui::Context, tile_db: &mut TileDb) {
egui::Window::new("Tiledb editor").show(ctx, |ui| {
@ -30,6 +30,23 @@ pub fn tiledb_edit_ui(ctx: &egui::Context, tile_db: &mut TileDb) {
}
}
}
match &mut def.bb {
Some(bb) => {
ui.label("x");
ui.add(egui::DragValue::new(&mut bb.x));
ui.label("y");
ui.add(egui::DragValue::new(&mut bb.y));
ui.label("w");
ui.add(egui::DragValue::new(&mut bb.w));
ui.label("h");
ui.add(egui::DragValue::new(&mut bb.h));
}
None => {
if ui.button("Insert bb").clicked() {
def.bb = Some(DEFAULT_TILE_BB);
}
}
}
}
});
ui.separator();

BIN
tiles.dat

Binary file not shown.