Building Browsergames: Getting started with a templating system (PHP)

May 16, 2008 – 8:00 am

When you start building significant pieces of your game beyond the basic login and registration systems, you start to realize that you’re copying and pasting the basic layout of your pages a lot. Wouldn’t it be nice to have a template that you can drop all of the unique content into, and re-use on every page?

The answer is that you can - and should. It will help you separate your design from your code, which(if you’re anything like me) means that you can have someone with actual designing skills come through and fix up your template before you push your site out to the rest of the world.

This will be a brief rundown on how to get up and running with a templating engine, which is what we will be using to build all of the other parts of our browsergame in progress. For a PHP templating engine, I’ve chosen Smarty. I did this by taking a look at Smarty’s list of features, and deciding whether I liked them or not - when you choose a templating engine, that’s really all the forethought you need to put into it - will it work for you, and are you okay with working with it? As an aside, if you don’t like your templating system you can always switch systems for your next project.

A lot of developers are fans of “rolling their own” templating system. While this can definitely work, you’re probably going to make larger gains by simply using an existing one - if you need anyone to help you with your game later(or it really takes off and you hire someone), it will be a benefit to be using a system that they might already know as opposed to a proprietary system. Also, why do all that work when it’s already been done for you?

The Smarty website has a smarty quick start tutorial, which you can use to get yourself up and running with Smarty.

Once you’ve gotten Smarty set up on your system, we’ll be building the index page that our login page from earlier redirects to for non-administrator users. To start off with, we’ll just use the testing index.tpl file from the Smarty quick start:

1
2
3
4
5
6
7
8
<html>
<head>
	<title>My Index Page</title>
</head>
<body>
	<p>Hello, {$name}!</p>
</body>
</html>

Next, we’ll use the index.php file from the Smarty quick start, and modify it so that it displays the currently authenticated user’s username:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?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');
 
?>

As you can see, there isn’t that much of a change made - we add a call to session_start() to load up our previously stored session values, and then we use one of them to display the user’s username. If you visit your testing page, you should see the username that you logged in with - which means that Smarty is working! With Smarty we’ll be able to make sure that our code and designs no longer have to be intermingled - meaning that there’s less chance of accidentally screwing up one while working on the other.

If you want to see it in action, you can first register, then login to get redirected to the index page - which will show you the username you’re currently logged in with.


Does your game need Javascript?

May 15, 2008 – 8:00 am

Ajax is defined as ‘Asynchronous Javascript And XML’, and is used to allow pages to update small pieces of themselves, without needing to refresh the page. But does your game need it?

While most developers have been eager to adopt Ajax and build it into any(and sometimes all) of their projects, the core of the matter is that you don’t really need it, and you shouldn’t worry about it until later.

There are a few reasons for this:

Users with Javascript turned off

According to browser stats from the W3C, as of January 2008 95% of their visitors had Javascript enabled - but what about the other 5%? If you don’t make sure to build the parts of your game that are Javascript-driven in such a way that they will also be available to users who don’t have Javascript turned on, you’ve effectively killed your game in their eyes - users with Javascript disabled will think that it’s broken.

And don’t think that you can just have a boilerplate disclaimer that says “you need to be using Javascript to use this site” - some users might be accessing your game in a situation where a network or systems administrator has told them to absolutely under no condition enable Javascript. It sounds strange, but it happens.

Browser Incompatabilities

While this can be solved with extensive debugging, if you don’t use Javascript, you’ll never encounter a problem with how your game behaves from browser-to-browser - and there will never be strange Javascript errors that you need to debug. It will all just work!

Javascript for Javascript’s sake

Some developers tend to go overboard when they first learn about Ajax, and start adding it to everything - instead of having a link to a page in a situation where a link to a page would be ideal, they write complicated Ajax wrappers to load the page and display it. This is a clear case of too much Javascript, and it will frustrate your users.


At the end of the day, whether you use Javascript/Ajax in your game or not is completely up to you - but carefully consider any decision that results in adding Javascript - will it improve the user’s experience? Will the feature still work as intended for users with Javascript disabled? Both are important questions you need to ask and answer before you write one line of Javascript for your game. Doesn’t matter how cool your game is.


