Video Gamers: Reflection of Society

Leave a comment Standard

Games in Culture

I’m not a guy, but I have lots of male gamer friends. My experiences amongst them have taught me they like games that are fast paced, action packed, and trigger happy. The constant stimulation and reaction type responses are valued as much as coordination and precision. Most games on the market for guys are the kind of thing you can sit down with a bunch of friends and battle it out. Sports and fighting games dominate the top of the charts tend to be the kind of games you can play the whole way through in a matter of minutes or hours. Most popular male games have lots of graphic violence, high pitched sound effects, and portray women in a sexual nature. They focus on complex combinations of buttons and buttons sequences and ranking up level after level.

Does this reflect the mindset in our patriarchal society? Are men driven towards quick relief, fast responses and sessions of intense violence? Crime ratings in men tend to be highest with sex offenders and extremely violent offenders being predominantly male. If video games are a reflection of our society as it stands now, the picture being painted is one twisted looking Van Gogh.

My inferences here come from my own personal preferences and the trends I see in young girls on my gaming websites. Growing up I found the games for female audiences sorely lacking: under-developed, under-budget atrocities with Barbie brands on their pink-petaled covers. These games use few buttons for movement, and lots of bright colors and “happy” gag-me sounds. In fact, the games becoming popular among girls and women are role playing, MMO and strategy games. Games dealing with community and society and God gameplay. These games seem to accurately represent the more social relationships between girls and women.

Does this reflect a growing consciousness in women? Once the underdogs of society you see more and more prominent figures cropping up every year. In fact, the changing attitudes in games marketed for women seem to reflect this — Barbie Super Sleuth to the Sims 2 and the new family centered Wii games.

Games as a Lifestyle

Come on now, let’s just step right out and say it. The more time and money we spend invested in video games the more they reflect our culture. What was once a form of entertainment has become a bona fide way of expression and in some ways an art form. Will the continuing trends in video games run parallel to the changing attitudes and perspectives of a nation as they seem to be now or will the road split and follow another path? With systems like the Wii and the more immersive gameplay being introduced my prediction is things are only going to converge.

Say bye bye to the TV and hello to the virtual world you can step into dressed like your favorite second life character. Wave your hand in your living room and watch as you construct a house in the middle of the forest on a different continent. Visit a dance club in Hong Kong while you bust a move in front of your bedroom window. Earn a living playing video games, go to the Halo Olympics or drive a car at high speeds from your couch.

Games as the Future

Who ever thought you could drive a motorized vehicle at speeds or over 100mph or cook an entire dinner in under a few minutes in a small heated box? Games are an expression of where we’ve been, where we are now, and where we’re going to be. The explore our creativity to the far ends of human possibility and continue to push and probe ever deeper. As we live and learn, are born and die, our games are molded and shaped by the hands of time and the inquisitive mind of technology.

Our culture, our games are a box overflowing with possibilities. All we have to do is step outside.

Crystal Reports FIX: Error Occurred Reading Records: Subscript out of range

Comments 2 Standard

Okay, this threw me completely. Turns out I was telling Crystal Reports that I was going to pass 2 parameters and then I only passed one. This can also happen if you’re trying to access something out of bounds in the stored procedure, like a record that doesn’t exist.

Pits of Doom Lesson 6: MySQL Database Class

Comment 1 Standard

In the last lesson I introduced you to functions, reading & writing to a file, some simple javascript and adding features to the game so we could swap in/out maps and move up/down map levels. Now this is all fine and dandy, but we live in the age of databases so it’s time to pull out your thinking caps. Let’s get busy converting everything we’ve done so far to a database.

Lesson Concepts

MySQL Basics

There are several big database software companies out there but I’m a particular fan on MySQL (especially since it’s free…). SQL is a standardized query language that’s not so standard. Most of the basic operations and ideas are available in the different kinds of database software but not all of them. All the SQL here will is put together assuming your using MySQL 4.0 or later.

So, what is a database? If you think you’ve never used a database before you’re wrong. Are you online right now reading this post?? Guess what, you’re reading information from a database. You can be almost 90% certain most any big website you visit they use a database for their online content.

What to compare it to? If you’ve ever used Microsoft Excel or Microsoft Access you have a step up in the basics I’m going to teach you. So, here it is.

Terminology – Database, Tables, Rows, Columns & Keys

A lot of people get confused with some of these terms so I’m going to go over them before I start officially using them.

Database – this can refer to two things. People often use it to refer to the database software (MySQL, Oracle) but it also refers to a repository, or large collection of data that consists of several tables. When I use the term database I am referring to the large collection of data, not to the actual software. If I want to refer to the software, I’ll call it by it’s name: MySQL. Think of a database as a workbook in Excel, where it contains multiple spreadsheets yet they’re all a part of the same file.

Table – a database consists of many tables. Tables help you gather similar data together, form relationships, and setup constraints/limits to the data you insert into it. In this lesson we’ll be creating and working with several tables that make up all of our map data. Think of tables as a single spreadsheet in excel.

Row – a row is a horizontal line of data in a table.

Column – a column is a vertical line of data in a table.

Keys – in SQL things are identified by keys. Think of a key as a way to distinguish one record from another. In the United States everyone has a unique social security number, that way the government can distinguish one John Smith from another. Sometimes keys can be made up of multiple things. For instance, if you knew one John Smith lived in Florida and the other lived in New Jersey you’d be able to tell the two apart. Keys can work the same way. Falling back on my earlier excel references, think of a Key as one of the column or row headers on the spreadsheet file (A-Z at across the top and down the side).

Creating A Database

For the sake of learning I’m going to walk you through some basic SQL before I introduce combine PHP into the mix. The first thing we need to do is make a database for Pits of Doom. To help you distinguish between when I’m writing SQL code versus PHP code I’m going to precede all my SQL statements with mysql> like you’d see the mysql command prompt screen.

mysql> CREATE DATABASE pitsofdoom

A lot less painful looking thing you thought it would be huh? Most people have a general rule with SQL where they capitalize SQL command words and put their own text in lowercase letters. I believe in some database software the capitalization is required, but it’s not required for MySQL. Choose whichever way you prefer.

Creating A Table

This is nearly as easy as creating a database with a few exceptions. When we create a table we have to give it all the row values we’ll be using and a type for each of those values. However, before we do that we’ll need to think about the design of these tables, the game map tables.

Let’s think about it this way:

Each map has 1 name and multiple levels — we’ll need to know what’s the deepest level you can go in each map.

Each map has lots of data for each level — it’s probably a good idea to separate this data from the map name and level data because there’s so much of it. Also, since we have so much map data we don’t want to repeat things like the map name over and over again (we don’t really need to know the map name more then once)

So, the maps in our game should have at least two tables. One table with the map name and level, the other table with all the data for that particular map. If we draw out a rough sketch of our tables they’d look like this:

Table Name: Map

Fields:

ID: a unique number for this map (number)

Name: the name of this map (string)

MaxDepth: the maximum depth level for this map (number)

Table Name: MapData

Fields:

Id: a unique number for this map data information (number)

MapId: the id of the map this data belongs to (number)

X: the x coordinate for this map value (number)

Y: the y coordinate for this map value (number)

Z: the depth of this place on the map (number)

Value: the value of the field in the map ie X, T, W, E (single character)

Now that we have our tables laid out we’ll convert them into SQL.

mysql> CREATE TABLE map (       id integer NOT NULL AUTO_INCREMENT,       name varchar(100) NOT NULL,       maxdepth integer NOT NULL,       UNIQUE KEY(id))

In this first table we’ve created our map information. We’ve set it up so the ID number must be unique, and so that it’ll automatically increment for us as we add records (so we don’t have to do that ourselves!). You’ll notice anything we wanted to put a number into has a type of INTEGER. Anything we wanted to put text into has the type of VARCHAR and then we specified the maximum number of characters for that field. So in this case the name of our map can’t be more then 100 character’s long.

A visual representation of the table we made would look something like this:

ID Name MaxDepth

These three fields combined make up our map table. Now let’s make our map data table:

mysql> CREATE TABLE mapdata (       id integer NOT NULL AUTO_INCREMENT,       mapid integer NOT NULL,       x integer NOT NULL,       y integer NOT NULL,       z integer NOT NULL,       value varchar(1),       UNIQUE KEY(id))

Visually, this would look something like this:

ID MapID X Y Z Value

All of these fields combined make up the mapdata table. However, our tables need a lot more information then just the columns for the data we’re going to add. Let’s see what it would look like visually if we added some information from the map we made for Round Hill.

ID Name MaxDepth
1 Round Hill 5

The first map in our game starts out with the ID number 1. If you remember, we setup our map table to auto-increment the ID field. That means it will always add 1 to the value of the ID number. The max depth of the first entry in our table is 5 because there are five levels in our map. Now let’s see what our map data table would look like with some of the first level’s information inserted into it:

ID MapID X Y Z Value
1 1 0 0 1 W
2 1 0 1 1 W
3 1 0 2 1 W
4 1 0 4 1 W
5 1 0 5 1 W
6 1 0 6 1 W
7 1 0 0 7 W
8 1 0 8 1 W
9 1 0 9 1 W
10 1 0 10 1 W
11 1 0 11 1 W
12 1 0 12 1 W
13 1 0 13 1 W
14 1 0 14 1 W
15 1 1 15 1 W
16 1 1 0 1 W
17 1 1 1 1 X
18 1 1 2 1 X
19 1 1 3 1 E
20 1 1 4 1 E
21 1 1 5 1 E
22 1 1 6 1 E
23 1 1 7 1 W
24 1 1 8 1 T
25 1 1 9 1 E
26 1 1 10 1 W
27 1 1 11 1 E
28 1 1 12 1 E
29 1 1 13 1 E
30 1 1 14 1 W

Does any of this look familiar? It should! This is the information from the first level of the map for Round Hill. It’s actually the first two top rows in the map file we exported. This brings us to our next topic, how in the heck do you add this information to the database using MySQL?

Inserting Values Into A Table

First, let’s try to insert the map information for Round Hill into our map table:

mysql > INSERT INTO map (name, maxdepth) VALUES ('Round Hill', '5')

The insert statement in SQL is comprised of the table you want to insert into, the fields you’re inserting data into, and then the data. The sequence of the data should match the order of the column names you put in. So if we reversed our values to ‘5’, ‘Round Hill’ we’d end up with an error when we tried to insert the text value Round Hill into a number value.

Now let’s insert some of our map information into the mapdata table.

mysql > INSERT INTO mapdata (mapid, x, y, z, value) VALUES ('1', '0', '0', '1', 'W'),         ('1', '0', '1', '1', 'W'), ('1', '0', '2', '1', 'W')

In this case, I’ve actually inserted three rows using one insert statement. Each entry is surrounded by parenthesis. When you insert something, you can use either of these formats, whichever works best for you.

Selecting Values From A Table

Once you have data in a table of your database you’re ready to start working with it. Let’s pretend we a table called members with the following data in it:

ID Name Username Password Email Show_Email
1 Jade Krafsig JadenDreamer ilovehorses jade@design1online.com Y
2 John Doe Jdoe imadope jdoe@gmail.com N
3 Jane Doe Jdoe howdy jane.doe@gmail.com N

We have three members in our database. Let’s pretend John Doe is trying to login using his email address and password. Before we can let him access any member’s only area we need to verify that this username and password are correct, then figure out what his show email status is.

mysql > SELECT id, name, show_email FROM members WHERE email='jdoe@gmail.com' AND password='imadope'

The select statement is broken into several parts, only a few of the basics which I’m going to show you right now. After the word SELECT, you list the name of the columns you want to view. After the word FROM you list the name of the table. The WHERE section is pretty self explanatory. If we ran this query we would get back the following table:

ID Name Show_Email
2 John Doe N

One thing to notice right off the bat, when we select something we always get back a TABLE. That means we can get more then one row of data from a select statement. For instance, take this query:

mysql > SELECT * FROM members WHERE username='Jdoe'
ID Name Username Password Email Show_Email
2 John Doe Jdoe imadope jdoe@gmail.com N
3 Jane Doe Jdoe howdy jane.doe@gmail.com N

In this example, we used an asterisk to tell MySQL we want all the column fields in the table where members have a username that equals Jdoe. Now you have multiple records returned. Take a look at some of the queries below, can you figure out what table would be generated if you ran them?

mysql > SELECT id FROM members WHERE show_email='N'

mysql > SELECT * FROM members WHERE email='jane.doe@gmail.com' OR email='jdoe@gmail.com'

mysql > SELECT * FROM members WHERE 1=1

mysql > SELECT * FROM members

mysql > SELECT username, password FROM members WHERE username != password

mysql > SELECT * FROM members WHERE id >= 2

Think you’ve figured them out? Good! Let’s go over them. The first one finds all members who have the show_email field set to N. The second one selects all columns where the email address is one value OR where the email address is another value. The third query will select everything in the entire database, as will the query after it. The next query shows all the usernames and passwords where the username field and the password field don’t have the same values in them, and the last query finds all members with an ID greater than or equal to the number 2.

Updating Values In A Table

Data doesn’t usually stay static, especially data for a multiplayer online game. People change passwords, write messages, go on quests, and more. In order for the game to reflect that we’ll need to update the data as people play. That’s were update statements come in. Let’s use the same members table we had before. Pretend that John Doe has logged into his account and wants to change his email address:

mysql > UPDATE members SET email='john.doe@gmail.com'

If you realized immediately that this will cause a problem you’ve got the right mindset. If you didn’t notice an error right away look again. Computers are really dumb, they do exactly what you tell them to. If you ran this query, you would change everyone’s password in the game to John Doe’s new email address. What a disaster!

This is where keys become important. In order to identify which record in our database belongs to John and only change data for information that belongs to John we can use the key for our member’s table: ID.

mysql > UPDATE members SET email='john.doe@gmail.com' WHERE id='2'

When we run this query only the email address for John is affected. Perfect!

Update statements can be as easy and as complicated as you want. We could update every other row by figuring out if the id number was odd or even, we could change passwords according to the show_email field, and more. However you have to be careful with update statements. What happens if we did this:

mysql > UPDATE members SET password='heya', email='john.doe@gmail.com' WHERE username='jdoe'

Now we run into the problem of changing multiple records again. In our members table both John and Jane Doe use the same username. If we ran this query, we’d reset both of their passwords to heya and both their email addresses to john.doe@gmail.com.

Take a look at some of these other update queries. Can you figure out what they’d do?

mysql > UPDATE members SET password='test' WHERE id <= 1

mysql > UPDATE members SET username='Jade2', password='newpass' WHERE email='jade@design1online.com' AND username='John'

mysql > UPDATE members SET showing_emails='Y'

The first query sets all member’s passwords to test if their ID number is less than 1. The second query sets both the username and password for all members whose email matches AND have the username John. The third and final query fails, there is no column called showing_emails. If it instead said show_email it would set everyone’s show_email value to Y.

Deleting Values From A Table

Taking things out of your database is sometimes almost as important as putting things in. I run pretty small servers with a lot of active people who play. In order to make queries faster I delete old data. There are other reasons to delete data as well and I’m sure you can think of a few.

So you know, there is no way to delete a certain field in one file. Deletion in mysql is an all or nothing, it either removes the whole row or it doesn’t.

mysql > DELETE FROM members WHERE id='3'

This removes Jane Doe from the members database. Again, you can end up with the same problems deleting as you did updating. Pay careful attention to any delete statement so you don’t delete everything in your database!

MySQL & PHP Working Together

In order to access our database information from mysql in our php files we have to open a connection to the database. I usually make this a file called dbconnect.php and include it at the top of every page I need database access to. Your file will vary based on the username, password, and name of the database you’re using so you’ll need to change this file to work for you:

<?php

/************
* File: dbconnect.php
* Purpose: open database connection
*************/

//open our database connection with the correct username & password
mysql_connect(“localhost”, “USERNAME_HERE”, “PASSWORD_HERE”)
or die
(“could not connect to the database because: ” . mysql_error());

//change to the database we want to use
mysql_select_db
(“DATABASE_NAME_HERE”)
or die (‘could not switch to using database because: ” . mysql_error());
?>

The first function mysql_connect starts the connection to the database. If you’re using a database that’s local to where you host your website then the words localhost will never change. The or die statement at the end of the function is a great way to help you debug your mysql/php code. If something goes wrong while mysql is trying to connect it’ll automatically give you a fairly descriptive error message about the problem.

The second function mysql_select_db switches to the database you’ll be using. Often times you have multiple databases on the same server. For instance, I have two servers. On each server I have anywhere from 2-15 databases. When I run a PHP script, it needs to know which of those databases I’m using before it can try to access any of my tables.

Now you’ve seen two of the great functions PHP has built in to make it easy working with MySQL. Since we can connect to our database let’s start performing operations on it.

<?php
include(‘dbconnect.php’);

//we start off by setting the result of our query to a variable named $result
$result = mysql_query(“SELECT id, name FROM members WHERE id=’1′”)
or die (‘cannot select the member id because: ‘ . mysql_error());

//now we need particular information from that result put into our $row variable
$row = mysql_fetch_assoc($result);

//now we can access the values in our $row variable using the name of the field we want
echo “Hello ” . $row[‘name’] . “! Your member ID number is: ” . $row[‘id’];

?>

This prints, Hello Jade! Your member ID number is: 1

I’m not sure about you but I think that’s totally awesome. But in this example we need to know someone’s ID number before we display information about them. What happens if we want to change that based on a number someone’s entered into a text field? Take a look at this next example:

<?php
include(‘dbconnect.php’);

if ($_POST[‘id’]) //they’ve entered an ID number into the box
{

$id = $_POST[‘id’]; //set this variable to what they entered

$result = mysql_query(“SELECT id, name FROM members WHERE id=’$id'”)
or die (‘cannot select the member id because: ‘ . mysql_error());

//now we need particular information from that result put into our $row variable
$row = mysql_fetch_assoc($result);

//now we can access the values in our $row variable using the name of the field we want
echo “Hello ” . $row[‘name’] . “! Your member ID number is: ” . $row[‘id’];

}
?>

<form action=”#” method=”post”>
Enter an ID number: <input type=”text” name=”id” value=”<?php echo $_POST[‘id’]; ?>” />
<center><input type=”submit” name=”submit” value=”Click Me!” /></center>
</form>

In this example our page now pulls the correct information about whichever member’s ID number you enter. Now this works fine if someone uses a number and its less then 4, but what happens if they enter something else? Can you fix this so it only displays information about the member if the number is valid? Here’s two hints, you can use the function isNumeric($number) to find out if what someone entered is a number, then you should can check to see if the value returned by $row[‘field_name’] has data in it.

Let’s display a list of all of our members. How do we do that? Take a look at this code:

<?php
include(‘dbconnect.php’);

//I always change this variable to loop so it’s easier to read
$loop = mysql_query(“SELECT id, name FROM members”)
or die (‘cannot select the member id because: ‘ . mysql_error());

//now we want all the information that $row finds, not just the top value
while ($row = mysql_fetch_assoc($loop))

{
echo “Member ID: ” . $row[‘id’] . ” – ” . $row[‘name’] . “<br/>”;

}
?>

This goes through and echo’s the ID number and name of every member in our database as long as $row has a value. That means as soon as we no longer have any results returned from our table the loop will stop automatically.

There’s one more thing you need to know before we go on to making an SQL class, and that’s how to update a row.

<?php
include(‘dbconnect.php’);

if ($_POST[‘password’])
{

//notice how we don’t set this equal to a variable now
mysql_query
(“UPDATE members SET password='” . $_POST[‘password’] . “‘ WHERE id=’1′”)
or die (‘cannot select the member id because: ‘ . mysql_error());

echo “You updated the password for Jade!”;

}
?>

<form action=”#” method=”post”>
Enter an ID number: <input type=”text” name=”password” />
<center><input type=”submit” name=”submit” value=”Update Jade’s Password!” /></center>
</form>

In this example we have only one major difference. With the mysql update or delete statement, you don’t need a variable in front of it. Either the update works, or fails. Either a delete works or fails. There’s nothing to store for later use.

Whooo!! Now we’re ready to combine the two skill sets for our game. Instead of writing tons of queries all over the place we’re going to create a SQL class to help us out. It’ll do a ton of the work for us so we can focus on the bigger picture.

Class Basics

A class is a good way to abstract lots of smaller details from a bigger picture. We’re going to create a simple vending machine class. Everyone has used a vending machine before so it’s a great example.

There are lots of different parts that make up a vending machine, but all combined together we only think of the vending machine as one object. A class uses the same kind of idea, lots of smaller parts making a bigger object. Let’s think about fruit:

Fruit Class

Multiple Types of Fruit

But all have common characteristics:

Name

Color

Size (small, medium, large, and extra-large)

Sweet (yes or no)

We can take several actions with fruit:

Wash

Eat

Shine

Take over the world — just kidding

Using this really simple break down, let’s make a fruit class:

<?php

class fruit

{

//class variables, these are variables
//that belong specifically to this class

var $name;
var $color;
var $size;

var $sweet;
var $clean;
var $washed;

function fruit($name)
{

//this is a class constructor. It always has the same name
//as the class and the same parameters. Whenever we
//make a fruit class this is called automatically

$this->name = $name; //we automatically give this fruit its name
$this->clean = False; //our fruit always needs to be washed first

$this->washed = 0; //we haven’t washed it any times yet

}

//but we want to be able to set other things about the fruit

function setColor($color)
{

$this->color = $color;

}

function setSize($size)
{

$this->size = $size;

}

function setSweet($sweet)
{

$this->sweet = $sweet;

}

//lets make a way to wash our fruit
function wash()
{

$this->clean = True; //our fruit is clean now
$this->washed++; //we’ve washed our fruit one more time

}

//we want to eat our fruit now
function eat()
{

if (!$this->clean)

echo “You should always wash your $this->color $this->name first!!! “;

if ($this->clean && $this->washed < 2)

echo “You’re eating a dull looking piece of $this->name… “;

if ($this->clean && $this->washed >= 2)

echo “You’re eating a shiny piece of $this->color $this->name! “;

if (!$this->clean && $this->washed >= 2)

echo “Your $this->name is shiny but you probably should wash it first. “

if ($this->sweet)

echo “This fruit is sweet.”;

else

echo “This fruit is classified as a vegetable!”;

}

//we can make a shine function, that washes the surface of the fruit as well
function shine()
{

$this->washed++;

}

} //end of our class

//now that we have our class, let’s make some fruit!!

$orange = new fruit(“Orange”);
$orange->setSize(“small”);
$orange->setColor(“orange”);
$orange->setSweet(True);

$fruit = new fruit(“Watermelon”);
$fruit->setSize(“large”);
$fruit->setColor(“green”);
$fruit->setSweet(True);

$veggie = new fruit(“Tomato”);
$veggie->setSize(“medium”);
$veggie->setColor(“red”);
$veggie->setSweet(False);

echo “Washing my $orange->name. “;
$orange->wash();

echo “<br>Eating my $veggie->size $veggie->name. “;
$veggie->eat();

echo “<br/>Washing my $orange->name again. “;
$orange->wash();

echo “<br/>Shining my $fruit->size $fruit->name. “;
$fruit->shine();

echo “<br/>Eating my $fruit->name. “;
$fruit->eat();

echo “<br/>Eating my $orange->size $orange->name. “;
$orange->eat();

?>

Try running this script. What happens? One of the neatest things about a class is that all of the functions you make inside of a class can be applied to any object of that class. In the example above we had three different fruit objects. Even though they were all different variables they all used the same functions of the fruit class in a different way. You’ll also notice we can access the variables we made in the class using the -> arrow. Try adding more functions to this class. Try making $veggie = $fruit. What happens when you do $veggie->name now? Try adding a function to the class that lets you set all properties (color, sweet, size) at the same time.

Creating A MySQL Class

So, here goes nothing:

<?php/*************** File: mysqlobj.php* Purpose: database class**************/

class database{    //variables for this class    var $database;    var $host;    var $username;    var $password;    var $classerror;    var $connected;

    /**************    * Purpose: default constructor, is called every time we create an object of this class    * Precondition: host, username & password for the database, database we're using    **************/    function database($host, $username, $password, $database)    {        if (!$username)            return errorMsg("You must enter a username");

        if ($username != "root" && !$password)            return errorMsg("You must enter a password");

        if (!$database)            return errorMsg("You must enter a database");

        if (!$host)            $this->host = "localhost";        else            $this->host = $host;

        $this->username = $username;        $this->password = $password;        $this->database = $database;        $this->classerror = "Database Error: ";

        //automatically connect to the database        $this->connect();    }

    /**************    * Purpose: connect to the database    * Precondition: none    * Postcondition: connected to the database    **************/    function connect()    {        mysql_connect($this->host, $this->username, $this->password)        or die ($this->classerror . mysql_error());

        mysql_select_db($this->database)        or die ($this->classerror . mysql_error());

        $this->connected = true;    }

    /**************    * Purpose: end connection to the database    * Precondition: none    * Postcondition: close database connection    **************/    function disconnect()    {        mysql_close();        $this->connected = false;    }

    /**************    * Purpose: check for connected to database    * Precondition: none    * Postcondition: connected to the database    **************/    function checkconnection()    {        if (!$this->connected)            $this->connect();    }

    /**************    * Purpose: query the database    * Precondition: query to run    * Postcondition: returns query data    **************/    function query($sql)    {        if (!$sql)            return errorMsg("You must enter a query");

        $this->checkconnection();

        $result = mysql_query($sql)        or die ($this->classerror . mysql_error());

        return $result;    }

    /**************    * Purpose: selection query    * Precondition: fields, table, where    * Postcondition: returns query data    **************/    function select($fields, $table, $where)    {        if (!$fields)            return errorMsg("You must enter a field");

        if (!$table)            return errorMsg("You must enter a table");

        $this->checkconnection();

        $result = mysql_query("SELECT $fields FROM $table $where")        or die ($this->classerror . mysql_error());

        $row = mysql_fetch_assoc($result);        return $row;    }

    /**************    * Purpose: update query    * Precondition: table, fields, where    * Postcondition: field has been updated    **************/    function update($table, $fields, $where)    {        if (!$fields)            return errorMsg("You must enter a field");

        if (!$table)            return errorMsg("You must enter a table");

        $this->checkconnection();

        mysql_query("UPDATE $table SET $fields $where")        or die ($this->classerror . mysql_error());    }

    /**************    * Purpose: delete query    * Precondition: table, where    * Postcondition: row in table has been deleted    **************/    function delete($table, $where)    {        if (!$table)            return errorMsg("You must enter a table");

        if (!$where)            return errorMsg("You must enter a where condition");

        $this->checkconnection();

        mysql_query("DELETE FROM $table $where")        or die ($this->classerror . mysql_error());    }

    /**************    * Purpose: insert query    * Precondition: table, values    * Postcondition: row in table has been deleted    **************/    function insert($table, $fields, $values)    {        if (!$table)            return errorMsg("You must enter a table");

        if (!$values)            return errorMsg("You must enter values in the table");

        $this->checkconnection();

        mysql_query("INSERT INTO $table ($fields) VALUES ($values)")        or die ($this->classerror . mysql_error());

        //id of the row just inserted        return mysql_insert_id();    }

    /**************    * Purpose: find objects in the database then load them into an array    * Precondition: field, table, and object    * Postcondition: returns query data    **************/    function loadArray($field, $table, $where, $object)    {        $loop = mysql_query("SELECT $field FROM $table $where")                or die ('cannot load object data from table $table: ' . mysql_error());

        $customarray = array();

        while ($row = mysql_fetch_array($loop))            array_push($customarray, new $object($row[$field]));

        return $customarray;    }

    /**************    * Purpose: delete everything in a table    * Precondition: table    * Postcondition: all fields in table have been deleted    **************/    function truncate($table)    {        if (!$table)            return errorMsg("You must enter a table");

        $this->checkconnection();

        mysql_query("TRUNCATE $table")        or die ($this->classerror . mysql_error());    }} //end of class

/*************** Purpose: show a formatted error message**************/function errorMsg($message){	echo "<center>Error: $message.</center><br/>";}/*************** Purpose: show a formatted success message**************/function successMsg($message){	echo "<center>Success! $message.</center><br/>";}?>

I know everything’s not color coded but this is such a big class it’ll take me forever. So the short of it is we can use this class to do everything we need to do with our database. Take a look at this test file I made to see if the class was working. Try creating a table named attributes with an ID number and a name. Enter a few values into the table, then run this script:

<?php

include("mysqlobj.php");

//testing connectionecho "<b>Testing connection:</b> ";$database = new database("localhost", "username_here", "password_here", "databasename_here");echo "success!<br/>";

//testing query functionecho "<b>Testing query function:</b> ";$loop = $database->query("SELECT * FROM attributes");while ($row = mysql_fetch_assoc($loop)){	print_r($row);	echo "<br/>";}

echo "<br/><br/><b>Testing select function:</b> ";//testing select function$result = $database->select("name", "attributes", "WHERE id='3'");echo $result['name'];

echo "<br/><br/><b>Testing update function:</b> ";$database->update("attributes", "name='test field'", "WHERE id='12'");$result = $database->select("name", "attributes", "WHERE id='12'");echo $result['name'];

echo "<br/><br/><b>Changing Name Back:</b> ";$database->update("attributes", "name='flexibility'", "WHERE id='12'");$result = $database->select("name", "attributes", "WHERE id='12'");echo $result['name'];

echo "<br/><br/><b>Testing Insert:</b> ";$id = $database->insert("attributes", "name", "name='test'");echo $id;

echo "<br/><br/><b>Testing Delete:</b> ";$database->delete("attributes", "WHERE id='$id'");echo "success!";

echo "<br/><br/><b>Testing disconnect:</b> ";$database->disconnect();echo "success!";

echo "<br/><br/><b>Testing Insert:</b> ";$id = $database->insert("attributes", "name", "name='test2'");echo $id;

echo "<br/><br/><b>Testing Insert:</b> ";$id = $database->insert("attributes", "name", "name='test3'");echo $id;

//testing query functionecho "<br/><br/><b>Listing all values in the database:</b> ";$loop = $database->query("SELECT * FROM attributes");while ($row = mysql_fetch_assoc($loop)){	print_r($row);	echo "<br/>";}

echo "<br/><br/><b>Testing Truncation:</b> ";$id = $database->truncate("attributes");echo $id;

//testing query functionecho "<br/><br/><b>Listing all values in the database:</b> ";$loop = $database->query("SELECT * FROM attributes");while ($row = mysql_fetch_assoc($loop)){	print_r($row);	echo "<br/>";}

echo "<br/><br/><b>Disconnecting:</b> ";$database->disconnect();echo "success!";?>

What happens when you view this page? Can you see how it’s effecting things in the database? Great!! Now we’re ready to convert everything over to a database in our game.

Converting Everything Over

There is no cut and paste way to convert what we’ve done so far to use the database. My advice to you is to approach it however you most feel comfortable. Personally, the way I’d approach it would be to start with the map editor so once it’s converted over you’ll have maps in the database to fix the character page.

Once someone goes to save a map we need to:

  1. check to see if a map with that name already exists in the map table
  2. if the map already exists we want to load the existing values for that map
  3. if the map doesn’t exist we can show what we did before
  4. when someone clicks on the save button we need to
    1. update the map values in the database if it already exists OR
    2. add those new values to our mapdata table
  5. that’s it!

With our character page we only have to do one thing:

1. Change the loadMap function to load data from the database

Summary

There is a lot to digest in this lesson. Don’t worry if it all doesn’t make sense. Try making a database and playing around with it, add things, delete things and update things using SQL or the database class I provided above. Once you feel confident there try assigning database values into variables, make a small form to update values in the database. Then once you’re tired of that move on to converting the character.php and mapeditor.php files to use the database.

If you get stuck there’s nothing to worry about! All the working code is below. Enjoy.

Game Files

Working Version:

Character File: character.php

Map Editor: mapeditor.php
I’ve left it so you can actually add maps to the database so PLEASE RESPECT MY DATABASE!! Thank you 🙂

Source Files:

Character File: character.php

Map Editor: mapeditor.php

Database Tables: database.sql (map file data included)

Database Tables: database_empty.sql (no map data included)

Map File Database Importer: mapfile_importer.php
this will import the map files we made before right into your database!!

Mysql Database Class: mysqlobj.php

Functions: functions.php

Lesson Reasoning

Now we’ve taken our simple 1-click button game and turned it into a decently functional database driven game!! Not only can we create maps with our map editor and store them directly into the database, we can move up and down levels in a map, use ladders, fall into pits, and make sure we don’t run into walls.

But our game is far from complete. In the next lesson we’ll discuss creating a member class and a character class and how they interact between each other. Then we’ll create a members table and a character table in our database. Finally we’ll write a login script so only members with a character can access our simple game map and play it.

Return to Lesson 5 or Continue to Lesson 7

Pits of Doom Lesson 5: Easy Map Editor

Comments 3 Standard

In the last lesson we made some real progress. Now, instead of having a boring page with a click of one button before the game is over, we have a character that can move around a much larger area, be blocked by walls, fall into pits and die, and then win if they find the treasure.

That’s all fine and dandy but our game needs more substance. It’s time to add more maps, map levels, and our very own easy map editor so we can quickly make maps, generate map files, and play our game with a whole new level of complexity.

Lesson Concepts

Including Files

One of the best things about programming is being able to break bigger, more complex problems down into smaller more manageable pieces. Include files are one way to do that. Let’s take our custom function we wrote last lesson to display the map on the screen. Did you notice that our character.php file is becoming a bit crowded and hard to read? Wouldn’t it be nice if we could take the displayMap() function out off of the code in that page but still use it on there?

That’s what an include file does. Using an include file is easy. First you create a new file. I like to call files where I keep a lot of functions something really generic: functions.php. That way when you go back looking for things later and you find a function being used that’s not in the file you have a good idea of where to check to find it.

The next thing you do is put some code inside of functions.php. In our case, the display map function. So all we do is cut/paste the function from our character.php file to the functions.php file.

Last but not least, we go back to character.php and at the top of the page we write:

<?php

session_start();
include(‘functions.php’);

//rest of the code here like normal….

?>

What does this do? It literally takes the contents of the functions.php file and dumps it onto the character.php page. That way any piece of code you have inside of functions.php is now accessible to the page just like if we’d written the displayMap() function directly inside the character.php page. How neat is that?

I’m sure you can already see the benefits of doing this like this. It makes everything much easier to read.

Question: When is it a good time to make a function?

Functions are great things. My rule of thumb is, if you have a piece of code, or even some kind of page formatting that you plan on using again and again, make it into a function. That way, instead of having to type the same thing over and over and over again all you do is call your function and pass it unique parameters.

Take our character movement for example. Every time someone clicks on a button we have to check to see which button they pressed, what’s in the direction they’re moving, and how to respond to what’s in that direction. Do you notice the similarities in the code for EVERY direction?? If you run into situations like this, it’s a good time to stop and think function.

Give it a try! Can you convert the character movement into a function? Here’s a hint: Every time the player moves all you really need to know is what direction it’s moving in. Then, according to that direction, you can check the x and y values of the map to see what’s there.

Automatic File Downloads

In this lesson we’re creating a map editor we can use to create map files fairly quickly. In our map editor, we want to take the map file we created and automatically download it, or export it, once we’re done. In order to do that you’ll need to know some information about files and http headers. Despite how hard these seems like it should be, it’s only a few lines of code.

Let’s talk about HTTP headers. HTTP is Hypertext Transfer Protocol, or one way we use to view files online. You may be familiar with other things like FTP, file transfer protocol or TCP/IP, Transfer Control Protocol/Internet Protocol. But we’re only concerned about the one.

Every time you request a file from someplace on the internet a lot of different things go on. If you’re interested in how everything works I highly suggest going to wikipedia’s networking section. However, the more important thing you need to know is that for any file you view online, it starts with header information that describes the type of file it is, the length of the file, and the content of the file.

PHP, since it’s a server side programming language, can be used to setup the headers on any file you create before someone else sees the file online. In this way, we can use PHP to tell the browser anything we write on a HTML file should be treated like it’s a music file, or an application, a PDF, or a text file. Whatever we want!

Create a file and call it testdownload.php. Now put this in it:

<?php

//let’s create a name for the file you’ll download

$filename = “My Funky File.txt”;

//Tell PHP that we want to change the header information for this .php file and instead it’ll become a .txt file

header(“Content-Type: text”);

//Now we add an additional statement that’s meant to make your browser automatically download this file’s content

header(‘Content-Disposition: attachment; filename=”‘ . $filename .’‘);

//now anything we echo on this page will become a part of the file we’re downloading! think of all the possibilities!

echo “This is my totally awesome, funky cool file that I made download automatically using .php! You can’t even tell this was actually inside a .php script because the headers are being set to text :)”;

?>

That’s it! See, with only a few lines of code you can create a file that automatically downloads anything you echo on the page with the name, and extension you want it to have. We can use this concept with our map editor, to echo all the options someone selects to the page after we’ve set the headers and create automatically downloads for the map files.

Reading From A File

Reading from a file is a bit trickier. Instead of going over the concept I’m going to put the actual code I wrote specifically for the map editor I made with a ton of comments explaining what I’ve done and why. Please note that I wrote this file reader for the format generated by the map editor. It probably won’t work for any map file you’ve made yourself so you’ll need to re-create it using the map editor first.

Another thing I’ll warn you about. I keep my map files in another directory called maps. If you keep your map files in a different location you’ll need to change the $directory variable to reflect that. If you keep the map files in the same place as the game and map editor files then uncomment the first $directory line and comment out the second $directory line.

<?php

/**************
* Load Maze File
* NOTE: This was designed specifiically for files made with the map editor
*	 	it's not guaranteed to work for a file you made and formatted yourself.
*		Please use the editor to generate these files for you.
**************/
function loadMap($filename, $level)
{
	$map = array();

	//if you keep the map files in a particular directory
	//fill that in below. Otherwise you can leave this blank

	//$directory = "";
	$directory = "maps/";

	if (file_exists($directory . $filename . "_" . $level . ".txt"))
	{
		//open our file for reading the contents
		$fileline = file($directory . $filename . "_" . $level . ".txt");

		$x = 0;

		//while there is data in the file
		//read it one line at a time
		foreach ($fileline as $line_num => $line)
		{
			$i = 1;
			$y = 0; //we need to reset this each time
				//so our row always starts at zero

				//if this data is the start of our map
				//it should always be a wall
				if (substr($line, $i, 1) == "W")
				{
					//start pulling the info for the first row
					//keep loading in info until we reach the end of the line
					//in the row
					while (substr($line, $i, 1) != "\n")
					{
						if ($i % 2 != 0) //we do this so we don't load
								//in any of the spaces between characters
						{
							$map[$x][$y] = substr($line, $i, 1);
							$y++;
						}
						$i++; //take the next character in the row
					}
					$x++; //increment to the next row
				}
		}
		return $map; //return the array with all the map data
	}
	else
		return "File not found!";
}

?>

This function does three major things. First, it checks to see if the file exists and if it doesn’t it gives us an error message. Otherwise it opens the file, searches through it until if finds the first line of the map. We know when we find the first line of the map because it’ll be a W character, the wall that runs all around the outside of the map. Once it finds a line in the file from the map it inserts it into the array and increments the array variables by 1. That way each row and column of the map are read in until it doesn’t find any more.

We know that we’ve reached the end of a line (or the end of a row in the map) when we reach a \n character. This is the same thing as a carriage return in the file, or an end of line character. This tells us there’s nothing else left to read on the line, so we increment the array to start reading from the next row.

If this seems like it’s a bit out of your understanding don’t worry. This is actually much easier to do when you’re reading or inserting values into a database that we’ll cover next lesson.

Some Simple Javascript

I know I said I wouldn’t go into AJAX and Javascript but in creating the map editor I realized it would be easier to use visually if I added some Javascript for automatic color coding. So I’ll go over both functions I wrote and how they work below.

Javascript starts with different tags then what you see in PHP but it has both a start and end tag.

<script language="javascript">
function setColor(object)
{
	object.style.backgroundColor = object.options[object.selectedIndex].style.backgroundColor;
	object.style.color = object.options[object.selectedIndex].style.color;
}

function resetColors(object)
{
	var i;

        //we need to make sure we skip the buttons at the
        //bottom of the page, so we have to subtract 2 from
        //all the items in the form
	for (i = 0; i < (object.length-2); i++)
			setColor(object[i]);
}
</script>

The very first function is simple. It takes the color of the option in the select box and changes the select box to match that color.

The second function is a little more complicated. When we call it we pass it a form, or all of the things between the <form> and </form> tags in our map editor file. This includes all of the select boxes we’re using to let you create the map. Then it goes through all of those select boxes and calls the setColor function.

The reason we use this second function has to do with first loading the editor. The first time the editor is loaded we run a PHP script so that the borders of the map are automatically walls. When we do this, we still want to update the color of the walls we set. That’s what the resetColors function is for, it goes through every select box on the page and sets it to the appropriate color. You’ll notice when you first start the editor it appears with all white select boxes after a few seconds the borders of the map changes to gray. That change is caused by the javascript call to reset the colors. Try removing the resetColors call from the map editor. Do you see the difference when you try to run it now?

Pits of Doom Map Editor

I know I haven’t done this before, but I feel like we’re at a point where more explanation is necessary. Now I’m going to talk about the map editor, some of it’s features, and how you use it.

The map editor is a great, useful tool we can use to build this game quickly and efficiently. It has three major features to it. The first page you see when you open it is setting up the name and the level of the map. If you’re making multiple levels on the same map then they all need the same name. Then you can enter a width and height for the map. I suggest using a size 15 x 15 or smaller, otherwise you’ll have to do a lot of back and forth scrolling, but any size you pick will work.

Once you’ve filled out the map details click on the start map editor. The screen you’ll see next has several neat features.

  • To help make building a map faster, all the edges are automatically turned into a wall. For the sake of the map file loader make sure you always have walls around the edge of your map.
  • The map editor is also color coded, to make everything more visually pleasing.
  • S is the starting position of the character. You can have more then one, but the files I’ve included always pick the starting position closest to the top of the board. If you’d like to add in functionality to randomly pick the starting position by all means go ahead.
  • An addition to the map editor is the L, or ladder. Ladders will allow the character to move up or down a level if they land on one. A character cannot move up a level if they’re on the top map level, or level 1. In the other direction, a character cannot move down a level if they’re on the bottom level of the map. Right now we’ll assume all maps have 5 levels.
  • The last (and best) function of the map editor is the export file button. This lets you automatically download your map as a .txt file. Then you can use these .txt files to load maps into your game and play them!

Ladders, Pits & Level Changes

In this version of Pits of Doom we need to add the functionality of moving up and down ladders and falling down pits. The easiest thing to do first is create a function for all of our movement in the game.

Once you’ve done that, we need to make our $_SESSION variable global to our function. That means the function can access the values we already have inside of the $_SESSION variable. By setting the map name and level in a session we’ll always know which map we’re on and which level we’re on. If we apply this same concept to the map array values, we’ll always know what’s in the map once we’ve loaded it.

Any time we’re on a pit we now need to change the level the character is on so they fall down a level (unless they’re not on the last level of the map!). To make things easier for ourselves, we’ll make sure the map at level 5 doesn’t have any pits in it.

Once the character’s level has been dropped to the map file below, we load the map for that new level. Before the character can start playing this level again we need to find the starting position on this new map. To do that I’ve written two simple functions:

<?php

/**************
* This finds the position of the starting location
* marked with the value S and returns the X
* coordinate. It MUST be passed an entire array
* filled with maze data for it to work.
*
* Tip!: The variable name in the function parameter
* 	(in this case its $array) does not have to match
*	the name of the variable you pass to the function
*	when you call it.
**************/
function startPositionX($array)
{
	for ($x = 0; $x < height($array); $x++)
		for ($y = 0; $y < width($array); $y++)
			if ($array[$x][$y] == "S")
				return $x;
}

/**************
* This finds the position of the starting location
* marked with the value S and returns the Y
* coordinate. It MUST be passed an entire array
* filled with maze data for it to work.
**************/
function startPositionY($array)
{
	for ($x = 0; $x < height($array); $x++)
		for ($y = 0; $y < width($array); $y++)
			if ($array[$x][$y] == "S")
				return $y;
}

?>

One of these finds the X position of the starting position and the other finds the Y position. Using these we can reset the character’s default position on the new map we loaded. Note that height and width are additional functions I’ve written to find the height and width of the two-dimensional array.

Ladders use a similar concept with one difference. If someone is on a ladder they now have the option of moving up or down instead. To do that, I’ve written a special if statement for ladders. When someone is on a ladder they can use the up and down buttons to move up or down the ladder instead of moving backwards or forwards on the map. If the character is on the bottom level, we allow them to move back instead of moving down the ladder, and if they’re on the top level we let them move forward instead of moving up a level.

Summary

Our game is really coming along! I’m quite pleased with what I have right now. Not only can I move up and down ladders, fall into pits, and find the treasure, I’m having fun doing it. Right now I feel like we have a really solid foundation for how character movement is going to work. I think it’s time to take things to a new level of complexity by adding in the database.

Game Files

Working Version:

character.php

mapeditor.php

Source Code:

character.txt

functions.txt

mapeditor.txt

mapsymbols.txt

Map Files

Round Hill_1.txt

Round Hill_2.txt

Round Hill_3.txt

Round Hill_4.txt

Round Hill_5.txt

Try it Yourself:

character.php

functions.php

Lesson Reasoning

In this lesson we’re really starting to tie a lot more things together. Now we know how to load a map from an outside data source and swap those maps as they get to certain points on the map. We now have a fairly decent skeleton of what our map/character movement functionality is going to be like once the game is finished.

But this still isn’t what we want!! We need everything to be done from the database, loaded and ready to go so we can change it as and how we see fit. In our next lesson we’ll work on an introduction to SQL, setting up and connecting to a database, creating tables, and changing over everything we’ve done so far (including our easy map editor) to pull from and save to the database.

Look at that! Only 5 lessons and we’re already moving on to interacting with a database.

Return to Lesson 4 or Continue to Lesson 6