1

私は処理Javaライブラリを使用して、ニュートン物理学を使用して2つの壁の間で跳ねるボールをシミュレートしています。加速度がないため、水平速度は一定です。シミュレーションは動作しましたが、床の高さを指定したいと思います。ただし、私の方程式では、ボールが画面の下部から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のサンプルコードを組み合わせて、それを解決しました。以下に示すソリューションでは、キャンバスはピクセル(整数値)で測定されるため、座標を指定するためにfloatを使用すると、処理でグラフィックの不具合が発生していました。そこで、フロート値が丸められるシステムを実装しました。アキュムレータ("xRounder"および"yRounder")に小数値が追加され、-1または1より大きい場合は丸められ、ボールの現在の位置に追加されます。これは私に床を与えました!

最終コード:

    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 に答える