client/src/models/index.ts
import * as PIXI from "pixi.js";
import { Coordinates, MenuStatus, config } from "interfaces/gamemap";
import { GameModelProperty } from "interfaces/pixi";
import GameMapContainer from "./map";
import Controllers from "./controller";
export default class {
app: PIXI.Application;
renderer: PIXI.Renderer;
gamemap: GameMapContainer;
controllers: Controllers;
timestamp: number;
coord: Coordinates;
delegate: number;
offset: number;
menu: MenuStatus;
debugText: PIXI.Text | undefined;
debugValue: any;
myid: number;
constructor(options: GameModelProperty) {
this.app = options.app;
this.renderer = options.app.renderer;
this.coord = {
cx: options.cx,
cy: options.cy,
scale: options.scale,
zoom: options.zoom
};
this.timestamp = 0;
this.offset = 0;
this.delegate = this.getDelegate();
this.myid = options.myid;
this.menu = MenuStatus.IDLE;
this.gamemap = new GameMapContainer(this);
this.controllers = new Controllers(this);
}
init() {
this.gamemap.init();
this.controllers.init();
this.initDebugText();
this.app.ticker.add(() => this.tick());
}
protected tick() {
this.offset++;
if (this.offset >= config.round) {
this.offset = 0;
}
this.gamemap.tick();
this.controllers.tick();
}
protected initDebugText() {
this.debugText = new PIXI.Text("");
this.debugText.style.fontSize = 14;
this.debugText.style.fill = 0xffffff;
this.debugText.x = 50;
this.app.stage.addChild(this.debugText);
setInterval(() => this.viewDebugInfo(), 250);
}
protected viewDebugInfo() {
if (this.debugText === undefined) {
return;
}
this.debugText.text =
"FPS: " +
this.app.ticker.FPS.toFixed(2) +
", " +
this.app.stage.children.length +
" entities" +
", debug=" +
this.debugValue +
", type=" +
this.app.renderer.type +
", menu=" +
this.menu;
}
setCoord(x: number, y: number, scale: number, force: boolean = false) {
this.setCenter(x, y);
this.setScale(scale);
this.updateCoord(force);
}
protected getDelegate() {
if (this.renderer.width < 600) {
// sm
return 2;
} else if (this.renderer.width < 960) {
// md
return 3;
} else if (this.renderer.width < 1280) {
// lg
return 3;
} else {
// xl
return 4;
}
}
protected updateDelegate() {
let old = this.delegate;
this.delegate = this.getDelegate();
if (this.delegate !== old) {
this.controllers.merge("delegate", this.delegate);
}
}
protected setCenter(x: number, y: number) {
let short = Math.min(this.renderer.width, this.renderer.height);
let long = Math.max(this.renderer.width, this.renderer.height);
let shortRadius = Math.pow(
2,
this.coord.scale - 1 + Math.log2(short / long)
);
let longRadius = Math.pow(2, this.coord.scale - 1);
if (this.renderer.width < this.renderer.height) {
// 縦長
if (x - shortRadius < config.gamePos.min.x) {
x = config.gamePos.min.x + shortRadius;
}
if (x + shortRadius > config.gamePos.max.x) {
x = config.gamePos.max.x - shortRadius;
}
if (y - longRadius < config.gamePos.min.y) {
y = config.gamePos.min.y + longRadius;
}
if (y + longRadius > config.gamePos.max.y) {
y = config.gamePos.max.y - longRadius;
}
if (this.coord.scale > config.scale.max) {
y = 0;
}
} else {
// 横長
if (x - longRadius < config.gamePos.min.x) {
x = config.gamePos.min.x + longRadius;
}
if (x + longRadius > config.gamePos.max.x) {
x = config.gamePos.max.x - longRadius;
}
if (y - shortRadius < config.gamePos.min.y) {
y = config.gamePos.min.y + shortRadius;
}
if (y + shortRadius > config.gamePos.max.y) {
y = config.gamePos.max.y - shortRadius;
}
if (this.coord.scale > config.scale.max) {
x = 0;
}
}
this.coord.cx = x;
this.coord.cy = y;
}
protected setScale(v: number) {
let old = this.coord.scale;
let short = Math.min(this.renderer.width, this.renderer.height);
let long = Math.max(this.renderer.width, this.renderer.height);
let maxScale = config.scale.max + Math.log2(long / short);
if (v < config.scale.min) {
v = config.scale.min;
}
if (v > maxScale) {
v = maxScale;
}
this.coord.zoom = v < old ? 1 : v > old ? -1 : 0;
this.coord.scale = v;
}
resize(width: number, height: number) {
let oldDelegate = this.delegate;
this.renderer.resize(width, height);
this.updateDelegate();
this.merge("resize", true);
return this.delegate !== oldDelegate;
}
protected updateCoord(force: boolean) {
this.merge("coord", this.coord);
if (force) {
this.merge("forceMove", true);
}
}
merge(key: string, value: any) {
this.controllers.merge(key, value);
this.gamemap.merge(key, value);
}
setMenuState(menu: MenuStatus) {
if (this.menu !== menu) {
this.merge("menu", menu);
this.menu = menu;
}
return menu;
}
unmount() {
this.gamemap.end();
this.controllers.end();
}
isReadOnly() {
return this.myid === 0;
}
}