情绪泡泡龙——ABC消消乐大作战(顺序优化版)
by LaserPirate42525 lines32.9 KB
<!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>情绪泡泡龙——ABC消消乐大作战(顺序优化版)</title>
<style>
:root {
--bg: #fdf6f0;
--card-bg: #fffaf5;
--text: #5a4a3a;
--shadow: 0 4px 15px rgba(0, 0, 0, 0.08);
--shadow-lg: 0 8px 30px rgba(0, 0, 0, 0.12);
--radius: 18px;
--font: 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'Noto Sans SC', sans-serif;
/* 增强颜色辨识度 */
--dark-belief: #9b8cbf;
--dark-emotion: #c49a9a;
--light-belief: #ffbf47;
--light-emotion: #ffd966;
--interference-bg: #f4b084;
--interference-border: #d4895a;
}
* { margin:0; padding:0; box-sizing:border-box; }
body {
font-family: var(--font);
background: linear-gradient(135deg, #fef5ed 0%, #fde9df 30%, #fdf0f5 60%, #fef8f3 100%);
min-height: 100vh; display: flex; justify-content: center; align-items: center; padding: 10px;
-webkit-tap-highlight-color: transparent; user-select: none; -webkit-user-select: none;
}
.game-container {
width: 100%; max-width: 480px; background: var(--card-bg); border-radius: 24px;
box-shadow: var(--shadow-lg); padding: 14px 14px 16px; display: flex; flex-direction: column;
gap: 10px; position: relative; overflow: hidden;
}
.game-container::before {
content: ''; position: absolute; top: 0; left: 0; right: 0; height: 6px;
background: linear-gradient(90deg, #f9c5a7, #f7d98c, #a7d4c5, #c4b5d4, #f9c5a7);
border-radius: 24px 24px 0 0;
}
.header {
display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 6px;
padding: 6px 8px; background: #fffefb; border-radius: 12px; box-shadow: var(--shadow); margin-top: 2px;
}
.header-item {
display: flex; align-items: center; gap: 4px; font-size: 0.85rem; font-weight: 600; color: var(--text);
}
.header-item .icon { font-size: 1.2rem; }
.header-item .value { color: #d4843a; font-weight: 700; font-size: 0.95rem; min-width: 24px; text-align: center; }
.timer-warning { color: #e05a5a !important; animation: pulse-warning 0.6s ease-in-out infinite; }
@keyframes pulse-warning { 0%,100%{transform:scale(1);} 50%{transform:scale(1.15);} }
.event-display {
background: linear-gradient(135deg, #fffef9, #fef9f2); border: 2px dashed #e8d5c4;
border-radius: 12px; padding: 8px 12px; text-align: center;
}
.event-label { font-size: 0.7rem; color: #b8957a; letter-spacing: 1px; margin-bottom: 2px; }
.event-text { font-size: 1rem; font-weight: 700; color: #5a3e2b; line-height: 1.4; }
.guide-text { font-size: 0.75rem; color: #a08060; margin-top: 4px; min-height: 20px; }
.bubble-grid {
display: grid; grid-template-columns: repeat(4,1fr); grid-template-rows: repeat(3,1fr);
gap: 8px; padding: 6px; background: #fefcf9; border-radius: var(--radius);
box-shadow: inset 0 2px 8px rgba(0,0,0,0.04); min-height: 240px;
}
@media (max-width:400px) {
.bubble-grid { gap:6px; padding:4px; }
.bubble { font-size:0.65rem !important; min-height:58px !important; }
.game-container { padding:10px 8px 12px; }
.event-text { font-size:0.9rem; }
}
.bubble {
display: flex; align-items: center; justify-content: center; text-align: center;
border-radius: 50%; cursor: pointer; font-weight: 700; font-size: 0.75rem; line-height: 1.25;
padding: 5px 3px; transition: transform 0.15s, box-shadow 0.15s; position: relative;
word-break: break-all; min-height: 62px; aspect-ratio: 1/1;
box-shadow: 0 4px 10px rgba(0,0,0,0.15), inset 0 2px 0 rgba(255,255,255,0.6);
letter-spacing: 0.3px; color: #2b2b2b;
}
.bubble:active { transform:scale(0.9); }
.bubble.selected {
transform: scale(1.08); box-shadow: 0 0 0 5px rgba(100,160,220,0.6), 0 6px 20px rgba(0,0,0,0.25) !important;
z-index: 5; animation: gentle-bounce 0.5s infinite;
}
@keyframes gentle-bounce { 0%,100%{transform:scale(1.08);} 50%{transform:scale(1.14);} }
.bubble.hint-glow {
animation: hint-pulse 0.7s infinite !important;
box-shadow: 0 0 0 6px rgba(255,180,50,0.9), 0 6px 22px rgba(255,150,30,0.6) !important; z-index:4;
}
@keyframes hint-pulse {
0%,100%{box-shadow: 0 0 0 6px rgba(255,180,50,0.9), 0 6px 22px rgba(255,150,30,0.6);}
50%{box-shadow: 0 0 0 12px rgba(255,180,50,0.3), 0 8px 28px rgba(255,150,30,0.7);}
}
/* 暗色泡泡 - 不合理信念 (紫色) */
.bubble.belief-negative {
background: linear-gradient(145deg, #b9a8d6, #9b8cbf);
box-shadow: 0 4px 10px rgba(120,100,150,0.4), inset 0 2px 0 rgba(255,255,255,0.5);
color: #fff;
}
/* 暗色泡泡 - 负性情绪 (暖灰) */
.bubble.emotion-negative {
background: linear-gradient(145deg, #d9b3b3, #c49a9a);
box-shadow: 0 4px 10px rgba(160,120,120,0.4), inset 0 2px 0 rgba(255,255,255,0.5);
color: #fff;
}
/* 亮色泡泡 - 合理信念 (亮橙) */
.bubble.belief-positive {
background: linear-gradient(145deg, #ffbf47, #f0a500);
box-shadow: 0 4px 12px rgba(200,150,40,0.5), inset 0 2px 0 rgba(255,255,255,0.6);
color: #3a2a0a;
}
/* 亮色泡泡 - 正性情绪 (浅金) */
.bubble.emotion-positive {
background: linear-gradient(145deg, #ffe28c, #ffd966);
box-shadow: 0 4px 12px rgba(200,150,30,0.5), inset 0 2px 0 rgba(255,255,255,0.6);
color: #3a2a0a;
}
/* 干扰泡泡 (橙色虚线) */
.bubble.interference {
background: linear-gradient(145deg, #f9bd8e, #f4b084);
box-shadow: 0 4px 10px rgba(180,120,80,0.4), inset 0 2px 0 rgba(255,255,255,0.5);
border: 2px dashed #c47a4a;
color: #fff;
}
.bubble.bursting { animation: burst-out 0.5s forwards; }
@keyframes burst-out { 0%{transform:scale(1);opacity:1;} 30%{transform:scale(1.3);opacity:0.7;} 100%{transform:scale(0);opacity:0;} }
.bubble.collecting { animation: collect-gold 0.6s forwards; }
@keyframes collect-gold { 0%{transform:scale(1);opacity:1;} 50%{transform:scale(1.4);opacity:0.9;box-shadow:0 0 30px 20px rgba(255,200,50,0.7);} 100%{transform:scale(0);opacity:0;} }
.bubble.shaking { animation: shake 0.4s; }
@keyframes shake { 0%,100%{transform:translateX(0);} 25%{transform:translateX(-6px);} 50%{transform:translateX(6px);} 75%{transform:translateX(-3px);} }
.floating-tip {
position: fixed; pointer-events: none; z-index: 100; font-weight: 700; font-size: 0.9rem;
color: #5a3a0a; background: #fef9e8; border: 2px solid #f0c94c; border-radius: 20px;
padding: 8px 16px; box-shadow: 0 6px 20px rgba(0,0,0,0.15); animation: float-up-long 4s forwards;
white-space: nowrap; text-align: center;
left: 50%; transform: translateX(-50%);
top: 25%; /* 居中偏上 */
}
@keyframes float-up-long {
0% { opacity:0; transform:translate(-50%, 0) scale(0.6); }
15% { opacity:1; transform:translate(-50%, -15px) scale(1.05); }
80% { opacity:0.9; transform:translate(-50%, -35px) scale(1); }
100% { opacity:0; transform:translate(-50%, -60px) scale(0.8); }
}
.btn-row { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }
.btn {
padding: 10px 18px; border-radius: 25px; border: none; font-size: 0.9rem; font-weight: 700;
cursor: pointer; letter-spacing: 0.5px; transition: all 0.2s; font-family: var(--font);
box-shadow: 0 3px 10px rgba(0,0,0,0.1); display: flex; align-items: center; gap: 6px;
}
.btn:active { transform: scale(0.94); }
.btn-hint { background: #fff3d6; color: #8b6914; border: 2px solid #f0c94c; }
.btn-hint:disabled { opacity: 0.4; cursor: not-allowed; pointer-events: none; }
.btn-reset { background: #f5f0eb; color: #7a6a5a; border: 2px solid #d5c8b5; }
/* 弹窗 */
.modal-overlay {
position: fixed; top:0; left:0; right:0; bottom:0; background: rgba(0,0,0,0.55);
z-index: 200; display: flex; align-items: center; justify-content: center; animation: fade-in 0.3s;
}
@keyframes fade-in { from{opacity:0;} to{opacity:1;} }
.modal {
background: #fffefb; border-radius: 24px; padding: 24px 20px; max-width: 420px; width: 90%;
box-shadow: 0 20px 50px rgba(0,0,0,0.25); text-align: center; max-height: 85vh;
overflow-y: auto; animation: slide-up 0.4s cubic-bezier(0.34,1.56,0.64,1);
}
@keyframes slide-up { from{transform:translateY(60px);opacity:0;} to{transform:translateY(0);opacity:1;} }
.modal h2 { font-size: 1.4rem; color: #5a3e2b; margin-bottom: 8px; }
.title-badge { display: inline-block; font-size: 1rem; font-weight: 700; padding: 8px 20px; border-radius: 25px; margin: 8px 0 14px; letter-spacing: 1px; }
.badge-diamond { background:#e8f8ff; color:#2b6f9a; border:2px solid #6bc4e8; }
.badge-gold { background:#fff8e8; color:#8b6914; border:2px solid #f0c94c; }
.badge-bronze { background:#fdf5f0; color:#8b5a3a; border:2px solid #d4a080; }
.score-display { font-size: 2.5rem; font-weight: 900; color: #d4843a; }
.stars-display { font-size: 1.8rem; letter-spacing: 4px; margin: 4px 0 10px; }
.quotes-list { text-align: left; background: #fefcf8; border-radius: 14px; padding: 14px; margin: 10px 0; border: 1px solid #f0e8d8; }
.quotes-list p { padding: 6px 0; border-bottom: 1px dotted #e8d8c4; font-size: 0.8rem; color: #5a4a3a; line-height: 1.5; }
.quotes-list p:last-child { border-bottom: none; }
.btn-close { margin-top: 12px; background: #f0c94c; color: #5a3a0a; font-size: 1rem; padding: 12px 30px; border-radius: 25px; border: none; font-weight: 700; cursor: pointer; box-shadow: 0 4px 14px rgba(200,150,30,0.3); font-family: var(--font); }
.rule-icon { display: inline-block; width: 24px; height: 24px; border-radius: 50%; margin-right: 4px; vertical-align: middle; }
.rule-icon.dark { background: #9b8cbf; }
.rule-icon.light { background: #ffbf47; }
.rule-icon.interference { background: #f4b084; border: 2px dashed #c47a4a; }
</style>
</head>
<body>
<div class="game-container" id="gameContainer">
<div class="header">
<div class="header-item"><span class="icon">🎯</span>关卡:<span class="value" id="levelDisplay">1/5</span></div>
<div class="header-item"><span class="icon">⭐</span>星星:<span class="value" id="starDisplay">0</span></div>
<div class="header-item"><span class="icon">💯</span>分数:<span class="value" id="scoreDisplay">0</span></div>
<div class="header-item"><span class="icon">⏱️</span>时间:<span class="value" id="timerDisplay">90</span>秒</div>
</div>
<div class="event-display" id="eventDisplay">
<div class="event-label">📋 当前事件 A</div>
<div class="event-text" id="eventText">小组合作作业,我的建议没被采纳。</div>
<div class="guide-text" id="guideText">👆 先点击暗色配对,再按顺序匹配亮色泡泡(先信念后情绪)</div>
</div>
<div class="bubble-grid" id="bubbleGrid"></div>
<div class="btn-row">
<button class="btn btn-hint" id="btnHint">💡 提示(1次)</button>
<button class="btn btn-reset" id="btnReset">🔄 重置本关</button>
</div>
</div>
<!-- 游戏规则弹窗 -->
<div class="modal-overlay" id="ruleModal" style="display:flex;">
<div class="modal">
<h2>🫧 游戏规则</h2>
<div style="text-align:left; font-size:0.9rem; line-height:1.6; color:#5a4a3a;">
<p style="margin-bottom:10px;">🎯 <strong>目标:</strong>消除所有暗色泡泡,并按顺序收集三组亮色泡泡。</p>
<p style="margin-bottom:10px;">📌 <strong>操作方法:</strong>依次点击两个同色系泡泡进行配对。</p>
<div style="margin:12px 0; padding:10px; background:#faf5ff; border-radius:12px;">
<p><span class="rule-icon dark"></span> <strong>暗色泡泡</strong> = 不合理信念 + 负性情绪(必须消除)</p>
<p><span class="rule-icon light"></span> <strong>亮色泡泡</strong> = 合理信念 + 正性情绪(需要收集)</p>
<p><span class="rule-icon interference"></span> <strong>橙色虚边</strong> = 干扰项,点击错误<strong style="color:#e05a5a;">-10秒</strong></p>
</div>
<p style="margin-bottom:10px;">🔁 <strong>重要顺序:</strong>配对暗色泡泡无顺序要求;配对亮色泡泡时,<strong>必须先点击信念再点击情绪</strong>,否则视为错误。</p>
<p style="margin-bottom:10px;">⏱️ 每关90秒,连续两次错误会自动提示。</p>
<p>⭐ 成功收集一组亮色泡泡得10分+一颗星,全部完成进入下一关。</p>
</div>
<button class="btn-close" id="btnStartGame">🎮 开始游戏</button>
</div>
</div>
<!-- 通关弹窗(隐藏) -->
<div class="modal-overlay" id="modalOverlay" style="display:none;">
<div class="modal" id="modalContent"></div>
</div>
<script>
(function() {
const eventsData = [
{ id:0, eventA:'小组合作作业,我的建议没被采纳。', beliefNegative:'他们肯定看不起我', emotionNegative:'委屈😭、愤怒😡',
positivePairs:[
{ belief:'方案有取舍很正常', emotion:'平静😊', encouragement:'不被采纳不代表你不好✨' },
{ belief:'我可以学习别人优点', emotion:'有动力💪', encouragement:'吸收优点,你会更强!' },
{ belief:'下次表达更清晰就好', emotion:'期待🌟', encouragement:'每一次尝试都是成长!' }
]},
{ id:1, eventA:'手机被老师暂时保管了。', beliefNegative:'老师故意针对我', emotionNegative:'暴怒😡、想顶撞',
positivePairs:[
{ belief:'规则对大家都一样', emotion:'释然😌', encouragement:'遵守规则,专注听课💪' },
{ belief:'正好练习专注力', emotion:'专心📵', encouragement:'无手机干扰,效率更高!' },
{ belief:'老师为全班好', emotion:'理解👍', encouragement:'换位思考,更懂秩序。' }
]},
{ id:2, eventA:'好朋友突然不回我消息。', beliefNegative:'他肯定讨厌我了', emotionNegative:'焦虑😰、难过😢',
positivePairs:[
{ belief:'他可能在忙', emotion:'耐心🤗', encouragement:'耐心是友谊的试金石。' },
{ belief:'也许手机没电了', emotion:'轻松😌', encouragement:'别多想,信任最重要。' },
{ belief:'我也常有晚回', emotion:'包容🍃', encouragement:'将心比心,关系更融洽。' }
]},
{ id:3, eventA:'考试没考好。', beliefNegative:'我太笨了,永远学不好', emotionNegative:'沮丧😞、想放弃',
positivePairs:[
{ belief:'这次暴露了提升空间', emotion:'反思🤔', encouragement:'发现盲区就是进步!' },
{ belief:'一次考试不代表全部', emotion:'制定计划✍️', encouragement:'查漏补缺,下次逆袭!' },
{ belief:'失败是成功之母', emotion:'行动🏃', encouragement:'把错误变成阶梯。' }
]},
{ id:4, eventA:'被同学当众开了玩笑。', beliefNegative:'他在羞辱我', emotionNegative:'羞耻😳、愤怒😡',
positivePairs:[
{ belief:'他只是开玩笑', emotion:'一笑了之😄', encouragement:'大度让玩笑变轻松。' },
{ belief:'幽默是调味品', emotion:'一起笑😆', encouragement:'参与欢笑,尴尬消失!' },
{ belief:'我的感受我做主', emotion:'自信💪', encouragement:'你定义自己的情绪。' }
]}
];
const globalQuotes = ['💡 想法一变,心情就亮了!','🌈 事件无法改变,但信念可以选择。','🧠 做情绪的主人,从转念开始。','🫧 暗色泡泡不可怕,转念就能变亮色!'];
let currentLevel = 0, score = 0, stars = 0, timeLeft = 90, timerInterval = null;
let hintUsed = false, selectedBubble = null, isProcessing = false, errorCount = 0;
let allBubbles = [], allEncouragements = [], totalElapsedSeconds = 0, levelStartTime = null, gameStarted = false;
const bubbleGrid = document.getElementById('bubbleGrid');
const eventText = document.getElementById('eventText');
const guideText = document.getElementById('guideText');
const levelDisplay = document.getElementById('levelDisplay');
const starDisplay = document.getElementById('starDisplay');
const scoreDisplay = document.getElementById('scoreDisplay');
const timerDisplay = document.getElementById('timerDisplay');
const btnHint = document.getElementById('btnHint');
const btnReset = document.getElementById('btnReset');
const modalOverlay = document.getElementById('modalOverlay');
const modalContent = document.getElementById('modalContent');
const ruleModal = document.getElementById('ruleModal');
const btnStartGame = document.getElementById('btnStartGame');
function genId() { return 'b_'+Date.now()+'_'+Math.random().toString(36).substr(2,8); }
function createBubble(eventId, type, chain, text, isInterference=false, pairId=null) {
return { id:genId(), eventId, type, chain, text, isInterference, pairId, htmlEl:null };
}
function buildBubblePool(level) {
const cur = eventsData[level];
const pool = [];
pool.push(createBubble(level, 'belief', 'negative', cur.beliefNegative));
pool.push(createBubble(level, 'emotion', 'negative', cur.emotionNegative));
cur.positivePairs.forEach((pair, idx) => {
pool.push(createBubble(level, 'belief', 'positive', pair.belief, false, idx));
pool.push(createBubble(level, 'emotion', 'positive', pair.emotion, false, idx));
});
const others = eventsData.filter((_,i)=>i!==level);
const shuffled = [...others].sort(()=>Math.random()-0.5);
const ev1 = shuffled[0], ev2 = shuffled[1] || shuffled[0];
pool.push(createBubble(ev1.id, 'belief', 'negative', ev1.beliefNegative, true));
pool.push(createBubble(ev2.id, 'emotion', 'negative', ev2.emotionNegative, true));
pool.push(createBubble(ev2.id, 'belief', 'positive', ev2.positivePairs[0].belief, true, 0));
pool.push(createBubble(ev1.id, 'emotion', 'positive', ev1.positivePairs[0].emotion, true, 0));
shuffleArray(pool);
return pool;
}
function shuffleArray(arr) { for(let i=arr.length-1; i>0; i--) { const j=Math.floor(Math.random()*(i+1)); [arr[i],arr[j]]=[arr[j],arr[i]]; } }
function renderGrid() {
bubbleGrid.innerHTML = '';
allBubbles = allBubbles.filter(b=>b);
allBubbles.forEach((bubble,index)=>{
const el = document.createElement('div');
el.className = 'bubble';
el.setAttribute('data-index', index);
el.textContent = bubble.text;
if(bubble.isInterference) el.classList.add('interference');
else if(bubble.chain==='negative') el.classList.add(bubble.type==='belief'?'belief-negative':'emotion-negative');
else el.classList.add(bubble.type==='belief'?'belief-positive':'emotion-positive');
el.addEventListener('click', ()=>onBubbleClick(index,el));
el.addEventListener('touchend', (e)=>{ e.preventDefault(); onBubbleClick(index,el); });
bubbleGrid.appendChild(el);
bubble.htmlEl = el; bubble.gridIndex = index;
});
}
function onBubbleClick(index, el) {
if(!gameStarted || isProcessing) return;
if(el.classList.contains('bursting')||el.classList.contains('collecting')) return;
const bubble = allBubbles[index];
if(!bubble) return;
if(selectedBubble && selectedBubble.id===bubble.id) { deselectBubble(); return; }
if(!selectedBubble) { selectBubble(bubble,el); return; }
const first = selectedBubble, firstEl = first.htmlEl;
const second = bubble, secondEl = el;
// 基础配对条件
let baseValid = !first.isInterference && !second.isInterference &&
first.eventId===second.eventId && first.type!==second.type && first.chain===second.chain;
// 亮色顺序检查:必须先信念后情绪
let orderValid = true;
if(baseValid && first.chain==='positive') {
orderValid = (first.type==='belief' && second.type==='emotion');
}
const isValid = baseValid && orderValid;
if(isValid) {
errorCount = 0;
isProcessing = true;
deselectBubbleSilent();
if(first.chain==='negative') handleNegativePair(first,second,firstEl,secondEl);
else handlePositivePair(first,second,firstEl,secondEl);
} else {
errorCount++;
firstEl.classList.add('shaking'); secondEl.classList.add('shaking');
deselectBubbleSilent();
setTimeout(()=>{ firstEl.classList.remove('shaking'); secondEl.classList.remove('shaking'); },400);
timeLeft = Math.max(0, timeLeft-10);
updateTimerDisplay();
if(timeLeft<=0) { clearInterval(timerInterval); handleTimeUp(); return; }
showFloatingTip('⏱️ -10秒');
if(errorCount>=2 && !isProcessing) { errorCount=0; autoShowHint(); }
}
}
function selectBubble(bubble,el) { deselectBubbleSilent(); selectedBubble=bubble; el.classList.add('selected'); }
function deselectBubble() { if(selectedBubble?.htmlEl) selectedBubble.htmlEl.classList.remove('selected'); selectedBubble=null; }
function deselectBubbleSilent() { if(selectedBubble?.htmlEl) selectedBubble.htmlEl.classList.remove('selected'); selectedBubble=null; }
function handleNegativePair(b1,b2,el1,el2) {
el1.classList.add('bursting'); el2.classList.add('bursting');
score+=5; updateUI();
showFloatingTip('💡 识别了不合理信念,接下来转化想法吧!');
setTimeout(()=>{ removeBubbleById(b1.id); removeBubbleById(b2.id); renderGrid(); checkLevelComplete(); isProcessing=false; },500);
}
function handlePositivePair(b1,b2,el1,el2) {
el1.classList.add('collecting'); el2.classList.add('collecting');
score+=10; stars+=1;
const cur = eventsData[currentLevel];
const pair = cur.positivePairs.find(p=>p.belief===b1.text||p.belief===b2.text);
const enc = pair ? pair.encouragement : '想法一转,心情就亮啦✨';
if(!allEncouragements.includes(enc)) allEncouragements.push(enc);
updateUI();
showFloatingTip(enc);
setTimeout(()=>{ removeBubbleById(b1.id); removeBubbleById(b2.id); renderGrid(); checkLevelComplete(); isProcessing=false; },550);
}
function removeBubbleById(id) { const idx = allBubbles.findIndex(b=>b&&b.id===id); if(idx>=0) allBubbles.splice(idx,1); }
function showFloatingTip(text) {
// 固定居中偏上位置
const tip = document.createElement('div');
tip.className = 'floating-tip';
tip.textContent = text;
document.body.appendChild(tip);
setTimeout(()=>{ if(tip.parentNode) tip.remove(); }, 4100);
}
function checkLevelComplete() {
const correctLeft = allBubbles.filter(b=>!b.isInterference).length;
if(correctLeft===0) {
allBubbles = []; renderGrid(); clearInterval(timerInterval);
if(levelStartTime) totalElapsedSeconds += Math.min(90, Math.round((Date.now()-levelStartTime)/1000));
if(currentLevel<4) { setTimeout(()=>{ currentLevel++; startLevel(currentLevel); },700); }
else { setTimeout(()=>showFinalModal(),600); }
} else if(allBubbles.filter(b=>b.chain==='negative'&&!b.isInterference).length===0 &&
allBubbles.filter(b=>b.chain==='positive'&&!b.isInterference).length>0) {
guideText.innerHTML = '✨ 暗色已清空!现在按顺序配对亮色泡泡(先信念后情绪)';
}
}
function startTimer() {
clearInterval(timerInterval); timeLeft=90; updateTimerDisplay();
levelStartTime = Date.now();
timerInterval = setInterval(()=>{ timeLeft--; updateTimerDisplay(); if(timeLeft<=0){ clearInterval(timerInterval); handleTimeUp(); } },1000);
}
function updateTimerDisplay() { timerDisplay.textContent = timeLeft; timerDisplay.classList.toggle('timer-warning', timeLeft<=15); }
function handleTimeUp() {
isProcessing=true; clearInterval(timerInterval);
showFloatingTip('⏰ 时间到!重新挑战本关吧~');
setTimeout(()=>{ isProcessing=false; startLevel(currentLevel); },1500);
}
function startLevel(level) {
currentLevel=level; clearInterval(timerInterval); isProcessing=false;
selectedBubble=null; hintUsed=false; errorCount=0;
btnHint.disabled=false; btnHint.textContent='💡 提示(1次)';
const ev = eventsData[level];
eventText.textContent = ev.eventA;
guideText.innerHTML = '👆 先点击暗色配对,再按顺序匹配亮色泡泡(先信念后情绪)';
levelDisplay.textContent = (level+1)+'/5';
updateUI();
allBubbles = buildBubblePool(level);
renderGrid();
timerDisplay.classList.remove('timer-warning');
updateTimerDisplay();
startTimer();
}
function updateUI() { scoreDisplay.textContent=score; starDisplay.textContent=stars; }
btnHint.addEventListener('click', ()=>{
if(!gameStarted || hintUsed||isProcessing) return;
hintUsed=true; btnHint.disabled=true; btnHint.textContent='💡 已使用';
applyHintGlow();
});
function autoShowHint() { if(!gameStarted || isProcessing) return; applyHintGlow(); showFloatingTip('🔍 亮色配对需先信念后情绪,短句要对应哦!'); }
function applyHintGlow() {
const gb = allBubbles.find(b=>!b.isInterference && b.chain==='positive' && b.type==='belief');
const ge = allBubbles.find(b=>!b.isInterference && b.chain==='positive' && b.type==='emotion' && b.pairId===gb?.pairId);
if(gb?.htmlEl) gb.htmlEl.classList.add('hint-glow');
if(ge?.htmlEl) ge.htmlEl.classList.add('hint-glow');
setTimeout(()=>{ if(gb?.htmlEl) gb.htmlEl.classList.remove('hint-glow'); if(ge?.htmlEl) ge.htmlEl.classList.remove('hint-glow'); },3000);
}
btnReset.addEventListener('click', ()=>{ if(!gameStarted || isProcessing) return; startLevel(currentLevel); });
function showFinalModal() {
clearInterval(timerInterval); isProcessing=true; gameStarted=false;
let badgeClass, titleName;
if(score>=80) { badgeClass='badge-diamond'; titleName='💎 钻石心灵大师'; }
else if(score>=50) { badgeClass='badge-gold'; titleName='🥇 黄金炼心师'; }
else { badgeClass='badge-bronze'; titleName='🥉 青铜净化师'; }
const totalTimeStr = (()=>{ const m=Math.floor(totalElapsedSeconds/60); const s=totalElapsedSeconds%60; return m+'分'+s+'秒'; })();
const quotes = [...new Set([...allEncouragements,...globalQuotes])];
modalContent.innerHTML = `
<h2>🎉 通关成功!</h2>
<div class="title-badge ${badgeClass}">${titleName}</div>
<div class="score-display">${score}</div>
<div>总分</div>
<div class="stars-display">${'⭐'.repeat(Math.min(stars,20))}</div>
<div>共获得 ${stars} 颗星星</div>
<div style="color:#d4843a;font-size:1.1rem;font-weight:700;margin:8px 0;">⏱️ 总耗时:${totalTimeStr}</div>
<div class="quotes-list"><strong>📝 心灵金句合集:</strong>${quotes.map(q=>`<p>${q}</p>`).join('')}</div>
<p style="font-size:0.8rem;">记住:<strong>事件A只是间接原因,信念B才是情绪C的直接原因</strong>。<br>做情绪的主人,从调整想法开始!🌈</p>
<button class="btn-close" id="btnCloseModal">🔄 重新挑战</button>
`;
modalOverlay.style.display='flex';
document.getElementById('btnCloseModal').addEventListener('click', ()=>{ modalOverlay.style.display='none'; resetGame(); });
}
function resetGame() {
currentLevel=0; score=0; stars=0; allEncouragements=[]; totalElapsedSeconds=0;
isProcessing=false; selectedBubble=null; hintUsed=false; errorCount=0;
btnHint.disabled=false; btnHint.textContent='💡 提示(1次)';
clearInterval(timerInterval); updateUI();
gameStarted = false;
ruleModal.style.display = 'flex';
startLevel(0);
modalOverlay.style.display='none';
}
modalOverlay.addEventListener('click', (e)=>{ if(e.target===modalOverlay) resetGame(); });
btnStartGame.addEventListener('click', ()=>{ ruleModal.style.display='none'; gameStarted=true; startLevel(0); });
function initGame() {
ruleModal.style.display='flex'; gameStarted=false;
currentLevel=0; score=0; stars=0; allEncouragements=[]; totalElapsedSeconds=0;
isProcessing=false; selectedBubble=null; hintUsed=false; errorCount=0;
btnHint.disabled=false; btnHint.textContent='💡 提示(1次)';
updateUI();
allBubbles = buildBubblePool(0);
eventText.textContent = eventsData[0].eventA;
guideText.innerHTML = '👆 先点击暗色配对,再按顺序匹配亮色泡泡(先信念后情绪)';
levelDisplay.textContent='1/5'; timerDisplay.textContent='90';
timerDisplay.classList.remove('timer-warning');
renderGrid();
clearInterval(timerInterval);
}
initGame();
})();
</script>
</body>
</html>Game Source: 情绪泡泡龙——ABC消消乐大作战(顺序优化版)
Creator: LaserPirate42
Libraries: none
Complexity: complex (525 lines, 32.9 KB)
The full source code is displayed above on this page.
Remix Instructions
To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: abc-laserpirate42-mpcw9hzw" to link back to the original. Then publish at arcadelab.ai/publish.