Building Browsergames: a simple combat system (PHP)

One of the things that virtually all browsergames other than mafia games have is some sort of battling system – users encounter monsters, and then they fight those monsters in order to gain gold, resources, and so on. And that’s what we’re going to build today.

To begin with, we’re going to need to make some database changes. To begin with, we’re going to add a monsters table, for keeping track of our monsters:

CREATE TABLE monsters (
	id int NOT NULL AUTO_INCREMENT,
	name text,
	PRIMARY KEY(id)
);

We’re also going to need to add two more stats to our game – Maximum HP, and Current HP. Maximum HP will be used to track the HP of users and monsters, and curent HP will be used to track a user’s HP. Monsters will use the exact same stats as players do, by way of a table we’ll create called monster_stats:

INSERT INTO stats(display_name,short_name) VALUES ('Maximum HP','maxhp');
INSERT INTO stats(display_name,short_name) VALUES ('Current HP','curhp');
CREATE TABLE monster_stats (
	id int NOT NULL AUTO_INCREMENT,
	monster_id int NOT NULL,
	stat_id int,
	value text,
	PRIMARY KEY(id)
);

And at this point, we can add a couple of monsters to our database, along with giving them some starting stats:

INSERT INTO monsters(name) VALUES ('Crazy Eric');
	INSERT INTO monster_stats(monster_id,stat_id,value) VALUES ((SELECT id FROM monsters WHERE name = 'Crazy Eric'),(SELECT id FROM stats WHERE short_name = 'atk'),2);
	INSERT INTO monster_stats(monster_id,stat_id,value) VALUES ((SELECT id FROM monsters WHERE name = 'Crazy Eric'),(SELECT id FROM stats WHERE short_name = 'def'),2);
	INSERT INTO monster_stats(monster_id,stat_id,value) VALUES ((SELECT id FROM monsters WHERE name = 'Crazy Eric'),(SELECT id FROM stats WHERE short_name = 'maxhp'),8);
	INSERT INTO monster_stats(monster_id,stat_id,value) VALUES ((SELECT id FROM monsters WHERE name = 'Crazy Eric'),(SELECT id FROM stats WHERE short_name = 'gc'),5);
INSERT INTO monsters(name) VALUES ('Lazy Russell');
	INSERT INTO monster_stats(monster_id,stat_id,value) VALUES ((SELECT id FROM monsters WHERE name = 'Lazy Russell'),(SELECT id FROM stats WHERE short_name = 'atk'),1);
	INSERT INTO monster_stats(monster_id,stat_id,value) VALUES ((SELECT id FROM monsters WHERE name = 'Lazy Russell'),(SELECT id FROM stats WHERE short_name = 'def'),0);
	INSERT INTO monster_stats(monster_id,stat_id,value) VALUES ((SELECT id FROM monsters WHERE name = 'Lazy Russell'),(SELECT id FROM stats WHERE short_name = 'maxhp'),4);
	INSERT INTO monster_stats(monster_id,stat_id,value) VALUES ((SELECT id FROM monsters WHERE name = 'Lazy Russell'),(SELECT id FROM stats WHERE short_name = 'gc'),20);
INSERT INTO monsters(name) VALUES ('Hard Hitting Louis');
	INSERT INTO monster_stats(monster_id,stat_id,value) VALUES ((SELECT id FROM monsters WHERE name = 'Hard Hitting Louis'),(SELECT id FROM stats WHERE short_name = 'atk'),4);
	INSERT INTO monster_stats(monster_id,stat_id,value) VALUES ((SELECT id FROM monsters WHERE name = 'Hard Hitting Louis'),(SELECT id FROM stats WHERE short_name = 'def'),3);
	INSERT INTO monster_stats(monster_id,stat_id,value) VALUES ((SELECT id FROM monsters WHERE name = 'Hard Hitting Louis'),(SELECT id FROM stats WHERE short_name = 'maxhp'),10);
	INSERT INTO monster_stats(monster_id,stat_id,value) VALUES ((SELECT id FROM monsters WHERE name = 'Hard Hitting Louis'),(SELECT id FROM stats WHERE short_name = 'gc'),5);