Interview: Josh Fisher from Urbaniacs

May 14, 2008 – 8:00 am

Urbaniacs Logo

I recently got in touch with Josh Fisher, the creative force behind the browser game Urbaniacs. We sent a few e-mails back and forth, and I managed to ask him a few questions about his browsergame:

What first got you started building browsergames?

I cam from traditional media. I spent about 8 years producing animation for companies like Fox Kids, Cartoon Network, ABC Family, and others. When Neopets first came out, I knew there was something really fun there, but I didn’t really know how to engage that world. Eventually, as bandwidth (and NeoPets) grew, it became an easy transition. While the animation market was shrinking, online game worlds seemed to be popping up everywhere. My partner Barry Collier and I decided to start one on our own, just for fun. the idea was that we both liked comic books and hip hop… so we created Urbaniacs. To us, it was a great combo of what we liked. In our world, you could be a funky urban hero or villain, play games, and meet some interesting people. It has been a real treat watching it grow into a thriving community.

What language(s) did you use to build Urbaniacs?

The site is programmed primarily in PHP.

What other game(s) have you made? What have you learned while building them?

I’ve been the producer on NFL Rush Zone, the NFL’s game world for kids, for the last 18 months. Working with their team has opened my eyes to the what is possible when you have a larger staff working together. Urbaniacs has always been a 2 and 3 person shop. It’s a lot easier to get things done in a short period of time when you have resources. The NFL has also inspired us to push the technical aspects a bit further. They have been great to work with and when someone gives you a great challenge with a great brand, it’s exciting to respond to that challenge.

Do you have any tips for someone looking to get into building browsergames, or for people just starting out?

I think the most important thing is planning. Know what you want and what you want to be before you get started. Switching gears can be a frustrating experience for the users and for your team. I’d rather spend some extra time digging in and understanding the audience, and knowing what it is we will be offering them. It’s really two things, 1 is good planning and the second is sticking to your plans and executing them in the best possible way.

Do you have any recommendations in terms of monetization or advertising strategies? There are a lot of browsergames out there to compete with.

If I had a good answer, my life would be easier. We’ve avoided VC at this point. Monetizing your traffic is the smartest money you can spend (when it’s your own money). We’ve got micro-payments and ads. We haven’t gone down the subscription road yet, but a lot of companies do well with that model. When I find one that really works, I’ll let you know.

About Urbaniacs

Urbaniacs is a comic book world come to virtual life. Transform your online self into your own funk-infused super-avatar known as an Urbaniac. Meet new “Homeys” or challenge your “Arch Enemies” to a multiplayer Battle. Each Urbaniac can be customized in thousands of ways. While the characters and styles are immediately attractive to younger audiences, the depth, clever games, and irreverent sensibility appeal to teens and adults who play. There is a wide range of humorous and entertaining interactions for anyone looking for an adventure. Direct your Urbaniac to The Streets to chat with friends and show off your funky super powers or cruise to the Arena, where you can take out some aggressions with a hilarious round of “Wedgie Toss.” You can join a local challenge to become a Boom Box master or spend some time earning Urbos (Urbanville’s currency) while playing Beat Bot Boogie. There are many compelling social community features built into the comic gameplay of the world. Once you’ve earned some Urbos you can head down to the “Pimp Out Depot” to trade them in for some fresh new gear and gadgets to equip on your Urbaniac. But be careful! At any moment, you could be faced with a challenge, assault, or battle by another Urbaniac or one of the in game characters. Scared? Don’t be. Just invite some homeys along and you and your crew could take over the city in no time.

The group elements make the site come to life. Try your best to out-rap Urbanville’s Mayor DaMan in the “Freestyle” rap forum or check out the “Newbie” posts to get some insider tips about how to play the more challenging games. Better yet, create your own forum and see how the Urbaniacs community responds. Urbaniacs is an evolving virtual world created to inspire the imagination and provide hours of fun, funny, funky entertainment and adventure to all who participate.

For more information contact Co-founder and Urbanville Mayor, Josh Fisher at Josh@Urbaniacs.com.

