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)
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()
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()
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)
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