Using Items (PHP)

What game is complete without usable items? Not ours, that’s for sure!

With that in mind, today we are going to write the code that makes items usable. To start off, check out a copy of the code for our project:

svn checkout http://building-browsergames-tutorial.googlecode.com/svn/trunk/php/pbbg tutorial -r 37

And then we’re ready to go!

To start off, we’ll build a basic template for our inventory page, and put it inside inventory.tpl:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<html>
<head>
	<title>Your Inventory</title>
</head>
<body>
	<p>This is your inventory. Check out all the stuff you've got!</p>
	<ul>
		{foreach from=$inventory key=id item=i}
		<li>
			<strong>{$i.name} x {$i.quantity}</strong>
			<form action='inventory.php' method='post'>
				<input type='hidden' name='item-id' value='{$i.id}' />
				<input type='submit' value='Use' />
			</form>
		</li>
		{/foreach}
	</ul>
</body>
</html>

With the template built, we can get started on the code for inventory.php:

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
<?php
 
require_once 'smarty.php';
 
session_start();
 
require_once 'config.php';		// our database settings
$conn = mysql_connect($dbhost,$dbuser,$dbpass)
	or die('Error connecting to mysql');
mysql_select_db($dbname);
// retrieve player's 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);
 
$inventory = array();
$query = sprintf("SELECT id, item_id, quantity FROM user_items WHERE user_id = '%s'",
		mysql_real_escape_string($userID));
$result = mysql_query($query);
while($row = mysql_fetch_assoc($result)) {
	 $item_query = sprintf("SELECT name FROM items WHERE id = '%s'",
		mysql_real_escape_string($row['item_id']));
	$item_result = mysql_query($item_query);
	list($row['name']) = mysql_fetch_row($item_result);
	array_push($inventory,$row);
}
$smarty->assign('inventory',$inventory);
$smarty->display('inventory.tpl');
 
?>

This code is essentially taken straight from our item shop code – but it’s missing one key thing: the ability to actually use items!

If you remember our initial database preparations, you’ll remember that we inserted a new stat called ‘Item Use Token’ – and this is where that stat will come into play. We will be using the ‘Item Use Token’ stat and something known as a Dispatch Table to easily write arbitrary code that can be run whenever our items are used.

For now, we’ll insert a single item with the use token of ‘potion’:

INSERT INTO items(name,type,price) VALUES ('Red Potion','Usable',10);
	INSERT INTO entity_stats(stat_id,entity_id,value,entity_type) VALUES ((SELECT id FROM stats WHERE short_name='token'),(SELECT id FROM items WHERE name='Red Potion'),'potion','Item');

With that token in place, we will be able to start writing our dispatch table.

Dispatch Tables are a bit of a strange beast; essentially, what you end up doing when you create a dispatch table is creating an associative array, filled with function definitions(instead of values). Then, you use a certain key value to retrieve the function you are supposed to call. This is actually perfect for items system, because it will allow us to easily add new and different types of items anytime we want or need to(by simply adding another token, and then writing the code to handle it). Let’s get started on our dispatch table:

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
function use_potion() {
	echo 'This is code that would run when the user used a potion.';
}
$actions = array('potion' => 'use_potion');
 
if($_POST) {
	if($_POST['item-id']) {
		$query = sprintf("SELECT item_id FROM user_items WHERE user_id = '%s' AND id = '%s'",
			mysql_real_escape_string($userID),
			mysql_real_escape_string($_POST['item-id']));
		$result = mysql_query($query);
		list($itemID) = mysql_fetch_row($result);
		require_once 'items.php';
		$token = getItemStat('token',$itemID);
		call_user_func($actions[$token]);
	}
}

And if you visit your inventory page and click ‘Use’ on the item in your character’s inventory, you should be treated to the simple message ‘This is code that would run when the user used a potion.’. Neat, eh?

While this shows you how to build this functionality for a single item, single items aren’t really what this code is geared towards. So let’s add another item and type:

INSERT INTO items(name,type,price) VALUES ('Crystal Ball','Usable',10);
	INSERT INTO entity_stats(stat_id,entity_id,value,entity_type) VALUES ((SELECT id FROM stats WHERE short_name='token'),(SELECT id FROM items WHERE name='Crystal Ball'),'crystal_ball','Item');

Now that we’ve added another item token to handle, we’ll write the code that gets run when an item with that token gets used:

17
18
19
20
	function use_crystal_ball() {
		echo 'This is code that would run when the user used a crystal ball.';
	}
	$actions = array('potion' => 'use_potion','crystal_ball' => 'use_crystal_ball');

And now if you use a crystal ball, you will get the message ‘This is code that would run when the user used a crystal ball.’.

This is why dispatch tables are so useful – it doesn’t take us long at all to write more code to support more items anytime we need to.

With that, our inventory page is essentially finished! You can run any code that should run after any item is used by running it just after the call to call_user_func(), and you can run any code specific to that item token by defining it within the $actions array. Handy!

Here’s the (slightly re-organized) code for inventory.php:

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
<?php
 
require_once 'smarty.php';
 
session_start();
 
require_once 'config.php';		// our database settings
$conn = mysql_connect($dbhost,$dbuser,$dbpass)
	or die('Error connecting to mysql');
