A small RPG & video game company

Name: Ostrich Riders
Version: 0.6.1
Author: Seby and Suiland
License: GPLv3
Operating System: Unix and Windows
Website: http://identicalsoftware.com/ostrichriders/

SFML

Some time ago I stumbled on a list of open source game clones. It includes a Joust clone called Ostrich Riders. The screenshots looked interesting so I decided to give it a try. The source comes with a cbp file used by Code::Blocks. A quick install of Code::Blocks and SFML library with the package manager for the distribution allowed the program to fail to compile.

The problem was SFML. For the transition from SFML 1.6 to SFML 2.0, the function naming convention changed. Sometimes libraries have to change interfaces due to a bad design. However I would argue that changing naming conventions is not a good idea. You force all developers to spend time fixing working code for no real gain.

SFML did far more than simply change the naming conventions. Separating an image in regular memory and an image loaded in the graphics memory is useful as operations on two objects are different. For most uses of the old sf::Image, you probably want sf::Texture instead of the new sf::Image class. For converting old code it would have been easier if sf::Image had been split into something like sf::ImageTexture and sf::ImageMemory. A typedef could even be included to make sf::Image become sf::ImageTexture. Other classes were renamed as well such as sf::String to sf::Text.

Even after converting all functions to begin with a lowercase letter instead of uppercase and modifying some class names, the old code won't compile. Some functions were replaced. SetX and SetY are no longer provided for sf::Sprite. Instead you must call the setPosition function. While I understand you will often be modifying both at the same time, keeping the old functions available wouldn't impose a huge maintenance burden while making life easier for developers using your library.

After fixing other renamed or replaced functions, a new function needed to be created for sf::Font::GetDefaultFont(). The function has been removed. Instead the developer is expected to open a font file to use. I created a simple function to load the Liberation Sans font. At this point the game compiled and ran correctly for a while before crashing.

Why did it crash? The greatest amount of original code for the conversion to SFML2 was the function to load the font. In the 16 lines of code in defaultfont.cpp, there was a bug. Instead of loading the font once, it kept loading the font file every call. Even though it was the same font file, loading it again caused former references to break. Even with really simple code you can forget something important.

The conversion wasn't too hard but SDL has also broken backward compatibility with the 2.0 release. They have a migration guide for developers. Granted I haven't tried converting any code so I don't know if it covers everything. Nothing similar seems to exist for SFML. I easily found suggestions with a quick search but feel library developers should provide more help to their users.

Overall Impression

The code is very well designed. It is split into two directories. The sfmlGame directory is a common base originally developed for FreeTumble based on the comments at the top of the files. The joust directory contains all the files specific to Ostrich Riders.

Memory management is mostly handled automatically. Any GameEntity derived class is automatically registered with the EntityManager. When the GameEntity is killed, the memory is released. I did find some memory leaks when looking at the code. A better fix than mine would be to use smart pointers.

One disappointment is the lack of a level editor. It is in the 0.6.0 release notes. There is a least one image in the files intended for the level editor but no source code to be found. Binaries packages for 0.6.0 included but the level editor but it is missing from the 0.6.1 release.

Third Player

I played a little with my oldest son before my youngest asked to play. As the game only supports two players, the reasonable thing would have been to let the two of them play. Instead I fired up GIMP to alter the colors of one of the player images. Adding a third player did pose a problem for score and lives. The UI only had spots for two players.

My initial implementation just avoided giving that information to the user. It was effective for my two boys who just wanted to play. There wasn't enough space to add another set of scores and lives. To avoid altering the image displayed for the scores, I created RotatingTextEntity derived from the TextEntity.

If there was only one or two players, they continued to function just like a TextEntity. With three players the text displaying "Player 1" and his score would display for ten seconds. Afterward it would switch to display "Player 3" and his score for ten seconds. The LifeEntity object was similarly modified. Some additional cleanup was needed to get Survivor and Cooperative bonuses to work properly

