XAMPP: Learn PHP & MySQL Without Online Hosting!!

Comment 1 Standard

One of the questions I get most frequently is what I use to make my SIM games. My answer is always the same, PHP and MySQL. Let’s say you wanted to learn these languages, so you find some tutorials and start reading. Only now you realize you need somewhere to practice what you’ve learned. Hosting can be expensive, especially for hosts that come with PHP/MySQL for someone who only wants to play around with the languages and isn’t looking to develop an entire website.

XAMPP is your solution. XAMPP is developed by Apache Friends and it will let you write and test PHP code as well as create and manging your own database. The best thing about it, its FREE!!

Go to this website: http://www.apachefriends.org/en/xampp.html and download XAMPP for your operating system. Once you’ve downloaded it run the installer (Windows machines) or follow the directions to get it setup (Linux machines).

Once you have it installed you’ll need to turn it on before you can use it. Navigate to the folder where you installed it. You’ll see two programs, one called XAMPP_START and the other called XAMPP_STOP. Every time you want to run XAMPP you need to click on XAMPP_START. Make sure you turn it off before you turn off the computer, otherwise you may get a startup error the next time you try to use it. It’s not going to keep XAMPP from working but its annoying (and has a really loud beeping noise).

Now that XAMPP is on you can make sure it installed correctly. Open a browser window (Internet Explorer, FireFox, Opera, Netscape, whatever you like most). In the address bar type in: http://localhost

One thing to understand here. You don’t have to be online for XAMPP to work. In fact that’s what makes it so powerful. Now you can test all your files and programs right from your computer at home even if you don’t have Internet access.

If you’ve installed XAMPP correctly you’ll see an orange and white screen that shows some demo programs. Take a look through them, there’s a few neat things. You’ll also see information about what’s currently running. One of the great things about XAMPP is that you can switch from php version 4 to php version 5. This is extremely useful for people who want to switch over scripts from one version to another. That way you can iron out any problems you have and fix them before you switch.

The next question is, where do you put your files to test things? Easy. Navigate to where you installed XAMPP. You’ll see a folder called htdocs. All of your php should go in that folder. For convience, its easier to make a folder called testing inside of htdocs because you’ll end up with a lot of stuff in there and all the demo programs are in there too.

So inside {XAMPP_install_path}/htdocs/testing you can now write and test your code! Let’s say you make a file called helloword.php inside of testing. That means it’s {XAMPP_install_path}/htdocs/testing/helloworld.php. To view this file open a browser window and type in: http://localhost/testing/helloword.php

Presto! Your php works!

But there’s one other thing that’s essential. MySQL. XAMPP comes with phpMyAdmin, which you may or may not be familiar with. It helps you setup all of your databases with a graphical interface. To get to it start XAMPP then go to http://localhost/phpmyadmin

So there you have it. Now you know how to get XAMPP, install it, start/stop it, add files so you can see them, and access phpMyAdmin to help you setup your databases.

And you didn’t need to pay for hosting ūüôā

Now, are you ready to learn some PHP? Read our three part Learn PHP tutorial to get you started in the right direction. Try putting some of the example code into your helloworld.php file and see what happens.

Advertisements

AJAX Tutorial: Hangman Game (no database required)

Comments 6 Standard

Last year I made an PHP tutorial of an OOP Hangman game (no database required) for a Siminar I spoke at. This year as a part of my new Game Tutorial Series I’m adding a new tutorial to my collection. This tutorial will teach you how to modify the PHP hangman game we created and add some AJAX to it using jQuery so we don’t have to refresh the page every time we guess a new letter or start a new game. If you haven’t followed along with the original PHP tutorial I would strongly suggest you do as I won’t touch on anything introduced in the last one.

Download the Working Source Code
.zip archive

Getting jQuery

First thing is first we’ll need to get the jQuery library before we start updating any code. For those of you that don’t know, jQuery is code library that makes doing JavaScript quick and pretty painless. You can download or link to a copy offered on a Content Delivery Network (CDN) like Google Code. Personally I recommend downloading a copy if you’re going to post this game on a high traffic/visibility website. Sometimes if you link to a copy of jQuery on a CDN your site can experience lag and/or delays if the CDN is slow and your game won’t work at all if the CDN is down. On the other hand if you have a small website or limited space to store your files then there’s no need to download a copy of jQuery, linking to it is a better option. In this tutorial I’ve downloaded and included the jQuery file in the js folder of the .zip archive.

Setting Up For AJAX

Because we want our game to display using AJAX we need to create a new JavaScript file called hangman.js. This is what we’ll use to make all of our AJAX calls and respond to the player’s input.

Now that we have two JavaScript files we have to update our index.php file so it knows both of those JavaScript files are necessary to run the game. In the <head> tag, under the link to our stylesheet, we add two lines of code that tell our browser to load our JavaScript files:

<head>
        <title>Hangman</title>
        <link rel="stylesheet" type="text/css" href="inc/style.css" />
        <script language="Javascript" src="js/jquery-1.7.1.min.js"></script>
        <script language="Javascript" src="js/hangman.js"></script>
</head>

We also need to remove our $_SESSION[‘game’][‘hangman’] check from the top of our index file. Our AJAX calls will be running the game so it’s no longer necessary here. However we leave the session_start() at the top of the page so that if the player accidentally refreshes the page they don’t loose the game they had in progress.

Next we remove the code¬† inside of our <div id=”content”> and set that aside for later because we’ll need to use parts of it in our AJAX. In it’s place we’re going to enter a loading message. This is what the page will display before the AJAX calls have finished processing.

<body>
        <div id="content">
        <center>Loading Hangman.... please wait.</center>
        </div>
</body>

Writing the Hangman.js File

