I am making a game and I have a problem with my code one mathematic function in ball speed has some fluctuations because Python can not calculate with 100% accuracy.
In normal code, it is not a problem but because I have a condition to change the type of movement from rising to falling it is set on some value which is interesting.
If I change this number to 300 it will do just one cycle of falling and rising but if I change it to 320 it will make a few.
The problem is that y coordination of the ball is so random ChatGPT said to me that it is because this fluctuation will accumulate but the last ball_y is so random sometimes it is 319 next 317, 320, but if it jumps on 322 or something bigger then 320 it will stop
I know that the easy way is to use some range but it is not working because it will always jump on some not good value. Can you tell me how to remove this problem with my code?
import pygame as pg
import random
pg.init()
# Constants
BACKGROUND_COLOR = pg.Color('black')
BALL_X = 240
# Initialize the game window
screen = pg.display.set_mode((500, 800))
clock = pg.time.Clock()
# Load the background image
background_image = pg.image.load("bg.png")
# Draw a rhombus shape
def draw_rhombus(screen, color, x, space):
point1 = (170 + x, 740 - space)
point2 = (350 + x, 740 - space)
point3 = (300 + x, 790 - space)
point4 = (120 + x, 790 - space)
points = [point1, point2, point3, point4]
return pg.draw.polygon(screen, color, points)
# Generate a list of unique colors
def generate_color_list():
colors = ["RED", "ORANGE", "BLUE", "WHITE"]
available_colors = colors.copy()
color_list = []
while len(color_list) < 43:
if not available_colors:
available_colors = colors.copy()
color = random.choice(available_colors)
if color_list and color == color_list[-1]:
continue
color_list.append(color)
available_colors.remove(color)
return color_list
# Draw a stack of rhombus shapes
def draw_rhombus_stack(color_list, space, x):
positions = []
for i in range(43):
x_position = x if i == 42 else 0
position = draw_rhombus(screen, color_list[i], x_position, space + i * 8)
positions.append(position)
return positions
# Move the rhombus stack left or right
def move_rhombus_stack(x, keys):
x_coor = x # Define x_coor variable
if keys[pg.K_LEFT] and x_coor > -500:
x_coor -= 5
if keys[pg.K_RIGHT] and x_coor < 500:
x_coor += 5
return x_coor
# Functions for handling the ball
def draw_ball(color, x, y):
pg.draw.circle(screen, color, (x, y), 15)
def move_ball_down(y, speed, acceleration, direction):
if direction == "down":
speed += acceleration
y += int(speed)
if y >= 415:
direction = "up"
return y, speed, direction
def move_ball_up(y, speed, acceleration, direction):
if direction == "up":
speed -= acceleration
if speed <= 2:
speed = 0
y -= int(speed)
if y <= 320:
direction = "down"
return y, speed, direction
def check_collision(space, color_list, ball_color, index):
if 0 < space < 500 and color_list[ball_color] != color_list[index]:
return True
return False
def choose_ball_color(color_list):
return random.randint(0, 4)
# Main game loop
done = False
color_list = generate_color_list()
ball_color_index = choose_ball_color(color_list)
ball_x = BALL_X
ball_y = 300
ball_speed = 1
ball_acceleration = 0.1
ball_direction = "down"
space = 0
x_coor =0
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
keys = pg.key.get_pressed()
x_coor = move_rhombus_stack(x_coor, keys)
screen.fill(BACKGROUND_COLOR)
# Draw rhombus stack and store their positions
rhombus_positions = draw_rhombus_stack(color_list, space, x_coor)
# Check for collisions
end = False
for i, position in enumerate(rhombus_positions):
end = check_collision(space, color_list, ball_color_index, i)
if end:
break
draw_ball(color_list[ball_color_index], ball_x, ball_y)
# Ball movement
ball_y, ball_speed, ball_direction = move_ball_down(ball_y, ball_speed, ball_acceleration, ball_direction)
ball_y, ball_speed, ball_direction = move_ball_up(ball_y, ball_speed, ball_acceleration, ball_direction)
# Check for game over condition
if end:
# Implement game over logic here
pass
pg.display.flip()
clock.tick(30)
pg.quit()
I suggest changing the condition when the ball changes direction and starts to fall. The ball does not change its direction at a certain height, but when the velocity is 0.
You will also get a more smooth movement if you do not convert the position of the ball to an integral value each time (), but keep the floating point value (y -= int(speed)
y -= speed
).
def move_ball_down(y, speed, acceleration, direction):
if direction == "down":
speed += acceleration
if y >= 415:
direction = "up"
else:
y += speed
return y, speed, direction
def move_ball_up(y, speed, acceleration, direction):
if direction == "up":
speed -= acceleration
if speed <= 0.0:
direction = "down"
speed = 0
y -= speed
return y, speed, direction
round
instead the position of the ball when it is drawn on the screen:
draw_ball(color_list[ball_color_index], ball_x, round(ball_y))
Also, if you start with a speed of 0 instead of 1 (ball_speed = 0
), the ball will always start falling at a height of 300.