Difficulty with movement in game close to Pong (pygame) - pygame

Note: I am really new in programming.
At first, I am just going to post the code I have written:
import pygame
import random
pygame.init()
screen = pygame.display.set_mode([640, 480])
paddle = pygame.image.load("pulgake.png")
pygame.display.set_caption("PONG!")
WHITE = [0, 0, 0]
back = pygame.image.load("taust.png")
screen.blit(back, (0, 0))
screen.blit(paddle, (600, 240))
pygame.display.flip()
xpaddle = 600
ypaddle = 240
delay = 10
interval = 10
pygame.key.set_repeat(delay, interval)
class Ball:
def __init__(self):
self.pos = [0,0]
self.velocity = [1,0]
def move():
self.pos[0] += self.velocity[0]
self.pos[1] += self.velocity[1]
if self.pos[0] > 10:
self.pos[0] *= -1
elif self.pos[1] > 470: # My background has a frame
self.pos[1] *= -1
elif self.pos[1] < 10:
self.pos[1] *= -1
elif self.pos[0] > 605:
False
def draw(screen):
pygame.draw.circle(screen,WHITE,self.pos,15)
pall = Ball()
while True:
pall.move()
screen.blit(back, (0,0))
screen.blit(paddle, (xpaddle, ypaddle))
pygame.display.flip()
for i in pygame.event.get():
if i.type == pygame.QUIT:
sys.exit()
elif i.type == pygame.KEYDOWN:
if i.key == pygame.K_UP:
ypaddle = ypaddle - 10
if ypaddle < 10:
ypaddle = 10
elif i.key == pygame.K_DOWN:
ypaddle = ypaddle + 10
if ypaddle > 410:
ypaddle = 410
I am getting this error-
line 44, in <module>
pall.move()
TypeError: move() takes no arguments (1 given)
So, I want to get a ball that bounces off the walls (and paddle as well, but I don't know yet how)
Also, I would be really grateful if somebody helps me to get a stopwatch in this game, showing time "survived".
EDIT: added def move(self)
Now, a bigger problem occured:
draw() and move() - global name"self" not defined.
I really can't figure out this one.

You are calling ball.move which doesn't exist, because move needs to be indented once more.
If you want "do stuff while key is held down" You can use getkeystate and use KEYDOWN events when you want 'do stuff once, when key is pressed'
see both here: https://stackoverflow.com/a/13207525/341744

Related

I'm trying to make a wild west game with pygame, but I can't get the shooting functions to work

I've been trying to make a wild west game in Pygame in which the player duels an NPC, but I can't get the shooting functions to work. I've basically tried to keep it simple, and I have a series of functions to make the bullet go across the screen, but they aren't working. Here's the code:
import pygame, time
pygame.init()
display_width = 800
display_height = 600
win = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption('The Old Wild West')
black = (0,0,0)
white = (255,255,255)
clock = pygame.time.Clock()
dead = False
avatar = pygame.image.load('cowboy.jfif')
avatar2 = pygame.image.load('enemy.jfif')
bullet = pygame.image.load('bullet.png')
bx2 = 330
bx3 = 440
bx4 = 550
bx = 220
by = 220
bspeed = 165
x = 50
ex = 550
ey = 225
y = 200
x_change = 0
speed = 0
def cowboy(x,y):
win.blit(avatar, (x,y))
def enemy(ex, ey):
win.blit(avatar2, (ex, ey))
def shootframe1():
win.blit(bullet, (bx, by))
def antiframe1():
pygame.draw.rect(win, (255, 255, 255), (bx, by, 50, 150))
def shootframe2():
win.blit(bullet, (bx2, by))
def antiframe2():
pygame.draw.rect(win, (255, 255, 255), (bx2, by, 50, 150))
def shootframe3():
win.blit(bullet, (bx3, by))
def antiframe3():
pygame.draw.rect(win, (255, 255, 255), (bx3, by, 50, 150))
def shootframe4():
win.blit(bullet, (bx4, by))
def antiframe4():
pygame.draw.rect(win, (255, 255, 255), (bx4, by, 50, 150))
while not dead:
for event in pygame.event.get():
if event.type == pygame.QUIT:
dead = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = -5
elif event.key == pygame.K_RIGHT:
x_change = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 0
if event.type == pygame.K_SPACE:
if event.key == pygame.K_SPACE:
shootframe1()
time.sleep(0.5)
antiframe1()
shootframe2()
time.sleep(0.5)
antiframe2()
shootframe3()
time.sleep(0.5)
antiframe3()
shootframe4()
time.sleep(0.5)
antiframe4()
x += x_change
win.fill(white)
cowboy(x,y)
enemy(ex, ey)
pygame.display.update()
clock.tick(60)
pygame.quit()
quit()
Here is cowboy.jfif, enemy.jfif and bullet.png:
bullet.png
cowboy.jfif
enemy.jfif
Please help me out with this confusion.
I updated your code drastically, I tried to comment everything pretty well so it's clear what is happening.
First, you were filling the screen white after drawing the bullet onto the screen so it never showed up.
Second, the space bar key didn't fire because you were checking if the space bar was an event type. So I moved it under the event.type == pygame.KEYDOWN
Third, using time.sleep(0.5) makes the game window freeze and stutter a lot so I would avoid doing that.
If you have any questions about the changes feel free to ask.
import pygame, time
pygame.init()
display_width = 800
display_height = 600
win = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption('The Old Wild West')
black = (0,0,0)
white = (255,255,255)
clock = pygame.time.Clock()
dead = False
avatar = pygame.image.load('cowboy.jfif')
avatar2 = pygame.image.load('enemy.jfif')
bullet = pygame.image.load('bullet.png')
bx2 = 330
bx3 = 440
bx4 = 550
bx = 220
by = 220
bspeed = 165
x = 50
ex = 550
ey = 225
y = 200
x_change = 0
speed = 0
def cowboy(x,y):
win.blit(avatar, (x,y))
def enemy(ex, ey):
win.blit(avatar2, (ex, ey))
# A single shoot function that appends a new bullet to our bullet list below.
def shoot():
bullet_list.append(Bullet(bx, by))
# A bullet class that holds information about a single bullet
class Bullet:
def __init__(self, x, y):
# Initializing variables for the bullet
self.x = x
self.y = y
self.image = pygame.image.load('bullet.png')
self.bullet_speed = 165
# Moves the bullet accross the screen by updating the x variable after each draw()
def _move_bullet(self):
self.x += self.bullet_speed
def draw(self):
# Get the surface (window)
surface = pygame.display.get_surface()
# Blit the bullet to the screen
surface.blit(self.image, (self.x, self.y))
# Update its position with the function above
self._move_bullet()
bullet_list = [] # Since the user can have multiple bullets firing, we need to keep track of them
while not dead:
win.fill(white) #Move this to the top so you're filling the screen before drawing anything
for event in pygame.event.get():
if event.type == pygame.QUIT:
dead = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = -5
elif event.key == pygame.K_RIGHT:
x_change = 5
if event.key == pygame.K_SPACE: # Moved this up here
shoot() # Spawn the bullet
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 0
x += x_change
cowboy(x,y)
enemy(ex, ey)
# Draw each bullet onto the screen by iterating over the list
for bullet in bullet_list:
# If the bullet has exited the screen we remove it from the list so they are not kept in memory
if bullet.x > display_width:
bullet_list.remove(bullet)
# Draw the bullet (called from the Class)
bullet.draw()
pygame.display.update()
clock.tick(60)
pygame.quit()
quit()

Cannot shoot more than one projectile

Shooting one bullet works but i can only shoot one and after that it stops working. I've tried to change my "bullet_fire" to False after KEYUP but this doesnt work either since then the bullet is only visible while i hold the arrow up key while the problem remain. How should i solve this problem?
Here is the code:
import pygame
pygame.init()
# Skärm
Screen = pygame.display.set_mode((1600, 900))
# Title och Logo
pygame.display.set_caption("Fjärt Spel")
icon = pygame.image.load('planet.png')
pygame.display.set_icon(icon)
# backround
backround = pygame.image.load("0000.png")
# player
playerIMG = pygame.image.load("soldier.png")
playerX = 350
playerY = 836
playerX_Change = 0
playerY_Change = 30
# enemy
enemyIMG = pygame.image.load("terrorist2.png")
enemyX = 500
enemyY = 810
enemyX_Change = 0
enemyY_Change = 0
# bullet
bulletIMG = pygame.image.load("pung(32x32).png")
bulletX = playerX
bulletY = playerY
bulletX_Change = 50
bulletY_Change = 0
bullet_fire = False
offScreen = 1600, 900
def player(x, y):
Screen.blit(playerIMG, (x, y))
def enemy(x, y):
Screen.blit(enemyIMG, (x, y))
Running = True
while Running:
Screen.fill((0, 0, 0))
# backround
Screen.blit(backround, (0, 0))
if bullet_fire == True:
Screen.blit(bulletIMG, (bulletX + 100, playerY))
bulletX += bulletX_Change
if bulletX > 1600:
bullet_fire == False
for event in pygame.event.get():
if event.type == pygame.QUIT:
Running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerX_Change = -10
if event.key == pygame.K_RIGHT:
playerX_Change = 10
if event.key == pygame.K_SPACE:
playerY_Change = -70
if event.key == pygame.K_UP:
bullet_fire = True
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT or event.key == pygame.K_SPACE:
playerX_Change = 0
playerY_Change = 30
# Ha player innan fill!!
playerX += playerX_Change
playerY += playerY_Change
if playerX <= 0:
playerX = 0
elif playerX >= 1436:
playerX = 1436
if playerY <= 0:
playerY = 0
elif playerY >= 836:
playerY = 836
player(playerX, playerY)
enemy(enemyX, enemyY)
pygame.display.update()
if bulletX > 1600:
bullet_fire == False
# ^^
This appears to want to set bullet_fire to False when it reaches a certain ordinate but, in reality, is comparing the two and throwing away the result. That means the first bullet you've fired is still going, has left the screen, and is probably halfway to Jupiter by now :-)
By way of example, this is similar to the following transcript:
>>> a = 7
>>> if a == 7:
... a == 14
... print(a)
...
False
7
You need to use == for comparison and = for assignment.
Keep in mind that's the likely cause of your issue. Since your question does not contain the code that decides whether a new bullet should be generated, it's a little hard to tell for sure. I'm therefore basing it on the assumption that one bullet at a time is all that's permitted (as in quite a few arcade games). Hence, if you never "destroy" the current bullet, you'll never be able to fire another one.
If that turns out to not be the case, you probably need to post more code so we can do an exhaustive analysis.
As an aside, I'm a little concerned about the physics involved in:
Screen.blit(bulletIMG, (bulletX + 100, playerY))
This appears to draw the bullet at the players current Y position meaning that, after the bullet is fired, it will track the player in some weird Einsteinian "spooky action at a distance" manner. While that makes the game a lot easier since you can direct the bullets after firing, I'm not convinced it will get a high score in the realism category :-)

Pygame Space Invaders Bug

'''There's a minor bug in this Space Invaders Code, everything works fine and well at the start , until all of a sudden sometimes, mostly at the end of the game, some of the enemy spaceships suddenly moves extremely fast and wayy faster than the other enemies, but follows the same path as the others..If I manage to shoot down the fast spaceships, more of them start moving at the very same fast speed, how it that??I have attached the code down below:'''
import pygame
import random
import math
from pygame import mixer
# Initialize and create a Game Window
pygame.init()
screen = pygame.display.set_mode(size=(800,600))
#Caption and Icon
pygame.display.set_caption('Space Invaders')
icon = pygame.image.load('ufo.png')
pygame.display.set_icon(icon)
#Background
background = pygame.image.load('background.png')
#BackgroundSound
mixer.music.load('background.wav')
mixer.music.play(-1)
#Player
playerImg = pygame.image.load('player.png')
playerX=360
playerY=470
playerX_change = 0
#Enemy
enemyImg=[]
enemyX = []
enemyY = []
enemyX_change = []
enemyY_change = []
num_of_enemies=6
for i in range(num_of_enemies):
enemyImg.append(pygame.image.load('enemy.png'))
enemyX.append(random.randint(0,736))
enemyY.append(random.randint(40,120))
enemyX_change.append(4)
enemyY_change.append(20)
#Bullet
bulletImg = pygame.image.load('bullet.png')
bulletX=0
bulletY=480
bulletX_change = 0
bulletY_change = -10
bulletstate = 'ready' # Bullet is 'ready' if its ready to shoot and 'fire' means a bullet is fired
#Number of Bullets
no_of_bullets=0
#Score
score_value=0
Score_font = pygame.font.Font("freesansbold.ttf" , 32)
textX=10
textY=10
#Number of bullets
def Show_score(x,y):
score=Score_font.render("Score: " + str(score_value) , True , (255,255,255))
screen.blit(score , (x,y))
def player(x,y):
screen.blit(playerImg , (playerX , playerY))
def enemy(x, y, i):
screen.blit(enemyImg[i] , (enemyX[i] , enemyY[i]))
def bullet_fire(x,y):
global bulletstate
bulletstate='fire'
screen.blit(bulletImg ,(x+16 , y+10))
def Collision(bulletX , bulletY , enemyX , enemyY):
distance=math.sqrt((math.pow(enemyX-bulletX,2)) + (math.pow(bulletY-enemyY,2)))
if distance<29:
return True
else:
return False
def game_over():
font1 = pygame.font.Font("BUBBLEGUMS.ttf" , 68)
gameover=font1.render("GAME OVER " , True , (255,255,255))
screen.blit(gameover , (100,200))
def numberofbullets():
font2=pygame.font.Font("blow.ttf",35)
number_of_bullets=font2.render("Number of Bullets Shot: " + str(no_of_bullets) , True , (0,255,255))
screen.blit(number_of_bullets , (170,375))
#Game Loop
running=True
while running:
# BackgroundImage
screen.blit(background ,(0,0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
#Keystroke
if event.type == pygame.KEYDOWN:
if event.key ==pygame.K_LEFT:
playerX_change -=6
if event.key == pygame.K_RIGHT:
playerX_change +=6
if bulletstate=='ready':
if event.key == pygame.K_SPACE:
no_of_bullets+=1
bulletX=playerX
bullet_fire(bulletX,bulletY)
bullet_sound = mixer.Sound('laser.wav')
bullet_sound.play()
if event.type ==pygame.KEYUP:
if event.key ==pygame.K_LEFT or event.key == pygame.K_RIGHT:
playerX_change=0
#Checking for Boundaries of Spaceship
playerX +=playerX_change
if playerX>=736:
playerX=736
elif playerX<=0:
playerX=0
# Enemy Movement
for i in range(num_of_enemies):
if enemyY[i]>440:
for j in range(num_of_enemies):
enemyY[j]=2000
game_over()
numberofbullets()
break
enemyX[i] +=enemyX_change[i]
if enemyX[i]>735:
enemyX_change[i]+=-4
enemyY[i] +=enemyY_change[i]
elif enemyX[i]<0:
enemyX_change[i]+=4
enemyY[i] +=enemyY_change[i]
#Collision
collision = Collision(bulletX, bulletY, enemyX[i], enemyY[i])
if collision:
collision_sound = mixer.Sound('explosion.wav')
collision_sound.play()
bulletY=480
bulletstate='ready'
enemyX[i]=random.randint(0,800)
enemyY[i]=random.randint(40,120)
score_value+=100
enemy(enemyX[i],enemyY[i] ,i)
#Bullet Movement
if bulletY<=0:
bulletY=480
bulletstate='ready'
if bulletstate=='fire':
bullet_fire(bulletX, bulletY)
bulletY+=bulletY_change
player(playerX,playerY)
Show_score(textX, textY)
pygame.display.update()
The problem of your code is that when your write this:
enemyX[i] +=enemyX_change[i]
if enemyX[i]>735:
enemyX_change[i]+=-4
enemyY[i] +=enemyY_change[i]
elif enemyX[i]<0:
enemyX_change[i]+=4
enemyY[i] +=enemyY_change[i]
every time the enemy reaches an edge enemyX_change[i] should be set to the opposite of what it was before, not by adding or subtracting 4, but directly by setting it to 4 or -4. Also you should set enemyX[i] to be 735 when the enemy reaches the left side and 0 when he reaches the right side.
If you change that piece of code with this one everything should work fine:
if enemyX[i]>735:
enemyX[i] = 735
enemyX_change[i] = -4
enemyY[i] +=enemyY_change[i]
elif enemyX[i]<0:
enemyX[i] = 0
enemyX_change[i] = 4
enemyY[i] +=enemyY_change[i]

TypeError: Rect argument is invalid pygame

i am new to pygame and wanted to make a game i found a playlist online at https://www.youtube.com/playlistlist=PLQVvvaa0QuDdLkP8MrOXLe_rKuf6r80KO t i followed it but i got a error like this
Traceback (most recent call last):
File "/home/pi/firstgamepyg.py", line 78, in <module>
game_loop()
File "/home/pi/firstgamepyg.py", line 65, in game_loop
things(thing_startx, thing_starty, thing_width, thing_height, black)
File "/home/pi/firstgamepyg.py", line 15, in things
pygame.draw.rect(gamedisplay, color,(thingx, thingy, thingw, thingh))
TypeError: Rect argument is invalid
this is my code
import pygame
import time
import random
pygame.init()
dw = 800
dh = 600
black = (0,0,0)
white = (255,255,255)
red = (255,0,0)
cw = 96
gamedisplay = pygame.display.set_mode((dw,dh))
cimg = pygame.image.load('/home/pi/Downloads/car.jpeg')
def things(thingx, thingy, thingw, color, thingh):
#error on next line
pygame.draw.rect(gamedisplay, color,(thingx, thingy, thingw, thingh))
def car(x,y):
gamedisplay.blit(cimg,(x,y))
def text_objects(text, font):
textsurface = font.render(text, True, red)
return textsurface, textsurface.get_rect()
def message_display(text):
largeText = pygame.font.Font('freesansbold.ttf',115)
TextSurf, TextRect = text_objects(text, largeText)
TextRect.center = ((dw/2),(dh/2))
gamedisplay.blit(TextSurf, TextRect)
pygame.display.update()
time.sleep(2)
game_loop()
def crash():
message_display('wasted')
def game_loop():
x = (dw * 0.45)
y = (dh * 0.65)
x_change = 0
thing_startx = random.randrange(0,800)
thing_starty = -600
thing_speed = 7
thing_width = 100
thing_height = 100
pygame.display.set_caption('A bit Racey')
clock = pygame.time.Clock()
gameexit = False
while not gameexit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameexit = True
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = -5
elif event.key == pygame.K_RIGHT:
x_change = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key==pygame.K_RIGHT:
x_change = 0
x += x_change
gamedisplay.fill(white)
things(thing_startx, thing_starty, thing_width, thing_height, black)
thing_starty += thing_speed
car(x,y)
if x > dw - cw or x < 0:
crash()
gameexit = True
pygame.display.update()
clock.tick(100)
game_loop()
pygame.quit()
quit()
i was trying to make a game where you are a car and avoid blocks but i cant add the blocks because i get an error
your things function is formatted incorrectly. you have the parameter list as (thingx, thingy, thingw, color, thingh) but then you call it as (thingx, thingy, things, thingh, color). to make the errors go away all that you need to do is in the function definition switch color with thingh

Pygame bounce off ceiling acting strangely

I have been working on a pygame project where a player controls a rectangle that hits a ball. When the ball hit the side walls, it bounces off perfectly, same with the floor, but when it hits the top, it works very weirdly in a way I can't describe. If anyone wants to test this, my code is below, just hit the ball onto the roof and it will show what I am trying to explain. I would like it so you can't ram the ball into the ceiling so it goes off the screen and for it to be a clean bounce instead of what it dose right now and sort of rolls down if it touches the ceiling.
import pygame as pg
from pygame.math import Vector2
pg.init()
LIGHTBLUE = pg.Color('lightskyblue2')
DARKBLUE = pg.Color(11, 8, 69)
screen = pg.display.set_mode((800, 600))
width, height = screen.get_size()
clock = pg.time.Clock()
# You need surfaces with an alpha channel for the masks.
bluecar = pg.Surface((60, 30), pg.SRCALPHA)
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(395, 15)
ballrect = BALL.get_rect(center=ball_pos)
ball_vel = Vector2(0, 0)
mask_blue = pg.mask.from_surface(bluecar)
mask_ball = pg.mask.from_surface(BALL)
pos_blue = Vector2(740, 500) # Just use the pos vector instead of x, y.
bluerect = bluecar.get_rect(center = pos_blue)
vel_blue = Vector2(0, 0) # Replace x_change, y_change with vel_blue.
# A constant value that you add to the y-velocity each frame.
GRAVITY = .5
on_ground = False
ground_y = height - 100
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:
vel_blue.x = -5
elif event.key == pg.K_d:
vel_blue.x = 5
elif event.key == pg.K_w:
#if on_ground: # Only jump if the player is on_ground.
vel_blue.y = -12
on_ground = False
elif event.type == pg.KEYUP:
if event.key == pg.K_a and vel_blue.x < 0:
vel_blue.x = 0
elif event.key == pg.K_d and vel_blue.x > 0:
vel_blue.x = 0
ball_vel.y += GRAVITY # Accelerate downwards.
ball_pos += ball_vel # Move the ball.
ballrect.center = ball_pos # Update the rect.
# Bounce when the ball touches the bottom of the screen.
if ballrect.bottom >= ground_y:
# Just invert the y-velocity to bounce.
ball_vel.y *= -0.7 # Change this value to adjust the elasticity.
ball_vel.x *= .95 # Friction
# Don't go below the ground.
ballrect.bottom = ground_y
ball_pos.y = ballrect.centery
# Left and right wall collisions.
if ballrect.left < 0:
ball_vel.x *= -1
ballrect.left = 0
ball_pos.x = ballrect.centerx
elif ballrect.right > width:
ball_vel.x *= -1
ballrect.right = width
ball_pos.x = ballrect.centerx
if ballrect.top <= 0:
# Just invert the y-velocity to bounce.
ball_vel.y *= 0.4 # Change this value to adjust the elasticity.
# Add the GRAVITY value to vel_blue.y, so that
# the object moves faster each frame.
vel_blue.y += GRAVITY
pos_blue += vel_blue
bluerect.center = pos_blue # You have to update the rect as well.
# Stop the object when it's near the bottom of the screen.
if bluerect.bottom >= ground_y:
bluerect.bottom = ground_y
pos_blue.y = bluerect.centery
vel_blue.y = 0
on_ground = True
if bluerect.x < 0:
bluerect.x = 0
pos_blue.x = bluerect.centerx
elif bluerect.right > width:
bluerect.right = width
pos_blue.x = bluerect.centerx
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.
if vel_blue.x != 0: # Player is moving.
ball_vel = Vector2(vel_blue.x, -17)
else: # If the player is standing, I just update the vel.y.
ball_vel.y = -17
# Draw everything.
screen.fill(LIGHTBLUE)
pg.draw.line(screen, (0, 0, 0), (0, ground_y), (width, ground_y))
screen.blit(bluecar, bluerect) # Blit it at the rect.
screen.blit(BALL, ballrect)
pg.display.update()
clock.tick(60)
pg.quit()
Just set the ballrect.top coordinate to 1, so that it stays in the game area and also update the ball_pos.y afterwards.
if ballrect.top <= 0:
# Just invert the y-velocity to bounce.
ball_vel.y *= -0.4 # Change this value to adjust the elasticity.
ballrect.top = 1
ball_pos.y = ballrect.centery