java 如果不打乱重力,就无法翻转球的方向

ekqde3dh  于 2022-12-02  发布在  Java
关注(0)|答案(1)|浏览(77)

我正在做一个类似乒乓球的游戏,除了只有一个球拍,球以抛射运动的方式运动。目标是让球在球拍上反弹尽可能长的时间。当我让球击中球拍时,速度的y分量的方向有它的符号翻转。这个游戏的问题是,当球向上运动时,重力作用在那个方向上。加速。代码如下
这是我的ball类的代码,这是每秒调用60次的tick方法

public Ball(double x, double y, Game game) {
    super(x,y);
    this.game=game;
}
public void tick() {
        time+=1.0/60.0;
        if(x<=0)
            xreflection=1.0;
        else if(x>=Game.Width-15)
            xreflection=-1.0;
        if(y<=0)
            yreflection=1.0;
        else if(y>=Game.Height-15)
            gameover=1;//different variable here as I use this to end the game if the ball hits the bottom of the screen
    x+=traj.xvel()*xreflection;
    y-=traj.yvel(time)*yreflection;

    if(Physics.Collision(this, game.getP())) {
    time=2;
        System.out.println("Collision");
        yreflection=-1;

    }

}

这是我的球轨迹课,它处理所有的数学问题

public double xvel() {
    double xvelo=initvel*Math.cos(Math.toRadians(theta));
    return xvelo;
}

public double yvel(double time) {
    double yvelo;
        yvelo=initvel*Math.sin(Math.toRadians(theta))-(9.8*time);
    return yvelo;
}

我试着用if语句和y反射,当y反射为1时,使9.8为负,当y反射为-1时,使9.8为正。

3ks5zfa0

3ks5zfa01#

you are not really doing reflection ... to reflect by major axis you should negate the appropriate coordinate of the speed vector (and correct the position) I do not see such behavior in your code. Instead your y velocity has no sign regardless of the direction up/down hence you just add gravity acc to it ... to remedy either rewrite the code or add the yreflection to your gravity related code too... also you got theta? I would expect angle only in the first shooting
see

You just use/add forces you want to use. But in your collision once you detect you are inside wall you need to correct the position along with the reflection of speed too otherwise you risk double collisions ...
Here small C++ example with air friction:

//---------------------------------------------------------------------------
double pos[2],vel[2],acc[2],r;  // ball
double x0,y0,x1,y1;             // walls
//---------------------------------------------------------------------------
void ball_update(double dt)
    {
    int i;
    double v,k=0.0001,g=9.81;
    dt*=10.0;                                   // time multiplier for simulation speed ...
    // compute driving force/acceleration
    v=sqrt((vel[0]*vel[0])+(vel[1]*vel[1]));    // |vel|
    acc[0]=  -(k*vel[0]*v);                     // gravity + air friction (k*vel^2)
    acc[1]=+g-(k*vel[1]*v);
    // Newton/D'Alembert simulation
    for (i=0;i<2;i++) vel[i]+=acc[i]*dt;
    for (i=0;i<2;i++) pos[i]+=vel[i]*dt;
    // colision/reflect
    if (pos[0]<x0+r){ pos[0]=x0+r; vel[0]=-vel[0]; }
    if (pos[0]>x1-r){ pos[0]=x1-r; vel[0]=-vel[0]; }
    if (pos[1]<y0+r){ pos[1]=y0+r; vel[1]=-vel[1]; }
    if (pos[1]>y1-r){ pos[1]=y1-r; vel[1]=-vel[1]; }
    }
//---------------------------------------------------------------------------
void ball_init()
    {
    Randomize();
    pos[0]=0.5*(x0+x1);
    pos[1]=0.5*(y0+y1);
    double a=2.0*M_PI*Random(),v=50.0;
    vel[0]=v*cos(a);
    vel[1]=v*sin(a);
    r=20.0;
    }
//---------------------------------------------------------------------------

My coordinate system is (0,0) is top left and x point right and y points down ... To use this just init the walls x0,y0,x1,y1 call the ball_init() and then in some timer call ball_update(dt) and render ball at pos and radius r ...
This is how it look like:

PS. You need to tweak the parameters like delta time dt , accelerations or add pixel scale to match your needs... You need to have all units compatible ... I recommend using SI (m,m/s,m/s^2,s,N,.. ) so you also need to decide how big is pixel (in meters)

相关问题