Fix physics depending on fps

This commit is contained in:
Paul Mathieu 2021-12-30 03:47:57 -08:00
parent e8e4ccb9ad
commit 0b45bfe1eb
4 changed files with 53 additions and 26 deletions

52
game.js
View File

@ -18,9 +18,7 @@ import {
* @param {WebGLRenderingContext} gl * @param {WebGLRenderingContext} gl
*/ */
function draw(gl, params, objects) { function draw(gl, params, objects) {
const skyColor = [0.6, 0.8, 1.0]; gl.clearColor(...params.skyColor, 1.0);
gl.clearColor(...skyColor, 1.0);
gl.clearDepth(1.0); gl.clearDepth(1.0);
gl.enable(gl.DEPTH_TEST); gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL); gl.depthFunc(gl.LEQUAL);
@ -46,7 +44,7 @@ function draw(gl, params, objects) {
glContext.setupScene({ glContext.setupScene({
projectionMatrix: params.projMatrix, projectionMatrix: params.projMatrix,
viewMatrix, viewMatrix,
fogColor: skyColor, fogColor: params.skyColor,
lightDirection: params.lightDirection, lightDirection: params.lightDirection,
ambiantLightAmount: params.ambiantLight, ambiantLightAmount: params.ambiantLight,
}); });
@ -72,12 +70,12 @@ function handleKeys(params) {
const dir = [right, 0, -forward, 1.0]; const dir = [right, 0, -forward, 1.0];
const ori = se3.roty(params.camera.orientation[1]); const ori = se3.roty(params.camera.orientation[1]);
const tf = se3.apply(ori, dir); const tf = se3.apply(ori, dir);
const maxSpeed = 0.1; const maxSpeed = 8;
const airMovement = 0.08; const airMovement = 0.08;
if (params.flying) { if (params.flying) {
params.camera.position[0] += tf[0]; params.camera.position[0] += tf[0] / 60;
params.camera.position[2] += tf[2]; params.camera.position[2] += tf[2] / 60;
} }
if (params.isOnGround) { if (params.isOnGround) {
params.camera.velocity[0] = tf[0]; params.camera.velocity[0] = tf[0];
@ -100,26 +98,26 @@ function handleKeys(params) {
params.keys.forEach(key => { params.keys.forEach(key => {
switch (key) { switch (key) {
case 'KeyW': case 'KeyW':
move(0.1, 0.0); move(8, 0.0);
return; return;
case 'KeyA': case 'KeyA':
move(0.0, -0.1); move(0.0, -8);
return; return;
case 'KeyS': case 'KeyS':
move(-0.1, 0.0); move(-8, 0.0);
return; return;
case 'KeyD': case 'KeyD':
move(0.0, 0.1); move(0.0, 8);
return; return;
case 'Space': case 'Space':
if (params.flying) { if (params.flying) {
params.camera.position[1] += 0.1; params.camera.position[1] += 8 / 60;
} }
return; return;
case 'ShiftLeft': case 'ShiftLeft':
params.camera.position[1] -= 0.1; params.camera.position[1] -= 8 / 60;
return; return;
} }
}); });
@ -161,14 +159,16 @@ function getObjects(world, z, x, glContext) {
})); }));
} }
function updatePhysics(params) { function updatePhysics(params, time) {
params.camera.velocity[1] += params.gravity / 60 / 60; const dt = (time - params.lastFrameTime) / 1000;
params.camera.velocity[1] += params.gravity * dt;
const oldPos = params.camera.position; const oldPos = params.camera.position;
const targetPos = params.flying ? oldPos : params.camera.position.map((v, i) => v + params.camera.velocity[i]); const targetPos = params.flying ? oldPos : params.camera.position.map((v, i) => v + params.camera.velocity[i] * dt);
const {isOnGround, newPos} = checkCollision(oldPos, targetPos, params.world); const {isOnGround, newPos} = checkCollision(oldPos, targetPos, params.world);
params.camera.position = newPos; params.camera.position = newPos;
params.camera.velocity = newPos.map((v, i) => v - oldPos[i]); params.camera.velocity = newPos.map((v, i) => (v - oldPos[i]) / dt);
if (isOnGround) { if (isOnGround) {
params.jumpAmount = 2; params.jumpAmount = 2;
params.camera.velocity = params.camera.velocity.map(v => v * 0.7); params.camera.velocity = params.camera.velocity.map(v => v * 0.7);
@ -259,6 +259,18 @@ export function setupParamPanel(params) {
params.jumpForce = e.target.value / 100; params.jumpForce = e.target.value / 100;
document.querySelector('#jumpForceValue').textContent = e.target.value / 100; document.querySelector('#jumpForceValue').textContent = e.target.value / 100;
}; };
document.querySelector('#skyr').oninput = e => {
params.skyColor[0] = e.target.value / 255;
document.querySelector('#skyColor').textContent = JSON.stringify(params.skyColor);
};
document.querySelector('#skyg').oninput = e => {
params.skyColor[1] = e.target.value / 255;
document.querySelector('#skyColor').textContent = JSON.stringify(params.skyColor);
};
document.querySelector('#skyb').oninput = e => {
params.skyColor[2] = e.target.value / 255;
document.querySelector('#skyColor').textContent = JSON.stringify(params.skyColor);
};
const collapsibles = document.getElementsByClassName("collapsible"); const collapsibles = document.getElementsByClassName("collapsible");
for (const collapsible of collapsibles) { for (const collapsible of collapsibles) {
@ -375,7 +387,7 @@ export function initUiListeners(params, canvas) {
export function tick(time, gl, params) { export function tick(time, gl, params) {
handleKeys(params); handleKeys(params);
updatePhysics(params); updatePhysics(params, time);
const campos = params.camera.position; const campos = params.camera.position;
@ -396,8 +408,8 @@ export function tick(time, gl, params) {
draw(gl, params, objects); draw(gl, params, objects);
const dt = (time - stuff.lastFrameTime) * 0.001; const dt = (time - params.lastFrameTime) * 0.001;
stuff.lastFrameTime = time; params.lastFrameTime = time;
document.querySelector('#fps').textContent = `${1.0 / dt} fps`; document.querySelector('#fps').textContent = `${1.0 / dt} fps`;
document.querySelector('#lightDirVec').textContent = JSON.stringify(params.lightDirection); document.querySelector('#lightDirVec').textContent = JSON.stringify(params.lightDirection);

View File

@ -40,7 +40,8 @@
<button class="collapsible">Parameters</button> <button class="collapsible">Parameters</button>
<div class="paramContent"> <div class="paramContent">
<div class="paramPanel"> <div class="paramPanel">
<h3>Light direction</h3> <h3>Light</h3>
<h4>Direction</h4>
<p> <p>
x: x:
<input type="range" min="-100" max="100" value="50" class="slider" id="lightx" /> <input type="range" min="-100" max="100" value="50" class="slider" id="lightx" />
@ -56,12 +57,25 @@
<p> <p>
<div id="lightDirVec"></div> <div id="lightDirVec"></div>
</p> </p>
</div> <h4>Ambiant light amount</h4>
<div class="paramPanel">
<h3>Ambiant light</h3>
<p> <p>
<input type="range" min="0" max="100" value="50" class="slider" id="ambiant" /> <input type="range" min="0" max="100" value="50" class="slider" id="ambiant" />
</p> </p>
<h4>Sky color</h4>
<p>
r:
<input type="range" min="0" max="255" value="115" class="slider" id="skyr" />
</p>
<p>
g:
<input type="range" min="0" max="255" value="191" class="slider" id="skyg" />
</p>
<p>
b:
<input type="range" min="0" max="255" value="255" class="slider" id="skyb" />
</p>
<p>
<div id="skyColor"></div>
</div> </div>
<div class="paramPanel"> <div class="paramPanel">
<h3>Physics</h3> <h3>Physics</h3>

View File

@ -22,6 +22,7 @@ async function main() {
}, },
keys: new Set(), keys: new Set(),
lightDirection: [-0.2, -0.5, 0.4], lightDirection: [-0.2, -0.5, 0.4],
skyColor: [0.45, 0.75, 1.0],
ambiantLight: 0.7, ambiantLight: 0.7,
blockSelectDistance: 8, blockSelectDistance: 8,
flying: false, flying: false,
@ -29,7 +30,7 @@ async function main() {
world: makeWorld(), world: makeWorld(),
worldGl: await initWorldGl(gl), worldGl: await initWorldGl(gl),
gravity: -17, gravity: -17,
jumpForce: 0.11, jumpForce: 6.5,
} }
setupParamPanel(params); setupParamPanel(params);

View File

@ -47,7 +47,7 @@ void main() {
if (color.a < 0.1) { if (color.a < 0.1) {
discard; discard;
} }
lowp float fogamount = smoothstep(40.0, 100.0, vDistance); lowp float fogamount = smoothstep(80.0, 100.0, vDistance);
gl_FragColor = mix(vec4(vLighting * color.rgb, color.a), vec4(uFogColor, 1.0), fogamount); gl_FragColor = mix(vec4(vLighting * color.rgb, color.a), vec4(uFogColor, 1.0), fogamount);
} }
`; `;