日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

小球碰撞python代码_Java 实现小球碰撞GUI

發布時間:2024/8/1 python 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 小球碰撞python代码_Java 实现小球碰撞GUI 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最后一次更新于2019/07/08

修復問題:

錯誤輸入未提醒問題

碰撞小球的圖形重疊問題

高速小球越界問題

感謝

大一暑假拜讀學姐的一篇文章:我說這是一篇很嚴肅的技術文章你信嗎,本篇在她的基礎上加以改進。

效果演示圖

基本思路

要實現小球運動,可以從以下幾點切入:

1. 小球都有那些具體特征?

涉及動能定理就需要考慮質量了,除此之外常規的幾個變量也不能忘:方向、球的尺寸,所在位置以及當前速度。

2. 誰能初始小球的狀態?

小球的狀態無非兩種:(隨機)默認值、人工手動輸入。

3. 誰能控制小球的運動?

我們控制小球是需要給予一定的指令的,就算是鼠標點擊也是簡單的指令之一,除此之外如果想要擁有稍微復雜一點的指令可以使用按鈕來實現。

根據分析,我們大概能構造出大概的類,無非是一個專門描述小球狀態的,一個控制所有命令的,一個構建出窗口和選項的。我們還可以在細化這三個類的功能:

球類

因為窗口也是二維的,構造方法僅需要包含:質量,沿x、y軸的分速度,二維坐標表示的位置,顏色,大小, 所在的畫板。

小球的外在屬性:顏色,尺寸。

小球的移動情況:

遇到邊界直接反彈

移動距離利用公式:距離 = 當前距離 + 速度 × 時間(這邊直接簡化成1)

小球之間的完全彈性碰撞公式:

$$\frac{{{\rm{(}}{{\rm{m}}_1} - {m_2}){v_{10}} + 2{m_2}{v_{20}}}}{{{{\rm{m}}_1} + {m_2}}}$$

$$\frac{{{\rm{(}}{{\rm{m}}_2} - {m_1}){v_{20}} + 2{m_1}{v_{10}}}}{{{{\rm{m}}_1} + {m_2}}}$$

碰撞的兩球形狀盡量不要重疊,當程序檢測到這種意外時要盡可能拉開兩球之間的距離,直到兩球距離恰好等于兩球半徑之和。

代碼如下:

/**

* 這個類主要是用來設置小球的各種屬性以及運動關系。

* @author Hephaest

* @version 2019/7/5

* @since jdk_1.8.202

*/

import java.awt.Color;

import java.awt.Graphics;

import java.util.ArrayList;