Now, we have three monsters within our database, along with their stats – attack, defence, Maximum HP, and gold. Attack and defence are pretty self-explanatory, and so is Maximum HP. If you’re wondering what the ‘gold’ stat is for, it’s so that we know how much gold to give the player after they manage to kill the monster. We’re going to use these four stats as the basic framework behind the combat system we’re going to build.

One of the first things that we’re going to do is modify our main page from earlier, so that it displays the user’s current HP, and has a link to the ‘Forest’ page – which is where the user will be fighting monsters. Here’s the new index.tpl:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<html>
<head>
	<title>Index Page</title>
</head>
<body>
	<p>Hello, {$name}!</p>
	<ul>
		<li>Attack: <strong>{$attack}</strong></li>
		<li>Defence: <strong>{$defence}</strong></li>
		<li>Magic: <strong>{$magic}</strong></li>
		<li>Gold in hand: <strong>{$gold}</strong></li>
		<li>Current HP: <strong>{$currentHP}/{$maximumHP}</strong>
	</ul>
	<p><a href='logout.php'>Logout</a></p>
	<p><a href='forest.php'>The Forest</a></p>
</body>
</html>

And this is the minor code change we need to make to index.php, so that it retrieves and sets those values for our user:

21
22
$smarty->assign('currentHP',getStat('curhp',$userID));
$smarty->assign('maximumHP',getStat('maxhp',$userID));

Now, if you login and visit the main page for your game, you’ll notice that your HP is set to 0 – which doesn’t really set up your character for success.

There are a few options that you can use when introducing a new stat into your game. You could, if you’re so inclined, go through and hand-insert the new default values for every user who signed up before the stat was introduced, in addition to modifying your registration page to also set up the default – or you could do it the easier way, and actually introduce two stats – one to track the actual stat, and one to track whether the player has been ‘introduced’ to the stat yet – as in, had the stat’s default value set.

Are you wondering how that works? It’s actually very simple. If you think back to when we got started with our stats code, you’ll remember that we set up our stats code to insert the new row and set the stat to 0 when it encountered a situation where the user didn’t have the stat. We’re going to use that to our advantage today, by using a second stat to flag whether a particular stat has been set to the default value for a particular user.

First off, we’ll insert the stat into the database:

INSERT INTO stats(display_name,short_name) VALUES ('Set Default HP Values','sethp');

And then, it’s a simple matter of doing a quick check on our index page(or any page, really):

22
23
24
25
26
27
28
29
30
$setHP = getStat('sethp',$userID);
if($setHP == 0) {
	// haven't set up the user's HP values yet - let's set those!
	setStat('curhp',$userID,10);
	setStat('maxhp',$userID,10);
	setStat('sethp',$userID,1);	
}
$smarty->assign('currentHP',getStat('curhp',$userID));
$smarty->assign('maximumHP',getStat('maxhp',$userID));

And that will handle setting up our default values for us. Because we know that our stats will default to 0, we know that when a ‘flag’ stat returns a 0, it hasn’t been set to anything – so we set up our defaults, and then mark our flag stat so that we won’t accidentally re-set the defaults the next time the user visits the page.

So that’s all done. We’ve modified our index page to set up a user’s default HP values, along with adding a link to the forest page, where they can fight monsters. Now, let’s build the forest page.

First off, we need a template. All our template is going to do is display the monster that a player encountered, and two options – ‘Attack’, or ‘Run Away’. Clicking on ‘Attack’ will go through a few rounds of combat with the monster, using the attack and defence values we set earlier to figure out whether the player or the monster wins. Clicking on ‘Run Away’ will send the player back to the index page. We’ll save our template inside a file called forest.tpl, stored inside our Smarty templates folder:

<html>
<head>
	<title>The Forest</title>
</head>
<body>
	<p>You've encountered a {$monster}!</p>
	<form action='forest.php' method='post'>
		<input type='submit' name='action' value='Attack' /> or 
		<input type='submit' name='action' value='Run Away' />
		<input type='hidden' name='monster' value='{$monster}' />
	</form>
