4 Hugues Ross - Blog: 09/01/2014 - 10/01/2014
Hugues Ross

9/29/14

Let's Make a CLI Game! - 1 - Limits

Previous PartNext Part
Just like I said in my last post, this is a tutorial series where we'll follow my attempt to make a strategy game designed to run on the command line. I'm going to be doing this in C, so I recommend that you learn the very basics of the language if you decide to follow along on your own. Lastly, while I'm hoping to teach you something, if you think I've made a mistake or need to be informed of something, then by all means email me or leave a comment below.
WARNING: The following tutorial segment is entirely preparatory. There is no code here, only reading. I think this information is important, but if you don't want to read it then just get through the final section, labelled 'Next Steps.' The next installment will be a bit more exciting.


When you start any coding project, it's especially important to know the limitations of your platform. If you don't, you're liable to cause yourself all kinds of problems later down the line. This can be especially true when you work with something as 'different' as your average terminal. Terminals can be quite limiting environments compared to your average graphical window. Let's examine some of these limits:

The first of limiting factor relates to how things are displayed in a terminal interface. Generally, text is added line-by-line to the window, and there's no apparent way to alter this. It is possible to do so, however. Most(all?) terminals provide a set of special escape sequences that allow you to perform various functions, like moving the cursor, changing text color, and so on. You can actually use these yourself if you know what they are, but I seriously wouldn't recommend it. Instead, the best solution is to just use a library for this. For this, I recommend curses. curses is pretty much the go-to library for building TUIs on most systems. It's extremely common on Mac and Linux systems, and there's a port called pdcurses for Windows. It does a few odd things, but it's common and reliable.

Now, after getting around the first problem we come to another: speed. curses, wonderful as it is, is a bit slow compared to modern hardware-accelerated graphics libraries. It doesn't take long to display things, but if you expect to have a gorgeous 60FPS then you are in for a major letdown. This is probably why most command-line games either have very low framerates, and very little to draw. In fact, if you're making a turn-based game you may be better off forgetting FPS altogether. You'll probably want output to be more reactive, only drawing when things change. This means forgoing most animations, but it also makes things much simpler to work with. Not only that, it may also let you use more complex calculations in your game, which is always a plus.

So far, our issues have been fairly simple. However, the next one is a bit harder. Depending on what sort of terminal or terminal emulator is being run, you're likely to run into color-related issues. Most terminals fall under one of these categories regarding color:
  1. Black and White - Monochrome terminals aren't as common as they used to be, but they certainly still exist. 
  2. 16 colors - As far as I'm aware, most color-supporting terminals have the same general default 16 colors. They are split into two sets, 8 normal and 8 bright. The colors are black, red, green, yellow, blue, magenta, cyan, and white. Generally, this makes the first 16 colors set for a terminal easy to guess.
  3. 256 colors - I believe this trend started with xterm, but nowadays this is fairly common, albeit less so than the basic 16.
  4. Full 24-bit color support - These are rare, but I've heard they exist. 24-bit color is equivalent to what you can normally draw to a screen(ignoring alpha). I've never tried to code for/use one of these before, so I have no real idea how it works.
As you can see, that's an incredibly wide range. Most games and applications generally seem to target the first two, since they aren't too far apart. However, since I'm building a game I'm going to try to support 256-color terminals as well. Another related difference is palette swapping. While the default colors are fairly predictable, many terminals allow you to change them. If that option is available, then much more can be done. However, just like every other feature it isn't guaranteed. Depending on how many optional graphical features you want to add, the complexity can ramp up significantly. Being a coding masochist, I've chosen most of them, but I'd recommend that a less experienced coder try to stick to simpler configurations. A good easy setup would be to try black+white paired with 16 color support, and maybe add 256 color support later if you feel up to it. Palette swapping can get very messy, but can have a great payoff if you have a solid understanding of it. If you don't believe me, look at these.

