Hello, loves!

Let’s see if we can gin up something that’s kind of fun. I have a simple idea that seems promising. Turns out to be Very Pleasing!

Let’s see how we create the DungeonView:

Here’s some of where it gets going:

class DungeonView:`
    def run(self):
        self.setup()
        self.dungeon.run()
        self.window.show_view(self)
        arcade.run()

    def setup(self):
        self.setup_scroller()
        self.setup_cameras()
        self.room_sprite_list = arcade.SpriteList()
        self.create_rooms(self.room_sprite_list)
        self.create_content_lists()

    def create_rooms(self, shape_list):
        for room in self.dungeon.rooms:
            RoomView(self.dungeon, room).create_floor(shape_list)

class RoomView:
class RoomView:
    def __init__(self, dungeon, room):
        self.dungeon = dungeon
        self.layout = dungeon.layout
        self.room = room
        self.texture_finder = TextureFinder()
        # if not self.texture_finder.verify():
        #     raise Exception('Invalid texture finder')

    def create_floor(self, shape_list):
        cells = set(self.room.cells)
        for cell in cells:
            self.choose_flooring(cell, shape_list)

    def choose_flooring(self, cell, shape_list):
        texture = self.choose_flooring_texture(cell)
        sprite = self.make_adjusted_sprite(cell, texture)
        shape_list.append(sprite)

Let’s save up our sprites:

class RoomView:
    def __init__(self, dungeon, room):
        self.dungeon = dungeon
        self.layout = dungeon.layout
        self.room = room
        self.sprites = []
        self.texture_finder = TextureFinder()
        # if not self.texture_finder.verify():
        #     raise Exception('Invalid texture finder')

    def choose_flooring(self, cell, shape_list):
        texture = self.choose_flooring_texture(cell)
        sprite = self.make_adjusted_sprite(cell, texture)
        self.sprites.append(sprite)
        shape_list.append(sprite)

Back in DungeonView, let’s save the RoomViews:

class DungeonView:
    def create_rooms(self, shape_list):
        for room in self.dungeon.rooms:
            view = RoomView(self.dungeon, room)
            self.room_views[room] = view
            view.create_floor(shape_list)

I’ve made a temporary change to ContentView that we’ll look at in a moment.

In on_draw, change this:

class DungeonView:
    def on_draw(self):
        self.clear()
        self.scroll_dungeon_camera()
        with self.dungeon_camera.activate():
            self.room_sprite_list.draw()
            self.draw_contents()
            self.draw_passages()
        with self.scroller_camera.activate():
            self.scroller.draw()

To this:

class DungeonView:
    def on_draw(self):
        self.clear()
        self.scroll_dungeon_camera()
        self.illuminate()
        with self.dungeon_camera.activate():
            self.room_sprite_list.draw()
            self.draw_contents()
            self.draw_passages()
        with self.scroller_camera.activate():
            self.scroller.draw()

    def illuminate(self):
        room = self.dungeon.player_cell.room
        view = self.room_views[room]
        view.illuminate()

And:

class RoomView:
    def illuminate(self):
        for sprite in self.sprites:
            sprite.visible = True

And run the game.

The rooms are dark until Dot enters them! Is that fine, or what? One change I didn’t show you was this:

class RoomView:
    def make_adjusted_sprite(self, cell, texture):
        scale = scale_texture(texture)
        sprite = arcade.Sprite(texture, scale=scale)
        sprite.position = cell.center_position(cell_size)
        sprite.visible = False
        return sprite

As we set up the sprite, we make it invisible. As you saw in the on_draw we unconditionally illuminate all the sprites in the room we’re in. We don’t even check to only do it once, though I won’t be able to resist doing that soon.

You may have noticed that the content did not appear, although when we stepped on the cell with the torch button in it, the announcement came out. We could make the appearing items set visible but they are designed to work by displaying a one-pixel transparent thing when invisible, because they work like the state-changing content like the spikes.

This is good. Commit: Room tiles only become visible once Dot has entered the room.

I’ve broken a test, what is it? Hahahaha:

class TestContentView:
    def test_creation(self):
        resource = ':resources:images/items/keyRed.png'
        factory = ContentFactory()
        item = factory.decor(name='key', resource=resource, scale=0.5)
        view = ContentView(item, item.resources)
        assert view.sprite.visible == True

I didn’t even notice the failure, I was so excited to see the darkness. Fix test, get back to work.

NOw let’s save up the ContentViews, by room.

class DungeonView:
    def create_content_lists(self):
        for room in self.dungeon.rooms:
            self.content_views_by_room[room] = []
        self.content_views = dict()
        self.content_sprite_list = arcade.SpriteList()
        for cell, content in self.dungeon.contents.items():
            for item in content:
                resources = item.resources
                scale = item.scale
                view = ContentView(item, resources, scale)
                view.sprite.position = cell.center_position(cell_size)
                self.content_views[item] = view
                self.content_views_by_room[cell.room].append(view)
                self.content_sprite_list.append(view.sprite)

And now I think we can do this:

class DungeonView:
    def illuminate(self):
        room = self.dungeon.player_cell.room
        view = self.room_views[room]
        view.illuminate()
        for content_view in self.content_views_by_room[room]:
            content_view.illuminate()

And that should do the trick:

Room content now appears when you first enter the room.

Summary

And that, my friends, is what I consider to be fun.

We’ll want to avoid setting “all those sprites” to visible when they already are visible, but I’ve seen arcade programs moving hundreds of sprites around the screen, so this inefficiency isn’t really hurting anything but our pride. Maybe we should rig up some kind of event, or maybe we will find something simpler.

But the fun! The dungeon is dark and your map is empty until you reach a new area. We could do something more clever, like raycasting to decide what cells illuminate, but I think this scheme gives us most of the effect with very little effort.

I am pleased. See you next time!