feat: add TRex movement controls, jump/duck, and forward-step scoring
This commit is contained in:
parent
93958c02a4
commit
5b1d0affca
92
js/game.js
92
js/game.js
@ -1,14 +1,97 @@
|
|||||||
const canvas = document.getElementById('game');
|
const canvas = document.getElementById('game');
|
||||||
const ctx = canvas.getContext('2d');
|
const ctx = canvas.getContext('2d');
|
||||||
|
const scoreEl = document.getElementById('score');
|
||||||
|
|
||||||
|
const keys = new Set();
|
||||||
|
const gravity = 1900;
|
||||||
|
const groundY = 420;
|
||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
running: true,
|
running: true,
|
||||||
lastTs: performance.now()
|
lastTs: performance.now(),
|
||||||
|
score: 0,
|
||||||
|
stepCarry: 0,
|
||||||
|
player: {
|
||||||
|
x: 160,
|
||||||
|
y: 0,
|
||||||
|
width: 64,
|
||||||
|
height: 76,
|
||||||
|
standingHeight: 76,
|
||||||
|
duckHeight: 48,
|
||||||
|
vx: 0,
|
||||||
|
vy: 0,
|
||||||
|
speed: 300,
|
||||||
|
jumpPower: 760,
|
||||||
|
onGround: true,
|
||||||
|
ducking: false
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
state.player.y = groundY - state.player.height;
|
||||||
|
|
||||||
|
window.addEventListener('keydown', (e) => {
|
||||||
|
if (["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"].includes(e.key)) {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
keys.add(e.key);
|
||||||
|
|
||||||
|
if (e.key === 'ArrowUp' && state.player.onGround) {
|
||||||
|
state.player.vy = -state.player.jumpPower;
|
||||||
|
state.player.onGround = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
window.addEventListener('keyup', (e) => keys.delete(e.key));
|
||||||
|
|
||||||
function drawBackground() {
|
function drawBackground() {
|
||||||
|
ctx.fillStyle = '#8ddcff';
|
||||||
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
ctx.fillStyle = '#88d34f';
|
ctx.fillStyle = '#88d34f';
|
||||||
ctx.fillRect(0, 420, canvas.width, 120);
|
ctx.fillRect(0, groundY, canvas.width, canvas.height - groundY);
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawTRex(p) {
|
||||||
|
ctx.fillStyle = '#35535f';
|
||||||
|
ctx.fillRect(p.x, p.y, p.width, p.height);
|
||||||
|
ctx.fillStyle = '#27404a';
|
||||||
|
ctx.fillRect(p.x + p.width - 12, p.y + 14, 7, 7); // eye
|
||||||
|
ctx.fillRect(p.x + 10, p.y + p.height - 8, 14, 8); // foot1
|
||||||
|
ctx.fillRect(p.x + p.width - 24, p.y + p.height - 8, 14, 8); // foot2
|
||||||
|
}
|
||||||
|
|
||||||
|
function updatePlayer(dt) {
|
||||||
|
const p = state.player;
|
||||||
|
let move = 0;
|
||||||
|
|
||||||
|
if (keys.has('ArrowLeft')) move -= 1;
|
||||||
|
if (keys.has('ArrowRight')) move += 1;
|
||||||
|
|
||||||
|
p.ducking = keys.has('ArrowDown') && p.onGround;
|
||||||
|
const targetHeight = p.ducking ? p.duckHeight : p.standingHeight;
|
||||||
|
if (targetHeight !== p.height) {
|
||||||
|
p.y += p.height - targetHeight;
|
||||||
|
p.height = targetHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.vx = move * p.speed;
|
||||||
|
const oldX = p.x;
|
||||||
|
p.x += p.vx * dt;
|
||||||
|
p.x = Math.max(0, Math.min(canvas.width - p.width, p.x));
|
||||||
|
|
||||||
|
if (p.x > oldX) {
|
||||||
|
state.stepCarry += p.x - oldX;
|
||||||
|
while (state.stepCarry >= 8) {
|
||||||
|
state.score += 1;
|
||||||
|
state.stepCarry -= 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p.vy += gravity * dt;
|
||||||
|
p.y += p.vy * dt;
|
||||||
|
|
||||||
|
if (p.y + p.height >= groundY) {
|
||||||
|
p.y = groundY - p.height;
|
||||||
|
p.vy = 0;
|
||||||
|
p.onGround = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function tick(ts) {
|
function tick(ts) {
|
||||||
@ -16,8 +99,13 @@ function tick(ts) {
|
|||||||
const dt = Math.min((ts - state.lastTs) / 1000, 0.05);
|
const dt = Math.min((ts - state.lastTs) / 1000, 0.05);
|
||||||
state.lastTs = ts;
|
state.lastTs = ts;
|
||||||
|
|
||||||
|
updatePlayer(dt);
|
||||||
|
|
||||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
drawBackground();
|
drawBackground();
|
||||||
|
drawTRex(state.player);
|
||||||
|
|
||||||
|
scoreEl.textContent = `Score: ${state.score}`;
|
||||||
|
|
||||||
requestAnimationFrame(tick);
|
requestAnimationFrame(tick);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user