Can't flip direction of ball without messing u

2019-03-07 02:18发布

问题:

I am making a game like pong except that there is only one paddle and the ball moves in projectile motion. The goal is to keep the ball bouncing on your paddle for as long as possible. I when I have the ball hit the paddle the direction of the y component of the velocity has it's sign flipped. The issue with this is that when the ball is moving up gravity acts upon in in that direction, speeding it up. The code is below

This is the code for my ball class, this is the tick method which is called 60 times a second

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;

    }

}

This is my ball Trajectory class which handles all the math for this

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;
}

And I have tried to use an if statement with y reflection to make 9.8 negative when yreflection is 1 and positive when it is -1.

回答1:

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

  • Bouncing Ball Making it slow down at peak of height
  • My Algorithm to Calculate Position of Smartphone - GPS and Sensors

    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[3],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'Lambert 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)