bug with objects moving
This commit is contained in:
+86
-1
@@ -396,6 +396,33 @@ impl Board {
|
|||||||
.collect()
|
.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)`.
|
/// 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)
|
/// 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 crate::utils::{Direction, ObjectId};
|
||||||
use color::Rgba8;
|
use color::Rgba8;
|
||||||
use std::collections::HashMap;
|
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.
|
/// Builds an all-empty `w×h` board.
|
||||||
///
|
///
|
||||||
@@ -704,6 +735,60 @@ pub(crate) mod tests {
|
|||||||
id
|
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
|
/// Adds an invisible, script-only [`Sensor`] at `(x, y)` running the world script
|
||||||
/// named `script`, returning its id.
|
/// named `script`, returning its id.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -553,7 +553,7 @@ fn step_object(board: &mut Board, id: ObjectId, dir: Direction) {
|
|||||||
|
|
||||||
if solid {
|
if solid {
|
||||||
// This is a real object on the board, try and push it
|
// This is a real object on the board, try and push it
|
||||||
board.push(loc.0, loc.1, dir);
|
board.move_object(loc.0, loc.1, dir);
|
||||||
} else {
|
} else {
|
||||||
// This is a sensor, we can just teleport it
|
// This is a sensor, we can just teleport it
|
||||||
board.move_sensor(id, dir);
|
board.move_sensor(id, dir);
|
||||||
|
|||||||
@@ -118,6 +118,11 @@ impl Direction {
|
|||||||
Some(if dy > 0 { Direction::South } else { Direction::North })
|
Some(if dy > 0 { Direction::South } else { Direction::North })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Translate the given point in this direction
|
||||||
|
pub fn from_point(self, x: i64, y: i64) -> (i64, i64) {
|
||||||
|
(x as i64 + self.dx(), y as i64 + self.dy())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A value that can be stored in a board's script registry across board transitions.
|
/// A value that can be stored in a board's script registry across board transitions.
|
||||||
|
|||||||
Reference in New Issue
Block a user