Hey!

Know someone who’s built(or is building) a cool browsergame? Drop me a line at buildingbrowsergames@gmail.com so I can get in touch with them!


Diary of a Browsergame: The Codex

May 13, 2008 – 8:00 am

Work is well under way on writing up the Design Document for Working Title, version 1.0. And while there have been a lot of neat ideas and a few not-so-neat ideas, I’m happy to say that I think it’s coming along - albeit slowly.

One of the first implementation choices that I’ve made(I haven’t written any code yet!) is to build Working Title using the Object-Oriented paradigm. That means that each of my players, monsters, and items will be an object, and completely self-contained.

One of the nice things about building all of my objects using the Object Oriented approach is that I can use inheritance to take care of some of the dirty work for me. One function that I will be implementing will exist on each object, and be known simply as toHTML() - all it will do is convert the object into some nice HTML output.

That HTML output is important, because it’s what will be getting used for a feature that I think is pretty neat: The Codex.

Working Title will have an area called “The Codex” that contains readable data on each entity within the game(except players). In order to output the HTML to display a specific entity, I’ll just load that entity and then call toHTML() on it to get at what I need to display to the user.

The Codex idea also brings me to a cool tooltip library I discovered a short time ago, called BoxOver. I’m planning on using it within the actual game itself, so that I can have tooltips everywhere with a minimal amount of extra cruft added to my code - at only 12KB uncompressed, the JavaScript file for BoxOver is nice and lean. And I’m sure I’ll compress it more before it actually gets deployed.

That’s just two of the implementation details for Working Title - there are a few more I’ve got up my sleeve that will either show up on this blog, or within the design document - but either way, you’ll get to see them when they show up.


Building Browsergames: Implementing an e-mail confirmation system (Perl)

May 12, 2008 – 8:00 am

For all that you probably don’t need a user’s e-mail address, there are still some times where you want to have users confirm their e-mail address. So today, we’ll go through how to build an e-mail verification system in Perl.

To begin with, we’ll use the code from our Perl registration page. We start off by adding two columns to our users table - one to track the user’s e-mail address, and another column to track whether they’ve actually confirmed their e-mail address yet or not:

ALTER TABLE  `users` ADD  `email` TEXT NOT NULL;
ALTER TABLE `users` ADD `confirmed` tinyint(1) NOT NULL DEFAULT 0;

The first thing we will do is add an input box to our code for the user’s e-mail address:

44
45
E-mail Address: <input type='text' name='email' /><br />
<input type='submit' value='Register!' />

Perl, unlike PHP, doesn’t have a built-in function for sending mail. So we’ll be printing messages to a program called sendmail in order to send our e-mail. If you’re on a linux host, it’s generally a safe bet that they have sendmail installed - although if they don’t, you can always send their support team an e-mail and ask if they can set it up for you. I am not sure if windows hosts have sendmail - but once again, try e-mailing their support and figuring it out that way.

All we’re going to actually change in our code is how the registration process occurs - now, when a user registers, their e-mail will be stored and they’ll be sent a quick e-mail to say “hey, click here to confirm your e-mail address!”:

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
			$sth = $dbh->prepare("INSERT INTO users(username,password,email) VALUES (?,?,?)");
			$sth->execute($arguments{username},crypt($arguments{username},$arguments{password}),$arguments{email});
			my $subject = "Subject: browsergame e-mail address confirmation\n";
			my $sendmail = '/usr/sbin/sendmail -t';
			my $reply_to = "Reply-to: webmaster\@example.com\n";
			my $content_type = "Content-type: text/html; charset=iso-8859-1\n\n";
			my $content = qq ~
<p>Hey! Thanks for signing up for the browsergame. Click below to confirm your e-mail address.</p>
<p><a href='http://website.com/confirm.cgi?email=$arguments{email}'>below</a></p>
			~;
			open(SENDMAIL, "| $sendmail") or die "Could not open $sendmail: $!";
			print SENDMAIL $reply_to, $subject, "To: $arguments{email}\n", $content_type, $content;
			close(SENDMAIL);			
			$html .= qq ~
