trouble with pygame's colliderect - python

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()

Related

Is there a way to remove the red outline from a rect? [duplicate]

I am new to pygame and python in general. Today I was trying to code a simplified TopDown movement. I did it and it runs without any issues. But i've got a problem anyways: The "player" is a rectangle but I want him to be an image or something like that. Is there a way to 'convert' a rect to an image?
Oh, and here's the code if you need it, I made it from another question I asked a week ago (or a bit longer):
import pygame
pygame.init()
win = pygame.display.set_mode((700, 700))
pygame.display.set_caption("TopDown")
clock = pygame.time.Clock()
player = pygame.Rect(350, 350, 40, 60)
vel = 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()
player.x += (keys[pygame.K_d] - keys[pygame.K_a]) * vel
player.y += (keys[pygame.K_s] - keys[pygame.K_w]) * vel
win.fill((0, 0, 0))
pygame.draw.rect(win, (255, 255, 255), player)
pygame.display.update()
pygame.quit()
Load the image with pygame.image.load(). This function returns a pygame.Surface object:
player_image = pygame.image.load("player_image.png").convert_alpha()
player_rect = player_image.get_rect(center = (350, 350))
Put the Surface onto the display with pygame.Surface.blit:
win.blit(player_image, player_rect)
Minimal example:
import pygame
pygame.init()
win = pygame.display.set_mode((700, 700))
pygame.display.set_caption("TopDown")
clock = pygame.time.Clock()
player_image = pygame.image.load("player_image.png").convert_alpha()
player_rect = player_image.get_rect(center = (350, 350))
vel = 5
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()
player_rect.x += (keys[pygame.K_d] - keys[pygame.K_a]) * vel
player_rect.y += (keys[pygame.K_s] - keys[pygame.K_w]) * vel
win.fill((64, 238, 255))
win.blit(player_image, player_rect)
pygame.display.update()
pygame.quit()

Sprite not being properly drawn to where rect is [duplicate]

I am new to pygame and python in general. Today I was trying to code a simplified TopDown movement. I did it and it runs without any issues. But i've got a problem anyways: The "player" is a rectangle but I want him to be an image or something like that. Is there a way to 'convert' a rect to an image?
Oh, and here's the code if you need it, I made it from another question I asked a week ago (or a bit longer):
import pygame
pygame.init()
win = pygame.display.set_mode((700, 700))
pygame.display.set_caption("TopDown")
clock = pygame.time.Clock()
player = pygame.Rect(350, 350, 40, 60)
vel = 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()
player.x += (keys[pygame.K_d] - keys[pygame.K_a]) * vel
player.y += (keys[pygame.K_s] - keys[pygame.K_w]) * vel
win.fill((0, 0, 0))
pygame.draw.rect(win, (255, 255, 255), player)
pygame.display.update()
pygame.quit()
Load the image with pygame.image.load(). This function returns a pygame.Surface object:
player_image = pygame.image.load("player_image.png").convert_alpha()
player_rect = player_image.get_rect(center = (350, 350))
Put the Surface onto the display with pygame.Surface.blit:
win.blit(player_image, player_rect)
Minimal example:
import pygame
pygame.init()
win = pygame.display.set_mode((700, 700))
pygame.display.set_caption("TopDown")
clock = pygame.time.Clock()
player_image = pygame.image.load("player_image.png").convert_alpha()
player_rect = player_image.get_rect(center = (350, 350))
vel = 5
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()
player_rect.x += (keys[pygame.K_d] - keys[pygame.K_a]) * vel
player_rect.y += (keys[pygame.K_s] - keys[pygame.K_w]) * vel
win.fill((64, 238, 255))
win.blit(player_image, player_rect)
pygame.display.update()
pygame.quit()

Pygame sprite won't move, exits game when key pressed [duplicate]

This question already has an answer here:
Difference between rect.move() and rect.move_ip in pygame
(1 answer)
Closed 9 months ago.
So I can't get my sprite to jump when the key is pressed. I've fixed a few errors but now I have one that says: File "/Users/josh/Desktop/fresh/main.py", line 52, in
screen.blit(player, player_rect)
TypeError: invalid destination position for blit
import pygame
from sys import exit
pygame.init()
screen = pygame.display.set_mode((800,400))
pygame.display.set_caption('Shooter Mania')
text = pygame.font.Font(None, 50)
clock = pygame.time.Clock()
#
bg = pygame.image.load('background.png')
#
player = pygame.image.load('player.png').convert_alpha()
player_rect = player.get_rect(midbottom=(80,300))
playerX = 0
playerY = 0
#
score_surf = text.render('SCORE:', False, 'white')
score_rect = score_surf.get_rect(center=(400,50))
#
enemy = pygame.image.load('enemy.png').convert_alpha()
enemy_rect = enemy.get_rect(bottomright=(600,300))
#
#
#
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
player_rect = player_rect.move_ip(0,5)
print(f'Jump')
screen.blit(bg, (0,0))
pygame.draw.rect(screen, 'Pink',score_rect)
screen.blit(score_surf,score_rect)
enemy_rect.x -= 4
if enemy_rect.right <= 0:
enemy_rect.left = 800
screen.blit(enemy,enemy_rect)
# if player_rect.y <= 400:
# player_rect.y = 300
# playerX +=1
# player_rect.y += playerX
screen.blit(player, player_rect)
pygame.display.update()
clock.tick(60)
When you move your rect, you use move_ip() which updates the rect in place (hence the name) and returns nothing, i.e. None. This then gets assigned to the player_rect variable and passed to screen.blit(), which fails. The solution is not to use the in-place version of move:
if event.key == pygame.K_SPACE:
player_rect = player_rect.move(0, 5)
print(f'Jump')
This will return the updated rect and assign it to player_rect. Alternatively, you could use the in-place version without assignment:
if event.key == pygame.K_SPACE:
player_rect.move_ip(0, 5)
print(f'Jump')

