Basic Effects
This commit is contained in:
parent
a56fac5bfd
commit
0679766f6c
4 changed files with 166 additions and 74 deletions
158
js/effects.js
vendored
Normal file
158
js/effects.js
vendored
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
The interface is like a flywheel.
|
||||||
|
*/
|
||||||
|
export class Flywheel {
|
||||||
|
constructor() {
|
||||||
|
this.value = 0.; // start at 0 - gradual meter
|
||||||
|
this.stage = 0.; // start at 0 - the various stages
|
||||||
|
|
||||||
|
this.f_falloff = (value) => value / 20; // value at which it reduces per second
|
||||||
|
this.f_stage = (value) => 5 * Math.log10(value); // value to stage calculation
|
||||||
|
|
||||||
|
this.value_min = 0;
|
||||||
|
this.value_max = 100; // gives stage 0-9
|
||||||
|
|
||||||
|
// this.interval = window.setInterval(this.step, 50)
|
||||||
|
this.time = null;
|
||||||
|
window.requestAnimationFrame(this.step.bind(this));
|
||||||
|
// TODO: once/twice per second should be enough! + on release (add())
|
||||||
|
|
||||||
|
this.effects = {
|
||||||
|
'shape': new ShapeEffect(),
|
||||||
|
'video': new VideoEffect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
step(time) {
|
||||||
|
if (this.time === null) {
|
||||||
|
// first run
|
||||||
|
this.time = time;
|
||||||
|
window.requestAnimationFrame(this.step.bind(this));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (time - this.time < 500) {
|
||||||
|
window.requestAnimationFrame(this.step.bind(this));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dt = time - this.time;
|
||||||
|
this.time = time;
|
||||||
|
|
||||||
|
this.value -= this.f_falloff(this.value) * dt / 1000; // linear falloff
|
||||||
|
|
||||||
|
if (this.value < 0) {
|
||||||
|
this.value = 0;
|
||||||
|
}
|
||||||
|
// console.log(this.value,this.falloff, dt,this.time);
|
||||||
|
|
||||||
|
// TODO: check if this should be different
|
||||||
|
|
||||||
|
const stage = Math.max(0, Math.floor(this.f_stage(this.value)));
|
||||||
|
if (stage != this.stage) {
|
||||||
|
this.changeStage(stage);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.requestAnimationFrame(this.step.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
add(increment) {
|
||||||
|
this.value += typeof increment == 'undefined' ? 1 : increment;
|
||||||
|
// cap:
|
||||||
|
if (this.value > this.value_max) this.value = this.value_max;
|
||||||
|
}
|
||||||
|
|
||||||
|
changeStage(stage) {
|
||||||
|
this.stage = stage;
|
||||||
|
console.log('stage now at', this.stage);
|
||||||
|
for (let fx of Object.values(this.effects)) {
|
||||||
|
fx.setStageHandler(this.stage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function effect(start_stage, end_stage) {
|
||||||
|
return class Effect {
|
||||||
|
constructor() {
|
||||||
|
this.enabled = false;
|
||||||
|
this.start_stage = start_stage;
|
||||||
|
this.end_stage = end_stage;
|
||||||
|
this.intensity = 0;
|
||||||
|
this.intensity_easing = (t) => t; // 0 < t <= 1: use this to make effect eg. more eased
|
||||||
|
}
|
||||||
|
|
||||||
|
setStageHandler(stage) {
|
||||||
|
if (stage < this.start_stage || stage > this.end_stage) {
|
||||||
|
this.disable(stage);
|
||||||
|
} else {
|
||||||
|
this.enable(stage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enable(stage) {
|
||||||
|
if (!this.enabled) {
|
||||||
|
this.enabled = true;
|
||||||
|
this.enableHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
const ds = this.end_stage - this.start_stage + 1;
|
||||||
|
if (ds === 1) {
|
||||||
|
this.setIntensity(1);
|
||||||
|
} else {
|
||||||
|
const s = stage - this.start_stage + 1;
|
||||||
|
const t = s / ds;
|
||||||
|
this.setIntensity(this.intensity_easing(t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
disable(stage) {
|
||||||
|
if (this.enabled) {
|
||||||
|
this.enabled = false;
|
||||||
|
this.disableHandler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setIntensity(intensity) {
|
||||||
|
if (intensity !== this.intensity) {
|
||||||
|
this.intensity = intensity;
|
||||||
|
this.intensityHandler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enableHandler() {/* to override */ }
|
||||||
|
disableHandler() {/* to override */ }
|
||||||
|
intensityHandler() {/* to override */ }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class ShapeEffect extends effect(3, 10) {
|
||||||
|
getAngles() {
|
||||||
|
if (!this.enabled) {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
if (this.intensity < .3) {
|
||||||
|
return 3;
|
||||||
|
} else if (this.intensity < .7) {
|
||||||
|
return 5;
|
||||||
|
} else {
|
||||||
|
// random pick
|
||||||
|
const corners = [3, 4, 5, 7]
|
||||||
|
return corners[Math.floor(Math.random() * corners.length)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class VideoEffect extends effect(3, 10) {
|
||||||
|
// override enable instead of using handler to apply it gradually
|
||||||
|
disableHandler() {
|
||||||
|
document.getElementById('video_background').style.opacity = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
intensityHandler() {
|
||||||
|
document.getElementById('video_background').style.opacity = this.intensity;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -1,66 +0,0 @@
|
||||||
|
|
||||||
/*
|
|
||||||
The interface is like a flywheel.
|
|
||||||
*/
|
|
||||||
export class Flywheel{
|
|
||||||
constructor() {
|
|
||||||
this.value = 0.; // start at 0 - gradual meter
|
|
||||||
this.stage = 0.; // start at 0 - the various stages
|
|
||||||
|
|
||||||
this.f_falloff = (value) => value/20; // value at which it reduces per second
|
|
||||||
this.f_stage = (value) => 5*Math.log10(value); // value to stage calculation
|
|
||||||
|
|
||||||
this.value_min = 0;
|
|
||||||
this.value_max = 100; // gives stage 0-9
|
|
||||||
|
|
||||||
// this.interval = window.setInterval(this.step, 50)
|
|
||||||
this.time = null;
|
|
||||||
window.requestAnimationFrame(this.step.bind(this));
|
|
||||||
// TODO: once/twice per second should be enough! + on release (add())
|
|
||||||
}
|
|
||||||
|
|
||||||
step(time){
|
|
||||||
if(this.time === null){
|
|
||||||
// first run
|
|
||||||
this.time = time;
|
|
||||||
window.requestAnimationFrame(this.step.bind(this));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(time-this.time < 500){
|
|
||||||
window.requestAnimationFrame(this.step.bind(this));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const dt = time - this.time;
|
|
||||||
this.time = time;
|
|
||||||
|
|
||||||
this.value -= this.f_falloff(this.value) * dt/1000; // linear falloff
|
|
||||||
|
|
||||||
if(this.value < 0){
|
|
||||||
this.value = 0;
|
|
||||||
}
|
|
||||||
// console.log(this.value,this.falloff, dt,this.time);
|
|
||||||
|
|
||||||
// TODO: check if this should be different
|
|
||||||
|
|
||||||
const stage = Math.max(0,Math.floor(this.f_stage(this.value)));
|
|
||||||
if (stage != this.stage){
|
|
||||||
this.changeStage(stage);
|
|
||||||
}
|
|
||||||
|
|
||||||
window.requestAnimationFrame(this.step.bind(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
add(increment){
|
|
||||||
this.value += typeof increment == 'undefined' ? 1 : increment;
|
|
||||||
// cap:
|
|
||||||
if(this.value > this.value_max) this.value = this.value_max;
|
|
||||||
}
|
|
||||||
|
|
||||||
changeStage(stage){
|
|
||||||
this.stage = stage;
|
|
||||||
console.log('stage now at', this.stage);
|
|
||||||
// TODO: handle stage change
|
|
||||||
}
|
|
||||||
}
|
|
13
js/game.js
13
js/game.js
|
@ -1,19 +1,16 @@
|
||||||
import { Flywheel } from "./flywheel.js";
|
import { Flywheel } from "./effects.js";
|
||||||
import { getPathShapeBetweenPoints } from "./svg.js";
|
import { getPathShapeBetweenPoints } from "./svg.js";
|
||||||
|
|
||||||
export function init(svgEl, crosshairXEl, crosshairYEl) {
|
export function init(svgEl, crosshairXEl, crosshairYEl) {
|
||||||
let flywheel = new Flywheel();
|
let flywheel = new Flywheel();
|
||||||
|
|
||||||
|
// use ?3 and ?4 ?28 etc in query string to determine segments
|
||||||
const segmentCount = window.location.search.substr(1).length ? window.location.search.substr(1) : 4;
|
const segmentCount = window.location.search.substr(1).length ? window.location.search.substr(1) : 4;
|
||||||
|
|
||||||
// canvas position relative to mouse/screen
|
// canvas position relative to mouse/screen
|
||||||
// TODO: update on resize:
|
// TODO: update on resize:
|
||||||
svgEl.setAttribute('viewBox', '0 0 ' + window.innerWidth + ' ' + window.innerHeight);
|
svgEl.setAttribute('viewBox', '0 0 ' + window.innerWidth + ' ' + window.innerHeight);
|
||||||
let rect = svgEl.getBoundingClientRect();
|
let rect = svgEl.getBoundingClientRect();
|
||||||
// let cx = rect.left + rect.width / 2;
|
|
||||||
// let cy = rect.top + rect.height / 2;
|
|
||||||
// let center = { 'x': cx, 'y': cy };
|
|
||||||
|
|
||||||
// move crosshairs
|
// move crosshairs
|
||||||
window.addEventListener('mousemove', function (mousemoveEv) {
|
window.addEventListener('mousemove', function (mousemoveEv) {
|
||||||
|
@ -27,16 +24,18 @@ export function init(svgEl, crosshairXEl, crosshairYEl) {
|
||||||
});
|
});
|
||||||
|
|
||||||
svgEl.addEventListener('mousedown', function (mousedownEv) {
|
svgEl.addEventListener('mousedown', function (mousedownEv) {
|
||||||
|
// create shape to draw
|
||||||
let shapeEl = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
let shapeEl = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
||||||
shapeEl.classList.add('rect');
|
shapeEl.classList.add('rect');
|
||||||
let p1 = { 'x': mousedownEv.clientX - rect.left, 'y': mousedownEv.clientY - rect.top }
|
let p1 = { 'x': mousedownEv.clientX - rect.left, 'y': mousedownEv.clientY - rect.top }
|
||||||
let d = getPathShapeBetweenPoints(p1, p1, segmentCount);
|
let corners = flywheel.effects.shape.getAngles();
|
||||||
|
let d = getPathShapeBetweenPoints(p1, p1, corners);
|
||||||
svgEl.appendChild(shapeEl);
|
svgEl.appendChild(shapeEl);
|
||||||
shapeEl.setAttribute('d', d);
|
shapeEl.setAttribute('d', d);
|
||||||
|
|
||||||
let mouseMoveEv = function (mousemoveEv) {
|
let mouseMoveEv = function (mousemoveEv) {
|
||||||
let p2 = { 'x': mousemoveEv.clientX - rect.left, 'y': mousemoveEv.clientY - rect.top }
|
let p2 = { 'x': mousemoveEv.clientX - rect.left, 'y': mousemoveEv.clientY - rect.top }
|
||||||
let d = getPathShapeBetweenPoints(p1, p2, segmentCount);
|
let d = getPathShapeBetweenPoints(p1, p2, corners);
|
||||||
shapeEl.setAttribute('d', d);
|
shapeEl.setAttribute('d', d);
|
||||||
};
|
};
|
||||||
let mouseUpEv = function () {
|
let mouseUpEv = function () {
|
||||||
|
|
|
@ -5,4 +5,5 @@ let crosshairXEl = document.getElementById('crosshair_x');
|
||||||
let crosshairYEl = document.getElementById('crosshair_y');
|
let crosshairYEl = document.getElementById('crosshair_y');
|
||||||
|
|
||||||
|
|
||||||
let game = init(svgEl, crosshairXEl, crosshairYEl);
|
var game = init(svgEl, crosshairXEl, crosshairYEl);
|
||||||
|
console.log('Initialised game', game);
|
Loading…
Reference in a new issue