the-world-engine
Version:
three.js based, unity like game engine for browser
257 lines (244 loc) • 8.99 kB
JavaScript
import { CoroutineProcessor } from "./coroutine/CoroutineProcessor";
import { EngineGlobalObject } from "./EngineGlobalObject";
import { GameState, GameStateKind } from "./GameState";
import { Scene } from "./hierarchy_object/Scene";
import { Physics2DProcessor } from "./physics/2d/Physics2DProcessor";
import { CameraContainer } from "./render/CameraContainer";
import { Color } from "./render/Color";
import { GameScreen } from "./render/GameScreen";
import { OptimizedCSS3DRenderer } from "./render/OptimizedCSS3DRenderer";
import { TransformMatrixProcessor } from "./render/TransformMatrixProcessor";
import { WebGLGlobalObject } from "./render/WebGLGlobalObject";
import { SceneProcessor } from "./SceneProcessor";
import { Time } from "./time/Time";
export class Game {
S;
C;
R;
K;
D;
O;
i;
_;
p;
v;
P;
G;
g;
L;
l;
j;
T=null;
F;
A;
M;
B;
W;
constructor(e, t = true) {
const i = document.createElement("div");
i.style.width = "100%";
i.style.height = "100%";
i.style.position = "relative";
e.appendChild(i);
e = i;
this.S = new Scene;
this.C = new GameScreen(e.clientWidth, e.clientHeight);
this.j = e;
{
this.i = new CameraContainer((e => {
if (this.D) {
const t = this.S.unsafeGetThreeScene();
if (e instanceof Color) {
const i = this.K;
i.r = e.r;
i.g = e.g;
i.b = e.b;
t.background = i;
} else {
t.background = e;
}
} else if (this.R) {
const t = this.R.domElement;
if (e === null) {
t.style.backgroundColor = "rgba(0, 0, 0, 0)";
} else if (e.isTexture) {
console.warn("THREE.Texture background is not supported in CSS3DRenderer");
t.style.backgroundColor = "rgba(0, 0, 0, 0)";
} else {
t.style.backgroundColor = "rgba(" + e.r * 255 + "," + e.g * 255 + "," + e.b * 255 + "," + e.a + ")";
}
}
}));
}
this._ = new Time;
this.p = new GameState(GameStateKind.WaitingForStart);
this.v = new SceneProcessor;
this.P = new CoroutineProcessor(this._);
this.G = new TransformMatrixProcessor;
this.g = new Physics2DProcessor;
this.L = new EngineGlobalObject(this.S, this.i, this._, this.p, this.C, this.v, this.P, this.G, this.g, e);
this.F = null;
this.A = false;
this.M = t;
this.B = this.resizeFramebuffer.bind(this);
if (t) window.addEventListener("resize", this.B);
this.W = this.q.bind(this);
}
resizeFramebuffer() {
const e = this.j.clientWidth;
const t = this.j.clientHeight;
if (e === this.C.width && t === this.C.height) return;
this.C.resize(e, t);
if (this.R) {
this.R.setSize(e, t);
this.R.domElement.style.width = "100%";
this.R.domElement.style.height = "100%";
}
if (this.D) {
this.D.setSize(e, t);
this.O.style.width = "100%";
this.O.style.height = "100%";
}
}
run(e, t) {
if (this.A) throw new Error("Game is disposed.");
if (this.p.kind !== GameStateKind.WaitingForStart) throw new Error("Game is already running.");
this.p.kind = GameStateKind.Initializing;
this._.start();
const i = new e(this.L, t);
const s = i.run();
this.T = i.getGameSettingObject();
this.L.applyGameSetting(this.T);
if (this.T.render.webGLRendererLoader) {
if (this.T.render.webGLRendererInitilizer === undefined) {
console.warn("webGLRendererLoader is specified, but webGLRenderer is not specified. so engine will not render as webgl.");
} else {
this.K = new this.T.render.webGLRendererLoader.Color;
const e = this.T.render.webGLRendererInitilizer();
let t;
let i;
let s;
if (e instanceof Array) {
t = e[0];
i = e[1];
s = false;
} else {
t = e;
i = e.domElement;
s = true;
}
const r = this.j;
this.O = i;
this.D = t;
this.D.setSize(r.clientWidth, r.clientHeight);
this.O.style.position = "absolute";
r.appendChild(this.O);
this.l = new WebGLGlobalObject(t, s ? t : null);
this.L.setWebGLGlobalObject(this.l);
}
} else {
if (this.T.render.webGLRendererInitilizer) {
console.warn("webGLRenderer is specified, but webGLRendererLoader is not specified. so engine will not render as webgl.");
}
}
if (this.T.render.useCss3DRenderer) {
const e = this.j;
this.R = new OptimizedCSS3DRenderer;
this.R.setSize(e.clientWidth, e.clientHeight);
const t = this.R.domElement;
t.style.width = "100%";
t.style.height = "100%";
t.style.position = "absolute";
t.style.pointerEvents = "none";
t.onscroll = e => {
const t = e.target;
t.scrollTop = 0;
t.scrollLeft = 0;
};
e.appendChild(t);
}
s.build();
if (!this.i.camera) throw new Error("Camera is not exist or not active in the scene.");
this.p.kind = GameStateKind.Running;
this.v.startProcessNonSyncedEvent();
this.g.update(this._.deltaTime);
this.P.updateAfterProcess();
if (!this.i.camera) throw new Error("Camera is not exist or not active in the scene.");
this.v.processRemoveObject();
const r = this.G.update();
if (this.R) {
this.R.render(r, this.S.unsafeGetThreeScene(), this.i.camera.threeCamera);
}
const o = this.l?.effectComposer;
if (o) {
o.render(this._.deltaTime);
} else if (this.D) {
this.D.render(this.S.unsafeGetThreeScene(), this.i.camera.threeCamera);
}
this.G.flush();
this.P.endFrameAfterProcess();
this.F = requestAnimationFrame(this.W);
}
q() {
this._.update();
this.v.startProcessNonSyncedEvent();
this.g.update(this._.deltaTime);
this.P.tryCompact();
this.P.updateAfterProcess();
if (!this.i.camera) throw new Error("Camera is not exist or not active in the scene.");
this.v.processRemoveObject();
const e = this.G.update();
if (this.R) {
this.R.render(e, this.S.unsafeGetThreeScene(), this.i.camera.threeCamera);
}
const t = this.l?.effectComposer;
if (t) {
t.render(this._.deltaTime);
} else if (this.D) {
this.D.render(this.S.unsafeGetThreeScene(), this.i.camera.threeCamera);
}
this.G.flush();
this.P.endFrameAfterProcess();
this.F = requestAnimationFrame(this.W);
}
stop() {
if (this.A) throw new Error("Game is disposed.");
if (this.p.kind !== GameStateKind.Running) throw new Error("Game is not running.");
this.p.kind = GameStateKind.Stopped;
if (this.F) cancelAnimationFrame(this.F);
this.F = null;
}
resume() {
if (this.A) throw new Error("Game is disposed.");
if (this.p.kind !== GameStateKind.Stopped) throw new Error("Game is not stopped.");
this.p.kind = GameStateKind.Running;
this.q();
}
dispose() {
if (this.A) return;
if (this.p.kind === GameStateKind.Running) {
this.p.kind = GameStateKind.Finalizing;
if (this.F) cancelAnimationFrame(this.F);
this.L.dispose();
const e = this.S.children;
for (let t = 0; t < e.length; ++t) {
e[t].gameObject.destroy();
}
if (this.R) this.j.removeChild(this.R.domElement);
if (this.O) this.j.removeChild(this.O);
if (this.l) this.l.dispose();
} else {
this.L.dispose();
}
if (this.M) window.removeEventListener("resize", this.B);
this.j.remove();
this.A = true;
this.p.kind = GameStateKind.Finalized;
}
get inputHandler() {
return this.L.input;
}
get currentGameState() {
return this.p.kind;
}
}