全域Emoji打怪(低负载)
by NovaStar20223 lines6.8 KB
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
<title>全域Emoji打怪(低负载)</title>
<style>
*{margin:0;padding:0;box-sizing:border-box;font-size:18px;}
body{background:#0a0a18;color:#fff;height:100vh;overflow:hidden;touch-action:none;}
#startPage{width:100%;height:100vh;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:24px;}
#gamePage{width:100%;height:100vh;display:none;position:relative;}
.info-bar{padding:10px;text-align:center;z-index:10;position:relative;}
#gameArea{width:100%;height:72vh;background:#111428;position:relative;overflow:hidden;}
.player{font-size:48px;position:absolute;z-index:2;user-select:none;}
.gun-item{font-size:40px;position:absolute;z-index:1;user-select:none;}
.monster{font-size:42px;position:absolute;user-select:none;}
.joystick-box{position:absolute;bottom:12px;left:16px;width:120px;height:120px;background:rgba(255,255,255,0.15);border-radius:50%;}
.joystick-stick{width:46px;height:46px;background:rgba(255,255,255,0.35);border-radius:50%;position:absolute;left:37px;top:37px;}
</style>
</head>
<body>
<div id="startPage">
<div style="font-size:34px">😃 全域打怪</div>
<div>摇杆自由移动,拾取枪械点击消灭怪物</div>
<button onclick="startGame()" style="font-size:22px;padding:14px 32px">开始游戏</button>
</div>
<div id="gamePage">
<div class="info-bar">
分数:<span id="scoreTxt">0</span>|生命:<span id="hpTxt">❤️❤️❤️</span>
</div>
<div id="gameArea">
<div class="player" id="player">😃</div>
<div class="gun-item" id="gunItem">🔫</div>
</div>
<div class="joystick-box" id="joyBox">
<div class="joystick-stick" id="joyStick"></div>
</div>
</div>
<script>
let score = 0;
let hp = 3;
let playerX = 45;
let playerY = 60;
const playerSpeed = 0.36;
let gameRun = false;
let hasGun = false;
let monsterList = [];
const MAX_MONSTER = 8;
let joyActive = false;
let joyVecX = 0;
let joyVecY = 0;
const gameArea = document.getElementById('gameArea');
const playerDom = document.getElementById('player');
const gunItem = document.getElementById('gunItem');
const scoreTxt = document.getElementById('scoreTxt');
const hpTxt = document.getElementById('hpTxt');
const joyBox = document.getElementById('joyBox');
const joyStick = document.getElementById('joyStick');
function resetGame(){
score = 0;
hp = 3;
playerX = 45;
playerY = 60;
hasGun = false;
monsterList = [];
gunItem.style.display = "block";
gunItem.style.left = playerX + "%";
gunItem.style.top = (playerY + 12) + "%";
document.querySelectorAll('.monster').forEach(el=>el.remove());
refreshUI();
}
function refreshUI(){
scoreTxt.innerText = score;
hpTxt.innerText = "❤️".repeat(hp);
playerDom.style.left = playerX + "%";
playerDom.style.top = playerY + "%";
}
function startGame(){
document.getElementById('startPage').style.display="none";
document.getElementById('gamePage').style.display="block";
resetGame();
gameRun=true;
loop();
setTimeout(spawnMonster,6000);
}
joyBox.addEventListener('touchstart',()=>{joyActive=true;});
joyBox.addEventListener('touchmove',e=>{
e.preventDefault();
const touch = e.touches[0];
const rect = joyBox.getBoundingClientRect();
const cx = 60, cy = 60;
let dx = touch.clientX - rect.left - cx;
let dy = touch.clientY - rect.top - cy;
const maxR = 50;
const dist = Math.hypot(dx,dy);
if(dist > maxR){
dx = dx/dist * maxR;
dy = dy/dist * maxR;
}
joyStick.style.left = (cx + dx - 23) + "px";
joyStick.style.top = (cy + dy - 23) + "px";
joyVecX = dx / maxR;
joyVecY = dy / maxR;
});
joyBox.addEventListener('touchend',()=>{
joyActive=false;
joyVecX = 0;
joyVecY = 0;
joyStick.style.left="37px";
joyStick.style.top="37px";
});
gameArea.addEventListener('touchstart',(evt)=>{
if(!gameRun || !hasGun) return;
const rect = gameArea.getBoundingClientRect();
const clickX = (evt.touches[0].clientX - rect.left)/rect.width*100;
const clickY = (evt.touches[0].clientY - rect.top)/rect.height*100;
for(let i = monsterList.length - 1; i >= 0; i--){
const m = monsterList[i];
const distance = Math.hypot(clickX - m.x, clickY - m.y);
if(distance < 6){
score += 10;
m.dom.remove();
monsterList.splice(i,1);
refreshUI();
break;
}
}
});
function spawnMonster(){
if(!gameRun) return;
if(monsterList.length >= MAX_MONSTER){
setTimeout(spawnMonster, 1800);
return;
}
const emoji = ["😈","😡"][Math.floor(Math.random()*2)];
let x,y;
const side = Math.floor(Math.random()*4);
switch(side){
case 0: x = Math.random()*100; y = -6; break;
case 1: x = Math.random()*100; y = 98; break;
case 2: x = -6; y = Math.random()*100; break;
case 3: x = 102; y = Math.random()*100; break;
}
const monsterDom = document.createElement('div');
monsterDom.className = "monster";
monsterDom.innerText = emoji;
monsterDom.style.left = x + "%";
monsterDom.style.top = y + "%";
gameArea.appendChild(monsterDom);
monsterList.push({
dom:monsterDom,
x:x,
y:y,
speed:0.22
});
setTimeout(spawnMonster, 1800);
}
function loop(){
if(!gameRun) return;
let needUpdate = false;
if(joyActive){
playerX += joyVecX * playerSpeed;
playerY += joyVecY * playerSpeed;
playerX = Math.max(3, Math.min(93, playerX));
playerY = Math.max(3, Math.min(88, playerY));
needUpdate = true;
}
if(!hasGun){
const gx = parseFloat(gunItem.style.left);
const gy = parseFloat(gunItem.style.top);
const distGun = Math.hypot(playerX-gx, playerY-gy);
if(distGun < 6){
hasGun = true;
gunItem.style.display = "none";
}
}
for(let i = monsterList.length - 1; i >= 0; i--){
const m = monsterList[i];
const dx = playerX - m.x;
const dy = playerY - m.y;
const dist = Math.hypot(dx,dy);
if(dist > 0.5){
m.x += dx/dist * m.speed;
m.y += dy/dist * m.speed;
}
m.dom.style.left = m.x + "%";
m.dom.style.top = m.y + "%";
const hitDist = Math.hypot(playerX - m.x, playerY - m.y);
if(hitDist < 5){
hp--;
needUpdate = true;
m.dom.remove();
monsterList.splice(i,1);
if(hp <= 0){
gameRun = false;
alert("游戏结束!得分:"+score);
setTimeout(resetGame, 1200);
}
}
}
if(needUpdate) refreshUI();
requestAnimationFrame(loop);
}
</script>
</body>
</html>
Game Source: 全域Emoji打怪(低负载)
Creator: NovaStar20
Libraries: none
Complexity: complex (223 lines, 6.8 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: emoji-novastar20" to link back to the original. Then publish at arcadelab.ai/publish.