can't get collision detection to work in platform game - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: Game Development (https://python-forum.io/forum-11.html) +--- Thread: can't get collision detection to work in platform game (/thread-37971.html) Pages:
1
2
|
can't get collision detection to work in platform game - chairmanme0wme0w - Aug-16-2022 the code isnt producing any errors, but the player just falls through the ground and platforms i set up, im not sure what the problem is!! any help would be super appreciated import pygame, sys # importing the library pygame and sys import time # imports time library from pygame.locals import * # import all pygames modules windowWidth = 960 # 64 * 15 windowHeight = 640 # 64 * 10 fps = 60 # frames per second/ updates and redraws per second main = True # main game loop is always true playerimg1 = pygame.image.load("idleghost.png") playerx = 0 playery = 512 playerspeed = 5 playerrect = pygame.Rect(playerx, playery, 64, 64) rightmovement = False # variables for player movement leftmovement = False jump = False player_y_momentum = 0 tilesize = 64 mapList = [['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a'], ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a'], ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a'], ['a', 'a', 'a', 'a', 'a', 'a', 'p', 'p', 'p', 'a', 'a', 'a', 'a', 'a', 'a'], ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'p', 'p', 'a'], ['a', 'a', 'p', 'p', 'p', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a'], ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a'], ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a'], ['a', 'a', 'a', 'a', 'a', 'a', 'p', 'p', 'a', 'a', 'a', 'a', 'a', 'a', 'a'], ['g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g']] background = pygame.image.load("wall.png") floor = pygame.image.load("floorboardtile.png") shelf = pygame.image.load("bookshelf.png") clock = pygame.time.Clock() # setting up the clock pygame.init() # initializing pygame window = pygame.display.set_mode((windowWidth, windowHeight)) # initializing the window/screen pygame.display.set_caption("Platform Game") # name of window def collision_test(rect, tiles): hit_list = [] for tile in tiles: if rect.colliderect(tile): hit_list.append(tile) return hit_list def move(rect, playerx, playery, tiles): collision_types = {'top': False, 'bottom': False, 'right': False, 'left': False} rect.x += playerx hit_list = collision_test(rect, tiles) for tile in hit_list: if rightmovement == True: rect.right = tile.left collision_types['right'] = True if leftmovement == True: rect.left = tile.right collision_types['left'] = True rect.y += playery hit_list = collision_test(rect, tiles) for tile in hit_list: if jump == False: rect.bottom = tile.top collision_types['bottom'] = True if jump == True: rect.top = tile.bottom collision_types['top'] = True return rect, collision_types while main == True: # main game loop window.blit(background, (0, 0)) # renders the background image, blit is used to place one surface upon another playerrect = pygame.Rect(playerx, playery, 60, 60) tile_rects = [] # sets up list of tile rects y = 0 # keeps track of x,y coordinates in tile map for row in mapList: # renders the tiles in the map list / for each row in the map list x = 0 for tile in row: # for each tile in each row if tile == 'g': # if a tile is the ground window.blit(floor, (x * tilesize, y * tilesize)) # render the floor image in the current co-ords if tile == 'p': # if a tile is a platform window.blit(shelf, (x * tilesize, y * tilesize)) if tile != 'a': tile_rects.append(pygame.Rect(x * tilesize, y * tilesize, tilesize, tilesize)) # add this tile to the tile rects list x += 1 # increase the x co-ord by 1 y += 1 # increase the y co-ord by 1 playery += player_y_momentum # add the players vertical momentum to their y position player_y_momentum += 0.2 # in every frame add 0.2 to the vertical momentum if player_y_momentum > 3: # stops the players vertical momentum being larger than 3 player_y_momentum = 3 playerrect, collisions_type = move(playerrect, playerx, playery, tile_rects) if collisions_type['bottom']: player_y_momentum = 0 window.blit(playerimg1, (playerx, playery)) # renders players image for event in pygame.event.get(): # the event loop if event.type == pygame.QUIT: # checks if the window is being closed pygame.quit() # stops pygame sys.exit() # stops the script running if event.type == KEYDOWN: if event.key == K_RIGHT or event.key == K_d: rightmovement = True if event.key == K_LEFT or event.key == K_a: leftmovement = True if event.key == K_UP or event.key == K_w: player_y_momentum = -5 if event.type == KEYUP: if event.key == K_RIGHT or event.key == K_d: rightmovement = False if event.key == K_LEFT or event.key == K_a: leftmovement = False if rightmovement == True: playerx = playerx + playerspeed if leftmovement == True: playerx = playerx - playerspeed pygame.display.update() # updates what is being displayed on screen clock.tick(fps) # maintains the frame rate (in this case 60) RE: can't get collision detection to work in platform game - deanhystad - Aug-16-2022 You collision detection fails because you pass playerx and playery to move() when you should pass player_speed and player_y_momentum. move() should look like this: def move(rect, xstep, ystep, tiles): collisions = {'top': False, 'bottom': False, 'right': False, 'left': False} # Move in x and check for collisions rect.x += xstep for tile in tiles: if rect.colliderect(tile): if xstep > 0: collisions['right'] = True elif xstep < 0: collisions['left'] = True break # Move in y and check for collisions rect.x -= xstep rect.y += ystep for tile in tiles: if ystep > 0: collisions['bottom'] = True elif ystep < 0: collisions['top'] = True break return collisionsYou weren't using the returned rect value, so don't return it. After checking for x collisions you want to move rect back (rect.x -= xstep) otherwise an x collision is also reported as a y collision. You'll also want to change the code that calls move() playery += player_y_momentum player_y_momentum = min(3, player_y_momentum + 0.2) collisions_type = move(playerrect, player_speed, player_y_momentum , tile_rects) RE: can't get collision detection to work in platform game - chairmanme0wme0w - Aug-16-2022 thank you!!! this was so helpful with the collisions stuff, it does now actually detect the ground! although it has made it so that once the player jumps, they do not fall back down, sorry this might be another error in the rest of my code, i've tried to solve it but just cant figure it out?? RE: can't get collision detection to work in platform game - deanhystad - Aug-17-2022 Jumping should give the player a negative momentum. Over time the integration of momentum (player_y_momentum = min(3, player_y_momentum + 0.2)) will bring momentum to zero (the apex of the jump) and then the player will begin to fall. It works when I press the up arrow. Look for code that changes playeer_y_momentum. I have an error in the move() code I posted. I forgot to check for y collisions. The function should look like this: def move(rect, xstep, ystep, tiles): collisions = {'top': False, 'bottom': False, 'right': False, 'left': False} # Move in x and check for collisions rect.x += xstep for tile in tiles: if rect.colliderect(tile): if xstep > 0: collisions['right'] = True elif xstep < 0: collisions['left'] = True break # Move in y and check for collisions rect.x -= xstep rect.y += ystep for tile in tiles: if rect.colliderect(tile): # Was missing this very important line. if ystep > 0: collisions['bottom'] = True elif ystep < 0: collisions['top'] = True break return collisions RE: can't get collision detection to work in platform game - chairmanme0wme0w - Aug-17-2022 thank you so much for your help!!! RE: can't get collision detection to work in platform game - chairmanme0wme0w - Aug-17-2022 i've managed to fix the jumping problem but now ive added the collisions for the sides of the platforms and i just cant get it to work when the player is supposed to stop after hitting the side of a platform they just continue through it, and when they hit the bottom of a floating platform they get stuck at that height!! sorry for all this, im just so confused lol ill reattach my code with the edits ive made: import pygame, sys # importing the library pygame and sys import time # imports time library from pygame.locals import * # import all pygames modules windowWidth = 960 # 64 * 15 windowHeight = 640 # 64 * 10 fps = 60 # frames per second/ updates and redraws per second main = True # main game loop is always true playerimg1 = pygame.image.load("idleghost.png") playerx = 0 playery = 512 playerspeed = 5 playerrect = pygame.Rect(playerx, playery, 64, 64) rightmovement = False # variables for player movement leftmovement = False jump = False player_y_momentum = 0 tilesize = 64 mapList = [['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a'], ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a'], ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a'], ['a', 'a', 'a', 'a', 'a', 'a', 'p', 'p', 'p', 'a', 'a', 'a', 'a', 'a', 'a'], ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'p', 'p', 'a'], ['a', 'a', 'p', 'p', 'p', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a'], ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a'], ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a'], ['a', 'a', 'a', 'a', 'a', 'a', 'p', 'p', 'a', 'a', 'a', 'a', 'a', 'a', 'a'], # y=576 ['g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g', 'g']] background = pygame.image.load("bloodywall.png") floor = pygame.image.load("floorboardtile.png") shelf = pygame.image.load("bookshelf.png") clock = pygame.time.Clock() # setting up the clock pygame.init() # initializing pygame window = pygame.display.set_mode((windowWidth, windowHeight)) # initializing the window/screen pygame.display.set_caption("Platform Game") # name of window def collision_test(rect, tiles): hit_list = [] for tile in tiles: if rect.colliderect(tile): hit_list.append(tile) return hit_list def move(rect, xstep, ystep, tiles): collisions = {'top': False, 'bottom': False, 'right': False, 'left': False} hit_list = collision_test(rect, tiles) # Move in x and check for collisions rect.x += xstep for tiles in hit_list: if rect.colliderect(tiles): if xstep > 0: collisions['right'] = True elif xstep < 0: collisions['left'] = True break # Move in y and check for collisions rect.x -= xstep rect.y += ystep for tiles in hit_list: if rect.colliderect(tiles): # Was missing this very important line. if ystep > 0: collisions['bottom'] = True elif ystep < 0: collisions['top'] = True break return collisions while main == True: # main game loop window.blit(background, (0, 0)) # renders the background image, blit is used to place one surface upon another playerrect = pygame.Rect(playerx, playery, playerimg1.get_width(), playerimg1.get_height()) tile_rects = [] # sets up list of tile rects y = 0 # keeps track of x,y coordinates in tile map for row in mapList: # renders the tiles in the map list / for each row in the map list x = 0 for tile in row: # for each tile in each row if tile == 'g': # if a tile is the ground window.blit(floor, (x * tilesize, y * tilesize)) # render the floor image in the current co-ords tile_rects.append(pygame.Rect(x * tilesize, y * tilesize, tilesize, tilesize)) if tile == 'p': # if a tile is a platform window.blit(shelf, (x * tilesize, y * tilesize)) tile_rects.append(pygame.Rect(x * tilesize, y * tilesize, tilesize, tilesize)) x += 1 # increase the x co-ord by 1 y += 1 # increase the y co-ord by 1 playery += player_y_momentum player_y_momentum = min(3, player_y_momentum + 0.2) # add the players vertical momentum to their y position collisions_type = move(playerrect, playerspeed, player_y_momentum, tile_rects) if collisions_type['bottom']: player_y_momentum = 0 if collisions_type['top']: player_y_momentum = 5 if collisions_type['right']: playerspeed = 0 else: playerspeed = 5 if collisions_type['left']: playerspeed = 0 else: playerspeed = 5 window.blit(playerimg1, (playerx, playery)) # renders players image for event in pygame.event.get(): # the event loop if event.type == pygame.QUIT: # checks if the window is being closed pygame.quit() # stops pygame sys.exit() # stops the script running if event.type == KEYDOWN: if event.key == K_RIGHT or event.key == K_d: rightmovement = True if event.key == K_LEFT or event.key == K_a: leftmovement = True if event.key == K_UP or event.key == K_w: player_y_momentum = -5 if event.type == KEYUP: if event.key == K_RIGHT or event.key == K_d: rightmovement = False if event.key == K_LEFT or event.key == K_a: leftmovement = False if event.key == K_UP or event.key == K_w: player_y_momentum = player_y_momentum + 0.2 if player_y_momentum > 3: player_y_momentum = 3 if rightmovement == True: playerx = playerx + playerspeed if leftmovement == True: playerx = playerx - playerspeed pygame.display.update() # updates what is being displayed on screen clock.tick(fps) # maintains the frame rate (in this case 60) RE: can't get collision detection to work in platform game - deanhystad - Aug-17-2022 Think about 1 problem at a time. I would start with stopping when running into a wall. If you can't figure that out by yourself I suggest you watch a few videos or do a tutorial. These are very basic components. If you don't understand them well you are just going to get frustrated. RE: can't get collision detection to work in platform game - XavierPlatinum - Aug-17-2022 (Aug-17-2022, 07:22 PM)chairmanme0wme0w Wrote: i've managed to fix the jumping problem but now ive added the collisions for the sides of the platforms and i just cant get it to work As for this point, when you add the momentum and check collision, you zero the momentum but don't subtract the movement you just added. They are still inside the block at the end of the turn. rect.x += xstep for tiles in hit_list: if rect.colliderect(tiles): rect.x -= xstepbetter would be something to the effect rect.x += xstep for tile in hit_list: if rect.colliderect(tile): # if moving right rect.right = tile.rect.left RE: can't get collision detection to work in platform game - deanhystad - Aug-18-2022 Your problem with left/right is you control player speed like this if rightmovement == True: playerx = playerx + playerspeed if leftmovement == True: playerx = playerx - playerspeedBut if you have a collision you don't set leftmovement or rightmovement false. Detecting collisions is useless if you don't take appropriate action. I would get rid of the left/right movement and work directly with player_speed. When the right key is pressed set player speed = 5. When the key is released set player speed = 0. When there is a x direction collision set player speed = 0. Do the same for the left key, except set the player speed to -5. This same sort of thing is why the player sticks when they jump up into a barrier. RE: can't get collision detection to work in platform game - chairmanme0wme0w - Aug-18-2022 i've made these changes, but i think the problem is moreso rooted in the actual collisions, as i made the tiles turn red upon being collided with, and that has suggested that even when a left/right collision isnt taking place, its registered as a collision if the player is touching the floor. does that make sense? thanks for all the help and advice! rect.x += xstep for tile in tiles: if rect.colliderect(tile): if xstep > 0: collisions['right'] = True pygame.draw.rect(window, (255, 0, 0), tile) elif xstep < 0: collisions['left'] = True break |