Higher FPS! (#19)
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import Cartographer from './cartographer.js';
|
import Cartographer from './cartographer.js';
|
||||||
|
|
||||||
import {rangeInclusive, sqrt2} from './utils.js';
|
import {rangeInclusive, invSqrt2} from './utils.js';
|
||||||
|
|
||||||
import Square from './square.js';
|
import Square from './square.js';
|
||||||
import Point from './point.js';
|
import Point from './point.js';
|
||||||
@@ -40,11 +40,11 @@ export default class CartographerFlatXY extends Cartographer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
maxWidth() {
|
maxWidth() {
|
||||||
return this.minWidth() * sqrt2;
|
return this.scale * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
minWidth() {
|
minWidth() {
|
||||||
return this.scale * 2;
|
return this.maxWidth() * invSqrt2;
|
||||||
}
|
}
|
||||||
|
|
||||||
horizontalOverhang() {
|
horizontalOverhang() {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Cartographer from './cartographer.js';
|
import Cartographer from './cartographer.js';
|
||||||
|
|
||||||
import {rangeInclusive, sqrt2} from './utils.js';
|
import {rangeInclusive, invSqrt2, sqrt2} from './utils.js';
|
||||||
|
|
||||||
import Square from './square.js';
|
import Square from './square.js';
|
||||||
import Point from './point.js';
|
import Point from './point.js';
|
||||||
@@ -40,11 +40,11 @@ export default class CartographerPointyXY extends Cartographer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
maxWidth() {
|
maxWidth() {
|
||||||
return this.minWidth() * sqrt2;
|
return this.scale * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
minWidth() {
|
minWidth() {
|
||||||
return this.scale * 2;
|
return this.maxWidth() * invSqrt2;
|
||||||
}
|
}
|
||||||
|
|
||||||
horizontalOverhang() {
|
horizontalOverhang() {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import {FLAT, POINTY} from './consts.js';
|
import {FLAT, POINTY} from './consts.js';
|
||||||
import {getColor, range, toFixed} from './utils.js';
|
import {getColor, range, toFixed, quickCanvas} from './utils.js';
|
||||||
|
|
||||||
export default class DrawHexagon {
|
export default class DrawHexagon {
|
||||||
constructor(settings) {
|
constructor(settings) {
|
||||||
@@ -50,6 +50,34 @@ export default class DrawHexagon {
|
|||||||
context.stroke();
|
context.stroke();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fill(context, scale, x, y, cell) {
|
||||||
|
// if (cell.cacheScale !== scale) {
|
||||||
|
// cell.cacheScale = scale;
|
||||||
|
// scale = scale * cell.scale;
|
||||||
|
//
|
||||||
|
// cell.cacheHalfWidth = scale;
|
||||||
|
// cell.cacheHalfHeight = scale;
|
||||||
|
//
|
||||||
|
// cell.cacheHex = quickCanvas((context, height, width) => {
|
||||||
|
// const hexCornerX = cell.orientation === POINTY ? this.pointyTopCornerX : this.flatTopCornerX;
|
||||||
|
// const hexCornerY = cell.orientation === POINTY ? this.pointyTopCornerY : this.flatTopCornerY;
|
||||||
|
//
|
||||||
|
// context.beginPath();
|
||||||
|
// context.moveTo(scale + scale * hexCornerX[0], scale + scale * hexCornerY[0]);
|
||||||
|
// context.lineTo(scale + scale * hexCornerX[1], scale + scale * hexCornerY[1]);
|
||||||
|
// context.lineTo(scale + scale * hexCornerX[2], scale + scale * hexCornerY[2]);
|
||||||
|
// context.lineTo(scale + scale * hexCornerX[3], scale + scale * hexCornerY[3]);
|
||||||
|
// context.lineTo(scale + scale * hexCornerX[4], scale + scale * hexCornerY[4]);
|
||||||
|
// context.lineTo(scale + scale * hexCornerX[5], scale + scale * hexCornerY[5]);
|
||||||
|
//
|
||||||
|
// context.fillStyle = getColor(cell.color);
|
||||||
|
// context.fill();
|
||||||
|
// }, scale * 2);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// context.drawImage(cell.cacheHex, x - cell.cacheHalfWidth, y - cell.cacheHalfHeight);
|
||||||
|
// }
|
||||||
|
|
||||||
fill(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;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import {getColor, range, sqrt2, toFixed} from './utils.js';
|
import {getColor, quickCanvas, range, invSqrt2, toFixed} from './utils.js';
|
||||||
import {HEX, SQUARE, FLAT, POINTY} from './consts.js';
|
import {HEX, SQUARE, FLAT, POINTY} from './consts.js';
|
||||||
|
|
||||||
const DEFAULTS = {
|
const DEFAULTS = {
|
||||||
@@ -52,7 +52,7 @@ const DEFAULTS = {
|
|||||||
green: 0,
|
green: 0,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
distance: 0.4,
|
distance: 0.6,
|
||||||
},
|
},
|
||||||
|
|
||||||
sides: 6,
|
sides: 6,
|
||||||
@@ -61,8 +61,8 @@ const DEFAULTS = {
|
|||||||
|
|
||||||
function generateFlatSquarePips () {
|
function generateFlatSquarePips () {
|
||||||
const pips = [];
|
const pips = [];
|
||||||
const pipX = [0, 1, 1, -1, -1, 1, -1, 0, 0];
|
const pipX = [0, invSqrt2, invSqrt2, -invSqrt2, -invSqrt2, invSqrt2, -invSqrt2, 0, 0];
|
||||||
const pipY = [0, 1, -1, -1, 1, 0, 0, -1, 1];
|
const pipY = [0, invSqrt2, -invSqrt2, -invSqrt2, invSqrt2, 0, 0, -invSqrt2, invSqrt2];
|
||||||
|
|
||||||
const getVertex = n => [pipX[n], pipY[n]];
|
const getVertex = n => [pipX[n], pipY[n]];
|
||||||
|
|
||||||
@@ -81,8 +81,8 @@ function generateFlatSquarePips () {
|
|||||||
|
|
||||||
function generatePointySquarePips () {
|
function generatePointySquarePips () {
|
||||||
const pips = [];
|
const pips = [];
|
||||||
const pipX = [0, sqrt2, 0, -sqrt2, 0, sqrt2 / 2, -sqrt2 / 2, sqrt2 / 2, -sqrt2 / 2];
|
const pipX = [0, 1, 0, -1, 0, 0.5, -0.5, 0.5, -0.5];
|
||||||
const pipY = [0, 0, -sqrt2, 0, sqrt2, -sqrt2 / 2, sqrt2 / 2, sqrt2 / 2, -sqrt2 / 2];
|
const pipY = [0, 0, -1, 0, 1, -0.5, 0.5, 0.5, -0.5];
|
||||||
|
|
||||||
const getVertex = n => [pipX[n], pipY[n]];
|
const getVertex = n => [pipX[n], pipY[n]];
|
||||||
|
|
||||||
@@ -144,6 +144,9 @@ export default class DrawShapes {
|
|||||||
this.slicesX = range(slices).map(slice => toFixed(Math.cos(((slice / slices) * sides) * (2 * Math.PI) / sides)));
|
this.slicesX = range(slices).map(slice => toFixed(Math.cos(((slice / slices) * sides) * (2 * Math.PI) / sides)));
|
||||||
this.slicesY = range(slices).map(slice => toFixed(Math.sin(((slice / slices) * sides) * (2 * Math.PI) / sides)));
|
this.slicesY = range(slices).map(slice => toFixed(Math.sin(((slice / slices) * sides) * (2 * Math.PI) / sides)));
|
||||||
|
|
||||||
|
this.pipCache = {};
|
||||||
|
this.mineCache = {};
|
||||||
|
|
||||||
this.pipVertices = {
|
this.pipVertices = {
|
||||||
[HEX]: {
|
[HEX]: {
|
||||||
[FLAT]: generateFlatHexPips(this.slicesX, this.slicesY),
|
[FLAT]: generateFlatHexPips(this.slicesX, this.slicesY),
|
||||||
@@ -174,41 +177,75 @@ export default class DrawShapes {
|
|||||||
context.arc(x, y, pipRadius, 0, Math.PI*2, true);
|
context.arc(x, y, pipRadius, 0, Math.PI*2, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
pips (context, scale, x, y, cell, pip = this.settings.pip) {
|
setPipCache (pips, scale) {
|
||||||
|
const pipDistance = scale * this.settings.pip.distance; //* cell.scale;
|
||||||
|
const pipBodyRadius = scale * this.settings.pip.body.scale;
|
||||||
|
const pipBorderRadius = scale * this.settings.pip.border.scale;
|
||||||
|
|
||||||
|
this.pipCache.scale = scale;
|
||||||
|
this.pipCache.height = (Math.ceil(pipBorderRadius) + 1) * 2;
|
||||||
|
this.pipCache.width = this.pipCache.height;
|
||||||
|
|
||||||
|
const pipCenter = this.pipCache.height / 2;
|
||||||
|
|
||||||
|
this.pipCache.pip = quickCanvas((context, height, width) => {
|
||||||
|
context.beginPath();
|
||||||
|
context.arc(pipCenter, pipCenter, pipBorderRadius, 0, Math.PI*2, true);
|
||||||
|
context.closePath();
|
||||||
|
context.fillStyle = getColor(this.settings.pip.border.color);
|
||||||
|
context.fill();
|
||||||
|
|
||||||
|
context.beginPath();
|
||||||
|
context.arc(pipCenter, pipCenter, pipBodyRadius, 0, Math.PI*2, true);
|
||||||
|
context.closePath();
|
||||||
|
context.fillStyle = getColor(this.settings.pip.body.color);
|
||||||
|
context.fill();
|
||||||
|
}, this.pipCache.height, this.pipCache.width);
|
||||||
|
|
||||||
|
const pipsCenter = scale - pipCenter;
|
||||||
|
|
||||||
|
this.pipCache.pips = pips.map(vertices => {
|
||||||
|
return quickCanvas(context => {
|
||||||
|
vertices.forEach(([pipX, pipY]) => context.drawImage(this.pipCache.pip, pipsCenter + (pipDistance * pipX), pipsCenter + (pipDistance * pipY)));
|
||||||
|
}, scale * 2);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pips (context, scale, x, y, cell) {
|
||||||
const {tileStyle, orientation, pips} = cell;
|
const {tileStyle, orientation, pips} = cell;
|
||||||
|
|
||||||
if (this.pipVertices[tileStyle]
|
if (this.pipVertices[tileStyle]
|
||||||
&& this.pipVertices[tileStyle][orientation]
|
&& this.pipVertices[tileStyle][orientation]
|
||||||
&& this.pipVertices[tileStyle][orientation][pips]) {
|
&& this.pipVertices[tileStyle][orientation][pips]) {
|
||||||
const pipBodyRadius = scale * pip.body.scale;
|
|
||||||
const pipBorderRadius = scale * pip.border.scale;
|
|
||||||
const pipDistance = scale * pip.distance;
|
|
||||||
|
|
||||||
context.beginPath();
|
if (scale !== this.pipCache.scale) {
|
||||||
|
this.setPipCache(this.pipVertices[tileStyle][orientation], scale);
|
||||||
|
}
|
||||||
|
|
||||||
this.pipVertices[tileStyle][orientation][pips]
|
const scaleWidth = (scale * 2) * cell.scale;
|
||||||
.forEach(([pipX, pipY]) => this.pip(context, scale, x,y, pipX, pipY, pipBorderRadius, pipDistance));
|
const scaleHeight = (scale * 2) * cell.scale;
|
||||||
|
|
||||||
context.closePath();
|
context.drawImage(this.pipCache.pips[pips], x - (scaleWidth / 2), y - (scaleHeight / 2), scaleWidth, scaleHeight);
|
||||||
context.fillStyle = getColor(pip.border.color);
|
|
||||||
context.fill();
|
|
||||||
|
|
||||||
context.beginPath();
|
|
||||||
|
|
||||||
this.pipVertices[tileStyle][orientation][pips]
|
|
||||||
.forEach(([pipX, pipY]) => this.pip(context, scale, x,y, pipX, pipY, pipBodyRadius, pipDistance));
|
|
||||||
|
|
||||||
context.closePath();
|
|
||||||
context.fillStyle = getColor(pip.body.color);
|
|
||||||
context.fill();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mine (context, scale, x, y, mine = this.settings.mine) {
|
mine (context, scale, x, y, mine = this.settings.mine) {
|
||||||
this._mine(context, scale, x, y, mine.border);
|
if (scale !== this.mineCache.scale) {
|
||||||
this._horns(context, scale, x, y, mine.border.horns, mine.border.color);
|
this.setMineCache(scale);
|
||||||
this._mine(context, scale, x, y, mine.body);
|
}
|
||||||
this._horns(context, scale, x, y, mine.body.horns, mine.body.color);
|
|
||||||
|
context.drawImage(this.mineCache.mine, x - scale, y - scale, scale * 2, scale * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
setMineCache (scale) {
|
||||||
|
this.mineCache.scale = scale;
|
||||||
|
|
||||||
|
this.mineCache.mine = quickCanvas(context => {
|
||||||
|
this._mine(context, scale, scale, scale, this.settings.mine.border);
|
||||||
|
this._horns(context, scale, scale, scale, this.settings.mine.border.horns, this.settings.mine.border.color);
|
||||||
|
this._mine(context, scale, scale, scale, this.settings.mine.body);
|
||||||
|
this._horns(context, scale, scale, scale, this.settings.mine.body.horns, this.settings.mine.body.color);
|
||||||
|
}, scale * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
_mine (context, scale, x, y, mine) {
|
_mine (context, scale, x, y, mine) {
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import {getColor, sqrt2} from './utils.js';
|
import {getColor, invSqrt2, sqrt2} from './utils.js';
|
||||||
import {FLAT, POINTY} from './consts.js';
|
import {FLAT, POINTY} from './consts.js';
|
||||||
|
|
||||||
export default class DrawSquare {
|
export default class DrawSquare {
|
||||||
constructor(settings) {
|
constructor(settings) {
|
||||||
this.settings = Object.assign({}, settings);
|
this.settings = Object.assign({}, settings);
|
||||||
|
|
||||||
this.squareX = [1, 1, -1, -1];
|
this.squareX = [invSqrt2, invSqrt2, -invSqrt2, -invSqrt2];
|
||||||
this.squareY = [1, -1, -1, 1];
|
this.squareY = [invSqrt2, -invSqrt2, -invSqrt2, invSqrt2];
|
||||||
this.diamondX = [sqrt2, 0, -sqrt2, 0, sqrt2 / 2, -sqrt2 / 2];
|
this.diamondX = [1, 0, -1, 0, 0.5, -0.5];
|
||||||
this.diamondY = [0, -sqrt2, 0, sqrt2, -sqrt2 / 2, sqrt2 / 2];
|
this.diamondY = [0, -1, 0, 1, -0.5, 0.5];
|
||||||
}
|
}
|
||||||
|
|
||||||
fill(context, scale, x, y, cell) {
|
fill(context, scale, x, y, cell) {
|
||||||
|
|||||||
49
src/main.js
49
src/main.js
@@ -27,7 +27,7 @@ class Demo {
|
|||||||
constructor() {
|
constructor() {
|
||||||
[
|
[
|
||||||
'setOriginTile',
|
'setOriginTile',
|
||||||
'setFadeToGray',
|
'setupKeydown',
|
||||||
'tap',
|
'tap',
|
||||||
'pressStart',
|
'pressStart',
|
||||||
'press',
|
'press',
|
||||||
@@ -50,7 +50,7 @@ class Demo {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.setOriginTile();
|
this.setOriginTile();
|
||||||
this.setFadeToGray();
|
this.setupKeydown();
|
||||||
|
|
||||||
this.tessellate = new Tessellate(Object.assign({
|
this.tessellate = new Tessellate(Object.assign({
|
||||||
element: '#container',
|
element: '#container',
|
||||||
@@ -99,10 +99,27 @@ class Demo {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
setFadeToGray () {
|
setupKeydown () {
|
||||||
|
this.pipDefault = null;
|
||||||
|
|
||||||
window.addEventListener('keydown', event => {
|
window.addEventListener('keydown', event => {
|
||||||
if (!event.repeat && event.key === 'Enter') {
|
if (!event.repeat) {
|
||||||
this.gray = this.gray ? null : Date.now();
|
if (event.key === 'Enter') {
|
||||||
|
this.gray = this.gray ? null : Date.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.key === `~`) {
|
||||||
|
this.mined = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.key === '`') {
|
||||||
|
this.pipDefault = '*';
|
||||||
|
}
|
||||||
|
|
||||||
|
const num = parseInt(event.key);
|
||||||
|
if (num >= 0 && num <= 9) {
|
||||||
|
this.pipDefault = num;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -221,9 +238,25 @@ class Demo {
|
|||||||
|
|
||||||
Tessellate.TILES[tile.tileStyle][tile.drawStyle](context, scale, pixelPoint.getX(), pixelPoint.getY(), tile);
|
Tessellate.TILES[tile.tileStyle][tile.drawStyle](context, scale, pixelPoint.getX(), pixelPoint.getY(), tile);
|
||||||
|
|
||||||
if (tile.pips) {
|
if (this.mined) {
|
||||||
this.counts[1] += tile.pips;
|
this.counts[2] += 1;
|
||||||
Tessellate.Shapes.pips(context, scale, pixelPoint.getX(), pixelPoint.getY(), tile);
|
Tessellate.Shapes.mine(context, scale, pixelPoint.getX(), pixelPoint.getY());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!tile.pips && this.pipDefault !== null) {
|
||||||
|
if (this.pipDefault === '*') {
|
||||||
|
const pipMax = this.settings.tile === Tessellate.TILE_STYLES.HEX ? 7 : 9;
|
||||||
|
tile.pips = Tessellate.utils.random(1, pipMax);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
tile = Tessellate.utils.extend(tile, {pips: this.pipDefault});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tile.pips) {
|
||||||
|
this.counts[1] += tile.pips;
|
||||||
|
Tessellate.Shapes.pips(context, scale, pixelPoint.getX(), pixelPoint.getY(), tile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
13
src/utils.js
13
src/utils.js
@@ -9,6 +9,9 @@ export const sqrt2 = Math.sqrt(2);
|
|||||||
// (2*S gives long width)
|
// (2*S gives long width)
|
||||||
export const sqrt3 = Math.sqrt(3);
|
export const sqrt3 = Math.sqrt(3);
|
||||||
|
|
||||||
|
// leg factor of isoscelese right triangle with unit hypotenuse
|
||||||
|
export const invSqrt2 = 1 / sqrt2
|
||||||
|
|
||||||
export function clone(obj) {
|
export function clone(obj) {
|
||||||
return JSON.parse(JSON.stringify(obj));
|
return JSON.parse(JSON.stringify(obj));
|
||||||
}
|
}
|
||||||
@@ -141,3 +144,13 @@ export function extend (obj, ...sources) {
|
|||||||
|
|
||||||
return extended;
|
return extended;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function quickCanvas (draw, height, width = height) {
|
||||||
|
const canvas = document.createElement('canvas');
|
||||||
|
canvas.height = height;
|
||||||
|
canvas.width = width;
|
||||||
|
|
||||||
|
draw(canvas.getContext('2d'), canvas.height, canvas.width);
|
||||||
|
|
||||||
|
return canvas;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user