微件:GGLScratchGame:修订间差异
来自Limbo Wiki Mirror
无编辑摘要 标签:(旧)WikiEditor |
无编辑摘要 标签:(旧)WikiEditor |
||
| 第1行: | 第1行: | ||
<noinclude> | <noinclude> | ||
== 使用文档 == | |||
这个Widget用于生成剧情向伪刮刮乐游戏。 | 这个Widget用于生成剧情向伪刮刮乐游戏。 | ||
=== 调用方式 === | |||
复制以下代码到你的条目或沙盒页面: | |||
<pre> | |||
{{#widget:GGLScratchGame | |||
|bg=图片1.png <!-- 彩票整体大底图 --> | |||
|cover=覆盖层.png <!-- 刮之前的涂层图片 --> | |||
|revealed=刮开后.png <!-- 刮开后的格子底图 --> | |||
}} | |||
</pre> | |||
*如果没有上传对应的图片,请删除对应的行,系统会使用默认颜色。* | |||
</noinclude> | </noinclude> | ||
<includeonly> | <includeonly> | ||
<style> | <style> | ||
/* 游戏容器 */ | /* 游戏容器 */ | ||
| 第21行: | 第31行: | ||
} | } | ||
.game-header { | .game-header { | ||
margin-bottom: 10px; | margin-bottom: 10px; | ||
| 第32行: | 第41行: | ||
} | } | ||
/* | /* --- 彩票主体 (接受 bg 参数) --- */ | ||
.ticket-container { | .ticket-container { | ||
width: 100%; | width: 100%; | ||
max-width: 350px; | max-width: 350px; | ||
margin: 0 auto; | margin: 0 auto; | ||
background-color: #fff; /* 默认白色背景 */ | |||
/* | /* 这里使用了 Smarty 语法来判断是否传入了 bg 参数 */ | ||
<!--{if $bg}--> | |||
background-image: url('{{filepath:<!--{$bg}-->}}'); | |||
<!--{/if}--> | |||
background-size: 100% 100%; | background-size: 100% 100%; | ||
background-repeat: no-repeat; | background-repeat: no-repeat; | ||
border: 2px dashed #999; | |||
border: 2px dashed #999; | |||
padding: 15px; | padding: 15px; | ||
box-shadow: 0 5px 15px rgba(0,0,0,0.2); | box-shadow: 0 5px 15px rgba(0,0,0,0.2); | ||
| 第59行: | 第65行: | ||
.ticket-header { | .ticket-header { | ||
background: #d32f2f; | background: #d32f2f; | ||
color: white; | color: white; | ||
padding: 8px 10px; | padding: 8px 10px; | ||
| 第69行: | 第75行: | ||
} | } | ||
.scratch-grid-area { | .scratch-grid-area { | ||
/* | /* 设为透明,以便显示大底图 */ | ||
background: | background: transparent; | ||
padding: 8px; | padding: 8px; | ||
display: grid; | display: grid; | ||
| 第78行: | 第83行: | ||
grid-template-rows: repeat(6, 1fr); | grid-template-rows: repeat(6, 1fr); | ||
gap: 4px; | gap: 4px; | ||
border: 2px solid #f9a825; | /* border: 2px solid #f9a825; */ /* 如果底图自带边框,可以注释掉这行 */ | ||
margin-bottom: 15px; | margin-bottom: 15px; | ||
} | } | ||
/* | /* --- 格子 (接受 cover 参数) --- */ | ||
.grid-cell { | .grid-cell { | ||
width: 100%; | width: 100%; | ||
aspect-ratio: 1; | aspect-ratio: 1; | ||
background-color: #222; /* 默认黑色涂层 */ | |||
color: | <!--{if $cover}--> | ||
background-image: url('{{filepath:<!--{$cover}-->}}'); | |||
<!--{/if}--> | |||
background-size: cover; | |||
background-position: center; | |||
color: transparent; | |||
display: flex; | display: flex; | ||
align-items: center; | align-items: center; | ||
| 第104行: | 第114行: | ||
} | } | ||
/* | /* --- 刮开后 (接受 revealed 参数) --- */ | ||
.grid-cell.revealed { | .grid-cell.revealed { | ||
/* -- | background-color: #eee; /* 默认灰色底 */ | ||
<!--{if $revealed}--> | |||
background-image: url('{{filepath:<!--{$revealed}-->}}'); | |||
<!--{/if}--> | |||
background-size: cover; | |||
color: #000; | color: #000; | ||
| 第115行: | 第129行: | ||
} | } | ||
/* | /* 底部控制区 */ | ||
.ticket-controls-area { | .ticket-controls-area { | ||
display: flex; | display: flex; | ||
justify-content: space-between; | justify-content: space-between; | ||
align-items: flex-end; | align-items: flex-end; | ||
margin-top: 10px; | margin-top: 10px; | ||
min-height: 60px; | min-height: 60px; | ||
} | } | ||
.mascot-section { | .mascot-section { | ||
display: flex; | display: flex; | ||
| 第137行: | 第150行: | ||
background: #fff; | background: #fff; | ||
border: 1px solid #333; | border: 1px solid #333; | ||
border-radius: 8px 8px 8px 0; | border-radius: 8px 8px 8px 0; | ||
padding: 8px; | padding: 8px; | ||
font-size: 12px; | font-size: 12px; | ||
| 第147行: | 第160行: | ||
width: 100%; | width: 100%; | ||
} | } | ||
.mascot-face { | .mascot-face { | ||
font-size: 18px; | font-size: 18px; | ||
| 第155行: | 第167行: | ||
} | } | ||
.main-btn { | .main-btn { | ||
padding: 8px 15px; | padding: 8px 15px; | ||
| 第179行: | 第190行: | ||
} | } | ||
.main-btn.next-mode { | .main-btn.next-mode { | ||
background: #4CAF50; | background: #4CAF50; | ||
} | } | ||
.main-btn.danger-mode { | .main-btn.danger-mode { | ||
| 第187行: | 第198行: | ||
} | } | ||
/* | /* 特效 */ | ||
.invert-filter { | .invert-filter { | ||
filter: invert(100%); | filter: invert(100%); | ||
| 第208行: | 第219行: | ||
</style> | </style> | ||
<div class="ggl-scratch-game-wrapper" id="ggl-game-root"> | <div class="ggl-scratch-game-wrapper" id="ggl-game-root"> | ||
<div class="game-header"> | <div class="game-header"> | ||
| 第215行: | 第225行: | ||
</div> | </div> | ||
<div class="ticket-container" id="ticket-container"> | <div class="ticket-container" id="ticket-container"> | ||
<div class="ticket-header"> | <div class="ticket-header"> | ||
| 第222行: | 第231行: | ||
</div> | </div> | ||
<div class="scratch-grid-area" id="scratch-grid"></div> | |||
<div class="scratch-grid-area" id="scratch-grid"> | |||
<div class="ticket-controls-area"> | <div class="ticket-controls-area"> | ||
<div class="mascot-section"> | <div class="mascot-section"> | ||
<div class="speech-bubble" id="mascot-text">请刮开覆盖层...</div> | <div class="speech-bubble" id="mascot-text">请刮开覆盖层...</div> | ||
<div class="mascot-face" id="mascot-face">(・ω・)</div> | <div class="mascot-face" id="mascot-face">(・ω・)</div> | ||
</div> | </div> | ||
<button id="action-btn" class="main-btn">扫描结果</button> | <button id="action-btn" class="main-btn">扫描结果</button> | ||
</div> | </div> | ||
| 第240行: | 第243行: | ||
</div> | </div> | ||
<div id="fake-wiki-entry" style="display:none; padding:20px; background:#fff; border:1px solid #ccc; max-width:800px; margin:0 auto;"> | <div id="fake-wiki-entry" style="display:none; padding:20px; background:#fff; border:1px solid #ccc; max-width:800px; margin:0 auto;"> | ||
<h1 style="border-bottom: 1px solid #aaa;">六世恶言</h1> | <h1 style="border-bottom: 1px solid #aaa;">六世恶言</h1> | ||
| 第258行: | 第260行: | ||
</div> | </div> | ||
<script> | <script> | ||
(function() { | (function() { | ||
| 第278行: | 第279行: | ||
var elFakeEntry = document.getElementById('fake-wiki-entry'); | var elFakeEntry = document.getElementById('fake-wiki-entry'); | ||
var cardsData = [ | var cardsData = [ | ||
{ type: 'normal', mascot: '', broadcast: '结果:谢谢惠顾。' }, | { type: 'normal', mascot: '', broadcast: '结果:谢谢惠顾。' }, | ||
{ type: 'normal', mascot: '(・ω・)', broadcast: '检测到异常字符。' }, | { type: 'normal', mascot: '(・ω・)', broadcast: '检测到异常字符。' }, | ||
{ type: 'bonus', mascot: '(^▽^)', broadcast: '恭喜!触发连击,奖励+2张!' }, | { type: 'bonus', mascot: '(^▽^)', broadcast: '恭喜!触发连击,奖励+2张!' }, | ||
{ type: 'normal', mascot: 'o(*≧▽≦)ツ', broadcast: '结果:1 Data 2。好耶!' }, | { type: 'normal', mascot: 'o(*≧▽≦)ツ', broadcast: '结果:1 Data 2。好耶!' }, | ||
{ type: 'cheat', mascot: '( ・_・)', broadcast: '结果:中奖...?数据好像变了。' }, | { type: 'cheat', mascot: '( ・_・)', broadcast: '结果:中奖...?数据好像变了。' }, | ||
{ type: 'narrative_bubble', mascot: '', broadcast: '对象已消失。', override: 'Data' }, | { type: 'narrative_bubble', mascot: '', broadcast: '对象已消失。', override: 'Data' }, | ||
{ type: 'glitch', mascot: '...', broadcast: 'ERR_#0x00 数据损坏', override: '???' }, | { type: 'glitch', mascot: '...', broadcast: 'ERR_#0x00 数据损坏', override: '???' }, | ||
{ type: 'pain', mascot: '', broadcast: '声音检测:"好痛!"', override: 'Pain' }, | { type: 'pain', mascot: '', broadcast: '声音检测:"好痛!"', override: 'Pain' }, | ||
{ type: 'talk', mascot: '', broadcast: '收到文本:"你是谁?"', override: 'Info' }, | { type: 'talk', mascot: '', broadcast: '收到文本:"你是谁?"', override: 'Info' }, | ||
{ type: 'stop', mascot: '', broadcast: '警告:立即停止操作。', override: '停下' }, | { type: 'stop', mascot: '', broadcast: '警告:立即停止操作。', override: '停下' }, | ||
{ type: 'final', mascot: 'ERROR', broadcast: '你知道的太多了。', override: '平安喜乐' } | { type: 'final', mascot: 'ERROR', broadcast: '你知道的太多了。', override: '平安喜乐' } | ||
]; | ]; | ||
| 第307行: | 第307行: | ||
revealedCount = 0; | revealedCount = 0; | ||
elBtn.innerText = "扫描结果"; | elBtn.innerText = "扫描结果"; | ||
elBtn.className = "main-btn"; | elBtn.className = "main-btn"; | ||
elBtn.disabled = false; | elBtn.disabled = false; | ||
elBtn.style = ""; | elBtn.style = ""; | ||
elTicketId.innerText = (index + 1).toString().padStart(3, '0'); | elTicketId.innerText = (index + 1).toString().padStart(3, '0'); | ||
| 第318行: | 第317行: | ||
var data = cardsData[index]; | var data = cardsData[index]; | ||
elGrid.innerHTML = ''; | elGrid.innerHTML = ''; | ||
updateMascot("请刮开覆盖层...", data.mascot); | updateMascot("请刮开覆盖层...", data.mascot); | ||
if (data.type === 'stop') { | if (data.type === 'stop') { | ||
elBtn.style.border = "2px solid red"; | elBtn.style.border = "2px solid red"; | ||
| 第334行: | 第330行: | ||
var content = data.override ? data.override : generateRandomContent(); | var content = data.override ? data.override : generateRandomContent(); | ||
if(index === 2 && (i === 10 || i === 11)) content = "大奖"; | if(index === 2 && (i === 10 || i === 11)) content = "大奖"; | ||
if(index === 8) content = "你是谁"; | if(index === 8) content = "你是谁"; | ||
| 第341行: | 第336行: | ||
cell.dataset.idx = i; | cell.dataset.idx = i; | ||
(function(c, cIdx, d){ | (function(c, cIdx, d){ | ||
c.addEventListener('click', function() { | c.addEventListener('click', function() { | ||
| 第350行: | 第344行: | ||
c.innerText = c.dataset.content; | c.innerText = c.dataset.content; | ||
if(cIdx === 5) { | |||
if(cIdx === 5) { | |||
var msg = ["别点了", "我在看你", "停下"][Math.floor(Math.random()*3)]; | var msg = ["别点了", "我在看你", "停下"][Math.floor(Math.random()*3)]; | ||
updateMascot(msg, ""); | updateMascot(msg, ""); | ||
c.innerText = ""; | c.innerText = ""; | ||
} | } | ||
if(cIdx === 7) { | if(cIdx === 7) { | ||
c.innerText = ["痛!", "别!", "啊!"][Math.floor(Math.random()*3)]; | c.innerText = ["痛!", "别!", "啊!"][Math.floor(Math.random()*3)]; | ||
c.style.color = "red"; | c.style.color = "red"; | ||
updateMascot("别挠我!", ">_<"); | updateMascot("别挠我!", ">_<"); | ||
} | } | ||
if(cIdx === 4 && revealedCount === 15) { | if(cIdx === 4 && revealedCount === 15) { | ||
updateMascot("诶...?", "(;゚д゚)"); | updateMascot("诶...?", "(;゚д゚)"); | ||
var cells = elGrid.querySelectorAll('.grid-cell'); | var cells = elGrid.querySelectorAll('.grid-cell'); | ||
| 第375行: | 第368行: | ||
elBtn.addEventListener('click', function() { | elBtn.addEventListener('click', function() { | ||
if (isScanned) { | if (isScanned) { | ||
currentCardIndex++; | currentCardIndex++; | ||
if (currentCardIndex < TOTAL_CARDS) { | if (currentCardIndex < TOTAL_CARDS) { | ||
| 第381行: | 第373行: | ||
} | } | ||
} else { | } else { | ||
if (revealedCount < 30 && currentCardIndex < 9) { | if (revealedCount < 30 && currentCardIndex < 9) { | ||
if(!confirm("还没刮完,确定扫描吗?")) return; | if(!confirm("还没刮完,确定扫描吗?")) return; | ||
| 第391行: | 第382行: | ||
setTimeout(function(){ | setTimeout(function(){ | ||
updateMascot(data.broadcast); | updateMascot(data.broadcast); | ||
if (data.type === 'bonus') { | if (data.type === 'bonus') { | ||
remainingTickets += 2; | remainingTickets += 2; | ||
elCount.innerText = remainingTickets; | elCount.innerText = remainingTickets; | ||
} | } | ||
if (data.type === 'stop') { | if (data.type === 'stop') { | ||
setTimeout(function(){ | setTimeout(function(){ | ||
| 第408行: | 第395行: | ||
return; | return; | ||
} | } | ||
if (data.type === 'final') { | if (data.type === 'final') { | ||
triggerEnding(); | triggerEnding(); | ||
return; | return; | ||
} | } | ||
remainingTickets--; | remainingTickets--; | ||
elCount.innerText = remainingTickets; | elCount.innerText = remainingTickets; | ||
if (remainingTickets < 0) { | if (remainingTickets < 0) { | ||
updateMascot("票据耗尽。"); | updateMascot("票据耗尽。"); | ||
| 第422行: | 第406行: | ||
return; | return; | ||
} | } | ||
elBtn.innerText = "再来一张"; | elBtn.innerText = "再来一张"; | ||
elBtn.classList.add('next-mode'); | elBtn.classList.add('next-mode'); | ||
}, 400); | }, 400); | ||
} | } | ||
| 第441行: | 第423行: | ||
crash.remove(); | crash.remove(); | ||
document.body.classList.remove('invert-filter'); | document.body.classList.remove('invert-filter'); | ||
root.style.display = 'none'; | root.style.display = 'none'; | ||
if(elFakeEntry) elFakeEntry.style.display = 'block'; | if(elFakeEntry) elFakeEntry.style.display = 'block'; | ||
window.scrollTo(0,0); | window.scrollTo(0,0); | ||
alert("【系统提示】您收到了一条新短信。"); | alert("【系统提示】您收到了一条新短信。"); | ||
| 第448行: | 第430行: | ||
}, 1500); | }, 1500); | ||
} | } | ||
loadCard(0); | loadCard(0); | ||
})(); | })(); | ||
</script> | </script> | ||
</includeonly> | </includeonly> | ||
2026年2月1日 (日) 12:45的版本
使用文档
这个Widget用于生成剧情向伪刮刮乐游戏。
调用方式
复制以下代码到你的条目或沙盒页面:
{{#widget:GGLScratchGame
|bg=图片1.png <!-- 彩票整体大底图 -->
|cover=覆盖层.png <!-- 刮之前的涂层图片 -->
|revealed=刮开后.png <!-- 刮开后的格子底图 -->
}}
- 如果没有上传对应的图片,请删除对应的行,系统会使用默认颜色。*
