Meta Description" name="description" />
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Rewind Run: Mobile Test</title>
<style>
* {
box-sizing: border-box;
user-select: none;
-webkit-user-select: none;
}
body {
background-color: #0a0a0a;
color: #00ffff;
font-family: sans-serif;
text-align: center;
margin: 0;
padding: 10px;
overflow: hidden; /* Prevents bouncing on mobile screens */
position: fixed;
width: 100%;
height: 100%;
}
h1 { font-size: 1.2rem; margin: 5px 0; color: #ff00ff; }
canvas {
background-color: #111;
border: 2px solid #00ffff;
display: block;
margin: 0 auto;
max-width: 100%;
height: auto;
}
/* Virtual D-Pad for Mobile Touch Controls */
#controls {
display: flex;
justify-content: space-between;
width: 100%;
max-width: 600px;
margin: 15px auto 0 auto;
padding: 0 20px;
}
.btn {
background: rgba(255, 0, 255, 0.2);
border: 2px solid #ff00ff;
color: #fff;
font-size: 1.5rem;
font-weight: bold;
width: 70px;
height: 70px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 0 10px #ff00ff;
}
.btn:active {
background: rgba(255, 0, 255, 0.6);
}
.dir-buttons { display: flex; gap: 15px; }
</style>
</head>
<body>
<h1>REWIND RUN: MOBILE</h1>
<canvas id="gameCanvas" width="600" height="300"></canvas>
<!-- Touch Buttons Interface -->
<div id="controls">
<div class="dir-buttons">
<div class="btn" id="btnLeft">◀</div>
<div class="btn" id="btnRight">▶</div>
</div>
<div class="btn" id="btnJump">▲</div>
</div>
<script>
const canvas = document.getElementById("gameCanvas");
const ctx = canvas.getContext("2d");
// Player physics
let player = { x: 50, y: 250, width: 20, height: 20, vx: 0, vy: 0, speed: 4, jump: -9, grounded: true };
const gravity = 0.4;
// Time and Ghost management
let timeLeft = 10.0;
let currentRunFrames = [];
let pastRuns = [];
let frameIndex = 0;
// Touch Input States
let moveLeft = false;
let moveRight = false;
let mustJump = false;
// Setup Event Listeners for Mobile Touch UI
setupTouchButton("btnLeft", (isPressed) => moveLeft = isPressed);
setupTouchButton("btnRight", (isPressed) => moveRight = isPressed);
setupTouchButton("btnJump", (isPressed) => { if (isPressed && player.grounded) mustJump = true; });
function setupTouchButton(id, callback) {
const btn = document.getElementById(id);
btn.addEventListener("touchstart", (e) => { e.preventDefault(); callback(true); });
btn.addEventListener("touchend", (e) => { e.preventDefault(); callback(false); });
}
function resetRun() {
pastRuns.push(currentRunFrames);
player.x = 50;
player.y = 250;
player.vx = 0;
player.vy = 0;
timeLeft = 10.0;
currentRunFrames = [];
frameIndex = 0;
}
function update() {
// --- TOUCH MOVEMENT PROCESSING ---
if (moveLeft) player.vx = -player.speed;
else if (moveRight) player.vx = player.speed;
else player.vx = 0;
if (mustJump && player.grounded) {
player.vy = player.jump;
player.grounded = false;
mustJump = false;
}
player.vy += gravity;
player.x += player.vx;
player.y += player.vy;
// Floor collision
if (player.y >= 250) {
player.y = 250;
player.vy = 0;
player.grounded = true;
}
// Boundary checks
if (player.x <= 0) player.x = 0;
if (player.x >= canvas.width - player.width) player.x = canvas.width - player.width;
// Record Frame
currentRunFrames.push({ x: player.x, y: player.y });
// Timer Tick
timeLeft -= 1 / 60;
if (timeLeft <= 0) {
resetRun();
}
frameIndex++;
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draw Floor line
ctx.fillStyle = "#333";
ctx.fillRect(0, 270, canvas.width, 30);
// Draw Past Ghosts
for (let i = 0; i < pastRuns.length; i++) {
let ghostFrames = pastRuns[i];
if (frameIndex < ghostFrames.length) {
ctx.fillStyle = "rgba(0, 255, 255, 0.35)";
ctx.fillRect(ghostFrames[frameIndex].x, ghostFrames[frameIndex].y, player.width, player.height);
}
}
// Draw Current Player
ctx.fillStyle = "#ff00ff";
ctx.fillRect(player.x, player.y, player.width, player.height);
// Display HUD
ctx.fillStyle = "#fff";
ctx.font = "16px sans-serif";
ctx.fillText("Time: " + Math.max(0, timeLeft).toFixed(2) + "s", 15, 25);
ctx.fillText("Ghosts: " + pastRuns.length, 15, 50);
}
function gameLoop() {
update();
draw();
requestAnimationFrame(gameLoop);
}
gameLoop();
</script>
</body>
</html>
1
1
6KB
6KB
111.0ms
132.0ms
111.0ms