用Trae自动生成的网页游戏(俄罗斯方块)AI自动生成的代码
·
文件名:game5.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, #0f0f1e, #1a1a3e);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
font-family: "Microsoft YaHei", sans-serif;
color: #fff;
user-select: none;
}
#wrapper {
display: flex;
gap: 20px;
align-items: flex-start;
}
h1 {
text-align: center;
font-size: 28px;
color: #00e5ff;
margin-bottom: 10px;
text-shadow: 0 0 20px rgba(0,229,255,0.4);
}
#game-container {
position: relative;
border-radius: 10px;
overflow: hidden;
box-shadow: 0 0 40px rgba(0,229,255,0.1), 0 20px 60px rgba(0,0,0,0.5);
}
canvas { display: block; background: #0a0a1a; }
#sidebar {
width: 140px;
display: flex;
flex-direction: column;
gap: 12px;
}
.panel {
background: rgba(255,255,255,0.05);
border: 1px solid rgba(0,229,255,0.2);
border-radius: 10px;
padding: 12px;
}
.panel h3 {
font-size: 13px;
color: #00e5ff;
margin-bottom: 8px;
text-transform: uppercase;
letter-spacing: 1px;
}
.panel .value {
font-size: 24px;
font-weight: bold;
color: #ffd700;
}
#next-canvas {
background: rgba(0,0,0,0.3);
border-radius: 6px;
}
#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: 36px; color: #00e5ff; margin-bottom: 12px; }
#overlay p { font-size: 18px; color: #ccc; margin-bottom: 20px; }
#overlay button {
padding: 12px 36px;
font-size: 18px;
font-weight: bold;
color: #0a0a1a;
background: linear-gradient(135deg, #00e5ff, #00b0ff);
border: none;
border-radius: 30px;
cursor: pointer;
box-shadow: 0 4px 15px rgba(0,229,255,0.4);
transition: transform 0.2s;
}
#overlay button:hover { transform: scale(1.08); }
#hint {
font-size: 12px;
color: rgba(255,255,255,0.4);
line-height: 1.8;
text-align: center;
}
</style>
</head>
<body>
<div>
<h1>俄罗斯方块</h1>
<div id="wrapper">
<div id="game-container">
<canvas id="game" width="300" height="600"></canvas>
<div id="overlay">
<h2 id="ov-title">俄罗斯方块</h2>
<p id="ov-text">消除整行获得分数</p>
<button onclick="startGame()">开始游戏</button>
</div>
</div>
<div id="sidebar">
<div class="panel">
<h3>分数</h3>
<div class="value" id="score">0</div>
</div>
<div class="panel">
<h3>最高</h3>
<div class="value" id="high">0</div>
</div>
<div class="panel">
<h3>等级</h3>
<div class="value" id="level">1</div>
</div>
<div class="panel">
<h3>行数</h3>
<div class="value" id="lines">0</div>
</div>
<div class="panel">
<h3>下一个</h3>
<canvas id="next-canvas" width="120" height="100"></canvas>
</div>
<div id="hint">
← → 移动<br>
↑ 旋转<br>
↓ 加速<br>
空格 直落<br>
P 暂停
</div>
</div>
</div>
</div>
<script>
var canvas = document.getElementById('game');
var ctx = canvas.getContext('2d');
var nextCanvas = document.getElementById('next-canvas');
var nextCtx = nextCanvas.getContext('2d');
var COLS = 10;
var ROWS = 20;
var CELL = 30;
// 7种方块定义
var SHAPES = {
I: { color: '#00e5ff', blocks: [[0,0,0,0],[1,1,1,1],[0,0,0,0],[0,0,0,0]] },
O: { color: '#ffd700', blocks: [[1,1],[1,1]] },
T: { color: '#ab47bc', blocks: [[0,1,0],[1,1,1],[0,0,0]] },
S: { color: '#4caf50', blocks: [[0,1,1],[1,1,0],[0,0,0]] },
Z: { color: '#ff5252', blocks: [[1,1,0],[0,1,1],[0,0,0]] },
J: { color: '#42a5f5', blocks: [[1,0,0],[1,1,1],[0,0,0]] },
L: { color: '#ff9800', blocks: [[0,0,1],[1,1,1],[0,0,0]] }
};
var KEYS = ['I','O','T','S','Z','J','L'];
var board, current, nextPiece;
var score, lines, level, highScore;
var dropTimer, dropInterval;
var state; // menu, playing, paused, gameover
var isPaused = false;
highScore = parseInt(localStorage.getItem('tetrisHigh') || '0');
document.getElementById('high').textContent = highScore;
function newBoard() {
var b = [];
for (var y = 0; y < ROWS; y++) {
b.push(new Array(COLS).fill(null));
}
return b;
}
function randomPiece() {
var key = KEYS[Math.floor(Math.random() * KEYS.length)];
var shape = SHAPES[key];
var blocks = shape.blocks.map(function(r) { return r.slice(); });
return {
type: key,
color: shape.color,
blocks: blocks,
x: Math.floor((COLS - blocks[0].length) / 2),
y: 0
};
}
function init() {
board = newBoard();
score = 0;
lines = 0;
level = 1;
dropInterval = 1000;
current = randomPiece();
nextPiece = randomPiece();
state = 'playing';
isPaused = false;
updateUI();
}
function startGame() {
hideOverlay();
init();
clearInterval(dropTimer);
dropTimer = setInterval(tick, 50);
}
function tick() {
if (state !== 'playing' || isPaused) {
draw();
return;
}
dropCounter += 50;
if (dropCounter >= dropInterval) {
dropCounter = 0;
moveDown();
}
draw();
}
var dropCounter = 0;
function moveDown() {
current.y++;
if (collides(current)) {
current.y--;
lockPiece();
return;
}
}
function collides(piece) {
for (var y = 0; y < piece.blocks.length; y++) {
for (var x = 0; x < piece.blocks[y].length; x++) {
if (piece.blocks[y][x]) {
var bx = piece.x + x;
var by = piece.y + y;
if (bx < 0 || bx >= COLS || by >= ROWS) return true;
if (by >= 0 && board[by][bx]) return true;
}
}
}
return false;
}
function lockPiece() {
for (var y = 0; y < current.blocks.length; y++) {
for (var x = 0; x < current.blocks[y].length; x++) {
if (current.blocks[y][x]) {
var by = current.y + y;
var bx = current.x + x;
if (by < 0) {
gameOver();
return;
}
board[by][bx] = current.color;
}
}
}
clearLines();
current = nextPiece;
nextPiece = randomPiece();
if (collides(current)) {
gameOver();
}
}
function clearLines() {
var cleared = 0;
for (var y = ROWS - 1; y >= 0; y--) {
var full = true;
for (var x = 0; x < COLS; x++) {
if (!board[y][x]) { full = false; break; }
}
if (full) {
board.splice(y, 1);
board.unshift(new Array(COLS).fill(null));
cleared++;
y++;
}
}
if (cleared > 0) {
var points = [0, 100, 300, 500, 800][cleared] * level;
score += points;
lines += cleared;
// 升级
var newLevel = Math.floor(lines / 10) + 1;
if (newLevel > level) {
level = newLevel;
dropInterval = Math.max(100, 1000 - (level - 1) * 80);
}
updateUI();
}
}
function rotate() {
var b = current.blocks;
var n = b.length;
var rotated = [];
for (var y = 0; y < n; y++) {
rotated.push([]);
for (var x = 0; x < n; x++) {
rotated[y][x] = b[n - 1 - x][y];
}
}
var oldBlocks = current.blocks;
current.blocks = rotated;
// 墙踢:尝试偏移
var kicks = [0, -1, 1, -2, 2];
for (var k = 0; k < kicks.length; k++) {
current.x += kicks[k];
if (!collides(current)) return;
current.x -= kicks[k];
}
current.blocks = oldBlocks; // 旋转失败
}
function move(dx) {
current.x += dx;
if (collides(current)) current.x -= dx;
}
function hardDrop() {
while (!collides(current)) {
current.y++;
}
current.y--;
score += 2;
lockPiece();
updateUI();
}
function gameOver() {
state = 'gameover';
clearInterval(dropTimer);
if (score > highScore) {
highScore = score;
localStorage.setItem('tetrisHigh', highScore);
}
showOverlay('游戏结束', '分数: ' + score, '重新开始');
}
function togglePause() {
if (state !== 'playing') return;
isPaused = !isPaused;
}
function updateUI() {
document.getElementById('score').textContent = score;
document.getElementById('lines').textContent = lines;
document.getElementById('level').textContent = level;
document.getElementById('high').textContent = highScore;
}
function showOverlay(title, text, btn) {
document.getElementById('ov-title').textContent = title;
document.getElementById('ov-text').textContent = text;
document.querySelector('#overlay button').textContent = btn;
document.getElementById('overlay').style.display = 'flex';
}
function hideOverlay() {
document.getElementById('overlay').style.display = 'none';
}
// ============ 渲染 ============
function draw() {
ctx.fillStyle = '#0a0a1a';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 网格
ctx.strokeStyle = 'rgba(255,255,255,0.03)';
ctx.lineWidth = 1;
for (var i = 0; i <= COLS; i++) {
ctx.beginPath();
ctx.moveTo(i * CELL, 0);
ctx.lineTo(i * CELL, canvas.height);
ctx.stroke();
}
for (var j = 0; j <= ROWS; j++) {
ctx.beginPath();
ctx.moveTo(0, j * CELL);
ctx.lineTo(canvas.width, j * CELL);
ctx.stroke();
}
// 已锁定方块
for (var y = 0; y < ROWS; y++) {
for (var x = 0; x < COLS; x++) {
if (board[y][x]) {
drawBlock(ctx, x * CELL, y * CELL, CELL, board[y][x]);
}
}
}
// 投影
if (current && state === 'playing' && !isPaused) {
var ghost = { blocks: current.blocks, x: current.x, y: current.y };
while (!collides(ghost)) ghost.y++;
ghost.y--;
for (var gy = 0; gy < ghost.blocks.length; gy++) {
for (var gx = 0; gx < ghost.blocks[gy].length; gx++) {
if (ghost.blocks[gy][gx]) {
drawGhost(x * CELL, gy, gx, ghost);
}
}
}
}
// 当前方块
if (current) {
for (var cy = 0; cy < current.blocks.length; cy++) {
for (var cx = 0; cx < current.blocks[cy].length; cx++) {
if (current.blocks[cy][cx]) {
drawBlock(ctx, (current.x + cx) * CELL, (current.y + cy) * CELL, CELL, current.color);
}
}
}
}
// 暂停
if (isPaused) {
ctx.fillStyle = 'rgba(0,0,0,0.6)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = '#00e5ff';
ctx.font = 'bold 28px "Microsoft YaHei"';
ctx.textAlign = 'center';
ctx.fillText('暂停', canvas.width / 2, canvas.height / 2);
}
// 画下一个
drawNext();
}
function drawGhost(cy_offset, gy, gx, ghost) {
var px = (ghost.x + gx) * CELL;
var py = (ghost.y + gy) * CELL;
ctx.strokeStyle = 'rgba(255,255,255,0.2)';
ctx.lineWidth = 1.5;
ctx.strokeRect(px + 2, py + 2, CELL - 4, CELL - 4);
}
function drawBlock(c, px, py, size, color) {
// 主体
var grad = c.createLinearGradient(px, py, px + size, py + size);
grad.addColorStop(0, lighten(color, 0.25));
grad.addColorStop(0.5, color);
grad.addColorStop(1, darken(color, 0.3));
c.fillStyle = grad;
c.fillRect(px + 1, py + 1, size - 2, size - 2);
// 高光
c.fillStyle = 'rgba(255,255,255,0.3)';
c.fillRect(px + 2, py + 2, size - 4, 3);
c.fillRect(px + 2, py + 2, 3, size - 4);
// 阴影
c.fillStyle = 'rgba(0,0,0,0.3)';
c.fillRect(px + 2, py + size - 5, size - 4, 3);
c.fillRect(px + size - 5, py + 2, 3, size - 4);
// 边框
c.strokeStyle = darken(color, 0.5);
c.lineWidth = 1;
c.strokeRect(px + 0.5, py + 0.5, size - 1, size - 1);
}
function drawNext() {
nextCtx.clearRect(0, 0, nextCanvas.width, nextCanvas.height);
if (!nextPiece) return;
var bs = nextPiece.blocks;
var size = 22;
var offX = (nextCanvas.width - bs[0].length * size) / 2;
var offY = (nextCanvas.height - bs.length * size) / 2;
for (var y = 0; y < bs.length; y++) {
for (var x = 0; x < bs[y].length; x++) {
if (bs[y][x]) {
drawBlock(nextCtx, offX + x * size, offY + y * size, size, nextPiece.color);
}
}
}
}
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);
return 'rgb(' + Math.round(r*(1-amt)) + ',' + Math.round(g*(1-amt)) + ',' + Math.round(b*(1-amt)) + ')';
}
// ============ 输入 ============
document.addEventListener('keydown', function(e) {
if (state !== 'playing') return;
if (isPaused && e.code !== 'KeyP') return;
switch(e.code) {
case 'ArrowLeft': case 'KeyA': e.preventDefault(); move(-1); break;
case 'ArrowRight': case 'KeyD': e.preventDefault(); move(1); break;
case 'ArrowDown': case 'KeyS': e.preventDefault(); moveDown(); score += 1; updateUI(); break;
case 'ArrowUp': case 'KeyW': e.preventDefault(); rotate(); break;
case 'Space': e.preventDefault(); hardDrop(); break;
case 'KeyP': e.preventDefault(); togglePause(); break;
}
draw();
});
// 初始画面
draw();
</script>
</body>
</html>
更多推荐



所有评论(0)