碰撞检测仅适用于最后放置的棋子

问题描述 投票:0回答:1

我一直在制作一个简单的俄罗斯方块游戏来提高我的java技能,这里有两个类:

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;

    }
}
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());
    }
}

我也有一个框架类,但只有几行,例如frame.pack()和frame.add(panel)... 我希望您不要评论我的代码的效率,因为我正在尝试通过自己的生活和解决来解决每个问题。但如果您对我应该如何更改代码有任何批评性和建设性的意见,我不会说不。

由于某种原因,我的碰撞检测仅适用于最后放置的棋子,而不是所有棋盘棋子。我尝试使用 ArrayList 类的 .toArray() 方法,以防数组列表可能出现问题,但这不起作用。

java collision-detection
1个回答
0
投票

这基本上应该是一条评论,但是有点长。 在您的

detectCollision()
方法中,您迭代棋盘列表,然后返回该测试的最后一个值。 换句话说,您会覆盖每个循环的碰撞检测值,因此您只能获得列表中的最后一个值。

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

}

通过立即返回碰撞来修复此问题:

            if( pixel.intersects(boardPiece) ) return true;

或者通过累积该值,这样它就不会被覆盖。

            collision |= pixel.intersects(boardPiece);
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.