当前位置: 首页 > 知识库问答 >
问题:

Java二维平台多矩形碰撞检测

晋越彬
2023-03-14

我在一个2D平台上工作在Java为一个任务。赋值指定我必须使用抽象形状类来绘制形状。我遇到的问题是让我的碰撞检测与多个矩形对象一起工作,我使用这些对象作为平台--我将它们存储在一个列表中。目前,我的碰撞检测将移动我的玩家,不管我撞到了哪个平台,所以如果我从右边撞到了一个平台,它会把我移到那个平台的顶部,因为它仍然在检查我下面的另一个平台,并假设我撞到了那个平台,因此把我移到平台的顶部。我想知道如何改变这一点,以便我的碰撞检测也检测到我与哪个平台发生了碰撞,以及相对于该平台(而不是每个平台)发生了碰撞。

预期产出:

我的播放器在与平台碰撞时应该停在原地。

package A2;

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

public class App extends JFrame {

    public App() {
        final Player player = new Player(200, 100);

        final ArrayList<Rectangle> platforms = new ArrayList<>();

        platforms.add(new Rectangle(100, 500, 400 ,10));
        platforms.add(new Rectangle(500, 100, 10 ,400));




        JPanel mainPanel = new JPanel() {
            public void paintComponent(Graphics g) {
                super.paintComponent(g);
                player.draw(g);

                for(Rectangle r : platforms){
                    r.draw(g);
                }

            }
        };

        mainPanel.addKeyListener(new InputControl(this, player, platforms));
        mainPanel.setFocusable(true);
        add(mainPanel);

        setLayout(new GridLayout());
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setSize(600, 600);
    }

    public static void main(String[] args) {
        App app = new App();
        app.setVisible(true);
    }
}



abstract class Shape {
    public void draw(Graphics g) { }
}
package A2;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;

import static java.awt.event.KeyEvent.*;

public class InputControl implements ActionListener, KeyListener {
    App app;
    Player player;
    Timer time = new Timer(5, this);
    ArrayList<Rectangle> platforms;
    ArrayList<Integer> keyList = new ArrayList<>();

    boolean keyReleased = false;
    boolean keyPressed = false;
    boolean[] keyUp = new boolean[256];
    boolean[] keyDown = new boolean[256];

    boolean topCollision = false;
    boolean rightCollision = false;
    boolean leftCollision = false;
    boolean botCollision = false;
    boolean onGround = false;

    private static final double GRAVITY = 2;
    private static final int MAX_FALL_SPEED = 5;

    double Xoverlap = 0;
    double Yoverlap = 0;
    boolean collision = false;



    public InputControl(App app, Player player, ArrayList<Rectangle> platforms) {
        this.app = app;
        this.player = player;
        this.platforms = platforms;
        time.start();
    }

    public void gravity(){
        if(player.yVelocity > MAX_FALL_SPEED){
            player.yVelocity = MAX_FALL_SPEED;
        }
        player.yVelocity += GRAVITY;
    }

    public void momentum(){}


    public void actionPerformed(ActionEvent e) {

        Rectangle2D offset = player.getOffsetBounds();

        for(int i = 0; i < platforms.size(); i++) {
            Rectangle r = platforms.get(i);
            //If collision
            if (offset.intersects(r.obj.getBounds2D())) {
                //Collision on Y axis
                if (offset.getX() + offset.getWidth() > r.obj.getX() &&
                        offset.getX() < r.obj.getX() + r.obj.getWidth() &&
                        offset.getY() + offset.getHeight() > r.obj.getY() &&
                        offset.getY() + player.yVelocity < r.obj.getY() + r.obj.getHeight()) {
                    player.y -= (offset.getY() + offset.getHeight()) - r.obj.getY();
                }
                //Collision on X axis
                if (offset.getX() + offset.getWidth() + player.xVelocity > r.obj.getX() &&
                        offset.getX() + player.xVelocity < r.obj.getX() + r.obj.getWidth() &&
                        offset.getY() + offset.getHeight() > r.obj.getY() &&
                        offset.getY() < r.obj.getY() + r.obj.getHeight()) {
                    player.x -= (offset.getX() + offset.getHeight()) - r.obj.getX();

                }
            }
            else {
                player.x += player.xVelocity;
                player.y += player.yVelocity;
            }
        }


        player.x += player.xVelocity;
        player.y += player.yVelocity;

        app.repaint();
    }

