   Hex Tiles assistance needed
  I am currently looking at the new HTML5 Canvas element and trying to learn its ins and outs. I am working on a hex-based mapping system using canvas as the display. Below is a pared down version of my code (the hex code minus the actual game code). You can scroll by holding down the middle mouse button. I have disabled zooming for this example. Also, I would suggest using Chrome (or maybe Firefox) to try this out since it is currently &#106avascript intensive. And that is the problem I am trying to solve here.I need to find a way to have the hex map be generated as needed instead of all at once. The dimensions the example uses is what I would like to have as the minimum. The actual map size should be theoretically unlimited. I have been struggling with this on and off for a about a week now. I have made some headway but always end up falling short of the goal. I would like for the map to be "updated" when it is translated a full hex. This is because certain game features (ex. trade routes) are dependent on hexes being at most 4 tiles apart from each other. This is also why the generated map is larger then what is actually shown. So for example, if I move the map 2 hexes "west" and 1 hex "south" (03-04 now in the TL corner), the map would update to "drop" the right most 2 columns and bottom most row and "add" 2 columns along the left and 1 along the top. I hope this explanation makes sense.Any help is much appreciated. Thanks.code for HexTile3.js:var sin18 = Math.sin(deg2rad([[18]]));var cos18 = Math.cos(deg2rad([[18]]));var sin20 = Math.sin(deg2rad([[20]]));var cos20 = Math.cos(deg2rad([[20]]));var sin30 = Math.sin(deg2rad([[30]]));var cos30 = Math.cos(deg2rad([[30]]))var sin210 = Math.sin(deg2rad([[210]]));var cos210 = Math.cos(deg2rad([[210]]));var sin315 = Math.sin(deg2rad([[315]]));var cos315 = Math.cos(deg2rad([[315]]))var backgroundColor = "#[[000000]]";var tileColor = "#FFFFFF";var translateOffsetX = [[0]];var translateOffsetY = [[0]];var dX = [[0]];var dY = [[0]];var lastMouseX = [[0]];var lastMouseY = [[0]];var cSize = [[19]];var rSize = [[15]];var outerSide = [[50]];var outerH = sin30 * outerSide;var outerR = cos30 * outerSide;var innerSide = outerSide - [[2]];var innerH = sin30 * innerSide;var innerR = cos30 * innerSide;var hexGrid = null;var canvas = null;var ctx = null;var selectedHex = null;var m_busy = false;var scale = [[1]].[[0]];var tr = new Array();var sector = new Object();function HexTile(data, xOffset, yOffset, color){this.center = new Object();this.center.x = xOffset + outerH;this.center.y = yOffset + outerR;this.location = new Object();this.location.x = xOffset + [[13]];this.location.y = yOffset + [[11]];this.location.text = data.location;this.outer = new Object();this.outer.active = true;this.outer.x = xOffset;this.outer.y = yOffset;this.outer.vertices;this.outer.lineWidth = [[2]].[[0]];this.outer.strokeStyle = color;this.outer.lineJoin = "round";this.inner = new Object();this.inner.active = false;this.inner.vertices;this.inner.xOffset = [[1]];this.inner.yOffset = [[2]];this.inner.x = xOffset + this.inner.xOffset;this.inner.y = yOffset + this.inner.yOffset;this.inner.lineWidth = [[2]].[[0]];this.inner.strokeStyle = "rgba([[256]],[[0]],[[0]],[[1]].[[0]])";this.inner.lineJoin = "round";this.init = function(){this.outer.vertices = [{x: this.outer.x,y: this.outer.y}, {x: this.outer.x - outerH,y: this.outer.y + outerR}, {x: this.outer.x,y: this.outer.y + outerR + outerR}, {x: this.outer.x + outerSide,y: this.outer.y + outerR + outerR}, {x: this.outer.x + outerSide + outerH,y: this.outer.y + outerR}, {x: this.outer.x + outerSide,y: this.outer.y}, {x: this.outer.x,y: this.outer.y}];this.inner.vertices = [{x: this.inner.x,y: this.inner.y}, {x: this.inner.x - innerH,y: this.inner.y + innerR}, {x: this.inner.x,y: this.inner.y + innerR + innerR}, {x: this.inner.x + innerSide,y: this.inner.y + innerR + innerR}, {x: this.inner.x + innerSide + innerH,y: this.inner.y + innerR}, {x: this.inner.x + innerSide,y: this.inner.y}, {x: this.inner.x,y: this.inner.y}];};this.drawHexOutline = function(hex){ctx.lineWidth = hex.lineWidth;ctx.lineJoin = hex.lineJoin;if (hex.active) ctx.strokeStyle = hex.strokeStyle;else ctx.strokeStyle = backgroundColor;ctx.save();ctx.scale(scale, scale);ctx.beginPath();ctx.moveTo(hex.vertices[[[0]]].x, hex.vertices[[[0]]].y);for (i = [[1]]; i < hex.vertices.length; i++) {ctx.lineTo(hex.vertices.x, hex.vertices.y);}ctx.closePath();ctx.stroke();ctx.restore();};this.select = function(){this.inner.active = true;this.drawHexOutline(this.inner);};this.unselect = function(){this.inner.active = false;this.drawHexOutline(this.inner);};this.draw = function(){this.drawHexOutline(this.outer);if (this.inner.active) {this.drawHexOutline(this.inner);}ctx.save();ctx.scale(scale, scale);ctx.fillStyle = "#FFFFFF";ctx.fillText(this.location.text, this.location.x, this.location.y);ctx.restore();};this.isActive = function(){return this.inner.active;}this.getVertices = function(){return this.inner.vertices;}this.init();}function HexagonGrid(tileType, columnSize, rowSize){this.columnSize = columnSize;this.rowSize = rowSize;this.grid = null;this.dragging = false;this.draw = function(){ctx.clearRect(-[[500]], -[[500]], canvas.height * [[10]], canvas.width * [[10]]);if (this.dragging) ctx.translate(dX, dY);ctx.save();for (cIdx = [[0]]; cIdx < this.columnSize; cIdx++) {for (rIdx = [[0]]; rIdx < this.rowSize; rIdx++) {this.grid[cIdx][rIdx].draw();}}ctx.restore();};this.init = function(tileType){var xOffset = [[0]];var yOffset = [[0]];var column = "";var row = "";var tileData = null;this.grid = new Array(this.columnSize);for (cIdx = [[0]]; cIdx < this.columnSize; cIdx++) {yOffset = cIdx % [[2]] * outerR + [[1]] - ([[8]] * outerR);column = this.getLocationString("C", cIdx);this.grid[cIdx] = new Array(this.rowSize);for (rIdx = [[0]]; rIdx < this.rowSize; rIdx++) {xOffset = cIdx * (outerH + outerSide) + [[1]] - ([[4]] * (outerH + outerSide));row = this.getLocationString("R", rIdx);tileData = new Object();tileData.location = column + "-" + row;this.grid[cIdx][rIdx] = new tileType(tileData, outerH + xOffset, (rIdx * [[2]] * outerR) + yOffset, tileColor);}}};this.getLocationString = function(type, idx){return ((idx) < [[9]] ? "[[0]]" : "") + new String(idx + [[1]]);}this.init(tileType);}function isPointInPoly(poly, pt){for (var c = false, i = -[[1]], l = poly.length, j = l - [[1]]; ++i < l; j = i) ((poly.y <= pt.y && pt.y < poly[j].y) || (poly[j].y <= pt.y && pt.y < poly.y)) &&(pt.x < (poly[j].x - poly.x) * (pt.y - poly.y) / (poly[j].y - poly.y) + poly.x) &&(c = !c);return c;}function deg2rad(deg){return deg * Math.PI / [[180]];}function draw(){hexGrid.draw();}function mouse_scroll(e){e = e || event;var delta = [[0]];if (e.wheelDelta) {delta = e.wheelDelta / [[120]];}else if (e.detail) {delta = -e.detail / [[3]];}scale += (delta >= [[0]]) ? -[[0]].[[1]] : [[0]].[[1]];if (scale <= [[0]].[[5]]) {scale = [[0]].[[5]]}if (scale >= [[2]].[[0]]) {scale = [[2]].[[0]];}if (e.preventDefault) e.preventDefault();draw();}function mouse_up(e){e = e || event;if (e.button == [[0]]) {}else if (e.button == [[1]]) {hexGrid.dragging = false;}else if (e.button == [[2]]) {}}function mouse_down(e){e = e || event;if (m_busy) {return;}m_busy = true;if (e.layerX || e.layerX === [[0]]) {/* Firefox */e._x = e.layerX - canvas.offsetLeft;e._y = e.layerY - canvas.offsetTop;}else if (e.offsetX || e.offsetX === [[0]]) {/* Opera */e._x = e.offsetX;e._y = e.offsetY;}if (e.button == [[0]]) {var offset = findPosition(canvas);var pt = {x: (e._x - offset.x - translateOffsetX) / scale,y: (e._y - offset.y - translateOffsetY) / scale};for (cIdx = [[0]]; cIdx < hexGrid.columnSize; cIdx++) {for (rIdx = [[0]]; rIdx < hexGrid.rowSize; rIdx++) {if (isPointInPoly(hexGrid.grid[cIdx][rIdx].getVertices(), pt)) {if (!hexGrid.grid[cIdx][rIdx].isActive()) {if (selectedHex) {selectedHex.unselect();}selectedHex = hexGrid.grid[cIdx][rIdx];selectedHex.select();}else {hexGrid.grid[cIdx][rIdx].unselect();}}}}}else if (e.button == [[1]]) {hexGrid.dragging = true;}else if (e.button == [[2]]) {//var offset = findPosition(canvas);e.preventDefault();}m_busy = false;}function mouse_move(e){e = e || event;var x = e.clientX - canvas.offsetLeft;var y = e.clientY - canvas.offsetTop;if (hexGrid.dragging === true) {dX = x - lastMouseX;dY = y - lastMouseY;translateOffsetX += dX;translateOffsetY += dY;hexGrid.draw();}lastMouseX = x;lastMouseY = y;}function findPosition(oElement){if (typeof(oElement.offsetParent) != 'undefined') {for (var posX = [[0]], posY = [[0]]; oElement; oElement = oElement.offsetParent) {posX += oElement.offsetLeft;posY += oElement.offsetTop;}return {x: posX,y: posY};}else {return {x: oElement.x,y: oElement.y};}}function init(){canvas = document.getElementById('tutorial');if (canvas.getContext) {//canvas.onmousewheel = mouse_scroll;canvas.onmousedown = mouse_down;canvas.onmouseup = mouse_up;canvas.onmousemove = mouse_move;if (canvas.addEventListener) {//canvas.addEventListener('DOMMouseScroll', mouse_scroll, false);}ctx = canvas.getContext('2d');canvas.height = [[600]];canvas.width = [[800]];hexGrid = new HexagonGrid(HexTile, cSize, rSize);draw();}}<html><head><title>Canvas tutorial</title><script type="text/&#106avascript" src="HexTile3.js"&gt;&lt;/script&gt;&lt;&#115;tyle type="text/css"&gt;canvas{border: 1px solid white;}body{background-color: black;}&lt;/&#115;tyle&gt;&lt;/head&gt;&lt;body &#111;nload="init();"&gt;&lt;canvas id="tutorial"&gt;Nada&lt;/canvas&gt;&lt;/body&gt;&lt;/html&gt;</pre>