1

So here is the full code, but the problem is in the class Ball where my function move is. What happens when it executes is that the ball bounces and starts going lower and lower, just like real life. But when it hits the limit of how low it can go, the ball starts going under the limit. I am very sorry for having taken your time.

from selectors import SelectorKey
from tkinter import Y
import pygame

pygame.init()
width, height = 1000, 600
Win = pygame.display.set_mode((width, height))
clock = pygame.time.Clock()
Acs = 0.5


class Ball():
    def __init__(self):
        self.y = 200
        self.velocity = 10
        self.bouncy = 1

    def draw(self):
        pygame.draw.circle(Win, (255, 0, 0), (500, self.y), 15)

    def move(self):
        self.velocity += Acs
        self.y += self.velocity
        print(self.velocity)
        if self.y > 400:
            self.velocity = -self.velocity + self.bouncy
        if self.y <= 400:
            self.velocity == 0
            self.bouncy == 0
            self.y == 400


def game():
    ball = Ball()
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return
        ball.move()

        Win.fill((255, 255, 255))
        pygame.draw.line(Win, (0, 0, 0), (0, 400), (1000, 400), 10)
        ball.draw()
        clock.tick(60)
        pygame.display.update()


game()
pygame.quit()


where I have a problem is here:

    def move(self):
        self.velocity += Acs
        self.y += self.velocity
        print(self.velocity)
        if self.y > 400:
            self.velocity = -self.velocity + self.bouncy
        if self.y <= 400:
            self.velocity == 0
            self.bouncy == 0
            self.y == 400
Ali Wapiti
  • 25
  • 3

1 Answers1

2

The problem with bouncing balls (and every non-linear physics simulation where you have very drastic changes) is that your simulation might put you below the limit in a single time step, so you have to make sure that you enforce the limit. A simple way to fix that for a game is to force the y position when you hit the floor. Change your move method to this and it works (note that the if self.y <= 400: branch didn't do anything, so I removed it).

    def move(self):
        self.velocity += Acs
        self.y += self.velocity
        if self.y > 400:
            self.velocity = -self.velocity + self.bouncy
            self.y = 400  # Ensure the limits

For a slightly more realistic bouncing effect, you can use your self.bouncy attribute as an actual coefficient of restitution and change slightly the formula for the bounce. 5% of loss every bounce gave a reasonably good result.

class Ball():
    def __init__(self):
        self.y = 200
        self.velocity = 10
        self.bouncy = 0.05  # Now a coefficient of restitution

    def draw(self):
        pygame.draw.circle(Win, (255, 0, 0), (500, self.y), 15)

    def move(self):
        self.velocity += Acs
        self.y += self.velocity
        if self.y > 400:  # Note that the loss of velocity is a function of the previous velocity
            self.velocity = -self.velocity + self.bouncy*self.velocity
            self.y = 400  # Ensure the limits
nonDucor
  • 2,057
  • 12
  • 17