so I am making a code where there is a character(A rectangle) and and Balloon(A circle) and the character has to catch the balloons before it hits the ground. Everything worked fine until I tried making the game look a little better and used the blit function to add an image. For some reason my text keeps buffering now.
Code:
import random
import pygame
from pygame.locals import *
pygame.init()
#Variables
white = (255, 255, 255)
blue = (70,130,180)
black = (0,0,0)
red = (255,0,0)
x = 400
y = 450
score = 0
cooly = 100
randomx = random.randint(100,800)
clock = pygame.time.Clock()
#screen stuff
screenwidth = 800
screenheight = 600
screen = pygame.display.set_mode((screenwidth, screenheight))
pygame.display.set_caption("Balloon Game!")
#end of screen stuff
#Initializing font
def show_text(msg, x, y, color,size):
fontobj= pygame.font.SysFont("freesans", size)
msgobj = fontobj.render(msg,False,color)
screen.blit(msgobj,(x, y))
#Game loop
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
exit()
# Draw Character
screen.fill(blue)
character = pygame.draw.rect(screen, red, (x, y, 60, 60))
#End of Drawing Character
#Draw Balloons
balloon = pygame.draw.circle(screen, (black), (randomx, cooly), 30, 30)
cooly = cooly + 2
# Making Arrow Keys
keyPressed = pygame.key.get_pressed()
if keyPressed[pygame.K_LEFT]:
x -= 3
if keyPressed[pygame.K_RIGHT]:
x += 3
#Drawing Cool Stuff
Cloud = pygame.image.load('Cloud.png')
screen.blit(Cloud,(100,75))
pygame.display.update()
#End of making arrow keys
show_text("Score:",130,0,black,50)
show_text(str(score),250,0,black,50)
#Collision
if balloon.colliderect(character):
randomx = random.randint(100,800)
cooly = 100
score = score + 1
#end of collision
#Ending
if cooly >= 600:
screen.fill(blue)
show_text("Game Over!", 200, 250, black, 100)
show_text("Score :", 200, 350, black, 75)
show_text(str(score), 400, 350, black, 75)
#Polishing
if score == score + 5:
cooly += 1
x += 3
pygame.display.update()
clock.tick(250)
The problem is caused by multiple calls to pygame.display.update(). An update of the display at the end of the application loop is sufficient. Multiple calls to pygame.display.update() or pygame.display.flip() cause flickering.
Remove all calls to pygame.display.update() from your code, but call it once at the end of the application loop.
Do not create the font object and do not load the images in the application loop. This are very expensive operatios, because the filed have to be read and interpreted:
fontobj= pygame.font.SysFont("freesans", size) #<-- INSERT
def show_text(msg, x, y, color,size):
# fontobj= pygame.font.SysFont("freesans", size) <-- DELET
msgobj = fontobj.render(msg,False,color)
screen.blit(msgobj,(x, y))
Cloud = pygame.image.load('Cloud.png') #<-- INSERT
# [...]
while True:
# [...]
# Cloud = pygame.image.load('Cloud.png') <-- DELETE
screen.blit(Cloud,(100,75))
# pygame.display.update() <-- DELETE
# [...]
pygame.display.update()
clock.tick(250)
Related
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'm just trying something with collisions and found the way to check one side of the rectangle with the other side.
I have the following problem:
If I move my game character (pink box) from the left against the object, my game character just moves through it:
If I come from the other side, everything works and my game character stops.
I mean to say that I need the same code for both sides but have to change the sides from if not player_rect.left == other_rect.right: to if not player_rect.right == other_rect.left:. But this does not work for one side.
import pygame
import sys
pygame.init()
clock = pygame.time.Clock()
window = pygame.display.set_mode([1200, 800])
pygame.display.set_caption("Collision Test")
x = 300
y = 300
width = 48
height = 96
velocity = 5
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
is_pressed = pygame.key.get_pressed()
player_rect = pygame.Rect(x, y, width, height)
other_rect = pygame.Rect(400, 300, 50, 50)
if is_pressed[pygame.K_d]:
if not player_rect.right == other_rect.left:
x += velocity
if is_pressed[pygame.K_a]:
if not player_rect.left == other_rect.right:
x -= velocity
window.fill((100, 150, 50))
pygame.draw.rect(window, (255, 50, 100), player_rect)
pygame.draw.rect(window, (255, 100, 50), other_rect)
pygame.display.update()
clock.tick(60)
Use collideRect().
Move the object and test if the rectangles are colliding. When a collision is detected, change the position of the object according to the moving direction:
is_pressed = pygame.key.get_pressed()
move_right = is_pressed[pygame.K_d]
move_left = is_pressed[pygame.K_a]
if move_right:
x += velocity
if move_left:
x -= velocity
player_rect = pygame.Rect(x, y, width, height)
other_rect = pygame.Rect(400, 300, 50, 50)
if player_rect.colliderect(other_rect):
if move_right:
player_rect.right = other_rect.left
x = player_rect.left
if move_left:
player_rect.left = other_rect.right
x = player_rect.left
For a smooth movement you've to do evaluate pygame.key.get_pressed() in the application loop rather than the event loop.
See also What all things happens inside pygame when I press a key? When to use pygame.event==KEYDOWN.
import pygame
import sys
pygame.init()
clock = pygame.time.Clock()
window = pygame.display.set_mode([1200, 800])
pygame.display.set_caption("Collision Test")
x = 300
y = 300
width = 48
height = 96
velocity = 5
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
is_pressed = pygame.key.get_pressed()
move_right = is_pressed[pygame.K_d]
move_left = is_pressed[pygame.K_a]
if move_right:
x += velocity
if move_left:
x -= velocity
player_rect = pygame.Rect(x, y, width, height)
other_rect = pygame.Rect(400, 300, 50, 50)
if player_rect.colliderect(other_rect):
if move_right:
player_rect.right = other_rect.left
x = player_rect.left
if move_left:
player_rect.left = other_rect.right
x = player_rect.left
window.fill((100, 150, 50))
pygame.draw.rect(window, (255, 50, 100), player_rect)
pygame.draw.rect(window, (255, 100, 50), other_rect)
pygame.display.update()
clock.tick(60)
import pygame
Red = 255, 0, 0
Black= 0,0,0
rectXpos = 2
rectypos = 2
speed = 2
screenedgex = 500
pygame.init()
window = pygame.display.set_mode(size=(500, 500))
clock = pygame.time.Clock()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.display.update()
window.fill(Black)
square = pygame.draw.rect(window, Red, [rectXpos, rectypos, 50, 50],2)
rectXpos += 2
if rectXpos < 500:
rectXpos -= 2
clock.tick(60)
print(rectXpos)`enter code here`
so what am i doing wrong? i tried making a if statment to stop the ball and reverse it but it keeps the ball at the edge of the window
This is complete code, I separated the x and y bounces, so you can use either one, also updated the code a bit more, plus some extra formatting.
# Imports
import pygame
# Vars
Red = 255, 0, 0
Black= 0,0,0
rectXpos = 2
rectYpos = 2
rect_width = 50
rect_height = 50
screen_width = 500
screen_height = 500
block_x_direction = 1
block_y_direction = 1
# Setup Code
pygame.init()
window = pygame.display.set_mode(size=(screen_width, screen_height))
clock = pygame.time.Clock()
running = True
# Game Loop
########################################################
while running:
# Event Loop
########################################################
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# Game Code - Update
########################################################
# Game Code - Update - Rect X Bounce
if rectXpos + (rect_width)>= screen_width:
block_x_direction = block_x_direction * -1
rectXpos += 2 * block_x_direction
# Game Code - Update - Rect Y Bounce
if rectYpos + (rect_height)>= screen_height:
block_y_direction = block_y_direction * -1
rectYpos += 2 * block_y_direction
# - Tick Game
clock.tick(60)
# Game Code - Render
########################################################
window.fill(Black)
square = pygame.draw.rect(window, Red, [rectXpos, rectYpos, rect_width, rect_height],2)
pygame.display.update()
# Game Code - Debug Code
########################################################
print(clock.tick)
I assume you want to move rectangle to and fro when mouse is moving.
There are 2 things you are doing wrong here:
1. correct this:
if rectXpos > 500: as you have to decrease X when it will reach 500
2. when reach rectXpos 501 it should change its direction till it reach rectXpos 0
but you have decreased position till it is greater than 500 so it will then stuck in between 499 to 501
correct code:
import pygame
Red = 255, 0, 0
Black= 0,0,0
rectXpos = 2
rectypos = 2
speed = 2
screenedgex = 500
pygame.init()
window = pygame.display.set_mode(size=(500, 500))
clock = pygame.time.Clock()
running = True
k=1 #here is k used to indicate direction
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.display.update()
window.fill(Black)
square = pygame.draw.rect(window, Red, [rectXpos, rectypos, 50, 50],2)
rectXpos += 2*k #here is addition of 2 in given direction
if (rectXpos > 500) or (rectXpos < 0): #here is condition to change direction
k=-k
clock.tick(60)
print(rectXpos)
You should add speed to position and when you touch border then you should change speed to -speed.
You could also use pygame.Rect() to keep position and size - it has properties .left and .right (and other) which can be very useful. And you can use Rect to draw pygame.draw.rect() (or to check collision with other Rect)
import pygame
# --- constants --- (UPPER_CASE_NAMES)
RED = (255, 0, 0)
BLACK = (0, 0, 0)
WIDTH = 500
HEIGHT = 500
# --- main ---
speed = 10
pygame.init()
window = pygame.display.set_mode((WIDTH, HEIGHT))
item = pygame.Rect(0, 0, 50, 50)
clock = pygame.time.Clock()
running = True
while running:
# - events -
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# - updates - (without draws)
item.x += speed
if item.right >= WIDTH:
speed = -speed
if item.left <= 0:
speed = -speed
# - draws - (without updates)
window.fill(BLACK)
pygame.draw.rect(window, RED, item, 2)
pygame.display.update()
clock.tick(60)
# - end -
pygame.quit()
I am trying to make a simple moving game with Pygame since I am currently learning it. Whenever i try to run the code I keep on getting a problem saying: "pygame.error: display Surface quit"
I've tried adding "break" at the end but the window closes immediately! I've tried searching for the solution but I can't find one that helps my code.
import pygame
import random
pygame.init()
# Window setup
size = [400, 400]
screen = pygame.display.set_mode(size)
clock = pygame.time.Clock()
# player position
x = size[0] // 2
y = size[1] // 2
# ball position
ballX = random.randrange(0, size[0])
ballY = random.randrange(0, size[1])
# colours
red = pygame.color.Color('#FF8080')
blue = pygame.color.Color('#8080FF')
white = pygame.color.Color('#FFFFFF')
black = pygame.color.Color('#000000')
def CheckOffScreenX(x):
if x > size[0]:
x = 0
elif x < 0:
x = size[0]
return x
def CheckOffScreenY(y):
if y > size[1]:
y = 0
elif y < 0:
y = size[1]
return y
# Game loop
done = False
while not done:
screen.fill(black)
keys = pygame.key.get_pressed()
#player movement
if keys[pygame.K_w]:
y -=1
if keys[pygame.K_s]:
y +=1
if keys[pygame.K_a]:
x -=1
if keys[pygame.K_d]:
x +=1
# Check offscreen
x = CheckOffScreenX(x)
y = CheckOffScreenY(y)
# draw player
pygame.draw.circle(screen, red, [x, y], 6)
pygame.display.flip()
# draw ball
pygame.draw.circle(screen, blue, [ballX, ballY], 6)
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
clock.tick(32)
pygame.quit()
Any help would be appreciated!
The issue is the pygame.quit() insider the main loop. pygame.quit() uninitialize all pygame modules. After the modules are uninitialized all further calls to pygyme instructions (in the next frame) will cause a crash.
Do pygame.quit() after the main loop, when the application has end.
done = False
while not done:
screen.fill(black)
# [...]
# pygame.quit() <----- delete
pygame.quit() # <---- add
Note, probably you've added an Indentation when you copied the code.
this program makes boxes move, but i need to make them move randomly and indepensent of each other,
by calling the method "rect.move()" for each of the boxes but i don't know how to do that can u help me.
ex. of how it should not look like: https://youtu.be/D7rkcA0-BR0
import pygame
import random
# Define some colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
class Rect():
def __init__(self):
self.rectXPos = 0
self.rectYPos = 0
self.height = 0
self.width = 0
self.changeX = 0
self.changeY = 0
self.x = 0
self.y = 0
def move(self):
self.x += self.changeX
self.y += self.changeY
def draw(self,screen):
pygame.draw.rect(screen,RED,[self.x + self.rectXPos, self.y + self.rectYPos, self.height,self.width])
pygame.init()
# Set the width and height of the screen [width, height]
size = (700, 500)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("My Game")
# Loop until the user clicks the close button.
done = False
# Used to manage how fast the screen updates
clock = pygame.time.Clock()
myList =[]
for i in range(10):
rect = Rect()
rect.rectXPos = random.randrange(0,700)
rect.rectYPos = random.randrange(0,500)
rect.height = random.randrange(20,70)
rect.width = random.randrange(20,70)
rect.changeX = random.randrange(-3,3)
rect.changeY = random.randrange(-3,3)
myList.append([rect.rectXPos , rect.rectYPos, rect.height, rect.width, rect.changeX, rect.changeY])
# -------- Main Program Loop -----------
while not done:
# --- Main event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# --- Game logic should go here
# --- Screen-clearing code goes here
# Here, we clear the screen to white. Don't put other drawing commands
# above this, or they will be erased with this command.
# If you want a background image, replace this clear with blit'ing the
# background image.
screen.fill(WHITE)
for i in range(10):
rect.rectXPos = myList[i][0]
rect.rectYPos = myList[i][1]
rect.height = myList[i][2]
rect.width = myList[i][3]
rect.changeX = myList[i][4]
rect.changeY= myList[i][5]
rect.draw(screen)
rect.move()
# --- Drawing code should go here
# --- Go ahead and update the screen with what we've drawn.
pygame.display.flip()
# --- Limit to 60 frames per second
clock.tick(60)
# Close the window and quit.
pygame.quit()
this is premade code from http://programarcadegames.com/
What you need is for the Rect attributes to be randomly generated with the random module. I have modified the code you gave an made some changes.
Firstly I changed the draw method so that it just draws at the x and y values.
The biggest change was that instead of the big complicated myList list in your code, I just stored 10 Rect objects in a list called myRects which I think is much simpler.
You can fiddle around some more with the number generation from around Line 45-52. You can read a bit more on the random.randrange() function here: https://docs.python.org/3/library/random.html#functions-for-integers
I hope this answer helped you! If you have any further questions please post a comment below!
import pygame
import random
# Define some colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
class Rect():
def __init__(self):
self.x = 0
self.y = 0
self.height = 0
self.width = 0
self.changeX = 0
self.changeY = 0
def move(self):
self.x += self.changeX
self.y += self.changeY
def draw(self, screen):
pygame.draw.rect(screen, RED, [self.x, self.y, self.width, self.height], 0)
pygame.init()
size = (700, 500)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("My Game")
done = False
clock = pygame.time.Clock()
myRects = []
for i in range(10):
rect = Rect()
rect.x = random.randrange(0, 700)
rect.y = random.randrange(0, 700)
rect.width = random.randrange(20, 70)
rect.height = random.randrange(20, 70)
rect.changeX = random.randrange(-3, 3)
rect.changeY = random.randrange(-3, 3)
myRects.append(rect)
print(myRects)
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
screen.fill(WHITE)
for rect in myRects:
rect.draw(screen)
rect.move()
pygame.display.update()
clock.tick(10)
pygame.quit()
quit()
I have been trying to animate drawing elements without success. I can animate imported images, but when I try to animate drawings generated by pygame they remain static.
Edit: By "animate" I mean "to move". As in making a circle move in x and y direction.
This is my code:
import pygame, sys
from pygame.locals import *
pygame.init()
FPS = 60
WIDTH = 600
HEIGHT = 500
fpsClock = pygame.time.Clock()
DISPLAYSURF = pygame.display.set_mode((WIDTH, HEIGHT), 0, 32)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
ballx = WIDTH / 2
bally = HEIGHT / 2
ball_vel = [1, 1]
ball_pos =(ballx, bally)
RADIUS = 20
# Game Loop:
while True:
# Check for quit event
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
# Erase the screen (I have tried with and without this step)
DISPLAYSURF.fill(BLACK)
# Update circle position
ballx += ball_vel[0]
bally += ball_vel[1]
# Draw Circle (I have tried with and without locks/unlocks)
DISPLAYSURF.lock()
pygame.draw.circle(DISPLAYSURF, WHITE, ball_pos, RADIUS, 2)
DISPLAYSURF.unlock()
# Update the screen
pygame.display.update()
fpsClock.tick(FPS)
I've tried with and without locking/unlocking the display surface (as the documentation suggests). I've tried with and without erasing the screen before updating it (as some tutorials suggest). I just can't get it to work.
What am I doing wrong? How do you animate drawing elements?
Thanks for your time.
You are not updating the ball_pos tuple: you set it to the start coordinates:
ballx = WIDTH / 2
bally = HEIGHT / 2
ball_vel = [1, 1]
ball_pos =(ballx, bally)
You later update ballx and bally, but never set ball_pos again to ballx, and bally.
In the while loop, after setting the ballx and bally, do this:
ball_pos = (ballx,bally)
import pygame, sys
from pygame.locals import *
pygame.init()
FPS = 60
WIDTH = 600
HEIGHT = 500
fpsClock = pygame.time.Clock()
DISPLAYSURF = pygame.display.set_mode((WIDTH, HEIGHT), 0, 32)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
ballx = WIDTH / 2
bally = HEIGHT / 2
ball_vel = [1, 1]
ball_pos =(ballx, bally)
RADIUS = 20
# Game Loop:
while True:
# Check for quit event
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
# Erase the screen (I have tried with and without this step)
DISPLAYSURF.fill(BLACK)
# Update circle position
ballx += ball_vel[0]
bally += ball_vel[1]
ball_pos =(ballx, bally)
# Draw Circle (I have tried with and without locks/unlocks)
pygame.draw.circle(DISPLAYSURF, WHITE, ball_pos, RADIUS, 2)
# Update the screen
pygame.display.flip()
fpsClock.tick(FPS)
flip = update()