Now it’s time to jump into jQuery and AJAX.

$(document).ready(function() {

    //start the game when the page loads
    playGame();

});

jQuery uses a special function to check when the page has finished loading. Anything you put inside of this function will run as soon as the page is loaded, or in response to something someone has done on the page, like mouse clicks or using the keyboard. For this tutorial all we need it to do is call our AJAX function that will load and display the game to the content div on our index.php file.

/***
* Purpose: play hangman
* Preconditions: none
* Postconditions: new game has started or existing game is in play
***/
function playGame()
{
    $.ajax({
        url: 'ajax/index.php',
        data: {type: 'playGame'},
        success: function( data ) {
            $("#content").html(data);
        }
    });
}

Inside of our playGame() function we use AJAX to tell the browser to load our ajax file and send it some data (the type of action we’re doing, whether or not to start a new game, the letter the player guessed). Then we use a success callback function to load the results of our ajax call onto the page. A callback function is a function that runs as a result of being called by another process. In this case our callback function, success,¬† is loading the data we’ve retrieved through AJAX and putting it into the content div’s HTML property.

/***
* Purpose: guess a letter
* Preconditions: none
* Postconditions: game status updated
***/
function guessLetter()
{
    //make sure they've entered something into the box
    if (!$("#letter").val()) {
        alert("You must enter a letter.");
        return;
    }

    //check to make sure they've entered a letter
    if (!isLetter($("#letter").val())) {
        alert("This is not a letter. Please enter a letter.");

        //clear out the value in the input box
        $("#letter").val("");
        return;
    }

    //if it was a letter then submit the guess
    $.ajax({
        url: 'ajax/index.php',
        data: {type: 'playGame', letter: $("#letter").val()},
        success: function( data ) {
            $("#content").html(data);
        }
    });
}

/***
* Purpose: check to see if a value is a letter
* Preconditions: value to check
* Postconditions: returns true if this is a letter
***/
function isLetter(value)
{
    var lettersOnly = /^[a-zA-Z]+$/;

    //check to make sure there are no numbers and the value isn't more than 1 characters
    if(value.match(lettersOnly) && value.length == 1)
        return true;

    //otherwise this isn't a letter
    return false;
}

If we want to respond to someone trying to guess a letter we use a fairly similar process. Our guessLetter function checks to make sure the player has entered a value into our letter input box, then checks to make sure the value inside of it is really a letter, and finally uses an AJAX call to update the game by passing it the letter entered.

/***
* Purpose: start a brand new game
* Preconditions: none
* Postconditions: new game has started
***/
function newGame()
{
    $.ajax({
        url: 'ajax/index.php',
        data: {type: 'playGame', newgame: true},
        success: function( data ) {
            $("#content").html(data);
        }
    });
}

The last piece of our ajax file is the newGame function. When the game is over we want to make sure we use AJAX to update the game state and then refresh the page to a new game.

Writing the AJAX File

Now that our JavaScript file will send AJAX requests we need to write the file on the other end of the request — the file that responds to the data we’re sending it. Create a new folder and name is ajax. Inside of it make an index.php file. Inside of the file put the following:

<?php
//include the required OOP files
require_once('../oop/class.game.php');
require_once('../oop/class.hangman.php');

//this will keep the game data as they make a new ajax request
session_start();

//respond to AJAX requests
echo doAction($_GET);

function doAction($getdata)
{
    switch ($_GET['type'])
    {
        case "playGame":
            return playGame($getdata);
        default:
            return "Invalid option selected.";
    }
}

/***
* Purpose: Display and play the game
* Preconditions: a game exists
* Postconditions: the current game is displayed to the screen
***/
function playGame($getdata)
{    
    //if they haven't started a game yet let's load one
    if (!$_SESSION['game']['hangman'])
        $_SESSION['game']['hangman'] = new hangman();

    echo "<h2>Let's Play Hangman!</h2>";
    $_SESSION['game']['hangman']->playGame($getdata);
}

In this file we have two functions, doAction and playGame. Both functions take the $_GET data sent by our AJAX calls and do various things depending on the data sent to them. doAction is run every time this ajax file loads. It decides which function it needs to call, depending on the type we’ve sent it, and then returns the result to the screen.

Now pull up that code I had you set aside earlier. We’re going to move that into our playGame function with a few adjustments. We no longer need the <form> tags around our game data. In addition instead of sending $_POST data to our hangman object we’re now sending $_GET data.¬† The $_GET data contains the information we were previously posting from the <form> tags. Since AJAX is refreshing what appears inside of our content div there’s no reason to use our <form> and $_POST variables anymore.

Last But Not Least

We’re almost done! Before we can view our handy work we need to open our hangman OOP file. Anywhere we had a $_POST statement we need to change that to a $_GET since we’re no longer using the $_POST variable.

Finally,  we need to update our new game and guess buttons so they run the newGame and playGame javascript functions we wrote earlier:

<input type=\"text\" name=\"letter\" value=\"\" size=\"2\" maxlength=\"1\" id=\"letter\" />
<input type=\"submit\" name=\"submit\" value=\"Guess\" onClick=\"guessLetter()\" />

<div id=\"start_game\"><input type=\"submit\" name=\"newgame\" value=\"New Game\" onClick=\"newGame()\" /></div>"

Conclusion

Well, that wasn’t so hard now was it? Try the working version to see what it’s like! In this tutorial we took our existing PHP Hangman game and modified it to use AJAX. If you play the game you’ll see the page no longer has to refresh each time you click the guess letter button or the new game button. To accomplish this we first downloaded jQuery, created a JavaScript file to make AJAX requests, wrote a file to return a response to our AJAX requests, and then updated our hangman class to use $_GET and our new JavaScript functions.

