This question already has answers here:
How do I detect collision in pygame?
(5 answers)
Closed 20 days ago.
I am making a platformer and am trying to make a player be able to stay on top of a platform. When I check if they are colliding, I check if the bottom of the player meets the top of the platform. It doesn't give an output, can someone please help?
The buggy part is the collisions where playerRect.colliderect(platform): and the bit below that as well. Help would be much appreciated.
import pygame
pygame.init()
screen = pygame.display.set_mode((1400, 900))
clock = pygame.time.Clock()
playerX = 700
playerY = 870
jumping = False
goingRight = False
goingLeft = False
jumpSpeed = 1
jumpHeight = 18
yVelocity = jumpHeight
gravity = 1
speed = 6
white = (255, 255, 255)
black = (0, 0, 0)
running = True
while running:
screen.fill(black)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
keys = pygame.key.get_pressed()
if keys[pygame.K_SPACE]:
jumping = True
if keys[pygame.K_LEFT]:
goingLeft = True
if keys[pygame.K_RIGHT]:
goingRight = True
platform = pygame.draw.rect(screen, white, (100, 840, 100, 30))
playerRect = pygame.draw.rect(screen, white, (playerX, playerY, 30, 30))
if jumping:
playerY -= yVelocity
yVelocity -= gravity
if yVelocity < -jumpHeight:
jumping = False
yVelocity = jumpHeight
if goingLeft:
playerX -= speed
if goingRight:
playerX += speed
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
goingLeft = False
if event.key == pygame.K_RIGHT:
goingRight = False
if playerRect.colliderect(platform):
if playerRect.bottom - platform.top == 0:
playerRect.bottom = platform.y
pygame.display.update()
clock.tick(60)
`
Most likely this part is the problem.
if playerRect.bottom - platform.top == 0:
You should check if bottom of the player is higher than the top of the platform since chance of them being exact is not high since your yVelocity is different than 1.
Related
This question already has answers here:
How do I detect collision in pygame?
(5 answers)
How to detect collisions between two rectangular objects or images in pygame
(1 answer)
Closed 1 year ago.
import pygame
pygame.init()
pygame.display.set_caption('...SHON...PONG...')
icon=pygame.image.load('icon.png')
pygame.display.set_icon(icon)
FPS=50
fpsClock=pygame.time.Clock()
screenh=500
screenw=300
screen=pygame.display.set_mode((screenh,screenw))
black =((0,0,0))
paddle1=pygame.image.load('paddle1.png')
paddle1_rect=paddle1.get_rect()
paddle1_y=100
paddle1_x=10
paddle2=pygame.image.load('paddle2.png')
paddle2_rect=paddle1.get_rect()
paddle2_y=100
paddle2_x=471
ball=pygame.image.load('player.png')
ball_rect=ball.get_rect()
ball_x=240
ball_y=130
ball_y_speed=2
ball_x_speed=2
speed=15
paddle1_rect.x=paddle1_x
paddle1_rect.y=paddle1_y
paddle2_rect.x=paddle2_x
paddle2_rect.y=paddle2_y
ball_rect.x=ball_x
ball_rect.y=ball_y
def ball_movement():
global ball_x, ball_y, ball_x_speed, ball_y_speed
ball_x -=ball_x_speed
ball_y +=ball_y_speed
def ball_collide_screen():
global ball_x, ball_y, ball_x_speed, ball_y_speed
if ball_y + screenw >= 600:
ball_y_speed = -2
if ball_y + screenw <= 300:
ball_y_speed = -2
def ball_collide_paddles():
global ball_rect, paddle1_rect, paddle2_rect
if paddle1_rect.right - ball_rect.left <= 0:
print('ho')
running=True
while running:
screen.fill((0,0,0))
screen.blit(paddle1, (paddle1_x,paddle1_y))
screen.blit(paddle2, (paddle2_x,paddle2_y))
screen.blit(ball, (ball_x, ball_y))
ball_collide_screen()
ball_movement()
ball_collide_paddles()
pygame.display.update()
fpsClock.tick(FPS)
for event in pygame.event.get():
if event.type==pygame.QUIT:
running=False
pygame.quit()
if event.type==pygame.KEYDOWN:
if event.key==pygame.K_w:
paddle1_y-= speed
if event.key==pygame.K_z:
paddle1_y+=speed
if event.key==pygame.K_UP:
paddle2_y-=speed
if event.key==pygame.K_DOWN:
paddle2_y+=speed
*i am getting problems with the pygame colliderect function. i put a print function whenever the ball collides with paddle and it continues print collide as long as the program is running.....i read somewhere that the rect position has to be matching with the balls initial position and i have tried doing that but all in vain .....i have been doing pygame for a while and i have encountered this problem trying to make this pong game *
You must update the location of the pygame.Rect objects, after moving the objects and before the collision detection:
def ball_movement():
global ball_x, ball_y, ball_x_speed, ball_y_speed
ball_x -=ball_x_speed
ball_y +=ball_y_speed
ball_rect.x=ball_x
ball_rect.y=ball_y
running=True
while running:
# [...]
for event in pygame.event.get():
if event.type==pygame.QUIT:
running=False
pygame.quit()
if event.type==pygame.KEYDOWN:
if event.key==pygame.K_w:
paddle1_y-= speed
if event.key==pygame.K_z:
paddle1_y+=speed
if event.key==pygame.K_UP:
paddle2_y-=speed
if event.key==pygame.K_DOWN:
paddle2_y+=speed
paddle1_rect.x=paddle1_x
paddle1_rect.y=paddle1_y
paddle2_rect.x=paddle2_x
paddle2_rect.y=paddle2_y
Note, you don't need the variables ball_x, ball_y, paddle1_x, paddle1_y, paddle2_x and paddle2_y at all.
Use ball_rect.x, ball_rect.y, paddle1_rect.x, paddle1_rect.y, paddle2_rect.x and paddle2_rect.y instead.
import pygame
pygame.init()
pygame.display.set_caption('...SHON...PONG...')
#icon = pygame.image.load('icon.png')
#pygame.display.set_icon(icon)
FPS = 50
fpsClock = pygame.time.Clock()
screenh = 500
screenw = 300
screen = pygame.display.set_mode((screenh,screenw))
black = ((0,0,0))
#paddle1 = pygame.image.load('paddle1.png')
paddle1 = pygame.Surface((5, 50))
paddle1.fill((255, 255, 255))
paddle1_rect = paddle1.get_rect(topleft = (10, 100))
#paddle2 = pygame.image.load('paddle2.png')
paddle2 = pygame.Surface((5, 50))
paddle2.fill((255, 255, 255))
paddle2_rect = paddle1.get_rect(topleft = (471, 100))
#ball = pygame.image.load('player.png')
ball = pygame.Surface((5, 5))
ball.fill((255, 255, 255))
ball_rect = ball.get_rect(topleft = (240, 130))
ball_x_speed = 2
ball_y_speed = 2
speed = 15
def ball_movement():
ball_rect.x += ball_x_speed
ball_rect.y += ball_y_speed
def ball_collide_screen():
global ball_x_speed, ball_y_speed
if ball_rect.left <= 0:
ball_x_speed = 2
if ball_rect.right >= screen.get_width():
ball_x_speed = -2
if ball_rect.top <= 0:
ball_y_speed = 2
if ball_rect.bottom >= screen.get_height():
ball_y_speed = -2
def ball_collide_paddles():
if paddle1_rect.right - ball_rect.left <= 0:
print('ho')
running=True
while running:
screen.fill((0,0,0))
screen.blit(paddle1, paddle1_rect)
screen.blit(paddle2, paddle2_rect)
screen.blit(ball, ball_rect)
pygame.display.update()
fpsClock.tick(FPS)
ball_collide_screen()
ball_movement()
ball_collide_paddles()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running=False
pygame.quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
paddle1_rect.y -= speed
if event.key == pygame.K_s:
paddle1_rect.y += speed
if event.key == pygame.K_UP:
paddle2_rect.y -= speed
if event.key == pygame.K_DOWN:
paddle2_rect.y += speed
I am currently attempting to programm a small game. An enemy is supposed to chase the player, the actual chasing is not implemented yet. I still need to figure out how to do that, but that's not the question.
I have made it so that the player returns to the start point once they collide with the enemy. In addition to that, a text 'Game over' is supposed to appear. The function for that is called at the end of the game loop and while the text appeared briefly(it actually only appeared once, I have tried it multiple times), it does not stay. I was planing on making it appear and then disappear after a few seconds so that the player can play again, but I'm not sure why it disappears instantly.
If this is the wrong place to post this, please tell me, I will delete this post. This is my code, would be amazing if somebody could help me out:
import pygame #imports pygame
import math
pygame.init()
#screen
screen = pygame.display.set_mode((800,600)) #width and height
#title and icon
pygame.display.set_caption("The Great Chase") #changes title
icon = pygame.image.load('game-controller.png')
pygame.display.set_icon(icon) #setting icon
#player
playerImg = pygame.image.load('scary-monster.png')
playerX = 370
playerY = 480
playerX_change = 0
playerY_change = 0
#enemy
enemyImg = pygame.image.load('caterpillar.png')
enemyX = 370
enemyY = 50
enemyX_change = 0
enemyY_change = 0
#GAME OVER
game_over_font = pygame.font.Font('Bubblegum.ttf',64)
def game_over_text():
game_over_text = game_over_font.render("GAME OVER", True, (255, 0, 0))
screen.blit(game_over_text, (200, 250))
def player(x, y): #function for player
screen.blit(playerImg, (x, y)) #draws image of player, blit -> means to draw
def enemy(x, y): #function for enemy
screen.blit(enemyImg,(x,y))
def isCollision(playerX, playerY, enemyX, enemyY):
distance = math.sqrt((math.pow(playerX-enemyX,2)) + (math.pow(playerY - enemyY,2)))
if distance < 25:
return True
else:
return False
def chase():
distance = math.sqrt((math.pow(playerX-enemyX,2)) + (math.pow(playerY - enemyY,2)))
#Game loop
running = True
while running:
screen.fill((255,255,0)) #0-255 RGB-> red, green & blue
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# if keystroke check whether right or left or up or down
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerX_change = -0.2
if event.key == pygame.K_RIGHT:
playerX_change = 0.2
if event.key == pygame.K_UP:
playerY_change = -0.2
if event.key == pygame.K_DOWN:
playerY_change = 0.2
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
playerX_change = 0
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
playerY_change = 0
playerX += playerX_change
playerY += playerY_change
#creating borders so that player won't leave screen
if playerX <=0:
playerX = 0
elif playerX >=768:
playerX = 768
if playerY <= 0:
playerY = 0
elif playerY >=568:
playerY = 568
#collision
collision = isCollision(playerX, playerY, enemyX, enemyY)
if collision:
playerY = 480
game_over_text()
player(playerX, playerY)
enemy(enemyX, enemyY)
pygame.display.update()
The collision only occurs for a moment and the game over text is only shown when the object collides. If you want to persist the text, set a gameover variable when the collision is detected and display the text based on the state of the variable:
gameover = False
running = True
while running:
# [...]
collision = isCollision(playerX, playerY, enemyX, enemyY)
if collision:
playerY = 480
gameover = True
player(playerX, playerY)
enemy(enemyX, enemyY)
if gameover:
game_over_text()
pygame.display.update()
Note, collision is set in every frame depending on the position of the objects. However, gameover is set once when a collision occurs and then maintains its state.
This question already has answers here:
How to detect collisions between two rectangular objects or images in pygame
(1 answer)
Why is my collision test always returning 'true' and why is the position of the rectangle of the image always wrong (0, 0)?
(1 answer)
How do I detect collision in pygame?
(5 answers)
Closed 2 years ago.
I want to make it kind of like a life system so that if it collides with the enemy 3 times it will quit
pygame.init()
screen_width = 800
screen_height = 600
window = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption('Test')
time = pygame.time.Clock()
bg_color1 = (135, 142, 142) # MAIN BG COLOR
bg_color2 = (255, 0, 0) # red
bg_color3 = (255, 255, 0) # yellow
UFO = pygame.image.load('ufo.png')
bg_pic = pygame.image.load('Letsgo.jpg')
clock = pygame.time.Clock()
playerImg = pygame.image.load('enemy.png')
playerX = random.randrange(0, screen_width)
playerY = -50
playerX_change = 0
player_speed = 5
def player(x, y):
window.blit(playerImg, (playerX, playerY))
crashed = False
rect = UFO.get_rect()
obstacle = pygame.Rect(400, 200, 80, 80)
menu = True
playerY = playerY + player_speed
if playerY > screen_height:
playerX = random.randrange(0, screen_width)
playerY = -25
def ufo(x, y):
window.blit(UFO, (x, y))
while menu:
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
menu = False
window.fill((0, 0, 0))
time.tick(30)
window.blit(bg_pic, (0, 0))
pygame.display.update()
x = (screen_width * 0.45)
y = (screen_height * 0.8)
x_change = 0
car_speed = 0
y_change = 0
while not crashed:
x += x_change
if x < 0:
x = 0
elif x > screen_width - UFO.get_width():
x = screen_width - UFO.get_width()
y += y_change
if y < 0:
y = 0
elif y > screen_height - UFO.get_height():
y = screen_height - UFO.get_height()
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
############SIDE TO SIDE################
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
###########UP AND DOWN#################
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
y_change = -5
elif event.key == pygame.K_DOWN:
y_change = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
y_change = 0
if playerY > screen_height:
playerX = random.randrange(0, screen_width)
playerY = 0
playerY += 10
##
window.fill(bg_color1)
ufo(x, y)
player(playerX, playerY)
pygame.display.update()
clock.tick(100)
pygame.quit()
quit()
im thinking of using a collide.rect but cant figure it out any help is appreciated
I want the "playerImg" to be the enemy ...................................................................................
Create a variable that stores the number of lives. Create pygme.Rect objects of the player and the UFO with the method get_rect. Set the location of the rectangles by keyword arguments. Use colliderect to test the collision and decrease the number of lives when a collision is detected and create a new random starting position:
lives = 3
while not crashed:
# [...]
player_rect = playerImg.get_rect(topleft = (playerX, playerY))
ufo_rect = UFO.get_rect(topleft = (x, y))
if player_rect.colliderect(ufo_rect):
lives -= 1
print(lives)
playerX = random.randrange(0, screen_width)
playerY = 0
if lives == 0:
crashed = True
# [...]
This question already has answers here:
How to detect collisions between two rectangular objects or images in pygame
(1 answer)
Why is my collision test always returning 'true' and why is the position of the rectangle of the image always wrong (0, 0)?
(1 answer)
How do I detect collision in pygame?
(5 answers)
Closed 2 years ago.
import pygame
import os
pygame.init()
# Images
bgImg = pygame.image.load("Images/background.png")
playerImgRight = (pygame.image.load("Images/playerRight.png"))
playerImgLeft = pygame.image.load("Images/playerLeft.png")
playerImgBack = pygame.image.load("Images/playerBack.png")
chestClosed = pygame.transform.scale(pygame.image.load("Images/chestsClosed.png"), (30, 40))
chestOpened = pygame.transform.scale(pygame.image.load("Images/chestOpen.png"), (30, 40))
currentPlayerImg = playerImgBack
screen = pygame.display.set_mode((800, 800))
pygame.display.set_caption("Richmonia")
pygame.display.set_icon(currentPlayerImg)
clock = pygame.time.Clock()
playerX = 380
playerY = 380
playerXSpeed = 0
playerYSpeed = 0
Chest Class
I want but the collision detection in the chest update function
class Chest:
def __init__(self, x, y, openImage, closeImage, playerX, playerY):
self.x = x
self.y = y
self.openImage = openImage
self.closeImage = closeImage
self.currentImage = self.closeImage
self.playerX = playerX
self.playerY = playerY
def update(self):
print("Placeholder")
def show(self):
screen.blit(self.currentImage, (self.x, self.y))
chestOne = Chest(100, 100, chestOpened, chestClosed, playerX, playerY)
running = True
while running:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
currentPlayerImg = playerImgBack
playerYSpeed = -5
if event.key == pygame.K_DOWN:
currentPlayerImg = playerImgBack
playerYSpeed = 5
if event.key == pygame.K_LEFT:
currentPlayerImg = playerImgLeft
playerXSpeed = -5
if event.key == pygame.K_RIGHT:
currentPlayerImg = playerImgRight
playerXSpeed = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP:
playerYSpeed = 0
if event.key == pygame.K_DOWN:
playerYSpeed = 0
if event.key == pygame.K_LEFT:
playerXSpeed = 0
if event.key == pygame.K_RIGHT:
playerXSpeed = 0
if playerY <= 0:
playerY = 0
if playerY >= 740:
playerY = 740
if playerX <= 0:
playerX = 0
if playerX >= 760:
playerX = 760
playerX += playerXSpeed
playerY += playerYSpeed
screen.blit(bgImg, (0, 0))
chestOne.show()
chestOne.update()
screen.blit(currentPlayerImg, (playerX, playerY))
pygame.display.update()
pygame.quit()
quit()
I know there is a way with sprites but I want to know if there is a way to do it with just the images.
Also bonus question how to I get the fps.
Use a pygame.Rect object and colliderect() to find a collision between a rectangle and an object.
pygame.Surface.get_rect.get_rect() returns a rectangle with the size of the Surface object, that always starts at (0, 0) since a Surface object has no position. The position of the rectangle can be specified by a keyword argument:
running = True
while running:
# [...]
player_rect = currentPlayerImg.get_rect(topleft = (playerX, playerY))
chestOne_rect = chestOne.currentImage.get_rect(topleft = (self.x, self.y))
if player_rect .colliderect(chestOne_rect):
print("hit")
# [...]
The method tick() of a pygame.time.Clock object, delays the game in that way, that every iteration of the loop consumes the same period of time.
So in your case the frames per second are 60:
while running:
clock.tick(60)
pygame.time.Clock.tick returns the number of milliseconds passed since the previous call. If you call it in the application loop, then this is the number of milliseconds passed since the last frame.
while run:
ms_since_last_frame = clock.tick(60)
I am making a mini-game that involves movement. I created an object that moves according to the controls, but how do i make it not move if it collides with a wall?
#Imports
import pygame, sys
#Functions
#General Set Up
pygame.init()
clock = pygame.time.Clock()
#Main Window
swid = 1280
shgt = 700
screen = pygame.display.set_mode((swid, shgt))
pygame.display.set_caption("Raid: The Game || Movement Test")
#Game Rectangles
player = pygame.Rect(30, 30, 30, 30)
wall = pygame.Rect(140, 80, 1000, 20)
window = pygame.Rect(300, 400, 220, 20)
door = pygame.Rect(500, 500, 120, 18)
bgcol = (0,0,0)
playercol = (200,0,0)
wallcol = pygame.Color("grey12")
doorcol = pygame.Color("blue")
windowcol = (100,100,100)
xwalkspeed = 0
ywalkspeed = 0
while True:
#Handling Input
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_DOWN:
ywalkspeed += 10
if event.key == pygame.K_UP:
ywalkspeed -= 10
if event.key == pygame.K_LEFT:
xwalkspeed -= 10
if event.key == pygame.K_RIGHT:
xwalkspeed += 10
if event.type == pygame.KEYUP:
if event.key == pygame.K_DOWN:
ywalkspeed -= 10
if event.key == pygame.K_UP:
ywalkspeed += 10
if event.key == pygame.K_LEFT:
xwalkspeed += 10
if event.key == pygame.K_RIGHT:
xwalkspeed -= 10
player.x += xwalkspeed
player.y += ywalkspeed
distancebetween = 0
if player.colliderect(wall):
ywalkspeed = 0
xwalkspeed= 0
if player.top <= 0:
player.top = 0
if player.bottom >= shgt:
player.bottom = shgt
if player.left <= 0:
player.left = 0
if player.right >= swid:
player.right = swid
#Visuals
screen.fill(bgcol)
pygame.draw.ellipse(screen, playercol, player)
pygame.draw.rect(screen, wallcol, wall)
pygame.draw.rect(screen, doorcol, door)
pygame.draw.rect(screen, windowcol, window)
#Updating the Window
pygame.display.flip()
clock.tick(60)
Whenever my Object collides upon a wall, it starts moving the opposite way until it is no longer seen in the screen.
I Found the Reason why it kept moving the opposite way when it collides the wall. It is because if I move towards the wall, my ywalkspeed = 10 and when I collided with the wall, it becomes 0, then if I started to let go of the movement key, the ywalkspeed becomes ywalkspeed = -10. I currently don't know a way how to fix this as I am just a noob.
Make a copy of the original player rectangle with copy(). Move the player. If a collision is detected, restore the player rectangle:
copy_of_player_rect = player.copy()
# move player
# [...]
if player.colliderect(wall):
player = copy_of_player_rect
You can watch for the distance between the wall and the player and when the distance according to axis positions reaches zero, just do
xwalkspeed = 0
ywalkspeed = 0
To measure the distance and smooth realistic movement, you can also use equations of motion from Physics.