</body>
</html>

We put a hidden field in called ‘monster’ so that we can keep track of which monster the player is about to fight – when they click on one of the buttons, we’ll be able to see which monster they’re about to interact with. The next thing we need to do is create forest.php, the page that will actually display the template we just created, along with selecting a random monster:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?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);
$query = sprintf("SELECT name FROM monsters ORDER BY RAND() LIMIT 1");
$result = mysql_query($query);
list($monster) = mysql_fetch_row($result);
 
$smarty->assign('monster',$monster);
 
$smarty->display('forest.tpl');
 
?>

We haven’t put in any of the logic to handle our buttons just yet – for now, all this page will do is show the user the name of a random monster.

I wanted to point out one SQL query that we’re using, that you may not have seen before – the ORDER BY RAND() query. This is how you retrieve a random row using MySQL – the LIMIT 1 at the end of it makes sure that we only retrieve one random row. Otherwise, we’d end up retrieving all the rows in a random order – that might be cool, but we only really need one row. You can also use a WHERE clause to limit what you’re pulling random rows out of – we’ll use that when we add some more functionality to our game later.

At this point, we’ve retrieved a random monster for the player to fight, but we haven’t actually handled what happens when they click on either of the buttons we gave them to click on – so let’s do that. We gave both buttons the name of ‘action’, so that we can use the value of $_POST['action'] to figure out what the player wants to do:

11
12
13
14
15
16
17
18
19
 
if($_POST) {
	if($_POST['action'] == 'Attack') {
		// fighting the monster	
	} else {
		// Running away! Send them back to the main page
		header('Location: index.php');	
	}
}

In order to handle fighting the monster, we’re going to customize our template slightly – adding an area to display the results of the fight, along with hiding the “you’ve encountered a <___>!” message:

6
7
8
9
10
11
12
13
14
15
16
17
18
19
	{if $combat eq ''}
		<p>You've encountered a {$monster}!</p>
		<form action='forest.php' method='post'>
			<input type='submit' name='action' value='Attack' /> or 
			<input type='submit' name='action' value='Run Away' />
			<input type='hidden' name='monster' value='{$monster}' />
		</form>
	{else}
		<ul>
		{foreach from=$combat key=id item=i}
			<li><strong>{$i.attacker}</strong> attacks {$i.defender} for {$i.damage} damage!</li>
		{/foreach}
		</ul>
	{/if}

This way, when a user chooses to fight a monster, we can display the results of their fight – without accidentally re-displaying the ‘you encountered a monster!’ message.

If that Smarty code looks a little new to you, that’s because it is – this will be the first time that we use Smarty’s {foreach} token, and we’ll be using it to display the results of our fight nicely.

Now we need to add the actual combat logic. But before we add that, we’ll need to retrieve our monster’s stats too – we haven’t built anything to do that yet. We’ll quickly tweak our stats code to work off of our monster_stats table, and take slightly different arguments:

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
<?php
 
function getMonsterStat($statName,$monsterID) {
	include 'config.php';
	$conn = mysql_connect($dbhost,$dbuser,$dbpass)
		or die ('Error connecting to mysql:');
	mysql_select_db($dbname);
	createMonsterStatIfNotExists($statName,$monsterID);
	$query = sprintf("SELECT value FROM monster_stats WHERE stat_id = (SELECT id FROM stats WHERE display_name = '%s' OR short_name = '%s') AND monster_id = '%s'",
		mysql_real_escape_string($statName),
		mysql_real_escape_string($statName),
		mysql_real_escape_string($monsterID));
	$result = mysql_query($query);
	list($value) = mysql_fetch_row($result);
	return $value;		
}
 
function createMonsterStatIfNotExists($statName,$monsterID) {
	include 'config.php';
	$conn = mysql_connect($dbhost,$dbuser,$dbpass)
		or die ('Error connecting to mysql:');
	mysql_select_db($dbname);
	$query = sprintf("SELECT count(value) FROM monster_stats WHERE stat_id = (SELECT id FROM stats WHERE display_name = '%s' OR short_name = '%s') AND monster_id = '%s'",
		mysql_real_escape_string($statName),
		mysql_real_escape_string($statName),
		mysql_real_escape_string($monsterID));
	$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 monster_stats(stat_id,monster_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($monsterID),
		'0');
		mysql_query($query);
	}	
}
 
