August 16, 2010

Custom Select Element

Since the post on styling the input box I thought I’d post a another method to create custom drop-down lists. Again, most browsers won’t let you do very much in the way of styling. IE lets you mess with scrollbars and gecko and webkit let you adjust line-heights and padding, but really, you are STILL left with the default select. However, utilizing some html, css and JavaScript (through jQuery) we can have our own pretty nifty looking drop down. This is part of a UI suite I’m hoping to work on called Clair.

Custom Dropdown

The functionality of our drop-down will mimic that of a regular dropdown box with one exception. Since we can not style the scrollbar, our drop-down will never display one. Instead, it will just keep expanding as you add new links.

HTML
To start off with, our select needs a few different elements to work properly. First off, we need a container that will hold our select. We will also require a list of elements that we want to appear when you click the drop-down. Finally, we need a default element to hold the current selected item and an arrow to signify that we can click on it to display more options. I’ve assigned the classes and Id’s to the elements as necessary. clair-select-active is the default item that will be displayed as well as what is displayed when an element is clicked on.

<div class="clair-select-container">
  <div class="clair-select">
    <div id="clair-select-active">Where My.Feet Have Been</div>
    <ul class="clair-select-links">
      <li><a href="#">Nookish</a></li>
      <li><a href="#">Orange Pine Co</a></li>
      <li><a href="#">Where My.Feet Have Been</a></li>
      <li><a href="#">Your Website</a></li>
    </ul>
  </div>
</div>

CSS
Before we get to the clair specific styles, these are the default ones applied to the entire page:

body{
  font-family: Arial, sans-serif; 
  font-weight: normal;
  font-size: 14pt; 
  background-image: url('bg.png'); 
  margin: 0px;
}
a {
  color: #CCC;
  font-weight: bold;
  text-decoration: none;
}

The first style we get is the clair-select and the clair-select-container These style our entire select container.

.clair-select-container{
  position: relative;
  padding: 10px 0px;
  margin: 0px 0px 40px;
}
.clair-select {
  background-color: #000; 
  color: #CCC;
  -moz-border-radius: 12px;
  -webkit-border-radius: 12px;
  -o-border-radius: 12px;
  -khtml-border-radius: 12px;
  border-radius: 12px;
  padding: 10px 12px 5px;
  font-size: 14px;
  display: inline-block;
  border: solid #555; 
  border-width: 1px 0px 0px 1px;
  width: 230px;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  opacity: 0.7;
  filter: alpha(opacity = 70);
  position: absolute;
  z-index: 2;
}

The purpose of clair-select-container is to make sure when we expand our select dropdown it doesn’t push elements out of the way. Instead of floats nicely above them, and our slight opacity setting will display a faint outline of what it’s coverting.

There is a lot of vendor specific styling going on in clair-select, but the only one that I think warrants explanation is box-sizing and filter.

  • box-sizing: is a CSS3 spec that allows us to change the way that the browser interprets the “box-model” I’ll have to do another post to fully explain the box-model, but essentially it is the difference between including padding and border sizes within the “width” element, or adding it on afterwards. This forces Firefox to render the box-model the way Internet Explorer would 1.
  • filter: is a Microsoft proprietary spec that allows us to use a number of IE only effects. The particular effect I am utilizing is alpha-blending which allows us to change the opacity of the element. I’ve turned the opacity done just a little so that things are still readable, while allowing us to see the background. This has the added benefit of a neat visual effect whereby it looks like our element is slightly inset.

The next style we’re going to add is that of the active element. All we do here is add the arrow as a background image and position it to appear on the right side of the element.

#clair-select-active{
  background-image: url('down.png'); 
  background-repeat: no-repeat;
  background-position: right;
}

Finally, we’re going to style all the links. Nothing too fancy here. We’re just getting rid of bullets, spacing everything out a little and treating the anchor tags as block elements within our li’s.

.clair-select-links {
  margin: 0px; 
  padding: 5px 0px 0px;
  display: none;
}
.clair-select-links li{
  list-style: none;
  padding: 1px;
  margin: 0px;
  overflow: hidden;
}
.clair-select-links li a{
  font-weight: normal; 
  display: block;
  padding: 5px;
  margin: 0px;
}
.clair-select-links li a:hover{
  background-color: #282828;
  -moz-border-radius: 8px;
  -webkit-border-radius: 8px;
  -o-border-radius: 8px;
  -khtml-border-radius: 8px;
  border-radius: 8px;
  color: #DDD;
}

JavaScript
To add functionality to our drop-down we need a bit of JavaScript. I’m utilizing jQuery, but your own JavaScript library should have similar functions. We need to add two kinds of functionality.

  1. We need to switch between minimized and maximized states whenever a user clicks on the clair-select-active element.
  2. We need to switch to minimized and populate clair-select-active with the text from the menu item
$(document).ready(function(e) {
  // This is just for cross-browser prettiness
  $('#clair-select-active').css('cursor','pointer');
 
  // This will toggle everything as necessary
  $('#clair-select-active').click(function(e) {
    if($('.clair-select-links').css('display') == 'block') {
      $('.clair-select-links').slideUp(); 
    }
    else {
      $('.clair-select-links').slideDown();
    }
  });
 
  // This will populate clair-select-active with whatever you click on
  $('.clair-select-links a').click(function(e) {
    e.preventDefault(); 
    $('#clair-select-active').html($(this).html()); 
    $('.clair-select-links').slideUp(); 
  });
});

And that’s it, you’ve built a custom select drop-down. With a little JavaScript trickery, we can even go so far as to include it within forms. We’d just need a hidden form element and then when we populate clair-select-active we would also populate the value attribute of our form element.

