I need help attaching an image to a rectangle in pygame.. I am trying to make a snake game in python(you know, the one that eats the apples and grows lol) and I wanna attach my teacher's face to head of the snake.
I've already tried defining a variable to import the image and then renaming the rectangle to be that image, but nothing seems to work.
snakeFace = pygame.image.load("Morrison.jpg").convert_alpha()
rect = snakeFace.get_rect()
screenWidth = 500
X=50
y= 50
height = 20
vel = 20
run = True
lastKey = None
while run:
pygame.time.delay(10) #1/2 milisecond delay
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False #this controls the "X" button
if event.type == pygame.KEYDOWN:
lastKey = event.key
keys = pygame.key.get_pressed()
if lastKey == pygame.K_LEFT and x > vel:
x-=vel
if lastKey == pygame.K_RIGHT and x< screenWidth - width -vel:
x+=vel
if lastKey == pygame.K_DOWN and y < screenWidth - height - vel:
y+= vel
if lastKey == pygame.K_UP and y > vel:
y-=vel
win.fill((0,0,0))
pygame.draw.rect(win, (255, 0, 0), (x, y, width, height))
pygame.display.update()
I expected there to be a square with my teachers face on it that runs around on the screen after a particular key is pressed on the screen but its just the regular old red square.
It's a red square because the code is drawing a red square:
pygame.draw.rect(win, (255, 0, 0), (x, y, width, height))
Paint the snakeFace bitmap instead:
win.blit(snakeFace, (x, y))
Here is the full example code that I use to add images to rect objects.
import pygame
vel = 5
pygame.init()
screen = pygame.display.set_mode((800,600))
pygame.display.set_caption('captions')
icon = pygame.image.load('test123.jpg')
pygame.display.set_icon(icon)
playerimg = pygame.image.load('test123.jpg')
playerx = 370
playery = 480
def player():
screen.blit(playerimg,(playerx,playery))
running = True
while running:
screen.fill((0, 0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
keys = pygame.key.get_pressed()
if keys[pygame.K_a] and playerx > vel:
playerx += vel
player()
pygame.display.update()
Related
trying to use pygames collide rect method to detect collision for the x axis of the player.
the collisions are not registering at all... which is my problem
im trying to mave a square to the right when i hold down the d button, and when i reach the platform, the program below should restrict me from passing through it
player_x = 400
player_y = 300
pygame.init()
player = pygame.image.load(the player)
player_rect = player.get_rect(midbottom = (player_x,player_y))
platform=pygame.image.load(the platform)
platform_rect=platform.get_rect(midbottom = (500,320))
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit
exit()
keys = pygame.key.get_pressed()
if keys[pygame.K_d]:
player_x += 1
platforms = [platform_rect]
x_collision = False
new_player_rect = player.get_rect(midbottom = (player_x,player_y))
for p in platforms:
if p.colliderect(new_player_rect):
x_collision = True
break
if not x_collision:
current_player_x = player_x
screen.blit(BACKGROUND, (0,0))
screen.blit(platform,platform_rect)
screen.blit(player,(current_player_x, player_y))
pygame.display.flip()
You need to set player_x = current_player_x before you change player_x, becuase If the plyer collides with the platform player_x needs to set to its previous position:
current_player_x = player_x
run = True
while run:
# [...]
player_x = current_player_x
if keys[pygame.K_d]:
player_x += 1
However you can simplify the code using new_player_rect. Minimal example:
import pygame
pygame.init()
screen = pygame.display.set_mode((600, 400))
clock = pygame.time.Clock()
BACKGROUND = pygame.Surface(screen.get_size())
player_x = 400
player_y = 300
player = pygame.Surface((20, 20))
player.fill((255, 0, 0))
player_rect = player.get_rect(midbottom = (player_x,player_y))
platform = pygame.Surface((20, 100))
platform.fill((128, 128, 128))
platform_rect=platform.get_rect(midbottom = (500,320))
current_player_x = player_x
run = True
while run:
clock.tick(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit
exit()
keys = pygame.key.get_pressed()
new_player_rect = player.get_rect(midbottom = (player_x, player_y))
if keys[pygame.K_d]:
new_player_rect.x += 1
platforms = [platform_rect]
x_collision = False
for p in platforms:
if p.colliderect(new_player_rect):
print("collide")
x_collision = True
break
if not x_collision:
player_x = new_player_rect.centerx
screen.blit(BACKGROUND, (0,0))
screen.blit(platform,platform_rect)
screen.blit(player, player.get_rect(midbottom = (player_x, player_y)))
pygame.display.flip()
This question already has answers here:
How to get keyboard input in pygame?
(11 answers)
I was wondering why my playerIMG wont load in pygame
(2 answers)
How can I make a sprite move when key is held down
(6 answers)
Closed 7 months ago.
Here is my code below this is my first pygame project any help will be appreciated! I think its something to do with the
def player(playerX,playerY):
pygame.display.update()
block of code. Though when I play around with it sometimes it won't even display my background object and only displays the screen filler black.
#initializing the game
pygame.init()
FPS = 60
black = (0,0,0)
white = (255,255,255)
#creating the screen and setting the size
gameDisplay = pygame.display.set_mode((800,600))
#setting the title of the window
pygame.display.set_caption('Space Crashers')
#going into our files and loading the image for the background
background = pygame.image.load(r'C:\\Users\\ahmad\\Downloads\\pygame projects\\Assets\\newBackground.jpg')
#player image and model
playerImg = pygame.image.load(r'C:\\Users\\ahmad\\Downloads\\pygame projects\\Assets\\blueShip.png')
#these cords are for the player ship to be in the middle of the screen
playerX = 370
playerY = 480
#creating player function
def player(x,y):
gameDisplay.blit(playerImg, (x,y))
# window creation
clock = pygame.time.Clock()
running = True
while running:
#setting the background to black
gameDisplay.fill(black)
#then changing the background to the image we loaded
gameDisplay.blit(background,(0,0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.display.update()
# if the keystroke is pressed, the player will move
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerX -= .01
if event.key == pygame.K_RIGHT:
playerX += .01
if event.key == pygame.K_UP:
playerY -= .01
if event.key == pygame.K_DOWN:
playerY += .01
def player(playerX,playerY):
pygame.display.update()
clock.tick(FPS)
pygame.quit()
quit()
In your game loop you should normally
fill your screen black
draw and blit everything to the screen
update the screen
catch the events
let the clock tick
You didn't call the player() function in your loop to draw the player image neither the clock.tick() function. You don't need to overwrite the player function. Also if ran without any arguments, you should only have one event loop, otherwise some events could be ignored.
pygame.init()
FPS = 60
black = (0, 0, 0)
white = (255, 255, 255)
# window
gameDisplay = pygame.display.set_mode((800,600))
pygame.display.set_caption('Space Crashers')
# background image
background = pygame.image.load(r'C:\\Users\\ahmad\\Downloads\\pygame projects\\Assets\\newBackground.jpg')
# player image
playerImg = pygame.image.load(r'C:\\Users\\ahmad\\Downloads\\pygame projects\\Assets\\blueShip.png')
# these coords are for the player ship to be in the middle of the screen
playerX = 370
playerY = 480
# draw player
def player(x, y):
gameDisplay.blit(playerImg, (x, y))
# window creation
clock = pygame.time.Clock()
running = True
while running:
# reset display
gameDisplay.fill(black)
# blit background
gameDisplay.blit(background, (0, 0))
### blit the player ###
player(playerX, playerY)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# move player
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerX -= .01
if event.key == pygame.K_RIGHT:
playerX += .01
if event.key == pygame.K_UP:
playerY -= .01
if event.key == pygame.K_DOWN:
playerY += .01
pygame.display.update()
clock.tick(FPS)
pygame.quit()
I am new to programming with pygame and python itself. I was trying to make a simple local multiplayer game using pygame. I wrote my code while watching a tutorial on moving only one rectangle because I did not find anything on what I am trying to do. When I finished, I copied the part of the script with the variables and the movement for the rectangle and then pasted it and changed the variable names so it does not crash or something. Now, here comes my problem: because the movement is simple, it would print a new rectangle, if I press the buttons to move. Because of that, the background is refreshing its color all the time (or something like that) so only the one rectangle I want to move is shown. But if there is a second rect, the color covers it, and only one is visible all the time. How can I fix that?
Here is the code:
import pygame
pygame.init()
win = pygame.display.set_mode((500, 500))
pygame.display.set_caption("local multiplayer")
#variables player 1
X = 200
Y = 200
Width = 40
Height = 60
Vel = 5
#variables player 2
x = 50
y = 50
width = 40
height = 60
vel = 5
run = True
while run:
pygame.time.delay(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
#player 1
if keys[pygame.K_a]:
X -= Vel
if keys[pygame.K_d]:
X += Vel
if keys[pygame.K_w]:
Y -= Vel
if keys[pygame.K_s]:
Y += Vel
win.fill((0, 0, 0))
pygame.draw.rect(win, (255, 255, 255), (X, Y, Width, Height))
pygame.display.update()
#player 2
if keys[pygame.K_LEFT]:
x -= vel
if keys[pygame.K_RIGHT]:
x += vel
if keys[pygame.K_UP]:
y -= vel
if keys[pygame.K_DOWN]:
y += vel
win.fill((0, 0, 0))
pygame.draw.rect(win, (255, 255, 255), (x, y, width, height))
pygame.display.update()
pygame.quit()
When you call win.fill((0, 0, 0)) the entire display is cleared. You have to draw the rectangles at once after clearing the display.
Update of the display at the end of the application loop. Multiple calls to pygame.display.update() or pygame.display.flip() cause flickering (see Why is the PyGame animation is flickering).
Simplify the code and use pygame.Rect objects to represent the players. Use pygame.Rect.clamp_ip to prevent the player from leaving the screen.
import pygame
pygame.init()
win = pygame.display.set_mode((500, 500))
pygame.display.set_caption("local multiplayer")
clock = pygame.time.Clock()
player1 = pygame.Rect(200, 200, 40, 60)
vel1 = 1
player2 = pygame.Rect(50, 40, 40, 60)
vel2 = 1
run = True
while run:
clock.tick(50)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
player1.x += (keys[pygame.K_d] - keys[pygame.K_a]) * vel1
player1.y += (keys[pygame.K_s] - keys[pygame.K_w]) * vel1
player2.x += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * vel2
player2.y += (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * vel2
player1.clamp_ip(win.get_rect())
player2.clamp_ip(win.get_rect())
win.fill((0, 0, 0))
pygame.draw.rect(win, (255, 255, 255), player1)
pygame.draw.rect(win, (255, 255, 255), player2)
pygame.display.update()
pygame.quit()
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()
You are doing win.fill((0, 0, 0)) right after displaying player 1. Remove this code before you display the second character. Also, keep the fill line at the top of your app loop. This would give:
pygame.init()
win = pygame.display.set_mode((500, 500))
pygame.display.set_caption("local multiplayer")
#variables player 1
X = 200
Y = 200
Width = 40
Height = 60
Vel = 5
#variables player 2
x = 50
y = 50
width = 40
height = 60
vel = 5
run = True
while run:
win.fill((0, 0, 0))
pygame.time.delay(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
#player 1
if keys[pygame.K_a]:
X -= Vel
if keys[pygame.K_d]:
X += Vel
if keys[pygame.K_w]:
Y -= Vel
if keys[pygame.K_s]:
Y += Vel
pygame.draw.rect(win, (255, 255, 255), (X, Y, Width, Height))
#player 2
if keys[pygame.K_LEFT]:
x -= vel
if keys[pygame.K_RIGHT]:
x += vel
if keys[pygame.K_UP]:
y -= vel
if keys[pygame.K_DOWN]:
y += vel
pygame.draw.rect(win, (255, 255, 255), (x, y, width, height))
pygame.display.update()
pygame.quit()
It is also good practice to only update the screen once per loop. Another thing I would do is put the input all in the same if block (but that is not necessary). To further improve your code- consider making a player class that has a render function to display itself, along with an update function to handle control.
I've been set a challenge to make a game using pygame ( I am making snake so it should be easy... but I've never used pygame) so using a more efficient language isn't an option.So my question is that I updating the snake grid is too slow and I'm not experienced enough in pygame to fix this, can anyone who is help.Also as a note if I only fill the grid it doesn't clear behind the Snake.
Using python 3.8
import pygame
import time
import random
pygame.init()
display_width = 800
display_height = 600
display = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption("Snake")
pureblue = (0,0,255)
purered = (255,0,0)
puregreen = (0,255,0)
white = (255,255,255)
black = (1,1,1)
grey = (50,50,50)
darkgrey = (25,25,25)
clock = pygame.time.Clock()
snake_block = 10
snake_speed = 30
font_style = pygame.font.SysFont(None, 50)
def drawGrid():
blockSize = 10
for x in range(display_width):
for y in range(display_height):
rect = pygame.Rect(x*blockSize, y*blockSize,blockSize, blockSize)
pygame.draw.rect(display, darkgrey, rect, 1)
def message(msg, colour):
text = font_style.render(msg, True, colour)
display.blit(text, [display_width/2, display_height/2])
def SnakeGameLoop():
game_over = False
X = display_width/2
Y = display_height/2
X_change = 0
Y_change = 0
while not game_over:
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_over = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
X_change = -10
Y_change = 0
elif event.key == pygame.K_RIGHT:
X_change = 10
Y_change = 0
elif event.key == pygame.K_UP:
X_change = 0
Y_change = -10
elif event.key == pygame.K_DOWN:
X_change = 0
Y_change = 10
if X >= display_width or X < 0 or Y >= display_height or Y < 0:
game_over = True
X += X_change
Y += Y_change
display.fill(grey)
drawGrid()
pygame.draw.rect(display,puregreen,[X,Y,10,10])
pygame.display.update()
clock.tick(15)
message("You lost", purered)
pygame.display.update()
time.sleep(2)
pygame.quit()
quit()
SnakeGameLoop()
To improve the game's performance, draw the grid on a pygame.Surface object with the size of the screen, before the application loop:
def drawGrid(surf):
surf.fill(grey)
blockSize = 10
for x in range(display_width):
for y in range(display_height):
rect = pygame.Rect(x*blockSize, y*blockSize,blockSize, blockSize)
pygame.draw.rect(surf, darkgrey, rect, 1)
grid_surf = pygame.Surface(display.get_size())
drawGrid(grid_surf)
blit the surface once per frame on the display instead of drawing the grid once per frame, in the application loop:
def SnakeGameLoop():
# [...]
while not game_over:
# [...]
display.blit(grid_surf, (0, 0))
pygame.draw.rect(display,puregreen,[X,Y,10,10])
pygame.display.update()
for some reason when I collide with the enemy it randomly spawns elsewhere which is all fine but when I un-collide the enemy goes back to its original position
here is the full code down below. If you run this code see what happens. Im looking for the red block to spawn in a random other location when the blue box collides with it.
import pygame
import random
# places where enemies can spawn (2 to make it simple at first)
enemy_locations = [100, 200]
pygame.init()
# clock
clock = pygame.time.Clock()
# frames per second
fps = 30
# colors
background_color = (255, 255, 255)
player_color = (0, 0, 255)
enemy_color = (255, 0, 0)
# width and height of screen
width = 1000
height = 800
# screen
screen = pygame.display.set_mode((width, height))
# x, y coordinates player
player_x = 300
player_y = 300
# ememy x, y coordinates
enemy_x = random.choice(enemy_locations)
enemy_y = random.choice(enemy_locations)
# new x, y coordinates for enemy player
new_x = random.choice(enemy_locations)
new_y = random.choice(enemy_locations)
# draw player
def draw():
enemy_rect = pygame.Rect(enemy_x, enemy_y, 25, 25)
player_rect = pygame.Rect(player_x, player_y, 25, 25)
if player_rect.colliderect(enemy_rect):
enemy = pygame.draw.rect(screen, enemy_color, (new_x, new_y, 25, 25))
else:
enemy = pygame.draw.rect(screen, enemy_color, enemy_rect)
player = pygame.draw.rect(screen, player_color, player_rect)
# pygame loop (always include)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# controls for player object
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
player_x -= 10
if event.key == pygame.K_RIGHT:
player_x += 10
if event.key == pygame.K_UP:
player_y -= 10
if event.key == pygame.K_DOWN:
player_y += 10
draw()
pygame.display.update()
screen.fill(background_color)
clock.tick(fps)
The draw method explicitly states to draw enemy rect either in the initial point or in some ONE random point. The random point is selected only once - during the start of an application. You should set the random point every time there is a collision in a draw method, e.g.
if player_rect.colliderect(enemy_rect):
enemy_x = random.choice(enemy_locations)
enemy_y = random.choice(enemy_locations)
You have to create a new random enemy position when the player collides with the enemy
if player_rect.colliderect(enemy_rect):
enemy_x = random.choice(enemy_locations)
enemy_y = random.choice(enemy_locations)
Use the global statement, to interpreted the variables enemy_x and enemy_y as global. With the statement global it is possible to write to variables in the global namespace within a function:
global enemy_x, enemy_y
Function draw:
def draw():
global enemy_x, enemy_y
enemy_rect = pygame.Rect(enemy_x, enemy_y, 25, 25)
player_rect = pygame.Rect(player_x, player_y, 25, 25)
if player_rect.colliderect(enemy_rect):
enemy_x = random.choice(enemy_locations)
enemy_y = random.choice(enemy_locations)
enemy = pygame.draw.rect(screen, enemy_color, enemy_rect)
player = pygame.draw.rect(screen, player_color, player_rect)
As others have said you either need to add more "locations" to the list or better, use random.randint(), and also enemy's coordinates does not "get random"(or updated in any way) after every collision, but only once when you initialize them.
I added new function get_new_coord() which will return the random number(I use these limits so the enemy won't go off the screen), which gets called once for every coordinate after each collision.
Also I moved player_rect and enemy_rect outside of the loop, and now draw() returns enemy_rect so it can stay updated if collision occurs.
This is a quick fix to your code, you should consider using Classes. And of course if you want to do so, I could help you with transforming the code.
import pygame
import random
# places where enemies can spawn (2 to make it simple at first)
enemy_locations = [100, 200]
pygame.init()
# clock
clock = pygame.time.Clock()
# frames per second
fps = 30
# colors
background_color = (255, 255, 255)
player_color = (0, 0, 255)
enemy_color = (255, 0, 0)
# width and height of screen
width = 1000
height = 800
# screen
screen = pygame.display.set_mode((width, height))
# x, y coordinates player
player_x = 300
player_y = 300
# ememy x, y coordinates
enemy_x = random.choice(enemy_locations)
enemy_y = random.choice(enemy_locations)
# new x, y coordinates for enemy player
new_x = random.choice(enemy_locations)
new_y = random.choice(enemy_locations)
def get_new_coord():
return random.randint(0, 800-25)
# draw player
def draw(player_rect, enemy_rect):
screen.fill(background_color)
if player_rect.colliderect(enemy_rect):
enemy_rect = pygame.Rect(get_new_coord(), get_new_coord(), 25, 25)
enemy = pygame.draw.rect(screen, enemy_color, enemy_rect)
else:
enemy = pygame.draw.rect(screen, enemy_color, enemy_rect)
player = pygame.draw.rect(screen, player_color, player_rect)
pygame.display.update()
return enemy_rect
# pygame loop (always include)
running = True
enemy_rect = pygame.Rect(enemy_x, enemy_y, 25, 25)
player_rect = pygame.Rect(player_x, player_y, 25, 25)
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# controls for player object
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
player_rect.x -= 10
if event.key == pygame.K_RIGHT:
player_rect.x += 10
if event.key == pygame.K_UP:
player_rect.y -= 10
if event.key == pygame.K_DOWN:
player_rect.y += 10
enemy_rect = draw(player_rect, enemy_rect)
clock.tick(fps)