diff --git a/index.html b/index.html index ceec926..02a2b55 100644 --- a/index.html +++ b/index.html @@ -59,195 +59,6 @@ - + \ No newline at end of file diff --git a/js/flywheel.js b/js/flywheel.js new file mode 100644 index 0000000..4e981a1 --- /dev/null +++ b/js/flywheel.js @@ -0,0 +1,66 @@ + + /* + 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 + } +} \ No newline at end of file diff --git a/js/game.js b/js/game.js new file mode 100644 index 0000000..b541931 --- /dev/null +++ b/js/game.js @@ -0,0 +1,66 @@ +import { Flywheel } from "./flywheel.js"; +import { getPathShapeBetweenPoints } from "./svg.js"; + +export function init(svgEl, crosshairXEl, crosshairYEl) { + let flywheel = new Flywheel(); + + + const segmentCount = window.location.search.substr(1).length ? window.location.search.substr(1) : 4; + + // canvas position relative to mouse/screen + // TODO: update on resize: + svgEl.setAttribute('viewBox', '0 0 ' + window.innerWidth + ' ' + window.innerHeight); + 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 + window.addEventListener('mousemove', function (mousemoveEv) { + let x = mousemoveEv.clientX - rect.left; + let y = mousemoveEv.clientY - rect.top; + + crosshairXEl.setAttribute('x1', x) + crosshairXEl.setAttribute('x2', x) + crosshairYEl.setAttribute('y1', y) + crosshairYEl.setAttribute('y2', y) + }); + + svgEl.addEventListener('mousedown', function (mousedownEv) { + let shapeEl = document.createElementNS('http://www.w3.org/2000/svg', 'path'); + shapeEl.classList.add('rect'); + let p1 = { 'x': mousedownEv.clientX - rect.left, 'y': mousedownEv.clientY - rect.top } + // shapeEl.setAttribute('x', p1.x); + // shapeEl.setAttribute('y', p1.y); + + // shapeEl.setAttribute('width', 0); + // shapeEl.setAttribute('height', 0); + + let d = getPathShapeBetweenPoints(p1, p1, segmentCount); + svgEl.appendChild(shapeEl); + shapeEl.setAttribute('d', d); + + let mouseMoveEv = function (mousemoveEv) { + let p2 = { 'x': mousemoveEv.clientX - rect.left, 'y': mousemoveEv.clientY - rect.top } + let d = getPathShapeBetweenPoints(p1, p2, segmentCount); + shapeEl.setAttribute('d', d); + }; + let mouseUpEv = function () { + console.log('up'); + window.removeEventListener('mousemove', mouseMoveEv); // remove itself. + window.removeEventListener('mouseup', mouseUpEv); // remove itself. + shapeEl.classList.add('locked'); + //TODO: calculate points + flywheel.add(); + + setTimeout(function () { + shapeEl.classList.add('hide'); + setTimeout(function () { + shapeEl.parentNode.removeChild(shapeEl); + }, 1000); + }, 1000); + }; + window.addEventListener('mousemove', mouseMoveEv); + window.addEventListener('mouseup', mouseUpEv); + }) +} \ No newline at end of file diff --git a/js/main.js b/js/main.js new file mode 100644 index 0000000..16c2c72 --- /dev/null +++ b/js/main.js @@ -0,0 +1,8 @@ +import { init } from "./game.js"; + +let svgEl = document.getElementById('canvas'); +let crosshairXEl = document.getElementById('crosshair_x'); +let crosshairYEl = document.getElementById('crosshair_y'); + + +let game = init(svgEl, crosshairXEl, crosshairYEl); \ No newline at end of file diff --git a/js/svg.js b/js/svg.js new file mode 100644 index 0000000..df6d4a2 --- /dev/null +++ b/js/svg.js @@ -0,0 +1,54 @@ + +function getPathShapeBetweenPoints(p1, p2, corners) { + let d = `M ${p1.x},${p1.y} L `; + if(corners == 4){ + + // draw inbetween p1 & p2. + let minx = Math.min(p1.x, p2.x); + let miny = Math.min(p1.y, p2.y); + let maxx = Math.max(p1.x, p2.x); + let maxy = Math.max(p1.y, p2.y); + + d += ` ${p1.x},${p2.y} ${p2.x},${p2.y} ${p2.x},${p1.y} ${p1.x},${p1.y} `; + } + else{ + // find center of circle that describes the polygon of which p1 and p2 are part + // it's _not_ the center between the two points, as p1 and p2 are corners on the shape + + // distance between p1 and p2 + const length = Math.sqrt(Math.pow(p1.x-p2.x,2)+ Math.pow(p1.y - p2.y, 2)); + + const segmentAngle = Math.PI * 2 / corners; + // we don't want + // const segmentsAngle = Math.floor(180/segmentAngle) * segmentAngle; + + const radius = (length*.5)/Math.sin(segmentAngle); + + const rotation = Math.atan2((p2.y -p1.y),(p2.x - p1.x)) + (Math.PI/2-segmentAngle); + + const dx = Math.cos(rotation) * radius;// * Math.sign(p2.x - p1.x); + const dy = Math.sin(rotation) * radius;// * Math.sign(p2.y - p1.y); + // we now have the center: + const cx = p2.x - dx; + const cy = p2.y - dy; + + // startpoint in relation to circle + const sx = cx - p1.x; + const sy = cy - p1.y; + + let startRot = Math.asin(sx / radius); + if(sy>0){startRot = -1 * startRot + Math.PI;} + // console.log(sx, radius, startRot); + // animI+= .1; + // console.log(sx, sy, startRot); + for (let a = 0; a < Math.PI*2; a += segmentAngle) { + let x = radius * Math.sin(a-startRot) + cx; + let y = radius * Math.cos(a-startRot) + cy; + d += ` ${x},${y}`; + } + + } + return d + ' Z'; +} + +export {getPathShapeBetweenPoints}; \ No newline at end of file