?>

As you can see, there’s very little changed from the code we use to retrieve player stats – we’ve changed the function names so that we won’t have any naming collisions, and we’ve adjusted the table that we retrieve from. We also don’t need a setStat() function for monsters, because players aren’t supposed to be able to set a monster’s stats – they only need to retrieve them for combat.

Now that that’s done, we can get to our actual combat code, back inside forest.php. We first need to include our stats and monster stats code, so that we can retrieve the monster and player stats for this encounter:

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
		require_once 'stats.php';			// player stats
		require_once 'monster-stats.php';	// monster stats
		// to begin with, we'll retrieve our player and our monster stats 
		$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);
		$player = array (
			name		=>	$_SESSION['username'],
			attack 		=>	getStat('atk',$userID),
			defence		=>	getStat('def',$userID),
			curhp		=>	getStat('curhp',$userID)
		);
		$query = sprintf("SELECT id FROM monsters WHERE name = '%s'",
					mysql_real_escape_string($_POST['monster']));
		$result = mysql_query($query);
		list($monsterID) = mysql_fetch_row($result);
		$monster = array (
			name		=>	$_POST['monster'],
			attack		=>	getMonsterStat('atk',$monsterID),
			defence		=>	getMonsterStat('def',$monsterID),
			curhp		=>	getMonsterStat('maxhp',$monsterID)
		);

What we’ve done here is first retrieved the ID values for our user and our monster, and then used those to retrieve the stats for both of them and store them into two arrays – $player, and $monster. By doing it this way, we can refer to a specific stat by doing something like $monster['attack'], which is much easier than having a bunch of confusingly-named variables.

Now that we’ve retrieved the stats for both the player and the monster, we can start doing the actual combat. It’s actually very simple, and boils down to a while loop:

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
68
69
		$combat = array();
		$turns = 0;		
		while($player['curhp'] > 0 && $monster['curhp'] > 0) {
			if($turns % 2 != 0) {
				$attacker = &$monster;
				$defender = &$player;	
			} else {
				$attacker = &$player;
				$defender = &$monster;
			}
			$damage = 0;
			if($attacker['attack'] > $defender['defence']) {
				$damage = $attacker['attack'] - $defender['defence'];	
			}
			$defender['curhp'] -= $damage;
			$combat[$turns] = array(
				attacker	=>	$attacker['name'],
				defender	=>	$defender['name'],
				damage		=>	$damage
			);
			$turns++;
		}
		setStat('curhp',$userID,$player['curhp']);
		if($player['curhp'] > 0) {
			// player won
			setStat('gc',$userID,getStat('gc',$userID)+getMonsterStat('gc',$monsterID));	
			$smarty->assign('won',1);
			$smarty->assign('gold',getMonsterStat('gc',$monsterID));
		} else {
			// monster won
			$smarty->assign('lost',1);	
		}
		$smarty->assign('combat',$combat);

While that code looks complex, it’s actually pretty simple. We first initialize the $combat array, which is what we’ll be storing into Smarty to display the results of our combat. We also set $turns to 0, because we’ll be using it to figure out who’s turn it is to attack(for even numbers it’s the monster, and for odd numbers it’s the player). Next, we get into our actual while loop – the real meat of our combat system.

To begin with, we store references to our stat arrays into $attacker and $defender. We do this because we’re going to be running the exact same code twice, with the only difference being which variable is doing what – so using references makes sense(repeating yourself is bad). Then, we start to keep track of how much damage the attacker does to the defender, based on this ultra-simple formula: damage = attack – defence. Using that formula, we change the defender’s HP to their old HP minus whatever damage was done to them, and we add an array filled with the information about this turn to $combat. That’s basically all our while loop does – and it goes until either the player or the monster runs out of health.

