11.8 脚本网页 星际逃生

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>星际逃生</title>
<style>
/* 一、基础样式设置 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: linear-gradient(135deg, #0f0c29, #302b63, #24243e);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
font-family: 'Arial', sans-serif;
overflow: hidden;
position: relative;
}
/* 二、游戏容器样式 - 改为竖屏模式 */
#gameContainer {
position: relative;
width: 100vw;
height: 100vh;
max-width: 600px;
max-height: 900px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 10px;
}
#gameCanvas {
border: 3px solid rgba(255, 255, 255, 0.3);
border-radius: 15px;
background: radial-gradient(ellipse at center, rgba(20, 20, 40, 0.9), rgba(0, 0, 0, 0.95));
box-shadow: 0 0 50px rgba(100, 100, 255, 0.3);
cursor: none;
display: block;
width: 100%;
height: auto;
max-height: 80vh;
}
/* 三、UI界面样式 - 适应竖屏 */
#gameInfo {
position: absolute;
top: 20px;
left: 20px;
color: #fff;
font-size: 18px;
text-shadow: 2px 2px 4px rgba(0,0,0,0.8);
background: rgba(0, 0, 0, 0.5);
padding: 15px;
border-radius: 10px;
backdrop-filter: blur(10px);
z-index: 10;
}
.info-item {
margin: 5px 0;
display: flex;
align-items: center;
}
.info-label {
color: #64b5f6;
margin-right: 10px;
}
.info-value {
color: #ffd54f;
font-weight: bold;
font-size: 20px;
}
/* 四、游戏结束界面 - 适应竖屏 */
#gameOver {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #fff;
font-size: 32px;
text-align: center;
display: none;
background: rgba(0, 0, 0, 0.9);
padding: 30px;
border-radius: 20px;
backdrop-filter: blur(10px);
border: 2px solid rgba(255, 255, 255, 0.2);
z-index: 20;
width: 80%;
max-width: 400px;
}
#gameOver h2 {
color: #ff6b6b;
margin-bottom: 20px;
font-size: 36px;
}
#finalTime {
color: #4ecdc4;
font-size: 28px;
margin: 15px 0;
}
#startBtn {
padding: 15px 30px;
font-size: 20px;
background: linear-gradient(45deg, #4ecdc4, #44a3aa);
color: white;
border: none;
cursor: pointer;
margin-top: 20px;
border-radius: 30px;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(78, 205, 196, 0.4);
}
#startBtn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(78, 205, 196, 0.6);
}
/* 五、警告提示样式 */
#warning {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #ff1744;
font-size: 28px;
font-weight: bold;
text-shadow: 0 0 20px rgba(255, 23, 68, 0.8);
display: none;
animation: pulse 0.5s infinite;
z-index: 15;
}
@keyframes pulse {
0%, 100% {
opacity: 1;
transform: translate(-50%, -50%) scale(1);
}
50% {
opacity: 0.5;
transform: translate(-50%, -50%) scale(1.1);
}
}
/* 六、移动端适配 - 竖屏优化 */
@media (max-width: 768px) and (orientation: portrait) {
#gameContainer {
max-width: 100vw;
max-height: 100vh;
padding: 5px;
}
#gameInfo {
font-size: 16px;
padding: 10px;
}
.info-value {
font-size: 18px;
}
#gameOver {
font-size: 24px;
padding: 20px;
width: 90%;
}
#gameOver h2 {
font-size: 28px;
}
#finalTime {
font-size: 22px;
}
#startBtn {
padding: 12px 24px;
font-size: 18px;
}
#warning {
font-size: 22px;
}
}
</style>
</head>
<body>
<div id="gameContainer">
<div id="gameInfo">
<div class="info-item">
<span class="info-label">⏱ 时间:</span>
<span class="info-value" id="time">0</span>
<span class="info-label">秒</span>
</div>
<div class="info-item">
<span class="info-label">⚡ 难度:</span>
<span class="info-value" id="difficulty">1</span>
</div>
</div>
<canvas id="gameCanvas"></canvas>
<div id="gameOver">
<h2>游戏结束!</h2>
<div>🏆 存活时间: <span id="finalTime">0</span>秒</div>
<button id="startBtn" onclick="resetGame()">重新开始</button>
</div>
<div id="warning">⚠️ 危险来袭!</div>
</div>
<script>
// 一、游戏配置变量 - 改为竖屏模式,降低速度
const CONFIG = {
canvas: {
width: 600, // 改为竖屏比例
height: 800, // 改为竖屏比例
bgColor: 'rgba(17, 17, 17, 0.1)'
},
player: {
radius: 12,
speed: 3, // 降低玩家速度
color: '#ffffff',
glowColor: 'rgba(255, 255, 255, 0.2)'
},
bulletTypes: {
normal: {
color: '#ff6b6b',
speed: 2, // 降低子弹速度
radius: 5
},
fast: {
color: '#4ecdc4',
speed: 3, // 降低子弹速度
radius: 4
},
large: {
color: '#ffe66d',
speed: 1.5, // 降低子弹速度
radius: 15
},
split: {
color: '#a8e6cf',
speed: 2, // 降低子弹速度
radius: 6,
split: true
},
rotating: {
color: '#ff8b94',
speed: 2.5, // 降低子弹速度
radius: 7,
rotating: true
},
teleport: {
color: '#c7ceea',
speed: 2, // 降低子弹速度
radius: 8,
teleport: true
},
sudden: {
color: '#ff1744',
speed: 2.5, // 降低子弹速度
radius: 10,
sudden: true
}
},
game: {
initialDifficulty: 3,
difficultyIncreaseInterval: 5,
specialAttackInterval: 180,
particleCount: 15,
invulnerableTime: 120
},
effects: {
warningDuration: 1000,
particleLife: 40,
trailOpacity: 0.1
}
};
// 二、游戏状态变量
let canvas, ctx;
let gameRunning = true;
let startTime = Date.now();
let difficulty = CONFIG.game.initialDifficulty;
let bullets = [];
let particles = [];
let specialAttackTimer = 0;
// 三、玩家对象
const player = {
x: CONFIG.canvas.width / 2,
y: CONFIG.canvas.height / 2,
radius: CONFIG.player.radius,
speed: CONFIG.player.speed,
invulnerable: 0
};
// 四、输入控制变量
let mouseX = player.x;
let mouseY = player.y;
let touchActive = false;
// 五、初始化函数
function init() {
// 1. 获取画布和上下文
canvas = document.getElementById('gameCanvas');
ctx = canvas.getContext('2d');
// 2. 设置画布尺寸 - 适应竖屏
resizeCanvas();
window.addEventListener('resize', resizeCanvas);
// 3. 绑定事件监听器
setupEventListeners();
// 4. 开始游戏循环
gameLoop();
}
// 六、画布尺寸调整 - 适应竖屏
function resizeCanvas() {
const container = document.getElementById('gameContainer');
const containerWidth = container.clientWidth - 10;
const containerHeight = container.clientHeight - 100;
// 计算缩放比例,优先保证高度填满屏幕
const scale = Math.min(
containerWidth / CONFIG.canvas.width,
containerHeight / CONFIG.canvas.height,
1
);
canvas.width = CONFIG.canvas.width * scale;
canvas.height = CONFIG.canvas.height * scale;
canvas.style.width = canvas.width + 'px';
canvas.style.height = canvas.height + 'px';
// 调整玩家初始位置
player.x = canvas.width / 2;
player.y = canvas.height / 2;
}
// 七、事件监听器设置
function setupEventListeners() {
// 1. 鼠标移动事件
canvas.addEventListener('mousemove', handleMouseMove);
// 2. 触摸事件
canvas.addEventListener('touchstart', handleTouchStart, { passive: false });
canvas.addEventListener('touchmove', handleTouchMove, { passive: false });
canvas.addEventListener('touchend', handleTouchEnd);
// 3. 防止页面滚动
document.body.addEventListener('touchmove', preventDefault, { passive: false });
}
// 八、输入处理函数
function handleMouseMove(e) {
const rect = canvas.getBoundingClientRect();
mouseX = (e.clientX - rect.left) * (CONFIG.canvas.width / rect.width);
mouseY = (e.clientY - rect.top) * (CONFIG.canvas.height / rect.height);
}
function handleTouchStart(e) {
e.preventDefault();
touchActive = true;
const touch = e.touches[0];
const rect = canvas.getBoundingClientRect();
mouseX = (touch.clientX - rect.left) * (CONFIG.canvas.width / rect.width);
mouseY = (touch.clientY - rect.top) * (CONFIG.canvas.height / rect.height);
}
function handleTouchMove(e) {
e.preventDefault();
if (touchActive) {
const touch = e.touches[0];
const rect = canvas.getBoundingClientRect();
mouseX = (touch.clientX - rect.left) * (CONFIG.canvas.width / rect.width);
mouseY = (touch.clientY - rect.top) * (CONFIG.canvas.height / rect.height);
}
}
function handleTouchEnd(e) {
e.preventDefault();
touchActive = false;
}
function preventDefault(e) {
if (e.target === canvas) {
e.preventDefault();
}
}
// 九、子弹创建函数
function createBullet(type, x, y, angle) {
const bullet = {
type: type,
x: x,
y: y,
vx: Math.cos(angle) * type.speed,
vy: Math.sin(angle) * type.speed,
radius: type.radius,
color: type.color,
angle: angle
};
if (type.rotating) {
bullet.rotationAngle = 0;
}
if (type.teleport) {
bullet.teleportTimer = Math.random() * 60 + 30;
}
if (type.sudden) {
bullet.warningTime = 30;
}
bullets.push(bullet);
}
// 十、弹幕生成系统
function spawnBullets() {
// 1. 计算生成率
const spawnRate = Math.max(15 - difficulty, 5);
// 2. 随机生成子弹
if (Math.random() < 1 / spawnRate) {
createRandomBullet();
}
// 3. 特殊攻击计时
specialAttackTimer++;
if (specialAttackTimer > CONFIG.game.specialAttackInterval) {
specialAttackTimer = 0;
performSpecialAttack();
}
}
// 十一、随机子弹生成
function createRandomBullet() {
// 1. 随机选择生成位置 - 适应竖屏
const side = Math.floor(Math.random() * 4);
let x, y, angle;
switch(side) {
case 0: // 上方
x = Math.random() * canvas.width;
y = -20;
angle = Math.PI / 2 + (Math.random() - 0.5) * Math.PI / 3;
break;
case 1: // 右方
x = canvas.width + 20;
y = Math.random() * canvas.height;
angle = Math.PI + (Math.random() - 0.5) * Math.PI / 3;
break;
case 2: // 下方
x = Math.random() * canvas.width;
y = canvas.height + 20;
angle = -Math.PI / 2 + (Math.random() - 0.5) * Math.PI / 3;
break;
case 3: // 左方
x = -20;
y = Math.random() * canvas.height;
angle = (Math.random() - 0.5) * Math.PI / 3;
break;
}
// 2. 随机选择子弹类型
const types = Object.values(CONFIG.bulletTypes);
const bulletType = types[Math.floor(Math.random() * types.length)];
createBullet(bulletType, x, y, angle);
}
// 十二、特殊攻击系统
function performSpecialAttack() {
const attackType = Math.floor(Math.random() * 3);
switch(attackType) {
case 0:
suddenAttack();
break;
case 1:
circleAttack();
break;
case 2:
teleportAttack();
break;
}
}
// 十三、特殊攻击类型
function suddenAttack() {
showWarning();
setTimeout(() => {
for (let i = 0; i < 5; i++) {
const angle = Math.random() * Math.PI * 2;
const distance = 100 + Math.random() * 200;
const x = player.x + Math.cos(angle) * distance;
const y = player.y + Math.sin(angle) * distance;
const targetAngle = Math.atan2(player.y - y, player.x - x);
createBullet(CONFIG.bulletTypes.sudden, x, y, targetAngle);
}
}, CONFIG.effects.warningDuration);
}
function circleAttack() {
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
const bulletCount = 12 + difficulty * 2;
for (let i = 0; i < bulletCount; i++) {
const angle = (i / bulletCount) * Math.PI * 2;
createBullet(CONFIG.bulletTypes.rotating, centerX, centerY, angle);
}
}
function teleportAttack() {
const count = 3 + Math.floor(difficulty / 2);
for (let i = 0; i < count; i++) {
setTimeout(() => {
const x = Math.random() * canvas.width;
const y = Math.random() * canvas.height;
const angle = Math.random() * Math.PI * 2;
createBullet(CONFIG.bulletTypes.teleport, x, y, angle);
}, i * 200);
}
}
// 十四、警告显示
function showWarning() {
const warning = document.getElementById('warning');
warning.style.display = 'block';
setTimeout(() => {
warning.style.display = 'none';
}, CONFIG.effects.warningDuration);
}
// 十五、子弹更新系统
function updateBullets() {
for (let i = bullets.length - 1; i >= 0; i--) {
const bullet = bullets[i];
// 1. 处理突然子弹警告
if (bullet.type.sudden && bullet.warningTime > 0) {
bullet.warningTime--;
if (bullet.warningTime <= 0) {
bullet.vx = Math.cos(bullet.angle) * bullet.type.speed;
bullet.vy = Math.sin(bullet.angle) * bullet.type.speed;
}
continue;
}
// 2. 处理旋转子弹
if (bullet.type.rotating) {
bullet.rotationAngle += 0.08;
bullet.vx = Math.cos(bullet.angle + bullet.rotationAngle) * bullet.type.speed;
bullet.vy = Math.sin(bullet.angle + bullet.rotationAngle) * bullet.type.speed;
}
// 3. 处理传送子弹
if (bullet.type.teleport) {
bullet.teleportTimer--;
if (bullet.teleportTimer <= 0) {
createParticles(bullet.x, bullet.y, bullet.color);
bullet.x = Math.random() * canvas.width;
bullet.y = Math.random() * canvas.height;
bullet.teleportTimer = Math.random() * 60 + 30;
}
}
// 4. 更新位置
bullet.x += bullet.vx;
bullet.y += bullet.vy;
// 5. 处理分裂子弹
if (bullet.type.split && Math.random() < 0.01) {
for (let j = 0; j < 3; j++) {
const newAngle = bullet.angle + (j - 1) * Math.PI / 4;
createBullet(CONFIG.bulletTypes.fast, bullet.x, bullet.y, newAngle);
}
createParticles(bullet.x, bullet.y, bullet.color);
bullets.splice(i, 1);
continue;
}
// 6. 移除超出边界的子弹
if (bullet.x < -50 || bullet.x > canvas.width + 50 ||
bullet.y < -50 || bullet.y > canvas.height + 50) {
bullets.splice(i, 1);
}
}
}
// 十六、粒子效果系统
function createParticles(x, y, color) {
for (let i = 0; i < CONFIG.game.particleCount; i++) {
particles.push({
x: x,
y: y,
vx: (Math.random() - 0.5) * 8,
vy: (Math.random() - 0.5) * 8,
radius: Math.random() * 4 + 1,
color: color,
life: CONFIG.effects.particleLife
});
}
}
function updateParticles() {
for (let i = particles.length - 1; i >= 0; i--) {
const particle = particles[i];
particle.x += particle.vx;
particle.y += particle.vy;
particle.vx *= 0.95;
particle.vy *= 0.95;
particle.life--;
particle.radius *= 0.96;
if (particle.life <= 0) {
particles.splice(i, 1);
}
}
}
// 十七、碰撞检测系统
function checkCollisions() {
if (player.invulnerable > 0) {
player.invulnerable--;
return;
}
for (let bullet of bullets) {
const dx = player.x - bullet.x;
const dy = player.y - bullet.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < player.radius + bullet.radius) {
createParticles(player.x, player.y, CONFIG.player.color);
gameOver();
return;
}
}
}
// 十八、游戏状态管理
function gameOver() {
gameRunning = false;
const survivalTime = Math.floor((Date.now() - startTime) / 1000);
document.getElementById('finalTime').textContent = survivalTime;
document.getElementById('gameOver').style.display = 'block';
}
function resetGame() {
gameRunning = true;
startTime = Date.now();
difficulty = CONFIG.game.initialDifficulty;
bullets = [];
particles = [];
specialAttackTimer = 0;
player.x = canvas.width / 2;
player.y = canvas.height / 2;
player.invulnerable = 0;
document.getElementById('gameOver').style.display = 'none';
}
// 十九、绘制系统
function draw() {
// 1. 清除画布(带拖尾效果)
ctx.fillStyle = CONFIG.canvas.bgColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 2. 绘制粒子
particles.forEach(particle => {
ctx.beginPath();
ctx.arc(particle.x, particle.y, particle.radius, 0, Math.PI * 2);
ctx.fillStyle = particle.color;
ctx.globalAlpha = particle.life / CONFIG.effects.particleLife;
ctx.fill();
ctx.globalAlpha = 1;
});
// 3. 绘制子弹
bullets.forEach(bullet => {
// 突然子弹警告效果
if (bullet.type.sudden && bullet.warningTime > 0) {
ctx.beginPath();
ctx.arc(bullet.x, bullet.y, bullet.radius + 15, 0, Math.PI * 2);
ctx.strokeStyle = `rgba(255, 23, 68, ${bullet.warningTime / 30})`;
ctx.lineWidth = 2;
ctx.stroke();
}
// 子弹主体
ctx.beginPath();
ctx.arc(bullet.x, bullet.y, bullet.radius, 0, Math.PI * 2);
ctx.fillStyle = bullet.color;
ctx.fill();
// 子弹光晕
ctx.beginPath();
ctx.arc(bullet.x, bullet.y, bullet.radius + 3, 0, Math.PI * 2);
ctx.strokeStyle = bullet.color;
ctx.globalAlpha = 0.5;
ctx.lineWidth = 1;
ctx.stroke();
ctx.globalAlpha = 1;
});
// 4. 绘制玩家
ctx.beginPath();
ctx.arc(player.x, player.y, player.radius, 0, Math.PI * 2);
ctx.fillStyle = player.invulnerable > 0 ? 'rgba(255, 255, 255, 0.5)' : CONFIG.player.color;
ctx.fill();
// 玩家光晕
ctx.beginPath();
ctx.arc(player.x, player.y, player.radius + 8, 0, Math.PI * 2);
ctx.strokeStyle = CONFIG.player.glowColor;
ctx.lineWidth = 2;
ctx.stroke();
}
// 二十、游戏更新系统
function update() {
if (!gameRunning) return;
// 1. 更新玩家位置
updatePlayerPosition();
// 2. 更新难度
updateDifficulty();
// 3. 生成弹幕
spawnBullets();
// 4. 更新游戏对象
updateBullets();
updateParticles();
// 5. 碰撞检测
checkCollisions();
}
function updatePlayerPosition() {
const dx = mouseX - player.x;
const dy = mouseY - player.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 1) {
player.x += (dx / distance) * player.speed;
player.y += (dy / distance) * player.speed;
}
// 限制玩家在画布内
player.x = Math.max(player.radius, Math.min(canvas.width - player.radius, player.x));
player.y = Math.max(player.radius, Math.min(canvas.height - player.radius, player.y));
}
function updateDifficulty() {
const currentTime = Math.floor((Date.now() - startTime) / 1000);
difficulty = CONFIG.game.initialDifficulty + Math.floor(currentTime / CONFIG.game.difficultyIncreaseInterval);
// 更新UI
document.getElementById('time').textContent = currentTime;
document.getElementById('difficulty').textContent = difficulty;
}
// 二十一、游戏主循环
function gameLoop() {
update();
draw();
requestAnimationFrame(gameLoop);
}
// 二十二、启动游戏
window.addEventListener('DOMContentLoaded', init);
</script>
</body>
</html>
