Refactor Maps (#2)
This commit is contained in:
@@ -50,6 +50,8 @@ export default class CartographerFlatXY extends Cartographer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tileToPixel(square) {
|
tileToPixel(square) {
|
||||||
|
square = typeof square === 'Square' ? square : new Square(...arguments);
|
||||||
|
|
||||||
const x = square.getX() * this.minWidth();
|
const x = square.getX() * this.minWidth();
|
||||||
const y = square.getY() * this.minWidth();
|
const y = square.getY() * this.minWidth();
|
||||||
|
|
||||||
@@ -57,6 +59,8 @@ export default class CartographerFlatXY extends Cartographer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pixelToTile(point) {
|
pixelToTile(point) {
|
||||||
|
point = typeof point === 'Point' ? point : new Point(x, y);
|
||||||
|
|
||||||
const pixelX = point.getX() - this.originX;
|
const pixelX = point.getX() - this.originX;
|
||||||
const pixelY = this.originY - point.getY();
|
const pixelY = this.originY - point.getY();
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ export default class CartographerFlatXYZ extends Cartographer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tileToPixel(hex) {
|
tileToPixel(hex) {
|
||||||
|
hex = typeof hex === 'Hex' ? hex : new Hex(...arguments);
|
||||||
|
|
||||||
const pixelX = this.scale * 3/2 * hex.getQ();
|
const pixelX = this.scale * 3/2 * hex.getQ();
|
||||||
const pixelY = this.scale * sqrt3 * (hex.getR() + (hex.getQ() / 2));
|
const pixelY = this.scale * sqrt3 * (hex.getR() + (hex.getQ() / 2));
|
||||||
|
|
||||||
@@ -57,6 +59,8 @@ export default class CartographerFlatXYZ extends Cartographer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pixelToTile(point) {
|
pixelToTile(point) {
|
||||||
|
point = typeof point === 'Point' ? point : new Point(x, y);
|
||||||
|
|
||||||
const pixelX = point.getX() - this.originX;
|
const pixelX = point.getX() - this.originX;
|
||||||
const pixelY = point.getY() - this.originY;
|
const pixelY = point.getY() - this.originY;
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ export default class CartographerPointyXY extends Cartographer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tileToPixel(square) {
|
tileToPixel(square) {
|
||||||
|
square = typeof square === 'Square' ? square : new Square(...arguments);
|
||||||
|
|
||||||
const x = square.getX();
|
const x = square.getX();
|
||||||
const y = square.getY();
|
const y = square.getY();
|
||||||
|
|
||||||
@@ -61,6 +63,8 @@ export default class CartographerPointyXY extends Cartographer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pixelToTile(point) {
|
pixelToTile(point) {
|
||||||
|
point = typeof point === 'Point' ? point : new Point(x, y);
|
||||||
|
|
||||||
const pixelX = point.getX() - this.originX;
|
const pixelX = point.getX() - this.originX;
|
||||||
const pixelY = this.originY - point.getY();
|
const pixelY = this.originY - point.getY();
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ export default class CartographerPointyXYZ extends Cartographer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tileToPixel(hex) {
|
tileToPixel(hex) {
|
||||||
|
hex = typeof hex === 'Hex' ? hex : new Hex(...arguments);
|
||||||
|
|
||||||
const pixelX = this.scale * sqrt3 * (hex.getQ() + (hex.getR() / 2));
|
const pixelX = this.scale * sqrt3 * (hex.getQ() + (hex.getR() / 2));
|
||||||
const pixelY = this.scale * 3/2 * hex.getR();
|
const pixelY = this.scale * 3/2 * hex.getR();
|
||||||
|
|
||||||
@@ -57,6 +59,8 @@ export default class CartographerPointyXYZ extends Cartographer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pixelToTile(point) {
|
pixelToTile(point) {
|
||||||
|
point = typeof point === 'Point' ? point : new Point(x, y);
|
||||||
|
|
||||||
const pixelX = point.getX() - this.originX;
|
const pixelX = point.getX() - this.originX;
|
||||||
const pixelY = point.getY() - this.originY;
|
const pixelY = point.getY() - this.originY;
|
||||||
|
|
||||||
|
|||||||
36
src/cell.js
36
src/cell.js
@@ -1,23 +1,31 @@
|
|||||||
import {random} from './utils.js';
|
import {random} from './utils.js';
|
||||||
|
import {
|
||||||
|
HEX, CIRCLE, SQUARE,
|
||||||
|
FLAT, POINTY,
|
||||||
|
FILL, OUTLINE,
|
||||||
|
} from './consts.js';
|
||||||
|
|
||||||
|
const DEFAULTS = {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
|
||||||
|
scale: 10,
|
||||||
|
orientation: FLAT,
|
||||||
|
tileStyle: HEX,
|
||||||
|
drawStyle: FILL,
|
||||||
|
width: 1,
|
||||||
|
|
||||||
|
red: 0,
|
||||||
|
green: 0,
|
||||||
|
blue: 0,
|
||||||
|
alpha: 0.5,
|
||||||
|
};
|
||||||
|
|
||||||
export default class Cell {
|
export default class Cell {
|
||||||
constructor(settings) {
|
constructor(settings) {
|
||||||
this.getColor = this.getColor.bind(this);
|
this.getColor = this.getColor.bind(this);
|
||||||
|
|
||||||
this.x = 0;
|
Object.assign(this, DEFAULTS, settings);
|
||||||
this.y = 0;
|
|
||||||
this.scale = 10;
|
|
||||||
this.pointyTop = false;
|
|
||||||
this.tile = 'circle';
|
|
||||||
this.style = 'filled';
|
|
||||||
this.width = 1;
|
|
||||||
this.red = 0;
|
|
||||||
this.green = 0;
|
|
||||||
this.blue = 0;
|
|
||||||
this.alpha = 0.5;
|
|
||||||
this.created = Date.now();
|
|
||||||
|
|
||||||
Object.assign(this, settings);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getColor() {
|
getColor() {
|
||||||
|
|||||||
@@ -17,3 +17,9 @@ export const TILE_ORIENTATIONS = {
|
|||||||
POINTY,
|
POINTY,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const FILL = 'fill';
|
||||||
|
export const OUTLINE = 'outline';
|
||||||
|
export const DRAW_STYLES = {
|
||||||
|
FILL,
|
||||||
|
OUTLINE,
|
||||||
|
};
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ export default class DrawCircle {
|
|||||||
constructor(settings) {
|
constructor(settings) {
|
||||||
}
|
}
|
||||||
|
|
||||||
filled(context, scale, x, y, cell) {
|
fill(context, scale, x, y, cell) {
|
||||||
context.beginPath();
|
context.beginPath();
|
||||||
context.arc(x, y, scale * cell.scale, 0, 2*Math.PI, false);
|
context.arc(x, y, scale * cell.scale, 0, 2*Math.PI, false);
|
||||||
context.fillStyle = cell.getColor();
|
context.fillStyle = cell.getColor();
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ export default class DrawHexagon {
|
|||||||
context.stroke();
|
context.stroke();
|
||||||
}
|
}
|
||||||
|
|
||||||
filled(context, scale, x, y, cell) {
|
fill(context, scale, x, y, cell) {
|
||||||
scale = scale * cell.scale;
|
scale = scale * cell.scale;
|
||||||
let hexCornerX = cell.orientation === POINTY ? this.pointyTopCornerX : this.flatTopCornerX;
|
let hexCornerX = cell.orientation === POINTY ? this.pointyTopCornerX : this.flatTopCornerX;
|
||||||
let hexCornerY = cell.orientation === POINTY ? this.pointyTopCornerY : this.flatTopCornerY;
|
let hexCornerY = cell.orientation === POINTY ? this.pointyTopCornerY : this.flatTopCornerY;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export default class DrawSquare {
|
|||||||
this.diamondY = [0, -sqrt2, 0, sqrt2];
|
this.diamondY = [0, -sqrt2, 0, sqrt2];
|
||||||
}
|
}
|
||||||
|
|
||||||
filled(context, scale, x, y, cell) {
|
fill(context, scale, x, y, cell) {
|
||||||
scale = scale * cell.scale;
|
scale = scale * cell.scale;
|
||||||
let squareCornerX = cell.orientation === POINTY ? this.diamondX : this.squareX;
|
let squareCornerX = cell.orientation === POINTY ? this.diamondX : this.squareX;
|
||||||
let squareCornerY = cell.orientation === POINTY ? this.diamondY : this.squareY;
|
let squareCornerY = cell.orientation === POINTY ? this.diamondY : this.squareY;
|
||||||
|
|||||||
@@ -64,6 +64,12 @@ export function find (obj, predicate) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function flatten (list) {
|
||||||
|
if (Array.isArray(list)) {
|
||||||
|
return list.reduce((memo, element) => memo.concat(Array.isArray(element) ? flatten(element) : element), []);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function forEach (obj, iteratee) {
|
export function forEach (obj, iteratee) {
|
||||||
if (Array.isArray(obj)) {
|
if (Array.isArray(obj)) {
|
||||||
// native 'forEach' but the return below allows us to chain
|
// native 'forEach' but the return below allows us to chain
|
||||||
@@ -250,6 +256,7 @@ export let _ = {
|
|||||||
contains,
|
contains,
|
||||||
filter,
|
filter,
|
||||||
find,
|
find,
|
||||||
|
flatten,
|
||||||
forEach,
|
forEach,
|
||||||
groupBy,
|
groupBy,
|
||||||
identity,
|
identity,
|
||||||
|
|||||||
85
src/main.js
85
src/main.js
@@ -4,22 +4,34 @@ import {utils} from './tessellate.js';
|
|||||||
import {DrawCircle, DrawHexagon, DrawSquare} from './tessellate.js';
|
import {DrawCircle, DrawHexagon, DrawSquare} from './tessellate.js';
|
||||||
import {Cell} from './tessellate.js';
|
import {Cell} from './tessellate.js';
|
||||||
|
|
||||||
|
const DEFAULTS = {
|
||||||
|
board: Tessellate.BOARD_STYLES.HEX,
|
||||||
|
style: Tessellate.DRAW_STYLES.FILL,
|
||||||
|
orientation: Tessellate.TILE_ORIENTATIONS.FLAT,
|
||||||
|
tile: Tessellate.TILE_STYLES.HEX,
|
||||||
|
};
|
||||||
|
|
||||||
class Demo {
|
class Demo {
|
||||||
constructor() {
|
constructor() {
|
||||||
['onTap', 'draw'].map(method => this[method] = this[method].bind(this));
|
[
|
||||||
|
'onTap',
|
||||||
|
'createTile',
|
||||||
|
'drawTile',
|
||||||
|
'draw',
|
||||||
|
].map(method => this[method] = this[method].bind(this));
|
||||||
|
|
||||||
this.map = [];
|
this.map = {};
|
||||||
|
this.taps = [];
|
||||||
|
|
||||||
const queryStringObj = utils.getQueryStringObj();
|
const queryStringObj = utils.getQueryStringObj();
|
||||||
|
|
||||||
let tessellate = new Tessellate(Object.assign({
|
this.settings = Object.assign({}, DEFAULTS, queryStringObj);
|
||||||
|
|
||||||
|
this.tessellate = new Tessellate(Object.assign({
|
||||||
element: '#container',
|
element: '#container',
|
||||||
board: Tessellate.BOARD_STYLES.HEX,
|
|
||||||
tile: Tessellate.TILE_STYLES.HEX,
|
|
||||||
tap: this.onTap,
|
tap: this.onTap,
|
||||||
draw: this.draw,
|
draw: this.draw,
|
||||||
orientation: Tessellate.TILE_ORIENTATIONS.FLAT,
|
}, this.settings));
|
||||||
}, queryStringObj));
|
|
||||||
|
|
||||||
this.circle = new DrawCircle();
|
this.circle = new DrawCircle();
|
||||||
this.square = new DrawSquare();
|
this.square = new DrawSquare();
|
||||||
@@ -30,28 +42,59 @@ class Demo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onTap(tap) {
|
onTap(tap) {
|
||||||
let scale = utils.random(10, 50);
|
|
||||||
|
|
||||||
console.log(tap.tile.getPoint());
|
console.log(tap.tile.getPoint());
|
||||||
|
|
||||||
this.map.push(new Cell({
|
this.taps.push(this.createTile(
|
||||||
tile: this.tiles[utils.random(this.tiles.length-1)],
|
tap.tile.x,
|
||||||
style: this.styles[utils.random(this.styles.length-1)],
|
tap.tile.y,
|
||||||
x: tap.point.x,
|
|
||||||
y: tap.point.y,
|
utils.random(Tessellate.DRAW_STYLES),
|
||||||
scale,
|
utils.random(Tessellate.TILE_STYLES),
|
||||||
orientation: utils.random(1) ? Tessellate.TILE_ORIENTATIONS.FLAT : Tessellate.TILE_ORIENTATIONS.POINTY,
|
utils.random(Tessellate.TILE_ORIENTATIONS),
|
||||||
|
));
|
||||||
|
console.log(this.map[this.map.length - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
createTile(x, y, drawStyle, tileStyle, orientation) {
|
||||||
|
return new Cell({
|
||||||
|
x, y,
|
||||||
|
|
||||||
|
scale: utils.random(7, 9) / 10,
|
||||||
|
|
||||||
|
drawStyle,
|
||||||
|
tileStyle,
|
||||||
|
orientation,
|
||||||
|
|
||||||
red: utils.random(255),
|
red: utils.random(255),
|
||||||
green: utils.random(255),
|
green: utils.random(255),
|
||||||
blue: utils.random(255),
|
blue: utils.random(255),
|
||||||
alpha: utils.random(25,75)/100
|
alpha: utils.random(25,75)/100
|
||||||
}));
|
});
|
||||||
console.log(this.map[this.map.length - 1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
draw(context) {
|
drawTile({x, y, z}, context, scale) {
|
||||||
let scale = 1;
|
const key = `${ x },${ z != null ? z : y }`;
|
||||||
this.map.forEach(cell => this[cell.tile][cell.style](context, scale, cell.x, cell.y, cell));
|
|
||||||
|
this.map[key] = this.map[key] || this.createTile(x, y, this.settings.style, this.settings.tile, this.settings.orientation);
|
||||||
|
|
||||||
|
const tile = this.map[key];
|
||||||
|
const pixelPoint = this.tessellate.tileToPixel(x, y, z);
|
||||||
|
|
||||||
|
Tessellate.TILES[tile.tileStyle][tile.drawStyle](context, scale, pixelPoint.getX(), pixelPoint.getY(), tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
draw({context, scale, tilePoints}) {
|
||||||
|
tilePoints.forEach(tilePoint => this.drawTile(tilePoint, context, scale));
|
||||||
|
|
||||||
|
this.taps.forEach(cell => {
|
||||||
|
const pixelPoint = this.tessellate.tileToPixel(cell.x, cell.y);
|
||||||
|
Tessellate.TILES[cell.tileStyle][cell.drawStyle](context, scale, pixelPoint.getX(), pixelPoint.getY(), cell);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!this.notFirstTime) {
|
||||||
|
this.notFirstTime = true;
|
||||||
|
console.log(tilePoints);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,9 @@
|
|||||||
import * as utils from './utils';
|
import * as utils from './utils';
|
||||||
export {utils};
|
export {utils};
|
||||||
|
|
||||||
|
import * as funky from './funky';
|
||||||
|
export {funky};
|
||||||
|
|
||||||
import OnTap from './onTap.js';
|
import OnTap from './onTap.js';
|
||||||
import Point from './point.js';
|
import Point from './point.js';
|
||||||
import Sketch from './sketch.js';
|
import Sketch from './sketch.js';
|
||||||
@@ -25,6 +28,8 @@ import {
|
|||||||
BOARD_STYLES,
|
BOARD_STYLES,
|
||||||
FLAT, POINTY,
|
FLAT, POINTY,
|
||||||
TILE_ORIENTATIONS,
|
TILE_ORIENTATIONS,
|
||||||
|
FILL, OUTLINE,
|
||||||
|
DRAW_STYLES,
|
||||||
} from './consts.js';
|
} from './consts.js';
|
||||||
|
|
||||||
const TILES = {
|
const TILES = {
|
||||||
@@ -61,9 +66,18 @@ export default class Tessellate {
|
|||||||
static get TILE_STYLES() {return TILE_STYLES}
|
static get TILE_STYLES() {return TILE_STYLES}
|
||||||
static get BOARD_STYLES() {return BOARD_STYLES}
|
static get BOARD_STYLES() {return BOARD_STYLES}
|
||||||
static get TILE_ORIENTATIONS() {return TILE_ORIENTATIONS}
|
static get TILE_ORIENTATIONS() {return TILE_ORIENTATIONS}
|
||||||
|
static get DRAW_STYLES() {return DRAW_STYLES}
|
||||||
|
|
||||||
constructor(settings) {
|
constructor(settings) {
|
||||||
['seedTiles', 'tap', 'draw', 'drawMap', 'move', 'zoom'].map(method => {this[method] = this[method].bind(this)});
|
[
|
||||||
|
'tap',
|
||||||
|
'move',
|
||||||
|
'zoom',
|
||||||
|
'pixelToTile',
|
||||||
|
'tileToPixel',
|
||||||
|
'getTilePoints',
|
||||||
|
'draw']
|
||||||
|
.map(method => {this[method] = this[method].bind(this)});
|
||||||
|
|
||||||
this.settings = Object.assign(DEFAULTS, settings);
|
this.settings = Object.assign(DEFAULTS, settings);
|
||||||
this.settings.element = this.settings.element instanceof HTMLElement ? this.settings.element :
|
this.settings.element = this.settings.element instanceof HTMLElement ? this.settings.element :
|
||||||
@@ -98,21 +112,6 @@ export default class Tessellate {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
seedTiles() {
|
|
||||||
this.map[0] = [];
|
|
||||||
|
|
||||||
this.map[0][0] = new Cell({
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
orientation: this.settings.orientation,
|
|
||||||
red: 0,
|
|
||||||
green: 0,
|
|
||||||
blue: 0,
|
|
||||||
alpha: 75/100,
|
|
||||||
scale: 9/10,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
tap(event) {
|
tap(event) {
|
||||||
let point = new Point(event.offsetX, event.offsetY);
|
let point = new Point(event.offsetX, event.offsetY);
|
||||||
let tile = this.cartographer.pixelToTile(point);
|
let tile = this.cartographer.pixelToTile(point);
|
||||||
@@ -134,47 +133,41 @@ export default class Tessellate {
|
|||||||
this.cartographer.zoom(event);
|
this.cartographer.zoom(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
drawMap(context) {
|
pixelToTile(x, y) {
|
||||||
const scale = this.cartographer.getScale();
|
return this.cartographer.pixelToTile(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
const upperLeft = new Point(0, 0);
|
tileToPixel(x, y, z) {
|
||||||
const upperRight = new Point(context.canvas.width, 0);
|
return this.cartographer.tileToPixel(x, y, z);
|
||||||
const lowerLeft = new Point(0, context.canvas.height);
|
}
|
||||||
const lowerRight = new Point(context.canvas.width, context.canvas.height);
|
|
||||||
|
|
||||||
const tiles = this.cartographer.boundingBox(upperLeft, upperRight, lowerLeft, lowerRight);
|
getTilePoints({upperLeftX, upperLeftY, lowerRightX, lowerRightY}) {
|
||||||
|
const upperLeft = new Point(upperLeftX, upperLeftY);
|
||||||
|
const upperRight = new Point(lowerRightX, 0);
|
||||||
|
const lowerLeft = new Point(0, lowerRightY);
|
||||||
|
const lowerRight = new Point(lowerRightX, lowerRightY);
|
||||||
|
|
||||||
tiles.forEach(row => row.forEach(tile => {
|
return funky.flatten(this.cartographer.boundingBox(upperLeft, upperRight, lowerLeft, lowerRight));
|
||||||
const tilePoint = this.cartographer.tileToPixel(tile);
|
|
||||||
|
|
||||||
if (!this.map[tile.getX()]) this.map[tile.getX()] = [];
|
|
||||||
|
|
||||||
if (!this.map[tile.getX()][tile.getY()]) {
|
|
||||||
this.map[tile.getX()][tile.getY()] = new Cell({
|
|
||||||
x: tile.getX(),
|
|
||||||
y: tile.getY(),
|
|
||||||
orientation: this.settings.orientation,
|
|
||||||
red: utils.random(64, 192),
|
|
||||||
green: utils.random(64, 192),
|
|
||||||
blue: utils.random(64, 192),
|
|
||||||
alpha: 0.75,
|
|
||||||
scale: utils.random(7, 9) / 10
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
TILES[this.settings.tile].filled(context, scale, tilePoint.getX(), tilePoint.getY(), this.map[tile.getX()][tile.getY()]);
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
draw(context) {
|
draw(context) {
|
||||||
let canvas = context.canvas;
|
const canvas = context.canvas;
|
||||||
let width = canvas.width;
|
const width = canvas.width;
|
||||||
let height = canvas.height;
|
const height = canvas.height;
|
||||||
|
|
||||||
context.clearRect(0, 0, width, height);
|
context.clearRect(0, 0, width, height);
|
||||||
|
|
||||||
this.drawMap(context);
|
this.settings.draw({
|
||||||
|
context,
|
||||||
|
|
||||||
this.settings.draw(context);
|
scale: this.cartographer.getScale(),
|
||||||
|
|
||||||
|
tilePoints: this.getTilePoints({
|
||||||
|
upperLeftX: 0,
|
||||||
|
upperLeftY: 0,
|
||||||
|
lowerRightX: width,
|
||||||
|
lowerRightY: height
|
||||||
|
}),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,14 @@ export function hypotenuse(a, b) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function random(min, max) {
|
export function random(min, max) {
|
||||||
|
if (Array.isArray(min)) {
|
||||||
|
return min[random(min.length - 1)];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof min === 'object') {
|
||||||
|
return min[random(Object.keys(min))];
|
||||||
|
}
|
||||||
|
|
||||||
if (max == null) {
|
if (max == null) {
|
||||||
max = min;
|
max = min;
|
||||||
min = 0;
|
min = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user