game_space_chunk_unit_chunk_unit.js

import Sprite from "../../../../registry/sprite/sprite.js";
import Color from "../../../../util/color/color.js";
import Vec2 from "../../../vector/vec2.js";
import CollisionComponent from "../../../actor/component/collision_component.js";
import Actor from "../../../actor/actor.js";
import Bounds from "../../../vector/bounds.js";
import SpritePartition from "../../../../registry/sprite/sprite_partition.js";
import LayeredSprite from "../../../../registry/sprite/layered_sprite.js";

/**
 * @module ChunkUnit
 * @fileoverview Contains ChunkUnit class.
 */

/**
 * @class
 * Individual unit within a space chunk.
 */
class ChunkUnit {
    /**
     * Create a new chunk unit.
     * @param {Chunk} chunk Parent space chunk
     * @param {number} x Global position along x-axis
     * @param {number} y Global position along y-axis
     * @param {string|Sprite|Color|null} sprite Sprite, sprite identifier, or color for drawing
     * @constructor
     */
    constructor({
        chunk,
        x = 0,
        y = 0,
        sprite = null
    } = {}) {
        this.chunk = chunk;
        this.x = x;
        this.y = y;

        this.sprite = null;
        if (sprite instanceof Sprite || sprite instanceof Color)
            this.sprite = sprite;
        else if (typeof sprite === "string")
            this.sprite = $$.reg.sprites.get(sprite);

        this.canWalkOn = false;
    }

    /**
     * Update the unit.
     * @param {number} elapsed Time since last update cycle in seconds
     */
    update(elapsed) {}

    /**
     * Draw the chunk unit.
     * @param {CanvasRenderingContext2D} ctx Canvas context to draw on
     */
    draw(ctx) {
        if (this.sprite === null)
            return;

        const extra = Math.ceil(this.chunk.space.camera.calcZoom()) + 1;

        const size = this.chunk.space.unitSize;
        const chunkPos = new Vec2(this.chunk.x, this.chunk.y).mulv(size * this.chunk.space.chunkSize);

        const x = this.x - chunkPos.x;
        const y = this.y - chunkPos.y;

        if (this.sprite instanceof Sprite || this.sprite instanceof SpritePartition || this.sprite instanceof LayeredSprite) {
            this.sprite.draw(ctx, new Vec2(x, y), new Vec2(size + extra, size + extra));
        } else if (this.sprite instanceof Color) {
            ctx.fillStyle = this.sprite.get();
            ctx.fillRect(x, y, size + extra, size + extra);
        }
    }


    //
    // Collision
    //

    checkCollision(actor, pos) {
        const pseudo = new Actor({
            pos: new Vec2(this.x, this.y),
            scale: this.chunk.space.unitSize,
            components: {
                "collision": new CollisionComponent({
                    bounds: new Bounds(new Vec2(0, 0),
                        new Vec2(1, 1))
                })
            }
        });

        for (const comp of actor.components.getCollisions()) {
            if (comp.layers.has("default")) {
                const check = pseudo.checkCollision(comp, pos);
                if (check.result)
                    return check;
            }
        }

        return {
            result: false
        };
    }
}

export default ChunkUnit;