Skip to content
Browse files

Started refactoring hit detection. Made it messier so far. Introduced…

… Rects and Points, and created a getBounds func on player and tile, then we can do an intersection between the player rect and the surrounding tiles. Works currently, but it's overly strict and counts too many tiles.

Also added hit detection debugging assistants in the form of bounding box and intersection display. In client.js, add showBoundingBoxes: true to the Renderer initialisation opts. Like so:

var renderer = new KaboomRenderer({
  arena: $('#arena'),
  playerLayer: $('#playerLayer'),
  holding: $('#holding'),
  game: game,
  showBoundingBoxes: true
});

I will clean all this up once I've had some sleep :)
  • Loading branch information...
1 parent a7d1a1d commit 36312acac9c85e306086c7dede6fb74de5a440e1 @jagregory jagregory committed Jun 5, 2011
View
14 public/css/bomber.css
@@ -63,4 +63,18 @@ body {
#player_4 {
background: url(../images/player-4.png);
+}
+
+.boundingBox {
+ border: 1px solid red;
+ position: absolute;
+ z-index: 100;
+}
+
+.boundingBox.player {
+ border: 1px solid green;
+}
+
+.intersecting {
+ background: rgba(0, 0, 255, 0.5);
}
View
9 public/js/game/client.js
@@ -103,13 +103,12 @@ KaboomClient.prototype = {
$(document).bind('keydown', this.onKeyDown.tie(this));
$(document).bind('keyup', this.onKeyUp.tie(this));
- var renderingTargets = {
+ var renderer = new KaboomRenderer({
arena: $('#arena'),
playerLayer: $('#playerLayer'),
- holding: $('#holding')
- };
-
- var renderer = new KaboomRenderer(renderingTargets, window.game);
+ holding: $('#holding'),
+ game: game
+ });
setInterval(function(){
window.game.update();
View
128 public/js/game/kaboom.game.js
@@ -60,9 +60,9 @@ KaboomGame.prototype = {
createPlayer : function() {
var spawn = this.level.getFirstEmptySpawnPoint();
- var that=this;
+ var that=this;
if (spawn == null) return(null);
- var player = new KaboomPlayer("Player " + spawn.number, that.tilesToPixels(spawn.position));
+ var player = new KaboomPlayer(spawn.number, "Player " + spawn.number, that.tilesToPixels(spawn.position));
console.log(player);
this.players[spawn.number - 1] = player;
return player;
@@ -86,37 +86,25 @@ KaboomGame.prototype = {
update: function() {
var game = this;
/* For each player, assume they have moved DISTANCE in their own velocity */
- this.players.forEach(function(p, idx)
- {
- if (p != null)
- {
- /* hacky "looks right for the image we've got values */
- var width = 43;
- var height = 38;
-
+ this.players.forEach(function(p, idx) {
+ if (p != null) {
var newPos = new Position(
p.position.x + game.DISTANCE * p.velocity.dx,
- p.position.y + game.DISTANCE * p.velocity.dy);
-
- function goodPos(position)
- {
- var tilePos = game.pixelsToTiles(position);
- var tile = game.level.rows[tilePos.y][tilePos.x];
-
- try {
- if (!tile.solid)
- return true;
- }
- catch (ex) {
- console.log(tilePos);
- return false;
- }
- }
+ p.position.y + game.DISTANCE * p.velocity.dy
+ );
+
+ var playerRect = new Rectangle(newPos.y, newPos.x, 48, 48);
+ var canMove = true;
+
+ game.level.forEachIntersectingTile(playerRect, game, function(tile) {
+ if (tile.solid) {
+ canMove = false;
+ }
+ });
- var rightPos = new Position(newPos.x + width, newPos.y);
- var downPos = new Position(newPos.x, newPos.y + height);
- if (goodPos(newPos) && goodPos(rightPos) && goodPos(downPos))
+ if (canMove) {
p.position = newPos;
+ }
}
});
}
@@ -141,9 +129,25 @@ function Level(initialTileMap) {
this.spawns = [];
this.copyStateFrom = function(that) {
- this.rows = that.rows;
+ this.rows = that.rows.map(function(row) {
+ return row.map(function(cell) {
+ return new Tile(cell.solid, cell.tileType, cell.row, cell.col);
+ });
+ });
this.spawns = that.spawns;
}
+
+ this.forEachIntersectingTile = function(rect, game, callback) {
+ $(this.rows).each(function(ri, row) {
+ $(row).each(function(ti, tile) {
+ tile.isIntersecting = false;
+ if (rect.intersects(tile.getBounds(game))) {
+ tile.isIntersecting = true;
+ callback(tile);
+ }
+ });
+ });
+ };
this.parseLevel = function(tileMap) {
var r, c;
@@ -153,15 +157,16 @@ function Level(initialTileMap) {
var solid, tileType;
var row = [];
+
+ for (var i = 0; i < tileMap.length; i++) {
+ var tileChar = tileMap[i];
- for (r = 0; r < tileMap.length; r++) {
- entry = tileMap[r];
- switch (entry) {
- case "\n":
- this.rows.push(row);
- row = [];
- continue;
- case "*":
+ switch (tileChar) {
+ case '\n':
+ this.rows.push(row);
+ row = [];
+ continue;
+ case "*":
tileType = TileType.Solid;
solid = true;
spawn = false;
@@ -202,19 +207,18 @@ function Level(initialTileMap) {
break;
default:
console.log(entry);
-
- }
- if (spawn)
- {
+ }
+
+ if (spawn) {
this.spawns.push(new Spawn(spawnNum, row.length, this.rows.length));
}
- var tile = new Tile(solid, tileType);
- row.push(tile);
- }
+
+ row.push(new Tile(solid, tileType, this.rows.length, row.length));
+ };
- if (row.length > 0)
+ if (row.length > 0) {
this.rows.push(row);
- console.log(this.spawns);
+ }
}
@@ -231,13 +235,39 @@ function Level(initialTileMap) {
}
}
-function Tile (solid, tileType) { // more shit to add
+function Tile (solid, tileType, row, col) {
this.solid = solid;
this.tileType = tileType;
-}
+ this.row = row;
+ this.col = col;
+ this.getBounds = function(game) {
+ return new Rectangle(this.col * game.TILE_SIZE, this.row * game.TILE_SIZE, game.TILE_SIZE, game.TILE_SIZE);
+ }
+};
function Spawn (num, x, y) {
this.number = num;
this.position = new Position(x,y);
this.player = null;
}
+
+function Rectangle(x, y, width, height) {
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+ this.left = x;
+ this.top = y;
+ this.right = this.left + width;
+ this.bottom = this.top + height;
+ this.pointIntersects = function(point) {
+ return point.x >= this.left && point.x < this.right &&
+ point.y >= this.top && point.y < this.bottom;
+ };
+ this.intersects = function(that) {
+ return this.pointIntersects({x: that.top, y: that.left}) ||
+ this.pointIntersects({x: that.top, y: that.right}) ||
+ this.pointIntersects({x: that.bottom, y: that.left}) ||
+ this.pointIntersects({x: that.bottom, y: that.right});
+ };
+};
View
7 public/js/game/kaboom.player.js
@@ -6,11 +6,15 @@
* To change this template use File | Settings | File Templates.
*/
-var KaboomPlayer = function(name, position, velocity) {
+var KaboomPlayer = function(id, name, position, velocity) {
/* Player.name must be unique and can be used to determine equality */
+ this.id = id;
this.name = name;
this.position = position || new Position(0,0);
this.velocity = velocity || new Velocity(0,0);
+ this.getBounds = function(game) {
+ return new Rectangle(this.position.x, this.position.y, game.TILE_SIZE, game.TILE_SIZE);
+ };
};
Position = function(x, y) {
@@ -66,6 +70,7 @@ KaboomPlayer.prototype = {
},
copyStateFrom : function(that) {
+ this.id = that.id;
this.name = that.name;
this.position = new Position(that.position.x, that.position.y);
this.velocity = new Velocity(that.velocity.dx, that.velocity.dy);
View
60 public/js/game/kaboom.renderer.js
@@ -1,4 +1,43 @@
-function KaboomRenderer(target, game) {
+KaboomPlayer.prototype.showBoundingBox = function(layer, game) {
+ var boundingBox = $('#player_'+this.id+'_boundingBox');
+ if (boundingBox.length == 0) {
+ boundingBox = $('<div id="player_'+this.id+'_boundingBox" class="boundingBox player" />');
+ layer.append(boundingBox);
+ }
+
+ var bounds = this.getBounds(game);
+ boundingBox.css({
+ top: bounds.top + 'px',
+ left: bounds.left + 'px',
+ width: bounds.width + 'px',
+ height: bounds.height + 'px'
+ });
+};
+
+Tile.prototype.showBoundingBox = function(layer, game) {
+ var boundingBox = $('#tile_'+this.row+'x'+this.col+'_boundingBox');
+ if (boundingBox.length == 0) {
+ boundingBox = $('<div id="tile_'+this.row+'x'+this.col+'_boundingBox" class="boundingBox" />');
+ layer.append(boundingBox);
+ }
+
+ var bounds = this.getBounds(game);
+ boundingBox.css({
+ top: bounds.top + 'px',
+ left: bounds.left + 'px',
+ width: bounds.width + 'px',
+ height: bounds.height + 'px'
+ });
+
+ if (this.isIntersecting) {
+ boundingBox.addClass('intersecting');
+ } else {
+ boundingBox.removeClass('intersecting');
+ }
+};
+
+function KaboomRenderer(opts) {
+ var game = opts.game;
this.itemImages = ["images/solid-block.png",
"images/destroyable-block.png",
"images/blank.png" ];
@@ -20,7 +59,7 @@ function KaboomRenderer(target, game) {
rowDiv.append(tileDiv);
}
- target.arena.append(rowDiv);
+ opts.arena.append(rowDiv);
}
// create players
@@ -32,18 +71,22 @@ function KaboomRenderer(target, game) {
this.createPlayer = function(num) {
var playerDiv = $('<div id="player_' + num + '" class="player" />');
- target.holding.append(playerDiv);
+ opts.holding.append(playerDiv);
};
this.updatePlayerLocations = function() {
for (var i = 0; i < game.players.length; i++) {
var player = game.players[i];
if (player != null) {
+ if (opts.showBoundingBoxes) {
+ player.showBoundingBox(opts.playerLayer, game);
+ }
+
var playerDiv = $('#player_' + (i + 1));
if (!playerDiv.data('isInPlay')) {
- target.playerLayer.append(playerDiv);
+ opts.playerLayer.append(playerDiv);
playerDiv.data('isInPlay', true);
}
@@ -76,10 +119,15 @@ function KaboomRenderer(target, game) {
url = 'url(' + this.itemImages[tile.tileType] + ')';
}
- if (tileDiv.data('background') != url)
+ if (tileDiv.data('background') != url) {
tileDiv.css('background', url);
tileDiv.data('background', url);
- }
+ }
+
+ if (opts.showBoundingBoxes) {
+ tile.showBoundingBox(opts.playerLayer, game);
+ }
+ }
}
};

0 comments on commit 36312ac

Please sign in to comment.
Something went wrong with that request. Please try again.