JSFiddle - React, Tailwind, and code Playground
by jcubed111
HTML
<canvas id="main" width=800 height=600></canvas>
<br>
<label>
<span>xVel</span>
<input type="range" id="xVel" min=0 max=10 value=7 step=0.1>
<span class="value" id="xVelDisp">0.15</span>
</label>
<label>
<span>fullG</span>
<input type="range" id="fullG" min=0 max=100 value=60 step=1>
<span class="value" id="fullGDisp">0.15</span>
</label>
<label>
<span>partialG</span>
<input type="range" id="partialG" min=0 max=100 value=15 step=1>
<span class="value" id="partialGDisp">0.15</span>
</label>
<label>
<span>maxJumpHeight</span>
<input type="range" id="maxJumpHeight" min=0 max=10 value=6.4 step=0.1>
<span class="value" id="maxJumpHeightDisp">0.15</span>
</label>
<label>
<span>jumpBuffer</span>
<input type="range" id="jumpBuffer" min=0 max=1 value=0.4 step=0.05>
<span class="value" id="jumpBufferDisp">0.15</span>
</label>
SCSS
@import url('https://fonts.googleapis.com/css2?family=Josefin+Sans:wght@300&display=swap');
body{
background: #223;
font-family: 'Josefin Sans', sans-serif;
font-size: 18px;
font-weight: 200;
color: #ddd;
}
label{
display: block;
span {
display: inline-block;
width: 125px;
vertical-align: middle;
text-align: right;
}
input {
width: 200px;
height: 25px;
vertical-align: -55%;
}
span.value {
text-align: left;
}
}
JavaScript
let canvas = document.getElementById('main');
let ctx = canvas.getContext('2d');
ctx.setTransform(1, 0, 0, -1, 0, 600);
const scale = 40;
function renderBack() {
ctx.clearRect(0, 0, 800, 600);
ctx.beginPath();
ctx.strokeStyle = '#fff1';
for (let z = 0; z < 600; z += scale) {
ctx.moveTo(0, z + .5);
ctx.lineTo(800, z + .5);
}
for (let x = 0; x < 800; x += scale) {
ctx.moveTo(x + .5, 0);
ctx.lineTo(x + .5, 600);
}
ctx.stroke();
}
function startV(d, b, g) {
return Math.sqrt(2*b**2*g**2 - 2*g*d) + 2*b*g;
}
function render(xVel, fullG, partialG, maxJumpHeight, jumpBuffer) {
// jumpBuffer: number of seconds of a = 0 at beginning of jump
renderBack();
const c = ({
x,
z
}) => [x * scale, z * scale];
['vel', 'pos'].forEach(l => {
[0.0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0].forEach(jumpDuration => {
const dt = 1 / 1000;
let pos = {
x: 2,
z: 1
};
let vel = {
x: xVel,
// z: Math.sqrt(jumpBuffer**2 * partialG**2 - 2*maxJumpHeight*partialG) + jumpBuffer*partialG
z: startV(maxJumpHeight, jumpBuffer, partialG),
};
const value = () => l == 'vel' ? {x: pos.x, z: vel.z} : pos;
ctx.strokeStyle = l == 'pos' ? '#0af' : '#70b';
ctx.beginPath();
ctx.moveTo(...c(value()));
for (let t = 0; t < 10.0; t += dt) {
let pressingUp = t < jumpDuration;
let az;
if(pressingUp && t < jumpBuffer) {
az = -partialG;
}else if(pressingUp){
az = partialG;
}else{
az = fullG;
}
pos.x += vel.x * dt;
pos.z += vel.z * dt + 0.5 * az * dt * dt;
vel.z...