forked from profectus/Profectus
Add function to boards for placing nodes in the next available space
This commit is contained in:
parent
c08ea9ce85
commit
425e85a1ee
1 changed files with 73 additions and 1 deletions
|
@ -12,7 +12,7 @@ import { globalBus } from "game/events";
|
||||||
import { DefaultValue, deletePersistent, Persistent, State } from "game/persistence";
|
import { DefaultValue, deletePersistent, Persistent, State } from "game/persistence";
|
||||||
import { persistent } from "game/persistence";
|
import { persistent } from "game/persistence";
|
||||||
import type { Unsubscribe } from "nanoevents";
|
import type { Unsubscribe } from "nanoevents";
|
||||||
import { isFunction } from "util/common";
|
import { Direction, isFunction } from "util/common";
|
||||||
import type {
|
import type {
|
||||||
Computable,
|
Computable,
|
||||||
GetComputableType,
|
GetComputableType,
|
||||||
|
@ -266,6 +266,8 @@ export interface BaseBoard {
|
||||||
receivingNode: Ref<BoardNode | null>;
|
receivingNode: Ref<BoardNode | null>;
|
||||||
/** The current mouse position, if over the board. */
|
/** The current mouse position, if over the board. */
|
||||||
mousePosition: Ref<{ x: number; y: number } | null>;
|
mousePosition: Ref<{ x: number; y: number } | null>;
|
||||||
|
/** Places a node in the nearest empty space in the given direction with the specified space around it. */
|
||||||
|
placeInAvailableSpace: (node: BoardNode, radius?: number, direction?: Direction) => void;
|
||||||
/** A symbol that helps identify features of the same type. */
|
/** A symbol that helps identify features of the same type. */
|
||||||
type: typeof BoardType;
|
type: typeof BoardType;
|
||||||
/** The Vue component used to render this feature. */
|
/** The Vue component used to render this feature. */
|
||||||
|
@ -484,6 +486,76 @@ export function createBoard<T extends BoardOptions>(
|
||||||
board.receivingNode!.value = node;
|
board.receivingNode!.value = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
board.placeInAvailableSpace = function (
|
||||||
|
node: BoardNode,
|
||||||
|
radius = 100,
|
||||||
|
direction = Direction.Right
|
||||||
|
) {
|
||||||
|
const nodes = processedBoard.nodes.value
|
||||||
|
.slice()
|
||||||
|
.filter(n => {
|
||||||
|
// Exclude self
|
||||||
|
if (n === node) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exclude nodes that aren't within the corridor we'll be moving within
|
||||||
|
if (
|
||||||
|
(direction === Direction.Down || direction === Direction.Up) &&
|
||||||
|
Math.abs(n.position.x - node.position.x) > radius
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
(direction === Direction.Left || direction === Direction.Right) &&
|
||||||
|
Math.abs(n.position.y - node.position.y) > radius
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exclude nodes in the wrong direction
|
||||||
|
return !(
|
||||||
|
(direction === Direction.Right &&
|
||||||
|
n.position.x < node.position.x - radius) ||
|
||||||
|
(direction === Direction.Left && n.position.x > node.position.x + radius) ||
|
||||||
|
(direction === Direction.Up && n.position.y > node.position.y + radius) ||
|
||||||
|
(direction === Direction.Down && n.position.y < node.position.y - radius)
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.sort(
|
||||||
|
direction === Direction.Right
|
||||||
|
? (a, b) => a.position.x - b.position.x
|
||||||
|
: direction === Direction.Left
|
||||||
|
? (a, b) => b.position.x - a.position.x
|
||||||
|
: direction === Direction.Up
|
||||||
|
? (a, b) => b.position.y - a.position.y
|
||||||
|
: (a, b) => a.position.y - b.position.y
|
||||||
|
);
|
||||||
|
for (let i = 0; i < nodes.length; i++) {
|
||||||
|
const nodeToCheck = nodes[i];
|
||||||
|
const distance =
|
||||||
|
direction === Direction.Right || direction === Direction.Left
|
||||||
|
? Math.abs(node.position.x - nodeToCheck.position.x)
|
||||||
|
: Math.abs(node.position.y - nodeToCheck.position.y);
|
||||||
|
|
||||||
|
// If we're too close to this node, move further
|
||||||
|
if (distance < radius) {
|
||||||
|
if (direction === Direction.Right) {
|
||||||
|
node.position.x = nodeToCheck.position.x + radius;
|
||||||
|
} else if (direction === Direction.Left) {
|
||||||
|
node.position.x = nodeToCheck.position.x - radius;
|
||||||
|
} else if (direction === Direction.Up) {
|
||||||
|
node.position.y = nodeToCheck.position.y - radius;
|
||||||
|
} else if (direction === Direction.Down) {
|
||||||
|
node.position.y = nodeToCheck.position.y + radius;
|
||||||
|
}
|
||||||
|
} else if (i > 0 && distance > radius) {
|
||||||
|
// If we're further from this node than the radius, then the nodes are past us and we can early exit
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
board[GatherProps] = function (this: GenericBoard) {
|
board[GatherProps] = function (this: GenericBoard) {
|
||||||
const {
|
const {
|
||||||
nodes,
|
nodes,
|
||||||
|
|
Loading…
Reference in a new issue