Spelunky is a Great Game. The procedurally generated treasure-hunting cave exploration game started (and still exists) as a free PC download created in GameMaker and was later upgraded to Spelunky HD for commercial release on Xbox Live. You can also play a port of the original in HTML5 for Chrome, by friend-of-the-blog Darius Kazemi, for free.
After contractual exclusivity of Spelunky HD ran its course, the Steam release of Spelunky added a “Daily Challenge” feature, ensuring everyone playing that mode on a given day experiences the same generated world. This motivated players to regularly engage the Daily Challenge and share their attempts on Twitch and YouTube.
Beyond individuals uploading runs to personal accounts, groups of players also aggregate their recordings in a central location as community activity (Spelunky Explorers Club) or within a competitive framework (Spelunky League Racing.) Since I’m not cool enough to join these parties, how can I contribute to this ecosystem?
Make a bot, obviously.
As in most Rogue-like[-like] games, Spelunky’s capacity to surprise and entertain players through myriad potential failure cascades provides a kind of reward-in-death. With cartoony sprites and real-time platforming framework, Spelunky offers a particular legibility of deaths as slapstick, even to non-players, which traditional Rogue-like games lack.
Originally intended to operate in the comments section of the Spelunky Explorers Club blog, I started working on codename death_extractor. Once I realized that automated posting of comments to WordPress and potentially spoiling dedicated SEC viewers were both things I didn’t want to do, the program became a Tumblr bot titled Book of the Dead instead, which draws from YouTube broadly instead of specific uploaders.
Once every 2 hours, an animated GIF of a death from some Spelunky Daily Challenge video is posted, along with a time-stamped link to the source on YouTube. I hope you enjoy it.
The death_extractor is my first bot made in Python, taking advantage of its robust OpenCV implementation for simple (in my case) computer vision tasks. It requires the OpenCV library be built with FFmpeg support for working with MP4 videos retrieved by youtube-dl. GIFs themselves are generated using ImageMagick.
The core of death_extractor is its
CvVideo class, which bundles a
cv2.VideoCapture object with various metadata and convenience methods for scrubbing through video, checking for template image matches, extracting a clip to an AVI
container, and converting resulting AVI to GIF.
With the affordances of
CvVideo, the logic of making a post to Book of the Dead looks something like this:
vid = CvVideo('path/to/input_video.mp4') vid.set_frame(vid.framecount - 1).read() vid.until_template(skull) vid.while_template(frame_skip=6) vid.skip_back(3.85) vid.clip_to_output(frame_skip=4, duration=4) vid.gif_from_temp_vid() vid.clear_temp_vid() vid.upload_gif_tumblr(tumblr)
We start at the end of the video, step back by 1 second increments until we see the skull UI element indicating the player has died, then go forward by 6 frame increments until the skull is no longer visible (UI cleared), we skip back 3.85 seconds and then grab 4 seconds of video at ~8fps which we make into a GIF and upload to Tumblr.
And what comes out the other end? Often, magical things.