HTML5 Canvas 跑酷游戏实现
我将使用HTML5 Canvas和JavaScript创建一个类似Chrome恐龙游戏的跑酷游戏,无需任何外部库。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTML5 Canvas 跑酷游戏</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
background: linear-gradient(135deg, #1a2a6c, #b21f1f, #1a2a6c);
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
}
.game-container {
position: relative;
width: 800px;
max-width: 95%;
box-shadow: 0 0 30px rgba(0, 0, 0, 0.6);
border-radius: 10px;
overflow: hidden;
}
.game-header {
background: linear-gradient(to right, #ff416c, #ff4b2b);
color: white;
padding: 15px 20px;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 3px solid #ff8a00;
}
.game-title {
font-size: 24px;
font-weight: bold;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
}
.score-container {
background: rgba(0, 0, 0, 0.3);
padding: 8px 20px;
border-radius: 30px;
font-size: 20px;
font-weight: bold;
}
.game-canvas-container {
position: relative;
background: #6b9ac4;
height: 400px;
}
canvas {
background: #87CEEB;
display: block;
}
.ground {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 30px;
background: linear-gradient(to bottom, #8B4513, #5D2906);
z-index: 10;
border-top: 3px solid #704214;
}
.controls {
background: rgba(0, 0, 0, 0.7);
padding: 15px;
color: white;
text-align: center;
font-size: 16px;
border-top: 2px solid #ff8a00;
}
.game-over {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.85);
display: none;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 100;
color: white;
}
.game-over h2 {
font-size: 48px;
color: #ff416c;
margin-bottom: 20px;
text-shadow: 0 0 10px rgba(255, 65, 108, 0.7);
}
.final-score {
font-size: 32px;
margin-bottom: 30px;
}
.restart-btn {
background: linear-gradient(to right, #00c9ff, #92fe9d);
border: none;
padding: 15px 40px;
font-size: 20px;
font-weight: bold;
border-radius: 50px;
cursor: pointer;
transition: all 0.3s;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
}
.restart-btn:hover {
transform: translateY(-3px);
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4);
}
.game-info {
position: absolute;
top: 20px;
left: 20px;
background: rgba(0, 0, 0, 0.6);
color: white;
padding: 15px;
border-radius: 10px;
z-index: 50;
max-width: 300px;
}
.character {
position: absolute;
bottom: 30px;
left: 100px;
z-index: 20;
}
.obstacle {
position: absolute;
bottom: 30px;
z-index: 15;
}
.cloud {
position: absolute;
z-index: 5;
}
</style>
</head>
<body>
<div class="game-container">
<div class="game-header">
<div class="game-title">像素跑酷冒险</div>
<div class="score-container">分数: <span id="score">0</span></div>
</div>
<div class="game-canvas-container">
<canvas id="gameCanvas" width="800" height="400"></canvas>
<div class="ground"></div>
<div class="game-info">
<h3>游戏说明</h3>
<p>按空格键或上箭头跳跃,避开障碍物!</p>
<p>游戏速度会随时间增加</p>
</div>
<div class="game-over" id="gameOver">
<h2>游戏结束!</h2>
<div class="final-score">最终分数: <span id="finalScore">0</span></div>
<button class="restart-btn" onclick="restartGame()">重新开始</button>
</div>
</div>
<div class="controls">
控制: 空格键或上箭头键跳跃 | 游戏速度: <span id="speed">1.0</span>x
</div>
</div>
<script>
// 游戏主要变量
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const scoreElement = document.getElementById('score');
const finalScoreElement = document.getElementById('finalScore');
const gameOverScreen = document.getElementById('gameOver');
const speedElement = document.getElementById('speed');
// 游戏状态
let gameRunning = true;
let score = 0;
let gameSpeed = 1.0;
let speedIncreaseTimer = 0;
// 玩家角色
const player = {
x: 100,
y: canvas.height - 80,
width: 40,
height: 50,
velocityY: 0,
jumping: false,
color: '#3498db',
draw: function() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
// 绘制玩家细节
ctx.fillStyle = '#2c3e50';
ctx.fillRect(this.x + 10, this.y + 10, 8, 8); // 眼睛
ctx.fillRect(this.x + 25, this.y + 10, 8, 8); // 眼睛
ctx.fillStyle = '#e74c3c';
ctx.fillRect(this.x + 15, this.y + 30, 10, 15); // 身体
// 腿
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y + 40, 10, 10);
ctx.fillRect(this.x + 30, this.y + 40, 10, 10);
},
update: function() {
// 重力
this.velocityY += 0.6;
this.y += this.velocityY;
// 地面碰撞
if (this.y > canvas.height - 80) {
this.y = canvas.height - 80;
this.velocityY = 0;
this.jumping = false;
}
},
jump: function() {
if (!this.jumping) {
this.velocityY = -15;
this.jumping = true;
}
}
};
// 障碍物
let obstacles = [];
function createObstacle() {
const height = 30 + Math.random() * 30;
const width = 20 + Math.random() * 20;
const type = Math.random() > 0.7 ? 'tall' : 'wide';
obstacles.push({
x: canvas.width,
y: canvas.height - 80 - (type === 'tall' ? height : 20),
width: type === 'tall' ? width : 60,
height: type === 'tall' ? height : 20,
type: type,
passed: false
});
}
// 云朵
let clouds = [];
function createCloud() {
clouds.push({
x: canvas.width,
y: 30 + Math.random() * 150,
width: 60 + Math.random() * 40,
speed: 0.5 + Math.random() * 1.0
});
}
// 游戏循环
function gameLoop() {
// 清除画布
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 绘制背景
drawBackground();
// 更新和绘制云朵
updateClouds();
// 更新玩家
player.update();
player.draw();
// 更新障碍物
updateObstacles();
// 更新分数
updateScore();
// 碰撞检测
checkCollisions();
// 随机生成障碍物
if (Math.random() < 0.02 * gameSpeed) {
createObstacle();
}
// 随机生成云朵
if (Math.random() < 0.01) {
createCloud();
}
// 增加游戏速度
speedIncreaseTimer++;
if (speedIncreaseTimer > 300) {
gameSpeed += 0.1;
speedIncreaseTimer = 0;
speedElement.textContent = gameSpeed.toFixed(1);
}
// 继续游戏循环
if (gameRunning) {
requestAnimationFrame(gameLoop);
}
}
function drawBackground() {
// 天空
const gradient = ctx.createLinearGradient(0, 0, 0, canvas.height);
gradient.addColorStop(0, "#87CEEB");
gradient.addColorStop(1, "#E0F7FA");
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 远山
ctx.fillStyle = "#5D8AA8";
ctx.beginPath();
ctx.moveTo(0, canvas.height - 100);
for (let i = 0; i < canvas.width; i += 50) {
const height = 50 + Math.sin(i * 0.05) * 20;
ctx.lineTo(i, canvas.height - 100 - height);
}
ctx.lineTo(canvas.width, canvas.height - 100);
ctx.lineTo(canvas.width, canvas.height);
ctx.lineTo(0, canvas.height);
ctx.closePath();
ctx.fill();
}
function updateClouds() {
for (let i = clouds.length - 1; i >= 0; i--) {
const cloud = clouds[i];
cloud.x -= cloud.speed * gameSpeed;
// 绘制云朵
ctx.fillStyle = "rgba(255, 255, 255, 0.8)";
ctx.beginPath();
ctx.arc(cloud.x, cloud.y, cloud.width * 0.3, 0, Math.PI * 2);
ctx.arc(cloud.x + cloud.width * 0.25, cloud.y - cloud.width * 0.1, cloud.width * 0.25, 0, Math.PI * 2);
ctx.arc(cloud.x + cloud.width * 0.4, cloud.y, cloud.width * 0.3, 0, Math.PI * 2);
ctx.arc(cloud.x - cloud.width * 0.2, cloud.y, cloud.width * 0.25, 0, Math.PI * 2);
ctx.fill();
// 移除屏幕外的云朵
if (cloud.x + cloud.width < 0) {
clouds.splice(i, 1);
}
}
}
function updateObstacles() {
for (let i = obstacles.length - 1; i >= 0; i--) {
const obstacle = obstacles[i];
// 移动障碍物
obstacle.x -= 5 * gameSpeed;
// 绘制障碍物
ctx.fillStyle = obstacle.type === 'tall' ? "#e74c3c" : "#f39c12";
ctx.fillRect(obstacle.x, obstacle.y, obstacle.width, obstacle.height);
// 添加障碍物细节
ctx.fillStyle = "#c0392b";
if (obstacle.type === 'tall') {
ctx.fillRect(obstacle.x + 5, obstacle.y + 5, obstacle.width - 10, 5);
ctx.fillRect(obstacle.x + 5, obstacle.y + 15, obstacle.width - 10, 5);
} else {
for (let j = 0; j < 3; j++) {
ctx.fillRect(obstacle.x + 5 + j * 18, obstacle.y + 5, 10, 5);
}
}
// 计分
if (!obstacle.passed && obstacle.x + obstacle.width < player.x) {
obstacle.passed = true;
score += 10;
}
// 移除屏幕外的障碍物
if (obstacle.x + obstacle.width < 0) {
obstacles.splice(i, 1);
}
}
}
function updateScore() {
score++;
scoreElement.textContent = Math.floor(score / 5);
}
function checkCollisions() {
for (let obstacle of obstacles) {
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
) {
endGame();
return;
}
}
}
function endGame() {
gameRunning = false;
finalScoreElement.textContent = Math.floor(score / 5);
gameOverScreen.style.display = "flex";
}
function restartGame() {
gameRunning = true;
score = 0;
gameSpeed = 1.0;
speedIncreaseTimer = 0;
obstacles = [];
clouds = [];
player.y = canvas.height - 80;
player.velocityY = 0;
player.jumping = false;
gameOverScreen.style.display = "none";
speedElement.textContent = gameSpeed.toFixed(1);
gameLoop();
}
// 键盘控制
document.addEventListener('keydown', function(e) {
if ((e.code === 'Space' || e.key === 'ArrowUp') && gameRunning) {
player.jump();
}
});
// 触摸控制
canvas.addEventListener('touchstart', function() {
if (gameRunning) {
player.jump();
}
});
// 初始化游戏
restartGame();
</script>
</body>
</html>
游戏特点
这个HTML5 Canvas跑酷游戏具有以下特点:
- 响应式设计:适应不同屏幕尺寸
- 像素风格角色:玩家角色和障碍物采用简洁的像素风格
- 动态背景:渐变天空、山脉背景和移动的云朵
- 游戏机制:
- 按空格键或上箭头跳跃
- 随机生成的障碍物(高障碍和宽障碍)
- 随游戏进行速度逐渐增加
- 碰撞检测
- 游戏界面:
- 实时分数显示
- 游戏速度指示器
- 游戏说明
- 游戏结束界面(显示最终分数和重新开始按钮)
如何玩
- 打开页面后游戏自动开始
- 按空格键或上箭头键使角色跳跃
- 避开各种障碍物
- 游戏速度会随时间增加,增加挑战性
- 碰撞到障碍物后游戏结束
- 点击"重新开始"按钮可以再次游戏
解析在代码中,请详细阅读!
游戏已完全实现,只需复制整个代码到HTML文件中即可直接运行!
HTML5 Canvas跑酷游戏开发教程

307

被折叠的 条评论
为什么被折叠?



