hud observation for generic game objects

This commit is contained in:
2025-11-07 12:48:36 +02:00
parent b972ab25f0
commit 48c7ea2e2a
7 changed files with 152 additions and 43 deletions
+88 -5
View File
@@ -1,4 +1,7 @@
import { PlaneGeometry, CylinderGeometry, CanvasTexture, Group, Mesh, MeshStandardMaterial, DoubleSide } from "three";
import {
PlaneGeometry, CylinderGeometry, CanvasTexture, Group,
Mesh, MeshStandardMaterial, MeshBasicMaterial, DoubleSide
} from "three";
import Utils from "./Utils";
class DashBoard {
constructor(engine) {
@@ -20,6 +23,7 @@ class DashBoard {
let texture = new CanvasTexture(canvas)
let updating = false;
let params = {}
let occupied = false;
img.addEventListener('load', function () {
ctx.drawImage(img, 0, 0, engine.w, engine.h);
@@ -28,18 +32,36 @@ class DashBoard {
updating = false;
})
const dash = new Group();
const dash = new Group(), hud = new Group(), hudTarget = new Group();
hud.visible = false;
let hudAnimation, hudPlane;
this.group = dash;
dash.add(hud);
hud.add(hudTarget)
dash.visible = false;
const dashGeometry = new PlaneGeometry(engine.aspect, 1);
const dashMesh = new Mesh(dashGeometry, new MeshStandardMaterial({
roughness: 0, metalness:0.1, transparent: true,
const dashMesh = new Mesh(dashGeometry, new MeshBasicMaterial({
transparent: true,
map: texture
}))
dash.add(dashMesh);
engine.scene.add(dash)
engine.scene.add(dash);
(async()=>{
hudPlane = new Mesh(
new PlaneGeometry(engine.aspect, 1),
new MeshBasicMaterial({
map: await engine.loadTexture('/static/textures/hud.png', ''),
opacity: 0.37,
transparent:true
})
);
hudPlane.position.z = -0.25;
hud.add(hudPlane)
})()
engine.addEventListener('beforeRender', ()=>{
dash.quaternion.copy(engine.camera.quaternion)
@@ -98,6 +120,67 @@ class DashBoard {
});
}
this.attach = (object, dashPlacement, rotate)=>{
hud.visible = true;
hudPlane.scale.set(0, .1, 1);
hudPlane.material.opacity = 0.5;
engine.motionQueue.add([{
o:hudPlane, a:{material:{opacity:0.73}}, t:.4, d:.8
},{
o:hudPlane, a:{scale:{x:1}}, t:.4
},{
o:hudPlane, a:{scale:{y:1}}, t:.4, d:.4,
}])
if (occupied) return false;
object._hud = {
parent: object.parent,
placement: {
position: object.position.clone(),
quaternion: object.quaternion.clone(),
scale: object.scale.clone()
}
}
hudTarget.attach(object);
occupied = true;
engine.motionQueue.add({
o: object,
a: dashPlacement || {
quaternion: { x:0, y:0, z:0, w:0 },
position: { x:0, y:0, z:0 },
scale: { x: 1, y:1, z:1 }
},
t: 1
})
if (rotate){
engine.motionQueue.add(hudAnimation = {
o: hudTarget,
a: {
rotation: { y: 2*Math.PI }
},
t: 4,
r: true,
d: 1
})
}
}
this.detach = object=>{
engine.motionQueue.remove(hudAnimation);
object._hud.parent.attach(object);
hud.rotation.y = 0;
hud.visible = false;
engine.motionQueue.add({
o: object,
a: object._hud.placement,
t: 1
});
delete object._hud;
occupied = false;
hudAnimation = null;
}
this.createProgressBar();
this.update();
}
-6
View File
@@ -485,12 +485,6 @@ class GameEngine extends THREE.EventDispatcher{
this.hero?.characterControls?.idleReset();
}
autoScale(object, mk = 1) {
let bb = new THREE.Box3().setFromObject(object);
let k = Math.max(bb.max.x - bb.min.x, bb.max.y - bb.min.y, bb.max.z - bb.min.z);
object.scale.multiplyScalar(mk / k);
}
setCamera(camera) {
//camera.updateProjectionMatrix();
this.camera = camera;
+25 -2
View File
@@ -1,4 +1,4 @@
import { TextureLoader } from "three";
import { TextureLoader, Box3, Vector3 } from "three";
function assignParams(mesh, params){
['scale', 'rotation', 'position'].forEach(p=>params[p] && mesh[p].fromArray(params[p]));
@@ -26,4 +26,27 @@ function assignMaterial(mesh, params){
}
}
export { assignParams, assignMaterial }
function getBoundingBox(object){
return new Box3().setFromObject(object);
}
function getBoundingBoxMaxLength(bb){
return Math.max(bb.max.x - bb.min.x, bb.max.y - bb.min.y, bb.max.z - bb.min.z)
}
function getBoundingBoxCenterPoint(bb, relativeTo){
relativeTo = relativeTo || new Vector3(0,0,0)
return new Vector3(
bb.min.x + (bb.max.x - bb.min.x)/2 - relativeTo.x,
bb.min.y + (bb.max.y - bb.min.y)/2 - relativeTo.y,
bb.min.z + (bb.max.z - bb.min.z)/2 - relativeTo.z
)
}
function autoScale(object, mk = 1) {
let bb = getBoundingBox(object);
let k = getBoundingBoxMaxLength(bb);
object.scale.multiplyScalar(mk / k);
}
export { assignParams, assignMaterial, autoScale, getBoundingBox, getBoundingBoxMaxLength, getBoundingBoxCenterPoint }
+8 -2
View File
@@ -26,6 +26,8 @@ class MotionEngine {
return target;
}
// a = {o-object, a-action, t-time, f-finish event, d-delay, m-mode, r-repeat,
// rd-repeat the delay, rf-reset on finish}
this.add = function (a) {
a = Array.isArray(a) ? a : [a];
a.forEach(e => {
@@ -35,7 +37,7 @@ class MotionEngine {
this.clear = function (object) {
for (var i = aq.length - 1; i >= 0; i--) {
if (object && aq[i].o == object || !object && aq[i].ct == aq[i].t) {
if (object && aq[i].o == object || !object && (aq[i].ct == aq[i].t || aq[i].rr)) {
aq.splice(i, 1);
}
}
@@ -75,7 +77,11 @@ class MotionEngine {
e.ct = e.ct + t;
if (e.ct > e.t) {
e.ct = e.t;
e.f && e.f();
e.f?.();
if (e.rf){
e.ct = t = 0;
e.rr = true;
}
}
calcValues(e.o, e.a, e.iv, e.ct / e.t, e.m || 'value');
if (e.ct == e.t && e.r) {