<span style='color:green'>Congratulations! You registered successfully!</span>			
			~;

And that should send the user an e-mail after they register.

Now, it’s important to mention something - you should always be testing to make sure that the e-mail address supplied to you is valid before you try to send something to it. A malicious user could do all sorts of things with sendmail, if they got access to it. One way to do this is by using the module Email::Valid:

7
8
9
10
11
12
13
14
15
16
17
18
use Email::Valid;
 
my $query = new CGI;
my %arguments = $query->Vars;
my $html;
unless(Email::Valid->address($arguments{email})) {
	print $query->header();
	print "You supplied an invalid e-mail address.";
	exit;	
}
 
if(%arguments) {

And with that all finished, we can move on to our confirmation page - which is what will actually mark a user as ‘confirmed’ after they click on the link in the e-mail we sent to them.

The confirm page is pretty simply - all it does is take in an e-mail address(or any other unique attribute), and use it to update a specific user’s information within the database:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/usr/bin/perl -w
 
use strict;
use CGI qw(:cgi);
use CGI::Carp qw(fatalsToBrowser warningsToBrowser);
use config;
 
my $query = new CGI;
my %arguments = $query->Vars;
my $output;
if(%arguments) {	
	my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost",$dbuser,$dbpass,{RaiseError => 1});
	my $sth = $dbh->prepare("SELECT count(id) FROM users WHERE email = ? AND confirmed = 0");
	my $count;
	$sth->execute($arguments{email});
	$sth->bind_columns(\$count);
	$sth->fetch;
	if($count >= 1) {
		$sth = $dbh->prepare("UPDATE users SET confirmed=1 WHERE email = ?");
		$sth->execute($arguments{email});
		$output = qq ~
<span style='color:green'>Congratulations, you've confirmed your e-mail address!</span>		
		~;
	} else {
		$output = qq ~
<span style='color:red'>Oops! Either that user doesn't exist, or that e-mail address has already been confirmed.</span>		
		~;	
	}
}
print $query->header();
print $output;

There isn’t much to this code that you haven’t seen before - as a matter of fact, there isn’t anything in this code that you haven’t seen before. All it does is take the supplied e-mail and check it against the database, updating whether a user is confirmed or not if it’s in there and unconfirmed. If it’s already been confirmed, it spits out a helpful error message.

And that’s all that’s involved in adding e-mail confirmation to your registration system! Here’s the revised registration page code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#!/usr/bin/perl -w
 
use strict;
use CGI qw(:cgi);
use CGI::Carp qw(fatalsToBrowser warningsToBrowser);
use DBI;
use Email::Valid;
 
my $query = new CGI;
my %arguments = $query->Vars;
my $html;
 
if(%arguments) {
	unless(defined $arguments{email} && Email::Valid->address($arguments{email})) {
		print $query->header();
		print "You supplied an invalid e-mail address.";
		exit;	
	}
	if($arguments{password} ne $arguments{confirm}) {
		$html .= qq ~
<span style='color:red'>Error! Those passwords do not match!</span>	
		~;	
	} else {
		use config;
		my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost",$dbuser,$dbpass,{RaiseError => 1});
		my $sth = $dbh->prepare("SELECT count(id) FROM users WHERE UPPER(username) = UPPER(?)");
		$sth->execute($arguments{username});
		my $count;
		$sth->bind_columns(\$count);
		$sth->fetch;
		if($count >= 1) {
			$html .= qq ~
<span style='color:red'>Error: that username is taken.</span>			
			~;	
		} else {
			$sth = $dbh->prepare("INSERT INTO users(username,password,email) VALUES (?,?,?)");
			$sth->execute($arguments{username},crypt($arguments{username},$arguments{password}),$arguments{email});
			my $subject = "Subject: browsergame e-mail address confirmation\n";
			my $sendmail = '/usr/sbin/sendmail -t';
			my $reply_to = "Reply-to: webmaster\@example.com\n";
			my $content_type = "Content-type: text/html; charset=iso-8859-1\n\n";
			my $content = qq ~
<p>Hey! Thanks for signing up for the browsergame. Click below to confirm your e-mail address.</p>
<p><a href='http://website.com/confirm.cgi?email=$arguments{email}'>below</a></p>
			~;
			open(SENDMAIL, "| $sendmail") or die "Could not open $sendmail: $!";
			print SENDMAIL $reply_to, $subject, "To: $arguments{email}\n", $content_type, $content;
			close(SENDMAIL);			
			$html .= qq ~
<span style='color:green'>Congratulations! You registered successfully!</span>			
			~;	
		}
	}
}
 
$html .= qq ~
<form method='post' action='register-email.cgi'>
Username: <input type='text' name='username' /><br />
Password: <input type='password' name='password' /><br />
Confirm Password: <input type='password' name='confirm' /><br />
E-mail Address: <input type='text' name='email' /><br />
<input type='submit' value='Register!' />
</form>
~;
 
print $query->header();
print $html;

And here’s the confirmation page code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/usr/bin/perl -w
 
use strict;
use CGI qw(:cgi);
use CGI::Carp qw(fatalsToBrowser warningsToBrowser);
use config;
 
my $query = new CGI;
my %arguments = $query->Vars;
my $output;
if(%arguments) {	
	my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost",$dbuser,$dbpass,{RaiseError => 1});
	my $sth = $dbh->prepare("SELECT count(id) FROM users WHERE email = ? AND confirmed = 0");
	my $count;
	$sth->execute($arguments{email});
	$sth->bind_columns(\$count);
	$sth->fetch;
	if($count >= 1) {
		$sth = $dbh->prepare("UPDATE users SET confirmed=1 WHERE email = ?");
		$sth->execute($arguments{email});
		$output = qq ~
<span style='color:green'>Congratulations, you've confirmed your e-mail address!</span>		
		~;
	} else {
		$output = qq ~
<span style='color:red'>Oops! Either that user doesn't exist, or that e-mail address has already been confirmed.</span>		
		~;	
	}
}
print $query->header();
print $output;

If you want to see it in action, you can check it out at the sample Perl e-mail registration page, where the code you see above is being run.


Building Browsergames: Implementing an e-mail confirmation system (PHP)

May 9, 2008 – 8:00 am

Even though you probably don’t need a user’s e-mail address, there are still some situations where you need to verify e-mail addresses. So today, I’ll walk you through building an e-mail verification system in PHP.

We’ll start off with our registration page from earlier, and build off of that. First off, we’ll add a column to our users table to track the user’s e-mail address(we’ll use this to confirm our user), along with another column to track whether they’ve confirmed their e-mail or not:

ALTER TABLE  `users` ADD  `email` TEXT NOT NULL;
ALTER TABLE `users` ADD `confirmed` tinyint(1) NOT NULL DEFAULT 0;

Then, we’ll add an input box for the user’s e-mail address:

33
34
E-mail Address: <input type='text' name='email' /><br />
<input type='submit' value='Register!' />

In order to send our confirmation e-mails, we’ll use PHP’s built-in mail() function. All we’re going to change in our code is what happens after a user registers - we’ll send them a quick little e-mail to say “hey, click here to confirm your e-mail address!”:

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
				$email = $_POST['email'];
				$query = sprintf("INSERT INTO users(username,password,email) VALUES ('%s','%s','%s');",
					mysql_real_escape_string($_POST['username']),
					mysql_real_escape_string(md5($password)),
					mysql_real_escape_string($email));
				mysql_query($query);
				$to = $email;
				$subject = 'browsergame e-mail address confirmation';
				$message = "
<p>Hey! Thanks for signing up for the browsergame. Click below to confirm your e-mail address.</p>
<p><a href='http://website.com/confirm.php?email=$email'>below</a></p>";
				$headers = 'From: webmaster@example.com' . "\r\n" .
							'Content-type: text/html; charset=iso-8859-1' . "\r\n";
				mail($to,$subject,$message,$headers);
			?>
<span style='color:green'>Congratulations, you've registered successfully! A confirmation e-mail has been sent to the address you entered.</span>

And if you run a quick test of your script, you should see the e-mail show up in the inbox of whatever e-mail you decided to test it with!

This is all well and good, but what about our actual confirm page? We’ll need one of those to actually mark a user as ‘confirmed’ after they click on the link in the e-mail we sent to them. So let’s create that page.

The confirm page is actually pretty easy. All it needs to do is take in an e-mail address, and then use that e-mail to update a specific user’s information within the database(you could modify it to work off of any unique attribute you wanted, really):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php
	if($_GET) {
		$email = $_GET['email'];
		require_once('config.php');
		$conn = mysql_connect($dbhost,$dbuser,$dbpass)
			or die ('Error connecting to mysql');
		mysql_select_db($dbname);
		$query = sprintf("SELECT COUNT(id) FROM users WHERE email = '%s' AND confirmed=0",
			mysql_real_escape_string($email));
		$result = mysql_query($query);
		list($count) = mysql_fetch_row($result);
		if($count >= 1) {
			$query = sprintf("UPDATE users SET confirmed=1 WHERE email = '%s'",
				mysql_real_escape_string($email));
			mysql_query($query);
?>
<span style='color:green'>Congratulations, you've confirmed your e-mail address!</span>
<?php
		} else {
?>
<span style='color:red'>Oops! Either that user doesn't exist, or that e-mail address has already been confirmed.</span>
<?php
		}
	}
?>

There’s really not that much to this one - all it does is look for users that have that particular e-mail address, and haven’t already confirmed their e-mail address. There’s nothing new in this code that you haven’t seen before.

And that’s all there is to e-mail confirmation! It’s really a lot simpler than you think. Here’s the revised registration page code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<?php
	if($_POST) {
		$password = $_POST['password'];
		$confirm = $_POST['confirm'];	
		if($password != $confirm) { ?>
<span style='color:red'>Error: Passwords do not match!</span>		
<?php		} else {
			require_once('config.php');	
			$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) { ?>
<span style='color:red'>Error: that username is taken.</span>
<?php			} else {
				$email = $_POST['email'];
				$query = sprintf("INSERT INTO users(username,password,email) VALUES ('%s','%s','%s');",
					mysql_real_escape_string($_POST['username']),
					mysql_real_escape_string(md5($password)),
					mysql_real_escape_string($email));
				mysql_query($query);
				$to = $email;
				$subject = 'browsergame e-mail address confirmation';
				$message = "
<p>Hey! Thanks for signing up for the browsergame. Click below to confirm your e-mail address.</p>
<p><a href='http://website.com/confirm.php?email=$email'>below</a></p>";
				$headers = 'From: webmaster@example.com' . "\r\n" .
							'Content-type: text/html; charset=iso-8859-1' . "\r\n";
				mail($to,$subject,$message,$headers);
			?>
<span style='color:green'>Congratulations, you've registered successfully! A confirmation e-mail has been sent to the address you entered.</span>
<?php
			}	
		}
	}
