Files
Tessellate/src/main.js

318 lines
7.0 KiB
JavaScript

import FPS from './fps.js';
const ONE_SECOND = 1000;
const PRESS_RIPPLE = ONE_SECOND / 3;
const DEFAULTS = {
board: Tessellate.BOARD_STYLES.HEX,
style: Tessellate.DRAW_STYLES.FILL,
orientation: Tessellate.ORIENTATION_STYLES.FLAT,
tile: Tessellate.TILE_STYLES.HEX,
};
const keyTemplate = ({x, y, z}) => `${ x },${ z != null ? z : y }`;
const pressRipple = function() {
const sinStart = 2 * Math.PI;
const halfPi = Math.PI / 2;
return pressFactor => Math.sin(sinStart + (pressFactor * halfPi)) + 1;
}();
const pressFade = function() {
const halfPi = Math.PI / 2;
return pressFactor => Math.sin(Math.PI + (pressFactor * halfPi)) + 1;
}();
class Demo {
constructor() {
[
'setOriginTile',
'setupKeydown',
'tap',
'pressStart',
'press',
'createTile',
'drawTile',
'draw',
].map(method => this[method] = this[method].bind(this));
const queryStringObj = Tessellate.utils.getQueryStringObj();
this.settings = Object.assign({}, DEFAULTS, queryStringObj);
this.map = {};
this.taps = [];
this.mines = {};
this.ripples = [];
this.fps = new FPS({
element: document.querySelector('#fps'),
});
this.setOriginTile();
this.setupKeydown();
this.tessellate = new Tessellate(Object.assign({
element: '#container',
tap: this.tap,
pressStart: this.pressStart,
press: this.press,
draw: this.draw,
}, this.settings));
}
setOriginTile() {
this.map['0,0'] = new Tessellate.Cell({
x: 0,
y: 0,
scale: 1,
drawStyle: Tessellate.DRAW_STYLES.FILL,
tileStyle: this.settings.tile,
orientation: this.settings.orientation,
color: {
red: 255,
green: 255,
blue: 0,
alpha: 1,
}
});
Tessellate.utils.rangeInclusive(0, 5)
.map(interval => interval ? interval * 0.2 : 0.01)
.forEach(interval => {
this.taps.push(new Tessellate.Cell({
x: 0,
y: 0,
scale: interval,
drawStyle: Tessellate.DRAW_STYLES.OUTLINE,
tileStyle: this.settings.tile,
orientation: this.settings.orientation,
color: {
red: 0,
green: 0,
blue: 0,
alpha: 1,
},
}));
});
}
setupKeydown () {
this.pipDefault = null;
window.addEventListener('keydown', event => {
if (!event.repeat) {
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;
}
}
});
}
tap(tap) {
const key = keyTemplate(tap.mapTile);
const pipMax = this.settings.tile === Tessellate.TILE_STYLES.HEX ? 7 : 9;
if (this.map[key]) {
this.map[key].pips = Tessellate.utils.random(1, pipMax);
console.log(tap.mapTile.getPoint());
}
else {
console.log('ERROR - no tile', key);
}
}
pressStart(tap) {
this.ripples.push({
timestamp: tap.event.timeStampUTC,
cell: this.createTile({
x: tap.tile.x,
y: tap.tile.y,
scale: 1.0,
drawStyle: Tessellate.DRAW_STYLES.FILL,
tileStyle: Tessellate.TILE_STYLES.CIRCLE,
orientation: Tessellate.ORIENTATION_STYLES.FLAT,
color: {
red: 128,
green: 128,
blue: 128,
alpha: 0.5,
},
})
});
if (tap.event.mobile) {
this.togglemine(tap.mapTile)
}
}
press(tap) {
if (!tap.event.mobile) {
this.togglemine(tap.mapTile)
}
}
togglemine(tile) {
const key = keyTemplate(tile);
if (this.mines[key]) {
delete this.mines[key];
}
else {
this.mines[key] = tile;
}
}
createTile({x, y,
drawStyle, tileStyle, orientation,
scale = Tessellate.utils.random(7, 9) / 10,
color = {
red: Tessellate.utils.random(255),
green: Tessellate.utils.random(255),
blue: Tessellate.utils.random(255),
alpha: Tessellate.utils.random(25, 75) / 100,
}
}) {
return new Tessellate.Cell({
x, y,
scale,
drawStyle,
tileStyle,
orientation,
color,
});
}
fadeToGray (tile, fadeFactor) {
tile.color.grayscale = tile.color.grayscale || Tessellate.utils.grayscale(tile.color);
const grayscale = tile.color.grayscale;
const color = {
red: parseInt(tile.color.red - ((tile.color.red - grayscale) * fadeFactor)),
green: parseInt(tile.color.green - ((tile.color.green - grayscale) * fadeFactor)),
blue: parseInt(tile.color.blue - ((tile.color.blue - grayscale) * fadeFactor)),
};
tile = Tessellate.utils.extend(tile, {color});
return tile;
}
drawTile(pointGroup, context, scale) {
const pixelX = pointGroup.pixelPoint.getX();
const pixelY = pointGroup.pixelPoint.getY();
this.counts[0] += 1;
const key = keyTemplate(pointGroup.mapPoint);
this.map[key] = this.map[key] || this.createTile({
x: pointGroup.mapPoint.x,
y: pointGroup.mapPoint.y,
drawStyle: this.settings.style,
tileStyle: this.settings.tile,
orientation: this.settings.orientation,
});
let tile = this.map[key];
const fadeFactor = this.gray ? Math.min((Date.now() - this.gray) / 5000, 1) : null;
tile = this.gray ? this.fadeToGray(tile, fadeFactor) : tile;
Tessellate.TILES[tile.tileStyle][tile.drawStyle](context, scale, pixelX, pixelY, tile);
if (this.mined || this.mines[key]) {
this.counts[2] += 1;
Tessellate.Shapes.mine(context, scale, pixelX, pixelY);
}
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, pixelX, pixelY, tile);
}
}
}
draw({context, height, width, scale, pointGroups, now, lastNow}) {
this.counts = [
0, // tiles
0, // pips
0, // mines
];
Tessellate.Shapes.background(context, height, width, {
red: 64,
green: 32,
blue: 128,
});
pointGroups
.filter(pointGroup => pointGroup.mapPoint)
.forEach(pointGroup => this.drawTile(pointGroup, context, scale));
this.ripples.forEach(({timestamp, cell}) => {
const pressFactor = Math.min((now - timestamp) / PRESS_RIPPLE, 1);
Object.assign(cell, {scale: pressRipple(pressFactor)});
Object.assign(cell.color, {alpha: pressFade(pressFactor)});
const pixelPoint = this.tessellate.tileToPixel(cell);
Tessellate.TILES[cell.tileStyle][cell.drawStyle](context, scale, pixelPoint.getX(), pixelPoint.getY(), cell);
});
this.ripples = this.ripples.filter(ripple => (ripple.timestamp + PRESS_RIPPLE) > now);
this.taps.forEach(cell => {
const pixelPoint = this.tessellate.tileToPixel(cell);
Tessellate.TILES[cell.tileStyle][cell.drawStyle](context, scale, pixelPoint.getX(), pixelPoint.getY(), cell);
});
// Tessellate.funky.forEach(this.mines, cell => {
// this.counts[2] += 1;
// const pixelPoint = this.tessellate.tileToPixel(cell);
// Tessellate.Shapes.mine(context, scale, pixelPoint.getX(), pixelPoint.getY());
// });
this.fps.frame(now, lastNow, this.counts);
}
}
let demo = new Demo();