[英]How to make ball drawn with Java bounce off the edges of the panel?
我有一個在擴展 JPanel 類的類中繪制一個紅球的 Java 代碼,我有一個由一個按鈕啟用的計時器,該按鈕使用計時器 ctor 變量 elapse 更新球的位置。 我試圖獲得面板的高度和繪制圓圈的 YPOSITION 的差異,如果它小於 0,則彈跳球需要繼續向下移動,否則它應該向上移動,我的球撞到牆上並繼續擊中它. 幫助我調試導致這種情況發生的代碼。 右面板類
import javax.swing.*;
import java.awt.*;
public class RightPanel extends JPanel {
//define the position where the circle will be drawn
private int positionX=150;
private int positionY=150;
private int radius=100;//as the shape is a circle
//override the paint method to draw the bounce ball on the second panel
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d= (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.RED);
g2d.fillOval(positionX,positionY,radius,radius);
}
//let's us update the position of the ball from another class
public int getPositionY(){
public void setPositionX(int positionX) {
this.positionX = positionX;
}
public void setPositionY(int positionY){
this.positionY=positionY;
}
public int getPositionX(){
return this.positionX;
}
return this.positionY;
}
}
下面計時器類中的邏輯是我需要GameInterface 類幫助的邏輯
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
public class GameInterface extends JFrame {
//declare a Timer object to start the movement
Graphics ctx;
RightPanel rightpanel;
private int height;
//declare a timer to start moving the ball
Timer mytimer= new Timer(50, new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
//check this and keep moving the ball down
if(rightpanel.getPositionY()- rightpanel.getHeight()<0){
rightpanel.setPositionY(rightpanel.getPositionY()+5);
rightpanel.paint(rightpanel.getGraphics());
}else{
//move the ball up
rightpanel.setPositionY(rightpanel.getPositionY()-5);
rightpanel.paint(rightpanel.getGraphics());
}
}
});
public GameInterface(){
setSize(new Dimension(800, 600));
height=this.getHeight();
setResizable(false);
setTitle("Bounce Game");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBackground(Color.black);
//define a new JSplitPane and use it to add two JPanels
JPanel leftpanel= new JPanel();
//add buttons to the left panel programatically
JButton up= new JButton("Move up");
//set the event listeners for the buttons
up.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
//start he timer
mytimer.start();
}
});
JButton down = new JButton("Move down");
down.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
//move my ball down
rightpanel.setPositionX(rightpanel.getPositionX());
rightpanel.setPositionY(rightpanel.getPositionY()+5);
rightpanel.paint(rightpanel.getGraphics());
}
});
leftpanel.add(up);
leftpanel.add(down);
rightpanel= new RightPanel();
JSplitPane splitpane= new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,leftpanel,rightpanel);
this.add(splitpane);
setVisible(true);
ctx=this.getGraphics();
}
}
基本思想是,當你“放下”球時,你需要確定球應該移動的運動方向。當timer
滴答作響時,它將應用該運動方向,直到它到達底部,此時三角洲被反轉,或者它到達頂部。
這里重要的部分是, timer
需要的所有狀態都應該在timer
啟動之前確定,而不是在timer
本身內計算,因為它需要的狀態不再相關。
例如...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
Ball ball = new Ball(20);
JFrame frame = new JFrame();
frame.add(new MainPane(ball));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class Ball {
private Point location;
private Dimension size;
private Shape shape;
public Ball(int radius) {
location = new Point(0, 0);
size = new Dimension(radius * 2, radius * 2);
shape = new Ellipse2D.Double(0, 0, radius * 2, radius * 2);
}
public Rectangle getBounds() {
return new Rectangle(location, size);
}
public void setLocation(Point p) {
location = new Point(p);
}
public void paint(Graphics2D g2d) {
g2d = (Graphics2D) g2d.create();
g2d.setColor(Color.RED);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.translate(location.x, location.y);
g2d.fill(shape);
g2d.dispose();
}
}
public class SurfacePane extends JPanel {
private Ball ball;
private Timer timer;
private int yDelta;
public SurfacePane(Ball ball) {
this.ball = ball;
this.ball.setLocation(new Point(200 - (ball.getBounds().width / 2), 0));
}
@Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
ball.paint(g2d);
g2d.dispose();
}
public void moveBallDown() {
Rectangle bounds = ball.getBounds();
Dimension size = ball.size;
Point location = bounds.getLocation();
location.y += size.height;
if (location.y + size.height > getHeight()) {
location.y = getHeight() - size.height;
}
ball.setLocation(location);
repaint();
}
public void dropBall() {
if (timer != null) {
return;
}
Rectangle bounds = ball.getBounds();
Dimension size = ball.size;
Point location = bounds.getLocation();
if (location.y + size.height > getHeight()) {
yDelta = -1;
} else {
yDelta = 1;
}
timer = new Timer(5, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Rectangle bounds = ball.getBounds();
Dimension size = ball.size;
Point location = bounds.getLocation();
location.y += yDelta;
if (location.y < 0) {
location.y = 0;
yDelta = 0;
timer.stop();
timer = null;
} else if (location.y + size.height > getHeight()) {
location.y = getHeight() - size.height;
yDelta *= -1;
}
ball.setLocation(location);
repaint();
}
});
timer.start();
}
}
public class MainPane extends JPanel {
private Ball ball;
private SurfacePane surfacePane;
public MainPane(Ball ball) {
setLayout(new BorderLayout());
this.ball = ball;
surfacePane = new SurfacePane(ball);
add(surfacePane);
JPanel actionPane = new JPanel(new GridBagLayout());
JButton up = new JButton("Up");
JButton down = new JButton("Down");
actionPane.add(up);
actionPane.add(down);
add(actionPane, BorderLayout.SOUTH);
up.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
surfacePane.dropBall();
}
});
down.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
surfacePane.moveBallDown();
}
});
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.