Поиск в интернет-магазине Bolero
<Каталог сайтов - Найдётся всё yandex-rambler.ru Приглашение!
Искать на Озоне

Ozon.ru Ozon.ru

Поиск в интернет-магазине Bolero
Назад в будущее


Chapter 20 -- Multi-User Games and CGI

Chapter 20

Multi-User Games and CGI


CONTENTS


Ever since the World Wide Web was created, its multimedia potential has attracted both game designers and game players. In addition, the worldwide connectivity of the Internet makes the Web a natural arena for multi-player games.

CGI programs are, for the most part, the backbone of gaming on the Web. Whether it is a two-player game of Checkers or an extensive open-ended MUD, CGI provides the capabilities required to provide on-the-fly page generation and state retention necessary to maintain a multi-player game on the Web.

The first step in creating a multi-user game for the Web is to check to see if it has already been done. The Web is a big place, and there is a good chance that someone else has done something similar to what you have planned. There is no need to re-invent the wheel (unless, of course, your wheel is better).

A quick glance at Yahoo! shows several dozen entries under the category of "Interactive Web Games" (see Figure 20.1). Only a few of these are true multi-player games, but even those that do not fit this description can be useful as a learning tool in the quest for the perfect multi-player game. Web-based games as a whole can be grouped by "multi-playerness" to gauge better how they relate to true multi-player gaming:

Figure 20.1: Yahoo!'s interactive Web games.

  • Single-Player Games-These are the most common games on the Web, ranging from board games (Chess, Checkers, and so on) and simple image manipulation (Mr. Potato Head, Dart Boards, Sliding Picture Puzzles), to fully realized, intricate Virtual Worlds. What connects these games is the fact that each person playing a particular game is playing alone, with no contact with any other players.
  • Noninteractive Multi-Player Games-These are games in which many people may be playing at once. Although each player may be aware of each other's actions, no player can affect another player's game. Making a noninteractive multi-player game can be as simple as adding a high score table to a single-player game. By far, the most widespread of this type of game are the many "Scavenger Hunts" on the Web (see Figure 20.2). Often sponsored by commercial entities, many of these games have real-life money and prizes at stake.

Figure 20.2: Lingua Center's Web Scavenger Hunt.

  • Cooperatively Interacting Multi-Player Games-Most of these "games" are not really games at all but cooperative endeavors between several people. Web-based "Interactive Fiction" and "Interactive Art" have become enormously popular, enabling people to build upon others' ideas in a public environment. The theory behind these "games" is useful when considering true multi-player games because, unlike most noninteractive games, most cooperative games require the information entered by one player to be remembered and to be automatically available to all players. This creates the problem of "state retention" that is crucial to multi-player games.
  • "True" Multi-Player Games-A "true" multi-player game is a game in which more than one player is present, and the actions of one player can possibly affect (positively or negatively) another player's game. This usually also entails informing the other player that his or her game has been altered. Because the Web is a "connectionless" medium, this can be a nontrivial (even downright difficult) task. Some games, such as Netropolis (http://www.delphi.co.uk/netropolis, shown in Figure 20.3), use a turn-based mechanism, so each player knows when to update his or her browser. Others, such as Onslaught (http://www.webplayer.com/, shown in Figure 20.4), are real-time, requiring the players to be constantly on their toes. No matter the type of game, making playable multi-player games is one of the most difficult tasks to accomplish over the Web.

Figure 20.3: Welcome to Netropolis.

Figure 20.4: On the battlefield of Onslaught.

Multi-User Games

The first (and arguably the most important) part of creating a Web-based multi-player game (or any game, for that matter) is planning. This is also the part that most programmers skip or gloss over. After you have your idea for BlastMasters from Outer Space in 3D, it is very tempting to begin hacking away at it all at once with only your inspiration to guide you. Not giving in to this temptation is important, especially for games meant for the Internet. It is a waste of time to code an earth-shattering 24-bit graphics full-motion video epic only to find out that no browser on the planet can play it.

Planning