?>
<form method='post' action='register-email.php'>Username: <input type='text' name='username' /><br />
Password: <input type='password' name='password' /><br />
Confirm Password: <input type='password' name='confirm' /><br />
E-mail Address: <input type='text' name='email' /><br />
<input type='submit' value='Register!' />
</form>

And here’s the confirmation page code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php
	if($_GET) {
		$email = $_GET['email'];
		require_once('config.php');
		$conn = mysql_connect($dbhost,$dbuser,$dbpass)
			or die ('Error connecting to mysql');
		mysql_select_db($dbname);
		$query = sprintf("SELECT COUNT(id) FROM users WHERE email = '%s' AND confirmed=0",
			mysql_real_escape_string($email));
		$result = mysql_query($query);
		list($count) = mysql_fetch_row($result);
		if($count >= 1) {
			$query = sprintf("UPDATE users SET confirmed=1 WHERE email = '%s'",
				mysql_real_escape_string($email));
			mysql_query($query);
?>
<span style='color:green'>Congratulations, you've confirmed your e-mail address!</span>
<?php
		} else {
?>
<span style='color:red'>Oops! Either that user doesn't exist, or that e-mail address has already been confirmed.</span>
<?php
		}
	}
?>

If you want to see it in action, you can check it out at the sample e-mail registration page, where the code you see above is being run.


