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/game/components/static_map_entity.js

183 lines
6.2 KiB

import { Math_radians } from "../../core/builtins";
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 { Component } from "../component";
export class StaticMapEntityComponent extends Component {
static getId() {
return "StaticMapEntity";
}
static getSchema() {
return {};
}
/**
*
* @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 {string=} param0.spriteKey Optional sprite
* @param {string=} param0.silhouetteColor Optional silhouette color override
*/
constructor({
origin = new Vector(),
tileSize = new Vector(1, 1),
rotation = 0,
originalRotation = 0,
spriteKey = null,
silhouetteColor = null,
}) {
super();
assert(
rotation % 90 === 0,
"Rotation of static map entity must be multiple of 90 (was " + rotation + ")"
);
this.origin = origin;
this.tileSize = tileSize;
this.spriteKey = spriteKey;
this.rotation = rotation;
this.originalRotation = originalRotation;
this.silhouetteColor = silhouetteColor;
}
/**
* Returns the effective rectangle of this entity in tile space
* @returns {Rectangle}
*/
getTileSpaceBounds() {
switch (this.rotation) {
case 0:
return new Rectangle(this.origin.x, this.origin.y, this.tileSize.x, this.tileSize.y);
case 90:
return new Rectangle(
this.origin.x - this.tileSize.y + 1,
this.origin.y,
this.tileSize.y,
this.tileSize.x
);
case 180:
return new Rectangle(
this.origin.x - this.tileSize.x + 1,
this.origin.y - this.tileSize.y + 1,
this.tileSize.x,
this.tileSize.y
);
case 270:
return new Rectangle(
this.origin.x,
this.origin.y - this.tileSize.x + 1,
this.tileSize.y,
this.tileSize.x
);
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);
}
/**
* Transforms the given vector/rotation from world space to local space
* @param {Vector} vector
* @returns {Vector}
*/
unapplyRotationToVector(vector) {
return vector.rotateFastMultipleOf90(360 - this.rotation);
}
/**
* Transforms the given direction from local space
* @param {enumDirection} direction
* @returns {enumDirection}
*/
localDirectionToWorld(direction) {
return Vector.transformDirectionFromMultipleOf90(direction, this.rotation);
}
/**
* Transforms the given direction from world to local space
* @param {enumDirection} direction
* @returns {enumDirection}
*/
worldDirectionToLocal(direction) {
return Vector.transformDirectionFromMultipleOf90(direction, 360 - this.rotation);
}
/**
* Transforms from local tile space to global tile space
* @param {Vector} localTile
* @returns {Vector}
*/
localTileToWorld(localTile) {
const result = this.applyRotationToVector(localTile);
result.addInplace(this.origin);
return result;
}
/**
* Transforms from world space to local space
* @param {Vector} worldTile
*/
worldToLocalTile(worldTile) {
const localUnrotated = worldTile.sub(this.origin);
return this.unapplyRotationToVector(localUnrotated);
}
/**
* 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
* @param {boolean=} clipping Whether to clip
*/
drawSpriteOnFullEntityBounds(parameters, sprite, extrudePixels = 0, clipping = true) {
const worldX = this.origin.x * globalConfig.tileSize;
const worldY = this.origin.y * globalConfig.tileSize;
if (this.rotation === 0) {
// Early out, is faster
sprite.drawCached(
parameters,
worldX - extrudePixels * this.tileSize.x,
worldY - extrudePixels * this.tileSize.y,
globalConfig.tileSize * this.tileSize.x + 2 * extrudePixels * this.tileSize.x,
globalConfig.tileSize * this.tileSize.y + 2 * extrudePixels * this.tileSize.y,
clipping
);
} else {
const rotationCenterX = worldX + globalConfig.halfTileSize;
const rotationCenterY = worldY + globalConfig.halfTileSize;
parameters.context.translate(rotationCenterX, rotationCenterY);
parameters.context.rotate(Math_radians(this.rotation));
sprite.drawCached(
parameters,
-globalConfig.halfTileSize - extrudePixels * this.tileSize.x,
-globalConfig.halfTileSize - extrudePixels * this.tileSize.y,
globalConfig.tileSize * this.tileSize.x + 2 * extrudePixels * this.tileSize.x,
globalConfig.tileSize * this.tileSize.y + 2 * extrudePixels * this.tileSize.y,
false
);
parameters.context.rotate(-Math_radians(this.rotation));
parameters.context.translate(-rotationCenterX, -rotationCenterY);
}
}
}