game_actor_moving_actor.js
import Actor from "./actor.js";
import Vec2 from "../vector/vec2.js";
/**
* @module MovingActor
* @fileoverview Contains MovingActor class.
*/
/**
* @class
* @extends Actor
* Base class for actors that move, whether controlled by the user or by pathing.
*/
class MovingActor extends Actor {
/**
* Create a new moving actor.
* @param {Vec2} pos Initial position of actor
* @param {number} Initial rotation of actor
* @param {number|Vec2} Initial scale of actor
* @param {string|Sprite|null} sprite Sprite for visual rendering
* @param {"auto"|null} collision Collision initializer (optional)
* @param {string|Controller|null} controller Controller for user movement (optional)
* @param {number} speed Speed of movement (300 by default)
* @constructor
*/
constructor({
pos = new Vec2(),
rotation = 0,
scale = 4,
sprite = null,
collision = null,
controller = null,
speed = 300,
} = {}) {
super({
pos: pos,
rotation: rotation,
scale: scale,
collision: collision,
sprite: sprite
});
this.move = new Vec2(0, 0);
this.speed = speed;
this.speedMultiplier = 1;
this.controller = null;
if (controller !== null)
this.setController(controller);
}
update(elapsed) {
if (this.controller != null) {
this.move = new Vec2(0, 0);
this.speedMultiplier = 1;
this.controller.update(this, elapsed);
}
this.doMoveIter(elapsed);
super.update(elapsed);
}
/**
* Set the controller of the moving actor.
* @param {string} id ID of the controller type to use
*/
setController(id) {
const controller = $$.reg.controller.get(id);
if (controller !== null)
this.controller = controller;
}
/**
* Perform multiple movements in a single frame. Helps with accuracy.
* @param {number} elapsed Time since last update cycle in seconds
*/
doMoveIter(elapsed) {
const n = 16;
for (let i = 0; i < n; i++)
this.doMove(this.move.copy(), elapsed / n);
}
/**
* Perform the movement controlled by a controller.
* @param {Vec2} move Movement vector
* @param {number} elapsed Time since last update
*/
doMove(move, elapsed) {
if (move.x !== 0 && move.y !== 0)
move = move.norm();
let speed = this.speedMultiplier;
const unit = this.space.getUnitAt(this.pos.x, this.pos.y);
if (unit !== null)
if (!unit.canWalkOn)
speed = 0.4;
move = move.mulv(this.speed * speed);
if (move.x !== 0 || move.y !== 0) {
const to = this.pos.add(move.mulv(elapsed));
let collision = {
result: false
};
let result = this.space.checkUnitCollision(this, to);
if (!result.result) {
for (const chunk of this.overlappingChunks.values()) {
result = chunk.checkCollision(this, to);
if (result.result)
collision = result;
}
} else {
collision = result;
}
if (collision.result) {
if (collision.axes.x !== 0)
this._pos.x = to.x - Math.sign(move.x) * (collision.overlap + 1) * Math.abs(collision.axes.x);
else
this._pos.x = to.x;
if (collision.axes.y !== 0)
this._pos.y = to.y - Math.sign(move.y) * (collision.overlap + 1) * Math.abs(collision.axes.y);
else
this._pos.y = to.y;
} else {
this.pos = to.copy();
}
}
}
}
export default MovingActor;