Building Browsergames: Creating the bank (PHP)

Earlier, we built a combat system with which players can fight monsters, and gain gold when they defeat those monsters. Today, we’re going to build a bank for them to put that gold into.

To begin with, we’ll add another link to our index page – this link will go to bank.php, the page that will handle all of the logic on that page.

<p><a href='bank.php'>The Bank</a></p>

And now that the link is there, we’re going to actually create the page. As usual, we’ll start off with a basic template:

 

<html>
<head>
	<title>The Bank</title>
</head>
<body>
	<p>Welcome to the bank. You currently have <strong>{$inbank}</strong> gold in the bank, and <strong>{$gold}</strong> gold in hand.</p>
	<form action='bank.php' method='post'>
		<input type='text' name='amount' /><br />
		<input type='submit' name='action' value='Deposit' /> or 
		<input type='submit' name='action' value='Withdraw' />
	</form>
	<p><a href='index.php'>Back to main</a></p>
</body>
</html>

Even though players have a gold stat, they’re missing one: gold in the bank. So we’re going to add another stat to our database, so that we can keep track of how much gold the player currently has in the bank. Here’s the SQL you’ll need to run:

INSERT INTO stats(display_name,short_name) VALUES (‘Gold In Bank’,’bankgc’);
Now that that’s finished, we’ll write the starter code for our bank page. Because the amount of gold that a player has in the bank starts at 0, we won’t need to add any special code to auto-set it to anything.

 

<?php
 
require_once 'smarty.php';
 
session_start();
 
require_once 'config.php';		// our database settings
require_once 'stats.php';
$conn = mysql_connect($dbhost,$dbuser,$dbpass)
	or die('Error connecting to mysql');
mysql_select_db($dbname);
// retrieve user ID
$query = sprintf("SELECT id FROM users WHERE UPPER(username) = UPPER('%s')",
			mysql_real_escape_string($_SESSION['username']));
$result = mysql_query($query);
list($userID) = mysql_fetch_row($result);
 
$smarty->assign('gold',getStat('gc',$userID));
$smarty->assign('inbank',getStat('bankgc',$userID));
$smarty->display('bank.tpl');
 
?>

Now, we can start writing the logic to handle what happens when a player presses one of the action buttons. We’re going to modify our template slightly, so that it can display two different messages – one for when a user deposits some gold, and one for when a user withdraws some gold:

 

{if $deposited ne 0}
		<p>You deposited <strong>{$deposited}</strong> gold into your bank account. Your total in the bank is now <strong>{$inbank}</strong>.</p>
	{/if}
	{if $withdrawn ne 0}
		<p>You withdraw <strong>{$withdrawn}</strong> gold from your bank account. Your total gold in hand is now <strong>{$gold}</strong>.</p>
	{/if}

We’re also going to make a slight modification to the area users input the amount they want to put into the bank, and make it auto-focus:

 

<input type='text' name='amount' id='amount' /><br />
		<input type='submit' name='action' value='Deposit' /> or 
		<input type='submit' name='action' value='Withdraw' />
	</form>
	<p><a href='index.php'>Back to main</a></p>
	<script type='text/javascript'>
		document.getElementById('amount').focus();
	</script>

Now that that’s finished, we can get to writing the code that handles all of the interactions on this page.

One of the things that always seems to get handled differently in browsergames is what they do when you enter a value they don’t expect into a textbox – like trying to deposit 200 gold when you only have 100, or just hitting enter without entering a value at all. Some games stop and tell you that you made a mistake, before forcing you to try again. Another approach that I’ve encountered is to just assume that something ‘weird’ means ‘use the maximum’ – so the game just quietly shifts your 200 into the 100 you have, and then tells you how much it deposited. I like the second option, so that’s how I will write my logic – but in your game you’re completely free to do whatever you want(and it shouldn’t be too hard to cusomize this code to display an error message if you need to):

 

$gold = getStat('gc',$userID);
if($_POST) {
	$amount = $_POST['amount'];	
	if($_POST['action'] == 'Deposit') {
		if($amount > $gold || $amount == '') {
			// the user input something weird - assume the maximum
			$amount = $gold;	
		}
		setStat('gc',$userID,getStat('gc',$userID) - $amount);
		setStat('bankgc',$userID,getStat('bankgc',$userID)+$amount);
		$smarty->assign('deposited',$amount);
	} else {
		$bankGold = getStat('bankgc',$userID);
		if($amount > $bankGold || $amount == '') {
			// the user input something weird again - again, assume the maximum
			$amount = $bankGold;
		}
		setStat('gc',$userID,getStat('gc',$userID) + $amount);
		setStat('bankgc',$userID,getStat('bankgc',$userID)-$amount);
		$smarty->assign('withdrawn',$amount);
	}
}

And that’s really all there is to handling a deposit or a withdrawal within our simple banking system. We check to see what action the user is taking, and then we perform almost exactly the same operation – the only differences are the value that we’re testing our posted amount against, and whether we’re increasing or decreasing their gold in hand vs. gold in the bank. Finally, we assign a variable in each case that will display the amount that the user either deposited or withdrew. The code is so similar I’m sure it could be implemented in a little less repetitious format using references – but I’ll leave that as an exercise for you, the reader.

Here’s all the code for the bank in a single block:

 

<?php
 
require_once 'smarty.php';
 
session_start();
 
require_once 'config.php';		// our database settings
require_once 'stats.php';
$conn = mysql_connect($dbhost,$dbuser,$dbpass)
	or die('Error connecting to mysql');
mysql_select_db($dbname);
// retrieve user ID
$query = sprintf("SELECT id FROM users WHERE UPPER(username) = UPPER('%s')",
			mysql_real_escape_string($_SESSION['username']));
$result = mysql_query($query);
list($userID) = mysql_fetch_row($result);
 
$gold = getStat('gc',$userID);
if($_POST) {
	$amount = $_POST['amount'];	
	if($_POST['action'] == 'Deposit') {
		if($amount > $gold || $amount == '') {
			// the user input something weird - assume the maximum
			$amount = $gold;	
		}
		setStat('gc',$userID,getStat('gc',$userID) - $amount);
		setStat('bankgc',$userID,getStat('bankgc',$userID)+$amount);
		$smarty->assign('deposited',$amount);
	} else {
		$bankGold = getStat('bankgc',$userID);
		if($amount > $bankGold || $amount == '') {
			// the user input something weird again - again, assume the maximum
			$amount = $bankGold;
		}
		setStat('gc',$userID,getStat('gc',$userID) + $amount);
		setStat('bankgc',$userID,getStat('bankgc',$userID)-$amount);
		$smarty->assign('withdrawn',$amount);
	}
}
 
$smarty->assign('gold',getStat('gc',$userID));
$smarty->assign('inbank',getStat('bankgc',$userID));
$smarty->display('bank.tpl');
 
?>