2016 lines
77 KiB
HTML
2016 lines
77 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>星际文明探索者</title>
|
||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||
<style>
|
||
* {
|
||
margin: 0;
|
||
padding: 0;
|
||
box-sizing: border-box;
|
||
user-select: none;
|
||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||
}
|
||
|
||
body {
|
||
background-color: #0a0a1a;
|
||
color: #e0e0ff;
|
||
overflow: hidden;
|
||
height: 100vh;
|
||
width: 100vw;
|
||
}
|
||
|
||
/* 游戏容器 */
|
||
#game-container {
|
||
position: relative;
|
||
width: 100%;
|
||
height: 100%;
|
||
overflow: hidden;
|
||
}
|
||
|
||
/* 星空背景 */
|
||
#starfield {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
z-index: 1;
|
||
}
|
||
|
||
/* 游戏画布 */
|
||
#game-canvas {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
z-index: 2;
|
||
}
|
||
|
||
/* UI容器 */
|
||
#ui-container {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
z-index: 3;
|
||
pointer-events: none;
|
||
}
|
||
|
||
/* 半透明磨砂玻璃效果UI元素 */
|
||
.ui-panel {
|
||
background: rgba(20, 20, 60, 0.7);
|
||
backdrop-filter: blur(10px);
|
||
border: 1px solid rgba(100, 150, 255, 0.3);
|
||
border-radius: 12px;
|
||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
|
||
padding: 20px;
|
||
pointer-events: all;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.ui-panel:hover {
|
||
border-color: rgba(150, 200, 255, 0.5);
|
||
box-shadow: 0 8px 32px rgba(100, 150, 255, 0.2);
|
||
}
|
||
|
||
/* 标题样式 */
|
||
.game-title {
|
||
font-size: 2.8rem;
|
||
background: linear-gradient(90deg, #8a2be2, #00bfff, #8a2be2);
|
||
-webkit-background-clip: text;
|
||
background-clip: text;
|
||
color: transparent;
|
||
text-align: center;
|
||
text-shadow: 0 0 15px rgba(138, 43, 226, 0.5);
|
||
margin-bottom: 10px;
|
||
letter-spacing: 2px;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.ui-header {
|
||
font-size: 1.5rem;
|
||
color: #a0c8ff;
|
||
margin-bottom: 15px;
|
||
border-bottom: 1px solid rgba(100, 150, 255, 0.3);
|
||
padding-bottom: 8px;
|
||
text-shadow: 0 0 8px rgba(100, 150, 255, 0.5);
|
||
}
|
||
|
||
/* 按钮样式 */
|
||
.game-btn {
|
||
background: linear-gradient(135deg, rgba(30, 60, 150, 0.8), rgba(60, 100, 200, 0.8));
|
||
border: 1px solid rgba(100, 150, 255, 0.4);
|
||
border-radius: 8px;
|
||
color: #e0f0ff;
|
||
padding: 12px 24px;
|
||
font-size: 1.1rem;
|
||
cursor: pointer;
|
||
transition: all 0.3s ease;
|
||
text-align: center;
|
||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
||
margin: 5px;
|
||
pointer-events: all;
|
||
}
|
||
|
||
.game-btn:hover {
|
||
background: linear-gradient(135deg, rgba(40, 80, 180, 0.9), rgba(80, 130, 220, 0.9));
|
||
border-color: rgba(150, 200, 255, 0.7);
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 6px 16px rgba(100, 150, 255, 0.3);
|
||
}
|
||
|
||
.game-btn:active {
|
||
transform: translateY(1px);
|
||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
||
}
|
||
|
||
/* 状态栏 */
|
||
#status-bar {
|
||
position: absolute;
|
||
top: 20px;
|
||
left: 20px;
|
||
width: 300px;
|
||
z-index: 10;
|
||
}
|
||
|
||
.status-item {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
margin-bottom: 8px;
|
||
padding: 6px 10px;
|
||
background: rgba(0, 10, 30, 0.5);
|
||
border-radius: 6px;
|
||
border-left: 3px solid #00bfff;
|
||
}
|
||
|
||
.status-label {
|
||
font-weight: 600;
|
||
color: #a0c8ff;
|
||
}
|
||
|
||
.status-value {
|
||
font-weight: 700;
|
||
color: #7fffd4;
|
||
}
|
||
|
||
/* 资源面板 */
|
||
#resource-panel {
|
||
position: absolute;
|
||
top: 20px;
|
||
right: 20px;
|
||
width: 250px;
|
||
z-index: 10;
|
||
}
|
||
|
||
.resource-item {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 10px;
|
||
padding: 8px;
|
||
background: rgba(10, 20, 50, 0.5);
|
||
border-radius: 8px;
|
||
}
|
||
|
||
.resource-icon {
|
||
width: 30px;
|
||
height: 30px;
|
||
border-radius: 50%;
|
||
margin-right: 12px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 1.2rem;
|
||
}
|
||
|
||
.resource-info {
|
||
flex: 1;
|
||
}
|
||
|
||
.resource-name {
|
||
font-size: 0.9rem;
|
||
color: #b0d0ff;
|
||
}
|
||
|
||
.resource-amount {
|
||
font-size: 1.2rem;
|
||
font-weight: 700;
|
||
color: #7fffd4;
|
||
}
|
||
|
||
/* 控制面板 */
|
||
#control-panel {
|
||
position: absolute;
|
||
bottom: 20px;
|
||
left: 20px;
|
||
width: 300px;
|
||
z-index: 10;
|
||
}
|
||
|
||
.control-row {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
margin-bottom: 12px;
|
||
}
|
||
|
||
/* 星球扫描面板 */
|
||
#scan-panel {
|
||
position: absolute;
|
||
bottom: 20px;
|
||
right: 20px;
|
||
width: 350px;
|
||
z-index: 10;
|
||
display: none;
|
||
}
|
||
|
||
.planet-info {
|
||
margin-top: 15px;
|
||
}
|
||
|
||
.planet-property {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
margin-bottom: 6px;
|
||
padding: 5px;
|
||
background: rgba(20, 40, 80, 0.3);
|
||
border-radius: 4px;
|
||
}
|
||
|
||
/* 升级面板 */
|
||
#upgrade-panel {
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
width: 500px;
|
||
z-index: 20;
|
||
display: none;
|
||
}
|
||
|
||
.upgrade-option {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 15px;
|
||
padding: 15px;
|
||
background: rgba(30, 50, 100, 0.5);
|
||
border-radius: 10px;
|
||
cursor: pointer;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.upgrade-option:hover {
|
||
background: rgba(40, 70, 130, 0.7);
|
||
transform: translateX(5px);
|
||
}
|
||
|
||
.upgrade-icon {
|
||
width: 50px;
|
||
height: 50px;
|
||
border-radius: 10px;
|
||
margin-right: 15px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 1.8rem;
|
||
background: rgba(0, 50, 100, 0.7);
|
||
}
|
||
|
||
.upgrade-details {
|
||
flex: 1;
|
||
}
|
||
|
||
.upgrade-name {
|
||
font-size: 1.2rem;
|
||
color: #a0c8ff;
|
||
margin-bottom: 5px;
|
||
}
|
||
|
||
.upgrade-desc {
|
||
font-size: 0.9rem;
|
||
color: #b0c0e0;
|
||
margin-bottom: 5px;
|
||
}
|
||
|
||
.upgrade-cost {
|
||
display: flex;
|
||
align-items: center;
|
||
font-size: 0.9rem;
|
||
color: #ffcc00;
|
||
}
|
||
|
||
/* 开始屏幕 */
|
||
#start-screen {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
background: rgba(5, 5, 20, 0.9);
|
||
z-index: 100;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
align-items: center;
|
||
text-align: center;
|
||
}
|
||
|
||
/* 游戏结束屏幕 */
|
||
#game-over-screen {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
background: rgba(10, 5, 20, 0.95);
|
||
z-index: 100;
|
||
display: none;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
align-items: center;
|
||
text-align: center;
|
||
}
|
||
|
||
/* 提示信息 */
|
||
#hint-box {
|
||
position: absolute;
|
||
bottom: 80px;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
background: rgba(20, 30, 60, 0.8);
|
||
padding: 15px 25px;
|
||
border-radius: 10px;
|
||
border-left: 4px solid #00bfff;
|
||
max-width: 500px;
|
||
text-align: center;
|
||
display: none;
|
||
z-index: 15;
|
||
}
|
||
|
||
/* 响应式设计 */
|
||
@media (max-width: 1024px) {
|
||
#status-bar, #resource-panel, #control-panel, #scan-panel {
|
||
width: 250px;
|
||
}
|
||
|
||
.game-title {
|
||
font-size: 2.2rem;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 768px) {
|
||
#status-bar, #resource-panel {
|
||
width: 200px;
|
||
font-size: 0.9rem;
|
||
}
|
||
|
||
#control-panel {
|
||
width: calc(100% - 40px);
|
||
bottom: 10px;
|
||
left: 20px;
|
||
}
|
||
|
||
#scan-panel, #upgrade-panel {
|
||
width: calc(100% - 40px);
|
||
}
|
||
|
||
.game-btn {
|
||
padding: 10px 15px;
|
||
font-size: 1rem;
|
||
}
|
||
|
||
.game-title {
|
||
font-size: 1.8rem;
|
||
}
|
||
}
|
||
|
||
/* 动画类 */
|
||
@keyframes pulse {
|
||
0% { opacity: 0.7; }
|
||
50% { opacity: 1; }
|
||
100% { opacity: 0.7; }
|
||
}
|
||
|
||
@keyframes float {
|
||
0% { transform: translateY(0); }
|
||
50% { transform: translateY(-10px); }
|
||
100% { transform: translateY(0); }
|
||
}
|
||
|
||
@keyframes glow {
|
||
0% { box-shadow: 0 0 5px rgba(0, 191, 255, 0.5); }
|
||
50% { box-shadow: 0 0 20px rgba(0, 191, 255, 0.8); }
|
||
100% { box-shadow: 0 0 5px rgba(0, 191, 255, 0.5); }
|
||
}
|
||
|
||
.pulse {
|
||
animation: pulse 2s infinite;
|
||
}
|
||
|
||
.float {
|
||
animation: float 3s infinite ease-in-out;
|
||
}
|
||
|
||
.glow {
|
||
animation: glow 2s infinite;
|
||
}
|
||
|
||
/* 进度条 */
|
||
.progress-bar {
|
||
height: 8px;
|
||
background: rgba(50, 50, 100, 0.5);
|
||
border-radius: 4px;
|
||
overflow: hidden;
|
||
margin-top: 5px;
|
||
}
|
||
|
||
.progress-fill {
|
||
height: 100%;
|
||
background: linear-gradient(90deg, #00bfff, #8a2be2);
|
||
border-radius: 4px;
|
||
transition: width 0.5s ease;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div id="game-container">
|
||
<!-- 星空背景 -->
|
||
<canvas id="starfield"></canvas>
|
||
|
||
<!-- 游戏主画布 -->
|
||
<canvas id="game-canvas"></canvas>
|
||
|
||
<!-- UI容器 -->
|
||
<div id="ui-container">
|
||
<!-- 状态栏 -->
|
||
<div id="status-bar" class="ui-panel">
|
||
<div class="ui-header">飞船状态</div>
|
||
<div class="status-item">
|
||
<span class="status-label">船体完整性</span>
|
||
<span class="status-value" id="hull-integrity">100%</span>
|
||
</div>
|
||
<div class="status-item">
|
||
<span class="status-label">护盾能量</span>
|
||
<span class="status-value" id="shield-energy">100%</span>
|
||
</div>
|
||
<div class="status-item">
|
||
<span class="status-label">引擎功率</span>
|
||
<span class="status-value" id="engine-power">100%</span>
|
||
</div>
|
||
<div class="status-item">
|
||
<span class="status-label">扫描范围</span>
|
||
<span class="status-value" id="scan-range">5 AU</span>
|
||
</div>
|
||
<div class="status-item">
|
||
<span class="status-label">危险等级</span>
|
||
<span class="status-value" id="danger-level">低</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 资源面板 -->
|
||
<div id="resource-panel" class="ui-panel">
|
||
<div class="ui-header">资源库存</div>
|
||
<div class="resource-item">
|
||
<div class="resource-icon" style="background: rgba(255, 215, 0, 0.2); color: #ffd700;">
|
||
<i class="fas fa-gem"></i>
|
||
</div>
|
||
<div class="resource-info">
|
||
<div class="resource-name">稀有矿物</div>
|
||
<div class="resource-amount" id="mineral-count">0</div>
|
||
</div>
|
||
</div>
|
||
<div class="resource-item">
|
||
<div class="resource-icon" style="background: rgba(0, 191, 255, 0.2); color: #00bfff;">
|
||
<i class="fas fa-bolt"></i>
|
||
</div>
|
||
<div class="resource-info">
|
||
<div class="resource-name">能量晶体</div>
|
||
<div class="resource-amount" id="energy-count">50</div>
|
||
</div>
|
||
</div>
|
||
<div class="resource-item">
|
||
<div class="resource-icon" style="background: rgba(138, 43, 226, 0.2); color: #8a2be2;">
|
||
<i class="fas fa-shield-alt"></i>
|
||
</div>
|
||
<div class="resource-info">
|
||
<div class="resource-name">遗迹碎片</div>
|
||
<div class="resource-amount" id="artifact-count">0</div>
|
||
</div>
|
||
</div>
|
||
<div class="progress-bar">
|
||
<div class="progress-fill" id="storage-fill" style="width: 10%;"></div>
|
||
</div>
|
||
<div style="text-align: center; margin-top: 5px; font-size: 0.8rem; color: #a0c8ff;">
|
||
存储: <span id="storage-percent">10%</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 控制面板 -->
|
||
<div id="control-panel" class="ui-panel">
|
||
<div class="ui-header">飞船控制</div>
|
||
<div class="control-row">
|
||
<button id="scan-btn" class="game-btn">
|
||
<i class="fas fa-satellite-dish"></i> 扫描区域
|
||
</button>
|
||
<button id="warp-btn" class="game-btn">
|
||
<i class="fas fa-rocket"></i> 曲速跳跃
|
||
</button>
|
||
</div>
|
||
<div class="control-row">
|
||
<button id="upgrade-btn" class="game-btn">
|
||
<i class="fas fa-wrench"></i> 飞船升级
|
||
</button>
|
||
<button id="map-btn" class="game-btn">
|
||
<i class="fas fa-map"></i> 星图
|
||
</button>
|
||
</div>
|
||
<div style="margin-top: 15px; text-align: center; font-size: 0.9rem; color: #a0c8ff;">
|
||
<p>使用 <kbd>WASD</kbd> 控制移动 | <kbd>空格</kbd> 发射武器</p>
|
||
<p>鼠标瞄准 | <kbd>ESC</kbd> 暂停游戏</p>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 星球扫描面板 -->
|
||
<div id="scan-panel" class="ui-panel">
|
||
<div class="ui-header">星球扫描结果</div>
|
||
<div style="text-align: center; margin-bottom: 15px;">
|
||
<div id="planet-name" style="font-size: 1.3rem; color: #7fffd4;">未命名行星</div>
|
||
<div id="planet-type" style="font-size: 0.9rem; color: #b0d0ff;">类地行星</div>
|
||
</div>
|
||
<div class="planet-info">
|
||
<div class="planet-property">
|
||
<span>地质构成</span>
|
||
<span id="planet-geology">硅酸盐/金属</span>
|
||
</div>
|
||
<div class="planet-property">
|
||
<span>水资源</span>
|
||
<span id="planet-water">丰富</span>
|
||
</div>
|
||
<div class="planet-property">
|
||
<span>大气层</span>
|
||
<span id="planet-atmosphere">氮氧混合</span>
|
||
</div>
|
||
<div class="planet-property">
|
||
<span>可居住性</span>
|
||
<span id="planet-habitability">适宜</span>
|
||
</div>
|
||
<div class="planet-property">
|
||
<span>资源丰富度</span>
|
||
<span id="planet-resources">中等</span>
|
||
</div>
|
||
</div>
|
||
<button id="harvest-btn" class="game-btn" style="width: 100%; margin-top: 15px;">
|
||
<i class="fas fa-download"></i> 采集资源
|
||
</button>
|
||
</div>
|
||
|
||
<!-- 升级面板 -->
|
||
<div id="upgrade-panel" class="ui-panel">
|
||
<div class="ui-header">飞船升级系统</div>
|
||
<div style="text-align: center; margin-bottom: 15px; color: #a0c8ff;">
|
||
升级点: <span id="upgrade-points" style="color: #ffcc00; font-weight: bold;">5</span>
|
||
</div>
|
||
<div class="upgrade-option" data-upgrade="engine">
|
||
<div class="upgrade-icon" style="color: #00bfff;">
|
||
<i class="fas fa-tachometer-alt"></i>
|
||
</div>
|
||
<div class="upgrade-details">
|
||
<div class="upgrade-name">推进系统升级</div>
|
||
<div class="upgrade-desc">提高移动速度和加速度</div>
|
||
<div class="upgrade-cost">
|
||
<i class="fas fa-bolt" style="margin-right: 5px;"></i>
|
||
消耗: <span id="engine-cost">15</span> 能量晶体
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="upgrade-option" data-upgrade="weapon">
|
||
<div class="upgrade-icon" style="color: #ff4d4d;">
|
||
<i class="fas fa-crosshairs"></i>
|
||
</div>
|
||
<div class="upgrade-details">
|
||
<div class="upgrade-name">武器系统升级</div>
|
||
<div class="upgrade-desc">提高武器威力和射速</div>
|
||
<div class="upgrade-cost">
|
||
<i class="fas fa-bolt" style="margin-right: 5px;"></i>
|
||
消耗: <span id="weapon-cost">20</span> 能量晶体
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="upgrade-option" data-upgrade="shield">
|
||
<div class="upgrade-icon" style="color: #8a2be2;">
|
||
<i class="fas fa-shield-alt"></i>
|
||
</div>
|
||
<div class="upgrade-details">
|
||
<div class="upgrade-name">护盾系统升级</div>
|
||
<div class="upgrade-desc">提高护盾容量和恢复速度</div>
|
||
<div class="upgrade-cost">
|
||
<i class="fas fa-bolt" style="margin-right: 5px;"></i>
|
||
消耗: <span id="shield-cost">25</span> 能量晶体
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="upgrade-option" data-upgrade="scanner">
|
||
<div class="upgrade-icon" style="color: #7fffd4;">
|
||
<i class="fas fa-satellite-dish"></i>
|
||
</div>
|
||
<div class="upgrade-details">
|
||
<div class="upgrade-name">扫描系统升级</div>
|
||
<div class="upgrade-desc">提高扫描范围和资源发现概率</div>
|
||
<div class="upgrade-cost">
|
||
<i class="fas fa-bolt" style="margin-right: 5px;"></i>
|
||
消耗: <span id="scanner-cost">30</span> 能量晶体
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<button id="close-upgrade-btn" class="game-btn" style="width: 100%; margin-top: 15px;">
|
||
关闭升级面板
|
||
</button>
|
||
</div>
|
||
|
||
<!-- 提示信息 -->
|
||
<div id="hint-box" class="ui-panel">
|
||
<p id="hint-text">欢迎来到星际文明探索者!使用WASD控制飞船移动,空格键发射武器。</p>
|
||
</div>
|
||
|
||
<!-- 开始屏幕 -->
|
||
<div id="start-screen">
|
||
<h1 class="game-title float">星际文明探索者</h1>
|
||
<p style="margin-bottom: 30px; max-width: 600px; color: #b0c0e0; line-height: 1.6;">
|
||
作为一名星际探险家,你将驾驶先进的星际飞船在浩瀚宇宙中穿梭,探索未知星球,收集稀有资源,抵御宇宙威胁,并逐步揭开宇宙文明的神秘面纱。
|
||
</p>
|
||
<button id="start-btn" class="game-btn glow" style="font-size: 1.3rem; padding: 15px 40px;">
|
||
<i class="fas fa-play"></i> 开始探险
|
||
</button>
|
||
<div style="margin-top: 40px; color: #a0c8ff;">
|
||
<h3 style="margin-bottom: 15px;">游戏控制说明</h3>
|
||
<div style="display: flex; flex-wrap: wrap; justify-content: center; gap: 15px;">
|
||
<div style="text-align: center;">
|
||
<kbd style="display: block; margin-bottom: 5px;">W A S D</kbd>
|
||
<span>飞船移动</span>
|
||
</div>
|
||
<div style="text-align: center;">
|
||
<kbd style="display: block; margin-bottom: 5px;">鼠标</kbd>
|
||
<span>瞄准方向</span>
|
||
</div>
|
||
<div style="text-align: center;">
|
||
<kbd style="display: block; margin-bottom: 5px;">空格</kbd>
|
||
<span>发射武器</span>
|
||
</div>
|
||
<div style="text-align: center;">
|
||
<kbd style="display: block; margin-bottom: 5px;">E</kbd>
|
||
<span>交互/采集</span>
|
||
</div>
|
||
<div style="text-align: center;">
|
||
<kbd style="display: block; margin-bottom: 5px;">ESC</kbd>
|
||
<span>暂停游戏</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 游戏结束屏幕 -->
|
||
<div id="game-over-screen">
|
||
<h1 class="game-title" style="margin-bottom: 20px;">任务结束</h1>
|
||
<div id="game-stats" style="background: rgba(20, 30, 60, 0.7); padding: 25px; border-radius: 15px; margin-bottom: 30px; text-align: left;">
|
||
<h3 style="color: #a0c8ff; margin-bottom: 15px;">任务统计</h3>
|
||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px;">
|
||
<div>探索的星球: <span id="stat-planets">0</span></div>
|
||
<div>采集的资源: <span id="stat-resources">0</span></div>
|
||
<div>击败的敌人: <span id="stat-enemies">0</span></div>
|
||
<div>航行的距离: <span id="stat-distance">0 AU</span></div>
|
||
<div>获得的经验: <span id="stat-xp">0</span></div>
|
||
<div>游戏时间: <span id="stat-time">00:00</span></div>
|
||
</div>
|
||
</div>
|
||
<p id="game-over-message" style="margin-bottom: 30px; max-width: 500px; color: #b0c0e0; line-height: 1.6;">
|
||
你的飞船在探索过程中受损严重,任务结束。
|
||
</p>
|
||
<button id="restart-btn" class="game-btn" style="font-size: 1.3rem; padding: 15px 40px;">
|
||
<i class="fas fa-redo"></i> 重新开始
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
// 游戏主模块
|
||
const Game = (function() {
|
||
// 游戏状态
|
||
let gameState = {
|
||
isRunning: false,
|
||
isPaused: false,
|
||
gameTime: 0,
|
||
score: 0,
|
||
level: 1,
|
||
xp: 0,
|
||
xpToNextLevel: 100,
|
||
discoveredPlanets: 0,
|
||
enemiesDefeated: 0,
|
||
resourcesCollected: 0,
|
||
distanceTraveled: 0
|
||
};
|
||
|
||
// 飞船状态
|
||
let shipState = {
|
||
hull: 100,
|
||
shield: 100,
|
||
energy: 100,
|
||
speed: 5,
|
||
weaponPower: 1,
|
||
shieldCapacity: 100,
|
||
scanRange: 300,
|
||
storageCapacity: 100,
|
||
storageUsed: 0
|
||
};
|
||
|
||
// 资源库存
|
||
let resources = {
|
||
minerals: 0,
|
||
energyCrystals: 50,
|
||
artifacts: 0
|
||
};
|
||
|
||
// 飞船升级状态
|
||
let upgrades = {
|
||
engine: { level: 1, cost: 15 },
|
||
weapon: { level: 1, cost: 20 },
|
||
shield: { level: 1, cost: 25 },
|
||
scanner: { level: 1, cost: 30 }
|
||
};
|
||
|
||
// 当前目标星球
|
||
let currentPlanet = null;
|
||
|
||
// 获取游戏状态
|
||
function getState() {
|
||
return { ...gameState };
|
||
}
|
||
|
||
// 获取飞船状态
|
||
function getShipState() {
|
||
return { ...shipState };
|
||
}
|
||
|
||
// 获取资源
|
||
function getResources() {
|
||
return { ...resources };
|
||
}
|
||
|
||
// 开始游戏
|
||
function start() {
|
||
gameState.isRunning = true;
|
||
gameState.isPaused = false;
|
||
gameState.gameTime = 0;
|
||
gameState.score = 0;
|
||
gameState.level = 1;
|
||
gameState.xp = 0;
|
||
gameState.xpToNextLevel = 100;
|
||
gameState.discoveredPlanets = 0;
|
||
gameState.enemiesDefeated = 0;
|
||
gameState.resourcesCollected = 0;
|
||
gameState.distanceTraveled = 0;
|
||
|
||
shipState.hull = 100;
|
||
shipState.shield = 100;
|
||
shipState.energy = 100;
|
||
shipState.storageUsed = 0;
|
||
|
||
resources.minerals = 0;
|
||
resources.energyCrystals = 50;
|
||
resources.artifacts = 0;
|
||
|
||
console.log("游戏开始!");
|
||
}
|
||
|
||
// 暂停游戏
|
||
function pause() {
|
||
gameState.isPaused = true;
|
||
}
|
||
|
||
// 恢复游戏
|
||
function resume() {
|
||
gameState.isPaused = false;
|
||
}
|
||
|
||
// 更新游戏状态
|
||
function update(deltaTime) {
|
||
if (!gameState.isRunning || gameState.isPaused) return;
|
||
|
||
// 更新游戏时间
|
||
gameState.gameTime += deltaTime;
|
||
|
||
// 恢复护盾和能量
|
||
shipState.shield = Math.min(shipState.shield + 0.5 * deltaTime, shipState.shieldCapacity);
|
||
shipState.energy = Math.min(shipState.energy + 0.2 * deltaTime, 100);
|
||
|
||
// 更新UI
|
||
updateUI();
|
||
}
|
||
|
||
// 更新UI
|
||
function updateUI() {
|
||
// 更新状态栏
|
||
document.getElementById('hull-integrity').textContent = `${Math.round(shipState.hull)}%`;
|
||
document.getElementById('shield-energy').textContent = `${Math.round(shipState.shield)}%`;
|
||
document.getElementById('engine-power').textContent = `${Math.round(shipState.energy)}%`;
|
||
document.getElementById('scan-range').textContent = `${Math.round(shipState.scanRange / 60)} AU`;
|
||
|
||
// 更新危险等级
|
||
const dangerLevel = shipState.hull < 30 ? '高' : shipState.hull < 70 ? '中' : '低';
|
||
document.getElementById('danger-level').textContent = dangerLevel;
|
||
document.getElementById('danger-level').style.color =
|
||
dangerLevel === '高' ? '#ff4d4d' : dangerLevel === '中' ? '#ffcc00' : '#7fffd4';
|
||
|
||
// 更新资源显示
|
||
document.getElementById('mineral-count').textContent = resources.minerals;
|
||
document.getElementById('energy-count').textContent = resources.energyCrystals;
|
||
document.getElementById('artifact-count').textContent = resources.artifacts;
|
||
|
||
// 更新存储进度条
|
||
const storagePercent = (shipState.storageUsed / shipState.storageCapacity) * 100;
|
||
document.getElementById('storage-fill').style.width = `${storagePercent}%`;
|
||
document.getElementById('storage-percent').textContent = `${Math.round(storagePercent)}%`;
|
||
|
||
// 更新升级点数
|
||
document.getElementById('upgrade-points').textContent =
|
||
Math.floor(gameState.xp / 100) + 5 - (upgrades.engine.level + upgrades.weapon.level + upgrades.shield.level + upgrades.scanner.level) + 4;
|
||
}
|
||
|
||
// 添加经验值
|
||
function addXP(amount) {
|
||
gameState.xp += amount;
|
||
gameState.score += amount;
|
||
|
||
// 检查升级
|
||
while (gameState.xp >= gameState.xpToNextLevel) {
|
||
gameState.xp -= gameState.xpToNextLevel;
|
||
gameState.level++;
|
||
gameState.xpToNextLevel = Math.round(gameState.xpToNextLevel * 1.5);
|
||
|
||
// 显示升级消息
|
||
showHint(`恭喜!你的飞船升级到 ${gameState.level} 级!`);
|
||
}
|
||
}
|
||
|
||
// 采集资源
|
||
function collectResource(type, amount) {
|
||
const resourceNames = {
|
||
'mineral': '稀有矿物',
|
||
'energy': '能量晶体',
|
||
'artifact': '遗迹碎片'
|
||
};
|
||
|
||
// 检查存储空间
|
||
const newStorage = shipState.storageUsed + amount;
|
||
if (newStorage > shipState.storageCapacity) {
|
||
showHint('存储空间不足!请先升级存储系统或使用资源。');
|
||
return false;
|
||
}
|
||
|
||
// 添加资源
|
||
switch(type) {
|
||
case 'mineral':
|
||
resources.minerals += amount;
|
||
break;
|
||
case 'energy':
|
||
resources.energyCrystals += amount;
|
||
break;
|
||
case 'artifact':
|
||
resources.artifacts += amount;
|
||
break;
|
||
}
|
||
|
||
shipState.storageUsed += amount;
|
||
gameState.resourcesCollected += amount;
|
||
|
||
// 显示提示
|
||
showHint(`采集到 ${amount} 单位 ${resourceNames[type]}!`);
|
||
|
||
// 添加经验值
|
||
addXP(amount * 5);
|
||
|
||
return true;
|
||
}
|
||
|
||
// 使用资源
|
||
function useResource(type, amount) {
|
||
switch(type) {
|
||
case 'mineral':
|
||
if (resources.minerals < amount) return false;
|
||
resources.minerals -= amount;
|
||
break;
|
||
case 'energy':
|
||
if (resources.energyCrystals < amount) return false;
|
||
resources.energyCrystals -= amount;
|
||
break;
|
||
case 'artifact':
|
||
if (resources.artifacts < amount) return false;
|
||
resources.artifacts -= amount;
|
||
break;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
// 飞船受到伤害
|
||
function takeDamage(amount) {
|
||
// 先减少护盾
|
||
if (shipState.shield > 0) {
|
||
const shieldDamage = Math.min(amount, shipState.shield);
|
||
shipState.shield -= shieldDamage;
|
||
amount -= shieldDamage;
|
||
}
|
||
|
||
// 剩余伤害减少船体
|
||
if (amount > 0) {
|
||
shipState.hull -= amount;
|
||
|
||
// 检查游戏是否结束
|
||
if (shipState.hull <= 0) {
|
||
shipState.hull = 0;
|
||
gameOver('你的飞船在探索过程中受损严重,任务结束。');
|
||
}
|
||
}
|
||
}
|
||
|
||
// 修复飞船
|
||
function repairShip(amount) {
|
||
shipState.hull = Math.min(shipState.hull + amount, 100);
|
||
}
|
||
|
||
// 升级飞船系统
|
||
function upgradeSystem(system) {
|
||
const upgrade = upgrades[system];
|
||
const cost = upgrade.cost;
|
||
|
||
// 检查是否有足够的资源
|
||
if (resources.energyCrystals < cost) {
|
||
showHint(`能量晶体不足!需要 ${cost} 单位。`);
|
||
return false;
|
||
}
|
||
|
||
// 消耗资源并升级
|
||
resources.energyCrystals -= cost;
|
||
upgrade.level++;
|
||
upgrade.cost = Math.round(upgrade.cost * 1.8);
|
||
|
||
// 应用升级效果
|
||
switch(system) {
|
||
case 'engine':
|
||
shipState.speed += 1;
|
||
showHint(`推进系统升级到 ${upgrade.level} 级!速度增加。`);
|
||
break;
|
||
case 'weapon':
|
||
shipState.weaponPower += 0.5;
|
||
showHint(`武器系统升级到 ${upgrade.level} 级!威力增加。`);
|
||
break;
|
||
case 'shield':
|
||
shipState.shieldCapacity += 20;
|
||
shipState.shield = shipState.shieldCapacity;
|
||
showHint(`护盾系统升级到 ${upgrade.level} 级!容量增加。`);
|
||
break;
|
||
case 'scanner':
|
||
shipState.scanRange += 50;
|
||
shipState.storageCapacity += 20;
|
||
showHint(`扫描系统升级到 ${upgrade.level} 级!扫描范围和存储空间增加。`);
|
||
break;
|
||
}
|
||
|
||
// 添加经验值
|
||
addXP(50);
|
||
|
||
return true;
|
||
}
|
||
|
||
// 扫描星球
|
||
function scanPlanet(planet) {
|
||
currentPlanet = planet;
|
||
gameState.discoveredPlanets++;
|
||
|
||
// 更新扫描面板
|
||
document.getElementById('planet-name').textContent = planet.name;
|
||
document.getElementById('planet-type').textContent = planet.type;
|
||
document.getElementById('planet-geology').textContent = planet.geology;
|
||
document.getElementById('planet-water').textContent = planet.water;
|
||
document.getElementById('planet-atmosphere').textContent = planet.atmosphere;
|
||
document.getElementById('planet-habitability').textContent = planet.habitability;
|
||
document.getElementById('planet-resources').textContent = planet.resources;
|
||
|
||
// 显示扫描面板
|
||
document.getElementById('scan-panel').style.display = 'block';
|
||
|
||
// 添加经验值
|
||
addXP(20);
|
||
|
||
// 显示提示
|
||
showHint(`发现 ${planet.name}!类型:${planet.type}`);
|
||
}
|
||
|
||
// 从星球采集资源
|
||
function harvestFromPlanet() {
|
||
if (!currentPlanet) return;
|
||
|
||
const resources = {
|
||
'类地行星': { mineral: 5, energy: 3, artifact: 1 },
|
||
'气态巨行星': { mineral: 2, energy: 8, artifact: 0 },
|
||
'冰冻星球': { mineral: 3, energy: 2, artifact: 3 },
|
||
'荒漠星球': { mineral: 8, energy: 1, artifact: 2 },
|
||
'海洋星球': { mineral: 2, energy: 4, artifact: 4 }
|
||
};
|
||
|
||
const planetResources = resources[currentPlanet.type] || resources['类地行星'];
|
||
|
||
// 采集各种资源
|
||
let harvested = false;
|
||
if (planetResources.mineral > 0) {
|
||
harvested = collectResource('mineral', planetResources.mineral) || harvested;
|
||
}
|
||
if (planetResources.energy > 0) {
|
||
harvested = collectResource('energy', planetResources.energy) || harvested;
|
||
}
|
||
if (planetResources.artifact > 0) {
|
||
harvested = collectResource('artifact', planetResources.artifact) || harvested;
|
||
}
|
||
|
||
if (harvested) {
|
||
showHint(`成功从 ${currentPlanet.name} 采集资源!`);
|
||
}
|
||
}
|
||
|
||
// 击败敌人
|
||
function defeatEnemy() {
|
||
gameState.enemiesDefeated++;
|
||
addXP(30);
|
||
|
||
// 有几率掉落资源
|
||
if (Math.random() > 0.5) {
|
||
collectResource('energy', Math.floor(Math.random() * 3) + 1);
|
||
}
|
||
}
|
||
|
||
// 显示提示
|
||
function showHint(message, duration = 3000) {
|
||
const hintBox = document.getElementById('hint-box');
|
||
const hintText = document.getElementById('hint-text');
|
||
|
||
hintText.textContent = message;
|
||
hintBox.style.display = 'block';
|
||
|
||
// 自动隐藏
|
||
clearTimeout(window.hintTimeout);
|
||
window.hintTimeout = setTimeout(() => {
|
||
hintBox.style.display = 'none';
|
||
}, duration);
|
||
}
|
||
|
||
// 游戏结束
|
||
function gameOver(message) {
|
||
gameState.isRunning = false;
|
||
|
||
// 更新游戏统计
|
||
document.getElementById('stat-planets').textContent = gameState.discoveredPlanets;
|
||
document.getElementById('stat-resources').textContent = gameState.resourcesCollected;
|
||
document.getElementById('stat-enemies').textContent = gameState.enemiesDefeated;
|
||
document.getElementById('stat-distance').textContent = `${Math.round(gameState.distanceTraveled)} AU`;
|
||
document.getElementById('stat-xp').textContent = gameState.xp;
|
||
|
||
// 格式化游戏时间
|
||
const minutes = Math.floor(gameState.gameTime / 60);
|
||
const seconds = Math.floor(gameState.gameTime % 60);
|
||
document.getElementById('stat-time').textContent =
|
||
`${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
|
||
|
||
// 设置结束消息
|
||
document.getElementById('game-over-message').textContent = message;
|
||
|
||
// 显示游戏结束屏幕
|
||
document.getElementById('game-over-screen').style.display = 'flex';
|
||
}
|
||
|
||
// 重新开始游戏
|
||
function restart() {
|
||
start();
|
||
document.getElementById('game-over-screen').style.display = 'none';
|
||
}
|
||
|
||
return {
|
||
getState,
|
||
getShipState,
|
||
getResources,
|
||
start,
|
||
pause,
|
||
resume,
|
||
update,
|
||
collectResource,
|
||
useResource,
|
||
takeDamage,
|
||
repairShip,
|
||
upgradeSystem,
|
||
scanPlanet,
|
||
harvestFromPlanet,
|
||
defeatEnemy,
|
||
showHint,
|
||
gameOver,
|
||
restart,
|
||
addXP
|
||
};
|
||
})();
|
||
|
||
// 渲染引擎模块
|
||
const Renderer = (function() {
|
||
// Canvas元素和上下文
|
||
let canvas, ctx, starfieldCanvas, starfieldCtx;
|
||
// 游戏对象
|
||
let ship, planets, enemies, projectiles, particles, resources;
|
||
// 视口尺寸
|
||
let viewportWidth, viewportHeight;
|
||
// 相机偏移
|
||
let cameraX = 0, cameraY = 0;
|
||
// 上次更新时间
|
||
let lastTime = 0;
|
||
|
||
// 初始化渲染器
|
||
function init() {
|
||
canvas = document.getElementById('game-canvas');
|
||
ctx = canvas.getContext('2d');
|
||
|
||
starfieldCanvas = document.getElementById('starfield');
|
||
starfieldCtx = starfieldCanvas.getContext('2d');
|
||
|
||
// 初始化游戏对象数组
|
||
planets = [];
|
||
enemies = [];
|
||
projectiles = [];
|
||
particles = [];
|
||
resources = [];
|
||
|
||
// 创建飞船
|
||
ship = {
|
||
x: 0,
|
||
y: 0,
|
||
width: 40,
|
||
height: 60,
|
||
color: '#00bfff',
|
||
enginePower: 0,
|
||
rotation: 0,
|
||
targetRotation: 0
|
||
};
|
||
|
||
// 生成初始游戏世界
|
||
generateWorld();
|
||
|
||
// 设置视口尺寸
|
||
resize();
|
||
|
||
// 开始渲染循环
|
||
requestAnimationFrame(render);
|
||
|
||
console.log("渲染器初始化完成");
|
||
}
|
||
|
||
// 调整画布尺寸
|
||
function resize() {
|
||
viewportWidth = window.innerWidth;
|
||
viewportHeight = window.innerHeight;
|
||
|
||
canvas.width = viewportWidth;
|
||
canvas.height = viewportHeight;
|
||
|
||
starfieldCanvas.width = viewportWidth;
|
||
starfieldCanvas.height = viewportHeight;
|
||
|
||
// 重新生成星空背景
|
||
generateStarfield();
|
||
}
|
||
|
||
// 生成星空背景
|
||
function generateStarfield() {
|
||
starfieldCtx.fillStyle = '#0a0a1a';
|
||
starfieldCtx.fillRect(0, 0, viewportWidth, viewportHeight);
|
||
|
||
// 绘制星星
|
||
starfieldCtx.fillStyle = '#ffffff';
|
||
for (let i = 0; i < 200; i++) {
|
||
const x = Math.random() * viewportWidth;
|
||
const y = Math.random() * viewportHeight;
|
||
const radius = Math.random() * 1.5;
|
||
|
||
starfieldCtx.beginPath();
|
||
starfieldCtx.arc(x, y, radius, 0, Math.PI * 2);
|
||
starfieldCtx.fill();
|
||
}
|
||
|
||
// 绘制星云
|
||
const gradient = starfieldCtx.createRadialGradient(
|
||
viewportWidth * 0.7, viewportHeight * 0.3, 0,
|
||
viewportWidth * 0.7, viewportHeight * 0.3, 300
|
||
);
|
||
gradient.addColorStop(0, 'rgba(138, 43, 226, 0.1)');
|
||
gradient.addColorStop(1, 'rgba(138, 43, 226, 0)');
|
||
|
||
starfieldCtx.fillStyle = gradient;
|
||
starfieldCtx.fillRect(0, 0, viewportWidth, viewportHeight);
|
||
|
||
// 另一个星云
|
||
const gradient2 = starfieldCtx.createRadialGradient(
|
||
viewportWidth * 0.3, viewportHeight * 0.7, 0,
|
||
viewportWidth * 0.3, viewportHeight * 0.7, 250
|
||
);
|
||
gradient2.addColorStop(0, 'rgba(0, 191, 255, 0.1)');
|
||
gradient2.addColorStop(1, 'rgba(0, 191, 255, 0)');
|
||
|
||
starfieldCtx.fillStyle = gradient2;
|
||
starfieldCtx.fillRect(0, 0, viewportWidth, viewportHeight);
|
||
}
|
||
|
||
// 生成游戏世界
|
||
function generateWorld() {
|
||
// 生成行星
|
||
const planetTypes = ['类地行星', '气态巨行星', '冰冻星球', '荒漠星球', '海洋星球'];
|
||
const planetColors = ['#4CAF50', '#FF9800', '#B3E5FC', '#795548', '#2196F3'];
|
||
const geologyTypes = ['硅酸盐/金属', '氢/氦大气', '冰/岩石', '硅酸盐/铁', '水/硅酸盐'];
|
||
const waterLevels = ['丰富', '微量', '冰封', '缺乏', '丰富'];
|
||
const atmospheres = ['氮氧混合', '氢氦', '二氧化碳', '稀薄', '氮氧混合'];
|
||
const habitabilities = ['适宜', '不适宜', '极端', '不适宜', '适宜'];
|
||
const resourceLevels = ['中等', '丰富', '贫乏', '中等', '丰富'];
|
||
|
||
for (let i = 0; i < 15; i++) {
|
||
const angle = Math.random() * Math.PI * 2;
|
||
const distance = 300 + Math.random() * 600;
|
||
const size = 20 + Math.random() * 40;
|
||
const typeIndex = Math.floor(Math.random() * planetTypes.length);
|
||
|
||
planets.push({
|
||
x: Math.cos(angle) * distance,
|
||
y: Math.sin(angle) * distance,
|
||
size: size,
|
||
color: planetColors[typeIndex],
|
||
type: planetTypes[typeIndex],
|
||
name: `行星 ${String.fromCharCode(65 + i)}-${Math.floor(Math.random() * 1000)}`,
|
||
geology: geologyTypes[typeIndex],
|
||
water: waterLevels[typeIndex],
|
||
atmosphere: atmospheres[typeIndex],
|
||
habitability: habitabilities[typeIndex],
|
||
resources: resourceLevels[typeIndex]
|
||
});
|
||
}
|
||
|
||
// 生成敌人
|
||
for (let i = 0; i < 8; i++) {
|
||
const angle = Math.random() * Math.PI * 2;
|
||
const distance = 200 + Math.random() * 500;
|
||
|
||
enemies.push({
|
||
x: Math.cos(angle) * distance,
|
||
y: Math.sin(angle) * distance,
|
||
size: 15 + Math.random() * 10,
|
||
color: '#ff4d4d',
|
||
speed: 0.5 + Math.random() * 1,
|
||
angle: Math.random() * Math.PI * 2,
|
||
health: 3
|
||
});
|
||
}
|
||
|
||
// 生成资源
|
||
for (let i = 0; i < 20; i++) {
|
||
const angle = Math.random() * Math.PI * 2;
|
||
const distance = 150 + Math.random() * 700;
|
||
const resourceTypes = ['mineral', 'energy', 'artifact'];
|
||
const type = resourceTypes[Math.floor(Math.random() * resourceTypes.length)];
|
||
const colors = {
|
||
mineral: '#ffd700',
|
||
energy: '#00bfff',
|
||
artifact: '#8a2be2'
|
||
};
|
||
|
||
resources.push({
|
||
x: Math.cos(angle) * distance,
|
||
y: Math.sin(angle) * distance,
|
||
size: 8 + Math.random() * 6,
|
||
color: colors[type],
|
||
type: type
|
||
});
|
||
}
|
||
}
|
||
|
||
// 渲染游戏世界
|
||
function render(currentTime) {
|
||
// 计算时间增量
|
||
const deltaTime = lastTime ? (currentTime - lastTime) / 1000 : 0;
|
||
lastTime = currentTime;
|
||
|
||
// 更新游戏状态
|
||
if (Game.getState().isRunning && !Game.getState().isPaused) {
|
||
Game.update(deltaTime);
|
||
updateWorld(deltaTime);
|
||
}
|
||
|
||
// 清除画布
|
||
ctx.clearRect(0, 0, viewportWidth, viewportHeight);
|
||
|
||
// 保存上下文状态
|
||
ctx.save();
|
||
|
||
// 应用相机变换(跟随飞船)
|
||
cameraX += (ship.x - cameraX) * 0.1;
|
||
cameraY += (ship.y - cameraY) * 0.1;
|
||
ctx.translate(viewportWidth / 2 - cameraX, viewportHeight / 2 - cameraY);
|
||
|
||
// 绘制游戏对象
|
||
drawResources();
|
||
drawPlanets();
|
||
drawEnemies();
|
||
drawProjectiles();
|
||
drawParticles();
|
||
drawShip();
|
||
|
||
// 恢复上下文状态
|
||
ctx.restore();
|
||
|
||
// 绘制扫描范围
|
||
if (document.getElementById('scan-btn').classList.contains('active')) {
|
||
drawScanRange();
|
||
}
|
||
|
||
// 继续渲染循环
|
||
requestAnimationFrame(render);
|
||
}
|
||
|
||
// 更新游戏世界
|
||
function updateWorld(deltaTime) {
|
||
const shipState = Game.getShipState();
|
||
|
||
// 更新飞船旋转
|
||
ship.rotation += (ship.targetRotation - ship.rotation) * 0.1;
|
||
|
||
// 更新飞船位置(由输入处理模块处理)
|
||
|
||
// 更新敌人
|
||
for (let i = enemies.length - 1; i >= 0; i--) {
|
||
const enemy = enemies[i];
|
||
|
||
// 移动敌人
|
||
enemy.x += Math.cos(enemy.angle) * enemy.speed;
|
||
enemy.y += Math.sin(enemy.angle) * enemy.speed;
|
||
|
||
// 随机改变方向
|
||
if (Math.random() < 0.01) {
|
||
enemy.angle += (Math.random() - 0.5) * 0.5;
|
||
}
|
||
|
||
// 检查与飞船的碰撞
|
||
const dx = ship.x - enemy.x;
|
||
const dy = ship.y - enemy.y;
|
||
const distance = Math.sqrt(dx * dx + dy * dy);
|
||
|
||
if (distance < (ship.width / 2 + enemy.size)) {
|
||
// 碰撞发生
|
||
Game.takeDamage(5);
|
||
|
||
// 创建爆炸粒子
|
||
createExplosion(enemy.x, enemy.y, enemy.color);
|
||
|
||
// 移除敌人
|
||
enemies.splice(i, 1);
|
||
Game.defeatEnemy();
|
||
|
||
// 生成新敌人
|
||
const angle = Math.random() * Math.PI * 2;
|
||
const distance = 400 + Math.random() * 500;
|
||
|
||
enemies.push({
|
||
x: ship.x + Math.cos(angle) * distance,
|
||
y: ship.y + Math.sin(angle) * distance,
|
||
size: 15 + Math.random() * 10,
|
||
color: '#ff4d4d',
|
||
speed: 0.5 + Math.random() * 1,
|
||
angle: Math.random() * Math.PI * 2,
|
||
health: 3
|
||
});
|
||
}
|
||
}
|
||
|
||
// 更新弹幕
|
||
for (let i = projectiles.length - 1; i >= 0; i--) {
|
||
const proj = projectiles[i];
|
||
|
||
// 移动弹幕
|
||
proj.x += Math.cos(proj.angle) * proj.speed;
|
||
proj.y += Math.sin(proj.angle) * proj.speed;
|
||
|
||
// 检查弹幕是否超出范围
|
||
const dx = proj.x - ship.x;
|
||
const dy = proj.y - ship.y;
|
||
const distance = Math.sqrt(dx * dx + dy * dy);
|
||
|
||
if (distance > 1000) {
|
||
projectiles.splice(i, 1);
|
||
continue;
|
||
}
|
||
|
||
// 检查弹幕与敌人的碰撞
|
||
for (let j = enemies.length - 1; j >= 0; j--) {
|
||
const enemy = enemies[j];
|
||
const edx = proj.x - enemy.x;
|
||
const edy = proj.y - enemy.y;
|
||
const edistance = Math.sqrt(edx * edx + edy * edy);
|
||
|
||
if (edistance < (proj.size + enemy.size)) {
|
||
// 击中敌人
|
||
enemy.health--;
|
||
|
||
// 创建击中粒子
|
||
createHitParticles(enemy.x, enemy.y, proj.color);
|
||
|
||
// 移除弹幕
|
||
projectiles.splice(i, 1);
|
||
|
||
// 如果敌人被击败
|
||
if (enemy.health <= 0) {
|
||
// 创建爆炸粒子
|
||
createExplosion(enemy.x, enemy.y, enemy.color);
|
||
|
||
// 移除敌人
|
||
enemies.splice(j, 1);
|
||
Game.defeatEnemy();
|
||
|
||
// 生成新敌人
|
||
const angle = Math.random() * Math.PI * 2;
|
||
const distance = 400 + Math.random() * 500;
|
||
|
||
enemies.push({
|
||
x: ship.x + Math.cos(angle) * distance,
|
||
y: ship.y + Math.sin(angle) * distance,
|
||
size: 15 + Math.random() * 10,
|
||
color: '#ff4d4d',
|
||
speed: 0.5 + Math.random() * 1,
|
||
angle: Math.random() * Math.PI * 2,
|
||
health: 3
|
||
});
|
||
}
|
||
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 更新粒子
|
||
for (let i = particles.length - 1; i >= 0; i--) {
|
||
const particle = particles[i];
|
||
|
||
// 更新粒子位置
|
||
particle.x += particle.vx;
|
||
particle.y += particle.vy;
|
||
|
||
// 更新粒子生命周期
|
||
particle.life -= deltaTime;
|
||
|
||
// 如果粒子生命周期结束,移除它
|
||
if (particle.life <= 0) {
|
||
particles.splice(i, 1);
|
||
}
|
||
}
|
||
|
||
// 检查资源采集
|
||
for (let i = resources.length - 1; i >= 0; i--) {
|
||
const resource = resources[i];
|
||
const dx = ship.x - resource.x;
|
||
const dy = ship.y - resource.y;
|
||
const distance = Math.sqrt(dx * dx + dy * dy);
|
||
|
||
// 如果飞船靠近资源
|
||
if (distance < (ship.width / 2 + resource.size + 10)) {
|
||
// 采集资源
|
||
const amount = Math.floor(Math.random() * 3) + 1;
|
||
const collected = Game.collectResource(resource.type, amount);
|
||
|
||
if (collected) {
|
||
// 创建采集粒子
|
||
createCollectionParticles(resource.x, resource.y, resource.color);
|
||
|
||
// 移除资源
|
||
resources.splice(i, 1);
|
||
|
||
// 生成新资源
|
||
const angle = Math.random() * Math.PI * 2;
|
||
const distance = 300 + Math.random() * 800;
|
||
|
||
const resourceTypes = ['mineral', 'energy', 'artifact'];
|
||
const type = resourceTypes[Math.floor(Math.random() * resourceTypes.length)];
|
||
const colors = {
|
||
mineral: '#ffd700',
|
||
energy: '#00bfff',
|
||
artifact: '#8a2be2'
|
||
};
|
||
|
||
resources.push({
|
||
x: ship.x + Math.cos(angle) * distance,
|
||
y: ship.y + Math.sin(angle) * distance,
|
||
size: 8 + Math.random() * 6,
|
||
color: colors[type],
|
||
type: type
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
// 检查行星扫描
|
||
for (const planet of planets) {
|
||
const dx = ship.x - planet.x;
|
||
const dy = ship.y - planet.y;
|
||
const distance = Math.sqrt(dx * dx + dy * dy);
|
||
|
||
// 如果飞船靠近行星
|
||
if (distance < (ship.width / 2 + planet.size + 50)) {
|
||
// 自动扫描行星
|
||
Game.scanPlanet(planet);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 绘制飞船
|
||
function drawShip() {
|
||
ctx.save();
|
||
ctx.translate(ship.x, ship.y);
|
||
ctx.rotate(ship.rotation);
|
||
|
||
// 绘制飞船主体
|
||
ctx.fillStyle = ship.color;
|
||
ctx.beginPath();
|
||
ctx.moveTo(0, -ship.height / 2);
|
||
ctx.lineTo(ship.width / 2, ship.height / 2);
|
||
ctx.lineTo(-ship.width / 2, ship.height / 2);
|
||
ctx.closePath();
|
||
ctx.fill();
|
||
|
||
// 绘制飞船细节
|
||
ctx.fillStyle = '#ffffff';
|
||
ctx.fillRect(-8, -10, 16, 8);
|
||
|
||
// 绘制引擎火焰
|
||
if (ship.enginePower > 0) {
|
||
const flameHeight = 15 + ship.enginePower * 10;
|
||
const flameWidth = 8 + ship.enginePower * 4;
|
||
|
||
ctx.fillStyle = '#ff9900';
|
||
ctx.beginPath();
|
||
ctx.moveTo(-flameWidth / 2, ship.height / 2);
|
||
ctx.lineTo(0, ship.height / 2 + flameHeight);
|
||
ctx.lineTo(flameWidth / 2, ship.height / 2);
|
||
ctx.closePath();
|
||
ctx.fill();
|
||
|
||
// 添加火焰粒子
|
||
if (Math.random() < 0.7) {
|
||
particles.push({
|
||
x: ship.x + Math.cos(ship.rotation + Math.PI) * (ship.height / 2 + 5),
|
||
y: ship.y + Math.sin(ship.rotation + Math.PI) * (ship.height / 2 + 5),
|
||
size: 3 + Math.random() * 4,
|
||
color: `rgba(255, ${Math.floor(100 + Math.random() * 155)}, 0, 1)`,
|
||
vx: Math.cos(ship.rotation + Math.PI + (Math.random() - 0.5) * 0.3) * (3 + Math.random() * 5),
|
||
vy: Math.sin(ship.rotation + Math.PI + (Math.random() - 0.5) * 0.3) * (3 + Math.random() * 5),
|
||
life: 0.5 + Math.random() * 0.5
|
||
});
|
||
}
|
||
}
|
||
|
||
ctx.restore();
|
||
}
|
||
|
||
// 绘制行星
|
||
function drawPlanets() {
|
||
for (const planet of planets) {
|
||
// 绘制行星
|
||
ctx.fillStyle = planet.color;
|
||
ctx.beginPath();
|
||
ctx.arc(planet.x, planet.y, planet.size, 0, Math.PI * 2);
|
||
ctx.fill();
|
||
|
||
// 绘制行星环(仅限气态巨行星)
|
||
if (planet.type === '气态巨行星') {
|
||
ctx.strokeStyle = 'rgba(255, 215, 0, 0.5)';
|
||
ctx.lineWidth = 3;
|
||
ctx.beginPath();
|
||
ctx.arc(planet.x, planet.y, planet.size + 15, 0, Math.PI * 2);
|
||
ctx.stroke();
|
||
|
||
ctx.strokeStyle = 'rgba(255, 215, 0, 0.3)';
|
||
ctx.lineWidth = 2;
|
||
ctx.beginPath();
|
||
ctx.arc(planet.x, planet.y, planet.size + 25, 0, Math.PI * 2);
|
||
ctx.stroke();
|
||
}
|
||
|
||
// 绘制行星名称
|
||
ctx.fillStyle = '#ffffff';
|
||
ctx.font = '12px Arial';
|
||
ctx.textAlign = 'center';
|
||
ctx.fillText(planet.name, planet.x, planet.y - planet.size - 10);
|
||
}
|
||
}
|
||
|
||
// 绘制敌人
|
||
function drawEnemies() {
|
||
for (const enemy of enemies) {
|
||
// 绘制敌人
|
||
ctx.fillStyle = enemy.color;
|
||
ctx.beginPath();
|
||
ctx.arc(enemy.x, enemy.y, enemy.size, 0, Math.PI * 2);
|
||
ctx.fill();
|
||
|
||
// 绘制敌人细节
|
||
ctx.fillStyle = '#000000';
|
||
ctx.beginPath();
|
||
ctx.arc(enemy.x, enemy.y, enemy.size * 0.6, 0, Math.PI * 2);
|
||
ctx.fill();
|
||
}
|
||
}
|
||
|
||
// 绘制资源
|
||
function drawResources() {
|
||
for (const resource of resources) {
|
||
// 绘制资源
|
||
ctx.fillStyle = resource.color;
|
||
ctx.beginPath();
|
||
ctx.arc(resource.x, resource.y, resource.size, 0, Math.PI * 2);
|
||
ctx.fill();
|
||
|
||
// 绘制资源发光效果
|
||
ctx.shadowColor = resource.color;
|
||
ctx.shadowBlur = 10;
|
||
ctx.beginPath();
|
||
ctx.arc(resource.x, resource.y, resource.size * 0.7, 0, Math.PI * 2);
|
||
ctx.fill();
|
||
ctx.shadowBlur = 0;
|
||
}
|
||
}
|
||
|
||
// 绘制弹幕
|
||
function drawProjectiles() {
|
||
for (const proj of projectiles) {
|
||
// 绘制弹幕
|
||
ctx.fillStyle = proj.color;
|
||
ctx.beginPath();
|
||
ctx.arc(proj.x, proj.y, proj.size, 0, Math.PI * 2);
|
||
ctx.fill();
|
||
|
||
// 绘制弹幕发光效果
|
||
ctx.shadowColor = proj.color;
|
||
ctx.shadowBlur = 15;
|
||
ctx.beginPath();
|
||
ctx.arc(proj.x, proj.y, proj.size * 0.5, 0, Math.PI * 2);
|
||
ctx.fill();
|
||
ctx.shadowBlur = 0;
|
||
}
|
||
}
|
||
|
||
// 绘制粒子
|
||
function drawParticles() {
|
||
for (const particle of particles) {
|
||
ctx.globalAlpha = particle.life;
|
||
ctx.fillStyle = particle.color;
|
||
ctx.beginPath();
|
||
ctx.arc(particle.x, particle.y, particle.size, 0, Math.PI * 2);
|
||
ctx.fill();
|
||
}
|
||
ctx.globalAlpha = 1;
|
||
}
|
||
|
||
// 绘制扫描范围
|
||
function drawScanRange() {
|
||
const scanRange = Game.getShipState().scanRange;
|
||
|
||
ctx.strokeStyle = 'rgba(0, 191, 255, 0.3)';
|
||
ctx.lineWidth = 2;
|
||
ctx.setLineDash([5, 5]);
|
||
ctx.beginPath();
|
||
ctx.arc(ship.x, ship.y, scanRange, 0, Math.PI * 2);
|
||
ctx.stroke();
|
||
ctx.setLineDash([]);
|
||
|
||
// 绘制扫描脉冲效果
|
||
const pulseSize = (Date.now() % 2000) / 2000 * scanRange;
|
||
ctx.strokeStyle = `rgba(0, 191, 255, ${0.5 - pulseSize/scanRange})`;
|
||
ctx.lineWidth = 1;
|
||
ctx.beginPath();
|
||
ctx.arc(ship.x, ship.y, pulseSize, 0, Math.PI * 2);
|
||
ctx.stroke();
|
||
}
|
||
|
||
// 创建爆炸粒子
|
||
function createExplosion(x, y, color) {
|
||
for (let i = 0; i < 30; i++) {
|
||
const angle = Math.random() * Math.PI * 2;
|
||
const speed = 1 + Math.random() * 5;
|
||
|
||
particles.push({
|
||
x: x,
|
||
y: y,
|
||
size: 2 + Math.random() * 4,
|
||
color: color,
|
||
vx: Math.cos(angle) * speed,
|
||
vy: Math.sin(angle) * speed,
|
||
life: 0.5 + Math.random() * 0.5
|
||
});
|
||
}
|
||
}
|
||
|
||
// 创建击中粒子
|
||
function createHitParticles(x, y, color) {
|
||
for (let i = 0; i < 10; i++) {
|
||
const angle = Math.random() * Math.PI * 2;
|
||
const speed = 1 + Math.random() * 3;
|
||
|
||
particles.push({
|
||
x: x,
|
||
y: y,
|
||
size: 1 + Math.random() * 2,
|
||
color: color,
|
||
vx: Math.cos(angle) * speed,
|
||
vy: Math.sin(angle) * speed,
|
||
life: 0.3 + Math.random() * 0.3
|
||
});
|
||
}
|
||
}
|
||
|
||
// 创建采集粒子
|
||
function createCollectionParticles(x, y, color) {
|
||
for (let i = 0; i < 15; i++) {
|
||
const angle = Math.random() * Math.PI * 2;
|
||
const speed = 0.5 + Math.random() * 2;
|
||
|
||
particles.push({
|
||
x: x,
|
||
y: y,
|
||
size: 2 + Math.random() * 3,
|
||
color: color,
|
||
vx: Math.cos(angle) * speed,
|
||
vy: Math.sin(angle) * speed,
|
||
life: 0.4 + Math.random() * 0.4
|
||
});
|
||
}
|
||
}
|
||
|
||
// 发射弹幕
|
||
function shoot() {
|
||
const shipState = Game.getShipState();
|
||
|
||
projectiles.push({
|
||
x: ship.x,
|
||
y: ship.y,
|
||
size: 4,
|
||
color: '#00ffcc',
|
||
angle: ship.rotation,
|
||
speed: 10 + shipState.weaponPower * 2
|
||
});
|
||
|
||
// 创建发射粒子
|
||
createHitParticles(
|
||
ship.x + Math.cos(ship.rotation) * ship.height / 2,
|
||
ship.y + Math.sin(ship.rotation) * ship.height / 2,
|
||
'#00ffcc'
|
||
);
|
||
}
|
||
|
||
// 移动飞船
|
||
function moveShip(dx, dy) {
|
||
const shipState = Game.getShipState();
|
||
|
||
ship.x += dx * shipState.speed;
|
||
ship.y += dy * shipState.speed;
|
||
|
||
// 更新飞船目标旋转角度
|
||
if (dx !== 0 || dy !== 0) {
|
||
ship.targetRotation = Math.atan2(dy, dx);
|
||
}
|
||
|
||
// 更新引擎功率
|
||
ship.enginePower = Math.sqrt(dx * dx + dy * dy);
|
||
|
||
// 更新旅行距离
|
||
if (Game.getState().isRunning) {
|
||
const gameState = Game.getState();
|
||
gameState.distanceTraveled += Math.sqrt(dx * dx + dy * dy) * 0.01;
|
||
}
|
||
}
|
||
|
||
// 获取飞船位置
|
||
function getShipPosition() {
|
||
return { x: ship.x, y: ship.y };
|
||
}
|
||
|
||
return {
|
||
init,
|
||
resize,
|
||
shoot,
|
||
moveShip,
|
||
getShipPosition
|
||
};
|
||
})();
|
||
|
||
// 输入处理模块
|
||
const InputHandler = (function() {
|
||
// 按键状态
|
||
let keys = {};
|
||
// 鼠标状态
|
||
let mouse = { x: 0, y: 0, down: false };
|
||
|
||
// 初始化输入处理
|
||
function init() {
|
||
// 键盘事件监听
|
||
document.addEventListener('keydown', (e) => {
|
||
keys[e.key.toLowerCase()] = true;
|
||
|
||
// 空格键发射武器
|
||
if (e.key === ' ' && Game.getState().isRunning && !Game.getState().isPaused) {
|
||
Renderer.shoot();
|
||
e.preventDefault();
|
||
}
|
||
|
||
// ESC键暂停游戏
|
||
if (e.key === 'Escape') {
|
||
if (Game.getState().isRunning) {
|
||
if (Game.getState().isPaused) {
|
||
Game.resume();
|
||
document.getElementById('upgrade-panel').style.display = 'none';
|
||
} else {
|
||
Game.pause();
|
||
}
|
||
}
|
||
}
|
||
|
||
// E键交互/采集
|
||
if (e.key === 'e' || e.key === 'E') {
|
||
if (document.getElementById('scan-panel').style.display === 'block') {
|
||
Game.harvestFromPlanet();
|
||
}
|
||
}
|
||
});
|
||
|
||
document.addEventListener('keyup', (e) => {
|
||
keys[e.key.toLowerCase()] = false;
|
||
});
|
||
|
||
// 鼠标事件监听
|
||
document.addEventListener('mousemove', (e) => {
|
||
mouse.x = e.clientX;
|
||
mouse.y = e.clientY;
|
||
});
|
||
|
||
document.addEventListener('mousedown', () => {
|
||
mouse.down = true;
|
||
});
|
||
|
||
document.addEventListener('mouseup', () => {
|
||
mouse.down = false;
|
||
});
|
||
|
||
// 防止上下文菜单
|
||
document.addEventListener('contextmenu', (e) => {
|
||
e.preventDefault();
|
||
});
|
||
|
||
console.log("输入处理器初始化完成");
|
||
}
|
||
|
||
// 更新输入状态
|
||
function update() {
|
||
// 处理飞船移动
|
||
let dx = 0, dy = 0;
|
||
|
||
if (keys['w'] || keys['arrowup']) dy -= 1;
|
||
if (keys['s'] || keys['arrowdown']) dy += 1;
|
||
if (keys['a'] || keys['arrowleft']) dx -= 1;
|
||
if (keys['d'] || keys['arrowright']) dx += 1;
|
||
|
||
// 归一化对角线移动
|
||
if (dx !== 0 && dy !== 0) {
|
||
const length = Math.sqrt(dx * dx + dy * dy);
|
||
dx /= length;
|
||
dy /= length;
|
||
}
|
||
|
||
// 更新飞船位置
|
||
Renderer.moveShip(dx, dy);
|
||
}
|
||
|
||
return {
|
||
init,
|
||
update
|
||
};
|
||
})();
|
||
|
||
// UI管理器模块
|
||
const UIManager = (function() {
|
||
// 初始化UI
|
||
function init() {
|
||
// 开始按钮
|
||
document.getElementById('start-btn').addEventListener('click', () => {
|
||
Game.start();
|
||
document.getElementById('start-screen').style.display = 'none';
|
||
Game.showHint('开始星际探险!探索未知星球,收集资源,升级你的飞船。');
|
||
});
|
||
|
||
// 重新开始按钮
|
||
document.getElementById('restart-btn').addEventListener('click', () => {
|
||
Game.restart();
|
||
});
|
||
|
||
// 扫描按钮
|
||
document.getElementById('scan-btn').addEventListener('click', () => {
|
||
const btn = document.getElementById('scan-btn');
|
||
btn.classList.toggle('active');
|
||
|
||
if (btn.classList.contains('active')) {
|
||
Game.showHint('扫描模式已激活。靠近星球自动扫描。');
|
||
} else {
|
||
Game.showHint('扫描模式已关闭。');
|
||
}
|
||
});
|
||
|
||
// 曲速跳跃按钮
|
||
document.getElementById('warp-btn').addEventListener('click', () => {
|
||
Game.showHint('曲速引擎正在充能...需要更多能量晶体!', 2000);
|
||
});
|
||
|
||
// 升级按钮
|
||
document.getElementById('upgrade-btn').addEventListener('click', () => {
|
||
document.getElementById('upgrade-panel').style.display = 'block';
|
||
Game.pause();
|
||
});
|
||
|
||
// 关闭升级面板按钮
|
||
document.getElementById('close-upgrade-btn').addEventListener('click', () => {
|
||
document.getElementById('upgrade-panel').style.display = 'none';
|
||
Game.resume();
|
||
});
|
||
|
||
// 升级选项
|
||
document.querySelectorAll('.upgrade-option').forEach(option => {
|
||
option.addEventListener('click', () => {
|
||
const system = option.getAttribute('data-upgrade');
|
||
Game.upgradeSystem(system);
|
||
});
|
||
});
|
||
|
||
// 采集资源按钮
|
||
document.getElementById('harvest-btn').addEventListener('click', () => {
|
||
Game.harvestFromPlanet();
|
||
});
|
||
|
||
// 星图按钮
|
||
document.getElementById('map-btn').addEventListener('click', () => {
|
||
Game.showHint('星图功能开发中...', 2000);
|
||
});
|
||
|
||
console.log("UI管理器初始化完成");
|
||
}
|
||
|
||
return {
|
||
init
|
||
};
|
||
})();
|
||
|
||
// 游戏主循环
|
||
function gameLoop() {
|
||
// 更新输入状态
|
||
InputHandler.update();
|
||
|
||
// 继续下一帧
|
||
requestAnimationFrame(gameLoop);
|
||
}
|
||
|
||
// 页面加载完成后初始化游戏
|
||
window.addEventListener('load', () => {
|
||
// 初始化各个模块
|
||
Renderer.init();
|
||
InputHandler.init();
|
||
UIManager.init();
|
||
|
||
// 启动游戏主循环
|
||
gameLoop();
|
||
|
||
// 窗口大小调整
|
||
window.addEventListener('resize', () => {
|
||
Renderer.resize();
|
||
});
|
||
|
||
// 显示使用说明
|
||
console.log("=== 星际文明探索者 - 操作指南 ===");
|
||
console.log("1. 使用 WASD 或方向键控制飞船移动");
|
||
console.log("2. 使用空格键发射武器");
|
||
console.log("3. 鼠标用于瞄准方向");
|
||
console.log("4. 靠近星球自动扫描");
|
||
console.log("5. 采集资源并升级飞船系统");
|
||
console.log("6. 击败敌人获得经验值和资源");
|
||
console.log("7. 使用 ESC 键暂停游戏");
|
||
console.log("8. 点击升级按钮打开升级面板");
|
||
console.log("9. 点击扫描按钮启用/禁用扫描模式");
|
||
console.log("10. 点击曲速跳跃进行长距离移动");
|
||
console.log("================================");
|
||
});
|
||
</script>
|
||
</body>
|
||
</html> |