teleporter interactive object

This commit is contained in:
2026-04-04 17:56:08 +03:00
parent e47aca9687
commit 065ce457cc
6 changed files with 92 additions and 3 deletions
@@ -19,10 +19,11 @@ import { SingleQuestion } from "./SingleQuestion/SingleQuestion";
import { MazeQuizGame } from "./MazeQuizGame/MazeQuizGame"; import { MazeQuizGame } from "./MazeQuizGame/MazeQuizGame";
import { Particles } from "./Particles/Particles"; import { Particles } from "./Particles/Particles";
import { SceneSwitcher } from "./SceneSwitcher/SceneSwitcher"; import { SceneSwitcher } from "./SceneSwitcher/SceneSwitcher";
import { Teleporter } from "./Teleporter/Teleporter";
import { GameEngine } from "@/lib/GameEngine"; import { GameEngine } from "@/lib/GameEngine";
const InteractiveObjectsImports = { const InteractiveObjectsImports = {
GenericObject, CharacterObject, TextObject, ImageObject, GltfObject, VideoPlayer, Particles, SceneSwitcher, GenericObject, CharacterObject, TextObject, ImageObject, GltfObject, VideoPlayer, Particles, SceneSwitcher, Teleporter,
PuzzleGame1, PuzzleGame2, PuzzleGame4, MazeQuizGame, ClassicPuzzle, PairMatchingGame, SingleQuestion PuzzleGame1, PuzzleGame2, PuzzleGame4, MazeQuizGame, ClassicPuzzle, PairMatchingGame, SingleQuestion
}; };
@@ -56,6 +57,7 @@ class InteractiveObject extends EventManager{
case 'SingleQuestion': case 'SingleQuestion':
case 'Particles': case 'Particles':
case 'SceneSwitcher': case 'SceneSwitcher':
case 'Teleporter':
this.io = await new InteractiveObjectsImports[obj.type](engine, obj); this.io = await new InteractiveObjectsImports[obj.type](engine, obj);
this.source = this.io.source || this.io; this.source = this.io.source || this.io;
this.object = this.io.object; this.object = this.io.object;
@@ -174,6 +176,7 @@ const InteractiveObjectTypes = [
'VideoPlayer', 'VideoPlayer',
'Particles', 'Particles',
'SceneSwitcher', 'SceneSwitcher',
'Teleporter',
'TextObject', 'TextObject',
'ImageObject' 'ImageObject'
]; ];
@@ -0,0 +1,41 @@
import { Group, CylinderGeometry, Mesh, MeshStandardMaterial } from 'three';
import { EventManager } from '@/lib/EventManager';
//import { TextObject } from '../TextObject/TextObject';
class Teleporter extends EventManager {
emits = ['interaction']
constructor(engine, data) {
super();
return new Promise(async (resolve, reject)=>{
const container = new Group();
const geometry = new CylinderGeometry(0.25, 0.25, 0.1);
const material = new MeshStandardMaterial({
color: 0x55aaff, roughness: 0.1, metalness: 0.9
});
const s1 = new Mesh(geometry, material);
s1.isIndividual = true;
s1.name = 'T1';
engine.clickable.add(s1, ()=>{
this.dispatchEvent({type:'interaction', value: 'T1'});
engine.hero?.teleport(s2.position)
});
const s2 = s1.clone();
s2.isIndividual = true;
s2.name = 'T2';
engine.clickable.add(s2, ()=>{
this.dispatchEvent({type:'interaction', value: 'T2'})
engine.hero?.teleport(s1.position)
});
s1.position.x = -1;
s2.position.x = 1;
container.add(s1);
container.add(s2);
this.object = engine.meshUtils.centerOrigin(container);
this.object.hasIndividualChildren = true;
resolve(this);
})
}
}
export { Teleporter }
@@ -0,0 +1,22 @@
<template>
</template>
<script>
export default {
data(){
return {
active: false
}
},
mounted(){
this.active = true;
},
props:{
modelValue: Object
},
methods:{
}
}
</script>
+2 -1
View File
@@ -59,13 +59,14 @@ import Particles from '../InteractiveObjects/Particles/Particles.vue';
import GenericObject from '../InteractiveObjects/GenericObject/GenericObject.vue'; import GenericObject from '../InteractiveObjects/GenericObject/GenericObject.vue';
import CharacterObject from '../InteractiveObjects/CharacterObject/CharacterObject.vue'; import CharacterObject from '../InteractiveObjects/CharacterObject/CharacterObject.vue';
import SceneSwitcher from '../InteractiveObjects/SceneSwitcher/SceneSwitcher.vue'; import SceneSwitcher from '../InteractiveObjects/SceneSwitcher/SceneSwitcher.vue';
import Teleporter from '../InteractiveObjects/Teleporter/Teleporter.vue';
import OffsetLine from './OffsetLine.vue'; import OffsetLine from './OffsetLine.vue';
import { InteractiveObjectTypes } from '../InteractiveObjects/InteractiveObject'; import { InteractiveObjectTypes } from '../InteractiveObjects/InteractiveObject';
const components = { const components = {
SvgIcon, OffsetLine, GenericObject, CharacterObject, VideoPlayer, TextObject, ImageObject, SceneSwitcher, SvgIcon, OffsetLine, GenericObject, CharacterObject, VideoPlayer, TextObject, ImageObject, SceneSwitcher,
PuzzleGame1, PuzzleGame2, MazeQuizGame, Particles, ClassicPuzzle, PairMatchingGame, SingleQuestion PuzzleGame1, PuzzleGame2, MazeQuizGame, Particles, ClassicPuzzle, PairMatchingGame, SingleQuestion, Teleporter
}; };
export default { export default {
+20
View File
@@ -340,6 +340,26 @@ class Hero{
//this.currentAction = 'idle' //this.currentAction = 'idle'
} }
async teleport(v3){
if (this.model.visible){
await this.engine.motionQueue.add({
o: this.model,
a: { visible: k => Math.round(k * 20) % 2 == 0},
t: 1.5, p: true
})
this.po.rigidBody.setNextKinematicTranslation(v3);
this.model.position.copy(v3);
await this.engine.motionQueue.add({
o: this.model,
a: { visible: k => Math.round(k * 20) % 2 == 0},
t: 1.5, p: true
})
}else{
this.po.rigidBody.setNextKinematicTranslation(v3);
this.model.position.copy(v3);
}
}
} }
export { Hero } export { Hero }
+2
View File
@@ -143,6 +143,7 @@ const lang = {
ImageObject: 'Image', ImageObject: 'Image',
Particles: 'Particles', Particles: 'Particles',
SceneSwitcher: 'Scene Switcher', SceneSwitcher: 'Scene Switcher',
Teleporter: 'Teleporter',
}, },
errors:{ errors:{
unauthorized: 'Unauthorized', unauthorized: 'Unauthorized',
@@ -310,6 +311,7 @@ const lang = {
ImageObject: 'Изображение', ImageObject: 'Изображение',
Particles: 'Частици', Particles: 'Частици',
SceneSwitcher: 'Превключвател на сцени', SceneSwitcher: 'Превключвател на сцени',
Teleporter: 'Телепортатор'
}, },
errors:{ errors:{
unauthorized: 'Отказан достъп', unauthorized: 'Отказан достъп',