用Trae自动生成的网页游戏(消消乐)AI自动生成的代码
·
文件名:game4.html
消消乐网页游戏,运行的效果不太好,直接po图和代码。

<!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: linear-gradient(135deg, #1a1a2e, #16213e);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
min-height: 100vh;
font-family: "Microsoft YaHei", sans-serif;
color: #fff;
user-select: none;
}
h1 {
font-size: 36px;
color: #ffd700;
margin-bottom: 6px;
text-shadow: 0 0 20px rgba(255,215,0,0.3);
}
#info {
display: flex;
gap: 40px;
margin-bottom: 12px;
font-size: 20px;
}
#info span { color: #ffd700; font-weight: bold; }
#game-container {
position: relative;
border-radius: 16px;
overflow: hidden;
box-shadow: 0 20px 60px rgba(0,0,0,0.5);
}
canvas { display: block; background: #0d1117; }
#controls {
margin-top: 15px;
display: flex;
gap: 12px;
}
.btn {
padding: 10px 28px;
font-size: 16px;
font-weight: bold;
color: #fff;
background: linear-gradient(135deg, #667eea, #764ba2);
border: none;
border-radius: 8px;
cursor: pointer;
transition: transform 0.15s;
}
.btn:hover { transform: scale(1.06); }
.btn.gold { background: linear-gradient(135deg, #ffd700, #ffb300); color: #4a3010; }
#overlay {
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
background: rgba(0,0,0,0.8);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 10;
}
#overlay h2 { font-size: 38px; color: #ffd700; margin-bottom: 12px; }
#overlay p { font-size: 20px; margin-bottom: 6px; color: #ccc; }
#overlay .final-score { color: #4fc3f7; font-size: 28px; margin: 10px 0 25px; }
#overlay button {
padding: 12px 40px;
font-size: 20px;
font-weight: bold;
color: #4a3010;
background: linear-gradient(135deg, #ffd700, #ffb300);
border: none;
border-radius: 30px;
cursor: pointer;
box-shadow: 0 4px 15px rgba(255,215,0,0.4);
transition: transform 0.2s;
}
#overlay button:hover { transform: scale(1.08); }
#hint {
margin-top: 10px;
font-size: 14px;
color: rgba(255,255,255,0.4);
}
#progress-bar {
width: 480px;
height: 8px;
background: rgba(255,255,255,0.1);
border-radius: 4px;
margin-bottom: 12px;
overflow: hidden;
}
#progress-fill {
height: 100%;
background: linear-gradient(90deg, #4caf50, #ffd700);
border-radius: 4px;
transition: width 0.3s;
}
</style>
</head>
<body>
<h1>消消乐</h1>
<div id="info">
<div>分数: <span id="score">0</span></div>
<div>步数: <span id="moves">20</span></div>
<div>目标: <span id="target">1000</span></div>
</div>
<div id="progress-bar"><div id="progress-fill" style="width:0%"></div></div>
<div id="game-container">
<canvas id="game" width="480" height="480"></canvas>
<div id="overlay">
<h2 id="ov-title">消消乐</h2>
<p id="ov-text">交换相邻方块,3个或以上同色即可消除</p>
<p class="final-score" id="ov-score"></p>
<button onclick="startGame()">开始游戏</button>
</div>
</div>
<div id="controls">
<button class="btn gold" onclick="startGame()">重新开始</button>
</div>
<div id="hint">点击选中方块,再点相邻方块交换 · 3个以上同色消除</div>
<script>
var canvas = document.getElementById('game');
var ctx = canvas.getContext('2d');
var GRID = 8;
var CELL = 60;
var COLORS = ['#ff5252', '#ffd700', '#4caf50', '#42a5f5', '#ab47bc', '#ff80ab'];
var COLOR_NAMES = ['红', '黄', '绿', '蓝', '紫', '粉'];
var board = [];
var selected = null;
var score = 0;
var moves = 20;
var targetScore = 1000;
var state = 'menu'; // menu, playing, animating, won, lost
var animations = [];
var floatTexts = [];
var particles = [];
function init() {
board = [];
score = 0;
moves = 20;
targetScore = 1000;
selected = null;
animations = [];
floatTexts = [];
particles = [];
state = 'playing';
// 生成无初始消除的棋盘
for (var y = 0; y < GRID; y++) {
board.push([]);
for (var x = 0; x < GRID; x++) {
var color;
do {
color = Math.floor(Math.random() * COLORS.length);
} while (
(x >= 2 && board[y][x-1] === color && board[y][x-2] === color) ||
(y >= 2 && board[y-1][x] === color && board[y-2][x] === color)
);
board[y].push(color);
}
}
updateUI();
draw();
}
function startGame() {
hideOverlay();
init();
}
// 检测匹配
function findMatches() {
var matches = [];
var matched = [];
for (var y = 0; y < GRID; y++) {
matched.push([]);
for (var x = 0; x < GRID; x++) matched[y].push(false);
}
// 横向
for (var y2 = 0; y2 < GRID; y2++) {
var runStart = 0;
for (var x2 = 1; x2 <= GRID; x2++) {
if (x2 === GRID || board[y2][x2] !== board[y2][runStart] || board[y2][runStart] === -1) {
if (x2 - runStart >= 3) {
for (var k = runStart; k < x2; k++) {
matched[y2][k] = true;
}
}
runStart = x2;
}
}
}
// 纵向
for (var x3 = 0; x3 < GRID; x3++) {
var runStart2 = 0;
for (var y3 = 1; y3 <= GRID; y3++) {
if (y3 === GRID || board[y3][x3] !== board[runStart2][x3] || board[runStart2][x3] === -1) {
if (y3 - runStart2 >= 3) {
for (var k2 = runStart2; k2 < y3; k2++) {
matched[k2][x3] = true;
}
}
runStart2 = y3;
}
}
}
for (var y4 = 0; y4 < GRID; y4++) {
for (var x4 = 0; x4 < GRID; x4++) {
if (matched[y4][x4]) matches.push({ x: x4, y: y4 });
}
}
return matches;
}
// 交换
function swap(x1, y1, x2, y2) {
var tmp = board[y1][x1];
board[y1][x1] = board[y2][x2];
board[y2][x2] = tmp;
}
function isAdjacent(x1, y1, x2, y2) {
return (Math.abs(x1 - x2) === 1 && y1 === y2) || (Math.abs(y1 - y2) === 1 && x1 === x2);
}
function handleClick(px, py) {
if (state !== 'playing') return;
var x = Math.floor(px / CELL);
var y = Math.floor(py / CELL);
if (x < 0 || x >= GRID || y < 0 || y >= GRID) return;
if (selected === null) {
selected = { x: x, y: y };
} else {
if (selected.x === x && selected.y === y) {
selected = null;
} else if (isAdjacent(selected.x, selected.y, x, y)) {
trySwap(selected.x, selected.y, x, y);
selected = null;
} else {
selected = { x: x, y: y };
}
}
draw();
}
function trySwap(x1, y1, x2, y2) {
swap(x1, y1, x2, y2);
var matches = findMatches();
if (matches.length === 0) {
// 无匹配,换回去
swap(x1, y1, x2, y2);
floatTexts.push({ text: '无效', x: x2 * CELL + CELL/2, y: y2 * CELL + CELL/2, color: '#f44336', life: 40 });
} else {
moves--;
state = 'animating';
processMatches();
}
updateUI();
}
function processMatches() {
var matches = findMatches();
if (matches.length === 0) {
state = 'playing';
checkEndGame();
return;
}
// 计分
var points = matches.length * 30;
if (matches.length >= 5) points = matches.length * 50;
score += points;
// 中心位置飘字
var avgX = 0, avgY = 0;
for (var i = 0; i < matches.length; i++) {
avgX += matches[i].x;
avgY += matches[i].y;
}
avgX = (avgX / matches.length) * CELL + CELL/2;
avgY = (avgY / matches.length) * CELL + CELL/2;
floatTexts.push({ text: '+' + points, x: avgX, y: avgY, color: '#ffd700', life: 60 });
// 粒子效果
for (var j = 0; j < matches.length; j++) {
var m = matches[j];
var cx = m.x * CELL + CELL/2;
var cy = m.y * CELL + CELL/2;
spawnParticles(cx, cy, COLORS[board[m.y][m.x]]);
board[m.y][m.x] = -1; // 标记消除
}
updateUI();
draw();
// 0.3秒后下落
setTimeout(function() {
dropAndFill();
}, 300);
}
function dropAndFill() {
// 下落
for (var x = 0; x < GRID; x++) {
var writeY = GRID - 1;
for (var y = GRID - 1; y >= 0; y--) {
if (board[y][x] !== -1) {
board[writeY][x] = board[y][x];
if (writeY !== y) board[y][x] = -1;
writeY--;
}
}
// 填充新方块
for (var y2 = writeY; y2 >= 0; y2--) {
board[y2][x] = Math.floor(Math.random() * COLORS.length);
}
}
draw();
// 检查连锁
setTimeout(function() {
processMatches();
}, 200);
}
function checkEndGame() {
if (score >= targetScore) {
state = 'won';
showOverlay('过关!', '分数: ' + score, '', '再来一局');
} else if (moves <= 0) {
state = 'lost';
showOverlay('游戏结束', '步数用完了', '分数: ' + score, '重新开始');
}
}
function showOverlay(title, text, scoreText, btn) {
document.getElementById('ov-title').textContent = title;
document.getElementById('ov-text').textContent = text;
document.getElementById('ov-score').textContent = scoreText;
var ovBtn = document.querySelector('#overlay button');
ovBtn.textContent = btn;
document.getElementById('overlay').style.display = 'flex';
}
function hideOverlay() {
document.getElementById('overlay').style.display = 'none';
}
function updateUI() {
document.getElementById('score').textContent = score;
document.getElementById('moves').textContent = moves;
document.getElementById('target').textContent = targetScore;
var pct = Math.min(100, (score / targetScore) * 100);
document.getElementById('progress-fill').style.width = pct + '%';
}
function spawnParticles(x, y, color) {
for (var i = 0; i < 10; i++) {
var a = Math.random() * Math.PI * 2;
var s = 2 + Math.random() * 5;
particles.push({
x: x, y: y,
vx: Math.cos(a) * s,
vy: Math.sin(a) * s - 3,
color: color,
life: 30,
size: 3 + Math.random() * 4
});
}
}
// ============ 渲染 ============
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 棋盘背景
ctx.fillStyle = '#0d1117';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 网格线
ctx.strokeStyle = 'rgba(255,255,255,0.04)';
ctx.lineWidth = 1;
for (var i = 0; i <= GRID; i++) {
ctx.beginPath();
ctx.moveTo(i * CELL, 0);
ctx.lineTo(i * CELL, canvas.height);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(0, i * CELL);
ctx.lineTo(canvas.width, i * CELL);
ctx.stroke();
}
// 方块
for (var y = 0; y < GRID; y++) {
for (var x = 0; x < GRID; x++) {
if (board[y][x] === -1) continue;
drawGem(x, y, board[y][x]);
}
}
// 选中高亮
if (selected) {
var sx = selected.x * CELL;
var sy = selected.y * CELL;
ctx.strokeStyle = '#fff';
ctx.lineWidth = 3;
ctx.strokeRect(sx + 2, sy + 2, CELL - 4, CELL - 4);
ctx.strokeStyle = 'rgba(255,255,255,0.3)';
ctx.lineWidth = 1;
ctx.strokeRect(sx - 1, sy - 1, CELL + 2, CELL + 2);
}
// 粒子
for (var p = particles.length - 1; p >= 0; p--) {
var pt = particles[p];
ctx.globalAlpha = pt.life / 30;
ctx.fillStyle = pt.color;
ctx.beginPath();
ctx.arc(pt.x, pt.y, pt.size, 0, Math.PI * 2);
ctx.fill();
pt.x += pt.vx;
pt.y += pt.vy;
pt.vy += 0.2;
pt.life--;
if (pt.life <= 0) particles.splice(p, 1);
}
ctx.globalAlpha = 1;
// 飘字
for (var f = floatTexts.length - 1; f >= 0; f--) {
var ft = floatTexts[f];
ctx.globalAlpha = ft.life / 60;
ctx.font = 'bold 22px "Microsoft YaHei"';
ctx.fillStyle = ft.color;
ctx.textAlign = 'center';
ctx.fillText(ft.text, ft.x, ft.y);
ft.y -= 1.5;
ft.life--;
if (ft.life <= 0) floatTexts.splice(f, 1);
}
ctx.globalAlpha = 1;
}
function drawGem(x, y, colorIdx) {
var cx = x * CELL + CELL / 2;
var cy = y * CELL + CELL / 2;
var r = CELL / 2 - 5;
var color = COLORS[colorIdx];
var shapes = ['circle', 'square', 'diamond', 'triangle', 'star', 'hexagon'];
var shape = shapes[colorIdx];
// 光晕
ctx.shadowColor = color;
ctx.shadowBlur = 8;
var grad = ctx.createRadialGradient(cx - r * 0.3, cy - r * 0.3, 0, cx, cy, r);
grad.addColorStop(0, lighten(color, 0.3));
grad.addColorStop(0.6, color);
grad.addColorStop(1, darken(color, 0.2));
ctx.fillStyle = grad;
ctx.beginPath();
switch(shape) {
case 'circle':
ctx.arc(cx, cy, r * 0.85, 0, Math.PI * 2);
break;
case 'square':
ctx.roundRect(cx - r * 0.75, cy - r * 0.75, r * 1.5, r * 1.5, 8);
break;
case 'diamond':
ctx.moveTo(cx, cy - r * 0.9);
ctx.lineTo(cx + r * 0.8, cy);
ctx.lineTo(cx, cy + r * 0.9);
ctx.lineTo(cx - r * 0.8, cy);
ctx.closePath();
break;
case 'triangle':
ctx.moveTo(cx, cy - r * 0.85);
ctx.lineTo(cx + r * 0.8, cy + r * 0.65);
ctx.lineTo(cx - r * 0.8, cy + r * 0.65);
ctx.closePath();
break;
case 'star':
for (var i = 0; i < 5; i++) {
var a1 = -Math.PI / 2 + i * Math.PI * 2 / 5;
var a2 = a1 + Math.PI / 5;
ctx.lineTo(cx + Math.cos(a1) * r * 0.9, cy + Math.sin(a1) * r * 0.9);
ctx.lineTo(cx + Math.cos(a2) * r * 0.4, cy + Math.sin(a2) * r * 0.4);
}
ctx.closePath();
break;
case 'hexagon':
for (var j = 0; j < 6; j++) {
var a = j * Math.PI / 3;
if (j === 0) ctx.moveTo(cx + Math.cos(a) * r * 0.85, cy + Math.sin(a) * r * 0.85);
else ctx.lineTo(cx + Math.cos(a) * r * 0.85, cy + Math.sin(a) * r * 0.85);
}
ctx.closePath();
break;
}
ctx.fill();
ctx.shadowBlur = 0;
// 高光
ctx.fillStyle = 'rgba(255,255,255,0.35)';
ctx.beginPath();
ctx.ellipse(cx - r * 0.3, cy - r * 0.35, r * 0.25, r * 0.12, -0.5, 0, Math.PI * 2);
ctx.fill();
}
function lighten(hex, amt) {
var r = parseInt(hex.substr(1,2), 16);
var g = parseInt(hex.substr(3,2), 16);
var b = parseInt(hex.substr(5,2), 16);
r = Math.min(255, r + (255 - r) * amt);
g = Math.min(255, g + (255 - g) * amt);
b = Math.min(255, b + (255 - b) * amt);
return 'rgb(' + Math.round(r) + ',' + Math.round(g) + ',' + Math.round(b) + ')';
}
function darken(hex, amt) {
var r = parseInt(hex.substr(1,2), 16);
var g = parseInt(hex.substr(3,2), 16);
var b = parseInt(hex.substr(5,2), 16);
r = Math.round(r * (1 - amt));
g = Math.round(g * (1 - amt));
b = Math.round(b * (1 - amt));
return 'rgb(' + r + ',' + g + ',' + b + ')';
}
// roundRect polyfill
if (!CanvasRenderingContext2D.prototype.roundRect) {
CanvasRenderingContext2D.prototype.roundRect = function(x, y, w, h, r) {
this.beginPath();
this.moveTo(x + r, y);
this.lineTo(x + w - r, y);
this.quadraticCurveTo(x + w, y, x + w, y + r);
this.lineTo(x + w, y + h - r);
this.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
this.lineTo(x + r, y + h);
this.quadraticCurveTo(x, y + h, x, y + h - r);
this.lineTo(x, y + r);
this.quadraticCurveTo(x, y, x + r, y);
this.closePath();
};
}
// ============ 输入 ============
canvas.addEventListener('click', function(e) {
var rect = canvas.getBoundingClientRect();
var px = (e.clientX - rect.left) * (canvas.width / rect.width);
var py = (e.clientY - rect.top) * (canvas.height / rect.height);
handleClick(px, py);
});
// 渲染循环
function loop() {
if (particles.length > 0 || floatTexts.length > 0) {
draw();
}
requestAnimationFrame(loop);
}
// 初始画面
draw();
loop();
</script>
</body>
</html>
更多推荐


所有评论(0)