Passage Screensaver

By Shamus Posted Monday Jan 13, 2014

Filed under: Programming 59 comments

I’m feeling the itch to code, but I think I need to let Good Robot alone right now. If you’ve ever noticed how some people tend to drive faster when they get lost, then you have a good idea of how I feel right now. I feel like there’s something wrong with my game, and I want to HURRY UP AND FIX IT so I can stop worrying about it. But hasty changes aren’t any better than hasty driving. I need to wait for some of the feedback and suggestions to sink in, and until then I can twiddle my thumbs doing something else.

So let’s make a screensaver.

When I was a kid, I was fascinated by infinite tunnels. I used to picture plunging down an infinite circular tunnel as I drifted off to sleep. I’m not sure where this came from. Dr. Who existed back then, but I’m pretty sure I hadn’t seen it yet. Was there some other sci-fi show that used the endless tunnel gag in the opening sequence? Maybe Lost in Space or Twilight Zone? I can’t remember.

Anyway, I want to make one.

So, I open an empty project and use this example to set up the boilerplate code. Windows screensavers are odd creatures. When written in C or C++, you don’t have a main (). In non-programmer talk, you don’t start with the usual first bit of code common to nearly all c++ programs. Instead, that code is packed in this external library. That library handles creating a window and all the other stuff that’s common to all screensavers. (Like, if there’s any input, the program exits.) You don’t have to worry about window resizing, menus, and a bunch of other stuff. This is a good thing, since it saves you from having to write (or more likely, copy & paste) a couple hundred lines of code. This saves you a lot of work, although it also makes your program about as non-portable as possible.

I start by making a simple straight tube of polygons and having the camera fly down it.


Of course, a straight tube is pretty boring. You can’t even tell you’re moving unless the walls have some texture. But I’m not sure I’m crazy about introducing textures to this. I’m aiming for something a little more abstract. I mean, if I use a texture then I’ll be stuck with bricks or metal or whatever texture I pick. And since I’m doing this for fun I don’t want to trouble myself with the un-fun task of making an interface where the user can choose textures. Yuck.

Hm. I try just coloring the polygons, but it’s still kind of boring. I try adding lighting, and it’s actually even less interesting. The lighting makes the tube look kind of flat and lifeless.

Not sure what the rectangle is in this shot. I think it’s a leftover from the example code.
Not sure what the rectangle is in this shot. I think it’s a leftover from the example code.

The wireframe is kind of interesting, though. Even making the tunnel twist around doesn’t do much to liven it up. What if I made the wireframe glow? Then I could have the camera flying through glowing rings, which might be kind of fun.

I fiddle with this for a while. I suppose if I was smart I’d have taken more screenshots of the work in progress, but I wasn’t and I didn’t. After about an hour of experimentation and tweaking, I find myself flying through what amounts to a series of glowing hoops.

At last, a simulation that gives us the view from a croquet ball at a rave.
At last, a simulation that gives us the view from a croquet ball at a rave.

I’m not sure I can even re-trace the steps of what might very generously be called logic to get from there to here. It was very much a process of doing random crap just to see what it would look like.

But still. Boring. Endless tunnels are boring. What works for a few seconds in the Dr. Who opening is kind of dull when deprived of titles and names and theme music and Tardises. We need more.

Well, variety would help. Lets have the shape of the tunnel deform as we go.


I’m kind of shocked at how dull the thing looks in stillframe. In motion it’s fast-moving and visually stimulating. Once in a while I catch myself staring during testing, hypnotized by the color and motion.

What we have here is a blend of many, many sine waves. Sine waves govern the lengths of the line segments of the hoops, so sometimes it’s round and sometimes it’s more octagonal or hexagonal. Sine waves govern the height and width of the hoops, so sometimes the passage is tight and sometimes it’s wide but low and sometimes it’s tall but narrow. Three different overlapping sine waves are used to create the side-to-side curves.

For movement: The camera just moves from the center of one hoop to the next. As you proceed, it takes the hoop behind you and places it at the end of the tunnel to give the “infinite tunnel” effect. The camera aims itself at the hoop a few steps ahead, which means it begins turning just slightly before you reach the curve. This seems more natural and less mechanical than just turning in unison with the curves. I’ve also got it banking very slightly, so when you go around a big bend you kind of lean into it a bit. If the above screenshots look sort of comically empty, I’ll defend it by saying it feels better than it looks.

