Aggro Detection with Javascript
So you want to make some games? Sure it sounds easy, but until you dive into it you’ll never notice all the little things that go into the backend of it that make or break your game. While this isn’t as big a deal in current browser-based games (they’re either muds, flash or static maps) things are changing in the browser. Everything is getting faster, and things like javascript based animation is actually feasible! So what is an aspiring game developer to do except buckle in and start programming their games?
Once you begin researching you’ll notice that while a lot of browser-based text games take into account Collision detection, they seem to be missing Aggro detection. Aggro stands for either aggravation or aggression and is essentially a way to tell if a monster will attack you or not.. As you’ve probably noticed some monsters tend to rush at you from across the map, while others seem to completely ignore you until you attack them. This is Aggro.
One of the easiest ways to detect aggro is to simply add a variable to your monsters to signify “sight”. This sight variable will dictate how far away you need to be before a monster will attack you. Set this to 100 to have a monster rush at you from across your map or set it to 0 so that it will never attack unless you attack first.
Detection aggro is as simple as following two formula’s. The first will be to figure out the distance between you and the monster and the second will simply be a quick check to see if you fall within the monsters aggro radius. To start off, you need to grab the jQuery javascript framework. While you CAN do this from scratch, jQuery lets you do it a lot easier, plus you can probably add a bit more jazz to your current game if you’re not already using it. If you’re unsure of how jQuery works, take a look at our quick intro to jQuery or just check out the jQuery documentation. Now just cobble together a quick webpage and include the jQuery library. I’m using the minified version 1.3.2 of jQuery, so if you’re not using the same one, make sure you replace that line.
<html>
<head>
<title>Collision Detection</title>
<style type="text/css">
table#grid{
border-style: solid;
border-width: 0px 1px 1px 0px;
border-color: #CCC;
padding: 0px;
}
table#grid tr th{
border-style: solid;
border-width: 1px 0px 0px 1px;
border-color: #CCC;
text-align: center;
color: #333;
font-size: 0.7em;
font-weight: bold;
font-family: "Arial";
background-color: #EDEDED;
}
table#grid tr th.run{
width: 12px;
}
table#grid tr td{
width: 50px;
height: 50px;
border-style: solid;
border-width: 1px 0px 0px 1px;
border-color: #CCC;
text-align: center;
color: #E0E0E0;
font-size: 0.7em;
font-weight: normal;
font-family: "Arial";
}
table#grid tr td:hover{
color: #333;
background-color: #F3F3F3;
}
.player{
background-color: #333;
}
.monsterA{
color: #333;
background-color: #AA0000;
}
div#debug{
border-style: solid;
border-color: #333;
border-width: 1px;
float: right;
border-color: #EDEDED;
text-align: left;
color: #333;
font-size: 0.9em;
font-weight: normal;
font-family: "Arial";
width: 300px;
padding: 10px;
}
.monsterN{
background-color: #00AA00;
}
</style>
<script type="text/javascript" src="jquery-1.3.2.min.js"></script>
</head>
<body>
</body>
</html>You’ll notice a bunch of CSS in there, but you can ignore that. It’s pretty straight forward and really it’s just meant to pretty things up a little. Now we’re going to add a quick grid so that you can get an easy visual representation of where you are and where your monsters are and if they will aggro or not. You can copy and paste the following line a few times, and change the y coordinate (x,y) to match which row you’re on.
<tr> <td>0,1</td><td>1,1</td><td>2,1</td><td>3,1</td><td>4,1</td><td>5,1</td><td>6,1</td><td>7,1</td><td>8,1</td><td>9,1</td> </tr>
Finally, I’ve just added a “debug” section, so you can get a textual representation of what’s going on. It’s just a div placed above the grid.
<div id="debug"> <b>Debug</b><br><br> </div>
The Code
Now for the code that will give us a visual representation of our player and our monsters. First off we are going to initiate a few variables that we will be using throughout our script. They’re pretty self explanatory.
var playerPlaced = false; var monster = []; var player = [];
Now we’re going to set it up so that when we click a square it will check if our player is already placed or not. If he is NOT placed, then we are going to place him and update our “debug” section.
$('#grid tr td').click(function(){ var distance; });
if(!playerPlaced){ player['loc'] = $(this).html().split(','); player['sight'] = 0; $(this).html('@'); $(this).addClass('player'); playerPlaced = true; $('#debug').append('Player: '+player['loc']+'<br>'); }
Notice that we’ve set player['sight'] to 0. Why? Simply because your player doesn’t have an aggro radius. He may or may not attack at your discretion, so it’s irrelevant. A monster however, will ALWAYS attack if you get within its aggro radius (assuming no other modifiers).
The next bit will just place our monsters if there is already a player on the field. When we do, however, we are going to call some functions that will take care of calculating distance and checking if the monster will aggro. We’ll go over those first, since they’re more complicated.
Distance
To calculate the distance of two points we are simply going to take the x,y coordinates of both our monster and player and perform some math on them. The formula that we will be using is actually the distance formula between two points (and you wondered when you would ever use it…) and something that’s been drilled into us in every math class. The formula itself is a basically sqrt(sq(x1-x2)+sq(y1-y2)) so translating that to our game code it will look more like
sqrt(sq(player[x]-monster[x])+sq(player[y]-monster[y]))
The squaring and square rooting would take us a lot more work, if JavaScript didn’t already have those built in! Our actual distance formula in JavaScript (after being placed in a function) will look like this:
function getDistance(from,to){ distance = Math.floor(Math.sqrt(Math.pow((from[0]-to[0]),2) + Math.pow((from[1]-to[1]),2))); return distance; }
Intersection
Basically intersection in our scenario will take a look at the player and see if he falls within the aggro radius of the monster. It’s a very simple check that just goes if (distance < aggroRad) then it will aggro.
function willAggro(aggro,distance){ if(distance > aggro){ return false; } else{ return true; } }
Monster Insertion
Finally, we’re going to do our check to see if a monster will aggro a player or not depending on its distance to the player.
monster['loc'] = $(this).html().split(','); monster['sight'] = 1; $(this).html('X'); distance = getDistance(player['loc'],monster['loc']); if(willAggro(monster['sight'],distance)){ $(this).addClass('monsterA'); } else{ $(this).addClass('monsterN'); } $('#debug').append('<b>Monster:</b> '+monster['loc']); $('#debug').append(' <b>Distance:</b> '+distance+''); $('#debug').append(' <b>Aggro:</b> '+willAggro(monster['sight'],distance)+'<br>');
And that’s all there is to it. If you run this page and take a look, you’ll notice that clicking a grid will place your player and clicking anywhere else will cause the monsters to appear in either green (if too far away to aggro) or red (if it will aggro). This is also noted in the debug section!
Here is our completed javascript section
$(document).ready(function(){ var playerPlaced = false; var monster = []; var player = []; $('#grid tr td').click(function(){ var distance; if(!playerPlaced){ player['loc'] = $(this).html().split(','); player['sight'] = 0; $(this).html('@'); $(this).addClass('player'); playerPlaced = true; $('#debug').append('Player: '+player['loc']+'<br>'); } else{ monster['loc'] = $(this).html().split(','); monster['sight'] = 1; $(this).html('X'); distance = getDistance(player['loc'],monster['loc']); if(willAggro(monster['sight'],distance)){ $(this).addClass('monsterA'); } else{ $(this).addClass('monsterN'); } $('#debug').append('<b>Monster:</b> '+monster['loc']); $('#debug').append(' <b>Distance:</b> '+distance+''); $('#debug').append(' <b>Aggro:</b> '+willAggro(monster['sight'],distance)+'<br>'); } }); }); function getDistance(from,to){ distance = Math.floor(Math.sqrt(Math.pow((from[0]-to[0]),2) + Math.pow((from[1]-to[1]),2))); return distance; } function willAggro(aggro,distance){ if(distance > aggro){ return false; } else{ return true; } }
This is a very simple way to check aggro and the reason I placed it in its own function was incase you needed to modify it in any way (for example if a monster was under 10 levels its aggro would be 0 always).

