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>

相关推荐
Hello.Reader2 小时前
Data Sink定义、参数与可落地示例
java·前端·网络
im_AMBER2 小时前
React 17
前端·javascript·笔记·学习·react.js·前端框架
一雨方知深秋2 小时前
2.fs模块对计算机硬盘进行读写操作(Promise进行封装)
javascript·node.js·promise·v8·cpython
LaoZhangGong1233 小时前
STM32 F103外部晶振8MHz改为12MHz,如何配置?
c语言·stm32·单片机·嵌入式硬件·晶振
谷歌开发者3 小时前
Web 开发指向标 | Chrome 开发者工具学习资源 (六)
前端·chrome·学习
一晌小贪欢3 小时前
【Html模板】电商运营可视化大屏模板 Excel存储 + 一键导出(已上线-可预览)
前端·数据分析·html·excel·数据看板·电商大屏·大屏看板
发现你走远了3 小时前
连接模拟器网页进行h5的调试(使用Chrome远程调试(推荐)) 保姆级图文
前端·chrome
街尾杂货店&4 小时前
css - 实现三角形 div 容器,用css画一个三角形(提供示例源码)简单粗暴几行代码搞定!
前端·css
顺凡4 小时前
删一个却少俩:Antd Tag 多节点同时消失的原因
前端·javascript·面试