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

Java俄罗斯方块游戏仅最后放置方块触发碰撞检测问题求助

简易俄罗斯方块Java实现问题

我正在制作一款简易俄罗斯方块游戏以提升Java技能,核心代码包含Piece与GamePanel类如下,此外还有一个仅包含frame.pack()、frame.add(panel)等少量代码的Frame类。希望不要评论代码效率,但欢迎关键且具建设性的修改意见。

Piece类代码

import java.awt.*;
import java.util.ArrayList;

public class Piece{
    int posX;
    int posY;

    boolean controllable;

    Rectangle pixel;
    Rectangle leftBorder = new Rectangle(0,0,20, 400);
    Rectangle rightBorder = new Rectangle(180, 0, 20,400);
    Rectangle bottomBorder = new Rectangle(0, 300, 200, 20);

    ArrayList<Rectangle> boardPieces = new ArrayList<>();

    //constructor
    public Piece(){
        spawnNew();
    }

    public int getPosX(){
        return pixel.x;
    }

    public int getPosY(){
        return pixel.y;
    }

    public void createPixel(){
        pixel = new Rectangle(posX*20, posY*20, 20, 20);
    }

    public void drawPixel(Graphics g, Rectangle r){
        Graphics2D g2D = (Graphics2D) g;
        g2D.fill(r);
    }

    public void spawnNew(){
        if (pixel != null){
            boardPieces.add(new Rectangle(getPosX(), getPosY(), 20, 20));
        }

        controllable = true;
        posX = 3;
        posY = 0;
        createPixel();
    }

    public void move(char c, String s){
        if(controllable){
            switch (c){
                //go in x direction
                case 'x':
                    if(s.equals("+")){//right
                        posX ++;
                        createPixel();
                        if(detectCollision(rightBorder) || detectCollision()){
                            posX --;
                            createPixel();
                        }
                    }else{//left
                        posX --;
                        createPixel();
                        if(detectCollision(leftBorder) || detectCollision()){
                            posX ++;
                            createPixel();
                        }
                    }
                    break;
                //go in y direction
                case 'y':
                    if(s.equals("+")){//down
                        posY ++;
                        createPixel();
                        if(detectCollision(bottomBorder) || detectCollision()){
                            posY--;
                            controllable = false;
                            createPixel();
                        }
                    }else{//up
                        posY --;
                        createPixel();
                    }
                    break;
            }
        }
    }

    public boolean detectCollision(Rectangle r){
        return pixel.intersects(r);
    }

    public boolean detectCollision(){
        boolean collision = false;
        for (Rectangle boardPiece : boardPieces) {
            if (boardPiece != null) {
                collision = pixel.intersects(boardPiece);
            }
        }
        System.out.println(boardPieces.toString());
        return collision;

    }
}

GamePanel类代码

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class GamePanel extends JPanel implements KeyListener{
    Piece piece;

    //constructor
    public GamePanel() {
        piece = new Piece();
        //set panel attributes
        this.setPreferredSize(new Dimension(200, 400));
        this.addKeyListener(this);
        this.setFocusable(true);
        this.requestFocusInWindow();

        //create timer
        Timer fallTimer = new Timer(500, _ -> {
            piece.move('y', "+");
            if(!piece.controllable){
                piece.createPixel();
                piece.spawnNew();
            }
            repaint();
        });
        fallTimer.start();
    }

    @Override
    public void paintComponent(Graphics g){
        //clear background
        super.paintComponent(g);


        g.setColor(Color.black);
        piece.drawPixel(g, piece.pixel);

        g.setColor(Color.green);
        for (Rectangle i: piece.boardPieces){
            if (i != null) {
                piece.drawPixel(g, i);
            }
        }

        g.setColor(Color.red);
        piece.drawPixel(g, piece.bottomBorder);
        piece.drawPixel(g, piece.leftBorder);
        piece.drawPixel(g, piece.rightBorder);
    }

    //empty
    @Override
    public void keyTyped(KeyEvent e) {}

    @Override
    public void keyPressed(KeyEvent e) {
        switch (e.getKeyCode()){
            //"a"
            case 65:
                piece.move('x', "-");
                repaint();
                break;
            //"d"
            case 68:
                piece.move('x', "+");
                repaint();
                break;
            //"s"
            case 83:
                piece.move('y', "+");
                if(!piece.controllable){
                    piece.spawnNew();
                }
                repaint();
                break;
            //"space"
            case 32:
                while(piece.controllable){
                    piece.move('y', "+");
                }
                repaint();
                if(!piece.controllable){
                    piece.spawnNew();
                }
                repaint();
                break;
        }

    }

    //get key codes
    @Override
    public void keyReleased(KeyEvent e) {
        this.requestFocusInWindow();
        System.out.printf("%c: %d\n", e.getKeyChar(), e.getKeyCode());
    }
}

遇到的问题

碰撞检测仅对最后放置的方块生效,无法检测当前可控方块与boardPieces中所有已放置方块的碰撞。我尝试过使用ArrayList的toArray方法,但未能解决问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 18:40:54