Once the player or the monster has run out of health, the fight is over – and we can figure out which entity won by checking their health values. If the player has no health left, the monster won, and vice versa. We set the player’s ‘Current HP’ stat regardless of whether they won or lost, so that it will save for the next fight. If they won the fight, we give them the gold that we set our monster up to carry earlier. There aren’t any penalties for losing a fight right now, but you’re free to experiment in your game.

After all of the variable setting and stat updating is finished, we set a couple of Smarty variables to mark whether the player won or lost. We also tweaked our Smarty template slightly, so that we could use those variables to display some helpful messages to the user:

19
20
21
22
23
24
25
26
		{if $won eq 1}
			<p>You killed <strong>{$smarty.post.monster}</strong>! You gained <strong>{$gold}</strong> gold.</p>
			<p><a href='forest.php'>Explore Again</a></p>
		{/if}
		{if $lost eq 1}
			<p>You were killed by <strong>{$smarty.post.monster}</strong>.</p>
		{/if}		
		<p><a href='index.php'>Back to main</a></p>

We give the player a helpful link back to the main page, and if they won the fight they get to see how much gold they got off of the monster they killed. We also give them a link to explore again if they won – because if they won, they must have HP left. Because the name of our monster was posted to us, we get Smarty to ‘remember’ it for us using the special {$smarty.post} token.

And that’s really all there is to combat! While this is by no means a complete combat system, it’s the basics – and we can always come back and tweak it later, now that we have it working and ready to go. Here’s forest.php in it’s entirety:

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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<?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);
 
if($_POST) {
	if($_POST['action'] == 'Attack') {
		require_once 'stats.php';			// player stats
		require_once 'monster-stats.php';	// monster stats
		// to begin with, we'll retrieve our player and our monster stats 
		$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);
		$player = array (
			name		=>	$_SESSION['username'],
			attack 		=>	getStat('atk',$userID),
			defence		=>	getStat('def',$userID),
			curhp		=>	getStat('curhp',$userID)
		);
		$query = sprintf("SELECT id FROM monsters WHERE name = '%s'",
					mysql_real_escape_string($_POST['monster']));
		$result = mysql_query($query);
		list($monsterID) = mysql_fetch_row($result);
		$monster = array (
			name		=>	$_POST['monster'],
			attack		=>	getMonsterStat('atk',$monsterID),
			defence		=>	getMonsterStat('def',$monsterID),
			curhp		=>	getMonsterStat('maxhp',$monsterID)
		);
		$combat = array();
		$turns = 0;		
		while($player['curhp'] > 0 && $monster['curhp'] > 0) {
			if($turns % 2 != 0) {
				$attacker = &$monster;
				$defender = &$player;	
			} else {
				$attacker = &$player;
				$defender = &$monster;
			}
			$damage = 0;
			if($attacker['attack'] > $defender['defence']) {
				$damage = $attacker['attack'] - $defender['defence'];	
			}
			$defender['curhp'] -= $damage;
			$combat[$turns] = array(
				attacker	=>	$attacker['name'],
				defender	=>	$defender['name'],
				damage		=>	$damage
			);
			$turns++;
		}
		setStat('curhp',$userID,$player['curhp']);
		if($player['curhp'] > 0) {
			// player won
			setStat('gc',$userID,getStat('gc',$userID)+getMonsterStat('gc',$monsterID));	
			$smarty->assign('won',1);
			$smarty->assign('gold',getMonsterStat('gc',$monsterID));
		} else {
			// monster won
			$smarty->assign('lost',1);	
		}
		$smarty->assign('combat',$combat);
	} else {
		// Running away! Send them back to the main page
		header('Location: index.php');	
	}
} else {
	$query = sprintf("SELECT name FROM monsters ORDER BY RAND() LIMIT 1");
	$result = mysql_query($query);
	list($monster) = mysql_fetch_row($result);
	$smarty->assign('monster',$monster);
}
 
$smarty->display('forest.tpl');
 
?>

And here’s the template file, forest.tpl:

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
<html>
<head>
	<title>The Forest</title>