$30,000 in prizes for your Flash games

Comment 1 Standard

Adobe and FGL Present: Cell Your Game Contest

Maybe you’ve heard the news: the newest Android mobile OS fully supports Flash. Guess what that means? Now’s the time to break into a brand new market for Flash games! Adobe and FGL are proud to host a very special contest exclusively for members of FGL. Create or port a game for mobile Flash platforms and you could win fabulous prizes — not to mention open a whole new world of players and profit. There are over $30,000 in cash and prizes and 150 games will win at least $100. Go on, check it out!

To say that we are excited about this new Flash game market would be a huge understatement. We’ve created a new forum full of guides, FAQs, and support to help you take advantage of this new frontier. Adobe is providing us with the latest guidelines, APIs, and tools, and we’ll make them available to you here.

It’s not every day that you get a chance to get in on the ground floor of a new audience for your games. And you may already have a bunch of great games that fit the mobile platform. You can back-port your catalog, or you can create new games that take advantage of the special features of Android phones, such as the accelerometer and touchscreen.

You’ve got nothing to lose and tons of money to gain. Come on!

Super Mario Programming Competition

Leave a comment Standard

Do you want to program your own Super Mario bot, that makes use of the
latest AI techniques (or your favourite dirty hacks) to guide Mario
through challenging levels? Or do you want to create an automatic
procedural level generator, that creates new levels that provide
optimal entertainment for individual human players with particular
skills and preferences? http://www.marioai.org

Are you ready to compete with researchers and programmers from around the world?

The 2010 Mario AI Championship will be held in conjunction with three
international conferences: EvoGames (part of EvoStar), IEEE World
Congress on Computational Intelligence and IEEE Conference on
Computational Intelligence and Games.

The competition is the extended successor to last year’s Mario AI
competition, which attracted the attention of leading international
news media and from which the video of the winning entry has been
shown more than 600.000 times on YouTube.

This year, the competition has three tracks:
– Gameplay track, where the goal is to submit an agent that can make
Mario survive through a number of increasingly difficult levels. This
track is similar to last year’s competition, but includes much more
difficult levels. Organized by Sergey Karakovskiy and Julian Togelius.
– Learning track, where the agent needs to learn how to play a
particular level optimally during a number of attempts. Organized by
Sergey Karakovskiy and Julian Togelius.
– Level generation track, where competitors submit level generators,
that generate fun levels according to player metrics and other
software-provided specifications. The levels will be tested “live”
on-site during the associated conferences. Organized by Noor Shaker,
Julian Togelius and Georgios Yannakakis.

The deadline for the EvoStar edition of the championship is April 1st;
deadlines for the WCCI and CIG editions are yet to be set, but will be
close to the relevant conferences (July and September).

Read more and download source code:
http://www.marioai.org

Please note that participation in the conference is not restricted to
academic researchers; professionals and students are also encouraged
to participate. Also note that the competition makes for excellent
class projects. We’re looking forward to see your entry in the
competition!

Julian Togelius
Assistant Professor
IT University of Copenhagen
Rued Langgaards Vej 7, 2300 Copenhagen S, Denmark
mail: julian@togelius.com, web: http://julian.togelius.co

Video Game References: 3D Models, Degrees, Associations & Other Useful Links

Leave a comment Standard

I find that I visit so many different sites I can’t keep them straight and I can’t remember to update my delicious account. So I started adding them as resources on my main website when I found one I liked or wanted to go back to someday in the future. Here’s a list you may want to check them out for yourself. I’ve added my own comments and knowledge thrown into the mix:

Game Engines

Crystal Space 3D

Dark GDK

G3D Engine – good tool libraries, large free model collections

jMonkey Engine

Panda3D

Torque Engine – popular with independent developers

Unreal Engine – it’s a classic… now available for free.

MMO Specific

Unity 3D – in browser 3D MMO games, quickly gaining popularity as an engine. Has iPhone and Wii capabilities.

Big World Technology

Byond – not really an engine so much as a point and click game maker

Hero Engine

Irrlicht – i really like this one, runs fast, lightweight, nice toolset. Free. Showcase includes

Multiverse

Ogre 3D – i found this one to be way too complicated and not very well planned out. API was hard to use and understand if you want something you can just jump into and start programming.

Realm Crafter

Flash Specific

SmartFoxServer – Specifically for Flash MMOs.¬† I’ve chosen this one for an MMO I have in production. Free for up to 20 users, license required for 100, 500, and unlimited users ($300 – $3,000 dollars). Showcase games include Club Penguin, Atlantas and facebook’s app YoVille, and Build-a-Bear Workshop.

Red5 Server – Completely open source and free. If you’re looking to build on your own functionality this one is for you

Electro Server – Haven’t had a chance to play around with this one but it has a free 25 user version. Licenses for up to 500 – 200,000 users ($700 to $4,500+) — no unlimited license that I could find.¬† Showcase games include WebKinz, Nickeldeon and Barbie Let’s Chat.

3D Models

3D Cafe

3D Links

3D M3

3D Revolution

TurboSquid – largest collection of models made in Maya

WireCase

Quality 3D

Poitra – expensive but nice stuff

Exchange 3D

DAZ 3D

Archive 3D – all free models

3D Extras – free models

Amazing 3D

3D Software

Maya – industry leader, costs a fortune though

3Ds Max – also an industry leader but cheaper than Maya. Owned by the same company.

Blender – free, can integrate python and lua scripting. Good support community, so-so documentation.

Drawing & Art Software

Photoshop -leading graphic art software, if you don’t have this you might as well quit now…

Painter – exclusively for people drawing with tablets

Gimp – essentially a free version of photoshop

Associations

ECA – Electronic Consumers Association