Planning is often not that difficult. A couple of pages of outline and a little research can cut your coding time in half. To begin, write down the answers to the following questions:

  1. What is your game about? This is the easy part. What do you want to make? A space game? A western? An abstract mind game? Here, your imagination is the only limit.
  2. How are the players going to interact? This is a base of your actual coding. Are your players going to fight? If so, will it be close-up or long-range combat? Will they trade? Communicate? All of the above?
  3. What constraints are going to be on the game? Because the Web is a connectionless medium, there is no constant link open between the client and the server. This makes on-the-fly updates difficult, if not impossible, by means of standard CGI (it is possible by using tools like Java, but that's another can of worms). Because of this, turn-based games are most natural for CGI. You must decide how long you want your turns to be. A minute? You better hope your players have fast connections to keep up. A day? You better hope your players have long attention spans. Also included in this question is the idea of "scalableness." Are you expecting five players to play this game? 100? Do you want to start at five and move to 100? These are questions best answered before you type your first printf() statement.

Outlining

Now you know what you want to do, you have a vague idea of how you are going to do it, and you have an idea of the size of the project. The next step is outlining. Ask yourself what your game entails. Break it up into segments and even write pseudo-code for parts. As an example, consider one of the most basic game designs: A bunch of people in a room shooting at each other. (Remember "Tank" on the Atari 2600?)

What does this game entail?

  • Character creation-People must be able to make new characters in order to join the game.
  • Map generation-A map that shows the positions of all the players has to be displayed.
  • Moving and attack-There must be some mechanism to carry out player requests to move or attack.
  • Report-Players must somehow be notified that they have hit or missed their target (or that they have been hit themselves).

You could even break this down further into more detailed segments, including pseudocode, along the way. The more detailed your outline is, the sooner design flaws will show up, and the quicker coding will be.

Now we must choose how the information in this game will be stored. Again, because the Web is a connectionless medium, the server forgets about the client after data has transferred. The CGI program itself is therefore responsible for "remembering" information about the player. There are many ways to do this, but the three most common (and easiest to implement) are E-Mail, Database, and Daemon.

  • E-Mail: This is by far the easiest because Form-to-E-Mail programs exist in bounty for every language used in CGI. (For example, http://www.boutell.com/email or, for Mac users, http://www.lib.ncsu.edu/staff/morgan/E-mail-cgi.html.) However, the price to pay for ease is speed and power. Unless you use an automatic mail-handling program (such as procmail), the game will progress only every time you read your mail. Even if you use mail filtering, you must write programs to interpret the forms and act accordingly. For slow-moving, long-term games, this may not be a bad thing, and an e-mail interface should be considered (maybe a "shared-fiction" type game where players are basically role-playing, for example). However, e-mail is probably not the best interface for "Shoot 'Em Up Alley."
  • Database: This is perhaps the most useful (and most used) method of interaction. This entails taking the output from the form and storing it in a database of some sort. This can be as simple as dumping the information to a text file for later manipulation, or as complicated as connecting to a full-featured database server for on-the-fly addition and modification of data. (Several packages exist to ease CGI interaction with most popular database servers, including mSQL, Sybase, Oracle, and many others.) For its simplicity in retrieval, this is the method we are going to use for our sample game.
  • Daemon: Though the Web itself is a connectionless medium, there is nothing stopping your CGI program from taking the data given to it from the form and then connecting to some sort of daemon and dealing with it at its leisure. The major disadvantage of this method is that it requires a daemon process to be continually running for the life of the game. This can be nontrivial in DOS/Windows platforms. Even on UNIX, it can be inconvenient if you are a user on a time-sharing system with fixed quotas. This method does have a large speed advantage and the added bonus of elimination of file manipulation, which can be bothersome in the CGI arena. Also included in this category are CGIs that, instead of connecting to a custom server, connect to a server that already exists for another purpose. For example, a CGI could take input from a form, connect to a (probably modified) MUD server, and then perform actions on the MUD based on the content of the form. This sort of MUD-WWW interaction is one of the most popular frontiers of Internet gaming at the present.

In addition to these three options, you can make your form interface with your game in other ways. For example, you can store retrievable information about users on their browsers in the form of small packets of data called cookies. However, cookies are supported in only a small number of browsers (and in a nonstandard way among those browsers).

For our own small multi-player game (let's call it "The Cage" because it's really just a bunch of people in a cage shooting at each other), we'll use a database to store information about the players and the game. This allows us to make the game relatively fast paced and still avoid the programming complexities of an entire daemon.

Coding

Only now, after completing a good portion of the game in thought and theory, do we make the step of choosing a language in which to write the game. There are several choices available for CGI programming, all of which have strengths and weaknesses in regard to game necessities. The first thing to consider is complexity. Which languages do you know? While it never hurts to learn a new language, if you can write the program with a language you already know, it may be best to stick with that language. If you've already had classes in Visual Basic or Pascal, it's very possible that they will be able to handle the great majority of your CGI needs. Then there is speed. How fast does this really have to be? If your game is to have hundreds of simultaneous players and large computations, speed will be a factor, and a fast language such as C or C++ might be called for. In our case, there will be only 5 to 10 players at once, and the computations are minimal, so this is not really a factor. Power is another concern. Whatever type of game you are making, it will be necessary to parse text (if only to read the form input). For this reason, Perl has become, by far, the most widely used language on the Web and the one we will use to write "The Cage."

As per our earlier outline, the first thing to provide is a means for character generation. What is a character? The character is the human player's presence in the world of the game, and until computers acquire the capability to be subjective, our only means of representation of a character is by statistics. Luckily, computers are very good at statistics. In our case, the statistics are relatively straightforward. Each player needs a unique identifier; in this case, we'll use an ID number. A player name is also nice for color. Because we'll be displaying on a two-dimensional screen, a 2D grid is natural for our playing field (although 3D or even more is possible and worth exploring). So we need two coordinates to place our players in the "cage." If players will be attacking each other, we need some measure of health; call it "hit points" for lack of originality. A mechanism for preventing other players from interfering with a player's move would also be helpful. We will implement that mechanism with another stat that is a "hidden" password. Finally, we will include a list of players who have hit the player recently, so he or she will know who to plan that sneak attack against. For simplicity, we will represent these
statistics in a form similar to a UNIX password file:

id:name:x position:y position:hit points:password:attackers

To avoid conflicts, before we write a new character to our database, we first have to check it against the existing players. So our first function will gather information from our database (in a file called state.dat) and store it in an associative array.

Caution
Perl 5 is required for this example because of the use of references. Perl 5 contains many new features and is almost completely backward compatible. It is available from http://www.perl.com/perl.

sub getinfo {            # Get information about existing players.
    open (P, "state.dat");     # Open player database.
        my $n=0;         # Number of active players.
        while (<P>) {         # Read through each player.
                chop;         # Remove newline.
                @dat=split(/:/,$_,7);    # Get values from lines.
                $p[$dat[0]]{'name'}=$dat[1];    # Get Name.
                $p[$dat[0]]{'xpos'}=$dat[2];    # Get X Position
                $p[$dat[0]]{'ypos'}=$dat[3];     # Get Y Position
                $p[$dat[0]]{'pass'}=$dat[4];    # Get Password
                $p[$dat[0]]{'hp'}=$dat[5];    # Get Hit Points
                $p[$dat[0]]{'mes'}=$dat[6];    # Get List of Attackers
                if ($p[$dat[0]]{'name'}) {$n++;} # If there was a character
                        # on this line, increment $n.
        }
        close P;
        $n­­; # Since the last character was incremented. Decrement $n.
        return $n; # Return $n. The rest of the data is stored in the
           # associative references \%$p[0..n]
}

This function uses some of the most basic and common functions of Perl with no actual CGI interface. You can use functions similar to this to retrieve and store any kind of information from text files (including e-mail messages).

Now we can actually create the new character. The actual HTML form can be anything as long as it returns a field with the name name. In this function, I make use of a Perl module called cgi_head.pm. This takes input from a form and stores it in variables called $FORM{'x'} where x is the name of the input field. It also prints the correct HTML header so the browser knows to expect HTML code. There are many modules available for Perl that provide similar functionality (including CGI.pm from CPAN http://www.perl.com/perl/CPAN/).

require cgi_head; # include the cgi_head.pm module

sub new_char {

$|=1;  # Turn off buffering. Mostly for good luck.
srand; # initialize the random number generator.

while (-e "statelock") { sleep 1; } # If someone else is modifying the
                    # database, wait till they finish.
system("touch statelock");           # Lock the database for our use.

$n=&getinfo;    # Get player information.

$xpos=int(rand(28)) + 1; # Create x and y coordinates
$ypos=int(rand(13)) + 1; # for new character.
loop:
for ($I=0; $I <=$n; $I++) {   # Look through all existing players.
                 # If another player has these
                 # coordinates, make new ones.
        if (($xpos==$p[$I]{'xpos'})&&($ypos==$p[$I]{'ypos'})) {
                $xpos=int(rand(28)) + 1;
                $ypos=int(rand(13)) + 1;
                next loop;
        }
}
open (P, ">>state.dat");   # append to database.
$pass=int(rand(1000));   # Make new password.

if ($n > 0) {    # A kludge to correctly increment $n if there are 0 or 1
        # existing players.
        $newp=$n++;
} elsif ($n eq "0") { $newp=1; }
else { $newp=0; }

print P "$newp:$FORM{'name'}:$xpos:$ypos:$pass:10:\n"; # make database entry.
close P;
system ("rm statelock"); # Remove lock.
print <<EOP; # Print confirmation.

<HTML><HEAD><TITLE>Welcome!</title></head><BODY>
<H2>Your character has been approved!</h2>
<FORM ACTION="begin.cgi">
<INPUT TYPE=HIDDEN NAME="name" VALUE="$FORM{'name'}">
<INPUT TYPE=HIDDEN NAME="pass" VALUE="$pass">
<INPUT TYPE=SUBMIT VALUE="Enter the Cage!">
</form></body></html>

EOP

There are two main things to note about this function. First, the "password" is just a random number out of 1000. The only purpose for this is to discourage players from forging other players' actions. The password is silently included on all transactions and matched with the password in the database. Also, the end of the script just prints out an HTML page that links to the game. The only reason this exists is to allow people to refresh the game screen by reloading the page on their browser. We could have directly loaded the game page from this CGI, but a reload would then re-create the character.

Now that we have any number of characters created, we need to design the actual game page on which to place them. Creating games on the Web is unique among all Web applications. It is not necessarily a bad thing (in fact, it can be a very good thing) to push the speed and technology limits of the Web. While you don't want your game to take 15 minutes to load, it does have to hold your player's attention, and graphics are vital to that. Additionally, while you'd like your game to be playable on as many browsers as possible, a game is the perfect showcase for the latest HTML extension or browser toy. Our example is going to be extremely Spartan, with one concession: frames. While frames have serious issues for serious pages, they bring a great advantage to game pages: the capability to display a "control panel" independent of the main display.

To accomplish this, we are actually going to have three CGI programs controlling the game: one to generate the frames, one for the control panel, and one for the game itself (the functions we've already created can be made part of the cage CGI with the use of hidden variables in the form, or they can be separate files).

The first CGI (which was referenced as begin.cgi in the new_char function) simply prints out the frames page (passing along the name and password of the player):

#!/bin/perl
require cgi_head;

$|=1;

print <<EOP;

<HTML><HEAD><TITLE>The Cage!</title></head>
<FRAMESET ROWS="80%,20%">
<FRAME SRC="cage.cgi?name=$FORM{'name'}&pass=$FORM{'pass'}" NAME=Cage>
<FRAME SRC="con.cgi?name=$FORM{'name'}&pass=$FORM{'pass'}" NAME=Con>
</frameset>
</html>

EOP

The control panel (called "con.cgi" here) is virtually the same code.

#!/bin/perl

require cgi_head;

print <<EOP;

<HTML><HEAD><TITLE>Control Panel</title></head><BODY>
<A HREF="cage.cgi?d=up&name=$FORM{'name'}&pass=$FORM{'pass'}" TARGET=Cage>Go Up
Â</a><br>
<A HREF="cage.cgi?d=down&name=$FORM{'name'}&pass=$FORM{'pass'}" TARGET=Cage>
ÂGo Down</a><br>
<A HREF="cage.cgi?d=left&name=$FORM{'name'}&pass=$FORM{'pass'}" TARGET=Cage>
ÂGo Left</a><br>
<A HREF="cage.cgi?d=right&name=$FORM{'name'}&pass=$FORM{'pass'}" TARGET=Cage>
ÂGo Right</a><br>

To attack, click on the player you wish to attack.
</body></html>

EOP

Again note that the generated links pass the name and password with every transaction.

Finally, the heart of the game: "cage.cgi":

#!/bin/perl

require cgi_head;
require getpos; # Or include the text of the getpos function from above.

srand; # Initialize the random number generator.
$|=1;

$name=$FORM{'name'}; # Grab name and password from the form.
$pass=$FORM{'pass'};

while ( -e "statelock") { sleep 1; } # Wait until database is free.

system ("touch statelock"); # Lock database.

$n=&getpos; # Get player information.

loop:                   # Find the player that initiated
for ($I=0; $I <=$n; $I++) {          # this transaction.Store their id
    if ($name ne $p[$I]{'name'}) {  # number in $me.
        next loop;
    }
    $me=$I;
}


# Make sure the correct password was passed to us.
# If not, print an error message and die (rememebering to free the database.)
if ($p[$me]{'pass'} ne $pass) { print <<EOP;
<HTML><HEAD><TITLE>Sorry!</title></head><BODY>
You are not authorized to play this character.
<A HREF="index.html">Go to the entry room</a> to create a new character.<br>
</body></html>

EOP
    system ("rm statelock");
    die;
}

@atts=split(',',$p[$me]{'mes'}); # Make an array of the recent attackers.

if ($d=$FORM{'d'}) {  # If the player is requesting movement, first
            # Check to see if they're trying to move past the
            # Boundries of the cage.  If not, move them.
            # We've chosen the cage to be 30x15, which displays
            # well on most browsers.

    if (($d eq "up") && ($p[$me]{'ypos'}==1)) {
    } elsif ($d eq "up") { $p[$me]{'ypos'}--; }
    if (($d eq "down") && ($p[$me]{'ypos'}==13)) {
    } elsif ($d eq "down") { $p[$me]{'ypos'}++; }
    if (($d eq "right") && ($p[$me]{'xpos'}==28)) {
    } elsif ($d eq "right") { $p[$me]{'xpos'}++; }
    if (($d eq "left") && ($p[$me]{'xpos'}==1)) {
    } elsif ($d eq "left") { $p[$me]{'xpos'}--; }
}

if ($a=$FORM{'a'}) {                # If attacking,
    $I=0;                  # Find id number of target
    while ($p[$I]{'name'} ne $a) { $I++; }  # and store it in $I.

    # Now calculate the distance between the players (using the
    # Pythagorean theorem.) The maximum range is (arbitrarily) sqrt(50)
    # (Which is just above 7.)
    $dis=abs(sqrt(abs($p[$I]{'xpos'}**2 + $p[$I]{'ypos'}**2)) -
           sqrt(abs($p[$me]{'xpos'}**2 + $p[$me]{'ypos'}**2)));

    # If the player are out of range, set a message.
    if ($dis**2 > 50) {
        $message="$p[$I]{'name'} is out of range!<br>\n";
    } else {
    # If they are in range, give them a 50-50 chance of hitting.
        $roll=int(rand(100)) + 1;
    # If they miss, set a message.
        if ( $roll < 50 ) {
            $message="You missed $p[$I]{'name'}<br>\n";
        } else {
    # If they hit, set a message, add the attackers name to the target's
    # list of attackers, and decrement the target's hit points.
               $message="You hit!\n";
               $p[$I]{'mes'}="$me,";
               $p[$I]{'hp'}-;
        }
    }
}

# Now we actually print the game page.  The "cage" itself is done in a
# 30x15 table, bordered with '*'s. Enemies are presented by their id number
# in a link which initiates attack. The player himself is represented by
# an asterisk.

print "<HTML><HEAD><TITLE>The Cage</title></head><BODY><TABLE BORDER=0>\n";
for ($y=0; $y < 15; $y++) {
    print "<TR>\n";
    for ($x=0; $x < 30; $x++) {
        for ($I=0; $I <=$n; $I++) {
            if (($x==$p[$I]{'xpos'}) && ($y==$p[$I]{'ypos'})) {
                if ($I==$me) { $c="*"; }
                else {
$c="<A HREF=\"cage.cgi?name=$p[$me]{'name'}&pass=$p[$me]{'name'}&a=$p[$I]{'name'}
Â\">$I</a>";
                }
            }
        }
        if ($c eq "") { $c="&nbsp"; }
        if (($x==0)||($y==0)||($x==29)||($y==14)) { $c="*"; }
        print "<TD>$c</td>";
        $c="";
    }
    print "\n</tr>\n";
}
print "</table>\n";

# Now print any message that may have been set above.
if ($message) { print $message, "<BR>"; }
# Then print the names of all recent attackers.
foreach $att (@atts) {
    print "$p[$att]{'name'} hit you!<br>\n";
}
# Print the player's hit points.
print "You have $p[$me]{'hp'} hit points left!<br>\n";
print "</body></html>\n";

# Now open the database and regenerate the entire thing. We must rewrite
# all players, because we may have changed another player's hit points.
open (P, ">state.dat");
for ($I=0; $I <=$n; $I++) {
    print P "$I:$p[$I]{'name'}:$p[$I]{'xpos'}:$p[$I]{'ypos'}:$p[$I]{'pass'}:$p[$I]
Â{'hp'}:$p[$I]{'mes'}\n";
}
close P;
system ("rm statelock"); # Unlock database.

And that's it. An entire multi-player Web game in less than 200 lines of Perl. Granted, it's not Mortal Kombat 5, but it has possibilities. It also has a few notable areas that could be improved:

  • The program completely violates namespace by making the reference $p[0..$n] global. This is fairly easily rectified by returning a reference to the entire @p array instead of $n.
  • It's not turn based! Despite all the earlier talk of the advantages of a turn-based mechanism, this game has no turns at all as it is. This means that all players will be able to move and attack as fast as they can click the mouse. This isn't a bad thing if all players are in the same room using similar equipment. However, if one player is two feet from the server and another is on another continent, problems will arise. The Internet is not instantaneous (yet), and to make the game fair, a turn-based mechanism is required. Fortunately, it wouldn't be hard to add one to our sample game. One way to accomplish this would be to queue moves. An extra stat could be added to the database for move requested ("move left," "attack Gary"). If a move already exists, further requests could be ignored. Then at the beginning of each turn (every 10 seconds, minute, or whatever), another script would run, probably as a cron job or maybe a running daemon (cron is a UNIX program that runs other programs at given time intervals, anywhere from once every minute to once every year). This script would execute each move (perhaps in random order) and then erase all moves to allow a new turn to begin.
  • There is no player collision. This is pretty trivial to implement by including a check for player positions when checking for the boundaries when a player moves.
  • Nothing happens when a player "dies." As is, when a player drops below 0 hit points, he or she just has negative hit points. Again, fixing this is trivial. If a player with less than 1 hit point attempts to make a move, the script could generate a "Game Over" page and erase that player from the database.
  • Security, security, security. This is an overriding concern for all CGI programs, especially those dealing with databases. Perhaps you typed in the previous scripts, and while they ran fine from the command line, they did nothing when accessed from the Web. This is because most Web servers are run as a user with minimal access rights to prevent security breaches (usually user "nobody" on UNIX machines). This means the server (and hence the CGI program run by the server) does not have permission to modify the database. The easiest method around this is to set the database with world writable permissions. (On UNIX-like machines, the command is chmod o+w.) Now, however, any user on your machine can modify (or even erase) the database. Because the name of the database is not available from the game pages themselves, you could make the database an obscure file in some obscure directory so that it is unlikely to be found; but if someone is intent on breaking the game, that is hardly going to stop them. In Perl, however, there is another option (which is also available in one form or another when using other languages). A module exists called CGIWrap (http://wwwcgi.umr.edu/~cgiwrap). This enables you to run your CGI program as the user who owns the program. Therefore, the cage.cgi could be run as if it were you, and then you could modify the database that is owned by you. However, this creates another problem. Now that the CGI is being run as if it were you, it has all the same permissions you do, and as such it can modify (or delete) any file in your account. You must, therefore, make absolutely sure that your script is foolproof and can be used to access other files in your account. More information on the security aspects of CGI can be found in Chapter 9, "Security."

Tip
Flags are your friends. One good way to check this is to run the script with the -T flag in Perl. This turns on taint checking, which is designed to prevent such abuses of your script. In addition, always test Perl scripts with the -w flag before using them. This turns on Perl's warning mode that gives out helpful hints on any mistakes, or even just bad decisions, you have made. Having Perl spot goofs you might have made can save hours of debugging for mistakes you have made.

These are just the glaring problems. Many (if not most) of the routines in the previous scripts could be made much more efficient and less naive. Also, you can make many improvements by using this game as a springboard:

  • Add graphics! The game does not need to be this plain. Make tiny icons for the players and the background. Instead of putting ASCII characters in the table, put the appropriate icon in (using <IMG SRC="whatever">). This simple modification improves the enjoyment of the game tremendously.

Caution
As of this writing, Mosaic (and possibly other browsers, as well) has problems with generating inline images within tables. Most other graphical browsers (including OmniWeb, Netscape, and Internet Explorer) do handle this correctly.

  • Allow players to chat. Human interaction is the raison d'etre of multi-player games, and any Web game worth its weight will have some capability to allow players to exchange messages. (What would network DOOM be like without the capability to hurl insults with your rockets?) This is a less trivial mechanism to implement, but its importance is paramount. Consider this (relatively) simple approach for implementing chatting in our sample game:
    Add extra fields in "con.cgi" that allow a player to choose another player to talk to (perhaps by pull-down menu) and another field for the player to type in a message.
    "cage.cgi" must then place these messages into the database (or maybe in another database). Each time the game screen is drawn, the messages will be printed and then erased from the database.

This is just the beginning of what you can do with this game. Slight modifications in the idea could produce entirely new games. Perhaps there could be another database that includes coordinates of obstacles (some that block movement, some that block attacks, some that do both). Maybe a goal could be included (the player must reach a certain coordinate while preventing other players from doing the same).

In this chapter, we have used Perl exclusively to create our programs. This is not to say that it could not be done in other languages. Perl's text-handling routines are superb, but C's speed can be vital. If you are working on a Windows machine, perhaps Visual Basic or C++ is all that is available. The sample Perl scripts here are not magical; you could write equivalent programs in any CGI language-even "sh" (the exact implementation is left as an exercise for the reader).

Summary

With the tools in this chapter as a springboard, there is an entire world of possibility when using CGI to design multi-player games for the Web. Take a look at what's out there (and don't limit yourself to multi-player games, either). Plan out your game and make an outline. Test your game on as many browsers as possible, and beware of performance issues. Take care to make your game secure, especially if you are using databases.

Finally, when considering the capabilities of the Web with respect to gaming, don't ignore the non-CGI alternatives available. Java has become a popular platform for gaming because of its graphical capabilities. However, Java does come with a whole bag full of security concerns, so use it with caution. Macromedia Shockwave is another environment that allows you to be very flashy and graphical, but its multi-user capabilities are limited. Finally, Penguin, a new module for Perl, promises to enable Perl code to be executed securely on remote machines. This opens the door for Web games that maintain stable connections with servers and other players, allowing for the real-time interaction that will really bring Web multi-player games to the next level.



Хостинг от uCoz