add physics to interactive objects

This commit is contained in:
2025-11-08 17:08:51 +02:00
parent 168fb5b770
commit f5a08a9702
10 changed files with 67 additions and 36 deletions
@@ -20,6 +20,7 @@
<script>
import { GameEngine } from '@/lib/GameEngine.js';
import { autoScale } from '@/lib/MeshUtils';
let gameEngine = null;
export default{
@@ -75,7 +76,7 @@ export default{
this.animations = gltf.animations.map(a => ({
name: a.name, id: a.uuid
}));
gameEngine.autoScale(gltf.scene);
autoScale(gltf.scene);
let bb = new gameEngine.$.Box3().setFromObject(gltf.scene);
gltf.scene.traverse(function (o) {
o.frustumCulled = false;
@@ -1,10 +1,10 @@
import { getBoundingBox, getBoundingBoxCenterPoint, getBoundingBoxMaxLength } from "@/lib/MeshUtils";
import { getBoundingBox, getBoundingBoxCenterPoint, getBoundingBoxMaxLength, centerOrigin } from "@/lib/MeshUtils";
class GenericObject{
constructor(engine, data){
return new Promise(async(resolve, reject)=>{
this.source = await engine.load(data.$go.asset.name);
this.object = this.source.scene;
this.object = centerOrigin(this.source.scene)
if (!data.exclude){
engine.clickable.add(this.object, async e=>{
@@ -3,6 +3,7 @@
<v-textarea :label="l.description" v-model="modelValue.description"></v-textarea>
<v-checkbox density="compact" v-model="modelValue.hud" hide-details label="Observe in head-up display"></v-checkbox>
<v-checkbox density="compact" v-model="modelValue.exclude" hide-details label="Disable interactions"></v-checkbox>
<v-checkbox density="compact" v-model="modelValue.noPhysics" hide-details label="Disable physics"></v-checkbox>
<v-img :src="`/asset/thumb/${modelValue.go}.webp`" />
<div class="text-caption text-center">{{ modelValue.title }}</div>
</div>
@@ -41,6 +41,7 @@ export default {
props:['modelValue'],
mounted(){
this.modelValue.questions ??= [];
this.modelValue.noPhysics = true;
},
methods:{
addQuestion(){
@@ -43,6 +43,7 @@ export default {
this.modelValue.count = 1000;
this.modelValue.w = 50;
this.modelValue.h = 50;
this.modelValue.noPhysics = true;
}
}
}
@@ -1,11 +1,12 @@
import { BoxGeometry, Mesh, MeshBasicMaterial, Group } from 'three';
import { MotionEngine } from '../../lib/MotionEngine';
import { centerOrigin } from '@/lib/MeshUtils';
class PuzzleGame1 {
constructor(engine, data) {
return new Promise(async (resolve, reject)=>{
let w = data.w, h = data.h, wh = w*h;
this.object = new Group();
let container = new Group();
const aq = new MotionEngine();
const pr = [[0, 2], [0, -1], [0, 1], [1, 0], [-1, 0], [0, 0]];
let d = 1.2;
@@ -50,16 +51,16 @@ class PuzzleGame1 {
if (idxs[4] == idxs[5]){
mesh._dd = true;
}
this.object.add(mesh);
container.add(mesh);
}
this.object.children[0].onBeforeRender = () => {
container.children[0].onBeforeRender = () => {
this.update();
};
var check = () => {
let i = 0;
this.object.children.forEach(o=>{
container.children.forEach(o=>{
if (o._ri == 5 || o._dd && o._ri == 0) i++;
})
return i == wh;
@@ -76,7 +77,7 @@ class PuzzleGame1 {
}
};
this.object.children.forEach(c => {
container.children.forEach(c => {
engine.clickable.add(c, clickFn);
});
@@ -84,18 +85,20 @@ class PuzzleGame1 {
aq.update();
if (aq.isIdle() && !this.done && check()) {
this.done = true;
this.object.children.forEach((c, i) => {
container.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
f: i == 0 && this.onfinish || undefined
});
});
//engine.dashboard.addPoints(10);
}
};
this.object = centerOrigin(container);
resolve(this);
})
}
@@ -1,5 +1,6 @@
import { BoxGeometry, Mesh, MeshBasicMaterial, Group } from 'three';
import { MotionEngine } from '../../lib/MotionEngine';
import { centerOrigin } from '@/lib/MeshUtils';
class PuzzleGame2 {
constructor(engine, data) {
@@ -17,7 +18,7 @@ class PuzzleGame2 {
});
let last, lidx = w - 1;
this.object = new Group();
let container = new Group();
let d = 1.2, p = [];
function check() {
@@ -60,7 +61,7 @@ class PuzzleGame2 {
// }
p.forEach((e, i) => {
let x = e % w, y = ~~(e / h);
this.object.children[i].position.set(x * d, y * d, 0);
container.children[i].position.set(x * d, y * d, 0);
});
};
@@ -89,11 +90,11 @@ class PuzzleGame2 {
}
let mesh = new Mesh(bg, i != lidx ? material : m2);
mesh.position.set(x * d, y * d, 0);
this.object.add(mesh);
container.add(mesh);
}
last = this.object.children[lidx];
last = container.children[lidx];
this.object.children[0].onBeforeRender = () => {
container.children[0].onBeforeRender = () => {
this.update();
};
@@ -101,7 +102,7 @@ class PuzzleGame2 {
let clickFn = (i) => {
if (!this.done && !aq.isActive(i.object)) {
let idx = this.object.children.indexOf(i.object);
let idx = container.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);
@@ -122,7 +123,7 @@ class PuzzleGame2 {
}
};
this.object.children.forEach(c => {
container.children.forEach(c => {
engine.clickable.add(c, clickFn);
});
@@ -130,7 +131,7 @@ class PuzzleGame2 {
aq.update();
if (aq.isIdle() && !this.done && check()) {
this.done = true;
this.object.children.forEach((c, i) => {
container.children.forEach((c, i) => {
last.material = material;
aq.add({
o: c,
@@ -142,6 +143,7 @@ class PuzzleGame2 {
//engine.dashboard.addPoints(10);
}
};
this.object = centerOrigin(container)
resolve(this)
});
}