Do you really need their e-mail address?

May 8, 2008 – 8:00 am

A Typical Registration Screen

It’s happened to all of us. You visit a website and try to get somewhere that looks interesting, and suddenly you see a “Whoops, you need to be logged in to see this!”. So you click on the register button, and you get the standard registration form: username, password, password confirm, and e-mail address.

As someone building a game, you will eventually have to answer the question: do you really need their e-mail address?

A lot of people justify needing a unique e-mail address by using the logic of “everyone else does it, so I will too” - but that’s wrong. Requiring a user’s e-mail address so that they can register is a bad idea unless you actually need it.

When do you need a user’s e-mail address? When having multiple characters for the same player would seriously distort the game - and that’s about the only time. In virtually all other cases, you do not actually need a user’s e-mail address.

Will it hurt you to ask a user for their e-mail address? Not really - but it tends to aggravate users if their e-mail isn’t actually needed to play the game - and in a lot of cases, the more tech-savvy users(and therefore more likely to try and register multiple accounts) will just use a temporary e-mail service like mintemail to provide you with a temporary e-mail address and make sure they don’t get spammed.

Even in the case of multiple accounts distorting play, you don’t really users to have unique e-mail addresses - you just need to do a bit more checking to make sure that two characters aren’t cooperating too much. How you define that is up to you - but as long as you have something in place to allow you to track which players interact with which other players and how much cooperation is going on between two specific characters, you’re fine without e-mail addresses.

