精华内容
下载资源
问答
  • 1、小球可以沿着一个随机的方向运动 2、运动时可以加减速 3、随时切换小球形状(圆形,正方形,三角形) 4、碰撞到边框时镜像反弹 5、小球的运动轨迹可以实时显示,边框设置为正方形时更容易画出美丽的图案哦 6、...
  • 前面已经实现了一个球在一个窗口中随机运动,下面将在前面的基础上实现个球的随机运动及碰撞,此次的代码中用到的算法参考了Twinsen写的一文中关于两球碰撞时的算法.程序仍旧有个类,一个Ball类,一个BallCanvas类,...

    前面已经实现了一个球在一个窗口中随机运动,下面将在前面的基础上实现两个球的随机运动及碰撞,此次的代码中用到的算法参考了Twinsen写的一文中关于两球碰撞时的算法.程序仍旧有两个类,一个Ball类,一个BallCanvas类,Ball类与前面相同,而BallCanvas类作了修改,修改后的代码如下:

    import java.awt.Canvas;

    import java.awt.Color;

    import java.awt.Graphics;

    import java.util.Random;

    public class BallCanvas extends Canvas implements Runnable {

    private int ballRadius = 40;   //球的半径

    private int ballAX,ballAY;        //当前A,B球的位置

    private int ballBX,ballBY;

    private double ballAXMoveLength= 7;     //A,B球当前速度在X,Y轴上的分速度

    private double ballAYMoveLength = 9;    //为了减少计算中数据丢失,用double型而不用int型

    private double ballBXMoveLength = 6;    //

    private double ballBYMoveLength = 5;     //如果用int型两球最终将停止运动

    private Random r;

    private boolean move = true;       //标志球是否移动

    private int screenWidth, screenHeight;        //屏幕宽及高

    private int ballARX, ballARY;  //A球圆心位置

    private int ballBRX, ballBRY;   //B球圆心位置

    public BallCanvas(int screenWidth, int screenHeight){

    r = new Random();

    ballAX = r.nextInt(screenWidth – 2*ballRadius);     //随机初始化A球的初始位置

    ballAY = r.nextInt(screenHeight – 2*ballRadius);

    do{        //随机初始化B球的初始位置,且确定A球跟B球不发生碰撞

    ballBX = r.nextInt(screenWidth – 2*ballRadius);

    ballBY = r.nextInt(screenHeight – 2*ballRadius);

    }while((int)Math.sqrt((ballAX-ballBX)*(ballAX-ballBX) +

    (ballAY-ballBY)*(ballAY-ballBY)) < 2*ballRadius);

    this.screenHeight = screenHeight;

    this.screenWidth = screenWidth;

    }

    public void paint(Graphics g){

    //g.setColor(Color.WHITE);            //此处使用背景色而不用白色,如果要自己清空屏幕,则需加上缓存,不然会产生画面抖动

    //g.fillRect(0, 0, screenWidth, screenHeight);

    g.setColor(Color.RED);

    g.fillArc((int)ballAX, (int)ballAY, (int)ballRadius*2, (int)ballRadius*2, 0, 360);

    g.fillArc((int)ballBX, (int)ballBY,(int) ballRadius*2, (int)ballRadius*2, 0, 360);

    }

    /**

    * 退出

    */

    public void exit(){

    move = false;

    }

    public void run(){

    while(move){

    //处理A球

    if(ballAX + ballAXMoveLength + 2*ballRadius > screenWidth ||

    ballAX + ballAXMoveLength < 0){         //当在X轴上碰到墙时,X轴行进方向改变

    ballAXMoveLength*=-1;

    }else{

    ballAX += ballAXMoveLength;                 //没碰壁时继续前进

    }

    if(ballAY + ballAYMoveLength + 2*ballRadius > screenHeight ||

    ballAY + ballAYMoveLength < 0){         //当在Y轴上碰到墙时,Y轴行进方向改变

    ballAYMoveLength*=-1;

    }else{

    ballAY += ballAYMoveLength;

    }

    //处理B球

    if(ballBX + ballBXMoveLength + 2*ballRadius > screenWidth ||

    ballBX + ballBXMoveLength < 0){         //当在X轴上碰到墙时,X轴行进方向改变

    ballBXMoveLength*=-1;

    }else{

    ballBX += ballBXMoveLength;                 //没碰壁时继续前进

    }

    if(ballBY + ballBYMoveLength + 2*ballRadius > screenHeight ||

    ballBY + ballBYMoveLength < 0){         //当在Y轴上碰到墙时,Y轴行进方向改变

    ballBYMoveLength*=-1;

    }else{

    ballBY += ballBYMoveLength;

    }

    ballsCollide();   //检查两球是否碰撞

    repaint();    //更新画面

    try{

    Thread.sleep(10);

    }catch(InterruptedException e){

    }

    }

    }

    /**

    * 检查并处理两球碰撞

    * 此处用向量来计算两球碰撞后的速度,具体算法分析请参见”向量几何在游戏编程中的使用”

    */

    public void ballsCollide(){

    if(Math.sqrt((ballAX-ballBX)*(ballAX-ballBX) +              //并没有产生碰撞

    (ballAY-ballBY)*(ballAY-ballBY)) > 2*ballRadius){

    return;

    }else{           //碰撞了

    ballARX = ballAX + ballRadius;  //A球圆心位置

    ballARY = ballAY + ballRadius;

    ballBRX = ballBX + ballRadius;   //B球圆心位置

    ballBRY = ballBY + ballRadius;

    // 求出s'(球心连线上的向量)

    double sx = ballARX – ballBRX ;

    double sy = ballARY – ballBRY ;

    // 求出s1(球心连线上的单位向量)

    double s1x = sx / Math.sqrt(sx*sx + sy*sy) ;

    double s1y = sy / Math.sqrt(sx*sx + sy*sy) ;

    // 求出t'(与球心连线垂直的向量)

    double tx = -sy ;

    double ty = sx ;

    // 求出t1(与球心连线垂直的单位向量)

    double t1x = tx / Math.sqrt(tx*tx + ty*ty) ;

    double t1y = ty / Math.sqrt(tx*tx + ty*ty) ;

    // 求v1a在s1上的投影v1s

    double v1s = ballAXMoveLength * s1x + ballAYMoveLength * s1y ;

    // 求v1a在t1上的投影v1t

    double v1t = ballAXMoveLength * t1x + ballAYMoveLength * t1y ;

    // 求v2a在s1上的投影v2s

    double v2s = ballBXMoveLength * s1x + ballBYMoveLength * s1y ;

    // 求v2a在t1上的投影v2t

    double v2t = ballBXMoveLength * t1x + ballBYMoveLength * t1y ;

    // 用公式求出v1sf和v2sf

    double v1sf = v2s ;

    double v2sf = v1s ;

    // 最后一步,注意这里我们简化一下,直接将v1sf,v1t和v2sf,v2t投影到x,y轴上,也就是v1’和v2’在x,y轴上的分量

    // 先将v1sf和v1t转化为向量

    double nsx = v1sf * s1x ;

    double nsy = v1sf * s1y ;

    double ntx = v1t * t1x ;

    double nty = v1t * t1y ;

    ballAXMoveLength =(nsx + ntx) ;

    ballAYMoveLength =(nsy + nty) ;

    // 然后将v2sf和v2t转化为向量

    nsx = v2sf * s1x ;

    nsy = v2sf * s1y ;

    ntx = v2t * t1x ;

    nty = v2t * t1y ;

    ballBXMoveLength = (nsx + ntx );

    ballBYMoveLength =(nsy + nty );

    //碰撞之后两球速度变化了,可是两球的位置仍处于碰撞时的位置,此时可能导致程序误以后两球再次发生碰撞

    //于是再次处理碰撞,造成程序的死循环,故碰撞后,两球应该以碰撞后的速度迅速产生一段距离避免碰撞的状态

    while(Math.sqrt((ballAX-ballBX)*(ballAX-ballBX) +              //仍旧处于碰撞时的位置

    (ballAY-ballBY)*(ballAY-ballBY)) < 2*ballRadius){

    if(ballAX + ballAXMoveLength + 2*ballRadius > screenWidth ||

    ballAX + ballAXMoveLength < 0){         //当在X轴上碰到墙时,X轴行进方向改变

    ballAXMoveLength*=-1;

    }else{

    ballAX += ballAXMoveLength;                 //没碰壁时继续前进

    }

    if(ballAY + ballAYMoveLength + 2*ballRadius > screenHeight ||

    ballAY + ballAYMoveLength < 0){         //当在Y轴上碰到墙时,Y轴行进方向改变

    ballAYMoveLength*=-1;

    }else{

    ballAY += ballAYMoveLength;

    }

    if(ballBX + ballBXMoveLength + 2*ballRadius > screenWidth ||

    ballBX + ballBXMoveLength < 0){         //当在X轴上碰到墙时,X轴行进方向改变

    ballBXMoveLength*=-1;

    }else{

    ballBX += ballBXMoveLength;                 //没碰壁时继续前进

    }

    if(ballBY + ballBYMoveLength + 2*ballRadius > screenHeight ||

    ballBY + ballBYMoveLength < 0){         //当在Y轴上碰到墙时,Y轴行进方向改变

    ballBYMoveLength*=-1;

    }else{

    ballBY += ballBYMoveLength;

    }

    }

    }

    }

    /**

    * 重新调整屏幕大小

    */

    public void canvasResize(){

    screenWidth = this.getWidth();

    screenHeight = this.getHeight();

    }

    }

    展开全文
  • 小球与小球之间的碰撞,要判断小球在被撞小球的哪个方向,从而判断小球该向哪个方向移动,同样的改变小球的坐标值,来实现小球的反弹 实现代码: <!doctype html> <html lang="en"> <head> <...
  • java实现小球碰撞功能

    2021-03-15 00:44:44
    供大家参考,具体内容如下这次我们做一个小球的碰撞的游戏,规则是:按下添加按钮,窗口的中心部分会产生一个小球(刚开始默认为黑色),四个方向随机产生,发射小球,再次按下即产生个小球。当小球碰到窗体边缘的...

    本文实例为大家分享了java实现小球碰撞的具体代码,供大家参考,具体内容如下

    这次我们做一个小球的碰撞的游戏,规则是:按下添加按钮,窗口的中心部分会产生一个小球(刚开始默认为黑色),四个方向随机产生,发射小球,再次按下即产生两个小球。当小球碰到窗体边缘的时候会产生反弹,当两个小球接触时会产生碰撞,双方交换速度,向相反方向移动。我们可以选择相应的颜色来改变下一个发射的小球颜色。当按下清除可以清除屏幕上的小球,当按下添加则会继续产生小球。最后我们还添加了自动产生小球的功能,按下开关,在屏幕中间会定时产生小球。接下来,我们来展示代码部分。

    public class Jframe {

    private Ball[] arrayball = new Ball[100];

    public static void main(String[] args) {

    Jframe frame = new Jframe();

    frame.showUI();

    }

    public void showUI() {

    javax.swing.JFrame jf = new javax.swing.JFrame();

    jf.setSize(1000, 1000);

    jf.getContentPane().setBackground(Color.WHITE);

    jf.setTitle("小球");

    jf.setDefaultCloseOperation(3);

    // 设置居中显示

    jf.setLocationRelativeTo(null);

    JPanel jp1 =new JPanel();

    JButton jb1 = new JButton("添加");

    jp1.add(jb1);

    // jb1.setBounds(100,50, 40, 20);

    JButton jb2 = new JButton("暂停");

    jp1.add(jb2);

    // jb1.setBounds(200,50, 40, 20);

    JButton jb3 = new JButton("清除");

    jp1.add(jb3);

    // jb1.setBounds(300,50, 40, 20);

    JButton jb4 = new JButton("自动添加");

    jp1.add(jb4);

    jf.add(jp1,BorderLayout.NORTH);

    Mouse mouse = new Mouse();

    Color[] color = {Color.RED,Color.BLUE,Color.BLACK,Color.GREEN,Color.YELLOW};

    for(int i=0;i

    JButton jbu = new JButton();

    jbu.setBackground(color[i]);

    jbu.setPreferredSize(new Dimension(30, 30));

    jp1.add(jbu);

    jbu.addActionListener(mouse);

    }

    jb1.addActionListener(mouse);

    jb2.addActionListener(mouse);

    jb3.addActionListener(mouse);

    jb4.addActionListener(mouse);

    jf.addMouseListener(mouse);

    jf.addMouseMotionListener(mouse);

    BallJpanel cp = new BallJpanel();

    cp.setBackground(Color.WHITE);

    jf.add(cp,BorderLayout.CENTER);

    jf.setVisible(true);

    Graphics g = cp.getGraphics();

    mouse.setcp(cp);

    mouse.setg(g);

    mouse.setarrayball(arrayball);

    mouse.setmouse(mouse);

    cp.setarrayball(arrayball);

    }

    }

    这是窗体的基本配置,采用边框布局,上方放置按钮,中间是画布。我们为按钮添加了动作监听器,并使用了一系列的方法来把对象传递到其他类中。

    public class Ball {

    public int size = 90; // 小球的直径

    public int x = 500; // 小球所在的x坐标

    public int y = 500; // 小球所在的y坐标

    public int vx = 5;

    public int vy = 5;

    public BallJpanel cp;

    public Color color = Color.BLACK;

    public int max_x, max_y, Min_x, Min_y;

    private Ball[] arrayball;

    public void setcp(BallJpanel cp) {

    this.cp = cp;

    }

    public void setarrayball(Ball[] arrayball) {

    this.arrayball = arrayball;

    }

    public void setX(int x) {

    this.x = x;

    }

    public int getX() {

    return x;

    }

    public void setY(int y) {

    this.y = y;

    }

    public int setY() {

    return y;

    }

    public Ball(int x, int y, int vx, int vy, Color color) {

    this.x = x;

    this.y = y;

    this.vx = vx;

    this.vy = vy;

    this.color = color;

    }

    public void ballMove(Graphics g) {

    x += vx;

    y += vy;

    max_y = cp.getHeight();

    max_x = cp.getWidth();

    if (x <= size / 2) {

    x = size / 2;

    vx = -vx;

    }

    if (y <= size / 2) {

    y = size / 2;

    vy = -vy;

    }

    if (x + size / 2 >= max_x) {

    x = max_x - size / 2;

    vx = -vx;

    }

    if (y + size / 2 >= max_y) {

    y = max_y - size / 2;

    vy = -vy;

    }

    for (int i = 0; i < arrayball.length; i++)

    {

    if (arrayball[i] == null)

    break;

    Ball ball = arrayball[i];

    if (this.equals(ball))

    continue;

    if ((ball.x - this.x) * (ball.x - this.x) + (ball.y - this.y) * (ball.y - this.y) <= size * size)

    {

    int tempvx = this.vx;

    int tempvy = this.vy;

    this.vx = ball.vx;

    this.vy = ball.vy;

    ball.vx = tempvx;

    ball.vy = tempvy;

    while ((ball.x - this.x) * (ball.x - this.x) + (ball.y - this.y) * (ball.y - this.y) <= size * size)

    {

    this.x += this.vx;

    this.y += this.vy;

    System.out.println("等待");

    }

    }

    }

    }

    }

    考虑到这是一个小球的运动系统,我们为小球写了一个类,添加小球的时候,会创建小球对象,并使其获得位置,颜色,速度等参数,并将其存入数组。小球的方法就是运动,每当执行ballMove方法,便会为小球修改位置坐标(基于其速度),再判断是否撞击边框,以及判断是否和别的小球有坐标重叠,如果有重叠,则跑一个循环,修改位置坐标,使其分离。Ball这部分代码和监听器中的方法有所联系,我们接下来介绍监听器的方法。

    public class Mouse implements MouseMotionListener, MouseListener, ActionListener {

    private Graphics g;

    private BallJpanel cp;

    private Ball[] arrayball;

    private int index = 0;

    private int x;

    private int y;

    private int vx;

    private int vy;

    private int random=1;

    private Color color=Color.black;

    private ThreadBall tb;

    private Mouse mouse;

    public int selfFlag=0;

    public void setmouse(Mouse mouse)

    {

    this.mouse= mouse;

    }

    public void setarrayball(Ball[] arrayball) {

    this.arrayball = arrayball;

    }

    public void setg(Graphics g) {

    this.g = g;

    }

    public void setcp(BallJpanel cp) {

    this.cp = cp;

    }

    public void actionPerformed(ActionEvent e) {

    if ("添加".equals(e.getActionCommand())) {

    System.out.println("添加");

    if (tb == null) {

    // 创建线程对象

    tb = new ThreadBall();

    tb.setcp(cp);

    tb.setarrayball(arrayball);

    tb.setg(g);

    tb.start();

    tb.setmouse(mouse);

    }

    tb.stopFlag=0;

    addBall();

    }

    if ("暂停".equals(e.getActionCommand())) {

    if(tb!=null)

    {

    if(tb.stopFlag==0)

    {

    tb.stopFlag=1;

    System.out.println("暂停");

    }

    else

    {

    tb.stopFlag=0;

    System.out.println("开始");

    }

    }

    }

    if ("清除".equals(e.getActionCommand())) {

    tb.stopFlag=1;

    cp.paint1(g);

    index=0;

    System.out.println("清除");

    }

    if ("自动添加".equals(e.getActionCommand())){

    if(selfFlag==0)

    {selfFlag=1;System.out.println("自动添加打开");}

    else

    {selfFlag=0;System.out.println("自动添加关闭");}

    }

    if("".equals(e.getActionCommand())){

    JButton jbu=(JButton)e.getSource();

    color=jbu.getBackground();

    g.setColor(color);

    }

    }

    public void mouseDragged(MouseEvent e) {

    }

    public void mouseMoved(MouseEvent e) {

    }

    public void mouseClicked(MouseEvent e) {

    }

    public void mousePressed(MouseEvent e) {

    }

    public void mouseReleased(MouseEvent e) {

    }

    public void mouseEntered(MouseEvent e) {

    }

    public void mouseExited(MouseEvent e) {

    }

    public void addBall() {

    x = 500;

    y = 500;

    random=1+(int)(Math.random()*4);

    switch(random)

    {

    case 1:

    vx=5;

    vy=5;

    break;

    case 2:

    vx=-5;

    vy=-5;

    break;

    case 3:

    vx=5;

    vy=-5;

    break;

    case 4:

    vx=-5;

    vy=5;

    break;

    }

    Ball ball = new Ball(x, y,vx , vy, color);

    arrayball[index++] = ball;

    }

    }

    监听器中,我们设置了一系列参数来控制一些方法的开启和关闭,以及写了添加小球的方法,为其赋初值,随机一个初始发射方向。这段代码我们用到了线程。线程的使用分为两步,创建线程对象并start线程。

    public class ThreadBall extends Thread {

    private Graphics g;

    private BallJpanel cp;

    private Ball[] arrayball;

    public int stopFlag=0;

    private int add=0;

    private Mouse mouse;

    public void setmouse(Mouse mouse)

    {

    this.mouse=mouse;

    }

    public void setcp(BallJpanel cp) {

    this.cp = cp;

    }

    public void setg(Graphics g)

    {

    this.g=g;

    }

    public void setarrayball(Ball[] arrayball) {

    this.arrayball = arrayball;

    }

    /**

    * 启动线程执行的方法

    */

    public void run() {

    while (true) {

    if(stopFlag==0)

    {

    for (int i = 0; i < arrayball.length; i++)

    {

    if(arrayball[i]==null)

    break;

    Ball ball = arrayball[i];

    ball.setarrayball(arrayball);

    ball.setcp(cp);

    ball.ballMove(g);

    }

    cp.paint(g);

    add++;

    if(add==5000)

    add=0;

    if(add%50==0&&mouse.selfFlag==1)

    mouse.addBall();

    }

    try {

    Thread.sleep(50);

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    }

    }

    }

    以上是线程的属性和方法,此类继承Thread并重写了run方法。run方法的思路是循环调用ballMove方法修改小球坐标,并调用paint方法更新显示,我们加入了一个延时函数,来控制调用的频率。

    public class BallJpanel extends JPanel {

    private Ball[] arrayball;

    public void setarrayball(Ball[] arrayball)

    {

    this.arrayball=arrayball;

    }

    public void paint(Graphics g)

    {

    super.paint(g);

    for(int i=0;i

    {

    if(arrayball[i]==null)

    {

    break;

    }

    Ball ball=arrayball[i];

    g.setColor(ball.color);

    g.fillOval(ball.x-ball.size/2, ball.y-ball.size/2, ball.size, ball.size);

    }

    }

    public void paint1(Graphics g)

    {

    super.paint(g);

    for(int i=0;i

    {

    if(arrayball[i]==null)

    {

    break;

    }

    arrayball[i]=null;

    }

    }

    }

    BallJpanel类写的是画布,及小球的运动区域,画笔也是从其对象cp上获得。类里用paint写画面的重绘方法(包括画板小球的重绘),paint1用来清空画布及数组。

    以上便是java小球运动的全部代码,我们来看一下效果。

    306c60802082304a7692bc2b021948c3.png

    06e4c980524ed10ba37105460b693b2c.png

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持免费资源网。

    展开全文
  • 两球完全弹性碰撞反弹方向问题

    千次阅读 2013-01-09 16:16:00
    一、初步分析 中学时候上物理课能够认真听讲的人(我?哦,不包括我)应该很熟悉的记得:当...1)首先我们要排除碰撞球相互作用之外的力,也就是假设没有外力作用于碰撞系统。 2)假设碰撞系统与外界没有能量

    一、初步分析

    中学时候上物理课能够认真听讲的人(我?哦,不包括我)应该很熟悉的记得:当两个球体在一个理想环境下相撞之后,它们的总动量保持不变,它们的总机械能也守恒。但这个理想环境是什么样的呢?理想环境会不会影响游戏的真实性?对于前者我们做出在碰撞过程中理想环境的假设:

    1)首先我们要排除两个碰撞球相互作用之外的力,也就是假设没有外力作用于碰撞系统。

    2)假设碰撞系统与外界没有能量交换。

    3)两个球体相互作用的时间极短,且相互作用的内力很大。

    有了这样的假设,我们就可以使用动量守恒和动能守恒定律来处理它们之间的速度关系了,因为1)确保没有外力参与,碰撞系统内部动量守恒,我们就可以使用动量守恒定律。2)保证了我们的碰撞系统的总能量不会改变,我们就可以使用动能守恒定律。3)两球发生完全弹性碰撞,不会粘在一起,没有动量、能量损失。

    flash中的向量(7)两球碰撞 - tina - 集

    而对于刚才的第二个问题,我的回答是不会,经验告诉我们,理想环境的模拟看起来也是很真实的。除非你是在进行科学研究,否则完全可以这样理想的去模拟。

    现在,我们可以通过方程来观察碰撞前后两球的速度关系。当两球球心移动方向共线(1-D处理)时的速度,或不共线(2-D处理)时共线方向的速度分量满足:

    (1)m1 * v1 + m2 * v2 = m1 * v1' + m2 * v2' (动量守恒定律)

    (2)1/2 * m1 * v1^2 + 1/2 * m2 * v2^2 = 1/2 * m1 * v1'^2 + 1/2 * m2 * v2'^2 (动能守恒定律)

    这里m1和m2是两球的质量,是给定的,v1和v2是两球的初速度也是我们已知的,v1'和v2'是两球的末速度,是我们要求的。好,现在我们要推导出v1'和v2'的表达式:

    由(1),得到v1' = (m1 * v1 + m2 * v2 - m2 * v2') / m1,代入(2),得

    1/2 * m1 * v1^2 + 1/2 * m2 * v2^2 = 1/2 * m1 * (m1 * v1 + m2 * v2 - m2 * v2')^2 + 1/2 * m2 * v2'^2

    => v2' = (2 * m1 * v1 + v2 * (m2 – m1)) / (m1 + m2),则

    => v1' = (2 * m2 * v2 + v1 * (m1 - m2)) / (m1 + m2)

    我们现在得到的公式可以用于处理当两球球心移动方向共线(1-D处理)时的速度关系,或者不共线(2-D处理)时共线方向的速度分量的关系。不管是前者还是后者,我们都需要把它们的速度分解到同一个轴上才能应用上述公式进行处理。

    二、深入分析

    首先我要说明一件事情:当两球碰撞时,它们的速度可以分解为球心连线方向的分速度和碰撞点切线方向的分速度。而由于它们之间相互作用的力只是在切点上,也就是球心连线方向上,因此我们只用处理这个方向上的力。而在切线方向上,它们不存在相互作用的力,而且在理想环境下也没有外力,因此这个方向上的力在碰撞前后都不变,因此不处理。好,知道了这件事情之后,我们就知道该如何把两球的速度分解到同一个轴上进行处理。

    flash中的向量(7)两球碰撞 - tina - 集

    现在看上面的分析图,s和t是我们根据两个相碰球m1和m2的位置建立的辅助轴,我们一会就将把速度投影到它们上面。v1和v2分别是m1和m2的初速度,v1'和v2'是它们碰撞后的末速度,也就是我们要求的。s'是两球球心的位置向量,t'是它的逆时针正交向量。s1是s'的单位向量,t1是t'的单位向量。

    我们的思路是这样的:首先我们假设两球已经相碰(在程序中可以通过计算两球球心之间的距离来判断)。接下来我们计算一下s'和t',注意s'和t'的方向正反无所谓(一会将解释),现在设m1球心为(m1x, m1y),m2球心为(m2x, m2y),则s'为(m1x-m2x, m1y-m2y),t'为s’.rotateNew(PI/2)

    再利用setLength(1)可以将两个向量归一,就得到了s和t的单位向量s1,t1.

    现在s和t轴的单位向量已经求出了,我们根据向量点乘的几何意义,计算v1和v2在s1和t1方向上的投影值,然后将s轴上投影值代入公式来计算s方向碰撞后的速度。注意,根据刚才的说明,t方向的速度不计算,因为没有相互作用的力,因此,t方向的分速度不变。所以我们要做的就是:把v1投影到s和t方向上,再把v2投影到s和t方向上,用公式分别计算v1和v2在s方向上的投影的末速度,然后把得到的末速度在和原来v1和v2在t方向上的投影速度再合成,从而算出v1'和v2'。好,我们接着这个思路做下去:

    先算v1(v1x, v1y)在s和t轴的投影值,分别设为v1s和v1t:

    v1s = v1.s1

    v1t = v1.t1

    再算v2(v2x, v2y)在s和t轴的投影值,分别设为v2s和v2t:

    v2s = v2.s1

    v2t = v2.t1

    接下来用公式

    => v2' = (2 * m1 * v1 + v2 * (m2 – m1)) / (m1 + m2),则

    => v1' = (2 * m2 * v2 + v1 * (m1 - m2)) / (m1 + m2)

    计算v1s和v2s的末值v1s'和v2s',重申v1t和v2t不改变:

    好,下一步,将v1s'和v1t再合成得到v1',将v2s'和v2t再合成得到v2',我们用向量和来做:

    首先求出v1t和v2t在t轴的向量v1t'和v2t'(将数值变为向量)

    v1t' = v1t * t1

    v2t' = v2t * t1

    再求出v1s'和v2s'在s轴的向量v1s'和v2s'(将数值变为向量)

    v1s'= v1s' * s1

    v2s'= v2s' * s1

    最后,合成,得

    v1' = v1t' + v1s'

    v2' = v2t' + v2s'

    从而就求出了v1'和v2'。下面解释为什么说s'和t'的方向正反无所谓:不论我们在计算s'时使用m1的球心坐标减去m2的球心坐标还是相反的相减顺序,由于两球的初速度的向量必有一个和s1是夹角大于90度小于270度的,而另外一个与s1的夹角在0度和90度之间或者说在270度到360度之间,则根据向量点积的定义|a|*|b|*cosA,计算的到的两个投影值一个为负另一个为正,也就是说,速度方向相反,这样就可以用上面的公式区求得末速度了。同时,求出的末速度也是方向相反的,从而在转换为v1s'和v2s'时也是正确的方向。同样的,求t'既可以是用s'逆时针90度得到也可以是顺时针90度得到。

    展开全文
  • 本文实例讲述了javascript实现10个随机运动碰撞的方法。分享给大家供大家参考。具体如下: 学了一段时间的javascript了,做过一些小案例,目前最有难度的就是10个小球随机碰撞效果,这不,把它上上来与大家分享...
  • 小球的随机运动

    2018-10-23 16:19:02
    JavaScript在Canvas上画一个小球,随机位置并且让它随机运动
  • js实现简单的小球与边框碰撞反弹改变运动方向及颜色,并且继续运动特效 思路:首先先实现一个小球的运动和撞边框反弹效果,并且改变其颜色 主要实现方法:1.小球定位,运动靠改变它的position上下左右值;2.获取...

    js实现简单的小球与边框碰撞反弹改变运动方向及颜色,并且继续运动的特效

    (代码可以直接复制使用,只需要把body中的div的id换成对应的就行,css中可以设置小球的大小和初始位置,修改小球大小之后需要在js里把现在的80改成小球的大小值)

    最终实现效果图:

    这里写图片描述

    思路:首先先实现一个小球的运动和撞边框反弹效果,并且改变其颜色,效果如下图:

    这里写图片描述

    主要实现方法:

    1.小球定位,运动靠改变它的position上下左右值;

    2.获取浏览器的宽高,由此设置小球运动的最大范围,大于等于这个范围的时候就改变运动方向;

    3.颜色的改变采用rgb方法,rgb的三个数值均用Math.random随机生成;

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>运动的小球</title>
        <style>
            <!--单个小球的样式-->
            .ball{
                width:80px;
                height:80px;
                background: red;
                border-radius: 50%;
                position:absolute;
                top:0;
                left:0;
            }
        </style>
    </head>
    <body>
        <div class="ball"></div>         <!--单个小球的div-->
    
        <script>
            var oBall = document.querySelector('.ball'),
                leftNum = 5;             //设置小球每次向左运动的像素值
                topNum = 5;              //设置小球每次向下运动的像素值
                leftMax = document.documentElement.clientWidth-oBall.clientWidth;             //浏览器窗口宽度减去小球的宽度等于小球能运动到的最大左边位置,下一行代码同理。
                topMax = document.documentElement.clientHeight-oBall.clientHeight;
            window.onresize = function(){     //当浏览器窗口发生变化时,实时获取浏览器窗口的宽高
                leftMax = document.documentElement.clientWidth-oBall.clientWidth;
                topMax = document.documentElement.clientHeight-oBall.clientHeight;
            }
            setInterval(function(){              //为小球的运动新建一个计时器
                var Left = oBall.offsetLeft+leftNum,    //小球每次运动完之后,距离浏览器左边边框的距离:上一次距离边框的距离加上这次运动的距离,下一行代码同理
                    Top = oBall.offsetTop+topNum;
                //判断当小球向左移动的位置大于之前限定的最大距离或者小于0时,也就是超出浏览器窗口的左右边框时,
                //使他运动的方向取反leftNum = -leftNum,下面Top的判断同理。
                if(Left>=leftMax){               
                    Left = leftMax;
                    leftNum = -leftNum;
                    ballBg(oBall);     //传参数到下面的获取随机颜色的function
                }else if(Left<=0){
                    Left = 0;
                    leftNum = -leftNum;
                    ballBg(oBall);
                };
                if(Top>=topMax){
                    Top = topMax;
                    topNum = -topNum;
                    ballBg(oBall);
                }else if(Top<=0){
                    Top = 0;
                    topNum = -topNum;
                    ballBg(oBall);
                };
                oBall.style.left = Left+'px';      
                oBall.style.top = Top+'px';
    
            },30);                        //小球每次执行运动的时间
    
            function ballBg(obj){             //随机获取小球颜色
                var r = Math.floor(Math.random()*256);
                    g = Math.floor(Math.random()*256);
                    b = Math.floor(Math.random()*256);
                   obj.style.backgroundColor = 'rgb('+r+','+g+','+b+')';
            }
        </script>
    </body>
    </html>

    一个小球的运动实现之后,当实现多个小球的时候,有两个问题需要考虑:

    1.小球数量不能写死,万一数量很多,所以最好不要用div写,而是用appendChild的方法追加,这样,原来<div class="ball"></div>单个;小球的div需要改成<div id="ball"></div> 一个大的div,然后往这个大的div中追加<div class="ball"></div>

    2.小球的运动起点虽然相同,但是运动速度不能相同,不然所有的小球都会重叠在一起运动;

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>运动的小球</title>
        <style>
            .ball{
                width:80px;
                height:80px;
                background: red;
                border-radius: 50%;
                position:absolute;
                top:0;
                left:0;
            }
        </style>
    </head>
    <body>
        <div id="ball"></div>
    
        <script>
            var oBall = document.querySelector('#ball'),
                leftNum = 0,
                topNum = 0,
                aBall = null,
                length = 0;
    
            reSize();    
            window.onresize = reSize;
    
            function reSize(){
                leftMax = document.documentElement.clientWidth-80;
                topMax = document.documentElement.clientHeight-80;
            }
    
            creatBall(oBall,10);         //传参,往oBall里面追加10个小球
            aBall = oBall.children;      //获取oBall里面的所有小球
            length = aBall.length;
            function creatBall(obj,num){     //创建小球的function
                for(var i=0;i<num;i++){
                    var cBall = document.createElement('div');
                    cBall.className = 'ball';
                    ballBg(cBall);
                    cBall.leftNum=cBall.topNum=(i+1)*1;    //这里去i+1而不取i的原因是,一个小球的i为0,如果不取i+1,那么第一个小球会永远在左上角不动并且不停地变颜色
                    obj.appendChild(cBall);
                };
            };
    
            setInterval(function(){       //这里注意需要将之前所有对oBall设置的都换成aBall[i]
                for (var i=0;i<length;i++ ){
                    var Left = aBall[i].offsetLeft+aBall[i].leftNum,
                    Top = aBall[i].offsetTop+aBall[i].topNum;
                if(Left>=leftMax){
                    Left = leftMax;
                    aBall[i].leftNum = -aBall[i].leftNum;
                    ballBg(aBall[i]);
                }else if(Left<=0){
                    Left = 0;
                    aBall[i].leftNum = -aBall[i].leftNum;
                    ballBg(aBall[i]);
                };
                if(Top>=topMax){
                    Top = topMax;
                    aBall[i].topNum = -aBall[i].topNum;
                    ballBg(aBall[i]);
                }else if(Top<=0){
                    Top = 0;
                    aBall[i].topNum = -aBall[i].topNum;
                    ballBg(aBall[i]);
                };
                aBall[i].style.left = Left+'px';
                aBall[i].style.top = Top+'px';
                }   
            },30);
    
            function ballBg(obj){
                var r = Math.floor(Math.random()*256);
                    g = Math.floor(Math.random()*256);
                    b = Math.floor(Math.random()*256);
                obj.style.backgroundColor = 'rgb('+r+','+g+','+b+')';
            }
    
        </script>
    </body>
    </html>

    以上,好多小球的碰撞效果就完成了,代码有问题或者还有可以优化的地方,请指教,如果您觉得这篇文章对您有帮助,麻烦点个赞吧~~

    展开全文
  • 基于Directx9实现的小球碰撞检测,实现的真实的碰撞算法,根据碰撞方向进行坐标轴分解,完美模拟真实物理碰撞,极具有参考意义,亲测能用。
  • J2ME中小球碰撞检测之后自动反弹,算法设计非常精巧
  • 资源介绍:对球体进行方向角度和速度的调整碰撞。可以将其应用到台球游戏中。资源作者:易语言源码如何使用资源界面:资源下载:
  • QT5-实现小球运动碰撞

    千次阅读 2019-11-05 16:17:58
    QT实现小球运动碰撞思路程序结构设置运动速度画出小球boundingRect和Shape函数运动碰撞反弹 编程工具为vs2010+qt 5.1.2 思路 由于第一次刚使用qt,所以就写写博客分享一个qt新手从入门到放弃这个过程。 这个小设计...
  • 天在研究canvas碰撞 先把小球开始运动的图拿出来 参考了一下别的的代码,在个小球碰撞处理上,我觉得不完善 怎么样处理才算完善呢,当然是要用高中物理学的动量守恒了和机械能守恒了 机械能守恒我...
  • 解决了擦边碰撞不正常的情况。2. 更新了碰撞回掉函数的调用情况。避免了刚出现小球时如果重叠一直调用的情况。使用方法说明1.此插件纯原生js编写,使用时引入此collision.js即可。2.生成容器,假设现有一个id为...
  • 主要为大家详细介绍了js控制小球在规定范围运动,碰到边界就改变运动方向,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 个小球碰撞速度计算方法

    万次阅读 2014-01-23 17:43:45
    一 . 碰撞的特点和简化处理 : ...1. 对心碰撞碰撞前后的速度都沿两球的连心线,也叫 一维碰撞 。 2. 碰撞过程 : ① 压缩过程 :从小球开始接触到小球达到共同速度。( b )和( c )图,特点: ② 恢
  • JavaScript实现小球...碰撞反弹,当碰撞到容器的边缘,进行反弹,反向改变坐标。首先创建Screen类,并在Screen的构造函数中给出了移动、碰撞所需的各种属性变量,如ballsnum、spring、bounce、gravity等等 ...
  • java实现小球的碰撞

    千次阅读 2018-11-03 00:29:01
    这次我们做一个小球的碰撞的游戏,规则是:按下添加按钮,窗口的中心部分会产生一个小球(刚开始默认为黑色),四个方向随机产生,发射小球,再次按下即产生个小球。当小球碰到窗体边缘的时候会产生反弹,当个...
  • 简单介绍 小球可以在方框内部自由运动 可以通过方向键控制黑色砖块上下左右移动去与小球发生碰撞 代码实现 复制代码代码如下: <!– To change this template, choose Tools | Templates and open the template ...
  • csp试题2:碰撞的小球

    2019-09-22 21:30:22
    csp试题2:碰撞的小球题目分析代码总结 题目 问题描述       数轴上有一条长度为L(L为偶数)的线段,左端点在原点,右端点在坐标L处。有n个不计体积的小球在线段上,开始时所有的小球...
  • 最近在写随机拖地机的状态机程序,因为底层驱动封装暂时未完成,无法上机实测。就打算写一个上位机,模拟拖地机随机运动。 本篇先记录随机小球运动模拟,后续再把状态机添加...#创建一个类,这个类含有个参数,一...
  • 注册x在高中物理中我就学到物体的平抛运动,今天我们在这里也老调重弹下,再次来回顾下这个经典的过程,不过这次讲解的要比之前平抛运动稍微复杂一些:$ Q- f# I$ |* `& R) l# G3 g* }/ l' g4 }小球的上抛运动的...
  • Java 实现小球碰撞GUI

    2021-02-12 01:24:21
    最后一次更新于2019/07/08修复问题:错误输入未提醒问题碰撞小球的图形重叠问题...涉及动能定理就需要考虑质量了,除此之外常规的几个变量也不能忘:方向的尺寸,所在位置以及当前速度。2. 谁能初始小球的状态...
  • js 小球碰壁反弹and小球碰撞

    万次阅读 2016-08-31 16:42:58
    好像好几天没有更博了呢,...如图~这个样子放上好像有点单调,这个案例就是实现了多个小球的同时碰壁反弹,并且不同的小球碰撞后也可发生碰撞反应,相应的小球运动方向也会发生改变。什么事情都要从简单开始,一点一
  • 资源内容:绘制递归小球,在给定初始速度以及方向的情况下在包围盒内运动,碰到包围盒按物理规律反弹 语言:C++ 运行环境:Visual Studio 2013/更高版本
  • #本人原创,费了不少功夫计算...#两球的位置和速度,R为半径,这里设质量一样,容易加上不同的质量和半径def collide(loc1,loc2,sp1,sp2): x,y=loc1 x2,y2 = loc2 dlx,dly = x-x2,y-y2 dx,dy = sp1 dx2,dy2 = sp2 ...
  • 上次一我实现了球碰撞后运动轨迹计算,这回要实现球的旋转。 1.角动量 我觉得这里应该用到角动量了,当球与球碰撞之后,球自身会因为碰撞点有摩擦力,导致球旋转的,主要就是来求这个旋转的速度,这里就是角速度...
  • Qt实现小球碰撞动画——屏保

    千次阅读 2018-07-29 15:54:41
    1、小球可以沿着一个随机的方向运动 2、运动时可以加减速 3、随时切换小球形状(圆形,正方形,三角形) 4、碰撞到边框时镜像反弹 5、小球的运动轨迹可以实时显示,边框设置为正方形时更容易画出美丽的图案哦 6...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,637
精华内容 2,254
关键字:

两球碰撞后的运动方向