1
0
mirror of https://github.com/tobspr/shapez.io.git synced 2024-10-27 20:34:29 +00:00
tobspr_shapez.io/src/js/game/components/static_map_entity.js

292 lines
8.9 KiB
JavaScript
Raw Normal View History

2020-05-09 14:45:23 +00:00
import { globalConfig } from "../../core/config";
import { DrawParameters } from "../../core/draw_parameters";
import { Rectangle } from "../../core/rectangle";
import { AtlasSprite } from "../../core/sprites";
import { enumDirection, Vector } from "../../core/vector";
import { types } from "../../savegame/serialization";
import { getBuildingDataFromCode } from "../building_codes";
2020-08-12 18:11:24 +00:00
import { Component } from "../component";
2020-05-09 14:45:23 +00:00
export class StaticMapEntityComponent extends Component {
static getId() {
return "StaticMapEntity";
}
static getSchema() {
2020-05-14 19:54:11 +00:00
return {
origin: types.tileVector,
rotation: types.float,
originalRotation: types.float,
// See building_codes.js
code: types.uint,
2020-05-14 19:54:11 +00:00
};
2020-05-09 14:45:23 +00:00
}
/**
* Returns the effective tile size
* @returns {Vector}
*/
getTileSize() {
return getBuildingDataFromCode(this.code).tileSize;
}
/**
* Returns the sprite
* @returns {AtlasSprite}
*/
getSprite() {
return getBuildingDataFromCode(this.code).sprite;
}
/**
* Returns the blueprint sprite
* @returns {AtlasSprite}
*/
getBlueprintSprite() {
return getBuildingDataFromCode(this.code).blueprintSprite;
}
/**
* Returns the silhouette color
* @returns {string}
*/
getSilhouetteColor() {
return getBuildingDataFromCode(this.code).silhouetteColor;
}
/**
* Returns the meta building
2020-08-12 18:11:24 +00:00
* @returns {import("../meta_building").MetaBuilding}
*/
getMetaBuilding() {
return getBuildingDataFromCode(this.code).metaInstance;
}
2020-09-24 10:53:40 +00:00
/**
* Returns the buildings variant
* @returns {string}
*/
getVariant() {
return getBuildingDataFromCode(this.code).variant;
}
2020-09-19 19:41:48 +00:00
/**
* Copy the current state to another component
* @param {Component} otherComponent
*/
copyAdditionalStateTo(otherComponent) {
2020-05-27 12:30:59 +00:00
return new StaticMapEntityComponent({
origin: this.origin.copy(),
rotation: this.rotation,
originalRotation: this.originalRotation,
code: this.code,
2020-05-27 12:30:59 +00:00
});
}
2020-05-09 14:45:23 +00:00
/**
*
* @param {object} param0
* @param {Vector=} param0.origin Origin (Top Left corner) of the entity
* @param {Vector=} param0.tileSize Size of the entity in tiles
* @param {number=} param0.rotation Rotation in degrees. Must be multiple of 90
* @param {number=} param0.originalRotation Original Rotation in degrees. Must be multiple of 90
* @param {number=} param0.code Building code
2020-05-09 14:45:23 +00:00
*/
constructor({
origin = new Vector(),
tileSize = new Vector(1, 1),
rotation = 0,
originalRotation = 0,
code = 0,
2020-05-09 14:45:23 +00:00
}) {
super();
assert(
rotation % 90 === 0,
"Rotation of static map entity must be multiple of 90 (was " + rotation + ")"
2020-05-09 14:45:23 +00:00
);
this.origin = origin;
this.rotation = rotation;
this.code = code;
this.originalRotation = originalRotation;
2020-05-09 14:45:23 +00:00
}
/**
* Returns the effective rectangle of this entity in tile space
* @returns {Rectangle}
*/
getTileSpaceBounds() {
const size = this.getTileSize();
switch (this.rotation) {
2020-05-09 14:45:23 +00:00
case 0:
return new Rectangle(this.origin.x, this.origin.y, size.x, size.y);
2020-05-09 14:45:23 +00:00
case 90:
return new Rectangle(this.origin.x - size.y + 1, this.origin.y, size.y, size.x);
2020-05-09 14:45:23 +00:00
case 180:
return new Rectangle(this.origin.x - size.x + 1, this.origin.y - size.y + 1, size.x, size.y);
2020-05-09 14:45:23 +00:00
case 270:
return new Rectangle(this.origin.x, this.origin.y - size.x + 1, size.y, size.x);
2020-05-09 14:45:23 +00:00
default:
assert(false, "Invalid rotation");
}
}
/**
* Transforms the given vector/rotation from local space to world space
* @param {Vector} vector
* @returns {Vector}
*/
applyRotationToVector(vector) {
return vector.rotateFastMultipleOf90(this.rotation);
2020-05-09 14:45:23 +00:00
}
/**
* Transforms the given vector/rotation from world space to local space
* @param {Vector} vector
* @returns {Vector}
*/
unapplyRotationToVector(vector) {
return vector.rotateFastMultipleOf90(360 - this.rotation);
2020-05-09 14:45:23 +00:00
}
/**
* Transforms the given direction from local space
* @param {enumDirection} direction
* @returns {enumDirection}
*/
localDirectionToWorld(direction) {
return Vector.transformDirectionFromMultipleOf90(direction, this.rotation);
2020-05-09 14:45:23 +00:00
}
/**
* Transforms the given direction from world to local space
* @param {enumDirection} direction
* @returns {enumDirection}
*/
worldDirectionToLocal(direction) {
return Vector.transformDirectionFromMultipleOf90(direction, 360 - this.rotation);
2020-05-09 14:45:23 +00:00
}
/**
* Transforms from local tile space to global tile space
* @param {Vector} localTile
* @returns {Vector}
*/
localTileToWorld(localTile) {
const result = localTile.rotateFastMultipleOf90(this.rotation);
result.x += this.origin.x;
result.y += this.origin.y;
2020-05-09 14:45:23 +00:00
return result;
}
/**
* Transforms from world space to local space
* @param {Vector} worldTile
*/
worldToLocalTile(worldTile) {
const localUnrotated = worldTile.sub(this.origin);
return this.unapplyRotationToVector(localUnrotated);
}
2020-05-18 15:40:20 +00:00
/**
* Returns whether the entity should be drawn for the given parameters
* @param {DrawParameters} parameters
*/
shouldBeDrawn(parameters) {
let x = 0;
let y = 0;
let w = 0;
let h = 0;
const size = this.getTileSize();
2020-05-18 15:40:20 +00:00
switch (this.rotation) {
case 0: {
x = this.origin.x;
y = this.origin.y;
w = size.x;
h = size.y;
2020-05-18 15:40:20 +00:00
break;
}
case 90: {
x = this.origin.x - size.y + 1;
2020-05-18 15:40:20 +00:00
y = this.origin.y;
w = size.y;
h = size.x;
2020-05-18 15:40:20 +00:00
break;
}
case 180: {
x = this.origin.x - size.x + 1;
y = this.origin.y - size.y + 1;
w = size.x;
h = size.y;
2020-05-18 15:40:20 +00:00
break;
}
case 270: {
x = this.origin.x;
y = this.origin.y - size.x + 1;
w = size.y;
h = size.x;
2020-05-18 15:40:20 +00:00
break;
}
default:
assert(false, "Invalid rotation");
}
return parameters.visibleRect.containsRect4Params(
x * globalConfig.tileSize,
y * globalConfig.tileSize,
w * globalConfig.tileSize,
h * globalConfig.tileSize
);
}
2020-05-09 14:45:23 +00:00
/**
* Draws a sprite over the whole space of the entity
* @param {DrawParameters} parameters
* @param {AtlasSprite} sprite
* @param {number=} extrudePixels How many pixels to extrude the sprite
2020-05-27 12:30:59 +00:00
* @param {Vector=} overridePosition Whether to drwa the entity at a different location
2020-05-09 14:45:23 +00:00
*/
drawSpriteOnBoundsClipped(parameters, sprite, extrudePixels = 0, overridePosition = null) {
2020-05-27 12:30:59 +00:00
if (!this.shouldBeDrawn(parameters) && !overridePosition) {
2020-05-18 15:40:20 +00:00
return;
}
const size = this.getTileSize();
2020-05-27 12:30:59 +00:00
let worldX = this.origin.x * globalConfig.tileSize;
let worldY = this.origin.y * globalConfig.tileSize;
if (overridePosition) {
worldX = overridePosition.x * globalConfig.tileSize;
worldY = overridePosition.y * globalConfig.tileSize;
}
2020-05-18 15:40:20 +00:00
if (this.rotation === 0) {
2020-05-09 14:45:23 +00:00
// Early out, is faster
sprite.drawCached(
parameters,
worldX - extrudePixels * size.x,
worldY - extrudePixels * size.y,
globalConfig.tileSize * size.x + 2 * extrudePixels * size.x,
2020-08-15 17:43:03 +00:00
globalConfig.tileSize * size.y + 2 * extrudePixels * size.y
2020-05-09 14:45:23 +00:00
);
} else {
const rotationCenterX = worldX + globalConfig.halfTileSize;
const rotationCenterY = worldY + globalConfig.halfTileSize;
parameters.context.translate(rotationCenterX, rotationCenterY);
parameters.context.rotate(Math.radians(this.rotation));
2020-05-09 14:45:23 +00:00
sprite.drawCached(
parameters,
-globalConfig.halfTileSize - extrudePixels * size.x,
-globalConfig.halfTileSize - extrudePixels * size.y,
globalConfig.tileSize * size.x + 2 * extrudePixels * size.x,
globalConfig.tileSize * size.y + 2 * extrudePixels * size.y,
2020-08-15 17:43:03 +00:00
false // no clipping possible here
2020-05-09 14:45:23 +00:00
);
parameters.context.rotate(-Math.radians(this.rotation));
2020-05-09 14:45:23 +00:00
parameters.context.translate(-rotationCenterX, -rotationCenterY);
}
}
}