starting to work on the endless runner
This commit is contained in:
parent
934fffac63
commit
5d11f87dd3
3 changed files with 120 additions and 2 deletions
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Document</title>
|
<title>Endless runner</title>
|
||||||
<link
|
<link
|
||||||
rel="apple-touch-icon"
|
rel="apple-touch-icon"
|
||||||
sizes="180x180"
|
sizes="180x180"
|
||||||
|
@ -23,5 +23,11 @@
|
||||||
/>
|
/>
|
||||||
<link rel="manifest" href="../../favicon_io/site.webmanifest" />
|
<link rel="manifest" href="../../favicon_io/site.webmanifest" />
|
||||||
</head>
|
</head>
|
||||||
<body></body>
|
<body>
|
||||||
|
<div class="game-container">
|
||||||
|
<canvas id="gameCanvas"></canvas>
|
||||||
|
<button id="restartBtn" onclick="restartGame()">Restart</button>
|
||||||
|
</div>
|
||||||
|
<script src="script.js"></script>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
import { useEffect, useRef, useState } from "react";
|
||||||
|
|
||||||
|
export default function EndlessRunner() {
|
||||||
|
const canvasRef = useRef(null);
|
||||||
|
const [running, setRunning] = useState(true);
|
||||||
|
const player = { x: 50, y: 150, width: 20, height: 20, dy: 0 };
|
||||||
|
const gravity = 0.5;
|
||||||
|
let obstacles = [];
|
||||||
|
let score = 0;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const canvas = canvasRef.current;
|
||||||
|
const ctx = canvas.getContext("2d");
|
||||||
|
canvas.width = window.innerWidth;
|
||||||
|
canvas.height = 300;
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
if (!running) return;
|
||||||
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
|
|
||||||
|
// Player physics
|
||||||
|
player.dy += gravity;
|
||||||
|
player.y += player.dy;
|
||||||
|
if (player.y > 150) {
|
||||||
|
player.y = 150;
|
||||||
|
player.dy = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw player
|
||||||
|
ctx.fillStyle = "blue";
|
||||||
|
ctx.fillRect(player.x, player.y, player.width, player.height);
|
||||||
|
|
||||||
|
// Obstacles
|
||||||
|
if (Math.random() < 0.02) {
|
||||||
|
obstacles.push({ x: canvas.width, y: 150, width: 20, height: 20 });
|
||||||
|
}
|
||||||
|
obstacles = obstacles.map(obstacle => ({ ...obstacle, x: obstacle.x - 5 }));
|
||||||
|
obstacles = obstacles.filter(obstacle => obstacle.x + obstacle.width > 0);
|
||||||
|
|
||||||
|
obstacles.forEach(obstacle => {
|
||||||
|
ctx.fillStyle = "red";
|
||||||
|
ctx.fillRect(obstacle.x, obstacle.y, obstacle.width, obstacle.height);
|
||||||
|
|
||||||
|
// Collision detection
|
||||||
|
if (
|
||||||
|
player.x < obstacle.x + obstacle.width &&
|
||||||
|
player.x + player.width > obstacle.x &&
|
||||||
|
player.y < obstacle.y + obstacle.height &&
|
||||||
|
player.y + player.height > obstacle.y
|
||||||
|
) {
|
||||||
|
setRunning(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Score
|
||||||
|
score++;
|
||||||
|
ctx.fillStyle = "black";
|
||||||
|
ctx.fillText("Score: " + score, 10, 20);
|
||||||
|
|
||||||
|
requestAnimationFrame(update);
|
||||||
|
}
|
||||||
|
|
||||||
|
update();
|
||||||
|
}, [running]);
|
||||||
|
|
||||||
|
function jump() {
|
||||||
|
if (player.y >= 150) {
|
||||||
|
player.dy = -10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col items-center">
|
||||||
|
<canvas ref={canvasRef} className="border" onClick={jump}></canvas>
|
||||||
|
{!running && <button onClick={() => window.location.reload()} className="mt-4 bg-blue-500 text-white px-4 py-2 rounded">Restart</button>}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 100vh;
|
||||||
|
background-color: #f4f4f4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.game-container {
|
||||||
|
position: relative;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas {
|
||||||
|
border: 2px solid black;
|
||||||
|
background-color: white;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#restartBtn {
|
||||||
|
margin-top: 10px;
|
||||||
|
padding: 10px 20px;
|
||||||
|
font-size: 16px;
|
||||||
|
background-color: #007bff;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#restartBtn:hover {
|
||||||
|
background-color: #0056b3;
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue