You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tobspr_shapez.io/src/js/core/rectangle.js

376 lines
9.0 KiB

4 years ago
import { globalConfig } from "./config";
import { epsilonCompare, round2Digits } from "./utils";
4 years ago
import { Vector } from "./vector";
export class Rectangle {
constructor(x = 0, y = 0, w = 0, h = 0) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
}
/**
* Creates a rectangle from top right bottom and left offsets
* @param {number} top
* @param {number} right
* @param {number} bottom
* @param {number} left
*/
static fromTRBL(top, right, bottom, left) {
return new Rectangle(left, top, right - left, bottom - top);
}
/**
* Constructs a new square rectangle
* @param {number} x
* @param {number} y
* @param {number} size
*/
static fromSquare(x, y, size) {
return new Rectangle(x, y, size, size);
}
/**
*
* @param {Vector} p1
* @param {Vector} p2
*/
static fromTwoPoints(p1, p2) {
const left = Math.min(p1.x, p2.x);
const top = Math.min(p1.y, p2.y);
const right = Math.max(p1.x, p2.x);
const bottom = Math.max(p1.y, p2.y);
4 years ago
return new Rectangle(left, top, right - left, bottom - top);
}
Puzzle DLC (#1172) * Puzzle mode (#1135) * Add mode button to main menu * [WIP] Add mode menu. Add factory-based gameMode creation * Add savefile migration, serialize, deserialize * Add hidden HUD elements, zone, and zoom, boundary constraints * Clean up lint issues * Add building, HUD exclusion, building exclusion, and refactor - [WIP] Add ConstantProducer building that combines ConstantSignal and ItemProducer functionality. Currently using temp assets. - Add pre-placement check to the zone - Use Rectangles for zone and boundary - Simplify zone drawing - Account for exclusion in savegame data - [WIP] Add puzzle play and edit buttons in puzzle mode menu * [WIP] Add building, component, and systems for producing and accepting user-specified items and checking goal criteria * Add ingame puzzle mode UI elements - Add minimal menus in puzzle mode for back, next navigation - Add lower menu for changing zone dimenensions Co-authored-by: Greg Considine <gconsidine@users.noreply.github.com> * Performance optimizations (#1154) * 1.3.1 preparations * Minor fixes, update translations * Fix achievements not working * Lots of belt optimizations, ~15% performance boost * Puzzle mode, part 1 * Puzzle mode, part 2 * Fix missing import * Puzzle mode, part 3 * Fix typo * Puzzle mode, part 4 * Puzzle Mode fixes: Correct zone restrictions and more (#1155) * Hide Puzzle Editor Controls in regular game mode, fix typo * Disallow shrinking zone if there are buildings * Fix multi-tile buildings for shrinking * Puzzle mode, Refactor hud * Puzzle mode * Fixed typo in latest puzzle commit (#1156) * Allow completing puzzles * Puzzle mode, almost done * Bump version to 1.4.0 * Fixes * [puzzle] Prevent pipette cheats (miners, emitters) (#1158) * Puzzle mode, almost done * Allow clearing belts with 'B' * Multiple users for the puzzle dlc * Bump api key * Minor adjustments * Update * Minor fixes * Fix throughput * Fix belts * Minor puzzle adjustments * New difficulty * Minor puzzle improvements * Fix belt path * Update translations * Added a button to return to the menu after a puzzle is completed (#1170) * added another button to return to the menu * improved menu return * fixed continue button to not go back to menu * [Puzzle] Added ability to lock buildings in the puzzle editor! (#1164) * initial test * tried to get it to work * added icon * added test exclusion * reverted css * completed flow for building locking * added lock option * finalized look and changed locked building to same sprite * removed unused art * added clearing every goal acceptor on lock to prevent creating impossible puzzles * heavily improved validation and prevented autocompletion * validation only checks every 100 ticks to improve performance * validation only checks every 100 ticks to improve performance * removed clearing goal acceptors as it isn't needed because of validation * Add soundtrack, puzzle dlc fixes Co-authored-by: Greg Considine <gconsidine@users.noreply.github.com> Co-authored-by: dengr1065 <dengr1065@gmail.com> Co-authored-by: Sense101 <67970865+Sense101@users.noreply.github.com>
3 years ago
/**
*
* @param {number} width
* @param {number} height
*/
static centered(width, height) {
return new Rectangle(-Math.ceil(width / 2), -Math.ceil(height / 2), width, height);
}
4 years ago
/**
* Returns if a intersects b
4 years ago
* @param {Rectangle} a
* @param {Rectangle} b
*/
static intersects(a, b) {
return a.left <= b.right && b.left <= a.right && a.top <= b.bottom && b.top <= a.bottom;
}
/**
* Copies this instance
* @returns {Rectangle}
*/
clone() {
return new Rectangle(this.x, this.y, this.w, this.h);
}
/**
* Returns if this rectangle is empty
* @returns {boolean}
*/
4 years ago
isEmpty() {
return epsilonCompare(this.w * this.h, 0);
}
/**
* Returns if this rectangle is equal to the other while taking an epsilon into account
* @param {Rectangle} other
Puzzle DLC (#1172) * Puzzle mode (#1135) * Add mode button to main menu * [WIP] Add mode menu. Add factory-based gameMode creation * Add savefile migration, serialize, deserialize * Add hidden HUD elements, zone, and zoom, boundary constraints * Clean up lint issues * Add building, HUD exclusion, building exclusion, and refactor - [WIP] Add ConstantProducer building that combines ConstantSignal and ItemProducer functionality. Currently using temp assets. - Add pre-placement check to the zone - Use Rectangles for zone and boundary - Simplify zone drawing - Account for exclusion in savegame data - [WIP] Add puzzle play and edit buttons in puzzle mode menu * [WIP] Add building, component, and systems for producing and accepting user-specified items and checking goal criteria * Add ingame puzzle mode UI elements - Add minimal menus in puzzle mode for back, next navigation - Add lower menu for changing zone dimenensions Co-authored-by: Greg Considine <gconsidine@users.noreply.github.com> * Performance optimizations (#1154) * 1.3.1 preparations * Minor fixes, update translations * Fix achievements not working * Lots of belt optimizations, ~15% performance boost * Puzzle mode, part 1 * Puzzle mode, part 2 * Fix missing import * Puzzle mode, part 3 * Fix typo * Puzzle mode, part 4 * Puzzle Mode fixes: Correct zone restrictions and more (#1155) * Hide Puzzle Editor Controls in regular game mode, fix typo * Disallow shrinking zone if there are buildings * Fix multi-tile buildings for shrinking * Puzzle mode, Refactor hud * Puzzle mode * Fixed typo in latest puzzle commit (#1156) * Allow completing puzzles * Puzzle mode, almost done * Bump version to 1.4.0 * Fixes * [puzzle] Prevent pipette cheats (miners, emitters) (#1158) * Puzzle mode, almost done * Allow clearing belts with 'B' * Multiple users for the puzzle dlc * Bump api key * Minor adjustments * Update * Minor fixes * Fix throughput * Fix belts * Minor puzzle adjustments * New difficulty * Minor puzzle improvements * Fix belt path * Update translations * Added a button to return to the menu after a puzzle is completed (#1170) * added another button to return to the menu * improved menu return * fixed continue button to not go back to menu * [Puzzle] Added ability to lock buildings in the puzzle editor! (#1164) * initial test * tried to get it to work * added icon * added test exclusion * reverted css * completed flow for building locking * added lock option * finalized look and changed locked building to same sprite * removed unused art * added clearing every goal acceptor on lock to prevent creating impossible puzzles * heavily improved validation and prevented autocompletion * validation only checks every 100 ticks to improve performance * validation only checks every 100 ticks to improve performance * removed clearing goal acceptors as it isn't needed because of validation * Add soundtrack, puzzle dlc fixes Co-authored-by: Greg Considine <gconsidine@users.noreply.github.com> Co-authored-by: dengr1065 <dengr1065@gmail.com> Co-authored-by: Sense101 <67970865+Sense101@users.noreply.github.com>
3 years ago
* @param {number} [epsilon]
*/
4 years ago
equalsEpsilon(other, epsilon) {
return (
epsilonCompare(this.x, other.x, epsilon) &&
epsilonCompare(this.y, other.y, epsilon) &&
epsilonCompare(this.w, other.w, epsilon) &&
epsilonCompare(this.h, other.h, epsilon)
);
}
/**
* @returns {number}
*/
4 years ago
left() {
return this.x;
}
/**
* @returns {number}
*/
4 years ago
right() {
return this.x + this.w;
}
/**
* @returns {number}
*/
4 years ago
top() {
return this.y;
}
/**
* @returns {number}
*/
4 years ago
bottom() {
return this.y + this.h;
}
/**
* Returns Top, Right, Bottom, Left
* @returns {[number, number, number, number]}
*/
4 years ago
trbl() {
return [this.y, this.right(), this.bottom(), this.x];
}
/**
* Returns the center of the rect
* @returns {Vector}
*/
4 years ago
getCenter() {
return new Vector(this.x + this.w / 2, this.y + this.h / 2);
}
/**
* Sets the right side of the rect without moving it
* @param {number} right
*/
4 years ago
setRight(right) {
this.w = right - this.x;
}
/**
* Sets the bottom side of the rect without moving it
* @param {number} bottom
*/
4 years ago
setBottom(bottom) {
this.h = bottom - this.y;
}
/**
* Sets the top side of the rect without scaling it
* @param {number} top
*/
4 years ago
setTop(top) {
const bottom = this.bottom();
this.y = top;
this.setBottom(bottom);
}
/**
* Sets the left side of the rect without scaling it
* @param {number} left
*/
4 years ago
setLeft(left) {
const right = this.right();
this.x = left;
this.setRight(right);
}
/**
* Returns the top left point
* @returns {Vector}
*/
4 years ago
topLeft() {
return new Vector(this.x, this.y);
}
/**
* Returns the bottom left point
* @returns {Vector}
*/
4 years ago
bottomRight() {
return new Vector(this.right(), this.bottom());
}
/**
* Moves the rectangle by the given parameters
* @param {number} x
* @param {number} y
*/
4 years ago
moveBy(x, y) {
this.x += x;
this.y += y;
}
/**
* Moves the rectangle by the given vector
* @param {Vector} vec
*/
4 years ago
moveByVector(vec) {
this.x += vec.x;
this.y += vec.y;
}
/**
* Scales every parameter (w, h, x, y) by the given factor. Useful to transform from world to
* tile space and vice versa
* @param {number} factor
*/
4 years ago
allScaled(factor) {
return new Rectangle(this.x * factor, this.y * factor, this.w * factor, this.h * factor);
}
/**
* Expands the rectangle in all directions
* @param {number} amount
* @returns {Rectangle} new rectangle
*/
expandedInAllDirections(amount) {
return new Rectangle(this.x - amount, this.y - amount, this.w + 2 * amount, this.h + 2 * amount);
4 years ago
}
/**
* Returns if the given rectangle is contained
* @param {Rectangle} rect
* @returns {boolean}
*/
containsRect(rect) {
return (
this.x <= rect.right() &&
rect.x <= this.right() &&
this.y <= rect.bottom() &&
rect.y <= this.bottom()
);
}
/**
* Returns if this rectangle contains the other rectangle specified by the parameters
* @param {number} x
* @param {number} y
* @param {number} w
* @param {number} h
* @returns {boolean}
*/
4 years ago
containsRect4Params(x, y, w, h) {
return this.x <= x + w && x <= this.right() && this.y <= y + h && y <= this.bottom();
}
/**
* Returns if the rectangle contains the given circle at (x, y) with the radius (radius)
* @param {number} x
* @param {number} y
* @param {number} radius
* @returns {boolean}
4 years ago
*/
containsCircle(x, y, radius) {
return (
this.x <= x + radius &&
x - radius <= this.right() &&
this.y <= y + radius &&
y - radius <= this.bottom()
);
}
/**
2 years ago
* Returns if the rectangle contains the given point
4 years ago
* @param {number} x
* @param {number} y
* @returns {boolean}
4 years ago
*/
containsPoint(x, y) {
return x >= this.x && x < this.right() && y >= this.y && y < this.bottom();
}
/**
* Returns the shared area with another rectangle, or null if there is no intersection
* @param {Rectangle} rect
* @returns {Rectangle|null}
*/
getIntersection(rect) {
const left = Math.max(this.x, rect.x);
const top = Math.max(this.y, rect.y);
4 years ago
const right = Math.min(this.x + this.w, rect.x + rect.w);
const bottom = Math.min(this.y + this.h, rect.y + rect.h);
4 years ago
if (right <= left || bottom <= top) {
return null;
}
return Rectangle.fromTRBL(top, right, bottom, left);
}
Puzzle DLC (#1172) * Puzzle mode (#1135) * Add mode button to main menu * [WIP] Add mode menu. Add factory-based gameMode creation * Add savefile migration, serialize, deserialize * Add hidden HUD elements, zone, and zoom, boundary constraints * Clean up lint issues * Add building, HUD exclusion, building exclusion, and refactor - [WIP] Add ConstantProducer building that combines ConstantSignal and ItemProducer functionality. Currently using temp assets. - Add pre-placement check to the zone - Use Rectangles for zone and boundary - Simplify zone drawing - Account for exclusion in savegame data - [WIP] Add puzzle play and edit buttons in puzzle mode menu * [WIP] Add building, component, and systems for producing and accepting user-specified items and checking goal criteria * Add ingame puzzle mode UI elements - Add minimal menus in puzzle mode for back, next navigation - Add lower menu for changing zone dimenensions Co-authored-by: Greg Considine <gconsidine@users.noreply.github.com> * Performance optimizations (#1154) * 1.3.1 preparations * Minor fixes, update translations * Fix achievements not working * Lots of belt optimizations, ~15% performance boost * Puzzle mode, part 1 * Puzzle mode, part 2 * Fix missing import * Puzzle mode, part 3 * Fix typo * Puzzle mode, part 4 * Puzzle Mode fixes: Correct zone restrictions and more (#1155) * Hide Puzzle Editor Controls in regular game mode, fix typo * Disallow shrinking zone if there are buildings * Fix multi-tile buildings for shrinking * Puzzle mode, Refactor hud * Puzzle mode * Fixed typo in latest puzzle commit (#1156) * Allow completing puzzles * Puzzle mode, almost done * Bump version to 1.4.0 * Fixes * [puzzle] Prevent pipette cheats (miners, emitters) (#1158) * Puzzle mode, almost done * Allow clearing belts with 'B' * Multiple users for the puzzle dlc * Bump api key * Minor adjustments * Update * Minor fixes * Fix throughput * Fix belts * Minor puzzle adjustments * New difficulty * Minor puzzle improvements * Fix belt path * Update translations * Added a button to return to the menu after a puzzle is completed (#1170) * added another button to return to the menu * improved menu return * fixed continue button to not go back to menu * [Puzzle] Added ability to lock buildings in the puzzle editor! (#1164) * initial test * tried to get it to work * added icon * added test exclusion * reverted css * completed flow for building locking * added lock option * finalized look and changed locked building to same sprite * removed unused art * added clearing every goal acceptor on lock to prevent creating impossible puzzles * heavily improved validation and prevented autocompletion * validation only checks every 100 ticks to improve performance * validation only checks every 100 ticks to improve performance * removed clearing goal acceptors as it isn't needed because of validation * Add soundtrack, puzzle dlc fixes Co-authored-by: Greg Considine <gconsidine@users.noreply.github.com> Co-authored-by: dengr1065 <dengr1065@gmail.com> Co-authored-by: Sense101 <67970865+Sense101@users.noreply.github.com>
3 years ago
/**
* Returns whether the rectangle fully intersects the given rectangle
* @param {Rectangle} rect
*/
intersectsFully(rect) {
const intersection = this.getIntersection(rect);
return intersection && Math.abs(intersection.w * intersection.h - rect.w * rect.h) < 0.001;
}
/**
* Returns the union of this rectangle with another
* @param {Rectangle} rect
*/
getUnion(rect) {
if (this.isEmpty()) {
// If this is rect is empty, return the other one
return rect.clone();
}
if (rect.isEmpty()) {
// If the other is empty, return this one
return this.clone();
}
// Find contained area
const left = Math.min(this.x, rect.x);
const top = Math.min(this.y, rect.y);
const right = Math.max(this.right(), rect.right());
const bottom = Math.max(this.bottom(), rect.bottom());
4 years ago
return Rectangle.fromTRBL(top, right, bottom, left);
}
/**
* Good for caching stuff
*/
toCompareableString() {
return (
round2Digits(this.x) +
"/" +
round2Digits(this.y) +
"/" +
round2Digits(this.w) +
"/" +
round2Digits(this.h)
);
}
/**
* Good for printing stuff
*/
toString() {
return (
"[x:" +
round2Digits(this.x) +
"| y:" +
round2Digits(this.y) +
"| w:" +
round2Digits(this.w) +
"| h:" +
round2Digits(this.h) +
"]"
);
}
4 years ago
/**
* Returns a new rectangle in tile space which includes all tiles which are visible in this rect
4 years ago
* @returns {Rectangle}
*/
toTileCullRectangle() {
return new Rectangle(
Math.floor(this.x / globalConfig.tileSize),
Math.floor(this.y / globalConfig.tileSize),
Math.ceil(this.w / globalConfig.tileSize),
Math.ceil(this.h / globalConfig.tileSize)
);
4 years ago
}
}