readyaim
Version:
readyaim provides an aiming mechanism using a THREE.js camera
152 lines (124 loc) • 4.2 kB
JavaScript
// Filename: readyaim_fuse.js
// Timestamp: 2017.11.11-23:06:51 (last modified)
// Author(s): bumblehead <chris@bumblehead.com>
//
// multiple fuse, one for each object
//
// ◎ ◉
const castas = require('castas');
module.exports = (o => {
o.getringgeometry = (THREE, opt) =>
new THREE.RingGeometry(
opt.innerRadius,
opt.outerRadius,
opt.thetaSegments, // outer perimeter segments
opt.phiSegments,
opt.thetaStart,
Math.PI / 2);
o.getringmesh = (THREE, opt) =>
new THREE.Mesh(o.getringgeometry(THREE, opt), new THREE.MeshBasicMaterial({
color : opt.color,
side : THREE.BackSide,
fog : false
}));
o.getfusemesh = (THREE, opt, mesh = o.getringmesh(THREE, opt)) => (
mesh.visible = opt.visible,
mesh.position.z = 0.0001, // at front of reticle
mesh.rotation.y = 180 * (Math.PI / 180), // make clockwise
mesh);
o.getopts = (THREE, opts = {}) => {
let finopt = {};
finopt.visible = castas.bool(opts.visible, true);
finopt.globalDuration = castas.num(opts.duration, 2.5);
finopt.vibratePattern = castas.num(opts.vibrate, 100);
finopt.color = opts.color || 0x00fff6;
finopt.innerRadius = castas.num(opts.innerRadius, 0.045);
finopt.outerRadius = castas.num(opts.outerRadius, 0.06);
finopt.clickCancel = castas.bool(opts.clickCancel, false);
finopt.phiSegments = 3;
finopt.thetaSegments = 32;
finopt.thetaStart = Math.PI / 2;
finopt.duration = castas.num(opts.duration, opts.Globalduration);
finopt.timeDone = false;
return finopt;
};
// ( x, y ) ._
// /| ^
// / | |
// / | |
// / |
// h / | y
// / |
// / | |
// /. | |
// / θ +--| |
// /____\_|__|_v
// | |
// <-- x -->
//
o.getvertex = (hypotenuse, radangle) => ({
x : hypotenuse * Math.cos(radangle),
y : hypotenuse * Math.sin(radangle)
});
//
// for speed, consider a different approach...
// adding more faces (resolution), then
// painting faces within range
//
o.updateringgeometry = (opts, percent, ringgeometry) => {
let thetaEnd = percent * Math.PI * 2,
thetaStart = Number(opts.thetaStart),
thetaSegments = Number(opts.thetaSegments),
hypotenuse = Number(opts.innerRadius),
radiusstep = (opts.outerRadius - hypotenuse) / opts.phiSegments;
ringgeometry.vertices.map((vertex, i) => {
let segmenttheta = i % (thetaSegments + 1),
segmentpercent = segmenttheta / thetaSegments;
if (i && segmenttheta === 0)
hypotenuse += radiusstep; // longer, each time around
vertex = Object.assign(vertex, o.getvertex(hypotenuse, (
thetaStart + thetaEnd * segmentpercent // segment angle
)));
});
ringgeometry.verticesNeedUpdate = true;
return ringgeometry;
};
o.update = (fuseopts, percent = 0) => {
fuseopts.mesh.geometry = o.updateringgeometry(
fuseopts, percent, fuseopts.mesh.geometry);
// active if lt 100%
fuseopts.active = percent < 1;
return fuseopts;
};
// only update if active and !timeDone
// consider moving timeDone to controlling script
o.updateactive = (opts, fuseopts, elapsed) =>
(fuseopts.active && !opts.timeDone)
? o.update(fuseopts, elapsed / fuseopts.duration)
: fuseopts;
o.hide = fuseopts => (
fuseopts.mesh.visibile = false,
fuseopts);
o.out = fuseopts =>
o.update(o.hide(Object.assign(fuseopts, {
active : false,
timeDone : false
})), 0);
o.over = (fuseopts, duration, visible, color) => {
fuseopts.duration = duration || fuseopts.globalDuration;
fuseopts.active = true;
fuseopts = o.update(fuseopts, 0);
fuseopts.mesh.visible = visible || fuseopts.visible;
fuseopts.mesh.material.color.set(color);
return fuseopts;
};
o.isdurationengaged = (fuseopts, duration) => (
fuseopts.duration <= duration &&
fuseopts.active === false &&
fuseopts.timeDone === false);
o.engage = fuseopts => (
fuseopts.timeDone = true,
fuseopts.mesh.visible = false,
fuseopts);
return o;
})({});