Skip navigation

Tag Archives: sdl

Here’s the announcement of my latest programming project. It’s called Star Rover 2, and it’s a space flying game. You can fly around in space, trade goods, fight against other ships and complete missions for different governments. It features different difficulty levels, a high score list and several ways for the player to play the game. It’s also the first game I wrote in Haskell that’s actually playable.

Flying between planets

The game itself is quite simple: you start on a planet, and you can buy some cargo if you want before launching into the space. In space, you can fly to other planets and see if you can sell your cargo for a better price. There are other ships in space as well, and you’ll get interrupted every once in a while when coming across one, with the possibility of attacking the other ship. If you win, you get their cargo, and the various governments may have their opinions about the attack as well.

(it looks better in motion :)

Combat in Star Rover 2

As the game progresses, you may earn a reputation among the governing bodies, which leads to new dangers and possibilities. The international relationships are complicated, and attacking a ship of one nationality may not only affect the nationality being attacked but their friends and enemies as well. By playing your cards right you can receive missions from governors, and by completing them you may boost your ranking further.

Captured cargo

The game is quite non-linear; it ends when your ship is destroyed often enough and you are too weak to continue, or when you choose to retire. At the end, your achievements are rated and you may make it to the high score list. Until then, you may choose your activities freely.

You can find Star Rover 2 at Hackage, so if you have cabal, you can install it by running cabal update && cabal install starrover2. You can also fetch the sources from github. As for dependencies, you’ll need SDL, OpenGL and FTGL.

In the beginning, Star Rover 2 was more or less a test of whether I can actually concentrate on one project enough to have a playable game in the end, and I’m glad it’s now reached a state where it can be released. Other than that, I was curious to see what programming such a game actually is like in Haskell, and I’m quite pleased with the results. I started working on Star Rover 2 on my spare time pretty much exactly a month ago, and now it amounts to about 2000 lines of Haskell code. I was a bit worried I couldn’t write a larger project in Haskell, but now I can see how well Haskell scales up to complex tasks. This was also my first project where monad transformers actually came in very handy.

Any feedback and bug reports are of course very welcome.

It’s time for a small post again. I haven’t updated my blog for a while, but for a reason: there hasn’t really been anything interesting to write about lately. Don’t worry, I’ve been working on my project, but rather implementing it than designing it. The last time I wrote about AI and mentioned it’d be the next thing to implement for Freekick. Well, the basics of AI are there, as well as the basics of everything else (server + client + the organizatory part). I’ve spent the last month writing the AI, writing a client (i.e. a window to the soccer pitch) and making sure the thing doesn’t crash by itself. Sounds like a 0.0.1 release, doesn’t it? Yeah, we’re that far already.

To the disappointment of neural network fans I haven’t implemented them at all in Freekick AI, not yet. The basic structure of the AI is slowly coming together, and when I can concentrate on the details, I’ll try and make some use of neural networks. At the moment, however, the AI follows simple logic for decision making that will be refined later. Having a simplified AI at this stage is helpful because it lets me concentrate on figuring out the bigger picture of the AI functionality.

The current AI is roughly split into two parts, one that defines the possible actions and another that compares these actions with each other and chooses between them. Here, defining the possible actions also includes a set of helper functions such as for finding the best spots on the pitch for scoring or the chances of a successful pass to a teammate.

Splitting the AI code like this makes maintaining it easier than if it was one bloated, monolithic monster. Improving the code should also be simpler in the long run, because if the two parts only communicate via clearly defined interfaces, one part could be swapped or reworked without interfering with the other part. This way I can first make things run with simple logic and when the AI starts to seem too stupid replacing parts of it with, say, neural networks shouldn’t be a big problem. At the moment, though, the AI code is rather transparent (with 10 files and 400 lines of Haskell code), but when the code grows, it will be necessary to make this division even clearer.

