Skip to content

Instantly share code, notes, and snippets.

@shadda
Created August 29, 2013 23:03
Show Gist options
  • Select an option

  • Save shadda/6384479 to your computer and use it in GitHub Desktop.

Select an option

Save shadda/6384479 to your computer and use it in GitHub Desktop.
(function()
{
TILES = {};
SELECTED_TILES = [];
INVALIDATED_TILES = {};
$stage = $('#stage');
$MAP_TILE_RADIUS = 22;
$MAP_TILE_HEIGHT = parseInt($MAP_TILE_RADIUS * Math.sqrt(3));
$REDRAW = true;
$SCALE = 1.0;
$ALLOW_MULTI_SELECT = true;
var NEIGHBORS_DI = [0, 1, 1, 0, -1,-1];
var NEIGHBORS_DJ = [
[-1, -1, 0, 1, 0, -1],
[-1, 0, 1, 1, 1, 0]
];
var NUM_NEIGHBORS = 6;
HexTile = function(radius, swatch)
{
this.$attributes = {};
this.$swatch = swatch;
this.$image = {};
this.layers = {
'provinces': {},
'height': {},
'terrain': {},
'buildings': []
};
this._x = 0; //Cell's left coordinate
this._y = 0; //Cell's top coordinate
this.x = 0; //Cell's horizontal grid coordinate
this.y = 0; //Cell's vertical grid coordinate
this.RADIUS = radius;
this.WIDTH = this.RADIUS * 2;
this.HEIGHT = parseInt(radius * Math.sqrt(3));
this.SIDE = this.RADIUS * 3 / 2;
this.CORNERS_DX = [
this.RADIUS / 2,
this.SIDE,
this.WIDTH,
this.SIDE,
this.RADIUS / 2,
0
];
this.CORNERS_DY = [
0, 0,
this.HEIGHT / 2,
this.HEIGHT,
this.HEIGHT,
this.HEIGHT / 2
];
}
HexTile.prototype.init = function()
{
this.$image = {};
this.RADIUS = $MAP_TILE_RADIUS;
this.WIDTH = this.RADIUS * 2;
this.HEIGHT = parseInt(this.RADIUS * Math.sqrt(3));
this.SIDE = this.RADIUS * 3 / 2;
this.CORNERS_DX = [
this.RADIUS / 2,
this.SIDE,
this.WIDTH,
this.SIDE,
this.RADIUS / 2,
0
];
this.CORNERS_DY = [
0, 0,
this.HEIGHT / 2,
this.HEIGHT,
this.HEIGHT,
this.HEIGHT / 2
];
this.setCellIndex(this.x, this.y);
}
HexTile.prototype.fromHash = function(data)
{
for(var key in data)
{
this[key] = data[key];
this.$attributes[key] = data[key];
}
this.setCellIndex(data['x'], data['y']);
}
HexTile.prototype.getData = function(callback)
{
var position = this.x + 'x' + this.y;
$.getJSON('map.getTileData.ajax', {position: position}, function(result)
{
callback.call(this, result);
});
}
HexTile.prototype.invalidate = function()
{
this.$image = {};
this.$swatch = null;
INVALIDATED_TILES[this._id] = this;
}
HexTile.prototype.setAttribute = function(key, val, layer)
{
var attribute = key;
if(layer)
attribute = key + ':' + layer.getLayerName();
this.$attributes[attribute] = {
key: 'key',
value: 'value',
layer: layer
};
}
HexTile.prototype.removeAttribute = function(key, layer)
{
var attribute = key;
if(layer)
attribute = key + ':' + layer;
if(this.$attributes[attribute])
delete this.$attributes[attribute];
}
HexTile.prototype.getIdentity = function()
{
return this.x + 'x' + this.y;
}
HexTile.prototype.getLeft = function()
{
return this._x;
}
HexTile.prototype.getTop = function()
{
return this._y;
}
HexTile.prototype.getCenterX = function()
{
return this._x + this.RADIUS;
}
HexTile.prototype.getCenterY = function()
{
return this._y + this.HEIGHT / 2;
}
HexTile.prototype.getCoordinates = function()
{
return {
'x': this.x,
'y': this.y
};
}
HexTile.prototype.getIndex_X = function()
{
return this.x;
}
HexTile.prototype.getIndex_Y = function()
{
return this.y;
}
HexTile.prototype.getNeighbors = function()
{
}
HexTile.prototype.getNeighborX = function(neighborId_x)
{
return this.x + NEIGHBORS_DI[neighborId_x];
}
HexTile.prototype.getNeighborY = function(neighborId_x)
{
return this.y + NEIGHBORS_DJ[this.x % 2][neighborId_x];
}
HexTile.prototype.computeCorners = function(cornersX, cornersY)
{
for(var k = 0; k < NUM_NEIGHBORS; k++)
{
cornersX[k] = mX + this.CORNERS_DX[k];
cornersY[k] = mY + this.CORNERS_DY[k];
}
return [cornersX, cornersY];
}
HexTile.prototype.setCellIndex = function(i, j)
{
this.x = i;
this.y = j;
this._x = i * this.SIDE;
this._y = this.HEIGHT * (2 * j + (i % 2)) / 2;
}
HexTile.prototype.setCellByPoint = function(x, y)
{
this._x = x;
this._y = y;
var ci = parseInt(Math.floor( parseFloat(x) / parseFloat(this.SIDE) ));
var cx = x - this.SIDE * ci;
var ty = y - (ci % 2) * this.HEIGHT / 2;
var cj = parseInt(Math.floor(parseFloat(ty) / parseFloat(this.HEIGHT)));
var cy = ty - this.HEIGHT * cj;
if(cx > Math.abs(this.RADIUS / 2 - this.RADIUS * cy / this.HEIGHT))
{
this.setCellIndex(ci, cj);
}
else
{
this.setCellIndex(ci - 1, cj + (ci % 2) - ((cy < this.HEIGHT / 2) ? 1 : 0));
}
}
HexTile.prototype.equals = function(tile)
{
if(this.getIndex_X() == tile.getIndex_X() &&
this.getIndex_Y() == tile.getIndex_Y())
{
return true;
}
return false;
}
HexTile.prototype.isVisible = function(x1, y1, x2, y2)
{
if(this._x < x1 || this._x > x2 || this._y < y1 || this._y > y2)
return false;
return true;
}
HexTile.prototype.save = function(callback)
{
$.ajax({
type: 'POST',
url: 'map.saveTile.ajax',
data: {tile: JSON.stringify(this)},
dataType: 'json',
success: callback
});
}
HexTile.prototype.createImage = function(swatch, radius)
{
var key = swatch + "_" + radius;
if(!this.$image[key])
{
//Revaluate our tile's data
this.init();
var canvas = $('<canvas></canvas>')
.attr('width', this.WIDTH + 8)
.attr('height', this.HEIGHT + 8);
var context = canvas[0].getContext('2d');
var $swatch = SWATCHES[swatch];
if(!$swatch) console.log("Holy merciful shit, swatch not found: " + swatch);
if(!$swatch)
{
$swatch = SWATCHES['default'];
}
if($swatch.image)
{
canvas.drawImage({
source: $swatch.image,
x: this.getCenterX() - this.getLeft(),
y: this.getCenterY() - this.getTop(),
fromCenter: true
});
}
else
{
var defaults = {
fillStyle: $swatch.fillStyle,
strokeStyle: $swatch.strokeStyle,
strokeWidth: $swatch.strokeWidth,
x: this.getCenterX() - this.getLeft() + 4,
y: this.getCenterY() - this.getTop() + 4,
radius: radius,
sides: 6
};
var options = $.extend(defaults, {});
canvas.drawPolygon(options);
}
this.$image[key] = canvas[0].toDataURL();
}
return this.$image[key];
}
var HexMapEvents =
{
'onWindowResize': function()
{
this.$canvas[0].width = ($(window).innerWidth() - 32 );
this.$canvas[0].height = ($(window).innerHeight() - 32 );
},
'onStageClick': function(game, map, tile, event)
{
if(map.isTileSelected(tile))
{
if(keydown.alt)
{
var tiles = SELECTED_TILES;
for(var k in tiles)
{
if(tiles[k].equals(tile))
{
delete SELECTED_TILES[k];
return;
}
}
}
else if(keydown.shift)
{
return;
}
else
{
map.setSelectedTiles([tile]);
return;
}
}
if($ALLOW_MULTI_SELECT && keydown.shift)
{
var tiles = SELECTED_TILES.concat([tile]);
map.setSelectedTiles(tiles);
return;
}
map.setSelectedTiles([tile]);
}
};
HexMap = function(canvas)
{
this.canvas = canvas;
this.context = this.canvas[0].getContext('2d');
this.radius = $MAP_TILE_RADIUS;
this.tile_height = parseInt(this.radius * Math.sqrt(3));
this.rows = parseInt(canvas.innerHeight() / this.tile_height);
this.columns = parseInt(canvas.innerWidth() / this.radius);
this.$layers = LAYERS;
this.$tiles = {};
this.$events = HexMapEvents;
this.$events.clickEvents = [
HexMapEvents.onStageClick
];
this.$ui = {};
this.$ui.coordinate_x = $('.coord_x');
this.$ui.coordinate_y = $('.coord_y');
this.$cache = {};
this.$ui.swatches = {
'selected': null
};
}
HexMap.prototype.getTiles = function(page, callback)
{
var totalPages = 0;
page = page ? page : 1;
console.log("Fetching page " + page + " of " + totalPages);
var self = this;
$.getJSON('map.getTiles.ajax', {page: page}, function(result)
{
var len = result.data.length;
totalPages = result.pages;
for(var i = 0; i < len; i++)
{
var row = result.data[i];
var tile = new HexTile(self.radius);
tile.fromHash(row);
tile.setCellIndex(row.x, row.y);
TILES[tile._id] = tile;
INVALIDATED_TILES[tile._id] = tile;
}
if(page < totalPages)
{
self.getTiles.call(self, page + 1, callback);
}
if(page == totalPages)
{
callback(TILES);
}
});
}
HexMap.prototype.createTile = function(position, radius)
{
var tile = new HexTile(radius);
tile.setCellIndex(position[0], position[1]);
//Shitty work around while I'm being drunk and lazy
//Going to rewrite tiles anyway.
tile.$attributes.layers = tile.layers;
return tile;
}
HexMap.prototype.isTileSelected = function(tile)
{
for(var k in SELECTED_TILES)
{
var selectedTile = SELECTED_TILES[k];
if(selectedTile.equals(tile))
{
return true;
}
}
return false;
}
HexMap.prototype.setSelectedTiles = function(tiles)
{
SELECTED_TILES = tiles;
}
HexMap.prototype.drawGrid = function()
{
}
HexMap.prototype.drawFromCache = function(cache_name, opts)
{
var cache = this.$cache[cache_name];
if(cache_name.indexOf('data:') !== -1)
{
cache = cache_name;
}
if(cache)
{
var defaults = {
x: 0,
y: 0,
width: this.canvas.width(),
height: this.canvas.height(),
fromCenter: false
};
var options = $.extend(defaults, opts);
options.source = cache;
this.canvas.drawImage(options);
}
}
HexMap.prototype.findHex = function(position)
{
var mX = position[0];
var mY = position[1];
var swatch = null;
var tile = new HexTile($MAP_TILE_RADIUS);
tile.setCellByPoint(mX, mY);
return [tile.x, tile.y];
}
HexMap.prototype.drawTile = function(tile, layer, cache_name, options)
{
cache_name = null;
if(cache_name && !this.$cache[cache_name])
{
var canvas = $('<canvas></canvas>')
.attr('width', tile.WIDTH)
.attr('height', tile.HEIGHT);
if(tile.$swatch)
{
this.$cache[cache_name] = tile.$swatch;
}
else
{
var defaults = {
fillStyle: 'black',
strokeStyle: 'white',
strokeWidth: 2,
x: (tile.getCenterX() - tile.getLeft()),
y: (tile.getCenterY() - tile.getTop()),
radius: tile.RADIUS,
sides: 6
};
var options = $.extend(defaults, options);
canvas.drawPolygon(options);
this.$cache[cache_name] = canvas[0].toDataURL();
}
}
else if(!cache_name)
{
if(tile.$swatch)
{
layer.$canvas.drawImage({
'source': tile.$swatch,
x: tile.getCenterX(),
y: tile.getCenterY(),
fromCenter:true
});
}
else
{
var defaults = {
fillStyle: 'black',
strokeStyle: 'white',
strokeWidth: 2,
x: tile.getCenterX(),
y: tile.getCenterY(),
radius: tile.RADIUS,
sides: 6
};
var options = $.extend(defaults, options);
layer.$canvas.drawPolygon(options);
}
}
return {
source: this.$cache[cache_name],
x: tile.getCenterX(),
y: tile.getCenterY(),
fromCenter: true
};
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment