1

我正在使用处理java库来模拟使用牛顿物理学在两堵墙之间弹跳的球;水平速度是一个常数,因为没有加速度。我让模拟工作,但是我想指定地板的高度。然而,在我的方程式中,当球距离屏幕底部 10 像素时尝试改变方向时,每次反弹后,球在“地板”下方越来越低。如果我将地板提高到 >20 像素,球不会停止,而是无限期地反弹。这是相关代码: 请注意,处理的坐标系从顶部开始,向下和向右运行。我在这里先向您的帮助表示感谢。

public class Testing extends PApplet {

boolean inFloor=false; 
float xPosition=500;
float yPosition=200;
float xVelocity=25;
float yVelocity=-80.0f;
float yAccelleration=+10.0f;
float elasticity=0.80f;

public void setup (){
  size(displayWidth,displayHeight);
  noStroke();
  ellipseMode(RADIUS);
  frameRate(35);
}
 public boolean sketchFullScreen() {
  return true;
 }



public void draw(){
    background(0);
    //Changes direction of motion when hitting a wall
    if(xPosition>=displayWidth||xPosition<0){
        xVelocity=-xVelocity;
    }
    //supposed to change direction of motion when the ball hits the floor
    if(yPosition>=displayHeight-20){
        yPosition=(displayHeight-20);    
        yVelocity=-(yVelocity)*elasticity;
        if(yVelocity>=-1 && yVelocity<=0){
            xVelocity=xVelocity*elasticity;
            yVelocity=0; 
            yAccelleration=0;
        }    
    }
    else{
        yVelocity=yVelocity+yAccelleration;
    }

    yPosition=yVelocity+yPosition;
    xPosition=xPosition+xVelocity;
    ellipse(xPosition,yPosition,10,10);
}

编辑:这可能是时间问题吗?

编辑:感谢您的所有回复。不幸的是,我不能对其中任何一个进行投票(只有 6 个代表)。我结合了@tobius_k 的答案、@Roberto_Mereghetti 的答案以及来自OpenProcessing.org的一些示例代码,从而解决了它。在下面提供的解决方案中,由于画布以像素(整数值)为单位进行测量,因此使用浮点数来指定坐标会导致处理过程中出现图形故障。所以我实现了一个系统,其中浮点值被四舍五入,十进制值被添加到累加器(“xRounder”和“yRounder”),当大于 -1 或 1 时被四舍五入并添加到 Ball 的当前位置。这给了我一个地板!

最终代码:

    import processing.core.*; 
    //import processing.xml.*; 

    import java.applet.*; 
    import java.awt.Dimension; 
    import java.awt.Frame; 
    import java.awt.event.MouseEvent; 
    import java.awt.event.KeyEvent; 
    import java.awt.event.FocusEvent; 
    import java.awt.Image; 
    import java.io.*; 
    import java.net.*; 
    import java.text.*; 
    import java.util.*; 
    import java.util.zip.*; 
    import java.util.regex.*; 

    public class Testing extends PApplet {
    int xPosition=500;
    int yPosition=200;
    float xRounder=0;
    float yRounder=0;
    float xVelocity=25;
    float yVelocity=-80.0f;
    float yAccelleration=+10.0f;
    float elasticity=0.80f;
    public void setup (){
    size(displayWidth,displayHeight);
    noStroke();
    ellipseMode(RADIUS);
    frameRate(15);
    }
    public boolean sketchFullScreen() {
      return true;
    }

     /* (non-Javadoc)
     * @see processing.core.PApplet#draw()
     */
    public void draw(){
    background(0);

    yPosition=round(yVelocity)+yPosition;
    yRounder+=(yVelocity-round(yVelocity));
    xPosition=round(xVelocity)+xPosition;
    xRounder+=(xVelocity-round(xVelocity));

    if(xRounder>=1||xRounder<=-1){
        xPosition=xPosition+round(xRounder);
        xRounder=xRounder-round(xRounder);
    }
    if(yRounder>=1||yRounder<=-1){
        yPosition+=round(yRounder); 
        yRounder=yRounder-round(yRounder);
    }

    if(yPosition>displayHeight-50 && yVelocity>0){
        yPosition=displayHeight-50;
        yVelocity=-(yVelocity)*elasticity;  
        xVelocity=xVelocity*elasticity;


    }

    if(xPosition>=displayWidth||xPosition<0){
    xVelocity=-xVelocity;
    }
    yVelocity=yVelocity+yAccelleration;  




    ellipse(xPosition,yPosition,10,10);


    }

        static public void main(String args[]) {
           PApplet.main(new String[] { "--bgcolor=#ECE9D8", "Testing" });
    //      new Testing().setVisible(true);
        }
    }
4

2 回答 2

0

这是我的解决方案。问题出在这一行:

 if(yVelocity>=-yAccelleration && yVelocity<=yAccelleration){

这是使用每个 yAcceleration 值停止球的唯一方法。

public void draw(){
    background(0);
    if(xPosition>=displayWidth||xPosition<0){
        xVelocity=-xVelocity;
    }

    if((yPosition>=displayHeight-40.0) && yVelocity>0){
        yPosition=(displayHeight-20);    
        yVelocity=-yVelocity*elasticity;
        if(yVelocity>=-yAccelleration && yVelocity<=yAccelleration){
            xVelocity=xVelocity*elasticity;
            yVelocity=0; 
            yAccelleration=0;
        }    
    }
    else{
        yVelocity=yVelocity+yAccelleration;
    }
    yPosition=yVelocity+yPosition;
    xPosition=xPosition+xVelocity;
    ellipse(xPosition,yPosition,10,10);
}
于 2012-09-09T15:53:30.523 回答
0

我不是 100% 肯定,但我认为通过在球实际到达底线以下几个像素时将球重置到底线,您可以完全补偿弹性系数,从而使球无限期地反弹。

尝试删除线yPosition=(displayHeight-20);,然后它应该工作得更好。

这样,球最终会停下来,但这仍然不正确,因为根本不计算球落地的时间。

更新好吧,我想现在我已经明白了。以下是相关位:

// first update position, then update velocity
yPosition=yVelocity+yPosition;
if (yPosition >= floor) {
    // invert velocity and position w/ elasticity applied
    yVelocity = -yVelocity * elasticity;
    yPosition = floor - (yPosition - floor) * elasticity;
}
if(Math.abs(yVelocity) <= 2 && Math.abs(yPosition - floor) <= 2){
    // stop everything when close to rest
    yPosition=floor;
    yVelocity=0; 
} else {
    // otherwise accelerate, even after bounce
    yVelocity=yVelocity+yAccelleration;
}

因此,您的代码的主要更改是:

  1. 首先更新位置,然后更新速度
  2. 而不是将球重置到地板上,恢复它从地板上掉下来的量,并将弹性系数应用于那个
  3. 总是加速球,即使它从地板上反弹

这里是它的样子(地板是 500)。不完美,但很接近。

在此处输入图像描述

更新 2:刚刚发现这个处理示例,它实际上非常接近您的原始代码,不同之处在于它们总是应用加速,并且它们在碰撞检查之前这样做。似乎仅此一项就可以解决问题。

于 2012-09-09T16:26:14.080 回答