mini games

This commit is contained in:
2025-07-01 10:21:18 +03:00
parent 03281ee582
commit bc800182e2
10 changed files with 211 additions and 16 deletions
+45
View File
@@ -0,0 +1,45 @@
import { Raycaster, Vector3 } from "three"
class Clickable {
constructor(defaultDistance) {
const objects = [];
const raycaster = new Raycaster();
let v = new Vector3;
this.add = function (object, fn, distance) {
objects.push(object);
object._clickable = { fn, distance: distance || defaultDistance };
};
this.remove = function (object) {
objects.splice(objects.indexOf(object), 1);
delete object._clickable;
};
this.update = function (mouse, camera, event) {
raycaster.setFromCamera(mouse, camera);
let forExecute = [];
objects.forEach(o => {
console.log(1)
o.getWorldPosition(v);
if (camera.position.distanceTo(v) <= o._clickable.distance && o.visible) {
console.log(2)
const intersects = raycaster.intersectObject(o);
// intersects.forEach(i=>{
// forExecute.push({o, i})
// })
if (intersects[0]) forExecute.push({ o, i: intersects[0] });
}
});
if (forExecute[0]) {
let sorted = forExecute.sort((a, b) => a.i.distance - b.i.distance);
sorted[0].o._clickable.fn(sorted[0].i);
if (this.onclick) {
this.onclick(sorted[0].o, sorted[0].i, event);
}
}
};
}
}
export {Clickable}
+2 -1
View File
@@ -96,7 +96,8 @@ class Hero{
}
update(){
return;
return
if (this.gameEngine.renderer.xr.isPresenting) return;
let { inputVelocity, velocity, euler, quat, v, targetQuaternion, clock } = this;
let pc = this.pointerControls;
pc.update();
+11 -2
View File
@@ -14,6 +14,7 @@ import { ARButton } from 'three/addons/webxr/ARButton.js';
import { XRButton } from 'three/addons/webxr/XRButton.js';
import { XRControllerModelFactory } from 'three/addons/webxr/XRControllerModelFactory.js';
import * as CANNON from 'cannon-es';
import { Clickable } from './Clickable.js';
class GameEngine {
async init(domNode, opts = {}) {
@@ -68,8 +69,8 @@ class GameEngine {
const renderer = new THREE.WebGLRenderer({
antialias: true,
// alpha: true,
preserveDrawingBuffer: true //this is important for screenshots capturing
//powerPreference: "high-performance",
preserveDrawingBuffer: true, //this is important for screenshots capturing
powerPreference: "high-performance",
});
renderer.setPixelRatio(window.devicePixelRatio);
// renderer.toneMapping = THREE.CineonToneMapping;
@@ -173,6 +174,8 @@ class GameEngine {
} : {}));
this.initXrControllers();
}
this.clickable = new Clickable(20);
}
initXrControllers() {
@@ -466,6 +469,12 @@ class GameEngine {
return intersects;
}
onClick(mouseEvent, domElement){
let mouse = this.getMouseVector(mouseEvent, domElement);
this.raycaster.setFromCamera(mouse, this.camera);
this.clickable.update(mouse, this.camera, mouseEvent);
}
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);
+3 -3
View File
@@ -1,4 +1,4 @@
import { BoxGeometry, Mesh, MeshBasicMaterial, Group, sRGBEncoding } from 'three';
import { BoxGeometry, Mesh, MeshBasicMaterial, Group } from 'three';
import { TextureLoader } from 'three/src/loaders/TextureLoader';
import { MotionEngine } from '../MotionEngine';
@@ -31,7 +31,7 @@ class Game1 {
let material = new MeshBasicMaterial({
map: new TextureLoader().load(image)
});
material.map.encoding = sRGBEncoding;
//material.map.encoding = sRGBEncoding;
for (let i = 0; i < 6; i++) {
let b = bm.clone();
@@ -87,7 +87,7 @@ class Game1 {
f: i == 0 && this.onfinish
});
});
context.dashboard.addPoints(10);
//context.dashboard.addPoints(10);
}
};
}
+3 -3
View File
@@ -1,11 +1,11 @@
import { BoxGeometry, Mesh, MeshBasicMaterial, Group, sRGBEncoding } from 'three';
import { BoxGeometry, Mesh, MeshBasicMaterial, Group } from 'three';
import { TextureLoader } from 'three/src/loaders/TextureLoader';
import { MotionEngine } from '../MotionEngine';
class Game2 {
constructor(context, image, w, h) {
const texture = new TextureLoader().load(image);
texture.encoding = sRGBEncoding;
//texture.encoding = sRGBEncoding;
const material = new MeshBasicMaterial({
map: texture
});
@@ -136,7 +136,7 @@ class Game2 {
f: i == 0 && this.onfinish
});
});
context.dashboard.addPoints(10);
//context.dashboard.addPoints(10);
}
};
+124
View File
@@ -0,0 +1,124 @@
import { Group, RGBAFormat } from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { MotionEngine } from '../MotionEngine';
var Game4 = function(context, gltf, w, h){
this.game = new Group();
const aq = new MotionEngine();
const pr = [];
let d = .51, c = w * h / 2, tc = w * h, m0=1, r0=.2;
let lastClicked;
function setMaterial(m, v){
if (v){
m.metalness = .5;
m.roughness = .383;
}else{
m.metalness = m0;
m.roughness = r0;
m.transparent = true;
m.format = RGBAFormat;
}
}
new GLTFLoader().load(gltf, gltf=>{
for (let i = 0; i<c; i++){
let o = gltf.scene.getObjectByName('c'+(i+1));
let ref = [];
for (let j = 0; j<2; j++){
let position;
do {
position = Math.floor(Math.random() * tc);
}while (pr[position]);
ref[j] = o.clone();
ref[j].material = o.material.clone();
setMaterial(ref[j].material, 0);
pr[position] = ref[j];
}
ref[0].$ref = ref[1];
ref[1].$ref = ref[0];
}
pr.forEach((c, i)=>{
c.position.set((i % w)*d , (~~(i / w))*d);
c.rotation.set(0, Math.PI, 0);
this.game.add(c);
context.clickable.add(c, clickFn);
})
this.game.children[0].onBeforeRender = ()=>{
this.update();
}
});
var check = ()=>{
if (!this.game.children.length) return false;
return pr.filter(c=>c.$active === false).length == tc;
}
let clickFn = (i)=>{
let clicked = i.object;
if (this.done && clicked){
aq.add({
o: clicked,
a: {rotation:{y: Math.PI}},
t: 1,
m: 'offset'
});
}
if (!clicked || clicked.$active === false || aq.isActive(clicked)) return;
setMaterial(clicked.material, 1);
let f;
if (lastClicked && lastClicked.$ref == clicked){
clicked.$active = lastClicked.$active = false;
[clicked, lastClicked].forEach(c => {
aq.add({
o: c,
a: {material:{opacity:0}},
t: 1,
d:1
});
});
lastClicked = null;
}else if(!lastClicked){
lastClicked = clicked;
}else{
f = ()=>{
setTimeout(()=>{
[clicked, lastClicked].filter(c=>c).forEach(c=>{
aq.add({
o: c,
a: {rotation:{y: Math.PI}, material:{metalness:m0, roughness:r0}},
t: 1
});
});
lastClicked = null;
}, 500);
}
}
aq.add({
o: clicked,
a: {rotation:{y: 0}},
t: .5,
f
});
}
this.update = ()=>{
aq.update();
if (!this.done && check()){
this.done = true;
this.game.children.forEach((c, i)=>{
aq.add({
o: c,
a: {material:{opacity:1}},
t: 1,
d:1+0.1*i
})
})
this.onfinish && this.onfinish();
//context.dashboard.addPoints(10);
}
}
}
export { Game4 }