    public void keyPressed(KeyEvent e) {
        if(e.getKeyCode() >= 0 && e.getKeyCode() < 256) {
            keyDown[e.getKeyCode()] = true;
            keyUp[e.getKeyCode()] = false;
            keyPressed = true;
            keyReleased = false;
        }
        if (keyDown[VK_UP]) {
            player.yVelocity = -1;

        }
        if (keyDown[VK_RIGHT]){
            player.xVelocity = 1;

        }
        if (keyDown[VK_LEFT]) {
            player.xVelocity = -1;

        }
        if (keyDown[VK_DOWN]) {
            player.yVelocity = 1;

        }
    }

    public void keyReleased(KeyEvent e) {
        if(e.getKeyCode() >= 0 && e.getKeyCode() < 256) {
            keyDown[e.getKeyCode()] = false;
            keyUp[e.getKeyCode()] = true;
            keyPressed = false;
            keyReleased = true;
        }
        if(keyUp[VK_RIGHT] || keyUp[VK_LEFT]){
            player.xVelocity = 0;
        }
        if(keyUp[VK_UP]){
            player.yVelocity = 0;
        }

    }
    public void keyTyped(KeyEvent e) { }



}
package A2;

import java.awt.*;
import java.awt.geom.Rectangle2D;

public class Player extends Shape {
    public double xVelocity;
    public double yVelocity;
    public double x;
    public double y;

    public double width = 60;
    public double height = 60;
    public double weight = 5;

    public  Rectangle2D obj;


    public Player(double x, double y) {
        this.x = x;
        this.y = y;
        obj = new Rectangle2D.Double(x, y, width, height);
    }

    public Rectangle2D getOffsetBounds(){
        return new Rectangle2D.Double( x, y, width, height);

    }

    public void draw(Graphics g) {
        Color c =new Color(1f,0f,0f,0.2f );
        obj = new Rectangle2D.Double(x, y, width, height);
        g.setColor(Color.BLACK);
        Graphics2D g2 = (Graphics2D)g;
        g2.fill(obj);
        g.drawString("(" + String.valueOf(x) + ", " + String.valueOf(y) + ")", 10, 20);
        g.drawString("X Speed: " + String.valueOf(xVelocity) + " Y Speed: " + String.valueOf(yVelocity) + ")", 10, 35);
        g.setColor(c);


    }
}
package A2;

import java.awt.*;
import java.awt.geom.Rectangle2D;

public class Rectangle extends Shape {
    public double width;
    public double height;
    public double x;
    public double y;
    boolean hasCollided = false;

    public Rectangle2D obj;

    public Rectangle(double x, double y, double width, double height) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
        obj = new Rectangle2D.Double(x, y, width, height);
    }

    public void draw(Graphics g) {
        g.setColor(Color.ORANGE);
        Graphics2D g2 = (Graphics2D)g;
        g2.fill(obj);

    }
}

共有1个答案

池阳伯
2023-03-14

首先,定义扩展Shape并提供绘图逻辑的ColorRectangle类:

// extends java.awt.Shape
abstract class ColorRectangle extends Rectangle {

    private static final long serialVersionUID = -3626687047605407698L;
    private final Color color;

    protected ColorRectangle(int x, int y, int width, int height, Color color) {
        super(x, y, width, height);
        this.color = color;
    }

    public void draw(Graphics2D g) {
        g.setColor(color);
        g.fillRect(x, y, width, height);
    }
}

其次,为表示播放器平台定义单独的类:

public final class Player extends ColorRectangle {

    private static final long serialVersionUID = -3909362955417024742L;

    public Player(int width, int height, Color color) {
        super(0, 0, width, height, color);
    }
}

public final class Platform extends ColorRectangle {

    private static final long serialVersionUID = 6602359551348037628L;

    public Platform(int x, int y, int width, int height, Color color) {
        super(x, y, width, height, color);
    }

    public boolean intersects(Player player, int offsX, int offsY) {
        return intersects(player.x + offsX, player.y + offsY, player.width, player.height);
    }
}

第三,定义包含演示应用程序逻辑的类。实际上,您可以拆分demo的逻辑和board的逻辑(包括actiona和key listeners),但是这些类非常简单,所以在给定的情况下,不需要拆分它。

public class CollisionDetectionDemo extends JFrame {

    public CollisionDetectionDemo() {
        setLayout(new GridLayout());
        add(new MainPanel());
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setSize(600, 600);
    }

    private static class MainPanel extends JPanel implements ActionListener, KeyListener {

        private static final long serialVersionUID = 8771401446680969350L;
        private static final int OFFS = 5;

        private final Player player = new Player(60, 60, Color.BLACK);
        private final List<Platform> platforms = Arrays.asList(
                new Platform(100, 500, 400, 10, Color.ORANGE),
                new Platform(500, 100, 10, 410, Color.RED),
                new Platform(150, 300, 100, 10, Color.BLUE),
                new Platform(150, 100, 100, 10, Color.GREEN));

