change event dispatcher

This commit is contained in:
2025-11-11 15:15:13 +02:00
parent 35fa1863ff
commit 351c6097f3
10 changed files with 71 additions and 67 deletions
@@ -1,7 +1,9 @@
import { getBoundingBox, getBoundingBoxCenterPoint, getBoundingBoxMaxLength, centerOrigin } from "@/lib/MeshUtils"; import { getBoundingBox, getBoundingBoxCenterPoint, getBoundingBoxMaxLength, centerOrigin } from "@/lib/MeshUtils";
import { EventDispatcher } from "three";
class GenericObject{ class GenericObject extends EventDispatcher{
constructor(engine, data){ constructor(engine, data){
super();
return new Promise(async(resolve, reject)=>{ return new Promise(async(resolve, reject)=>{
this.source = await engine.load(data.$go.asset.name); this.source = await engine.load(data.$go.asset.name);
this.object = centerOrigin(this.source.scene) this.object = centerOrigin(this.source.scene)
@@ -34,7 +36,7 @@ class GenericObject{
} }
if (data.description){ if (data.description){
engine.dashboard.updateText(this.object._active ? data.description : '', (d)=>{ engine.dashboard.updateText(this.object._active ? data.description : '', (d)=>{
console.log('DONETEXT', d) d && this.dispatchEvent({type:'finish'})
}) })
} }
} }
@@ -1,4 +1,4 @@
import { Group } from "three"; import { Group, EventDispatcher } from "three";
import { GenericObject } from "./GenenricObject"; import { GenericObject } from "./GenenricObject";
import { TextObject } from "./TextObject"; import { TextObject } from "./TextObject";
@@ -16,12 +16,13 @@ import { Particles } from "./Particles";
import { assignMaterial, assignParams } from "@/lib/MeshUtils"; import { assignMaterial, assignParams } from "@/lib/MeshUtils";
const InteractiveObjectsImports = { const InteractiveObjectsImports = {
PuzzleGame1, PuzzleGame2, PuzzleGame4, VideoPlayer, GenericObject, CharacterObject, TextObject, ImageObject, VideoPlayer, Particles,
GenericObject, CharacterObject, MazeQuizGame, Particles PuzzleGame1, PuzzleGame2, PuzzleGame4, MazeQuizGame
}; };
class InteractiveObject { class InteractiveObject extends EventDispatcher{
constructor(gameEngine, obj) { constructor(gameEngine, obj) {
super();
this.name = obj.name; this.name = obj.name;
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
switch (obj.type || 'GenericObject') { switch (obj.type || 'GenericObject') {
@@ -32,14 +33,6 @@ class InteractiveObject {
this.object.add(gameMesh.object); this.object.add(gameMesh.object);
} }
break; break;
case 'Text':
this.source = new TextObject(gameEngine, obj);
this.object = this.source.object;
break;
case 'Image':
this.source = new ImageObject(gameEngine, obj);
this.object = this.source.object;
break;
case 'Gltf': case 'Gltf':
let gltf = await gameEngine.load(obj.value, ''); let gltf = await gameEngine.load(obj.value, '');
let gltfObj = gltf.scene; let gltfObj = gltf.scene;
@@ -63,27 +56,20 @@ class InteractiveObject {
this.object = gltfObj; this.object = gltfObj;
this.source = gltf; this.source = gltf;
break; break;
case 'Text':
case 'Image':
case 'GenericObject': case 'GenericObject':
case 'CharacterObject': case 'CharacterObject':
let go = await new InteractiveObjectsImports[obj.type](gameEngine, obj) //await gameEngine.load(obj.$go.asset.name);
this.source = go.source;
this.object = go.object;
break;
case 'PuzzleGame3':
case 'PuzzleGame4':
case 'PuzzleGame5':
case 'PuzzleGame6':
let game = new InteractiveObjectsImports[obj.type](gameEngine, obj.args[0], obj.args[1], obj.args[2]);
this.object = game.object;
this.object.game = game;
break;
case 'VideoPlayer': case 'VideoPlayer':
case 'PuzzleGame1': case 'PuzzleGame1':
case 'PuzzleGame2': case 'PuzzleGame2':
case 'MazeQuizGame': case 'MazeQuizGame':
case 'Particles': case 'Particles':
this.source = await new InteractiveObjectsImports[obj.type](gameEngine, obj); this.io = await new InteractiveObjectsImports[obj.type](gameEngine, obj);
this.object = this.source.object; this.source = this.io.source || this.io;
this.object = this.io.object;
this.io.addEventListener?.('finish', this.dispatchEvent.bind(this))
break; break;
} }
assignParams(this.object, obj); assignParams(this.object, obj);
@@ -1,5 +1,6 @@
import { MazeObject } from "./MazeObject"; import { MazeObject } from "./MazeObject";
import Utils from "@/lib/Utils"; import Utils from "@/lib/Utils";
import { EventDispatcher } from "three";
const params = { const params = {
scale: 5, scale: 5,
@@ -34,7 +35,7 @@ const defaults = {
const tl = 4; const tl = 4;
class MazeQuizGame { class MazeQuizGame extends EventDispatcher {
constructor(engine, data) { constructor(engine, data) {
data.noPhysics = true; data.noPhysics = true;
return new Promise(async (resolve, reject)=>{ return new Promise(async (resolve, reject)=>{
@@ -57,7 +58,7 @@ class MazeQuizGame {
engine.hero.characterControls.direction += Math.PI; engine.hero.characterControls.direction += Math.PI;
//engine.hero.model.rotation.y += Math.PI; //engine.hero.model.rotation.y += Math.PI;
await Utils.wait(10000); await Utils.wait(10000);
this.onfinish?.() this.dispatchEvent({type:'finish'})
}else{ }else{
engine.hero.animationsMap.idle = engine.hero.animationsMap._idle engine.hero.animationsMap.idle = engine.hero.animationsMap._idle
engine.hero.characterControls.cameraDelta = 0 engine.hero.characterControls.cameraDelta = 0
@@ -1,9 +1,10 @@
import { BoxGeometry, Mesh, MeshStandardMaterial, Group } from 'three'; import { BoxGeometry, Mesh, MeshStandardMaterial, Group, EventDispatcher } from 'three';
import { MotionEngine } from '../../lib/MotionEngine'; import { MotionEngine } from '../../lib/MotionEngine';
import { centerOrigin } from '@/lib/MeshUtils'; import { centerOrigin } from '@/lib/MeshUtils';
class PuzzleGame1 { class PuzzleGame1 extends EventDispatcher {
constructor(engine, data) { constructor(engine, data) {
super();
return new Promise(async (resolve, reject)=>{ return new Promise(async (resolve, reject)=>{
let w = data.w, h = data.h, wh = w*h; let w = data.w, h = data.h, wh = w*h;
let container = new Group(); let container = new Group();
@@ -92,7 +93,9 @@ class PuzzleGame1 {
o: c, o: c,
a: { position: { x: i % w, y: Math.trunc(i/w)} }, a: { position: { x: i % w, y: Math.trunc(i/w)} },
t: 1, t: 1,
f: i == 0 && this.onfinish || undefined f: i == 0 ? ()=>{
this.dispatchEvent({type:'finish'})
} : undefined
}); });
}); });
//engine.dashboard.addPoints(10); //engine.dashboard.addPoints(10);
@@ -1,9 +1,10 @@
import { BoxGeometry, Mesh, MeshBasicMaterial, Group } from 'three'; import { BoxGeometry, Mesh, MeshBasicMaterial, Group, EventDispatcher } from 'three';
import { MotionEngine } from '../../lib/MotionEngine'; import { MotionEngine } from '../../lib/MotionEngine';
import { centerOrigin } from '@/lib/MeshUtils'; import { centerOrigin } from '@/lib/MeshUtils';
class PuzzleGame2 { class PuzzleGame2 extends EventDispatcher {
constructor(engine, data) { constructor(engine, data) {
super();
return new Promise(async (resolve, reject)=>{ return new Promise(async (resolve, reject)=>{
let w = data.w, h = data.h, wh = w*h; let w = data.w, h = data.h, wh = w*h;
const texture = await engine.loadTexture(data.$go.asset.name); const texture = await engine.loadTexture(data.$go.asset.name);
@@ -137,7 +138,9 @@ class PuzzleGame2 {
o: c, o: c,
a: { position: { x: i % w, y: ~~(i / h) } }, a: { position: { x: i % w, y: ~~(i / h) } },
t: 1, t: 1,
f: i == 0 ? this.onfinish : undefined f: i == 0 ? ()=>{
this.dispatchEvent({type:'finish'})
} : undefined
}); });
}); });
//engine.dashboard.addPoints(10); //engine.dashboard.addPoints(10);
@@ -115,7 +115,7 @@ var PuzzleGame4 = function(context, gltf, w, h){
d:1+0.1*i d:1+0.1*i
}) })
}) })
this.onfinish && this.onfinish(); this.dispatchEvent({type:'finish'})
//context.dashboard.addPoints(10); //context.dashboard.addPoints(10);
} }
} }
@@ -1,25 +1,28 @@
import * as THREE from 'three'; import {
PlaneGeometry, MeshStandardMaterial, SRGBColorSpace,
VideoTexture, DoubleSide, Mesh, EventDispatcher
} from 'three';
class VideoPlayer extends EventDispatcher {
class VideoPlayer {
constructor(engine, data){ constructor(engine, data){
super();
let vi, plane; let vi, plane;
return new Promise((resolve, reject)=>{ return new Promise((resolve, reject)=>{
vi = document.createElement('video'); vi = document.createElement('video');
vi.src = engine.assetPath + data.$go.asset.name; vi.src = engine.assetPath + data.$go.asset.name;
vi.addEventListener('loadedmetadata', ()=>{ vi.addEventListener('loadedmetadata', ()=>{
this.aspect = vi.videoWidth / vi.videoHeight; this.aspect = vi.videoWidth / vi.videoHeight;
let geometry = new THREE.PlaneGeometry( this.aspect, 1 ); let geometry = new PlaneGeometry( this.aspect, 1 );
let map = new THREE.VideoTexture( vi ); let map = new VideoTexture( vi );
map.colorSpace = THREE.SRGBColorSpace; map.colorSpace = SRGBColorSpace;
let material = new THREE.MeshStandardMaterial( { let material = new MeshStandardMaterial( {
color: 0xffffff, color: 0xffffff,
map, map,
transparent: true, transparent: true,
opacity: 0.5, opacity: 0.5,
side: THREE.DoubleSide side: DoubleSide
} ); } );
plane = new THREE.Mesh( geometry, material ); plane = new Mesh( geometry, material );
this.object = plane; this.object = plane;
engine.clickable.add(plane, ()=>{ engine.clickable.add(plane, ()=>{
if (vi.paused){ if (vi.paused){
@@ -46,7 +49,7 @@ class VideoPlayer {
} }
}) })
vi.addEventListener('ended', ()=>{ vi.addEventListener('ended', ()=>{
this.onfinish?.(); this.dispatchEvent({type:'finish'})
}) })
this.video = vi; this.video = vi;
+20 -11
View File
@@ -53,11 +53,13 @@ class DashBoard {
const loadingPlane = new Mesh( const loadingPlane = new Mesh(
new PlaneGeometry(engine.aspect, 1), new PlaneGeometry(engine.aspect, 1),
new MeshBasicMaterial({ new MeshStandardMaterial({
color:0xFAFAFA, color:0xffffff,
opacity:0, transparent:true,
roughness:0, metalness:0.1
}) })
); );
const loadingProgress = new ProgressBar(); const loadingProgress = new ProgressBar(engine);
loadingProgress.object.scale.set(engine.aspect*0.8, 0.05, 0.05) loadingProgress.object.scale.set(engine.aspect*0.8, 0.05, 0.05)
loadingProgress.object.position.set(-engine.aspect/2 + engine.aspect*0.1, 0, 0.1) loadingProgress.object.position.set(-engine.aspect/2 + engine.aspect*0.1, 0, 0.1)
loadingPlane.add(loadingProgress.object); loadingPlane.add(loadingProgress.object);
@@ -135,7 +137,7 @@ class DashBoard {
}) })
} }
levelProgress = new ProgressBar({}) levelProgress = new ProgressBar(engine)
dash.add(levelProgress.object); dash.add(levelProgress.object);
levelProgress.object.position.set(-engine.aspect/2 + engine.aspect/30, 0.45, -0.01) levelProgress.object.position.set(-engine.aspect/2 + engine.aspect/30, 0.45, -0.01)
levelProgress.object.scale.set(engine.aspect/3, 0.02, 0.02) levelProgress.object.scale.set(engine.aspect/3, 0.02, 0.02)
@@ -230,11 +232,11 @@ class DashBoard {
hudAnimation = null; hudAnimation = null;
} }
this.loading = function(progress){ this.loading = function(progress, tt){
loadingPlane.visible = progress > 0 && progress < 1; loadingPlane.visible = progress > 0 && progress < 1;
loadingProgress.update(progress) loadingProgress.update(progress, tt)
} }
this.loading(1); this.loading(0,0);
} }
get active(){ get active(){
@@ -247,7 +249,7 @@ class DashBoard {
} }
class ProgressBar{ class ProgressBar{
constructor(params = {}){ constructor(engine, params = {}){
this.object = new Group(); this.object = new Group();
const geometry = new CylinderGeometry( 0.5, 0.5, 1, 3, 1, false, 0, Math.PI ); const geometry = new CylinderGeometry( 0.5, 0.5, 1, 3, 1, false, 0, Math.PI );
const staticCylinder = new Mesh( geometry, new MeshStandardMaterial({ const staticCylinder = new Mesh( geometry, new MeshStandardMaterial({
@@ -263,10 +265,17 @@ class ProgressBar{
progressCylinder.rotation.set(Math.PI/2, 0, Math.PI/2,) progressCylinder.rotation.set(Math.PI/2, 0, Math.PI/2,)
this.object.add( progressCylinder ); this.object.add( progressCylinder );
this.update = function(value){ this.update = function(value, transitionTime = 0.5){
progressCylinder.visible = !!value; progressCylinder.visible = !!value;
progressCylinder.scale.y = value; engine.motionQueue.clear(progressCylinder);
progressCylinder.position.x = progressCylinder.scale.y / 2 engine.motionQueue.add({
o: progressCylinder,
a: {
scale: {y: value},
position: {x: value / 2}
},
t: transitionTime
})
} }
this.update(0) this.update(0)
+3 -3
View File
@@ -99,12 +99,12 @@ class GameEngine extends THREE.EventDispatcher{
this.stereo = new StereoEffect(renderer); this.stereo = new StereoEffect(renderer);
this.stereo.setSize(this.w, this.h); this.stereo.setSize(this.w, this.h);
const dashboard = new DashBoard(this);
this.dashboard = dashboard;
this.motionQueue = new MotionEngine(); this.motionQueue = new MotionEngine();
this.assetPath = assetPath; this.assetPath = assetPath;
const dashboard = new DashBoard(this);
this.dashboard = dashboard;
this.activeObjects = new THREE.Group(); this.activeObjects = new THREE.Group();
scene.add(this.activeObjects); scene.add(this.activeObjects);
+3 -6
View File
@@ -119,7 +119,7 @@ export default {
//await gameEngine.loadPanorama(`/asset/default/43.webp`); //await gameEngine.loadPanorama(`/asset/default/43.webp`);
gameEngine.clearScene(); gameEngine.clearScene();
gameEngine.activeObjects.visible = false; gameEngine.activeObjects.visible = false;
gameEngine.dashboard?.loading(0); gameEngine.dashboard?.loading(0,0);
await this.expandScenarioData(scene); await this.expandScenarioData(scene);
gameEngine.dashboard?.loading(0.1); gameEngine.dashboard?.loading(0.1);
@@ -147,9 +147,6 @@ export default {
let loaded = 0; let loaded = 0;
for (let i of this.scene.data.items) { for (let i of this.scene.data.items) {
let io = await new InteractiveObject(gameEngine, i.data) let io = await new InteractiveObject(gameEngine, i.data)
//let gltf = await gameEngine.load(`/asset/default/${i.data.$go.asset.name}`);
//console.log(i.data, io.object)
this.setObjectAttributes(l, i.data, io.object, io.source, 1); this.setObjectAttributes(l, i.data, io.object, io.source, 1);
gameEngine.activeObjects.add(io.object); gameEngine.activeObjects.add(io.object);
if (this.env == 'GamePlaying'){ if (this.env == 'GamePlaying'){
@@ -169,10 +166,10 @@ export default {
}) })
} }
} }
io.onfinish=()=>{ io.addEventListener('finish', ()=>{
gameEngine.dashboard?.addPoints(i.data.points) gameEngine.dashboard?.addPoints(i.data.points)
i.data.points = 0; i.data.points = 0;
} })
} }
loaded += 1/this.scene.data.items.length loaded += 1/this.scene.data.items.length
gameEngine.dashboard?.loading(0.1 + 0.89*loaded); gameEngine.dashboard?.loading(0.1 + 0.89*loaded);