import { Collision } from '../Collision';
import { config } from '../../config';
import { randomFromArray } from '../../util';
/**
* Grenade projectile handler.
* @class
* @category Game Ballistics
*/
export class Grenade
{
/**
* Create new grenade projectile.
*
* @constructor
* @param {CanvasRenderingContext2D} context - the canvas rendering context
* @param {Player} player - the player entity
* @param {number} i - grenade projectile spread index
*/
constructor (context, player, i) {
/**
* vectorX - the projectile vector x-coordinate
* @type {number}
*/
this.vectorX = Math.cos(player.angle + 90 * Math.PI / 180 + i * 5 * Math.PI / 180);
/**
* vectorY - the projectile vector y-coordinate
* @type {number}
*/
this.vectorY = Math.sin(player.angle + 90 * Math.PI / 180 + i * 5 * Math.PI / 180);
/**
* x - the projectile current x-coordinate
* @type {number}
*/
this.x = player.x + this.vectorX * config.cell.radius * 1.5;
/**
* y - the projectile current y-coordinate
* @type {number}
*/
this.y = player.y + this.vectorY * config.cell.radius * 1.5;
/**
* radius - the rendered projectile radius size
* @type {number}
*/
this.radius = 5;
/**
* bounds - the entity's bounds for intersection.
* @type {Object}
*/
this.bounds = {
x: this.x - this.radius,
y: this.y - this.radius,
width: this.radius * 2,
height: this.radius * 2
};
/**
* context - the canvas rendering context
* @type {CanvasRenderingContext2D}
*/
this.context = context;
/**
* frames - counter to control the rendering/update frequency
* @type {number}
*/
this.frames = 0;
/**
* markToDelete - determines whether or not the grenade should be rendered/updated
* @type {boolean}
*/
this.markToDelete = false;
}
/**
* Render the grenade projectile on the canvas.
*
* This is called every frame/repaint to render the bullet. Note that this
* is an animated entity, therefore the x,y coordinates will change on update.
*
* @param {array|string} color - the color(s) of the projectile.
*
* @returns {void}
*/
render (color) {
if (Array.isArray(color)) {
color = randomFromArray(color);
}
this.context.beginPath();
this.context.arc(this.x, this.y, this.radius, 0, 2 * Math.PI);
this.context.fillStyle = color;
this.context.fill();
}
/**
* Update the projectile data for bounds tracking, collision and cleanup.
*
* Updates the grenade's x,y coordinates depending on the vector coordinates and projectile
* dropoff value, checks frames to ensure the grenade should remain active, and checks for
* collision against walls to determine if the grenade should remain active. This is called
* every frame/repaint.
*
* @param {Wall[]} walls - the rendered walls
* @param {number} dropoff - the projectile dropoff rate
*
* @returns {void}
*/
update (walls, dropoff = 25) {
this.x += this.vectorX * dropoff;
this.y += this.vectorY * dropoff;
this.bounds.x = this.x - this.radius;
this.bounds.y = this.y - this.radius;
this.frames++;
if (this.frames > 15) {
this.markToDelete = true;
}
for (let i = 0; i < walls.length; i++) {
const wall = walls[i];
if (Collision.intersection(wall.bounds, this.bounds)) {
this.markToDelete = true;
}
}
}
}
Source