我正在使用processing 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);
}
}
答案 0 :(得分: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);
}
答案 1 :(得分:0)
我不是百分百确定,但我认为通过将球重置到底线,当它实际到达以下底线时,你会完全补偿弹性系数,这样就可以了球无限期地反弹。
尝试删除行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;
}
所以主要的变化是w.r.t.你的代码是:
这就是它的样子(地板在500)。不完美,但很接近。
更新2 :刚刚找到了this Processing example,它实际上与原始代码非常接近,区别在于它们始终应用加速,并且它们是在碰撞检查之前执行。好像这样就好了。