The final, most obvious limitation is the medium: In the terminal, everything is text! In fact, it's usually just ASCII. Sometimes other fonts and character sets can be supported, but that's no more reliable than color support is. Depending on what is being represented there are a number of methods for displaying things. If you want to draw something large and potentially elaborate, then ASCII art may be the right choice. However, if you want to draw a lot of smaller things, then you may want to only give them one character each, based on what they are. Players are often represented with an @ sign, a dragon could be an uppercase D, and so on. You aren't restricted to using one form of depiction in a game, but it needs to at least make sense.

Now that we've examined our target platform, we can really start. That'll have to wait until the next installment, though. For now, let me thank you for  reading through all of this. I promise we'll start coding soon! Next follows a short section that I'll be putting at the end of each tutorial segment, where I provide some tasks for you to try and complete before continuing to the next.


Next Steps:

  1. Come up with an idea for a game, or adapt one that you already had according to the issues addressed above.
  2. Decide what sort of terminal setups you'll be targeting.
  3. Get set up. Make sure you have a decent environment for C programming, and curses. Ensure that curses programs compile and run properly. While you're at it, make sure that the terminal that you use matches your target(s). If you have multiple targets, you need to make sure that you can test for all of them.
  4. Look over an ASCII table, and think about how to best depict the elements of your game.
  5. If you don't already know how, learn to use a version control system. I recommend Git, but plenty of options exist. This isn't required, but if you plan to code any decently large projects then it'll help.

Tutorial: Let's Make a CLI Game!

Next Part
Recently I've been playing XCOM (both of them), and they've left me wanting to make something similar. As far as I can remember, I've never actually made a strategy game, so I think it would be a fun learning experience. That said, my 7DRL attempt has gotten me thinking about the terminal more, and I think such a game would fit perfectly on a platform like this. Thus, I've decided to try and make a strategy game for the command-line. At this point, you may be wondering: "What does this have to do with a tutorial?" and the answer is simple:
I've always wanted to give something back to anyone who reads this blog, so from now on I'll be writing tutorials and posting them up here! Thus will be the first series, but you can expect more in the future. Eventually, I'd like to see this blog become mostly a collection of information and resources for devs, and this is the first step in that direction. As I create this game, I'll be writing up posts explaining what I'm doing, why I'm doing it, and how I'm doing it. I hope you'll stick with me for this experiment, and hopefully the first real post will be up later this week.

Even if you're just curious I encourage you to stick around. You're bound to learn something!


One final note: These tutorials will take considerably more time and effort than my usual posts, so don't expect them to show up as often.

9/27/14

Singularity Update 6

Changelog

-Added basic support for RSS enclosures.
-Made some improvements to the feed adding dialog.


Adding Feeds

When I released Singularity last week, you could already add feeds to the program easily enough. However, there were a number of small annoyances concerning this. Originally, I had the dialog hide itself when you did anything with the main application, but I found it to just be an annoyance. Finally, I've gotten around to letting it stick around. Additionally, the url input on the popup was accepting extra lines, resizing the dialog when when it got long urls, and just generally being a pain in the butt. This has been fixed. However, these changes are just temporary. I plan on redesigning some parts of the UI based on my own experience using the program.


Redesign?

Right now, Singularity has most of its screen space taken up by a web view. If you're trying to read some updates, this is great, but any other action renders the area completely useless. Thus, I've decided that most of the UI that was going to be put in dialog boxes is going to go there instead. That way, the space won't be wasted. I haven't tried this setup yet, but I think it'll work much better than what I'm doing right now.

9/21/14

Singularity 0.1 Released!

It's been almost a full month since I started rewriting Singularity, and almost a year and a half since the project was originally announced. This makes Singularity my longest running (regularly updated) project. That's partly why it's such a relief for me to announce the very first public release of the software! All of the project's source code is freely available on Github, under the GNU General Public License.

