Common lisp is a wonderful language, a lot of people tend to think it is a functional programming language, and while that is not a bad thing, Lisp is not a functional programming language, it is a multi-paradigm programming language. While it is not considered good Lisp style, you can program in an imperative way; Why am I telling you all this? well, because people always object that being functional makes it difficult to program games, which is not completely true either, but Common Lisp will work with you and not force you to work around it.
While I am in the theme of fallacies, another false misconception about Lisp is that it does not have libraries, it does have more than a descent amount of native libraries, Common Lisp implementations also have FFIs which has allowed to create bindings to very useful C libraries, and since bindings are commonly not “Lispy” some times we have great adventurers creating wrappers that made them feel like they were written for Common Lisp.
So, What do you need to program a game?, in the simplest terms you need:
- Output: A place to show text, graphics, lights, sound or whatever your game uses for interaction with the user.
- Input: Devices to interact with the game (i.e, move the character, move icons, write text, etc).
- Assets: Different types of things that go into your game (images, models, sounds, maps, music).
- Constraints: A set of rules that physically or logically constraint the actions that you as a player can do (i.e. physic engines)
- Logic: A set of rules that affect how the user interacts with elements in the world. (i.e. open a chest, a door, use a computer etc)
You might argue there are more things, but to me this five make the core of what you need. So lets break this down for Spycursion, which is our game, I will intentionally leave out the socket magic happening between the client and server, which is necessary in any MMO.
There are two types of interaction in our game, the Computer GUI and Terminals and the 3D world.
The computers in Spycursion are meant to look like real computers, once you start using a computer you will either see a GUI environment or a Terminal, so what we need here is a GUI library, we could (and actually thought about) write one from scratch, but with so many solutions in existence out there we decided to use one with the characteristics we needed, and the winner was Qt, one of it’s redeeming qualities being portability, which is important when you are writing a game that runs in Linux, Mac and Windows. To write our Qt in a lispy way we use the fantastic Qtools library written by Nicholas Hafner (a.k.a Shinmera).
Qt provides the necessary tools to import icons, images, play sounds, and even render html, so it is relatively easy to get a full screen application that looks like a computer desktop.
Constraining a GUI is very easy, you just provide the programs that you want people to be able to use, and what those programs are capable of doing. Constraining a terminal is even easier, you just decide what commands exist and how they interact with others (piping, I/O). In both cases you can restrict user rights, so it ends up being a bit like real life system administration, but with more control.
Implementing Logic in Qt is very straight forward, you can decide what happens when you press a button, hit enter, change text, etc.
I won’t provide examples because there are plenty on the Internet.
Spycursion 3D World
Since we are shooting for a 3D world the safest bet is to use OpenGL, Lisp has the cl-opengl library, but that is too verbose, the good news is that Chris Bagley (a.k.a Baggers) created CEPL, which has as a design goal, and I cite “… making the user feel that GPU programming has always been part of the languages standard.”, asides from that promise, Baggers has spend hours doing great videos which he has shared on Youtube.
To run OpenGL you need what is called a surface, which is basically a graphic container, when we started doing this the only stable option for CEPL was SDL2, so we to use cl-sdl2 too. The library, in this setup, is used only to have a display window, but it is capable of a lot more, as an example you can look at sketch, which you could use to create 2D games.
A lot of the things we care about were also concerns to Baggers, and he has a whole ecosystem of related stuff, some of which even come installed with CEPL or are part of it, for Input his contribution is called skitter, which allows us to detect mouse movement, position, clicks, keyboard presses and all that jazz, it can even handle game controllers. While we use it with CEPL it is independent of it.
So far we have been worried more about showing a 3D world, some menus and text, so I will talk only about those aspects, of course there are options to import and play sound, but I will focus on 3D models. You should be able to use a 3D modeling program to create your assets, save files, and get the data from those files imported into your program, that is the job of the great assimp library, and of course we have classimp which is classier ;-), with that library you can import several 3D model file formats, so you can use a variety of programs to create your model, including free options like Blender, or you can buy them in a format you can use. Of course this only creates a data structure, so you have to do all the wiring yourselves, but you will be able to import models including the animations which you need for your game.
All constrains and logic are programmed in Lisp, with some help from stenciling, this is one of the few instances where we used cl-opengl directly instead of using the CEPL scaffolding. In general Common Lisp is a very potent programming language, so writing logic in it is very straightforward and flexible. We are currently not using physics engines but there are libraries for that too.
Some final thoughts
There are many wonderful tools you can use to make your game, we are just talking about the ones we used, you could use Xelf for 2D games, or Trial for 3D and 2D, there are libraries for text rendering both in 2D and 3D, libraries to do text based games (i.e. cl-ncurses), tools for importing and playing sound. There have been games written in Common Lisp in recent years, and there are Common Lisp game jams (the next one starts on April 18th, 2019), the fact is that writing games has been improving the ecosystem.
If you ask for it, we could expand in some of these themes, but the basics are the same, choose the type of game you want and the look for it, choose the adequate input and output libraries, add suitable libraries for importing assets, use some libraries for collision detection and physics if necessary, add your own logic, mix everything with tons of creativity, and you’ll have a game.