console
<!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>
*{margin:0;padding:0;box-sizing:border-box;}
body{background:#1a1a1a;color:#fff;overflow:hidden;font-family:system-ui,sans-serif;}
#gameWrap{width:100vw;height:100vh;display:flex;flex-direction:column;align-items:center;}
#title{padding:12px;font-size:20px;text-align:center;}
#gameBox{width:min(90vw,400px);height:min(120vh,600px);background:#222;border-radius:16px;position:relative;overflow:hidden;border:2px solid #444;}
.ball{position:absolute;border-radius:50%;overflow:hidden;cursor:pointer;}
.ball img{width:100%;height:100%;object-fit:cover;}
#tip{position:fixed;bottom:20px;text-align:center;width:100%;font-size:14px;color:#aaa}
.modal{
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.7);
display: none;
align-items: center;
justify-content: center;
z-index:99;
}
.modal-content{
background:#2b2b2b;
padding:30px 40px;
border-radius:16px;
text-align:center;
font-size:20px;
}
.modal button{
margin-top:20px;
border:none;
padding:8px 20px;
border-radius:8px;
background:#3498db;
color:white;
font-size:16px;
}
</style>
</head>
<body>
<div id="gameWrap">
<div id="title">自拍合成大照片|合成到8级雨伞自拍获胜</div>
<div id="gameBox"></div>
<div id="tip">点击屏幕上方投放图片,相同自拍碰撞合成升级</div>
</div>
<div class="modal" id="winModal">
<div class="modal-content">
<div>恭喜生成雨中回忆录一张</div>
<button id="closeBtn">确定</button>
</div>
</div>
<script>
// 你的图片链接
const imgList = [
"https://i.ibb.co/kVTLK9Mw/image.jpg", //1级
"https://i.ibb.co/Ld9qLxw9/image.jpg", //2级
"https://i.ibb.co/XZnTGSd8/image.jpg", //3级
"https://i.ibb.co/RGSs9cfJ/image.jpg", //4级
"https://i.ibb.co/C5qNzYXd/image.jpg", //5级
"https://i.ibb.co/LXB53w11/image.jpg", //6级
"https://i.ibb.co/pr12tpVF/image.jpg", //7级
"https://i.ibb.co/Z1LJM1Kr/image.jpg" //8级
];
const levelName = [
"1级:手托脸自拍",
"2级:斜拍自拍",
"3级:捂嘴自拍",
"4级:抬手自拍",
"5级:操场白衣全身照",
"6级:白上衣视频截图",
"7级:暗调氛围感自拍",
"8级:雨伞自拍"
];
// 球体半径,等级越高越大
const radiusArr = [32,40,48,56,64,72,80,90];
const gameBox = document.getElementById("gameBox");
const boxW = gameBox.clientWidth;
const boxH = gameBox.clientHeight;
let balls = [];
let nextLevel = 0;
let animId;
const winModal = document.getElementById("winModal");
const closeBtn = document.getElementById("closeBtn");
closeBtn.onclick = ()=>{
winModal.style.display = "none";
}
// 创建球
function createBall(lv,x,y){
const div = document.createElement("div");
div.className = "ball";
const r = radiusArr[lv];
div.style.width = r*2 +"px";
div.style.height = r*2 +"px";
div.style.left = x - r +"px";
div.style.top = y - r +"px";
const img = document.createElement("img");
img.src = imgList[lv];
img.alt = levelName[lv];
div.appendChild(img);
gameBox.appendChild(div);
return {
el:div,
lv:lv,
x:x,
y:y,
r:r,
vx:0,
vy:0
}
}
// 点击投放
gameBox.onclick = function(e){
const rect = gameBox.getBoundingClientRect();
const clickX = e.clientX - rect.left;
if(balls.length > 25) return;
const newBall = createBall(nextLevel, clickX, 60);
balls.push(newBall);
nextLevel = Math.floor(Math.random()*2); //随机出1级/2级
}
// 物理循环
function loop(){
const gravity = 0.28;
const bounce = 0.72;
const friction = 0.99;
for(let b of balls){
b.vy += gravity;
b.x += b.vx;
b.y += b.vy;
//左右墙碰撞
if(b.x - b.r <0){
b.x = b.r;
b.vx *= -bounce;
}
if(b.x + b.r > boxW){
b.x = boxW - b.r;
b.vx *= -bounce;
}
//底部碰撞
if(b.y + b.r > boxH){
b.y = boxH - b.r;
b.vy *= -bounce;
b.vx *= friction;
}
b.el.style.left = (b.x - b.r)+"px";
b.el.style.top = (b.y - b.r)+"px";
}
//碰撞检测 合成
for(let i=0;i<balls.length;i++){
for(let j=i+1;j<balls.length;j++){
const a = balls[i];
const b = balls[j];
const dx = a.x - b.x;
const dy = a.y - b.y;
const dist = Math.sqrt(dx*dx + dy*dy);
if(dist < a.r + b.r && a.lv === b.lv){
if(a.lv >=7) {
//合成8级,弹出提示
winModal.style.display = "flex";
a.el.remove();
b.el.remove();
balls = balls.filter(item=>item!==a && item!==b);
break;
}
//删除两个旧球
a.el.remove();
b.el.remove();
//生成更高一级
const newLv = a.lv +1;
const nx = (a.x + b.x)/2;
const ny = (a.y + b.y)/2;
const newBall = createBall(newLv, nx, ny);
balls.push(newBall);
balls = balls.filter(item=>item!==a && item!==b);
break;
}
}
}
animId = requestAnimationFrame(loop);
}
loop();
</script>
</body>
</html>