cs349 - Developing User Interfaces - Spring 2010

Assignment 1 - Game interfaces. 2D graphics - Draft.

To be handed in: In class, 13.30, 24 May, 2010.

Game programming

When programming a game it is normal to use programming techniques that allow the tightest possible control over what happens on the screen, and when it happens. The architecture appropriate for such programming is the event loop: a single-threaded flow of control checks for an event, responds appropriately to it, then returns to check for the following event, and so on. There are two types of event loop.

  1. Blocking. The function that gets an event blocks until an event is available.
  2. Non-blocking. The blocking function that gets an event is protected by a test to see if any event is available, allowing the program to change state in response to no event.

Blocking event loops are paced by user actions; non-blocking event loops must be paced by some other method, usually calls to a real-time clock.

Game programming is usually done assuming that program performance will not be degraded by other users of the computer on which the program runs, which will, unfortunately, not be true for you, at least when you program in the undergraduate environment. (Please remember that we will run your submission in the undergraduate environment, so allow yourself time to port your sbumission, and to tune it, in the undergraduate environment.)

In addition to the event loop you will need a graphics model so that you can draw things to predictable places on the screen and get input from the mouse.

Thus, the purpose of this assignment is to give you some implementation experience with three important concepts:

  1. the event loop,
  2. two dimensional graphics, and
  3. managing the sequence of things that occur in a user interface.

In doing this assignment you start with a program that does simple mouse/keyboard interaction. This program is written in C, using the Xlib library, which implements a 2D graphics model similar to the one described in class. You are assumed to be familiar with C programming and I expect you to acquire information about Xlib functions you wish to use from documentation like the following examples.

It is also useful to have some example programs to examine. Here are a few I have found on the web.

This process is quite simple: you know roughly what you want to do on the screen, and look at functions with suggestive names until you find the right one.

The Assignment

The game is played in a window, which can be moved around the screen, iconified and resized without influencing the progress of the game. (Except the player's ability to figure out what to do next, of course.)

The window contains a crate of bottles, each of which contains a jinn. (A jinn is a magic being, usually evil, who is able to operate without regard for the normal laws of physics. Bottles containing jinn should be kept closed at all cost. Escaped jinn -- the plural of jinn is jinn -- often try to do very bad things to the person who helps them escape. Typical jinn reasoning goes like this

During the first century after the strong magician imprisoned me in the bottle I promised myself that the person to release me would be given the right to the fulfilment of any three wishes they would choose to make. During the second century, I promised myself that the person to release me would be given every benefit I can provide -- riches, beauty, respect, love -- and that I would be their slave for an entire century. But during the third century I became impatient that the person to release me was being so slow to do it. I decided not to provide them with anything, but as a reward for releasing me I would let them live. Then, during the fourth century I became very angry with the laziness of my releaser, and I swore to eradicate them and their children, and their children's children, until the end of time. But as a reward for releasing me I would allow them to choose the manner of their death. Now, how would you like to die?

Obviously, the player wants to keep the jinn in their bottles.)

Unfortunately, the crate has been jostled, and some of the magical seals loosened. A loosened seal allows the cork of the bottle slowly to push out of the bottle, like the loosened cork of a bottle of champagne. The player has to move the mouse over the cork, and click the button to push it back into the bottle. If this is too slow then the jinn escapes and the game is lost. The process running the game, and its children and its children's children, are all terminated with utmost prejudice, but only after the jinn has a good laugh at the losing player. When all corks have been pushed back into their bottles the game is won.

Here's what you have to get yourself started.

  1. The source code to a small program with a blocking event loop. It shows you:
  2. List insertion and deletion functions. These are for students who are uncomfortable with memory management in C.
  3. The binary for a prototype model solution, made by Erin Lester, which you can execute to answer questions about how the game is supposed to work. (Note that this prototype solution assumes that the player has enough imagination to see bottles and jinn in simple geometric objects. In judging your implementation success we assume that players have imaginations, and most highly reward assignments that make neat looking solutions using the simplest of means. For example, don't use colour.)

These are all in the course account in /u/cs498r/assignments/a1 on any CS undergraduate machine.

Here is a rough outline of the game, as implemented in the binary.

  1. The crate is a five by five array. Bottles begin to open at random times and speeds.
  2. The mouse controls the position of a fist, which punches a cork back in when any mouse button is pressed.
  3. Punching a bottle when the cork is not opening breaks the bottle and releases the jinn, losing the game.
  4. Failing to punch a bottle before the cork releases completely lets the jinn escape and the game is lost.
  5. The game is won when all bottles have been punched. A notice appears telling the player that they have won.
  6. When a jinn escapes it expands to fill the whole screen, and laughs at the losing player, who shakes with fear.
  7. `q', typed at any time, causes the program to exit.

Three factors increase and decrease the difficulty of the game.

  1. The number of bottles in the crate.
  2. The speed at which the corks move in the bottles.
  3. The average interval between corks starting to move.

For the latter two program hot keys ( cork speed: `<' to increase, `>' to decrease; average interval: `,' to increase, `.' to decrease) so that you can experiment to get a feeling for the region in which the game is playable.

Erin's implementation is deliberately programmed to have a mediocre appearance. Choose how big things are, and where you put them, to approve the appearance. An implementation identical to hers, with perfectly answered questions is worth about 80%. Do not use any colours but black and white in your implementation, and don't bother with fancy textures either.

Here are a few possibly helpful hints.

  1. I use the function void napms( int duration ), from the curses library, to get constantly moving corks and jinn. To use it I
    #include <curses.h>

    in my code and use the compilation command.

    gcc -o game -lX11 game.c -lcurses

    Work out a value for duration by experimenting in the undergrad environment. (There are many other ways of getting the time with a fine enough granularity, but also lots of machine dependence. For example, I believe that napms does not actually work on all the undergraduate machines.)

  2. If you want to position text XStringWidth will tell you how long a string is in pixels.
  3. I use a rough, and easy to program, algorithm for determining if the mouse is clicked inside a bottle. Users don't notice its deficiencies.
  4. I only put corks and bottles into my display list explicitly, leaving the crate and other stuff in the `display list' that is implicit in the repaint function.

When your implementation is complete, experiment informally with the speed, interval and number of bottles, to find ranges of values that are `playable' in the undergrad environment. Pay attention to what makes the game harder and what makes it easier.

Here's what we would like you to hand in.

  1. The source code for your game, which may be in one or more files, plus a Makefile that compiles it. We will compile your code using your makefile.
  2. A file answers.txt, containing answers to the following questions.
    1. What is the range of playable values you found for your implementation? What goes wrong outside the playable range? Which parts of the playable range are hard? Why?
    2. What did you do to improve the interface of your implementation? Why?
    3. What did you do to improve the appearance of your implementation? Why?
    4. Did your hot keys adjust the values arithmetically (by adding and subtracting) or geometrically (by multiplying and dividing)? Why?

    To keep you from spending too much time on this part of the assignment we will truncate submitted answers to 200 words. (wc is handy for knowing how much you have written.)You need not reproduce the questions, but please number your answers.

The assignment will be marked as follows.

When considering `quality of code' we will look at two factors

  1. use of X functions, overall organization, algorithms, data structures, and
  2. variable names, comments, white space, etc.

The first is more important.

Return to: