<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>第一視角摩托車</title>
<style>
html, body {
margin: 0;
padding: 0;
background: #000;
overflow: hidden;
user-select: none;
font-family: Arial, sans-serif;
}
#gameCanvas {
display: block;
background: linear-gradient(to bottom, #87CEEB 0%, #87CEEB 45%, #98FB98 45%, #228B22 100%);
}
#hud {
position: absolute;
top: 20px;
left: 20px;
color: white;
font-size: 20px;
text-shadow: 2px 2px 4px rgba(0,0,0,0.8);
background: rgba(0,0,0,0.5);
padding: 15px;
border-radius: 10px;
}
#controls {
position: absolute;
bottom: 50px;
left: 50%;
transform: translateX(-50%);
display: flex;
gap: 200px;
align-items: center;
}
#speedControls {
position: absolute;
bottom: 150px;
left: 50%;
transform: translateX(-50%);
display: flex;
gap: 20px;
align-items: center;
}
.control-btn {
width: 80px;
height: 80px;
border-radius: 50%;
background: rgba(255,255,255,0.3);
border: 3px solid white;
color: white;
font-size: 30px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.2s ease;
box-shadow: 0 4px 15px rgba(0,0,0,0.3);
}
.control-btn:active {
background: rgba(255,255,255,0.5);
transform: scale(0.9);
}
.speed-btn {
width: 100px;
height: 60px;
border-radius: 30px;
font-size: 24px;
}
#startScreen {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.8);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: white;
}
#startBtn {
padding: 20px 40px;
font-size: 24px;
background: #ff6b6b;
color: white;
border: none;
border-radius: 10px;
cursor: pointer;
margin-top: 20px;
transition: background 0.3s ease;
}
#startBtn:hover {
background: #ff5252;
}
</style>
</head>
<body>
<canvas id="gameCanvas"></canvas>
<div id="hud">
<div>速度: <span id="speed">0</span> km/h</div>
<div>時間: <span id="time">0</span>s</div>
<div>距離: <span id="distance">0</span>m</div>
</div>
<div id="speedControls">
<button class="control-btn speed-btn" id="accelerateBtn">▲ 加速</button>
<button class="control-btn speed-btn" id="brakeBtn">▼ 減速</button>
</div>
<div id="controls">
<button class="control-btn" id="leftBtn">?</button>
<button class="control-btn" id="rightBtn">?</button>
</div>
<div id="startScreen">
<h1>🏍? 摩托車競速</h1>
<p>使用屏幕兩側按鈕控制方向</p>
<p>▲▼ 按鈕控制加速和減速</p>
<button id="startBtn">開始游戲</button>
</div>
? ? <script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
// 設置畫布大小
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
resizeCanvas();
window.addEventListener('resize', resizeCanvas);
// 游戲狀態
let gameStarted = false;
let speed = 0;
let maxSpeed = 200;
let acceleration = 1.5;
let deceleration = 2;
let position = 0;
let roadCurve = 0;
let targetCurve = 0;
let leanAngle = 0;
let startTime = Date.now();
// 道路生成
const roadSegments = [];
const segmentCount = 500;
const segmentLength = 50;
// 生成隨機道路
for (let i = 0; i < segmentCount; i++) {
roadSegments.push({
z: i * segmentLength,
curve: Math.sin(i * 0.02) * 200 + Math.sin(i * 0.05) * 100,
y: Math.sin(i * 0.03) * 30
});
}
// 控制狀態
const controls = {
left: false,
right: false,
accelerate: false,
brake: false
};
// 設置控制按鈕
const leftBtn = document.getElementById('leftBtn');
const rightBtn = document.getElementById('rightBtn');
const accelerateBtn = document.getElementById('accelerateBtn');
const brakeBtn = document.getElementById('brakeBtn');
// 方向控制
leftBtn.addEventListener('mousedown', () => controls.left = true);
leftBtn.addEventListener('mouseup', () => controls.left = false);
leftBtn.addEventListener('touchstart', (e) => { e.preventDefault(); controls.left = true; });
leftBtn.addEventListener('touchend', () => controls.left = false);
rightBtn.addEventListener('mousedown', () => controls.right = true);
rightBtn.addEventListener('mouseup', () => controls.right = false);
rightBtn.addEventListener('touchstart', (e) => { e.preventDefault(); controls.right = true; });
rightBtn.addEventListener('touchend', () => controls.right = false);
// 速度控制
accelerateBtn.addEventListener('mousedown', () => controls.accelerate = true);
accelerateBtn.addEventListener('mouseup', () => controls.accelerate = false);
accelerateBtn.addEventListener('touchstart', (e) => { e.preventDefault(); controls.accelerate = true; });
accelerateBtn.addEventListener('touchend', () => controls.accelerate = false);
brakeBtn.addEventListener('mousedown', () => controls.brake = true);
brakeBtn.addEventListener('mouseup', () => controls.brake = false);
brakeBtn.addEventListener('touchstart', (e) => { e.preventDefault(); controls.brake = true; });
brakeBtn.addEventListener('touchend', () => controls.brake = false);
// 鍵盤控制
document.addEventListener('keydown', (e) => {
switch(e.key) {
case 'ArrowLeft': controls.left = true; break;
case 'ArrowRight': controls.right = true; break;
case 'ArrowUp': controls.accelerate = true; break;
case 'ArrowDown': controls.brake = true; break;
}
});
document.addEventListener('keyup', (e) => {
switch(e.key) {
case 'ArrowLeft': controls.left = false; break;
case 'ArrowRight': controls.right = false; break;
case 'ArrowUp': controls.accelerate = false; break;
case 'ArrowDown': controls.brake = false; break;
}
});
// 開始游戲
document.getElementById('startBtn').addEventListener('click', () => {
document.getElementById('startScreen').style.display = 'none';
gameStarted = true;
startTime = Date.now();
gameLoop();
});
// 繪制道路
function drawRoad() {
const centerX = canvas.width / 2;
const horizon = canvas.height * 0.7;
const segmentHeight = canvas.height * 0.5 / 30;
// 找到當前位置對應的路段
const currentSegment = Math.floor(position / segmentLength);
for (let i = 1; i < 30; i++) {
const segmentIndex = (currentSegment + i) % segmentCount;
const segment = roadSegments[segmentIndex];
const prevSegment = roadSegments[(segmentIndex - 1 + segmentCount) % segmentCount];
const z = segment.z - position;
const scale = 200 / z;
const x1 = centerX + (prevSegment.curve + roadCurve) * scale;
const x2 = centerX + (segment.curve + roadCurve) * scale;
const y1 = horizon - i * segmentHeight;
const y2 = horizon - (i - 1) * segmentHeight;
const roadWidth = 400 * scale;
// 繪制路面
ctx.fillStyle = i % 2 ? '#444' : '#555';
ctx.beginPath();
ctx.moveTo(x1 - roadWidth/2, y1);
ctx.lineTo(x1 + roadWidth/2, y1);
ctx.lineTo(x2 + roadWidth/2, y2);
ctx.lineTo(x2 - roadWidth/2, y2);
ctx.fill();
// 繪制路邊
ctx.fillStyle = '#228B22';
ctx.fillRect(0, y1, x1 - roadWidth/2, y2 - y1);
ctx.fillRect(x1 + roadWidth/2, y1, canvas.width - x1 - roadWidth/2, y2 - y1);
// 繪制中線
if (i % 4 === 0) {
ctx.strokeStyle = '#FFF';
ctx.lineWidth = 4 * scale;
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
}
}
}
// 繪制摩托車把手
function drawHandlebars() {
const centerX = canvas.width / 2;
const centerY = canvas.height - 120;
ctx.save();
ctx.translate(centerX, centerY);
ctx.rotate(leanAngle * 0.02);
// 繪制把手主體
ctx.strokeStyle = '#333';
ctx.lineWidth = 12;
ctx.beginPath();
ctx.moveTo(-180, 0);
ctx.lineTo(180, 0);
ctx.stroke();
// 繪制左手把
ctx.fillStyle = '#222';
ctx.fillRect(-200, -8, 40, 16);
// 繪制右手把
ctx.fillRect(160, -8, 40, 16);
// 繪制后視鏡
ctx.fillStyle = '#666';
ctx.fillRect(-220, -20, 15, 10);
ctx.fillRect(205, -20, 15, 10);
// 繪制儀表
ctx.fillStyle = '#000';
ctx.fillRect(-40, -25, 80, 30);
ctx.strokeStyle = '#0F0';
ctx.lineWidth = 2;
ctx.strokeRect(-40, -25, 80, 30);
// 速度顯示
ctx.fillStyle = '#0F0';
ctx.font = '16px monospace';
ctx.textAlign = 'center';
ctx.fillText(`${speed.toFixed(0)} km/h`, 0, -8);
ctx.restore();
}
// 更新游戲狀態
function update() {
if (!gameStarted) return;
// 處理輸入
if (controls.accelerate) {
speed = Math.min(speed + acceleration, maxSpeed);
}
if (controls.brake) {
speed = Math.max(speed - deceleration * 2, 0);
}
if (controls.left) {
targetCurve -= 3;
leanAngle = Math.max(leanAngle - 2, -15);
} else if (controls.right) {
targetCurve += 3;
leanAngle = Math.min(leanAngle + 2, 15);
} else {
leanAngle *= 0.9;
}
targetCurve *= 0.95;
roadCurve += (targetCurve - roadCurve) * 0.1;
// 更新位置
position += speed * 0.5;
if (position >= segmentCount * segmentLength) {
position -= segmentCount * segmentLength;
}
// 更新HUD
const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
document.getElementById('time').textContent = elapsed;
document.getElementById('distance').textContent = (position / 10).toFixed(0);
document.getElementById('speed').textContent = speed.toFixed(0);
}
// 渲染畫面
function render() {
// 清空畫布
ctx.fillStyle = '#87CEEB';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 繪制道路
drawRoad();
// 繪制摩托車把手
drawHandlebars();
}
// 游戲循環
function gameLoop() {
update();
render();
if (gameStarted) {
requestAnimationFrame(gameLoop);
}
}
// 防止觸摸滾動
document.addEventListener('touchmove', (e) => {
e.preventDefault();
}, { passive: false });
</script>
</body>
</html>