示例#1
0
class Room:
    '''Container for all in-game elements'''
    def __init__(self, floor_data, parent_game):
        self._scenario_ = TileMapLayer(floor_data, mask=get_color_mask())
        self._camera_ = Camera(self._scenario_)
        self._game_ = parent_game
        self._game_objects_ = {}
        self._decorations_ = {}
        self.block = self._compute_walls_collisions_()
        self._spawns_ = self._get_spawns_()

    @property
    def initial_objects(self):
        '''List of all objects defined in the map initially'''
        return self._scenario_.objects

    @property
    def game_objects(self):
        '''Map of current-living objects'''
        return self._game_objects_

    def _compute_walls_collisions_(self):
        block = []
        for y in range(self._scenario_.map_height):
            row = []
            for x in range(self._scenario_.map_width):
                row.append(self._scenario_.get_cell_at(x, y) in BLOCK_CELLS)
            block.append(row)
        return block

    def _get_spawns_(self):
        spawns = {}
        for candidate in self._game_objects_.values():
            if isinstance(candidate, Spawn):
                spawns[candidate.spawn] = candidate.position
        return spawns

    @property
    def camera(self):
        '''Room camera'''
        return self._camera_

    def set_camera_target(self, game_object):
        '''Change target of the camera'''
        self._camera_.set_target(game_object)

    @property
    def tilemaps(self):
        '''Map layers'''
        return self._scenario_

    def spawn(self, game_object):
        '''Spawn new object at a spawn zone'''
        spawn_zone = game_object.spawn if game_object.spawn in self._spawns_ else DEFAULT_SPAWN
        self.spawn_at(game_object, self._spawns_[spawn_zone])

    def spawn_at(self, game_object, position):
        '''Spawn new object at a given position'''
        self._game_objects_[game_object.identifier] = game_object
        self._game_objects_[game_object.identifier].position = position
        self._game_objects_[game_object.identifier].room = self
        self._spawns_.update(self._get_spawns_())

    def spawn_decoration(self, decoration_id, position):
        '''Spawn decoration'''
        decoration = game.decoration.new(decoration_id, position)
        self._decorations_[decoration.identifier] = decoration
        self._decorations_[decoration.identifier].room = self

    def kill(self, game_object):
        '''Kill an object'''
        identifier = game_object if isinstance(game_object,
                                               str) else game_object.identifier

        if identifier == self._game_.identifier:
            self._game_.player.attribute.update(
                self._game_objects_[identifier].attribute)

        if identifier in self._game_objects_:
            self._game_objects_[identifier].room = None
            del self._game_objects_[identifier]
        elif identifier in self._decorations_:
            self._decorations_[identifier].room = None
            del self._decorations_[identifier]

        if identifier == self._game_.identifier:
            self._game_.end_current_room()

    def open_door(self, door_identifier):
        '''Open a existing door'''
        door_position = self._search_door_(door_identifier)
        if not door_position:
            return
        doors = self._adjacent_doors_(door_position)
        for door in doors:
            self.kill(door)
            self.send_event(('kill_object', door))

    def _search_door_(self, door_identifier):
        if door_identifier not in self._game_objects_:
            return None
        y = 0
        for row in self.block:
            x = 0
            for cell in row:
                if cell == door_identifier:
                    return (x, y)
                x += 1
            y += 1
        return None

    def _adjacent_doors_(self, location, visited=None):
        if not visited:
            visited = []
        x, y = location
        if location in visited:
            return []
        visited.append((x, y))
        if (y not in range(len(self.block))) or (x not in range(
                len(self.block[0]))):
            return []
        identifier = self.block[y][x]
        door = self._game_objects_[identifier]
        if not isinstance(door, Door):
            return []
        doors = [door.identifier]
        door_tile_id = door.attribute[TILE_ID]
        for dir_x, dir_y in _DOOR_DIRECTION_[door_tile_id]:
            doors += self._adjacent_doors_((x + dir_x, y + dir_y), visited)
        return doors

    def update(self):
        '''A game loop iteration'''
        for game_object in list(self._game_objects_.values()):
            game_object.update()
            if not game_object.acting:
                self.kill(game_object)
            if game_object.body:
                self.check_collisions_with(game_object)

    def render(self):
        '''Draw a frame'''
        self._camera_.update()
        self._scenario_.render(*self._camera_.position)

        for game_object in self._game_objects_.values():
            game_object.render(*self._camera_.position)

        for decoration in list(self._decorations_.values()):
            decoration.render(*self._camera_.position)

    def check_collisions_with(self, game_object):
        '''Compute collisions for all game objects'''
        if not game_object.body:
            return
        for other_game_object in list(self._game_objects_.values()):
            if (other_game_object is
                    game_object) or (not other_game_object.body):
                continue
            if game_object.body.collides_with(other_game_object):
                self.send_event(('collision', game_object.identifier,
                                 other_game_object.identifier))

    def send_event(self, event):
        '''Send event to orchestrator'''
        self._game_.send_event(event)
