You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java实现俄罗斯方块:JLabel方块碰撞检测与停止移动问题

解决俄罗斯方块方块碰撞停止问题

别用颜色检测来判断碰撞,这种方式既不可靠又容易出bug——JLabel的渲染延迟、边框像素干扰都会让检测结果出错。直接通过坐标+已落地方块的位置记录来做碰撞检测才是正确的思路,具体实现步骤如下:


1. 维护落地方块的位置记录

创建一个二维数组(比如boolean[][] occupiedGrid),用来标记游戏区域内每个网格单元是否已经被落地的方块占据。假设每个方块尺寸固定为40x40,游戏区域是10列20行的网格,数组可定义为boolean[10][20]。

每当有方块停止下落时,就把该方块(包括piece和piece2)占据的网格位置在数组中标记为true。

2. 修改定时器的碰撞检测逻辑

在原有底部边界检测的基础上,加入“下一个位置是否存在障碍物”的判断:

  • 计算当前下落方块(piece和piece2)下落一格后的y坐标
  • 将像素坐标转换为网格坐标,检查对应occupiedGrid位置是否为true,或是否超出游戏区域底部
  • 若满足任一条件,立即停止定时器并执行后续逻辑

修改后的示例代码

// 类级别变量:网格记录、方块尺寸、游戏区域底部边界
private boolean[][] occupiedGrid = new boolean[10][20];
private static final int BLOCK_SIZE = 40;
private static final int GAME_AREA_BOTTOM = 825;

Runnable timer = new Runnable() {
    public void run() {
        boolean shouldStop = false;

        // 检测piece的碰撞
        int nextPieceY = piece.getY() + BLOCK_SIZE;
        int pieceGridRow = nextPieceY / BLOCK_SIZE;
        int pieceGridCol = (piece.getX() - 40) / BLOCK_SIZE; // 40为游戏区域左侧x偏移,需根据实际调整
        if (nextPieceY + piece.getHeight() >= GAME_AREA_BOTTOM 
            || (pieceGridRow < 20 && occupiedGrid[pieceGridCol][pieceGridRow])) {
            shouldStop = true;
        }

        // 检测piece2的碰撞(若存在)
        if (!shouldStop && piece2 != null) {
            int nextPiece2Y = piece2.getY() + BLOCK_SIZE;
            int piece2GridRow = nextPiece2Y / BLOCK_SIZE;
            int piece2GridCol = (piece2.getX() - 40) / BLOCK_SIZE;
            if (nextPiece2Y + piece2.getHeight() >= GAME_AREA_BOTTOM 
                || (piece2GridRow < 20 && occupiedGrid[piece2GridCol][piece2GridRow])) {
                shouldStop = true;
            }
        }

        if (shouldStop) {
            executor.shutdown();
            // 将当前方块标记到网格中
            markBlockToGrid(piece);
            if (piece2 != null) markBlockToGrid(piece2);
            block();
            time();
        } else {
            // 正常下落一格
            piece.setLocation(piece.getX(), piece.getY() + BLOCK_SIZE);
            if (piece2 != null) {
                piece2.setLocation(piece2.getX(), piece2.getY() + BLOCK_SIZE);
            }
        }
    }   
};

// 辅助方法:将方块位置标记到网格
private void markBlockToGrid(JLabel block) {
    int gridCol = (block.getX() - 40) / BLOCK_SIZE;
    int gridRow = block.getY() / BLOCK_SIZE;
    // 若方块是多格组成的形状,需遍历所有占据的网格单元
    if (gridCol >= 0 && gridCol < 10 && gridRow >= 0 && gridRow < 20) {
        occupiedGrid[gridCol][gridRow] = true;
    }
}

// 启动定时器
executor.scheduleAtFixedRate(timer, 2, 1, TimeUnit.SECONDS);

关键说明

  • 放弃颜色检测:颜色检测依赖像素采样,极易因JLabel布局偏移、渲染抗锯齿等问题误判,坐标+网格记录的方式逻辑清晰且稳定。
  • 网格坐标转换:需根据你的游戏界面布局,调整像素坐标到网格坐标的偏移量(比如示例中的左侧x偏移40)。
  • 多格形状适配:如果方块由多个JLabel组成(如I型、L型),需要遍历所有组成方块的位置,逐个检查下一个位置是否存在碰撞。

内容的提问来源于stack exchange,提问作者MildArachnophobe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 00:22:19