Refactor Maps (#2)
This commit is contained in:
@@ -50,6 +50,8 @@ export default class CartographerFlatXY extends Cartographer {
|
||||
}
|
||||
|
||||
tileToPixel(square) {
|
||||
square = typeof square === 'Square' ? square : new Square(...arguments);
|
||||
|
||||
const x = square.getX() * this.minWidth();
|
||||
const y = square.getY() * this.minWidth();
|
||||
|
||||
@@ -57,6 +59,8 @@ export default class CartographerFlatXY extends Cartographer {
|
||||
}
|
||||
|
||||
pixelToTile(point) {
|
||||
point = typeof point === 'Point' ? point : new Point(x, y);
|
||||
|
||||
const pixelX = point.getX() - this.originX;
|
||||
const pixelY = this.originY - point.getY();
|
||||
|
||||
|
||||
@@ -50,6 +50,8 @@ export default class CartographerFlatXYZ extends Cartographer {
|
||||
}
|
||||
|
||||
tileToPixel(hex) {
|
||||
hex = typeof hex === 'Hex' ? hex : new Hex(...arguments);
|
||||
|
||||
const pixelX = this.scale * 3/2 * hex.getQ();
|
||||
const pixelY = this.scale * sqrt3 * (hex.getR() + (hex.getQ() / 2));
|
||||
|
||||
@@ -57,6 +59,8 @@ export default class CartographerFlatXYZ extends Cartographer {
|
||||
}
|
||||
|
||||
pixelToTile(point) {
|
||||
point = typeof point === 'Point' ? point : new Point(x, y);
|
||||
|
||||
const pixelX = point.getX() - this.originX;
|
||||
const pixelY = point.getY() - this.originY;
|
||||
|
||||
|
||||
@@ -50,6 +50,8 @@ export default class CartographerPointyXY extends Cartographer {
|
||||
}
|
||||
|
||||
tileToPixel(square) {
|
||||
square = typeof square === 'Square' ? square : new Square(...arguments);
|
||||
|
||||
const x = square.getX();
|
||||
const y = square.getY();
|
||||
|
||||
@@ -61,6 +63,8 @@ export default class CartographerPointyXY extends Cartographer {
|
||||
}
|
||||
|
||||
pixelToTile(point) {
|
||||
point = typeof point === 'Point' ? point : new Point(x, y);
|
||||
|
||||
const pixelX = point.getX() - this.originX;
|
||||
const pixelY = this.originY - point.getY();
|
||||
|
||||
|
||||
@@ -50,6 +50,8 @@ export default class CartographerPointyXYZ extends Cartographer {
|
||||
}
|
||||
|
||||
tileToPixel(hex) {
|
||||
hex = typeof hex === 'Hex' ? hex : new Hex(...arguments);
|
||||
|
||||
const pixelX = this.scale * sqrt3 * (hex.getQ() + (hex.getR() / 2));
|
||||
const pixelY = this.scale * 3/2 * hex.getR();
|
||||
|
||||
@@ -57,6 +59,8 @@ export default class CartographerPointyXYZ extends Cartographer {
|
||||
}
|
||||
|
||||
pixelToTile(point) {
|
||||
point = typeof point === 'Point' ? point : new Point(x, y);
|
||||
|
||||
const pixelX = point.getX() - this.originX;
|
||||
const pixelY = point.getY() - this.originY;
|
||||
|
||||
|
||||
36
src/cell.js
36
src/cell.js
@@ -1,23 +1,31 @@
|
||||
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 {
|
||||
constructor(settings) {
|
||||
this.getColor = this.getColor.bind(this);
|
||||
|
||||
this.x = 0;
|
||||
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);
|
||||
Object.assign(this, DEFAULTS, settings);
|
||||
}
|
||||
|
||||
getColor() {
|
||||
|
||||
@@ -17,3 +17,9 @@ export const TILE_ORIENTATIONS = {
|
||||
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) {
|
||||
}
|
||||
|
||||
filled(context, scale, x, y, cell) {
|
||||
fill(context, scale, x, y, cell) {
|
||||
context.beginPath();
|
||||
context.arc(x, y, scale * cell.scale, 0, 2*Math.PI, false);
|
||||
context.fillStyle = cell.getColor();
|
||||
|
||||
@@ -51,7 +51,7 @@ export default class DrawHexagon {
|
||||
context.stroke();
|
||||
}
|
||||
|
||||
filled(context, scale, x, y, cell) {
|
||||
fill(context, scale, x, y, cell) {
|
||||
scale = scale * cell.scale;
|
||||
let hexCornerX = cell.orientation === POINTY ? this.pointyTopCornerX : this.flatTopCornerX;
|
||||
let hexCornerY = cell.orientation === POINTY ? this.pointyTopCornerY : this.flatTopCornerY;
|
||||
|
||||
@@ -9,7 +9,7 @@ export default class DrawSquare {
|
||||
this.diamondY = [0, -sqrt2, 0, sqrt2];
|
||||
}
|
||||
|
||||
filled(context, scale, x, y, cell) {
|
||||
fill(context, scale, x, y, cell) {
|
||||
scale = scale * cell.scale;
|
||||
let squareCornerX = cell.orientation === POINTY ? this.diamondX : this.squareX;
|
||||
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) {
|
||||
if (Array.isArray(obj)) {
|
||||
// native 'forEach' but the return below allows us to chain
|
||||
@@ -250,6 +256,7 @@ export let _ = {
|
||||
contains,
|
||||
filter,
|
||||
find,
|
||||
flatten,
|
||||
forEach,
|
||||
groupBy,
|
||||
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 {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 {
|
||||
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();
|
||||
|
||||
let tessellate = new Tessellate(Object.assign({
|
||||
this.settings = Object.assign({}, DEFAULTS, queryStringObj);
|
||||
|
||||
this.tessellate = new Tessellate(Object.assign({
|
||||
element: '#container',
|
||||
board: Tessellate.BOARD_STYLES.HEX,
|
||||
tile: Tessellate.TILE_STYLES.HEX,
|
||||
tap: this.onTap,
|
||||
draw: this.draw,
|
||||
orientation: Tessellate.TILE_ORIENTATIONS.FLAT,
|
||||
}, queryStringObj));
|
||||
}, this.settings));
|
||||
|
||||
this.circle = new DrawCircle();
|
||||
this.square = new DrawSquare();
|
||||
@@ -30,28 +42,59 @@ class Demo {
|
||||
}
|
||||
|
||||
onTap(tap) {
|
||||
let scale = utils.random(10, 50);
|
||||
|
||||
console.log(tap.tile.getPoint());
|
||||
|
||||
this.map.push(new Cell({
|
||||
tile: this.tiles[utils.random(this.tiles.length-1)],
|
||||
style: this.styles[utils.random(this.styles.length-1)],
|
||||
x: tap.point.x,
|
||||
y: tap.point.y,
|
||||
scale,
|
||||
orientation: utils.random(1) ? Tessellate.TILE_ORIENTATIONS.FLAT : Tessellate.TILE_ORIENTATIONS.POINTY,
|
||||
this.taps.push(this.createTile(
|
||||
tap.tile.x,
|
||||
tap.tile.y,
|
||||
|
||||
utils.random(Tessellate.DRAW_STYLES),
|
||||
utils.random(Tessellate.TILE_STYLES),
|
||||
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),
|
||||
green: utils.random(255),
|
||||
blue: utils.random(255),
|
||||
alpha: utils.random(25,75)/100
|
||||
}));
|
||||
console.log(this.map[this.map.length - 1]);
|
||||
});
|
||||
}
|
||||
|
||||
draw(context) {
|
||||
let scale = 1;
|
||||
this.map.forEach(cell => this[cell.tile][cell.style](context, scale, cell.x, cell.y, cell));
|
||||
drawTile({x, y, z}, context, scale) {
|
||||
const key = `${ x },${ z != null ? z : y }`;
|
||||
|
||||
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';
|
||||
export {utils};
|
||||
|
||||
import * as funky from './funky';
|
||||
export {funky};
|
||||
|
||||
import OnTap from './onTap.js';
|
||||
import Point from './point.js';
|
||||
import Sketch from './sketch.js';
|
||||
@@ -25,6 +28,8 @@ import {
|
||||
BOARD_STYLES,
|
||||
FLAT, POINTY,
|
||||
TILE_ORIENTATIONS,
|
||||
FILL, OUTLINE,
|
||||
DRAW_STYLES,
|
||||
} from './consts.js';
|
||||
|
||||
const TILES = {
|
||||
@@ -61,9 +66,18 @@ export default class Tessellate {
|
||||
static get TILE_STYLES() {return TILE_STYLES}
|
||||
static get BOARD_STYLES() {return BOARD_STYLES}
|
||||
static get TILE_ORIENTATIONS() {return TILE_ORIENTATIONS}
|
||||
static get DRAW_STYLES() {return DRAW_STYLES}
|
||||
|
||||
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.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) {
|
||||
let point = new Point(event.offsetX, event.offsetY);
|
||||
let tile = this.cartographer.pixelToTile(point);
|
||||
@@ -134,47 +133,41 @@ export default class Tessellate {
|
||||
this.cartographer.zoom(event);
|
||||
}
|
||||
|
||||
drawMap(context) {
|
||||
const scale = this.cartographer.getScale();
|
||||
pixelToTile(x, y) {
|
||||
return this.cartographer.pixelToTile(x, y);
|
||||
}
|
||||
|
||||
const upperLeft = new Point(0, 0);
|
||||
const upperRight = new Point(context.canvas.width, 0);
|
||||
const lowerLeft = new Point(0, context.canvas.height);
|
||||
const lowerRight = new Point(context.canvas.width, context.canvas.height);
|
||||
tileToPixel(x, y, z) {
|
||||
return this.cartographer.tileToPixel(x, y, z);
|
||||
}
|
||||
|
||||
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 => {
|
||||
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()]);
|
||||
}));
|
||||
return funky.flatten(this.cartographer.boundingBox(upperLeft, upperRight, lowerLeft, lowerRight));
|
||||
}
|
||||
|
||||
draw(context) {
|
||||
let canvas = context.canvas;
|
||||
let width = canvas.width;
|
||||
let height = canvas.height;
|
||||
const canvas = context.canvas;
|
||||
const width = canvas.width;
|
||||
const height = canvas.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) {
|
||||
if (Array.isArray(min)) {
|
||||
return min[random(min.length - 1)];
|
||||
}
|
||||
|
||||
if (typeof min === 'object') {
|
||||
return min[random(Object.keys(min))];
|
||||
}
|
||||
|
||||
if (max == null) {
|
||||
max = min;
|
||||
min = 0;
|
||||
|
||||
Reference in New Issue
Block a user