Refactor Maps (#2)

This commit is contained in:
gavin
2018-07-17 21:28:17 +00:00
committed by Gitea
parent 0545c0a5d9
commit 57ada13a8d
13 changed files with 167 additions and 86 deletions

View File

@@ -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();

View File

@@ -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;

View File

@@ -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();

View File

@@ -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;

View File

@@ -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() {

View File

@@ -17,3 +17,9 @@ export const TILE_ORIENTATIONS = {
POINTY,
};
export const FILL = 'fill';
export const OUTLINE = 'outline';
export const DRAW_STYLES = {
FILL,
OUTLINE,
};

View File

@@ -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();

View File

@@ -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;

View File

@@ -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;

View File

@@ -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,

View File

@@ -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);
}
}
}

View File

@@ -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();
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);
const tiles = this.cartographer.boundingBox(upperLeft, upperRight, lowerLeft, lowerRight);
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
});
pixelToTile(x, y) {
return this.cartographer.pixelToTile(x, y);
}
TILES[this.settings.tile].filled(context, scale, tilePoint.getX(), tilePoint.getY(), this.map[tile.getX()][tile.getY()]);
}));
tileToPixel(x, y, z) {
return this.cartographer.tileToPixel(x, y, z);
}
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);
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
}),
});
}
}

View File

@@ -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;