根据球接触的网格改变球的行为(JAVA Swing)

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

我有一个框架,我用 Java Swing 的网格方法将其绘制为半黑半白。在这个帧上,有一个白球开始在黑色部分上移动,一个黑球开始在白色部分上移动。我希望这些球在接触与它们颜色相同的网格时反弹回来,并将它们接触的网格涂成相反的颜色。我已经完成了除了最后一个功能之外的所有内容,但我不知道如何在应用程序中实现最后一个功能。

接口.java

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

public class Interface extends JFrame{
    
    private int frameHeight = 637;
    private int frameWidth = 1214;
    
    public Interface() {

        setSize(frameWidth, frameHeight);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLayout(new BorderLayout());
        setTitle("Bouncing Ball");
        add(new Core());
        setVisible(true);

    }

    public static void main(String[] args){

        new Interface();

    }

}

核心.java

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

public class Core extends JPanel{
    
    int xw = 10, yw = 10, xb = 1000, yb = 400;
    int bounds = 20, gridSize = 20;
    int vxw = 5, vyw = 5, vxb = 5, vyb = 5;
    int rows, columns;

    public Core() {

        rows = getHeight() / gridSize;
        columns = getWidth() / gridSize;
        
        Timer timer = new Timer(10, new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                
                System.out.println(getHeight());
                System.out.println(getWidth());
                
                xw += vxw;
                yw += vyw;

                xb -= vxb;
                yb -= vyb;

                if (xw > getWidth() - bounds || xw < 0) {vxw = -vxw;}
                if (yw > getHeight() - bounds || yw < 0) {vyw = -vyw;}
                if (xb > getWidth() - bounds || xb < 0) {vxb = -vxb;}
                if (yb > getHeight() - bounds || yb < 0) {vyb = -vyb;}

                repaint();

            }
            
        });

        timer.start();

    }

    public void paintComponent(Graphics g) {

        Graphics2D g2dw = (Graphics2D) g;
        Graphics2D g2db = (Graphics2D) g;
        Graphics2D grid = (Graphics2D) g;
        
        super.paintComponent(g);    
            
            for (int k = 0; k < getWidth(); k += gridSize) {
                for (int z = 0; z < getHeight(); z += gridSize) {
                     
                    grid.drawRect(k, z, gridSize, gridSize);

                     if (k < getWidth() / 2) {
                        grid.setColor(Color.BLACK);
                        grid.fillRect(k, z, gridSize, gridSize);
                     } else {
                        grid.setColor(Color.WHITE);
                        grid.fillRect(k, z, gridSize, gridSize);

                     }
                }
            }
        

            g2dw.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2dw.setColor(Color.white);
            g2dw.fillOval(xw, yw, bounds, bounds);
            //g2d.dispose();

            g2db.setColor(Color.black);
            g2db.fillOval(xb, yb, bounds, bounds);

    }

    public static void main(String[] args){

        

    }

}

输出示例: https://github.com/vnglst/pong-wars

我正在尝试学习如何编写一个功能,使球在接触与它们颜色相同的网格时弹跳,并用相反的颜色绘制它们接触的网格。如果您不想编写 Java 代码,任何提示或指导也将不胜感激。

我尝试创建一个包含 1 或 0 个值的 2D 数组(1 表示白色网格,0 表示黑色),但遇到了 IndexBound 错误。

java swing awt
1个回答
0
投票

根据camickr的说明,有Java代码:

核心.java

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

class Core extends JPanel {

    //Adjusting the starting points of balls and other variables
    protected int xw = Interface.frameWidth / 2 - 40, yw = Interface.frameHeight / 2, xb = Interface.frameWidth / 2 + 40, yb = Interface.frameHeight / 2;
    private int bounds;
    private int rows, columns, tileSize;
    private ArrayList<ColoredShape> tiles;
    private ArrayList<Ball> balls;

