共计 14805 个字符,预计需要花费 38 分钟才能阅读完成。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>乳糖酶大冒险 · 消化系统奇遇记</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
user-select: none;
}
body {
background: linear-gradient(145deg, #d4eefe 0%, #b8d9f5 100%);
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 20px;
font-family: 'Segoe UI', 'system-ui', 'Poppins', sans-serif;
}
/* 游戏主容器 */
.game-container {
background: #2b4f6e;
padding: 12px;
border-radius: 28px;
box-shadow: 0 20px 35px rgba(0, 0, 0, 0.3), inset 0 1px 2px rgba(255, 255, 255, 0.2);
}
canvas {
display: block;
margin: 0 auto;
border-radius: 16px;
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.4);
cursor: pointer;
}
.info-panel {
background: #fff7e8;
border-radius: 48px;
padding: 8px 20px;
margin-bottom: 14px;
width: 800px;
display: flex;
justify-content: space-between;
align-items: center;
font-weight: bold;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
border: 1px solid #ffdd99;
backdrop-filter: blur(2px);
}
.hp-area {
display: flex;
align-items: center;
gap: 12px;
background: #2d2f36;
padding: 5px 15px;
border-radius: 40px;
color: white;
text-shadow: 0 1px 0 black;
}
.bar-box {
width: 120px;
height: 18px;
background-color: #4a2a2a;
border-radius: 20px;
overflow: hidden;
border: 1px solid #ffb347;
}
.hp-bar {
width: 100%;
height: 100%;
background: #e63946;
transition: width 0.1s ease;
border-radius: 20px;
}
.score-board {
background: #1e2f3c;
padding: 5px 20px;
border-radius: 32px;
color: #f9d56e;
font-family: monospace;
font-size: 1.2rem;
letter-spacing: 1px;
}
.state-badge {
background: #3a5e3f;
padding: 5px 18px;
border-radius: 28px;
color: #e9f5db;
font-size: 0.9rem;
box-shadow: inset 0 0 4px #7abf7e, 0 2px 4px rgba(0,0,0,0.2);
}
.tip {
margin-top: 16px;
background: #fef9e6;
padding: 8px 20px;
border-radius: 60px;
font-size: 14px;
color: #2c4b32;
font-weight: 500;
width: 800px;
text-align: center;
box-shadow: 0 2px 6px rgba(0,0,0,0.1);
border: 1px solid #ffcf9a;
}
.tip kbd {
background: #333;
color: white;
border-radius: 6px;
padding: 2px 8px;
font-family: monospace;
margin: 0 4px;
font-weight: bold;
}
@keyframes pulse {
0% { opacity: 0.7; }
100% { opacity: 1; }
}
</style>
</head>
<body>
<div class="info-panel">
<div class="hp-area">
💊 酶活性 · 血量
<div class="bar-box">
<div id="hp-bar" class="hp-bar" style="width: 100%"></div>
</div>
<span id="hp-text" style="min-width: 45px;">3/3</span>
</div>
<div class="score-board">
🧬 第 <span id="level">1</span> 关 | 乳糖收集:<span id="score">0</span> / <span id="targetNum">22</span>
</div>
<div class="state-badge" id="state">
🟢 乳糖酶活性正常
</div>
</div>
<div class="game-container">
<canvas id="gameCanvas" width="800" height="420" style="border: 3px solid #ffcf8a; background: #9fc9e0;"></canvas>
</div>
<div class="tip">
🎮 <kbd>←</kbd> <kbd>→</kbd> 移动 | <kbd>空格</kbd> 跳跃 <br>
🧪 收集黄色 <span style="color:#e5b83c;">●</span> 乳糖达标自动过关 | 🍇 绿色 <span style="color:#45b634;">●</span> 葡萄糖回血(5 秒刷新)<br>
🦠 避开黑色病菌 | 🔵 镁离子获得无敌 + 净化 | ⚠️ 红 / 紫 / 灰 / 绿地面会失活并持续掉血
</div>
<script>
(function(){
// ---------- CANVAS ----------
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
// ---------- 全局状态 ----------
let nowLevel = 1;
let score = 0, target = 22;
let hp = 3, maxHp = 3;
let isInactive = false, inactiveTimer = 0;
let isLowTemp = false, lowTempTimer = 0;
let inDanger = false; // 是否站在危险地形上
let dangerDamageCooldown = 0; // 危险地形伤害间隔(帧)
let invincible = 0; // 无敌帧数
let healTimer = 0;
const GLU_REFRESH_TIME = 300; // 葡萄糖刷新帧数(5 秒 60fps ≈300)
// 玩家属性
const player = {
x: 40, y: 320, w: 30, h: 36,
speed: 3.2,
jumpSp: -11.8,
grav: 0.52,
vy: 0,
onGround: true
};
// ---------- 关卡数据(完整修复断层 + 衔接跳板)----------
const levelData = {
1: {
target: 22,
map: [
{x:0,y:380,w:110,h:40,t:0},{x:110,y:380,w:130,h:40,t:1},{x:240,y:380,w:95,h:40,t:0},
{x:335,y:380,w:105,h:40,t:2},{x:440,y:380,w:85,h:40,t:0},{x:525,y:380,w:120,h:40,t:3},
{x:645,y:380,w:75,h:40,t:0},{x:720,y:380,w:80,h:40,t:4},
{x:70,y:305,w:65,h:22,t:0},{x:180,y:275,w:72,h:22,t:5},{x:295,y:310,w:68,h:22,t:0},
{x:405,y:265,w:75,h:22,t:5},{x:530,y:300,w:70,h:22,t:0},{x:640,y:255,w:80,h:22,t:0},
{x:150,y:210,w:75,h:22,t:0},{x:270,y:175,w:82,h:22,t:4},{x:395,y:205,w:78,h:22,t:0},
{x:520,y:160,w:85,h:22,t:1},{x:655,y:195,w:72,h:22,t:0},{x:320,y:110,w:90,h:22,t:0}
],
lactose: [
{x:55,y:342,w:18,h:18},{x:270,y:342,w:18,h:18},{x:470,y:342,w:18,h:18},{x:675,y:342,w:18,h:18},
{x:92,y:267,w:18,h:18},{x:205,y:237,w:18,h:18},{x:318,y:272,w:18,h:18},
{x:430,y:227,w:18,h:18},{x:552,y:262,w:18,h:18},{x:668,y:217,w:18,h:18},
{x:175,y:172,w:18,h:18},{x:318,y:132,w:18,h:18},{x:422,y:167,w:18,h:18},
{x:555,y:122,w:18,h:18},{x:678,y:157,w:18,h:18},{x:355,y:67,w:18,h:18},
{x:15,y:342,w:18,h:18},{x:395,y:342,w:18,h:18},{x:575,y:342,w:18,h:18},
{x:122,y:267,w:18,h:18},{x:460,y:227,w:18,h:18},{x:235,y:172,w:18,h:18}
],
glucose: [
{x:100,y:265,w:16,h:16,exist:true,cd:0,originX:100,originY:265},
{x:440,y:225,w:16,h:16,exist:true,cd:0,originX:440,originY:225},
{x:665,y:155,w:16,h:16,exist:true,cd:0,originX:665,originY:155}
],
germs: [
{x:535,y:274,w:26,h:26,minX:530,maxX:595,speed:0.55,dir:1},
{x:660,y:169,w:26,h:26,minX:655,maxX:722,speed:0.55,dir:-1}
],
mg: {x:358,y:70,w:20,h:20,exist:true},
playerStart: {x:40,y:320}
},
2: {
target: 24,
map: [
{x:0,y:380,w:90,h:40,t:1},{x:90,y:380,w:120,h:40,t:0},{x:210,y:380,w:100,h:40,t:3},
{x:310,y:380,w:110,h:40,t:0},{x:420,y:380,w:95,h:40,t:4},{x:515,y:380,w:105,h:40,t:0},
{x:620,y:380,w:90,h:40,t:2},{x:710,y:380,w:90,h:40,t:0},
{x:50,y:295,w:70,h:22,t:5},{x:160,y:260,w:80,h:22,t:0},{x:275,y:300,w:75,h:22,t:5},
{x:390,y:250,w:82,h:22,t:0},{x:510,y:290,w:76,h:22,t:5},{x:630,y:240,w:85,h:22,t:0},
{x:120,y:200,w:80,h:22,t:0},
{x:210,y:182,w:45,h:22,t:0},{x:235,y:165,w:78,h:22,t:1},
{x:322,y:182,w:38,h:22,t:0},{x:355,y:195,w:83,h:22,t:0},
{x:475,y:150,w:80,h:22,t:0},{x:560,y:168,w:35,h:22,t:0},
{x:595,y:180,w:75,h:22,t:4},{x:290,y:100,w:95,h:22,t:0}
],
lactose: [
{x:115,y:342,w:18,h:18},{x:340,y:342,w:18,h:18},{x:540,y:342,w:18,h:18},{x:730,y:342,w:18,h:18},
{x:72,y:257,w:18,h:18},{x:185,y:222,w:18,h:18},{x:300,y:257,w:18,h:18},
{x:418,y:212,w:18,h:18},{x:538,y:252,w:18,h:18},{x:658,y:202,w:18,h:18},
{x:145,y:157,w:18,h:18},{x:262,y:122,w:18,h:18},{x:382,y:152,w:18,h:18},
{x:502,y:107,w:18,h:18},{x:622,y:137,w:18,h:18},{x:322,y:57,w:18,h:18},
{x:20,y:342,w:18,h:18},{x:445,y:342,w:18,h:18},{x:645,y:342,w:18,h:18},
{x:98,y:257,w:18,h:18},{x:443,y:212,w:18,h:18},{x:258,y:157,w:18,h:18},
{x:525,y:107,w:18,h:18},{x:682,y:202,w:18,h:18}
],
glucose: [
{x:182,y:220,w:16,h:16,exist:true,cd:0,originX:182,originY:220},
{x:535,y:250,w:16,h:16,exist:true,cd:0,originX:535,originY:250},
{x:500,y:105,w:16,h:16,exist:true,cd:0,originX:500,originY:105}
],
germs: [
{x:165,y:234,w:26,h:26,minX:160,maxX:238,speed:0.55,dir:1},
{x:635,y:214,w:26,h:26,minX:630,maxX:713,speed:0.55,dir:-1}
],
mg: {x:325,y:58,w:20,h:20,exist:true},
playerStart: {x:30,y:320}
}
};
// 当前关卡动态数据
let currentMap = [];
let currentLactose = [];
let currentGlucose = [];
let currentGerms = [];
let currentMg = {};
// ---------- 辅助函数 ----------
function updateHpUI() {
let percent = (hp / maxHp) * 100;
document.getElementById('hp-bar').style.width = percent + '%';
document.getElementById('hp-text').innerText = `${hp}/${maxHp}`;
}
// AABB 碰撞检测
function rectCollide(r1, r2) {
return !(r2.x > r1.x + r1.w ||
r2.x + r2.w < r1.x ||
r2.y > r1.y + r1.h ||
r2.y + r2.h < r1.y);
}
// 受到伤害
function loseHp() {
if (invincible > 0) return;
hp--;
invincible = 55; // 大约 0.9 秒无敌
updateHpUI();
if (hp <= 0) {
alert('💔 乳糖酶失活!病菌与恶劣环境破坏了酶结构... 重新挑战本关');
loadLevel(nowLevel);
}
}
// 葡萄糖回血 + 刷新计时
function addHpByGlc(item) {
if (hp < maxHp) {
hp++;
updateHpUI();
}
item.exist = false;
item.cd = GLU_REFRESH_TIME;
}
// 加载关卡
function loadLevel(lv) {
const data = levelData[lv];
if (!data) return;
nowLevel = lv;
target = data.target;
score = 0;
hp = maxHp;
invincible = 0;
isInactive = false; inactiveTimer = 0;
isLowTemp = false; lowTempTimer = 0;
inDanger = false;
dangerDamageCooldown = 0;
healTimer = 0;
// 深拷贝避免引用混乱
currentMap = JSON.parse(JSON.stringify(data.map));
currentLactose = JSON.parse(JSON.stringify(data.lactose));
currentGlucose = JSON.parse(JSON.stringify(data.glucose));
currentGerms = JSON.parse(JSON.stringify(data.germs));
currentMg = JSON.parse(JSON.stringify(data.mg));
player.x = data.playerStart.x;
player.y = data.playerStart.y;
player.vy = 0;
player.onGround = true;
document.getElementById('level').innerText = lv;
document.getElementById('targetNum').innerText = target;
document.getElementById('score').innerText = score;
updateHpUI();
}
// ---------- 键盘控制 ----------
const keys = { left: false, right: false, jump: false };
window.addEventListener('keydown', (e) => {
if (e.code === 'ArrowLeft') keys.left = true;
if (e.code === 'ArrowRight') keys.right = true;
if (e.code === 'Space') {
keys.jump = true;
e.preventDefault();
}
// 防止方向键滚动页面
if (e.code === 'ArrowUp' || e.code === 'ArrowDown') e.preventDefault();
});
window.addEventListener('keyup', (e) => {
if (e.code === 'ArrowLeft') keys.left = false;
if (e.code === 'ArrowRight') keys.right = false;
if (e.code === 'Space') keys.jump = false;
});
// ---------- 游戏主循环 & 逻辑 ----------
function updateGame() {
// 1. 无敌递减
if (invincible > 0) invincible--;
// 2. 异常状态计时
if (isInactive) {
inactiveTimer--;
if (inactiveTimer <= 0) isInactive = false;
}
if (isLowTemp) {
lowTempTimer--;
if (lowTempTimer <= 0) isLowTemp = false;
}
// 3. 速度 / 跳跃倍率(失活 & 低温)
let spRate = 1.0, jumpRate = 1.0;
if (isInactive) { spRate = 0.5; jumpRate = 0.62; }
else if (isLowTemp) { spRate = 0.76; jumpRate = 0.86; }
let moveSpeed = player.speed * spRate;
let jumpPower = player.jumpSp * jumpRate;
// 4. 移动
if (keys.left) player.x -= moveSpeed;
if (keys.right) player.x += moveSpeed;
player.x = Math.max(2, Math.min(canvas.width - player.w - 2, player.x));
// 5. 跳跃
if (keys.jump && player.onGround) {
player.vy = jumpPower;
player.onGround = false;
}
// 6. 重力
player.vy += player.grav;
player.y += player.vy;
player.onGround = false;
// 7. 地形碰撞 (暂存安全 / 危险标志)
let safeGroundFlag = false;
let dangerFlag = false;
let newInactiveFlag = false;
let newLowTempFlag = false;
let inactiveTimerAdd = 0;
let lowTempTimerAdd = 0;
// 先按 y 排序从下往上处理? 但简单循环即可,每碰撞修正一次位置
for (let i = 0; i < currentMap.length; i++) {
const plat = currentMap[i];
if (rectCollide(player, plat)) {
// 碰撞方向: 主要处理从上往下落到平台上
let playerBottom = player.y + player.h;
let platTop = plat.y;
let prevBottom = playerBottom - player.vy;
if (player.vy >= 0 && prevBottom <= platTop) {
// 落到平台上
player.y = plat.y - player.h;
player.vy = 0;
player.onGround = true;
// 根据平台类型施加效果
if (plat.t === 0) {
safeGroundFlag = true; // 安全地面
}
else if (plat.t === 1 || plat.t === 2 || plat.t === 3 || plat.t === 4) {
// 危险失活地面
dangerFlag = true;
newInactiveFlag = true;
inactiveTimerAdd = 180;
}
else if (plat.t === 5) {
// 低温地面
newLowTempFlag = true;
lowTempTimerAdd = 220;
}
}
// 防止头顶卡砖(简单向上顶头)
else if (player.vy < 0 && player.y <= plat.y + plat.h && player.y + player.h > plat.y) {
player.y = plat.y + plat.h;
if (player.vy < 0) player.vy = 0;
}
// 左右墙推开(极少情况,但避免卡墙)
else if (player.x + player.w > plat.x && player.x < plat.x + plat.w) {
if (player.x + player.w - plat.x < plat.x + plat.w - player.x) {
player.x = plat.x - player.w;
} else {
player.x = plat.x + plat.w;
}
}
}
}
// 应用地面效果(失活 / 低温)
if (newInactiveFlag) {
isInactive = true;
inactiveTimer = Math.max(inactiveTimer, inactiveTimerAdd);
}
if (newLowTempFlag) {
isLowTemp = true;
lowTempTimer = Math.max(lowTempTimer, lowTempTimerAdd);
}
inDanger = dangerFlag;
// 8. 危险地形掉血(间隔伤害,每 25 帧约 0.4 秒掉 1 血,避免瞬间蒸发)
if (inDanger && !isInactive) {
if (dangerDamageCooldown <= 0) {
loseHp();
dangerDamageCooldown = 28; // 伤害间隔
} else {
dangerDamageCooldown--;
}
} else {
dangerDamageCooldown = 0;
}
// 9. 边界掉落死亡 (掉出画布)
if (player.y + player.h > canvas.height + 30) {
loseHp();
// 重置位置到起点
const startX = levelData[nowLevel].playerStart.x;
const startY = levelData[nowLevel].playerStart.y;
player.x = startX;
player.y = startY;
player.vy = 0;
player.onGround = false;
if (hp > 0) {
// 轻微惩罚: 避免连续掉落致死, 但已经扣血一次了
}
}
// 10. 站在安全地面回血 (且无失活 / 低温)
if (safeGroundFlag && !isInactive && !isLowTemp && hp < maxHp) {
healTimer++;
if (healTimer >= 150) { // 2.5 秒回 1 血 (60 帧)
hp++;
if (hp > maxHp) hp = maxHp;
updateHpUI();
healTimer = 0;
}
} else {
healTimer = 0;
}
// 11. 乳糖收集
for (let i = 0; i < currentLactose.length; i++) {
const lac = currentLactose[i];
if (rectCollide(player, lac)) {
score++;
document.getElementById('score').innerText = score;
currentLactose.splice(i,1);
i--;
}
}
// 12. 过关检测
if (score >= target) {
if (nowLevel === 1) {
alert('🎉 第一关通过!乳糖酶活力充沛,前往更复杂的肠道环境!');
loadLevel(2);
} else if (nowLevel === 2) {
alert('🏆 完美通关!乳糖酶成功消化所有乳糖,肠道恢复健康!🎊');
loadLevel(1); // 循环重新开始
}
return; // 关卡重载后直接跳帧重置,避免额外操作
}
// 13. 镁离子 (净化 + 无敌)
if (currentMg.exist) {
if (rectCollide(player, currentMg)) {
currentMg.exist = false;
invincible = 320; // 超长无敌
// 清除负面状态
isInactive = false;
inactiveTimer = 0;
isLowTemp = false;
lowTempTimer = 0;
}
}
// 14. 葡萄糖刷新与拾取
for (let g of currentGlucose) {
if (!g.exist) {
g.cd--;
if (g.cd <= 0) {
g.exist = true;
g.x = g.originX;
g.y = g.originY;
}
}
if (g.exist && rectCollide(player, g)) {
addHpByGlc(g);
}
}
// 15. 病菌移动 & 碰撞
for (let g of currentGerms) {
g.x += g.speed * g.dir;
if (g.x <= g.minX) { g.x = g.minX; g.dir = 1; }
if (g.x >= g.maxX) { g.x = g.maxX; g.dir = -1; }
if (rectCollide(player, g)) {
loseHp();
}
}
}
// ---------- 绘图模块 ----------
function draw() {
ctx.clearRect(0, 0, 800, 420);
// 背景装饰(肠道氛围)
ctx.fillStyle = '#9fc9e0';
ctx.fillRect(0,0,800,420);
ctx.fillStyle = '#c1e2f0';
for(let i=0;i<12;i++) {
ctx.beginPath();
ctx.arc(70+i*70, 40+Math.sin(Date.now()*0.002+i)*12, 12,0,Math.PI*2);
ctx.fill();
}
// 1. 绘制地形
for (let p of currentMap) {
let col = '#f5ecd8';
switch(p.t){
case 0: col='#f5e6c4'; break;
case 1: col='#e35f3e'; break;
case 2: col='#4d9b3a'; break;
case 3: col='#b87bcb'; break;
case 4: col='#6e6c6a'; break;
case 5: col='#7ac5e0'; break;
}
ctx.fillStyle = col;
ctx.shadowBlur = 0;
ctx.fillRect(p.x, p.y, p.w, p.h);
// 质感边缘
ctx.strokeStyle = 'rgba(0,0,0,0.2)';
ctx.strokeRect(p.x, p.y, p.w, p.h);
}
// 2. 乳糖(金黄色小球)
for (let lac of currentLactose) {
ctx.fillStyle = '#FFD966';
ctx.shadowBlur = 8;
ctx.shadowColor = '#ccaa44';
ctx.beginPath();
ctx.arc(lac.x + lac.w/2, lac.y + lac.h/2, 9, 0, Math.PI*2);
ctx.fill();
ctx.fillStyle = '#f0b27a';
ctx.beginPath();
ctx.arc(lac.x + lac.w/2 - 2, lac.y + lac.h/2 - 2, 2, 0, Math.PI*2);
ctx.fill();
}
// 3. 葡萄糖(绿色能量球)
for (let g of currentGlucose) {
if(g.exist){
ctx.fillStyle = '#5FDD9D';
ctx.shadowBlur = 6;
ctx.beginPath();
ctx.arc(g.x+8, g.y+8, 8, 0, Math.PI*2);
ctx.fill();
ctx.fillStyle = '#226622';
ctx.beginPath();
ctx.arc(g.x+5, g.y+5, 2, 0, Math.PI*2);
ctx.fill();
}
}
// 4. 镁离子(闪耀蓝光)
if (currentMg.exist) {
ctx.fillStyle = '#3B9EFF';
ctx.shadowBlur = 12;
ctx.beginPath();
ctx.arc(currentMg.x+10, currentMg.y+10, 12, 0, Math.PI*2);
ctx.fill();
ctx.fillStyle = '#FFFFFF';
ctx.beginPath();
ctx.arc(currentMg.x+7, currentMg.y+7, 3, 0, Math.PI*2);
ctx.fill();
}
// 5. 病菌
for (let g of currentGerms) {
ctx.fillStyle = '#2F2E2F';
ctx.shadowBlur = 2;
ctx.fillRect(g.x, g.y, g.w, g.h);
ctx.fillStyle = '#5a3e2e';
ctx.fillRect(g.x+5, g.y+5, 6, 6);
ctx.fillRect(g.x+15, g.y+5, 6, 6);
ctx.fillStyle = '#961010';
ctx.fillRect(g.x+10, g.y+15, 6, 5);
}
// 6. 玩家 - 乳糖酶(可爱酶蛋白)
ctx.shadowBlur = 5;
if(invincible > 0 && (Math.floor(Date.now()/60)%3 < 1)) {
ctx.fillStyle = '#F9F3C1';
} else if(isInactive) {
ctx.fillStyle = '#7C7F8C';
} else if(isLowTemp) {
ctx.fillStyle = '#5FA7CF';
} else {
ctx.fillStyle = '#E65348';
}
ctx.fillRect(player.x, player.y, player.w, player.h);
// 酶的眼睛
ctx.fillStyle = "#FFFFFF";
ctx.fillRect(player.x+6, player.y+8, 7, 7);
ctx.fillRect(player.x+18, player.y+8, 7, 7);
ctx.fillStyle = "#1F2A2E";
ctx.fillRect(player.x+7, player.y+10, 4, 4);
ctx.fillRect(player.x+19, player.y+10, 4, 4);
// 微笑
ctx.beginPath();
ctx.arc(player.x+15, player.y+22, 8, 0.05, Math.PI - 0.05);
ctx.strokeStyle = "#341C0E";
ctx.lineWidth = 2;
ctx.stroke();
ctx.shadowBlur = 0;
// 状态特效(显示危险标识)
if(inDanger && !isInactive) {
ctx.font = "bold 18px monospace";
ctx.fillStyle = "#ff5555aa";
ctx.fillText("⚠️", player.x-10, player.y-5);
}
}
// 刷新 UI 文字
function updateUItext() {
let statusMsg = '';
if (isInactive) statusMsg = '❄️ 变性失活 · 虚弱';
else if (isLowTemp) statusMsg = '🧊 低温抑制 · 活性下降';
else statusMsg = '✅ 乳糖酶活性正常';
document.getElementById('state').innerHTML = statusMsg;
document.getElementById('score').innerText = score;
}
// ---------- 动画循环 ----------
function gameLoop() {
updateGame();
draw();
updateUItext();
requestAnimationFrame(gameLoop);
}
// 启动游戏!
loadLevel(1);
gameLoop();
})();
</script>
</body>
</html>
HTML
正文完