ESA – Electronic Software Association

ESRB – Entertainment Software Rating Board

IGDA – International Game Developers Association

Artists

Geninne – artist in Mexico, I want her on one of my projects one day

Creative Thursday – artists post to a new topic every thursday, great way to find a diamond in the rough

Illustration Friday – same as Creative Thursday with a bigger following

Simon Reeves – freelance 3D artist. Has done several commercials so I doubt he’s cheap.

Sarah J How – worked with her on graphics for one of my pet games. Highly recommended. She was a texture/character artists for Deep Red Games, looks like she’s running her own studio now.

DeviantArt.com – tons of various artists. As a last resort you can probably find someone here.

SQL Tutorial: Easily Update Rows Based on Complex Joins

Comment 1 Standard

There are a lot of times I’d like to update hundreds of rows in a database based on a complex set of conditions. In doing a traditional update SQL statement there is no way to pull in joins and compare the values. My little cheat for this is to run a select statement that generates all the appropriate update statements. Then all you have to do is run the resulting SQL string.

For example: Lets say you have a car racing game. You added a new garage feature where members can sort their cars into the appropriate garage. By default you gave each member their own garage when you created the new feature. Now you want to update each car belonging to every member so that it is placed inside the appropriate garage. You could build something like the following.

select ("update cars set garage='" + G.id + "' where car_id='" +  C.id + "';") as SQL from garage G
inner join cars C on C.owner = G.owner

This would give you results along the lines of:

update cars set garage='2' where car_id='3421';
update cars set garage='2341' where car_id='133212';
update cars set garage='4452'' where car_id='98321';

Pits Of Doom Lesson 7: Join, Login & Lost Password

Comments 16 Standard

In the last lesson we created a database class to make doing queries quick and easy to handle. Then we converted over the current character file and map editor to use the database when storing/retrieving information. Finally, I added an additional file so you could import your map.txt files into your database from any you made in the previous lessons.

Now it’s time to make our game start to feel like a real game. In this lesson we’ll create two new classes, a member’s class and a character’s class. Then we’ll create two new tables, a member’s table and a character’s table. Then we’ll create a join, login and lost password page so members can join, login, and access their own personal account and personal character. Last but not least, we’ll load characters that belong only to the member whose logged in and show those in the game map.

Lesson Concepts

Database Tables

In order to figure out if someone is a member of our game or not we have to store all the information in the database. This way we can pull it out any time someone tries to play the game using PHP. Just like we did with the map tables, we need to plan out the member and character tables. Think of the essential things we need to know about members and characters then draft it out like this:

Members

ID (number) – a unique number assigned to all members

Username (string) – must be at least 3 characters long, no longer then 30
cannot be changed by member

Password (string) – must be at least 5 characters long, no longer then 15
can be changed by member

Use both their username and password to login to the game

Email (string) – so we can send them their account info if they can’t remember it

Last Login (date & time) – we can keep track of the last time they logged in

Online (true or false) – we set this once they login and unset it once they logout

Money (number) – how much money they have in the game, start off with 500G

Current Character (number id of the character) – the character they’re playing right now

Banned (true or false) – if they’re banned we can make sure they can’t login and play

If we think of anything else we can add it later. If you can think of something you want on your game that is specifically for members go ahead and add it here now.

Characters

ID (number) – each character has a unique number

Member ID (number) – the ID of the member this character belongs to

First Name – must be at least 3 letters long, no longer then 15
cannot be changed after being set by member

Last Name – must be at least 5 letters long, no longer then 15
cannot be changed after being set by member

*NO 2 CHARACTERS CAN HAVE THE SAME FIRST & LAST NAME!!

Type (id of a type) – human, dragon, elf, ogre, dwarf, vampire, mage, whatever, we want to add lots of these so it’d be best to make another table and pull in the ID of the type from there.

Monster (true or false) – if this is set to true, the game automatically plays this character otherwise the character will be played by whoever it belongs to (member id).

Money (number) – characters will pickup money as they play

Health (number) – 0 to 100, when a character’s health is 0 they’re dead

Speed (number) – 0 to 100 how fast the character moves

Intelligence (number) – 0 to 100 how smart the character is

Strength (number) – 0 to 100 how powerful the character’s blows are

Agility (number) – 0 to 100 how evasive the character is

Magic (number) – 0 to 100 strength of their magic

Fighting Level (number) – starts at 0, increases after every character they kill above or equal to their fighting level

Magic Level (number) – starts at 0, increases every time they defeat someone using magic of the same or higher magic level

Magic Amount (number) – starts at 100, how much magic they have they can currently used

Weapon Equipped (id of a item) – the weapon in they’re using

Spell Equipped (id of a item) – the spell they’re using

Armor Equipped (id of item) – the armor they’re wearing

Shield Equipped (id of a item) – the shield they’re using

Map (id of a map) – the map they’re currently on

X (number) – their x position on the current map

Y (number) – their y position on the current map

Z (number) – their level on the current map

Active (true or false) – this automatically turns on when the player logs into the game and off when they logout and the character isn’t fighting

Attacking (number) – ID of the character or monster they’re attacking

Character Types

Sometimes you’ll find as you make a game adding an additional table is a HUGE help. In this case, we can easily add as many different character types to the game as we want and set the default range values they should have when they’re created. By giving each random statistics as soon as they’re made, no two will be the same.

ID (number) – a unique ID of the type of character

Name (string) – the name of this character type

To make things easier for monster creation, we can setup the minimum/maximum values each of these types should have when they’re created in the game. For instance, an Elf type would be faster then a Dwarf type.

MinHealth (number)

MaxHealth (number)

MinSpeed (number)

MaxSpeed (number)

MinIntelligence (number)

