pub struct Level { /* private fields */ }Expand description
Tiles on a grid, with refills. Outside the grid, the sides and the top are open air, and below the bottom the character falls out. Its parts are read and changed through methods, which keep them consistent (the grid with its size, the refills with the tile size).
Implementations§
Source§impl Level
impl Level
Sourcepub fn parse(rows: &[&str]) -> Self
pub fn parse(rows: &[&str]) -> Self
Parse a level from tile rows (see DEMO): # solid, = one-way platform, *
dash refill, P spawn, anything else air. Panics on ragged rows: levels
written in code should fail loudly on a typo.
Sourcepub fn parse_with(rows: &[&str], tile: impl Fn(char) -> Option<Tile>) -> Self
pub fn parse_with(rows: &[&str], tile: impl Fn(char) -> Option<Tile>) -> Self
Like Level::parse, with characters of your own: tile(c) is asked first for
each one, and a Some wins over the built-in meaning (so Some(Tile::Custom(0))
for ^ makes spikes, and Some(Tile::Empty) for * leaves the refills out). A
spawn marker of your own: Level::find it and Level::set_spawn_tile there.
use game_toolkit_platformer::sim::{Level, Rect, Tile};
const SPIKES: u8 = 0;
let level = Level::parse_with(&["....", ".^^.", "####"], |c| match c {
'^' => Some(Tile::Custom(SPIKES)),
_ => None,
});
let feet = Rect { x: 10, y: 4, w: 6, h: 12 };
assert!(level.tiles_touching(feet).any(|(_, _, t)| t == Tile::Custom(SPIKES)));
// `S`, a start pad of your own, is the spawn.
const PAD: u8 = 1;
let mut level = Level::parse_with(&["..S.", "####"], |c| (c == 'S').then_some(Tile::Custom(PAD)));
let (tx, ty) = level.find(Tile::Custom(PAD)).unwrap();
level.set_spawn_tile(tx, ty);
assert_eq!(level.spawn_tile(), (2, 0));Sourcepub fn from_fn(w: i32, h: i32, tile: impl Fn(i32, i32) -> Tile) -> Self
pub fn from_fn(w: i32, h: i32, tile: impl Fn(i32, i32) -> Tile) -> Self
A w x h level whose tile at x, y is tile(x, y): the way in from your own
tilemap. No refills, the spawn at the top-left; add them as you like.
Sourcepub fn with_tile_size(self, size: i32) -> Self
pub fn with_tile_size(self, size: i32) -> Self
This level with tiles of size units (refills scaled along). For a tilemap whose
tiles are bigger than the feel’s 8 units; to keep the feel at any tile size, keep
8-unit tiles and draw them scaled, or use a Builder::scale with your own terrain.
Sourcepub fn define(&mut self, id: u8, tile: CustomTile)
pub fn define(&mut self, id: u8, tile: CustomTile)
Make custom tile id tile to the movement: solid ground of some Surface (ice,
a conveyor, a wall that can’t be climbed), a one-way platform
(CustomTile::platform: a bouncy ledge), or air again with
CustomTile::default().
use game_toolkit_platformer::sim::{CustomTile, Level, Rect, Surface, Tile};
const ICE: u8 = 0;
let mut level = Level::parse_with(&["....", "~~~~"], |c| (c == '~').then_some(Tile::Custom(ICE)));
level.define(ICE, CustomTile::solid(Surface { friction: 0.1, ..Surface::DEFAULT }));
let feet = Rect { x: 8, y: 8, w: 6, h: 1 };
assert!(level.solid_tile(1, 1));
assert_eq!(level.surface_at(feet).friction, 0.1);Sourcepub fn custom_tile(&self, id: u8) -> CustomTile
pub fn custom_tile(&self, id: u8) -> CustomTile
What custom tile id is to the movement (air unless Level::defined).
Sourcepub fn tile_size(&self) -> i32
pub fn tile_size(&self) -> i32
The size of a tile in units: TILE unless Level::with_tile_size changed it.
Sourcepub fn spawn_tile(&self) -> (i32, i32)
pub fn spawn_tile(&self) -> (i32, i32)
The spawn tile (the character stands on the tile below it; see Level::start).
Sourcepub fn set_spawn_tile(&mut self, tx: i32, ty: i32)
pub fn set_spawn_tile(&mut self, tx: i32, ty: i32)
Move the spawn to tile tx, ty: a marker of your own (see Level::parse_with).
Sourcepub fn refills(&self) -> &[Crystal]
pub fn refills(&self) -> &[Crystal]
The dash refills, with whether each is there (Crystal::ready): for drawing.
Sourcepub fn add_refill(&mut self, tx: i32, ty: i32)
pub fn add_refill(&mut self, tx: i32, ty: i32)
Add a dash refill filling tile tx, ty (of this level’s tile size).
Sourcepub fn refill_back(&self) -> f32
pub fn refill_back(&self) -> f32
Seconds before a used refill comes back.
Sourcepub fn set_refill_back(&mut self, seconds: f32)
pub fn set_refill_back(&mut self, seconds: f32)
Make used refills come back after seconds.
Sourcepub fn find(&self, tile: Tile) -> Option<(i32, i32)>
pub fn find(&self, tile: Tile) -> Option<(i32, i32)>
The first tile that is tile, row by row: where a marker of your own is.
Sourcepub fn start(&self) -> Spot
pub fn start(&self) -> Spot
Where a character starts: standing on the bottom of the spawn tile, centered on it (units).
Sourcepub fn set(&mut self, tx: i32, ty: i32, tile: Tile)
pub fn set(&mut self, tx: i32, ty: i32, tile: Tile)
Change the tile at tx, ty (outside the grid: nothing happens).
Sourcepub fn tiles_touching(
&self,
r: Rect,
) -> impl Iterator<Item = (i32, i32, Tile)> + '_
pub fn tiles_touching( &self, r: Rect, ) -> impl Iterator<Item = (i32, i32, Tile)> + '_
The tiles r overlaps, as (tx, ty, tile), row by row: what the character’s
hitbox touches (spikes, water, the goal), with Tile::Custom tiles of your own.
Sourcepub fn touches(&self, hitboxes: &[Rect], tile: Tile) -> Option<Rect>
pub fn touches(&self, hitboxes: &[Rect], tile: Tile) -> Option<Rect>
The first of hitboxes that touches a tile, if any: pass
Platformer::hitboxes to test every step of the last
frame. The result is a copy, so you can act on the character right away:
if level.touches(hero.hitboxes(), SPIKES).is_some() { hero.respawn(); }.
Sourcepub fn solid_tile(&self, tx: i32, ty: i32) -> bool
pub fn solid_tile(&self, tx: i32, ty: i32) -> bool
Whether tile tx, ty is solid: Tile::Solid, or a custom tile
Level::defined solid.
Sourcepub fn platform_tile(&self, tx: i32, ty: i32) -> bool
pub fn platform_tile(&self, tx: i32, ty: i32) -> bool
Whether tile tx, ty is a one-way platform: Tile::Platform, or a custom tile
Level::defined one.
Sourcepub fn surface_at(&self, r: Rect) -> Surface
pub fn surface_at(&self, r: Rect) -> Surface
The surface r touches (the row under the feet, the column beside a wall): of the
holding tile under r’s center if there is one, else of the first holding tile it
overlaps, else Surface::DEFAULT. The same rule as Grid::surface_of.
Sourcepub fn overlaps(&self, r: Rect) -> bool
pub fn overlaps(&self, r: Rect) -> bool
Whether r overlaps any solid tile (platforms don’t count).
Sourcepub fn on_platform(&self, r: Rect) -> bool
pub fn on_platform(&self, r: Rect) -> bool
Whether r stands exactly on top of a one-way platform.
Trait Implementations§
impl StructuralPartialEq for Level
Source§impl Terrain for Level
impl Terrain for Level
Source§fn solid(&self, r: Rect) -> bool
fn solid(&self, r: Rect) -> bool
r overlaps anything solid (walls, floors, ceilings, moving solids).Source§fn platform(&self, r: Rect) -> bool
fn platform(&self, r: Rect) -> bool
r stands exactly on top of a one-way platform (its bottom edge on the
platform’s top). One-way platforms hold from above, let the character jump up
through them, and drop it on down + jump.Source§fn refill(&mut self, r: Rect) -> bool
fn refill(&mut self, r: Rect) -> bool
r touches a dash refill: use it up and return true (it’s
only asked when a dash is spent).Source§fn surface(&self, r: Rect) -> Surface
fn surface(&self, r: Rect) -> Surface
r touches: the row under the feet while standing, the
column beside the body at a wall. Ice, conveyor belts, walls that can’t be climbed,
bouncy pads (see Surface). Default: the base’s, or Surface::DEFAULT.Source§fn tick(&mut self, dt: f32, _bodies: &[Rect])
fn tick(&mut self, dt: f32, _bodies: &[Rect])
bodies (one, unless several share the terrain through a crate::Party): let
things fall onto them, refills come back, platforms move. Only this layer’s state:
Terrain::update runs the bases’ ticks by itself. Default: nothing.Source§fn base(&self) -> Option<&dyn Terrain>
fn base(&self) -> Option<&dyn Terrain>
None.
terrain_layer! writes it with Terrain::base_mut and
Terrain::as_any_mut. Required, so a wrapper can’t lose its base’s platforms,
refills and pits by forgetting it.Source§fn as_any_mut(&mut self) -> Option<&mut dyn Any>
fn as_any_mut(&mut self) -> Option<&mut dyn Any>
Ability can reach your type
through find_mut (break a block, flip a
switch): Some(self), which terrain_layer! writes.
Default: None, it isn’t found (its Terrain::base still is).Source§fn update(&mut self, dt: f32, bodies: &[Rect])
fn update(&mut self, dt: f32, bodies: &[Rect])
Terrain::tick on this layer, then on every base
down the chain. Don’t write it; write Terrain::tick. Only an adapter that hands
its base something else than it got (converted bodies, say) writes it, and then
calls the base’s update.Auto Trait Implementations§
impl Freeze for Level
impl RefUnwindSafe for Level
impl Send for Level
impl Sync for Level
impl Unpin for Level
impl UnsafeUnpin for Level
impl UnwindSafe for Level
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.