Not able to shoot bullet in pygame

So recently I have been trying to make my first big game but I'm stuck on the shooting phase. Basically, my problem is I want to make it so that I can shoot multiple bullets and move around while doing so, but I can't seem to figure it out.
Code:
import pygame
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((600,600))
pygame.display.set_caption("Shooter Game!")
#Variables
playerX = 5
playerY = 5
black = (0,0,0)
blue = (0,0,255)
red = (255,0,0)
clicking = False
bulletX = playerX
bulletY = playerY
#End Of Variables#
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
exit()
screen.fill(blue)
player = pygame.image.load("Young_Link_2D.png").convert_alpha()
screen.fill(blue)
player1 = pygame.transform.scale(player, (100,100))
screen.blit(player1,(playerX,playerY))
keyPressed = pygame.key.get_pressed()
#Controls
if keyPressed[pygame.K_a]:
playerX -= 1
bulletX = playerX
if keyPressed[pygame.K_d]:
playerX += 1
bulletX = playerX
if keyPressed[pygame.K_w]:
playerY -= 1
bulletY = playerY
if keyPressed[pygame.K_s]:
playerY += 1
bulletY = playerY
#End of Controls
#Shooting
if event.type == pygame.MOUSEBUTTONUP:
if event.button == 1:
Bullet = pygame.draw.rect(screen, red, (bulletX+35,bulletY + 60,10,25))
bulletY = bulletY + 1
pygame.display.update()
Here is what i meant by classes:
import pygame
import Bullet
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((600, 600))
pygame.display.set_caption("Shooter Game!")
# Variables
playerX = 5
playerY = 5
black = (0, 0, 0)
blue = (0, 0, 255)
red = (255, 0, 0)
clicking = False
bulletX = playerX
bulletY = playerY
bullets = []
newBullet = False
# End Of Variables#
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
exit()
screen.fill(blue)
player = pygame.image.load("100x100_logo.png").convert_alpha()
screen.fill(blue)
player1 = pygame.transform.scale(player, (100, 100))
screen.blit(player1, (playerX, playerY))
keyPressed = pygame.key.get_pressed()
# Controls
if keyPressed[pygame.K_a]:
playerX -= 1
bulletX = playerX
if keyPressed[pygame.K_d]:
playerX += 1
bulletX = playerX
if keyPressed[pygame.K_w]:
playerY -= 1
bulletY = playerY
if keyPressed[pygame.K_s]:
playerY += 1
bulletY = playerY
# End of Controls
# Shooting
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
bullets.append(Bullet.Bullet(bulletX + 35, bulletY + 60))
for i in range(len(bullets)):
bullets[i].draw(screen, (255, 0, 0))
bullets[i].move(1)
print(len(bullets))
pygame.display.update()
Thats your main code. There is still a bug where there is no cooldown so multiple bullets are created consecutively when holding the mouse button.
import pygame
class Bullet:
def __init__(self, x, y):
self.x = x
self.y = y
def draw(self, win, colour):
pygame.draw.rect(win, colour, (self.x, self.y, 10, 25))
def move(self, speed):
self.y += speed
and thats the bullet class to create multiple instances
See How do I stop more than 1 bullet firing at once? and How can i shoot a bullet with space bar?.
You need to manage the bullets in a list:
bullets = []
Add a new bullet to the list when the mouse click is detected. Use pygame.Rect objects to represent the bullets. The events must be handled in the event loop:
for event in pygame.event.get():
# [...]
if event.type == pygame.MOUSEBUTTONUP:
if event.button == 1:
bullets.append(pygame.Rect(playerX, playerY, 35, 60))
Move the bullets in a loop. Remove the bullets from the list, when they when they move off the screen. See How to remove items from a list while iterating?:
for bullet in bullets[:]:
bullet.y += 5
if bullet.top > 600:
bullets.remove(bullet)
Draw all the bullets in the list in another loop:
for bullet in bullets:
pygame.draw.rect(screen, red, bullet)
Complete example:
import pygame
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((600,600))
pygame.display.set_caption("Shooter Game!")
#Variables
player = pygame.image.load("Young_Link_2D.png").convert_alpha()
playerX, playerY = 5, 5
black = (0,0,0)
blue = (0,0,255)
red = (255,0,0)
clicking = False
bullets = []
#End Of Variables#
clock = pygame.time.Clock()
running = True
while running:
clock.tick(100)
for event in pygame.event.get():
if event.type == QUIT:
running = False
if event.type == pygame.MOUSEBUTTONUP:
if event.button == 1:
bullets.append(pygame.Rect(playerX, playerY, 35, 60))
keyPressed = pygame.key.get_pressed()
playerX += keyPressed[pygame.K_d] - keyPressed[pygame.K_a]
playerY += keyPressed[pygame.K_s] - keyPressed[pygame.K_w]
for bullet in bullets[:]:
bullet.y += 5
if bullet.top > 600:
bullets.remove(bullet)
screen.fill(blue)
player1 = pygame.transform.scale(player, (100,100))
screen.blit(player1,(playerX,playerY))
for bullet in bullets:
pygame.draw.rect(screen, red, bullet)
pygame.display.update()
pygame.quit()
exit()

How to attach an image to a rect in pygame?

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()

Categories