I then went on to write an SDL client for Freekick. It’s actually a bit early to call it a client, since there is no single player (nor multi player) mode and the client doesn’t control a player but merely spectates the match, but for now it’s enough to see what the AI is doing. A simple single player mode with some awkward controls will be added later. The client is very ugly, though, and thereby reflects my artistic skills rather perfectly. Here’s a screen shot.

Soccer in all its beauty.

Soccer in all its beauty.

Here it probably starts to become clear for everyone why I wanted Freekick to be so modular. The client is just a client, its duties are merely receiving the match status from the server and displaying it as it sees fit, as well as taking input from the player. It can be exchanged or rewritten in another language without the need to touch the rest of the game logic. I’m also planning on writing an ncurses client for use in non-graphical environments (as if the SDL client wasn’t ugly enough).

As for the server (i.e. the code that handles the network, communication, enforces soccer rules and world physics), it’s running with no major problems. Minor problems include network code that has problems handling disconnecting clients and relatively inaccurate physics, but for now it’s adequate. Probably the biggest thing that differentiates Freekick from a real alpha version of a very ugly spectator only soccer game is (along with the fact that the match actually never ends) that there is actually no connection between the “organizatory part” (i.e. choosing two clubs that play a friendly game against each other, or starting a knockout tournament) and the actual, viewable match.

This all means there is still some more work to do before Freekick could be considered usable. But in the spirit of “Release early, release often” I’m giving you the code (written in Haskell as usual) already anyways. If you have darcs, the easiest way to the code is “darcs get http://code.haskell.org/freekick/”, but there are also tarballs of the code as well of a binary version (x86, Linux) at http://finder.homelinux.org/freekick/files/. With enough playing around one might be able to start the thing, but I’ll write here the way it’s supposed to work anyway. First you start the server (“physics”) with a matchdata file (“matchdata.md”) as parameter. Then you start both the client and the AI, which both connect to the server. AI interprets the information from the server and sends the desired player actions to it. The client displays the players in all its SDL glory. And voila, you’re witnessing a soccer AI experiment.

From the issues mentioned above, the ones I’ll be concentrating on in the near future will be the ability to actually play the game and control a player, finishing up the match flow (i.e. ending the match at some point), and tying the organizatory part together with the match part. After these steps, it’s probably time for some polish, like a main menu, configuration options and a prettier client. As for the 0.0.2 release, it’ll be available, soon. I’ll keep you posted.

I’ve been tinkering with my project in the past week so much that it’s time for a small update again. The last time I wrote I was starting to get to know Haskell better. I also wrote some Python scripts to create some XML data to be parsed and serialized by my Haskell code. Since then I’ve written a small Haskell program that reads in the XML data (with a slightly improved XML serializer) and creates small soccer cups. Since the results are generated randomly, the next steps for my project would be both simulating match outcomes in a more realistic way and programming the actual soccer match.

This is where I have to think some more about the actual software architecture of my game. The ones who played Sensible World of Soccer may remember how the game seemed to have two major modes, the “organisatory” mode with menus and league tables, and the “match” mode with the actual, well, match. (Later soccer games probably have a same kind of division.) I’ve been playing with the idea of dividing my game to two separate processes, one for the organization and other for the match. In the past few days I’ve been reading The Art of Unix Programming (a book I sincerely recommend, even if you’re programming for other OSes), which inspires me regarding modularity in software even more.

The basic principle I’ve been thinking of is that the organizational part creates a temporary file with the data about the clubs that will play against each other, time, place, etc. and starts the match process with this file as a parameter. Match process then reads in the file and plays the match based on the data. After the match is finished, the match process writes another file describing the result and maybe possible player injuries (if I ever get that far). The reason for this is simply making the programming work easier; I can fiddle around with one part without being able to break the other one, and I can even program the two parts in different languages without problems.

While planning the architecture I actually went even a bit farther than that. When the match starts, I’ll have more than one process doing the work. Simply following the Rule of Modularity, I’ll have a small server-client structure, with the server having the information about the match and doing all the AI, and client drawing the match and handling the controls as well as other user interface.