</head>
<body>
	{if $combat eq ''}
		<p>You've encountered a {$monster}!</p>
		<form action='forest.php' method='post'>
			<input type='submit' name='action' value='Attack' /> or 
			<input type='submit' name='action' value='Run Away' />
			<input type='hidden' name='monster' value='{$monster}' />
		</form>
	{else}
		<ul>
		{foreach from=$combat key=id item=i}
			<li><strong>{$i.attacker}</strong> attacks {$i.defender} for {$i.damage} damage!</li>
		{/foreach}
		</ul>
		{if $won eq 1}
			<p>You killed <strong>{$smarty.post.monster}</strong>! You gained <strong>{$gold}</strong> gold.</p>
			<p><a href='forest.php'>Explore Again</a></p>
		{/if}
		{if $lost eq 1}
			<p>You were killed by <strong>{$smarty.post.monster}</strong>.</p>
		{/if}		
			<p><a href='index.php'>Back to main</a></p>
	{/if}
</body>
</html>

And with that being said, our browsergame is getting close to being playable! You can take a look at the results of all we’ve built so far by first visiting the registration page, and then the login page – all of those pages are running off the exact same code as you see here.

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.

Wednesday, June 11th, 2008 buildingbrowsergames, code, php
  • MeeeeeePa

    I decided to not use Smarty. but I can't understand how to "translate" the Smarty Template into PHP. Help?

  • Nirkun

    hey, your tutorial is great! It really helps me with my understanding of php.
    I would love to insert a random number in that battlesystem. But when i do so in every fight the number doesn't change throughout the turns. Were is the best place to add the rand so i have a different damage in every turn? Or am I just unlucky and it always takes the same random number...
    Would be nice to know were you would do that
    Again thanks for this tutorial!

  • BUnzaga

    Perhaps do what they did in diablo 2 (and other games I am sure) put a minimum acceptable value. Something like

    damage = (attack-defense) || 1;

    So no matter what they will at least do 1 damage. Or if put in a different formula

    damage = (attack-defense > 0) ? attack-defense : (Math.rand() > .5) ? 1 : 0;

    By tweaking a system like this, if the attack is greater than 0, it will do the attack. If not, it will get a random value between 0 and 1. If it is greater than .5 then it will take off 1 damage. If it is less than .5, it will take off 0 damage.

    Doing something like this will get rid of those never ending battles. Or perhaps put in a situational check at the start:

    if (($player['attack'] - $monster['defense'] < 1) && ($monster['attack'] - $player['defense'] < 1){
    // end in draw.
    }

    Anyway, there are a few different ideas to work around this.

  • someone

    I tried modifying the attack of the third monster from 3 to 7, you will end up with a situation where in the loop the attack is always less than defence, and the loop never exists causing a fatal error of memory loss.

    5 player attack value ____ monster defence value 7 > no one will lose any health
    4 monster attack value ____ player defence value 5 > no one will lose any health

  • I get errors like this:
    "Notice: Use of undefined constant attacker - assumed 'attacker' in /Users/Niels/Sites/bg/smarty/bg/forest.php on line 53"

    Caused by the arrays:
    $combat[$turns] = array(
    attacker => $attacker['name'],
    defender => $defender['name'],
    damage => $damage
    );

    I fixed it this way:
    $combat[$turns] = array(
    'attacker' => $attacker['name'],
    'defender' => $defender['name'],
    'damage' => $damage
    );

    PS: I realy like this tutorial, i was searching a long time for something like this :) .

  • MrLollige

    This works, but only if you allow people to freely escape from their battles. If you do not want people to be able to flee, will you have to add a row for every instance of a monster, and update their hp every time?

    Right now, if things are going bad, you could navigate away and your HP is back to normal again....

  • I think that you may have misinterpreted the way that the combat system
    works, here - after encounting a monster and clicking attack, the entire
    combat simulation is run and the player's health is updated, before the next
    screen. There isn't really a screen where they can see the battle is going
    badly and run away.

  • MrLollige

    Oh yes, true, I did not fully read it AND did not fully try to understand that code indeed. I am still a beginner in these things, and expected that smarty (the part I skipped) would enable you to decide every turn what you want to do.
    Thanks for your reply!

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