For an university programming course final project me and my team are building a platfromer. I'm responsible for making a collisions system. Even though I was able to code one I'm not satisfied with the outcome due to its imperfection.
The problem is that occasionally when character is falling after reaching the platform the player and the block overlap with each other for one frame. Of course, they don't stay like that forever. I've made it so the character teleports back on top of the platform. However, that action is excecuted only in the second frame. For whoever plays this game it will seem like the character is glitching. I believe that the problem lies somewhere in the collision detection. Sadly I couldn't find it.
Any help would be appreciated. Also I hope that this question won't be perceived as me begging someone else to complete my homework. I'm just striving for an advice :)
Collision detection function:
def Collision_Occurs(Block,Block_Length):
global Character, Max_Y_Speed
if(((Character.x <= Block.x Block_Length and Character.x >= Block.x) or
(Character.x 100 <= Block.x Block_Length and Character.x 100 >= Block.x)) and
(Character.y 100 <= Block.y Max_Y_Speed 1 and Character.y 100 >= Block.y)):
return True
return False
Entire game code:
import pygame
from sys import exit
pygame.init()
screen = pygame.display.set_mode((1000,650))
pygame.display.set_caption("The Game")
Block1 = pygame.Rect(250,500,500,50)
Block2 = pygame.Rect(100,250,250,50)
Block3 = pygame.Rect(650,250,250,50)
clock = pygame.time.Clock()
Character = pygame.Rect(200,100,100,100)
Moving_X = False
X_Speed = 0
Max_X_Speed = 5
Y_Speed = 0
Max_Y_Speed = 15
Collisions_Off_Timer = 0
Jump_Count = 0
Time_Since_Last_Jump = 60
'''
-------------------------------------------------------------
Collision Detection
-------------------------------------------------------------
'''
def Collision_Occurs(Block,Block_Length):
global Character, Max_Y_Speed
if(((Character.x <= Block.x Block_Length and Character.x >= Block.x) or
(Character.x 100 <= Block.x Block_Length and Character.x 100 >= Block.x)) and
(Character.y 100 <= Block.y Max_Y_Speed 1 and Character.y 100 >= Block.y)):
return True
return False
'''
-------------------------------------------------------------
Teleportation back on the platform
-------------------------------------------------------------
'''
def Teleport_Back_Up(Block):
global Character
Character.bottom = Block.top
'''
-------------------------------------------------------------
Game loop
-------------------------------------------------------------
'''
while True:
for event in pygame.event.get():
if(event.type == pygame.QUIT):
pygame.quit()
exit()
screen.fill((0,0,0))
pygame.draw.rect(screen,'Red',Block1)
pygame.draw.rect(screen,'Red',Block2)
pygame.draw.rect(screen,'Red',Block3)
pygame.draw.rect(screen,'Blue',Character)
'''
-------------------------------------------------------------
Input
-------------------------------------------------------------
'''
keys = pygame.key.get_pressed()
if(keys[pygame.K_DOWN]):
Collisions_Off_Timer = 5
if(keys[pygame.K_UP] and Jump_Count < 2 and Time_Since_Last_Jump >= 30):
Y_Speed = -20
Collisions_Off_Timer = 20
Jump_Count = 1
Time_Since_Last_Jump = 0
if(keys[pygame.K_RIGHT]):
Moving_X = True
if(X_Speed<Max_X_Speed):
X_Speed =1
if(keys[pygame.K_LEFT]):
Moving_X = True
if(X_Speed>Max_X_Speed*(-1)):
X_Speed-=1
'''
-------------------------------------------------------------
Friction
-------------------------------------------------------------
'''
if not(Moving_X):
if X_Speed > 0:
X_Speed -= 1
if X_Speed < 0:
X_Speed = 1
Moving_X = False
if not(Y_Speed>Max_Y_Speed):
Y_Speed = 1
'''
-------------------------------------------------------------
Checking for collisions
-------------------------------------------------------------
'''
if(Y_Speed > 0 and Collisions_Off_Timer <=0):
if Collision_Occurs(Block1,500):
Teleport_Back_Up(Block1)
Y_Speed = 0
Jump_Count = 0
if Collision_Occurs(Block2,250):
Teleport_Back_Up(Block2)
Y_Speed = 0
Jump_Count = 0
if Collision_Occurs(Block3,250):
Teleport_Back_Up(Block3)
Y_Speed = 0
Jump_Count = 0
'''
-------------------------------------------------------------
Teleport back to the middle when vertical bounds are crossed
-------------------------------------------------------------
'''
if Character.y >=1500:
Character.x = 450
Character.y = 350
Y_Speed = 0
Collisions_Off_Timer -= 1
Time_Since_Last_Jump =1
Character.x =X_Speed
Character.y =Y_Speed
pygame.display.update()
clock.tick(60)
CodePudding user response:
Just do the move before collision detection. This corrects the y-position of the player (Teleport_Back_Up
) after the player has been moved and before the display is updated:
while True:
# [...]
Character.x =X_Speed # <--- INSERT
Character.y =Y_Speed
'''
-------------------------------------------------------------
Checking for collisions
-------------------------------------------------------------
'''
if(Y_Speed > 0 and Collisions_Off_Timer <=0):
if Collision_Occurs(Block1,500):
Teleport_Back_Up(Block1)
Y_Speed = 0
Jump_Count = 0
if Collision_Occurs(Block2,250):
Teleport_Back_Up(Block2)
Y_Speed = 0
Jump_Count = 0
if Collision_Occurs(Block3,250):
Teleport_Back_Up(Block3)
Y_Speed = 0
Jump_Count = 0
# [...]
Collisions_Off_Timer -= 1
Time_Since_Last_Jump =1
# Character.x =X_Speed <--- DELETE
# Character.y =Y_Speed