MaxIntelligence (number)

MinStrength (number)

MaxStrength (number)

MinAgility (number)

MaxAgility (number)

MinMagic (number)

MaxMagic (number)

Now that we have our three tables sketched out we can go ahead and generate the SQL for them. That would look like this:

mysql > CREATE TABLE members (
   id integer NOT NULL AUTO_INCREMENT,
   username varchar(30) NOT NULL,
   password varchar(15) NOT NULL,
   email varchar(50) NOT NULL,
   lastlogin datetime,
   online bool,
   money integer DEFAULT 500,
   curcharacter integer,
   banned bool,
   UNIQUE KEY(id)
);

mysql > CREATE TABLE characters (
   id integer NOT NULL AUTO_INCREMENT,
   memberid integer NOT NULL,
   firstname varchar(15) NOT NULL,
   lastname varchar(15) NOT NULL,
   type integer NOT NULL,
   monster bool NOT NULL,
   money integer NOT NULL,
   health integer NOT NULL,
   speed integer NOT NULL,
   intelligence integer NOT NULL,
   strength integer NOT NULL,
   agility integer NOT NULL,
   magic integer NOT NULL,
   fightlvl integer NOT NULL,
   magiclvl integer NOT NULL,
   magicamount integer NOT NULL,
   weapon integer NOT NULL,
   spell integer NOT NULL,
   armor integer NOT NULL,
   shield integer NOT NULL,
   mapid integer NOT NULL,
   x integer NOT NULL,
   y integer NOT NULL,
   z integer NOT NULL,
   active bool NOT NULL,
   attacking integer NOT NULL,
   UNIQUE KEY(id)
);

mysql > CREATE TABLE character_types (
   id integer NOT NULL AUTO_INCREMENT,
   name varchar(50) NOT NULL,
   minhealth integer NOT NULL,
   maxhealth integer NOT NULL,
   minspeed integer NOT NULL,
   maxspeed integer NOT NULL,
   minintelligence integer NOT NULL,
   maxintelligence integer NOT NULL,
   minstrength integer NOT NULL,
   maxstrength integer NOT NULL,
   minagility integer NOT NULL,
   maxagility integer NOT NULL,
   minmagic integer NOT NULL,
   maxmagic integer NOT NULL,
   UNIQUE KEY(id)
);

Creating The Classes

Now that we have our tables I find it easiest to create classes for them. This way, once we start programming, we don’t even have to worry about any of the database stuff that’s going on in the back end. I find it easier to see the big picture and put the smaller things out of mind as much as possible. So that’s what we’ll do now. In order to use these classes, we must have already established a connection to the database.

For the members class, the easiest thing to do is think of all the things you DO as a member. You join, login, change your password, pick a character to play as, and so forth. These are all things we’ll need to incorporate into our members class. For right now we’ll only do implement the things we need to join, login, and send for a lost password but you’ll see a lot more of this class as the game progresses.

I have several rules of thumb for my classes. I’ve found following these basic tips takes a lot of stress out of making a game:

1) Always comment!! If you look at your code later and don’t understand what’s going on, or why you did what you did, sometimes it takes hours — or days even — to retrace your steps. Give yourself clear cut comments on what a function does and why it does it. No, you don’t have to write a book but you should have enough information there so you can come back later and figure it out in under 5 minutes.

2) Name your class variables the same as your database field names. This may seem like a “duh” kind of comment but there are two reasons this is helpful. First, you’ll know what the field name is when you write queries in a class because all the fields are right at the top of the page. Second, we can do some really nifty database queries and assign the values right back into the variables because they both have the same name.

3) When in doubt think it out. The reason we’re making classes for our game is to help separate things out and join things together (a contradiction, I know!!). Don’t make a class do something do something that seems awkward. For example, the member doesn’t fight a monster, the character does. A character doesn’t have pits or walls, the map does. It wouldn’t make sense to give the member class a fight() function or the character class a hasPit(x, y, z) kind of function.

Member Class

<?php
/**************
* File: memberobj.php
* Purpose: member class
**************/

class member
{

    //these are named exactly the same as in the database
    //to make it easier when we use the $database class later
    var $id;
    var $username;
    var $password;
    var $email;
    var $lastlogin;
    var $online;
    var $money;
    var $curcharacter;
    var $banned;
    var $database;

   //these values are for our database queries
   var $table;
   var $where;

   //these are arrays we keep for this member
   var $characters = array(); //a list of all characters they own
   
   /**************
   * Default constructor, load this member's information
   * Remember, this always has to match the name of the class
   **************/
   function member($id)
   {
    //we need to get access to the database class
    global $_SESSION;

      if (!$id || !isNumeric($id)) //don't try to do any of this if there's no id number
         return null;

      $this->id = $id;
      $this->database = $_SESSION['database'];
      $this->table = "members"; //the name of the table we're using in our database when we
                                //run any queries on members
      $this->where = "WHERE id='$this->id'"; //we always want records from members with this ID

      //now we use the database class we made to pull in all the information about this member
      $this->username = $this->database->select("username", $this->table, $this->where);
      $this->password = $this->database->select("password", $this->table, $this->where);
      $this->email = $this->database->select("email", $this->table, $this->where);
      $this->lastlogin = $this->database->select("lastlogin", $this->table, $this->where);
      $this->online = $this->database->select("online", $this->table, $this->where);
      $this->money = $this->database->select("money", $this->table, $this->where);
      $this->curcharacter = $this->database->select("curcharacter", $this->table, $this->where);
      $this->banned = $this->database->select("banned", $this->table, $this->where);

     //last but not least, we have to load any characters they have
     //this uses a function in the database class I never talked about before
     //it goes through the database and finds the ID number of every character they own
     //then it creates a character object for each of those characters they own and puts
     //them into an array. Finally, it returns that array to the character class so we can
     //view all of the players characters.
     $this->characters = $this->database->loadArray("id", "characters", "WHERE memberid='$this->id'", "character");

     //!!!!! To really get an understanding of what this does, I suggest you uncomment the line
     //below and see what happens. It will print out all the information on each character the
     //member owns.

     //print_r($this->characters);

   } //end default constructor

