Pygame Bouncy Ball Sinks Through Floor - python

The code below bounces a ball but for some reason the ball goes through the ground after it finishes its bounces. Anyone Know Why? The idea of the code is a ball starts at the top left corner and then falls and bounces and then goes up and back down and so on until it stops bouncing, but when it stops bouncing it starts jittering and slowly sinks through the ground. Idk why and I cant figure it out. Anyone know why? Thanks for the help
import pygame
pygame.init()
#All keyboard and mouse input will be handled by the following function
def handleEvents():
#This next line of code lets this function access the dx and dy
#variables without passing them to the function or returning them.
global dx,dy
#Check for new events
for event in pygame.event.get():
#This if makes it so that clicking the X actually closes the game
#weird that that wouldn't be default.
if event.type == pygame.QUIT:
pygame.quit(); exit()
#Has any key been pressed?
elif event.type == pygame.KEYDOWN:
#Escape key also closes the game.
if event.key == pygame.K_ESCAPE:
pygame.quit(); exit()
elif event.key == pygame.K_RIGHT or event.key == pygame.K_d:
dx = dx + 5
elif event.key == pygame.K_LEFT or event.key == pygame.K_a:
dx = dx - 5
elif event.key == pygame.K_UP or event.key == pygame.K_w:
dy = dy - 5
elif event.key == pygame.K_DOWN or event.key == pygame.K_s:
dy = dy + 5
width = 1000
height = 600
size = (width, height)
black = (0, 0, 0) #r g b
screen = pygame.display.set_mode(size)
clock = pygame.time.Clock()
ball = pygame.image.load("ball.gif")
ballrect = ball.get_rect()
x = 0
y = 0
dx = 3
dy = 3
done = False
while not done:
handleEvents()
#Move the ball
x = x + dx
y = y + dy
ballrect.topleft = (x,y)
#PART A
if ballrect.left < 0 or ballrect.right > width:
dx = -dx
if ballrect.top < 0 or ballrect.bottom > height:
dy = -dy
'''If the ball is outside of the range delta y,
then delta y becomes the negative version of it, and the same goes
for delta x if it is outside the boundries of delta x
'''
#PART B
dy = dy * 0.99
dx = dx * 0.99
'''Could be useful if you want
the ball to stop moving after a certain amount of time,
or the opposite, it could make the ball slowly move a greater distance each frame'''
#PART C
dy = dy + 0.3
'''dy slowly gets .3 added to itself each frame, making the bounce
smaller each time until eventually it stops fully'''
#Draw everything
screen.fill(black)
screen.blit(ball, ballrect)
pygame.display.flip()
#Delay to get 30 fps
clock.tick(30)
pygame.quit()

Since the falling speed of the ball is greater than 1 pixel, you have to make sure that the ball does not fall below the lower edge of the window.
You need to constrain the bottom of the ball to the bottom of the window:
done = False
while not done:
# [...]
x = x + dx
y = y + dy
ballrect.topleft = (x,y)
#PART A
if ballrect.left < 0 or ballrect.right > width:
dx = -dx
if ballrect.top < 0:
dy = -dy
if ballrect.bottom > height:
ballrect.bottom = height # <---
y = ballrect.top # <---
dy = -dy
# [...]

Related

Pong paddles have some weird bug preventing from letting a player score [duplicate]