public class Ball{

/**

* 聲明小球的各種變量。

*/

private int xPos, yPos, size, xSpeed, ySpeed,mass;

private Color color;

private BallFrame bf;

/**

* 球類的構造函數。

* @param xPos 小球在X軸上的位置。

* @param yPos 小球在Y軸上的位置。

* @param size 小球的直徑長度。

* @param xSpeed 小球在X軸上的分速度。

* @param ySpeed 小球在Y軸上的分速度。

* @param color 小球的顏色。

* @param mass 小球的質量。

* @param bf 當前小球所在的畫板。

*/

public Ball(int xPos, int yPos, int size, int xSpeed, int ySpeed, Color color, int mass, BallFrame bf) {

super();

this.xPos = xPos;

this.yPos = yPos;

this.size = size;

this.xSpeed = xSpeed;

this.ySpeed = ySpeed;

this.color = color;

this.mass = mass;

this.bf = bf;

}

/**

* 在畫板上繪制小球。

* @param g 當前小球。

*/

public void drawBall(Graphics g) {

if(xPos + size> bf.getWidth() - 4) xPos = bf.getWidth() - size - 4;

else if(xPos < 4) xPos = 4;

if(yPos < 4) yPos = 4;

else if(yPos > bf.getHeight()) yPos = bf.getHeight() - size - 4;

g.setColor(color);

g.fillOval(xPos, yPos, size, size);

}

/**

* 該方法是用來判斷下一秒小球的移動方向并計算當前小球的位置。

* @param bf 當前小球所在的畫板。

*/

public void moveBall(BallFrame bf) {

if (xPos + size + xSpeed > bf.getWidth() - 4 || xPos + xSpeed < 4)

{

xSpeed = -xSpeed;

}

if (yPos + ySpeed < 2 || yPos + size + ySpeed > bf.getHeight() - 163)

{

ySpeed = - ySpeed;

}

xPos += xSpeed;

yPos += ySpeed;

}

/**

* 該方法是用于判斷碰撞是否發生了,如果發生了,盡量避免小球形狀之間的重疊。

* @param balls 所有小球。

*/

public void collision(ArrayList balls) {

for (int i = 0; i < balls.size(); i++) {

Ball ball = balls.get(i);

if (ball != this) {

double d1 = Math.abs(this.xPos - ball.xPos);

double d2 = Math.abs(this.yPos - ball.yPos);

double d3 = Math.sqrt(Math.pow(d1,2) + Math.pow(d2,2));

if (d3 <= (this.size / 2 + ball.size / 2)) {

if (this.xPos > ball.xPos) {

xPos++;

while(Math.sqrt(Math.pow(this.xPos - ball.xPos,2) + Math.pow(d2,2)) < this.size / 2 + ball.size / 2) xPos++;

} else {

ball.xPos++;

while(Math.sqrt(Math.pow(ball.xPos - this.xPos,2) + Math.pow(d2,2)) < this.size / 2 + ball.size / 2) ball.xPos++;

}

/* 應用完美彈性碰撞的速度公式 */

this.xSpeed=((this.mass - ball.mass) * this.xSpeed + 2 * ball.mass * ball.xSpeed)/(this.mass + ball.mass);

this.ySpeed=((this.mass - ball.mass) * this.ySpeed + 2 * ball.mass * ball.ySpeed)/(this.mass + ball.mass);

ball.xSpeed=((ball.mass - this.mass) * ball.xSpeed + 2 * this.mass * this.xSpeed)/(this.mass + ball.mass);

ball.ySpeed=((ball.mass - this.mass) * ball.ySpeed + 2 * this.mass * this.ySpeed)/(this.mass + ball.mass);

}

}

}

}

}

事件監聽器

構造方法中需要同時引入涉及文本框、按鈕和小球所在的類。

如果點擊鼠標,生成一個除了大小給定其他隨機的彩色小球。

如果點 Play 文本框的信息被讀取,生成指定的小球。

如果點 Stop 小球停止運動但不消失。

如果點 Reset 文本框恢復默認值,用戶可以選擇重新輸入。

如果點 Continue 小球繼續剛剛的運動。

如果點 Clear 小球停止運動且線程立即中斷。

代碼如下:

/**

* 此類是用于監聽 BallFrame GUI 的文字輸入和按監聽的。

* 用戶可以輸入參數然后點擊按鈕"Play"或者在畫板中指定區域單機鼠標生成小球。

* @author Hephaest

* @version 2019/7/5

* @since jdk_1.8.202

*/

import java.awt.Color;

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 java.util.Random;

import java.util.regex.Pattern;

import javax.swing.*;

