コード例 #1
0
ファイル: editor.py プロジェクト: Panurb/fightbattle
class Editor:
    def __init__(self):
        # init mixer first to prevent audio delay
        pygame.mixer.pre_init(44100, -16, 2, 2048)
        pygame.mixer.init()

        pygame.init()
        pygame.display.set_caption('NEXTGAME')

        self.option_handler = optionhandler.OptionHandler()

        mode = 0
        if self.option_handler.fullscreen:
            mode = pygame.FULLSCREEN

        self.screen = pygame.display.set_mode(self.option_handler.resolution,
                                              mode)

        self.image_handler = imagehandler.ImageHandler()
        self.input_handler = inputhandler.InputHandler()

        self.clock = pygame.time.Clock()
        self.time_step = 15.0 / self.option_handler.fps
        self.font = pygame.font.Font(None, 30)

        self.level = Level()

        self.grid_color = [150, 150, 150]

        self.wall_start = None
        self.grabbed_object = None
        self.grab_offset = np.zeros(2)
        self.object_types = ['wall', 'platform']
        self.type_index = 0

        self.camera = Camera([0, 0], self.option_handler.resolution)

    def main_loop(self):
        while not self.input_handler.quit:
            self.input_handler.update(self.camera)
            self.input()

            if self.grabbed_object is not None:
                w = self.grabbed_object.collider.half_width
                h = self.grabbed_object.collider.half_height
                pos = np.floor(self.input_handler.mouse_position +
                               self.grab_offset - np.floor(w) - np.floor(h))
                self.grabbed_object.set_position(pos + w + h)

            self.screen.fill((50, 50, 50))
            self.draw_grid(1.0)
            self.level.draw(self.screen, self.camera, self.image_handler)

            for p in self.level.player_spawns:
                p.draw(self.screen, self.camera, self.image_handler)

            self.draw_selection()

            type_str = self.font.render(self.object_types[self.type_index],
                                        True, self.image_handler.debug_color)
            self.screen.blit(type_str, (50, 50))

            pygame.display.update()
            self.clock.tick(self.option_handler.fps)

    def input(self):
        if self.input_handler.mouse_pressed[0]:
            for obj in self.level.walls + self.level.player_spawns + list(self.level.objects.values()) + \
                       [self.level.scoreboard]:
                if obj.collider.point_inside(
                        self.input_handler.mouse_position):
                    self.grabbed_object = obj
                    self.grab_offset = self.grabbed_object.position - self.input_handler.mouse_position
                    break
            else:
                self.wall_start = np.round(self.input_handler.mouse_position)

        if self.input_handler.mouse_released[0]:
            if self.grabbed_object is not None:
                if isinstance(self.grabbed_object, Weapon):
                    for obj in self.level.objects.values():
                        if type(obj) is Crate and obj.collider.point_inside(
                                self.input_handler.mouse_position):
                            obj.loot_list.append(type(obj))
                            del self.grabbed_object
                            break

                self.grabbed_object = None
            else:
                end = np.round(self.input_handler.mouse_position)
                pos = 0.5 * (self.wall_start + end)
                size = np.abs(end - self.wall_start)
                if np.all(size):
                    if self.type_index == 0:
                        self.level.add_wall(pos, size[0], size[1])
                    else:
                        self.level.add_platform(pos, size[0])
                self.wall_start = None

        if self.input_handler.mouse_down[1]:
            self.camera.position -= self.input_handler.mouse_change

        if self.input_handler.mouse_pressed[2]:
            for w in self.level.walls:
                if w.collider.point_inside(self.input_handler.mouse_position):
                    self.level.walls.remove(w)

            for w in self.level.player_spawns:
                if w.collider.point_inside(self.input_handler.mouse_position):
                    self.level.player_spawns.remove(w)

            for k in list(self.level.objects.keys()):
                if self.level.objects[k].collider.point_inside(
                        self.input_handler.mouse_position):
                    del self.level.objects[k]

        if self.input_handler.mouse_pressed[3]:
            self.camera.zoom *= 1.5

        if self.input_handler.mouse_pressed[4]:
            self.camera.zoom /= 1.5

        if self.input_handler.keys_pressed[pygame.K_s]:
            for i, o in enumerate(self.level.objects.values()):
                o.id = i

            with open('data/levels/lvl.pickle', 'wb') as f:
                pickle.dump(self.level.get_data(), f)

        if self.input_handler.keys_pressed[pygame.K_l]:
            with open('data/levels/lvl.pickle', 'rb') as f:
                data = pickle.load(f)
                self.level.clear()
                self.level.apply_data(data)

        if self.input_handler.keys_pressed[pygame.K_DELETE]:
            self.level.clear()

        if self.input_handler.keys_pressed[pygame.K_w]:
            if self.type_index == len(self.object_types) - 1:
                self.type_index = 0
            else:
                self.type_index += 1

        pos = np.floor(self.input_handler.mouse_position) + np.array(
            [0.5, 0.501])

        if self.input_handler.keys_pressed[pygame.K_p]:
            self.level.player_spawns.append(PlayerSpawn(pos))

        if self.input_handler.keys_pressed[pygame.K_c]:
            self.level.add_object(Crate(pos))

        if self.input_handler.keys_pressed[pygame.K_b]:
            self.level.add_object(Ball(pos))

        if self.input_handler.keys_pressed[pygame.K_g]:
            self.level.add_object(Shotgun(pos))

        if self.input_handler.keys_pressed[pygame.K_t]:
            self.level.walls.append(Basket(pos))

        if self.input_handler.keys_pressed[pygame.K_i]:
            self.level.scoreboard = Scoreboard(pos)

    def draw_grid(self, size):
        x_min = math.floor(self.camera.position[0] -
                           self.camera.half_width[0] / self.camera.zoom)
        x_max = math.ceil(self.camera.position[0] +
                          self.camera.half_width[0] / self.camera.zoom)
        y_min = math.floor(self.camera.position[1] -
                           self.camera.half_height[1] / self.camera.zoom)
        y_max = math.ceil(self.camera.position[1] +
                          self.camera.half_height[1] / self.camera.zoom)

        for x in np.linspace(x_min, x_max, int(abs(x_max - x_min) / size) + 1):
            if x % 5 == 0:
                width = 3
            else:
                width = 1
            pygame.draw.line(self.screen, self.grid_color,
                             self.camera.world_to_screen([x, y_min]),
                             self.camera.world_to_screen([x, y_max]), width)

        for y in np.linspace(y_min, y_max, int(abs(y_max - y_min) / size) + 1):
            if y % 5 == 0:
                width = 3
            else:
                width = 1
            pygame.draw.line(self.screen, self.grid_color,
                             self.camera.world_to_screen([x_min, y]),
                             self.camera.world_to_screen([x_max, y]), width)

    def draw_selection(self):
        if self.wall_start is not None:
            end = np.round(self.input_handler.mouse_position)
            size = self.camera.zoom * (end - self.wall_start)
            size[1] *= -1
            pos = self.camera.world_to_screen(self.wall_start)
            rect = pygame.rect.Rect(pos[0], pos[1], size[0], size[1])
            pygame.draw.rect(self.screen, [255, 255, 255], rect, 5)