Maybe some vertical hills would be nice? Also, maybe I ought to do something about this rainbow puke color scheme?

Ah. Now we can puke over motion sickness instead of the color scheme.
Ah. Now we can puke over motion sickness instead of the color scheme.

It suddenly feels very roller coaster. So I add some… numbers? To make it go faster downhill and slow down on the uphill. To call this primitive stuff “physics” is like calling a flip-book of Aquaman fan-fiction “cinema”, but in practice it feels about right.

In fact, it feels so much like a roller-coaster that I kind of want to…

So it’s a roller coaster. Sue me.
So it’s a roller coaster. Sue me.

So we set out to make an infinite tunnel and wound up with a roller coaster made of glowsticks. I guess that’s okay. I think we’re done here.

This was just an afternoon project. Sure, there’s a ton of stuff we could do with it from here, but all of that is boring interface and tweaking and I’m bored now. So I guess I’ll just put the source up for others to play with.

Passage screensaver source.

That’s the code and project file, which was created using Visual Studio Express 2010. main.cpp is the boilerplate screensaver stuff. gltypes.cpp is my general-purpose toolkit for 3D vector math (the exact same code is in Good Robot) and is ALWAYS under construction. render.cpp is the interesting stuff and if you want to play with the polygons that’s where you’ll want to go.

I’m releasing this under a wtfpl license, which is basically: Do what you like, commercial or free, public or private, educational or stupid. Give credit or don’t. Sell it or don’t. Paypal tips (see donate button, right) are always appreciated if you just really, really find code useful, but I’m not releasing this to get money and I don’t expect it.

If you’re not the coding type, you can get the screensaver itself here:

Passage screensaver.

Just unzip that sucker and throw it in your windows/system32 directory and it should appear in your list of screen savers. Windows only. Sorry. If you want a port, maybe you can bug one of your programmer friends to have a go at the source. Trust me. Your programmer friends LOVE random tasks like porting half-assed windows applications.

Well, that was a quick afternoon lark. Hope it was at least mildly amusing for you.


From The Archives:

