Example #1
0
class MyGame(arcade.Window):

    def __init__(self, width, height, title):
        """
        Set up the application.
        """
        super().__init__(width, height, title)
        self.time = 0
        self.frame = 0
        self.background = arcade.load_texture(":resources:images/backgrounds/abstract_1.jpg")

        self.light_layer = LightLayer(SCREEN_WIDTH, SCREEN_HEIGHT)
        self.light_layer.set_background_color(arcade.color.WHITE)
        # Add some random lights
        for _ in range(500):
            self.light_layer.add(
                Light(
                    random.randrange(0, SCREEN_WIDTH),
                    random.randrange(0, SCREEN_HEIGHT),
                    radius=50,
                    mode='soft',
                    color=(random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
                ),
            )

    def on_draw(self):
        arcade.start_render()

        # Everything that should be affected by lights in here
        with self.light_layer:
            # The light layer is just cleared using the background color here (white)
            pass

        # Draw the contents with lighting
        self.light_layer.draw()

        # image = arcade.get_image()
        # image.save(f'screenshots/frame{str(self.frame).zfill(3)}.png', 'png')

    def on_update(self, dt):
        # dt = 0.1
        self.frame += 1
        try:
            self.time += dt
            for i, light in enumerate(self.light_layer):
                light.radius = 20 + math.sin(self.time + i) * 40
        except Exception as e:
            print(e)

    def on_resize(self, width, height):
        arcade.set_viewport(0, width, 0, height)
        self.light_layer.resize(width, height)
Example #2
0
class Game(arcade.Window):
    def __init__(self):
        super(Game, self).__init__(SW, SH, "Adventure Dungeon")
        map = arcade.tilemap.read_tmx("resources/dungeon.tmx")

        # process each layer from tilemap and create a spritelist from it
        self.ground_list = arcade.tilemap.process_layer(map, "floor", scaling=SCALE)
        self.wall_list = arcade.tilemap.process_layer(map, "walls", scaling=SCALE)
        self.background = arcade.tilemap.process_layer(map, "bg", scaling=SCALE)
        self.doors = arcade.tilemap.process_layer(map, "doors", scaling=SCALE)
        self.light_list = arcade.tilemap.process_layer(map, "lit_lights", scaling=SCALE)
        self.perma_torches = arcade.tilemap.process_layer(map, "perma_lights", scaling=SCALE)
        self.unlit_lights = arcade.tilemap.process_layer(map, "unlit_lights", scaling=SCALE)
        self.chests = arcade.tilemap.process_layer(map, "chests", scaling=SCALE)
        self.decor = arcade.tilemap.process_layer(map, "decor", scaling=SCALE)

        # viewport scroll manager
        self.scroll_manager = screen_scroll.ScrollManager(self)

        # create the player
        self.player = player_sprite.Player(2816*SCALE, 192*SCALE, SCALE, player_sprite.Inventory(10))
        # initialize control values
        self.controls = {'w': MOVEMENT_SPEED, 'a': -MOVEMENT_SPEED, 's': -MOVEMENT_SPEED, 'd': MOVEMENT_SPEED}
        self.keys_pressed = []
        # mouse position
        self.mouse_pos = 0
        # scroll margin (how close player needs to be to the edge of view for it to scroll)
        margin_lr = SW/2 - self.player.width/2
        margin_tb = SH/2 - self.player.height/2
        # set the margins
        self.scroll_manager.set_view_change_margins(right=margin_lr, left=margin_lr, top=margin_tb, bottom=margin_tb)
        # set the initial view
        self.scroll_manager.set_view("right", 2208)
        self.scroll_manager.set_view("left", 2208 - SW)
        self.scroll_manager.set_view("bottom", self.player.center_y - (SH/2))
        self.scroll_manager.set_view("top", self.player.center_y + (SH/2))

        self.hit_wall = False
        # create physics engine
        self.physics_engine = arcade.PhysicsEngineSimple(self.player, self.wall_list)
        self.light_index = 0
        # self.textures = arcade.load_spritesheet("resources/dungeon_sprites.png", 16, 16, 16, 72)
        # print(len(self.textures))

        # for lighting
        self.light_layer = None
        self.player_light = None
        self.torches = {}
        self.text = Dialogue("Welcome to Adventure Game!", delay=3)
        self.candle = None
        self.candle_light = None
        self.start_time = time.time()

        candle = items.Candle(self.player.right, self.player.center_y, .5, False)
        self.player.set_candle(candle)

        # generate loot
        self.room_loot = backend.gen_loot()
        self.show_text = False

        # inv show
        self.show_inv = False
        self.setup()

    def setup(self):
        # create the light layer (width and height of screen)
        self.light_layer = LightLayer(SW, SH)
        # set background color
        self.light_layer.set_background_color(arcade.color.BLACK)

        # create the player light
        radius = 100 * SCALE
        mode = 'soft'
        color = arcade.csscolor.WHITE
        self.player_light = Light(0, 0, radius, color, mode)
        # add the light layer
        self.light_layer.add(self.player_light)
        # create a light for each torch
        for torch in self.light_list:
            light = TorchLight(torch.center_x, torch.center_y, TORCH_RADIUS)
            self.light_layer.add(light)
            self.torches[torch] = light
        # lighting for torches that cant be unlit
        for torch in self.perma_torches:
            light = TorchLight(torch.center_x, torch.center_y, TORCH_RADIUS)
            self.light_layer.add(light)
            self.torches[torch] = light


        # add loot to chests
        loot = []
        for room in self.room_loot:
            loot += room
        for chest, loot in zip(self.chests, loot):
            chest.loot = loot



    def on_draw(self):
        arcade.start_render()
        # draw background (but dont illuminate it)
        self.background.draw()
        # draw all the sprites in light layer (lighting will illuminate them)
        with self.light_layer:
            self.ground_list.draw()
            self.doors.draw()
            self.wall_list.draw()
            self.chests.draw()
            self.decor.draw()
            self.player.draw()
            self.light_list.draw()
            self.unlit_lights.draw()
            self.perma_torches.draw()

        # draw the actual light layer
        self.light_layer.draw(ambient_color=AMBIENT_COLOR)


        if self.candle:
            fuel_len = self.candle.fuel_level / 2
            if self.candle_light.radius > 1:
                # draw the candle fuel bar above player
                arcade.draw_lrtb_rectangle_filled(self.player.left, self.player.left + fuel_len + 1, self.player.top + 10, self.player.top + 5, (255, 213, 105))
        # draw tutorial text for the first 5 seconds after startup
        if time.time() - self.start_time < 5:
            x = self.scroll_manager.get_view('right')
            y = self.scroll_manager.get_view('bottom')
            arcade.draw_text("press 'space' to toggle your candle", x - (SW / 2), y + 225, arcade.color.CREAM, 20,
                             anchor_x='center')
            arcade.draw_text("press 'q' to toggle torches on the wall (some torches can't be toggled)", x - (SW / 2), y + 250,
                             arcade.color.CREAM, 20, anchor_x='center')

        # show dialogue text
        if self.show_text:
            x = self.scroll_manager.get_view('right')
            y = self.scroll_manager.get_view('bottom')
            arcade.draw_text(self.text.output(), x - (SW/2), y + 200, arcade.color.CREAM, 20, anchor_x='center', align='center')

        if self.show_inv:
            inv_text = self.player.inv.display()
            leng = self.player.inv.get_len() * 20
            top = self.player.center_y + leng/2
            bottom = self.player.center_y - leng/2
            # ban = arcade.Sprite("resources/sprites/Dungeon_Tileset/sprite_074.png", self.player.right + 10, self.player.center_y, image_height=leng, image_width=150)
            # ban.draw()
            arcade.draw_lrtb_rectangle_filled(self.player.right + 10, self.player.center_x + 200, top, bottom, (118, 74, 45))
            arcade.draw_text(inv_text, self.player.right + 15, self.player.center_y, (255, 253, 208, 200), 11,
                             anchor_x='left', anchor_y='center', align='left', font_name='Chalkboard')




    def on_update(self, delta_time: float):
        # update physics engine
        self.physics_engine.update()
        self.decor.update_animation()
        if self.player.holding_candle:
            self.candle.update()
            # calculate ratio of remaining fuel
            fuel_ratio = self.candle.fuel_level / 100
            # set light radius progressively smaller as fuel runs out
            if fuel_ratio < .5:
                self.candle_light.radius = CANDLE_RADI[int(self.light_index)] - ((400 - (400 * fuel_ratio))/5)
            else:
                self.candle_light.radius = CANDLE_RADI[int(self.light_index)]
            # change candle position based on player direction
            if self.player.direction == 1:
                self.player.candle.position = self.player.right, self.player.center_y
            else:
                self.player.candle.position = self.player.left, self.player.center_y
            # set the position of light object equal to candles position
            self.candle_light.position = self.candle.position
            # if the candle runs out of fuel, disable it and re-enable players light source
            if self.candle.fuel_level <= 0:
                self.candle_light.radius = 0
                self.player_light.radius = 100

        # make player light follow
        self.player_light.position = self.player.position
        # update screen view
        self.scroll_manager.update()
        # vary the light radius of torches to simulate real fire
        for light in self.torches.values():
            light.radius = TORCH_RADI[int(self.light_index)]
        # increase light index by .1. only whole number indexes so every
        # 10 frames it will increase by a whole number and update
        self.light_index += .1
        if self.light_index >= len(TORCH_RADI):
            self.light_index = 0
        self.perma_torches.update_animation()
        self.light_list.update_animation()
        # update
        self.player.update()
        # update keys
        self.key_change()
        # advance dialogue text\
        if self.text:
            self.text.advance()


    # movement system
    def key_change(self):
        v_keys = 0
        h_keys = 0
        if self.keys_pressed:
            for key in self.keys_pressed:
                if key in 'ws':
                    self.player.move_y(self.controls[key])
                    v_keys += 1
                elif key in 'ad':
                    h_keys += 1
                    self.player.move_x(self.controls[key])
            if not v_keys:
                self.player.move_y(0)
            elif not h_keys:
                self.player.move_x(0)
        else:
            self.player.move_x(0)
            self.player.move_y(0)


    def on_mouse_press(self, x: float, y: float, button: int, modifiers: int):
        light = arcade.get_sprites_at_point((x, y), self.unlit_lights)
        # if light:


    def on_mouse_release(self, x: float, y: float, button: int,
                         modifiers: int):
        pass

    def on_key_press(self, symbol: int, modifiers: int):
        global SCALE

        key = chr(symbol)
        # if key in movement controls add to keys pressed
        if key in list(self.controls.keys()):
            self.keys_pressed.append(key)
        elif key == 'q':  # toggle torches on the wall on/off
            if not self.loot_chest():
                self.toggle_torch()

        elif key == 'e':
            if self.show_inv:
                self.show_inv = False
            else:
                self.show_inv = True

        elif symbol == arcade.key.SPACE and self.show_text:
            self.show_text = False
            self.text = None

        elif key == 'm':
            print("mouse_pos:", self.mouse_pos)
            print("playerpos:", self.player.position)
            self.scroll_manager.output_values()

        # toggle the players candle
        elif symbol == arcade.key.SPACE:
            # if the player is holding a candle, toggle it off
            if self.player.holding_candle:
                self.player.toggle_candle()  # toggle
                self.light_layer.remove(self.candle_light)  # remove light source
                self.perma_torches.remove(self.candle)  # remove from torches (it will not draw anymore)
                self.player_light.radius = 100 * SCALE # re-enable player default light
                self.candle = None  # set candle to None
            # if player isn't holding candle, toggle it on
            else:
                # toggle
                self.player.toggle_candle()
                # create lightsource object

                light = Light(self.player.candle.center_x, self.player.candle.center_y, 400 * SCALE, TORCH_LIGHT, 'soft')
                self.perma_torches.append(self.player.candle)  # add player candle to perma_torches (cant be toggled by pressing q)
                self.candle = self.player.candle  # set the candle to the players candle
                self.candle_light = light  # set candle light to light object
                self.player_light.radius = 0  # disable the players default light
                self.light_layer.add(self.candle_light)  # add light source to light layer

        self.key_change()

    def loot_chest(self):
        # get closest chest sprite
        chest = arcade.get_closest_sprite(self.player, self.chests)
        dist = chest[1]
        chest = chest[0]
        # if the chest is within range, loot it and display the contents
        if dist < ACTION_RANGE:
            item = chest.loot
            if item:
                # set show text to true and create new dialogue object
                self.show_text = True
                self.text = Dialogue(self.player.collect(item),'\n', item.description, delay=3)
                chest.loot = None
                return True
            else:
                # loot can only be found once
                self.show_text = True
                self.text = Dialogue(f"You already found the loot in this chest.")


    def toggle_torch(self):
        # get closest unlit torch
        unlit_torch = arcade.get_closest_sprite(self.player, self.unlit_lights)
        dist = unlit_torch[1]
        unlit_torch = unlit_torch[0]
        # if torch is within action range, turn it on
        if dist < ACTION_RANGE:
            # create new lit torch to replace unlit torch
            new_torch = items.Torch(unlit_torch.center_x, unlit_torch.center_y, SCALE)
            # get rid of unlit torch
            unlit_torch.kill()
            # add torch to list of torches
            self.light_list.append(new_torch)
            # create a new light source and assign it to the torch
            light = Light(new_torch.center_x, new_torch.center_y, TORCH_RADIUS, TORCH_LIGHT, 'soft')
            self.torches[new_torch] = light
            self.light_layer.add(light)
        else:
            lit_torch = arcade.get_closest_sprite(self.player, self.light_list)
            dist = lit_torch[1]
            lit_torch = lit_torch[0]
            # self.torches.pop(lit_torch)
            # if there isnt an unlit torch in range, but there is a lit torch, turn it off
            if dist < ACTION_RANGE:
                # make new unlit torch
                new_torch = items.UnlitTorch(lit_torch.center_x, lit_torch.center_y, SCALE)
                # get rid of light source
                light = self.torches[lit_torch]
                self.light_layer.remove(light)
                # get rid of lit torch and add unlit torch
                lit_torch.kill()
                self.unlit_lights.append(new_torch)


    def on_key_release(self, symbol: int, modifiers: int):
        key = chr(symbol)
        if key in self.keys_pressed:
            self.keys_pressed.remove(key)

        self.key_change()

    def on_mouse_motion(self, x: float, y: float, dx: float, dy: float):
        self.mouse_pos = (x, y)


        pass
class MyGame(arcade.Window):
    """ Main Game Window """
    def __init__(self, width, height, title):
        """ Set up the class. """
        super().__init__(width, height, title, resizable=True)

        # Sprite lists
        self.background_sprite_list = None
        self.player_list = None
        self.wall_list = None
        self.player_sprite = None

        # Physics engine
        self.physics_engine = None

        # Used for scrolling
        self.view_left = 0
        self.view_bottom = 0

        # --- Light related ---
        # List of all the lights
        self.light_layer = None
        # Individual light we move with player, and turn on/off
        self.player_light = None

    def setup(self):
        """ Create everything """

        # Create sprite lists
        self.background_sprite_list = arcade.SpriteList()
        self.player_list = arcade.SpriteList()
        self.wall_list = arcade.SpriteList()

        # Create player sprite
        self.player_sprite = arcade.Sprite(
            ":resources:images/animated_characters/female_person/femalePerson_idle.png",
            0.4)
        self.player_sprite.center_x = 64
        self.player_sprite.center_y = 270
        self.player_list.append(self.player_sprite)

        # --- Light related ---
        # Lights must shine on something. If there is no background sprite or color,
        # you will just see black. Therefore, we use a loop to create a whole bunch of brick tiles to go in the
        # background.
        for x in range(-128, 2000, 128):
            for y in range(-128, 1000, 128):
                sprite = arcade.Sprite(
                    ":resources:images/tiles/brickTextureWhite.png")
                sprite.position = x, y
                self.background_sprite_list.append(sprite)

        # Create a light layer, used to render things to, then post-process and
        # add lights. This must match the screen size.
        self.light_layer = LightLayer(SCREEN_WIDTH, SCREEN_HEIGHT)
        # We can also set the background color that will be lit by lights,
        # but in this instance we just want a black background
        self.light_layer.set_background_color(arcade.color.BLACK)

        # Here we create a bunch of lights.

        # Create a small white light
        x = 100
        y = 200
        radius = 100
        mode = 'soft'
        color = arcade.csscolor.WHITE
        light = Light(x, y, radius, color, mode)
        self.light_layer.add(light)

        # Create an overlapping, large white light
        x = 300
        y = 150
        radius = 200
        color = arcade.csscolor.WHITE
        mode = 'soft'
        light = Light(x, y, radius, color, mode)
        self.light_layer.add(light)

        # Create three, non-overlapping RGB lights
        x = 50
        y = 450
        radius = 100
        mode = 'soft'
        color = arcade.csscolor.RED
        light = Light(x, y, radius, color, mode)
        self.light_layer.add(light)

        x = 250
        y = 450
        radius = 100
        mode = 'soft'
        color = arcade.csscolor.GREEN
        light = Light(x, y, radius, color, mode)
        self.light_layer.add(light)

        x = 450
        y = 450
        radius = 100
        mode = 'soft'
        color = arcade.csscolor.BLUE
        light = Light(x, y, radius, color, mode)
        self.light_layer.add(light)

        # Create three, overlapping RGB lights
        x = 650
        y = 450
        radius = 100
        mode = 'soft'
        color = arcade.csscolor.RED
        light = Light(x, y, radius, color, mode)
        self.light_layer.add(light)

        x = 750
        y = 450
        radius = 100
        mode = 'soft'
        color = arcade.csscolor.GREEN
        light = Light(x, y, radius, color, mode)
        self.light_layer.add(light)

        x = 850
        y = 450
        radius = 100
        mode = 'soft'
        color = arcade.csscolor.BLUE
        light = Light(x, y, radius, color, mode)
        self.light_layer.add(light)

        # Create three, overlapping RGB lights
        # But 'hard' lights that don't fade out.
        x = 650
        y = 150
        radius = 100
        mode = 'hard'
        color = arcade.csscolor.RED
        light = Light(x, y, radius, color, mode)
        self.light_layer.add(light)

        x = 750
        y = 150
        radius = 100
        mode = 'hard'
        color = arcade.csscolor.GREEN
        light = Light(x, y, radius, color, mode)
        self.light_layer.add(light)

        x = 850
        y = 150
        radius = 100
        mode = 'hard'
        color = arcade.csscolor.BLUE
        light = Light(x, y, radius, color, mode)
        self.light_layer.add(light)

        # Create a light to follow the player around.
        # We'll position it later, when the player moves.
        # We'll only add it to the light layer when the player turns the light
        # on. We start with the light off.
        radius = 150
        mode = 'soft'
        color = arcade.csscolor.WHITE
        self.player_light = Light(0, 0, radius, color, mode)

        # Create the physics engine
        self.physics_engine = arcade.PhysicsEngineSimple(
            self.player_sprite, self.wall_list)

        # Set the viewport boundaries
        # These numbers set where we have 'scrolled' to.
        self.view_left = 0
        self.view_bottom = 0

    def on_draw(self):
        """ Draw everything. """
        arcade.start_render()

        # --- Light related ---
        # Everything that should be affected by lights gets rendered inside this
        # 'with' statement. Nothing is rendered to the screen yet, just the light
        # layer.
        with self.light_layer:
            self.background_sprite_list.draw()
            self.player_list.draw()

        # Draw the light layer to the screen.
        # This fills the entire screen with the lit version
        # of what we drew into the light layer above.
        self.light_layer.draw(ambient_color=AMBIENT_COLOR)

        # Now draw anything that should NOT be affected by lighting.
        arcade.draw_text("Press SPACE to turn character light on/off.",
                         10 + self.view_left, 10 + self.view_bottom,
                         arcade.color.WHITE, 20)

    def on_resize(self, width, height):
        """ User resizes the screen. """

        # --- Light related ---
        # We need to resize the light layer to
        self.light_layer.resize(width, height)

        # Scroll the screen so the user is visible
        self.scroll_screen()

    def on_key_press(self, key, _):
        """Called whenever a key is pressed. """

        if key == arcade.key.UP:
            self.player_sprite.change_y = MOVEMENT_SPEED
        elif key == arcade.key.DOWN:
            self.player_sprite.change_y = -MOVEMENT_SPEED
        elif key == arcade.key.LEFT:
            self.player_sprite.change_x = -MOVEMENT_SPEED
        elif key == arcade.key.RIGHT:
            self.player_sprite.change_x = MOVEMENT_SPEED
        elif key == arcade.key.SPACE:
            # --- Light related ---
            # We can add/remove lights from the light layer. If they aren't
            # in the light layer, the light is off.
            if self.player_light in self.light_layer:
                self.light_layer.remove(self.player_light)
            else:
                self.light_layer.add(self.player_light)

    def on_key_release(self, key, _):
        """Called when the user releases a key. """

        if key == arcade.key.UP or key == arcade.key.DOWN:
            self.player_sprite.change_y = 0
        elif key == arcade.key.LEFT or key == arcade.key.RIGHT:
            self.player_sprite.change_x = 0

    def scroll_screen(self):
        """ Manage Scrolling """

        # Scroll left
        left_boundary = self.view_left + VIEWPORT_MARGIN
        if self.player_sprite.left < left_boundary:
            self.view_left -= left_boundary - self.player_sprite.left

        # Scroll right
        right_boundary = self.view_left + self.width - VIEWPORT_MARGIN
        if self.player_sprite.right > right_boundary:
            self.view_left += self.player_sprite.right - right_boundary

        # Scroll up
        top_boundary = self.view_bottom + self.height - VIEWPORT_MARGIN
        if self.player_sprite.top > top_boundary:
            self.view_bottom += self.player_sprite.top - top_boundary

        # Scroll down
        bottom_boundary = self.view_bottom + VIEWPORT_MARGIN
        if self.player_sprite.bottom < bottom_boundary:
            self.view_bottom -= bottom_boundary - self.player_sprite.bottom

        # Make sure our boundaries are integer values. While the viewport does
        # support floating point numbers, for this application we want every pixel
        # in the view port to map directly onto a pixel on the screen. We don't want
        # any rounding errors.
        self.view_left = int(self.view_left)
        self.view_bottom = int(self.view_bottom)

        arcade.set_viewport(self.view_left, self.width + self.view_left,
                            self.view_bottom, self.height + self.view_bottom)

    def on_update(self, delta_time):
        """ Movement and game logic """

        # Call update on all sprites (The sprites don't do much in this
        # example though.)
        self.physics_engine.update()

        # --- Light related ---
        # We can easily move the light by setting the position,
        # or by center_x, center_y.
        self.player_light.position = self.player_sprite.position

        # Scroll the screen so we can see the player
        self.scroll_screen()
Example #4
0
class MyGame(arcade.Window):
    """ Main application class. """
    def __init__(self):
        """ Initializer """
        # Call the parent class initializer
        super().__init__(SCREEN_WIDTH,
                         SCREEN_HEIGHT,
                         SCREEN_TITLE,
                         fullscreen=False)

        # Set the working directory (where we expect to find files) to the same
        # directory this .py file is in. You can leave this out of your own
        # code, but it is needed to easily run the examples using "python -m"
        # as mentioned at the top of this program.
        file_path = os.path.dirname(os.path.abspath(__file__))
        os.chdir(file_path)

        # Variables that will hold sprite lists
        self.player_list = None
        self.coin_list = None
        self.bullet_list = None
        self.explosions_list = None
        self.wall_list = None

        # Set up the player info
        self.player = None
        self.score = 0

        self.can_move = True

        self.light_layer = None
        self.player_light = None
        self.player_radius = 200

        # Pre-load the animation frames. We don't do this in the __init__
        # of the explosion sprite because it
        # takes too long and would cause the game to pause.
        self.explosion_texture_list = []

        columns = 16
        count = 60
        sprite_width = 256
        sprite_height = 256
        file_name = ":resources:images/spritesheets/explosion.png"

        # Load the explosions from a sprite sheet
        self.explosion_texture_list = arcade.load_spritesheet(
            file_name, sprite_width, sprite_height, columns, count)

        # Load sounds. Sounds from kenney.nl
        self.gun_sound = arcade.sound.load_sound(
            ":resources:sounds/laser2.wav")
        self.hit_sound = arcade.sound.load_sound(
            ":resources:sounds/explosion2.wav")

        self.a_down = False
        self.d_down = False
        self.s_down = False
        self.w_down = False

        self.VIEW_LEFT = 0 - (SCREEN_WIDTH / 2)
        self.VIEW_BOT = 0 - (SCREEN_HEIGHT / 2)

    def setup(self):
        """ Set up the game and initialize the variables. """

        # Sprite lists
        self.player_list = arcade.SpriteList()
        self.coin_list = arcade.SpriteList()
        self.bullet_list = arcade.SpriteList()
        self.explosions_list = arcade.SpriteList()
        self.wall_list = maps.create_walls()

        # Set up the player
        self.score = 0

        # Image from kenney.nl
        self.player = player.PlayerCharacter()
        self.player.center_x = 0
        self.player.center_y = 0
        self.player_list.append(self.player)
        self.physics_engine = arcade.PhysicsEngineSimple(
            self.player, self.wall_list)

        # Create the coins
        for coin_index in range(COIN_COUNT):

            # Create the coin instance
            # Coin image from kenney.nl
            coin = arcade.Sprite(":resources:images/items/coinGold.png",
                                 SPRITE_SCALING_COIN)

            # Position the coin
            coin.center_x = random.randrange(SCREEN_WIDTH)
            coin.center_y = random.randrange(150, SCREEN_HEIGHT)

            # Add the coin to the lists
            self.coin_list.append(coin)

        # Set the background color
        #arcade.set_background_color(arcade.color.CELESTIAL_BLUE)

        # Lighting
        self.light_layer = LightLayer(SCREEN_WIDTH, SCREEN_HEIGHT)
        self.light_layer.set_background_color(arcade.color.CELESTIAL_BLUE)

        # Player lighting
        self.player_light = Light(0, 0, self.player_radius,
                                  arcade.csscolor.WHITE, 'soft')
        self.light_layer.add(self.player_light)

    def on_key_press(self, key, modifiers):
        if not self.can_move:
            return

        if key == arcade.key.A:
            self.a_down = True
            self.player.change_x = -PLAYER_SPEED
        elif key == arcade.key.D:
            self.d_down = True
            self.player.change_x = PLAYER_SPEED
        elif key == arcade.key.S:
            self.s_down = True
            self.player.change_y = -PLAYER_SPEED
        elif key == arcade.key.W:
            self.w_down = True
            self.player.change_y = PLAYER_SPEED

    def on_key_release(self, key, modifiers):
        if key == arcade.key.A:
            self.a_down = False
            if not self.d_down:
                self.player.change_x = 0
        elif key == arcade.key.D:
            self.d_down = False
            if not self.a_down:
                self.player.change_x = 0
        elif key == arcade.key.S:
            self.s_down = False
            if not self.w_down:
                self.player.change_y = 0
        elif key == arcade.key.W:
            self.w_down = False
            if not self.s_down:
                self.player.change_y = 0

    def disable_movement(self):
        self.player.change_x = 0
        self.player.change_y = 0
        self.can_move = False

    def enable_movement(self):
        self.can_move = True

    def on_draw(self):
        """
        Render the screen.
        """

        # This command has to happen before we start drawing
        arcade.start_render()

        # Draw all the sprites.
        with self.light_layer:
            self.coin_list.draw()
            self.bullet_list.draw()
            self.player_list.draw()
        self.light_layer.draw(ambient_color=(0, 0, 0))

        self.explosions_list.draw()
        self.wall_list.draw()

        # Render the text
        arcade.draw_text(f"Score: {self.score}", 10, 20, arcade.color.WHITE,
                         14)

    def on_mouse_press(self, x, y, button, modifiers):
        """
        Called whenever the mouse button is clicked.
        """
        self.shoot()

    def on_update(self, delta_time):
        """ Movement and game logic """

        self.physics_engine.update()
        self.player_list.update_animation()

        # Call update on bullet sprites
        self.bullet_list.update()
        self.explosions_list.update()

        arcade.set_viewport(
            self.VIEW_LEFT + self.player.center_x,
            self.VIEW_LEFT + self.player.center_x + SCREEN_WIDTH,
            self.VIEW_BOT + self.player.center_y,
            self.VIEW_BOT + self.player.center_y + SCREEN_HEIGHT,
        )

        self.player_light.position = self.player.position

        # Loop through each bullet
        for bullet in self.bullet_list:

            # Check this bullet to see if it hit a coin
            hit_list = arcade.check_for_collision_with_list(
                bullet, self.coin_list)

            # If it did...
            if len(hit_list) > 0:

                # Make an explosion
                explosion = Explosion(self.explosion_texture_list)

                # Move it to the location of the coin
                explosion.center_x = hit_list[0].center_x
                explosion.center_y = hit_list[0].center_y

                # Call update() because it sets which image we start on
                explosion.update()

                # Add to a list of sprites that are explosions
                self.explosions_list.append(explosion)

                # Get rid of the bullet
                bullet.remove_from_sprite_lists()

            # For every coin we hit, add to the score and remove the coin
            for coin in hit_list:
                coin.remove_from_sprite_lists()
                self.score += 1

                # Hit Sound
                arcade.sound.play_sound(self.hit_sound)

            # If the bullet flies off-screen, remove it.
            if bullet.bottom > SCREEN_HEIGHT:
                bullet.remove_from_sprite_lists()
Example #5
0
class MyGame(arcade.Window):

    def __init__(self, width, height, title):
        """
        Set up the application.
        """
        super().__init__(width, height, title)
        self.time = 0
        self.background = arcade.load_texture(":resources:images/backgrounds/abstract_1.jpg")

        self.torch_list = arcade.SpriteList(is_static=True)
        self.torch_list.extend([
            arcade.Sprite(":resources:images/tiles/torch1.png", scale=0.4, center_x=100, center_y=150),
            arcade.Sprite(":resources:images/tiles/torch1.png", scale=0.4, center_x=300, center_y=150),
            arcade.Sprite(":resources:images/tiles/torch1.png", scale=0.4, center_x=500, center_y=150),
            arcade.Sprite(":resources:images/tiles/torch1.png", scale=0.4, center_x=700, center_y=150),

            arcade.Sprite(":resources:images/tiles/torch1.png", scale=0.4, center_x=100, center_y=450),
            arcade.Sprite(":resources:images/tiles/torch1.png", scale=0.4, center_x=300, center_y=450),
            arcade.Sprite(":resources:images/tiles/torch1.png", scale=0.4, center_x=500, center_y=450),
            arcade.Sprite(":resources:images/tiles/torch1.png", scale=0.4, center_x=700, center_y=450),
        ])

        self.light_layer = LightLayer(SCREEN_WIDTH, SCREEN_HEIGHT)
        # Add lights to the location of the torches. We're just using hacky tweak value list here
        params = (
            (100, 'hard'),
            (100, 'hard'),
            (100, 'hard'),
            (100, 'hard'),
            (120, 'soft'),
            (120, 'soft'),
            (120, 'soft'),
            (120, 'soft'),
        )
        for sprite, p in zip(self.torch_list, params):
            self.light_layer.add(
                Light(sprite.center_x, sprite.center_y, radius=p[0], mode=p[1]),
            )
        self.moving_light = Light(400, 300, radius=300, mode='soft')
        self.light_layer.add(self.moving_light)

    def on_draw(self):
        arcade.start_render()

        # Everything that should be affected by lights in here
        with self.light_layer:
            arcade.draw_lrwh_rectangle_textured(
                0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, self.background)
            self.torch_list.draw()

        # Draw the contents with lighting
        self.light_layer.draw()
        # draw with ambient
        # self.light_layer.draw(ambient_color=(127, 127, 127))

    def on_update(self, dt):
        # Keep track of elapsed time
        self.time += dt
        self.moving_light.position = (
            400 + math.sin(self.time) * 300,
            300 + math.cos(self.time) * 50
        )
        self.moving_light.radius = 300 + math.sin(self.time * 2.34) * 150

    def on_resize(self, width, height):
        arcade.set_viewport(0, width, 0, height)
        self.light_layer.resize(width, height)
Example #6
0
class GameEngine:
    __instance = None

    @staticmethod
    def get_instance():
        if GameEngine.__instance == None:
            GameEngine()
        return GameEngine.__instance

    def __init__(self):
        if GameEngine.__instance != None:
            raise Exception("singleton! class")
        else:
            GameEngine.__instance == self

        self.stories = {}  # 階層を格納する変数
        self.cur_level = None

        self.player = None
        self.game_map = None
        self.action_queue = []
        self.messages = deque(maxlen=8)
        self.selected_item = 0  # キー押下で直接選択したアイテム
        self.turn_check = []
        self.game_state = GAME_STATE.NORMAL
        self.skill_shape = None
        self.grid_select_handlers = []
        self.move_switch = True
        self.damage_pop = []
        self.pop_position = 30
        self.messenger = None
        self.found_item = []  # 発見済みのアイテム

        self.player = Player(inventory=Inventory(capacity=18))

        # 光源システム
        self.light_layer = LightLayer(SCREEN_WIDTH, SCREEN_HEIGHT)
        self.light_layer.set_background_color(arcade.color.BLACK)

        self.player_light = Light(0, 0, 390, (230, 230, 230), mode="soft")
        self.light_layer.add(self.player_light)

    def setup_level(self, level_number):
        """未踏の階層を生成する"""

        self.map_width, self.map_height = MAP_WIDTH, MAP_HEIGHT
        self.game_level = GameLevel()

        if level_number == 0:
            return self.start_town_init()
        elif level_number >= 99:
            return self.test_map(level_number)
        elif level_number >= 1:
            # cur_map = self.basic_dungeon_init(level_number)
            # cur_map = self.bps_dungeon_init(level_number)
            cur_map = self.drunker_dungeon_init(level_number)
            return cur_map

    def setup(self):

        arcade.set_background_color(COLORS["black"])
        self.flower_sprites = arcade.SpriteList(use_spatial_hash=True,
                                                spatial_hash_cell_size=32)
        self.cur_level = self.setup_level(level_number=99)
        self.stories[self.cur_floor_name] = self.cur_level
        self.turn_loop = TurnLoop(self.player)
        self.item_point = ItemPoint(self)
        self.fov()

    def test_map(self, level):
        image_set = {"wall": "basic_wall", "floor": IMAGE_ID["color_tile_1"]}
        self.init_dungeon_sprites(TestMap(self.map_width,
                                          self.map_height,
                                          dungeon_level=99),
                                  image_set=image_set)

        self.wb = Water_vole(x=10, y=17)
        # self.game_level.actor_sprites.append(self.wb)
        self.gs = Goblin_Shaman(x=11, y=17)
        self.game_level.actor_sprites.append(self.gs)
        self.cs = CabbageSnail(x=12, y=17)
        # self.game_level.actor_sprites.append(self.cs)

        self.game_level.floor_level = level
        self.game_level.map_name = f"test_dungeon"

        self.st = Up_Stairs(self.player.x + 1, self.player.y - 1)
        self.st.scale = 2
        self.game_level.map_obj_sprites.append(self.st)

        self.ut = Down_Stairs(self.player.x, self.player.y - 1)
        self.ut.scale = 2
        self.game_level.map_obj_sprites.append(self.ut)

        return self.game_level

    def start_town_init(self):
        """初期townmapの生成"""
        self.town_map = TownMap(self.map_width, self.map_height)
        self.town_map.player_set(self.player)
        #スプライトリストの初期化
        floor_sprite = ActorPlacement(self.town_map, self).tiled_floor_set()
        wall_sprite = ActorPlacement(self.town_map, self).tiled_wall_set()
        map_point_sprite = ActorPlacement(self.town_map, self).map_point_set()
        map_obj_sprite = ActorPlacement(self.town_map,
                                        self).tiled_map_obj_set()
        actorsprite = ActorPlacement(self.town_map, self).tiled_npc_set()
        itemsprite = arcade.SpriteList(use_spatial_hash=True,
                                       spatial_hash_cell_size=32)
        items_point_sprite = arcade.SpriteList(use_spatial_hash=True,
                                               spatial_hash_cell_size=32)

        self.game_level.floor_sprites = floor_sprite
        self.game_level.wall_sprites = wall_sprite
        self.game_level.map_point_sprites = map_point_sprite
        self.game_level.map_obj_sprites = map_obj_sprite
        self.game_level.actor_sprites = actorsprite
        self.game_level.item_sprites = itemsprite
        self.game_level.item_point_sprites = items_point_sprite
        self.game_level.equip_sprites = arcade.SpriteList(
            use_spatial_hash=True, spatial_hash_cell_size=32)
        self.game_level.chara_sprites = arcade.SpriteList(
            use_spatial_hash=True, spatial_hash_cell_size=32)

        self.game_level.chara_sprites.append(self.player)

        ##########################################
        self.pineapple = Pineapple(self.player.x - 1, self.player.y + 1)
        self.game_level.item_sprites.append(self.pineapple)

        self.hp = Paeonia(self.player.x - 1, self.player.y)
        self.game_level.item_sprites.append(self.hp)

        self.silver_grass = SilverGrass(self.player.x + 1, self.player.y)
        self.game_level.item_sprites.append(self.silver_grass)

        self.sunflower = Sunflower(self.player.x, self.player.y - 2)
        self.game_level.item_sprites.append(self.sunflower)

        #######################################

        self.game_level.floor_level = 0

        self.game_level.map_name = f"town"

        return self.game_level

    def init_dungeon_sprites(self, dungeon, image_set=None, level=1):
        dungeon.game_map = dungeon
        dungeon.game_map.generate_tile()

        #スプライトリストの初期化
        wall_sprite = ActorPlacement(dungeon.game_map,
                                     self).wall_set(image_set["wall"])
        floor_sprite = ActorPlacement(dungeon.game_map, self).floor_set(
            image_set["floor"], image_set.get("floor_wall"))
        map_point_sprite = ActorPlacement(dungeon.game_map,
                                          self).map_point_set()
        map_obj_sprite = ActorPlacement(dungeon.game_map, self).map_obj_set()
        actorsprite = ActorPlacement(dungeon.game_map, self).actor_set()
        itemsprite = ActorPlacement(dungeon.game_map, self).items_set()
        items_point_sprite = ActorPlacement(dungeon.game_map,
                                            self).items_point_set()

        self.game_level.floor_sprites = floor_sprite
        self.game_level.wall_sprites = wall_sprite
        self.game_level.map_point_sprites = map_point_sprite
        self.game_level.map_obj_sprites = map_obj_sprite
        self.game_level.actor_sprites = actorsprite
        self.game_level.item_sprites = itemsprite
        self.game_level.item_point_sprites = items_point_sprite
        self.game_level.equip_sprites = arcade.SpriteList(
            use_spatial_hash=True, spatial_hash_cell_size=32)
        self.game_level.chara_sprites = arcade.SpriteList(
            use_spatial_hash=True, spatial_hash_cell_size=32)
        self.game_level.chara_sprites.append(self.player)

        self.player.x, self.player.y = dungeon.game_map.PLAYER_POINT
        self.player.from_x, self.player.from_y = self.player.position

        # playerを目標にしたダイクストラマップ作成
        self.target_player_map = DijkstraMap(dungeon.game_map.tiles,
                                             [self.player])
        self.target_tile_map = DijkstraMap(dungeon.game_map.tiles,
                                           self.game_level.floor_sprites)

        ####################
        # テスト用エンティティ

        self.pineapple = Pineapple(self.player.x + 1, self.player.y + 1)
        self.game_level.item_sprites.append(self.pineapple)

        self.hp = Paeonia(self.player.x - 1, self.player.y)
        self.game_level.item_sprites.append(self.hp)

        self.silver_grass = SilverGrass(self.player.x + 1, self.player.y)
        random_flower_gen(self.silver_grass, 20)
        self.game_level.item_sprites.append(self.silver_grass)

        self.sunflower = Sunflower(self.player.x, self.player.y - 2)
        self.game_level.item_sprites.append(self.sunflower)

        self.bananaflower = Bananaflower(self.player.x - 1, self.player.y + 1)
        self.game_level.item_sprites.append(self.bananaflower)

        self.aconite = Aconite(self.player.x + 1, self.player.y - 2)
        self.game_level.item_sprites.append(self.aconite)

        self.bamboo = Bambooflower(self.player.x + 2, self.player.y - 2)
        self.game_level.item_sprites.append(self.bamboo)

        self.cabbageflower = Cabbageflower(self.player.x, self.player.y - 1)
        self.game_level.item_sprites.append(self.cabbageflower)

    def drunker_dungeon_init(self, level=1, stairs=None):
        image_set = {
            "wall": "color_tile_walls",
            "floor": "color_tile_1",
            "floor_wall": "side_color_tile_1"
        }
        self.init_dungeon_sprites(DrunkerWalk(self.map_width,
                                              self.map_height,
                                              dungeon_level=level),
                                  image_set=image_set)
        self.game_level.floor_level = level
        self.game_level.map_name = f"drunker_dungeon"

        return self.game_level

    def bps_dungeon_init(self, level=1, stairs=None):
        image_set = {
            "wall": "basic_wall",
            "floor": "block_floor",
            "floor_wall": "side_floor"
        }
        self.init_dungeon_sprites(BSPTree(self.map_width,
                                          self.map_height,
                                          dungeon_level=level),
                                  image_set=image_set)
        self.game_level.floor_level = level
        self.game_level.map_name = f"bps_dungeon"

        return self.game_level

    def basic_dungeon_init(self, level=1, stairs=None):
        """基本のdungeonの生成"""

        image_set = {
            "wall": "basic_wall",
            "floor": "block_floor",
            "floor_wall": "side_floor"
        }
        self.init_dungeon_sprites(BasicDungeon(self.map_width,
                                               self.map_height,
                                               dungeon_level=level),
                                  image_set=image_set)

        self.game_level.floor_level = level
        self.game_level.map_name = f"basic_dungeon"

        self.ut = Down_Stairs(self.player.x, self.player.y - 1)
        self.ut.scale = 2
        self.game_level.map_obj_sprites.append(self.ut)

        return self.game_level

    @property
    def cur_floor_name(self):
        return f"{self.cur_level.map_name}{self.cur_level.floor_level}"

    def get_actor_dict(self, actor):
        name = actor.__class__.__name__
        return {name: actor.get_dict()}

    @stop_watch
    def get_dict(self):
        """ オブジェクトをjsonにダンプする為の辞書を作る関数 """
        self.game_state = GAME_STATE.DELAY_WINDOW
        ##############

        player_dict = self.get_actor_dict(self.player)

        levels_dict = {}
        for map_name, level in self.stories.items():

            actor_dict = [self.get_actor_dict(s) for s in level.actor_sprites]
            floor_dict = [self.get_actor_dict(s) for s in level.floor_sprites]
            wall_dict = [self.get_actor_dict(s) for s in level.wall_sprites]
            map_point_dict = [
                self.get_actor_dict(s) for s in level.map_point_sprites
            ]
            dungeon_obj_dict = [
                self.get_actor_dict(s) for s in level.map_obj_sprites
            ]
            item_dict = [self.get_actor_dict(s) for s in level.item_sprites]
            item_point_dict = [
                self.get_actor_dict(s) for s in level.item_point_sprites
            ]

            level_dict = {
                "level": level.floor_level,
                "map_name": level.map_name,
                "actor": actor_dict,
                "floor": floor_dict,
                "wall": wall_dict,
                "map_point": map_point_dict,
                "dungeon_obj": dungeon_obj_dict,
                "item": item_dict,
                "item_point": item_point_dict,
            }
            levels_dict[map_name] = level_dict

        # ビューポートの位置情報を保存
        viewport = arcade.get_viewport()

        result = {
            "player":
            player_dict,
            "viewport":
            viewport,
            "levels":
            levels_dict,
            "cur_level_name":
            f"{self.cur_level.map_name}{self.cur_level.floor_level}",
        }

        ##############
        self.action_queue.append({"message": "*save*"})
        self.game_state = GAME_STATE.NORMAL
        print(f"**save**{result=}")
        return result

    def restore_from_dict(self, data):
        """ オブジェクトをjsonから復元する為の関数 """
        self.game_state = GAME_STATE.DELAY_WINDOW
        self.player.state = state.READY

        print("**load**")
        ####################

        player_dict = data["player"]
        self.player.restore_from_dict(player_dict["Player"])

        self.town_map = TownMap(self.map_width, self.map_height)

        for map_name, level_dict in data["levels"].items():
            level = GameLevel()

            level.chara_sprites = arcade.SpriteList(use_spatial_hash=True,
                                                    spatial_hash_cell_size=32)

            level.actor_sprites = arcade.SpriteList(use_spatial_hash=True,
                                                    spatial_hash_cell_size=16)

            level.floor_sprites = arcade.SpriteList(use_spatial_hash=True,
                                                    spatial_hash_cell_size=32)

            level.wall_sprites = arcade.SpriteList(use_spatial_hash=True,
                                                   spatial_hash_cell_size=32)

            level.map_point_sprites = arcade.SpriteList(
                use_spatial_hash=True, spatial_hash_cell_size=32)

            level.map_obj_sprites = arcade.SpriteList(
                use_spatial_hash=True, spatial_hash_cell_size=32)

            level.item_sprites = arcade.SpriteList(use_spatial_hash=True,
                                                   spatial_hash_cell_size=16)

            level.item_point_sprites = arcade.SpriteList(
                use_spatial_hash=True, spatial_hash_cell_size=16)

            level.equip_sprites = arcade.SpriteList(use_spatial_hash=True,
                                                    spatial_hash_cell_size=16)

            level.floor_level = level_dict["level"]
            level.map_name = level_dict["map_name"]

            level.chara_sprites.append(self.player)

            for actor_dict in level_dict["actor"]:
                actor = restore_actor(actor_dict)
                level.actor_sprites.append(actor)

            if map_name == "town0":
                floors = ActorPlacement(self.town_map, self).tiled_floor_set()
                for f in floors:
                    level.floor_sprites.append(f)

            else:
                for floor_dict in level_dict["floor"]:
                    floors = restore_actor(floor_dict)
                    level.floor_sprites.append(floors)

            if map_name == "town0":
                walls = ActorPlacement(self.town_map, self).tiled_wall_set()
                for w in walls:
                    level.wall_sprites.append(w)
            else:
                for wall_dict in level_dict["wall"]:
                    walls = restore_actor(wall_dict)
                    level.wall_sprites.append(walls)

            for map_point_dict in level_dict["map_point"]:
                map_points = restore_actor(map_point_dict)
                level.map_point_sprites.append(map_points)

            for dungeon_obj_dict in level_dict["dungeon_obj"]:
                map_obj = restore_actor(dungeon_obj_dict)
                level.map_obj_sprites.append(map_obj)

            for item_dict in level_dict["item"]:
                item = restore_actor(item_dict)
                level.item_sprites.append(item)

            for item_point_dict in level_dict["item_point"]:
                item_point = restore_actor(item_point_dict)
                level.item_point_sprites.append(item_point)

            self.stories[map_name] = level
        print(self.stories)
        self.flower_sprites = arcade.SpriteList(use_spatial_hash=True,
                                                spatial_hash_cell_size=32)

        self.cur_level = self.stories[
            data["cur_level_name"]]  #dataに格納した現在階層を適応する

        # ビューポートを復元する
        arcade.set_viewport(*data["viewport"])

        ####################
        self.action_queue.append({"message": "*load*"})
        self.player.state = state.READY
        self.game_state = GAME_STATE.NORMAL
        self.fov()
        self.player.equipment.item_sprite_check(self.flower_sprites)
        self.player.equipment.equip_position_reset()

    def process_action_queue(self, delta_time):
        """アクターの基本的な行動を制御するアクションキュー
        エンジン内にある各メソッドの返り値(damage, message等)はここに送る
        """
        new_action_queue = []
        for action in self.action_queue:
            if "player_turn" in action:
                print("player_turn")
                self.player.state = state.READY
            if "action" in action:
                target = action["action"][0]
                dist = action["action"][1]
                result = dist_action(dist, target, self)
                if result:
                    new_action_queue.extend(result)

            if "None" in action:
                pass

            if "message" in action:
                self.messages.append(action["message"])

            if "remove" in action:
                target = action["remove"]
                target.remove_from_sprite_lists()

            if "turn_end" in action:
                target = action["turn_end"]
                target.fighter.wait += target.fighter.speed
                target.state = state.TURN_END
                print(f"{target.name} is pass Turn_END")

            if "dead" in action:
                target = action["dead"]
                target.color = COLORS["dead"]
                target.is_dead = True
                if target is self.player:
                    new_action_queue.extend([{"message": "player has died!"}])
                else:
                    # EXP獲得処理
                    self.player.fighter.current_xp += target.fighter.xp_reward
                    self.player.equipment.item_exp_add(
                        target.fighter.xp_reward)
                    drop_system(self, target)
                    self.move_switch = False

                    # dungeon追放anm
                    Expulsion(target, image=target.texture)
                    new_action_queue.extend([{
                        "message":
                        f"{target.name} was Thrown out of the dungeon!"
                    }])

                    # ここでplayerにEXPが入る
                    check_experience_level(self.player, self)

            if "delay" in action:
                target = action["delay"]
                target["time"] -= delta_time
                if target["time"] > 0:
                    new_action_queue.extend([{"delay": target}])
                    self.move_switch = False
                else:
                    new_action_queue.extend([target["action"]])
                    self.move_switch = True

            if "use_skill" in action:
                select_skill = action["use_skill"]
                user = action["user"]
                if select_skill and user:
                    skill = user.fighter.active_skill

                    if select_skill is not None and len(skill) >= select_skill:
                        skill = skill[select_skill - 1]
                        if skill and Tag.active in skill.tag:
                            results = skill.use(self)
                            if results:
                                new_action_queue.extend(results)

            if "use_item" in action:
                item_number = self.selected_item
                if item_number is not None:
                    item = self.player.inventory.get_item_number(item_number)
                    if item and Tag.used in item.tag:
                        results = item.use(self)
                        if results:
                            new_action_queue.extend(results)
                            self.player.state = state.TURN_END

            if "equip_item" in action:
                item_number = self.selected_item
                if item_number is not None:
                    item = self.player.inventory.get_item_number(item_number)
                    if item and Tag.equip in item.tag:
                        results = self.player.equipment.toggle_equip(item)
                        if results:
                            if "dequipped" not in results[0]["message"]:
                                self.flower_sprites.append(item)

                            results.extend([{"turn_end": self.player}])
                            # self.game_state = GAME_STATE.NORMAL

                            new_action_queue.extend(results)

            if "pickup" in action:
                items = arcade.get_sprites_at_point(
                    (self.player.center_x, self.player.center_y),
                    self.cur_level.item_sprites)
                for item in items:
                    if Tag.item in item.tag:
                        results = self.player.inventory.add_item(item, self)

                        if results:
                            new_action_queue.extend(results)
                            # mapからPOINTを消す
                            if "You pick up" in "".join(
                                    list(*results[0].values())):
                                self.item_point.remove_point(item)

            if "drop_item" in action:
                item_number = self.selected_item
                if item_number is not None:
                    item = self.player.inventory.get_item_number(item_number)

                    # これはequipを外す処理
                    if item and item in self.player.equipment.flower_slot:
                        self.player.equipment.toggle_equip(item)

                    # ここでドロップ
                    if item:
                        self.player.inventory.remove_item_number(item_number)
                        item.x = self.player.x
                        item.y = self.player.y
                        self.item_point.add_point(item)  # mapにPOINTを表示
                        self.cur_level.item_sprites.append(item)
                        new_action_queue.extend([{
                            "message":
                            f"You dropped the {item.name}"
                        }])

            if "use_stairs" in action:
                result = self.use_stairs()
                if result:
                    new_action_queue.extend(result)
                    self.flower_sprites = arcade.SpriteList(
                        use_spatial_hash=True, spatial_hash_cell_size=32)
                    TMP_EFFECT_SPRITES = arcade.SpriteList(
                        use_spatial_hash=True, spatial_hash_cell_size=32)

                    self.player.equipment.item_sprite_check(
                        self.flower_sprites)
                    self.player.equipment.equip_position_reset()
                    self.game_state = GAME_STATE.NORMAL
                    self.turn_loop = TurnLoop(self.player)
                    self.fov()

            if "grid_select" in action:
                self.game_state = GAME_STATE.SELECT_LOCATION

            if "close_door" in action:
                self.player.form = form.DOOR
                self.player.state = state.DOOR
                new_action_queue.extend([{
                    "message":
                    f"What direction do you want the door to close?"
                }])

            if "use_door" in action:
                door_dist = (action["use_door"])
                result = self.use_door(door_dist)
                if result:
                    new_action_queue.extend(result)

            if "damage_pop" in action:
                target = action["damage_pop"]
                damage = action["damage"]
                txt_color = arcade.color.WHITE
                if isinstance(damage, str):
                    txt_color = arcade.color.WHITE
                elif 0 < damage:
                    txt_color = arcade.color.MINT_GREEN
                elif 0 > damage:
                    txt_color = COLORS["status_bar_foreground"]
                    damage = -damage
                y = self.pop_position
                self.damage_pop.append(DamagePop(damage, txt_color, target, y))
                self.pop_position += 33
                # Damagepop(self, damage, txt_color,  target, y)

            if "talk" in action:
                actor = action.pop("talk")
                if hasattr(actor, "message_event"):
                    self.game_state = GAME_STATE.MESSAGE_WINDOW
                    self.messenger = actor
                else:
                    actor.center_x, actor.center_y = self.player.center_x, self.player.center_y
                    actor.x, actor.y = self.player.x, self.player.y
                action = None

        self.action_queue = new_action_queue

    def grid_click(self, grid_x, grid_y):
        """ クリックしたグリッドをself.grid_select_handlersに格納する 
        """
        for f in self.grid_select_handlers:
            results = f(grid_x, grid_y)
            if results:
                self.action_queue.extend(results)
        self.grid_select_handlers = []

    def fov(self):
        recalculate_fov(self, FOV_RADIUS)

    def check_new_item(self):
        check = False
        visible_item = [v for v in self.cur_level.item_sprites if v.is_visible]
        for i in visible_item:
            if i.found_item == False:
                check = True
                i.found_item = True
                self.action_queue.append(
                    {"message": f"{self.player.name} found a {i.name}!"})
        return check

    def check_for_player_movement(self, dist):
        """プレイヤーの移動"""

        if self.player.state == state.TURN_END:
            self.check_new_item()

        if self.player.state == state.READY and dist and self.move_switch:
            self.action_queue.extend([{"action": (self.player, (dist))}])
            dist = None

    def auto_move_check(self):

        if self.player.state == state.AUTO or self.player.tmp_state == state.AUTO:
            visible_mns = [
                v for v in self.cur_level.actor_sprites
                if v.ai.visible_check or v.is_visible
            ]

            check = self.check_new_item()
            if check:
                return

            if not visible_mns:
                dist_auto = auto_explore(self, self.player)
                if dist_auto:
                    self.action_queue.extend(dist_auto)
                    self.player.tmp_state = state.AUTO

                else:
                    dist_auto = auto_explore(self, self.player, tar="stairs")
                    if dist_auto:
                        self.action_queue.extend(dist_auto)
                        self.player.tmp_state = state.AUTO
                    else:
                        self.player.state = state.READY
                        self.player.tmp_state = state.READY

            else:
                self.player.state = state.READY
                self.player.tmp_state = state.READY

    def normal_state_update(self, player_direction, delta_time):
        # ノーマルステート時に更新したい関数
        self.turn_loop.loop_on(self)
        if self.turn_loop.game_turn == Turn.PLAYER:
            self.skill_position_update()
            self.check_for_player_movement(player_direction)
            self.skill_dispry_check()

    def skill_dispry_check(self):
        # 装備スプライトの表示を強制する関数
        for skill in self.cur_level.equip_sprites:
            if skill in self.cur_level.equip_sprites and skill not in chain(
                    self.player.fighter.active_skill,
                    self.player.fighter.passive_skill):
                skill.remove_from_sprite_lists()

        for i, skill in enumerate(
                chain(self.player.fighter.active_skill,
                      self.player.fighter.passive_skill)):

            # 階を移動したときに装備が消えないよう処理
            if skill not in self.cur_level.equip_sprites and Tag.equip in skill.tag:
                self.cur_level.equip_sprites.append(skill)

    def skill_position_update(self):
        # skill_itemをプレイヤーに追従するようにする
        for i, skill in enumerate(self.player.fighter.skill_weight_list):
            if self.player.state == state.ON_MOVE or self.player.state == state.READY:
                skill.item_position_x = self.player.fighter.equip_position[i][
                    0]
                skill.item_position_y = self.player.fighter.equip_position[i][
                    1]

    def flower_light(self):
        self.light_layer = LightLayer(SCREEN_WIDTH, SCREEN_HEIGHT)
        self.light_layer.set_background_color(arcade.color.BLACK)

        self.player_light = Light(0, 0, 390, arcade.color.WHITE, mode="soft")
        self.light_layer.add(self.player_light)

        for i, flower in enumerate(self.player.equipment.flower_slot):
            flower.light = Light(0,
                                 0,
                                 radius=flower.texture.width / 3,
                                 color=flower.flower_color,
                                 mode="soft")
            self.light_layer.add(flower.light)

    def use_stairs(self):
        """階段及びplayerの位置の判定
        """

        get_stairs = arcade.get_sprites_at_exact_point(
            point=self.player.position,
            sprite_list=self.cur_level.map_obj_sprites)
        player_dict = self.get_actor_dict(self.player)

        for stairs in get_stairs:
            if isinstance(stairs, Down_Stairs):
                cur_level_name = f"{self.cur_level.map_name}{self.cur_level.floor_level}"

                next_level = self.setup_level(self.cur_level.floor_level + 1)
                next_level_name = f"{next_level.map_name}{self.cur_level.floor_level+1}"

                self.stories[cur_level_name] = self.cur_level
                if next_level_name not in self.stories.keys():
                    self.cur_level = next_level

                    up_stairs = [
                        i for i in self.cur_level.map_obj_sprites
                        if isinstance(i, Up_Stairs)
                    ]
                    self.player.restore_from_dict(player_dict["Player"])
                    self.stories[next_level_name] = self.cur_level
                    self.player.x, self.player.y = up_stairs[0].x, up_stairs[
                        0].y

                else:
                    load_level = self.stories[next_level_name]
                    self.cur_level = load_level
                    self.cur_level.floor_level = load_level.floor_level

                    up_stairs = [
                        i for i in self.cur_level.map_obj_sprites
                        if isinstance(i, Up_Stairs)
                    ]
                    self.player.restore_from_dict(player_dict["Player"])
                    self.player.x, self.player.y = up_stairs[0].x, up_stairs[
                        0].y

                self.player.state = state.READY
                self.flower_light()
                return [{"message": "You went down a level."}]

        for stairs in get_stairs:
            if isinstance(stairs, Up_Stairs):
                prev_level_name = f"{self.cur_level.map_name}{self.cur_level.floor_level-1}"
                self.stories[
                    f"{self.cur_level.map_name}{self.cur_level.floor_level}"] = self.cur_level
                return_level = (self.cur_level.floor_level - 1)

                if 0 == return_level:

                    load_level = self.stories[f"town0"]
                    self.cur_level = load_level

                    down_stairs = [
                        i for i in self.cur_level.map_obj_sprites
                        if isinstance(i, Down_Stairs)
                    ]
                    self.player.restore_from_dict(player_dict["Player"])
                    self.player.x, self.player.y = down_stairs[
                        0].x, down_stairs[0].y

                elif -1 >= return_level:
                    raise ValueError

                else:
                    self.cur_level = self.stories[prev_level_name]

                    down_stairs = [
                        i for i in self.cur_level.map_obj_sprites
                        if isinstance(i, Down_Stairs)
                    ]
                    self.player.restore_from_dict(player_dict["Player"])
                    self.player.x, self.player.y = down_stairs[
                        0].x, down_stairs[0].y

                self.flower_light()
                return [{"message": "You went UP a level."}]

        return None  #[{"message": "There are no stairs here"}]

    def use_door(self, door_dist):
        result = []
        dx, dy = door_dist
        dest_x = self.player.x + dx
        dest_y = self.player.y + dy
        # door_actor = get_door(dest_x, dest_y, self.cur_level.map_obj_sprites)
        for door in self.cur_level.map_obj_sprites:
            if Tag.door in door.tag:
                if (door.x, door.y) == (dest_x, dest_y):
                    if door.left_face:
                        door.left_face = False
                    elif not door.left_face:
                        door.left_face = True

                    result.extend([{
                        "delay": {
                            "time": 0.5,
                            "action": {
                                "turn_end": self.player
                            }
                        }
                    }])
                    if result:
                        return result

        else:
            result.extend([{"message": f"There is no door in that direction"}])
            result.extend([{"delay": {"time": 0.5, "action": {"None"}}}])

        return result
class SingleScene(BaseScene):
    def setup(self, win):
        left, self.screen_width, bottom, self.screen_height = win.get_viewport(
        )
        self.coils = ActorList()
        self.light_layer = LightLayer(self.screen_width, self.screen_height)
        # self.light_layer.set_background_color(arcade.color.BLACK)
        radius = 1000
        b = arcade.color.MIDNIGHT_BLUE
        darken = 0.2
        light_color = b[0] * darken, b[1] * darken, b[2] * darken
        self.light1 = Light(0,
                            0,
                            radius=radius,
                            mode='soft',
                            color=light_color)
        self.light_layer.add(self.light1)
        self.light2 = Light(0,
                            0,
                            radius=radius,
                            mode='soft',
                            color=light_color)
        self.light_layer.add(self.light2)
        self.light3 = Light(0,
                            0,
                            radius=radius,
                            mode='soft',
                            color=light_color)
        self.light_layer.add(self.light3)
        self.light4 = Light(0,
                            0,
                            radius=radius,
                            mode='soft',
                            color=light_color)
        self.light_layer.add(self.light4)

    def add_coil(self):
        x = random.randint(0, self.screen_width)
        y = random.randint(0, self.screen_height)
        arc_count = random.randint(MIN_ARCS, MAX_ARCS)
        coil = Coil(self, x, y, START_RADIUS, RADIUS_STEP, arc_count)
        self.coils.append(coil)
        coil.start_anim(self)

    def enter_scene(self, previous_scene):
        for _ in range(COIL_COUNT):
            self.add_coil()
        self.add_anim_to_light(self.light1)
        self.add_anim_to_light(self.light2)
        self.add_anim_to_light(self.light3)
        self.add_anim_to_light(self.light4)

    def add_anim_to_light(self, light):
        light.animate = AnimationManagerProxy(light)
        elapsed = 0.0
        seq = Sequence(loop=True)
        for _ in range(10):
            key = KeyFrame(position=(random.randint(0, self.screen_width),
                                     random.randint(0, self.screen_height)))
            seq.add_keyframe(elapsed, key)
            elapsed += random.uniform(15.0, 30.0)
        light.animate(seq)

    def draw(self):
        with self.light_layer:
            arcade.draw_xywh_rectangle_filled(0, 0, self.screen_width,
                                              self.screen_height,
                                              arcade.color.WHITE)
        self.light_layer.draw(ambient_color=arcade.color.BLACK)
        self.coils.draw()
        self.coils.update(0.0)  # to make sure coils get reaped from ActorList