693 lines
27 KiB
HTML
693 lines
27 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
|
<title>🧩 Blocky Blast | 方块消除</title>
|
|
<script src="https://game-cdn.poki.com/scripts/v2/poki-sdk.js"></script>
|
|
<script src="https://code.playcanvas.com/playcanvas-stable.min.js"></script>
|
|
<style>
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
html, body {
|
|
width: 100%;
|
|
height: 100%;
|
|
overflow: hidden;
|
|
background: #0a0a1a;
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
touch-action: none;
|
|
}
|
|
#game-container {
|
|
width: 100%;
|
|
height: 100%;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
canvas {
|
|
display: block;
|
|
box-shadow: 0 0 40px rgba(0, 100, 255, 0.3);
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="game-container">
|
|
<canvas id="application"></canvas>
|
|
</div>
|
|
|
|
<script>
|
|
// ============================================
|
|
// Poki SDK 管理器
|
|
// ============================================
|
|
class PokiManager {
|
|
constructor() {
|
|
this.initialized = false;
|
|
}
|
|
|
|
async init() {
|
|
try {
|
|
await PokiSDK.init();
|
|
console.log('✅ Poki SDK 初始化成功');
|
|
this.initialized = true;
|
|
PokiSDK.gameLoadingFinished();
|
|
|
|
window.addEventListener('keydown', (e) => {
|
|
if (['ArrowDown', 'ArrowUp', ' '].includes(e.key)) e.preventDefault();
|
|
});
|
|
window.addEventListener('wheel', (e) => e.preventDefault(), { passive: false });
|
|
} catch (err) {
|
|
console.warn('⚠️ Poki SDK 初始化失败:', err);
|
|
}
|
|
}
|
|
|
|
gameplayStart() {
|
|
if (this.initialized) PokiSDK.gameplayStart();
|
|
}
|
|
|
|
gameplayStop() {
|
|
if (this.initialized) PokiSDK.gameplayStop();
|
|
}
|
|
|
|
async showAd() {
|
|
if (!this.initialized) return;
|
|
try {
|
|
await PokiSDK.commercialBreak();
|
|
} catch (err) {}
|
|
}
|
|
}
|
|
|
|
// ============================================
|
|
// Blocky Blast - PlayCanvas版本
|
|
// ============================================
|
|
class BlockyBlastGame {
|
|
constructor() {
|
|
this.width = 480;
|
|
this.height = 640;
|
|
|
|
this.canvas = document.getElementById('application');
|
|
this.app = new pc.Application(this.canvas, {
|
|
mouse: new pc.Mouse(this.canvas),
|
|
touch: new pc.TouchDevice(this.canvas),
|
|
elementInput: new pc.ElementInput(this.canvas)
|
|
});
|
|
|
|
this.app.start();
|
|
this.app.setCanvasFillMode(pc.FILLMODE_NONE);
|
|
this.resize();
|
|
window.addEventListener('resize', () => this.resize());
|
|
|
|
this.poki = new PokiManager();
|
|
|
|
// 游戏配置
|
|
this.GRID_SIZE = 8;
|
|
this.CELL_SIZE = 48;
|
|
this.COLORS = [
|
|
new pc.Color(1, 0.42, 0.42), // 红
|
|
new pc.Color(0.31, 0.8, 0.77), // 青
|
|
new pc.Color(0.27, 0.72, 0.82), // 蓝
|
|
new pc.Color(0.59, 0.81, 0.71), // 绿
|
|
new pc.Color(1, 0.92, 0.65), // 黄
|
|
];
|
|
|
|
// 游戏状态
|
|
this.grid = [];
|
|
this.score = 0;
|
|
this.combo = 0;
|
|
this.gameState = 'loading';
|
|
this.dragging = false;
|
|
this.selectedPiece = null;
|
|
this.pieces = [];
|
|
|
|
this.init();
|
|
}
|
|
|
|
resize() {
|
|
const container = document.getElementById('game-container');
|
|
const aspect = this.width / this.height;
|
|
const containerAspect = container.clientWidth / container.clientHeight;
|
|
|
|
let canvasWidth, canvasHeight;
|
|
if (containerAspect > aspect) {
|
|
canvasHeight = container.clientHeight;
|
|
canvasWidth = canvasHeight * aspect;
|
|
} else {
|
|
canvasWidth = container.clientWidth;
|
|
canvasHeight = canvasWidth / aspect;
|
|
}
|
|
|
|
this.canvas.style.width = canvasWidth + 'px';
|
|
this.canvas.style.height = canvasHeight + 'px';
|
|
this.app.resizeCanvas(canvasWidth, canvasHeight);
|
|
}
|
|
|
|
async init() {
|
|
this.createScene();
|
|
this.createMaterials();
|
|
await this.poki.init();
|
|
this.initGrid();
|
|
this.spawnPieces();
|
|
this.createUI();
|
|
this.setupInput();
|
|
this.startGame();
|
|
this.app.on('update', (dt) => this.update(dt));
|
|
}
|
|
|
|
createScene() {
|
|
this.camera = new pc.Entity('camera');
|
|
this.camera.addComponent('camera', {
|
|
clearColor: new pc.Color(0.04, 0.04, 0.1),
|
|
projection: pc.PROJECTION_ORTHOGRAPHIC,
|
|
orthoHeight: this.height / 2
|
|
});
|
|
this.camera.setPosition(0, 0, 10);
|
|
this.app.root.addChild(this.camera);
|
|
|
|
const light = new pc.Entity('light');
|
|
light.addComponent('light', {
|
|
type: 'directional',
|
|
color: new pc.Color(1, 1, 1),
|
|
intensity: 1
|
|
});
|
|
light.setEulerAngles(45, 30, 0);
|
|
this.app.root.addChild(light);
|
|
|
|
this.gameRoot = new pc.Entity('gameRoot');
|
|
this.app.root.addChild(this.gameRoot);
|
|
|
|
this.uiRoot = new pc.Entity('uiRoot');
|
|
this.app.root.addChild(this.uiRoot);
|
|
|
|
// 游戏板背景
|
|
const boardSize = this.GRID_SIZE * this.CELL_SIZE;
|
|
const board = new pc.Entity('board');
|
|
board.addComponent('render', { type: 'plane' });
|
|
board.setLocalScale(boardSize + 10, 1, boardSize + 10);
|
|
board.setPosition(0, 0, -1);
|
|
|
|
const boardMat = new pc.StandardMaterial();
|
|
boardMat.diffuse = new pc.Color(0.08, 0.1, 0.15);
|
|
boardMat.update();
|
|
board.render.material = boardMat;
|
|
this.gameRoot.addChild(board);
|
|
|
|
// 网格线
|
|
this.createGridLines();
|
|
}
|
|
|
|
createGridLines() {
|
|
const boardSize = this.GRID_SIZE * this.CELL_SIZE;
|
|
const halfSize = boardSize / 2;
|
|
const lineMat = new pc.StandardMaterial();
|
|
lineMat.diffuse = new pc.Color(0.2, 0.25, 0.35);
|
|
lineMat.update();
|
|
|
|
for (let i = 0; i <= this.GRID_SIZE; i++) {
|
|
const pos = -halfSize + i * this.CELL_SIZE;
|
|
|
|
// 横线
|
|
const hLine = new pc.Entity('hline');
|
|
hLine.addComponent('render', { type: 'box' });
|
|
hLine.setLocalScale(boardSize, 1, 1);
|
|
hLine.setPosition(0, pos, -0.5);
|
|
hLine.render.material = lineMat;
|
|
this.gameRoot.addChild(hLine);
|
|
|
|
// 竖线
|
|
const vLine = new pc.Entity('vline');
|
|
vLine.addComponent('render', { type: 'box' });
|
|
vLine.setLocalScale(1, boardSize, 1);
|
|
vLine.setPosition(pos, 0, -0.5);
|
|
vLine.render.material = lineMat;
|
|
this.gameRoot.addChild(vLine);
|
|
}
|
|
}
|
|
|
|
createMaterials() {
|
|
this.materials = [];
|
|
for (const color of this.COLORS) {
|
|
const mat = new pc.StandardMaterial();
|
|
mat.diffuse = color;
|
|
mat.shininess = 60;
|
|
mat.update();
|
|
this.materials.push(mat);
|
|
}
|
|
|
|
this.highlightMat = new pc.StandardMaterial();
|
|
this.highlightMat.diffuse = new pc.Color(1, 1, 1);
|
|
this.highlightMat.emissive = new pc.Color(0.3, 0.3, 0.3);
|
|
this.highlightMat.opacity = 0.3;
|
|
this.highlightMat.blendType = pc.BLEND_NORMAL;
|
|
this.highlightMat.update();
|
|
}
|
|
|
|
initGrid() {
|
|
this.grid = [];
|
|
for (let y = 0; y < this.GRID_SIZE; y++) {
|
|
this.grid[y] = [];
|
|
for (let x = 0; x < this.GRID_SIZE; x++) {
|
|
this.grid[y][x] = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
spawnPieces() {
|
|
// 清理旧方块
|
|
for (const piece of this.pieces) {
|
|
piece.entity.destroy();
|
|
}
|
|
this.pieces = [];
|
|
this.initGrid();
|
|
|
|
// 生成3个随机方块
|
|
const shapes = this.getShapes();
|
|
for (let i = 0; i < 3; i++) {
|
|
this.createPiece(shapes[i], i);
|
|
}
|
|
}
|
|
|
|
getShapes() {
|
|
const shapes = [
|
|
// 单格
|
|
[[1]],
|
|
// 双格
|
|
[[1, 1]],
|
|
// 三格直线
|
|
[[1, 1, 1]],
|
|
// 三格L形
|
|
[[1, 0], [1, 1]],
|
|
// 四格直线
|
|
[[1, 1, 1, 1]],
|
|
// 四格方块
|
|
[[1, 1], [1, 1]],
|
|
// 四格T形
|
|
[[1, 1, 1], [0, 1, 0]],
|
|
// 四格Z形
|
|
[[1, 1, 0], [0, 1, 1]],
|
|
// 五格十字
|
|
[[0, 1, 0], [1, 1, 1], [0, 1, 0]],
|
|
];
|
|
|
|
// 随机打乱并取前3个
|
|
return shapes.sort(() => Math.random() - 0.5).slice(0, 3);
|
|
}
|
|
|
|
createPiece(shape, index) {
|
|
const pieceGroup = new pc.Entity('piece' + index);
|
|
const cells = [];
|
|
|
|
const colorIdx = Math.floor(Math.random() * this.COLORS.length);
|
|
|
|
for (let y = 0; y < shape.length; y++) {
|
|
for (let x = 0; x < shape[y].length; x++) {
|
|
if (shape[y][x]) {
|
|
const cell = new pc.Entity('cell');
|
|
cell.addComponent('render', { type: 'box' });
|
|
cell.setLocalScale(this.CELL_SIZE - 4, this.CELL_SIZE - 4, 10);
|
|
cell.setPosition(
|
|
(x - shape[0].length / 2) * this.CELL_SIZE,
|
|
-(y - shape.length / 2) * this.CELL_SIZE,
|
|
0
|
|
);
|
|
cell.render.material = this.materials[colorIdx];
|
|
pieceGroup.addChild(cell);
|
|
cells.push({ x, y, entity: cell });
|
|
}
|
|
}
|
|
}
|
|
|
|
// 初始位置(底部候选区)
|
|
const startX = -160 + index * 160;
|
|
const startY = -this.height / 2 + 80;
|
|
pieceGroup.setPosition(startX, startY, 5);
|
|
|
|
this.uiRoot.addChild(pieceGroup);
|
|
|
|
this.pieces.push({
|
|
entity: pieceGroup,
|
|
shape: shape,
|
|
colorIdx: colorIdx,
|
|
cells: cells,
|
|
index: index,
|
|
originalPos: new pc.Vec3(startX, startY, 5)
|
|
});
|
|
}
|
|
|
|
createUI() {
|
|
// 分数
|
|
this.scoreText = this.createText(`💎 得分: 0`, 0, this.height/2 - 40, 28);
|
|
this.uiRoot.addChild(this.scoreText);
|
|
|
|
// 连击
|
|
this.comboText = this.createText('', 0, this.height/2 - 80, 20);
|
|
this.uiRoot.addChild(this.comboText);
|
|
}
|
|
|
|
createText(text, x, y, fontSize) {
|
|
const entity = new pc.Entity('text');
|
|
entity.setPosition(x, y, 10);
|
|
entity.addComponent('element', {
|
|
type: 'text',
|
|
text: text,
|
|
fontSize: fontSize,
|
|
color: new pc.Color(1, 1, 1),
|
|
anchor: new pc.Vec4(0.5, 0.5, 0.5, 0.5),
|
|
pivot: new pc.Vec2(0.5, 0.5)
|
|
});
|
|
return entity;
|
|
}
|
|
|
|
setupInput() {
|
|
this.app.mouse.on(pc.EVENT_MOUSEDOWN, (e) => this.onInputStart(e.x, e.y));
|
|
this.app.mouse.on(pc.EVENT_MOUSEMOVE, (e) => this.onInputMove(e.x, e.y));
|
|
this.app.mouse.on(pc.EVENT_MOUSEUP, () => this.onInputEnd());
|
|
|
|
this.app.touch.on(pc.EVENT_TOUCHSTART, (e) => {
|
|
const touch = e.touches[0];
|
|
this.onInputStart(touch.x, touch.y);
|
|
});
|
|
this.app.touch.on(pc.EVENT_TOUCHMOVE, (e) => {
|
|
const touch = e.touches[0];
|
|
this.onInputMove(touch.x, touch.y);
|
|
});
|
|
this.app.touch.on(pc.EVENT_TOUCHEND, () => this.onInputEnd());
|
|
}
|
|
|
|
onInputStart(screenX, screenY) {
|
|
if (this.gameState !== 'playing') return;
|
|
|
|
const worldPos = this.screenToWorld(screenX, screenY);
|
|
|
|
// 检查是否点击了某个方块
|
|
for (const piece of this.pieces) {
|
|
const pos = piece.entity.getPosition();
|
|
const dx = worldPos.x - pos.x;
|
|
const dy = worldPos.y - pos.y;
|
|
|
|
if (Math.abs(dx) < 60 && Math.abs(dy) < 60) {
|
|
this.dragging = true;
|
|
this.selectedPiece = piece;
|
|
piece.entity.setPosition(worldPos.x, worldPos.y, 10);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
onInputMove(screenX, screenY) {
|
|
if (!this.dragging || !this.selectedPiece) return;
|
|
|
|
const worldPos = this.screenToWorld(screenX, screenY);
|
|
this.selectedPiece.entity.setPosition(worldPos.x, worldPos.y, 10);
|
|
}
|
|
|
|
onInputEnd() {
|
|
if (!this.dragging || !this.selectedPiece) return;
|
|
|
|
const pos = this.selectedPiece.entity.getPosition();
|
|
|
|
// 检查是否可以放置到网格
|
|
const gridPos = this.worldToGrid(pos.x, pos.y);
|
|
|
|
if (this.canPlace(this.selectedPiece, gridPos.x, gridPos.y)) {
|
|
this.placePiece(this.selectedPiece, gridPos.x, gridPos.y);
|
|
} else {
|
|
// 返回原位置
|
|
this.selectedPiece.entity.setPosition(this.selectedPiece.originalPos);
|
|
this.selectedPiece.entity.setLocalEulerAngles(0, 0, 0);
|
|
}
|
|
|
|
this.dragging = false;
|
|
this.selectedPiece = null;
|
|
}
|
|
|
|
screenToWorld(screenX, screenY) {
|
|
const rect = this.canvas.getBoundingClientRect();
|
|
const x = (screenX - rect.left) / rect.width * this.width - this.width / 2;
|
|
const y = this.height / 2 - (screenY - rect.top) / rect.height * this.height;
|
|
return { x, y };
|
|
}
|
|
|
|
worldToGrid(worldX, worldY) {
|
|
const boardSize = this.GRID_SIZE * this.CELL_SIZE;
|
|
const halfSize = boardSize / 2;
|
|
|
|
const x = Math.floor((worldX + halfSize) / this.CELL_SIZE);
|
|
const y = Math.floor((halfSize - worldY) / this.CELL_SIZE);
|
|
|
|
return { x, y };
|
|
}
|
|
|
|
canPlace(piece, gridX, gridY) {
|
|
const shape = piece.shape;
|
|
|
|
for (let y = 0; y < shape.length; y++) {
|
|
for (let x = 0; x < shape[y].length; x++) {
|
|
if (shape[y][x]) {
|
|
const targetX = gridX + x;
|
|
const targetY = gridY + y;
|
|
|
|
if (targetX < 0 || targetX >= this.GRID_SIZE ||
|
|
targetY < 0 || targetY >= this.GRID_SIZE ||
|
|
this.grid[targetY][targetX] !== null) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
placePiece(piece, gridX, gridY) {
|
|
const shape = piece.shape;
|
|
const boardSize = this.GRID_SIZE * this.CELL_SIZE;
|
|
const halfSize = boardSize / 2;
|
|
|
|
// 放置到网格
|
|
for (let y = 0; y < shape.length; y++) {
|
|
for (let x = 0; x < shape[y].length; x++) {
|
|
if (shape[y][x]) {
|
|
const targetX = gridX + x;
|
|
const targetY = gridY + y;
|
|
|
|
this.grid[targetY][targetX] = piece.colorIdx;
|
|
|
|
// 创建静态方块
|
|
const cell = new pc.Entity('placed');
|
|
cell.addComponent('render', { type: 'box' });
|
|
cell.setLocalScale(this.CELL_SIZE - 4, this.CELL_SIZE - 4, 10);
|
|
cell.setPosition(
|
|
-halfSize + targetX * this.CELL_SIZE + this.CELL_SIZE / 2,
|
|
halfSize - targetY * this.CELL_SIZE - this.CELL_SIZE / 2,
|
|
0
|
|
);
|
|
cell.render.material = this.materials[piece.colorIdx];
|
|
this.gameRoot.addChild(cell);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 移除拖动的方块
|
|
piece.entity.destroy();
|
|
this.pieces = this.pieces.filter(p => p !== piece);
|
|
|
|
// 计分
|
|
const cellCount = shape.flat().filter(c => c).length;
|
|
this.score += cellCount * 10;
|
|
|
|
// 检查消除
|
|
this.checkLines();
|
|
|
|
// 检查是否还有可放置的位置
|
|
if (this.pieces.length === 0) {
|
|
this.spawnPieces();
|
|
} else if (!this.hasValidMoves()) {
|
|
this.gameOver();
|
|
}
|
|
|
|
this.updateUI();
|
|
}
|
|
|
|
checkLines() {
|
|
const linesToClear = [];
|
|
|
|
// 检查行
|
|
for (let y = 0; y < this.GRID_SIZE; y++) {
|
|
if (this.grid[y].every(cell => cell !== null)) {
|
|
linesToClear.push({ type: 'row', index: y });
|
|
}
|
|
}
|
|
|
|
// 检查列
|
|
for (let x = 0; x < this.GRID_SIZE; x++) {
|
|
if (this.grid.every(row => row[x] !== null)) {
|
|
linesToClear.push({ type: 'col', index: x });
|
|
}
|
|
}
|
|
|
|
// 执行消除
|
|
if (linesToClear.length > 0) {
|
|
this.combo++;
|
|
const baseScore = linesToClear.length * this.GRID_SIZE * 10;
|
|
const comboBonus = this.combo * 50;
|
|
this.score += baseScore + comboBonus;
|
|
|
|
// 清除行/列
|
|
for (const line of linesToClear) {
|
|
if (line.type === 'row') {
|
|
for (let x = 0; x < this.GRID_SIZE; x++) {
|
|
this.grid[line.index][x] = null;
|
|
}
|
|
} else {
|
|
for (let y = 0; y < this.GRID_SIZE; y++) {
|
|
this.grid[y][line.index] = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 重建网格显示
|
|
this.rebuildGrid();
|
|
|
|
// 显示连击
|
|
this.comboText.element.text = `🔥 ${this.combo}连击! +${comboBonus}`;
|
|
setTimeout(() => {
|
|
this.comboText.element.text = '';
|
|
}, 1500);
|
|
} else {
|
|
this.combo = 0;
|
|
}
|
|
}
|
|
|
|
rebuildGrid() {
|
|
// 清除所有已放置的方块实体
|
|
const placed = this.gameRoot.findByName('placed');
|
|
while (placed) {
|
|
placed.destroy();
|
|
}
|
|
|
|
// 根据grid重新创建
|
|
const boardSize = this.GRID_SIZE * this.CELL_SIZE;
|
|
const halfSize = boardSize / 2;
|
|
|
|
for (let y = 0; y < this.GRID_SIZE; y++) {
|
|
for (let x = 0; x < this.GRID_SIZE; x++) {
|
|
if (this.grid[y][x] !== null) {
|
|
const cell = new pc.Entity('placed');
|
|
cell.addComponent('render', { type: 'box' });
|
|
cell.setLocalScale(this.CELL_SIZE - 4, this.CELL_SIZE - 4, 10);
|
|
cell.setPosition(
|
|
-halfSize + x * this.CELL_SIZE + this.CELL_SIZE / 2,
|
|
halfSize - y * this.CELL_SIZE - this.CELL_SIZE / 2,
|
|
0
|
|
);
|
|
cell.render.material = this.materials[this.grid[y][x]];
|
|
this.gameRoot.addChild(cell);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
hasValidMoves() {
|
|
for (const piece of this.pieces) {
|
|
for (let y = 0; y < this.GRID_SIZE; y++) {
|
|
for (let x = 0; x < this.GRID_SIZE; x++) {
|
|
if (this.canPlace(piece, x, y)) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
gameOver() {
|
|
this.gameState = 'gameover';
|
|
this.poki.gameplayStop();
|
|
|
|
// 显示结束面板
|
|
this.showGameOverUI();
|
|
}
|
|
|
|
showGameOverUI() {
|
|
const panel = new pc.Entity('gameOverPanel');
|
|
panel.setPosition(0, 0, 20);
|
|
this.uiRoot.addChild(panel);
|
|
|
|
// 背景
|
|
const bg = new pc.Entity('bg');
|
|
bg.addComponent('render', { type: 'plane' });
|
|
bg.setLocalScale(300, 1, 250);
|
|
const bgMat = new pc.StandardMaterial();
|
|
bgMat.diffuse = new pc.Color(0.1, 0.12, 0.2);
|
|
bgMat.opacity = 0.95;
|
|
bgMat.blendType = pc.BLEND_NORMAL;
|
|
bgMat.update();
|
|
bg.render.material = bgMat;
|
|
panel.addChild(bg);
|
|
|
|
// 标题
|
|
const title = this.createText('游戏结束', 0, 60, 36);
|
|
panel.addChild(title);
|
|
|
|
// 分数
|
|
const score = this.createText(`最终得分: ${this.score}`, 0, 0, 24);
|
|
panel.addChild(score);
|
|
|
|
// 提示
|
|
const hint = this.createText('点击重新开始', 0, -60, 16);
|
|
hint.element.color = new pc.Color(0.7, 0.8, 1);
|
|
panel.addChild(hint);
|
|
|
|
this.gameOverPanel = panel;
|
|
|
|
// 点击重启
|
|
this.app.mouse.on(pc.EVENT_MOUSEDOWN, () => this.restart());
|
|
this.app.touch.on(pc.EVENT_TOUCHSTART, () => this.restart());
|
|
}
|
|
|
|
restart() {
|
|
if (this.gameOverPanel) {
|
|
this.gameOverPanel.destroy();
|
|
}
|
|
|
|
this.score = 0;
|
|
this.combo = 0;
|
|
this.grid = [];
|
|
this.initGrid();
|
|
this.rebuildGrid();
|
|
this.spawnPieces();
|
|
this.updateUI();
|
|
this.startGame();
|
|
}
|
|
|
|
updateUI() {
|
|
this.scoreText.element.text = `💎 得分: ${this.score}`;
|
|
}
|
|
|
|
startGame() {
|
|
this.gameState = 'playing';
|
|
this.poki.gameplayStart();
|
|
}
|
|
|
|
update(dt) {
|
|
// 方块浮动动画
|
|
const time = Date.now() * 0.002;
|
|
for (const piece of this.pieces) {
|
|
if (piece !== this.selectedPiece) {
|
|
const pos = piece.originalPos.clone();
|
|
pos.y += Math.sin(time + piece.index) * 3;
|
|
piece.entity.setPosition(pos);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
const game = new BlockyBlastGame();
|
|
</script>
|
|
<!-- 登录认证 -->
|
|
<script src="../auth.js?v=1"></script>
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
GAME_AUTH.init('blocky-blast', '方块拼图');
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|