python - Pygame: Collision With tiles not working -
i working on abstraction layer pygame, , have come across problem when trying check collisions maps. able load , display map, store rectangles collidable. when print list of rectangles, see in place, when iterate on every rect , try check collision rect, returns true when rects not collide. also, when try debug rects drawing red-outlined rectangle on each 1 of them, nothing gets drawn though when print rectangle, prints rectangle exists.
here few snippets framework:
class tilemap(object): """this tilemap object, takes array of strings object, , places surface have in strings. supports 1 surface per map, have make multiple maps floor, walls, etc.""" def __init__(self, level_surface,level_string = none, string_char = "#", surface = none, surface_dim = vector2(50, 50),surface_color = (255, 255, 255)): self.level = level_string self.char = string_char self.surface = surface if self.surface none: self.surface = pygame.surface(surface_dim) self.surface.fill(surface_color) self.surface_width = self.surface.get_rect().w self.surface_height = self.surface.get_rect().h self.collision_list = [] y in xrange(len(self.level)): x in xrange(len(self.level[y])): if self.level[y][x] self.char: self.collision_list.insert(len(self.collision_list), rect((x) * self.surface_width,(y) * self.surface_height, self.surface_width, self.surface_height)) print self.collision_list y in xrange(len(self.level)): x in xrange(len(self.level[y])): if self.level[y][x] self.char: level_surface.blit(self.surface.convert_alpha(), (self.surface_width * x, self.surface_height * y)) def replace_char_with(self, level_surface,char = ".", surface = none): y in xrange(len(self.level)): x in xrange(len(self.level[y])): if self.level[y][x] char: level_surface.blit(surface.convert_alpha(), (surface.get_width() * x, surface.get_height() * y)) def check_col(self, rect): tilerect in self.collision_list: if rect.x + rect.w > tilerect.x or rect.y + rect.h > tilerect.y or rect.x < tilerect.x + tilerect.w or rect.y < tilerect.y + tilerect.h: return true else: return false def debug_draw(self, screen): rect in self.collision_list: pygame.draw.rect(screen, (255, 0, 0), rect, 2)
snippet # 2, testing code:
def main(): pygame.locals import k_w, k_a, k_s, k_d pygame.init() screen = pygame.display.set_mode((640, 480)) clock = pygame.time.clock() player = sprite(pygame.image.load("trapdoor_tile.png"), vector2(100, 100)) floor = ["########################################", "########################################", "#####...##.#.#..###.#.###..#############", "#####.######.#.#.####.##.#.#############", "######.###.#.##..##.#.###.##############", "#####.####.########.####################", "#####.#.##.###.#.##.#.##.#.#############", "########################################", "#######################################", "########################################", "########################################", "########################################", "########################################", "########################################" "########################################", "########################################", "########################################", "########################################", "########################################", "########################################", "########################################", "########################################", "########################################", "########################################", "########################################", "########################################", "########################################", "########################################", "########################################", "########################################"] walls = ["########################################", "#......................................#", "#......................................#", "#......................................#", "#......................................#", "#......................................#", "#......................................#", "#......................................#", "#......................................#", "#......................................#", "#......................................#", "#......................................#", "#......................................#", "#......................................#", "#......................................#", "#......................................#", "#......................................#", "#......................................#", "#......................................#", "#......................................#", "#......................................#", "#......................................#", "#......................................#", "#......................................#", "#......................................#", "#......................................#", "#......................................#", "#......................................#", "#......................................#", "########################################"] level_surf = pygame.surface((640, 480)) floor_map = tilemap(level_surf, floor, "#", pygame.image.load("ground_tile.png").convert_alpha()) floor_map.replace_char_with(level_surf, ".", pygame.image.load("trapdoor_tile.png").convert_alpha()) wall_map = tilemap(level_surf, walls, "#", pygame.image.load("wall_tile.png").convert_alpha()) while true: screen.fill((0, 0, 0)) milliseconds = clock.tick(60) / 10. event in pygame.event.get(): if event.type == pygame.locals.quit: pygame.quit() raise systemexit wall_map.debug_draw(screen); screen.blit(level_surf, vector2(0, 0)) if wall_map.check_col(player.dummyrect): player.colliding = true print "why!" else: player.colliding = false player.update(milliseconds) player.draw(screen) keystate = pygame.key.get_pressed() player.apply_drag() if keystate[k_w]: player.set_accel_y(-5) elif keystate[k_s]: player.set_accel_y(5) elif keystate[k_a]: player.set_accel_x(-5) elif keystate[k_d]: player.set_accel_x(5) pygame.display.flip()
the sprite class player created:
class sprite(object): def __init__(self, surface = none, initial_position = (100, 100)): self.surface = surface self.rect = self.surface.get_rect(center = initial_position) self.acceleration = vector2(0, 0) self.delta_time = none self.dummyrect = self.rect self.colliding = false def update(self, delta_time): self.dummyrect = self.rect.move(self.acceleration.x * delta_time, self.acceleration.y * delta_time) if not self.colliding: self.rect = self.dummyrect else: self.dummyrect = self.rect self.delta_time = delta_time def draw(self, screen): screen.blit(self.surface, self.rect) def draw_to_cam(self, screen,camera): screen.blit(self.surface, camera.to_camera_coords(vector2(self.rect.x, self.rect.y))) def collide(self, rectangle): if self.rect.x + self.rect.w > rectangle.x: self.rect.x -= 1; if self.rect.x < rectangle.x + rectangle.w: self.rect.x += 1 if self.rect.y < rectangle.y + rectangle.h: self.rect.y += 1; if self.rect.y + self.rect.h > rectangle.y: self.rect.y -= 1; def set_accel_x(self, new_val): self.acceleration.x = new_val def set_accel_y(self, new_val): self.acceleration.y = new_val def apply_drag(self, drag_mul = 1): if self.acceleration.x > 0: self.acceleration.x -= self.delta_time * drag_mul else: self.acceleration.x += self.delta_time * drag_mul if self.acceleration.y > 0: self.acceleration.y -= self.delta_time * drag_mul else: self.acceleration.y += self.delta_time * drag_mul if self.acceleration.x < 0.1 or self.acceleration.x > -0.1: self.acceleration.x = 0 if self.acceleration.x < 0.1 or self.acceleration.x > -0.1: self.acceleration.x = 0 if self.acceleration.y < 0.1 or self.acceleration.y > -0.1: self.acceleration.y = 0 if self.acceleration.y < 0.1 or self.acceleration.y > -0.1: self.acceleration.y = 0 def get_center(self): return vector2(self.rect.centerx, self.rect.centery)
those 3 main snippets involved, have no idea why collision returned every time, seems so. if has answer, or explanation @ least, why occurs, please brother out!
your check_col function using 'or' operators, meaning you're returning true collision long 1 condition met. here code:
def check_col(self, rect): tilerect in self.collision_list: if rect.x + rect.w > tilerect.x or rect.y + rect.h > tilerect.y or rect.x < tilerect.x + tilerect.w or rect.y < tilerect.y + tilerect.h: return true else: return false
what want more this:
def check_col(self, rect): tilerect in self.collision_list: if ((rect.x + rect.w > tilerect.x , rect.x <= tilerect.x + tilerect.width) or (tilerect.x + tilerect.width > rect.x , tilerect.x <= rect.x + rect.width)) , ((rect.y + rect.h > tilerect.y , rect.y <= tilerect.y + tilerect.height) or (tilerect.y + tilerect.height > rect.y , tilerect.y <= rect.y + rect.height)) return true else: return false
also, might worth pointing out pygame's rect class has own set of collision detection functions. detect collision between 2 rects can use rect.colliderect(rect).
http://www.pygame.org/docs/ref/rect.html#pygame.rect.colliderect
Comments
Post a Comment