And that’s not even enough modularity for me. The server process should have a frontend that actually communicates with the client and handles the physics and player movements based on the input from the client(s) and from the other part of the server – the AI process, which calculates the AI actions and passes the AI “input” to the physics part of the server. I actually wanted to go as far as dividing the client to two processes, one process handling user input and another drawing graphics, but that would probably make the implementation too difficult.

So, in a nutshell, the server part consists of two processes, AI and physics. The client part sends input to the server (physics part) and draws the match. The physics part of the server receives input from the clients and AI process and calculates the player positions as well as the rest of the match data, sending the data to both clients and the AI process.

At this point a reader might wonder why make it so complicated. Well, I want it to be modular, and I don’t think a plugin architecture would really be enough. I want the game to be easily customizable, so that one can e.g. write his own AI component and use it with the rest of the game, as long as he follows the protocol. Or, put another way, the client side I will program will probably be ugly as hell, and if someone wants to make it better he can just exchange that part without having to reprogram the whole game. The architecture also makes the game playable on older hardware, if a lightweight client is implemented as well. (I’m thinking of ncurses.) In the end it’s basically the same principle as in Freeciv, with the server having the game data and client displaying it (but with even more modularity).

The other reason why to divide the game in processes is that I want to make using several programming languages as easy as possible. That way, people wanting to hack with the game are not restricted to the programming language(s) I’ve chosen. For example, I’ve done a bit of programming AI in C in the past and I started to get the feeling that a linearly increasing complexity of the AI makes the code exponentially complex. Still, I’m sure there are people that can program better AI in C than what I can do in Haskell, and it might as well be that I’ll decide to use C later after all. I also don’t think I want to program everything in e.g. Haskell (which seems to fit well for AI), especially the client side. (There are SDL and OpenGL bindings for Haskell though.) In the end, I will probably use quite weird programming language combinations and I don’t want to mess with foreign function interfaces too much, so separating everything into processes feels like a good idea.

One may also wonder how badly the performance of the game is hit when it is divided to so (relatively) many processes. I looked at Beej’s Guide to Unix Interprocess Communication (my game should be cross-platform in the end, though), and it seems like the most efficient way to do this is through shared memory. Since I’m not really sure if that plays well with higher programming languages like Haskell or Python that I also planned on using on my project and since I thought having the communication streamed would be the easiest way I decided to go for good ol’ BSD sockets. They seem reasonably fast and another bonus with them is that the possible inclusion of multiplayer in the game would be smaller hassle.

Another point from the book mentioned above I also want to follow is first getting the program to work, then getting it to work well. Probably the biggest reason why the software I’ve written until now was never really ready to be released is that I always wanted to make it huge from the start. (Actually, if you look at this project, I’m still doing it.) Dividing the project to so clearly dividable modules makes it possible for me to actually try to program each module in a quick and dirty way just to get a prototype done, and improve each module separately later.

In other words, the next step in my project is to write small functionality for each part of my project and make them work with each other. Since I’m lazy, I thought about doing the client side either with Pygame (the SDL bindings to Python) or just reusing the C++/SDL code I made a couple of months ago that displays a simple soccer pitch with some triangles as players. I’d like to do the AI part with Haskell, since I can imagine how pure functions and lazy evaluation make that task easier. And besides, I think it’s a great language (once you get the hang of it). The third process of my project involves physics, i.e. moving the ball and the players depending on their actions, which may not be a very difficult thing to accomplish and I might as well program it in C.

Of course, another difficult thing is getting the parts work well with each other and designing the protocols between them. That means I still have some planning ahead before I actually get to writing the code, but when I do, I hope it actually doesn’t take forever before I have something to show. When I do have something finished (whenever that may be), I’ll set up a (darcs) repository for the readers to have a look. In any case, when I have some new design or code to write about, I’ll keep you posted.