This commit is contained in:
Evert Prants 2022-04-16 09:50:46 +03:00
parent 51a2396d9a
commit e3186f7f41
Signed by: evert
GPG Key ID: 1688DA83D222D0B5
12 changed files with 138 additions and 23 deletions

View File

@ -12,13 +12,13 @@ import { CubeMap } from './object/resource/cubemap';
import { VideoPlayer } from './object/other/video-player'; import { VideoPlayer } from './object/other/video-player';
import { Player } from './object/player'; import { Player } from './object/player';
import { PlayerEntity } from './object/player-entity'; import { PlayerEntity } from './object/player-entity';
import { ClientWorld } from './object/world/ClientWorld';
import { ClientWorldLoader } from './object/world/ClientWorldLoader';
import { ClientWorldManifest } from './object/world/ClientWorldManifest';
import { Renderer } from './renderer'; import { Renderer } from './renderer';
import { to2D } from '../common/convert';
import { Grass } from './object/model/grass'; import { Grass } from './object/model/grass';
import { BaseTexture } from './object/resource/texture'; import { BaseTexture } from './object/resource/texture';
import { ClientWorld } from './object/world/client-world';
import { ClientWorldManifest } from './object/world/client-world-manifest';
import { ClientWorldLoader } from './object/world/client-world-loader';
import { LoadingManagerWrapper } from './object/resource/loading-manager';
export class Game { export class Game {
public players: (Player | PlayerEntity)[] = []; public players: (Player | PlayerEntity)[] = [];
@ -38,6 +38,8 @@ export class Game {
constructor(public socket: Socket) {} constructor(public socket: Socket) {}
async initialize(): Promise<void> { async initialize(): Promise<void> {
LoadingManagerWrapper.getInstance().initialize();
const worldManifest = await ClientWorldManifest.loadManifest(); const worldManifest = await ClientWorldManifest.loadManifest();
this.world = new ClientWorld(new ClientWorldLoader(), worldManifest); this.world = new ClientWorld(new ClientWorldLoader(), worldManifest);

View File

@ -14,7 +14,7 @@ import { FullStatePacket, CharacterPacket } from '../../../common/types/packet';
import { CanvasUtils } from '../canvas-utils'; import { CanvasUtils } from '../canvas-utils';
import { NameTag } from '../nametag'; import { NameTag } from '../nametag';
import { PonyModelLoader } from '../resource/pony-loader'; import { PonyModelLoader } from '../resource/pony-loader';
import { ClientWorld } from '../world/ClientWorld'; import { ClientWorld } from '../world/client-world';
import { PonyEyes } from './eyes'; import { PonyEyes } from './eyes';
const nameTagBuilder = new CanvasUtils({ const nameTagBuilder = new CanvasUtils({
@ -124,7 +124,7 @@ export class PonyEntity {
} }
public jump() { public jump() {
this.velocity.y = 16; this.velocity.y = 12;
} }
public setColor(color: number | string) { public setColor(color: number | string) {

View File

@ -1,6 +1,9 @@
import { CubeTextureLoader, CubeTexture } from 'three'; import { CubeTextureLoader, CubeTexture } from 'three';
import { LoadingManagerWrapper } from './loading-manager';
const loader = new CubeTextureLoader(); const loader = new CubeTextureLoader(
LoadingManagerWrapper.getInstance().manager,
);
export class CubeMap { export class CubeMap {
constructor(public source: string, public texture: CubeTexture) {} constructor(public source: string, public texture: CubeTexture) {}

View File

@ -0,0 +1,43 @@
import { LoadingManager } from 'three';
let instance: LoadingManagerWrapper;
export class LoadingManagerWrapper {
public manager = new LoadingManager();
public element = document.createElement('div');
private _inner = document.createElement('div');
private _status = document.createElement('span');
private _barWrapper = document.createElement('div');
private _bar = document.createElement('div');
public static getInstance(): LoadingManagerWrapper {
if (!instance) {
instance = new LoadingManagerWrapper();
}
return instance;
}
public initialize() {
this.element.classList.add('loading__wrapper');
this._inner.classList.add('loading');
this._status.classList.add('loading__status');
this._barWrapper.classList.add('loading__bar');
this._bar.classList.add('loading__bar-inner');
this._barWrapper.append(this._bar);
this._inner.append(this._status, this._barWrapper);
this.element.append(this._inner);
this._status.innerText = 'Loading (0 %)';
this.manager.onProgress = (url, loaded, total) => {
const percent = (loaded / total) * 100;
this._status.innerText = `Loading (${Math.floor(percent)} %)`;
this._bar.style.setProperty('--loading-percentage', `${percent}%`);
};
this.manager.onLoad = () => {
this.element.classList.add('loading--complete');
};
document.body.prepend(this.element);
}
}

View File

@ -1,11 +1,14 @@
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'; import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
import { LoadingManagerWrapper } from './loading-manager';
// Instantiate a loader // Instantiate a loader
const loader = new GLTFLoader(); const loader = new GLTFLoader(LoadingManagerWrapper.getInstance().manager);
// Optional: Provide a DRACOLoader instance to decode compressed mesh data // Optional: Provide a DRACOLoader instance to decode compressed mesh data
const dracoLoader = new DRACOLoader(); const dracoLoader = new DRACOLoader(
LoadingManagerWrapper.getInstance().manager,
);
dracoLoader.setDecoderPath('/examples/js/libs/draco/'); dracoLoader.setDecoderPath('/examples/js/libs/draco/');
loader.setDRACOLoader(dracoLoader); loader.setDRACOLoader(dracoLoader);

View File

@ -1,6 +1,7 @@
import { TextureLoader, Texture } from 'three'; import { TextureLoader, Texture } from 'three';
import { LoadingManagerWrapper } from './loading-manager';
const loader = new TextureLoader(); const loader = new TextureLoader(LoadingManagerWrapper.getInstance().manager);
export class BaseTexture { export class BaseTexture {
constructor(public source: string, public texture: Texture) {} constructor(public source: string, public texture: Texture) {}

View File

@ -1,13 +1,6 @@
import { import { ShaderMaterial, UniformsLib, UniformsUtils } from 'three';
Color,
MultiplyOperation,
ShaderMaterial,
UniformsLib,
UniformsUtils,
Vector3,
} from 'three';
import { WorldChunk } from '../../../common/world/WorldChunk'; import { WorldChunk } from '../../../common/world/WorldChunk';
import { ClientWorldTexture } from './ClientWorldTexture'; import { ClientWorldTexture } from './client-world-texture';
// Adapted from the Lambert Material shader // Adapted from the Lambert Material shader
// https://github.com/mrdoob/three.js/blob/44837d13a1bc0cf59824f3a6ddfab19ecd5ff435/src/renderers/shaders/ShaderLib/meshlambert.glsl.js // https://github.com/mrdoob/three.js/blob/44837d13a1bc0cf59824f3a6ddfab19ecd5ff435/src/renderers/shaders/ShaderLib/meshlambert.glsl.js

View File

@ -1,8 +1,9 @@
import { ImageLoader } from 'three'; import { ImageLoader } from 'three';
import { WorldLoader } from '../../../common/world/WorldLoader'; import { WorldLoader } from '../../../common/world/WorldLoader';
import { CanvasUtils } from '../canvas-utils'; import { CanvasUtils } from '../canvas-utils';
import { LoadingManagerWrapper } from '../resource/loading-manager';
const loader = new ImageLoader(); const loader = new ImageLoader(LoadingManagerWrapper.getInstance().manager);
const canvasUtil = new CanvasUtils(); const canvasUtil = new CanvasUtils();
const worldPath = '/assets/terrain/region'; const worldPath = '/assets/terrain/region';

View File

@ -1,6 +1,7 @@
import { RepeatWrapping, Texture, TextureLoader } from 'three'; import { RepeatWrapping, Texture, TextureLoader } from 'three';
import { LoadingManagerWrapper } from '../resource/loading-manager';
const loader = new TextureLoader(); const loader = new TextureLoader(LoadingManagerWrapper.getInstance().manager);
export class ClientWorldTexture { export class ClientWorldTexture {
constructor(public source: string, public texture: Texture) {} constructor(public source: string, public texture: Texture) {}

View File

@ -1,8 +1,8 @@
import { Object3D, Vector2, Vector3 } from 'three'; import { Object3D, Vector2, Vector3 } from 'three';
import { WorldChunk } from '../../../common/world/WorldChunk'; import { WorldChunk } from '../../../common/world/WorldChunk';
import { WorldManager } from '../../../common/world/WorldManager'; import { WorldManager } from '../../../common/world/WorldManager';
import { ClientWorldChunkShader } from './ClientWorldChunkShader'; import { ClientWorldChunkShader } from './client-world-chunk-shader';
import { ClientWorldTexture } from './ClientWorldTexture'; import { ClientWorldTexture } from './client-world-texture';
import { QuadtreeMesher } from './quadtree/quadtree-mesher'; import { QuadtreeMesher } from './quadtree/quadtree-mesher';
// TODO: distance loading // TODO: distance loading

View File

@ -177,3 +177,71 @@ body {
width: 100%; width: 100%;
} }
} }
.loading {
display: flex;
flex-direction: column;
max-width: 400px;
width: 100vw;
margin: 10% auto;
text-align: center;
font-size: 2rem;
padding: 2rem;
&__wrapper {
position: absolute;
z-index: 3000;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: #202020;
color: #fff;
transition: opacity 1s linear;
opacity: 1;
pointer-events: none;
&.loading--complete {
opacity: 0;
}
}
&__bar {
width: 100%;
height: 20px;
margin-top: 2rem;
background-color: #141414;
border-radius: 4px;
overflow: hidden;
&-inner {
width: var(--loading-percentage);
height: 20px;
background-color: #1098ab;
transition: width 50ms linear;
background-image: linear-gradient(
-45deg,
rgba(255, 255, 255, .2) 25%,
transparent 25%,
transparent 50%,
rgba(255, 255, 255, .2) 50%,
rgba(255, 255, 255, .2) 75%,
transparent 75%,
transparent
);
z-index: 1;
background-size: 50px 50px;
animation: move 2s linear infinite;
}
}
}
@keyframes move {
0% {
background-position: 0 0;
}
100% {
background-position: 50px 50px;
}
}