diff --git a/index.html b/index.html
index 648996a..05a005d 100644
--- a/index.html
+++ b/index.html
@@ -130,6 +130,7 @@
+
diff --git a/lib/ClassicGame.js b/lib/ClassicGame.js
index 57cc674..79f7aa5 100644
--- a/lib/ClassicGame.js
+++ b/lib/ClassicGame.js
@@ -115,9 +115,9 @@ ltjs.ClassicGame = Class( 'ClassicGame' )
this._render.clearCanvas();
}
- var map = this._mapSet.getMapByNumber( 1 );
-
- var map_state = ltjs.MapState( map, this._gameObjFactory );
+ var map = this._mapSet.getMapByNumber( 1 ),
+ map_state = ltjs.MapState( map, this._gameObjFactory ),
+ bounds = ltjs.MapBounds( map );
// render the first map (hardcoded for now)
this._render = ltjs.MapRender( ctx, this._tileSet )
@@ -141,7 +141,7 @@ ltjs.ClassicGame = Class( 'ClassicGame' )
return;
}
- map_state.movePlayer( dir );
+ map_state.movePlayer( dir, bounds );
};
return this;
diff --git a/lib/MapAction.js b/lib/MapAction.js
index 8dd1354..a36f46c 100644
--- a/lib/MapAction.js
+++ b/lib/MapAction.js
@@ -29,15 +29,25 @@ ltjs.MapAction = Class( 'MapAction',
'private _dir': 0,
+ 'private _srcPos': 0,
+ 'public srcPos': 0,
+
+ 'private _bounds': null,
'private _stateCallback': null,
'private _moveCallback': null,
- __construct: function( state_callback, move_callback )
+ __construct: function( bounds, state_callback, move_callback )
{
+ if ( !( Class.isA( ltjs.MapBounds, bounds ) ) )
+ {
+ throw TypeError( 'Invalid MapBounds provided' );
+ }
+
this._dir = this.__self.$( 'D_UP' );
+ this._bounds = bounds;
this._stateCallback = state_callback;
this._moveCallback = move_callback;
},
@@ -51,7 +61,16 @@ ltjs.MapAction = Class( 'MapAction',
'public move': function()
{
- this._moveCallback( this._dir );
+ var method = [
+ 'getLeftPos',
+ 'getUpperPos',
+ 'getRightPos',
+ 'getLowerPos',
+ ][ this._dir ];
+
+ this._moveCallback(
+ this._bounds[ method ].call( this._bounds, this.srcPos )
+ );
},
diff --git a/lib/MapBounds.js b/lib/MapBounds.js
new file mode 100644
index 0000000..6f9797c
--- /dev/null
+++ b/lib/MapBounds.js
@@ -0,0 +1,190 @@
+/**
+ * Handles map boundaries for collision detection and movement
+ *
+ * Copyright (C) 2012 Mike Gerwitz
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+
+/**
+ * Calculates map bounding box
+ *
+ * This simply encapsulates the process of determining whether a given position
+ * is against an edge of the map.
+ */
+ltjs.MapBounds = Class( 'MapBounds',
+{
+ /**
+ * Map width (number of tiles)
+ * @type {number}
+ */
+ 'private _mw': 0,
+
+ /**
+ * Map height (number of tiles)
+ * @type {number}
+ */
+ 'private _mh': 0,
+
+
+ /**
+ * Initialize bounding box for a given map
+ *
+ * @param {Map} map map for which bounds should be calculated
+ */
+ __construct: function( map )
+ {
+ if ( !( Class.isA( ltjs.Map, map ) ) )
+ {
+ throw TypeError( 'Invalid Map provided' );
+ }
+
+ // we are only interested in the dimensions of the map
+ var dimen = map.getDimensions();
+ this._mw = dimen[ 0 ];
+ this._mh = dimen[ 1 ];
+ },
+
+
+ /**
+ * Retrieve the tile position above the given position
+ *
+ * If the given tile position is at the top of the map, then the given
+ * position will be returned.
+ *
+ * @param {number} pos original tile position
+ *
+ * @return {number} tile position above given position or current position
+ */
+ 'public getUpperPos': function( pos )
+ {
+ return ( this.isAtTop( pos ) )
+ ? pos
+ : pos - 1;
+ },
+
+
+ /**
+ * Retrieve the tile position below the given position
+ *
+ * If the given tile position is at the bottom of the map, then the given
+ * position will be returned.
+ *
+ * @param {number} pos original tile position
+ *
+ * @return {number} tile position below given position or current position
+ */
+ 'public getLowerPos': function( pos )
+ {
+ return ( this.isAtBottom( pos ) )
+ ? pos
+ : pos + 1;
+ },
+
+
+ /**
+ * Retrieve the tile position to the left of the given position
+ *
+ * If the given tile position is at the leftmost column of the map, then the
+ * given position will be returned.
+ *
+ * @param {number} pos original tile position
+ *
+ * @return {number} tile position left of given position or current
+ * position
+ */
+ 'public getLeftPos': function( pos )
+ {
+ return ( this.isAtLeft( pos ) )
+ ? pos
+ : pos - this._mh;
+ },
+
+
+ /**
+ * Retrieve the tile position to the right of the given position
+ *
+ * If the given tile position is at the rightmost column of the map, then
+ * the given position will be returned.
+ *
+ * @param {number} pos original tile position
+ *
+ * @return {number} tile position right of given position or current
+ * position
+ */
+ 'public getRightPos': function( pos )
+ {
+ return ( this.isAtRight( pos ) )
+ ? pos
+ : pos + this._mh;
+ },
+
+
+ /**
+ * Determines if the given position is in the topmost row of the map
+ *
+ * @param {number} pos tile position
+ *
+ * @return {boolean} true if within topmost row, otherwise false
+ */
+ 'public isAtTop': function( pos )
+ {
+ // since tile positions are zero-indexed, we know that we're at the top
+ // if the map height divides the position
+ return ( pos % this._mh === 0 );
+ },
+
+
+ /**
+ * Determines if the given position is in the bottom row of the map
+ *
+ * @param {number} pos tile position
+ *
+ * @return {boolean} true if within bottom row, otherwise false
+ */
+ 'public isAtBottom': function( pos )
+ {
+ // this "works" because tile positions are vertically indexed
+ return this.isAtTop( pos + 1 );
+ },
+
+
+ /**
+ * Determines if the given position is in the leftmost column of the map
+ *
+ * @param {number} pos tile position
+ *
+ * @return {boolean} true if within leftmost column, otherwise false
+ */
+ 'public isAtLeft': function( pos )
+ {
+ // check if index is within the left-most column
+ return ( pos <= this._mh );
+ },
+
+
+ /**
+ * Determines if the given position is in the rightmost column of the map
+ *
+ * @param {number} pos tile position
+ *
+ * @return {boolean} true if within rightmost column, otherwise false
+ */
+ 'public isAtRight': function( pos )
+ {
+ // check if index is within the right-most column
+ return ( pos >= ( this._mh * ( this._mw - 1 ) ) );
+ },
+} );
diff --git a/lib/MapState.js b/lib/MapState.js
index ada6865..af67506 100644
--- a/lib/MapState.js
+++ b/lib/MapState.js
@@ -437,13 +437,6 @@ ltjs.MapState = Class( 'MapState',
},
- // TODO
- 'private _calcPos': function( pos, dir )
- {
- return pos - 1;
- },
-
-
/**
* Creates a callback to alter the state of an object
*
@@ -497,15 +490,14 @@ ltjs.MapState = Class( 'MapState',
{
var _self = this;
- return function( dir )
+ return function( dest )
{
- var newpos = _self._calcPos( pos, dir );
- _self._moveObj( obj, pos, newpos );
+ _self._moveObj( obj, pos, dest );
// call continuation with new position, if requested
if ( typeof c === 'function' )
{
- c( newpos );
+ c( dest );
}
};
},
@@ -517,17 +509,21 @@ ltjs.MapState = Class( 'MapState',
* The directions, as defined in MapAction, are: 0:left, 1:up, 2:right,
* 3:down.
*
- * @param {number} direction direction code
+ * XXX: the bounds argument is temporary
+ *
+ * @param {number} direction direction code
+ * @param {MapBounds} bounds map boundaries
*
* @return {undefined}
*/
- 'public movePlayer': function( direction )
+ 'public movePlayer': function( direction, bounds )
{
var _self = this,
player = this._player;
// XXX: tightly coupled
var action = ltjs.MapAction(
+ bounds,
this._createStateCallback( player, this._playerPos, function( o )
{
_self._player = o;
@@ -540,6 +536,7 @@ ltjs.MapState = Class( 'MapState',
);
action.direction = direction;
+ action.srcPos = this._playerPos;
player.move( action );
}
} );