<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>董测浩解救许子昂 - 手机冒险游戏</title>
<style>
/* 所有样式保持不变,已在原代码中提供 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
-webkit-tap-highlight-color: transparent;
touch-action: manipulation;
}
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);
overflow: hidden;
padding: 10px;
width: 100%;
height: 100%;
touch-action: none;
}
/* 横屏提示 */
#orientationWarning {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.95);
display: none;
flex-direction: column;
justify-content: center;
align-items: center;
color: white;
z-index: 1000;
padding: 20px;
text-align: center;
}
#orientationWarning h2 {
color: #FFD700;
margin-bottom: 20px;
font-size: 2rem;
}
#orientationWarning p {
font-size: 1.2rem;
margin-bottom: 30px;
max-width: 80%;
line-height: 1.5;
}
#orientationWarning .rotate-icon {
font-size: 4rem;
margin: 20px 0;
animation: rotate 2s infinite;
}
@keyframes rotate {
0% { transform: rotate(0deg); }
100% { transform: rotate(90deg); }
}
#gameContainer {
position: relative;
width: 100%;
max-width: 1024px;
height: 100vh;
max-height: 100vh;
box-shadow: 0 15px 35px rgba(0, 0, 0, 0.5);
border-radius: 10px;
overflow: hidden;
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.2);
}
#gameCanvas {
display: block;
width: 100%;
height: 70%;
background: linear-gradient(to bottom, #87CEEB, #1E90FF);
}
/* 移动端控制按钮 */
#mobileControls {
position: absolute;
bottom: 20px;
width: 100%;
display: flex;
justify-content: space-between;
padding: 0 20px;
z-index: 100;
pointer-events: none;
}
.control-group {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
pointer-events: auto;
}
.direction-controls {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(2, 1fr);
gap: 8px;
}
.action-controls {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: repeat(2, 1fr);
gap: 8px;
}
.control-btn {
width: 60px;
height: 60px;
border-radius: 50%;
background: rgba(0, 0, 0, 0.7);
border: 2px solid rgba(255, 255, 255, 0.3);
color: white;
font-size: 1.2rem;
font-weight: bold;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
user-select: none;
-webkit-user-select: none;
backdrop-filter: blur(5px);
transition: all 0.1s;
touch-action: manipulation;
}
.control-btn:active {
transform: scale(0.9);
background: rgba(0, 0, 0, 0.9);
border-color: rgba(255, 255, 255, 0.6);
}
.control-btn.move-btn {
background: rgba(52, 152, 219, 0.8);
}
.control-btn.jump-btn {
background: rgba(46, 204, 113, 0.8);
grid-column: 2;
grid-row: 1;
}
.control-btn.shoot-btn {
background: rgba(231, 76, 60, 0.8);
}
.control-btn.skill-btn {
background: rgba(241, 196, 15, 0.8);
}
.control-btn.ability-btn {
background: rgba(155, 89, 182, 0.8);
}
.control-btn.pause-btn {
background: rgba(52, 73, 94, 0.8);
width: 50px;
height: 50px;
font-size: 1rem;
}
.control-btn.long-btn {
width: 140px;
border-radius: 30px;
font-size: 1rem;
}
/* 顶部玩家信息栏 */
#topBar {
display: flex;
justify-content: space-between;
padding: 10px 15px;
background: rgba(0, 0, 0, 0.85);
color: white;
border-bottom: 2px solid rgba(255, 255, 255, 0.1);
position: absolute;
top: 0;
left: 0;
right: 0;
z-index: 25;
}
.player-status {
display: flex;
align-items: center;
gap: 10px;
flex-wrap: wrap;
}
.player-info {
display: flex;
align-items: center;
gap: 6px;
background: rgba(255, 255, 255, 0.1);
padding: 6px 10px;
border-radius: 15px;
border: 1px solid rgba(255, 255, 255, 0.2);
font-size: 0.9rem;
}
.player-icon {
width: 28px;
height: 28px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
color: white;
font-size: 0.9rem;
background: linear-gradient(135deg, #3498db, #2980b9);
}
.skill-status {
display: flex;
align-items: center;
gap: 4px;
font-size: 0.8rem;
}
.skill-indicator {
width: 10px;
height: 10px;
border-radius: 50%;
background: #2ecc71;
}
.skill-indicator.cooldown {
background: #e74c3c;
}
.level-info {
display: flex;
align-items: center;
gap: 8px;
background: rgba(255, 255, 255, 0.1);
padding: 6px 12px;
border-radius: 15px;
border: 1px solid rgba(255, 255, 255, 0.2);
font-size: 0.9rem;
}
/* 游戏开始界面 */
#startScreen {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.95);
display: none;
flex-direction: column;
justify-content: center;
align-items: center;
color: white;
z-index: 30;
padding: 20px;
text-align: center;
}
#gameTitle {
margin-bottom: 20px;
text-align: center;
}
h1 {
font-size: 2.2rem;
margin-bottom: 10px;
color: #FFD700;
text-shadow: 2px 2px 0 #FF5722, 3px 3px 0 rgba(0, 0, 0, 0.2);
letter-spacing: 1px;
font-weight: 800;
}
h2 {
font-size: 1.3rem;
color: #4FC3F7;
text-shadow: 1px 1px 0 #0288D1;
font-weight: 600;
}
.game-description {
max-width: 90%;
background: rgba(255, 255, 255, 0.1);
padding: 15px;
border-radius: 15px;
margin: 15px 0 20px;
backdrop-filter: blur(5px);
border: 2px solid rgba(255, 255, 255, 0.2);
line-height: 1.5;
font-size: 1rem;
}
.mobile-controls-info {
display: flex;
flex-direction: column;
gap: 15px;
margin: 15px 0 25px;
width: 90%;
}
.mobile-control-set {
background: rgba(255, 255, 255, 0.1);
padding: 15px;
border-radius: 15px;
backdrop-filter: blur(5px);
border: 2px solid rgba(255, 255, 255, 0.2);
}
.control-title {
font-size: 1.1rem;
margin-bottom: 10px;
color: #FFD700;
font-weight: 600;
}
.mobile-control-row {
display: flex;
align-items: center;
gap: 10px;
margin: 8px 0;
}
.mobile-btn-demo {
width: 50px;
height: 50px;
border-radius: 50%;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: bold;
font-size: 1rem;
border: 2px solid rgba(255, 255, 255, 0.3);
}
.mobile-btn-demo.move {
background: rgba(52, 152, 219, 0.8);
}
.mobile-btn-demo.jump {
background: rgba(46, 204, 113, 0.8);
}
.mobile-btn-demo.shoot {
background: rgba(231, 76, 60, 0.8);
}
.mobile-btn-demo.skill {
background: rgba(241, 196, 15, 0.8);
}
button {
background: linear-gradient(to bottom, #FF5722, #E64A19);
border: none;
color: white;
padding: 14px 35px;
border-radius: 50px;
cursor: pointer;
font-size: 1.2rem;
font-weight: 600;
margin-top: 10px;
transition: all 0.3s;
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.3);
border: 2px solid rgba(255, 255, 255, 0.2);
letter-spacing: 1px;
min-height: 50px;
min-width: 200px;
}
button:hover {
background: linear-gradient(to bottom, #FF7043, #F4511E);
transform: translateY(-3px);
box-shadow: 0 12px 25px rgba(0, 0, 0, 0.4);
}
button:active {
transform: translateY(-1px);
}
/* 公告屏幕 */
#announcementScreen {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.95);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
color: white;
z-index: 35;
padding: 20px;
text-align: center;
}
#announcementContent {
max-width: 90%;
background: rgba(255, 255, 255, 0.1);
padding: 25px;
border-radius: 20px;
backdrop-filter: blur(10px);
border: 2px solid rgba(255, 255, 255, 0.2);
margin-bottom: 20px;
}
#announcementContent h2 {
font-size: 1.8rem;
margin-bottom: 15px;
color: #FFD700;
}
#announcementContent p {
margin: 10px 0;
line-height: 1.6;
font-size: 1rem;
}
.copyright {
margin-top: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 0.9rem;
}
/* 游戏UI */
#ui {
position: absolute;
top: 70px;
left: 10px;
right: 10px;
display: flex;
justify-content: space-between;
color: white;
font-size: 1rem;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.7);
z-index: 10;
}
#levelComplete {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0, 0, 0, 0.95);
color: white;
padding: 25px 35px;
border-radius: 20px;
text-align: center;
display: none;
z-index: 25;
backdrop-filter: blur(10px);
border: 3px solid rgba(255, 255, 255, 0.2);
box-shadow: 0 0 40px rgba(0, 0, 0, 0.7);
width: 90%;
max-width: 500px;
}
#levelComplete h2 {
font-size: 2rem;
margin-bottom: 15px;
color: #FFD700;
text-shadow: 2px 2px 0 #FF5722;
}
/* 响应式设计 - 针对横屏优化 */
@media (max-width: 768px) and (orientation: portrait) {
#orientationWarning {
display: flex;
}
#gameContainer {
display: none;
}
}
@media (orientation: landscape) {
#orientationWarning {
display: none;
}
#gameContainer {
display: block;
}
}
@media (max-width: 768px) and (orientation: landscape) {
body {
padding: 5px;
}
#gameContainer {
max-width: 100%;
height: 100vh;
border-radius: 0;
}
h1 {
font-size: 1.8rem;
}
h2 {
font-size: 1.1rem;
}
.game-description {
font-size: 0.9rem;
padding: 12px;
}
button {
padding: 12px 30px;
font-size: 1.1rem;
min-height: 44px;
}
#levelComplete {
padding: 20px 25px;
}
#levelComplete h2 {
font-size: 1.6rem;
}
.control-btn {
width: 55px;
height: 55px;
font-size: 1.1rem;
}
.control-btn.long-btn {
width: 130px;
font-size: 0.9rem;
}
/* 横屏下画布更大 */
#gameCanvas {
height: 75%;
}
#mobileControls {
bottom: 10px;
}
#topBar {
padding: 8px 10px;
}
}
/* 横屏优化 */
@media (orientation: landscape) {
#gameCanvas {
height: 80%;
}
#mobileControls {
bottom: 10px;
}
.control-btn {
width: 45px;
height: 45px;
font-size: 0.9rem;
}
.control-btn.long-btn {
width: 100px;
font-size: 0.8rem;
}
#topBar {
padding: 8px 10px;
}
}
/* 动画效果 */
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.05); }
100% { transform: scale(1); }
}
.pulse {
animation: pulse 2s infinite;
}
.floating {
animation: floating 3s ease-in-out infinite;
}
@keyframes floating {
0% { transform: translateY(0px); }
50% { transform: translateY(-8px); }
100% { transform: translateY(0px); }
}
/* 游戏UI元素 */
#pauseScreen {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.95);
display: none;
flex-direction: column;
justify-content: center;
align-items: center;
color: white;
z-index: 40;
padding: 20px;
text-align: center;
}
#pauseScreen h2 {
font-size: 2.2rem;
margin-bottom: 20px;
color: #FFD700;
}
#pauseScreen button {
margin: 8px;
width: 200px;
max-width: 80%;
}
#gameStats {
display: flex;
flex-direction: column;
gap: 8px;
margin-top: 15px;
background: rgba(255, 255, 255, 0.1);
padding: 12px;
border-radius: 10px;
backdrop-filter: blur(5px);
border: 2px solid rgba(255, 255, 255, 0.2);
}
.stat-item {
display: flex;
justify-content: space-between;
font-size: 0.9rem;
}
#bossHealthBar {
position: absolute;
top: 8px;
left: 50%;
transform: translateX(-50%);
width: 300px;
height: 20px;
background: rgba(0, 0, 0, 0.5);
border-radius: 10px;
overflow: hidden;
display: none;
z-index: 20;
border: 2px solid rgba(255, 255, 255, 0.2);
}
#bossHealthFill {
height: 100%;
background: linear-gradient(to right, #FF5722, #FFD700);
width: 100%;
transition: width 0.3s;
}
#bossName {
position: absolute;
top: -25px;
left: 0;
width: 100%;
text-align: center;
color: white;
font-weight: bold;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.7);
font-size: 1rem;
}
#powerUpDisplay {
position: absolute;
bottom: 180px;
left: 10px;
display: flex;
gap: 8px;
color: white;
font-size: 0.8rem;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.7);
background: rgba(0, 0, 0, 0.5);
padding: 8px 12px;
border-radius: 10px;
backdrop-filter: blur(5px);
border: 2px solid rgba(255, 255, 255, 0.2);
}
.powerUp-item {
display: flex;
align-items: center;
gap: 4px;
}
.powerUp-icon {
width: 14px;
height: 14px;
border-radius: 50%;
}
.laser-icon {
background: #2196F3;
}
.shield-icon {
background: #4CAF50;
}
#scoreDisplay {
position: absolute;
top: 60px;
right: 10px;
color: white;
font-size: 1rem;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.7);
background: rgba(0, 0, 0, 0.5);
padding: 8px 12px;
border-radius: 10px;
backdrop-filter: blur(5px);
border: 2px solid rgba(255, 255, 255, 0.2);
}
#comboDisplay {
position: absolute;
top: 60px;
left: 10px;
color: white;
font-size: 1rem;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.7);
background: rgba(0, 0, 0, 0.5);
padding: 8px 12px;
border-radius: 10px;
backdrop-filter: blur(5px);
border: 2px solid rgba(255, 255, 255, 0.2);
display: none;
}
.damage-popup {
position: absolute;
color: #ff5555;
font-weight: bold;
font-size: 14px;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.7);
animation: floatUp 1s ease-out forwards;
pointer-events: none;
}
@keyframes floatUp {
0% {
transform: translateY(0);
opacity: 1;
}
100% {
transform: translateY(-40px);
opacity: 0;
}
}
.screen-shake {
animation: shake 0.5s ease-in-out;
}
@keyframes shake {
0%, 100% { transform: translateX(0); }
10%, 30%, 50%, 70%, 90% { transform: translateX(-5px); }
20%, 40%, 60%, 80% { transform: translateX(5px); }
}
#checkpointIndicator {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
font-size: 0.8rem;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.7);
background: rgba(0, 0, 0, 0.5);
padding: 10px 20px;
border-radius: 10px;
backdrop-filter: blur(5px);
border: 2px solid rgba(255, 255, 255, 0.2);
display: none;
z-index: 30;
}
/* 对话系统 */
#dialogueScreen {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.95);
display: none;
flex-direction: column;
justify-content: center;
align-items: center;
color: white;
z-index: 50;
padding: 20px;
text-align: center;
}
#dialogueContent {
max-width: 90%;
background: rgba(255, 255, 255, 0.1);
padding: 20px;
border-radius: 20px;
backdrop-filter: blur(10px);
border: 2px solid rgba(255, 255, 255, 0.2);
margin-bottom: 20px;
}
#dialogueText {
font-size: 1.1rem;
line-height: 1.5;
margin-bottom: 15px;
text-align: left;
}
#dialogueSpeaker {
font-size: 1rem;
color: #FFD700;
text-align: left;
margin-bottom: 10px;
font-weight: bold;
}
#dialogueNext {
background: linear-gradient(to bottom, #4CAF50, #2E7D32);
border: none;
color: white;
padding: 10px 25px;
border-radius: 50px;
cursor: pointer;
font-size: 1rem;
font-weight: 600;
transition: all 0.3s;
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.3);
border: 2px solid rgba(255, 255, 255, 0.2);
min-height: 44px;
}
#dialogueNext:hover {
background: linear-gradient(to bottom, #66BB6A, #388E3C);
transform: translateY(-3px);
}
/* 设置界面 */
#settingsScreen {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.95);
display: none;
flex-direction: column;
justify-content: center;
align-items: center;
color: white;
z-index: 60;
padding: 20px;
text-align: center;
}
#settingsContent {
max-width: 90%;
background: rgba(255, 255, 255, 0.1);
padding: 25px;
border-radius: 20px;
backdrop-filter: blur(10px);
border: 2px solid rgba(255, 255, 255, 0.2);
margin-bottom: 20px;
}
.level-select {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 12px;
margin: 15px 0;
}
.level-btn {
padding: 12px;
background: rgba(255, 255, 255, 0.1);
border: 2px solid rgba(255, 255, 255, 0.2);
border-radius: 10px;
color: white;
font-size: 1rem;
cursor: pointer;
transition: all 0.3s;
min-height: 44px;
}
.level-btn:hover {
background: rgba(255, 255, 255, 0.2);
transform: translateY(-3px);
}
.level-btn.locked {
opacity: 0.5;
cursor: not-allowed;
}
.level-btn.completed {
background: rgba(76, 175, 80, 0.3);
border-color: #4CAF50;
}
/* 玩家名字显示 */
.player-name {
position: absolute;
top: -20px;
left: 50%;
transform: translateX(-50%);
color: white;
font-weight: bold;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.7);
background: rgba(0, 0, 0, 0.5);
padding: 2px 8px;
border-radius: 8px;
font-size: 0.8rem;
white-space: nowrap;
z-index: 5;
}
/* 被绑架的许子昂 */
.kidnapped-person {
position: absolute;
width: 35px;
height: 50px;
background: #9C27B0;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: bold;
font-size: 0.7rem;
text-align: center;
z-index: 10;
}
/* 天神效果 */
.god-effect {
position: absolute;
width: 100%;
height: 100%;
background: radial-gradient(circle, rgba(255, 215, 0, 0.3) 0%, transparent 70%);
z-index: 5;
pointer-events: none;
animation: godPulse 2s infinite;
}
@keyframes godPulse {
0% { opacity: 0.5; }
50% { opacity: 0.8; }
100% { opacity: 0.5; }
}
/* 天神降临效果 */
.god-arrival {
position: absolute;
top: -80px;
left: 50%;
transform: translateX(-50%);
color: #FFD700;
font-size: 1.5rem;
font-weight: bold;
text-shadow: 0 0 10px rgba(255, 215, 0, 0.8);
animation: fallDown 1s ease-out forwards;
z-index: 100;
}
@keyframes fallDown {
0% { top: -80px; opacity: 0; }
100% { top: 50%; opacity: 1; }
}
/* 触摸设备优化 */
@media (hover: none) and (pointer: coarse) {
button, .level-btn, .control-btn {
min-height: 44px;
}
.mobile-btn-demo {
width: 45px;
height: 45px;
}
}
/* 竖屏优化 */
@media (orientation: portrait) and (max-height: 700px) {
#gameCanvas {
height: 65%;
}
#powerUpDisplay {
bottom: 160px;
}
}
/* 超大屏幕优化 */
@media (min-width: 768px) and (min-height: 1024px) {
#gameContainer {
max-width: 768px;
max-height: 1024px;
}
h1 {
font-size: 2.5rem;
}
h2 {
font-size: 1.5rem;
}
.game-description {
font-size: 1.2rem;
}
button {
padding: 15px 40px;
font-size: 1.3rem;
}
.control-btn {
width: 70px;
height: 70px;
font-size: 1.3rem;
}
.control-btn.long-btn {
width: 160px;
font-size: 1.1rem;
}
}
/* 防止长按菜单 */
.no-context-menu {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
/* 设置中的帧率选项 */
.fps-selector {
display: flex;
flex-direction: column;
gap: 10px;
margin: 15px 0;
align-items: center;
}
.fps-option {
padding: 10px 20px;
background: rgba(255, 255, 255, 0.1);
border: 2px solid rgba(255, 255, 255, 0.2);
border-radius: 10px;
color: white;
font-size: 1rem;
cursor: pointer;
transition: all 0.3s;
min-width: 150px;
}
.fps-option:hover {
background: rgba(255, 255, 255, 0.2);
}
.fps-option.selected {
background: rgba(76, 175, 80, 0.3);
border-color: #4CAF50;
}
/* 机关类样式 */
.trap {
position: absolute;
width: 40px;
height: 40px;
background: #FF9800;
border-radius: 5px;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: bold;
font-size: 0.8rem;
z-index: 10;
cursor: pointer;
}
.trap.active {
background: #4CAF50;
animation: pulse 1s infinite;
}
/* 小兵生成效果 */
.minion-spawn {
position: absolute;
width: 30px;
height: 30px;
background: radial-gradient(circle, rgba(255, 0, 0, 0.8) 0%, transparent 70%);
animation: spawnEffect 0.5s ease-out forwards;
z-index: 10;
}
@keyframes spawnEffect {
0% { transform: scale(0); opacity: 0; }
50% { transform: scale(1.5); opacity: 1; }
100% { transform: scale(1); opacity: 1; }
}
</style>
</head>
<body class="no-context-menu">
<!-- 横屏提示 -->
<div id="orientationWarning">
<h2>请横屏游戏</h2>
<p>为了获得最佳游戏体验,请将设备横屏放置</p>
<div class="rotate-icon">↻</div>
<p>本游戏专为横屏设计,竖屏模式下无法正常游戏</p>
</div>
<div id="gameContainer">
<div id="topBar">
<div class="player-status">
<div class="player-info">
<div class="player-icon">董</div>
<div>生命: <span id="playerLives">3</span></div>
<div class="skill-status">
| 射击:
<div class="skill-indicator" id="playerSkill"></div>
<span id="playerSkillText">可用</span>
</div>
</div>
</div>
<div class="level-info">
<div>关卡: <span id="currentLevel">1</span>/4</div>
<button id="settingsBtn" style="margin-left: 10px; padding: 4px 12px; font-size: 0.8rem; min-height: 30px;">设置</button>
</div>
</div>
<canvas id="gameCanvas" width="1024" height="576"></canvas>
<!-- 移动端控制按钮 -->
<div id="mobileControls">
<div class="control-group">
<div class="direction-controls">
<div class="control-btn move-btn" id="mobileLeft">←</div>
<div class="control-btn jump-btn" id="mobileJump">↑</div>
<div class="control-btn move-btn" id="mobileRight">→</div>
</div>
</div>
<div class="control-group">
<div class="action-controls">
<div class="control-btn shoot-btn" id="mobileShoot">射击</div>
<div class="control-btn skill-btn" id="mobileSkill">技能</div>
<div class="control-btn ability-btn" id="mobileAbility">能力</div>
<div class="control-btn pause-btn" id="mobilePause">暂停</div>
</div>
</div>
</div>
<!-- 游戏UI元素 -->
<div id="bossHealthBar">
<div id="bossHealthFill"></div>
<div id="bossName">金文翔</div>
<div id="bossHitCount" style="position: absolute; top: -35px; left: 0; width: 100%; text-align: center; color: white; font-size: 0.8rem;">击中: <span id="bossHits">0</span>/2000</div>
</div>
<div id="powerUpDisplay">
<div class="powerUp-item">
<div class="powerUp-icon laser-icon"></div>
<span id="laserTimer">0</span>
</div>
<div class="powerUp-item">
<div class="powerUp-icon shield-icon"></div>
<span id="shieldCount">0</span>
</div>
<div class="powerUp-item">
<div class="powerUp-icon" style="background: #FFD700;"></div>
<span id="godTimer">天神模式</span>
</div>
</div>
<div id="scoreDisplay">分数: <span id="scoreValue">0</span></div>
<div id="comboDisplay">连击: <span id="comboValue">0</span>x</div>
<div id="checkpointIndicator">检查点已激活!</div>
<!-- 游戏界面 -->
<div id="levelComplete">
<h2 id="levelCompleteTitle">关卡完成!</h2>
<p id="levelCompleteText">恭喜你通过了当前关卡!</p>
<div id="gameStats">
<div class="stat-item">
<span>收集金币:</span>
<span id="collectedCoins">0</span>
</div>
<div class="stat-item">
<span>消灭敌人:</span>
<span id="killedEnemies">0</span>
</div>
<div class="stat-item">
<span>剩余生命:</span>
<span id="remainingLives">0</span>
</div>
<div class="stat-item">
<span>连击次数:</span>
<span id="maxCombo">0</span>
</div>
<div class="stat-item">
<span>获得分数:</span>
<span id="levelScore">0</span>
</div>
</div>
<button id="nextLevelBtn">下一关</button>
<button id="menuBtn2">主菜单</button>
</div>
<div id="pauseScreen">
<h2>游戏暂停</h2>
<button id="resumeBtn">继续游戏</button>
<button id="restartBtn">重新开始</button>
<button id="menuBtn">返回主菜单</button>
<button id="settingsBtn2">关卡选择</button>
</div>
<!-- 对话系统 -->
<div id="dialogueScreen">
<div id="dialogueContent">
<div id="dialogueSpeaker">对话</div>
<div id="dialogueText">这里是对话内容...</div>
<button id="dialogueNext">继续</button>
</div>
</div>
<!-- 设置界面 -->
<div id="settingsScreen">
<div id="settingsContent">
<h2>游戏设置</h2>
<p>选择要游玩的关卡:</p>
<div class="level-select" id="levelSelect">
<!-- 关卡按钮将通过JS动态生成 -->
</div>
<div class="fps-selector">
<h3>帧率设置</h3>
<div class="fps-option" data-fps="30">30 FPS (流畅)</div>
<div class="fps-option selected" data-fps="60">60 FPS (流畅)</div>
</div>
<button id="backToGameBtn">返回游戏</button>
<button id="backToMenuBtn">返回主菜单</button>
</div>
</div>
<!-- 公告屏幕最先显示 -->
<div id="announcementScreen">
<div id="announcementContent">
<h2>游戏公告</h2>
<p>亲爱的用户,本次更新,适配移动端,受同学委托,本游戏完全由同学定制,游戏中出现的名字全部由本班同学,本版本为第7代游戏版本增强版。</p>
<p>优化内容:</p>
<p>1. 修复了第3关传送门位置问题</p>
<p>2. Boss血量增强至2000,可以生成小兵</p>
<p>3. 增加了第3关机关机制,触发机关后出现传送门</p>
<p>4. 增强了所有关卡难度和地图大小</p>
<p>5. 天神模式现在永久持续</p>
<p>6. 优化了横屏游戏体验</p>
<p>7. 增加了帧率设置选项</p>
<p>8. 增强了游戏视觉效果和玩法</p>
<p>制作人员: XLANGJISHI</p>
<p>制作网站: bi.cool</p>
<p>游戏代码: HTML5</p>
</div>
<button id="continueBtn">开始游戏</button>
<div class="copyright">© 2023 XLANGJISHI 版权所有 - 第7代增强版</div>
</div>
<!-- 开始游戏屏幕(主菜单) -->
<div id="startScreen">
<div id="gameTitle" class="floating">
<h1>董测浩解救许子昂</h1>
<h2>手机冒险游戏 - 横屏版</h2>
</div>
<div class="game-description">
董测浩的好友许子昂被金文翔绑架了!帮助董测浩通过所有关卡,击败金文翔,解救许子昂!
</div>
<div class="mobile-controls-info">
<div class="mobile-control-set">
<div class="control-title">游戏控制</div>
<div class="mobile-control-row">
<div class="mobile-btn-demo move">←</div>
<span>左右移动</span>
</div>
<div class="mobile-control-row">
<div class="mobile-btn-demo jump">↑</div>
<span>跳跃</span>
</div>
<div class="mobile-control-row">
<div class="mobile-btn-demo shoot">射击</div>
<span>发射子弹</span>
</div>
<div class="mobile-control-row">
<div class="mobile-btn-demo skill">技能</div>
<span>特殊技能</span>
</div>
</div>
</div>
<button id="startBtn" class="pulse">开始冒险</button>
<p style="margin-top: 10px; font-size: 0.8rem; color: rgba(255, 255, 255, 0.6);">创作者提醒你:少谈恋爱,少撸管,爱国爱党,爱人民</p>
</div>
<!-- 开发者致谢界面 -->
<div id="thanksScreen" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.95); display: none; flex-direction: column; justify-content: center; align-items: center; color: white; z-index: 100; padding: 20px; text-align: center;">
<div style="max-width: 90%; background: rgba(255, 255, 255, 0.1); padding: 25px; border-radius: 20px; backdrop-filter: blur(10px); border: 2px solid rgba(255, 255, 255, 0.2); margin-bottom: 20px;">
<h2 style="color: #FFD700; margin-bottom: 20px;">感谢您的游玩!</h2>
<p style="margin: 10px 0; line-height: 1.6; font-size: 1rem;">恭喜你完成了游戏!</p>
<p style="margin: 10px 0; line-height: 1.6; font-size: 1rem;">感谢您的使用,如有反馈,请联系快手号S20124005</p>
<p style="margin: 10px 0; line-height: 1.6; font-size: 1rem;">制作人员: XLANGJISHI</p>
<p style="margin: 10px 0; line-height: 1.6; font-size: 1rem;">制作软件: bi.cool</p>
<p style="margin: 10px 0; line-height: 1.6; font-size: 1rem;">游戏代码: HTML5, JavaScript, CSS3</p>
<p style="margin: 10px 0; line-height: 1.6; font-size: 1rem;">累计代码: 5000行,中型游戏</p>
<p style="margin: 10px 0; line-height: 1.6; font-size: 1rem;">特殊错误修复: 由DeepSeek辅助修复</p>
<p style="margin: 10px 0; line-height: 1.6; font-size: 1rem;">除错误以外,均为本人开发</p>
<p style="margin: 10px 0; line-height: 1.6; font-size: 1rem; color: #FFD700;">感谢您的游玩,我将不负众望,继续前行。</p>
</div>
<button id="thanksBackBtn">返回主菜单</button>
</div>
</div>
<script>
// 游戏初始化
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const announcementScreen = document.getElementById('announcementScreen');
const startScreen = document.getElementById('startScreen');
const startBtn = document.getElementById('startBtn');
const continueBtn = document.getElementById('continueBtn');
const levelCompleteScreen = document.getElementById('levelComplete');
const nextLevelBtn = document.getElementById('nextLevelBtn');
const pauseScreen = document.getElementById('pauseScreen');
const resumeBtn = document.getElementById('resumeBtn');
const restartBtn = document.getElementById('restartBtn');
const menuBtn = document.getElementById('menuBtn');
const menuBtn2 = document.getElementById('menuBtn2');
const settingsBtn = document.getElementById('settingsBtn');
const settingsBtn2 = document.getElementById('settingsBtn2');
const bossHealthBar = document.getElementById('bossHealthBar');
const bossHealthFill = document.getElementById('bossHealthFill');
const bossName = document.getElementById('bossName');
const bossHitsElement = document.getElementById('bossHits');
const laserTimerElement = document.getElementById('laserTimer');
const shieldCountElement = document.getElementById('shieldCount');
const godTimerElement = document.getElementById('godTimer');
const scoreDisplay = document.getElementById('scoreDisplay');
const scoreValue = document.getElementById('scoreValue');
const comboDisplay = document.getElementById('comboDisplay');
const comboValue = document.getElementById('comboValue');
const maxComboElement = document.getElementById('maxCombo');
const levelScoreElement = document.getElementById('levelScore');
const levelCompleteTitle = document.getElementById('levelCompleteTitle');
const levelCompleteText = document.getElementById('levelCompleteText');
const checkpointIndicator = document.getElementById('checkpointIndicator');
const dialogueScreen = document.getElementById('dialogueScreen');
const dialogueText = document.getElementById('dialogueText');
const dialogueSpeaker = document.getElementById('dialogueSpeaker');
const dialogueNextBtn = document.getElementById('dialogueNext');
const settingsScreen = document.getElementById('settingsScreen');
const levelSelect = document.getElementById('levelSelect');
const backToGameBtn = document.getElementById('backToGameBtn');
const backToMenuBtn = document.getElementById('backToMenuBtn');
const thanksScreen = document.getElementById('thanksScreen');
const thanksBackBtn = document.getElementById('thanksBackBtn');
const orientationWarning = document.getElementById('orientationWarning');
// 移动控制按钮
const mobileLeft = document.getElementById('mobileLeft');
const mobileRight = document.getElementById('mobileRight');
const mobileJump = document.getElementById('mobileJump');
const mobileShoot = document.getElementById('mobileShoot');
const mobileSkill = document.getElementById('mobileSkill');
const mobileAbility = document.getElementById('mobileAbility');
const mobilePause = document.getElementById('mobilePause');
// 获取所有需要的UI元素
const playerLivesElement = document.getElementById('playerLives');
const playerSkillElement = document.getElementById('playerSkill');
const playerSkillTextElement = document.getElementById('playerSkillText');
const currentLevelElement = document.getElementById('currentLevel');
const collectedCoinsElement = document.getElementById('collectedCoins');
const killedEnemiesElement = document.getElementById('killedEnemies');
const remainingLivesElement = document.getElementById('remainingLives');
// 游戏状态
let gameRunning = false;
let gamePaused = false;
let currentLevel = 1;
let totalLevels = 4;
let score = 0;
let combo = 0;
let maxCombo = 0;
let comboTimeout = null;
let gameStats = {
collectedCoins: 0,
killedEnemies: 0,
remainingLives: 0
};
// 帧率控制
let targetFPS = 60;
let frameInterval = 1000 / targetFPS;
let lastTime = 0;
// 检查点系统
let checkpoint = {
x: 50,
y: 300,
active: false
};
// 对话系统
let currentDialogue = 0;
let dialogueSequence = [];
let dialogueCallback = null;
// 天神系统 - 陈浩然
let chenHaoranMode = false;
let jumpCount = 0;
let lastJumpTime = 0;
let godEffectElement = null;
let allLevelsUnlocked = false; // 天神模式下解锁所有关卡
// 机关系统 - 第3关
let trapActivated = false;
let traps = [];
// 解锁的关卡
let unlockedLevels = [1];
// 键盘状态管理
const keys = {
'a': false, 'd': false, 'w': false, 'j': false, 'k': false, 'q': false, 'p': false
};
// 移动端触摸状态
const touchState = {
left: false,
right: false,
jump: false,
shoot: false,
skill: false,
ability: false
};
// 游戏对象
let player, platforms, enemies, coins, hazards, goal, powerUps, checkpoints, kidnappedPerson, boss;
// 初始化移动端控制
function initMobileControls() {
// 左方向键
mobileLeft.addEventListener('touchstart', (e) => {
e.preventDefault();
touchState.left = true;
keys['a'] = true;
});
mobileLeft.addEventListener('touchend', (e) => {
e.preventDefault();
touchState.left = false;
keys['a'] = false;
});
// 右方向键
mobileRight.addEventListener('touchstart', (e) => {
e.preventDefault();
touchState.right = true;
keys['d'] = true;
});
mobileRight.addEventListener('touchend', (e) => {
e.preventDefault();
touchState.right = false;
keys['d'] = false;
});
// 跳跃键
mobileJump.addEventListener('touchstart', (e) => {
e.preventDefault();
touchState.jump = true;
keys['w'] = true;
// 跳跃计数检测
const currentTime = Date.now();
if (currentTime - lastJumpTime < 500) { // 500ms内算连续跳跃
jumpCount++;
} else {
jumpCount = 1;
}
lastJumpTime = currentTime;
// 检测10次跳跃触发陈浩然天神
if (jumpCount >= 10 && !chenHaoranMode) {
activateChenHaoranMode();
jumpCount = 0;
}
});
mobileJump.addEventListener('touchend', (e) => {
e.preventDefault();
touchState.jump = false;
keys['w'] = false;
});
// 射击键
mobileShoot.addEventListener('touchstart', (e) => {
e.preventDefault();
touchState.shoot = true;
keys['j'] = true;
});
mobileShoot.addEventListener('touchend', (e) => {
e.preventDefault();
touchState.shoot = false;
keys['j'] = false;
});
// 技能键
mobileSkill.addEventListener('touchstart', (e) => {
e.preventDefault();
touchState.skill = true;
keys['k'] = true;
});
mobileSkill.addEventListener('touchend', (e) => {
e.preventDefault();
touchState.skill = false;
keys['k'] = false;
});
// 能力键
mobileAbility.addEventListener('touchstart', (e) => {
e.preventDefault();
touchState.ability = true;
keys['q'] = true;
});
mobileAbility.addEventListener('touchend', (e) => {
e.preventDefault();
touchState.ability = false;
keys['q'] = false;
});
// 暂停键
mobilePause.addEventListener('click', (e) => {
e.preventDefault();
if (gameRunning) {
togglePause();
}
});
// 防止页面滚动
document.addEventListener('touchmove', function(e) {
if (gameRunning && !gamePaused) {
e.preventDefault();
}
}, { passive: false });
}
// 屏幕尺寸适配
function adjustForScreenSize() {
const container = document.getElementById('gameContainer');
const canvas = document.getElementById('gameCanvas');
// 获取容器实际尺寸
const containerWidth = container.clientWidth;
const containerHeight = container.clientHeight;
// 设置画布尺寸为容器尺寸
const canvasWidth = Math.floor(containerWidth);
const canvasHeight = Math.floor(containerHeight * 0.7);
canvas.width = canvasWidth;
canvas.height = canvasHeight;
canvas.style.width = canvasWidth + 'px';
canvas.style.height = canvasHeight + 'px';
// 更新UI元素位置
updateUIPositions();
// 如果游戏没有运行,绘制一次背景
if (!gameRunning) {
drawBackground();
}
}
// 横屏检测
function checkOrientation() {
const isPortrait = window.innerHeight > window.innerWidth;
if (isPortrait) {
orientationWarning.style.display = 'flex';
document.getElementById('gameContainer').style.display = 'none';
} else {
orientationWarning.style.display = 'none';
document.getElementById('gameContainer').style.display = 'block';
adjustForScreenSize();
}
}
// 窗口大小变化时调整
window.addEventListener('resize', function() {
checkOrientation();
if (!orientationWarning.style.display || orientationWarning.style.display === 'none') {
adjustForScreenSize();
}
});
window.addEventListener('orientationchange', function() {
setTimeout(function() {
checkOrientation();
if (!orientationWarning.style.display || orientationWarning.style.display === 'none') {
adjustForScreenSize();
}
}, 100);
});
// 初始化横屏检测
checkOrientation();
// 更新UI元素位置
function updateUIPositions() {
// 更新被绑架的许子昂位置
if (kidnappedPerson && kidnappedPerson.element) {
kidnappedPerson.updateElementPosition();
}
// 更新玩家名字位置
if (player && player.nameElement) {
player.updateNamePosition();
}
}
// 键盘事件
window.addEventListener('keydown', (e) => {
const key = e.key.toLowerCase();
if (keys.hasOwnProperty(key)) {
keys[key] = true;
if (key === 'p' && gameRunning) {
togglePause();
}
// 跳跃计数检测
if (key === 'w') {
const currentTime = Date.now();
if (currentTime - lastJumpTime < 500) { // 500ms内算连续跳跃
jumpCount++;
} else {
jumpCount = 1;
}
lastJumpTime = currentTime;
// 检测10次跳跃触发陈浩然天神
if (jumpCount >= 10 && !chenHaoranMode) {
activateChenHaoranMode();
jumpCount = 0;
}
}
e.preventDefault();
}
});
window.addEventListener('keyup', (e) => {
const key = e.key.toLowerCase();
if (keys.hasOwnProperty(key)) {
keys[key] = false;
e.preventDefault();
}
});
// 伤害数字显示
const damagePopups = [];
function createDamagePopup(x, y, damage) {
damagePopups.push({
x: x,
y: y,
text: damage.toString(),
life: 60,
maxLife: 60
});
}
function updateDamagePopups() {
for (let i = damagePopups.length - 1; i >= 0; i--) {
damagePopups[i].life--;
damagePopups[i].y -= 1;
if (damagePopups[i].life <= 0) {
damagePopups.splice(i, 1);
}
}
}
function drawDamagePopups() {
ctx.save();
ctx.font = 'bold 14px Arial';
ctx.textAlign = 'center';
for (let popup of damagePopups) {
const alpha = popup.life / popup.maxLife;
ctx.fillStyle = `rgba(255, 85, 85, ${alpha})`;
ctx.fillText(popup.text, popup.x, popup.y);
}
ctx.restore();
}
// 屏幕震动效果
function screenShake() {
document.getElementById('gameContainer').classList.add('screen-shake');
setTimeout(() => {
document.getElementById('gameContainer').classList.remove('screen-shake');
}, 500);
}
// 连击系统
function addCombo() {
combo++;
if (combo > maxCombo) {
maxCombo = combo;
}
comboValue.textContent = combo;
comboDisplay.style.display = 'block';
// 清除之前的计时器
if (comboTimeout) {
clearTimeout(comboTimeout);
}
// 设置连击重置计时器
comboTimeout = setTimeout(() => {
combo = 0;
comboDisplay.style.display = 'none';
}, 3000);
}
// 检查点系统
function activateCheckpoint(x, y) {
checkpoint.x = x;
checkpoint.y = y;
checkpoint.active = true;
// 显示检查点激活提示
checkpointIndicator.style.display = 'block';
setTimeout(() => {
checkpointIndicator.style.display = 'none';
}, 2000);
}
// 陈浩然天神模式 - 永久持续
function activateChenHaoranMode() {
if (chenHaoranMode) return;
chenHaoranMode = true;
// 解锁所有关卡
allLevelsUnlocked = true;
for (let i = 1; i <= totalLevels; i++) {
if (!unlockedLevels.includes(i)) {
unlockedLevels.push(i);
}
}
// 创建天神降临效果
const godArrival = document.createElement('div');
godArrival.className = 'god-arrival';
godArrival.textContent = '陈浩然天神降临!';
document.getElementById('gameContainer').appendChild(godArrival);
// 创建天神效果
godEffectElement = document.createElement('div');
godEffectElement.className = 'god-effect';
document.getElementById('gameContainer').appendChild(godEffectElement);
// 播放陈浩然对话
showDialogue([
{ speaker: "陈浩然", text: "老78头子,看在你这么用力的份上,我就暂且帮助你一下。" },
{ speaker: "陈浩然", text: "你将获得永久神力,可以随意启动关卡,也可以无限发射子弹,射速加快两倍,伤害加倍!" },
{ speaker: "陈浩然", text: "这如果死了,你就直接在地里面呆着别活了。" }
], function() {
// 对话结束后继续游戏
});
// 移除天神降临文字
setTimeout(() => {
if (godArrival.parentNode) {
godArrival.parentNode.removeChild(godArrival);
}
}, 2000);
// 更新UI
godTimerElement.textContent = "天神模式";
}
// 粒子效果类
class Particle {
constructor(x, y, color, size, speedX, speedY, life) {
this.x = x;
this.y = y;
this.color = color;
this.size = size;
this.speedX = speedX;
this.speedY = speedY;
this.life = life;
this.maxLife = life;
}
update() {
this.x += this.speedX;
this.y += this.speedY;
this.life--;
// 添加重力效果
this.speedY += 0.1;
return this.life > 0;
}
draw() {
const alpha = this.life / this.maxLife;
ctx.save();
ctx.globalAlpha = alpha;
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
ctx.fill();
ctx.restore();
}
}
// 子弹类
class Bullet {
constructor(x, y, direction, color, type = 'normal') {
this.x = x;
this.y = y;
this.width = 8;
this.height = 8;
this.speed = type === 'laser' ? 15 : (chenHaoranMode ? 20 : 10); // 陈浩然模式下速度加倍
this.direction = direction;
this.color = color;
this.type = type;
this.particles = [];
this.damage = type === 'laser' ? 2 : (chenHaoranMode ? 2 : 1); // 陈浩然模式下伤害加倍
}
update() {
this.x += this.speed * this.direction;
// 激光子弹的特殊效果
if (this.type === 'laser' || chenHaoranMode) {
// 添加粒子效果
if (Math.random() < 0.7) {
this.particles.push(new Particle(
this.x,
this.y + (Math.random() - 0.5) * 10,
this.color,
Math.random() * 3 + 1,
(Math.random() - 0.5) * 2,
(Math.random() - 0.5) * 2,
Math.random() * 20 + 10
));
}
// 更新粒子
for (let i = this.particles.length - 1; i >= 0; i--) {
if (!this.particles[i].update()) {
this.particles.splice(i, 1);
}
}
}
}
draw() {
if (this.type === 'laser' || chenHaoranMode) {
// 绘制激光子弹
ctx.fillStyle = this.color;
ctx.fillRect(this.x - 10, this.y - 2, 20, 4);
// 绘制发光效果
ctx.fillStyle = 'rgba(255, 255, 255, 0.7)';
ctx.fillRect(this.x - 8, this.y - 1, 16, 2);
// 绘制粒子
for (let particle of this.particles) {
particle.draw();
}
} else {
// 普通子弹
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.x, this.y, this.width/2, 0, Math.PI * 2);
ctx.fill();
// 添加发光效果
ctx.fillStyle = 'white';
ctx.beginPath();
ctx.arc(this.x - 2 * this.direction, this.y, this.width/4, 0, Math.PI * 2);
ctx.fill();
}
}
isOffScreen() {
return this.x < 0 || this.x > canvas.width;
}
}
// 机关类 - 第3关
class Trap {
constructor(x, y) {
this.x = x;
this.y = y;
this.width = 40;
this.height = 40;
this.color = '#FF9800';
this.active = false;
this.activated = false;
this.element = null;
this.createElement();
}
createElement() {
this.element = document.createElement('div');
this.element.className = 'trap';
this.element.textContent = '机关';
this.element.style.left = this.x + 'px';
this.element.style.top = this.y + 'px';
this.element.style.width = this.width + 'px';
this.element.style.height = this.height + 'px';
// 添加点击事件
this.element.addEventListener('click', () => {
this.activate();
});
document.getElementById('gameContainer').appendChild(this.element);
}
updateElementPosition() {
if (this.element) {
const scaleX = canvas.clientWidth / canvas.width;
const scaleY = canvas.clientHeight / canvas.height;
this.element.style.left = (this.x * scaleX) + 'px';
this.element.style.top = (this.y * scaleY) + 'px';
this.element.style.width = (this.width * scaleX) + 'px';
this.element.style.height = (this.height * scaleY) + 'px';
}
}
activate() {
if (!this.activated) {
this.activated = true;
this.active = true;
this.element.classList.add('active');
this.element.textContent = '已激活';
// 激活所有机关
for (let trap of traps) {
trap.active = true;
trap.activated = true;
if (trap.element) {
trap.element.classList.add('active');
trap.element.textContent = '已激活';
}
}
trapActivated = true;
// 显示提示
showDialogue([
{ speaker: "系统", text: "机关已激活!传送门现在可以进入了!" }
], function() {
// 对话结束后继续游戏
});
}
}
draw() {
// 机关由DOM元素绘制,这里不需要canvas绘制
}
checkCollision(player) {
return !this.activated &&
this.x < player.x + player.width &&
this.x + this.width > player.x &&
this.y < player.y + player.height &&
this.y + this.height > player.y;
}
}
// 道具类
class PowerUp {
constructor(x, y, type) {
this.x = x;
this.y = y;
this.width = 20;
this.height = 20;
this.type = type;
this.collected = false;
this.animation = 0;
// 根据类型设置颜色
if (type === 'health') {
this.color = '#FF5252';
} else if (type === 'laser') {
this.color = '#2196F3';
} else if (type === 'shield') {
this.color = '#4CAF50';
} else if (type === 'score') {
this.color = '#FFD700';
} else if (type === 'speed') {
this.color = '#9C27B0';
}
}
update() {
this.animation += 0.05;
this.y += Math.sin(this.animation) * 0.5; // 上下浮动效果
}
draw() {
ctx.save();
// 闪烁效果
const alpha = 0.7 + 0.3 * Math.sin(this.animation * 3);
ctx.globalAlpha = alpha;
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.x, this.y, this.width/2, 0, Math.PI * 2);
ctx.fill();
// 绘制内部图标
ctx.fillStyle = 'white';
if (this.type === 'health') {
// 心形
ctx.beginPath();
ctx.moveTo(this.x, this.y - 3);
ctx.bezierCurveTo(
this.x + 5, this.y - 8,
this.x + 8, this.y - 3,
this.x, this.y + 5
);
ctx.bezierCurveTo(
this.x - 8, this.y - 3,
this.x - 5, this.y - 8,
this.x, this.y - 3
);
ctx.fill();
} else if (this.type === 'laser') {
// 闪电
ctx.beginPath();
ctx.moveTo(this.x - 3, this.y - 5);
ctx.lineTo(this.x + 3, this.y);
ctx.lineTo(this.x - 3, this.y);
ctx.lineTo(this.x + 3, this.y + 5);
ctx.fill();
} else if (this.type === 'shield') {
// 盾牌
ctx.beginPath();
ctx.arc(this.x, this.y, 6, 0, Math.PI * 2);
ctx.fill();
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.x, this.y, 4, 0, Math.PI * 2);
ctx.fill();
} else if (this.type === 'score') {
// 星星
ctx.beginPath();
ctx.moveTo(this.x, this.y - 5);
ctx.lineTo(this.x + 2, this.y - 2);
ctx.lineTo(this.x + 5, this.y);
ctx.lineTo(this.x + 2, this.y + 2);
ctx.lineTo(this.x, this.y + 5);
ctx.lineTo(this.x - 2, this.y + 2);
ctx.lineTo(this.x - 5, this.y);
ctx.lineTo(this.x - 2, this.y - 2);
ctx.closePath();
ctx.fill();
} else if (this.type === 'speed') {
// 闪电
ctx.beginPath();
ctx.moveTo(this.x - 3, this.y - 5);
ctx.lineTo(this.x + 3, this.y);
ctx.lineTo(this.x - 3, this.y);
ctx.lineTo(this.x + 3, this.y + 5);
ctx.fill();
}
ctx.restore();
}
checkCollision(player) {
return !this.collected &&
this.x < player.x + player.width &&
this.x + this.width > player.x &&
this.y < player.y + player.height &&
this.y + this.height > player.y;
}
}
// 玩家类 - 董测浩
class Player {
constructor(x, y, color, controls, skillType) {
this.x = x;
this.y = y;
this.width = 32;
this.height = 48;
this.color = color;
this.velocityX = 0;
this.velocityY = 0;
this.jumping = false;
this.onGround = false;
this.lives = 3;
this.skillCooldown = 0;
this.skillActive = false;
this.skillDuration = 0;
this.controls = controls;
this.skillType = skillType;
this.facingRight = true;
this.collectedCoins = 0;
this.invincible = 0;
this.animationFrame = 0;
this.bullets = [];
this.maxBullets = chenHaoranMode ? 999 : 3; // 陈浩然模式下无限子弹
this.powerUps = {
laser: 0,
shield: 0,
speed: 0
};
this.particles = [];
this.abilityCooldown = 0;
this.abilityActive = false;
this.abilityDuration = 0;
this.name = "董测浩";
this.nameElement = null;
this.createNameElement();
}
createNameElement() {
this.nameElement = document.createElement('div');
this.nameElement.className = 'player-name';
this.nameElement.textContent = this.name;
document.getElementById('gameContainer').appendChild(this.nameElement);
}
updateNamePosition() {
if (this.nameElement) {
const scaleX = canvas.clientWidth / canvas.width;
const scaleY = canvas.clientHeight / canvas.height;
this.nameElement.style.left = ((this.x + this.width/2) * scaleX) + 'px';
this.nameElement.style.top = ((this.y - 10) * scaleY) + 'px';
}
}
update(platforms, enemies, coins, hazards, powerUps, checkpoints) {
if (gamePaused) return;
// 更新动画帧
this.animationFrame++;
// 无敌时间减少
if (this.invincible > 0) {
this.invincible--;
}
// 陈浩然天神模式
if (chenHaoranMode) {
// 永久天神模式,不需要时间减少
this.maxBullets = 999;
godTimerElement.textContent = "天神模式";
}
// 应用重力
if (!this.onGround) {
this.velocityY += 0.4;
}
// 限制下落速度
if (this.velocityY > 10) {
this.velocityY = 10;
}
// 更新位置
this.x += this.velocityX;
this.y += this.velocityY;
// 技能冷却
if (this.skillCooldown > 0) {
this.skillCooldown--;
}
// 技能持续时间
if (this.skillActive) {
this.skillDuration--;
if (this.skillDuration <= 0) {
this.skillActive = false;
}
}
// 特殊能力冷却
if (this.abilityCooldown > 0) {
this.abilityCooldown--;
}
// 特殊能力持续时间
if (this.abilityActive) {
this.abilityDuration--;
if (this.abilityDuration <= 0) {
this.abilityActive = false;
}
}
// 边界检查
if (this.x < 0) this.x = 0;
if (this.x + this.width > canvas.width) this.x = canvas.width - this.width;
if (this.y > canvas.height) {
this.respawn();
this.lives--;
if (this.lives <= 0) {
gameOver();
}
}
// 平台碰撞检测
this.onGround = false;
for (let platform of platforms) {
if (this.x < platform.x + platform.width &&
this.x + this.width > platform.x &&
this.y + this.height > platform.y &&
this.y + this.height < platform.y + platform.height &&
this.velocityY > 0) {
this.y = platform.y - this.height;
this.velocityY = 0;
this.onGround = true;
this.jumping = false;
}
}
// 检查点碰撞检测
for (let cp of checkpoints) {
if (this.x < cp.x + cp.width &&
this.x + this.width > cp.x &&
this.y < cp.y + cp.height &&
this.y + this.height > cp.y) {
if (!cp.activated) {
cp.activated = true;
activateCheckpoint(cp.x, cp.y);
}
}
}
// 机关碰撞检测 - 第3关
for (let trap of traps) {
if (trap.checkCollision(this)) {
trap.activate();
}
}
// 敌人碰撞检测
if (this.invincible === 0 && !chenHaoranMode) { // 陈浩然模式下无敌
for (let enemy of enemies) {
if (!enemy.dead && this.x < enemy.x + enemy.width &&
this.x + this.width > enemy.x &&
this.y < enemy.y + enemy.height &&
this.y + this.height > enemy.y) {
// 检查是否从上方踩到敌人
if (this.velocityY > 0 && this.y + this.height < enemy.y + enemy.height/2) {
// 踩死敌人
enemy.dead = true;
gameStats.killedEnemies++;
this.velocityY = -10; // 反弹
// 添加粒子效果
for (let i = 0; i < 10; i++) {
this.particles.push(new Particle(
enemy.x + enemy.width/2,
enemy.y + enemy.height/2,
enemy.color,
Math.random() * 3 + 1,
(Math.random() - 0.5) * 5,
(Math.random() - 0.5) * 5,
Math.random() * 30 + 20
));
}
// 增加分数和连击
addScore(50);
addCombo();
} else {
// 如果玩家有护盾道具,则不受伤害
if (this.powerUps.shield > 0) {
this.powerUps.shield--;
// 反弹敌人
if (this.x < enemy.x) {
enemy.velocityX = 5;
} else {
enemy.velocityX = -5;
}
} else {
this.respawn();
this.lives--;
this.invincible = 120; // 2秒无敌时间
if (this.lives <= 0) {
gameOver();
}
}
}
}
}
}
// 危险物品碰撞检测
if (this.invincible === 0 && !chenHaoranMode) { // 陈浩然模式下无敌
for (let hazard of hazards) {
if (this.x < hazard.x + hazard.width &&
this.x + this.width > hazard.x &&
this.y < hazard.y + hazard.height &&
this.y + this.height > hazard.y) {
this.respawn();
this.lives--;
this.invincible = 120;
if (this.lives <= 0) {
gameOver();
}
}
}
}
// 金币碰撞检测
for (let i = coins.length - 1; i >= 0; i--) {
let coin = coins[i];
if (this.x < coin.x + coin.width &&
this.x + this.width > coin.x &&
this.y < coin.y + coin.height &&
this.y + this.height > coin.y) {
this.collectedCoins++;
gameStats.collectedCoins++;
coins.splice(i, 1);
// 增加分数
addScore(10);
// 添加粒子效果
for (let i = 0; i < 5; i++) {
this.particles.push(new Particle(
coin.x + coin.width/2,
coin.y + coin.height/2,
coin.color,
Math.random() * 2 + 1,
(Math.random() - 0.5) * 3,
(Math.random() - 0.5) * 3,
Math.random() * 20 + 10
));
}
}
}
// 道具碰撞检测
for (let i = powerUps.length - 1; i >= 0; i--) {
let powerUp = powerUps[i];
if (powerUp.checkCollision(this)) {
powerUp.collected = true;
powerUps.splice(i, 1);
if (powerUp.type === 'health') {
this.lives = Math.min(this.lives + 1, 5);
playerLivesElement.textContent = this.lives;
} else if (powerUp.type === 'laser') {
this.powerUps.laser = 300; // 5秒激光子弹
} else if (powerUp.type === 'shield') {
this.powerUps.shield = 3; // 3次护盾
} else if (powerUp.type === 'score') {
addScore(100);
} else if (powerUp.type === 'speed') {
this.powerUps.speed = 300; // 5秒加速
}
// 添加粒子效果
for (let i = 0; i < 15; i++) {
this.particles.push(new Particle(
powerUp.x,
powerUp.y,
powerUp.color,
Math.random() * 3 + 1,
(Math.random() - 0.5) * 4,
(Math.random() - 0.5) * 4,
Math.random() * 40 + 20
));
}
}
}
// 处理玩家输入(移动端使用touchState)
if (touchState.left || keys['a']) {
this.move('left');
} else if (touchState.right || keys['d']) {
this.move('right');
} else {
this.move('stop');
}
if (touchState.jump || keys['w']) {
this.jump();
}
if (touchState.shoot || keys['j']) {
this.useSkill();
}
if ((touchState.ability || keys['q']) && this.abilityCooldown === 0) {
this.useAbility();
}
// 更新子弹
for (let i = this.bullets.length - 1; i >= 0; i--) {
this.bullets[i].update();
// 检查子弹是否超出屏幕
if (this.bullets[i].isOffScreen()) {
this.bullets.splice(i, 1);
}
}
// 更新粒子
for (let i = this.particles.length - 1; i >= 0; i--) {
if (!this.particles[i].update()) {
this.particles.splice(i, 1);
}
}
// 更新道具持续时间
if (this.powerUps.laser > 0) {
this.powerUps.laser--;
}
if (this.powerUps.speed > 0) {
this.powerUps.speed--;
}
// 更新名字位置
this.updateNamePosition();
// 更新UI
if (playerSkillElement) {
playerSkillElement.className = this.skillCooldown > 0 ? 'skill-indicator cooldown' : 'skill-indicator';
}
if (playerSkillTextElement) {
playerSkillTextElement.textContent = this.skillCooldown > 0 ? '冷却' : '可用';
}
}
draw() {
// 绘制玩家角色
ctx.save();
// 无敌闪烁效果
if (this.invincible > 0 && Math.floor(this.invincible / 10) % 2 === 0) {
ctx.globalAlpha = 0.5;
}
// 陈浩然天神模式效果
if (chenHaoranMode) {
ctx.globalAlpha = 0.8;
ctx.fillStyle = '#FFD700';
} else {
ctx.fillStyle = this.color;
}
// 绘制身体
ctx.fillRect(this.x, this.y, this.width, this.height);
// 绘制眼睛 - 改进版
ctx.fillStyle = 'white';
ctx.fillRect(this.facingRight ? this.x + 20 : this.x + 8, this.y + 12, 8, 8);
ctx.fillStyle = 'black';
ctx.fillRect(this.facingRight ? this.x + 22 : this.x + 10, this.y + 14, 4, 4);
// 绘制嘴巴
ctx.fillStyle = '#FF5252';
ctx.fillRect(this.x + 12, this.y + 28, 8, 4);
// 绘制手臂
ctx.fillStyle = chenHaoranMode ? '#FFD700' : this.color;
let armOffset = Math.sin(this.animationFrame * 0.2) * 3;
if (this.velocityX !== 0 && this.onGround) {
// 行走时手臂摆动
ctx.fillRect(this.x - 5, this.y + 15, 8, 10);
ctx.fillRect(this.x + this.width - 3, this.y + 15, 8, 10);
} else {
// 静止时手臂
ctx.fillRect(this.x - 5, this.y + 15, 8, 10);
ctx.fillRect(this.x + this.width - 3, this.y + 15, 8, 10);
}
// 绘制腿(动画效果)
ctx.fillStyle = chenHaoranMode ? '#FFD700' : this.color;
let legOffset = Math.sin(this.animationFrame * 0.2) * 3;
if (this.velocityX !== 0 && this.onGround) {
ctx.fillRect(this.x + 5, this.y + this.height, 8, -10 + legOffset);
ctx.fillRect(this.x + this.width - 13, this.y + this.height, 8, -10 - legOffset);
} else {
ctx.fillRect(this.x + 5, this.y + this.height, 8, -10);
ctx.fillRect(this.x + this.width - 13, this.y + this.height, 8, -10);
}
// 绘制子弹
for (let bullet of this.bullets) {
bullet.draw();
}
// 绘制粒子
for (let particle of this.particles) {
particle.draw();
}
// 绘制护盾效果
if (this.powerUps.shield > 0) {
ctx.strokeStyle = '#4CAF50';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.arc(this.x + this.width/2, this.y + this.height/2, this.width, 0, Math.PI * 2);
ctx.stroke();
}
// 绘制加速效果
if (this.powerUps.speed > 0) {
ctx.strokeStyle = '#9C27B0';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.arc(this.x + this.width/2, this.y + this.height/2, this.width + 5, 0, Math.PI * 2);
ctx.stroke();
}
// 绘制特殊能力效果
if (this.abilityActive) {
ctx.strokeStyle = '#FFD700';
ctx.lineWidth = 3;
ctx.beginPath();
ctx.arc(this.x + this.width/2, this.y + this.height/2, this.width + 10, 0, Math.PI * 2);
ctx.stroke();
}
ctx.restore();
}
move(direction) {
const baseSpeed = 4;
const speedMultiplier = this.powerUps.speed > 0 ? 1.5 : 1;
if (direction === 'left') {
this.velocityX = -baseSpeed * speedMultiplier;
this.facingRight = false;
} else if (direction === 'right') {
this.velocityX = baseSpeed * speedMultiplier;
this.facingRight = true;
} else if (direction === 'stop') {
this.velocityX = 0;
}
}
jump() {
if (this.onGround && !this.jumping) {
this.velocityY = -10;
this.jumping = true;
this.onGround = false;
}
}
useSkill() {
// 陈浩然模式下无冷却时间,无限子弹
const canShoot = chenHaoranMode ? true : (this.skillCooldown === 0 && this.bullets.length < this.maxBullets);
if (canShoot) {
this.skillActive = true;
this.skillCooldown = this.powerUps.laser > 0 ? 10 : (chenHaoranMode ? 0 : 20); // 陈浩然模式下无冷却
// 创建子弹
let bulletX = this.facingRight ? this.x + this.width : this.x;
let bulletY = this.y + this.height / 2;
let direction = this.facingRight ? 1 : -1;
let bulletColor = chenHaoranMode ? '#FFD700' : this.color;
let bulletType = (this.powerUps.laser > 0 || chenHaoranMode) ? 'laser' : 'normal';
this.bullets.push(new Bullet(bulletX, bulletY, direction, bulletColor, bulletType));
// 陈浩然模式下可以连续发射多颗子弹
if (chenHaoranMode && Math.random() < 0.3) {
this.bullets.push(new Bullet(bulletX, bulletY + 10, direction, bulletColor, bulletType));
this.bullets.push(new Bullet(bulletX, bulletY - 10, direction, bulletColor, bulletType));
}
}
}
useAbility() {
if (this.abilityCooldown === 0) {
this.abilityActive = true;
this.abilityDuration = 180; // 3秒持续时间
this.abilityCooldown = 600; // 10秒冷却时间
// 能力:范围爆炸
for (let enemy of enemies) {
if (!enemy.dead) {
const distance = Math.sqrt(
Math.pow(this.x - enemy.x, 2) +
Math.pow(this.y - enemy.y, 2)
);
if (distance < 150) {
enemy.hitByBullet('ability');
createDamagePopup(enemy.x + enemy.width/2, enemy.y, 3);
addScore(30);
addCombo();
}
}
}
// 添加爆炸粒子效果
for (let i = 0; i < 50; i++) {
this.particles.push(new Particle(
this.x + this.width/2,
this.y + this.height/2,
'#3498db',
Math.random() * 5 + 2,
(Math.random() - 0.5) * 10,
(Math.random() - 0.5) * 10,
Math.random() * 40 + 20
));
}
// 屏幕震动
screenShake();
}
}
respawn() {
// 如果有激活的检查点,就在检查点重生
if (checkpoint.active) {
this.x = checkpoint.x;
this.y = checkpoint.y;
} else {
this.x = 50;
this.y = canvas.height * 0.6; // 根据画布高度调整
}
this.velocityX = 0;
this.velocityY = 0;
this.bullets = [];
this.invincible = 120;
}
removeNameElement() {
if (this.nameElement && this.nameElement.parentNode) {
this.nameElement.parentNode.removeChild(this.nameElement);
}
}
}
// 平台类
class Platform {
constructor(x, y, width, height, color = '#8B4513', moving = false, moveRange = 0, moveSpeed = 0, vertical = false) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.color = color;
this.moving = moving;
this.moveRange = moveRange;
this.moveSpeed = moveSpeed;
this.direction = 1;
this.originalX = x;
this.originalY = y;
this.vertical = vertical;
}
update() {
if (this.moving) {
if (this.vertical) {
this.y += this.moveSpeed * this.direction;
if (this.y <= this.originalY - this.moveRange || this.y >= this.originalY + this.moveRange) {
this.direction *= -1;
}
} else {
this.x += this.moveSpeed * this.direction;
if (this.x <= this.originalX - this.moveRange || this.x >= this.originalX + this.moveRange) {
this.direction *= -1;
}
}
}
}
draw() {
// 绘制平台主体
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
// 添加平台纹理
ctx.fillStyle = '#A0522D';
for (let i = 0; i < this.width; i += 15) {
ctx.fillRect(this.x + i, this.y, 8, 5);
}
// 绘制平台阴影
ctx.fillStyle = 'rgba(0, 0, 0, 0.2)';
ctx.fillRect(this.x, this.y + this.height, this.width, 5);
}
}
// 检查点类
class Checkpoint {
constructor(x, y, width, height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.activated = false;
}
draw() {
ctx.save();
if (this.activated) {
ctx.fillStyle = '#00FF00';
} else {
ctx.fillStyle = '#FFFF00';
}
ctx.fillRect(this.x, this.y, this.width, this.height);
// 绘制旗帜
ctx.fillStyle = '#FF0000';
ctx.beginPath();
ctx.moveTo(this.x + this.width/2, this.y);
ctx.lineTo(this.x + this.width/2, this.y - 20);
ctx.lineTo(this.x + this.width/2 + 15, this.y - 10);
ctx.closePath();
ctx.fill();
ctx.restore();
}
}
// 牢笼类 - 用于关押许子昂
class Cage {
constructor(x, y, width, height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.broken = false;
this.bars = [];
this.createBars();
}
createBars() {
// 创建牢笼的栏杆
for (let i = 0; i < 5; i++) {
this.bars.push({
x: this.x + i * (this.width / 4),
y: this.y,
width: 8,
height: this.height
});
}
// 创建横杆
this.bars.push({x: this.x, y: this.y, width: this.width, height: 8});
this.bars.push({x: this.x, y: this.y + this.height - 8, width: this.width, height: 8});
}
draw() {
if (this.broken) return;
ctx.save();
// 绘制牢笼栏杆
ctx.fillStyle = '#795548';
for (let bar of this.bars) {
ctx.fillRect(bar.x, bar.y, bar.width, bar.height);
}
// 绘制锁
ctx.fillStyle = '#FFD700';
ctx.fillRect(this.x + this.width/2 - 10, this.y + this.height/2 - 5, 20, 10);
ctx.fillStyle = '#B8860B';
ctx.fillRect(this.x + this.width/2 - 8, this.y + this.height/2 - 3, 16, 6);
ctx.restore();
}
checkCollision(player) {
if (this.broken) return false;
// 检查玩家是否接触到牢笼
for (let bar of this.bars) {
if (player.x < bar.x + bar.width &&
player.x + player.width > bar.x &&
player.y < bar.y + bar.height &&
player.y + player.height > bar.y) {
return true;
}
}
return false;
}
break() {
this.broken = true;
// 添加破碎效果
if (player) {
for (let bar of this.bars) {
for (let i = 0; i < 10; i++) {
player.particles.push(new Particle(
bar.x + bar.width/2,
bar.y + bar.height/2,
'#795548',
Math.random() * 3 + 1,
(Math.random() - 0.5) * 5,
(Math.random() - 0.5) * 5,
Math.random() * 30 + 20
));
}
}
}
}
}
// 被绑架的许子昂类
class KidnappedPerson {
constructor(x, y) {
this.x = x;
this.y = y;
this.width = 40;
this.height = 60;
this.color = '#9C27B0';
this.name = "许子昂";
this.rescued = false;
this.element = null;
this.cage = new Cage(x - 20, y - 20, this.width + 40, this.height + 40);
this.createElement();
}
createElement() {
this.element = document.createElement('div');
this.element.className = 'kidnapped-person';
this.element.textContent = this.name;
document.getElementById('gameContainer').appendChild(this.element);
this.updateElementPosition();
}
draw() {
if (this.rescued) return;
// 绘制牢笼
this.cage.draw();
ctx.save();
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
// 绘制脸部 - 改进版
ctx.fillStyle = 'white';
ctx.fillRect(this.x + 10, this.y + 15, 8, 8);
ctx.fillRect(this.x + 22, this.y + 15, 8, 8);
// 绘制眼睛
ctx.fillStyle = 'black';
ctx.fillRect(this.x + 12, this.y + 17, 4, 4);
ctx.fillRect(this.x + 24, this.y + 17, 4, 4);
// 绘制嘴巴
ctx.fillStyle = '#FF5252';
ctx.fillRect(this.x + 15, this.y + 30, 10, 5);
// 绘制手臂
ctx.fillStyle = this.color;
ctx.fillRect(this.x - 5, this.y + 20, 8, 10);
ctx.fillRect(this.x + this.width - 3, this.y + 20, 8, 10);
// 绘制腿
ctx.fillRect(this.x + 5, this.y + this.height, 8, -10);
ctx.fillRect(this.x + this.width - 13, this.y + this.height, 8, -10);
ctx.restore();
}
rescue() {
// 先打破牢笼
this.cage.break();
// 延迟解救效果
setTimeout(() => {
this.rescued = true;
if (this.element && this.element.parentNode) {
this.element.parentNode.removeChild(this.element);
}
// 显示解救成功消息
showDialogue([
{ speaker: "许子昂", text: "董测浩!谢谢你救了我!" },
{ speaker: "董测浩", text: "不用谢,我们是最好的朋友!" }
], function() {
// 对话结束后继续游戏
});
}, 500);
}
updateElementPosition() {
if (this.element) {
const scaleX = canvas.clientWidth / canvas.width;
const scaleY = canvas.clientHeight / canvas.height;
this.element.style.left = (this.x * scaleX) + 'px';
this.element.style.top = (this.y * scaleY) + 'px';
this.element.style.width = (this.width * scaleX) + 'px';
this.element.style.height = (this.height * scaleY) + 'px';
this.element.style.fontSize = Math.max(10, 12 * Math.min(scaleX, scaleY)) + 'px';
}
}
checkCollision(player) {
// 检查玩家是否接触到许子昂
if (this.rescued) return false;
if (player.x < this.x + this.width &&
player.x + player.width > this.x &&
player.y < this.y + this.height &&
player.y + player.height > this.y) {
// 检查牢笼是否被打破
if (!this.cage.broken) {
// 打破牢笼
this.cage.break();
return false;
} else {
// 解救许子昂
this.rescue();
return true;
}
}
return false;
}
}
// 敌人类
class Enemy {
constructor(x, y, type, patrolRange = 100) {
this.x = x;
this.y = y;
this.type = type;
this.patrolRange = patrolRange;
this.startX = x;
this.startY = y;
this.dead = false;
this.particles = [];
this.hitCount = 0; // 用于Boss战计数
this.dialogueTriggered = false; // 对话触发标记
this.minionSpawnTimer = 0; // 小兵生成计时器
this.minions = []; // Boss生成的小兵
if (type === 'walker') {
this.width = 36;
this.height = 36;
this.speed = 2.0; // 增加速度
this.color = '#FF5252';
this.direction = 1;
this.velocityX = this.speed * this.direction;
this.velocityY = 0;
this.health = 2; // 增加生命值
} else if (type === 'jumper') {
this.width = 32;
this.height = 32;
this.speed = 1.5; // 增加速度
this.color = '#FF9800';
this.direction = 1;
this.velocityX = this.speed * this.direction;
this.velocityY = 0;
this.jumpTimer = 0;
this.health = 2; // 增加生命值
} else if (type === 'chaser') {
this.width = 28;
this.height = 28;
this.speed = 2.5; // 增加速度
this.color = '#E91E63';
this.velocityX = 0;
this.velocityY = 0;
this.aggroRange = 200; // 增加追踪范围
this.health = 2; // 增加生命值
} else if (type === 'flyer') {
this.width = 30;
this.height = 30;
this.speed = 2.0; // 增加速度
this.color = '#9C27B0';
this.direction = 1;
this.velocityX = this.speed * this.direction;
this.velocityY = 0;
this.patrolRange = patrolRange;
this.health = 2; // 增加生命值
} else if (type === 'shooter') {
this.width = 35;
this.height = 35;
this.speed = 1.5; // 增加速度
this.color = '#795548';
this.direction = 1;
this.velocityX = this.speed * this.direction;
this.velocityY = 0;
this.shootTimer = 0;
this.bullets = [];
this.health = 3; // 增加生命值
} else if (type === 'boss') {
this.width = 100; // 增加Boss大小
this.height = 100;
this.speed = 1.5; // 增加速度
this.color = '#D32F2F';
this.direction = 1;
this.velocityX = this.speed * this.direction;
this.velocityY = 0;
this.shootTimer = 0;
this.bullets = [];
this.health = 2000; // 血量增强到2000
this.maxHealth = 2000;
this.attackPattern = 0;
this.attackTimer = 0;
this.hitCount = 0; // 记录被击中的次数
this.rageMode = false; // 狂暴模式
this.rageTimer = 0;
this.dialogueCooldown = 0; // 对话冷却
this.minionSpawnTimer = 180; // 3秒生成一次小兵
this.minions = [];
boss = this; // 设置全局boss变量
}
}
update(platforms, players) {
if (this.dead || gamePaused) return;
// 对话冷却
if (this.dialogueCooldown > 0) {
this.dialogueCooldown--;
}
// 更新小兵
for (let i = this.minions.length - 1; i >= 0; i--) {
this.minions[i].update(platforms, players);
if (this.minions[i].dead) {
this.minions.splice(i, 1);
}
}
if (this.type === 'walker') {
this.velocityX = this.speed * this.direction;
this.x += this.velocityX;
// 巡逻范围限制
if (this.x <= this.startX - this.patrolRange || this.x >= this.startX + this.patrolRange) {
this.direction *= -1;
}
// 平台边缘检测
let onPlatform = false;
for (let platform of platforms) {
if (this.x < platform.x + platform.width &&
this.x + this.width > platform.x &&
this.y + this.height > platform.y &&
this.y + this.height < platform.y + platform.height &&
this.velocityX * this.direction > 0) {
onPlatform = true;
}
}
if (!onPlatform) {
this.direction *= -1;
}
}
else if (this.type === 'jumper') {
this.velocityX = this.speed * this.direction;
this.x += this.velocityX;
// 巡逻范围限制
if (this.x <= this.startX - this.patrolRange || this.x >= this.startX + this.patrolRange) {
this.direction *= -1;
}
// 平台边缘检测
let onPlatform = false;
for (let platform of platforms) {
if (this.x < platform.x + platform.width &&
this.x + this.width > platform.x &&
this.y + this.height > platform.y &&
this.y + this.height < platform.y + platform.height &&
this.velocityX * this.direction > 0) {
onPlatform = true;
}
}
if (!onPlatform) {
this.direction *= -1;
}
// 跳跃逻辑
this.jumpTimer++;
if (this.jumpTimer > 100 && onPlatform) { // 减少跳跃间隔
this.velocityY = -12;
this.jumpTimer = 0;
}
// 应用重力
this.velocityY += 0.5;
this.y += this.velocityY;
// 平台碰撞
for (let platform of platforms) {
if (this.x < platform.x + platform.width &&
this.x + this.width > platform.x &&
this.y + this.height > platform.y &&
this.y + this.height < platform.y + platform.height &&
this.velocityY > 0) {
this.y = platform.y - this.height;
this.velocityY = 0;
}
}
}
else if (this.type === 'chaser') {
// 追踪最近的玩家
let closestPlayer = null;
let minDistance = this.aggroRange;
for (let player of players) {
let distance = Math.sqrt(
Math.pow(this.x - player.x, 2) +
Math.pow(this.y - player.y, 2)
);
if (distance < minDistance) {
minDistance = distance;
closestPlayer = player;
}
}
if (closestPlayer) {
// 追踪逻辑
if (this.x < closestPlayer.x) {
this.velocityX = this.speed;
} else if (this.x > closestPlayer.x) {
this.velocityX = -this.speed;
}
if (this.y < closestPlayer.y) {
this.velocityY = this.speed;
} else if (this.y > closestPlayer.y) {
this.velocityY = -this.speed;
}
} else {
// 没有玩家在范围内,随机移动
this.velocityX *= 0.9;
this.velocityY *= 0.9;
}
// 限制速度
if (this.velocityX > this.speed) this.velocityX = this.speed;
if (this.velocityX < -this.speed) this.velocityX = -this.speed;
if (this.velocityY > this.speed) this.velocityY = this.speed;
if (this.velocityY < -this.speed) this.velocityY = -this.speed;
this.x += this.velocityX;
this.y += this.velocityY;
}
else if (this.type === 'flyer') {
// 飞行敌人,可以在空中移动
this.velocityX = this.speed * this.direction;
this.x += this.velocityX;
// 巡逻范围限制
if (this.x <= this.startX - this.patrolRange || this.x >= this.startX + this.patrolRange) {
this.direction *= -1;
}
// 上下浮动
this.y = this.startY + Math.sin(Date.now() / 500) * 30; // 增加浮动幅度
}
else if (this.type === 'shooter') {
// 射手敌人
this.velocityX = this.speed * this.direction;
this.x += this.velocityX;
// 巡逻范围限制
if (this.x <= this.startX - this.patrolRange || this.x >= this.startX + this.patrolRange) {
this.direction *= -1;
}
// 平台边缘检测
let onPlatform = false;
for (let platform of platforms) {
if (this.x < platform.x + platform.width &&
this.x + this.width > platform.x &&
this.y + this.height > platform.y &&
this.y + this.height < platform.y + platform.height &&
this.velocityX * this.direction > 0) {
onPlatform = true;
}
}
if (!onPlatform) {
this.direction *= -1;
}
// 射击逻辑
this.shootTimer++;
if (this.shootTimer > 120) { // 每2秒射击一次
let bulletX = this.direction > 0 ? this.x + this.width : this.x;
let bulletY = this.y + this.height / 2;
this.bullets.push(new Bullet(bulletX, bulletY, this.direction, '#795548'));
this.shootTimer = 0;
}
// 更新子弹
for (let i = this.bullets.length - 1; i >= 0; i--) {
this.bullets[i].update();
// 检查子弹是否超出屏幕
if (this.bullets[i].isOffScreen()) {
this.bullets.splice(i, 1);
} else {
// 检查子弹与玩家碰撞
for (let player of players) {
if (this.bullets[i].x < player.x + player.width &&
this.bullets[i].x + this.bullets[i].width > player.x &&
this.bullets[i].y < player.y + player.height &&
this.bullets[i].y + this.bullets[i].height > player.y) {
player.respawn();
player.lives--;
player.invincible = 120;
this.bullets.splice(i, 1);
if (player.lives <= 0) {
gameOver();
}
break;
}
}
}
}
}
else if (this.type === 'boss') {
// Boss敌人 - 金文翔
this.velocityX = this.speed * this.direction;
this.x += this.velocityX;
// 狂暴模式
if (this.health <= this.maxHealth * 0.3 && !this.rageMode) {
this.rageMode = true;
this.rageTimer = 300; // 5秒狂暴模式
this.speed *= 1.5;
this.color = '#FF0000'; // 变红
// 触发对话
if (this.dialogueCooldown === 0) {
showDialogue([
{ speaker: "金文翔", text: "可恶!你竟然把我逼到这种地步!我要认真了!" }
], function() {
// 对话结束后继续游戏
});
this.dialogueCooldown = 300; // 5秒冷却
}
}
if (this.rageMode) {
this.rageTimer--;
if (this.rageTimer <= 0) {
this.rageMode = false;
this.speed /= 1.5;
this.color = '#D32F2F';
}
}
// 生成小兵
this.minionSpawnTimer--;
if (this.minionSpawnTimer <= 0) {
this.spawnMinion();
this.minionSpawnTimer = 180 + Math.floor(Math.random() * 60); // 3-4秒生成一次
}
// 随机触发对话
if (Math.random() < 0.002 && this.dialogueCooldown === 0 && !this.dialogueTriggered) { // 低概率触发
const dialogues = [
{ speaker: "金文翔", text: "哈哈哈,宾犬就这点本事吗?" },
{ speaker: "金文翔", text: "许子昂是我的,你休想救走他!" },
{ speaker: "金文翔", text: "看我的绝招!" },
{ speaker: "金文翔", text: "我的小兵们,给我上!" },
{ speaker: "金文翔", text: "你不可能打败我的!" }
];
const randomDialogue = dialogues[Math.floor(Math.random() * dialogues.length)];
showDialogue([randomDialogue], function() {
// 对话结束后继续游戏
});
this.dialogueCooldown = 300; // 5秒冷却
this.dialogueTriggered = true;
}
// 边界检查
if (this.x <= 0 || this.x + this.width >= canvas.width) {
this.direction *= -1;
}
// 上下浮动
this.y = this.startY + Math.sin(Date.now() / 300) * 40; // 增加浮动幅度
// 攻击模式
this.attackTimer++;
if (this.attackTimer > 120) {
this.attackPattern = Math.floor(Math.random() * 4); // 增加攻击模式
this.attackTimer = 0;
}
// 射击逻辑 - 增强Boss技能
this.shootTimer++;
if (this.shootTimer > 60) { // 每1秒射击一次
if (this.attackPattern === 0) {
// 单发子弹
let bulletX = this.direction > 0 ? this.x + this.width : this.x;
let bulletY = this.y + this.height / 2;
this.bullets.push(new Bullet(bulletX, bulletY, this.direction, '#D32F2F'));
} else if (this.attackPattern === 1) {
// 三发散射
for (let i = -1; i <= 1; i++) {
let bulletX = this.direction > 0 ? this.x + this.width : this.x;
let bulletY = this.y + this.height / 2 + i * 25;
this.bullets.push(new Bullet(bulletX, bulletY, this.direction, '#D32F2F'));
}
} else if (this.attackPattern === 2) {
// 五发散弹
for (let i = -2; i <= 2; i++) {
let bulletX = this.direction > 0 ? this.x + this.width : this.x;
let bulletY = this.y + this.height / 2 + i * 20;
this.bullets.push(new Bullet(bulletX, bulletY, this.direction, '#D32F2F'));
}
} else if (this.attackPattern === 3) {
// 追踪子弹
if (player) {
let dx = player.x - this.x;
let dy = player.y - this.y;
let distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
let bulletX = this.x + this.width / 2;
let bulletY = this.y + this.height / 2;
let bullet = new Bullet(bulletX, bulletY, 1, '#FF0000');
bullet.speed = 8;
bullet.directionX = dx / distance;
bullet.directionY = dy / distance;
bullet.update = function() {
this.x += this.speed * this.directionX;
this.y += this.speed * this.directionY;
};
this.bullets.push(bullet);
}
}
}
this.shootTimer = 0;
}
// 更新子弹
for (let i = this.bullets.length - 1; i >= 0; i--) {
if (this.bullets[i].update) {
this.bullets[i].update();
}
// 检查子弹是否超出屏幕
if (this.bullets[i].x < -100 || this.bullets[i].x > canvas.width + 100 ||
this.bullets[i].y < -100 || this.bullets[i].y > canvas.height + 100) {
this.bullets.splice(i, 1);
} else {
// 检查子弹与玩家碰撞
for (let player of players) {
if (this.bullets[i].x < player.x + player.width &&
this.bullets[i].x + this.bullets[i].width > player.x &&
this.bullets[i].y < player.y + player.height &&
this.bullets[i].y + this.bullets[i].height > player.y) {
player.respawn();
player.lives--;
player.invincible = 120;
this.bullets.splice(i, 1);
if (player.lives <= 0) {
gameOver();
}
break;
}
}
}
}
// 更新Boss血条
if (bossHealthBar.style.display !== 'block') {
bossHealthBar.style.display = 'block';
}
bossHealthFill.style.width = `${(this.health / this.maxHealth) * 100}%`;
bossHitsElement.textContent = this.hitCount;
}
// 边界检查
if (this.x < 0) this.x = 0;
if (this.x + this.width > canvas.width) this.x = canvas.width - this.width;
if (this.y < 0) this.y = 0;
if (this.y + this.height > canvas.height) this.y = canvas.height - this.height;
// 更新粒子
for (let i = this.particles.length - 1; i >= 0; i--) {
if (!this.particles[i].update()) {
this.particles.splice(i, 1);
}
}
}
spawnMinion() {
if (this.type === 'boss') {
// 生成小兵
const minionTypes = ['walker', 'jumper', 'flyer'];
const minionType = minionTypes[Math.floor(Math.random() * minionTypes.length)];
// 在小范围内随机生成位置
const offsetX = (Math.random() - 0.5) * 100;
const offsetY = (Math.random() - 0.5) * 100;
const minion = new Enemy(
this.x + this.width/2 + offsetX,
this.y + this.height/2 + offsetY,
minionType,
50
);
// 小兵生成效果
const spawnEffect = document.createElement('div');
spawnEffect.className = 'minion-spawn';
spawnEffect.style.left = (minion.x * canvas.clientWidth / canvas.width) + 'px';
spawnEffect.style.top = (minion.y * canvas.clientHeight / canvas.height) + 'px';
document.getElementById('gameContainer').appendChild(spawnEffect);
// 移除效果
setTimeout(() => {
if (spawnEffect.parentNode) {
spawnEffect.parentNode.removeChild(spawnEffect);
}
}, 500);
this.minions.push(minion);
enemies.push(minion);
// 显示对话
if (Math.random() < 0.3 && this.dialogueCooldown === 0) {
showDialogue([
{ speaker: "金文翔", text: "出来吧,我的小兵们!" }
], function() {
// 对话结束后继续游戏
});
this.dialogueCooldown = 300;
}
}
}
draw() {
if (this.dead) return;
// 绘制小兵
for (let minion of this.minions) {
minion.draw();
}
ctx.fillStyle = this.color;
if (this.type === 'walker') {
// 绘制身体
ctx.fillRect(this.x, this.y, this.width, this.height);
// 绘制眼睛
ctx.fillStyle = 'white';
ctx.fillRect(this.direction > 0 ? this.x + this.width - 15 : this.x + 5, this.y + 10, 8, 8);
ctx.fillStyle = 'black';
ctx.fillRect(this.direction > 0 ? this.x + this.width - 13 : this.x + 7, this.y + 12, 4, 4);
// 绘制嘴巴
ctx.fillStyle = '#FF5252';
ctx.fillRect(this.x + 12, this.y + 25, 10, 4);
// 绘制手臂
ctx.fillStyle = this.color;
ctx.fillRect(this.x - 5, this.y + 10, 8, 10);
ctx.fillRect(this.x + this.width - 3, this.y + 10, 8, 10);
}
else if (this.type === 'jumper') {
// 绘制身体
ctx.beginPath();
ctx.arc(this.x + this.width/2, this.y + this.height/2, this.width/2, 0, Math.PI * 2);
ctx.fill();
// 绘制眼睛
ctx.fillStyle = 'white';
ctx.beginPath();
ctx.arc(this.direction > 0 ? this.x + this.width - 10 : this.x + 10, this.y + 12, 4, 0, Math.PI * 2);
ctx.fill();
ctx.fillStyle = 'black';
ctx.beginPath();
ctx.arc(this.direction > 0 ? this.x + this.width - 10 : this.x + 10, this.y + 12, 2, 0, Math.PI * 2);
ctx.fill();
// 绘制嘴巴
ctx.fillStyle = '#FF5252';
ctx.beginPath();
ctx.arc(this.x + this.width/2, this.y + 20, 6, 0, Math.PI);
ctx.fill();
}
else if (this.type === 'chaser') {
// 绘制身体
ctx.beginPath();
ctx.moveTo(this.x + this.width/2, this.y);
ctx.lineTo(this.x + this.width, this.y + this.height);
ctx.lineTo(this.x, this.y + this.height);
ctx.closePath();
ctx.fill();
// 绘制眼睛
ctx.fillStyle = 'white';
ctx.beginPath();
ctx.arc(this.x + this.width/2, this.y + 12, 4, 0, Math.PI * 2);
ctx.fill();
ctx.fillStyle = 'black';
ctx.beginPath();
ctx.arc(this.x + this.width/2, this.y + 12, 2, 0, Math.PI * 2);
ctx.fill();
// 绘制嘴巴
ctx.fillStyle = '#FF5252';
ctx.beginPath();
ctx.arc(this.x + this.width/2, this.y + 20, 5, 0, Math.PI);
ctx.fill();
}
else if (this.type === 'flyer') {
// 绘制身体
ctx.beginPath();
ctx.arc(this.x + this.width/2, this.y + this.height/2, this.width/2, 0, Math.PI * 2);
ctx.fill();
// 绘制翅膀
ctx.fillStyle = '#7B1FA2';
ctx.beginPath();
ctx.ellipse(this.x + this.width/2, this.y + this.height/2, this.width, this.height/3, 0, 0, Math.PI * 2);
ctx.fill();
// 绘制眼睛
ctx.fillStyle = 'white';
ctx.beginPath();
ctx.arc(this.direction > 0 ? this.x + this.width - 10 : this.x + 10, this.y + 12, 4, 0, Math.PI * 2);
ctx.fill();
ctx.fillStyle = 'black';
ctx.beginPath();
ctx.arc(this.direction > 0 ? this.x + this.width - 10 : this.x + 10, this.y + 12, 2, 0, Math.PI * 2);
ctx.fill();
// 绘制嘴巴
ctx.fillStyle = '#FF5252';
ctx.beginPath();
ctx.arc(this.x + this.width/2, this.y + 20, 5, 0, Math.PI);
ctx.fill();
}
else if (this.type === 'shooter') {
// 绘制身体
ctx.fillRect(this.x, this.y, this.width, this.height);
// 绘制炮管
ctx.fillStyle = '#5D4037';
ctx.fillRect(this.direction > 0 ? this.x + this.width : this.x - 10, this.y + this.height/2 - 3, 10, 6);
// 绘制眼睛
ctx.fillStyle = 'white';
ctx.fillRect(this.direction > 0 ? this.x + this.width - 15 : this.x + 5, this.y + 10, 8, 8);
ctx.fillStyle = 'black';
ctx.fillRect(this.direction > 0 ? this.x + this.width - 13 : this.x + 7, this.y + 12, 4, 4);
// 绘制嘴巴
ctx.fillStyle = '#FF5252';
ctx.fillRect(this.x + 12, this.y + 25, 10, 4);
// 绘制手臂
ctx.fillStyle = this.color;
ctx.fillRect(this.x - 5, this.y + 10, 8, 10);
ctx.fillRect(this.x + this.width - 3, this.y + 10, 8, 10);
// 绘制子弹
for (let bullet of this.bullets) {
bullet.draw();
}
}
else if (this.type === 'boss') {
// 绘制Boss身体
ctx.fillRect(this.x, this.y, this.width, this.height);
// 绘制装饰
ctx.fillStyle = '#B71C1C';
ctx.fillRect(this.x + 10, this.y + 10, this.width - 20, 15);
ctx.fillRect(this.x + 10, this.y + this.height - 25, this.width - 20, 15);
// 绘制眼睛 - 改进版
ctx.fillStyle = 'white';
ctx.fillRect(this.x + 25, this.y + 30, 20, 20);
ctx.fillRect(this.x + this.width - 45, this.y + 30, 20, 20);
ctx.fillStyle = 'black';
ctx.fillRect(this.x + 30, this.y + 35, 10, 10);
ctx.fillRect(this.x + this.width - 40, this.y + 35, 10, 10);
// 绘制嘴巴
ctx.fillStyle = '#FF5252';
ctx.fillRect(this.x + 40, this.y + 70, this.width - 80, 15);
// 绘制牙齿
ctx.fillStyle = 'white';
for (let i = 0; i < 7; i++) {
ctx.fillRect(this.x + 42 + i * 12, this.y + 70, 8, 6);
}
// 绘制手臂
ctx.fillStyle = this.color;
ctx.fillRect(this.x - 15, this.y + 25, 20, 30);
ctx.fillRect(this.x + this.width - 5, this.y + 25, 20, 30);
// 绘制狂暴模式效果
if (this.rageMode) {
ctx.strokeStyle = '#FF0000';
ctx.lineWidth = 5;
ctx.strokeRect(this.x - 10, this.y - 10, this.width + 20, this.height + 20);
// 绘制狂暴粒子
if (Math.random() < 0.5) {
this.particles.push(new Particle(
this.x + Math.random() * this.width,
this.y + Math.random() * this.height,
'#FF0000',
Math.random() * 5 + 2,
(Math.random() - 0.5) * 3,
(Math.random() - 0.5) * 3,
Math.random() * 30 + 20
));
}
}
// 绘制子弹
for (let bullet of this.bullets) {
bullet.draw();
}
// 绘制名字 - 金文翔
ctx.fillStyle = 'white';
ctx.font = 'bold 20px Arial';
ctx.textAlign = 'center';
ctx.fillText('金文翔', this.x + this.width/2, this.y - 15);
}
// 绘制粒子
for (let particle of this.particles) {
particle.draw();
}
}
hitByBullet(bulletType) {
// 激光子弹造成双倍伤害
const damage = bulletType === 'laser' ? 2 : bulletType === 'ability' ? 3 : 1;
this.health -= damage;
this.hitCount++;
// 显示伤害数字
createDamagePopup(this.x + this.width/2, this.y, damage);
// 添加粒子效果
for (let i = 0; i < 5; i++) {
this.particles.push(new Particle(
this.x + this.width/2,
this.y + this.height/2,
this.color,
Math.random() * 3 + 1,
(Math.random() - 0.5) * 3,
(Math.random() - 0.5) * 3,
Math.random() * 20 + 10
));
}
if (this.health <= 0) {
this.dead = true;
gameStats.killedEnemies++;
// 增加分数和连击
addScore(this.type === 'boss' ? 5000 : 100);
addCombo();
// 添加更多粒子效果
for (let i = 0; i < 25; i++) {
this.particles.push(new Particle(
this.x + this.width/2,
this.y + this.height/2,
this.color,
Math.random() * 6 + 3,
(Math.random() - 0.5) * 8,
(Math.random() - 0.5) * 8,
Math.random() * 40 + 30
));
}
// 如果是Boss,隐藏血条
if (this.type === 'boss') {
bossHealthBar.style.display = 'none';
// 显示通关消息
setTimeout(() => {
showDialogue([
{ speaker: "系统", text: "666,你竟然通关了!" },
{ speaker: "董测浩", text: "太好了!我击败了金文翔!" },
{ speaker: "旁白", text: "现在可以去解救许子昂了!" }
], function() {
// 对话结束后继续游戏
});
}, 1000);
}
}
}
}
// 金币类
class Coin {
constructor(x, y) {
this.x = x;
this.y = y;
this.width = 15;
this.height = 15;
this.color = '#FFD700';
this.animation = 0;
}
update() {
this.animation += 0.1;
}
draw() {
ctx.save();
ctx.translate(this.x + this.width/2, this.y + this.height/2);
ctx.rotate(this.animation);
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(0, 0, this.width/2, 0, Math.PI * 2);
ctx.fill();
// 添加光泽效果
ctx.fillStyle = 'rgba(255, 255, 255, 0.7)';
ctx.beginPath();
ctx.arc(-3, -3, 3, 0, Math.PI * 2);
ctx.fill();
ctx.restore();
}
}
// 危险物品类
class Hazard {
constructor(x, y, width, height, type = 'spike') {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.type = type;
this.color = type === 'spike' ? '#FF0000' : '#FF9800';
this.animation = 0;
}
update() {
this.animation += 0.05;
}
draw() {
ctx.fillStyle = this.color;
if (this.type === 'spike') {
// 绘制尖刺
ctx.beginPath();
ctx.moveTo(this.x, this.y + this.height);
ctx.lineTo(this.x + this.width/2, this.y);
ctx.lineTo(this.x + this.width, this.y + this.height);
ctx.closePath();
ctx.fill();
} else if (this.type === 'fire') {
// 绘制火焰
const pulse = 0.5 + 0.5 * Math.sin(this.animation * 3);
const size = this.width/2 * (0.8 + 0.2 * pulse);
ctx.beginPath();
ctx.arc(this.x + this.width/2, this.y + this.height/2, size, 0, Math.PI * 2);
ctx.fill();
// 火焰效果
ctx.fillStyle = 'orange';
ctx.beginPath();
ctx.arc(this.x + this.width/2, this.y + this.height/2, size * 0.6, 0, Math.PI * 2);
ctx.fill();
}
}
}
// 终点类
class Goal {
constructor(x, y, width, height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.color = '#00FF00';
this.pulse = 0;
this.glow = 0;
this.visible = true; // 第3关需要机关激活才可见
}
update() {
this.pulse += 0.05;
this.glow = 0.5 + 0.5 * Math.sin(this.pulse * 2);
// 第3关机关激活检查
if (currentLevel === 3 && !trapActivated) {
this.visible = false;
} else {
this.visible = true;
}
}
draw() {
if (!this.visible) return;
// 绘制传送门发光效果
ctx.save();
// 外发光
ctx.fillStyle = `rgba(0, 255, 255, ${0.3 * this.glow})`;
ctx.beginPath();
ctx.arc(this.x + this.width/2, this.y + this.height/2, this.width * 0.8, 0, Math.PI * 2);
ctx.fill();
// 内发光
ctx.fillStyle = `rgba(0, 200, 255, ${0.6 * this.glow})`;
ctx.beginPath();
ctx.arc(this.x + this.width/2, this.y + this.height/2, this.width * 0.6, 0, Math.PI * 2);
ctx.fill();
// 传送门核心
ctx.fillStyle = '#00FFFF';
ctx.beginPath();
ctx.arc(this.x + this.width/2, this.y + this.height/2, this.width * 0.4, 0, Math.PI * 2);
ctx.fill();
// 传送门内部旋转效果
ctx.strokeStyle = '#FFFFFF';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.arc(this.x + this.width/2, this.y + this.height/2, this.width * 0.3, 0 + this.pulse, Math.PI + this.pulse);
ctx.stroke();
ctx.beginPath();
ctx.arc(this.x + this.width/2, this.y + this.height/2, this.width * 0.25, Math.PI + this.pulse, Math.PI * 2 + this.pulse);
ctx.stroke();
ctx.restore();
// 添加脉冲效果
ctx.strokeStyle = `rgba(0, 255, 255, ${0.5 + 0.5 * Math.sin(this.pulse)})`;
ctx.lineWidth = 3;
ctx.strokeRect(this.x - 5, this.y - 5, this.width + 10, this.height + 10);
}
checkCollision(player) {
if (!this.visible) return false;
return (player.x < this.x + this.width &&
player.x + player.width > this.x &&
player.y < this.y + this.height &&
player.y + player.height > this.y);
}
}
// 对话系统
function showDialogue(dialogueArray, callback) {
dialogueSequence = dialogueArray;
currentDialogue = 0;
dialogueCallback = callback;
dialogueScreen.style.display = 'flex';
showNextDialogue();
}
function showNextDialogue() {
if (currentDialogue >= dialogueSequence.length) {
dialogueScreen.style.display = 'none';
// 如果有回调函数,则调用
if (dialogueCallback) {
dialogueCallback();
}
return;
}
const dialogue = dialogueSequence[currentDialogue];
dialogueSpeaker.textContent = dialogue.speaker;
dialogueText.textContent = dialogue.text;
currentDialogue++;
}
// 初始化关卡选择界面
function initLevelSelect() {
levelSelect.innerHTML = '';
for (let i = 1; i <= totalLevels; i++) {
const levelBtn = document.createElement('button');
levelBtn.className = 'level-btn';
levelBtn.textContent = `关卡 ${i}`;
if (allLevelsUnlocked || unlockedLevels.includes(i)) {
if (i < currentLevel) {
levelBtn.classList.add('completed');
}
levelBtn.onclick = () => {
if (gameRunning) {
togglePause();
}
startLevel(i);
};
} else {
levelBtn.classList.add('locked');
levelBtn.textContent += ' (锁定)';
}
levelSelect.appendChild(levelBtn);
}
// 初始化帧率选择
const fpsOptions = document.querySelectorAll('.fps-option');
fpsOptions.forEach(option => {
option.addEventListener('click', () => {
// 移除所有选中状态
fpsOptions.forEach(opt => opt.classList.remove('selected'));
// 添加当前选中状态
option.classList.add('selected');
// 设置帧率
targetFPS = parseInt(option.getAttribute('data-fps'));
frameInterval = 1000 / targetFPS;
});
});
}
// 关卡配置 - 4个关卡,增强版
const levelConfigs = [
// 关卡1:开始冒险 - 增强版
{
platforms: [
{x: 0, y: 500, width: 1024, height: 50}, // 地面加宽加厚
{x: 100, y: 420, width: 200, height: 20},
{x: 400, y: 360, width: 150, height: 20},
{x: 600, y: 300, width: 100, height: 20},
{x: 200, y: 240, width: 150, height: 20},
{x: 500, y: 180, width: 200, height: 20},
{x: 800, y: 120, width: 150, height: 20}, // 新增平台
{x: 100, y: 60, width: 150, height: 20}, // 新增平台
{x: 700, y: 400, width: 100, height: 20, moving: true, moveRange: 50, moveSpeed: 1}, // 移动平台
],
enemies: [
{x: 300, y: 400, type: 'walker', patrolRange: 120},
{x: 500, y: 350, type: 'walker', patrolRange: 100},
{x: 400, y: 250, type: 'flyer', patrolRange: 180},
{x: 700, y: 380, type: 'jumper', patrolRange: 80}, // 新增敌人
{x: 150, y: 50, type: 'chaser'}, // 新增敌人
],
coins: [
{x: 150, y: 390},
{x: 450, y: 340},
{x: 250, y: 240},
{x: 550, y: 170},
{x: 850, y: 110},
{x: 150, y: 50},
{x: 750, y: 390},
],
hazards: [
{x: 350, y: 480, width: 50, height: 20, type: 'spike'},
{x: 650, y: 480, width: 50, height: 20, type: 'spike'},
],
powerUps: [
{x: 350, y: 350, type: 'score'},
{x: 800, y: 110, type: 'health'},
{x: 250, y: 230, type: 'laser'},
],
checkpoints: [
{x: 300, y: 450, width: 50, height: 30}
],
goal: {x: 150, y: 40, width: 50, height: 50},
kidnappedPerson: null,
traps: []
},
// 关卡2:追踪线索 - 增强版
{
platforms: [
{x: 0, y: 500, width: 1024, height: 50},
{x: 100, y: 420, width: 150, height: 20},
{x: 300, y: 360, width: 150, height: 20},
{x: 500, y: 300, width: 150, height: 20},
{x: 200, y: 240, width: 150, height: 20},
{x: 400, y: 180, width: 150, height: 20},
{x: 600, y: 120, width: 150, height: 20},
{x: 800, y: 60, width: 150, height: 20},
{x: 100, y: 300, width: 100, height: 20, moving: true, moveRange: 80, moveSpeed: 1.5, vertical: true}, // 垂直移动平台
{x: 900, y: 200, width: 100, height: 20, moving: true, moveRange: 100, moveSpeed: 1}, // 水平移动平台
],
enemies: [
{x: 200, y: 400, type: 'jumper', patrolRange: 100},
{x: 400, y: 350, type: 'walker', patrolRange: 100},
{x: 550, y: 300, type: 'jumper', patrolRange: 100},
{x: 450, y: 160, type: 'flyer', patrolRange: 150},
{x: 750, y: 110, type: 'shooter', patrolRange: 80}, // 新增射手敌人
{x: 950, y: 50, type: 'chaser'}, // 新增追踪敌人
],
coins: [
{x: 150, y: 390},
{x: 350, y: 340},
{x: 550, y: 290},
{x: 250, y: 240},
{x: 450, y: 170},
{x: 650, y: 110},
{x: 850, y: 50},
{x: 150, y: 290},
{x: 950, y: 190},
],
hazards: [
{x: 200, y: 480, width: 80, height: 20, type: 'fire'},
{x: 500, y: 480, width: 80, height: 20, type: 'fire'},
{x: 800, y: 480, width: 80, height: 20, type: 'fire'},
],
powerUps: [
{x: 400, y: 350, type: 'health'},
{x: 200, y: 230, type: 'score'},
{x: 600, y: 110, type: 'shield'},
{x: 850, y: 50, type: 'laser'},
],
checkpoints: [
{x: 400, y: 450, width: 50, height: 30}
],
goal: {x: 850, y: 40, width: 50, height: 50},
kidnappedPerson: null,
traps: []
},
// 关卡3:接近目标 - 增强版,增加机关
{
platforms: [
{x: 0, y: 500, width: 1024, height: 50},
{x: 100, y: 420, width: 100, height: 20},
{x: 250, y: 360, width: 100, height: 20},
{x: 400, y: 300, width: 100, height: 20},
{x: 550, y: 240, width: 100, height: 20},
{x: 400, y: 180, width: 100, height: 20},
{x: 250, y: 120, width: 100, height: 20},
{x: 100, y: 60, width: 100, height: 20},
{x: 700, y: 400, width: 150, height: 20},
{x: 850, y: 340, width: 150, height: 20},
{x: 700, y: 280, width: 150, height: 20},
{x: 550, y: 400, width: 100, height: 20, moving: true, moveRange: 60, moveSpeed: 1.5}, // 移动平台
],
enemies: [
{x: 200, y: 400, type: 'chaser'},
{x: 350, y: 350, type: 'jumper', patrolRange: 80},
{x: 500, y: 300, type: 'chaser'},
{x: 350, y: 110, type: 'flyer', patrolRange: 150},
{x: 750, y: 380, type: 'shooter', patrolRange: 100},
{x: 900, y: 330, type: 'walker', patrolRange: 120},
{x: 750, y: 270, type: 'jumper', patrolRange: 80},
],
coins: [
{x: 140, y: 390},
{x: 290, y: 340},
{x: 440, y: 290},
{x: 440, y: 170},
{x: 290, y: 110},
{x: 750, y: 370},
{x: 900, y: 320},
{x: 750, y: 260},
{x: 590, y: 390},
{x: 150, y: 50},
],
hazards: [
{x: 300, y: 480, width: 100, height: 30, type: 'spike'},
{x: 600, y: 480, width: 100, height: 30, type: 'spike'},
{x: 900, y: 480, width: 100, height: 30, type: 'spike'},
{x: 150, y: 410, width: 30, height: 30, type: 'fire'},
{x: 800, y: 410, width: 30, height: 30, type: 'fire'},
],
powerUps: [
{x: 550, y: 230, type: 'laser'},
{x: 100, y: 390, type: 'score'},
{x: 400, y: 290, type: 'health'},
{x: 850, y: 330, type: 'shield'},
{x: 250, y: 110, type: 'speed'},
],
checkpoints: [
{x: 400, y: 450, width: 50, height: 30}
],
goal: {x: 150, y: 40, width: 50, height: 50}, // 修复传送门位置
kidnappedPerson: null,
traps: [
{x: 400, y: 170},
{x: 250, y: 110},
{x: 550, y: 230},
]
},
// 关卡4:最终决战 - 增强版
{
platforms: [
{x: 0, y: 500, width: 1024, height: 50},
{x: 300, y: 380, width: 200, height: 20},
{x: 200, y: 280, width: 100, height: 20},
{x: 500, y: 280, width: 100, height: 20},
{x: 100, y: 180, width: 80, height: 20},
{x: 620, y: 180, width: 80, height: 20},
{x: 400, y: 100, width: 150, height: 20},
{x: 700, y: 380, width: 150, height: 20, moving: true, moveRange: 100, moveSpeed: 1}, // 移动平台
{x: 100, y: 380, width: 150, height: 20, moving: true, moveRange: 100, moveSpeed: 1, vertical: true}, // 垂直移动平台
],
enemies: [
{x: 360, y: 310, type: 'boss'}
],
coins: [
{x: 250, y: 370},
{x: 550, y: 370},
{x: 150, y: 270},
{x: 650, y: 270},
{x: 50, y: 170},
{x: 750, y: 170},
{x: 400, y: 90},
{x: 750, y: 370},
{x: 150, y: 370},
],
hazards: [
{x: 0, y: 450, width: 150, height: 50, type: 'fire'},
{x: 874, y: 450, width: 150, height: 50, type: 'fire'},
{x: 200, y: 450, width: 150, height: 50, type: 'spike'},
{x: 500, y: 450, width: 150, height: 50, type: 'spike'},
{x: 350, y: 450, width: 100, height: 30, type: 'fire'},
{x: 574, y: 450, width: 100, height: 30, type: 'fire'},
],
powerUps: [
{x: 100, y: 370, type: 'health'},
{x: 700, y: 370, type: 'health'},
{x: 400, y: 90, type: 'laser'},
{x: 300, y: 370, type: 'score'},
{x: 200, y: 270, type: 'shield'},
{x: 500, y: 270, type: 'speed'},
],
checkpoints: [
{x: 400, y: 450, width: 50, height: 30}
],
goal: {x: 400, y: 80, width: 50, height: 50},
kidnappedPerson: {x: 400, y: 150},
traps: []
}
];
// 初始化关卡
function initLevel(level) {
// 移除之前的玩家名字元素
if (player) {
player.removeNameElement();
}
// 移除之前的许子昂元素
if (kidnappedPerson && kidnappedPerson.element) {
kidnappedPerson.element.parentNode.removeChild(kidnappedPerson.element);
}
// 移除天神效果
if (godEffectElement && godEffectElement.parentNode) {
godEffectElement.parentNode.removeChild(godEffectElement);
godEffectElement = null;
}
// 移除机关元素
for (let trap of traps) {
if (trap.element && trap.element.parentNode) {
trap.element.parentNode.removeChild(trap.element);
}
}
platforms = [];
enemies = [];
coins = [];
hazards = [];
powerUps = [];
checkpoints = [];
kidnappedPerson = null;
traps = [];
trapActivated = false;
boss = null;
const config = levelConfigs[level - 1] || levelConfigs[0];
// 创建平台
for (let platformConfig of config.platforms) {
platforms.push(new Platform(
platformConfig.x,
platformConfig.y,
platformConfig.width,
platformConfig.height,
platformConfig.color,
platformConfig.moving,
platformConfig.moveRange,
platformConfig.moveSpeed,
platformConfig.vertical
));
}
// 创建敌人
for (let enemyConfig of config.enemies) {
enemies.push(new Enemy(
enemyConfig.x,
enemyConfig.y,
enemyConfig.type,
enemyConfig.patrolRange
));
}
// 创建金币
for (let coinConfig of config.coins) {
coins.push(new Coin(coinConfig.x, coinConfig.y));
}
// 创建危险物品
for (let hazardConfig of config.hazards) {
hazards.push(new Hazard(
hazardConfig.x,
hazardConfig.y,
hazardConfig.width,
hazardConfig.height,
hazardConfig.type
));
}
// 创建道具
for (let powerUpConfig of config.powerUps) {
powerUps.push(new PowerUp(
powerUpConfig.x,
powerUpConfig.y,
powerUpConfig.type
));
}
// 创建检查点
for (let checkpointConfig of config.checkpoints) {
checkpoints.push(new Checkpoint(
checkpointConfig.x,
checkpointConfig.y,
checkpointConfig.width,
checkpointConfig.height
));
}
// 创建机关 - 第3关
if (config.traps && config.traps.length > 0) {
for (let trapConfig of config.traps) {
const trap = new Trap(trapConfig.x, trapConfig.y);
traps.push(trap);
}
}
// 创建终点 - 使用关卡配置中的位置
goal = new Goal(config.goal.x, config.goal.y, config.goal.width, config.goal.height);
// 创建被绑架的许子昂(只在最后一关)
if (config.kidnappedPerson) {
kidnappedPerson = new KidnappedPerson(config.kidnappedPerson.x, config.kidnappedPerson.y);
}
// 初始化玩家 - 根据屏幕尺寸调整初始位置
const startX = Math.min(50, canvas.width * 0.1);
const startY = canvas.height * 0.6; // 根据画布高度调整
player = new Player(startX, startY, '#3498db',
{left: 'a', right: 'd', up: 'w', skill: 'j', ability: 'q'},
'shoot');
// 重置游戏统计
gameStats = {
collectedCoins: 0,
killedEnemies: 0,
remainingLives: player.lives
};
// 重置检查点
checkpoint.active = false;
// 更新UI
playerLivesElement.textContent = player.lives;
currentLevelElement.textContent = currentLevel;
scoreValue.textContent = score;
// 调整屏幕尺寸
adjustForScreenSize();
}
// 开始特定关卡
function startLevel(level) {
currentLevel = level;
if (!unlockedLevels.includes(level)) {
unlockedLevels.push(level);
}
settingsScreen.style.display = 'none';
levelCompleteScreen.style.display = 'none';
pauseScreen.style.display = 'none';
dialogueScreen.style.display = 'none'; // 确保对话屏幕隐藏
initLevel(currentLevel);
gameRunning = true;
gamePaused = false;
// 显示剧情对话
if (currentLevel === 1) {
showDialogue([
{ speaker: "电话", text: "叮叮叮..." },
{ speaker: "董测浩", text: "喂喂喂!哪位?" },
{ speaker: "金文翔", text: "就你是许子昂大哥是吧?我跟你告诉你,你这个臭傻子,许子昂已经被我抓住了,杜宾犬级别,老弟,有本事就来抓我!" },
{ speaker: "董测浩", text: "可以,你这个老傻子还骂我杜宾犬是吧?行,老弟你等着,我这就过来了。" },
{ speaker: "旁白", text: "于是董测浩踏上了解救许子昂的旅程。" }
], function() {
// 对话结束后开始游戏
lastTime = performance.now();
requestAnimationFrame(gameLoop);
});
} else if (currentLevel === 2) {
showDialogue([
{ speaker: "董测浩", text: "继续前进,我一定要救出许子昂!这一关敌人更多了,要小心!" }
], function() {
// 对话结束后开始游戏
lastTime = performance.now();
requestAnimationFrame(gameLoop);
});
} else if (currentLevel === 3) {
showDialogue([
{ speaker: "董测浩", text: "快接近目标了,许子昂坚持住!这一关有机关,需要激活所有机关才能打开传送门!" },
{ speaker: "系统", text: "注意:需要点击屏幕上的机关按钮来激活机关,然后传送门才会出现!" }
], function() {
// 对话结束后开始游戏
lastTime = performance.now();
requestAnimationFrame(gameLoop);
});
} else if (currentLevel === 4) {
showDialogue([
{ speaker: "金文翔", text: "哟,宾犬竟然追过来了" },
{ speaker: "董测浩", text: "老狗屎头子,接受我的制裁吧。" },
{ speaker: "金文翔", text: "哈哈哈,许子昂就在牢笼里,有本事就来救他!我的血量可是2000,还能召唤小兵,你不可能赢的!" }
], function() {
// 对话结束后开始游戏
lastTime = performance.now();
requestAnimationFrame(gameLoop);
});
} else {
showDialogue([
{ speaker: "董测浩", text: `第${currentLevel}关,离许子昂又近了一步!` }
], function() {
// 对话结束后开始游戏
lastTime = performance.now();
requestAnimationFrame(gameLoop);
});
}
}
// 绘制背景
function drawBackground() {
// 绘制天空渐变
const skyGradient = ctx.createLinearGradient(0, 0, 0, canvas.height);
skyGradient.addColorStop(0, '#87CEEB');
skyGradient.addColorStop(1, '#1E90FF');
ctx.fillStyle = skyGradient;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 绘制云朵
ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
drawCloud(100, 80, 1);
drawCloud(600, 120, 1.2);
drawCloud(300, 60, 0.8);
drawCloud(800, 90, 1.1);
drawCloud(1000, 70, 0.9);
// 绘制远处山脉
ctx.fillStyle = 'rgba(0, 100, 0, 0.3)';
ctx.beginPath();
ctx.moveTo(0, canvas.height - 100);
ctx.lineTo(150, canvas.height - 150);
ctx.lineTo(300, canvas.height - 120);
ctx.lineTo(450, canvas.height - 180);
ctx.lineTo(600, canvas.height - 140);
ctx.lineTo(750, canvas.height - 160);
ctx.lineTo(900, canvas.height - 130);
ctx.lineTo(1024, canvas.height - 100);
ctx.lineTo(canvas.width, canvas.height);
ctx.lineTo(0, canvas.height);
ctx.closePath();
ctx.fill();
// 绘制太阳
ctx.fillStyle = '#FFD700';
ctx.beginPath();
ctx.arc(canvas.width - 70, 70, 30, 0, Math.PI * 2);
ctx.fill();
// 绘制太阳光芒
ctx.strokeStyle = 'rgba(255, 215, 0, 0.5)';
ctx.lineWidth = 3;
for (let i = 0; i < 12; i++) {
ctx.save();
ctx.translate(canvas.width - 70, 70);
ctx.rotate(i * Math.PI / 6);
ctx.beginPath();
ctx.moveTo(35, 0);
ctx.lineTo(50, 0);
ctx.stroke();
ctx.restore();
}
}
// 绘制云朵
function drawCloud(x, y, scale) {
ctx.save();
ctx.translate(x, y);
ctx.scale(scale, scale);
ctx.beginPath();
ctx.arc(0, 0, 20, 0, Math.PI * 2);
ctx.arc(20, -10, 25, 0, Math.PI * 2);
ctx.arc(40, 0, 20, 0, Math.PI * 2);
ctx.fill();
ctx.restore();
}
// 更新道具显示
function updatePowerUpDisplay() {
// 显示玩家的道具状态
laserTimerElement.textContent = Math.ceil(player.powerUps.laser / 60);
shieldCountElement.textContent = player.powerUps.shield;
// 显示陈浩然天神模式时间
if (chenHaoranMode) {
godTimerElement.textContent = "天神模式";
} else {
godTimerElement.textContent = "0";
}
}
// 增加分数
function addScore(points) {
score += points;
scoreValue.textContent = score;
}
// 游戏循环
function gameLoop(currentTime) {
if (!gameRunning || gamePaused) return;
// 帧率控制
const deltaTime = currentTime - lastTime;
if (deltaTime < frameInterval) {
requestAnimationFrame(gameLoop);
return;
}
lastTime = currentTime - (deltaTime % frameInterval);
// 清除画布
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 绘制背景
drawBackground();
// 更新游戏对象
for (let platform of platforms) {
platform.update();
}
player.update(platforms, enemies, coins, hazards, powerUps, checkpoints);
for (let enemy of enemies) {
enemy.update(platforms, [player]);
// 检查玩家子弹与敌人碰撞
for (let i = player.bullets.length - 1; i >= 0; i--) {
let bullet = player.bullets[i];
if (!enemy.dead &&
bullet.x < enemy.x + enemy.width &&
bullet.x + bullet.width > enemy.x &&
bullet.y < enemy.y + enemy.height &&
bullet.y + bullet.height > enemy.y) {
enemy.hitByBullet(bullet.type);
player.bullets.splice(i, 1);
break;
}
}
}
for (let coin of coins) {
coin.update();
}
for (let hazard of hazards) {
hazard.update();
}
for (let powerUp of powerUps) {
powerUp.update();
}
for (let trap of traps) {
trap.updateElementPosition();
}
goal.update();
// 更新被绑架的许子昂位置
if (kidnappedPerson) {
kidnappedPerson.updateElementPosition();
// 检查玩家是否接触到许子昂
kidnappedPerson.checkCollision(player);
}
// 更新伤害数字
updateDamagePopups();
// 绘制游戏对象
for (let platform of platforms) {
platform.draw();
}
for (let hazard of hazards) {
hazard.draw();
}
for (let powerUp of powerUps) {
powerUp.draw();
}
for (let coin of coins) {
coin.draw();
}
for (let checkpoint of checkpoints) {
checkpoint.draw();
}
for (let enemy of enemies) {
enemy.draw();
}
// 绘制被绑架的许子昂
if (kidnappedPerson) {
kidnappedPerson.draw();
}
goal.draw();
player.draw();
// 绘制伤害数字
drawDamagePopups();
// 更新道具显示
updatePowerUpDisplay();
// 检查关卡完成条件
if (goal.checkCollision(player)) {
// 如果是最后一关,需要击败Boss并且解救许子昂才能完成
if (currentLevel === totalLevels) {
let bossDefeated = true;
for (let enemy of enemies) {
if (enemy.type === 'boss' && !enemy.dead) {
bossDefeated = false;
break;
}
}
// 检查许子昂是否被解救
let rescued = kidnappedPerson ? kidnappedPerson.rescued : false;
if (bossDefeated && rescued) {
levelComplete();
}
} else {
levelComplete();
}
}
// 继续游戏循环
requestAnimationFrame(gameLoop);
}
// 关卡完成
function levelComplete() {
gameRunning = false;
// 解锁下一关
if (!unlockedLevels.includes(currentLevel + 1) && currentLevel < totalLevels) {
unlockedLevels.push(currentLevel + 1);
}
// 更新游戏统计
gameStats.remainingLives = player.lives;
collectedCoinsElement.textContent = gameStats.collectedCoins;
killedEnemiesElement.textContent = gameStats.killedEnemies;
remainingLivesElement.textContent = gameStats.remainingLives;
maxComboElement.textContent = maxCombo;
levelScoreElement.textContent = score;
// 如果是最后一关,显示特殊消息和开发者致谢
if (currentLevel === totalLevels) {
levelCompleteTitle.textContent = "大获全胜!";
levelCompleteText.textContent = "恭喜你成功解救许子昂!";
// 显示开发者致谢界面
setTimeout(() => {
levelCompleteScreen.style.display = 'none';
thanksScreen.style.display = 'flex';
}, 2000);
} else {
levelCompleteTitle.textContent = "关卡完成!";
levelCompleteText.textContent = "恭喜你通过了当前关卡!";
levelCompleteScreen.style.display = 'block';
}
}
// 游戏结束
function gameOver() {
gameRunning = false;
// 显示失败消息
showDialogue([
{ speaker: "金文翔", text: "哈哈哈,你这个老狗屎头子杜宾犬董测浩还想通关?" },
{ speaker: "董测浩", text: "可恶!我一定会再来的!" }
], function() {
// 延迟返回主菜单
setTimeout(() => {
startScreen.style.display = 'flex';
}, 2000);
});
}
// 从公告进入主菜单
function showMainMenu() {
announcementScreen.style.display = 'none';
startScreen.style.display = 'flex';
}
// 开始游戏(从主菜单开始)
function startGame() {
startScreen.style.display = 'none';
levelCompleteScreen.style.display = 'none';
pauseScreen.style.display = 'none';
currentLevel = 1;
score = 0;
scoreValue.textContent = score;
unlockedLevels = [1];
allLevelsUnlocked = false;
// 开始第一关
startLevel(currentLevel);
}
// 下一关
function nextLevel() {
currentLevel++;
if (currentLevel > totalLevels) {
alert('恭喜!你完成了所有关卡!');
startScreen.style.display = 'flex';
return;
}
levelCompleteScreen.style.display = 'none';
startLevel(currentLevel);
}
// 暂停游戏
function togglePause() {
gamePaused = !gamePaused;
if (gamePaused) {
pauseScreen.style.display = 'flex';
} else {
pauseScreen.style.display = 'none';
if (gameRunning) {
lastTime = performance.now();
requestAnimationFrame(gameLoop);
}
}
}
// 重新开始当前关卡
function restartLevel() {
pauseScreen.style.display = 'none';
startLevel(currentLevel);
}
// 返回主菜单
function returnToMenu() {
pauseScreen.style.display = 'none';
settingsScreen.style.display = 'none';
thanksScreen.style.display = 'none';
startScreen.style.display = 'flex';
gameRunning = false;
// 移除玩家名字元素
if (player) {
player.removeNameElement();
}
// 移除机关元素
for (let trap of traps) {
if (trap.element && trap.element.parentNode) {
trap.element.parentNode.removeChild(trap.element);
}
}
}
// 打开设置界面
function openSettings() {
pauseScreen.style.display = 'none';
initLevelSelect();
settingsScreen.style.display = 'flex';
}
// 事件监听
continueBtn.addEventListener('click', showMainMenu);
startBtn.addEventListener('click', startGame);
nextLevelBtn.addEventListener('click', nextLevel);
resumeBtn.addEventListener('click', () => togglePause());
restartBtn.addEventListener('click', restartLevel);
menuBtn.addEventListener('click', returnToMenu);
menuBtn2.addEventListener('click', returnToMenu);
settingsBtn.addEventListener('click', openSettings);
settingsBtn2.addEventListener('click', openSettings);
dialogueNextBtn.addEventListener('click', showNextDialogue);
backToGameBtn.addEventListener('click', () => {
settingsScreen.style.display = 'none';
if (gameRunning) {
togglePause();
}
});
backToMenuBtn.addEventListener('click', returnToMenu);
thanksBackBtn.addEventListener('click', returnToMenu);
// 初始化移动端控制
initMobileControls();
// 初始化:显示公告屏幕
announcementScreen.style.display = 'flex';
// 初始调整屏幕尺寸
adjustForScreenSize();
// 页面加载完成后初始化
window.onload = function() {
checkOrientation();
if (!orientationWarning.style.display || orientationWarning.style.display === 'none') {
adjustForScreenSize();
drawBackground(); // 绘制初始背景
}
};
</script>
</body>
</html>
index.html
style.css
index.js
md
README.md
index.html