wip
This commit is contained in:
@@ -16,30 +16,30 @@ fn tick(dt) {
|
||||
// Direction from the builtin tag; clockwise unless explicitly counter-clockwise.
|
||||
let cw = !Me.has_tag("BUILTIN_spinner_ccw");
|
||||
|
||||
let ox = Me.x;
|
||||
let oy = Me.y;
|
||||
|
||||
// The 8 neighbour offsets in clockwise order, starting at North.
|
||||
let ring = [
|
||||
[ 0, -1], // N
|
||||
[ 1, -1], // NE
|
||||
[ 1, 0], // E
|
||||
[ 1, 1], // SE
|
||||
[ 0, 1], // S
|
||||
[-1, 1], // SW
|
||||
[-1, 0], // W
|
||||
[-1, -1], // NW
|
||||
let cw_ring = [
|
||||
[Me.x, Me.y-1], // N
|
||||
[Me.x+1, Me.y-1], // NE
|
||||
[Me.x+1, Me.y], // E
|
||||
[Me.x+1, Me.y+1], // SE
|
||||
[Me.x, Me.y+1], // S
|
||||
[Me.x-1, Me.y+1], // SW
|
||||
[Me.x-1, Me.y], // W
|
||||
[Me.x-1, Me.y-1], // NW
|
||||
];
|
||||
|
||||
// The cardinal step that carries each ring cell to the *next* slot in the spin
|
||||
// direction, and the index offset to that slot (+1 clockwise, -1 == +7 counter).
|
||||
// CW: N->NE is East, NE->E is South, ... CCW: N->NW is West, NE->N is West, ...
|
||||
let dirs = if cw {
|
||||
[East, South, South, West, West, North, North, East]
|
||||
// For CCW, it's the same list in reverse
|
||||
let ccw_ring = [];
|
||||
for neighbor in cw_ring {
|
||||
ccw_ring.insert(0, neighbor);
|
||||
}
|
||||
|
||||
// Rotate the neighbor cells:
|
||||
if cw {
|
||||
shift(cw_ring);
|
||||
} else {
|
||||
[West, West, North, North, East, East, South, South]
|
||||
};
|
||||
let step = if cw { 1 } else { 7 };
|
||||
shift(ccw_ring);
|
||||
}
|
||||
|
||||
// Animate the glyph one frame per rotation (changing only the character): the
|
||||
// line spins '/'-'\'-, slash-swapped for counter-clockwise. Frame state lives in
|
||||
@@ -50,55 +50,5 @@ fn tick(dt) {
|
||||
set_tile(frames[f % 4]);
|
||||
Registry.set(fkey, (f + 1) % 4);
|
||||
|
||||
// moves[i]: will ring cell i rotate into its destination slot? Seed with
|
||||
// can_shift, which is true only when cell i holds a pushable whose immediate
|
||||
// next cell isn't a wall (so it could move *if* that next cell ends up free).
|
||||
let moves = [];
|
||||
for i in 0..8 {
|
||||
let sx = ox + ring[i][0];
|
||||
let sy = oy + ring[i][1];
|
||||
moves.push(can_shift(sx, sy, dirs[i]));
|
||||
}
|
||||
|
||||
// Cascade: a cell may only move if its destination is a hole (`passable`), or
|
||||
// the occupant of that destination also moves. Demote until stable. A broken
|
||||
// arc collapses back from the jam; a full pushable cycle never demotes (every
|
||||
// destination's occupant moves) and rotates whole via swap's cycle handling.
|
||||
loop {
|
||||
let changed = false;
|
||||
for i in 0..8 {
|
||||
let n = (i + step) % 8;
|
||||
let pn = (i + step - 1) % 8;
|
||||
let dx = ox + ring[n][0];
|
||||
let dy = oy + ring[n][1];
|
||||
let sx = ox + ring[pn][0];
|
||||
let sy = oy + ring[pn][1];
|
||||
|
||||
let blocked = !passable(dx, dy) && !combinable(sx, sy, dx, dy);
|
||||
|
||||
if moves[i] && blocked && !moves[n] {
|
||||
moves[i] = false;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
if !changed { break; }
|
||||
}
|
||||
|
||||
// Emit the surviving rotations as one simultaneous batch, then pace to twice
|
||||
// a second. Coordinates are pulled into locals first to keep each expression
|
||||
// simple (Rhai caps expression complexity).
|
||||
let batch = [];
|
||||
for i in 0..8 {
|
||||
if moves[i] {
|
||||
let n = (i + step) % 8;
|
||||
let sx = ox + ring[i][0];
|
||||
let sy = oy + ring[i][1];
|
||||
let dx = ox + ring[n][0];
|
||||
let dy = oy + ring[n][1];
|
||||
batch.push([sx, sy, dx, dy]);
|
||||
}
|
||||
}
|
||||
|
||||
swap(batch);
|
||||
delay(0.5);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user