自定义皮肤打地鼠
by CrystalMeteor49212 lines6.7 KB
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>自定义皮肤打地鼠</title>
<style>
*{box-sizing:border-box;margin:0;padding:0;font-family:system-ui}
img {
object-fit: contain;
}
body{background:#eef6ff;padding:16px}
#wrap{max-width:500px;margin:0 auto}
.topbar{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px}
.info{font-size:28px;font-weight:bold}
#startBtn{padding:8px 16px;font-size:20px}
.holeGrid{display:grid;grid-template-columns:1fr 1fr 1fr;gap:12px;margin:20px 0}
.hole{aspect-ratio:1/1;background:#8b572a;border-radius:50%;position:relative;overflow:hidden}
.mouse{width:70%;height:70%;position:absolute;bottom:0;left:15%;display:none}
.bottomBar{display:flex;justify-content:space-between;align-items:center;margin-top:16px;gap:8px}
.bottomBar button{padding:8px 12px;font-size:18px}
#drawPanel{position:fixed;inset:0;background:rgba(0,0,0,0.6);display:none;align-items:center;justify-content:center}
.drawBox{background:white;padding:16px;border-radius:10px}
#skinCanvas{border:1px solid #999}
.drawBtns{margin-top:8px;display:flex;gap:8px}
#bagPanel{position:fixed;inset:0;background:rgba(0,0,0,0.6);display:none;align-items:center;justify-content:center}
.bagBox{background:white;padding:16px;border-radius:10px;max-width:90vw}
.skinItem{width:80px;height:80px;border:1px solid #ccc;margin:4px;cursor:pointer}
</style>
</head>
<body>
<div id="wrap">
<div class="topbar">
<div class="info">分数:<span id="score">0</span> 时间:<span id="time">60</span></div>
<button id="startBtn">开始游戏</button>
</div>
<div class="holeGrid" id="grid">
<div class="hole"><img class="mouse" src="" alt=""></div>
<div class="hole"><img class="mouse" src="" alt=""></div>
<div class="hole"><img class="mouse" src="" alt=""></div>
<div class="hole"><img class="mouse" src="" alt=""></div>
<div class="hole"><img class="mouse" src="" alt=""></div>
<div class="hole"><img class="mouse" src="" alt=""></div>
<div class="hole"><img class="mouse" src="" alt=""></div>
<div class="hole"><img class="mouse" src="" alt=""></div>
<div class="hole"><img class="mouse" src="" alt=""></div>
</div>
<div class="bottomBar">
<button id="drawBtn">自定义皮肤</button>
<button id="bagBtn">背包</button>
<button id="soundBtn">🔊</button>
</div>
</div>
<div id="drawPanel">
<div class="drawBox">
<canvas id="skinCanvas" width="120" height="120"></canvas>
<div class="drawBtns">
<button id="saveSkin">保存皮肤</button>
<button id="closeDraw">关闭</button>
</div>
</div>
</div>
<div id="bagPanel">
<div class="bagBox">
<div id="skinList"></div>
<button id="closeBag">关闭</button>
</div>
</div>
<script>
const scoreEl=document.getElementById("score");
const timeEl=document.getElementById("time");
const startBtn=document.getElementById("startBtn");
const grid=document.getElementById("grid");
const holes=Array.from(document.querySelectorAll(".hole"));
const mouses=Array.from(document.querySelectorAll(".mouse"));
const drawBtn=document.getElementById("drawBtn");
const bagBtn=document.getElementById("bagBtn");
const soundBtn=document.getElementById("soundBtn");
const drawPanel=document.getElementById("drawPanel");
const bagPanel=document.getElementById("bagPanel");
const skinCanvas=document.getElementById("skinCanvas");
const ctx=skinCanvas.getContext("2d");
const saveSkin=document.getElementById("saveSkin");
const closeDraw=document.getElementById("closeDraw");
const closeBag=document.getElementById("closeBag");
const skinList=document.getElementById("skinList");
let score=0;
let time=60;
let running=false;
let timer=null;
let popTimer=null;
let soundOn=true;
let currentSkin=null;
let skins=JSON.parse(localStorage.getItem("skinList")||"[]");
// 默认皮肤
const defaultSkinUrl="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Ccircle cx='50' cy='50' r='45' fill='%238b572a'/%3E%3Ccircle cx='35' cy='40' r='8' fill='black'/%3E%3Ccircle cx='65' cy='40' r='8' fill='black'/%3E%3Cellipse cx='50' cy='65' rx='10' ry='7' fill='%23553322'/%3E%3C/svg%3E";
skins.unshift(defaultSkinUrl);
renderBag();
// 音效
function hitSound(){
if(!soundOn) return;
const a=new AudioContext();
const o=a.createOscillator();
const g=a.createGain();
o.connect(g);g.connect(a.destination);
o.frequency.value=600;
g.gain.setValueAtTime(0.2,a.currentTime);
g.gain.exponentialRampToValueAtTime(0.001,a.currentTime+0.12);
o.start();o.stop(a.currentTime+0.12);
}
// 开始游戏
startBtn.onclick=()=>{
if(running) return;
running=true;
score=0;time=60;
scoreEl.textContent=score;
timeEl.textContent=time;
timer=setInterval(()=>{
time--;
timeEl.textContent=time;
if(time<=0){clearInterval(timer);running=false;clearTimeout(popTimer)}
},1000);
popUp();
}
function popUp(){
if(!running) return;
hideAll();
const idx=Math.floor(Math.random()*9);
const mouse=mouses[idx];
mouse.src=currentSkin||skins[0];
mouse.style.display="block";
popTimer=setTimeout(()=>{
mouse.style.display="none";
popUp();
},900)
}
function hideAll(){mouses.forEach(m=>m.style.display="none")}
holes.forEach((h,i)=>{
h.onclick=()=>{
if(!running) return;
const m=mouses[i];
if(m.style.display==="block"){
score++;
scoreEl.textContent=score;
hitSound();
m.style.display="none";
}
}
})
// 画布绘画
let drawing=false;
skinCanvas.onmousedown=(e)=>{drawing=true}
skinCanvas.onmouseup=()=>{drawing=false}
skinCanvas.onmouseleave=()=>{drawing=false}
skinCanvas.onmousemove=(e)=>{
if(!drawing) return;
const r=skinCanvas.getBoundingClientRect();
const x=e.clientX-r.left;
const y=e.clientY-r.top;
ctx.fillStyle="#222";
ctx.beginPath();
ctx.arc(x,y,5,0,Math.PI*2);
ctx.fill();
}
ctx.fillStyle="#cccccc";
ctx.fillRect(0,0,120,120);
saveSkin.onclick=()=>{
const url=skinCanvas.toDataURL("image/png");
skins.push(url);
localStorage.setItem("skinList",JSON.stringify(skins));
renderBag();
drawPanel.style.display="none";
}
closeDraw.onclick=()=>drawPanel.style.display="none";
drawBtn.onclick=()=>{
ctx.fillStyle="#cccccc";
ctx.fillRect(0,0,120,120);
drawPanel.style.display="flex";
}
closeBag.onclick=()=>bagPanel.style.display="none";
bagBtn.onclick=()=>{renderBag();bagPanel.style.display="flex"}
function renderBag(){
skinList.innerHTML="";
skins.forEach((s,i)=>{
const img=document.createElement("img");
img.src=s;
img.className="skinItem";
img.onclick=()=>{currentSkin=s}
skinList.appendChild(img);
})
}
soundBtn.onclick=()=>{
soundOn=!soundOn;
soundBtn.textContent=soundOn?"🔊":"🔇";
}
</script>
</body>
</html>
Game Source: 自定义皮肤打地鼠
Creator: CrystalMeteor49
Libraries: none
Complexity: complex (212 lines, 6.7 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: game-crystalmeteor49" to link back to the original. Then publish at arcadelab.ai/publish.