    public Core(int rows, int columns, int tileSize) {
        
        this.rows = rows;
        this.columns = columns;
        this.tileSize = tileSize;
        this.bounds = tileSize / 2;
        this.tiles = new ArrayList<>();
        this.balls = new ArrayList<>();

        // Creating tiles
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < columns; j++) {
                
                int x = j * tileSize;
                int y = i * tileSize;
                Shape rect = new Rectangle(x, y, tileSize, tileSize);
                Color color = (j < columns / 2) ? Color.BLACK : Color.WHITE;
                tiles.add(new ColoredShape(rect, color));

            }
        }

        // Creating balls
        balls.add(new Ball(xw, yw, bounds, Color.WHITE, 10, 3));
        balls.add(new Ball(xb, yb, bounds, Color.BLACK, 10, -3));

        // Animation part
        Timer timer = new Timer(10, new ActionListener() {
            
            @Override
            public void actionPerformed(ActionEvent e) {
                
                moveBalls();
                checkCollision();
                repaint();
            }

        });

        timer.start();
    }

    //Moving balls
    private void moveBalls() {
        for (Ball ball : balls) {
            
            ball.setX(ball.getX() + ball.getVx());
            ball.setY(ball.getY() + ball.getVy());
    
            // Bouncing back from walls
            if (ball.getX() > getWidth() - ball.getShape().width || ball.getX() < 0) {
                ball.setVx(-ball.getVx());
            }
            if (ball.getY() > getHeight() - ball.getShape().height || ball.getY() < 0) {
                ball.setVy(-ball.getVy());
            }

        }
    }

    private void checkCollision() {
        
        for (Ball ball : balls) {
            
            for (ColoredShape tile : tiles) {
                
                if (ball.getShape().getBounds().intersects(tile.getShape().getBounds())) {
                    
                    if (ball.getColor().equals(tile.getColor())) {
                        
                        tile.setColor(ball.getColor().equals(Color.WHITE) ? Color.BLACK : Color.WHITE);
                        
                        // Calculating the angle of incidence
                        double tileCenterX = tile.getShape().getBounds2D().getCenterX();
                        double tileCenterY = tile.getShape().getBounds2D().getCenterY();
                        double ballCenterX = ball.getShape().getCenterX();
                        double ballCenterY = ball.getShape().getCenterY();

                        double angle = Math.atan2(ballCenterY - tileCenterY, ballCenterX - tileCenterX);

                        // Adjusting velocity based on angle of incidence
                        if (Math.abs(angle) < Math.PI / 4 || Math.abs(angle) > 3 * Math.PI / 4) {
                            // Adjusting x velocity
                            ball.setVx(-ball.getVx());
                        } else {
                            // Adjusting y velocity
                            ball.setVy(-ball.getVy());
                        }

                    }
                    
                }
            }
        }
    }

    public void paintComponent(Graphics g) {
        
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;

        // Drawing tiles
        for (ColoredShape tile : tiles) {
            g2d.setColor(tile.getColor());
            g2d.fill(tile.getShape());
        }

        // Drawing balls
        for (Ball ball : balls) {
            g2d.setColor(ball.getColor());
            g2d.fill(ball.getShape());
        }
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(columns * tileSize, rows * tileSize);
    }

}

接口.java

import javax.swing.*;
import java.awt.*;
import java.awt.geom.Ellipse2D;

public class Interface extends JFrame {

    protected static int frameHeight = 637;
    protected static int frameWidth = 637;
    private int tileSize = 30;

    public Interface() {

        setSize(frameWidth, frameHeight);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLayout(new BorderLayout());
        setTitle("Bouncing Ball");
        add(new Core(frameHeight / tileSize, frameWidth / tileSize, tileSize)); // Rows, Columns, TileSize
        setVisible(true);

    }

    public static void main(String[] args) {
        new Interface();
    }

}

class ColoredShape {
    
    private Shape shape;
    private Color color;

    public ColoredShape(Shape shape, Color color) {
        
        this.shape = shape;
        this.color = color;

    }

    public Shape getShape() {
        return shape;
    }

    public Color getColor() {
        return color;
    }

    public void setColor(Color color) {
        this.color = color;
    }

}

class Ball {
    
    private Ellipse2D.Double shape;
    private Color color;
    private int vx;
    private int vy;

    public Ball(int x, int y, int diameter, Color color, int vx, int vy) {
        
        this.shape = new Ellipse2D.Double(x, y, diameter, diameter);
        this.color = color;
        this.vx = vx;
        this.vy = vy;

    }

    public Ellipse2D.Double getShape() {
        return shape;
    }

    public Color getColor() {
        return color;
    }

    public int getVx() {
        return vx;
    }

    public void setVx(int vx) {
        this.vx = vx;
    }

    public int getVy() {
        return vy;
    }

    public void setVy(int vy) {
        this.vy = vy;
    }

    public int getX() {
        return (int) shape.x;
    }

    public void setX(int x) {
        shape.x = x;
    }

    public int getY() {
        return (int) shape.y;
    }

    public void setY(int y) {
        shape.y = y;
    }
    
}

您的代码中有一个逻辑错误,我已修复它:

  • 当球接触到正方形时,x 和 y 方向变量都会改变方向,这阻止了真实的碰撞,在一段时间后,球会以对称的方式永远以相同的方式碰撞。 我通过计算碰撞角度来修复它,如您提供的示例代码中所示。
© www.soinside.com 2019 - 2024. All rights reserved.