示例#2
0
class Game:
    def __init__(self):
        init()
        font.init()
        display.set_caption(TITLE)
        key.set_repeat()

        self.playing = False

        self.screen = display.set_mode((WIDTH, HEIGHT))

        self.clock = time.Clock()
        self.dt = self.clock.tick(FPS) / 1000

        self.labels = list()
        self.infos = list()

        self.all_sprites = Group()

        self.adventure = Home(self)

        self.camera = Camera(self.adventure.map.width, self.adventure.map.height)
        self.score = Score("Renato")

        self.game_over = False

    def update_adventure(self, adventure):
        self.show_ended_screen()

        self.adventure.player.kill()
        self.labels = list()
        self.infos = list()

        self.adventure = adventure
        self._update_camera()

        self.show_go_screen()

        self.score.start_adventure(adventure.level.level_score)

    def run(self):
        self.playing = True

        while self.playing:
            self.events()
            self.update()
            self.draw()

            if self.game_over:
                break

            if self.adventure.finish:
                self.show_end_adventure_screen()
                break

    def update(self):
        # update info
        self.infos = list()

        self.adventure.update()
        self.all_sprites.update()

        self.camera.update(self.adventure.player)

    def draw(self):
        if not self.adventure.has_menu:
            self.screen.blit(self.adventure.map_image, self.camera.apply_rect(self.adventure.map_rect))

            for sprite in self.all_sprites:
                self.screen.blit(sprite.image, self.camera.apply(sprite))

            for label in self.labels:
                self.screen.blit(label.surface, self.camera.apply_rect(label.rect))

            for info in self.infos:
                self.screen.blit(info.surface, info.rect)

            for zombie in self.adventure.zombies:
                zombie.draw_health()

        display.flip()

    def events(self):
        events = key_event.get()
        if not self.adventure.has_menu:
            for event in events:
                if event.type == QUIT:
                    self.__quit__()
                if event.type == KEYDOWN:
                    if event.key == K_ESCAPE:
                        self.__quit__()

        self.adventure.events(events)

    def show_start_screen(self):
        pass

    def show_go_screen(self):
        self.update()

        start_display = Surface((WIDTH, HEIGHT), SRCALPHA)
        for alpha in range(255, 0, -1):
            start_display.fill((0, 0, 0, alpha))

            self.screen.blit(self.adventure.map_image, self.camera.apply_rect(self.adventure.map_rect))
            self.screen.blit(start_display, (0, 0))

            display.flip()
            time.delay(10)

    def show_ended_screen(self):
        self.update()

        start_display = Surface((WIDTH, HEIGHT), SRCALPHA)
        for alpha in range(255):
            start_display.fill((0, 0, 0, alpha))

            self.screen.blit(self.adventure.map_image, self.camera.apply_rect(self.adventure.map_rect))
            self.screen.blit(start_display, (0, 0))

            display.flip()
            time.delay(10)

    def show_game_over_screen(self):
        game_over_display = Surface((WIDTH, HEIGHT), SRCALPHA)
        game_over_text = Label('Game Over', 'assets/fonts/blocks.ttf', 20, (HEIGHT / 2) - 100, font_size=72)
        score_text = Label('For save the score you need finish adventure', 'assets/fonts/future_narrow.ttf', 20,
                           (HEIGHT / 2) - 120, font_size=24)

        return_text = Label('You will return to home', 'assets/fonts/future_narrow.ttf', 20, (HEIGHT / 2) - 160,
                            font_size=24)
        for alpha in range(255):
            game_over_display.fill((0, 0, 0, alpha))

            self.screen.blit(game_over_display, (0, 0))

            self.screen.blit(game_over_text.surface, game_over_text.rect)
            self.screen.blit(score_text.surface, score_text.rect)
            self.screen.blit(return_text.surface, return_text.rect)

            display.flip()

            time.delay(10)

    def show_end_adventure_screen(self):
        end_surface = Surface((WIDTH, HEIGHT), SRCALPHA)
        end_text = Label('Good Nice!', 'assets/fonts/blocks.ttf', 20, (HEIGHT / 2) - 100, font_size=72)
        score_text = Label(f'Score: {self.score.calculate_score()}', 'assets/fonts/future_narrow.ttf', 20,
                           (HEIGHT / 2) - 120, font_size=24)

        return_text = Label('You will return to home and see you score ranking', 'assets/fonts/future_narrow.ttf', 20,
                            (HEIGHT / 2) - 160,
                            font_size=24)
        for alpha in range(255):
            end_surface.fill((0, 0, 0, alpha))

            self.screen.blit(end_surface, (0, 0))

            self.screen.blit(end_text.surface, end_text.rect)
            self.screen.blit(score_text.surface, score_text.rect)
            self.screen.blit(return_text.surface, return_text.rect)

            display.flip()

            time.delay(10)

    def _update_camera(self):
        self.camera = Camera(self.adventure.map.width, self.adventure.map.height)

    @staticmethod
    def __quit__():
        quit()
        sys.exit()