This question already has an answer here:
How to detect collisions between two rectangular objects or images in pygame
(1 answer)
Closed 2 years ago.
I have made a pong game. Now the problem is that when I move the paddle, the ball doesn't go past it but bounces of some invisible wall. Here is my code and run it yourselves and you can see the problem(You have to move the paddles around a little bit)
# Pong
# Importing libraries
import pygame
import random
import time
# Initializing PyGame
pygame.init()
# Creating a font
font = pygame.font.SysFont(None, 30)
# Set the height and width of the screen
window_width = 700
window_height = 500
size = [window_width, window_height]
game_win = pygame.display.set_mode(size)
# Creating a messaging system
def message(sentence, x, y):
sentence = font.render(sentence, True, white)
game_win.blit(sentence, [x, y])
# Creating a color
white = (225, 225, 225)
black = (0, 0, 0)
# Setting up ball
ball_size = 25
class Ball:
"""
Class to keep track of a ball's location and vector.
"""
def __init__(self):
self.x = 0
self.y = 0
self.change_x = 0
self.change_y = 0
def make_ball():
ball = Ball()
# Starting position of the ball.
# Take into account the ball size so we don't spawn on the edge.
ball.x = 350
ball.y = 250
# Speed and direction of rectangle
ball.change_x = 5
ball.change_y = 5
return ball
def main():
# Scores
left_score = 0
right_score = 0
pygame.init()
pygame.display.set_caption("Ping Pong")
# Loop until the user clicks the close button.
done = False
# Used to manage how fast the screen updates
clock = pygame.time.Clock()
ball_list = []
ball = make_ball()
ball_list.append(ball)
# Right paddle coordinates
y = 200
y_change = 0
x = 50
# Left paddle coordinates
y1 = 200
y1_change = 0
x1 = 650
while not done:
# --- Event Processing
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
y_change = -5
elif event.key == pygame.K_s:
y_change = 5
elif event.key == pygame.K_UP:
y1_change = -5
elif event.key == pygame.K_DOWN:
y1_change = 5
elif event.type == pygame.KEYUP:
y_change = 0
y1_change = 0
y += y_change
y1 += y1_change
if y > window_height - 100:
y -= 5
if y < 50:
y += 5
if y1 > window_height - 100:
y1 -= 5
if y1 < 50:
y1 += 5
message("Left player score: " + str(left_score), 10, 10)
message("Right player score: " + str(right_score), 490, 10)
# Drawing a left paddle
pygame.draw.rect(game_win, white, [x, y, 25, 100])
# Drawing a right paddle
pygame.draw.rect(game_win, white, [x1, y1, 25, 100])
# Updating screen to changes take place
pygame.display.update()
# Logic
for ball in ball_list:
# Move the ball's center
ball.x += ball.change_x
ball.y += ball.change_y
# Bounce the ball if needed
if ball.y > 50 - ball_size or ball.y < ball_size:
ball.change_y *= -1
if ball.x > window_width - ball_size:
ball.change_x *= -1
left_score += 1
if ball.x < ball_size:
ball.change_x *= -1
right_score += 1
# Here is the part where it all becomes weird and buggy
if ball.x-ball_size <= x <= ball.x + ball_size:
ball.change_x *= -1
if ball.x-ball_size <= x1 <= ball.x + ball_size:
ball.change_x *= -1
if ball.y-ball_size <= y <= ball.y + ball_size:
ball.change_x *= -1
if ball.y-ball_size <= y1 <= ball.y + ball_size:
ball.change_x *= -1
if right_score == 10:
message('RIGHT PLAYER HAS WON!!', 300, 200)
time.sleep(10)
done = True
elif left_score == 10:
message("LEFT PLAYER HAS WON!!", 300, 200)
time.sleep(10)
done = True
# Drawing
# Set the screen background
game_win.fill(black)
# Draw the balls
for ball in ball_list:
pygame.draw.circle(game_win, white, [ball.x, ball.y], ball_size)
# Wrap-up
# Limit to 60 frames per second
clock.tick(60)
# Go ahead and update the screen with what we've drawn.
pygame.display.flip()
# Close everything down
pygame.quit()
if __name__ == "__main__":
main()
When I move the paddle away, the ball can still bounce off some invisible wall. Everything else is good, just the part where I have put # Bounce if needed.
I recommend to compute the bounding rectangle of the ball and the paddles and to use pygame.Rect and colliderect() to detect the collision between a ball and a paddle.
See alos Sometimes the ball doesn't bounce off the paddle in pong game.
For instance:
def main():
# [...]
while not done:
# [...]
# Logic
for ball in ball_list:
# [...]
ball_rect = pygame.Rect(ball.x-ball_size, ball.y-ball_size, ball_size*2, ball_size*2)
left_paddle_rect = pygame.Rect(x, y, 25, 75)
if ball.change_x < 0 and ball_rect.colliderect(left_paddle_rect):
ball.change_x = abs(ball.change_x)
right_paddle_rect = pygame.Rect(x1, y1, 25, 75)
if ball.change_x > 0 and ball_rect.colliderect(right_paddle_rect):
ball.change_x = -abs(ball.change_x)
Furthermore, there the height of the window is 500 rather than 50_
if ball.y > 50 - ball_size or ball.y < ball_size:
if ball.y > 500 - ball_size or ball.y < ball_size:
I recommend to remove the multiple calls to pygame.display.flip() respectively pygame.display.update(). Do just one update of the display at the end of the main application loop. See the complete example:
# Importing libraries
import pygame
import random
import time
# Initializing PyGame
pygame.init()
# Creating a font
font = pygame.font.SysFont(None, 30)
# Set the height and width of the screen
window_width = 700
window_height = 500
size = [window_width, window_height]
game_win = pygame.display.set_mode(size)
# Creating a messaging system
def message(sentence, x, y):
sentence = font.render(sentence, True, white)
game_win.blit(sentence, [x, y])
# Creating a color
white = (225, 225, 225)
black = (0, 0, 0)
# Setting up ball
ball_size = 25
class Ball:
"""
Class to keep track of a ball's location and vector.
"""
def __init__(self):
self.x = 0
self.y = 0
self.change_x = 0
self.change_y = 0
def make_ball():
ball = Ball()
# Starting position of the ball.
# Take into account the ball size so we don't spawn on the edge.
ball.x = 350
ball.y = 250
# Speed and direction of rectangle
ball.change_x = 5
ball.change_y = 5
return ball
def main():
# Scores
left_score = 0
right_score = 0
pygame.init()
pygame.display.set_caption("Ping Pong")
# Loop until the user clicks the close button.
done = False
# Used to manage how fast the screen updates
clock = pygame.time.Clock()
ball_list = []
ball = make_ball()
ball_list.append(ball)
# Right paddle coordinates
y = 200
y_change = 0
x = 50
# Left paddle coordinates
y1 = 200
y1_change = 0
x1 = 650
while not done:
# --- Event Processing
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
y_change = -5
elif event.key == pygame.K_s:
y_change = 5
elif event.key == pygame.K_UP:
y1_change = -5
elif event.key == pygame.K_DOWN:
y1_change = 5
elif event.type == pygame.KEYUP:
y_change = 0
y1_change = 0
y += y_change
y1 += y1_change
if y > window_height - 100:
y -= 5
if y < 50:
y += 5
if y1 > window_height - 100:
y1 -= 5
if y1 < 50:
y1 += 5
message("Left player score: " + str(left_score), 10, 10)
message("Right player score: " + str(right_score), 490, 10)
# Logic
for ball in ball_list:
# Move the ball's center
ball.x += ball.change_x
ball.y += ball.change_y
# Bounce the ball if needed
if ball.y > 500 - ball_size or ball.y < ball_size:
ball.change_y *= -1
if ball.x > window_width - ball_size:
ball.change_x *= -1
left_score += 1
if ball.x < ball_size:
ball.change_x *= -1
right_score += 1
# Here is the part where it all becomes weird and buggy
ball_rect = pygame.Rect(ball.x-ball_size, ball.y-ball_size, ball_size*2, ball_size*2)
left_paddle_rect = pygame.Rect(x, y, 25, 75)
if ball.change_x < 0 and ball_rect.colliderect(left_paddle_rect):
ball.change_x = abs(ball.change_x)
right_paddle_rect = pygame.Rect(x1, y1, 25, 75)
if ball.change_x > 0 and ball_rect.colliderect(right_paddle_rect):
ball.change_x = -abs(ball.change_x)
if right_score == 10:
message('RIGHT PLAYER HAS WON!!', 300, 200)
time.sleep(10)
done = True
elif left_score == 10:
message("LEFT PLAYER HAS WON!!", 300, 200)
time.sleep(10)
done = True
# Drawing
# Set the screen background
game_win.fill(black)
# Drawing a left paddle
pygame.draw.rect(game_win, white, [x, y, 25, 100])
# Drawing a right paddle
pygame.draw.rect(game_win, white, [x1, y1, 25, 100])
# Draw the balls
for ball in ball_list:
pygame.draw.circle(game_win, white, [ball.x, ball.y], ball_size)
# Go ahead and update the screen with what we've drawn.
pygame.display.flip()
# Wrap-up
# Limit to 60 frames per second
clock.tick(60)
# Close everything down
pygame.quit()
if __name__ == "__main__":
main()