コード例 #2
0
ファイル: gameloop.py プロジェクト: Panurb/fightbattle
class GameLoop:
    def __init__(self, option_handler):
        self.option_handler = option_handler
        self.state = State.MENU

        self.level = Level()
        self.players = dict()
        self.colliders = []

        self.time_scale = 1.0

        self.camera = Camera([0, 0], self.option_handler.resolution)

        self.respawn_time = 50.0

        self.menu = MainMenu()
        self.player_menus = [
            PlayerMenu((6 * i - 9) * basis(0)) for i in range(4)
        ]
        self.options_menu = OptionsMenu()
        self.options_menu.set_values(self.option_handler)

        self.network = None
        self.network_id = -1
        self.obj_id = -1

        self.controller_id = 0

    def load_level(self):
        self.level = Level('lvl')
        size = [
            int(self.camera.zoom * self.level.width),
            int(self.camera.zoom * self.level.height)
        ]
        self.level.background = pygame.Surface(size)
        self.level.background.fill((150, 150, 150))

        self.colliders.clear()

        self.colliders = [[[] for _ in range(int(self.level.height))]
                          for _ in range(int(self.level.width))]

        for wall in self.level.walls:
            wall.collider.update_occupied_squares(self.colliders)

        for obj in self.level.objects.values():
            obj.collider.update_occupied_squares(self.colliders)

    def reset_game(self):
        for w in self.level.walls:
            if type(w) is Basket:
                self.level.scoreboard.scores[w.team] = w.score

        for o in self.level.objects.values():
            if o.collider:
                o.collider.clear_occupied_squares(self.colliders)

        self.level.reset()

        for o in self.level.objects.values():
            o.collider.update_occupied_squares(self.colliders)

        for p in self.players.values():
            p.set_spawn(self.level, self.players)
            p.reset(self.colliders)

    def add_player(self, controller_id, network_id=-1):
        if network_id == -1:
            network_id = controller_id
        player = Player([0, 0], controller_id, network_id)
        self.players[network_id] = player

    def update(self, time_step):
        if self.state is State.PLAY:
            alive = 0
            for player in self.players.values():
                if player.active:
                    alive += 1

                player.update(self.level.gravity, self.time_scale * time_step,
                              self.colliders)

            if len(self.players) > 1 >= alive:
                self.reset_game()

            self.level.update(self.time_scale * time_step, self.colliders)

            for o in list(self.level.objects.values()):
                if type(o) is Ball and o.scored and o.speed < 0.1:
                    self.reset_game()

            self.camera.update(self.time_scale * time_step, self.players,
                               self.level)
        elif self.state is State.MENU:
            self.menu.update(time_step)
            self.state = self.menu.target_state
            self.menu.target_state = State.MENU

            if self.state is State.OPTIONS:
                self.option_handler.load()
                self.options_menu.set_values(self.option_handler)
        elif self.state is State.PLAYER_SELECT:
            if not self.players:
                return

            for pm in self.player_menus:
                if pm.controller_id is not None:
                    # FIXME: hardcoded index
                    self.players[pm.controller_id].body_type = pm.buttons[
                        1].get_value()
                    self.players[pm.controller_id].head_type = pm.buttons[
                        0].get_value()

            for pm in self.player_menus:
                if pm.controller_id is None:
                    if pm.controller_id in self.players:
                        del self.players[pm.controller_id]

                if pm.target_state is State.MENU:
                    pm.target_state = State.PLAYER_SELECT
                    self.state = State.MENU
                    self.players.clear()
                    return

                if pm.controller_id is not None and pm.target_state is State.PLAYER_SELECT:
                    return

            self.state = State.PLAY
            self.load_level()
            for p in self.players.values():
                p.set_spawn(self.level, self.players)
                p.reset(self.colliders)
        elif self.state is State.LAN:
            if self.network is None:
                self.network = Network()
                data = self.network.data

                if data is None:
                    print('Server can not be reached')
                    self.network = None
                    self.state = State.MENU
                    return

                self.network_id = data[0][0]

                self.add_player(self.controller_id, data[0][0])
                self.players[data[0][0]].apply_data(data[0])

                self.level.clear()
                self.level.apply_data(data[1])

                self.colliders = [[[]
                                   for _ in range(int(self.level.height + 1))]
                                  for _ in range(int(self.level.width + 1))]

                for wall in self.level.walls:
                    wall.collider.update_occupied_squares(self.colliders)

                for obj in self.level.objects.values():
                    obj.collider.update_occupied_squares(self.colliders)

                start_new_thread(self.network_thread, ())

            player = self.players[self.network_id]
            player.update(self.level.gravity, self.time_scale * time_step,
                          self.colliders)

            obj = self.players[self.network_id].object
            if obj is not None:
                obj.update(self.level.gravity, self.time_scale * time_step,
                           self.colliders)

            self.camera.update(time_step, self.players, self.level)

            for i in list(self.level.objects):
                obj = self.level.objects[i]
                if isinstance(obj, Destroyable):
                    obj.update(self.level.gravity, self.time_scale * time_step,
                               self.colliders)
                    if obj.destroyed and not obj.debris:
                        del self.level.objects[i]
                elif isinstance(obj, Bullet):
                    obj.update(self.level.gravity, self.time_scale * time_step,
                               self.colliders)
                    if obj.destroyed and not obj.particle_clouds:
                        del self.level.objects[i]
        elif self.state is State.OPTIONS:
            self.state = self.options_menu.target_state
            self.options_menu.target_state = State.OPTIONS

            if self.options_menu.options_changed:
                if self.options_menu.buttons[0].get_value() == 'windowed':
                    pygame.display.set_mode(
                        self.options_menu.buttons[1].get_value())
                    self.option_handler.fullscreen = False
                else:
                    pygame.display.set_mode(
                        self.options_menu.buttons[1].get_value(),
                        pygame.FULLSCREEN)
                    self.option_handler.fullscreen = True

                self.camera.set_resolution(
                    self.options_menu.buttons[1].get_value())

                self.option_handler.resolution = self.options_menu.buttons[
                    1].get_value()

                self.option_handler.shadows = self.options_menu.buttons[
                    4].get_value() == 'ON'

                self.option_handler.save()

                self.options_menu.options_changed = False

    def network_thread(self):
        while True:
            data = [self.players[self.network_id].get_data()]

            if self.obj_id != -1:
                data.append(self.level.objects[self.obj_id].get_data())
                self.level.objects[self.obj_id].attacked = False

            data = self.network.send(data)

            for p in data[0]:
                if p[0] == self.network_id:
                    player = self.players[self.network_id]
                    if player.health <= 0 < p[9]:
                        player.set_spawn(self.level, self.players)
                        player.reset(self.colliders)
                    player.health = p[9]
                else:
                    if p[0] not in self.players:
                        self.add_player(-1, p[0])

                    self.players[p[0]].apply_data(p)

            # kinda purkka
            ids = [p[0] for p in data[0]]
            for k in list(self.players.keys()):
                if k != self.network_id and k not in ids:
                    del self.players[k]

            for d in data[1]:
                if d[0] == self.obj_id:
                    continue

                if d[0] in self.level.objects:
                    self.level.objects[d[0]].apply_data(d)
                else:
                    obj = d[1]([d[2], d[3]])
                    obj.apply_data(d)
                    self.level.objects[d[0]] = obj
                    self.colliders[obj.collider.group].append(obj.collider)

            ids = [o[0] for o in data[1]]
            for i in list(self.level.objects):
                obj = self.level.objects[i]
                obj.collider.update_occupied_squares(self.colliders)
                if i not in ids:
                    if isinstance(obj, Destroyable):
                        obj.destroy(self.colliders)
                    elif isinstance(obj, Bullet):
                        obj.destroy()

    def input(self, input_handler):
        input_handler.update(self.camera)

        if input_handler.quit:
            self.state = State.QUIT

        if self.state is State.PLAY:
            if 0 in self.players:
                input_handler.relative_mouse[:] = input_handler.mouse_position - self.players[
                    0].shoulder

            for i, player in enumerate(self.players.values()):
                player.input(input_handler)

            if input_handler.keys_pressed[pygame.K_r]:
                self.reset_game()
        elif self.state is State.MENU:
            self.menu.input(input_handler)
            for i in range(len(input_handler.controllers)):
                if self.menu.selection_moved[i]:
                    self.controller_id = i
                    break
        elif self.state is State.PLAYER_SELECT:
            for i, controller in enumerate(input_handler.controllers):
                for pm in self.player_menus:
                    if pm.controller_id == i:
                        pm.input(input_handler, i)
                        break
                else:
                    for pm in self.player_menus:
                        if pm.controller_id is None:
                            pm.input(input_handler, i)
                        if pm.controller_id == i:
                            self.add_player(i)
                            break

            if all(pm.target_state is State.PLAYER_SELECT
                   for pm in self.player_menus):
                for i, controller in enumerate(input_handler.controllers):
                    if controller.button_down['B']:
                        self.state = State.MENU
        elif self.state is State.LAN:
            if self.network is not None:
                player = self.players[self.network_id]

                input_handler.relative_mouse[:] = input_handler.mouse_position - player.shoulder

                self.obj_id = player.object.id if player.object is not None else -1

                player.input(input_handler)
        elif self.state is State.OPTIONS:
            self.options_menu.input(input_handler)

    def draw(self, screen, image_handler):
        if self.state in [State.PLAY, State.LAN]:
            screen.fill((0, 0, 0))
            screen.blit(
                self.level.background,
                self.camera.world_to_screen(np.array([0, self.level.height])))

            if self.option_handler.shadows:
                self.level.draw_shadow(screen, self.camera, image_handler)
                for p in self.players.values():
                    p.draw_shadow(screen, self.camera, image_handler,
                                  self.level.light)

            self.level.draw(screen, self.camera, image_handler)

            for player in self.players.values():
                player.draw(screen, self.camera, image_handler)

            if self.option_handler.debug_draw:
                self.debug_draw(screen, image_handler)
        elif self.state is State.MENU:
            screen.fill((50, 50, 50))
            self.menu.draw(screen, self.camera, image_handler)
        elif self.state is State.PLAYER_SELECT:
            screen.fill((50, 50, 50))
            for pm in self.player_menus:
                pm.draw(screen, self.camera, image_handler)
                if pm.controller_id is not None:
                    self.players[pm.controller_id].set_position(pm.position +
                                                                3 * basis(1))
                    self.players[pm.controller_id].on_ground = True
                    self.players[pm.controller_id].animate(0.0)
                    self.players[pm.controller_id].draw(
                        screen, self.camera, image_handler)
        elif self.state is State.OPTIONS:
            screen.fill((50, 50, 50))
            self.options_menu.draw(screen, self.camera, image_handler)

    def debug_draw(self, screen, image_handler):
        for player in self.players.values():
            player.debug_draw(screen, self.camera, image_handler)

        self.level.debug_draw(screen, self.camera, image_handler)

    def play_sounds(self, sound_handler):
        if self.state in [State.PLAY, State.LAN]:
            for p in self.players.values():
                p.play_sounds(sound_handler)

            self.level.play_sounds(sound_handler)
        elif self.state is State.OPTIONS:
            sound_handler.set_volume(self.options_menu.buttons[2].get_value())
            sound_handler.set_music_volume(
                self.options_menu.buttons[3].get_value())

            self.option_handler.sfx_volume = self.options_menu.buttons[
                2].get_value()
            self.option_handler.music_volume = self.options_menu.buttons[
                3].get_value()
            self.option_handler.save()

            self.menu.play_sounds(sound_handler)
            self.options_menu.play_sounds(sound_handler)
        else:
            self.menu.play_sounds(sound_handler)
            self.options_menu.play_sounds(sound_handler)
            for pm in self.player_menus:
                pm.play_sounds(sound_handler)