Why did I only add a third player and not a fourth or fifth? Partially because the effort to create a distinct enough image for new players. Also the game has four spawn points for enemies. With four players you could potentially kill all enemies before they could move. However, most of the ground work to support more players is implemented. In most places it iterates through all the players to perform actions instead of hard coding checks for three players. The game originally only supported one joystick and keyboard controls. With three players, one person needs to be on a joystick because three people around a single keyboard doesn't work well. The code has been modified to support more joysticks.

Packaging

As a longtime Linux user, I appreciate programs packaged for distribution. For a while now, I've been working to get Bt Builder added to Fedora. Before I could do the same for Ostrich Riders, one bug needed to be fixed. Whenever Ostrich Riders started, X Windows popped up a message saying it was not responding. This message is displayed because the program didn't respond fast enough to a request from X Windows. However the program was running fine.

My suspicion was the design of SFML. The library encourages the use of sf::WindowRender::pollEvent. Polling typically keeps the CPU active which is generally not considered a good thing. SFML avoids this by calling sf::WindowRender::setFramerateLimit. After asking on the forums and playing around with a simple SFML example, I created a similar program which didn't exhibit the problem. Another Fedora user also pointed me to a program using SFML which doesn't get the popup.

The core of all the programs were the same as Ostrich Riders. Removing the frame rate limit still caused the warning. Removing all the logic to move the entities and render the screen still caused the problem. Looking earlier in the code, I found it created the window, loaded the images and sounds, then started the main loop with the pollEvent call. Inserting a pollEvent call before loading images and before sounds caused the problem to go away. Reworking the code to load images and sounds before creating the window was the final solution.

Ostrich Riders needed additional changes to be packaged into rpm. The program assumed, it was being run in the directory with it's data directory containing all the needed images and other data. This is common for Windows but not Linux although it is done by many commercial games. Distributions prefer to keep the binaries in /usr/bin and other data in /usr/share. While you could use a shell script to change directory to a /usr/share directory and run the program that isn't very elegant. Additionally the program tries to the config file with any modified controls you setup and a high score file. Most users do not have write permission to directories in /usr/share.

The game does support Windows just changing it to require everything in /usr/share would break that. It would also prevent you from running it without installing it. To fix the first issue, Ostrich Riders now defaults /usr/share/ostrichriders under Linux and ./data under Windows. For testing without installing the easiest solution is to allow the data directory location to be specified with command line argument. Code::Blocks allows you to specify arguments to use when running the program. By setting this up new users can easily try the program within the IDE without even knowing the command line option.

Configuration files with user specified key configurations or other options are usually stored in the user's home directory in a dot file directory under Linux. High scores is not as standardized. If you want the high score file to apply to every user on the system you need the program able to write the file in a common location for everyone. However you don't want the users to be able to cheat by just editing it directly in another program. You could use setuid to accomplish this. I find it it more effort than it is worth. Far easier solution is to simply keep it in the same directory as the configuration file.

At this point a spec file is fairly easy to generate. Desktop and appdata files are added to allow the program to be launched easily and display screenshots. Generating the rpm file failed. Although Code::Blocks has a command line option to compile the program, it still opens a window. When building the rpm, I didn't use an account with access to X Windows.

While I could create a makefile easily enough, it would become out of synch with the project file. cbp2make is a program to generate a makefile from a project file. Ideally it would be a build requirement but cbp2make is not packaged for Fedora. Not wanting to package another program, I generated the makefile for Ostrich Riders and included it in the source files.

Future Improvements

There are some unimplemented features from Joust which could be added. The lava monster and pterodactyl are missing. Additionally braking in Joust lowers you a tiny bit. If a braking jouster hits a standing or running one in Joust, he loses. Ostrich Riders just bounce in a tie. My oldest has requested a boss monster. I'm considering a multiple segmented snake but haven't given it a lot of thought. This diverges from cloning Joust but many remakes add new elements. Some are great additions while others you'd rather forget.

Comments

No comments yet.




(optional, e-mail address only visible by admins)

Last modified: 2016-04-12, 02:08

© 2009-2022 Identical Games

powered by phpSQLiteCMS