Why doesn't this collision detection apply to objects previously created?

After hours of searching, I still can't figure out why only the most recently spawned circle is affected by the collision detection. I commented out the code in question. I experimented with sprites and that may be the answer but I still got the same results.
import pygame,random
pygame.init()
width,height,radius = 1280,720,20
class Ball():
def __init__(self):
self.x = 0
self.y = 0
self.vx = 0
self.vy = 0
def make_ball():
ball = Ball()
ball.x = random.randrange(radius, width - radius)
ball.y = random.randrange(radius, 100)
ball.vx = random.randint(1,2)
ball.vy = 0
return ball
def main():
rect_x = 60
display = pygame.display.set_mode((width,height))
pygame.display.set_caption("BOUNCE")
running = True
ball_list = []
ball = make_ball()
ball_list.append(ball)
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
ball = make_ball()
ball_list.append(ball)
for ball in ball_list:
ball.x += ball.vx
ball.vy += 0.02
ball.y += ball.vy
if ball.y >= height - radius:
ball.vy *= -1
if ball.x >= width - radius or ball.x <= radius:
ball.vx *= -1
display.fill((0,0,0))
for ball in ball_list:
random_color = (random.randint(1,255),random.randint(1,255),random.randint(1,255))
circle = pygame.draw.circle(display,random_color,(int(ball.x), int(ball.y)),radius)
rectangle = pygame.draw.rect(display,(255,255,255),(int(rect_x),660,60,60))
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT and rect_x > 0:
rect_x -= 2
if event.key == pygame.K_RIGHT and rect_x < width - 60:
rect_x += 2
'''if pygame.Rect(circle).colliderect(rectangle) == True: ###THIS IS THE BAD CODE!
print('Your Score:',pygame.time.get_ticks())
running = False'''
text = pygame.font.Font(None,120).render(str(pygame.time.get_ticks()),True,(255,255,255))
display.blit(text,(50,50))
pygame.display.flip()
pygame.quit()
if __name__ == "__main__":
main()
Indentation and code organization is the key to this. the offending section is (comments removed):
for ball in ball_list:
random_color = (random.randint(1,255),random.randint(1,255),random.randint(1,255))
circle = pygame.draw.circle(display,random_color,(int(ball.x), int(ball.y)),radius)
rectangle = pygame.draw.rect(display,(255,255,255),(int(rect_x),660,60,60))
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT and rect_x > 0:
rect_x -= 2
if event.key == pygame.K_RIGHT and rect_x < width - 60:
rect_x += 2
if pygame.Rect(circle).colliderect(rectangle) == True:
print('Your Score:',pygame.time.get_ticks())
running = False
You had all the correct pieces, but the order in which you are doing them is off as well as the indentation:
for ball in ball_list:
random_color = (random.randint(1,255),random.randint(1,255),random.randint(1,255))
circle = pygame.draw.circle(display,random_color,(int(ball.x), int(ball.y)),radius)
rectangle = pygame.draw.rect(display,(255,255,255),(int(rect_x),660,60,60))
if pygame.Rect(circle).colliderect(rectangle):
print('Your Score:',pygame.time.get_ticks())
running = False
This will now run through every ball in the list and check each one for collision. notice the colliderect if statement is indented into the for loop. Also notice i removed the KEYDOWN check from in the middle of it all
Speaking of that I would recommend using:
pressed = pygame.key.get_pressed()
if pressed[pygame.K_LEFT] and rect_x > 0:
rect_x -= 2
if pressed[pygame.K_RIGHT] and rect_x < width - 60:
rect_x += 2
for ball in ball_list:
# for loop from above
instead of what you had. This works best for when you want to allow for holding a key down. pygame.key.get_pressed() gets the state of all the keys all the time, not just when an event happens