public class Listener extends MouseAdapter implements ActionListener,Runnable {

/**

* 聲明監聽器里的所有變量。

* 需要注意何時更改 clearFlag 和 pauseFlag 的布爾值。

*/

private BallFrame bf;

private Random rand = new Random();

private volatile boolean clearFlag = false, pauseFlag = false;

private ArrayList ball;

Thread playing;

/**

* 監聽器的構造函數。

* @param bf BallFrame 類的實例。

* @param ball 所有小球組成的列表。

*/

public Listener(BallFrame bf, ArrayList ball) {

this.bf = bf;

this.ball = ball;

}

/**

* 每次點擊小球時,只能直到生成小球的初始位置,但是它的速度分量都是隨機數。

*/

public void mousePressed(MouseEvent e) {

int x = e.getX();

int y = e.getY();

if(x + 50 > bf.getWidth() - 4) x = bf.getWidth() - 54;

else if(x < 4) x = 4;

if(y < 163) y = 163;

else if(y + 50 > bf.getHeight()) y = bf.getHeight() - 46;

Ball newBall = new Ball(x, y - 163, 50, (1 + rand.nextInt(9) * (Math.random() > 0.5 ? 1 : -1)),

(1 + rand.nextInt(9) * (Math.random() > 0.5? 1 : -1)),

new Color(rand.nextInt(255),rand.nextInt(255), rand.nextInt(255)),rand.nextInt(9) + 1, bf);

ball.add(newBall);

}

@Override

/**

* 該方法是 Runnable 的重寫。

* 如果用戶選擇暫停的話,需要停止畫板刷新和新的繪制。

*/

public void run() {

while (!clearFlag) {

if(!pauseFlag)

{

bf.repaint();

try {

Thread.sleep(30);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

/**

* 該方法用來響應不同按鈕的需求。

*/

public void actionPerformed(ActionEvent event) {

String command = event.getActionCommand();

if (command.equals("Play")) {

if (checkValid(bf.massText.getText(), bf.sizeText.getText(), bf.xPositionText.getText(), bf.yPositionText.getText())) {

startPlaying();

} else {

JOptionPane.showMessageDialog(null, "Please enter correct numbers!");

}

}

if (command.equals("Stop")) {

stopPlaying();

}

if (command.equals("Reset")) {

setAllFields();

}

if (command.equals("Continue")) {

continuePlaying();

}

if (command.equals("Clear")) {

clearPlaying();

}

}

/**

* 該方法用來響應 "Reset" 按鈕。

* 每個文本框都設置默認值。

* 重置完后無法再點擊 "Reset" 或 "Continue"。

*/

void setAllFields() {

bf.massText.setText("1");

bf.xSpeedText.setText("1");

bf.xPositionText.setText("0");

bf.sizeText.setText("50");

bf.ySpeedText.setText("1");

bf.yPositionText.setText("0");

bf.reset.setEnabled(false);

bf.play.setEnabled(true);

bf.Continue.setEnabled(false);

bf.clear.setEnabled(true);

}

/**

* 該方法用來響應 "Play" 按鈕。

* 需要創建一個新的進程并設置 clearFlag 為 false, 這樣 run() 函數可以正常運行。

* 運行完后無法再點擊 "play" again 或 "Continue"。

*/

void startPlaying() {

playing = new Thread(this);

playing.start();

clearFlag = false;

bf.play.setEnabled(false);

bf.Continue.setEnabled(false);

bf.stop.setEnabled(true);

bf.reset.setEnabled(true);

bf.clear.setEnabled(true);

String xP = bf.xPositionText.getText();

int x = Integer.parseInt(xP);

String yP = bf.yPositionText.getText();

int y = Integer.parseInt(yP);

String Size = bf.sizeText.getText();

int size = Integer.parseInt(Size);

String Xspeed = bf.xSpeedText.getText();

int xspeed = Integer.parseInt(Xspeed);

String Yspeed = bf.ySpeedText.getText();

int yspeed = Integer.parseInt(Yspeed);

String Mass = bf.massText.getText();

int mass = Integer.parseInt(Mass);

Ball myball = new Ball(x, y, size, xspeed,yspeed,

new Color(rand.nextInt(255), rand.nextInt(255), rand.nextInt(255)), mass, bf);

ball.add(myball);

}

/**

* 該方法用來響應 "Stop" 按鈕。

* 這個不需要重新繪制。

* 用戶無法再點擊 "Stop" 按鈕。

*/

void stopPlaying() {

bf.stop.setEnabled(false);

bf.play.setEnabled(true);

bf.reset.setEnabled(true);

bf.Continue.setEnabled(true);

bf.clear.setEnabled(true);

pauseFlag=true;

}

/**

* 該方法用來響應 "Continue" 按鈕。

* 需要設置 pauseFlag 的值用來一遍又一遍地重繪窗口。

* 需要記住線程 "Playing" 仍在工作!

* 用戶無法再點擊 "Continue" 按鈕。

*/

void continuePlaying()

{

bf.stop.setEnabled(true);

bf.play.setEnabled(true);

bf.reset.setEnabled(true);

bf.Continue.setEnabled(false);

bf.clear.setEnabled(true);

pauseFlag = false;

}

/**

* 該方法用來響應 "Clear" 按鈕。

* 通過將線程聲明為null來減少CPU的浪費。

* 需要清空所有小球并重新繪制。

* 用戶無法再點擊 "Clear" 或 "Stop" 或 "Continue" 按鈕。

*/

void clearPlaying()

{

bf.clear.setEnabled(false);

bf.stop.setEnabled(false);

bf.play.setEnabled(true);

bf.reset.setEnabled(true);

bf.Continue.setEnabled(false);

playing = null;

clearFlag = true;

ball.clear();

bf.repaint();

}

/**

* 核查用戶在文本框里的輸入是否正確。

* @param mass 小球的質量。

* @param size 小球的直徑。

* @param xPos 小球在X軸的位置。

* @param yPos 小球在Y軸的位置。

* @return 返回核驗結果。

*/

private boolean checkValid(String mass, String size, String xPos, String yPos)

{

Pattern pattern = Pattern.compile("[0-9]*");

if (!pattern.matcher(mass).matches() || !pattern.matcher(size).matches() || !pattern.matcher(xPos).matches() || !pattern.matcher(yPos).matches())

return false;

else if (Integer.parseInt(mass) <= 0 || Integer.parseInt(size) <= 0 || Integer.parseInt(xPos) < 0 || Integer.parseInt(yPos) < 0)

return false;

else

return true;

}

}

GUI框架

需要文本框實現輸入,兩行,每行3個變量。

需要5個按鈕,分別代表 "Play"、"Stop"、"Reset"、"Continue"、"Clear"。

需要一個畫布,可以顯示出球類的動畫。

代碼如下

/**

* 該類主要用于繪制GUI。

* @author Hephaest

* @version 2019/7/5

* @since jdk_1.8.202

*/

import java.awt.FlowLayout;

import java.awt.Graphics;

import java.awt.Graphics2D;

import java.awt.GridLayout;

import java.awt.Image;

import java.awt.RenderingHints;

import java.util.ArrayList;

import javax.swing.JButton;

import javax.swing.JFrame;

import javax.swing.JLabel;

import javax.swing.JPanel;

import javax.swing.JTextField;

import javax.swing.UIManager;

public class BallFrame extends JFrame {

private ArrayList ball = new ArrayList();

private Image img;

private Graphics2D graph;

/**

* JPanel 用于一行一行的放置文本框和按鈕

*/

JPanel row1 = new JPanel();

JLabel mass = new JLabel("mass:", JLabel.RIGHT);

JTextField massText, xSpeedText, xPositionText, sizeText, ySpeedText, yPositionText;

JLabel xSpeed = new JLabel("xSpeed:", JLabel.RIGHT);

JLabel xPosition = new JLabel("xPosition:", JLabel.RIGHT);

JLabel size = new JLabel("size:", JLabel.RIGHT);

JLabel ySpeed = new JLabel("ySpeed:", JLabel.RIGHT);

JLabel yPosition = new JLabel("yPosition:", JLabel.RIGHT);

JPanel row2 = new JPanel();

JButton stop = new JButton("Stop");

JButton Continue = new JButton("Continue");

JButton clear = new JButton("Clear");

JButton play = new JButton("Play");

JButton reset = new JButton("Reset");

/**

* BallFrame 類的構造函數。

*/

public BallFrame()

{

super("BallGame");

setSize(600, 600);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//使第一個模塊都是文本框。

row1.setLayout(new GridLayout(2, 3, 10, 10));

//把文本框和標簽加到row1。

row1.add(mass);

massText = new JTextField("1");

row1.add(massText);

row1.add(xSpeed);

xSpeedText = new JTextField("1");

row1.add(xSpeedText);

row1.add(xPosition);

xPositionText = new JTextField("0");

row1.add(xPositionText);

row1.add(size);

sizeText = new JTextField("50");

row1.add(sizeText);

row1.add(ySpeed);

ySpeedText = new JTextField("1");

row1.add(ySpeedText);

row1.add(yPosition);

yPositionText = new JTextField("0");

row1.add(yPositionText);

add(row1,"North");

//使按鈕居中。

FlowLayout layout3 = new FlowLayout(FlowLayout.CENTER, 10, 10);

row2.setLayout(layout3);

row2.add(play);

row2.add(stop);

row2.add(reset);

row2.add(Continue);

row2.add(clear);

add(row2);

setResizable(false);

setVisible(true);

}

//主函數。

public static void main(String[] args) {

BallFrame.setLookAndFeel();

BallFrame bf = new BallFrame();

bf.UI();

}

/**

* 添加監聽器。

*/

public void UI() {

Listener lis = new Listener(this, ball);

this.addMouseListener(lis);

clear.addActionListener(lis);

Continue.addActionListener(lis);

stop.addActionListener(lis);

play.addActionListener(lis);

reset.addActionListener(lis);

Thread current = new Thread(lis);

current.start();

}

/**

* 這種方法是為了確保跨操作系統能夠顯示窗口。

*/

private static void setLookAndFeel() {

try {

UIManager.setLookAndFeel(

"com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"

);

} catch (Exception exc) {

// 忽略。

}

}

/**

* 該方法是用于重繪不同區域的畫布。

*/

public void paint(Graphics g) {

// Panel需要被重繪,不然無法顯示。

row1.repaint(0,0,this.getWidth(), 80);

row2.repaint(0,0,this.getWidth(), 42);

img = this.createImage(this.getWidth(), this.getHeight());

graph = (Graphics2D)img.getGraphics();

//渲染使無鋸齒。

graph.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

graph.setBackground(getBackground());

//遍歷更新每一個小球的運動情況。

for (int i = 0; i < ball.size(); i++) {

Ball myBall = ball.get(i);

myBall.drawBall(graph);

myBall.collision(ball);

myBall.moveBall(this);

}

g.drawImage(img, 0, 150, this);

}

}

源碼

如果我的文章可以幫到您,勞煩您點進源碼點個 ★ Star 哦!

總結

以上是生活随笔為你收集整理的小球碰撞python代码_Java 实现小球碰撞GUI的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 你懂的网站在线 | 中文字幕日韩一区二区三区不卡 | 激情图片区 | 黄色一级淫片 | 美女色黄网站 | 18日本xxxxxxxxx95 国产又好看的毛片 | 少妇网站在线观看 | 福利在线免费视频 | 亚洲福利小视频 | 日韩av手机在线观看 | 无码国模国产在线观看 | 欧美一级免费 | 欧美www视频 | 亚洲最新偷拍 | 日韩视频一区二区三区四区 | 欧美日韩成人在线视频 | 国产精品成人99一区无码 | 国产婷婷色一区二区 | 97av在线视频 | 香蕉久草 | av免费大全| 泷泽萝拉在线播放 | 九一国产视频 | 午夜免费网 | 日本美女黄视频 | 天堂av片| 美女视频黄的免费 | 性生生活性生交a级 | 国产成人无码精品 | 欧美日韩亚洲精品一区二区 | 国产亚洲av综合人人澡精品 | 久久乐av| 黄视频免费在线观看 | 黄色在线免费观看网站 | 亚洲生活片 | 免费男女乱淫真视频免费播放 | 精品国产免费一区二区三区 | 亚洲精品国产精品国自产 | 两个人看的www视频免费完整版 | 亚欧洲精品在线视频 | 在线视频亚洲色图 | 日韩一区二区三区四区在线 | 麻豆精品免费 | 久久99国产精品久久99 | 全毛片| 日韩欧美黄色片 | 国产睡熟迷奷系列精品视频 | 国产色宗合| 娇小萝被两个黑人用半米长 | 手机在线精品视频 | 看个毛片| 妖精视频污 | 亚洲少妇毛片 | 中文字幕丰满乱子伦无码专区 | 精品免费在线观看 | 噜噜噜久久久 | 亚洲精品中文字幕在线 | 中文人妻熟女乱又乱精品 | 国产伦理一区 | 中文字幕视频免费 | 国产成人在线播放视频 | 日韩精品四区 | 91麻豆网| 亚洲性网站 | 男人天堂1024| 黄色99 | 人妻精油按摩bd高清中文字幕 | 四虎首页 | 草草影院第一页 | 久久99国产精品久久99果冻传媒 | 免费啊v在线观看 | 蜜乳av一区二区三区 | 日批视屏 | 国产自偷自拍视频 | 可以在线观看的av | 久久久久久久国产精品美女 | 天堂在线资源库 | 色婷婷激情五月 | 黄色污污视频软件 | 桃谷绘里香在线播放 | 国产成人综合在线 | 亚洲一区二区三区四区 | 在线不卡欧美 | 找av123导航| 久久久成人免费 | 青青成人在线 | 国模精品一区二区三区 | 在线免费观看污 | 国产日产精品一区 | 六月丁香综合网 | 欧美区二区三区 | 亚洲永久精品在线观看 | 欧美精品一级二级三级 | 三级中文字幕在线 | 成人免费入口 | 欧美性猛交xxxx乱大交退制版 | 国产成人精品一区二区三 | 日韩精品人妻一区二区中文字幕 | 伊人影院在线观看 |