mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00

cd newIDE/app && npm run format cd newIDE/electron-app && npm run format cd GDJS && npm run format
212 lines
6.2 KiB
TypeScript
212 lines
6.2 KiB
TypeScript
/*
|
|
GDevelop - Pathfinding Behavior Extension
|
|
Copyright (c) 2013-2016 Florian Rival (Florian.Rival@gmail.com)
|
|
*/
|
|
|
|
namespace gdjs {
|
|
declare var rbush: any;
|
|
|
|
/**
|
|
* PathfindingObstaclesManager manages the common objects shared by objects having a
|
|
* pathfinding behavior: In particular, the obstacles behaviors are required to declare
|
|
* themselves (see `PathfindingObstaclesManager.addObstacle`) to the manager of their associated scene
|
|
* (see `gdjs.PathfindingRuntimeBehavior.obstaclesManagers`).
|
|
*/
|
|
export class PathfindingObstaclesManager {
|
|
_obstaclesRBush: any;
|
|
|
|
/**
|
|
* @param object The object
|
|
*/
|
|
constructor(runtimeScene: gdjs.RuntimeScene) {
|
|
this._obstaclesRBush = new rbush();
|
|
}
|
|
|
|
/**
|
|
* Get the obstacles manager of a scene.
|
|
*/
|
|
static getManager(runtimeScene) {
|
|
if (!runtimeScene.pathfindingObstaclesManager) {
|
|
//Create the shared manager if necessary.
|
|
runtimeScene.pathfindingObstaclesManager =
|
|
new gdjs.PathfindingObstaclesManager(runtimeScene);
|
|
}
|
|
return runtimeScene.pathfindingObstaclesManager;
|
|
}
|
|
|
|
/**
|
|
* Add a obstacle to the list of existing obstacles.
|
|
*/
|
|
addObstacle(
|
|
pathfindingObstacleBehavior: PathfindingObstacleRuntimeBehavior
|
|
) {
|
|
if (pathfindingObstacleBehavior.currentRBushAABB)
|
|
pathfindingObstacleBehavior.currentRBushAABB.updateAABBFromOwner();
|
|
else
|
|
pathfindingObstacleBehavior.currentRBushAABB =
|
|
new gdjs.BehaviorRBushAABB(pathfindingObstacleBehavior);
|
|
|
|
this._obstaclesRBush.insert(pathfindingObstacleBehavior.currentRBushAABB);
|
|
}
|
|
|
|
/**
|
|
* Remove a obstacle from the list of existing obstacles. Be sure that the obstacle was
|
|
* added before.
|
|
*/
|
|
removeObstacle(
|
|
pathfindingObstacleBehavior: PathfindingObstacleRuntimeBehavior
|
|
) {
|
|
this._obstaclesRBush.remove(pathfindingObstacleBehavior.currentRBushAABB);
|
|
}
|
|
|
|
/**
|
|
* Returns all the platforms around the specified object.
|
|
* @param maxMovementLength The maximum distance, in pixels, the object is going to do.
|
|
* @return An array with all platforms near the object.
|
|
*/
|
|
getAllObstaclesAround(
|
|
x: float,
|
|
y: float,
|
|
radius: float,
|
|
result: gdjs.PathfindingObstacleRuntimeBehavior[]
|
|
): void {
|
|
const searchArea = gdjs.staticObject(
|
|
PathfindingObstaclesManager.prototype.getAllObstaclesAround
|
|
);
|
|
// @ts-ignore
|
|
searchArea.minX = x - radius;
|
|
// @ts-ignore
|
|
searchArea.minY = y - radius;
|
|
// @ts-ignore
|
|
searchArea.maxX = x + radius;
|
|
// @ts-ignore
|
|
searchArea.maxY = y + radius;
|
|
const nearbyObstacles: gdjs.BehaviorRBushAABB<gdjs.PathfindingObstacleRuntimeBehavior>[] =
|
|
this._obstaclesRBush.search(searchArea);
|
|
result.length = 0;
|
|
nearbyObstacles.forEach((nearbyObstacle) =>
|
|
result.push(nearbyObstacle.behavior)
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* PathfindingObstacleRuntimeBehavior represents a behavior allowing objects to be
|
|
* considered as a obstacle by objects having Pathfinding Behavior.
|
|
*/
|
|
export class PathfindingObstacleRuntimeBehavior extends gdjs.RuntimeBehavior {
|
|
_impassable: boolean;
|
|
_cost: float;
|
|
_oldX: float = 0;
|
|
_oldY: float = 0;
|
|
_oldWidth: float = 0;
|
|
_oldHeight: float = 0;
|
|
_manager: PathfindingObstaclesManager;
|
|
_registeredInManager: boolean = false;
|
|
currentRBushAABB: gdjs.BehaviorRBushAABB<PathfindingObstacleRuntimeBehavior> | null =
|
|
null;
|
|
|
|
constructor(
|
|
runtimeScene: gdjs.RuntimeScene,
|
|
behaviorData,
|
|
owner: gdjs.RuntimeObject
|
|
) {
|
|
super(runtimeScene, behaviorData, owner);
|
|
this._impassable = behaviorData.impassable;
|
|
this._cost = behaviorData.cost;
|
|
this._manager = PathfindingObstaclesManager.getManager(runtimeScene);
|
|
|
|
//Note that we can't use getX(), getWidth()... of owner here:
|
|
//The owner is not yet fully constructed.
|
|
}
|
|
|
|
updateFromBehaviorData(oldBehaviorData, newBehaviorData): boolean {
|
|
if (oldBehaviorData.impassable !== newBehaviorData.impassable) {
|
|
this.setImpassable(newBehaviorData.impassable);
|
|
}
|
|
if (oldBehaviorData.cost !== newBehaviorData.cost) {
|
|
this.setCost(newBehaviorData.cost);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
onDestroy() {
|
|
if (this._manager && this._registeredInManager) {
|
|
this._manager.removeObstacle(this);
|
|
}
|
|
}
|
|
|
|
doStepPreEvents(runtimeScene: gdjs.RuntimeScene) {
|
|
//Make sure the obstacle is or is not in the obstacles manager.
|
|
if (!this.activated() && this._registeredInManager) {
|
|
this._manager.removeObstacle(this);
|
|
this._registeredInManager = false;
|
|
} else {
|
|
if (this.activated() && !this._registeredInManager) {
|
|
this._manager.addObstacle(this);
|
|
this._registeredInManager = true;
|
|
}
|
|
}
|
|
|
|
//Track changes in size or position
|
|
if (
|
|
this._oldX !== this.owner.getX() ||
|
|
this._oldY !== this.owner.getY() ||
|
|
this._oldWidth !== this.owner.getWidth() ||
|
|
this._oldHeight !== this.owner.getHeight()
|
|
) {
|
|
if (this._registeredInManager) {
|
|
this._manager.removeObstacle(this);
|
|
this._manager.addObstacle(this);
|
|
}
|
|
this._oldX = this.owner.getX();
|
|
this._oldY = this.owner.getY();
|
|
this._oldWidth = this.owner.getWidth();
|
|
this._oldHeight = this.owner.getHeight();
|
|
}
|
|
}
|
|
|
|
doStepPostEvents(runtimeScene: gdjs.RuntimeScene) {}
|
|
|
|
getAABB() {
|
|
return this.owner.getAABB();
|
|
}
|
|
|
|
onActivate() {
|
|
if (this._registeredInManager) {
|
|
return;
|
|
}
|
|
this._manager.addObstacle(this);
|
|
this._registeredInManager = true;
|
|
}
|
|
|
|
onDeActivate() {
|
|
if (!this._registeredInManager) {
|
|
return;
|
|
}
|
|
this._manager.removeObstacle(this);
|
|
this._registeredInManager = false;
|
|
}
|
|
|
|
getCost() {
|
|
return this._cost;
|
|
}
|
|
|
|
setCost(cost: float): void {
|
|
this._cost = cost;
|
|
}
|
|
|
|
isImpassable(): boolean {
|
|
return this._impassable;
|
|
}
|
|
|
|
setImpassable(impassable: boolean): void {
|
|
this._impassable = impassable;
|
|
}
|
|
}
|
|
gdjs.registerBehavior(
|
|
'PathfindingBehavior::PathfindingObstacleBehavior',
|
|
gdjs.PathfindingObstacleRuntimeBehavior
|
|
);
|
|
}
|