wrapping for flat hex tiles almost working

This commit is contained in:
Gavin McDonald
2018-12-28 16:31:55 -05:00
parent e631691289
commit c77f179ad3
5 changed files with 132 additions and 45 deletions

View File

@@ -30,8 +30,8 @@ export default class CartographerFlatXY extends Cartographer {
'tileToPixel', 'tileToPixel',
'_pixelToTile', '_pixelToTile',
'teleport', 'teleport',
'inBounds', 'inBounds',
'enforceBoundries', 'enforceBoundries',
'boundingBox', 'boundingBox',

View File

@@ -1,10 +1,13 @@
import Cartographer from './cartographer.js'; import Cartographer from './cartographer.js';
import * as funky from './funky';
import {rangeInclusive, sqrt3} from './utils.js'; import {rangeInclusive, sqrt3} from './utils.js';
import Hex from './hex.js'; import Hex from './hex.js';
import Point from './point.js'; import Point from './point.js';
const tilePointToHex = ({tilePoint, pixelPoint}) => ({tilePoint: new Hex(tilePoint), pixelPoint});
export default class CartographerFlatXYZ extends Cartographer { export default class CartographerFlatXYZ extends Cartographer {
constructor(settings) { constructor(settings) {
super(settings); super(settings);
@@ -26,9 +29,11 @@ export default class CartographerFlatXYZ extends Cartographer {
'calculateVerticalScale', 'calculateVerticalScale',
'tileToPixel', 'tileToPixel',
'pixelToTile', '_pixelToTile',
'teleport',
'inBounds', 'inBounds',
'enforceBoundries',
'boundingBox', 'boundingBox',
].map(method => this[method] = this[method].bind(this)); ].map(method => this[method] = this[method].bind(this));
} }
@@ -82,7 +87,7 @@ export default class CartographerFlatXYZ extends Cartographer {
return new Point(pixelX + this.originX, pixelY + this.originY); return new Point(pixelX + this.originX, pixelY + this.originY);
} }
pixelToTile(point) { _pixelToTile(point) {
point = point instanceof Point ? point : new Point(...arguments); point = point instanceof Point ? point : new Point(...arguments);
const pixelX = point.getX() - this.originX; const pixelX = point.getX() - this.originX;
@@ -94,45 +99,94 @@ export default class CartographerFlatXYZ extends Cartographer {
return new Hex(q, r); return new Hex(q, r);
} }
inBounds (q, r, s = -q - r) { teleport (hex) {
hex = hex instanceof Hex ? hex : new Hex(hex);
let {col, row} = hex.getOffsetHex();
if (this.radius) { if (this.radius) {
if (this.negativeTiles) {
return Math.max(Math.abs(q), Math.abs(r), Math.abs(s)) <= Math.floor(this.radius);
} }
else { else {
return Math.max(Math.abs(q - this.radius), Math.abs(r + this.radius), Math.abs(s)) <= this.radius; const halfWidth = Math.floor(this.width / 2);
const halfHeight = Math.floor(this.height / 2);
if (this.negativeTiles) {
col += halfWidth;
row += halfHeight;
}
col = col % this.width;
row = row % this.height;
col = col < 0 ? col + this.width : col;
row = row < 0 ? row + this.height : row;
if (this.negativeTiles) {
col -= halfWidth;
row -= halfHeight;
}
return Hex.offsetToCube(col, row);
}
}
inBounds ({x, y, z = -x - y}) {
if (this.radius) {
if (this.negativeTiles) {
return Math.max(Math.abs(x), Math.abs(y), Math.abs(z)) <= Math.floor(this.radius);
}
else {
return Math.max(Math.abs(x - this.radius), Math.abs(y + this.radius), Math.abs(z)) <= this.radius;
} }
} }
else if (this.width || this.height) { else if (this.width || this.height) {
if (this.negativeTiles) { if (this.negativeTiles) {
return (!this.width || (Math.abs(q) < this.width / 2)) return (!this.width || (Math.abs(x) < this.width / 2))
&& (!this.height || (Math.abs(-r - Math.floor(q / 2)) < (this.height / 2))); && (!this.height || (Math.abs(-y - Math.floor(x / 2)) < (this.height / 2)));
} }
else { else {
return (!this.width || (q >= 0 && q < this.width)) return (!this.width || (x >= 0 && x < this.width))
&& (!this.height || (r <= (Math.floor(q / 2) * -1) && (-r - Math.floor(q / 2)) < this.height)); && (!this.height || (y <= (Math.floor(x / 2) * -1) && (-y - Math.floor(x / 2)) < this.height));
} }
} }
} }
enforceBoundries ({tilePoint, pixelPoint}) {
return this.wrap ? ({tilePoint: this.teleport(tilePoint), pixelPoint}) :
this.inBounds(tilePoint) ? ({tilePoint, pixelPoint}) :
null;
}
boundingBox(upperLeftPoint, upperRightPoint, lowerLeftPoint, lowerRightPoint) { boundingBox(upperLeftPoint, upperRightPoint, lowerLeftPoint, lowerRightPoint) {
const upperLeftTile = this.pixelToTile(upperLeftPoint); const upperLeftTile = this._pixelToTile(upperLeftPoint);
const lowerLeftTile = this.pixelToTile(lowerLeftPoint); const lowerLeftTile = this._pixelToTile(lowerLeftPoint);
const lowerRightTile = this.pixelToTile(lowerRightPoint); const lowerRightTile = this._pixelToTile(lowerRightPoint);
const upperRightTile = this.pixelToTile(upperRightPoint); const upperRightTile = this._pixelToTile(upperRightPoint);
const columns = rangeInclusive(upperLeftTile.getQ() - 1, upperRightTile.getQ() + 1); const columns = rangeInclusive(upperLeftTile.getQ() - 1, upperRightTile.getQ() + 1);
const height = lowerRightTile.getR() - upperRightTile.getR(); const height = lowerRightTile.getR() - upperRightTile.getR();
return columns.map((q, index) => {
const makeAPointPair = tilePoint => ({tilePoint, pixelPoint: this.tileToPixel(tilePoint)});
const processRow = (q, index) => {
const top = upperLeftTile.getR() - Math.floor(index / 2); const top = upperLeftTile.getR() - Math.floor(index / 2);
const bottom = top + height; const bottom = top + height;
const rows = rangeInclusive(top, bottom + 1); const rows = rangeInclusive(top, bottom + 1);
return rows.map(r => ({q, r})) const makeAPoint = r => ({x: q, y: r, z: -q - r});
.reduce((flat, list) => flat.concat(list), [])
.filter(({q, r}) => this.inBounds(q, r)) return funky.chain(rows)
.map(({q, r}) => new Hex(q, r)); .map(makeAPoint)
}); .map(makeAPointPair)
.map(this.enforceBoundries)
.compact()
.map(tilePointToHex)
.value();
};
return funky.chain(columns)
.map(processRow)
.flatten()
.value();
} }
} }

