Skip to content

Instantly share code, notes, and snippets.

@dariusk
Created June 10, 2011 15:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save dariusk/1019000 to your computer and use it in GitHub Desktop.
Save dariusk/1019000 to your computer and use it in GitHub Desktop.
Explanation of tileCollision in Akihabara
/**
* Checks if the specified object is colliding with tiles in the map in an area defined by the object's colw and colh variables as well as the tolerance and approximation variables that are passed in through data. Only tiles in the map marked as solid are checked against. The alogrithm checks the
* @param {Object} th The object that is being checked against the tilemap.
* @param {Object} map This is the asci map that the tile map is generated from.
* @param {Object} tilemap This is the array of tile objects that it itterated over checking for collisions.
* @param {Object} defaulttile The default tile to be returned if nothing can be found. Null can be used here.
* @param {Object} data Passes is extra dat to the function. Can be set as null.
* <ul>
* <li>tolerance{Integer}: This is subtracted from the collision space to get the maximum collision area for the object. This defaults to 6.</li>
* <li>approximation{Integer}: This is the amount that the checked values are incremented by until they reach the maximum value allowed. This defaults to 10.</li>
* </ul>
*/
tileCollision:function(th,map,tilemap,defaulttile,data) {
// First, we set collisions on all sides of "th" (the object we're checking) to be false.
// We'll set these to true if it turns out we're colliding. If these are colliding, the
// function will then set acceleration along these axes to zero. You may not want to do this!
// The way your object reacts to collsion should probably be in its own function!
th.touchedup=false; th.toucheddown=false; th.touchedleft=false; th.touchedright=false;
// Set our tolerance and approximation to defaults if not provided by the "data" object -- see
// official documentation above
var tolerance=(data&&(data.tolerance!=null)?data.tolerance:6);
var approximation=(data&&(data.approximation!=null)?data.approximation:10);
// IMPORTANT: To make this easier to understand, I'm going to assume that tolerance = 0 for
// the rest of this function! once you understand it without tolerance, it's easy to add in
// the concept of tolerance. ALSO IMPORANT: We'll assume approximation = 1.
// This "t" variable is confusing, but for our purposes it's -1.
var t=tolerance-approximation;
// A do-while loop that runs until t === the width of the object's collision area minus
// tolerance minus 1. So if we have a 32x32 object we're checking, using our values this will
// run until t is 31 (32-1=31) Basically the loop runs left to right across the sprite's
// collision area (that's what t does, it traverses x) and then checks above and below the
// sprite to see if we're colliding on the top or bottom at position x=t
do {
// On our first loop we're adding approximation right back to t, so t = tolerance, which is
// 0 in our case. He could have just said "t = tolerance" and incremented the variable at
// the end of this block, but whatever.
t+=approximation;
// If we're far enough to the right that we're outside of the area we're testing for
// collision (in this case, when t>31) we clamp the value for t to 31. This does two things:
// it breaks the while loop because we're done traversing, but it also makes sure that we
// always get ONE collision test on the very far right edge of our collision area (if
// approximation is bigger than the width of our collision area, we could skip the sprite
// altogether -- this ensures we get at least one valid check)
if (t>th.colw-tolerance-1) t=th.colw-tolerance-1;
// When you see "th.x+th.colx" or "th.y+th.coly", that is just "the absolute x/y position of
// the upper left corner of our collision mask". So to break it down: the first argument
// we're passing getTileInMap is the absolute X position that we're at while we traverse the
// collision mask from right to left. The second argument is a constant: it's just the
// bottom of our collision mask, minus 1. So we're asking for the tile that is along our
// current X value, but is just inside the bottom edge of our collision mask. IE: "Hey, what
// tile am I colliding with on the bottom at at this particular X point?"
var bottom=help.getTileInMap(th.x+th.colx+t,th.y+th.coly+th.colh-1,map,defaulttile,tilemap);
// Same but for the top instead of the bottom of the collision mask
var top=help.getTileInMap(th.x+th.colx+t,th.y+th.coly,map,defaulttile,tilemap);
// If our top or bottom colliding tiles are solid, set the appropriate variables
if (map.tileIsSolid(th,top)) th.touchedup=true;
if (map.tileIsSolid(th,bottom)) th.toucheddown=true;
// Keep on trucking until we get all the way to the right of our collision mask
} while (t!=th.colw-tolerance-1);
// This does the same thing but traverses top to bottom and checks tiles that are just inside
// the left or right edge of our collision mask
t=tolerance-approximation;
do {
t+=approximation;
if (t>th.colh-tolerance-1) t=th.colh-tolerance-1;
var left=help.getTileInMap(th.x+th.colx,th.y+th.coly+t,map,defaulttile,tilemap);
var right=help.getTileInMap(th.x+th.colx+th.colw-1,th.y+th.coly+t,map,defaulttile,tilemap);
if (map.tileIsSolid(th,left)) th.touchedleft=true;
if (map.tileIsSolid(th,right)) th.touchedright=true;
} while (t!=th.colh-tolerance-1);
// Set acceleration to 0 depending on the direction we're colliding in, and clamp the object's
// position along the axis to be just adjacent to the tile we're colliding with. (This
// prevents us rubberbanding into walls as we collide into them, and makes it a smooth stop.)
if (th.touchedup) {
th.accy=0;
th.y=help.yPixelToTile(map,th.y+th.coly,1)-th.coly;
}
if (th.toucheddown) {
th.accy=0;
th.y=help.yPixelToTile(map,th.y+th.coly+th.colh-1)-th.coly-th.colh;
}
if (th.touchedleft) {
th.accx=0;
th.x=help.xPixelToTile(map,th.x+th.colx,1)-th.colx;
}
if (th.touchedright) {
th.accx=0;
th.x=help.xPixelToTile(map,th.x+th.colx+th.colw-1)-th.colx-th.colw;
}
},
// A NOTE ON TOLERANCE AND APPROXIMATION: Tolerance will affect how "forgiving" your collision is.
// It affects the outer bounds of those while loops. Approximation is just how many X/Y positions we
// want to skip during our test. So an approximation of 1 is pixel-perfect collision along those
// axes. An approximation of 2 skips every other pixel. Etc.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment