微件:GGLScratchGame:修订间差异

来自Limbo Wiki Mirror
Gaoice留言 | 贡献
无编辑摘要
标签(旧)WikiEditor
Gaoice留言 | 贡献
无编辑摘要
标签(旧)WikiEditor
第1行: 第1行:
<noinclude>
<noinclude>
<!-- Widget文档区 -->
== 使用文档 ==
这个Widget用于生成剧情向伪刮刮乐游戏。
这个Widget用于生成剧情向伪刮刮乐游戏。
调用方法: {{#widget:GGLScratchGame}}
 
=== 调用方式 ===
复制以下代码到你的条目或沙盒页面:
<pre>
{{#widget:GGLScratchGame
|bg=图片1.png          <!-- 彩票整体大底图 -->
|cover=覆盖层.png      <!-- 刮之前的涂层图片 -->
|revealed=刮开后.png  <!-- 刮开后的格子底图 -->
}}
</pre>
 
*如果没有上传对应的图片,请删除对应的行,系统会使用默认颜色。*
</noinclude>
</noinclude>


<includeonly>
<includeonly>
<!-- 1. CSS 样式部分 -->
<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}-->
      
      
    /* 使用 {{filepath:图片1.png}} 自动获取路径 */
    background-image: url('{{filepath:图片1.png}}');
   
    /* 确保图片铺满 */
     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: #fdd835;  
     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; /* 默认黑色涂层 */
    background: #222;  
    /* background-image: url('你的覆盖层URL'); background-size: cover; */
      
      
     color: #222; /* 隐藏文字 */
    <!--{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; /* 默认灰色底 */
     background: #eee;
   
    /* background-image: url('你的刮开后底图URL'); background-size: cover; */
    <!--{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>


<!-- 2. HTML 结构部分 -->
<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">
            <!-- JS生成 -->
        </div>


        <!-- 底部控制区:左吐槽,右按钮 -->
         <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>


<!-- 3. JavaScript 逻辑部分 -->
<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: '结果:谢谢惠顾。' }, // 1. 无
         { type: 'normal', mascot: '', broadcast: '结果:谢谢惠顾。' },
         { type: 'normal', mascot: '(・ω・)', broadcast: '检测到异常字符。' }, // 2. 颜文字出场
         { type: 'normal', mascot: '(・ω・)', broadcast: '检测到异常字符。' },
         { type: 'bonus', mascot: '(^▽^)', broadcast: '恭喜!触发连击,奖励+2张!' }, // 3. 欢呼+加票
         { type: 'bonus', mascot: '(^▽^)', broadcast: '恭喜!触发连击,奖励+2张!' },
         { type: 'normal', mascot: 'o(*≧▽≦)ツ', broadcast: '结果:1 Data 2。好耶!' }, // 4. 思考
         { type: 'normal', mascot: 'o(*≧▽≦)ツ', broadcast: '结果:1 Data 2。好耶!' },
         { type: 'cheat', mascot: '( ・_・)', broadcast: '结果:中奖...?数据好像变了。' }, // 5. 意识到不对
         { type: 'cheat', mascot: '( ・_・)', broadcast: '结果:中奖...?数据好像变了。' },
         { type: 'narrative_bubble', mascot: '', broadcast: '对象已消失。', override: 'Data' }, // 6. 消失
         { type: 'narrative_bubble', mascot: '', broadcast: '对象已消失。', override: 'Data' },
         { type: 'glitch', mascot: '...', broadcast: 'ERR_#0x00 数据损坏', override: '???' }, // 7. 乱码
         { type: 'glitch', mascot: '...', broadcast: 'ERR_#0x00 数据损坏', override: '???' },
         { type: 'pain', mascot: '', broadcast: '声音检测:"好痛!"', override: 'Pain' }, // 8. 受击
         { type: 'pain', mascot: '', broadcast: '声音检测:"好痛!"', override: 'Pain' },
         { type: 'talk', mascot: '', broadcast: '收到文本:"你是谁?"', override: 'Info' }, // 9. 交流
         { type: 'talk', mascot: '', broadcast: '收到文本:"你是谁?"', override: 'Info' },
         { type: 'stop', mascot: '', broadcast: '警告:立即停止操作。', override: '停下' }, // 10. 停下
         { type: 'stop', mascot: '', broadcast: '警告:立即停止操作。', override: '停下' },
         { type: 'final', mascot: 'ERROR', broadcast: '你知道的太多了。', override: '平安喜乐' } // 11. 结局
         { 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);
          
          
        // 卡片10: 红色警告
         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   <!-- 刮开后的格子底图 -->
}}
  • 如果没有上传对应的图片,请删除对应的行,系统会使用默认颜色。*