lately I've been trying to create a ping pong game with Pygame but I can't seem to figure out why? or how the ball started tracing when I made it a moving object in the game. how can I go about fixing this problem?
import pygame, sys
def ball_ani():
global speedx, speedy
ball.x += speedx
ball.y += speedy
if ball.top <= 0 or ball.bottom >= h:
speedy *= -1
if ball.left <= 0 or ball.right >= w:
speedx *= -1
if ball.colliderect(player) or ball.colliderect(player2):
speedx *= -1
pygame.init()
clock = pygame.time.Clock()
w, h = 1000, 500
pygame.display.set_caption('Fut Pong')
win = pygame.display.set_mode((w, h))
win.fill("black")
pygame.draw.line(win, "white", (w//2, 0), (w//2, h), 3)
ball = pygame.Rect(w//2 - 10, h//2 - 10, 20, 20)
player = pygame.Rect(w - 15, h//2 - 50, 10, 100)
player2 = pygame.Rect(5, h//2 - 50, 10, 100)
speedx, speedy = 7, 7
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
ball_ani()
pygame.draw.ellipse(win, "green", ball)
pygame.draw.rect(win, "white", player)
pygame.draw.rect(win, "white", player2)
pygame.display.flip()
clock.tick(60)
You must clear the display in ever frame:
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = Fasle
ball_ani()
win.fill("black") # <--- this is missing
pygame.draw.ellipse(win, "green", ball)
pygame.draw.rect(win, "white", player)
pygame.draw.rect(win, "white", player2)
pygame.display.flip()
clock.tick(60)
pygame.quit()
exit()
The typical PyGame application loop has to:
limit the frames per second to limit CPU usage with pygame.time.Clock.tick
handle the events by calling either pygame.event.pump() or pygame.event.get().
update the game states and positions of objects dependent on the input events and time (respectively frames)
clear the entire display or draw the background
draw the entire scene (blit all the objects)
update the display by calling either pygame.display.update() or pygame.display.flip()
Related
I am making a pong game and the ball object leaves a trail when it moves and I was wondering how to stop it from doing this any help would be greatly appreciated. Thank you in advance.
Here is my code:
import sys
import pygame
pygame.init()
clock = pygame.time.Clock()
# screen setup
screen_width = 1200
screen_height = 700
screen = pygame.display.set_mode((screen_width, screen_height))
background = pygame.image.load("spacebackground.png").convert_alpha()
pygame.mouse.set_visible(False)
pygame.display.set_caption('pong')
# set up player and opponent and ball rect
player = pygame.Rect(screen_width - 20,screen_height/2 - 70,10,140)
opponent = pygame.Rect(10,screen_height/2 - 70,10,140 )
ball = pygame.Rect(screen_width/2-15, screen_height/2 - 15,30, 30)
ball_speed_x = 7
ball_speed_y = 7
# defining clock and colour
red = (0,0,0)
clock = pygame.time.Clock()
while True:
pygame.display.update(ball)
pygame.display.flip()
screen.blit(background, (0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
ball.x += ball_speed_x
ball.y += ball_speed_y
# Drawing the rects
pygame.draw.rect(background, red, player)
pygame.draw.rect(background, red, opponent)
pygame.draw.ellipse(background, red, ball)
pygame.display.update(ball)
clock.tick(60)
Draw the objects on the screen instead of on the background:
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
ball.x += ball_speed_x
ball.y += ball_speed_y
# draw background on the screen
screen.blit(background, (0, 0))
# draw objects on the screen
pygame.draw.rect(screen, red, player)
pygame.draw.rect(screen, red, opponent)
pygame.draw.ellipse(screen, red, ball)
# update the display
pygame.display.flip()
clock.tick(60)
pygame.quit()
sys.exit()
This question already has an answer here:
How can I move the ball instead of leaving a trail all over the screen in pygame?
(1 answer)
Closed 1 year ago.
So my ball animation for my multiplayer pong game is broken. Instead of moving and bouncing normally, the ball draws it self again after moving.
How do i fix the ball to not like clone itself after it moves 5 pixels? This is the animation code:
enter code here
import pygame
pygame.init()
#Creating the window
screen_width, screen_height = 1000, 600
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("Pong")
#FPS
FPS = 60
clock = pygame.time.Clock()
#Game Variables
light_grey = (170,170,170)
#Paddles
paddle_1 = pygame.Rect(screen_width - 30, screen_height/2 - 70, 20,100)
paddle_2 = pygame.Rect(10, screen_height/2 - 70, 20, 100)
#Ball
ball = pygame.Rect(screen_width/2, screen_height/2, 30, 30)
ball_xVel = 5
ball_yVel = 5
def ball_animation():
global ball_xVel, ball_yVel
ball.x += ball_xVel
ball.y += ball_yVel
if ball.x > screen_width or ball.x < 0:
ball_xVel *= -1
if ball.y > screen_height or ball.y < 0:
ball_yVel *= -1
def draw():
pygame.draw.ellipse(screen, light_grey, ball)
pygame.draw.rect(screen, light_grey, paddle_1)
pygame.draw.rect(screen, light_grey, paddle_2)
def main():
#main game loop
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
draw()
ball_animation()
pygame.display.update()
clock.tick(FPS)
pygame.quit()
if __name__ == "__main__":
main()
You have to clear the display in every frame with pygame.Surface.fill:
screen.fill(0)
The typical PyGame application loop has to:
handle the events by either pygame.event.pump() or pygame.event.get().
update the game states and positions of objects dependent on the input events and time (respectively frames)
clear the entire display or draw the background
draw the entire scene (blit all the objects)
update the display by either pygame.display.update() or pygame.display.flip()
limit frames per second to limit CPU usage with pygame.time.Clock.tick
def main():
# main application loop
run = True
while run:
# event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
# update and move objects
ball_animation()
# clear the display
screen.fill(0)
# draw the scene
draw()
# update the display
pygame.display.update()
# limit frames per second
clock.tick(FPS)
pygame.quit()
exit()
I am making a game with pygame where you have to dodge falling objects. I am having trouble with the collision detection, as when the obstacle touches the player, it just passes through to the bottom. Here is my code.
pygame.K_LEFT:
p_x_change = 0
screen.fill(WHITE)
pygame.draw.rect(screen,BLUE,(p_x,p_y, 60, 60))
pygame.draw.rect(screen,RED,(e_x,e_y,100,100))
p_x += p_x_change
e_y += e_ychange
if e_y > display_height:
e_y = 0
e_x = random.randint(1,display_width)
#Collision detection below
elif e_y == p_y - 90 and e_x == p_x :
done = True
clock.tick(60)
pygame.display.update()
Could you tell me what is wrong with my code?
I suggest to create two pygame.Rects, one for the player and one for the enemy. Then move the enemy by incrementing the y attribute of the rect and use the colliderect method to see if the two rects collide.
import random
import pygame
pygame.init()
screen = pygame.display.set_mode((640, 480))
display_width, display_height = screen.get_size()
clock = pygame.time.Clock()
BG_COLOR = pygame.Color('gray12')
BLUE = pygame.Color('dodgerblue1')
RED = pygame.Color('firebrick1')
# Create two rects (x, y, width, height).
player = pygame.Rect(200, 400, 60, 60)
enemy = pygame.Rect(200, 10, 100, 100)
e_ychange = 2
done = False
while not done:
# Event handling.
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
keys = pygame.key.get_pressed()
if keys[pygame.K_a]:
player.x -= 5
elif keys[pygame.K_d]:
player.x += 5
# Game logic.
enemy.y += e_ychange # Move the enemy.
if enemy.y > display_height:
enemy.y = 0
enemy.x = random.randint(1, display_width)
# Use the colliderect method for the collision detection.
elif player.colliderect(enemy):
print('collision')
# Drawing.
screen.fill(BG_COLOR)
pygame.draw.rect(screen, BLUE, player)
pygame.draw.rect(screen, RED, enemy)
pygame.display.flip()
clock.tick(30)
pygame.quit()
I've have this dodging aliens game and it's not working. I can get the front begin screen to open but then when I hit enter to start it crashes and freezes. I've tried running it from python.exe instead of just IDLE but in that case it just pops up then closes right down. A few errors popped up the first few times I tried to run it but now there are no errors indicating what might be wrong. It just stops responding. What am I doing wrong here?
import pygame, random, sys
from pygame.locals import *
def startGame():
if event.type == K_ENTER:
if event.key == K_ESCAPE:
sys.exit()
return
def playerCollision():
for a in aliens:
if playerRect.colliderect(b['rect']):
return True
return False
pygame.init()
screen = pygame.display.set_mode((750,750))
clock = pygame.time.Clock()
pygame.display.set_caption('Dodge the Aliens')
font = pygame.font.SysFont(None, 55)
playerImage = pygame.image.load('')
playerRect = playerImage.get_rect()
alienImage = pygame.image.load('')
drawText('Dodge the Aliens!', font, screen, (750 / 3), (750 / 3))
drawText('Press ENTER to start.', font, screen, (750 / 3) - 45, (750 / 3) + 65)
pygame.display.update()
topScore = 0
while True:
aliens = []
score = 0
playerRect.topleft = (750 /2, 750 - 50)
alienAdd = 0
while True:
score += 1
pressed = pygame.key.get_pressed()
if pressed[pygame.K_LEFT]: x -=3
if pressed[pygame.K_RIGHT]: x += 3
if pressed[pygame.K_ESCAPE]: sys.exit()
alienAdd += 1
if alienAdd == addedaliens:
aliendAdd = 0
alienSize = random.randint(10, 40)
newAlien = {'rect': pygame.Rect(random.randint(0, 750 - alienSize), 0 -alienSize, alienSize, alienSize), 'speed': random.randint(1, 8), 'surface':pygame.transform.scale(alienImage, (alienSize, alienSize)), }
aliens.append(newAlien)
for a in aliens[:]:
if a['rect'].top > 750:
aliens.remove(a)
screen.fill(0,0,0)
drawText('Score %s' % (score), font, screen, 10, 0)
screen.blit(playerImage, playerRect)
for a in aliens:
screen.blit(b['surface'], b['rect'])
pygame.display.update()
if playerCollision(playerRect, aliens):
if score > topScore:
topScore = score
break
clock.tick(60)
drawText('Game Over!', font, screen, (750 / 3), ( 750 / 3))
drawText('Press ENTER To Play Again.', font, screen, ( 750 / 3) - 80, (750 / 3) + 50)
pygame.display.update()
startGame()
Here's my new code after modifying it some
import pygame, random, sys
from pygame.locals import*
alienimg = pygame.image.load('C:\Python27\alien.png')
playerimg = pygame.image.load('C:\Python27\spaceship.png')
def playerCollision(): # a function for when the player hits an alien
for a in aliens:
if playerRect.colliderect(b['rect']):
return True
return False
def screenText(text, font, screen, x, y): #text display function
textobj = font.render(text, 1, (255, 255, 255))
textrect = textobj.get_rect()
textrect.topleft = (x,y)
screen.blit(textobj, textrect)
def main(): #this is the main function that starts the game
pygame.init()
screen = pygame.display.set_mode((750,750))
clock = pygame.time.Clock()
pygame.display.set_caption('Dodge the Aliens')
font = pygame.font.SysFont("monospace", 55)
pressed = pygame.key.get_pressed()
aliens = []
score = 0
alienAdd = 0
addedaliens = 0
while True: #our while loop that actually runs the game
for event in pygame.event.get(): #key controls
if event.type == KEYDOWN and event.key == pygame.K_ESCAPE:
sys.exit()
elif event.type == KEYDOWN and event.key == pygame.K_LEFT:
playerRect.x -= 3
elif event.type == KEYDOWN and event.key == pygame.K_RIGHT:
playerRect.x += 3
playerImage = pygame.image.load('C:\\Python27\\spaceship.png').convert() # the player images
playerRect = playerImage.get_rect()
playerRect.topleft = (750 /2, 750 - 50)
alienImage = pygame.image.load('C:\\Python27\\alien.png').convert() #alien images
alienAdd += 1
pygame.display.update()
if alienAdd == addedaliens: # randomly adding aliens of different sizes and speeds
aliendAdd = 0
alienSize = random.randint(10, 40)
newAlien = {'rect': pygame.Rect(random.randint(0, 750 - alienSize), 0 -alienSize, alienSize, alienSize), 'speed': random.randint(1, 8), 'surface':pygame.transform.scale(alienImage, (alienSize, alienSize)), }
aliens.append(newAlien)
for a in aliens[:]:
if a['rect'].top > 750:
aliens.remove(a) #removes the aliens when they get to the bottom of the screen
screen.blit(screen, (0,0))
screenText('Score %s' % (score), font, screen, 10, 0)
screen.blit(playerImage, playerRect)
for a in aliens:
screen.blit(b['surface'], b['rect'])
pygame.display.flip()
if playerCollision(playerRect, aliens):
if score > topScore:
topScore = score
break
clock.tick(60)
screenText('Game Over!', font, screen, (750 / 6), ( 750 / 6))
screenText('Press ENTER To Play Again.', font, screen, ( 750 / 6) - 80, (750 / 6) + 50)
pygame.display.update()
main()
I still see several issues with your code and I think you're trying to do too much at once for the very beginning. Try to keep it as simple as possible. Try creating a display and draw some image:
import pygame
pygame.init()
display = pygame.display.set_mode((750, 750))
img = pygame.image.load("""C:\\Game Dev\\alien.png""")
display.blit(img, (0, 0))
pygame.display.flip()
You'll have to adjust the img path of course. Running this you should either get an explicit Error (which you should then post in another thread) or see your img on the screen. BUT the program will not respond as there's no event handling and no main loop at all.
To avoid this, you could introduce a main loop like:
import sys
import pygame
pygame.init()
RESOLUTION = (750, 750)
FPS = 60
display = pygame.display.set_mode(RESOLUTION)
clock = pygame.time.Clock()
img = pygame.image.load("""C:\\Game Dev\\alien.png""")
while True: # <--- game loop
# check quit program
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
# clear the screen
display.fill((0, 0, 0))
# draw the image
display.blit(img, (0, 0))
# update the screen
pygame.display.flip()
# tick the clock
clock.tick(FPS)
This should result in a program that displays the same img over and over, and it can be quit properly using the mouse. But still it's like a script, and if someone imported this, it would execute immediately, which is not what we want. So let's fix that as well and wrap it all up in a main function like this:
import sys
import pygame
#defining some constants
RESOLUTION = (750, 750)
FPS = 60
def main(): # <--- program starts here
# setting things up
pygame.init()
display = pygame.display.set_mode(RESOLUTION)
clock = pygame.time.Clock()
img = pygame.image.load("""C:\\Game Dev\\alien.png""")
while True: # <--- game loop
# check quit program
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
# clear the screen
display.fill((0, 0, 0))
# draw the image
display.blit(img, (0, 0))
# update the screen
pygame.display.flip()
# tick the clock
clock.tick(FPS)
if __name__ == "__main__":
main()
The 'if name == "main":' ensures that the program does not execute when it's imported.
I hope this helps. And remember: Don't try too much all at once. Take small steps, one after another, and try to keep the control over your program. If needed, you can even put a print statement after every single line of code to exactly let you know what your program does and in what order.
I have to move the rectangular object straight through the pygame window. I have tried some code with pygame. The code is
import pygame
from itertools import cycle
pygame.init()
screen = pygame.display.set_mode((300, 300))
s_r = screen.get_rect()
player = pygame.Rect((100, 100, 50, 50))
timer = pygame.time.Clock()
movement = "straight"
x = 0
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
raise
if movement == 'straight':
x += 50
screen.fill(pygame.color.Color('Black'))
pygame.draw.rect(screen, pygame.color.Color('Grey'), player)
pygame.display.flip()
timer.tick(25)
Here the image didnt moves. What I need is that the image must be moved in a straight way.
x is adding, but that does not affect player, which actually affects the drawing of the rectangle.
import pygame
from itertools import cycle
pygame.init()
screen = pygame.display.set_mode((300, 300))
s_r = screen.get_rect()
timer = pygame.time.Clock()
movement = "straight"
x = 0
player = pygame.Rect((x, 100, 50, 50))
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
raise
if movement == 'straight':
x += 10
player = pygame.Rect((x, 100, 50, 50))
if x >= 300:
x = 0
screen.fill(pygame.color.Color('Black'))
pygame.draw.rect(screen, pygame.color.Color('Grey'), player)
pygame.display.flip()
timer.tick(25)
You need to adjust the player rectangle each time you change x. From http://www.pygame.org/docs/ref/rect.html, you can see that the first two arguments are "left" and "top". So, if you want to the rectangle to move from left to right, you'll want something like this:
player = pygame.Rect((100 + x, 100, 50, 50))
pygame.draw.rect(screen, pygame.color.Color('Grey'), player)
import pygame
BLACK = pygame.color.Color('Black')
GREY = pygame.color.Color('Grey')
pygame.init()
screen = pygame.display.set_mode((300, 300))
screen_rect = screen.get_rect()
timer = pygame.time.Clock()
movement = "straight"
player = pygame.Rect(0, 100, 50, 50) # four aguments in place of tuple (,,,)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if movement == 'straight':
player.x += 10
if player.x >= 300: # check only when `player.x` was changed
player.x = 0
screen.fill(BLACK)
pygame.draw.rect(screen, GREY, player)
pygame.display.flip()
timer.tick(25)
BTW:
don't use raise to exit program.
use readable variable - not s_r but screen_rect
you don't need x - you have player.x
you can create rectangle only once
remove repeated empty lines when you add code to question