Java中的弹跳球
我正在创建一个弹跳球项目,每次点击鼠标时都会以随机的速度、随机的大小和随机的位置生成弹跳球,除了一件事之外,一切都很完美,当球从顶部和左侧撞击墙壁时,它会完全反弹,但当球撞击窗户底部和右侧时,它们也会反弹,但不是完全反弹,我的意思是,球在撞击墙壁之前从窗户右侧反弹,当几乎一半的球超过窗户时从底部反弹。 问题是什么,为什么要这样做 代码如下:Java中的弹跳球,java,swing,Java,Swing,我正在创建一个弹跳球项目,每次点击鼠标时都会以随机的速度、随机的大小和随机的位置生成弹跳球,除了一件事之外,一切都很完美,当球从顶部和左侧撞击墙壁时,它会完全反弹,但当球撞击窗户底部和右侧时,它们也会反弹,但不是完全反弹,我的意思是,球在撞击墙壁之前从窗户右侧反弹,当几乎一半的球超过窗户时从底部反弹。 问题是什么,为什么要这样做 代码如下: import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import j
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();
}
}
}
import java.awt.event.MouseAdapter;
导入java.awt.event.MouseEvent;
导入java.util.ArrayList;
//生成随机颜色
/*新颜色((int)Math.floor((Math.random()*256)),(int)Math.floor((Math.random()*256)),(int)
Math.floor((Math.random()*256)))*/
公开课弹跳球{
公共静态void main(字符串[]args){
程序=新程序();
program.run();
}
}
班级计划{
受保护的JFrame主机;
受保护的抽板抽板;
受保护的java.util.List球;
无效运行(){
balls=新的ArrayList();
大型机=新的JFrame();
drawPanel=新的drawPanel();
mainFrame.getContentPane().add(drawPanel);
大型机.setTitle(“弹跳球”);
大型机。设置大小(640480);
mainFrame.setVisible(true);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
/*生球*/
mainFrame.addMouseListener(新的MouseAdapter(){
公共无效mouseClicked(MouseEvent me){
System.out.println(“鼠标点击”);
球=新球(
/*从0到windowWidth或windowHeight的随机位置*/
(int)Math.floor(Math.random()*640),
(int)Math.floor(Math.random()*480),
/*随机大小从10到30*/
(int)Math.floor(Math.random()*20)+10,
/*随机RGB颜色*/
新颜色(0x851E3E),
/*从-5到5的随机速度*/
(int)数学层((Math.random()*10)-5),
(int)Math.floor((Math.random()*10)-5)
);
添加(ball);
}
});
while(true){
用于(球b:球){
b、 更新();
}
/*给Swing 10毫秒来查看更新*/
试一试{
睡眠(30);
}捕捉(中断异常e){
e、 printStackTrace();
}
mainFrame.repaint();
}
}
类DrawPanel扩展了JPanel{
@凌驾
公共虚空绘制组件(图形){
super.paintComponent(图形);
用于(球b:球){
b、 绘制(图形);
}
}
}
班级舞会{
私有int posX,posY,size;
私人色彩;
私有intvx;
私营企业;
公共球(int-posX,int-posY,int-size,Color-Color,int-vx,int-vy){
this.posX=posX;
this.posY=posY;
这个。大小=大小;
这个颜色=颜色;
这是vx=vx;
this.vy=vy;
}
无效更新(){
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;
}
这个.posX+=vx;
this.posY+=vy;
}
虚线绘制(图形g){
g、 设置颜色(颜色);
g、 Fillova(posX、posY、size、size);
g、 getClipBounds();
g、 getClipBounds();
}
}
}
好的,那么您有一些关键问题
JFrame
包含contentPane
和装饰。装饰出现在框架的边界内,这使得contentPane
s的大小等于框架大小减去装饰插图。这是您主要遇到问题的地方,因为您使用的是帧大小而不是DrawPanel
size来确定碰撞检测
相反,您应该使用DrawPanel
s大小(已添加到contentPane
)
有关更多详细信息,请参阅
这是一个重建的代码示例,它使用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);
}
}
}
}
导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.EventQueue;
导入java.awt.Graphics;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.awt.event.MouseAdapter;
导入java.awt.event.MouseEvent;
导入java.util.ArrayList;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.Timer;
公开课考试{
公共静态void main(字符串[]args){
新测试();
}
公开考试(){
invokeLater(新的Runnable(){
@凌驾
公开募捐{
程序=新程序();
program.run();
}
});
}
班级计划{
受保护的JFrame主机;
受保护的抽板抽板;
无效运行(){
大型机=新的JFrame();
drawPanel=新的drawPanel();
mainFrame.getContentPane().add(drawPanel);
大型机.setTitle(“弹跳球”);
mainFrame.pack();
mainFrame.setVisible(true);
mainFrame.setD