integrate game1 and game2
This commit is contained in:
@@ -62,14 +62,14 @@ export default{
|
|||||||
if (this.forRendering) {
|
if (this.forRendering) {
|
||||||
gameEngine.activeObjects.clear();
|
gameEngine.activeObjects.clear();
|
||||||
if (this.obj.type == 'panorama2d') {
|
if (this.obj.type == 'panorama2d') {
|
||||||
await gameEngine.loadPanorama(`/asset/default/${this.obj.asset.name}`);
|
await gameEngine.loadPanorama(this.obj.asset.name);
|
||||||
// let t = await gameEngine.loadTexture(`/asset/default/${this.obj.asset.name}`);
|
// let t = await gameEngine.loadTexture(`/asset/default/${this.obj.asset.name}`);
|
||||||
// t.mapping = gameEngine.$.EquirectangularReflectionMapping;
|
// t.mapping = gameEngine.$.EquirectangularReflectionMapping;
|
||||||
// gameEngine.scene.background = t;
|
// gameEngine.scene.background = t;
|
||||||
// gameEngine.scene.environment = t;
|
// gameEngine.scene.environment = t;
|
||||||
// gameEngine.scene.add(gameEngine.camera);
|
// gameEngine.scene.add(gameEngine.camera);
|
||||||
} else {
|
} else {
|
||||||
let gltf = await gameEngine.load(`/asset/default/${this.obj.asset.name}`);
|
let gltf = await gameEngine.load(this.obj.asset.name);
|
||||||
//console.debug('GLTF', gltf);
|
//console.debug('GLTF', gltf);
|
||||||
this.loadedAsset = gltf;
|
this.loadedAsset = gltf;
|
||||||
this.animations = gltf.animations.map(a => ({
|
this.animations = gltf.animations.map(a => ({
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { VideoPlayer } from "./VideoPlayer";
|
|||||||
import { MazeQuizGame } from "./MazeQuizGame/MazeQuizGame";
|
import { MazeQuizGame } from "./MazeQuizGame/MazeQuizGame";
|
||||||
import { assignMaterial, assignParams } from "@/lib/MeshUtils";
|
import { assignMaterial, assignParams } from "@/lib/MeshUtils";
|
||||||
|
|
||||||
const games = {PuzzleGame1, PuzzleGame2, PuzzleGame4};
|
const games = {PuzzleGame1, PuzzleGame2, PuzzleGame4, MazeQuizGame};
|
||||||
|
|
||||||
class InteractiveObject {
|
class InteractiveObject {
|
||||||
constructor(obj, gameEngine, params) {
|
constructor(obj, gameEngine, params) {
|
||||||
@@ -35,7 +35,7 @@ class InteractiveObject {
|
|||||||
this.object = this.source.object;
|
this.object = this.source.object;
|
||||||
break;
|
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;
|
||||||
gltfObj.traverse(function (object) {
|
gltfObj.traverse(function (object) {
|
||||||
object.frustumCulled = false;
|
object.frustumCulled = false;
|
||||||
@@ -58,11 +58,9 @@ class InteractiveObject {
|
|||||||
this.source = gltf;
|
this.source = gltf;
|
||||||
break;
|
break;
|
||||||
case 'GenericObject':
|
case 'GenericObject':
|
||||||
this.source = await gameEngine.load(`/asset/default/${obj.$go.asset.name}`);
|
this.source = await gameEngine.load(obj.$go.asset.name);
|
||||||
this.object = this.source.scene;
|
this.object = this.source.scene;
|
||||||
break;
|
break;
|
||||||
case 'PuzzleGame1':
|
|
||||||
case 'PuzzleGame2':
|
|
||||||
case 'PuzzleGame3':
|
case 'PuzzleGame3':
|
||||||
case 'PuzzleGame4':
|
case 'PuzzleGame4':
|
||||||
case 'PuzzleGame5':
|
case 'PuzzleGame5':
|
||||||
@@ -72,13 +70,14 @@ class InteractiveObject {
|
|||||||
this.object.game = game;
|
this.object.game = game;
|
||||||
break;
|
break;
|
||||||
case 'VideoPlayer':
|
case 'VideoPlayer':
|
||||||
let vp = new VideoPlayer(gameEngine, `/asset/default/${obj.$go.asset.name}`);
|
let vp = new VideoPlayer(gameEngine, gameEngine.assetPath + obj.$go.asset.name);
|
||||||
this.source = await vp.ready;
|
this.source = await vp.ready;
|
||||||
this.object = vp.object;
|
this.object = vp.object;
|
||||||
break;
|
break;
|
||||||
|
case 'PuzzleGame1':
|
||||||
|
case 'PuzzleGame2':
|
||||||
case 'MazeQuizGame':
|
case 'MazeQuizGame':
|
||||||
this.source = new MazeQuizGame(gameEngine, obj);
|
this.source = await new games[obj.type](gameEngine, obj);
|
||||||
await this.source.load();
|
|
||||||
this.object = this.source.object;
|
this.object = this.source.object;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -91,9 +90,11 @@ class InteractiveObject {
|
|||||||
const InteractiveObjectTypes = [
|
const InteractiveObjectTypes = [
|
||||||
{
|
{
|
||||||
id: 'PuzzleGame1', name: 'Puzzle Game 1'
|
id: 'PuzzleGame1', name: 'Puzzle Game 1'
|
||||||
}, {
|
},{
|
||||||
|
id: 'PuzzleGame2', name: 'Puzzle Game 2'
|
||||||
|
},{
|
||||||
id: 'MazeQuizGame', name: 'Maze Quiz Game'
|
id: 'MazeQuizGame', name: 'Maze Quiz Game'
|
||||||
}, {
|
},{
|
||||||
id: 'VideoPlayer', name: 'Video Player'
|
id: 'VideoPlayer', name: 'Video Player'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ class MazeObject {
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.load = async function(){
|
this.load = async function(){
|
||||||
let mazeAsset = await engine.load('/static/meshes/quiz.gltf');
|
let mazeAsset = await engine.load('/static/meshes/quiz.gltf', '');
|
||||||
['tunnel', 'wall', 'door', 'floor'].forEach(e => {
|
['tunnel', 'wall', 'door', 'floor'].forEach(e => {
|
||||||
o[e] = mazeAsset.scene.getObjectByName(e);
|
o[e] = mazeAsset.scene.getObjectByName(e);
|
||||||
//o[e].frustumCulled = false;
|
//o[e].frustumCulled = false;
|
||||||
|
|||||||
@@ -18,47 +18,46 @@ const tl = 4;
|
|||||||
|
|
||||||
class MazeQuizGame {
|
class MazeQuizGame {
|
||||||
constructor(engine, data) {
|
constructor(engine, data) {
|
||||||
let questions = data.shuffle ? Utils.shuffleArray(data.questions) : data.questions;
|
return new Promise(async (resolve, reject)=>{
|
||||||
let def = this.generate(questions);
|
let questions = data.shuffle ? Utils.shuffleArray(data.questions) : data.questions;
|
||||||
this.mazeObject = new MazeObject(engine, def)
|
let def = this.generate(questions);
|
||||||
engine.addEventListener('collision', async e=>{
|
this.mazeObject = new MazeObject(engine, def)
|
||||||
let ud1 = engine.physics.world.getCollider(e.handle1)?.parent()?.userData,
|
engine.addEventListener('collision', async e=>{
|
||||||
ud2 = engine.physics.world.getCollider(e.handle2)?.parent()?.userData;
|
let ud1 = engine.physics.world.getCollider(e.handle1)?.parent()?.userData,
|
||||||
let ud = {...ud1, ...ud2}
|
ud2 = engine.physics.world.getCollider(e.handle2)?.parent()?.userData;
|
||||||
if (ud?.finish){
|
let ud = {...ud1, ...ud2}
|
||||||
if (e.started){
|
if (ud?.finish){
|
||||||
engine.dashboard.updateProgress(1)
|
if (e.started){
|
||||||
engine.hero.animationsMap._idle = engine.hero.animationsMap.idle
|
engine.dashboard.updateProgress(1)
|
||||||
if ( engine.hero.animationsMap?.win){
|
engine.hero.animationsMap._idle = engine.hero.animationsMap.idle
|
||||||
engine.hero.animationsMap.idle = engine.hero.animationsMap.win
|
if ( engine.hero.animationsMap?.win){
|
||||||
|
engine.hero.animationsMap.idle = engine.hero.animationsMap.win
|
||||||
|
}
|
||||||
|
await Utils.wait(1000);
|
||||||
|
engine.hero.characterControls.cameraDelta = Math.PI;
|
||||||
|
engine.hero.characterControls.direction += Math.PI;
|
||||||
|
//engine.hero.model.rotation.y += Math.PI;
|
||||||
|
await Utils.wait(10000);
|
||||||
|
this.onfinish?.()
|
||||||
|
}else{
|
||||||
|
engine.hero.animationsMap.idle = engine.hero.animationsMap._idle
|
||||||
|
engine.hero.characterControls.cameraDelta = 0
|
||||||
}
|
}
|
||||||
await Utils.wait(1000);
|
|
||||||
engine.hero.characterControls.cameraDelta = Math.PI;
|
|
||||||
engine.hero.characterControls.direction += Math.PI;
|
|
||||||
//engine.hero.model.rotation.y += Math.PI;
|
|
||||||
await Utils.wait(10000);
|
|
||||||
this.onfinish?.()
|
|
||||||
}else{
|
|
||||||
engine.hero.animationsMap.idle = engine.hero.animationsMap._idle
|
|
||||||
engine.hero.characterControls.cameraDelta = 0
|
|
||||||
}
|
}
|
||||||
}
|
if (ud.qid !== undefined && e.started){
|
||||||
if (ud.qid !== undefined && e.started){
|
engine.dashboard.update({
|
||||||
engine.dashboard.update({
|
hint: ud.question.q
|
||||||
hint: ud.question.q
|
})
|
||||||
})
|
engine.dashboard.updateProgress(ud.qid / questions.length)
|
||||||
engine.dashboard.updateProgress(ud.qid / questions.length)
|
}
|
||||||
}
|
//console.log(e, ud, engine.hero?.animationsMap);
|
||||||
//console.log(e, ud, engine.hero?.animationsMap);
|
})
|
||||||
|
await this.mazeObject.load();
|
||||||
|
this.object = this.mazeObject.object;
|
||||||
|
resolve(this)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async load(){
|
|
||||||
await this.mazeObject.load();
|
|
||||||
this.object = this.mazeObject.object;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
generate(questions, qid = 0, len){
|
generate(questions, qid = 0, len){
|
||||||
let question = questions[qid]
|
let question = questions[qid]
|
||||||
if (!question) return {
|
if (!question) return {
|
||||||
|
|||||||
@@ -1,95 +1,99 @@
|
|||||||
import { BoxGeometry, Mesh, MeshBasicMaterial, Group } from 'three';
|
import { BoxGeometry, Mesh, MeshBasicMaterial, Group } from 'three';
|
||||||
import { TextureLoader } from 'three/src/loaders/TextureLoader';
|
|
||||||
import { MotionEngine } from '../../lib/MotionEngine';
|
import { MotionEngine } from '../../lib/MotionEngine';
|
||||||
|
|
||||||
class PuzzleGame1 {
|
class PuzzleGame1 {
|
||||||
constructor(context, image, w, h) {
|
constructor(engine, data) {
|
||||||
this.object = new Group();
|
return new Promise(async (resolve, reject)=>{
|
||||||
const aq = new MotionEngine();
|
let w = data.w, h = data.h, wh = w*h;
|
||||||
const pr = [[0, -1], [0, 1], [1, 0], [-1, 0], [0, 0], [0, 2]];
|
this.object = new Group();
|
||||||
let d = 1.2;
|
const aq = new MotionEngine();
|
||||||
|
const pr = [[0, -1], [0, 1], [1, 0], [-1, 0], [0, 0], [0, 2]];
|
||||||
|
let d = 1.2;
|
||||||
|
|
||||||
let bm = new BoxGeometry(1, 1, 1);
|
let bm = new BoxGeometry(1, 1, 1);
|
||||||
let uv = bm.getAttribute('uv');
|
let uv = bm.getAttribute('uv');
|
||||||
|
|
||||||
for (let i = 0; i < 6; i++) {
|
for (let i = 0; i < wh; i++) {
|
||||||
let s = [(i % w) / w, (i % h) / h];
|
let s = [(i % w) / w, Math.trunc(i / w) / h];
|
||||||
//top left
|
//top left
|
||||||
uv.array[8 * i] = s[0];
|
uv.array[8 * i] = s[0];
|
||||||
uv.array[8 * i + 1] = s[1] + 1 / h;
|
uv.array[8 * i + 1] = s[1] + 1 / h;
|
||||||
//top right
|
//top right
|
||||||
uv.array[8 * i + 2] = s[0] + 1 / w;
|
uv.array[8 * i + 2] = s[0] + 1 / w;
|
||||||
uv.array[8 * i + 3] = s[1] + 1 / h;
|
uv.array[8 * i + 3] = s[1] + 1 / h;
|
||||||
//bottom left
|
//bottom left
|
||||||
uv.array[8 * i + 4] = s[0];
|
uv.array[8 * i + 4] = s[0];
|
||||||
uv.array[8 * i + 5] = s[1];
|
uv.array[8 * i + 5] = s[1];
|
||||||
//bottom right
|
//bottom right
|
||||||
uv.array[8 * i + 6] = s[0] + 1 / w;
|
uv.array[8 * i + 6] = s[0] + 1 / w;
|
||||||
uv.array[8 * i + 7] = s[1];
|
uv.array[8 * i + 7] = s[1];
|
||||||
}
|
|
||||||
|
|
||||||
let material = new MeshBasicMaterial({
|
|
||||||
map: new TextureLoader().load(image)
|
|
||||||
});
|
|
||||||
//material.map.encoding = sRGBEncoding;
|
|
||||||
|
|
||||||
for (let i = 0; i < 6; i++) {
|
|
||||||
let b = bm.clone();
|
|
||||||
let mesh = new Mesh(b, material);
|
|
||||||
mesh.position.set((i % w) * d, (i % h) * d, 0);
|
|
||||||
let ri;
|
|
||||||
do {
|
|
||||||
ri = Math.floor(Math.random() * 6);
|
|
||||||
} while (ri == this.object.children.length);
|
|
||||||
mesh.rotation.set(pr[ri][0] * Math.PI / 2, pr[ri][1] * Math.PI / 2, 0);
|
|
||||||
mesh._ri = ri;
|
|
||||||
this.object.add(mesh);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.object.children[0].onBeforeRender = () => {
|
|
||||||
this.update();
|
|
||||||
};
|
|
||||||
|
|
||||||
var check = () => {
|
|
||||||
if (!this.object.children.length) return false;
|
|
||||||
let i = 0;
|
|
||||||
for (let c of this.object.children) {
|
|
||||||
if (Math.abs(c.rotation.x - pr[i][0] * Math.PI / 2) > 0.0001 || Math.abs(c.rotation.y - pr[i][1] * Math.PI / 2) > 0.0001) return false;
|
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
let clickFn = (i) => {
|
let material = new MeshBasicMaterial({
|
||||||
if (!this.done && !aq.isActive(i.object)) {
|
map: await engine.loadTexture(data.$go.asset.name)
|
||||||
i.object._ri = (i.object._ri + 1) % 6;
|
});
|
||||||
aq.add({
|
//material.map.encoding = sRGBEncoding;
|
||||||
o: i.object,
|
|
||||||
a: { rotation: { x: pr[i.object._ri][0] * Math.PI / 2, y: pr[i.object._ri][1] * Math.PI / 2 } },
|
for (let i = 0; i < wh; i++) {
|
||||||
t: .5
|
let b = bm.clone();
|
||||||
});
|
let mesh = new Mesh(b, material);
|
||||||
|
mesh.position.set((i % w) * d, (Math.trunc(i / w)) * d, 0);
|
||||||
|
let ri;
|
||||||
|
do {
|
||||||
|
ri = Math.floor(Math.random() * 6);
|
||||||
|
} while (ri == this.object.children.length);
|
||||||
|
mesh.rotation.set(pr[ri][0] * Math.PI / 2, pr[ri][1] * Math.PI / 2, 0);
|
||||||
|
mesh._ri = ri;
|
||||||
|
this.object.add(mesh);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
this.object.children.forEach(c => {
|
this.object.children[0].onBeforeRender = () => {
|
||||||
context.clickable.add(c, clickFn);
|
this.update();
|
||||||
});
|
};
|
||||||
|
|
||||||
this.update = () => {
|
var check = () => {
|
||||||
aq.update();
|
if (!this.object.children.length) return false;
|
||||||
if (aq.isIdle() && !this.done && check()) {
|
let i = 0;
|
||||||
this.done = true;
|
for (let c of this.object.children) {
|
||||||
this.object.children.forEach((c, i) => {
|
if (Math.abs(c.rotation.x - pr[i][0] * Math.PI / 2) > 0.0001 || Math.abs(c.rotation.y - pr[i][1] * Math.PI / 2) > 0.0001) return false;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
let clickFn = (i) => {
|
||||||
|
if (!this.done && !aq.isActive(i.object)) {
|
||||||
|
i.object._ri = (i.object._ri + 1) % 6;
|
||||||
aq.add({
|
aq.add({
|
||||||
o: c,
|
o: i.object,
|
||||||
a: { position: { x: i % w, y: i % h } },
|
a: { rotation: { x: pr[i.object._ri][0] * Math.PI / 2, y: pr[i.object._ri][1] * Math.PI / 2 } },
|
||||||
t: 1,
|
t: .5
|
||||||
f: i == 0 && this.onfinish
|
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
//context.dashboard.addPoints(10);
|
};
|
||||||
}
|
|
||||||
};
|
this.object.children.forEach(c => {
|
||||||
|
engine.clickable.add(c, clickFn);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.update = () => {
|
||||||
|
aq.update();
|
||||||
|
if (aq.isIdle() && !this.done && check()) {
|
||||||
|
this.done = true;
|
||||||
|
this.object.children.forEach((c, i) => {
|
||||||
|
aq.add({
|
||||||
|
o: c,
|
||||||
|
a: { position: { x: i % w, y: Math.trunc(i/w)} },
|
||||||
|
t: 1,
|
||||||
|
f: i == 0 && this.onfinish
|
||||||
|
});
|
||||||
|
});
|
||||||
|
//engine.dashboard.addPoints(10);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
resolve(this);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,40 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<v-card v-if="modelValue.go">
|
||||||
|
<v-card-item>
|
||||||
|
<v-number-input density="compact" label="Width" v-model="modelValue.w"></v-number-input>
|
||||||
|
<v-number-input density="compact" label="Height" v-model="modelValue.h"></v-number-input>
|
||||||
|
<v-img :src="`/asset/thumb/${modelValue.go}.webp`" />
|
||||||
|
<div class="text-caption text-center">{{ modelValue.title }}</div>
|
||||||
|
</v-card-item>
|
||||||
|
</v-card>
|
||||||
|
<asset-selector @select="assignTexture" :type="['Texture']">
|
||||||
|
<template v-slot:activator="props">
|
||||||
|
<v-btn v-bind="props" prepend-icon="mdi-video-box" color="deep-orange-darken-4" block>Choose image object</v-btn>
|
||||||
|
</template>
|
||||||
|
</asset-selector>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
data(){
|
||||||
|
return {
|
||||||
|
active: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted(){
|
||||||
|
this.active = true;
|
||||||
|
},
|
||||||
|
props:{
|
||||||
|
modelValue: Object
|
||||||
|
},
|
||||||
|
methods:{
|
||||||
|
assignTexture(e){
|
||||||
|
this.modelValue.go = e.id;
|
||||||
|
this.modelValue.title = e.name
|
||||||
|
this.modelValue.w = 2;
|
||||||
|
this.modelValue.h = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -1,145 +1,147 @@
|
|||||||
import { BoxGeometry, Mesh, MeshBasicMaterial, Group } from 'three';
|
import { BoxGeometry, Mesh, MeshBasicMaterial, Group } from 'three';
|
||||||
import { TextureLoader } from 'three/src/loaders/TextureLoader';
|
|
||||||
import { MotionEngine } from '../../lib/MotionEngine';
|
import { MotionEngine } from '../../lib/MotionEngine';
|
||||||
|
|
||||||
class PuzzleGame2 {
|
class PuzzleGame2 {
|
||||||
constructor(context, image, w, h) {
|
constructor(engine, data) {
|
||||||
const texture = new TextureLoader().load(image);
|
return new Promise(async (resolve, reject)=>{
|
||||||
//texture.encoding = sRGBEncoding;
|
let w = data.w, h = data.h, wh = w*h;
|
||||||
const material = new MeshBasicMaterial({
|
const texture = await engine.loadTexture(data.$go.asset.name);
|
||||||
map: texture
|
//texture.encoding = sRGBEncoding;
|
||||||
});
|
const material = new MeshBasicMaterial({
|
||||||
const aq = new MotionEngine();
|
map: texture
|
||||||
const m2 = new MeshBasicMaterial({
|
|
||||||
map: texture,
|
|
||||||
transparent: true,
|
|
||||||
opacity: 0.37
|
|
||||||
});
|
|
||||||
let last, lidx = w - 1;
|
|
||||||
|
|
||||||
this.object = new Group();
|
|
||||||
let d = 1.2, p = [];
|
|
||||||
|
|
||||||
function check() {
|
|
||||||
if (p.length) {
|
|
||||||
for (let i = 0; i < p.length; i++) {
|
|
||||||
if (p[i] != i) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function xch(x, y) {
|
|
||||||
let temp = p[x];
|
|
||||||
p[x] = p[y];
|
|
||||||
p[y] = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.shuffle = function () {
|
|
||||||
function getMoves() {
|
|
||||||
let m = [], pl = p[lidx];
|
|
||||||
let xl = pl % w, yl = ~~(pl / h);
|
|
||||||
if (xl > 0) m.push(p.indexOf(pl - 1));
|
|
||||||
if (xl < w - 1) m.push(p.indexOf(pl + 1));
|
|
||||||
if (yl > 0) m.push(p.indexOf(pl - w));
|
|
||||||
if (yl < h - 1) m.push(p.indexOf(pl + w));
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
for (let i = 0; i < w * h; i++) {
|
|
||||||
p[i] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let iter = 0; iter < 73 * w * h; iter++) {
|
|
||||||
let m = getMoves();
|
|
||||||
xch(m[Math.floor(Math.random() * m.length)], lidx);
|
|
||||||
}
|
|
||||||
// while (p.length<9){
|
|
||||||
// let n = Math.floor(Math.random()*9);
|
|
||||||
// if (p.indexOf(n) == -1) p.push(n);
|
|
||||||
// }
|
|
||||||
p.forEach((e, i) => {
|
|
||||||
let x = e % w, y = ~~(e / h);
|
|
||||||
this.object.children[i].position.set(x * d, y * d, 0);
|
|
||||||
});
|
});
|
||||||
};
|
const aq = new MotionEngine();
|
||||||
|
const m2 = new MeshBasicMaterial({
|
||||||
|
map: texture,
|
||||||
|
transparent: true,
|
||||||
|
opacity: 0.37
|
||||||
|
});
|
||||||
|
let last, lidx = w - 1;
|
||||||
|
|
||||||
for (let i = 0; i < w * h; i++) {
|
this.object = new Group();
|
||||||
let x = i % w, xp = x / w;
|
let d = 1.2, p = [];
|
||||||
let y = ~~(i / h), yp = y / h;
|
|
||||||
let bg = new BoxGeometry(1, 1, 1);
|
|
||||||
let uv = bg.getAttribute('uv');
|
|
||||||
for (let k = 0; k < 6; k++) {
|
|
||||||
//top left
|
|
||||||
uv.array[8 * k] = xp;
|
|
||||||
uv.array[8 * k + 1] = yp + 1 / h;
|
|
||||||
//top right
|
|
||||||
uv.array[8 * k + 2] = xp + 1 / w;
|
|
||||||
uv.array[8 * k + 3] = yp + 1 / h;
|
|
||||||
//bottom left
|
|
||||||
uv.array[8 * k + 4] = xp;
|
|
||||||
uv.array[8 * k + 5] = yp;
|
|
||||||
//bottom right
|
|
||||||
uv.array[8 * k + 6] = xp + 1 / w;
|
|
||||||
uv.array[8 * k + 7] = yp;
|
|
||||||
}
|
|
||||||
let mesh = new Mesh(bg, i != lidx ? material : m2);
|
|
||||||
mesh.position.set(x * d, y * d, 0);
|
|
||||||
this.object.add(mesh);
|
|
||||||
}
|
|
||||||
last = this.object.children[lidx];
|
|
||||||
|
|
||||||
this.object.children[0].onBeforeRender = () => {
|
function check() {
|
||||||
this.update();
|
if (p.length) {
|
||||||
};
|
for (let i = 0; i < p.length; i++) {
|
||||||
|
if (p[i] != i) return false;
|
||||||
this.shuffle();
|
}
|
||||||
|
return true;
|
||||||
let clickFn = (i) => {
|
|
||||||
if (!this.done && !aq.isActive(i.object)) {
|
|
||||||
let idx = this.object.children.indexOf(i.object);
|
|
||||||
if (idx == lidx) return; //we ignore the empty cell
|
|
||||||
let xc = p[idx] % w, yc = ~~(p[idx] / h);
|
|
||||||
let xl = p[lidx] % w, yl = ~~(p[lidx] / h);
|
|
||||||
if (Math.abs(xc - xl) + Math.abs(yc - yl) == 1) {
|
|
||||||
aq.add({
|
|
||||||
o: i.object,
|
|
||||||
a: { position: { x: (xl - xc) * d, y: (yl - yc) * d } },
|
|
||||||
t: .3,
|
|
||||||
m: 'offset'
|
|
||||||
});
|
|
||||||
aq.add({
|
|
||||||
o: last,
|
|
||||||
a: { position: { x: (xc - xl) * d, y: (yc - yl) * d } },
|
|
||||||
t: .3,
|
|
||||||
m: 'offset'
|
|
||||||
});
|
|
||||||
xch(idx, lidx);
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
this.object.children.forEach(c => {
|
function xch(x, y) {
|
||||||
context.clickable.add(c, clickFn);
|
let temp = p[x];
|
||||||
});
|
p[x] = p[y];
|
||||||
|
p[y] = temp;
|
||||||
|
}
|
||||||
|
|
||||||
this.update = () => {
|
this.shuffle = function () {
|
||||||
aq.update();
|
function getMoves() {
|
||||||
if (aq.isIdle() && !this.done && check()) {
|
let m = [], pl = p[lidx];
|
||||||
this.done = true;
|
let xl = pl % w, yl = ~~(pl / h);
|
||||||
this.object.children.forEach((c, i) => {
|
if (xl > 0) m.push(p.indexOf(pl - 1));
|
||||||
last.material = material;
|
if (xl < w - 1) m.push(p.indexOf(pl + 1));
|
||||||
aq.add({
|
if (yl > 0) m.push(p.indexOf(pl - w));
|
||||||
o: c,
|
if (yl < h - 1) m.push(p.indexOf(pl + w));
|
||||||
a: { position: { x: i % w, y: ~~(i / h) } },
|
return m;
|
||||||
t: 1,
|
}
|
||||||
f: i == 0 && this.onfinish
|
for (let i = 0; i < wh; i++) {
|
||||||
});
|
p[i] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let iter = 0; iter < 73 * wh; iter++) {
|
||||||
|
let m = getMoves();
|
||||||
|
xch(m[Math.floor(Math.random() * m.length)], lidx);
|
||||||
|
}
|
||||||
|
// while (p.length<9){
|
||||||
|
// let n = Math.floor(Math.random()*9);
|
||||||
|
// if (p.indexOf(n) == -1) p.push(n);
|
||||||
|
// }
|
||||||
|
p.forEach((e, i) => {
|
||||||
|
let x = e % w, y = ~~(e / h);
|
||||||
|
this.object.children[i].position.set(x * d, y * d, 0);
|
||||||
});
|
});
|
||||||
//context.dashboard.addPoints(10);
|
};
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
for (let i = 0; i < wh; i++) {
|
||||||
|
let x = i % w, xp = x / w;
|
||||||
|
let y = ~~(i / h), yp = y / h;
|
||||||
|
let bg = new BoxGeometry(1, 1, 1);
|
||||||
|
let uv = bg.getAttribute('uv');
|
||||||
|
for (let k = 0; k < 6; k++) {
|
||||||
|
//top left
|
||||||
|
uv.array[8 * k] = xp;
|
||||||
|
uv.array[8 * k + 1] = yp + 1 / h;
|
||||||
|
//top right
|
||||||
|
uv.array[8 * k + 2] = xp + 1 / w;
|
||||||
|
uv.array[8 * k + 3] = yp + 1 / h;
|
||||||
|
//bottom left
|
||||||
|
uv.array[8 * k + 4] = xp;
|
||||||
|
uv.array[8 * k + 5] = yp;
|
||||||
|
//bottom right
|
||||||
|
uv.array[8 * k + 6] = xp + 1 / w;
|
||||||
|
uv.array[8 * k + 7] = yp;
|
||||||
|
}
|
||||||
|
let mesh = new Mesh(bg, i != lidx ? material : m2);
|
||||||
|
mesh.position.set(x * d, y * d, 0);
|
||||||
|
this.object.add(mesh);
|
||||||
|
}
|
||||||
|
last = this.object.children[lidx];
|
||||||
|
|
||||||
|
this.object.children[0].onBeforeRender = () => {
|
||||||
|
this.update();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.shuffle();
|
||||||
|
|
||||||
|
let clickFn = (i) => {
|
||||||
|
if (!this.done && !aq.isActive(i.object)) {
|
||||||
|
let idx = this.object.children.indexOf(i.object);
|
||||||
|
if (idx == lidx) return; //we ignore the empty cell
|
||||||
|
let xc = p[idx] % w, yc = ~~(p[idx] / h);
|
||||||
|
let xl = p[lidx] % w, yl = ~~(p[lidx] / h);
|
||||||
|
if (Math.abs(xc - xl) + Math.abs(yc - yl) == 1) {
|
||||||
|
aq.add({
|
||||||
|
o: i.object,
|
||||||
|
a: { position: { x: (xl - xc) * d, y: (yl - yc) * d } },
|
||||||
|
t: .3,
|
||||||
|
m: 'offset'
|
||||||
|
});
|
||||||
|
aq.add({
|
||||||
|
o: last,
|
||||||
|
a: { position: { x: (xc - xl) * d, y: (yc - yl) * d } },
|
||||||
|
t: .3,
|
||||||
|
m: 'offset'
|
||||||
|
});
|
||||||
|
xch(idx, lidx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.object.children.forEach(c => {
|
||||||
|
engine.clickable.add(c, clickFn);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.update = () => {
|
||||||
|
aq.update();
|
||||||
|
if (aq.isIdle() && !this.done && check()) {
|
||||||
|
this.done = true;
|
||||||
|
this.object.children.forEach((c, i) => {
|
||||||
|
last.material = material;
|
||||||
|
aq.add({
|
||||||
|
o: c,
|
||||||
|
a: { position: { x: i % w, y: ~~(i / h) } },
|
||||||
|
t: 1,
|
||||||
|
f: i == 0 && this.onfinish
|
||||||
|
});
|
||||||
|
});
|
||||||
|
//engine.dashboard.addPoints(10);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
resolve(this)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
<template>
|
||||||
|
<v-card v-if="modelValue.go">
|
||||||
|
<v-card-item>
|
||||||
|
<v-number-input density="compact" label="Width" v-model="modelValue.w"></v-number-input>
|
||||||
|
<v-number-input density="compact" label="Height" v-model="modelValue.h"></v-number-input>
|
||||||
|
<v-img :src="`/asset/thumb/${modelValue.go}.webp`" />
|
||||||
|
<div class="text-caption text-center">{{ modelValue.title }}</div>
|
||||||
|
</v-card-item>
|
||||||
|
</v-card>
|
||||||
|
<asset-selector @select="assignTexture" :type="['Texture']">
|
||||||
|
<template v-slot:activator="props">
|
||||||
|
<v-btn v-bind="props" prepend-icon="mdi-video-box" color="deep-orange-darken-4" block>Choose image object</v-btn>
|
||||||
|
</template>
|
||||||
|
</asset-selector>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data(){
|
||||||
|
return {
|
||||||
|
active: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted(){
|
||||||
|
this.active = true;
|
||||||
|
},
|
||||||
|
props:{
|
||||||
|
modelValue: Object
|
||||||
|
},
|
||||||
|
methods:{
|
||||||
|
assignTexture(e){
|
||||||
|
this.modelValue.go = e.id;
|
||||||
|
this.modelValue.title = e.name
|
||||||
|
this.modelValue.w = 3;
|
||||||
|
this.modelValue.h = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -34,12 +34,13 @@ import Utils from '@/lib/Utils';
|
|||||||
|
|
||||||
import VideoPlayer from '../InteractiveObjects/VideoPlayer.vue';
|
import VideoPlayer from '../InteractiveObjects/VideoPlayer.vue';
|
||||||
import PuzzleGame1 from '../InteractiveObjects/PuzzleGame1.vue';
|
import PuzzleGame1 from '../InteractiveObjects/PuzzleGame1.vue';
|
||||||
|
import PuzzleGame2 from '../InteractiveObjects/PuzzleGame2.vue';
|
||||||
import MazeQuizGame from '../InteractiveObjects/MazeQuizGame/MazeQuizGame.vue';
|
import MazeQuizGame from '../InteractiveObjects/MazeQuizGame/MazeQuizGame.vue';
|
||||||
import GenericObject from '../InteractiveObjects/GenericObject.vue';
|
import GenericObject from '../InteractiveObjects/GenericObject.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
emits:['target', 'preview'],
|
emits:['target', 'preview'],
|
||||||
components: { SvgIcon, VideoPlayer, PuzzleGame1, MazeQuizGame, GenericObject },
|
components: { SvgIcon, VideoPlayer, PuzzleGame1, PuzzleGame2, MazeQuizGame, GenericObject },
|
||||||
data(){
|
data(){
|
||||||
return {
|
return {
|
||||||
active: false
|
active: false
|
||||||
|
|||||||
+11
-8
@@ -16,6 +16,8 @@ import { Clickable } from './Clickable.js';
|
|||||||
import { DashBoard } from './Dashboard.js';
|
import { DashBoard } from './Dashboard.js';
|
||||||
import { MotionEngine } from './MotionEngine.js';
|
import { MotionEngine } from './MotionEngine.js';
|
||||||
|
|
||||||
|
const assetPath = '/asset/default/';
|
||||||
|
|
||||||
class GameEngine extends THREE.EventDispatcher{
|
class GameEngine extends THREE.EventDispatcher{
|
||||||
async init(domNode, opts = {}) {
|
async init(domNode, opts = {}) {
|
||||||
this.w = domNode.clientWidth || 1200, this.h = domNode.clientHeight || 800;
|
this.w = domNode.clientWidth || 1200, this.h = domNode.clientHeight || 800;
|
||||||
@@ -101,6 +103,7 @@ class GameEngine extends THREE.EventDispatcher{
|
|||||||
this.dashboard = dashboard;
|
this.dashboard = dashboard;
|
||||||
|
|
||||||
this.motionQueue = new MotionEngine();
|
this.motionQueue = new MotionEngine();
|
||||||
|
this.assetPath = assetPath;
|
||||||
|
|
||||||
this.activeObjects = new THREE.Group();
|
this.activeObjects = new THREE.Group();
|
||||||
scene.add(this.activeObjects);
|
scene.add(this.activeObjects);
|
||||||
@@ -158,7 +161,7 @@ class GameEngine extends THREE.EventDispatcher{
|
|||||||
|
|
||||||
domNode.appendChild(renderer.domElement);
|
domNode.appendChild(renderer.domElement);
|
||||||
|
|
||||||
let texture = await this.loadTexture('/static/textures/bck.webp');
|
let texture = await this.loadTexture('/static/textures/bck.webp', '');
|
||||||
// let bck = await this.loadTexture('/static/textures/bck.webp');
|
// let bck = await this.loadTexture('/static/textures/bck.webp');
|
||||||
// bck.premultiplyAlpha = true;
|
// bck.premultiplyAlpha = true;
|
||||||
texture.mapping = THREE.EquirectangularReflectionMapping;
|
texture.mapping = THREE.EquirectangularReflectionMapping;
|
||||||
@@ -383,12 +386,12 @@ class GameEngine extends THREE.EventDispatcher{
|
|||||||
|
|
||||||
$ = THREE;
|
$ = THREE;
|
||||||
|
|
||||||
async load(url, progress) {
|
async load(url, path = assetPath, progress) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
this.loader.load(url, o => {
|
this.loader.load(`${path}${url}`, o => {
|
||||||
o.scene.traverse(object => {
|
o.scene.traverse(object => {
|
||||||
if (object.name == 'environment' || object.material){
|
if (object.name == 'environment' || object.material){
|
||||||
console.log('env recomputing')
|
//console.log('env recomputing')
|
||||||
object.material.shading = THREE.SmoothShading;
|
object.material.shading = THREE.SmoothShading;
|
||||||
object.geometry.computeVertexNormals(true);
|
object.geometry.computeVertexNormals(true);
|
||||||
//object.material.metalness = 0;
|
//object.material.metalness = 0;
|
||||||
@@ -408,9 +411,9 @@ class GameEngine extends THREE.EventDispatcher{
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadTexture(url, progress) {
|
async loadTexture(url, path = assetPath, progress) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
new THREE.TextureLoader().load(url, texture => {
|
new THREE.TextureLoader().load(`${path}${url}`, texture => {
|
||||||
//texture.encoding = THREE.sRGBEncoding;
|
//texture.encoding = THREE.sRGBEncoding;
|
||||||
texture.colorSpace = THREE.SRGBColorSpace;
|
texture.colorSpace = THREE.SRGBColorSpace;
|
||||||
resolve(texture)
|
resolve(texture)
|
||||||
@@ -418,8 +421,8 @@ class GameEngine extends THREE.EventDispatcher{
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadPanorama(url) {
|
async loadPanorama(url, path = assetPath) {
|
||||||
let t = await this.loadTexture(url);
|
let t = await this.loadTexture(url, path);
|
||||||
t.mapping = THREE.EquirectangularReflectionMapping;
|
t.mapping = THREE.EquirectangularReflectionMapping;
|
||||||
this.scene.background = t;
|
this.scene.background = t;
|
||||||
this.scene.environment = t;
|
this.scene.environment = t;
|
||||||
|
|||||||
@@ -102,13 +102,7 @@ export default {
|
|||||||
})
|
})
|
||||||
|
|
||||||
for (let i of scene.data.items || []) {
|
for (let i of scene.data.items || []) {
|
||||||
if (i.data.io){
|
promises.push(this.$api.gameObject.load(i.data.go).then(r=>i.data.$go = r.data));
|
||||||
if (i.data.io.go){
|
|
||||||
promises.push(this.$api.gameObject.load(i.data.io.go).then(r=>i.data.io.$go = r.data));
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
promises.push(this.$api.gameObject.load(i.data.go).then(r=>i.data.$go = r.data));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
},
|
},
|
||||||
@@ -128,10 +122,10 @@ export default {
|
|||||||
target.objects = target.objects || {};
|
target.objects = target.objects || {};
|
||||||
let l = target.objects;
|
let l = target.objects;
|
||||||
if (this.scene.data.$environment){
|
if (this.scene.data.$environment){
|
||||||
await gameEngine.loadPanorama(`/asset/default/${this.scene.data.$environment.asset.name}`);
|
await gameEngine.loadPanorama(this.scene.data.$environment.asset.name);
|
||||||
}
|
}
|
||||||
if (this.scene.data.$scene){
|
if (this.scene.data.$scene){
|
||||||
let env = await gameEngine.load(`/asset/default/${this.scene.data.$scene.asset.name}`);
|
let env = await gameEngine.load(this.scene.data.$scene.asset.name);
|
||||||
//console.log('ENV', env)
|
//console.log('ENV', env)
|
||||||
this.setObjectAttributes(l, this.scene.data, env.scene, env, 100);
|
this.setObjectAttributes(l, this.scene.data, env.scene, env, 100);
|
||||||
gameEngine.activeObjects.add(env.scene);
|
gameEngine.activeObjects.add(env.scene);
|
||||||
@@ -193,7 +187,7 @@ export default {
|
|||||||
['position', 'scale', 'rotation'].forEach(p=>{
|
['position', 'scale', 'rotation'].forEach(p=>{
|
||||||
object[p].copy(l[data.id][p])
|
object[p].copy(l[data.id][p])
|
||||||
})
|
})
|
||||||
}else{
|
}else if (!data.type || data.type == 'GenericObject'){
|
||||||
gameEngine.autoScale(object, autoScaleFactor);
|
gameEngine.autoScale(object, autoScaleFactor);
|
||||||
}
|
}
|
||||||
l[data.id] = l[data.id] || {};
|
l[data.id] = l[data.id] || {};
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export default {
|
|||||||
}, {
|
}, {
|
||||||
value: 'object2d',
|
value: 'object2d',
|
||||||
icon: 'file-image-outline',
|
icon: 'file-image-outline',
|
||||||
type: 'Descriptive',
|
type: 'Texture',
|
||||||
color: 'cyan-darken-3'
|
color: 'cyan-darken-3'
|
||||||
}, {
|
}, {
|
||||||
value: 'player3d',
|
value: 'player3d',
|
||||||
|
|||||||
Reference in New Issue
Block a user