ボールのアニメーションで、2つのボールが衝突したときに回数をカウントし、画面上に表示させるプログラムを作りました。カウント自体はうまくいきましたが、ボールが長時間接触している時に衝突回数がカウントされ続けてしまうので、最終時には衝突回数が無限に増え続けてしまいます(その時の状況を画像として載せました)。このような欠陥をどうにかする方法が分かれば、ぜひ教えてください。
PinBall
1import java.awt.BorderLayout; 2import java.awt.FlowLayout; 3import java.awt.Graphics; 4import java.awt.event.ActionEvent; 5import java.awt.event.ActionListener; 6import java.awt.Container; 7 8import javax.swing.JFrame; 9import javax.swing.JPanel; 10import javax.swing.Timer; 11import javax.swing.JButton; 12import javax.swing.JLayeredPane; 13 14public class PinBall { 15 public static void main(String[] args) { 16 JFrame window = new JFrame("PinBall"); 17 window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 18 window.setSize(650, 400); 19 20 21 PanelGameBoard panel = new PanelGameBoard(); 22 window.add(panel); 23 window.setVisible(true); 24 25 panel.animationStart(); 26 27 28 } 29} 30 31class PanelGameBoard extends JPanel implements ActionListener { 32 private final Ball ball; 33 private final Timer timer; 34 private Ball ballEx; 35 private int count = 0;//衝突回数のカウンタ 36 37 JButton button = new JButton("上から落とす"); 38 // 再描画タイミング 39 private static final int INTERVAL = 50; 40 41 public PanelGameBoard() { 42 timer = new Timer(INTERVAL, this); 43 ball = new Ball(this); 44 ballEx = new Ball(this); 45 ballEx.setX(150); 46 ballEx.setY(130); 47 this.add(button); 48 button.addActionListener(this); 49 } 50 51 public void animationStart() { 52 ball.goHome(); 53 timer.start(); 54 } 55 56 @Override 57 public void paintComponent(Graphics graphics) { 58 super.paintComponent(graphics); 59 ball.draw(graphics); 60 ballEx.draw(graphics); 61 graphics.drawString("ボールの衝突回数:"+count+"回", 500, 300); 62 if((ball.getX()-ballEx.getX())*(ball.getX()-ballEx.getX())+(ball.getY()-ballEx.getY())*(ball.getY()-ballEx.getY())<=(double)2*ball.getR()*ball.getR()) 63 count++; 64 } 65 66 @Override 67 public void actionPerformed(ActionEvent event) { 68 ball.next(); 69 ballEx.next(); 70 repaint(); 71 if(event.getSource() == button){ 72 ball.setY(0); 73 ballEx.setY(0); 74 } 75 if((ball.getX()-ballEx.getX())*(ball.getX()-ballEx.getX())+(ball.getY()-ballEx.getY())*(ball.getY()-ballEx.getY())<=(double)2*ball.getR()*ball.getR()){ 76 ball.setVx(((1+ball.getE())*ball.getVx()+(1-ball.getE())*ballEx.getVx())/(double)2); 77 ball.setVy(((1+ball.getE())*ball.getVy()+(1-ball.getE())*ballEx.getVy())/(double)2); 78 ballEx.setVx(((1-ball.getE())*ball.getVx()+(1+ball.getE())*ballEx.getVx())/(double)2);//2つのボールにおける中心間の距離が直径より小さくなれば 79 ballEx.setVy(((1-ball.getE())*ball.getVy()+(1+ball.getE())*ballEx.getVy())/(double)2);//衝突したと判定として運動量保存則に基づき速度を変える 80 81 } 82 83 } 84 85 86}
Ball
1import java.awt.Color; 2import java.awt.Graphics; 3 4import javax.swing.JPanel; 5 6public class Ball { 7 // ボールの半径 8 private double r = 10.0; 9 10 // ボールの中心座標 11 private double x = 0.0; 12 private double y = 0.0; 13 14 // ボールの速度(1フレーム当たりの移動距離) 15 private double vx = 15.0; 16 private double vy = -15.0; 17 18 // ボールの色 19 private Color color = Color.BLACK; 20 21 // y軸 正の方向の加速度(1フレーム当たりの上記「速度」の変化量) 22 private double g = 0.5; 23 24 // 反発係数 25 private double e = 0.8; 26 27 // ボールを描画するパネル 28 private JPanel panel; 29 30 public Ball(JPanel panel) { 31 this.panel = panel; 32 } 33 34 public Ball(double r, double x, double y, double vx, double vy, Color color, JPanel panel) { 35 this.r = r; 36 this.x = x; 37 this.y = y; 38 this.vx = vx; 39 this.vy = vy; 40 this.color = color; 41 this.panel = panel; 42 } 43 44 /*--- アクセサメソッド ---*/ 45 // getter 46 public double getR() { return r; } 47 public double getE() { return e; } 48 49 public double getX() { return x; } 50 public double getY() { return y; } 51 52 public double getVx() { return vx; } 53 public double getVy() { return vy; } 54 55 // setter 56 public void setR(double r) { this.r = r; } 57 58 public void setX(double x) { this.x = x; } 59 public void setY(double y) { this.y = y; } 60 public void setXY(double x, double y) { this.x = x; this.y = y; } 61 62 public void setVx(double vx) { this.vx = vx; } 63 public void setVy(double vy) { this.vy = vy; } 64 public void setVxVy(double vx, double vy) { this.vx = vx; this.vy = vy; } 65 66 public void setG(double g) { this.g = g; } 67 public void setE(double e) { this.e = e; } 68 public void setColor(Color color) { this.color = color; } 69 70 // ボールを描画 71 public void draw(Graphics graphics) { 72 Color prevColor = graphics.getColor(); 73 graphics.setColor(color); 74 graphics.fillOval((int) (x - r), (int) (y - r), (int) (2 * r), (int) (2 * r)); 75 graphics.setColor(prevColor); 76 } 77 78 // ボールを左下隅へ移動 79 public void goHome() { 80 x = r; 81 y = panel.getHeight() - r; 82 } 83 84 // 座標、速度更新 85 public void next() { 86 // 画面の幅と高さ取得 87 int width = panel.getWidth(); 88 int height = panel.getHeight(); 89 90 x = x + vx; 91 y = y + vy; 92 93 /*--- 衝突判定 ---*/ 94 if (x < r) { 95 x = r; 96 vx = -vx * e; 97 } 98 99 if (x + r > width) { 100 x = width - r; 101 vx = -vx * e; 102 } 103 104 if (y < r) { 105 y = r; 106 vy = -vy * e; 107 } 108 109 if (y + r > height) { 110 y = height - r; 111 vy = -vy * e; 112 } 113 114 // 画面下向きの加速度 115 vy = vy + g; 116 } 117} 118
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/01/12 13:09