   /**************
   * The member has supplied the correct login information, log them into the game
   **************/
   function login()
   {

       //remember to update the object value
       $this->lastlogin = time();

       //and the database value for the field
       $this->database->update($this->table, "lastlogin", $this->lastlogin);

       $this->online = true;
       $this->database->update($this->table, "online", $this->online);

       //make all their character's active now that they're online
       $this->database->update("characters", "active=true", "WHERE memberid='$this->id'");
   }

   /**************
   * The member is leaving the game
   **************/
   function logout()
   {

       $this->online = false;
       $this->database->update($this->table, "online", $this->online);

       //make all their character's active now that they're online
       $this->database->update("characters", "active=false", "WHERE memberid='$this->id'");
   }
} //end the members class
?>

Character Class

<?php
/**************
* File: characterobj.php
* Purpose: character class
**************/

class character
{

    //my rule of thumb is, always have variables
    //for every field in your database so you can access them
    //quickly and easily
    var $id;
    var $memberid;
    var $firstname;
    var $lastname;
    var $type;
    var $monster;
    var $money;
    var $health;
    var $speed;
    var $intelligence;
    var $strength;
    var $agility;
    var $magic;
    var $fightlvl;
    var $magiclvl;
    var $magicamount;
    var $weapon;
    var $spell;
    var $armor;
    var $shield;
    var $mapid;
    var $x;
    var $y;
    var $z;
    var $active;
    var $attacking;
    var $database;


   //these values are for our database queries
   var $table;
   var $where;
   
   /**************
   * Default constructor, load this characters's information
   **************/
   function character($id)
   {
    //we need to get access to the database class
    global $_SESSION;

      if (!$id || !isNumeric($id)) //don't try to do any of this if there's no id number
         return null;

      $this->id = $id;
      $this->database = $_SESSION['database'];
      $this->table = "characters";
      $this->where = "WHERE id='$this->id'";

      //now we use the database class we made to pull in all the information about this member
      $this->id = $this->database->select("id", $this->table, $this->where);
      $this->firstname = $this->database->select("firstname", $this->table, $this->where);
      $this->lastname = $this->database->select("lastname", $this->table, $this->where);
      $this->type = $this->database->select("type", $this->table, $this->where);
      $this->monster = $this->database->select("monster", $this->table, $this->where);
      $this->money = $this->database->select("money", $this->table, $this->where);
      $this->health = $this->database->select("health", $this->table, $this->where);
      $this->speed = $this->database->select("speed", $this->table, $this->where);
      $this->intelligence = $this->database->select("intelligence", $this->table, $this->where);
      $this->strength = $this->database->select("strength", $this->table, $this->where);
      $this->agility = $this->database->select("agility", $this->table, $this->where);
      $this->fightlvl = $this->database->select("fightlvl", $this->table, $this->where);
      $this->magiclvl = $this->database->select("magiclvl", $this->table, $this->where);
      $this->magicamount = $this->database->select("magicamount", $this->table, $this->where);
      $this->weapon = $this->database->select("weapon", $this->table, $this->where);
      $this->spell = $this->database->select("spell", $this->table, $this->where);
      $this->armor = $this->database->select("armor", $this->table, $this->where);
      $this->shield = $this->database->select("shield", $this->table, $this->where);
      $this->mapid = $this->database->select("mapid", $this->table, $this->where);
      $this->x = $this->database->select("x", $this->table, $this->where);
      $this->y = $this->database->select("y", $this->table, $this->where);
      $this->z = $this->database->select("z", $this->table, $this->where);
      $this->active = $this->database->select("active", $this->table, $this->where);
      $this->attacking = $this->database->select("attacking", $this->table, $this->where);

   } //end default constructor

