amazing
This commit is contained in:
@@ -1,333 +0,0 @@
|
|||||||
import { Scene, Clock, PointLight, Group, TextGeometry, MeshStandardMaterial, MeshBasicMaterial, PlaneGeometry, Mesh, TextureLoader, sRGBEncoding,
|
|
||||||
AnimationMixer, LoopPingPong, Vector3, DirectionalLight, Matrix4, LoopRepeat, EquirectangularReflectionMapping, EquirectangularRefractionMapping } from 'three';
|
|
||||||
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
|
|
||||||
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
|
|
||||||
import {FontLoader} from 'three/examples/jsm/loaders/FontLoader';
|
|
||||||
import * as BufferGeometryUtils from 'three/examples/jsm/utils/BufferGeometryUtils';
|
|
||||||
import { Clickable } from '../lib/Clickable';
|
|
||||||
import { Draggable } from '../lib/Draggable';
|
|
||||||
import { GameObject } from '../lib/GameObject';
|
|
||||||
import { MotionEngine } from '../lib/MotionEngine';
|
|
||||||
|
|
||||||
class Maze {
|
|
||||||
constructor(context) {
|
|
||||||
const scene = new Scene();
|
|
||||||
const motionEngine = new MotionEngine();
|
|
||||||
this.context = context;
|
|
||||||
context.motionEngine = motionEngine;
|
|
||||||
context.scene = scene;
|
|
||||||
const clickable = new Clickable(2);
|
|
||||||
context.clickable = clickable;
|
|
||||||
context.draggable = new Draggable(2);
|
|
||||||
|
|
||||||
if (context.dashboard) context.dashboard.onpoints = context.onpoints;
|
|
||||||
|
|
||||||
context.wallSize = context.wallSize || .65;
|
|
||||||
context.tubeSize = context.tubeSize || .8;
|
|
||||||
context.wallDepth = context.wallDepth || .1;
|
|
||||||
context.fontPath = context.fontPath || './assets/fonts/ZapfChanceryC.otf';
|
|
||||||
scene.background = new TextureLoader().load('./assets/textures/room/a3-2.jpg');
|
|
||||||
scene.background.encoding = sRGBEncoding;
|
|
||||||
scene.background.mapping = EquirectangularRefractionMapping;
|
|
||||||
|
|
||||||
const _tf = {
|
|
||||||
rotation: {
|
|
||||||
r: 3 * Math.PI / 2, f: 0, l: Math.PI / 2, b: Math.PI
|
|
||||||
},
|
|
||||||
position: {
|
|
||||||
r: [-context.wallSize, context.wallSize],
|
|
||||||
f: [0, 2 * context.wallSize],
|
|
||||||
l: [context.wallSize, context.wallSize]
|
|
||||||
},
|
|
||||||
pNext: {
|
|
||||||
r: [-context.wallSize - (context.wallSize + context.wallDepth) / 2, context.wallSize],
|
|
||||||
f: [0, 2 * context.wallSize + context.wallSize / 2],
|
|
||||||
l: [context.wallSize + (context.wallSize + context.wallDepth) / 2, context.wallSize]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const _l = new PointLight(0xffffff, 1, 10, 0.5);
|
|
||||||
let pLoad = [];
|
|
||||||
const mixers = [];
|
|
||||||
context.mixers = mixers;
|
|
||||||
context.assets = {};
|
|
||||||
const clock = new Clock();
|
|
||||||
context.activate = function (what) {
|
|
||||||
scene.traverse(o => {
|
|
||||||
if (o.name == what) {
|
|
||||||
o.visible = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
context.gameObject = function (name) {
|
|
||||||
let result;
|
|
||||||
scene.traverse(o => {
|
|
||||||
if (o.name == name) {
|
|
||||||
result = o;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
const areas = [];
|
|
||||||
context.areas = areas;
|
|
||||||
let mazeGeometries = [];
|
|
||||||
const cameraNear = .2;
|
|
||||||
let heroDistance = .2;
|
|
||||||
let o = {};
|
|
||||||
var loader = new GLTFLoader().setPath(context.path);
|
|
||||||
loader.setDRACOLoader(new DRACOLoader().setDecoderPath('./lib/draco/'));
|
|
||||||
const fontLoader = new FontLoader().setPath(context.path);
|
|
||||||
pLoad.push(new Promise((resolve, reject) => {
|
|
||||||
loader.load('maze2.gltf', function (gltf) {
|
|
||||||
console.log(gltf);
|
|
||||||
gltf.scene.traverse(function (object) {
|
|
||||||
if (object.isMesh || object.isObject3D) {
|
|
||||||
//object.castShadow = true;
|
|
||||||
//object.receiveShadow = true;
|
|
||||||
}
|
|
||||||
if (object.name) {
|
|
||||||
context.assets[object.name] = object;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
['tunnel', 'wall', 'door', 'floor'].forEach(e => {
|
|
||||||
o[e] = gltf.scene.getObjectByName(e);
|
|
||||||
});
|
|
||||||
resolve(gltf);
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
pLoad.push(new Promise((resolve, reject) => {
|
|
||||||
loader.setPath(context.path + 'human2/');
|
|
||||||
loader.load('human.gltf', function (gltf) {
|
|
||||||
console.log(gltf);
|
|
||||||
gltf.scene.traverse(function (object) {
|
|
||||||
if (object.isMesh || object.isObject3D) {
|
|
||||||
//object.castShadow = true;
|
|
||||||
//object.receiveShadow = true;
|
|
||||||
object.frustumCulled = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
o.hero = gltf.scene;
|
|
||||||
o.hero.scale.set(.033, .033, .033);
|
|
||||||
o.hero.position.y = 0;
|
|
||||||
let mixer = new AnimationMixer(gltf.scene);
|
|
||||||
mixers.push(mixer);
|
|
||||||
o.hero.actionWalk = mixer.clipAction(gltf.animations.find(a => a.name == 'walk'));
|
|
||||||
o.hero.actionIdle = mixer.clipAction(gltf.animations.find(a => a.name == 'idle'));
|
|
||||||
o.hero.actionIdle.play();
|
|
||||||
resolve(gltf);
|
|
||||||
});
|
|
||||||
loader.setPath(context.path);
|
|
||||||
}));
|
|
||||||
|
|
||||||
pLoad.push(new Promise((resolve, reject) => {
|
|
||||||
fontLoader.load('font.json', function (font) {
|
|
||||||
context.fontMaterial = new MeshBasicMaterial({
|
|
||||||
color: 0x885e2c,
|
|
||||||
transparent: true,
|
|
||||||
opacity: 0.73
|
|
||||||
});
|
|
||||||
context.font = font;
|
|
||||||
resolve(font);
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
|
|
||||||
const staticThings = new Group();
|
|
||||||
const staticPointer = new Mesh(
|
|
||||||
new PlaneGeometry(.010, .010),
|
|
||||||
new MeshStandardMaterial({
|
|
||||||
map: new TextureLoader().load('./assets/maze/x.png'),
|
|
||||||
alphaTest: .5,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
staticPointer.frustumCulled = false;
|
|
||||||
staticPointer.material.map.encoding = sRGBEncoding;
|
|
||||||
staticThings.add(staticPointer);
|
|
||||||
|
|
||||||
scene.add(staticThings);
|
|
||||||
|
|
||||||
Promise.all(pLoad).then(function () {
|
|
||||||
loadScene();
|
|
||||||
context.onload && context.onload();
|
|
||||||
});
|
|
||||||
|
|
||||||
var that = this;
|
|
||||||
function loadScene() {
|
|
||||||
mazeObject(context.maze, scene);
|
|
||||||
scene.add(o.hero);
|
|
||||||
scene.add(new Mesh(BufferGeometryUtils.mergeBufferGeometries(mazeGeometries, false), o.tunnel.material));
|
|
||||||
scene.add(_l);
|
|
||||||
that.ready = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function between(a, b, x) {
|
|
||||||
return (a < b && a < x && x < b) || (b < a && b < x && x < a);
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkArea(x, z) {
|
|
||||||
let allowed = areas.filter(e => e.type != 'deny' && between(e.a[0].x, e.a[1].x, x) && between(e.a[0].z, e.a[1].z, z));
|
|
||||||
let denied = areas.filter(e => e.type == 'deny' && between(e.a[0].x, e.a[1].x, x) && between(e.a[0].z, e.a[1].z, z));
|
|
||||||
return { area: allowed, block: allowed.length == 0 || denied.length > 0 };
|
|
||||||
}
|
|
||||||
|
|
||||||
this.scene = scene;
|
|
||||||
const _vector = new Vector3();
|
|
||||||
let heroState = 0;
|
|
||||||
let lastCamera = new Vector3(0, .5, 0.5);
|
|
||||||
this.update = function (camera) {
|
|
||||||
let currentArea = checkArea(camera.position.x, camera.position.z);
|
|
||||||
if (currentArea.block) {
|
|
||||||
if (!checkArea(camera.position.x, lastCamera.z).block) {
|
|
||||||
camera.position.z = lastCamera.z;
|
|
||||||
} else if (!checkArea(lastCamera.x, camera.position.z).block) {
|
|
||||||
camera.position.x = lastCamera.x;
|
|
||||||
} else {
|
|
||||||
camera.position.copy(lastCamera);
|
|
||||||
}
|
|
||||||
currentArea = checkArea(camera.position.x, camera.position.z);
|
|
||||||
}
|
|
||||||
_l.position.copy(camera.position);
|
|
||||||
context.onupdate && context.onupdate();
|
|
||||||
motionEngine.update();
|
|
||||||
let delta = clock.getDelta();
|
|
||||||
mixers.forEach(m => m.update(delta));
|
|
||||||
if (o.hero) {
|
|
||||||
let dst = Math.abs(camera.position.distanceTo(lastCamera));
|
|
||||||
if (dst <= 0.005 && heroState == 1) {
|
|
||||||
o.hero.actionWalk.crossFadeTo(o.hero.actionIdle.play(), .5);
|
|
||||||
heroState = 0;
|
|
||||||
}
|
|
||||||
else if (dst <= 0.0005 && heroState == 0 && o.hero.actionWalk.isRunning()) {
|
|
||||||
o.hero.actionWalk.stop();
|
|
||||||
} else if (dst > 0.005 && heroState == 0) {
|
|
||||||
o.hero.actionIdle.crossFadeTo(o.hero.actionWalk.reset().play(), .5);
|
|
||||||
heroState = 1;
|
|
||||||
} else if (dst > 0.007 && heroState == 1 && o.hero.actionIdle.isRunning()) {
|
|
||||||
o.hero.actionIdle.stop();
|
|
||||||
}
|
|
||||||
_vector.setFromMatrixColumn(camera.matrix, 0);
|
|
||||||
_vector.crossVectors(camera.up, _vector);
|
|
||||||
|
|
||||||
o.hero.position.copy(camera.position);
|
|
||||||
o.hero.position.addScaledVector(_vector, heroDistance);
|
|
||||||
o.hero.position.y = 0;
|
|
||||||
o.hero.rotation.y = camera.rotation.y - Math.PI;
|
|
||||||
|
|
||||||
if (checkArea(o.hero.position.x, o.hero.position.z).block) {
|
|
||||||
o.hero.visible = false;
|
|
||||||
} else {
|
|
||||||
o.hero.visible = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
staticThings.position.copy(camera.position);
|
|
||||||
camera.getWorldDirection(_vector);
|
|
||||||
staticThings.position.addScaledVector(_vector, .6);
|
|
||||||
staticThings.rotation.copy(camera.rotation);
|
|
||||||
}
|
|
||||||
lastCamera.copy(camera.position);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.onclick = function (camera, mouse, event) {
|
|
||||||
mouse = mouse || new Vector3(0, 0, 0);
|
|
||||||
clickable.update(mouse, camera, event);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.onpointer = function (camera, mouse, action) {
|
|
||||||
mouse = mouse || new Vector3(0, 0, 0);
|
|
||||||
context.draggable.update(mouse, camera, action);
|
|
||||||
};
|
|
||||||
|
|
||||||
var mazeObject = function (def, room, step = 0) {
|
|
||||||
let offsetZ = 0, e;
|
|
||||||
def.len = def.len || 0;
|
|
||||||
if (step == 0) {
|
|
||||||
e = o.door.geometry.clone();
|
|
||||||
e.rotateY(_tf.rotation.f);
|
|
||||||
mazeGeometries.push(e);
|
|
||||||
}
|
|
||||||
for (let i = 0; i < def.len; i++) {
|
|
||||||
let t = o.tunnel.geometry.clone();
|
|
||||||
t.translate(0, 0, i * context.tubeSize + context.wallDepth / 2);
|
|
||||||
def.matrix && t.applyMatrix4(def.matrix);
|
|
||||||
|
|
||||||
mazeGeometries.push(t);
|
|
||||||
}
|
|
||||||
offsetZ = context.wallDepth + def.len * context.tubeSize - context.tubeSize / 2;
|
|
||||||
if (!def.len) offsetZ = -.275;
|
|
||||||
areas.push({
|
|
||||||
a: [
|
|
||||||
room.localToWorld(new Vector3(-context.tubeSize / 2 + cameraNear, 0, -context.tubeSize / 2 - cameraNear)),
|
|
||||||
room.localToWorld(new Vector3(context.tubeSize / 2 - cameraNear, 0, offsetZ + cameraNear))
|
|
||||||
]
|
|
||||||
});
|
|
||||||
if (def.type == 'area') {
|
|
||||||
def.area.forEach(ar => {
|
|
||||||
areas.push({
|
|
||||||
a: [
|
|
||||||
room.localToWorld(new Vector3(ar[0] + cameraNear, 0, offsetZ + ar[1] - cameraNear)),
|
|
||||||
room.localToWorld(new Vector3(ar[2] - cameraNear, 0, offsetZ + ar[3] + cameraNear))
|
|
||||||
]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
if (def.noRoom) {
|
|
||||||
// e = o.wall.geometry.clone();
|
|
||||||
// e.rotateY(_tf.rotation.f);
|
|
||||||
// e.translate(0,0,offsetZ + 0);
|
|
||||||
// def.matrix && e.applyMatrix4(def.matrix);
|
|
||||||
// mazeGeometries.push(e);
|
|
||||||
} else {
|
|
||||||
e = [o.floor.geometry.clone(), o.door.geometry.clone(), o[def.r ? 'door' : 'wall'].geometry.clone(),
|
|
||||||
o[def.f ? 'door' : 'wall'].geometry.clone(), o[def.l ? 'door' : 'wall'].geometry.clone()];
|
|
||||||
e[0].translate(0, 0, offsetZ + context.wallSize);
|
|
||||||
|
|
||||||
e[1].rotateY(_tf.rotation.b);
|
|
||||||
e[2].rotateY(_tf.rotation.r);
|
|
||||||
e[3].rotateY(_tf.rotation.f);
|
|
||||||
e[4].rotateY(_tf.rotation.l);
|
|
||||||
|
|
||||||
e[1].translate(0, 0, offsetZ + 0);
|
|
||||||
e[2].translate(-context.wallSize, 0, offsetZ + context.wallSize);
|
|
||||||
e[3].translate(0, 0, offsetZ + context.wallSize * 2);
|
|
||||||
e[4].translate(context.wallSize, 0, offsetZ + context.wallSize);
|
|
||||||
|
|
||||||
e.forEach(g => {
|
|
||||||
def.matrix && g.applyMatrix4(def.matrix);
|
|
||||||
mazeGeometries.push(g);
|
|
||||||
});
|
|
||||||
areas.push({
|
|
||||||
a: [
|
|
||||||
room.localToWorld(new Vector3(-context.wallSize + cameraNear, 0, offsetZ + cameraNear)),
|
|
||||||
room.localToWorld(new Vector3(context.wallSize - cameraNear, 0, offsetZ + context.wallSize * 2 - cameraNear))
|
|
||||||
]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def.objects && def.objects.forEach(obj => {
|
|
||||||
obj.room = room;
|
|
||||||
let go = new GameObject(obj, context);
|
|
||||||
go.ready.then(mesh => {
|
|
||||||
room.add(mesh);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
def.room = room;
|
|
||||||
['r', 'f', 'l'].forEach((d, i) => {
|
|
||||||
if (!def[d]) return;
|
|
||||||
let mtx = new Matrix4();
|
|
||||||
mtx.makeRotationY(_tf.rotation[d]);
|
|
||||||
mtx.setPosition(_tf.pNext[d][0], 0, _tf.pNext[d][1] + offsetZ);
|
|
||||||
let rr = new Group();
|
|
||||||
scene.add(rr);
|
|
||||||
def[d].matrix = mtx.premultiply(def.matrix || new Matrix4());
|
|
||||||
rr.applyMatrix4(def[d].matrix);
|
|
||||||
rr.updateMatrixWorld();
|
|
||||||
mazeObject(def[d], rr, step + 1);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export { Maze };
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Group, Vector3, Matrix4, Mesh, Quaternion, BoxGeometry } from 'three';
|
import { Group, Vector3, Matrix4, Mesh, Quaternion, PlaneGeometry, MeshStandardMaterial, DoubleSide } from 'three';
|
||||||
import { InteractiveObject } from '../InteractiveObject';
|
import { InteractiveObject } from '../InteractiveObject';
|
||||||
|
|
||||||
class MazeObject {
|
class MazeObject {
|
||||||
@@ -8,6 +8,8 @@ class MazeObject {
|
|||||||
this.object = room;
|
this.object = room;
|
||||||
let context = {};
|
let context = {};
|
||||||
|
|
||||||
|
const bbox = {l:0, r:0, f:0}
|
||||||
|
|
||||||
const scale = 5;
|
const scale = 5;
|
||||||
|
|
||||||
context.wallSize = params.wallSize || 1.2*scale; //half
|
context.wallSize = params.wallSize || 1.2*scale; //half
|
||||||
@@ -19,11 +21,11 @@ class MazeObject {
|
|||||||
this.context = context;
|
this.context = context;
|
||||||
let _tf = {
|
let _tf = {
|
||||||
rotation: {
|
rotation: {
|
||||||
r: 3 * Math.PI / 2, f: 0, l: Math.PI / 2, b: Math.PI
|
r: 3 * Math.PI / 2, f: 0, l: Math.PI / 2, b: 0
|
||||||
},
|
},
|
||||||
pNext: {
|
pNext: {
|
||||||
r: [-context.wallSize/2, context.wallSize/2],
|
r: [-context.wallSize/2, context.wallSize/2],
|
||||||
f: [0, context.wallSize / 2],
|
f: [0, context.wallSize],
|
||||||
l: [context.wallSize/2, context.wallSize/2]
|
l: [context.wallSize/2, context.wallSize/2]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -62,7 +64,6 @@ class MazeObject {
|
|||||||
e[4].rotateY(_tf.rotation.l);
|
e[4].rotateY(_tf.rotation.l);
|
||||||
|
|
||||||
e[1].position.set(0, 0, offsetZ + 0);
|
e[1].position.set(0, 0, offsetZ + 0);
|
||||||
|
|
||||||
e[2].position.set(-context.wallSize/2, 0, offsetZ + context.wallSize/2);
|
e[2].position.set(-context.wallSize/2, 0, offsetZ + context.wallSize/2);
|
||||||
e[3].position.set(0, 0, offsetZ + context.wallSize);
|
e[3].position.set(0, 0, offsetZ + context.wallSize);
|
||||||
e[4].position.set(context.wallSize/2, 0, offsetZ + context.wallSize/2);
|
e[4].position.set(context.wallSize/2, 0, offsetZ + context.wallSize/2);
|
||||||
@@ -86,6 +87,9 @@ class MazeObject {
|
|||||||
e.forEach(g => {
|
e.forEach(g => {
|
||||||
g.applyMatrix4(def.matrix);
|
g.applyMatrix4(def.matrix);
|
||||||
root.add(g);
|
root.add(g);
|
||||||
|
bbox.l = Math.min(g.position.x, bbox.l)
|
||||||
|
bbox.r = Math.max(g.position.x, bbox.r)
|
||||||
|
bbox.f = Math.max(g.position.z, bbox.f)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,7 +171,14 @@ class MazeObject {
|
|||||||
// //engine.phy.add(mesh, 'fixed')
|
// //engine.phy.add(mesh, 'fixed')
|
||||||
// })
|
// })
|
||||||
|
|
||||||
console.log(o.tunnel)
|
console.log(bbox, 'bbox')
|
||||||
|
const floorGeometry = new PlaneGeometry(bbox.r - bbox.l + 10*scale, bbox.f + 10*scale);
|
||||||
|
const floor = new Mesh(floorGeometry,new MeshStandardMaterial({
|
||||||
|
roughness: 0, metalness:1, color: 0x00ffff, side: DoubleSide
|
||||||
|
}))
|
||||||
|
floor.rotation.set(Math.PI/2, 0, 0)
|
||||||
|
floor.position.set((bbox.l + bbox.r)/2, 0.3, bbox.f/2);
|
||||||
|
root.add(floor);
|
||||||
//scene.add(new Mesh(BufferGeometryUtils.mergeGeometries(mazeGeometries, false), o.tunnel.material));
|
//scene.add(new Mesh(BufferGeometryUtils.mergeGeometries(mazeGeometries, false), o.tunnel.material));
|
||||||
//console.log(room);
|
//console.log(room);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,12 +5,12 @@ const defaults = {
|
|||||||
arrows:{
|
arrows:{
|
||||||
r: len => ({ type: 'image', value: '/static/textures/arrow.png', position:[-.5,.44,len+.96], rotation:[0,Math.PI, 0], scale: [0.03, 0.03, 0.03] }),
|
r: len => ({ type: 'image', value: '/static/textures/arrow.png', position:[-.5,.44,len+.96], rotation:[0,Math.PI, 0], scale: [0.03, 0.03, 0.03] }),
|
||||||
l: len => ({ type: 'image', value: '/static/textures/arrow.png', position:[.5,.44,len+.96], rotation:[0,Math.PI, Math.PI], scale: [0.03, 0.03, 0.03] }),
|
l: len => ({ type: 'image', value: '/static/textures/arrow.png', position:[.5,.44,len+.96], rotation:[0,Math.PI, Math.PI], scale: [0.03, 0.03, 0.03] }),
|
||||||
f: len => ({ type: 'image', value: '/static/textures/arrow.png', position:[0,.73,len+.96], rotation:[0,Math.PI, Math.PI/2], scale: [0.03, 0.03, 0.03] })
|
f: len => ({ type: 'image', value: '/static/textures/arrow.png', position:[0,.7,len+.96], rotation:[0,Math.PI, Math.PI/2], scale: [0.03, 0.03, 0.03] })
|
||||||
},
|
},
|
||||||
answers:{
|
answers:{
|
||||||
r: (len, text) => ({ type: 'text', text, position:[-.5,.3,len+.9], rotation:[0,Math.PI, 0] }),
|
r: (len, text) => ({ type: 'text', width:0.5, text, fontSize:0.025, position:[-.5,.3,len+.9], rotation:[0,Math.PI, 0] }),
|
||||||
l: (len, text) => ({ type: 'text', text, position:[.5,.3,len+.9], rotation:[0,Math.PI, 0] }),
|
l: (len, text) => ({ type: 'text', width:0.5, text, fontSize:0.025, position:[.5,.3,len+.9], rotation:[0,Math.PI, 0] }),
|
||||||
f: (len, text) => ({ type: 'text', text, position:[0,.7,len+.9], rotation:[0,Math.PI, 0] })
|
f: (len, text) => ({ type: 'text', width:0.5, text, fontSize:0.025, position:[0,.55,len+.9], rotation:[0,Math.PI, 0] })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,16 +28,16 @@ class MazeQuizGame {
|
|||||||
return this.object;
|
return this.object;
|
||||||
}
|
}
|
||||||
|
|
||||||
generate(questions, idx = 0){
|
generate(questions, idx = 0, len){
|
||||||
let cq = questions[idx]
|
let cq = questions[idx]
|
||||||
if (!cq) return {};
|
if (!cq) return {};
|
||||||
let len = Math.round(Math.random()*tl) + 2;
|
len = len || Math.round(Math.random()*tl) + 2;
|
||||||
|
|
||||||
let l = {
|
// let l = {
|
||||||
l: Math.round(Math.random()*tl) + 2,
|
// l: Math.round(Math.random()*tl) + 2,
|
||||||
r: Math.round(Math.random()*tl) + 2,
|
// r: Math.round(Math.random()*tl) + 2,
|
||||||
f: Math.round(Math.random()*tl) + 2
|
// f: Math.round(Math.random()*tl/2) + 2
|
||||||
}
|
// }
|
||||||
|
|
||||||
let directions = Utils.shuffleArray( ['l', 'r', 'f'] )
|
let directions = Utils.shuffleArray( ['l', 'r', 'f'] )
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ class MazeQuizGame {
|
|||||||
len,
|
len,
|
||||||
objects:[
|
objects:[
|
||||||
{
|
{
|
||||||
type: 'text', text: cq.q, position:[0,.4,len + .96], rotation:[0,Math.PI, 0]
|
type: 'text', text: cq.q, fontSize:0.033, width:0.5, position:[0,.33,len + .96], rotation:[0,Math.PI, 0]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -58,35 +58,38 @@ class MazeQuizGame {
|
|||||||
)
|
)
|
||||||
let dd;
|
let dd;
|
||||||
if (d == 'f'){
|
if (d == 'f'){
|
||||||
dd = l.l > l.r ? 'l' : 'r';
|
dd = Math.round() > 0.5 ? 'l' : 'r';
|
||||||
}else {
|
}else {
|
||||||
dd = d == 'l' ? 'r' : 'l'
|
dd = d == 'l' ? 'r' : 'l'
|
||||||
}
|
}
|
||||||
if (i == 0){
|
if (i == 0){
|
||||||
mo[d] = {
|
mo[d] = {
|
||||||
len: l[d],
|
len: 4,
|
||||||
[dd]: this.generate(questions, idx + 1)
|
[dd]: this.generate(questions, idx + 1, 3)
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
mo[d] = {
|
mo[d] = {
|
||||||
len: l[d],
|
len: 4,
|
||||||
[dd]: {
|
[dd]: {
|
||||||
len: 8 - l[d],
|
len: 2,
|
||||||
objects:[
|
objects:[
|
||||||
{
|
{
|
||||||
type: 'text', text: cq.h, position:[0,.44,8 - l[d]+.96], rotation:[0,Math.PI, 0]
|
type: 'text', width:0.5, color:0xff0000, text: cq.h, fontSize:0.033, position:[0,.44,2+.96], rotation:[0,Math.PI, 0]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (d == 'f'){
|
if (d == 'f'){
|
||||||
|
mo[d].len = 2;
|
||||||
|
if (i == 0){
|
||||||
let path = mo[d][dd];
|
let path = mo[d][dd];
|
||||||
mo[d][dd] = {
|
mo[d][dd] = {
|
||||||
len: 1,
|
len: 1,
|
||||||
[dd == 'r' ? 'l' : 'r']: path
|
[dd == 'r' ? 'l' : 'r']: path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return mo;
|
return mo;
|
||||||
|
|||||||
+32
-125
@@ -40,7 +40,10 @@ export class CharacterControls {
|
|||||||
|
|
||||||
this.orbitControl = engine.orbitControls
|
this.orbitControl = engine.orbitControls
|
||||||
this.camera = engine.camera
|
this.camera = engine.camera
|
||||||
this.updateCameraTarget(new THREE.Vector3(0,1,5))
|
//this.updateCameraTarget(new THREE.Vector3(0,1,5))
|
||||||
|
|
||||||
|
this.direction = this.model.rotation.y;
|
||||||
|
this.directionVelocity = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
switchRunToggle() {
|
switchRunToggle() {
|
||||||
@@ -75,44 +78,19 @@ export class CharacterControls {
|
|||||||
|
|
||||||
let velocity = 0
|
let velocity = 0
|
||||||
if (this.currentAction == 'run' || this.currentAction == 'walk') {
|
if (this.currentAction == 'run' || this.currentAction == 'walk') {
|
||||||
// calculate towards camera direction
|
let input = this.getInput(pointerControls)
|
||||||
var angleYCameraDirection = Math.atan2(
|
this.directionVelocity = this.directionVelocity * 2.5 * Math.abs(input[0])
|
||||||
(this.camera.position.x - this.model.position.x),
|
this.direction += input[0] * delta * 2.5 //this.directionVelocity;
|
||||||
(this.camera.position.z - this.model.position.z))
|
this.model.rotation.y = this.direction;
|
||||||
// diagonal movement angle offset
|
this.walkDirection.set(input[0], 0, input[1])
|
||||||
var directionOffset = this.directionOffset(pointerControls)
|
this.walkDirection.applyAxisAngle(this.rotateAngle, this.direction)
|
||||||
|
this.walkDirection.normalize();
|
||||||
|
|
||||||
// rotate model
|
|
||||||
this.rotateQuarternion.setFromAxisAngle(this.rotateAngle, Math.PI + angleYCameraDirection + directionOffset)
|
|
||||||
this.model.quaternion.slerp(this.rotateQuarternion, delta*7)
|
|
||||||
|
|
||||||
// calculate direction
|
//let dst = Math.sqrt(Math.pow(cameraPosition.x - this.model.position.x, 2) + Math.pow(cameraPosition.z - this.model.position.z, 2));
|
||||||
this.camera.getWorldDirection(this.walkDirection)
|
|
||||||
this.walkDirection.y = 0
|
|
||||||
this.walkDirection.normalize()
|
|
||||||
this.walkDirection.applyAxisAngle(this.rotateAngle, directionOffset)
|
|
||||||
|
|
||||||
//this.camera.quaternion.rotateTowards(this.rotateQuarternion, delta)
|
|
||||||
|
|
||||||
let cameraPosition = new THREE.Vector3().copy(this.camera.position)
|
|
||||||
let cameraDesiredPosition = new THREE.Vector3(
|
|
||||||
this.model.position.x + 5* Math.sin(angleYCameraDirection + directionOffset),
|
|
||||||
3,
|
|
||||||
this.model.position.z + 5* Math.cos(angleYCameraDirection + directionOffset)
|
|
||||||
)
|
|
||||||
|
|
||||||
cameraPosition.lerp(cameraDesiredPosition, delta*2)
|
|
||||||
|
|
||||||
let dst = Math.sqrt(Math.pow(cameraPosition.x - this.model.position.x, 2) + Math.pow(cameraPosition.z - this.model.position.z, 2));
|
|
||||||
//cameraPosition.y = 8 - dst;
|
//cameraPosition.y = 8 - dst;
|
||||||
if (dst >0.52){
|
//if (dst >0.52){
|
||||||
this.camera.position.copy(cameraPosition)
|
//}
|
||||||
this.camera.lookAt(new THREE.Vector3(
|
|
||||||
this.model.position.x,
|
|
||||||
2,
|
|
||||||
this.model.position.z
|
|
||||||
))
|
|
||||||
}
|
|
||||||
//this.camera.zoom = dst
|
//this.camera.zoom = dst
|
||||||
//this.camera.updateProjectionMatrix();
|
//this.camera.updateProjectionMatrix();
|
||||||
|
|
||||||
@@ -130,12 +108,6 @@ export class CharacterControls {
|
|||||||
this.walkDirection, // The movement we would like to apply if there wasn’t any obstacle.
|
this.walkDirection, // The movement we would like to apply if there wasn’t any obstacle.
|
||||||
);
|
);
|
||||||
|
|
||||||
// for (let i = 0; i < this.characterController.numComputedCollisions(); i++) {
|
|
||||||
// let collision = this.characterController.computedCollision(i);
|
|
||||||
// console.log('c', collision)
|
|
||||||
// // Do something with that collision information.
|
|
||||||
// }
|
|
||||||
|
|
||||||
let correctedMovement = this.characterController.computedMovement();
|
let correctedMovement = this.characterController.computedMovement();
|
||||||
|
|
||||||
let v = new THREE.Vector3();
|
let v = new THREE.Vector3();
|
||||||
@@ -144,93 +116,28 @@ export class CharacterControls {
|
|||||||
|
|
||||||
this.po.rigidBody.setNextKinematicTranslation(v);
|
this.po.rigidBody.setNextKinematicTranslation(v);
|
||||||
|
|
||||||
//console.log(this.walkDirection, correctedMovement);
|
|
||||||
//this.po.rigidBody.setNextKinematicRotation(this.rotateQuarternion);
|
|
||||||
|
|
||||||
// if (translation.y < -1) {
|
|
||||||
// // don't fall below ground
|
|
||||||
// this.rigidBody.setNextKinematicTranslation( {
|
|
||||||
// x: 0,
|
|
||||||
// y: 10,
|
|
||||||
// z: 0
|
|
||||||
// });
|
|
||||||
// } else {
|
|
||||||
|
|
||||||
|
|
||||||
const cameraPositionOffset = this.camera.position.sub(this.model.position);
|
|
||||||
this.model.position.copy(this.po.rigidBody.nextTranslation())
|
this.model.position.copy(this.po.rigidBody.nextTranslation())
|
||||||
//this.camera.position.add(correctedMovement)
|
|
||||||
// // update model and camera
|
|
||||||
// this.model.position.x = translation.x
|
|
||||||
// this.model.position.y = translation.y
|
|
||||||
// this.model.position.z = translation.z
|
|
||||||
|
|
||||||
this.updateCameraTarget(cameraPositionOffset, correctedMovement)
|
let cameraPosition = new THREE.Vector3().copy(this.camera.position)
|
||||||
|
let cameraDesiredPosition = new THREE.Vector3(
|
||||||
|
this.model.position.x + 5* Math.sin(this.model.rotation.y + Math.PI),
|
||||||
|
3,
|
||||||
|
this.model.position.z + 5* Math.cos(this.model.rotation.y + Math.PI)
|
||||||
|
)
|
||||||
|
|
||||||
// this.walkDirection.y += this.lerp(this.storedFall, -9.81 * delta, 0.10)
|
cameraPosition.lerp(cameraDesiredPosition, delta*2)
|
||||||
// this.storedFall = this.walkDirection.y
|
this.camera.position.copy(cameraPosition)
|
||||||
// this.ray.origin.x = translation.x
|
this.camera.lookAt(new THREE.Vector3(
|
||||||
// this.ray.origin.y = translation.y
|
this.model.position.x,
|
||||||
// this.ray.origin.z = translation.z
|
2,
|
||||||
// let hit = world.castRay(this.ray, 0.5, false, 0xfffffffff);
|
this.model.position.z
|
||||||
// if (hit) {
|
))
|
||||||
// const point = this.ray.pointAt(hit.timeOfImpact);
|
|
||||||
// let diff = translation.y - ( point.y + CONTROLLER_BODY_RADIUS);
|
|
||||||
// if (diff < 0.0) {
|
|
||||||
// this.storedFall = 0
|
|
||||||
// this.walkDirection.y = this.lerp(0, -diff, 0.5)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// this.walkDirection.x = this.walkDirection.x * velocity * delta
|
|
||||||
// this.walkDirection.z = this.walkDirection.z * velocity * delta
|
|
||||||
|
|
||||||
// this.rigidBody.setNextKinematicTranslation( {
|
|
||||||
// x: translation.x + this.walkDirection.x,
|
|
||||||
// y: translation.y + this.walkDirection.y,
|
|
||||||
// z: translation.z + this.walkDirection.z
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateCameraTarget(offset, cm) {
|
getInput(pointerControls) {
|
||||||
// move camera
|
return [
|
||||||
const rigidTranslation = this.po.rigidBody.nextTranslation();
|
pointerControls.moveLeft * 1 + pointerControls.moveRight * -1,
|
||||||
this.camera.position.x = rigidTranslation.x + offset.x
|
pointerControls.moveForward * 1 + pointerControls.moveBackward * -1
|
||||||
this.camera.position.y = rigidTranslation.y + offset.y
|
]
|
||||||
this.camera.position.z = rigidTranslation.z + offset.z
|
|
||||||
|
|
||||||
// update camera target
|
|
||||||
this.cameraTarget.x = rigidTranslation.x
|
|
||||||
this.cameraTarget.y = rigidTranslation.y + 1
|
|
||||||
this.cameraTarget.z = rigidTranslation.z
|
|
||||||
this.orbitControl.target = this.cameraTarget
|
|
||||||
}
|
|
||||||
|
|
||||||
directionOffset(pointerControls) {
|
|
||||||
///TODO: REWRITE!!!!
|
|
||||||
var directionOffset = 0 // w
|
|
||||||
|
|
||||||
if (pointerControls.moveForward) {
|
|
||||||
if (pointerControls.moveLeft) {
|
|
||||||
directionOffset = Math.PI / 4 // w+a
|
|
||||||
} else if (pointerControls.moveRight) {
|
|
||||||
directionOffset = - Math.PI / 4 // w+d
|
|
||||||
}
|
|
||||||
} else if (pointerControls.moveBackward) {
|
|
||||||
if (pointerControls.moveLeft) {
|
|
||||||
directionOffset = Math.PI / 4 + Math.PI / 2 // s+a
|
|
||||||
} else if (pointerControls.moveRight) {
|
|
||||||
directionOffset = -Math.PI / 4 - Math.PI / 2 // s+d
|
|
||||||
} else {
|
|
||||||
directionOffset = Math.PI // s
|
|
||||||
}
|
|
||||||
} else if (pointerControls.moveLeft) {
|
|
||||||
directionOffset = Math.PI / 2 // a
|
|
||||||
} else if (pointerControls.moveRight) {
|
|
||||||
directionOffset = - Math.PI / 2 // d
|
|
||||||
}
|
|
||||||
|
|
||||||
return directionOffset
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,14 +2,13 @@ import { TextureLoader } from "three";
|
|||||||
|
|
||||||
function assignParams(mesh, params){
|
function assignParams(mesh, params){
|
||||||
['scale', 'rotation', 'position'].forEach(p=>params[p] && mesh[p].fromArray(params[p]));
|
['scale', 'rotation', 'position'].forEach(p=>params[p] && mesh[p].fromArray(params[p]));
|
||||||
['visible', 'name'].forEach(p=>{
|
['visible', 'name', 'fontSize', 'color'].forEach(p=>{
|
||||||
if (params[p]!==undefined) mesh[p] = params[p];
|
if (params[p]!==undefined) mesh[p] = params[p];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function assignMaterial(mesh, params, context){
|
function assignMaterial(mesh, params, context){
|
||||||
if (params.name && params.material){
|
if (params.name && params.material){
|
||||||
console.log(mesh)
|
|
||||||
//let mp = params.material.metalness ? new MeshStandardMaterial(params.material) : new MeshBasicMaterial(params.material)
|
//let mp = params.material.metalness ? new MeshStandardMaterial(params.material) : new MeshBasicMaterial(params.material)
|
||||||
Object.assign(mesh.material, params.material)
|
Object.assign(mesh.material, params.material)
|
||||||
if (params.dm){
|
if (params.dm){
|
||||||
|
|||||||
Reference in New Issue
Block a user