Building Browsergames: Putting it all together (PHP)

So, we’ve built a simple registration page, and a simple login page. Now it’s time to tie it all together, so that we can use the things we’ve been working on in our game.

First off, we’re not going to require users to validate their e-mail addresses. This is a decision that’s really up to you – but for the sake of this tutorial, users won’t need to validate their e-mail. If you want to make them verify it, you can always use the e-mail confirmation system we walked you through building earlier.

But before we start writing any code, we’re going to need a database structure to work with. We’ll just work off of the structure we set up in the other tutorials:

CREATE TABLE users (
	id int NOT NULL AUTO_INCREMENT,
	username varchar(250),
	password varchar(50),
	is_admin tinyint(1) DEFAULT 0,
	PRIMARY KEY(id)
);[php]
[php]CRE/ATE TABLE stats (
	id int NOT NULL AUTO_INCREMENT,
	display_name text,
	short_name varchar(10),
	PRIMARY KEY(id)
);

 

INSERT INTO stats(display_name,short_name) VALUES ('Magic','mag');
INSERT INTO stats(display_name,short_name) VALUES ('Attack','atk');
INSERT INTO stats(display_name,short_name) VALUES ('Defence','def');
CREATE TABLE user_stats (
	id int NOT NULL AUTO_INCREMENT,
	user_id int,
	stat_id int,
	value text,
	PRIMARY KEY(id)
);

On the code side, we’ll start with making our registration page from earlier and make it auto-focus, remember the values sent to it, and use Smarty. This is what the Smarty template for our registration page will look like:

 

<html>
	<head>
		<title>Register</title>
	</head>
	<body>
		{if $error ne ""}
			<span style='color:red'>Error: {$error}</span>
		{/if}
		{if $message ne ""}
			<span style='color:green'>{$message}</span>
		{/if}
		<form method='post' action='register.php'>
			Username: <input type='text' name='username' id='username' value='{$smarty.post.username}' /><br />
			Password: <input type='password' name='password' /><br />
			Confirm Password: <input type='password' name='confirm' /><br />
			<input type='submit' value='Register!' />
		</form>
		<script type='text/javascript'>
		document.getElementById('username').focus();
		</script>
	</body>
	</html>

We used a conditional statement to make sure that our error and success messages only display when there is actually something to display – but other than that, you’ve seen all of this before. Save that file as register.tpl, and put it into your smarty templates directory that we set up earlier.

The next thing we need to build is the actual registration page that uses the Smarty template. It’s pretty easy to just modify our other registration code to work with Smarty:

 

<?php
 
// put full path to Smarty.class.php
require('/usr/local/lib/php/Smarty/Smarty.class.php');
$smarty = new Smarty();
 
$smarty->template_dir = '/web/www.domain.com/smarty/templates';
$smarty->compile_dir = '/web/www.domain.com/smarty/templates_c';
$smarty->cache_dir = '/web/www.domain.com/smarty/cache';
$smarty->config_dir = '/web/www.domain.com/smarty/configs';
 
if($_POST) {
	$password = $_POST['password'];
	$confirm = $_POST['confirm'];
	if($password != $confirm) {
		$error = 'Passwords do not match!';	
	} else {
		require_once 'config.php';		// our database settings
		$conn = mysql_connect($dbhost,$dbuser,$dbpass)
			or die('Error connecting to mysql');
		mysql_select_db($dbname);
		$query = sprintf("SELECT COUNT(id) FROM users WHERE UPPER(username) = UPPER('%s')",
			mysql_real_escape_string($_POST['username']));
		$result = mysql_query($query);
		list($count) = mysql_fetch_row($result);
		if($count >= 1) { 
			$error = 'that username is taken.';
		} else {
			$query = sprintf("INSERT INTO users(username,password) VALUES ('%s','%s');",
				mysql_real_escape_string($_POST['username']),
				mysql_real_escape_string(md5($password)));
			mysql_query($query);			
			$message = 'Congratulations, you registered successfully!';
		}
	}	
}
$smarty->assign('error',$error);
$smarty->assign('message',$message);
$smarty->display('bb-register.tpl');
 
?>

And that’s our registration form, using Smarty. But we still don’t quite have any stats set up for the user – and they’re going to need some stats. Let’s take our flexible stats code from earlier, and bake it into our code. To begin with, we’ll start off with the basic stats code from before, and just add the fact that whenever a stat is requested that doesn’t exist, it creates a new row in the database for that stat for the user, and sets the stat’s value to 0:

 

function getStat($statName,$userID) {
	require_once 'config.php';
	$conn = mysql_connect($dbhost,$dbuser,$dbpass)
		or die ('Error connecting to mysql');
	mysql_select_db($dbname);
	$query = sprintf("SELECT count(value) FROM user_stats WHERE stat_id = (SELECT id FROM stats WHERE display_name = '%s' OR short_name = '%s') AND user_id = '%s'",
		mysql_real_escape_string($statName),
		mysql_real_escape_string($statName),
		mysql_real_escape_string($userID));
	$result = mysql_query($query);
	list($count) = mysql_fetch_row($result);
	if($count == 0) {
		// the stat doesn't exist; insert it into the database
		$query = sprintf("INSERT INTO user_stats(stat_id,user_id,value) VALUES ((SELECT id FROM stats WHERE display_name = '%s' OR short_name = '%s'),'%s','%s')",
		mysql_real_escape_string($statName),
		mysql_real_escape_string($statName),
		mysql_real_escape_string($userID),
		'0');
		mysql_query($query);
	}
	$query = sprintf("SELECT value FROM user_stats WHERE stat_id = (SELECT id FROM stats WHERE display_name = '%s' OR short_name = '%s') AND user_id = '%s'",
		mysql_real_escape_string($statName),
		mysql_real_escape_string($statName),
		mysql_real_escape_string($userID));
	$result = mysql_query($query);
	list($value) = mysql_fetch_row($result);
	return $value;		
}
function setStat($statName,$userID,$value) {
	require_once 'config.php';
	$conn = mysql_connect($dbhost,$dbuser,$dbpass)
		or die ('Error connecting to mysql');
	mysql_select_db($dbname);
	$query = sprintf("UPDATE user_stats SET value = '%s' WHERE stat_id = (SELECT id FROM stats WHERE display_name = '%s' OR short_name = '%s') AND user_id = '%s'",
		mysql_real_escape_string($value),
		mysql_real_escape_string($statName),
		mysql_real_escape_string($statName),
		mysql_real_escape_string($userID));
	$result = mysql_query($query);
}