mysql_select_db($dbname);
// retrieve player's 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);
 
$actions = array('potion' => 'use_potion','crystal_ball' => 'use_crystal_ball');
 
if($_POST) {
	if($_POST['item-id']) {
		$query = sprintf("SELECT item_id FROM user_items WHERE user_id = '%s' AND id = '%s'",
			mysql_real_escape_string($userID),
			mysql_real_escape_string($_POST['item-id']));
		$result = mysql_query($query);
		list($itemID) = mysql_fetch_row($result);
		require_once 'items.php';
		$token = getItemStat('token',$itemID);
		call_user_func($actions[$token]);
	}
}
 
$inventory = array();
$query = sprintf("SELECT id, item_id, quantity FROM user_items WHERE user_id = '%s'",
		mysql_real_escape_string($userID));
$result = mysql_query($query);
while($row = mysql_fetch_assoc($result)) {
	 $item_query = sprintf("SELECT name FROM items WHERE id = '%s'",
		mysql_real_escape_string($row['item_id']));
	$item_result = mysql_query($item_query);
	list($row['name']) = mysql_fetch_row($item_result);
	array_push($inventory,$row);
}
$smarty->assign('inventory',$inventory);
$smarty->display('inventory.tpl');
 
function use_potion() {
	echo 'This is code that would run when the user used a potion.';
}
function use_crystal_ball() {
	echo 'This is code that would run when the user used a crystal ball.';
}
?>

And here’s the template(inventory.tpl):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<html>
<head>
	<title>Your Inventory</title>
</head>
<body>
	<p>This is your inventory. Check out all the stuff you've got!</p>
	<ul>
		{foreach from=$inventory key=id item=i}
		<li>
			<strong>{$i.name} x {$i.quantity}</strong>
			<form action='inventory.php' method='post'>
				<input type='hidden' name='item-id' value='{$i.id}' />
				<input type='submit' value='Use' />
			</form>
		</li>
		{/foreach}
	</ul>
</body>
</html>

Extra Credit

  • Build healing potions that heal the player for 10, 20, or 30 HP (you may need to add another stat to the item to do this).

Wish there was more?

I'm considering writing an ebook - click here.

.

Luke is the primary editor of Building Browsergames, and has written a large portion of the articles that you read here. He generally has no idea what to say when asked to write about himself in the third person.

Tags: , , ,

Thursday, October 16th, 2008 buildingbrowsergames, medieval
  • Green Magi0

    Example Inventory from database;
    usedspaces = 11
    inventory = 12 , 9 , 13 , 3 , 2 , 2 , 9 , 9 , 2 , 2 , 11
    Each number is an item ID.
    I'm not good with arrays, so I use the field, "usedspaces," to tell my functions how many times to repeat the cycles.

    $query = "SELECT * FROM users WHERE username = '$user'";
    $results = mysql_query($query) or die(mysql_error());
    $row = mysql_fetch_array($results) or die(mysql_error());
    $invo = $row['inventory'];
    $inventory = explode(" , ",$invo);

    $n = 0;
    while ($n <= $usedspaces)
    {
    $currentitem = $inventory[$n];
    $query1 = "SELECT * " .
    "FROM items " .
    "WHERE id = '$currentitem'";
    $results1 = mysql_query($query1) or die(mysql_error());
    $row1 = mysql_fetch_array($results1) or die(mysql_error());
    $name1 = $row1['name'];
    $id1 = $currentitem;
    echo "<td width="90"><center><font size="2">$name1</font>
    <img border="0" src="images/items/$id1.png">
    <font size="2">Drop</font> / <font size="2">Use</font>
    <font size="2">Deposit</font></center></td>";
    $n++;
    }

    I have 5 copies of the code inside the while so that I get 5 items to display per row, then it creates a new row, and repeats until it goes through every item in your inventory.

  • Green Magi0

    I think that's what you wanted to see, if not, let me know and I'll get the correct code up. :P

    I'm kind of a PHP noob, but I want to go to school for it, and become a Webmaster, or possibly just a freelance webdeveloper/ designer soon. I need a job soon, and I love making websites.

  • Green Magi0

    It looks like you have more code than necessary. I have a pbbg and my game uses literally 4-5 lines of php to extract and build your inventory from the database, then it uses a while statement, and fills in the variables it got into the html tables.

  • Hi greenmagi0,
    That's probably true - typically the first pass of these tutorials has a bit
    more code than it needs. Would you care to share your inventory code?

  • Green Magi0

    What all pieces would you want to see?
    I have a shop system that builds onto your inventory when you buy items, you can drop items, I have inventory system, also equipment system.

  • I think for now just seeing the way that you load a player's inventory would
    be good - although if you have ideas on how to improve the other areas of
    the tutorial as well, please e-mail them to buildingbrowsergames@gmail.com.

blog comments powered by Disqus

About

Building Browsergames is a blog about browsergames(also known as PBBG's). It's geared towards the beginner to intermediate developer who has an interest in building their own browsergame.

Sponsors

Got Something to Say?

Send an e-mail to luke@buildingbrowsergames.com, or get in touch through Twitter at http://twitter.com/bbrowsergames