For those of you who aren't aware of what this is all about, or perhaps have forgotten, here's what this is all about:

Singularity is a simple GTK-based RSS reader. Development was started when Google first announced that Google Reader was being shut down. The project has come a long way since then, with 3 major releases(although this is the first public one), each one featuring a codebase rewrite. The first release, 1.0, was little more than a basic proof of concept. The entire app spanned only two code files, was filled with strange and arcane workarounds to simple problems, and was developed in a very short span of time. Regardless, it did its job(somehow). Afterwards, I felt the need to try and turn Singularity into a halfway decent piece of work. This led to version 1.5, released fairly soon after the 1.0 release. This version was much better than the last, and is the longest-used version so far. However, it wasn't very well designed, had a fairly large number of issues and missing features, and slowly acquired quite a bit of cruft. When I revisited the project this summer, I considered working with the code that I had. However, After spending some time reviewing it I decided it was best to get a fresh start. To that end, I rewrote the whole thing again, and even rolled the version number back to 0.1. That brings us to today. I've used 0.1 for a couple of weeks, even as development continued, and I think I can safely say that it doesn't have any massive issues. There are still bugs, and there's much more to be done, but it's a decent start.

Here's what features are in this version:

  • Subscribing to/unsubscribing from feeds, and getting updates.
  • Viewing specific feeds, or just reading unread items
  • automatic deletion of old items that have been read (This is the only thing that I haven't tested thoroughly. It should work fine, but I'll know in a week or two if it doesn't.)
  • Partial RSS, Atom, and RDF support.
  • Partial custom themes
The list is pretty short so far, but it's a solid start. The most essential parts are all there, and now it's more about improving quality than just getting the thing to work. At this point, updates will probably be a little infrequent. I've got plenty of other projects in mind, after all. Of course, I'll probably never drop support, since I rely on this app myself. You can rest assured that I'll be keeping this thing in working order for a long time to come.

9/17/14

Fixing things up, part 1

UPDATE: The new games page is up! Go check it out!

Since creating this blog, I've done very little to the content apart from occasionally changing the canned theme. As a result, things have gotten a bit messy around here. Today, since Singularity's new release is done, I've decided to blow out the cobwebs, so to speak, and make the site a little bit nicer.

The first change is coming to the games page. Currently, the game content is poorly formatted, overflowing in some areas, and generally looks like crap. I've redone a portion of the page, and I think I've made some big improvements to the way everything looks. I've added a header to each project, adding a header and some symbolic icons showing the target platforms. I've also messed with the alignment to make sure that noting spills over: The images stay on the left, and the text stays on the right. Overall, even though the changes aren't huge I'm quite happy with the result. Here's a side-by-side comparison of the old and new layouts:
This new change should hit the main site within a day or two.

While I was at it, I also removed a few widgets that I didn't find very useful, and added a custom favicon based on the DFEngine logo. It doesn't seem to have updated yet on my end, but it'll probably be there soon.

I plan to make more changes in the future, but I think I'll leave things at this for now. Hopefully the site will continue to improve as I work on it! If you have any feedback about these changes, or want to make a suggestion, leave your thoughts in the comments below or email me at hugues.ross@gmail.com.

9/16/14

DFEngine Update 7

Changelog:

  • Removed Tweens
  • Upgraded the collision handling. Scripts can now be called when an object comes into contact with another, maintains contact, or loses contact. This should make some things faster and easier than they were before.
  • Rewrote the code for creating PhysicsComponents. It's far more intuitive to create them in scripts now. Also, you now select the shape on creation. Currently the only shapes are Box, Sphere, and Capsule. However, I'll be adding support for custom models shortly.
  • Started working on raycast functions. Eventually, this will let you check if the mouse is over a particular object, which will be great for FPS games.
  • Moved the model drawing code to its own place(again). The custom drawing functions are back, but now they can draw anything.
  • PhysicsComponents now share their angular factor with scripts. In layman's terms, it means that you can now control how objects rotate on each axis.
  • Transoformation data is now stored inside the Entity class, not the PhysicsComponent. This means that you can put a GraphicsComponent onto an entity without forcing it to have physics as well. You can also now access rotations as either quaternions or Euler angles, depending on your preferences.

I always love a hefty changelog. The game jam did a lot of good, and it inspired me to work on DFEngine quite a bit. Unfortunately, I had quite a bit of homework, and didn't manage to finish the game I was making, but at least I was still very productive! There are only two downsides to this slew of updates: First, Tweens were removed. It needed to happen soon, since they were always causing tons of issues, but I don't yet have a suitable replacement. That's probably the next thing that I need to do, before anything else. The other downside is that the new PhysicsComponent creation code doesn't let you do as much as the old one. To be fair, I mostly removed the features that won't often get used, and it makes things much simpler. However, I still need to make sure that these features can still be used somewhere. I haven't checked yet, since the change was so recent, but it shouldn't be hard to replace anything that I've removed. Once I have both of those issues cleared up, I'll probably start working on a basic editor. It's one of the things that I've been missing for a while when using this engine, and I think it'll help me get interested in making games again.

Singularity Update 5

Changelog:

  • Upgraded to use a newer version of WebKit
  • Links now open in your default web browser
  • Fixed even more bugs regarding parsing and such
  • Items are now marked as read when you see them, not when they are loaded into a view

This is starting to get a bit silly, so I'm releasing Singularity before the end of this week. Already, this version of Singularity greatly exceeds my expectations for a 0.1 release, but general nervousness and an inability to call the version done have held it back. I'm going to figure out licensing, stick it up on Github, and post the link up here. Hopefully, it'll be done in a day or two. At worst, I'll finish before next Monday.

9/13/14

Autumn Game Jam, 24 hours in

Like the last jam, I'm going for something simple. DFEngine works, but it's not at a point where I feel like I can do a ton with it. I think the biggest reason for this is that it take s a while to get things done still. Things are slowly getting better on that front, but it definitely places a big restriction on me when I'm jamming.

Here's my game so far, which I've affectionately named 'ANGRY SUN AAAAAARGHHHH!!' The sun has gotten tired of setting, and now it's taking vengeance on humankind. So far, there's no way to win or lose, just fire big molten rocks at random civilians and rack up points. I might keep it that way.

9/12/14

Autumn Game Jam - Surprise!

Out of a mixture of business and laziness, I've neglected to mention that this weekend is a game jam at all! As always, I'm participating. This means that I plan to delay my update posts until this Sunday, after the jam ends. This will not only give me more time to write them, but it'll also give me a chance to discuss any updates to DFEngine that I make during the jam.

For now, I'm tired so I'll just post the theme: Twilight

9/5/14

Singularity Update 4

Changelog:

  • Added support for RDF feeds
  • Tested 252 different feeds on Singularity, currently 251 of them are correctly handled.
  • Fixed a ton of issues when trying to get/parse feeds in various situations.
  • Added icons to the GUI that display the load/update status of each feed.

I really want to release Singularity as it is. I really do. At this point, the old version doesn't even compare to what I have now, and I'm starting to get antsy. However, there still remains one obstacle before I can put out a release. Currently, clicking on links will open the contents in the same view that's being used to display feeds. Obviously, that's a bit of an issue. The old Singularity doesn't have this issue, but it has a bad habit of opening embedded content in a browser window. It's a small annoyance, but with larger feeds it can get quite out of hand. I want to find a better solution before I release this version, since being able to actually open the links that come in is (obviously) a very important part of the software. Once I figure that out, I'll be set to release this version. This time, it's good enough to provide publicly as well. I probably won't post another update on this until the release, but I also expect the release to come next week so it shouldn't make any difference. When that post DOES come, I'll give a general round up of what's there and talk about the future of the project a bit.