   /**************
   * Move around the map (does this look familiar?!?)
   **************/
   function move($direction)
   {

        //we need to get the character's current location
	$newx = $this->x;
	$newy = $this->y;

	switch($direction) //we want to change what we're checking
			   //depending on the direction the character is moving
	{
		case "right": $newy++; //add one to the y value
			break;
		case "left": $newy--; //subtract one from the y value
			break;
		case "back": $newx++; //add one to x value
			break;
		case "forward": $newx--; //subtract one from the x value
			break;
	}

	if (getValue($newx, $newy, $this->mapid, $this->z) == "L")
	{
		//they are currently ON a ladder position
		//if they hit the up direction, move them up a level (if not at level 1)
		if ($direction == "forward" && $this->z != 1)
		{
			echo "You moved up the ladder!";

			//move them up a level
			$this->z = $this->z - 1;

			//set the character's starting position in the map
			$this->x = startPositionX($this->mapid, $this->z);
			$this->y = startPositionY($this->mapid, $this->z);

			//now we save their position to the database so if they log off
			//or leave the game the character is still in this position when
			//they come back and play later
			$this->database->update("character", "x=$this->x, y=$this->y, z=$this->z", $this->where);

		}
		else if ($direction != "back")
		{
				//let them move some other direction
				if (getValue($newx, $newy, $this->mapid, $this->z) == "T")
				{
					//the treasure is in this direction
					echo "You found the treasure!";
					$this->x = $newx;
					$this->y = $newy;

					//update their position
					$this->database->update("character", "x=$this->x, y=$this->y", $this->where);
				}

				else if (getValue($newx, $newy, $this->mapid, $this->z) == "W")
				{
					//don't update their position, they can't move here
					echo "You hit a wall!";
				}

				else if (getValue($newx, $newy, $this->mapid, $this->level) == "E")
				{
					//empty space, move them to this new location
					echo "You moved $direction one space.";

					$this->x = $newx;
					$this->y = $newy;

					//update their position
					$this->database->update("character", "x=$this->x, y=$this->y", $this->where);
				}

				else if (getValue($newx, $newy, $this->mapid, $this->level) == "S")
				{
					//starting location, move them to this new location
					echo "You moved $direction one space.";

					$this->x = $newx;
					$this->y = $newy;

					//update their position
					$this->database->update("character", "x=$this->x, y=$this->y", $this->where);
				}

				else if (getValue($newx, $newy, $this->mapid, $this->level) == "X")
				{
					//they found a pit
					echo "You fell into a pit and dropped down a level!";

					//move them down a level
					$this->z = $this->z + 1;

					$this->x = startPositionX($this->mapid, $this->z);
					$this->y = startPositionY($this->mapid, $this->z);

					//update their position
					$this->database->update("character", "x=$this->x, y=$this->y, z=$this->z", $this->where);
				}

				else if (getValue($newx, $newy, $this->mapid, $this->z) == "L")
				{
					//they found a ladder
					echo "You found a ladder. Move up or down?";

					//move them to the position on the map that has the ladder
					//but don't change which level they're on
					$this->x = $newx;
					$this->y = $newy;

					//update their position
					$this->database->update("character", "x=$this->x, y=$this->y", $this->where);
				}
		}

		//if they hit the down direction, move them down a level (if not at level 5)
		if ($direction == "back" && $this->z != 5)
		{
			echo "You moved down the ladder!";

			//move them down a level
			$this->z = $this->z + 1;

			//set the character's starting position in the NEW map
			$this->x = startPositionX($this->mapid, $this->z);
			$this->y = startPositionY($this->mapid, $this->z);

			//update their position
			$this->database->update("character", "x=$this->x, y=$this->y, z=$this->z", $this->where);
		}
		else if ($direction != "forward")
		{
			//let them move some other direction
				if (getValue($newx, $newy, $this->mapid, $this->z) == "T")
				{
					//the treasure is in this direction
					echo "You found the treasure!";

					$this->x = $newx;
					$this->y = $newy;

					//update their position
					$this->database->update("character", "x=$this->x, y=$this->y", $this->where);

				}

				else if (getValue($newx, $newy, $this->mapid, $this->level) == "W")
				{
					//don't update their position, they can't move here
					echo "You hit a wall!";
				}

				else if (getValue($newx, $newy, $this->mapid, $this->level) == "E")
				{
					//empty space, move them to this new location
					echo "You moved $direction one space.";
					$this->x = $newx;
					$this->y = $newy;

					//update their position
					$this->database->update("character", "x=$this->x, y=$this->y", $this->where);
				}

				else if (getValue($newx, $newy, $this->mapid, $this->z) == "S")
				{
					//starting location, move them to this new location
					echo "You moved $direction one space.";
					$this->x = $newx;
					$this->y = $newy;

					//update their position
					$this->database->update("character", "x=$this->x, y=$this->y", $this->where);
				}

				else if (getValue($newx, $newy, $this->mapid, $this->z) == "X")
				{
					//they found a pit
					echo "You fell into a pit and dropped down a level!";

					//move them down a level
					$this->z = $this->z + 1;

					$this->x = startPositionX($this->mapid, $this->z);
					$this->y = startPositionY($this->mapid, $this->z);

					//update their position
					$this->database->update("character", "x=$this->x, y=$this->y, z=$this->z", $this->where);
				}

				else if (getValue($newx, $newy, $this->mapid, $this->z) == "L")
				{
					//they found a ladder
					echo "You found a ladder. Move up or down?";

					//move them to the position on the map that has the ladder
					//but don't change which level they're on
					$this->x = $newx;
					$this->y = $newy;

					//update their position
					$this->database->update("character", "x=$this->x, y=$this->y", $this->where);
				}
		}
	}

	else if (getValue($newx, $newy, $this->mapid, $this->z) == "T")
	{
		//the treasure is in this direction
		echo "You found the treasure!";

		$this->x = $newx;
		$this->y = $newy;

		//update their position
		$this->database->update("character", "x=$this->x, y=$this->y", $this->where);
	}

	else if (getValue($newx, $newy, $this->mapid, $this->z) == "W")
	{
		//don't update their position, they can't move here
		echo "You hit a wall!";
	}

	else if (getValue($newx, $newy, $this->mapid, $this->z)== "E")
	{
		//empty space, move them to this new location
		echo "You moved $direction one space.";

		$this->x = $newx;
		$this->y = $newy;

		//update their position
		$this->database->update("character", "x=$this->x, y=$this->y", $this->where);
	}

	else if (getValue($newx, $newy, $this->mapid, $this->z) == "S")
	{
		//starting location, move them to this new location
		echo "You moved $direction one space.";

		$this->x = $newx;
		$this->y = $newy;

		//update their position
		$this->database->update("character", "x=$this->x, y=$this->y", $this->where);
	}

	else if (getValue($newx, $newy, $this->mapid, $this->z) == "X")
	{
		//they found a pit
		echo "You fell into a pit and dropped down a level!";

		//move them down a level
		$this->z = $this->z + 1;

		//set the character's starting position in the map
		$this->x = startPositionX($this->mapid, $this->z);
		$this->y = startPositionY($this->mapid, $this->z);

		//update their position
		$this->database->update("character", "x=$this->x, y=$this->y, z=$this->z", $this->where);
	}

	else if (getValue($newx, $newy, $this->mapid, $this->z) == "L")
	{
		//they found a ladder
		echo "You found a ladder. Move up or down?";

		//move them to the position on the map that has the ladder
		//but don't change which level they're on
		$this->x = $newx;
		$this->y = $newy;

		//update their position
		$this->database->update("character", "x=$this->x, y=$this->y", $this->where);
	}

} //end the character class
?>

Character Types Class

<?php
/**************
* File: charactertypeobj.php
* Purpose: character types
**************/

class charactertype
{

