Writing a roguelike - in Racket! (Day 0)

Back when I finished my 7DRL, I said that I was going to try to write a full tutorial series on writing a Roguelike in Racket, modeled somewhat on Trystan’s excellent series in Java: roguelike tutorial 01: Java, Eclipse, AsciiPanel, application, applet.

Well, it’s about that time. Technically, I’ll be starting next week. But to get that far, I wanted to make the ascii-canvas that I was working on finished and really solid so that I could actually have nice pictures throughout and not worry about working on both the framework and the tutorial at the same time.

So to that end, I present ascii-canvas:

Basically, I gave up for the moment on using fonts directly and fell back to a more traditional sprite sheet as a code page. This will also allow for a sort of tile graphics, albeit with a hard limit (at the moment) at 256 characters ((I haven’t actually tried a larger image…)). Here’s the image that I’m using for testing:

Anything in white will be drawing in the foreground color, anything in magenta will use the background color. My goal is to support grayscale images eventually with appropriate tinting, but that’s not currently supported.

The API is actually identical ChessLike, so I’m already familiar with it. Plus, it’s really straight forward to write. All you have to deal with is clear, write for single characters, write-string for strings, and write-center for centered strings. There’s no automatic line feeds like some libraries have, but that would be entirely possible to add in the future.

To show off a bit of what it can do, here are a few examples:

First, we just write out all of the currently possible characters:

(for* ([xi (in-range 16)]
       [yi (in-range 16)])
  (define c (integer->char (+ xi (* yi 16))))
  (send test-ac write c xi yi))

Next, let’s color them. You can add either just the foreground or the foreground and background colors. Any color can be specified either as a color string (see the color database for a full list) or using make-color with RGB. Here’s a nice gradient example:

(for* ([xi (in-range 16)]
       [yi (in-range 16)])
  (define c (integer->char (+ xi (* yi 16))))
  (send test-ac write c xi yi (make-color (* xi 16) (* yi 16) 0)))

After that, we can play a moment with simple centered strings (with foreground and/or background colors):

(send test-ac write-center "this is a test" 10)
(send test-ac write-center "this is a test in blue" 11 "blue")
(send test-ac write-center "this is a test in blue on yellow" 12 "blue" "yellow")

And finally, we have some nice screen corruption with randomly placed and colored characters appearing around the screen:

(thread
 (lambda ()
   (let loop ()
     (send test-ac write 
           (integer->char (random 256)) 
           (random 40) (random 20) 
           (make-color (random 256) (random 256) (random 256))
           (make-color (random 256) (random 256) (random 256)))
     (sleep 0.1)
     (loop))))

(thread
 (lambda ()
   (let loop ()
     (send test-frame refresh)
     (sleep 0.5)
     (loop))))

Or you could just run them all at once:


I think the most impressive example was taking the code and converting House on the Hill to use it (click the image to embiggen):

It took about 20 minutes to convert everything (and I got to learn about Git submodules in the process!), most of which consisted of flipping the arguments to the draw/write functions so the character/string was first. Here’s a diff if you’re curious: commit 2f6f7147. And dang does it look nicer. You can actually sort of see what’s going on, as opposed to some of the old images when half the characters were larger than the tiles.

If you decide to download the House on the Hill source, make sure you run git submodule update. For whatever reason, Git doesn’t pull down submodules by default (which will do a pretty good job of breaking things).

That’s all I have today, but now that’s out of the way–full speed ahead!