59 thoughts on “Passage Screensaver

  1. IronCore says:

    I miss the old city screensaver.

    1. swenson says:

      I still have it! Unfortunately, the only working code I could find for it isn’t actually random (I believe the “random” number is permanently set to 6), so you get the same city every time. I even tried messing with the code directly, but it’s old enough and relies on enough deprecated/obsolete libraries that I couldn’t get it to compile.

      So, uh, yeah, if you’re looking for a little project, Shamus, I would not be averse to a fixed version of the city code… :)

      1. Zidynnala says:

        The original PixelCity code was added to GitHub and forked several times by various people, at least one or two versions which ported PixelCity to various Visual Studio code. You then can download the code from one of the forked versions and compile it with Visual Studios to get random cities again. I did it a few months ago and I don’t recall any major problems.

        If you do run into problems, just let me know and when I get home, I can give you more details, like which fork I used, and even upload the actual screensaver program.

        1. swenson says:

          Ooh, thank you. I was messing with it ages ago and I guess never came across it on GitHub.

      2. IronCore says:

        I found it in the archives.

        I like this tunnel program as well. I think Shamus could turn it into something really fun to just sit and stare at if he cared to. The city though for some reason captured my imagination in a way that I don’t think I’ll ever forget it.

  2. MrGuy says:

    That’s actually pretty cool. Have some donate. :)

    1. MrGuy says:

      Hmm….donate message is the same as last time I donated, but e-mail address has changed and is no longer obviously related to this site or a member of Clan Young. I’m assuming your link is OK?

      1. MichaelGC says:

        Should be OK – if you Google the email address you’ll see it does belong to Clan Young!

        PS I am still chuckling over that ‘Aquaman fan-fiction’ simile…

      2. Yeah, still connected. My old email got dumped when we moved (thanks stupid internet company for not carrying it over) and I had to switch. We are all set to finally use Shamus’ paypal again (his was old and he had lost bits of it and well… mine is used regularly so we just used that for now) but we both need to be home and awake and not busy at the same time for it to actually happen.

        1. MrGuy says:

          No worries – thanks!

  3. Eric Meyer says:

    “Was there some other sci-fi show that used the endless tunnel gag in the opening sequence?”

    Could it have been, perchance?

    1. ET says:

      Maybe it was a videogame instead?
      A quick search on the interwebs shows Cosmic Tunnels from about 1984.
      Shamus would have been a young teenager; Maybe that’s too late of a timeframe already?

  4. Benjamin Hilton says:

    The license link made me chuckle.

    1. ET says:

      It’s a cool little license, although you could get the same effect by just releasing it into the public domain.
      I personally would’ve done this, since although the WTFPL is an interesting license, I’d be hesitant to have any legal document which includes cursing, and is written in a way that sounds like a joke.

      1. Chris Robertson says:

        Both of your concerns are covered in the FAQ.

        Basically, putting things in the public domain may not be possible some places, and if you don’t like profanity (a) you can re-license the code to something without profanity and (b) it’s free speech and if you don’t like profanity… Go read the FAQ. I can’t find a way to condense it without the abrasion.

      2. Nentuaby says:

        The public domain isn’t an internationally portable option; a lot of countries’ laws don’t actually support dedication to the PD, works there can only enter it by expiration. Hence, maximally permissive licenses like the WTFPL or CC-0 which are identical to public domain dedication in the US do nonetheless have their place.

        1. ET says:

          Good point, thanks.
          I wasn’t aware that public domain wasn’t world-wide.

          1. MichaelG says:

            I vaguely remember reading that some places have “creators rights” that never expire. So there’s no way to truly release all rights and make something public domain.

  5. Mersadeon says:

    Maybe the show you’re thinking of was Sliders? I don’t know how old that is, I watched reruns of it as a kid, so maybe it’s not old enough to be the one you’re thinking of.

    Just as an aside: I love Sliders. Such a good show. And what a horrible way to treat that show. The last few Seasons were awful.

    1. Mersadeon says:

      Just looked it up, Sliders is way too new. 1995-2000 – so that is not from Shamus childhood.

  6. Kai v. Eggenburg says:

    That is a terrific result of an afternoon well spent. I just spent several minutes on a roller coaster ride without having to leave my chair. Thanks!

    1. Kai v. Eggenburg says:

      And actually, the not so smooth passages from one frame to the next, which might be frowned upon as insufficient programming, added to the realism of the experience. Yay for a bumpy ride!

  7. MDCore says:

    Shamus, have you considered automating your screenshots? Perhaps when you are coding what might end up on the blog, run a program which takes a screenshot every minute. Maybe you’ll catch more of that in-between stuff.

    1. ET says:

      Anyone know a good free and/or open source program for this?
      I think FRAPS does it, but only in the paid version. :|

      1. swenson says:

        No, you can do that in the free version as well. When I was getting screencaps for a text Let’s Play (…of sorts, it ended up more like a text Spoiler Warning), I used it. Quite handy for when you get in the middle of something and forget to take a screenshot!

        1. ET says:

          Oh, cool!
          I haven’t tried FRAPS in a while, so I guess I was remembering incorrectly.

      2. Richard says:

        Now, there’s a project!

        Write a little silly program that takes a screenshot of the active window at user-defined intervals.

        Might have a poke at a Windows version of that, I need an excuse to use some of the Windows APIs I just discovered.

      3. If you’re on Linux it’s a trivial one-liner:

        watch -n60 ‘import -window root $(date +%Y-%m-%d-%H%M%S.png)’

        You can use ffmpeg, or even a video encoder directly, to encode the result into a video later.

        1. Neko says:

          Note to anyone trying the above code: It won’t work if you copy-paste, because WordPress has in its infinite wisdom decided to change the single-quote character to ‘smart’ quotes.

          I think ‘code’ blocks work here, right? Or is it ‘pre’ that I need? Well, you could change it to use a different method of sleeping to get around that, anyway:-

          while true; do sleep 60; import -window root $(date +%Y-%m-%d-%H%M%S.png); done

          use ctrl-C to cancel it.

  8. Theminimanx says:

    It does feel a little bit too much like a rollercoaster. Not that I don’t like rollercoasters, I love them, but they don’t make good screensavers.
    I’ll just stick with pixel city for now.

  9. MelTorefas says:

    Man, this reminds me of my favorite screensaver when I was young. It was a maze thing with a “mouse” (triangle) that held the camera view, and an enemy “mouse” (other triangle), and both would move around the maze until one of them got to the exit (or found the cheese, or something). You could change the maze textures and such, and they were sort of random, but the “mice” would always turn in one direction. Still, I thought it was great, for some reason.

    1. Guvnorium says:

      Oh man, that thing was the greatest!

  10. Kyte says:

    Wow I managed to find myself in a perfect stop of 10 FPS and really bad appearance, unless was your intent.

    1. Kyte says:

      (Kinda miss post editing now)

      Anyways, given your tendency to optimize for the low-end case the choppiness was quite unexpected.

    2. ET says:

      Looks like it only might only work well on computers with dedicated graphics cards.
      My laptop at home works A-OK, but this machine at work, with its integrated Intel chip, is really slow.
      Like, not only is the framerate slow, but the simulation/update of the 3D tunnel is slow.
      Still, not too bad for an afternoon’s worth of programming.

      1. Kyte says:

        This laptop does have a dedicated graphics card, even if it’s an old one. It’s good enough to run Bioshock Infinite, at least.

      2. anaphysik says:

        On my integrated-graphics laptop, the screensaver runs INCREDIBLY slowly. The tiny-window preview given by the screensaver selector show it running pretty quick.

  11. MPR says:

    Battlestar Galactica had some pretty long tubes.

    1. Duneyrr says:

      I’ve never seen Battlestar Galactica, but that was hilarious.

  12. TMTVL says:

    Might see if I can get it to play nice with xscreensaver when I have an afternoon off.

  13. Exetera says:

    So, I very sloppily converted this to POSIX-y SDL code. I strongly suspect that this won’t run on Windows, because it uses some Unix time functions. It’s also not a screensaver. You can find the conversion here; you’ll have to compile it yourself, but I expect it to run on Linux and Mac OS X, and it requires OpenGL and SDL.

    I also made a few small changes; I sped the tunnel up a bit (change this back at the top of render.cpp) and severely reduced the line with (change this back at the top of render.h). Note that I messed with the line width because it was causing ugly artifacts on my system; the same could presumably happen to you, if you change it back. Additionally, if you want to change the window width and height, edit VWIDTH and VHEIGHT at the top of master.h.

  14. Paul Spooner says:

    Very cool! I tried it out and it displays fine. The only problem is that I work on a dual-monitor setup, and that puts the split right in the center of the display. Makes watching a bit less rewarding, but maybe that’s a good thing because I’m supposed to be working anyway.

    I wish there were more games made with this kind of “neon glowing stuff” aesthetic. Black Velvet Topia in Psychonauts has a similar feel. We’ve got to find someone who can use your talents!

  15. MichaelG says:

    Has anyone done a Dr. Who hyperspace tunnel screen saver? Might be fun.

  16. Cordance says:

    If you recall pixal city code got used to make an android screen saver from your generous donation of the code to the world. I dont know how much of a pain that is from where you at but it might be worth doing next time your bored and feel like scratching your own eyes out.

  17. Nick Powell says:

    I made it faster and increased the number of points in the rungs. Now it’s smooth as balls.

  18. SteveDJ says:

    Just looking at the screencaps you have here, something looks a little off in the next-to-last image (the one before the roller coaster image). It appears as if the tunnel is narrow at the bottom, and wider at the top — and as you planned, you are in the “middle” (both vertically and horizontally).

    But, it just feels as if you should be in the center of the widest point … so in this case, I’d think the camera should be a bit higher up. What kind of a challenge would it be to do that?

  19. Traiden says:

    Running the screensaver for more than 12 hours will result in extreme hairpin turns for each gateway. Just to let it be known.

    1. Paul Spooner says:

      This kind of community-based testing is fantastic for a software developer. It is even more fantastic in proportion to the quantity of details one can provide. Also, I’m curious. Screenshots?

      1. Traiden says:

        I am not sure how I might take a screenshot of the screensaver but the best I can describe it as if you had a sine wave of a very high frequency and amplitude for each gate. I don’t know how else I could tell you more. I leave my computer on for long stretches of time, so if you could let me know how I might take a screenshot of a screensaver without grabbing a camera and taking a picture that fashion I will upload it on the forum.

        1. Paul Spooner says:

          Based on my initial look at the code, the problem exists somewhere in “render.cpp”
          “RenderScene” appears to increment the float “flight_pos” without limit. My guess is that, after twelve hours, the float gets large enough that it starts to cause problems. From there “flight_pos” is used to generate “rung_now” (an int), which turns into “rung_in” when passed into “do_tube”, and then gets fed into some sinusoidal functions, as well as being used to drive “generate_hub”. Somewhere in that process, I’m guessing that the trig functions are receiving a really huge float, and going a bit crazy. I haven’t located anything specific, but re-compiling using a really large value to initialize “flight_pos” should expose the problems you saw without having to test for tens of hours each time.

          Further note, this is pretty clean code. The variables are named reasonably, there are a prudent number of comments scattered throughout. As such it’s a bit distressing to see the odd inconsistencies. For example:
          r = (float)rung
          (three lines later)
          vary2 = sin (r / 31.0f) * 17;
          (six lines later)
          elevation = cos ((float)rung / 17.0f)…

          Why not use “r” throughout? Did Shamus forget about the variable he made for this express purpose? Did he re-factor half the code and then get distracted? It’s not a problem really, especially for a throw-away project like this, but still rather entertaining to see.

        2. Paul Spooner says:

          I’ve definitely noticed this tendency as well. The lateral bending of the path increases in frequency as time goes on. It starts out at nearly zero, and seems to increase continuously.

          I skimmed through the source again, but I’m not familiar enough with it to know where this behavior might arise from. It doesn’t appear to be in any of the obvious places anyway.

  20. urs says:

    Man, I’d make sososo many screensavers… if my ways of programming worked outside of my programming tool.

  21. kdansky says:

    I’ve not used a screen-saver in about a decade. My screen just turns to black after a certain amount of time, saving some energy and light pollution. I guess I’m not a fun person to be around.

  22. Vegedus says:

    Having just finished a course in Computer Graphics, I understand now why these oddly elaborate screensavers and music visualizers exist. It’s just plain fun to experiment with creating pretty visual effects.

  23. neolith says:

    How did this not end up as a Doctor Who screensaver?

  24. Neil Roy says:

    Thanks for this. I look forward to taking a peek at your code. Damn you for making me run VS2010 rather than my beloved Code::Blocks. ;)

    But more than that, thanks for the laughs. I always look forward to reading your blogs. It’s strange, because I have been working on a game as well and am bored to tears from working on it, I desperately want to just get it done and release it so I can move on. I hate working on something else because then the game will never get done, I am sure you know what I mean. ;) but… maybe I’ll forgo that rule of mine and work on something new. You inspire me. LOL :)

  25. Jin says:

    I have ported this to OS X, for Mac people to try. I did this as an exercise in learning a little about screensavers, and a very little about OpenGL. I’m sure I didn’t handle everything in the best way possible, but it does appear to work. Without having run the original, I am not certain how faithful it is to the original regarding speed of display.

    ZIP file with XCode project is here. There is also a precompiled binary .saver file compiled for OS X 10.9 (not sure how it will work in earlier versions).

Thanks for joining the discussion. Be nice, don't post angry, and enjoy yourself. This is supposed to be fun. Your email address will not be published. Required fields are marked*

You can enclose spoilers in <strike> tags like so:
<strike>Darth Vader is Luke's father!</strike>

You can make things italics like this:
Can you imagine having Darth Vader as your <i>father</i>?

You can make things bold like this:
I'm <b>very</b> glad Darth Vader isn't my father.

You can make links like this:
I'm reading about <a href="">Darth Vader</a> on Wikipedia!

You can quote someone like this:
Darth Vader said <blockquote>Luke, I am your father.</blockquote>

Leave a Reply

Your email address will not be published. Required fields are marked *