Adding boundaries in Pygame with movable characters/images

I have been creating a game where an image moves according to player input with Keydown and Keyup methods. I want to add boundaries so that the user cannot move the image/character out of the display (I dont want a game over kind of thing if boundary is hit, just that the image/character wont be able to move past that boundary)
import pygame
pygame.init()#initiate pygame
black = (0,0,0)
white = (255,255,255)
red = (255,0,0)
display_width = 1200
display_height = 800
display = pygame.display.set_mode((display_width,display_height))
characterimg_left = pygame.image.load(r'/Users/ye57324/Desktop/Make/coding/python/characterimg_left.png')
characterimg_right = pygame.image.load(r'/Users/ye57324/Desktop/Make/coding/python/characterimg_right.png')
characterimg = characterimg_left
def soldier(x,y):
display.blit(characterimg, (x,y))
x = (display_width * 0.30)
y = (display_height * 0.2)
pygame.display.set_caption('No U')
clock = pygame.time.Clock()#game clock
flip_right = False
x_change = 0
y_change = 0
bg_x = 0
start = True
bg = pygame.image.load(r'/Users/ye57324/Desktop/Make/coding/python/bg.png').convert()
class player:
def __init__(self, x, y):
self.jumping = False
p = player(x, y)
while start:
for event in pygame.event.get():
if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
start = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change += -4
if flip_right == True:
characterimg = characterimg_left
flip_right = False
x += -150
elif event.key == pygame.K_RIGHT:
x_change += 4
if flip_right == False:
characterimg = characterimg_right
flip_right = True
x += 150
elif event.key == pygame.K_UP:
y_change += -4
elif event.key == pygame.K_DOWN:
y_change += 4
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
x_change += 4
elif event.key == pygame.K_RIGHT:
x_change += -4
elif event.key == pygame.K_UP:
y_change += 4
elif event.key == pygame.K_DOWN:
y_change += -4
x += x_change
y += y_change
display.fill(white)
soldier(x,y)
pygame.display.update()
clock.tick(120)#fps
pygame.quit()
I have tried several times including switching to the key pressed method but they all failed. Help please, thank you.
Basically you want to limit the player's movement.
So everytime you want to "move" the player (I'm guessing this is "x_change" / "y_change") you need to check whether they would still be inside your boundaries after the move.
Example: Your display x boundary is 0 pixels on the left of your screen and 500 to the right. I only allow the actual movement if the result of the movement is within my boundaries.
boundary_x_lower = 0
boundary_x_upper = 500
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
if boundary_x_lower < (x_change - 4):
# I allow the movement if I'm still above the lower boundary after the move.
x_change -= 4
elif event.key == pygame.K_RIGHT:
if boundary_x_upper > (x_change +4):
# I allow the movement if I'm still below the upper boundary after the move.
x_change += 4
PS: I am confused by your code as you subtract when you move to the right... I am used to 2D games where you increment the player's position if you move to the right... and subtract if you go to the left.
Feel free to adapt the code to fit your project. The basic principle applies also to the y-axis movement: with boundary_y_lower & _y_upper. if you have further questions, just ask!
Just clamp the x and y values between 0 and the display width and height.
# In the main while loop after the movement.
if x < 0:
x = 0
elif x + image_width > display_width:
x = display_width - image_width
if y < 0:
y = 0
elif y + image_height > display_height:
y = display_height - image_height
I also recommend checking out how pygame.Rects work. You could define a rect with the size of the display,
display_rect = display.get_rect()
and a rect for the character which will be used as the blit position:
rect = characterimg_left.get_rect(center=(x, y))
Then move and clamp the rect in this way:
rect.move_ip((x_change, y_change))
rect.clamp_ip(display_rect)
display.fill(white)
# Blit the image at the `rect.topleft` coordinates.
display.blit(characterimg, rect)

Object bounce and movement [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I have been making a game where 2 people try to score a goal on a net, but to do so, the ball must move and bounce. I would like the ball to move forward and upwards at a realistic angle, then bounce on the ground a few times before becoming stationary again. I'm not sure how to achieve this, my code is below, I really hope someone can edit it to work.
When I run the code, I get the following error
TypeError: unsupported operand type(s) for +=: 'pygame.math.Vector2' and 'int'(for the line "ball_vel += x2")
import pygame as pg
from pygame.math import Vector2
pg.init()
LIGHTBLUE = pg.Color('lightskyblue2')
screen = pg.display.set_mode((800, 600))
width, height = screen.get_size()
clock = pg.time.Clock()
pg.display.set_caption("Super Acrobatic Rocket Powered Battle Polygons(SARPBP)")
x = 740
y = 0
x2 = 370
y2 = 500
x_change = 0
y_change = 0
bluespeed = 5
on_ground = False
bluecar = pg.Surface((60, 30))
bluecar.fill((0,0,255))
BALL = pg.Surface((30, 30), pg.SRCALPHA)
pg.draw.circle(BALL, [0,0,0], [15, 15], 15)
ball_pos = Vector2(x2, y2)
ballrect = BALL.get_rect(center=ball_pos)
ball_vel = Vector2(0, 0)
ball_mask = pg.mask.from_surface(BALL)
mask_blue = pg.mask.from_surface(bluecar)
mask_ball = pg.mask.from_surface(BALL)
pos_blue = Vector2(x,y)
bluerect = bluecar.get_rect(center = pos_blue)
vel_blue = Vector2(bluespeed,0)
# A constant value that you add to the y_change each frame.
GRAVITY = .5
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
elif event.type == pg.KEYDOWN:
if event.key == pg.K_a:
x_change = -5
elif event.key == pg.K_d:
x_change = 5
elif event.key == pg.K_w:
if on_ground: # Only jump if the player is on_ground.
y_change = -12
on_ground = False
elif event.type == pg.KEYUP:
if event.key == pg.K_a and x_change < 0:
x_change = 0
elif event.key == pg.K_d and x_change > 0:
x_change = 0
# Add the GRAVITY value to y_change, so that
# the object moves faster each frame.
y_change += GRAVITY
x += x_change
y += y_change
#x += vel_blue
# Stop the object when it's near the bottom of the screen.
if y >= height - 100:
y = height - 100
y_change = 0
on_ground = True
if x == 0:
x = 5
elif x == 740:
x = 735
offset_blue = bluerect[0] - ballrect[0], bluerect[1] - ballrect[1]
overlap_blue = mask_ball.overlap(mask_blue, offset_blue)
if overlap_blue: # Blue collides with the ball.
ball_vel = Vector2(x_change) * 1.4
ball_vel += x2
# Draw everything.
screen.fill(LIGHTBLUE)
pg.draw.line(screen, (0, 0, 0), (0, height-70), (width, height-70))
screen.blit(bluecar, (x, y))
screen.blit(BALL, (x2,y2))
pg.display.update()
clock.tick(60)
pg.quit()
You can just invert the y component of the velocity vector when the ball touches the ground to make it bounce: ball_vel.y *= -1. Change the value by which you multiply the velocity to adjust the elasticity: ball_vel.y *= -0.94 # Lower elasticity.
import pygame as pg
from pygame.math import Vector2
pg.init()
LIGHTBLUE = pg.Color('lightskyblue2')
screen = pg.display.set_mode((800, 600))
width, height = screen.get_size()
clock = pg.time.Clock()
BALL = pg.Surface((30, 30), pg.SRCALPHA)
pg.draw.circle(BALL, [0,0,0], [15, 15], 15)
ball_pos = Vector2(370, 0)
ballrect = BALL.get_rect(center=ball_pos)
ball_vel = Vector2(0, 0)
ground_pos = 70
GRAVITY = .9
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
ball_vel.y += GRAVITY # Accelerate downwards.
ball_pos += ball_vel # Move the ball.
ballrect.center = ball_pos
# Bounce when the ball touches the bottom of the screen.
if ballrect.bottom >= height - ground_pos:
# Just invert the y-velocity to bounce.
ball_vel.y *= -0.94 # Change this value to adjust the elasticity.
# Don't go below the ground.
ballrect.bottom = height - ground_pos
ball_pos.y = ballrect.centery
# Draw everything.
screen.fill(LIGHTBLUE)
pg.draw.line(screen, (0, 0, 0), (0, height-70), (width, height-ground_pos))
screen.blit(BALL, ballrect)
pg.display.update()
clock.tick(60)
pg.quit()
The error says that you cannot add an int and Vector2 together directly. The program does not know how to. What you need to do instead is to add to the x value of the vector. Change the line ball_vel += x2 to ball_vel.x += x2.

pygame sample code with events

I can not seem to find the bug in my program. The program will run without errors however, my paddle image will not move. I have spent hours researching and tried multiple different changes. I am using python 3.4.1. My goal is to create a paddle game of sorts. Thank you.
# Python game
import pygame
import sys
pygame.init()
ball_image = pygame.image.load("ball.png")
ballrect = ball_image.get_rect()
paddle_image = pygame.image.load("paddle.png")
paddlerect = paddle_image.get_rect()
screen_w = 825
screen_h = 727
size = [screen_w, screen_h]
speed = [1, 1]
black = (0, 0, 0)
blue = (0,0,255)
screen = pygame.display.set_mode(size)
class paddle(object):
paddle_speed = [0, 0]
paddle_speed_d = [0, -1]
paddle_speed_u = [0, 1]
image = paddle_image
rect = image.get_rect()
x = 20
y = screen_h / 2
w = rect.width
h = rect.height
def __init__(self, side):
self.side = side
if side == "l":
x == width - 20 - w
def move_d(self):
self.rect.move(self.paddle_speed_d)
def move_u(self):
self.rect.move(self.paddle_speed_u)
pad1 = paddle("r")
#pad2 = paddle("l")
while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_DOWN:
pad1.move_d()
if event.key == pygame.K_UP:
pad1.move_u()
ballrect = ballrect.move(speed)
if ballrect.left < 0 or ballrect.right > screen_w:
speed[0] = -speed[0]
if ballrect.top < 0 or ballrect.bottom > screen_h:
speed[1] = -speed[1]
#if ballrect.bottom == 0:
#ballrect.y = screen_h
#if ballrect.top == screen_h:
#ballrect.bottom = 0
screen.fill(black)
screen.blit(ball_image, ballrect)
screen.blit(pad1.image, pad1.rect)
pygame.display.flip()
pygame.time.wait(1)
From the documentation:
move()
Returns a new rectangle that is moved by the given offset. The x and y arguments can be any integer value, positive or negative.
move_ip()
Same as the Rect.move() method, but operates in place.
If you change self.rect.move(self.paddle_speed_d) to self.rect.move_ip(self.paddle_speed_d) in move_d(), that should do the trick (likewise for move_u().
(This still leaves the problem that move_d() is only called on key down. This means you have to repeatedly press the down key to move your paddle. This may be what you want, but if it's not, consider having an update function move the paddle on every loop, and have move_d() and move_u() set the velocity of the paddle.)
Thanks for trying to help, but I discovered my problem. The format in which I saved my image was not showing movement. I changed my image and now it works.

Categories

Resources