How the snapping function was implemented

March 15th, 2006 in The Making of TheBroth · By David Tapper

One of our goals was to allow players to position and align tiles with pixel-perfect-precision. We wanted to be able to automatically “snap” tiles to adjacent tiles, if the player opts to do so: If you hold down the shift key when you drop a tile near where you want it to go, it will automagically align next to the closest tile. No more squinting! This article describes how we implemented this functionality using JavaScript on the client side.

How does it work?

The code for the snapping is an algorithm built into the mouseUp handler - a function called mU(). It runs through a series of checks and calculations to work out where you actually want the tile to be.

Checking the for SHIFT key

The first task is to check whether the SHIFT key is down. This is determined by checking the shiftKey property of the event object. If it is true, then we know the player wants the tile to snap and the algorithm runs.

Here is a code fragment lifted straight from the mU() function:

if (window.event) e=window.event;
	if (e.shiftKey) {
            // we need to snap

Find the nearest tile

The next task is to find the tile that is nearest to the one you dropped. We loop through all the tiles checking their distance from the tile you just dropped. If no tile is within 1.5 tile widths, the algorithm assumes you don’t actually want to snap to a tile. (Why are you holding the shift key, dude?)

The method for finding the nearest tile includes some “if” statements. We check whether the tile is within 1.5 tile widths on the X and Y axis. For each tile that passes this test, we check it’s distance from the dragged tile using pythagoras’ famous square-on-the-hypotenuse equation:

distance = Math.sqrt(offsetX * offsetX + offsetY * offsetY);

We run this equation for each tile that’s within close proximity (as defined by being not farther away than 1.5 tile widths). The tile with the smallest distance is the one we want to align with.

We could just run pythagoras’ equation for every tile and find the smallest distance. However, this would be CPU intensive, especially if there are many tiles that make up the mosaic; in our case, we have a 1000 tiles in each mosaic. The X and Y if statements narrow down the number of potential tiles without much demand on the CPU. The more expensive, but more accurate pythagoras equation is then run on a small number of nearby tiles.

Align the dropped tile

The next task is to find which edge of the stationary tile we want to align to.

There are eight possible positions: each of the four corners and four edges of the stationary tile. We use another set of if statements to find which edge is the nearest. If the tiles are aligned diagonally, then the dropped tile will snap to the nearest corner. Otherwise it will snap to the nearest edge.

Adjusting for the game area boundaries

Once we know where to snap the tile to, we have one last task. We need to make sure that the new, snapped-to position of the tile is not outside the game area. This is a simple check comparing the new position with the borders of the game area. If it is outside, then it is shifted in so that it meets the edge of the area.

Snap complete!

We now have a new snapped position for our tile. As the snapping happens on the client side, the snapped tile position will be sent to the server and on to all the other players in the next update cycle.

Share this:
  • del.icio.us
  • StumbleUpon
  • Furl
  • Netscape
  • Reddit
  • Technorati
  • YahooMyWeb

5 Responses to “How the snapping function was implemented”

Stephen VanDyke12 Jul 06

This doesn’t work on a mac, fyi.

Markus12 Jul 06

Stephen, that’s surprising to hear - which browser are you using? We’ve been developing TheBroth on macs using Firefox and Safari and it actually works fine on these browsers.

Freaky Friday25 Jul 06

Works for me and I’m on a Mac/Firefox.

Bryan6 Aug 06

I’m just wondering why you didn’t use a kay like the caps lock button, which can be locked down. Or the number lock so it doesn’t interfere with your chat?

I think it’d be nice if there was a button on the mosaic page that you could push and it’d simulate as if the shift key is down so that you don’t have to hold it for like two hours if you’re making a really mosaicy piece. How am I to drink, shift and drag at the same time?

Lol,

Just an idea, but I think that it would be easy to implement.

misspie26 Aug 06

This is an awesome feature! I wasn’t aware of it until someone mentioned it to me and ever since then I have been greatly motivated to use it! I love it and frequently use it!

This page would be an example to show high school students who say, “I hate math, when will I ever use it anyway?” Simply stated, algorithms go far baby!

Leave a comment