This solution works in the following scenarios:

  • IE 7+
  • Firefox 3.5+
  • Chrome 3+
  • Opera 10+

You can download all the files used in this tutorial here: Custom Select Files

Notes:

  1. The IE way, takes your width and keeps your content that size, and adds borders and padding within it
June 25, 2010

Model – View – Controller

The Model-View-Controller (MVC) paradigm of programming is one that is often misused by most developers because it is simply the least understood. When reading tutorials on MVC principles most developers will launch right into the code, which is easy to follow for the purpose of the tutorial. But when those same users try and do it themselves, they find out that it’s a lot harder than it seems. This post aims to correct that by explaining the principles behind the MVC framework and the pro’s and con’s of using it.

In web development, every page will have it’s own Model, View and Controller. This is to ensure that only the information you are requesting is loaded. A lot of those new to the MVC approach will attempt to create a master controller which will then delegate this information to each Model as requested. In MVC, this approach doesn’t quite work. By creating separate entities for each requested page you will find that not only is it easier to maintain and update, but that MVC isn’t that hard to understand at all.

The Big Picture
The easiest way to understand MVC is to step back and look at the whole picture in terms of real-life. In this example, our Controller is going to be the Librarian, the Model is going to be the Library Catalogue and the View is going to be a Book. A user will come up to the Librarian and say “Hey, do you have Book XYZ?” The Librarian of course has no idea. It’s not their job to know where each Book is, but simply to know where to find the information that you are requesting. Regardless of what you are requesting the Librarian will look through a Library Catalogue, but they may look in different kinds of Catalogues. For example, if you say “Hey, do you have the Horror Book XYZ?” they can ignore every other category except Horror. Likewise if you say “Hey, do you have the Romance Book XYZ?” they can ignore every other category except Romance.

The Pieces of the Puzzle – The Controller
The Controller the is the primary building block of an MVC system. Everything you build is managed by the Controller (it Controls see? Programmers love these little word games). The Controller figures out what the user is trying to do and accordingly it goes through the appropriate Model and returns those results to the appropriate View. You can think of the Controller as a messenger. Basically when the user visits a page they are saying “I would like to see the [Gallery] page”. The Gallery Controller will see this and go right over to the GalleryModel and say “The user has requested this information”. It then waits for GalleryModel to respond, and then it takes those results and runs over to GalleryView and goes “Pretty this up”. It then shows you the prettied-up version.

The Model
The Model is also known as your Data Manipulation layer. This should contain functions that interface with the database. Insertion, Updating and Deletion should all occur here, with the results of each passed back to the caller. This centralizes all your DB calls to a single file for a single controller. In this way you know that modifying your “Gallery” table means only modifying your GalleryModel and GalleryView. It doesn’t seem like a big issue to inter-twine your database manipulation and controller at this stage simply because it isn’t. Of course you can integrate your Model directly with the Controller, but by segmenting these you can ensure a much easier re-use of code. Think about it this way – a gallery model can be copied and modified a little to turn it into a blog model. Since the Model doesn’t care about what to DO with the fields, you just need to update what fields it SHOULD be dealing with.

The View
The View is the easiest piece to explain. It simply acts as a display mechanism. It accepts some values from the Controller, mixes it with HTML and spits the result back to the controller. Think of it is a node-based theme engine. For example, you could have a function in your GalleryView that just accepted the URL of a thumbnail and added some HTML which, when styled, made it resemble a Polariod. At a later point in time, if you want to change this, modifying this single function will ensure that everything is changed uniformly.

The Big Picture – Now with the right words
So now we can revisit our Librarian and ask for a new book. We ask the LibraryController for “Horror book XYZ”. The LibraryController invokes the LibraryModel and executes the findBook() function passing it the genre (horror) and book name (XYZ). The LibraryModel executes a quick Database Query to figure out the results. Just so happens there are 5 books in that genre that contain XYZ (XYZ, WXYZ, AXYZ, XYZZ, XXYZ). It passes the result set BACK to LibraryController. LibraryControlled takes the result set and invokes LibraryView, calling the formatBookList() function using the result set as the argument. formatBookList() adds some HTML mockup to each entry and makes everything look good and then passes the HTML back to LibraryController. LibraryController shows you the result.

Variations
Some descriptions of MVC will modify it so that the Controller ignores the view and instead the Model is what passes the data to the View. Either way still conforms with MVC standards, which really just involve separting everything.

Advanced Concepts


Routers
When dealing with server-side languages on the web we have to remember that things don’t work the same as in a desktop environment. Event-driven programming may work fine for C# and Java, but doesn’t work the same way for PHP. In PHP, our equivalent fo Event-driven programming would be URL-based programming. An “event” as far as PHP is concerned, is the user trying to visit a page. This page should trigger some kind of action. In most MVC frameworks (all I would think), you get something called a “Router”. This Router class is essentially a way of registering URLS to certain Controllers. For example visiting www.example.com/gallery/view/48 would cause the Router (or page that invokes the Router) to invoke the GalleryController and make a call to the view() function passing it 48 as an argument. In this way they abstract away explicitly invoking galleryies and can have a single index.php page which invokes the Router and makes the calls as necessary.

Multiple Inheritance
While PHP doesn’t allow for Multiple inheritance (ie GalleryController extends c1, c2, c3) it does allow for cascading inheritance (GalleryController extends c3; c3 extends c2; c2 extends c1; and now GalleryController can do everything c1, c2 and c3 can). Because of this we can actually speed up our Model/Controller creation by extending a singple base Model or Controller class. These classes would ideally have common functions that all Models or Controllers could potentially need at some point. One example would be to force all Models to inherit from BaseModel which could be a custom created Database Manipulation functions that all Models would need.

December 21, 2009

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).