124 lines
3.6 KiB
JavaScript
124 lines
3.6 KiB
JavaScript
import { Group, RGBAFormat } from 'three';
|
|
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
|
|
import { MotionEngine } from '../../lib/MotionEngine';
|
|
|
|
var PuzzleGame4 = function(context, gltf, w, h){
|
|
this.object = 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.object.add(c);
|
|
context.clickable.add(c, clickFn);
|
|
})
|
|
|
|
this.object.children[0].onBeforeRender = ()=>{
|
|
this.update();
|
|
}
|
|
});
|
|
|
|
var check = ()=>{
|
|
if (!this.object.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.object.children.forEach((c, i)=>{
|
|
aq.add({
|
|
o: c,
|
|
a: {material:{opacity:1}},
|
|
t: 1,
|
|
d:1+0.1*i
|
|
})
|
|
})
|
|
this.dispatchEvent({type:'finish'})
|
|
//context.dashboard.addPoints(10);
|
|
}
|
|
}
|
|
}
|
|
|
|
export { PuzzleGame4 } |