0

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.

When the ball is hit by the paddle, the y component of its velocity has it's sign flipped. The issue with this is that gravity also acts upon the ball, so when a ball is hit upwards it to speeds up due to the reversed effect of gravity.

This is the code for the ball class, including 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 the ball Trajectory class which handles all the math:

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

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

cybersam
  • 63,203
  • 6
  • 53
  • 76
CRT TV
  • 185
  • 2
  • 8
  • I don't know how to rewrite the code to do so... I have tried adding the gravity separately from the velocity calculation and flipping the sign of the velocity to the appropriate direction before adding gravity but that breaks my collision detecion – CRT TV Dec 05 '18 at 14:42
  • When I tried to rewrite my code using the model in the bouncing ball example my ball just moves extremely fast and It doesn't work – CRT TV Dec 05 '18 at 15:39
  • No matter what I do this won't work I have tried tweaking everything – CRT TV Dec 05 '18 at 16:27
  • I just figured it out, the issue was double collisions not math.I just needed to displace the ball up by the distance of the ball after a collision to avoid this. Thank you for the help, sorry to bother – CRT TV Dec 05 '18 at 16:52
  • I moved the comments into answer along small C++ example with friction – Spektre Dec 05 '18 at 17:26

1 Answers1

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

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)

Spektre
  • 49,595
  • 11
  • 110
  • 380