class Dugeon(object): """docstring for Dugeon""" def __init__(self): super(Dugeon, self).__init__() self.cells_count = 100 self.rooms_group = pg.sprite.LayeredDirty() self.doors_group = pg.sprite.LayeredDirty() self.backgound = pg.sprite.LayeredDirty() self.visible_sprites = pg.sprite.LayeredDirty() self.doors = [] self.cells = [] while (len(self.cells) < self.cells_count): c = Cell() self.cells.append(c) self.rooms = self.select_main_rooms(self.cells) area, min_x, min_y = self.separate_cells(self.rooms) print("Dugeon dimentions With: %s Heigth: %s" % area) w = area[0] + MAX_ROOM_W * TS2 + TS2 h = area[1] + MAX_ROOM_H * TS2 + TS2 self.image = pg.Surface((w, h)) self.image.fill((0, 0, 0)) self.bg_image = pg.Surface((SCREEN_RECT.w, SCREEN_RECT.h)) self.bg_image.fill((0, 0, 0)) self.rect = self.image.get_rect() self.clip_rooms(min_x, min_y) self.halls = self.connet_rooms(self.rooms) self.initial_room = random.choice(self.rooms) self.initial_room.spawed = True self.walls = [] self.make_walls() # self.remove_useless_doors() self.fix_walls() self.player = Player(self.initial_room.rect.center, ALL_SPRITES) self.viewport = Viewport() self.viewport.update(self.player, self.rect) # Custom Cursor pg.mouse.set_visible(False) self.cursor = Cursor((0, 0), ALL_SPRITES) self.cursor.update(self.viewport) ALL_SPRITES.change_layer(self.cursor, 9) def separate_cells(self, cells): """based on http://fisherevans.com/blog/post/dungeon-generation """ touching = True interation = 0 min_x = 0 max_x = 0 min_y = 0 max_y = 0 while touching: touching = False for i in range(len(cells)): a = cells[i] for j in range(i + 1, len(cells)): b = cells[j] if a.rect.colliderect(b.rect.inflate(TS4, TS4)): touching = True dx = min(a.rect.right - b.rect.left + TS4, a.rect.left - b.rect.right - TS4) dy = min(a.rect.bottom - b.rect.top + TS4, a.rect.top - b.rect.bottom - TS4) if (abs(dx) < abs(dy)): dy = 0 else: dx = 0 dxa = -dx / 2 dxb = dx + dxa dya = -dy / 2 dyb = dy + dya dxa = math.floor(((dxa + TS4 - 1) / TS4)) * TS4 dxb = math.floor(((dxb + TS4 - 1) / TS4)) * TS4 dya = math.floor(((dya + TS4 - 1) / TS4)) * TS4 dyb = math.floor(((dyb + TS4 - 1) / TS4)) * TS4 a.pos[0] += dxa a.pos[1] += dya b.pos[0] += dxb b.pos[1] += dyb min_x = min(min_x, a.pos[0], b.pos[0]) min_y = min(min_y, a.pos[1], b.pos[1]) max_x = max(max_x, a.pos[0], b.pos[0]) max_y = max(max_y, a.pos[1], b.pos[1]) a.rect.topleft = a.pos b.rect.topleft = b.pos area = ((max_x - min_x), (max_y - min_y)) return area, min_x, min_y def select_main_rooms(self, cells): seleted = [] for room in cells: if (room.rect.w > MIN_ROOM_W * TS2 and room.rect.h > MIN_ROOM_H * TS2): room.seleted = True room.generate_image() seleted.append(room) room.add(ALL_SPRITES, self.rooms_group, self.backgound) print("Rooms selected as main rooms %s" % len(seleted)) return seleted def connet_rooms(self, rooms): paths = [] for i in range(len(rooms)): a = rooms[i] for j in range(i + 1, len(rooms)): skip = False b = rooms[j] ab_dist = math.pow(a.rect.centerx-b.rect.centerx, 2) + \ math.pow(a.rect.centery-b.rect.centery, 2) for k in range(len(rooms)): if (k == i or k == j): continue c = rooms[k] ac_dist = math.pow(a.rect.centerx-c.rect.centerx, 2) + \ math.pow(a.rect.centery-c.rect.centery, 2) bc_dist = math.pow(b.rect.centerx-c.rect.centerx, 2) + \ math.pow(b.rect.centery-c.rect.centery, 2) if (ac_dist < ab_dist and bc_dist < ab_dist): skip = True if not skip: ps = self.create_path(a.rect.center, b.rect.center) paths += ps return paths def create_path(self, p1, p2): # A always left o B if (p1[0] < p2[0]): a = p1 b = p2 else: a = p2 b = p1 a = list(a) b = list(b) w = h = TS2 # magic o make the perfect centered hallways a[0] -= TILE_SIZE a[1] -= TILE_SIZE b[0] -= TILE_SIZE b[1] -= TILE_SIZE a[0] = math.floor(((a[0] + TS2 - 1) / TS2)) * TS2 a[1] = math.floor(((a[1] + TS2 - 1) / TS2)) * TS2 b[0] = math.floor(((b[0] + TS2 - 1) / TS2)) * TS2 b[1] = math.floor(((b[1] + TS2 - 1) / TS2)) * TS2 clockwise = random.randint(0, 1) == 1 dx = b[0] - a[0] # A avobe B if (a[1] < b[1]): dy = b[1] - a[1] if clockwise: r1 = pg.Rect(a[0], a[1], dx + w, h) r2 = pg.Rect(b[0], a[1], w, dy) else: r1 = pg.Rect(a[0], a[1], w, dy + h) r2 = pg.Rect(a[0], b[1], dx + w, h) else: dy = a[1] - b[1] if clockwise: r1 = pg.Rect(b[0], b[1], w, dy + h) r2 = pg.Rect(a[0], a[1], dx + w, h) else: r1 = pg.Rect(a[0], b[1], dx + w, h) r2 = pg.Rect(a[0], b[1], w, dy + h) h1 = Hallway(r1, ALL_SPRITES, self.backgound) h2 = Hallway(r2, ALL_SPRITES, self.backgound) return [h1, h2] def clip_rooms(self, min_x, min_y): for r in self.rooms: r.pos[0] += abs(min_x) + TS2 r.pos[1] += abs(min_y) + TS2 r.rect.topleft = r.pos def make_walls(self): for room in self.rooms: x, y = room.rect.topleft w = int(room.rect.w / TS2) h = int(room.rect.h / TS2) old_hall = None for i in range(w): for j in range(h): if (j > 0 and j < h - 1) and (i > 0 and i < w - 1): y += TS2 continue wall = Wall((x, y), i, j, w, h) hit_walls = pg.sprite.spritecollideany(wall, self.walls) hit_rooms = pg.sprite.spritecollideany( wall, self.rooms_group) if not hit_walls or not hit_rooms: hall = pg.sprite.spritecollideany(wall, self.halls) if hall: if old_hall != hall: door = Door((x, y), i, j, w, h) door.add(self.doors_group, ALL_SPRITES) ALL_SPRITES.change_layer(door, 6) self.doors.append(door) door.room = room room.doors.append(door) old_hall = hall else: self.walls.append(wall) ALL_SPRITES.add(wall) y += TS2 x += TS2 y = room.rect.top for hall in self.halls: x, y = hall.rect.topleft x -= TS2 y -= TS2 w = int(hall.rect.w / TS2) + 2 h = int(hall.rect.h / TS2) + 2 for i in range(w): for j in range(h): if (j > 0 and j < h - 1) and (i > 0 and i < w - 1): y += TS2 continue wall = Wall((x, y), i, j, w, h) if not pg.sprite.spritecollideany(wall, ALL_SPRITES): self.walls.append(wall) ALL_SPRITES.add(wall) ALL_SPRITES.change_layer(wall, 3) else: old_wall = pg.sprite.spritecollideany(wall, self.walls) if old_wall: old_wall.need_fix = True y += TS2 x += TS2 y = hall.rect.top - TS2 def remove_useless_doors(self): for i in range(len(self.doors)): a = self.doors[i] a.rect.inflate_ip(TS2, 0) walls_around = pg.sprite.spritecollide(a, self.walls, False) a.rect.inflate_ip(-TS2, TS2) if len(walls_around) < 2: walls_around = pg.sprite.spritecollide(a, self.walls, False) if len(walls_around) < 2: a.kill() continue a.rect.inflate_ip(TS2, 0) for j in range(i + 1, len(self.doors)): b = self.doors[j] if pg.sprite.collide_rect(a, b) and not b.locked: b.kill() a.rect.inflate_ip(-TS2, -TS2) def fix_walls(self): pass # a = self.walls[0] # a.rect.inflate_ip(TS2, TS2) # walls_around = pg.sprite.spritecollide(a, self.walls, False) # for w in walls_around: # a.rect.inflate_ip(-TS2, -TS2) def handle_input(self, event): self.player.handle_input(event) # if event.type == pg.MOUSEMOTION: # print(x1+x2, y1+y2) def update(self, dt): visible_walls = pg.sprite.spritecollide(self.viewport, self.walls, False) self.player.update(dt, self.walls, self.doors_group, self.cursor) self.viewport.update(self.player, self.rect) self.cursor.update(self.viewport) # BULLETS_GROUP.update(dt) ENEMIES_GROUP.update(dt, self.player) self.rooms_group.update() visible_sprites = pg.sprite.spritecollide(self.viewport, ALL_SPRITES, False) self.visible_sprites.add(visible_sprites) for sprite in self.visible_sprites.sprites(): if not sprite in self.backgound: self.visible_sprites.change_layer(sprite, sprite.rect.centery) else: self.visible_sprites.change_layer(sprite, sprite.layer) self.visible_sprites.change_layer(self.cursor, 9999) if sprite not in visible_sprites: self.visible_sprites.remove(sprite) def render(self, surface): # ALL_SPRITES.repaint_rect(self.viewport) self.image.blit(self.bg_image, (self.viewport.rect)) self.visible_sprites.draw(self.image) BULLETS_GROUP.draw(self.image) ENEMIES_GROUP.draw(self.image) DECORATOR_GROUP.draw(self.image) surface.blit(self.image, (0, 0), self.viewport) self.viewport.render(surface)
if event.key == pygame.K_ESCAPE: running = False elif event.type == pygame.KEYUP: if event.key == pygame.K_w: iddle_move = 'IDDLE_UP' if event.key == pygame.K_s: iddle_move = 'IDDLE_DOWN' if event.key == pygame.K_a: iddle_move = 'IDDLE_LEFT' if event.key == pygame.K_d: iddle_move = 'IDDLE_RIGHT' # elif event.type == pygame.MOUSEMOTION: # enemy.rect.center = event.pos enemy.update() enemy.draw() player.draw() player.update(iddle_move) if pygame.sprite.spritecollide(player, enemies, False, pygame.sprite.collide_mask): pygame.display.set_caption('collision') else: pygame.display.set_caption('no collision') # Update the screen in every loop pygame.display.update() pygame.quit()