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

弹跳球在Java[关闭]

苏硕
2023-03-14

我正在创建一个弹跳球项目,每次点击鼠标时,都会以随机的速度、随机的大小和随机的位置生成弹跳球,除了一件事,一切都很完美,当球从顶部和左侧撞击墙壁时,它会完全反弹,但是当球撞击窗户的底部和右侧时,它们也会反弹,但不是完全反弹,我的意思是,球在撞击墙壁之前会从窗户的右侧反弹,当球超过窗户的一半时,会从底部反弹。问题是什么,为什么要这样做?

下面是代码:

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
//To generate random colors
/*new Color((int) Math.floor((Math.random() * 256)),(int) Math.floor((Math.random() * 256)),(int) 
Math.floor((Math.random() * 256)))*/
public class bouncingBalls {
public static void main(String[] args) {
    Program program = new Program();
    program.run();
}
}

class Program {
protected JFrame mainFrame;
protected DrawPanel drawPanel;
protected java.util.List<Ball> balls;
void run() {

    balls = new ArrayList<>();
    mainFrame = new JFrame();
    drawPanel = new DrawPanel();
    mainFrame.getContentPane().add(drawPanel);
    mainFrame.setTitle("Bouncing Balls");
    mainFrame.setSize(640, 480);
    mainFrame.setVisible(true);
    mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    /* Generate balls */
    mainFrame.addMouseListener(new MouseAdapter() {
        public void mouseClicked(MouseEvent me) {
            System.out.println("Mouse clicked");
            Ball ball = new Ball(
                    /* Random positions from 0 to windowWidth or windowHeight */
                    (int) Math.floor(Math.random() * 640),
                    (int) Math.floor(Math.random() * 480),
                    /* Random size from 10 to 30 */
                    (int) Math.floor(Math.random() * 20) + 10,
                    /* Random RGB colors*/
                    new Color(0x851E3E),
                    /* Random velocities from -5 to 5 */
                    (int) Math.floor((Math.random() * 10) - 5),
                    (int) Math.floor((Math.random() * 10) - 5)
            );

            balls.add(ball);
        }
    });
    while (true) {
        for (Ball b: balls) {
            b.update();
        }

        /* Give Swing 10 milliseconds to see the update! */
        try {
            Thread.sleep(30);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        mainFrame.repaint();
    }
}

class DrawPanel extends JPanel {
    @Override
    public void paintComponent(Graphics graphics) {
        super.paintComponent(graphics);

        for (Ball b: balls) {
            b.draw(graphics);
        }

    }
}

class Ball {
    private int posX, posY, size;
    private Color color;

    private int vx;
    private int vy;

    public Ball(int posX, int posY, int size, Color color, int vx, int vy) {
        this.posX = posX;
        this.posY = posY;
        this.size = size;
        this.color = color;
        this.vx = vx;
        this.vy = vy;
    }

    void update() {

        if (posX > mainFrame.getWidth()-size*2 || posX < 0) {
            vx *= -1;
        }

        if (posY > mainFrame.getHeight()-size-32 || posY < 0) {
            vy *= -1;
        }

        if (posX > mainFrame.getWidth()-size*2) {
            posX = mainFrame.getWidth()-size*2;
        }

        if (posX < 0) {
            posX = 0;
        }

        if (posY > mainFrame.getHeight()-size-32) {
            posY = mainFrame.getHeight()-size-32;
        }

        if (posY < 0) {
            posY = 0;
        }

        this.posX += vx;
        this.posY += vy;

    }

    void draw(Graphics g) {
        g.setColor(color);
        g.fillOval(posX, posY, size, size);
        g.getClipBounds();
        g.getClipBounds();
    }
}
}

共有1个答案

夏侯兴怀
2023-03-14

好的,所以你有一些关键问题。

一个JFrame包含一个ContentPane和装饰。装饰出现在框架的边界内,这使得ContentPane的大小等于框架大小减去装饰插页。这是您遇到问题的主要原因,因为您使用框架大小而不是DrawPanel大小来确定冲突检测。

相反,您应该使用绘图面板s大小(已添加到内容窗格)。

你看我怎么能把它放在中间?更多细节。

这是一个重新构建的代码示例,它使用SwingTimer而不是Thread,因此它是线程安全的,并将主工作负载放置到DrawPanel中,而不是将其分散到所有地方。

有关更多详细信息,请参见如何使用Swing定时器

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Test {

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

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                Program program = new Program();
                program.run();
            }
        });
    }

    class Program {

        protected JFrame mainFrame;
        protected DrawPanel drawPanel;

        void run() {

            mainFrame = new JFrame();
            drawPanel = new DrawPanel();
            mainFrame.getContentPane().add(drawPanel);
            mainFrame.setTitle("Bouncing Balls");
            mainFrame.pack();
            mainFrame.setVisible(true);
            mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        }

        class DrawPanel extends JPanel {

            private java.util.List<Ball> balls;
            private Timer timer;

            public DrawPanel() {
                balls = new ArrayList<>(25);
                addMouseListener(new MouseAdapter() {
                    public void mouseClicked(MouseEvent me) {
                        System.out.println("Mouse clicked");
                        Ball ball = new Ball(
                                /* Random positions from 0 to windowWidth or windowHeight */
                                (int) Math.floor(Math.random() * 640),
                                (int) Math.floor(Math.random() * 480),
                                /* Random size from 10 to 30 */
                                (int) Math.floor(Math.random() * 20) + 10,
                                /* Random RGB colors*/
                                Color.RED,
                                /* Random velocities from -5 to 5 */
                                (int) Math.floor((Math.random() * 10) - 5),
                                (int) Math.floor((Math.random() * 10) - 5)
                        );

                        balls.add(ball);
                    }
                });
            }

            @Override
            public void addNotify() {
                super.addNotify();
                if (timer != null) {
                    timer.stop();
                }

                timer = new Timer(30, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent arg0) {
                        for (Ball b : balls) {
                            b.update(getSize());
                        }
                        repaint();
                    }
                });
                timer.start();
            }

            @Override
            public void removeNotify() {
                super.removeNotify();
                if (timer == null) {
                    return;
                }
                timer.stop();
            }

            @Override
            public Dimension getPreferredSize() {
                return new Dimension(640, 480);
            }

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

                for (Ball b : balls) {
                    b.draw(graphics);
                }

            }
        }

        class Ball {

            private int posX, posY, size;
            private Color color;

            private int vx;
            private int vy;

            public Ball(int posX, int posY, int size, Color color, int vx, int vy) {
                this.posX = posX;
                this.posY = posY;
                this.size = size;
                this.color = color;
                this.vx = vx;
                this.vy = vy;
            }

            void update(Dimension bounds) {

                if (posX + size > bounds.width || posX < 0) {
                    vx *= -1;
                }

                if (posY + size > bounds.height || posY < 0) {
                    vy *= -1;
                }

                if (posX + size > bounds.width) {
                    posX = bounds.width - size;
                }

                if (posX < 0) {
                    posX = 0;
                }

                if (posY + size > bounds.height) {
                    posY = bounds.height - size;
                }

                if (posY < 0) {
                    posY = 0;
                }

                this.posX += vx;
                this.posY += vy;

            }

            void draw(Graphics g) {
                g.setColor(color);
                g.fillOval(posX, posY, size, size);
            }
        }
    }
}
 类似资料:
  • 提前感谢帮助我创建了一个程序,使多个弹跳球当用户点击屏幕上一个新的球应该出现并在屏幕上移动。但是当我点击屏幕上一个球出现,根本不移动。当另一个点击发生时,以前创建的球立即跳到另一个位置。 这是ball类:用于创建球 这是一个ball组件类:用于创建面板

  • 问题内容: 因此,我只是想使屏幕周围的球弹起,该球应由于重力而减慢,并像普通球一样从墙壁反射(弹起)。有人可以给出一些基础知识并且非常简单地实现吗?其他示例似乎有些“过高”,似乎超出了我想要做的事情。我已经试过了: 这是我一个人得到的最接近的东西。顺便说一下,x和y值来自加速度计。任何帮助将不胜感激,谢谢! 问题答案: 我认为您将需要三件事,即力(您拥有的x和y),速度(分别称为xVel和yVel

  • 本文向大家介绍python3.6使用tkinter实现弹跳小球游戏,包括了python3.6使用tkinter实现弹跳小球游戏的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了python3.6实现弹跳小球游戏的具体代码,供大家参考,具体内容如下 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。

  • 本文向大家介绍jquery制作 随机弹跳的小球特效,包括了jquery制作 随机弹跳的小球特效的使用技巧和注意事项,需要的朋友参考一下 以下是源码:

  • 我正在为一个使用精灵工具包物理引擎的小型弹跳球游戏工作。我的问题是: 当我对弹跳球施加巨大的冲力使其快速落在地面上时,有时它可能会穿过地面(非常薄,高度=2)。 我在Apple文档中找到了这个,但它不起作用。 为小型或快速移动的对象指定高精度碰撞 当 Sprite Kit 执行碰撞检测时,它首先确定场景中所有物理体的位置。然后,它确定是否发生了冲突或接触。这种计算方法速度很快,但有时会导致错过碰撞

  • 本文向大家介绍python3实现弹弹球小游戏,包括了python3实现弹弹球小游戏的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了python3实现弹弹球小游戏的具体代码,供大家参考,具体内容如下 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。