567 lines
15 KiB
TypeScript

enum ObjectType {
CUBOT = 1,
BIOMASS = 2,
HARVESTER_NPC = 10,
FACTORY = 3,
RADIO_TOWER = 4
}
enum ItemType {
BIOMASS = 1,
IRON = 3,
COPPER = 4
}
enum Action {
IDLE,
DIGGING,
WALKING,
WITHDRAWING,
DEPOSITING,
LISTENING,
JUMPING
}
abstract class GameObject extends Phaser.Plugin.Isometric.IsoSprite {
public tileX: number;
public tileY: number;
id: number;
protected direction: Direction;
protected action: Action;
public updated: boolean;
protected text: Phaser.Text;
constructor(x: number, y: number, z: number, key: any, frame: any) {
super(mar.game, x, y, z, key, frame);
}
public abstract updateObject(json): void;
public abstract onTileHover(): void;
public abstract onTileExit(): void;
/**
* Factory method for GameObjects
*/
public static createObject(json): GameObject {
switch (json.t) {
case ObjectType.CUBOT:
return new Cubot(json);
case ObjectType.BIOMASS:
return new BiomassBlob(json);
case ObjectType.HARVESTER_NPC:
return new HarvesterNPC(json);
case ObjectType.FACTORY:
return new Factory(json);
case ObjectType.RADIO_TOWER:
return new RadioTower(json);
default:
return null;
}
}
/**
* Set text that will appear on top of the object. Usually used for hover text
*/
protected setText(text: string): void {
this.text = mar.game.make.text(0, 0, text, {
fontSize: 22,
fill: config.textFill,
stroke: config.textStroke,
strokeThickness: 2,
font: "fixedsys"
});
this.text.anchor.set(0.5, 0);
this.addChild(this.text);
}
/**
* Tested to trigger onTileHover and onTileExit
*/
public isAt(x: number, y: number): boolean {
return x == this.tileX && y == this.tileY;
}
}
enum HologramMode {
CLEARED,
HEX,
STRING,
DEC
}
class Cubot extends GameObject {
username: string;
heldItem: ItemType;
energy: number;
private hologram: Phaser.Text;
/**
* List of animation functions queued for execution.
*/
queuedAnimations = [];
private hovered: boolean = false;
constructor(json) {
super(Util.getIsoX(json.x), Util.getIsoY(json.y), 15, "sheet", null);
if (DEBUG) {
console.log("Creating Cubot object");
}
this.anchor.set(0.5, 0);
this.id = json.i;
this.tileX = json.x;
this.tileY = json.y;
this.username = json.parent;
this.heldItem = json.heldItem;
this.direction = json.direction;
this.action = json.action;
this.energy = json.energy;
this.animations.add("walk_w", mar.animationFrames.walk_w);
this.animations.add("walk_s", mar.animationFrames.walk_s,);
this.animations.add("walk_e", mar.animationFrames.walk_e);
this.animations.add("walk_n", mar.animationFrames.walk_n);
this.animations.add("dig_w", mar.animationFrames.dig_w);
this.animations.add("dig_s", mar.animationFrames.dig_s);
this.animations.add("dig_e", mar.animationFrames.dig_e);
this.animations.add("dig_n", mar.animationFrames.dig_n);
this.createUsername();
this.updateDirection();
this.tint = this.getTint();
}
onTileHover(): void {
mar.game.add.tween(this).to({isoZ: 45}, 200, Phaser.Easing.Quadratic.InOut, true);
mar.game.add.tween(this.scale).to({x: 1.2, y: 1.2}, 200, Phaser.Easing.Linear.None, true);
this.tint = config.cubotHoverTint;
if (this.text !== undefined) {
this.text.visible = true;
}
this.hovered = true;
}
onTileExit(): void {
mar.game.add.tween(this).to({isoZ: 15}, 400, Phaser.Easing.Bounce.Out, true);
mar.game.add.tween(this.scale).to({x: 1, y: 1}, 200, Phaser.Easing.Linear.None, true);
if (this.text !== undefined) {
this.text.visible = false;
}
this.hovered = false;
this.tint = this.getTint();
}
public getTint(): number {
if (!this.hovered) {
if (this.energy <= config.lowEnergy) {
return config.lowEnergyTint;
} else {
return config.cubotTint;
}
} else {
return config.cubotHoverTint;
}
}
updateObject(json): void {
if (DEBUG) {
console.log("Updating Cubot object")
}
this.action = json.action;
this.energy = json.energy;
this.direction = json.direction;
//Update color
this.tint = this.getTint();
//Update Location
if (!this.isAt(json.x, json.y)) {
//Location changed
if (this.action == Action.WALKING) {
//Walking..
this.tileX = json.x;
this.tileY = json.y;
this.walk();
}
// else if (this.action == Action.JUMPING) {
// //TODO
// }
}
// if (this.action == Action.DIGGING) {
// //TODO dig animation
// }
this.updateDirection();
this.updateHologram(json.holoMode, json.holoC, json.holo, json.holoStr);
}
private updateHologram(holoMode: HologramMode, holoColor: number, holoValue: number, holoStr: string): void {
//Create hologram if not exist, set style
if (this.hologram == undefined) {
this.hologram = mar.game.make.text(0, 32, "");
this.hologram.anchor.set(0.5, 0);
this.addChild(this.hologram);
this.hologram.setStyle(config.holoStyle(holoColor));
} else {
this.hologram.setStyle(config.holoStyle(holoColor));
}
switch (holoMode) {
case HologramMode.CLEARED:
this.hologram.text = "";
break;
case HologramMode.DEC:
this.hologram.text = Number(holoValue).toString();
break;
case HologramMode.HEX:
this.hologram.text = "0x" + ("0000" + Number(holoValue).toString(16).toUpperCase()).slice(-4);
break;
case HologramMode.STRING:
this.hologram.text = holoStr.replace(/[\n|\t]/g, '');
break;
}
}
/**
* Set appropriate frame based on direction
*/
public updateDirection() {
switch (this.direction) {
case Direction.NORTH:
this.animations.frameName = "cubot/walk_n/0001";
break;
case Direction.EAST:
this.animations.frameName = "cubot/walk_e/0001";
break;
case Direction.SOUTH:
this.animations.frameName = "cubot/walk_s/0001";
break;
case Direction.WEST:
this.animations.frameName = "cubot/walk_w/0001";
break;
}
}
/**
* Initiate the walk animation. Handles multiple calls of this function even if the previous animations
* were not completed
*/
public walk() {
let self = this;
let walkAnimation = function (duration) {
//Move the Cubot to desired tile
let tween = mar.game.add.tween(self).to({isoX: Util.getIsoX(self.tileX), isoY: Util.getIsoY(self.tileY)},
duration, Phaser.Easing.Linear.None, true);
//Play appropriate animation
switch (self.direction) {
case Direction.NORTH:
self.animations.play("walk_n", 60, true);
break;
case Direction.SOUTH:
self.animations.play("walk_s", 60, true);
break;
case Direction.EAST:
self.animations.play("walk_e", 60, true);
break;
case Direction.WEST:
self.animations.play("walk_w", 60, true);
break;
}
//When moved to destination,
tween.onComplete.add(function () {
self.animations.stop();
self.updateDirection();
//Resync position
self.isoX = Util.getIsoX(self.tileX);
self.isoY = Util.getIsoY(self.tileY);
self.onTileExit();
//Execute all the queued walk animations at a faster pace
for (let i = 0; i < self.queuedAnimations.length; i++) {
self.queuedAnimations[i](config.walkDuration / 2);
self.queuedAnimations.splice(i, 1)
}
});
};
if (this.animations.currentAnim.isPlaying) {
//Queue up the animation
this.queuedAnimations.push(walkAnimation);
} else {
walkAnimation(config.walkDuration);
}
}
/**
* Create the username text that will appear on top of the Cubot. Text will have alternate
* color when current username matches. This function is also responsable for setting the
* reduced transparency of other Cubots
*/
public createUsername() {
let username = mar.game.make.text(0, -24, this.username, {
fontSize: 22,
fill: config.textFill,
stroke: config.textStroke,
strokeThickness: 2,
font: "fixedsys"
});
username.alpha = 0.85;
username.anchor.set(0.5, 0);
//Color own username
if (this.username === mar.client.username) {
username.tint = config.selfUsernameColor;
} else {
this.alpha = config.otherCubotAlpha;
}
this.addChild(username);
}
}
class HarvesterNPC extends Cubot {
constructor(json) {
super(json);
//Overwrite Cubot's animations
this.animations.add("walk_w", mar.animationFrames.harvester_walk_w);
this.animations.add("walk_s", mar.animationFrames.harvester_walk_s);
this.animations.add("walk_e", mar.animationFrames.harvester_walk_e);
this.animations.add("walk_n", mar.animationFrames.harvester_walk_n);
this.updateDirection();
this.setText("Harvester NPC");
this.text.visible = false;
}
/**
* Needs to be overridden because Cubot() calls getTint() when initialised
*/
public getTint() {
return config.cubotTint;
}
public updateDirection() {
switch (this.direction) {
case Direction.NORTH:
this.animations.frameName = "harvester/walk_n/0001";
break;
case Direction.EAST:
this.animations.frameName = "harvester/walk_e/0001";
break;
case Direction.SOUTH:
this.animations.frameName = "harvester/walk_s/0001";
break;
case Direction.WEST:
this.animations.frameName = "harvester/walk_w/0001";
break;
}
}
updateObject(json) {
if (DEBUG) {
console.log("Updating Harvester NPC object")
}
this.action = json.action;
this.direction = json.direction;
//Update Location
if (!this.isAt(json.x, json.y)) {
//Location changed
if (this.action == Action.WALKING) {
//Walking..
this.tileX = json.x;
this.tileY = json.y;
this.walk();
}
}
//Update Direction
this.updateDirection();
}
public createUsername() {
//No-op
}
}
class BiomassBlob extends GameObject {
onTileHover() {
mar.game.tweens.removeFrom(this);
mar.game.add.tween(this).to({isoZ: 45}, 200, Phaser.Easing.Quadratic.InOut, true);
this.tint = config.biomassHoverTint;
mar.game.add.tween(this.scale).to({x: 1.2, y: 1.2}, 200, Phaser.Easing.Linear.None, true);
this.text.visible = true;
}
onTileExit() {
mar.game.tweens.removeFrom(this);
mar.game.add.tween(this).to({isoZ: 15}, 400, Phaser.Easing.Bounce.Out, true);
mar.game.add.tween(this.scale).to({x: 1, y: 1}, 200, Phaser.Easing.Linear.None, true);
this.tint = config.biomassTint;
this.text.visible = false;
}
updateObject(json) {
if (DEBUG) {
console.log("Updating Biomass object")
}
}
constructor(json) {
super(Util.getIsoX(json.x), Util.getIsoY(json.y), 10, "sheet", 1);
if (DEBUG) {
console.log("Creating Biomass object")
}
this.anchor.set(0.5, 0);
this.id = json.i;
this.tileX = json.x;
this.tileY = json.y;
this.tint = config.biomassTint;
this.animations.add("idle", mar.animationFrames.biomassIdle);
this.animations.play("idle", 45, true);
this.setText("Biomass");
this.text.visible = false;
}
}
class Factory extends GameObject {
public onTileHover() {
mar.game.tweens.removeFrom(this);
mar.game.add.tween(this).to({isoZ: 25}, 200, Phaser.Easing.Quadratic.InOut, true);
mar.game.add.tween(this.scale).to({x: 1.06, y: 1.06}, 200, Phaser.Easing.Linear.None, true);
this.tint = config.cubotHoverTint;
this.text.visible = true;
}
public onTileExit() {
mar.game.tweens.removeFrom(this);
mar.game.add.tween(this).to({isoZ: 15}, 400, Phaser.Easing.Bounce.Out, true);
mar.game.add.tween(this.scale).to({x: 1, y: 1}, 200, Phaser.Easing.Linear.None, true);
this.tint = config.cubotTint;
this.text.visible = false;
}
public updateObject(json) {
//No op
}
public isAt(x: number, y: number) {
//Factory is 2x2
return (this.tileX === x || this.tileX + 1 === x) && (this.tileY + 1 === y || this.tileY === y);
};
constructor(json) {
super(Util.getIsoX(json.x), Util.getIsoY(json.y), 15, "sheet", "objects/factory");
this.anchor.set(0.5, .25);
this.setText("Factory");
this.text.visible = false;
this.id = json.i;
this.tileX = json.x;
this.tileY = json.y;
}
}
class RadioTower extends GameObject {
public onTileHover() {
mar.game.tweens.removeFrom(this);
mar.game.add.tween(this).to({isoZ: 25}, 200, Phaser.Easing.Quadratic.InOut, true);
mar.game.add.tween(this.scale).to({x: 1.06, y: 1.06}, 200, Phaser.Easing.Linear.None, true);
this.tint = config.cubotHoverTint;
this.text.visible = true;
}
public onTileExit() {
mar.game.tweens.removeFrom(this);
mar.game.add.tween(this).to({isoZ: 15}, 400, Phaser.Easing.Bounce.Out, true);
mar.game.add.tween(this.scale).to({x: 1, y: 1}, 200, Phaser.Easing.Linear.None, true);
this.tint = config.cubotTint;
this.text.visible = false;
}
public updateObject(json) {
//No op
}
constructor(json) {
super(Util.getIsoX(json.x), Util.getIsoY(json.y), 15, "sheet", "objects/RadioTower");
this.anchor.set(0.5, 0.64);
this.setText("Radio Tower");
this.text.visible = false;
this.id = json.i;
this.tileX = json.x;
this.tileY = json.y;
}
}