        private MainPanel() {
            player.x = 200;
            player.y = 200;
            new Timer(5, this).start();

            setFocusable(true);
            addKeyListener(this);
        }

        private void drawPlayerPosition(Graphics g) {
            g.setColor(Color.BLACK);
            g.drawString(String.format("(%d, %d)", player.x, player.y), 10, 20);
        }

        private void movePlayer(int offsX, int offsY) {
            if (!intersects(player, offsX, offsY)) {
                player.x += offsX;
                player.y += offsY;
            }
        }

        private boolean intersects(Player player, int offsX, int offsY) {
            for (Platform platform : platforms)
                if (platform.intersects(player, offsX, offsY))
                    return true;

            return false;
        }

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

            Color color = g.getColor();
            drawPlayerPosition(g);
            player.draw((Graphics2D)g);
            platforms.forEach(platform -> platform.draw((Graphics2D)g));
            g.setColor(color);
        }

        @Override
        public void actionPerformed(ActionEvent event) {
            repaint();
        }

        @Override
        public void keyTyped(KeyEvent event) {
        }

        @Override
        public void keyPressed(KeyEvent event) {
            if (event.getKeyCode() == VK_UP)
                movePlayer(0, -OFFS);
            else if (event.getKeyCode() == VK_DOWN)
                movePlayer(0, OFFS);
            else if (event.getKeyCode() == VK_LEFT)
                movePlayer(-OFFS, 0);
            else if (event.getKeyCode() == VK_RIGHT)
                movePlayer(OFFS, 0);
        }

        @Override
        public void keyReleased(KeyEvent event) {
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new CollisionDetectionDemo().setVisible(true));
    }
}
 类似资料:
  • 问题内容: 我遇到一个问题,即一个矩形与另一个矩形发生碰撞。所以我的问题是,如何获取相交方法以检查碰撞?还是在这种情况下还有其他方法可以处理碰撞? 我正在创建一个回合制战斗游戏(类似于《最终幻想》或《龙骑传奇》),其中玩家的角色在屏幕的右侧,而敌人在屏幕的左侧。玩家和敌人轮流进攻。因此,当玩家攻击时,子画面动画会从右到左在屏幕上移动,直到停在敌人面前,进行攻击并返回到其起始坐标。玩家和敌人周围都有

  • 我遇到了一个问题,显示一个矩形与另一个矩形发生了碰撞。所以我的问题是,如何让Intersect方法检查碰撞?或者在这种情况下有其他方法来处理碰撞吗? 我正在制作一个回合制战斗游戏(类似于《最终幻想》或《龙骑兵传说》),其中玩家的角色位于屏幕的右侧,敌人位于屏幕左侧。玩家和敌人轮流攻击。因此,当玩家攻击时,精灵动画会在屏幕上从右向左移动,直到它停在敌人面前,攻击并返回到其起始坐标。玩家和敌人都有一个

  • 因此,我创建了一个方法来检测球形球和矩形球之间的碰撞。我把它分成了4部分;它检测圆的顶部、圆的左侧、圆的底部、圆的右侧和矩形之间的碰撞。其中的两个工作是检测圆上的左点和矩形之间的碰撞,以及检测圆上的右点和矩形之间的碰撞。但是,不起作用的是,如果最上面的点或最下面的点接触矩形,就不会检测到碰撞,正如我记录if语句以查看是否输入它时所看到的那样。下面是我的代码(方法。getr()获取圆圈半径): 我已

  • 所以我试图用pygame制作一个我们之间的游戏。我刚刚开始,所以我没有太多东西,现在正在制作地图。然而,我正在努力解决的一件事是碰撞逻辑。地图目前有一个细长的八边形形状,但是我想不管是什么形状,我都会使用类似pygame多边形的东西。当我运行我现在的代码时,它会检查我的玩家(pygame矩形)和墙壁(pygame多边形)之间的碰撞,它说: 我发现这是因为pygame多边形返回了一个矩形,但在碰撞检

  • 我正在编写一个游戏,涉及碰撞的一个移动的圆,由用户控制,和一个移动的矩形,由计算机控制。 完整的代码可以在这里找到:游戏 我在圆和矩形之间的碰撞检测方面遇到了麻烦。当矩形是静态的,碰撞检测工作完美。当圆和矩形的边缘在任一边接触时,程序就会按照它应该的方式进行操作。 这是碰撞检测功能。 谢谢。

  • 在我的自上而下游戏中,当我的玩家通过婴儿床时,我该如何让他发生碰撞?我用的是交叉矩形。 这是我的密码 更新方法 在渲染方法中 这是完整的代码 谁能告诉我矩形碰撞检测的正确实现是什么?没有重叠,我是这个框架的新手。致谢和预付款:)