There are sure to be some false positives using the above system. But no matter what you do, you cannot prevent someone from cheating if their mind is set firmly enough on it. That’s it. They’ll make temporary e-mails, they’ll create multitudes of characters, and they’ll find creative ways around everything you throw at them.

So do you really need users to give you their e-mail addresses? Think long and hard about it - because chances are, you don’t.


Building Browsergames: Implementing a flexible stats system (Perl)

May 7, 2008 – 8:00 am

You already know how to design a flexible stats system - so let’s go over how to implement it, using Perl.

To begin with, we will need some starting table structure and data:

CREATE TABLE users (
	id int NOT NULL AUTO_INCREMENT,
	username varchar(250),
	password varchar(50),
	PRIMARY KEY(id)
);
CREATE 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');
CREATE TABLE user_stats (
	id int NOT NULL AUTO_INCREMENT,
	user_id int,
	stat_id int,
	value text,
	PRIMARY KEY(id)
);

And now that this is done, we can begin actually writing code.

First off, we need a way to retrieve the stat value for a particular user ID. The SQL for this query looks like this:

SELECT value FROM user_stats WHERE stat_id = <foo> AND user_id = <bar>

That’s okay, but not exactly optimal - if we wanted to retrieve the value for a particular stat, we’d first need to figure out what its ID was(by using its name or short name), and then use that to figure out the value of the stat. Thankfully, we can shorten than down to just one query:

SELECT value FROM user_stats WHERE stat_id = (SELECT id FROM stats WHERE display_name = <foo> OR short_name = <foo>) AND user_id = <bar>

By using the above query, we can retrieve the stat value based on the stat’s name and the user’s ID - which is much easier for us as a developer to work with, because we can refer to our stats as “atk”, or “attack” - instead of needing to figure out that “atk” actually means “1″. Using this sub-query, retrieving the stat value for a player is easy:

1
2
3
4
5
6
7
8
9
10
11
sub getStat {
	my ($statName,$userID) = @_;
	use config;
	my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost",$dbuser,$dbpass,{RaiseError => 1});
	my $sth = $dbh->prepare("SELECT value FROM user_stats WHERE stat_id = (SELECT id FROM stats WHERE display_name = ? OR short_name = ?) AND user_id = ?");
	$sth->execute($statName,$statName,$userID);
	my $value;
	$sth->bind_columns(\$value);
	$sth->fetch;
	return $value;
}

And that’s all we need to do to retrieve a stat. But what if we wanted to store a new value for a stat?