示例#3
0
class VaniaGame:
    """
    An attempt to make a 'Metroidvania' style platform game.
    """
    def __init__(self):
        pygame.init()
        os.environ['SDL_VIDEO_CENTERED'] = '1'
        pygame.display.set_caption("Vania")
        world_size = [4096, 4096]
        self.camera = Camera((400, 300), (800, 600), world_size)
        pygame.display.set_icon(pygame.image.load('images/icon.png'))
        self.screen = pygame.display.set_mode(self.camera.dimensions, 0, 0)

        self.fonts = {
            "default_12":
            pygame.font.Font("data/fonts/Pavanam-Regular.ttf", 12),
            "default_12_bold":
            pygame.font.Font("data/fonts/Pavanam-Regular.ttf", 12),
            "default_14":
            pygame.font.Font("data/fonts/Pavanam-Regular.ttf", 14),
            "default_14_bold":
            pygame.font.Font("data/fonts/Pavanam-Regular.ttf", 14),
            "default_16":
            pygame.font.Font("data/fonts/Pavanam-Regular.ttf", 16),
            "default_16_bold":
            pygame.font.Font("data/fonts/Pavanam-Regular.ttf", 16),
            "default_32":
            pygame.font.Font("data/fonts/Pavanam-Regular.ttf", 32),
            "default_64":
            pygame.font.Font("data/fonts/Pavanam-Regular.ttf", 64),
            "julee_128":
            pygame.font.Font(os.path.abspath("data/fonts/Julee-Regular.ttf"),
                             128),
            "roboto_14_bold":
            pygame.font.Font("data/fonts/Roboto-Bold.ttf", 14)
        }

        self.fonts["default_12_bold"].set_bold(True)
        self.fonts["default_14_bold"].set_bold(True)
        self.fonts["default_16_bold"].set_bold(True)

        self.background = pygame.Surface(self.camera.dimensions)
        self.background.fill(pygame.Color("#c4dbf3"))

        grid_square_size = 64

        world_filling_number_of_grid_squares = [
            int(world_size[0] / grid_square_size),
            int(world_size[1] / grid_square_size)
        ]
        self.collision_grid = CollisionGrid(
            world_filling_number_of_grid_squares, grid_square_size)

        self.moving_sprites_group = pygame.sprite.Group()
        self.ui_sprites_group = pygame.sprite.Group()

        self.player = Player(self.moving_sprites_group, self.ui_sprites_group,
                             self.fonts, self.collision_grid, self.camera)
        self.player_health_ui = UIPlayerHealthBar(
            (20, self.camera.dimensions[1] - 30), self.fonts)

        self.tiled_level = TiledLevel(self.collision_grid,
                                      world_filling_number_of_grid_squares,
                                      self.moving_sprites_group,
                                      self.ui_sprites_group)
        self.editor = MapEditor(self.tiled_level, self.fonts,
                                self.collision_grid, self.camera)

        self.main_menu = MainMenu(self.fonts, self.camera)

        self.is_main_menu = True
        self.is_editor = False
        self.start_game = False

        self.gravity = 800.0
        self.clock = pygame.time.Clock()
        self.fps_counter = FPSCounter(self.fonts)
        self.running = True

    def run(self):
        while self.running:
            frame_time = self.clock.tick(60)
            time_delta = min(0.1, frame_time / 1000.0)

            # TODO: make these three states into state classes and use a state machine dictionary to switch between them
            if self.is_main_menu:
                is_main_menu_and_index = self.main_menu.run(self.screen)
                if is_main_menu_and_index[0] == 0:
                    self.is_main_menu = True
                elif is_main_menu_and_index[0] == 1:
                    self.is_main_menu = False
                    self.start_game = True
                    self.camera.reset_camera_tracking()
                    self.camera.position[0] = 316.0
                    self.camera.position[1] = 596.0
                    self.player.respawn()
                    self.tiled_level.reset_entities()
                elif is_main_menu_and_index[0] == 2:
                    self.is_main_menu = False
                    self.is_editor = True
                elif is_main_menu_and_index[0] == 3:
                    self.running = False

            elif self.is_editor:
                self.is_editor = self.editor.run(self.screen, self.background,
                                                 time_delta)
                if not self.is_editor:
                    self.is_main_menu = True
            else:
                for event in pygame.event.get():
                    if event.type == QUIT:
                        self.is_main_menu = True
                    if event.type == KEYDOWN:
                        if event.key == K_ESCAPE:
                            self.is_main_menu = True

                    self.player.process_events(event)

                if self.player.has_exited_level:
                    self.player.has_exited_level = False
                    self.is_main_menu = True

                self.camera.set_target_position(self.player.world_position)
                self.camera.update(time_delta)

                self.tiled_level.update(time_delta, self.camera)
                self.moving_sprites_group.update(time_delta, self.gravity,
                                                 self.camera)
                self.collision_grid.update_shape_grid_positions()
                self.collision_grid.check_collisions()

                self.screen.blit(self.background, (0, 0))
                self.tiled_level.draw_back_layers(self.screen)
                self.moving_sprites_group.draw(self.screen)
                self.tiled_level.draw_front_layers(self.screen)

                # draw the collision shapes
                # self.tiled_level.draw_collision_shapes(self.screen, self.camera)
                # self.player.draw_collision_shapes(self.screen, self.camera)
                # for sprite in self.moving_sprites_group:
                #    if sprite.type == "enemy":
                #        sprite.draw_debug_info(self.screen, self.camera)

                self.player_health_ui.update(self.player)
                self.player_health_ui.draw(self.screen)

                self.ui_sprites_group.update()
                self.ui_sprites_group.draw(self.screen)

                self.fps_counter.update(time_delta)
                self.fps_counter.draw(self.screen, self.camera)

            pygame.display.flip()