View File

@@ -30,8 +30,8 @@ export default class CartographerPointyXY extends Cartographer {
'tileToPixel', 'tileToPixel',
'_pixelToTile', '_pixelToTile',
'teleport', 'teleport',
'inBounds', 'inBounds',
'enforceBoundries', 'enforceBoundries',
'boundingBox', 'boundingBox',
@@ -151,8 +151,7 @@ export default class CartographerPointyXY extends Cartographer {
const makeAPointPair = tilePoint => ({tilePoint, pixelPoint: this.tileToPixel(tilePoint)}); const makeAPointPair = tilePoint => ({tilePoint, pixelPoint: this.tileToPixel(tilePoint)});
return funky.chain(columns) const processRow = x => {
.map(x => {
let top = x < midway ? upperLeftIntercept + x : upperRightIntercept - x; let top = x < midway ? upperLeftIntercept + x : upperRightIntercept - x;
let bottom = x < midway ? lowerRightIntercept - x : lowerLeftIntercept + x; let bottom = x < midway ? lowerRightIntercept - x : lowerLeftIntercept + x;
@@ -160,18 +159,21 @@ export default class CartographerPointyXY extends Cartographer {
top = Math.max(bottom, top); top = Math.max(bottom, top);
// push out by 1 on either end to account for interlocking tiles // push out by 1 on either end to account for interlocking tiles
const rows = rangeInclusive(bottom - 1, top + 1); const row = rangeInclusive(bottom - 1, top + 1);
const makeAPoint = y => ({x, y}); const makeAPoint = y => ({x, y});
return funky.chain(rows) return funky.chain(row)
.map(makeAPoint) .map(makeAPoint)
.map(makeAPointPair) .map(makeAPointPair)
.map(this.enforceBoundries) .map(this.enforceBoundries)
.compact() .compact()
.map(tilePointToSquare) .map(tilePointToSquare)
.value(); .value();
}) };
return funky.chain(columns)
.map(processRow)
.flatten() .flatten()
.value(); .value();
} }

View File

@@ -1,5 +1,10 @@
export function chain (obj) { export function chain (obj) {
let chainInstance = { let chainInstance = {
log: function () {
console.log(obj);
return chainInstance;
},
value: function () { value: function () {
return obj; return obj;
} }

View File

@@ -35,11 +35,26 @@ function roundOff(hex) {
} }
export default class Hex extends Point { export default class Hex extends Point {
static offsetToCube (col, row) {
const x = col;
const z = row - (col + (col & 1)) / 2;
const y = -x - z;
return new Hex(x, y, z);
}
constructor() { constructor() {
super(); super();
if (arguments.length === 2) { // hex = Hex(q, r); if (arguments.length === 1) {
const {q, r, s = -q - r} = arguments[0];
const {x, y, z = -x - y} = arguments[0];
this.x = !isNaN(q) ? q : x;
this.y = !isNaN(s) ? s : y;
this.z = !isNaN(r) ? r : z;
}
else if (arguments.length === 2) { // hex = Hex(q, r);
this.x = arguments[0]; this.x = arguments[0];
this.z = arguments[1]; this.z = arguments[1];
this.y = computeY(this.x, this.z); this.y = computeY(this.x, this.z);
@@ -57,65 +72,76 @@ export default class Hex extends Point {
getY() {return this.y;} getY() {return this.y;}
getZ() {return this.z;} getZ() {return this.z;}
setX(newX) {this.x = newX; return this;} setX (newX) {this.x = newX; return this;}
setY(newY) {this.y = newY; return this;} setY (newY) {this.y = newY; return this;}
setZ(newZ) {this.z = newZ; return this;} setZ (newZ) {this.z = newZ; return this;}
moveX(byX) {this.x += byX; return this;} moveX (byX) {this.x += byX; return this;}
moveY(byY) {this.y += byY; return this;} moveY (byY) {this.y += byY; return this;}
moveZ(byZ) {this.z += byZ; return this;} moveZ (byZ) {this.z += byZ; return this;}
getQ() {return this.x;} getQ () {return this.x;}
getR() {return this.z;} getR () {return this.z;}
setQ(newQ) { setQ (newQ) {
this.x = newQ; this.x = newQ;
this.y = computeY(this.x, this.z); this.y = computeY(this.x, this.z);
return this; return this;
} }
setR(newR) {
setR (newR) {
this.z = newR; this.z = newR;
this.y = computeY(this.x, this.z); this.y = computeY(this.x, this.z);
return this; return this;
} }
moveQ(byQ) { moveQ (byQ) {
this.x += byQ; this.x += byQ;
this.y = computeY(this.x, this.z); this.y = computeY(this.x, this.z);
return this; return this;
} }
moveR(byR) {
moveR (byR) {
this.z += byR; this.z += byR;
this.y = computeY(this.x, this.z); this.y = computeY(this.x, this.z);
return this; return this;
} }
getPoint() { return {x: this.x, y: this.y, z: this.z}; } getPoint () { return {x: this.x, y: this.y, z: this.z}; }
setHex(newHex) { setHex (newHex) {
this.x = newHex.x; this.x = newHex.x;
this.y = newHex.y; this.y = newHex.y;
this.z = newHex.z; this.z = newHex.z;
return this; return this;
} }
moveHex(byHex) { moveHex (byHex) {
this.x += byHex.x; this.x += byHex.x;
this.y += byHex.y; this.y += byHex.y;
this.z += byHex.z; this.z += byHex.z;
return this; return this;
} }
getAxial() {return {q: this.x, r: this.z};} getAxial () {return {q: this.x, r: this.z};}
setAxial(newAxial) {
setAxial (newAxial) {
this.x = newAxial.q; this.x = newAxial.q;
this.z = newAxial.r; this.z = newAxial.r;
this.y = computeY(this.x, this.y); this.y = computeY(this.x, this.y);
return this; return this;
} }
moveAxial(byAxial) {
moveAxial (byAxial) {
this.x += byAxial.q; this.x += byAxial.q;
this.z += byAxial.r; this.z += byAxial.r;
this.y = computeY(this.x, this.z); this.y = computeY(this.x, this.z);
return this; return this;
} }
getOffsetHex () {
const col = this.x;
const row = this.z + (this.x + (this.x & 1)) / 2;
return {col, row};
}
} }