diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..f59dd0e
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,11 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 2
+indent_style = space
+insert_final_newline = true
+max_line_length = 160
+tab_width = 2
+trim_trailing_whitespace = true
diff --git a/index.html b/index.html
index 0765a27..5746392 100644
--- a/index.html
+++ b/index.html
@@ -1,134 +1,143 @@
-
-
-
- The Legend of SimonDev
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+ The Legend of SimonDev
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/attacker-controller.js b/src/attacker-controller.js
index 9e220ef..591dd85 100644
--- a/src/attacker-controller.js
+++ b/src/attacker-controller.js
@@ -1,4 +1,4 @@
-import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.118/build/three.module.js';
+import * as THREE from 'three';
import {entity} from './entity.js';
@@ -46,7 +46,7 @@ export const attack_controller = (() => {
if (c.entity == this._parent) {
return false;
}
-
+
const h = c.entity.GetComponent('HealthComponent');
if (!h) {
return false;
@@ -65,7 +65,7 @@ export const attack_controller = (() => {
const forward = new THREE.Vector3(0, 0, 1);
forward.applyQuaternion(this._parent._rotation);
forward.normalize();
-
+
let damage = this.GetComponent('HealthComponent')._params.strength;
if (item) {
damage *= item.Params.damage;
@@ -88,4 +88,4 @@ export const attack_controller = (() => {
return {
AttackController: AttackController,
};
-})();
\ No newline at end of file
+})();
diff --git a/src/entity.js b/src/entity.js
index cb983db..73d773f 100644
--- a/src/entity.js
+++ b/src/entity.js
@@ -1,4 +1,4 @@
-import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.118/build/three.module.js';
+import * as THREE from 'three';
export const entity = (() => {
@@ -120,4 +120,4 @@ export const entity = (() => {
Component: Component,
};
-})();
\ No newline at end of file
+})();
diff --git a/src/equip-weapon-component.js b/src/equip-weapon-component.js
index 2e53400..c5fc49d 100644
--- a/src/equip-weapon-component.js
+++ b/src/equip-weapon-component.js
@@ -1,6 +1,6 @@
import {entity} from './entity.js';
-import {FBXLoader} from 'https://cdn.jsdelivr.net/npm/three@0.118.1/examples/jsm/loaders/FBXLoader.js';
+import {FBXLoader} from 'three/FBXLoader';
export const equip_weapon_component = (() => {
@@ -87,4 +87,4 @@ export const equip_weapon_component = (() => {
return {
EquipWeapon: EquipWeapon,
};
-})();
\ No newline at end of file
+})();
diff --git a/src/gltf-component.js b/src/gltf-component.js
index dff5bac..b8449ca 100644
--- a/src/gltf-component.js
+++ b/src/gltf-component.js
@@ -1,236 +1,236 @@
-import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.118/build/three.module.js';
-
-import {GLTFLoader} from 'https://cdn.jsdelivr.net/npm/three@0.118.1/examples/jsm/loaders/GLTFLoader.js';
-import {FBXLoader} from 'https://cdn.jsdelivr.net/npm/three@0.118.1/examples/jsm/loaders/FBXLoader.js';
-
-import {entity} from './entity.js';
-
-
-export const gltf_component = (() => {
-
- class StaticModelComponent extends entity.Component {
- constructor(params) {
- super();
- this._Init(params);
- }
-
- _Init(params) {
- this._params = params;
-
- this._LoadModels();
- }
-
- InitComponent() {
- this._RegisterHandler('update.position', (m) => { this._OnPosition(m); });
- }
-
- _OnPosition(m) {
- if (this._target) {
- this._target.position.copy(m.value);
- }
- }
-
- _LoadModels() {
- if (this._params.resourceName.endsWith('glb') || this._params.resourceName.endsWith('gltf')) {
- this._LoadGLB();
- } else if (this._params.resourceName.endsWith('fbx')) {
- this._LoadFBX();
- }
- }
-
- _OnLoaded(obj) {
- this._target = obj;
- this._params.scene.add(this._target);
-
- this._target.scale.setScalar(this._params.scale);
- this._target.position.copy(this._parent._position);
-
- let texture = null;
- if (this._params.resourceTexture) {
- const texLoader = new THREE.TextureLoader();
- texture = texLoader.load(this._params.resourceTexture);
- texture.encoding = THREE.sRGBEncoding;
- }
-
- this._target.traverse(c => {
- let materials = c.material;
- if (!(c.material instanceof Array)) {
- materials = [c.material];
- }
-
- for (let m of materials) {
- if (m) {
- if (texture) {
- m.map = texture;
- }
- if (this._params.specular) {
- m.specular = this._params.specular;
- }
- if (this._params.emissive) {
- m.emissive = this._params.emissive;
- }
- }
- }
- if (this._params.receiveShadow != undefined) {
- c.receiveShadow = this._params.receiveShadow;
- }
- if (this._params.castShadow != undefined) {
- c.castShadow = this._params.castShadow;
- }
- if (this._params.visible != undefined) {
- c.visible = this._params.visible;
- }
- });
- }
-
- _LoadGLB() {
- const loader = new GLTFLoader();
- loader.setPath(this._params.resourcePath);
- loader.load(this._params.resourceName, (glb) => {
- this._OnLoaded(glb.scene);
- });
- }
-
- _LoadFBX() {
- const loader = new FBXLoader();
- loader.setPath(this._params.resourcePath);
- loader.load(this._params.resourceName, (fbx) => {
- this._OnLoaded(fbx);
- });
- }
-
- Update(timeInSeconds) {
- }
- };
-
-
- class AnimatedModelComponent extends entity.Component {
- constructor(params) {
- super();
- this._Init(params);
- }
-
- InitComponent() {
- this._RegisterHandler('update.position', (m) => { this._OnPosition(m); });
- }
-
- _OnPosition(m) {
- if (this._target) {
- this._target.position.copy(m.value);
- this._target.position.y = 0.35;
- }
- }
-
- _Init(params) {
- this._params = params;
-
- this._LoadModels();
- }
-
- _LoadModels() {
- if (this._params.resourceName.endsWith('glb') || this._params.resourceName.endsWith('gltf')) {
- this._LoadGLB();
- } else if (this._params.resourceName.endsWith('fbx')) {
- this._LoadFBX();
- }
- }
-
- _OnLoaded(obj, animations) {
- this._target = obj;
- this._params.scene.add(this._target);
-
- this._target.scale.setScalar(this._params.scale);
- this._target.position.copy(this._parent._position);
-
- this.Broadcast({
- topic: 'update.position',
- value: this._parent._position,
- });
-
- let texture = null;
- if (this._params.resourceTexture) {
- const texLoader = new THREE.TextureLoader();
- texture = texLoader.load(this._params.resourceTexture);
- texture.encoding = THREE.sRGBEncoding;
- }
-
- this._target.traverse(c => {
- let materials = c.material;
- if (!(c.material instanceof Array)) {
- materials = [c.material];
- }
-
- for (let m of materials) {
- if (m) {
- if (texture) {
- m.map = texture;
- }
- if (this._params.specular) {
- m.specular = this._params.specular;
- }
- if (this._params.emissive) {
- m.emissive = this._params.emissive;
- }
- }
- }
- if (this._params.receiveShadow != undefined) {
- c.receiveShadow = this._params.receiveShadow;
- }
- if (this._params.castShadow != undefined) {
- c.castShadow = this._params.castShadow;
- }
- if (this._params.visible != undefined) {
- c.visible = this._params.visible;
- }
- });
-
- const _OnLoad = (anim) => {
- const clip = anim.animations[0];
- const action = this._mixer.clipAction(clip);
-
- action.play();
- };
-
- const loader = new FBXLoader();
- loader.setPath(this._params.resourcePath);
- loader.load(this._params.resourceAnimation, (a) => { _OnLoad(a); });
-
- this._mixer = new THREE.AnimationMixer(this._target);
-
- this._parent._mesh = this._target;
- this.Broadcast({
- topic: 'load.character',
- model: this._target,
- });
- }
-
- _LoadGLB() {
- const loader = new GLTFLoader();
- loader.setPath(this._params.resourcePath);
- loader.load(this._params.resourceName, (glb) => {
- this._OnLoaded(glb.scene, glb.animations);
- });
- }
-
- _LoadFBX() {
- const loader = new FBXLoader();
- loader.setPath(this._params.resourcePath);
- loader.load(this._params.resourceName, (fbx) => {
- this._OnLoaded(fbx);
- });
- }
-
- Update(timeInSeconds) {
- if (this._mixer) {
- this._mixer.update(timeInSeconds);
- }
- }
- };
-
-
- return {
- StaticModelComponent: StaticModelComponent,
- AnimatedModelComponent: AnimatedModelComponent,
- };
-
-})();
\ No newline at end of file
+import * as THREE from 'three';
+
+import { GLTFLoader } from 'three/GLTFLoader';
+import { FBXLoader } from 'three/FBXLoader';
+
+import { entity } from './entity.js';
+
+export const gltf_component = (() => {
+
+ class StaticModelComponent extends entity.Component {
+ constructor(params) {
+ super();
+ this._Init(params);
+ }
+
+ _Init(params) {
+ this._params = params;
+
+ this._LoadModels();
+ }
+
+ InitComponent() {
+ this._RegisterHandler('update.position', (m) => {
+ this._OnPosition(m);
+ });
+ }
+
+ _OnPosition(m) {
+ if (this._target) {
+ this._target.position.copy(m.value);
+ }
+ }
+
+ _LoadModels() {
+ if (this._params.resourceName.endsWith('glb') || this._params.resourceName.endsWith('gltf')) {
+ this._LoadGLB();
+ } else if (this._params.resourceName.endsWith('fbx')) {
+ this._LoadFBX();
+ }
+ }
+
+ _OnLoaded(obj) {
+ this._target = obj;
+ this._params.scene.add(this._target);
+
+ this._target.scale.setScalar(this._params.scale);
+ this._target.position.copy(this._parent._position);
+
+ let texture = null;
+ if (this._params.resourceTexture) {
+ const texLoader = new THREE.TextureLoader();
+ texture = texLoader.load(this._params.resourceTexture);
+ texture.encoding = THREE.sRGBEncoding;
+ }
+
+ this._target.traverse(c => {
+ let materials = c.material;
+ if (!(c.material instanceof Array)) {
+ materials = [c.material];
+ }
+
+ for (let m of materials) {
+ if (m) {
+ if (texture) {
+ m.map = texture;
+ }
+ if (this._params.specular) {
+ m.specular = this._params.specular;
+ }
+ if (this._params.emissive) {
+ m.emissive = this._params.emissive;
+ }
+ }
+ }
+ if (this._params.receiveShadow != undefined) {
+ c.receiveShadow = this._params.receiveShadow;
+ }
+ if (this._params.castShadow != undefined) {
+ c.castShadow = this._params.castShadow;
+ }
+ if (this._params.visible != undefined) {
+ c.visible = this._params.visible;
+ }
+ });
+ }
+
+ _LoadGLB() {
+ const loader = new GLTFLoader();
+ loader.setPath(this._params.resourcePath);
+ loader.load(this._params.resourceName, (glb) => {
+ this._OnLoaded(glb.scene);
+ });
+ }
+
+ _LoadFBX() {
+ const loader = new FBXLoader();
+ loader.setPath(this._params.resourcePath);
+ loader.load(this._params.resourceName, (fbx) => {
+ this._OnLoaded(fbx);
+ });
+ }
+
+ Update(timeInSeconds) {
+ }
+ }
+
+ class AnimatedModelComponent extends entity.Component {
+ constructor(params) {
+ super();
+ this._Init(params);
+ }
+
+ InitComponent() {
+ this._RegisterHandler('update.position', (m) => {
+ this._OnPosition(m);
+ });
+ }
+
+ _OnPosition(m) {
+ if (this._target) {
+ this._target.position.copy(m.value);
+ this._target.position.y = 0.35;
+ }
+ }
+
+ _Init(params) {
+ this._params = params;
+
+ this._LoadModels();
+ }
+
+ _LoadModels() {
+ if (this._params.resourceName.endsWith('glb') || this._params.resourceName.endsWith('gltf')) {
+ this._LoadGLB();
+ } else if (this._params.resourceName.endsWith('fbx')) {
+ this._LoadFBX();
+ }
+ }
+
+ _OnLoaded(obj, animations) {
+ this._target = obj;
+ this._params.scene.add(this._target);
+
+ this._target.scale.setScalar(this._params.scale);
+ this._target.position.copy(this._parent._position);
+
+ this.Broadcast({
+ topic: 'update.position',
+ value: this._parent._position,
+ });
+
+ let texture = null;
+ if (this._params.resourceTexture) {
+ const texLoader = new THREE.TextureLoader();
+ texture = texLoader.load(this._params.resourceTexture);
+ texture.encoding = THREE.sRGBEncoding;
+ }
+
+ this._target.traverse(c => {
+ let materials = c.material;
+ if (!(c.material instanceof Array)) {
+ materials = [c.material];
+ }
+
+ for (let m of materials) {
+ if (m) {
+ if (texture) {
+ m.map = texture;
+ }
+ if (this._params.specular) {
+ m.specular = this._params.specular;
+ }
+ if (this._params.emissive) {
+ m.emissive = this._params.emissive;
+ }
+ }
+ }
+ if (this._params.receiveShadow != undefined) {
+ c.receiveShadow = this._params.receiveShadow;
+ }
+ if (this._params.castShadow != undefined) {
+ c.castShadow = this._params.castShadow;
+ }
+ if (this._params.visible != undefined) {
+ c.visible = this._params.visible;
+ }
+ });
+
+ if (Array.isArray(animations) && animations.length > 0) {
+ setTimeout(() => {
+ this._mixer = new THREE.AnimationMixer(this._target);
+ const clip = animations[0];
+ const action = this._mixer.clipAction(clip);
+
+ action.play();
+ });
+ }
+
+ this._parent._mesh = this._target;
+ this.Broadcast({
+ topic: 'load.character',
+ model: this._target,
+ });
+ }
+
+ _LoadGLB() {
+ const loader = new GLTFLoader();
+ loader.setPath(this._params.resourcePath);
+ loader.load(this._params.resourceName, (glb) => {
+ this._OnLoaded(glb.scene, glb.animations);
+ });
+ }
+
+ _LoadFBX() {
+ const loader = new FBXLoader();
+ loader.setPath(this._params.resourcePath);
+ loader.load(this._params.resourceName, (fbx) => {
+ loader.load(this._params.resourceAnimation, (a) => {
+ this._OnLoaded(fbx, a.animations);
+ });
+ });
+ }
+
+ Update(timeInSeconds) {
+ if (this._mixer) {
+ this._mixer.update(timeInSeconds);
+ }
+ }
+ }
+
+ return {
+ StaticModelComponent: StaticModelComponent,
+ AnimatedModelComponent: AnimatedModelComponent,
+ };
+
+})();
diff --git a/src/health-bar.js b/src/health-bar.js
index 62ca31d..e665005 100644
--- a/src/health-bar.js
+++ b/src/health-bar.js
@@ -1,4 +1,4 @@
-import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.118.1/build/three.module.js';
+import * as THREE from 'three';
import {entity} from './entity.js';
import {math} from './math.js';
@@ -6,7 +6,7 @@ import {math} from './math.js';
export const health_bar = (() => {
- const _VS = `#version 300 es
+ const _VS = `
varying vec2 vUV;
void main() {
@@ -16,7 +16,7 @@ void main() {
}
`;
- const _PS = `#version 300 es
+ const _PS = `
uniform vec3 colour;
uniform float health;
@@ -54,6 +54,7 @@ class HealthBar extends entity.Component {
depthTest: false,
depthWrite: false,
side: THREE.DoubleSide,
+ glslVersion: THREE.GLSL3,
});
this._geometry = new THREE.BufferGeometry();
@@ -75,7 +76,7 @@ class HealthBar extends entity.Component {
_OnHealth(msg) {
const healthPercent = (msg.health / msg.maxHealth);
-
+
this._realHealth = healthPercent;
}
@@ -134,4 +135,4 @@ class HealthBar extends entity.Component {
return {
HealthBar: HealthBar,
};
-})();
\ No newline at end of file
+})();
diff --git a/src/level-up-component.js b/src/level-up-component.js
index c3f8b4e..1bd4d0f 100644
--- a/src/level-up-component.js
+++ b/src/level-up-component.js
@@ -1,4 +1,4 @@
-import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.118.1/build/three.module.js';
+import * as THREE from 'three';
import {particle_system} from "./particle-system.js";
import {entity} from "./entity.js";
@@ -35,11 +35,11 @@ export const level_up_component = (() => {
this._particles._alphaSpline.AddPoint(0.1, 1.0);
this._particles._alphaSpline.AddPoint(0.7, 1.0);
this._particles._alphaSpline.AddPoint(1.0, 0.0);
-
+
this._particles._colourSpline.AddPoint(0.0, new THREE.Color(0x00FF00));
this._particles._colourSpline.AddPoint(0.5, new THREE.Color(0x40C040));
this._particles._colourSpline.AddPoint(1.0, new THREE.Color(0xFF4040));
-
+
this._particles._sizeSpline.AddPoint(0.0, 0.05);
this._particles._sizeSpline.AddPoint(0.5, 0.25);
this._particles._sizeSpline.AddPoint(1.0, 0.0);
@@ -48,7 +48,7 @@ export const level_up_component = (() => {
InitComponent() {
this._particles.AddParticles(this._parent._position, 300);
}
-
+
Update(timeElapsed) {
this._particles.Step(timeElapsed);
if (this._particles._particles.length == 0) {
@@ -56,9 +56,9 @@ export const level_up_component = (() => {
}
}
}
-
+
return {
LevelUpComponent: LevelUpComponent,
LevelUpComponentSpawner: LevelUpComponentSpawner,
};
-})();
\ No newline at end of file
+})();
diff --git a/src/main.js b/src/main.js
index a129afb..c3f730c 100644
--- a/src/main.js
+++ b/src/main.js
@@ -1,427 +1,426 @@
-import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.118.1/build/three.module.js';
-
-import {third_person_camera} from './third-person-camera.js';
-import {entity_manager} from './entity-manager.js';
-import {player_entity} from './player-entity.js'
-import {entity} from './entity.js';
-import {gltf_component} from './gltf-component.js';
-import {health_component} from './health-component.js';
-import {player_input} from './player-input.js';
-import {npc_entity} from './npc-entity.js';
-import {math} from './math.js';
-import {spatial_hash_grid} from './spatial-hash-grid.js';
-import {ui_controller} from './ui-controller.js';
-import {health_bar} from './health-bar.js';
-import {level_up_component} from './level-up-component.js';
-import {quest_component} from './quest-component.js';
-import {spatial_grid_controller} from './spatial-grid-controller.js';
-import {inventory_controller} from './inventory-controller.js';
-import {equip_weapon_component} from './equip-weapon-component.js';
-import {attack_controller} from './attacker-controller.js';
-
-
-const _VS = `
-varying vec3 vWorldPosition;
-
-void main() {
- vec4 worldPosition = modelMatrix * vec4( position, 1.0 );
- vWorldPosition = worldPosition.xyz;
-
- gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
-}`;
-
-
-const _FS = `
-uniform vec3 topColor;
-uniform vec3 bottomColor;
-uniform float offset;
-uniform float exponent;
-
-varying vec3 vWorldPosition;
-
-void main() {
- float h = normalize( vWorldPosition + offset ).y;
- gl_FragColor = vec4( mix( bottomColor, topColor, max( pow( max( h , 0.0), exponent ), 0.0 ) ), 1.0 );
-}`;
-
-
-
-class HackNSlashDemo {
- constructor() {
- this._Initialize();
- }
-
- _Initialize() {
- this._threejs = new THREE.WebGLRenderer({
- antialias: true,
- });
- this._threejs.outputEncoding = THREE.sRGBEncoding;
- this._threejs.gammaFactor = 2.2;
- this._threejs.shadowMap.enabled = true;
- this._threejs.shadowMap.type = THREE.PCFSoftShadowMap;
- this._threejs.setPixelRatio(window.devicePixelRatio);
- this._threejs.setSize(window.innerWidth, window.innerHeight);
- this._threejs.domElement.id = 'threejs';
-
- document.getElementById('container').appendChild(this._threejs.domElement);
-
- window.addEventListener('resize', () => {
- this._OnWindowResize();
- }, false);
-
- const fov = 60;
- const aspect = 1920 / 1080;
- const near = 1.0;
- const far = 10000.0;
- this._camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
- this._camera.position.set(25, 10, 25);
-
- this._scene = new THREE.Scene();
- this._scene.background = new THREE.Color(0xFFFFFF);
- this._scene.fog = new THREE.FogExp2(0x89b2eb, 0.002);
-
- let light = new THREE.DirectionalLight(0xFFFFFF, 1.0);
- light.position.set(-10, 500, 10);
- light.target.position.set(0, 0, 0);
- light.castShadow = true;
- light.shadow.bias = -0.001;
- light.shadow.mapSize.width = 4096;
- light.shadow.mapSize.height = 4096;
- light.shadow.camera.near = 0.1;
- light.shadow.camera.far = 1000.0;
- light.shadow.camera.left = 100;
- light.shadow.camera.right = -100;
- light.shadow.camera.top = 100;
- light.shadow.camera.bottom = -100;
- this._scene.add(light);
-
- this._sun = light;
-
- const plane = new THREE.Mesh(
- new THREE.PlaneGeometry(5000, 5000, 10, 10),
- new THREE.MeshStandardMaterial({
- color: 0x1e601c,
- }));
- plane.castShadow = false;
- plane.receiveShadow = true;
- plane.rotation.x = -Math.PI / 2;
- this._scene.add(plane);
-
- this._entityManager = new entity_manager.EntityManager();
- this._grid = new spatial_hash_grid.SpatialHashGrid(
- [[-1000, -1000], [1000, 1000]], [100, 100]);
-
- this._LoadControllers();
- this._LoadPlayer();
- this._LoadFoliage();
- this._LoadClouds();
- this._LoadSky();
-
- this._previousRAF = null;
- this._RAF();
- }
-
- _LoadControllers() {
- const ui = new entity.Entity();
- ui.AddComponent(new ui_controller.UIController());
- this._entityManager.Add(ui, 'ui');
- }
-
- _LoadSky() {
- const hemiLight = new THREE.HemisphereLight(0xFFFFFF, 0xFFFFFFF, 0.6);
- hemiLight.color.setHSL(0.6, 1, 0.6);
- hemiLight.groundColor.setHSL(0.095, 1, 0.75);
- this._scene.add(hemiLight);
-
- const uniforms = {
- "topColor": { value: new THREE.Color(0x0077ff) },
- "bottomColor": { value: new THREE.Color(0xffffff) },
- "offset": { value: 33 },
- "exponent": { value: 0.6 }
- };
- uniforms["topColor"].value.copy(hemiLight.color);
-
- this._scene.fog.color.copy(uniforms["bottomColor"].value);
-
- const skyGeo = new THREE.SphereBufferGeometry(1000, 32, 15);
- const skyMat = new THREE.ShaderMaterial({
- uniforms: uniforms,
- vertexShader: _VS,
- fragmentShader: _FS,
- side: THREE.BackSide
- });
-
- const sky = new THREE.Mesh(skyGeo, skyMat);
- this._scene.add(sky);
- }
-
- _LoadClouds() {
- for (let i = 0; i < 20; ++i) {
- const index = math.rand_int(1, 3);
- const pos = new THREE.Vector3(
- (Math.random() * 2.0 - 1.0) * 500,
- 100,
- (Math.random() * 2.0 - 1.0) * 500);
-
- const e = new entity.Entity();
- e.AddComponent(new gltf_component.StaticModelComponent({
- scene: this._scene,
- resourcePath: './resources/nature2/GLTF/',
- resourceName: 'Cloud' + index + '.glb',
- position: pos,
- scale: Math.random() * 5 + 10,
- emissive: new THREE.Color(0x808080),
- }));
- e.SetPosition(pos);
- this._entityManager.Add(e);
- e.SetActive(false);
- }
- }
-
- _LoadFoliage() {
- for (let i = 0; i < 100; ++i) {
- const names = [
- 'CommonTree_Dead', 'CommonTree',
- 'BirchTree', 'BirchTree_Dead',
- 'Willow', 'Willow_Dead',
- 'PineTree',
- ];
- const name = names[math.rand_int(0, names.length - 1)];
- const index = math.rand_int(1, 5);
-
- const pos = new THREE.Vector3(
- (Math.random() * 2.0 - 1.0) * 500,
- 0,
- (Math.random() * 2.0 - 1.0) * 500);
-
- const e = new entity.Entity();
- e.AddComponent(new gltf_component.StaticModelComponent({
- scene: this._scene,
- resourcePath: './resources/nature/FBX/',
- resourceName: name + '_' + index + '.fbx',
- scale: 0.25,
- emissive: new THREE.Color(0x000000),
- specular: new THREE.Color(0x000000),
- receiveShadow: true,
- castShadow: true,
- }));
- e.AddComponent(
- new spatial_grid_controller.SpatialGridController({grid: this._grid}));
- e.SetPosition(pos);
- this._entityManager.Add(e);
- e.SetActive(false);
- }
- }
-
- _LoadPlayer() {
- const params = {
- camera: this._camera,
- scene: this._scene,
- };
-
- const levelUpSpawner = new entity.Entity();
- levelUpSpawner.AddComponent(new level_up_component.LevelUpComponentSpawner({
- camera: this._camera,
- scene: this._scene,
- }));
- this._entityManager.Add(levelUpSpawner, 'level-up-spawner');
-
- const axe = new entity.Entity();
- axe.AddComponent(new inventory_controller.InventoryItem({
- type: 'weapon',
- damage: 3,
- renderParams: {
- name: 'Axe',
- scale: 0.25,
- icon: 'war-axe-64.png',
- },
- }));
- this._entityManager.Add(axe);
-
- const sword = new entity.Entity();
- sword.AddComponent(new inventory_controller.InventoryItem({
- type: 'weapon',
- damage: 3,
- renderParams: {
- name: 'Sword',
- scale: 0.25,
- icon: 'pointy-sword-64.png',
- },
- }));
- this._entityManager.Add(sword);
-
- const girl = new entity.Entity();
- girl.AddComponent(new gltf_component.AnimatedModelComponent({
- scene: this._scene,
- resourcePath: './resources/girl/',
- resourceName: 'peasant_girl.fbx',
- resourceAnimation: 'Standing Idle.fbx',
- scale: 0.035,
- receiveShadow: true,
- castShadow: true,
- }));
- girl.AddComponent(new spatial_grid_controller.SpatialGridController({
- grid: this._grid,
- }));
- girl.AddComponent(new player_input.PickableComponent());
- girl.AddComponent(new quest_component.QuestComponent());
- girl.SetPosition(new THREE.Vector3(30, 0, 0));
- this._entityManager.Add(girl);
-
- const player = new entity.Entity();
- player.AddComponent(new player_input.BasicCharacterControllerInput(params));
- player.AddComponent(new player_entity.BasicCharacterController(params));
- player.AddComponent(
- new equip_weapon_component.EquipWeapon({anchor: 'RightHandIndex1'}));
- player.AddComponent(new inventory_controller.InventoryController(params));
- player.AddComponent(new health_component.HealthComponent({
- updateUI: true,
- health: 100,
- maxHealth: 100,
- strength: 50,
- wisdomness: 5,
- benchpress: 20,
- curl: 100,
- experience: 0,
- level: 1,
- }));
- player.AddComponent(
- new spatial_grid_controller.SpatialGridController({grid: this._grid}));
- player.AddComponent(new attack_controller.AttackController({timing: 0.7}));
- this._entityManager.Add(player, 'player');
-
- player.Broadcast({
- topic: 'inventory.add',
- value: axe.Name,
- added: false,
- });
-
- player.Broadcast({
- topic: 'inventory.add',
- value: sword.Name,
- added: false,
- });
-
- player.Broadcast({
- topic: 'inventory.equip',
- value: sword.Name,
- added: false,
- });
-
- const camera = new entity.Entity();
- camera.AddComponent(
- new third_person_camera.ThirdPersonCamera({
- camera: this._camera,
- target: this._entityManager.Get('player')}));
- this._entityManager.Add(camera, 'player-camera');
-
- for (let i = 0; i < 50; ++i) {
- const monsters = [
- {
- resourceName: 'Ghost.fbx',
- resourceTexture: 'Ghost_Texture.png',
- },
- {
- resourceName: 'Alien.fbx',
- resourceTexture: 'Alien_Texture.png',
- },
- {
- resourceName: 'Skull.fbx',
- resourceTexture: 'Skull_Texture.png',
- },
- {
- resourceName: 'GreenDemon.fbx',
- resourceTexture: 'GreenDemon_Texture.png',
- },
- {
- resourceName: 'Cyclops.fbx',
- resourceTexture: 'Cyclops_Texture.png',
- },
- {
- resourceName: 'Cactus.fbx',
- resourceTexture: 'Cactus_Texture.png',
- },
- ];
- const m = monsters[math.rand_int(0, monsters.length - 1)];
-
- const npc = new entity.Entity();
- npc.AddComponent(new npc_entity.NPCController({
- camera: this._camera,
- scene: this._scene,
- resourceName: m.resourceName,
- resourceTexture: m.resourceTexture,
- }));
- npc.AddComponent(
- new health_component.HealthComponent({
- health: 50,
- maxHealth: 50,
- strength: 2,
- wisdomness: 2,
- benchpress: 3,
- curl: 1,
- experience: 0,
- level: 1,
- camera: this._camera,
- scene: this._scene,
- }));
- npc.AddComponent(
- new spatial_grid_controller.SpatialGridController({grid: this._grid}));
- npc.AddComponent(new health_bar.HealthBar({
- parent: this._scene,
- camera: this._camera,
- }));
- npc.AddComponent(new attack_controller.AttackController({timing: 0.35}));
- npc.SetPosition(new THREE.Vector3(
- (Math.random() * 2 - 1) * 500,
- 0,
- (Math.random() * 2 - 1) * 500));
- this._entityManager.Add(npc);
- }
- }
-
- _OnWindowResize() {
- this._camera.aspect = window.innerWidth / window.innerHeight;
- this._camera.updateProjectionMatrix();
- this._threejs.setSize(window.innerWidth, window.innerHeight);
- }
-
- _UpdateSun() {
- const player = this._entityManager.Get('player');
- const pos = player._position;
-
- this._sun.position.copy(pos);
- this._sun.position.add(new THREE.Vector3(-10, 500, -10));
- this._sun.target.position.copy(pos);
- this._sun.updateMatrixWorld();
- this._sun.target.updateMatrixWorld();
- }
-
- _RAF() {
- requestAnimationFrame((t) => {
- if (this._previousRAF === null) {
- this._previousRAF = t;
- }
-
- this._RAF();
-
- this._threejs.render(this._scene, this._camera);
- this._Step(t - this._previousRAF);
- this._previousRAF = t;
- });
- }
-
- _Step(timeElapsed) {
- const timeElapsedS = Math.min(1.0 / 30.0, timeElapsed * 0.001);
-
- this._UpdateSun();
-
- this._entityManager.Update(timeElapsedS);
- }
-}
-
-
-let _APP = null;
-
-window.addEventListener('DOMContentLoaded', () => {
- _APP = new HackNSlashDemo();
-});
+import * as THREE from 'three';
+//import * as THREE from 'https://cdn.jsdelivr.net/npm/three @0.118.1/build/three.module.js';
+
+import { third_person_camera } from './third-person-camera.js';
+import { entity_manager } from './entity-manager.js';
+import { player_entity } from './player-entity.js';
+import { entity } from './entity.js';
+import { gltf_component } from './gltf-component.js';
+import { health_component } from './health-component.js';
+import { player_input } from './player-input.js';
+import { npc_entity } from './npc-entity.js';
+import { math } from './math.js';
+import { spatial_hash_grid } from './spatial-hash-grid.js';
+import { ui_controller } from './ui-controller.js';
+import { health_bar } from './health-bar.js';
+import { level_up_component } from './level-up-component.js';
+import { quest_component } from './quest-component.js';
+import { spatial_grid_controller } from './spatial-grid-controller.js';
+import { inventory_controller } from './inventory-controller.js';
+import { equip_weapon_component } from './equip-weapon-component.js';
+import { attack_controller } from './attacker-controller.js';
+
+const _VS = `
+varying vec3 vWorldPosition;
+
+void main() {
+ vec4 worldPosition = modelMatrix * vec4( position, 1.0 );
+ vWorldPosition = worldPosition.xyz;
+
+ gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
+}`;
+
+const _FS = `
+uniform vec3 topColor;
+uniform vec3 bottomColor;
+uniform float offset;
+uniform float exponent;
+
+varying vec3 vWorldPosition;
+
+void main() {
+ float h = normalize( vWorldPosition + offset ).y;
+ gl_FragColor = vec4( mix( bottomColor, topColor, max( pow( max( h , 0.0), exponent ), 0.0 ) ), 1.0 );
+}`;
+
+class HackNSlashDemo {
+ constructor() {
+ this._Initialize();
+ }
+
+ _Initialize() {
+ this._threejs = new THREE.WebGLRenderer({
+ antialias: true,
+ });
+ this._threejs.outputEncoding = THREE.sRGBEncoding;
+ // THREE.WebGLRenderer: .gammaFactor has been removed
+ // this._threejs.gammaFactor = 2.2;
+ this._threejs.colorSpace = THREE.sRGBColorSpace;
+ this._threejs.shadowMap.enabled = true;
+ this._threejs.shadowMap.type = THREE.PCFSoftShadowMap;
+ this._threejs.setPixelRatio(window.devicePixelRatio);
+ this._threejs.setSize(window.innerWidth, window.innerHeight);
+ this._threejs.domElement.id = 'threejs';
+
+ document.getElementById('container').appendChild(this._threejs.domElement);
+
+ window.addEventListener('resize', () => {
+ this._OnWindowResize();
+ }, false);
+
+ const fov = 60;
+ const aspect = 1920 / 1080;
+ const near = 1.0;
+ const far = 10000.0;
+ this._camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
+ this._camera.position.set(25, 10, 25);
+
+ this._scene = new THREE.Scene();
+ this._scene.background = new THREE.Color(0xFFFFFF);
+ this._scene.fog = new THREE.FogExp2(0x89b2eb, 0.002);
+
+ let light = new THREE.DirectionalLight(0xFFFFFF, 1.0);
+ light.position.set(-10, 500, 10);
+ light.target.position.set(0, 0, 0);
+ light.castShadow = true;
+ light.shadow.bias = -0.001;
+ light.shadow.mapSize.width = 4096;
+ light.shadow.mapSize.height = 4096;
+ light.shadow.camera.near = 0.1;
+ light.shadow.camera.far = 1000.0;
+ light.shadow.camera.left = 100;
+ light.shadow.camera.right = -100;
+ light.shadow.camera.top = 100;
+ light.shadow.camera.bottom = -100;
+ this._scene.add(light);
+
+ this._sun = light;
+
+ const plane = new THREE.Mesh(
+ new THREE.PlaneGeometry(5000, 5000, 10, 10),
+ new THREE.MeshStandardMaterial({
+ color: 0x1e601c,
+ }));
+ plane.castShadow = false;
+ plane.receiveShadow = true;
+ plane.rotation.x = -Math.PI / 2;
+ this._scene.add(plane);
+
+ this._entityManager = new entity_manager.EntityManager();
+ this._grid = new spatial_hash_grid.SpatialHashGrid(
+ [[-1000, -1000], [1000, 1000]], [100, 100]);
+
+ this._LoadControllers();
+ this._LoadPlayer();
+ this._LoadFoliage();
+ this._LoadClouds();
+ this._LoadSky();
+
+ this._previousRAF = null;
+ this._RAF();
+ }
+
+ _LoadControllers() {
+ const ui = new entity.Entity();
+ ui.AddComponent(new ui_controller.UIController());
+ this._entityManager.Add(ui, 'ui');
+ }
+
+ _LoadSky() {
+ const hemiLight = new THREE.HemisphereLight(0xFFFFFF, 0xFFFFFFF, 0.6);
+ hemiLight.color.setHSL(0.6, 1, 0.6);
+ hemiLight.groundColor.setHSL(0.095, 1, 0.75);
+ this._scene.add(hemiLight);
+
+ const uniforms = {
+ 'topColor': {value: new THREE.Color(0x0077ff)},
+ 'bottomColor': {value: new THREE.Color(0xffffff)},
+ 'offset': {value: 33},
+ 'exponent': {value: 0.6},
+ };
+ uniforms['topColor'].value.copy(hemiLight.color);
+
+ this._scene.fog.color.copy(uniforms['bottomColor'].value);
+
+ const skyGeo = new THREE.SphereGeometry(1000, 32, 15);
+ const skyMat = new THREE.ShaderMaterial({
+ uniforms: uniforms,
+ vertexShader: _VS,
+ fragmentShader: _FS,
+ side: THREE.BackSide,
+ });
+
+ const sky = new THREE.Mesh(skyGeo, skyMat);
+ this._scene.add(sky);
+ }
+
+ _LoadClouds() {
+ for (let i = 0; i < 20; ++i) {
+ const index = math.rand_int(1, 3);
+ const pos = new THREE.Vector3(
+ (Math.random() * 2.0 - 1.0) * 500,
+ 100,
+ (Math.random() * 2.0 - 1.0) * 500);
+
+ const e = new entity.Entity();
+ e.AddComponent(new gltf_component.StaticModelComponent({
+ scene: this._scene,
+ resourcePath: './resources/nature2/GLTF/',
+ resourceName: 'Cloud' + index + '.glb',
+ position: pos,
+ scale: Math.random() * 5 + 10,
+ emissive: new THREE.Color(0x808080),
+ }));
+ e.SetPosition(pos);
+ this._entityManager.Add(e);
+ e.SetActive(false);
+ }
+ }
+
+ _LoadFoliage() {
+ for (let i = 0; i < 100; ++i) {
+ const names = [
+ 'CommonTree_Dead', 'CommonTree',
+ 'BirchTree', 'BirchTree_Dead',
+ 'Willow', 'Willow_Dead',
+ 'PineTree',
+ ];
+ const name = names[math.rand_int(0, names.length - 1)];
+ const index = math.rand_int(1, 5);
+
+ const pos = new THREE.Vector3(
+ (Math.random() * 2.0 - 1.0) * 500,
+ 0,
+ (Math.random() * 2.0 - 1.0) * 500);
+
+ const e = new entity.Entity();
+ e.AddComponent(new gltf_component.StaticModelComponent({
+ scene: this._scene,
+ resourcePath: './resources/nature/FBX/',
+ resourceName: name + '_' + index + '.fbx',
+ scale: 0.25,
+ emissive: new THREE.Color(0x000000),
+ specular: new THREE.Color(0x000000),
+ receiveShadow: true,
+ castShadow: true,
+ }));
+ e.AddComponent(
+ new spatial_grid_controller.SpatialGridController({grid: this._grid}));
+ e.SetPosition(pos);
+ this._entityManager.Add(e);
+ e.SetActive(false);
+ }
+ }
+
+ _LoadPlayer() {
+ const params = {
+ camera: this._camera,
+ scene: this._scene,
+ };
+
+ const levelUpSpawner = new entity.Entity();
+ levelUpSpawner.AddComponent(new level_up_component.LevelUpComponentSpawner({
+ camera: this._camera,
+ scene: this._scene,
+ }));
+ this._entityManager.Add(levelUpSpawner, 'level-up-spawner');
+
+ const axe = new entity.Entity();
+ axe.AddComponent(new inventory_controller.InventoryItem({
+ type: 'weapon',
+ damage: 3,
+ renderParams: {
+ name: 'Axe',
+ scale: 0.25,
+ icon: 'war-axe-64.png',
+ },
+ }));
+ this._entityManager.Add(axe);
+
+ const sword = new entity.Entity();
+ sword.AddComponent(new inventory_controller.InventoryItem({
+ type: 'weapon',
+ damage: 3,
+ renderParams: {
+ name: 'Sword',
+ scale: 0.25,
+ icon: 'pointy-sword-64.png',
+ },
+ }));
+ this._entityManager.Add(sword);
+
+ const girl = new entity.Entity();
+ girl.AddComponent(new gltf_component.AnimatedModelComponent({
+ scene: this._scene,
+ resourcePath: './resources/girl/',
+ resourceName: 'peasant_girl.fbx',
+ resourceAnimation: 'Standing Idle.fbx',
+ scale: 0.035,
+ receiveShadow: true,
+ castShadow: true,
+ }));
+ girl.AddComponent(new spatial_grid_controller.SpatialGridController({
+ grid: this._grid,
+ }));
+ girl.AddComponent(new player_input.PickableComponent());
+ girl.AddComponent(new quest_component.QuestComponent());
+ girl.SetPosition(new THREE.Vector3(30, 0, 0));
+ this._entityManager.Add(girl);
+
+ const player = new entity.Entity();
+ player.AddComponent(new player_input.BasicCharacterControllerInput(params));
+ player.AddComponent(new player_entity.BasicCharacterController(params));
+ player.AddComponent(
+ new equip_weapon_component.EquipWeapon({anchor: 'RightHandIndex1'}));
+ player.AddComponent(new inventory_controller.InventoryController(params));
+ player.AddComponent(new health_component.HealthComponent({
+ updateUI: true,
+ health: 100,
+ maxHealth: 100,
+ strength: 50,
+ wisdomness: 5,
+ benchpress: 20,
+ curl: 100,
+ experience: 0,
+ level: 1,
+ }));
+ player.AddComponent(
+ new spatial_grid_controller.SpatialGridController({grid: this._grid}));
+ player.AddComponent(new attack_controller.AttackController({timing: 0.7}));
+ this._entityManager.Add(player, 'player');
+
+ player.Broadcast({
+ topic: 'inventory.add',
+ value: axe.Name,
+ added: false,
+ });
+
+ player.Broadcast({
+ topic: 'inventory.add',
+ value: sword.Name,
+ added: false,
+ });
+
+ player.Broadcast({
+ topic: 'inventory.equip',
+ value: sword.Name,
+ added: false,
+ });
+
+ const camera = new entity.Entity();
+ camera.AddComponent(
+ new third_person_camera.ThirdPersonCamera({
+ camera: this._camera,
+ target: this._entityManager.Get('player'),
+ }));
+ this._entityManager.Add(camera, 'player-camera');
+
+ for (let i = 0; i < 50; ++i) {
+ const monsters = [
+ {
+ resourceName: 'Ghost.fbx',
+ resourceTexture: 'Ghost_Texture.png',
+ },
+ {
+ resourceName: 'Alien.fbx',
+ resourceTexture: 'Alien_Texture.png',
+ },
+ {
+ resourceName: 'Skull.fbx',
+ resourceTexture: 'Skull_Texture.png',
+ },
+ {
+ resourceName: 'GreenDemon.fbx',
+ resourceTexture: 'GreenDemon_Texture.png',
+ },
+ {
+ resourceName: 'Cyclops.fbx',
+ resourceTexture: 'Cyclops_Texture.png',
+ },
+ {
+ resourceName: 'Cactus.fbx',
+ resourceTexture: 'Cactus_Texture.png',
+ },
+ ];
+ const m = monsters[math.rand_int(0, monsters.length - 1)];
+
+ const npc = new entity.Entity();
+ npc.AddComponent(new npc_entity.NPCController({
+ camera: this._camera,
+ scene: this._scene,
+ resourceName: m.resourceName,
+ resourceTexture: m.resourceTexture,
+ }));
+ npc.AddComponent(
+ new health_component.HealthComponent({
+ health: 50,
+ maxHealth: 50,
+ strength: 2,
+ wisdomness: 2,
+ benchpress: 3,
+ curl: 1,
+ experience: 0,
+ level: 1,
+ camera: this._camera,
+ scene: this._scene,
+ }));
+ npc.AddComponent(
+ new spatial_grid_controller.SpatialGridController({grid: this._grid}));
+ npc.AddComponent(new health_bar.HealthBar({
+ parent: this._scene,
+ camera: this._camera,
+ }));
+ npc.AddComponent(new attack_controller.AttackController({timing: 0.35}));
+ npc.SetPosition(new THREE.Vector3(
+ (Math.random() * 2 - 1) * 500,
+ 0,
+ (Math.random() * 2 - 1) * 500));
+ this._entityManager.Add(npc);
+ }
+ }
+
+ _OnWindowResize() {
+ this._camera.aspect = window.innerWidth / window.innerHeight;
+ this._camera.updateProjectionMatrix();
+ this._threejs.setSize(window.innerWidth, window.innerHeight);
+ }
+
+ _UpdateSun() {
+ const player = this._entityManager.Get('player');
+ const pos = player._position;
+
+ this._sun.position.copy(pos);
+ this._sun.position.add(new THREE.Vector3(-10, 500, -10));
+ this._sun.target.position.copy(pos);
+ this._sun.updateMatrixWorld();
+ this._sun.target.updateMatrixWorld();
+ }
+
+ _RAF() {
+ requestAnimationFrame((t) => {
+ if (this._previousRAF === null) {
+ this._previousRAF = t;
+ }
+
+ this._RAF();
+
+ this._threejs.render(this._scene, this._camera);
+ this._Step(t - this._previousRAF);
+ this._previousRAF = t;
+ });
+ }
+
+ _Step(timeElapsed) {
+ const timeElapsedS = Math.min(1.0 / 30.0, timeElapsed * 0.001);
+
+ this._UpdateSun();
+
+ this._entityManager.Update(timeElapsedS);
+ }
+}
+
+let _APP = null;
+
+window.addEventListener('DOMContentLoaded', () => {
+ _APP = new HackNSlashDemo();
+});
diff --git a/src/npc-entity.js b/src/npc-entity.js
index cdc25c1..c70a4d8 100644
--- a/src/npc-entity.js
+++ b/src/npc-entity.js
@@ -1,6 +1,6 @@
-import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.118/build/three.module.js';
+import * as THREE from 'three';
-import {FBXLoader} from 'https://cdn.jsdelivr.net/npm/three@0.118.1/examples/jsm/loaders/FBXLoader.js';
+import {FBXLoader} from 'three/FBXLoader';
import {finite_state_machine} from './finite-state-machine.js';
import {entity} from './entity.js';
@@ -9,10 +9,10 @@ import {player_state} from './player-state.js';
export const npc_entity = (() => {
-
+
class AIInput {
constructor() {
- this._Init();
+ this._Init();
}
_Init() {
@@ -224,14 +224,14 @@ export const npc_entity = (() => {
frameDecceleration.multiplyScalar(timeInSeconds);
frameDecceleration.z = Math.sign(frameDecceleration.z) * Math.min(
Math.abs(frameDecceleration.z), Math.abs(velocity.z));
-
+
velocity.add(frameDecceleration);
const controlObject = this._target;
const _Q = new THREE.Quaternion();
const _A = new THREE.Vector3();
const _R = controlObject.quaternion.clone();
-
+
this._input._keys.forward = false;
const acc = this._acceleration;
@@ -248,23 +248,23 @@ export const npc_entity = (() => {
dirToPlayer,
new THREE.Vector3(0, 1, 0));
_R.setFromRotationMatrix(m);
-
+
controlObject.quaternion.copy(_R);
-
+
const oldPosition = new THREE.Vector3();
oldPosition.copy(controlObject.position);
-
+
const forward = new THREE.Vector3(0, 0, 1);
forward.applyQuaternion(controlObject.quaternion);
forward.normalize();
-
+
const sideways = new THREE.Vector3(1, 0, 0);
sideways.applyQuaternion(controlObject.quaternion);
sideways.normalize();
-
+
sideways.multiplyScalar(velocity.x * timeInSeconds);
forward.multiplyScalar(velocity.z * timeInSeconds);
-
+
const pos = controlObject.position.clone();
pos.add(forward);
pos.add(sideways);
@@ -278,7 +278,7 @@ export const npc_entity = (() => {
controlObject.position.copy(pos);
this._position.copy(pos);
-
+
this._parent.SetPosition(this._position);
this._parent.SetQuaternion(this._target.quaternion);
}
@@ -303,7 +303,7 @@ export const npc_entity = (() => {
time: this._stateMachine._currentState._action.time,
});
}
-
+
if (this._mixer) {
this._mixer.update(timeInSeconds);
}
@@ -314,4 +314,4 @@ export const npc_entity = (() => {
NPCController: NPCController,
};
-})();
\ No newline at end of file
+})();
diff --git a/src/particle-system.js b/src/particle-system.js
index c91ea69..ee6833b 100644
--- a/src/particle-system.js
+++ b/src/particle-system.js
@@ -1,4 +1,4 @@
-import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.118.1/build/three.module.js';
+import * as THREE from 'three';
export const particle_system = (() => {
@@ -21,7 +21,7 @@ export const particle_system = (() => {
vAngle = vec2(cos(angle), sin(angle));
vColour = colour;
}`;
-
+
const _FS = `
uniform sampler2D diffuseTexture;
@@ -33,42 +33,42 @@ export const particle_system = (() => {
vec2 coords = (gl_PointCoord - 0.5) * mat2(vAngle.x, vAngle.y, -vAngle.y, vAngle.x) + 0.5;
gl_FragColor = texture2D(diffuseTexture, coords) * vColour;
}`;
-
-
+
+
class LinearSpline {
constructor(lerp) {
this._points = [];
this._lerp = lerp;
}
-
+
AddPoint(t, d) {
this._points.push([t, d]);
}
-
+
Get(t) {
let p1 = 0;
-
+
for (let i = 0; i < this._points.length; i++) {
if (this._points[i][0] >= t) {
break;
}
p1 = i;
}
-
+
const p2 = Math.min(this._points.length - 1, p1 + 1);
-
+
if (p1 == p2) {
return this._points[p1][1];
}
-
+
return this._lerp(
(t - this._points[p1][0]) / (
this._points[p2][0] - this._points[p1][0]),
this._points[p1][1], this._points[p2][1]);
}
}
-
-
+
+
class ParticleSystem {
constructor(params) {
const uniforms = {
@@ -79,7 +79,7 @@ export const particle_system = (() => {
value: window.innerHeight / (2.0 * Math.tan(0.5 * 60.0 * Math.PI / 180.0))
}
};
-
+
this._material = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: _VS,
@@ -90,36 +90,36 @@ export const particle_system = (() => {
transparent: true,
vertexColors: true
});
-
+
this._camera = params.camera;
this._particles = [];
-
+
this._geometry = new THREE.BufferGeometry();
this._geometry.setAttribute('position', new THREE.Float32BufferAttribute([], 3));
this._geometry.setAttribute('size', new THREE.Float32BufferAttribute([], 1));
this._geometry.setAttribute('colour', new THREE.Float32BufferAttribute([], 4));
this._geometry.setAttribute('angle', new THREE.Float32BufferAttribute([], 1));
-
+
this._points = new THREE.Points(this._geometry, this._material);
-
+
params.parent.add(this._points);
-
+
this._alphaSpline = new LinearSpline((t, a, b) => {
return a + t * (b - a);
});
-
+
this._colourSpline = new LinearSpline((t, a, b) => {
const c = a.clone();
return c.lerp(b, t);
});
-
+
this._sizeSpline = new LinearSpline((t, a, b) => {
return a + t * (b - a);
});
-
+
this._UpdateGeometry();
}
-
+
AddParticles(origin, n) {
for (let i = 0; i < n; i++) {
const life = (Math.random() * 0.75 + 0.25) * 3.0;
@@ -141,20 +141,20 @@ export const particle_system = (() => {
});
}
}
-
+
_UpdateGeometry() {
const positions = [];
const sizes = [];
const colours = [];
const angles = [];
-
+
for (let p of this._particles) {
positions.push(p.position.x, p.position.y, p.position.z);
colours.push(p.colour.r, p.colour.g, p.colour.b, p.alpha);
sizes.push(p.currentSize);
angles.push(p.rotation);
}
-
+
this._geometry.setAttribute(
'position', new THREE.Float32BufferAttribute(positions, 3));
this._geometry.setAttribute(
@@ -163,32 +163,32 @@ export const particle_system = (() => {
'colour', new THREE.Float32BufferAttribute(colours, 4));
this._geometry.setAttribute(
'angle', new THREE.Float32BufferAttribute(angles, 1));
-
+
this._geometry.attributes.position.needsUpdate = true;
this._geometry.attributes.size.needsUpdate = true;
this._geometry.attributes.colour.needsUpdate = true;
this._geometry.attributes.angle.needsUpdate = true;
}
-
+
_UpdateParticles(timeElapsed) {
for (let p of this._particles) {
p.life -= timeElapsed;
}
-
+
this._particles = this._particles.filter(p => {
return p.life > 0.0;
});
-
+
for (let p of this._particles) {
const t = 1.0 - p.life / p.maxLife;
-
+
p.rotation += timeElapsed * 0.5;
p.alpha = this._alphaSpline.Get(t);
p.currentSize = p.size * this._sizeSpline.Get(t);
p.colour.copy(this._colourSpline.Get(t));
-
+
p.position.add(p.velocity.clone().multiplyScalar(timeElapsed));
-
+
const drag = p.velocity.clone();
drag.multiplyScalar(timeElapsed * 2.0);
drag.x = Math.sign(p.velocity.x) * Math.min(Math.abs(drag.x), Math.abs(p.velocity.x));
@@ -196,23 +196,23 @@ export const particle_system = (() => {
drag.z = Math.sign(p.velocity.z) * Math.min(Math.abs(drag.z), Math.abs(p.velocity.z));
p.velocity.sub(drag);
}
-
+
this._particles.sort((a, b) => {
const d1 = this._camera.position.distanceTo(a.position);
const d2 = this._camera.position.distanceTo(b.position);
-
+
if (d1 > d2) {
return -1;
}
-
+
if (d1 < d2) {
return 1;
}
-
+
return 0;
});
}
-
+
Step(timeElapsed) {
this._UpdateParticles(timeElapsed);
this._UpdateGeometry();
@@ -222,4 +222,4 @@ export const particle_system = (() => {
return {
ParticleSystem: ParticleSystem,
};
-})();
\ No newline at end of file
+})();
diff --git a/src/player-entity.js b/src/player-entity.js
index bb69c52..b017174 100644
--- a/src/player-entity.js
+++ b/src/player-entity.js
@@ -1,6 +1,6 @@
-import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.118.1/build/three.module.js';
+import * as THREE from 'three';
-import {FBXLoader} from 'https://cdn.jsdelivr.net/npm/three@0.118.1/examples/jsm/loaders/FBXLoader.js';
+import {FBXLoader} from 'three/FBXLoader';
import {entity} from './entity.js';
import {finite_state_machine} from './finite-state-machine.js';
@@ -15,7 +15,7 @@ export const player_entity = (() => {
this._proxy = proxy;
this._Init();
}
-
+
_Init() {
this._AddState('idle', player_state.IdleState);
this._AddState('walk', player_state.WalkState);
@@ -24,12 +24,12 @@ export const player_entity = (() => {
this._AddState('death', player_state.DeathState);
}
};
-
+
class BasicCharacterControllerProxy {
constructor(animations) {
this._animations = animations;
}
-
+
get animations() {
return this._animations;
}
@@ -48,11 +48,11 @@ export const player_entity = (() => {
this._acceleration = new THREE.Vector3(1, 0.125, 50.0);
this._velocity = new THREE.Vector3(0, 0, 0);
this._position = new THREE.Vector3();
-
+
this._animations = {};
this._stateMachine = new CharacterFSM(
new BasicCharacterControllerProxy(this._animations));
-
+
this._LoadModels();
}
@@ -71,7 +71,7 @@ export const player_entity = (() => {
this._target = fbx;
this._target.scale.setScalar(0.035);
this._params.scene.add(this._target);
-
+
this._bones = {};
for (let b of this._target.children[1].skeleton.bones) {
@@ -97,7 +97,7 @@ export const player_entity = (() => {
const _OnLoad = (animName, anim) => {
const clip = anim.animations[0];
const action = this._mixer.clipAction(clip);
-
+
this._animations[animName] = {
clip: clip,
action: action,
@@ -108,7 +108,7 @@ export const player_entity = (() => {
this._manager.onLoad = () => {
this._stateMachine.SetState('idle');
};
-
+
const loader = new FBXLoader(this._manager);
loader.setPath('./resources/guard/');
loader.load('Sword And Shield Idle.fbx', (a) => { _OnLoad('idle', a); });
@@ -171,7 +171,7 @@ export const player_entity = (() => {
currentState.Name != 'idle') {
return;
}
-
+
const velocity = this._velocity;
const frameDecceleration = new THREE.Vector3(
velocity.x * this._decceleration.x,
@@ -181,19 +181,19 @@ export const player_entity = (() => {
frameDecceleration.multiplyScalar(timeInSeconds);
frameDecceleration.z = Math.sign(frameDecceleration.z) * Math.min(
Math.abs(frameDecceleration.z), Math.abs(velocity.z));
-
+
velocity.add(frameDecceleration);
-
+
const controlObject = this._target;
const _Q = new THREE.Quaternion();
const _A = new THREE.Vector3();
const _R = controlObject.quaternion.clone();
-
+
const acc = this._acceleration.clone();
if (input._keys.shift) {
acc.multiplyScalar(2.0);
}
-
+
if (input._keys.forward) {
velocity.z += acc.z * timeInSeconds;
}
@@ -210,23 +210,23 @@ export const player_entity = (() => {
_Q.setFromAxisAngle(_A, 4.0 * -Math.PI * timeInSeconds * this._acceleration.y);
_R.multiply(_Q);
}
-
+
controlObject.quaternion.copy(_R);
-
+
const oldPosition = new THREE.Vector3();
oldPosition.copy(controlObject.position);
-
+
const forward = new THREE.Vector3(0, 0, 1);
forward.applyQuaternion(controlObject.quaternion);
forward.normalize();
-
+
const sideways = new THREE.Vector3(1, 0, 0);
sideways.applyQuaternion(controlObject.quaternion);
sideways.normalize();
-
+
sideways.multiplyScalar(velocity.x * timeInSeconds);
forward.multiplyScalar(velocity.z * timeInSeconds);
-
+
const pos = controlObject.position.clone();
pos.add(forward);
pos.add(sideways);
@@ -238,15 +238,15 @@ export const player_entity = (() => {
controlObject.position.copy(pos);
this._position.copy(pos);
-
+
this._parent.SetPosition(this._position);
this._parent.SetQuaternion(this._target.quaternion);
}
};
-
+
return {
BasicCharacterControllerProxy: BasicCharacterControllerProxy,
BasicCharacterController: BasicCharacterController,
};
-})();
\ No newline at end of file
+})();
diff --git a/src/player-input.js b/src/player-input.js
index bd53b83..3b62759 100644
--- a/src/player-input.js
+++ b/src/player-input.js
@@ -1,4 +1,4 @@
-import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.118/build/three.module.js';
+import * as THREE from 'three';
import {entity} from "./entity.js";
@@ -20,7 +20,7 @@ export const player_input = (() => {
this._params = params;
this._Init();
}
-
+
_Init() {
this._keys = {
forward: false,
@@ -35,7 +35,7 @@ export const player_input = (() => {
document.addEventListener('keyup', (e) => this._onKeyUp(e), false);
document.addEventListener('mouseup', (e) => this._onMouseUp(e), false);
}
-
+
_onMouseUp(event) {
const rect = document.getElementById('threejs').getBoundingClientRect();
const pos = {
@@ -96,7 +96,7 @@ export const player_input = (() => {
break;
}
}
-
+
_onKeyUp(event) {
switch(event.keyCode) {
case 87: // w
@@ -126,4 +126,4 @@ export const player_input = (() => {
PickableComponent: PickableComponent,
};
-})();
\ No newline at end of file
+})();
diff --git a/src/player-state.js b/src/player-state.js
index 9b3cbac..6a7abc7 100644
--- a/src/player-state.js
+++ b/src/player-state.js
@@ -1,4 +1,4 @@
-import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.118/build/three.module.js';
+import * as THREE from 'three';
export const player_state = (() => {
@@ -7,7 +7,7 @@ export const player_state = (() => {
constructor(parent) {
this._parent = parent;
}
-
+
Enter() {}
Exit() {}
Update() {}
@@ -16,21 +16,21 @@ export const player_state = (() => {
class DeathState extends State {
constructor(parent) {
super(parent);
-
+
this._action = null;
}
-
+
get Name() {
return 'death';
}
-
+
Enter(prevState) {
this._action = this._parent._proxy._animations['death'].action;
-
+
if (prevState) {
const prevAction = this._parent._proxy._animations[prevState.Name].action;
-
- this._action.reset();
+
+ this._action.reset();
this._action.setLoop(THREE.LoopOnce, 1);
this._action.clampWhenFinished = true;
this._action.crossFadeFrom(prevAction, 0.2, true);
@@ -39,38 +39,38 @@ export const player_state = (() => {
this._action.play();
}
}
-
+
Exit() {
}
-
+
Update(_) {
}
};
-
+
class AttackState extends State {
constructor(parent) {
super(parent);
-
+
this._action = null;
-
+
this._FinishedCallback = () => {
this._Finished();
}
}
-
+
get Name() {
return 'attack';
}
-
+
Enter(prevState) {
this._action = this._parent._proxy._animations['attack'].action;
const mixer = this._action.getMixer();
mixer.addEventListener('finished', this._FinishedCallback);
-
+
if (prevState) {
const prevAction = this._parent._proxy._animations[prevState.Name].action;
-
- this._action.reset();
+
+ this._action.reset();
this._action.setLoop(THREE.LoopOnce, 1);
this._action.clampWhenFinished = true;
this._action.crossFadeFrom(prevAction, 0.2, true);
@@ -79,42 +79,42 @@ export const player_state = (() => {
this._action.play();
}
}
-
+
_Finished() {
this._Cleanup();
this._parent.SetState('idle');
}
-
+
_Cleanup() {
if (this._action) {
this._action.getMixer().removeEventListener('finished', this._FinishedCallback);
}
}
-
+
Exit() {
this._Cleanup();
}
-
+
Update(_) {
}
};
-
+
class WalkState extends State {
constructor(parent) {
super(parent);
}
-
+
get Name() {
return 'walk';
}
-
+
Enter(prevState) {
const curAction = this._parent._proxy._animations['walk'].action;
if (prevState) {
const prevAction = this._parent._proxy._animations[prevState.Name].action;
-
+
curAction.enabled = true;
-
+
if (prevState.Name == 'run') {
const ratio = curAction.getClip().duration / prevAction.getClip().duration;
curAction.time = prevAction.time * ratio;
@@ -123,17 +123,17 @@ export const player_state = (() => {
curAction.setEffectiveTimeScale(1.0);
curAction.setEffectiveWeight(1.0);
}
-
+
curAction.crossFadeFrom(prevAction, 0.1, true);
curAction.play();
} else {
curAction.play();
}
}
-
+
Exit() {
}
-
+
Update(timeElapsed, input) {
if (input._keys.forward || input._keys.backward) {
if (input._keys.shift) {
@@ -141,28 +141,28 @@ export const player_state = (() => {
}
return;
}
-
+
this._parent.SetState('idle');
}
};
-
-
+
+
class RunState extends State {
constructor(parent) {
super(parent);
}
-
+
get Name() {
return 'run';
}
-
+
Enter(prevState) {
const curAction = this._parent._proxy._animations['run'].action;
if (prevState) {
const prevAction = this._parent._proxy._animations[prevState.Name].action;
-
+
curAction.enabled = true;
-
+
if (prevState.Name == 'walk') {
const ratio = curAction.getClip().duration / prevAction.getClip().duration;
curAction.time = prevAction.time * ratio;
@@ -171,17 +171,17 @@ export const player_state = (() => {
curAction.setEffectiveTimeScale(1.0);
curAction.setEffectiveWeight(1.0);
}
-
+
curAction.crossFadeFrom(prevAction, 0.1, true);
curAction.play();
} else {
curAction.play();
}
}
-
+
Exit() {
}
-
+
Update(timeElapsed, input) {
if (input._keys.forward || input._keys.backward) {
if (!input._keys.shift) {
@@ -189,21 +189,21 @@ export const player_state = (() => {
}
return;
}
-
+
this._parent.SetState('idle');
}
};
-
-
+
+
class IdleState extends State {
constructor(parent) {
super(parent);
}
-
+
get Name() {
return 'idle';
}
-
+
Enter(prevState) {
const idleAction = this._parent._proxy._animations['idle'].action;
if (prevState) {
@@ -218,10 +218,10 @@ export const player_state = (() => {
idleAction.play();
}
}
-
+
Exit() {
}
-
+
Update(_, input) {
if (input._keys.forward || input._keys.backward) {
this._parent.SetState('walk');
@@ -240,4 +240,4 @@ export const player_state = (() => {
DeathState: DeathState,
};
-})();
\ No newline at end of file
+})();
diff --git a/src/third-person-camera.js b/src/third-person-camera.js
index d0d6317..0b3d83e 100644
--- a/src/third-person-camera.js
+++ b/src/third-person-camera.js
@@ -1,9 +1,9 @@
-import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.118/build/three.module.js';
+import * as THREE from 'three';
import {entity} from './entity.js';
export const third_person_camera = (() => {
-
+
class ThirdPersonCamera extends entity.Component {
constructor(params) {
super();
@@ -49,4 +49,4 @@ export const third_person_camera = (() => {
ThirdPersonCamera: ThirdPersonCamera
};
-})();
\ No newline at end of file
+})();