src/components/templates/AnimateMap/game/map/systems/AvatarTuningSystem.ts
import { Engine, NodeList, System } from "@ash.ts/ash";
import { Sprite } from "pixi.js";
import { GameConfig } from "components/templates/AnimateMap/configs/GameConfig";
import { avatarCycles, avatarFeets } from "../../constants/AssetConstants";
import EntityFactory from "../entities/EntityFactory";
import { Avatar } from "../graphics/Avatar";
import { AvatarTuningNode } from "../nodes/AvatarTuningNode";
import { PlayerMovementNode } from "../nodes/PlayerMovementNode";
import { ViewportNode } from "../nodes/ViewportNode";
export class AvatarTuningSystem extends System {
private creator: EntityFactory;
private viewport?: NodeList<ViewportNode>;
private avatars?: NodeList<AvatarTuningNode>;
private player?: NodeList<PlayerMovementNode>;
private zoomLevelCurrent = 0;
private zoomChanged = true;
constructor(creator: EntityFactory) {
super();
this.creator = creator;
}
addToEngine(engine: Engine) {
this.player = engine.getNodeList(PlayerMovementNode);
this.player.nodeAdded.add(this.handlePlayerAdded);
this.player.nodeRemoved.add(this.handlePlayerRemoved);
this.avatars = engine.getNodeList(AvatarTuningNode);
this.avatars.nodeAdded.add(this.handleAvatarAdded);
this.avatars.nodeRemoved.add(this.handleAvatarRemoved);
this.viewport = engine.getNodeList(ViewportNode);
this.viewport.nodeAdded.add(this.handleViewportAdded);
if (this.viewport.head) {
this.zoomLevelCurrent = this.viewport.head.viewport.zoomLevel;
this.zoomChanged = true;
}
}
removeFromEngine(engine: Engine) {
if (this.player) {
this.player.nodeAdded.remove(this.handlePlayerAdded);
this.player.nodeRemoved.remove(this.handlePlayerRemoved);
this.player = undefined;
}
if (this.avatars) {
this.avatars.nodeAdded.remove(this.handleAvatarAdded);
this.avatars.nodeRemoved.remove(this.handleAvatarRemoved);
this.avatars = undefined;
}
if (this.viewport) {
this.viewport.nodeAdded.remove(this.handleViewportAdded);
this.viewport = undefined;
}
}
update(time: number) {
this.updatePlayerDirections();
if (!this.zoomChanged) {
return;
}
this.zoomChanged = false;
for (let avatar = this.avatars?.head; avatar; avatar = avatar.next) {
this.handleAvatarAdded(avatar);
}
if (this.player && this.player.head) {
this.handlePlayerAdded(this.player.head);
}
}
private handlePlayerAdded = (node: PlayerMovementNode) => {
this.creator.updatePlayerTuning(node);
};
private handlePlayerRemoved = (node: PlayerMovementNode) => {
this.creator.removePlayerTuning(node);
};
private updatePlayerDirections = () => {
if (
this.zoomLevelCurrent !== GameConfig.ZOOM_LEVEL_FLYING &&
this.player &&
this.player.head &&
this.player.head.movement.velocityX !== 0
) {
const sprite = (this.player.head.sprite.view as Avatar).cycle;
if (sprite) {
const scaleY = Math.abs(sprite.scale.y);
const scaleX =
scaleY * (this.player.head.movement.velocityX > 0 ? 1 : -1);
// console.log(sprite.scale.x, sprite.scale.y, scaleX, this.player.head.movement.velocityX)
sprite.scale.set(scaleX, scaleY);
}
}
};
private handleAvatarAdded = (node: AvatarTuningNode) => {
const view: Avatar = node.sprite.view as Avatar;
if (!view.avatar) {
return;
}
if (
this.player &&
this.player.head &&
this.player.head.player.data.data.id === node.tuning.user.data.id
) {
if (view.cycle && view.cycle.parent) {
view.cycle.parent.removeChild(view.cycle);
}
if (this.zoomLevelCurrent === GameConfig.ZOOM_LEVEL_WALKING) {
view.cycle = Sprite.from(avatarFeets[0]);
view.cycle.y = view.avatar.height * 0.55;
view.cycle.anchor.set(0.5);
// TODO HARDCODE
view.cycle.scale.set(1);
view.addChildAt(view.cycle, view.getChildIndex(view.avatar));
} else if (this.zoomLevelCurrent === GameConfig.ZOOM_LEVEL_CYCLING) {
view.cycle = Sprite.from(avatarCycles[0]);
view.cycle.y = view.avatar.height * 0.46;
view.cycle.anchor.set(0.5);
// TODO HARDCODE
view.cycle.scale.set(1.1);
view.addChildAt(view.cycle, view.getChildIndex(view.avatar));
}
}
// HAT
if (
node.tuning.user.data.hat &&
this.zoomLevelCurrent !== GameConfig.ZOOM_LEVEL_FLYING &&
!view.hat
) {
view.hat = Sprite.from(node.tuning.user.data.hat);
view.hat.y = -view.avatar.height / 2;
view.hat.anchor.set(0.5);
view.addChild(view.hat);
} else if (
(!node.tuning.user.data.cycle ||
this.zoomLevelCurrent === GameConfig.ZOOM_LEVEL_FLYING) &&
view.hat
) {
view.removeChild(view.hat);
view.hat = undefined;
}
// ACCESSORIES
if (
node.tuning.user.data.accessories &&
this.zoomLevelCurrent !== GameConfig.ZOOM_LEVEL_FLYING &&
!view.accessories
) {
view.accessories = Sprite.from(node.tuning.user.data.accessories);
view.accessories.anchor.set(0.5);
view.addChild(view.accessories);
} else if (
(!node.tuning.user.data.accessories ||
this.zoomLevelCurrent === GameConfig.ZOOM_LEVEL_FLYING) &&
view.accessories
) {
view.removeChild(view.accessories);
view.accessories = undefined;
}
};
private handleAvatarRemoved = (node: AvatarTuningNode) => {
const avatar: Avatar = node.sprite.view as Avatar;
if (!avatar) {
return;
}
if (avatar.cycle) {
avatar.removeChild(avatar.cycle);
avatar.cycle = undefined;
}
if (avatar.hat) {
avatar.removeChild(avatar.hat);
avatar.hat = undefined;
}
if (avatar.accessories) {
avatar.removeChild(avatar.accessories);
avatar.accessories = undefined;
}
};
private handleViewportAdded = (node: ViewportNode) => {
if (this.zoomLevelCurrent !== node.viewport.zoomLevel) {
this.zoomChanged = true;
this.zoomLevelCurrent = node.viewport.zoomLevel;
}
};
}