Files
GDevelop/Extensions/PlatformBehavior/platformruntimebehavior.ts
T

238 lines
7.6 KiB
TypeScript

/*
GDevelop - Platform Behavior Extension
Copyright (c) 2013-2016 Florian Rival (Florian.Rival@gmail.com)
*/
namespace gdjs {
declare var rbush: any;
/**
* Manages the common objects shared by objects having a
* platform behavior: in particular, the platforms behaviors are required to declare
* themselves (see PlatformObjectsManager.addPlatform) to the manager of their associated scene
* (see PlatformRuntimeBehavior.getManager).
*/
export class PlatformObjectsManager {
private _platformRBush: any;
/**
* @param object The object
*/
constructor(runtimeScene: gdjs.RuntimeScene) {
this._platformRBush = new rbush(9, [
'.owner.getAABB().min[0]',
'.owner.getAABB().min[1]',
'.owner.getAABB().max[0]',
'.owner.getAABB().max[1]',
]);
}
/**
* Get the platforms manager of a scene.
*/
static getManager(runtimeScene: gdjs.RuntimeScene) {
// @ts-ignore
if (!runtimeScene.platformsObjectsManager) {
//Create the shared manager if necessary.
// @ts-ignore
runtimeScene.platformsObjectsManager = new gdjs.PlatformObjectsManager(
runtimeScene
);
}
// @ts-ignore
return runtimeScene.platformsObjectsManager;
}
/**
* Add a platform to the list of existing platforms.
*/
addPlatform(platformBehavior: gdjs.PlatformRuntimeBehavior) {
this._platformRBush.insert(platformBehavior);
}
/**
* Remove a platform from the list of existing platforms. Be sure that the platform was
* added before.
*/
removePlatform(platformBehavior: gdjs.PlatformRuntimeBehavior) {
this._platformRBush.remove(platformBehavior);
}
/**
* 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.
*/
getAllPlatformsAround(
object: gdjs.RuntimeObject,
maxMovementLength: number,
result: gdjs.PlatformRuntimeBehavior[]
): any {
// TODO: This would better be done using the object AABB (getAABB), as (`getCenterX`;`getCenterY`) point
// is not necessarily in the middle of the object (for sprites for example).
const ow = object.getWidth();
const oh = object.getHeight();
const x = object.getDrawableX() + object.getCenterX();
const y = object.getDrawableY() + object.getCenterY();
const searchArea = gdjs.staticObject(
PlatformObjectsManager.prototype.getAllPlatformsAround
);
// @ts-ignore
searchArea.minX = x - ow / 2 - maxMovementLength;
// @ts-ignore
searchArea.minY = y - oh / 2 - maxMovementLength;
// @ts-ignore
searchArea.maxX = x + ow / 2 + maxMovementLength;
// @ts-ignore
searchArea.maxY = y + oh / 2 + maxMovementLength;
const nearbyPlatforms = this._platformRBush.search(searchArea);
result.length = 0;
result.push.apply(result, nearbyPlatforms);
}
}
/**
* PlatformRuntimeBehavior represents a behavior allowing objects to be
* considered as a platform by objects having PlatformerObject Behavior.
*/
export class PlatformRuntimeBehavior extends gdjs.RuntimeBehavior {
//Load the platform type
_platformType: integer;
_canBeGrabbed: boolean;
_yGrabOffset: float;
//Note that we can't use getX(), getWidth()... of owner here: The owner is not fully constructed.
_oldX: float = 0;
_oldY: float = 0;
_oldWidth: float = 0;
_oldHeight: float = 0;
_manager: gdjs.PlatformObjectsManager;
_registeredInManager: boolean = false;
constructor(
runtimeScene: gdjs.RuntimeScene,
behaviorData,
owner: gdjs.RuntimeObject
) {
super(runtimeScene, behaviorData, owner);
this._platformType = behaviorData.platformType;
if (behaviorData.platformType === 'Ladder') {
this._platformType = PlatformRuntimeBehavior.LADDER;
} else if (behaviorData.platformType === 'Jumpthru') {
this._platformType = PlatformRuntimeBehavior.JUMPTHRU;
} else {
this._platformType = PlatformRuntimeBehavior.NORMALPLAFTORM;
}
this._canBeGrabbed = behaviorData.canBeGrabbed || false;
this._yGrabOffset = behaviorData.yGrabOffset || 0;
this._manager = PlatformObjectsManager.getManager(runtimeScene);
}
updateFromBehaviorData(oldBehaviorData, newBehaviorData): boolean {
if (oldBehaviorData.platformType !== newBehaviorData.platformType) {
this.changePlatformType(newBehaviorData.platformType);
}
if (oldBehaviorData.canBeGrabbed !== newBehaviorData.canBeGrabbed) {
this._canBeGrabbed = newBehaviorData.canBeGrabbed;
}
if (oldBehaviorData.yGrabOffset !== newBehaviorData.yGrabOffset) {
this._yGrabOffset = newBehaviorData.yGrabOffset;
}
return true;
}
onDestroy() {
if (this._manager && this._registeredInManager) {
this._manager.removePlatform(this);
}
}
doStepPreEvents(runtimeScene: gdjs.RuntimeScene) {
//Scene change is not supported
/*if ( parentScene != &scene ) //Parent scene has changed
{
if ( sceneManager ) //Remove the object from any old scene manager.
sceneManager->RemovePlatform(this);
parentScene = &scene;
sceneManager = parentScene ? &ScenePlatformObjectsManager::managers[&scene] : NULL;
registeredInManager = false;
}*/
//Make sure the platform is or is not in the platforms manager.
if (!this.activated() && this._registeredInManager) {
this._manager.removePlatform(this);
this._registeredInManager = false;
} else {
if (this.activated() && !this._registeredInManager) {
this._manager.addPlatform(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.removePlatform(this);
this._manager.addPlatform(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) {}
onActivate() {
if (this._registeredInManager) {
return;
}
this._manager.addPlatform(this);
this._registeredInManager = true;
}
onDeActivate() {
if (!this._registeredInManager) {
return;
}
this._manager.removePlatform(this);
this._registeredInManager = false;
}
changePlatformType(platformType: string) {
if (platformType === 'Ladder') {
this._platformType = PlatformRuntimeBehavior.LADDER;
} else if (platformType === 'Jumpthru') {
this._platformType = PlatformRuntimeBehavior.JUMPTHRU;
} else {
this._platformType = PlatformRuntimeBehavior.NORMALPLAFTORM;
}
}
getPlatformType() {
return this._platformType;
}
canBeGrabbed() {
return this._canBeGrabbed;
}
getYGrabOffset() {
return this._yGrabOffset;
}
static NORMALPLAFTORM = 0;
static JUMPTHRU = 1;
static LADDER = 2;
}
gdjs.registerBehavior(
'PlatformBehavior::PlatformBehavior',
gdjs.PlatformRuntimeBehavior
);
}