I found a 1x1 transparent PNG. Let’s use it for AppearingContent. A sweet little improvement.

we add it to the object’s textures here:

class AppearingContent:
    def __init__(self, name, resource, scale=0.5):
        blank = '/Users/ron/Desktop/DungeonTiles/png/objects/1x1.png'
        self.name = name
        self.resources = [blank, resource]
        self.scale = scale

We Change run to send state_number instead of set_visibility. (In Python boolean is a subclass of integer, with values 0 or 1, so this is legit.)

class AppearingContent:
    def run(self, dungeon):
        dungeon.publish('state_number', self, False)
        self.visible = False
        def callback(event):
            dungeon.announce(f'{self.name} has appeared!')
            dungeon.publish('state_number', self, True)
            self.visible = True
        dungeon.subscribe_once(self.name + ' button_pressed', callback)

DungeonView no longer needs to subscribe to set_visibility, so we delete this:

class DungeonView:
    def subscribe_to_visibility(self, dungeon):
        def callback(event, item, a_boolean):
            self.view_do(item, lambda view:view.set_visibility(a_boolean))
        dungeon.subscribe('item_visibility', callback)

We can remove set_visibility from ContentView, leaving just remove_from_sprite_lists and set_state:

    def remove_from_sprite_lists(self):
        self.sprite.remove_from_sprite_lists()

    def set_state(self, state_number):
        self.sprite.set_texture(state_number)

I did find one glitch, which was in trying to set the scale of the image. I was scaling according to the first texture provided. I changed that code to scale using the last:

class ContentView:
    error_texture = ':resources:images/items/star.png'
    def __init__(self, content_item, resources, scale=0.5):
        self.item = content_item
        self.sprite = Sprite()
        for resource in resources:
            try:
                texture = arcade.load_texture(resource)
            except (FileNotFoundError, AttributeError):
                texture = arcade.load_texture(self.error_texture)
            self.sprite.append_texture(texture)
        self.sprite.set_texture(0)
        self.sprite.scale = scale_texture(self.sprite.textures[-1], scale)

The -1 in the last line selects the last texture assigned to the sprite, which is also the first if there’s only one. (If there were zero that would be bad.)

And it works:

Before Dot steps on the button to her right, there is no key:

Before Dot steps on the button to her right, there is no key:

After Dot steps on the button to her right, there is a key:

After Dot steps on the button to her right, there is a key:

So that works nicely. We removed methods from ContentView and DungeonView, changed a line here and there and now there’s one less difference between the Button and the AppearingContent. More capability, less code. Sweet.

I rename the subscribing methods to use the full name of what they subscribe to:

    self.subscribe_to_remove_item(dungeon)
    self.subscribe_to_state_number(dungeon)

And we commit: AppearingContent now uses a transparent texture for zero-state and uses state_number to appear.

Summary

A sweet little improvement, the sort of thing we do when we don’t feel like taking on anything difficult.

See you next time!