示例#4
0
class Game:
    def __init__(self):
        pg.init()
        pg.mixer.init()
        self.screen = pg.display.set_mode((WIDTH, HEIGHT))
        pg.display.set_caption(TITLE)
        self.clock = pg.time.Clock()
        self.running = True
        self.double_speed = False
        self.number_of_levels = 4

        self.navigator = Navigator(self)
        self.drawer = Drawer(self.screen)
        self.creator = Creator()

        self.init_player()
        self.init_sprite_lists()

        self.camera = Camera(self.player, self.creator.shiftable,
                             self.creator.texts)

        self.is_tutorial = False
        self.current_level = 0

    def init_sprite_lists(self):
        self.all_sprites = self.creator.all_sprites
        self.platform_list = self.creator.platforms
        self.tile_list = self.creator.tiles
        self.enemy_list = self.creator.enemies
        self.coin_list = self.creator.coins
        self.player.collide_list = self.creator.player_collide_list
        self.bullet_list = self.creator.bullets

    def init_player(self):
        self.player = self.creator.player
        self.player.weapon = Weapon(self.creator)

    def stop(self):
        self.playing = False
        self.running = False

    def new(self, level):
        """ Calls level or final level building and playing loop """
        self.current_level = level
        if level == self.number_of_levels - 1:
            self.creator.build_level_final(self.player)
            self.run()
        elif 0 <= level < self.number_of_levels - 1:
            self.creator.build_level(self.player)
            self.run()
        else:
            return

    def run(self):
        self.playing = True
        while self.playing:
            self.clock.tick(FPS)
            self.events()
            self.update()
            if self.playing:
                self.draw()

    def update(self):
        """ Handles screen updates """

        if self.player.hp <= 0:
            self.player.kill()
            self.navigator.show_go_screen()

        for coin in pg.sprite.spritecollide(self.player, self.coin_list,
                                            False):
            coin.kill()
            self.player.money += 30

        for enemy in pg.sprite.spritecollide(self.player, self.enemy_list,
                                             False):
            if abs(enemy.rect.x - self.player.rect.x) <= self.player.rect.width / 2 \
                    and self.player.rect.bottom == enemy.rect.bottom:
                self.player.receive_damage(1)

            if isinstance(enemy, AirEnemy) \
                    and abs(enemy.rect.x - self.player.rect.x) <= self.player.rect.width / 2 \
                    and abs(enemy.rect.y - self.player.rect.y) <= self.player.rect.height / 2:
                if not self.is_tutorial:
                    self.player.receive_damage(1)

            if isinstance(enemy, SlimeBlock) \
                    and abs(enemy.rect.x - self.player.rect.x) <= self.player.rect.width / 2 \
                    and abs(enemy.rect.y - self.player.rect.y) <= self.player.rect.height / 2:
                if not self.is_tutorial:
                    self.player.receive_damage(1)

        pg.sprite.groupcollide(self.bullet_list, self.platform_list, True,
                               False)
        pg.sprite.groupcollide(self.bullet_list, self.tile_list, True, False)

        collision_dict = pg.sprite.groupcollide(self.bullet_list,
                                                self.enemy_list, True, False)
        for bullet in collision_dict:
            for enemy in collision_dict[bullet]:
                enemy.hp -= bullet.damage

        self.all_sprites.update()
        self.camera.update()

    def events(self):
        """ Handles key events """
        for event in pg.event.get():
            if event.type == pg.QUIT:
                pg.quit()
                sys.exit()

            if event.type == pg.KEYDOWN:
                if event.key == pg.K_SPACE:
                    self.player.fire()

                if event.key == pg.K_LEFT:
                    if self.double_speed:
                        self.player.go_left_fast()
                    else:
                        self.player.go_left()
                if event.key == pg.K_RIGHT:
                    if self.double_speed:
                        self.player.go_right_fast()
                    else:
                        self.player.go_right()
                if event.key == pg.K_LSHIFT:
                    if not self.double_speed:
                        self.double_speed = True
                    else:
                        self.double_speed = False
                if event.key == pg.K_UP:
                    self.player.jump()

            if event.type == pg.KEYUP:
                if event.key == pg.K_LEFT and self.player.vel_x < 0:
                    self.player.stop()
                if event.key == pg.K_RIGHT and self.player.vel_x > 0:
                    self.player.stop()

        self.all_sprites.update()


        if abs((self.creator.right_wall.rect.x -
                self.creator.right_wall.rect.width / 2) -
               (self.player.rect.x + self.player.rect.width / 2)) <= 25:
            if self.is_tutorial:
                self.navigator.show_tutorial_done_screen()
            else:
                if self.current_level < self.number_of_levels - 1:
                    self.navigator.go_to_store()
                elif self.is_boss_level():
                    if not self.creator.boss.alive():
                        self.navigator.show_congrats_screen()

    def draw_stats_bar(self):
        self.drawer.draw_player_stats(self.player)

        if self.is_boss_level():
            self.drawer.draw_health_bar(
                self.creator.boss, 700, 20, 5)

    def draw(self):
        self.screen.fill(RED)
        self.draw_stats_bar()
        self.all_sprites.draw(self.screen)
        if self.is_tutorial:
            self.blit_texts()
        pg.display.flip()

    def blit_texts(self):
        for sf, rect in self.creator.texts:
            self.screen.blit(sf, rect.midtop)

    def reset(self):
        self.player.hp = 15
        self.player.money = 0
        self.running = True
        self.playing = True
        pass

    def tutorial(self):
        self.is_tutorial = True
        self.creator.build_tutorial_level(self.player, self.screen)
        self.run()

    def is_boss_level(self):
        if self.is_tutorial:
            return False
        return self.current_level == self.number_of_levels - 1