Bouncing Ball with Gravity

Screen shot of bouncing ball
bouncing_ball.py
 1"""
 2Bounce a ball on the screen, using gravity.
 3
 4If Python and Arcade are installed, this example can be run from the command line with:
 5python -m arcade.examples.bouncing_ball
 6"""
 7
 8import arcade
 9
10# --- Set up the constants
11
12# Size of the screen
13SCREEN_WIDTH = 600
14SCREEN_HEIGHT = 600
15SCREEN_TITLE = "Bouncing Ball Example"
16
17# Size of the circle.
18CIRCLE_RADIUS = 20
19
20# How strong the gravity is.
21GRAVITY_CONSTANT = 0.3
22
23# Percent of velocity maintained on a bounce.
24BOUNCINESS = 0.9
25
26
27def draw(_delta_time):
28    """
29    Use this function to draw everything to the screen.
30    """
31
32    # Start the render. This must happen before any drawing
33    # commands. We do NOT need an stop render command.
34    arcade.start_render()
35
36    # Draw our rectangle
37    arcade.draw_circle_filled(draw.x, draw.y, CIRCLE_RADIUS,
38                              arcade.color.BLACK)
39
40    # Modify rectangles position based on the delta
41    # vector. (Delta means change. You can also think
42    # of this as our speed and direction.)
43    draw.x += draw.delta_x
44    draw.y += draw.delta_y
45
46    draw.delta_y -= GRAVITY_CONSTANT
47
48    # Figure out if we hit the left or right edge and need to reverse.
49    if draw.x < CIRCLE_RADIUS and draw.delta_x < 0:
50        draw.delta_x *= -BOUNCINESS
51    elif draw.x > SCREEN_WIDTH - CIRCLE_RADIUS and draw.delta_x > 0:
52        draw.delta_x *= -BOUNCINESS
53
54    # See if we hit the bottom
55    if draw.y < CIRCLE_RADIUS and draw.delta_y < 0:
56        # If we bounce with a decent velocity, do a normal bounce.
57        # Otherwise we won't have enough time resolution to accurate represent
58        # the bounce and it will bounce forever. So we'll divide the bounciness
59        # by half to let it settle out.
60        if draw.delta_y * -1 > GRAVITY_CONSTANT * 15:
61            draw.delta_y *= -BOUNCINESS
62        else:
63            draw.delta_y *= -BOUNCINESS / 2
64
65
66# Below are function-specific variables. Before we use them
67# in our function, we need to give them initial values. Then
68# the values will persist between function calls.
69#
70# In other languages, we'd declare the variables as 'static' inside the
71# function to get that same functionality.
72#
73# Later on, we'll use 'classes' to track position and velocity for multiple
74# objects.
75draw.x = CIRCLE_RADIUS                  # type: ignore # dynamic attribute on function obj  # Initial x position
76draw.y = SCREEN_HEIGHT - CIRCLE_RADIUS  # type: ignore # dynamic attribute on function obj  # Initial x position
77draw.delta_x = 2                        # type: ignore # dynamic attribute on function obj  # Initial x position
78draw.delta_y = 0                        # type: ignore # dynamic attribute on function obj  # Initial x position
79
80
81def main():
82    # Open up our window
83    arcade.open_window(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
84    arcade.set_background_color(arcade.color.WHITE)
85
86    # Tell the computer to call the draw command at the specified interval.
87    arcade.schedule(draw, 1 / 80)
88
89    # Run the program
90    arcade.run()
91
92    # When done running the program, close the window.
93    arcade.close_window()
94
95
96if __name__ == "__main__":
97    main()