Hi
I want the code below to create a ball that bounces on the bottom of the screen as well as on platforms. The bottom isn’t really the issue here, its just easier to create the problem when including it.
Problem: The ball tends to being slowly suck through the platforms when bouncing against them from below. Only happens occasionally and when Platforms move()
.
What i found out: I know this problem is rather common. Found an article on the former forum that is about a ball bouncing in a canvas https://forum.processing.org/two/discussion/19877/why-does-the-ball-get-stuck-on-canvas. But either i do not get the solutions or they don’t work out due to the platforms moving.
I think i get why it happens(please confirm if i am right). Due to how the velocity
of the ball is created by adding gravity
every time to it, the speed varies.
It can happen that it first bounces against the Platform. The next time draw()
is executed the Platform moves down as far or further or just a little less than the ball. That way, the bounce()
condition is true again, the velocity is reversed and it goes up.
The code so far(fat part is where problem is):
Ball ball = new Ball();
int size = 7;
Platform[] platforms = new Platform[size];
void setup()
{
size(300, 400);
for (int i=0; i<size; i++) {
platforms[i] = new Platform();
}
}
void draw()
{
background(23);
if(keyPressed) {
ball.move();
}
for (int i=0; i<size; i++) {
platforms[i].move();
ball.bounce(platforms[i]);
platforms[i].display();
}
ball.display();
}
class Ball
{
PVector xy;//current position
PVector velocity;
float d;//diameter
color col;
float gravity = 9.81/60*d;
Ball()
{
xy = new PVector (100, 150);
velocity = new PVector (0, 0);
d = 14;
col = color(20, 490, 430 );
gravity = 9.81/60/30;
}
void display()
{
fill(col);
ellipse(xy.x, xy.y, d, d);
}
void move()
{
if (key == 'd') {
xy.x+=2;
background(0, 200, 0);
}
if (key == 'a')
xy.x-=2;
}
**void bounce(Platform other)**
** {**
** if (xy.y >= height||**
** (((xy.y+d/2 >= other.xy.y) && (xy.y -d/2 <= other.xy.y )) &&//if platform**
** ((xy.x >= other.xy.x) && (xy.x <= other.xy.x+other.w)))) {**
** velocity.y = -velocity.y;**
** } else {**
** velocity.y += gravity;**
** }**
** xy.add(velocity);**
** }**
}
class Platform
{
PVector xy;
color col;
float w, h;
float yspeed = 0.6;
Platform()
{
xy = new PVector(random(width), random(height));
col = color(20, 490, 430 );
w = 50;
h = 4;
}
void display()
{
fill(col);
rect(xy.x, xy.y, w, h, 2);
}
void move()
{
xy.y += yspeed;
if (xy.y >= 400)
xy.y = 0;
}
}
What i tried in order to prevent this:
I tried to introduce a variable called check
to notice whether the ball bounced the last time draw was called. In that case it should just ignore the bounce. I am still trying around with that solution but it gets kind of difficult because i have to store the check values in some array as i got an array of platforms…
I replaced the fat code(bounce) by this
if ((((xy.y+d/2 >= other.xy.y) && (xy.y -d/2 <= other.xy.y + other.h ))) &&//if platform
((xy.x >= other.xy.x) && (xy.x <= other.xy.x+other.w)) &&
velocity.y<0) {//and velocity smaller zero
velocity.y = abs(velocity.y);//make speed positive
xy.y = other.xy.y + other.h + d/2;//set ball position below platform
}
else if ((((xy.y+d/2 >= other.xy.y) && (xy.y -d/2 <= other.xy.y + other.h ))) &&//if platform
((xy.x >= other.xy.x) && (xy.x <= other.xy.x+other.w)) &&
velocity.y>0) {//and velocity positive
velocity.y = -abs(velocity.y);//make speed negative
xy.y = other.xy.y - other.h - d/2;//set ball position above platform
}
else if (xy.y >= height) {
velocity.y = -abs(velocity.y);
}
else {
velocity.y += gravity;//if speed isnt reversed add gravity
}
xy.add(velocity);
Problem here: As the position of the ball is changed the maximum height of the ball changes. I also can’t just leave out the position change because if the platforms moves faster than the ball at a specific point, the ball will first hit it with negative velocity, velocity will get positive, the ball will go down and hit the platform that overtook him with positive speed.
Of course i could set the speed and therefore maximum height new every time the ball hits the floor.
But can someone tell me if there is another solution?
Thx