At this point, we’ve set up our database structure, created our registration page, and set up the stats code so that we can retrieve a user’s stats after they’ve logged in. But we still don’t have a login page! We’ll start off by creating another Smarty template, called login.tpl:

<html>
	<head>
		<title>Login</title>
	</head>
	<body>
		{if $error ne ""}
			<span style='color:red'>Error: {$error}</span>
		{/if}
		<form action='login.php' method='post'>
			Username: <input type='text' name='username' id='username' value='{$smarty.post.username}' /><br />
			Password: <input type='password' name='password' /><br />
			<input type='submit' value='Login' />
		</form>	
		<script type='text/javascript'>
		document.getElementById('username').focus();
		</script>
	</body>
	</html>

Next, we’ll modify our login page to use Smarty and the template we just built:

 

<?php
 
// put full path to Smarty.class.php
require('/usr/local/lib/php/Smarty/Smarty.class.php');
$smarty = new Smarty();
 
$smarty->template_dir = '/web/www.domain.com/smarty/templates';
$smarty->compile_dir = '/web/www.domain.com/smarty/templates_c';
$smarty->cache_dir = '/web/www.domain.com/smarty/cache';
$smarty->config_dir = '/web/www.domain.com/smarty/configs';
 
session_start();
if($_POST) {
	require_once 'config.php';
	$username = $_POST['username'];
	$password = $_POST['password'];		
	$conn = mysql_connect($dbhost,$dbuser,$dbpass)
		or die ('Error connecting to mysql');
	mysql_select_db($dbname);
	$query = sprintf("SELECT COUNT(id) FROM users WHERE UPPER(username) = UPPER('%s') AND password='%s'",
		mysql_real_escape_string($username),
		mysql_real_escape_string(md5($password)));
	$result = mysql_query($query);
	list($count) = mysql_fetch_row($result);
	if($count == 1) {
		$_SESSION['authenticated'] = true;
		$_SESSION['username'] = $username;
		$query = sprintf("UPDATE users SET last_login = NOW() WHERE UPPER(username) = UPPER('%s') AND password = '%s'",
			mysql_real_escape_string($username),
			mysql_real_escape_string(md5($password)));
		mysql_query($query);
		$query = sprintf("SELECT is_admin FROM users WHERE UPPER(username) = UPPER('%s') AND password='%s'",
			mysql_real_escape_string($username),
			mysql_real_escape_string(md5($password)));
		$result = mysql_query($query);
		list($is_admin) = mysql_fetch_row($result);
		if($is_admin == 1) {
			header('Location:admin.php');			
		} else {
			header('Location:index.php');				
		}
	} else {	
		$error = 'There is no username/password combination like that in the database.';
	}
}
 
$smarty->assign('error',$error);
$smarty->display('bb-login.tpl');
?>

And finally, we’ll add an ultra-basic index page – for now, it will just show the user their current username, and give them a link to log out. Here’s what the template will look like – save it as index.tpl:

 

<html>
	<head>
		<title>Index Page</title>
	</head>
	<body>
		<p>Hello, {$name}!</p>
		<p><a href='logout.php'>Logout</a></p>
	</body>
	</html>

And here’s the code behind our ultra-simple index page:

 

<?php
 
// put full path to Smarty.class.php
require('/usr/local/lib/php/Smarty/Smarty.class.php');
$smarty = new Smarty();
 
$smarty->template_dir = '/web/www.domain.com/smarty/templates';
$smarty->compile_dir = '/web/www.domain.com/smarty/templates_c';
$smarty->cache_dir = '/web/www.domain.com/smarty/cache';
$smarty->config_dir = '/web/www.domain.com/smarty/configs';
 
session_start();
$smarty->assign('name', $_SESSION['username']);
$smarty->display('index.tpl');
 
?>

And, to put the icing on the cake, let’s add our logout page. It’s pretty simple:

 

<?php
session_start();
$_SESSION = array();
if (isset($_COOKIE[session_name()])) {
    setcookie(session_name(), '', time()-42000, '/');
}
session_destroy();
header('Location:http://google.com');
?>

All it does is clear all the session data, remove the cookie being used to track the session, and then redirect the user to http://google.com – although you could redirect them to whatever page you wanted to(WordPress, for example, redirects to the login page with ?logged_out=true, displaying a little ‘hey, you logged out!’ message.).

And that’s all there is to the beginnings of our game! Now users can register, log in, see their username on the index page, and log out. It might not seem like much, but it’s the basic framework that every game needs – including yours.