bug with objects moving
This commit is contained in:
+86
-1
@@ -396,6 +396,33 @@ impl Board {
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Tries to walk the object in x,y in the given direction. Pushes the cell in that direction
|
||||
/// first. This won't move anything if:
|
||||
/// - the cell x,y is empty; no-op
|
||||
/// - x,y is out of bounds, no-op
|
||||
/// - the target cell can't be pushed in that direction, either because it's `Block` or
|
||||
/// something in its chain is
|
||||
pub fn move_object(&mut self, x: usize, y: usize, dir: Direction) {
|
||||
// Is this even a cell?
|
||||
if self.in_bounds((x as i64, y as i64)) {
|
||||
// Is there anything in this cell?
|
||||
if self.get(x, y).is_some() {
|
||||
let (tx, ty) = dir.from_point(x as i64, y as i64);
|
||||
// Is the _target_ in bounds?
|
||||
if self.in_bounds((tx, ty)) {
|
||||
// Attempt to push the target out of the way
|
||||
self.push(tx as usize, ty as usize, dir);
|
||||
// Is the cell now empty?
|
||||
if self.get(tx as usize, ty as usize).is_none() {
|
||||
// Then finally, move the thing:
|
||||
let thing = self.grid[x + y * self.width].take();
|
||||
self.grid[tx as usize + ty as usize * self.width] = thing;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Moves the single solid occupant of `(x, y)` one step by `(dx, dy)`.
|
||||
///
|
||||
/// A solid object is relocated; otherwise the solid terrain archetype (a crate)
|
||||
@@ -636,7 +663,11 @@ pub(crate) mod tests {
|
||||
use crate::utils::{Direction, ObjectId};
|
||||
use color::Rgba8;
|
||||
use std::collections::HashMap;
|
||||
use crate::tile::{DrawLayer, IntoTile, Optics, ScriptAttributes, Sensor, SensorSpec, Tile, TileSpec};
|
||||
use crate::object_def::ObjectDef;
|
||||
use crate::tile::{
|
||||
DrawLayer, EnterResponse, IntoTile, Optics, ScriptAttributes, Sensor, SensorSpec, Tile,
|
||||
TileSpec,
|
||||
};
|
||||
|
||||
/// Builds an all-empty `w×h` board.
|
||||
///
|
||||
@@ -704,6 +735,60 @@ pub(crate) mod tests {
|
||||
id
|
||||
}
|
||||
|
||||
/// Stamps a scripted object at `(x, y)` running the world script named `script`,
|
||||
/// answering entry attempts with `enter`, and returns its id.
|
||||
///
|
||||
/// The on-grid counterpart to [`sensor_at`]: this object occupies its cell and
|
||||
/// takes part in collision, so `enter` decides how it responds to something
|
||||
/// moving into it (`Block` for an ordinary solid, `Push(..)` for a shovable one).
|
||||
pub(crate) fn object_at(
|
||||
board: &mut Board,
|
||||
x: usize,
|
||||
y: usize,
|
||||
script: &str,
|
||||
enter: EnterResponse,
|
||||
) -> ObjectId {
|
||||
let tile = TileSpec::Object {
|
||||
script: Some(script.to_string()),
|
||||
enter,
|
||||
glyph: ObjectDef::default_glyph(),
|
||||
optics: Optics { opaque: true, glow: 0 },
|
||||
name: None,
|
||||
tags: Vec::new(),
|
||||
}
|
||||
.into_tile(&mut board.next_object_id)
|
||||
.expect("an object spec always resolves");
|
||||
let id = match &tile {
|
||||
Tile::Object(obj) => obj.scripting.id,
|
||||
Tile::Player => unreachable!("an object spec never resolves to the player"),
|
||||
};
|
||||
*board.get_mut(x, y) = Some(tile);
|
||||
id
|
||||
}
|
||||
|
||||
/// Stamps a solid object at `(x, y)` with **no script attached**, returning its id.
|
||||
///
|
||||
/// For exercising the "an object without a script is inert" path; everything
|
||||
/// else should use [`object_at`].
|
||||
pub(crate) fn plain_object_at(board: &mut Board, x: usize, y: usize) -> ObjectId {
|
||||
let tile = TileSpec::Object {
|
||||
script: None,
|
||||
enter: EnterResponse::Block,
|
||||
glyph: ObjectDef::default_glyph(),
|
||||
optics: Optics { opaque: true, glow: 0 },
|
||||
name: None,
|
||||
tags: Vec::new(),
|
||||
}
|
||||
.into_tile(&mut board.next_object_id)
|
||||
.expect("an object spec always resolves");
|
||||
let id = match &tile {
|
||||
Tile::Object(obj) => obj.scripting.id,
|
||||
Tile::Player => unreachable!("an object spec never resolves to the player"),
|
||||
};
|
||||
*board.get_mut(x, y) = Some(tile);
|
||||
id
|
||||
}
|
||||
|
||||
/// Adds an invisible, script-only [`Sensor`] at `(x, y)` running the world script
|
||||
/// named `script`, returning its id.
|
||||
///
|
||||
|
||||
Reference in New Issue
Block a user