Can’t flip direction of ball without messing up gravity

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

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:

preview

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)

Leave a Comment