簡體   English   中英

多個矩形的Java 2D Platformer碰撞檢測

[英]Java 2D Platformer Collision Detection for multiple Rectangles

我正在用Java開發2D平台程序進行作業。 作業指定我必須使用抽象形狀類來繪制形狀。 我遇到的問題是使碰撞檢測與作為平台使用的多個Rectangle Objects一起工作-我將它們存儲在列表中。 目前,無論我與哪個平台發生碰撞,碰撞檢測都將移動我的玩家,因此,如果我從右側與一個平台碰撞,它將使我移動到該平台的頂部,因為它仍在檢查我下面的另一個平台,並且會假設我已經達到目標,因此將我帶到平台的頂部。 我想知道如何更改此設置,以便碰撞檢測還可以檢測到與哪個平台發生碰撞並相對於該平台(相對於每個平台)發生碰撞的情況。

這是當前正在發生的事情: 在此處輸入圖片說明

預期產量:

與平台碰撞時,我的播放器應該停在原地。

我的應用程式類別:

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

    }
}

首先,定義ColorRectangle類,該類擴展Shape並提供繪圖邏輯:

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

其次,為表示PlayerPlatform定義單獨的類:

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

第三,定義包含演示應用程序邏輯的類。 實際上,您可以拆分用於演示的邏輯和用於開發板的邏輯(包括actiona和按鍵偵聽器),但是這些類非常簡單,因此在給定的情況下,無需拆分它。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM