I'm working on a platformer game with pygame. So I have those platforms, and what I'm trying to do, is that when I press the down arrow or the S key the player falls through the platform. I just can't figure out the proper way to do it. If anyone has any example or if you can help me please, here the main code:
class Player:
def __init__(self, x, y):
self.entity = e.entity(x, y, 14, 29, 'player')
self.movingRight = False
self.movingLeft = False
self.momentum = 0
self.airTimer = 0
self.movement = [0,0]
self.platformCollision = False
self.onPlatform = False
self.through = False
self.levelOver = False
def events(self, event, dt):
if event.type == KEYDOWN:
if event.key == K_RIGHT:
self.movingRight = True
if event.key == K_d:
self.movingRight = True
if event.key == K_LEFT:
self.movingLeft = True
if event.key == K_a:
self.movingLeft = True
if event.key == K_UP:
if self.airTimer == 0:
self.momentum = -5
if event.key == K_w:
if self.airTimer == 0:
self.momentum = -5
if event.key == K_DOWN:
self.through = not self.through
if event.key == K_s:
self.through = not self.through
if event.type == KEYUP:
if event.key == K_RIGHT:
self.movingRight = False
if event.key == K_d:
self.movingRight = False
if event.key == K_LEFT:
self.movingLeft = False
if event.key == K_a:
self.movingLeft = False
def update(self, tile_rects, enemiesList, movingList, notCollisionable, screen, scroll, dt, distance):
self.movement = [0,0]
if self.movingRight == True:
self.movement[0] += 300 * dt
if self.movingLeft == True:
self.movement[0] -= 300 * dt
self.movement[1] += self.momentum*2.4
self.momentum += 20 * dt
if self.momentum > 5:
self.momentum = 5
if self.movement[0] == 0:
self.entity.set_action('idle')
elif self.movement[0] > 0:
self.entity.set_flip(False)
self.entity.set_action('run')
elif self.movement[0] < 0:
self.entity.set_flip(True)
self.entity.set_action('run')
collisionList = self.entity.move(self.movement, tile_rects, enemiesList, movingList, notCollisionable, self.airTimer)
exitData = [False, False]
for platform in collisionList['data']:
if platform[1][3]:
self.airTimer = 0
self.momentum = 0
self.platformCollision = False
else:
self.airTimer = 0
self.platformCollision = False
if platform[2] == 'horizontal':
self.entity.obj.x += distance
if platform[2] == "static":
self.onPlatform = True
if platform[2] == 'throughMiddle':
if self.through:
#HERE IS WHERE I DONT KNOW WHAT TO DO
pass
else:
self.onPlatform = False
if platform[2] == "spikeTop":
exitData[0] = True
if platform[2] == "endBall":
self.levelOver = True
exitData[1] = True
if not collisionList['bottom']:
self.airTimer += 1
self.entity.changeFrame(1)
self.entity.display(screen, scroll)
return exitData
Here's the engine section that handles the entities class:
class entity(object):
global animation_database, animation_higher_database
def __init__(self,x,y,size_x,size_y,e_type): # x, y, size_x, size_y, type
self.x = x
self.y = y
self.size_x = size_x
self.size_y = size_y
self.obj = physics_obj(x,y,size_x,size_y)
self.animation = None
self.image = None
self.animation_frame = 0
self.animation_tags = []
self.flip = False
self.offset = [0,0]
self.rotation = 0
self.type = e_type # used to determine animation set among other things
self.action_timer = 0
self.action = ''
self.set_action('idle') # overall action for the entity
self.entity_data = {}
self.alpha = None
def set_pos(self,x,y):
self.x = x
self.y = y
self.obj.x = x
self.obj.y = y
self.obj.rect.x = x
self.obj.rect.y = y
def move(self,momentum,platforms,ramps=[], platRects=[], vertRects=[], airTimer=0):
collisions = self.obj.move(momentum,platforms,ramps, platRects, vertRects, airTimer)
self.x = self.obj.x
self.y = self.obj.y
return collisions
def rect(self):
return pygame.Rect(self.x,self.y,self.size_x,self.size_y)
def set_flip(self,boolean):
self.flip = boolean
def set_animation_tags(self,tags):
self.animation_tags = tags
def set_animation(self,sequence):
self.animation = sequence
self.animation_frame = 0
def set_action(self,action_id,force=False):
if (self.action == action_id) and (force == False):
pass
else:
self.action = action_id
anim = animation_higher_database[self.type][action_id]
self.animation = anim[0]
self.set_animation_tags(anim[1])
self.animation_frame = 0
def get_entity_angle(entity_2):
x1 = self.x+int(self.size_x/2)
y1 = self.y+int(self.size_y/2)
x2 = entity_2.x+int(entity_2.size_x/2)
y2 = entity_2.y+int(entity_2.size_y/2)
angle = math.atan((y2-y1)/(x2-x1))
if x2 < x1:
angle += math.pi
return angle
def get_center(self):
x = self.x+int(self.size_x/2)
y = self.y+int(self.size_y/2)
return [x,y]
def clear_animation(self):
self.animation = None
def set_image(self,image):
self.image = image
def set_offset(self,offset):
self.offset = offset
def set_frame(self,amount):
self.animation_frame = amount
def handle(self):
self.action_timer += 1
self.change_frame(1)
def changeFrame(self,amount):
self.animation_frame += amount
if self.animation != None:
while self.animation_frame < 0:
if 'loop' in self.animation_tags:
self.animation_frame += len(self.animation)
else:
self.animation = 0
while self.animation_frame >= len(self.animation):
if 'loop' in self.animation_tags:
self.animation_frame -= len(self.animation)
else:
self.animation_frame = len(self.animation)-1
def get_current_img(self):
if self.animation == None:
if self.image != None:
return flip(self.image,self.flip)
else:
return None
else:
return flip(animation_database[self.animation[self.animation_frame]],self.flip)
def get_drawn_img(self):
image_to_render = None
if self.animation == None:
if self.image != None:
image_to_render = flip(self.image,self.flip).copy()
else:
image_to_render = flip(animation_database[self.animation[self.animation_frame]],self.flip).copy()
if image_to_render != None:
center_x = image_to_render.get_width()/2
center_y = image_to_render.get_height()/2
image_to_render = pygame.transform.rotate(image_to_render,self.rotation)
if self.alpha != None:
image_to_render.set_alpha(self.alpha)
return image_to_render, center_x, center_y
def display(self,surface,scroll):
image_to_render = None
if self.animation == None:
if self.image != None:
image_to_render = flip(self.image,self.flip).copy()
else:
image_to_render = flip(animation_database[self.animation[self.animation_frame]],self.flip).copy()
if image_to_render != None:
center_x = image_to_render.get_width()/2
center_y = image_to_render.get_height()/2
image_to_render = pygame.transform.rotate(image_to_render,self.rotation)
if self.alpha != None:
image_to_render.set_alpha(self.alpha)
blit_center(surface,image_to_render,(int(self.x)-scroll[0]+self.offset[0]+center_x,int(self.y)-scroll[1]+self.offset[1]+center_y))
and the function that handles collisions:
class physics_obj(object):
def __init__(self,x,y,x_size,y_size):
self.width = x_size
self.height = y_size
self.rect = pygame.Rect(x,y,self.width,self.height)
self.x = x
self.y = y
self.prevX = 0
def move(self, movement, tiles, enemiesList=[], movingList=[], notCollisionable=[], airTimer=0):
#tile_rects, enemiesList, movingList, notCollisionable
self.x += movement[0]
self.rect.x = int(self.x)
collision_types = {'top':False,'bottom':False,'right':False,'left':False,'slant_bottom':False,'data':[]}
# added collision data to "collision_types". ignore the poorly chosen variable name
#====================================================================
block_hit_list = collision_test(self.rect, tiles)
for block in block_hit_list:
type = "tile"
markers = [False,False,False,False]
if movement[0] > 0:
self.rect.right = block.left
collision_types['right'] = True
markers[0] = True
elif movement[0] < 0:
self.rect.left = block.right
collision_types['left'] = True
markers[1] = True
collision_types['data'].append([block,markers, type])
self.x = self.rect.x
self.y += movement[1]
self.rect.y = int(self.y)
block_hit_list = collision_test(self.rect,tiles)
for block in block_hit_list:
type = "tile"
markers = [False,False,False,False]
if movement[1] > 0:
self.rect.bottom = block.top
collision_types['bottom'] = True
markers[2] = True
elif movement[1] < 0:
self.rect.top = block.bottom
collision_types['top'] = True
markers[3] = True
collision_types['data'].append([block,markers, type])
self.change_y = 0
self.y = self.rect.y
#====================================================================
block_hit_list = movingCollision(self.rect, movingList)
for block in block_hit_list:
type = block.type
markers = [False,False,False,False]
tol = abs(self.rect.bottom - block.entity.obj.rect.top)
if movement[1] > 0 and tol < 16:
self.rect.bottom = block.entity.obj.rect.top
collision_types['bottom'] = True
markers[2] = True
collision_types['data'].append([block.entity.obj.rect,markers, type])
self.change_y = 0
self.y = self.rect.y
#====================================================================
block_hit_list = movingCollision(self.rect, enemiesList)
for block in block_hit_list:
type = block.type
markers = [False,False,False,False]
if movement[0] > 0:
self.rect.right = block.entity.obj.rect.left
collision_types['right'] = True
markers[0] = True
elif movement[0] < 0:
#self.rect.left = block.entity.obj.rect.right
collision_types['left'] = True
markers[1] = True
elif movement[1] > 0:
#self.rect.bottom = block.entity.obj.rect.top
collision_types['bottom'] = True
markers[2] = True
elif movement[1] < 0:
#self.rect.top = block.entity.obj.rect.bottom
collision_types['top'] = True
markers[3] = True
collision_types['data'].append([block.entity.obj.rect,markers, type])
#====================================================================
block_hit_list = movingCollision(self.rect, notCollisionable)
for block in block_hit_list:
type = block.type
markers = [False,False,False,False]
if movement[0] > 0:
collision_types['right'] = True
markers[0] = True
elif movement[0] < 0:
#self.rect.left = block.entity.obj.rect.right
collision_types['left'] = True
markers[1] = True
elif movement[1] > 0:
#self.rect.bottom = block.entity.obj.rect.top
collision_types['bottom'] = True
markers[2] = True
elif movement[1] < 0:
#self.rect.top = block.entity.obj.rect.bottom
collision_types['top'] = True
markers[3] = True
collision_types['data'].append([block.entity.obj.rect,markers, type])
return collision_types