好友
阅读权限25
听众
最后登录1970-1-1
|
寂寞知己
发表于 2026-1-14 13:59
本帖最后由 寂寞知己 于 2026-1-15 09:29 编辑
相信经常逛吾爱破解的朋友对论坛那个 404 页面的“围住小猫”游戏都不陌生。本来只是个打发时间的小游戏,但我总觉得玩法单一了点。于是利用一下时间,撸了一个“定制助手”脚本。不仅能改游戏规则(多步连走),还能拉上好基友开启本地双人甚至四人乱斗模式!目前已经是某音直播娱乐必备的非常有节目效果的多人小游戏!!!
还有贪吃蛇版在下面!!!
一、 脚本亮点
- 界面美化:将404改成了帅哥标题和头像。
- 单人定制:支持设置“玩家连续放墙次数”(1次、2次、3次甚至无限),还独家新增了“1-2-1-2 循环步数”玩法。
- 双人模式:伙伴不再是观众!你可以放墙,伙伴可以手动控猫逃跑,开启真正的博弈。
- 四人模式(双猫乱斗):屏幕左侧会空降第二只紫猫。支持 2 名玩家 + 2 只猫交替行动,场面一度非常混乱又充满趣味!
- 智能逻辑:四人模式下,如果其中一只猫被围死,脚本会自动跳过它的回合,直到所有猫都被围住才判定胜利。
- 极简 UI:右上角悬浮窗,支持一键收起/展开,收起后就是一个精致的小头像,完全不遮挡视线。
- 按需开启:脚本非常聪明,只有在检测到是论坛 404 页面时才会加载,不占用其他页面的内存。
二、 玩法说明
- 基础玩法: 安装脚本后,进入 404 页面,点击右上角“猫猫助手”的“应用修改并重置”即可生效。
- 四人模式: 流程为:玩家 1 放墙 -\> 猫 1(中间)行动 -\> 玩家 2 放墙 -\> 猫 2(左侧,紧邻中间猫)行动。
- 1-2-1-2 序列: 这是单人模式下的进阶玩法。第一回合你只能放 1 堵墙,第二回合可以放 2 堵,第三回合又变回 1 堵,以此循环。这非常考验你的长远布局能力!
(贪吃蛇版)鼠标在贪吃蛇前面悬浮移动则贪吃蛇跟着你走,先吃掉所有黑点,最后吃猫,成功后进入下一关
三、 游戏链接
https://www.52pojie.cn/thread-2086417-1-1.html 游戏介绍
https://www.52pojie.cn/404.html 游戏界面
或者 随便不存在的帖子比如:https://www.52pojie.cn/thread-1314521.html
// ==UserScript==
// @name 猫猫定制助手
// @namespace http://tampermonkey.net/
// @version 2.1
// @description 自定义吾爱破解404猫猫游戏规则:优化最小化样式、修改页面标题与祝福语、支持四人模式及循环步数。
// @AuThor 52pojie
// @match https://www.52pojie.cn/*
// @Icon https://avatar.52pojie.cn/data/avatar/000/00/00/01_avatar_middle.jpg
// @grant GM_addStyle
// @run-at document-end
// ==/UserScript==
(function() {
'use strict';
const win = (typeof unsafeWindow !== 'undefined') ? unsafeWindow : window;
// --- 0. 页面判定与内容修改 ---
const is404Page = () => {
const h1 = document.querySelector('.container h1');
const h2 = document.querySelector('.container h2');
const gameContainer = document.getElementById('catch-the-cat');
if (h1 && h1.innerText.includes('404') && gameContainer) {
// 修改标题为 Hmily的猫猫
h1.innerText = 'Hmily的猫猫';
// 修改副标题为祝福语
if (h2) {
h2.innerText = '吾爱破解祝你:喵运当头,锦鲤附体!🐾';
}
return true;
}
return false;
};
if (!is404Page()) return;
// --- 1. 样式定义 ---
GM_addStyle(`
#cat-mod-panel {
position: fixed;
top: 20px;
right: 20px;
width: 260px;
background: #fff;
border-radius: 12px;
box-shadow: 0 10px 25px rgba(0,0,0,0.3);
z-index: 10000;
padding: 15px;
font-family: "Segoe UI", Roboto, sans-serif;
font-size: 14px;
border: 2px solid #007bff;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
overflow: hidden;
display: flex;
flex-direction: column;
}
/* 最小化状态:彻底圆化,移除外层边框影响 */
#cat-mod-panel.minimized {
width: 44px;
height: 44px;
padding: 0;
cursor: pointer;
border-radius: 50%;
justify-content: center;
align-items: center;
border: none; /* 移除收起时的外边框 */
box-shadow: 0 4px 12px rgba(0,123,255,0.4); /* 增加一个柔和的呼吸阴影 */
}
#cat-mod-panel .panel-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 12px;
border-bottom: 1px solid #eee;
padding-bottom: 8px;
}
#cat-mod-panel.minimized .panel-header {
border: none;
margin: 0;
padding: 0;
width: 100%;
height: 100%;
justify-content: center;
}
.header-left { display: flex; align-items: center; }
#cat-mod-panel .panel-icon {
width: 28px;
height: 28px;
border-radius: 50%;
border: 1px solid #007bff;
transition: all 0.3s ease;
object-fit: cover;
}
/* 最小化时图标填满整个圆形容器 */
#cat-mod-panel.minimized .panel-icon {
width: 44px;
height: 44px;
margin: 0;
border: none;
}
#cat-mod-panel h3 { margin: 0 0 0 10px; font-size: 16px; color: #007bff; white-space: nowrap; }
/* 隐藏内容逻辑 */
#cat-mod-panel.minimized h3,
#cat-mod-panel.minimized .mod-item,
#cat-mod-panel.minimized .turn-indicator,
#cat-mod-panel.minimized .restart-btn,
#cat-mod-panel.minimized .status-info,
#cat-mod-panel.minimized .minimize-btn-text,
#cat-mod-panel.minimized #btn-minimize {
display: none;
}
.toggle-btn {
background: none;
border: none;
color: #007bff;
cursor: pointer;
font-size: 12px;
padding: 2px 5px;
border-radius: 4px;
}
.toggle-btn:hover { background: #f0f7ff; }
.mod-item { margin-bottom: 12px; }
.mod-item label { display: block; margin-bottom: 5px; font-weight: bold; color: #333; }
.mod-item select { width: 100%; padding: 6px; border-radius: 4px; border: 1px solid #ccc; background: #f9f9f9; }
.turn-indicator {
padding: 8px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;
transition: all 0.3s; border: 1px solid #eee; font-size: 13px;
}
.turn-p1 { background: #e7f3ff; color: #007bff; border-color: #007bff; }
.turn-c1 { background: #fff4e5; color: #ff9800; border-color: #ff9800; }
.turn-p2 { background: #e7ffe7; color: #28a745; border-color: #28a745; }
.turn-c2 { background: #f3e5f5; color: #9c27b0; border-color: #9c27b0; }
.status-info {
font-size: 11px; color: #fff; margin-top: 10px;
background: #333; padding: 6px; border-radius: 4px;
max-height: 80px; overflow-y: auto; font-family: monospace;
}
.restart-btn {
background: #28a745; color: #fff; border: none; padding: 10px; width: 100%;
border-radius: 5px; cursor: pointer; margin-top: 10px; font-weight: bold;
}
`);
// --- 2. 状态变量 ---
let config = {
mode: 'solo',
stepsPerTurn: '1',
currentTurn: 'p1',
turnIndex: 0
};
let currentPlayerSteps = 0;
let isGameHooked = false;
let secondCat = null;
// --- 3. UI 构建 ---
function createUI() {
const panel = document.createElement('div');
panel.id = 'cat-mod-panel';
panel.innerHTML = `
<div class="panel-header" id="panel-header">
<div class="header-left">
<img src="https://avatar.52pojie.cn/data/avatar/000/00/00/01_avatar_middle.jpg" class="panel-icon" id="panel-logo" alt="icon">
<h3>猫猫助手 V2.1</h3>
</div>
<button class="toggle-btn" id="btn-minimize"><span class="minimize-btn-text">收起</span></button>
</div>
<div class="mod-item">
<label>游戏模式</label>
<select id="select-mode">
<option value="solo">单人定制 (多步走)</option>
<option value="duo">双人模式 (1玩家+1猫)</option>
<option value="multi">四人模式 (2玩家+2猫)</option>
</select>
</div>
<div class="mod-item">
<label>玩家连续放墙次数</label>
<select id="select-steps">
<option value="1">固定 1 次</option>
<option value="2">固定 2 次</option>
<option value="3">固定 3 次</option>
<option value="seq-1-2">1-2-1-2 循环步数</option>
</select>
</div>
<div id="turn-box" class="turn-indicator turn-p1">等待应用配置...</div>
<button class="restart-btn" id="btn-restart">应用修改并重置</button>
<div class="status-info" id="mod-status">正在连接游戏...</div>
`;
document.body.appendChild(panel);
const toggleBtn = document.getElementById('btn-minimize');
const logo = document.getElementById('panel-logo');
const toggleMinimize = () => {
panel.classList.toggle('minimized');
if (!panel.classList.contains('minimized')) {
toggleBtn.innerHTML = '<span class="minimize-btn-text">收起</span>';
}
};
toggleBtn.onclick = (e) => { e.stopPropagation(); toggleMinimize(); };
panel.onclick = () => { if(panel.classList.contains('minimized')) toggleMinimize(); };
document.getElementById('select-mode').onchange = (e) => { config.mode = e.target.value; resetTurn(); };
document.getElementById('select-steps').onchange = (e) => { config.stepsPerTurn = e.target.value; currentPlayerSteps = 0; updateTurnUI(); };
document.getElementById('btn-restart').onclick = () => {
resetTurn();
injectHook(true);
};
}
function resetTurn() {
config.currentTurn = 'p1';
config.turnIndex = 0;
currentPlayerSteps = 0;
updateTurnUI();
}
function getStepsLimit() {
if (config.stepsPerTurn === 'seq-1-2') {
return (config.turnIndex % 2 === 0) ? 1 : 2;
}
return parseInt(config.stepsPerTurn);
}
function updateTurnUI() {
const box = document.getElementById('turn-box');
if (!box) return;
const limit = getStepsLimit();
const stepInfo = (limit > 1 && config.currentTurn.startsWith('p')) ? ` (${currentPlayerSteps}/${limit})` : "";
const turnMap = {
'p1': { text: 'P1 放墙', class: 'turn-p1' },
'c1': { text: '猫 1 行动', class: 'turn-c1' },
'p2': { text: 'P2 放墙', class: 'turn-p2' },
'c2': { text: '猫 2 行动', class: 'turn-c2' }
};
const current = turnMap[config.currentTurn];
box.innerText = current.text + stepInfo;
box.className = `turn-indicator ${current.class}`;
}
function addLog(msg) {
const el = document.getElementById('mod-status');
if (el) el.innerHTML = `<div>> ${msg}</div>` + el.innerHTML;
}
function getDirection(fromI, fromJ, toI, toJ) {
const neighbors = win.game.mainScene.constructor.getNeighbours(fromI, fromJ);
return neighbors.findIndex(n => n.i === toI && n.j === toJ);
}
// --- 4. 逻辑劫持 ---
function injectHook(forceReset = false) {
const game = win.game;
if (!game || !game.mainScene || !game.mainScene.blocks) return false;
const scene = game.mainScene;
if (forceReset) {
scene.reset();
if (secondCat) { secondCat.destroy(); secondCat = null; }
}
if (config.mode === 'multi' && !secondCat) {
secondCat = new scene.cat.constructor(scene);
scene.add.existing(secondCat);
secondCat.setIJ(4, 5);
secondCat.setTint(0x9c27b0);
addLog("猫猫 2 已就位");
} else if (config.mode !== 'multi' && secondCat) {
secondCat.destroy();
secondCat = null;
}
if (!scene.originalPlayerClick) scene.originalPlayerClick = scene.playerClick;
scene.playerClick = function(t, e) {
const block = this.getBlock(t, e);
if (!block) return false;
const limit = getStepsLimit();
if (config.mode === 'multi') {
if (config.currentTurn === 'p1' || config.currentTurn === 'p2') {
if (block.isWall || (this.cat.i === t && this.cat.j === e) || (secondCat && secondCat.i === t && secondCat.j === e)) return false;
block.isWall = true;
currentPlayerSteps++;
if (this.cat.isCaught() && secondCat && secondCat.isCaught()) {
this.setStatusText("双猫全围!玩家胜!");
this.state = "win";
return true;
}
if (currentPlayerSteps >= limit) {
currentPlayerSteps = 0;
if (config.currentTurn === 'p1') {
config.currentTurn = this.cat.isCaught() ? 'p2' : 'c1';
} else {
config.currentTurn = (secondCat && secondCat.isCaught()) ? 'p1' : 'c2';
if (config.currentTurn === 'p1') config.turnIndex++;
}
}
updateTurnUI();
return true;
} else {
const activeCat = (config.currentTurn === 'c1') ? this.cat : secondCat;
const dir = getDirection(activeCat.i, activeCat.j, t, e);
if (dir === -1 || block.isWall) return false;
activeCat.stepDirection(dir);
if (!activeCat.isEscaped()) {
if (config.currentTurn === 'c1') { config.currentTurn = 'p2'; }
else { config.currentTurn = 'p1'; config.turnIndex++; }
updateTurnUI();
}
return true;
}
}
if (config.mode === 'duo') {
if (config.currentTurn === 'p1') {
if (block.isWall || (this.cat.i === t && this.cat.j === e)) return false;
block.isWall = true;
currentPlayerSteps++;
if (this.cat.isCaught()) { this.state = "win"; return true; }
if (currentPlayerSteps >= limit) { currentPlayerSteps = 0; config.currentTurn = 'c1'; }
updateTurnUI();
return true;
} else {
const dir = getDirection(this.cat.i, this.cat.j, t, e);
if (dir === -1 || block.isWall) return false;
this.cat.stepDirection(dir);
if (!this.cat.isEscaped()) { config.currentTurn = 'p1'; config.turnIndex++; updateTurnUI(); }
return true;
}
}
if (config.mode === 'solo') {
if (block.isWall || (this.cat.i === t && this.cat.j === e)) return false;
currentPlayerSteps++;
if (currentPlayerSteps < limit) {
block.isWall = true;
if (this.cat.isCaught()) { this.state = "win"; }
updateTurnUI();
return true;
} else {
currentPlayerSteps = 0; config.turnIndex++; updateTurnUI();
return this.originalPlayerClick(t, e);
}
}
};
scene.blocks.forEach(row => {
row.forEach(block => {
block.off('player_click');
block.on('player_click', scene.playerClick.bind(scene));
});
});
isGameHooked = true;
addLog("V2.1 逻辑已就绪");
return true;
}
createUI();
setInterval(() => { if (!isGameHooked) injectHook(); }, 1500);
})();
贪吃蛇版
玩法说明:鼠标在贪吃蛇前面悬浮移动则贪吃蛇跟着你走,先吃掉所有黑点,最后吃猫,成功后进入下一关
// ==UserScript==
// @name Hmily的猫猫:贪吃蛇自动版
// @namespace http://tampermonkey.net/
// @version 2.1
// @description 【单人闯关版】
// @author 52pojie
// @match https://www.52pojie.cn/*
// @icon https://avatar.52pojie.cn/data/avatar/000/00/00/01_avatar_middle.jpg
// @grant GM_addStyle
// @run-at document-end
// ==/UserScript==
(function() {
'use strict';
const win = (typeof unsafeWindow !== 'undefined') ? unsafeWindow : window;
// --- 0. 页面判定与内容修改 ---
const is404Page = () => {
const h1 = document.querySelector('.container h1');
const h2 = document.querySelector('.container h2');
const gameContainer = document.getElementById('catch-the-cat');
if (h1 && h1.innerText.includes('404') && gameContainer) {
h1.innerText = 'Hmily的猫猫:贪吃蛇闯关';
if (h2) h2.innerText = '吾爱破解祝你:喵运当头,锦鲤附体!🐾';
return true;
}
return false;
};
if (!is404Page()) return;
// --- 1. 样式定义 ---
GM_addStyle(`
#snake-mod-panel {
position: fixed; top: 20px; right: 20px; width: 260px;
background: #fff; border-radius: 12px; box-shadow: 0 10px 25px rgba(0,0,0,0.3);
z-index: 10000; padding: 15px; font-family: sans-serif; border: 2px solid #28a745;
transition: all 0.3s ease; overflow: hidden; display: flex; flex-direction: column;
}
#snake-mod-panel.minimized {
width: 44px; height: 44px; padding: 0; cursor: pointer; border-radius: 50%;
border: none; box-shadow: 0 4px 12px rgba(40,167,69,0.4);
}
.panel-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; border-bottom: 1px solid #eee; padding-bottom: 8px; }
#snake-mod-panel.minimized .panel-header { border: none; margin: 0; padding: 0; width: 100%; height: 100%; justify-content: center; }
.header-left { display: flex; align-items: center; }
.panel-icon { width: 28px; height: 28px; border-radius: 50%; border: 1px solid #28a745; transition: all 0.3s ease; object-fit: cover; }
#snake-mod-panel.minimized .panel-icon { width: 44px; height: 44px; border: none; }
.level-tag { background: #28a745; color: #fff; padding: 2px 6px; border-radius: 6px; font-size: 11px; margin-left: 8px; white-space: nowrap; }
.toggle-btn { background: none; border: none; color: #28a745; cursor: pointer; font-size: 12px; padding: 2px 5px; }
#snake-mod-panel.minimized h3,
#snake-mod-panel.minimized .level-tag,
#snake-mod-panel.minimized .info-box,
#snake-mod-panel.minimized .timer-box,
#snake-mod-panel.minimized .restart-btn,
#snake-mod-panel.minimized .status-msg,
#snake-mod-panel.minimized .toggle-btn,
#snake-mod-panel.minimized .reset-data,
#snake-mod-panel.minimized .hint { display: none; }
.info-box { padding: 8px; border-radius: 6px; text-align: center; margin-bottom: 10px; border: 1px solid #eee; background: #f8f9fa; font-size: 13px; line-height: 1.6; }
.timer-box { font-size: 20px; text-align: center; color: #d9534f; font-weight: bold; margin: 5px 0 10px 0; display: none; }
.restart-btn { background: #28a745; color: #fff; border: none; padding: 10px; width: 100%; border-radius: 5px; cursor: pointer; font-weight: bold; margin-bottom: 5px; }
.reset-data { font-size: 10px; color: #999; text-align: center; cursor: pointer; text-decoration: underline; margin-top: 5px; }
.status-msg { font-size: 12px; color: #666; margin-top: 8px; font-family: monospace; border-top: 1px solid #eee; padding-top: 5px; }
.hint { font-size: 11px; color: #999; text-align: center; margin-bottom: 8px; line-height: 1.4; }
#cat-god-overlay {
position: fixed; top: 0; left: 0; width: 100vw; height: 100vh;
background: rgba(0,0,0,0.7); display: flex; flex-direction: column;
justify-content: center; align-items: center; z-index: 20000;
pointer-events: none; opacity: 0; transition: opacity 1s;
}
#cat-god-text {
font-size: 120px; font-weight: 900; color: #ffcc00;
text-shadow: 0 0 20px #ff6600, 0 0 40px #ffcc00;
transform: scale(0.5); transition: transform 0.8s cubic-bezier(0.175, 0.885, 0.32, 1.275);
font-family: "Microsoft YaHei", sans-serif;
}
.confetti {
position: absolute; width: 10px; height: 10px; border-radius: 2px;
animation: confetti-fall 3s linear forwards;
}
@keyframes confetti-fall {
0% { transform: translateY(-10vh) rotate(0deg); opacity: 1; }
100% { transform: translateY(110vh) rotate(720deg); opacity: 0; }
}
`);
// --- 2. 游戏状态 ---
let gameState = {
level: 1,
snake: [],
foodCount: 0,
direction: 1,
gameTimerId: null,
catTimerId: null,
huntTimerId: null,
timeLeft: 30,
isHunting: false,
isGameOver: false,
isHooked: false
};
const saveLevel = (lvl) => localStorage.setItem('hmily_cat_snake_lvl', lvl);
const getLevel = () => {
let lvl = parseInt(localStorage.getItem('hmily_cat_snake_lvl')) || 1;
return Math.min(lvl, 15);
};
function getLevelName(lvl) {
return lvl >= 15 ? "最终关" : `第 ${lvl} 关`;
}
// --- 3. UI 构建 ---
function createUI() {
const panel = document.createElement('div');
panel.id = 'snake-mod-panel';
gameState.level = getLevel();
document.body.appendChild(panel);
const overlay = document.createElement('div');
overlay.id = 'cat-god-overlay';
overlay.innerHTML = `<div id="cat-god-text">你是猫神</div>`;
document.body.appendChild(overlay);
updatePanelHTML();
}
function updatePanelHTML() {
const panel = document.getElementById('snake-mod-panel');
if (!panel) return;
const foodGoal = calculateFoodLimit();
const timeGoal = calculateCatchTime();
panel.innerHTML = `
<div class="panel-header" id="panel-header">
<div class="header-left">
<img src="https://avatar.52pojie.cn/data/avatar/000/00/00/01_avatar_middle.jpg" class="panel-icon" id="panel-logo">
<h3 style="margin:0 0 0 8px; font-size:15px; color:#28a745;">贪吃蛇闯关</h3>
<span class="level-tag">${getLevelName(gameState.level)}</span>
</div>
<button class="toggle-btn" id="btn-minimize">收起</button>
</div>
<div class="hint">悬停蛇头相邻格转向</div>
<div id="target-info" class="info-box">
<b>本关目标</b><br>
吃掉 <span style="color:#d9534f">${foodGoal}</span> 个黑点<br>
抓猫限时 <span style="color:#d9534f">${timeGoal}</span> 秒
</div>
<div id="status-display" class="info-box" style="color:#28a745; display:none;">剩余黑点:--</div>
<div class="timer-box" id="game-timer">倒计时:${timeGoal}s</div>
<button class="restart-btn" id="btn-start-snake">开始挑战</button>
<div class="reset-data" id="btn-reset-data">重置进度</div>
<div class="status-msg" id="snake-log">> 准备就绪</div>
`;
const minimizeBtn = document.getElementById('btn-minimize');
const togglePanel = () => {
panel.classList.toggle('minimized');
minimizeBtn.innerText = panel.classList.contains('minimized') ? "" : "收起";
};
minimizeBtn.onclick = (e) => { e.stopPropagation(); togglePanel(); };
panel.onclick = () => { if(panel.classList.contains('minimized')) togglePanel(); };
document.getElementById('btn-start-snake').onclick = initSnakeGame;
document.getElementById('btn-reset-data').onclick = () => {
if(confirm("确定要重置进度到第一关吗?")) {
saveLevel(1);
location.reload();
}
};
}
function calculateCatchTime() {
if (gameState.level >= 15) return 10;
return (gameState.level % 2 === 0) ? 20 : 30;
}
function calculateFoodLimit() {
if (gameState.level >= 15) return 2;
return Math.max(2, 8 - Math.floor((gameState.level - 1) / 2));
}
function addLog(msg) {
const log = document.getElementById('snake-log');
if (log) log.innerText = "> " + msg;
}
// --- 4. 特效逻辑 ---
function handleWinEffect(scene) {
if (gameState.level >= 15) {
showCatGodEffect();
}
scene.setStatusText(`恭喜通过 ${getLevelName(gameState.level)}!`);
scene.state = "win";
if (gameState.level < 15) {
gameState.level++;
saveLevel(gameState.level);
}
updatePanelHTML();
addLog("成功抓住!");
}
function showCatGodEffect() {
const overlay = document.getElementById('cat-god-overlay');
const text = document.getElementById('cat-god-text');
overlay.style.opacity = "1";
text.style.transform = "scale(1)";
for (let i = 0; i < 100; i++) {
setTimeout(() => {
const confetti = document.createElement('div');
confetti.className = 'confetti';
confetti.style.left = Math.random() * 100 + 'vw';
confetti.style.backgroundColor = ['#ff0', '#f0f', '#0ff', '#f00', '#0f0'][Math.floor(Math.random() * 5)];
overlay.appendChild(confetti);
setTimeout(() => confetti.remove(), 3000);
}, i * 20);
}
setTimeout(() => {
overlay.style.opacity = "0";
text.style.transform = "scale(0.5)";
}, 5000);
}
// --- 5. 核心逻辑 ---
function initSnakeGame() {
if (!win.game || !win.game.mainScene) return;
const scene = win.game.mainScene;
scene.reset();
stopAllTimers();
gameState.level = getLevel();
const foodGoal = calculateFoodLimit();
gameState.timeLeft = calculateCatchTime();
scene.cat.isEscaped = function() { return false; };
scene.checkWin = function() { return false; };
scene.lose = function() { return gameState.isGameOver ? true : false; };
scene.win = function() { return false; };
gameState.snake = [{i: 5, j: 4}];
gameState.direction = 1;
gameState.isHunting = false;
gameState.isGameOver = false;
document.getElementById('game-timer').style.display = 'none';
document.getElementById('status-display').style.display = 'block';
document.getElementById('status-display').innerText = `剩余黑点:${foodGoal}`;
setupMapFood(scene, foodGoal);
updateVisuals();
if (!gameState.isHooked) hookEvents();
const snakeSpeed = Math.max(200, 400 - (gameState.level * 10));
const catSpeed = Math.max(250, 400 - (gameState.level * 9));
gameState.gameTimerId = setInterval(() => {
if (!gameState.isGameOver) autoMoveStep();
}, snakeSpeed);
gameState.catTimerId = setInterval(() => {
if (!gameState.isGameOver) moveCatAI(scene);
}, catSpeed);
addLog(`${getLevelName(gameState.level)} 已启动!`);
}
function setupMapFood(scene, limit) {
scene.blocks.forEach(row => row.forEach(b => b.isWall = false));
let placed = 0;
while (placed < limit) {
let ri = Math.floor(Math.random() * 11);
let rj = Math.floor(Math.random() * 11);
let b = scene.getBlock(ri, rj);
if (b && !b.isWall && (ri !== 5 || rj !== 5) && (ri !== 5 || rj !== 4)) {
b.isWall = true;
placed++;
}
}
gameState.foodCount = placed;
}
function updateVisuals() {
const scene = win.game.mainScene;
scene.blocks.forEach(row => row.forEach(b => {
b.fillColor = b.isWall ? 0x333333 : 0xb3ffbf00;
gameState.snake.forEach((part, index) => {
if (b.i === part.i && b.j === part.j) {
b.fillColor = (index === 0) ? 0x28a745 : 0x71d581;
}
});
}));
}
function hookEvents() {
const scene = win.game.mainScene;
const handleHover = function(block) {
if (gameState.isGameOver || !gameState.snake.length) return;
const head = gameState.snake[0];
const neighbors = scene.constructor.getNeighbours(head.i, head.j);
const dirIndex = neighbors.findIndex(n => n.i === block.i && n.j === block.j);
if (dirIndex !== -1) gameState.direction = dirIndex;
};
scene.blocks.forEach(row => row.forEach(b => {
b.off('player_click');
b.on('pointerover', () => handleHover(b));
b.on('player_click', () => handleHover(b));
}));
gameState.isHooked = true;
}
function stopAllTimers() {
if (gameState.gameTimerId) clearInterval(gameState.gameTimerId);
if (gameState.catTimerId) clearInterval(gameState.catTimerId);
if (gameState.huntTimerId) clearInterval(gameState.huntTimerId);
gameState.gameTimerId = null;
gameState.catTimerId = null;
gameState.huntTimerId = null;
}
function autoMoveStep() {
const scene = win.game.mainScene;
const head = gameState.snake[0];
const neighbors = scene.constructor.getNeighbours(head.i, head.j);
const next = neighbors[gameState.direction];
const targetBlock = scene.getBlock(next.i, next.j);
if (!targetBlock || gameState.snake.some(p => p.i === next.i && p.j === next.j)) {
gameState.isGameOver = true;
stopAllTimers();
scene.setStatusText("失败!按开始重试");
addLog("失败:发生撞击");
return;
}
if (scene.cat.i === next.i && scene.cat.j === next.j) {
if (gameState.isHunting) {
gameState.isGameOver = true;
stopAllTimers();
handleWinEffect(scene);
return;
}
}
const newHead = {i: next.i, j: next.j};
if (targetBlock.isWall) {
targetBlock.isWall = false;
gameState.snake.unshift(newHead);
gameState.foodCount--;
document.getElementById('status-display').innerText = `剩余黑点:${gameState.foodCount}`;
if (gameState.foodCount <= 0 && !gameState.isHunting) startHuntingPhase();
} else {
gameState.snake.unshift(newHead);
gameState.snake.pop();
}
updateVisuals();
}
function startHuntingPhase() {
gameState.isHunting = true;
const scene = win.game.mainScene;
document.getElementById('game-timer').style.display = 'block';
document.getElementById('status-display').style.display = 'none';
scene.setStatusText(`抓猫时刻:${gameState.timeLeft}s`);
gameState.huntTimerId = setInterval(() => {
if (gameState.isGameOver) return;
gameState.timeLeft--;
document.getElementById('game-timer').innerText = `倒计时:${gameState.timeLeft}s`;
scene.setStatusText(`抓猫时刻:${gameState.timeLeft}s`);
if (gameState.timeLeft <= 0) {
stopAllTimers();
gameState.isGameOver = true;
scene.setStatusText("时间到,抓猫失败!");
scene.state = "lose";
addLog("失败:倒计时结束");
}
}, 1000);
}
function moveCatAI(scene) {
if (gameState.isGameOver) return;
const cat = scene.cat;
const head = gameState.snake[0];
const neighbors = scene.constructor.getNeighbours(cat.i, cat.j);
let validMoves = neighbors.filter(n => {
if (n.i < 0 || n.i > 10 || n.j < 0 || n.j > 10) return false;
const b = scene.getBlock(n.i, n.j);
return b && !b.isWall && !gameState.snake.some(p => p.i === n.i && p.j === n.j);
});
if (validMoves.length > 0) {
validMoves.sort((a, b) => {
const distA = Math.hypot(a.i - head.i, a.j - head.j);
const distB = Math.hypot(b.i - head.i, b.j - head.j);
if (Math.abs(distA - distB) < 0.5) {
return Math.hypot(a.i - 5, a.j - 5) - Math.hypot(b.i - 5, b.j - 5);
}
return distB - distA;
});
const best = validMoves[0];
const dir = neighbors.findIndex(n => n.i === best.i && n.j === best.j);
cat.stepDirection(dir);
cat.i = Math.max(0, Math.min(10, cat.i));
cat.j = Math.max(0, Math.min(10, cat.j));
}
}
createUI();
})();
|
免费评分
-
查看全部评分
|