Hey all,
While doing my first big typescript project I've posted a couple of times about random issues I have found
I thought this time I would give back with some useful functions that I have found/written along the way!
Most of these were found during the conversion from raw Javascript to Typescript, as by default TS doesn't let you do the weird-hacks that JS does
Since when has that stopped anyone however!
I will add to this thread when I find more weird things to do, the project I have building for this can be found on Github Here if anyone is interested!
Please enjoy, and run at your own risk!
Get Construct Object Type from String
Example Usage => Get the specific Bullet you want your Turret to spawn, when the turret baseline are Family based
// general typescript function, to get the property off the object using
export function getProperty<T, K extends keyof T>(o: T, propertyName: K): T[K] {
return o[propertyName]; // o[propertyName] is of type T[K]
}
// get an ObjectType from the runtime objects list based on the name of the object
// mostly used to be able to spawn items via configuration
export function getObjectType<T extends IWorldInstance>(runtime: IRuntime, name: string): IObjectType<T> {
// get the object key using the Construct Object Name
// eg - runtime.objects.MyEnemyType
const typekey = name as keyof IConstructProjectObjects;
return getProperty(runtime.objects, typekey) as IObjectType<T>;
}
Get Effect Type - Bug Workaround
Currently accessing Effects via typescript is bugged - discussed here
// bugfix workaround for effects
// casts the effects object to an array, then pulls the type via name
export function getEffectType(effectArray: any , name: string): IEffectInstance | null {
const hackCast = effectArray as IEffectInstance[];
const found = hackCast.find((ef) => ef.name == name);
return found != null ? found as IEffectInstance : null;
}
Parse a Project JSON File at runtime
export const safeJsonParse = <T>(str: string) => {
try {
const jsonValue: T = JSON.parse(str);
return jsonValue;
} catch {
return undefined;
}
};
export const safeGetConstructFileJson = <T>(runtime: IRuntime, fileName: string) : Promise<T> =>{
return new Promise((resolve, reject) =>
runtime.assets
// get project file URL Promise
.getProjectFileUrl(fileName)
.then((filepath) =>
// ajax get the file contents (also promise)
fetch(filepath)
.then((response) =>
// get the text from the file (AGAIN another promis)
response.text()
.then((rawJSON) => {
// parse the results
const result = safeJsonParse<T>(rawJSON);
result !== undefined
// funally resolve the promise stack
? resolve(result)
: reject(`Unable to parse to ${fileName} : + ${rawJSON}`);
})
.catch((reason) => reject(`Unable to fetch ${fileName} Datafile - ${reason}`))
)
.catch((reason) => `Unable to FIND ${fileName} data file - ${reason}`)
)
.catch((reason) => `the install didnt work, cant find ${fileName} - ${reason}`)
);
}
Easy Instance Object Configuration
runtime.objects.Type.setInstanceClass
Doing that manually is very boring and very prone to human error
So I made a method to do it easy
async function ConfigureCustomTypes(runtime:IRuntime)
{
const customTypeMapping = [
{
InstanceType: EnemyControl,
ConstructObjectTypes: [runtime.objects.BasicEnemy, runtime.objects.BasicEnemy2],
},
{
InstanceType: TowerController,
ConstructObjectTypes: [runtime.objects.basicTower, runtime.objects.BasicTower2],
},
...
];
customTypeMapping.forEach(tm => {
const type = tm.InstanceType;
tm.ConstructObjectTypes.forEach((n) => {
if (n != null) n.setInstanceClass(type);
});
})
Make 2D Array
Want to make a giant 2d array to represent say a grid?
Say to map objects on top of a tile map?
function makeArray<T>(w: number, h: number, val: T) {
var arr: T[][] = [];
for(let i = 0; i < w; i++) {
arr[i] = [];
for(let j = 0; j < h; j++) {
arr[i][j] = val;
}
}
return arr;
}
Get Tilemap Coords from Mouseclick
You have a tilemap
you have things ONTOP of the tile map, and you need to figure out if there is something IN the tilemap
// do this earlier somewhere to use
mouseXYAr = this.gridLayer!.cssPxToLayer(pointerEvent.clientX, pointerEvent.clientY);
private getGridCoordsAndSize(tilemap: ITilemapInstance, mouseXYAr: number[]) {
const tileSizeX = tilemap.tileWidth;
const tileSizeY = tilemap.tileHeight;
const cellCoords = [Math.floor(mouseXYAr[0] / tileSizeX), Math.floor(mouseXYAr[1] / tileSizeY)];
return { cellCoords, tileSizeX, tileSizeY };
}