As it turns out, that’s pretty easy too - it’s practically the same code:

1
2
3
4
5
6
7
sub setStat {
	my ($statName,$userID,$statValue) = @_;
	use config;
	my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost",$dbuser,$dbpass,{RaiseError => 1});
	my $sth = $dbh->prepare("UPDATE user_stats SET value = ? WHERE stat_id = (SELECT id FROM stats WHERE display_name = ? OR short_name = ?) AND user_id = ?");
	$sth->execute($statValue,$statName,$statName,$userID);
}

And that’s all there is to updating the stat! You can do whatever transformations you want to perform on the stat(like adding, subtracting, multipling) before you save it back into the database.

And that’s all the code that you need to use to implement stats in Perl! It’s just as simple as it sounds - and by doing it this way, you can add stats any time you need to without worrying about having to actually make changes to your database - just add the stat and write your new code to deal with it. Here’s all the code in one place(which is perfect for putting it into its own module - like stats.pm or something):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
sub getStat {
	my ($statName,$userID) = @_;
	use config;
	my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost",$dbuser,$dbpass,{RaiseError => 1});
	my $sth = $dbh->prepare("SELECT value FROM user_stats WHERE stat_id = (SELECT id FROM stats WHERE display_name = ? OR short_name = ?) AND user_id = ?");
	$sth->execute($statName,$statName,$userID);
	my $value;
	$sth->bind_columns(\$value);
	$sth->fetch;
	return $value;
}
sub setStat {
	my ($statName,$userID,$statValue) = @_;
	use config;
	my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost",$dbuser,$dbpass,{RaiseError => 1});
	my $sth = $dbh->prepare("UPDATE user_stats SET value = ? WHERE stat_id = (SELECT id FROM stats WHERE display_name = ? OR short_name = ?) AND user_id = ?");
	$sth->execute($statValue,$statName,$statName,$userID);
}

Building Browsergames: Implementing a flexible stats system (PHP)

May 6, 2008 – 8:00 am

Now that we’ve been over how to design a flexible stats system, let’s look at how to implement it in PHP.

To begin with, we will need some starting table structure and data:

CREATE TABLE users (
	id int NOT NULL AUTO_INCREMENT,
	username varchar(250),
	password varchar(50),
	PRIMARY KEY(id)
);
CREATE 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');
CREATE TABLE user_stats (
	id int NOT NULL AUTO_INCREMENT,
	user_id int,
	stat_id int,
	value text,
	PRIMARY KEY(id)
);

And now that this is done, we can begin actually writing code.

To begin with, we will need a way to pull back the value for a particular stat. The SQL query looks like this:

SELECT value FROM user_stats WHERE stat_id = <foo> AND user_id = <bar>

That’s pretty handy, but not exactly what we want - why would we want to first retrieve the stat’s ID, and then use it to retrieve the value? It’d be much nicer to do it all with one query:

SELECT value FROM user_stats WHERE stat_id = (SELECT id FROM stats WHERE display_name = <foo> OR short_name = <foo>) AND user_id = <bar>

By using what’s known as a sub-query to retrieve our stat ID, we can shorten our SQL down to just one query - which means that we only need to interact with the database once to retrieve a stat for a player. This makes writing a function to retrieve stats for a player trivial:

1
2
3
4
5
6
7
8
9
10
11
12
13
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 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;		
}

You’ve seen all this code before - all we’re doing is creating a specific query, and then returning whatever we retrieve. That’s about as complex as stat retrieval gets, whether you’re using a flexible system or otherwise. And that’s really all there is to implementing this stats system - we take in the name(which could be either the display name or the short name), and we retrieve and then return the value inside the table.

But what if you wanted to update the stat’s value? That’s just as easy:

1
2
3
4
5
6
7
8
9
10
11
12
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);
}

And that’s how you can update the stat! You can then do any transforming or displaying for your stat in your other logic, and just call those two functions when you need to store/retrieve stats(I’d even recommend splitting it off into its own page - something like stats.php or something).

Here’s all the code in one spot:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function getStat($statName,$userID) {
	require_once 'config.php';
	$conn = mysql_connect