    var $id;
    var $name;
    var $minhealth;
    var $maxhealth;
    var $minspeed;
    var $maxspeed;
    var $minintelligence;
    var $maxintelligence;
    var $minstrength;
    var $maxstrength;
    var $minagility;
    var $maxagility;
    var $minmagic;
    var $maxmagic;
    var $database;

   //these values are for our database queries
   var $table;
   var $where;
   
   /**************
   * Default constructor, load character type
   **************/
   function charactertype($id)
   {
    //we need to get access to the database class
    global $_SESSION;

      if (!$id || !isNumeric($id)) //don't try to do any of this if there's no id number
         return null;

      $this->id = $id;
      $this->database = $_SESSION['database'];
      $this->table = "character_types"; //the name of the table we're using in our database when we
                                //run any queries on members
      $this->where = "WHERE id='$this->id'"; //we always want records from members with this ID

      //now we use the database class we made to pull in all the information about this member
      $this->name = $this->database->select("name", $this->table, $this->where);
      $this->minhealth = $this->database->select("minhealth", $this->table, $this->where);
      $this->maxhealth = $this->database->select("maxhealth", $this->table, $this->where);
      $this->minspeed = $this->database->select("minspeed", $this->table, $this->where);
      $this->maxspeed = $this->database->select("maxspeed", $this->table, $this->where);
      $this->minintelligence = $this->database->select("minintelligence", $this->table, $this->where);
      $this->maxintelligence = $this->database->select("maxintelligence", $this->table, $this->where);
      $this->minstrength = $this->database->select("minstrength", $this->table, $this->where);
      $this->maxstrength = $this->database->select("maxstrength", $this->table, $this->where);
      $this->minagility = $this->database->select("minagility", $this->table, $this->where);
      $this->maxagility = $this->database->select("maxagility", $this->table, $this->where);
      $this->minmagic = $this->database->select("minmagic", $this->table, $this->where);
      $this->maxmagic = $this->database->select("maxmagic", $this->table, $this->where);

   } //end default constructor

} //end the character type class
?>

Join Script

We don’t want just anyone to be able to access characters and maps in the game, they should only see things that belong to them. In order to do this we’ll have them make an account in our database and automatically create a character for them to start playing with. When we do this we’ll generate random statistics for the character based on the data we have in our character types data.

Lost Password Script

It’s inevitable, eventually you’ll forget the information you entered when you joined the site. Creating a lost password script will remedy this situation. Now your members can have their login & password sent directly to their email address instead of bogging down your inbox with pointless password requests!

Login Script

Time to verify, are you who you say you are? The biggest downfall of a login is that anyone who has the correct login/password combination will be able to access the information for the account, but that’s something we’ve come to accept as unavoidable with online account security. However, we can make things as secure as possible by only allowing members who have logged in to view certain parts of the website. We’ll enhance that even further by only giving them access to records they own or created themselves.

$database = & new database($host, $username, $password, $db);

if ($_POST['submit'])
{

	//check to see if this login is in the members table
	//by retrieving their member id if their username and password matches
	$id = $database->single("id", "members", "WHERE username='" . $_POST['username'] . "' AND
							password='" . $_POST['password'] . "'");

	//we found the member, let's create a session with this member's information
	if ($id)
	{
		$_SESSION['database'] = $database;
		$_SESSION['member'] = & new member($id);

		//log them into the game
		$_SESSION['member']->login();

		//now let's redirect them to the map and their character
		header("Location: character_v6.php");
		exit;
	}

	//we didn't find the login, we won't let them login
	$error = errorMsg("Incorrect login information");
}

The logic behind this script is fairly straightforward. First we connect to the database, then if they’ve hit the submit button we pass the username and password they entered into the form to our member object. If we find a member ID that matches that information we give them access to the game by storing the member object into a session. Otherwise their login information was incorrect and they need to try again.

Summary

Try the working version! In this lesson we added a huge backbone to what is going to quickly become a working, running game. Now we’ve restricted access to the map view to people who have logged in. In order to be logged in you must have an account in our database — thus we created a join script people can use to create a default character and setup their own unique login and password. Finally, to top it off, we made a lost password form so anyone who forgets their login information can have it emailed to them.

Game Files

Working Version:

Pits of Doom, use the login below or sign up and create your own account!

Login: test

Password: test

Source Files:

Class Files:

classfiles.php
functions.php

Object Files:

mysqlobj.php
memberobj.php
characterobj.php
charactertypeobj.php

Game Files

login.php
join.php
lostpassword.php
character.php

SQL Data:

pitsofdoom.sql — includes character types and default map

Lesson Reasoning

This lessons is all about planning out the underlying structure of members and characters and how they interact with the game map. Each member can have multiple characters. In order to do that we have to prompt the user for their login information: this way we can verify they are who they say they are. Once we know who the member is, we load all the information from the database about the characters they have. Finally, we display their character’s information in the map depending on the information we have about the character in our database.

In the next lesson we’ll create a way for members to create their own characters, instead of automatically creating one for them when they join. We’ll also start working on monsters (!!!!) and letting character’s battle them in the map.

Go Back to Lesson 6 or Continue to Lesson 8