import { config } from '../config';
/**
* Entity Renderer
* @class
* @category Game
*/
export class Renderer
{
/**
* Render the entity on the canvas.
*
* This method is called on every frame/repaint. It checks to see if the entity render state
* is active, and checks the entity type to apply specified behaviour and styles.
*
* @param {CanvasRenderingContext2D} context - the canvas context for rendering.
* @param {Object} entity - the entity to render
*
* @returns {void}
*/
static render (entity, context) {
if (entity.sleep) {
return;
}
if (entity.type === 'pickup') {
context.shadowBlur = entity.glow;
context.shadowColor = entity.color;
const size = config.cell.size / 2;
if (entity.image.complete) {
context.drawImage(entity.image, entity.x, entity.y, size, size);
} else {
entity.image.onload = () => context.drawImage(entity.image, entity.x, entity.y, size, size);
}
} else {
Renderer.beginRotationOffset(context, entity.x, entity.y, entity.angle);
if (! entity.dead) {
entity.type === 'enemy'
? Renderer.enemy(context, entity.position, entity.color)
: Renderer.player(context, entity.position);
} else {
entity.type === 'enemy'
? Renderer.deadEnemy(context, entity.color)
: Renderer.deadPlayer(context);
}
Renderer.endRotationOffset(context, entity.x, entity.y, entity.angle);
Renderer.health(context, entity.x, entity.y, entity.health);
}
}
/**
* Calculate offset and begin rotating entity to given angle at position.
*
* @param {CanvasRenderingContext2D} context - the canvas context for rendering
* @param {number} x - the entity x-coordinate
* @param {number} y - the entity y-coordinate
* @param {number} angle the angle to rotate on the canvas
*
* @returns {void}
*/
static beginRotationOffset (context, x, y, angle) {
context.translate(-(-x + context.canvas.width / 2), -(-y + context.canvas.height / 2));
context.translate(context.canvas.width / 2, context.canvas.height / 2);
context.rotate(angle);
}
/**
* Stop rotating entity to given angle at position.
*
* @param {CanvasRenderingContext2D} context - the canvas context for rendering
* @param {number} x - the entity x-coordinate
* @param {number} y - the entity y-coordinate
* @param {number} angle the angle to rotate on the canvas
*
* @returns {void}
*/
static endRotationOffset (context, x, y, angle) {
context.rotate(-angle);
context.translate(-context.canvas.width / 2, -context.canvas.height / 2);
context.translate(+(-x + context.canvas.width / 2), +(-y + context.canvas.height / 2));
}
/**
* Draw the player entity.
*
* @param {CanvasRenderingContext2D} context - the canvas context for rendering
* @param {number} position - the entity's position for feet animation
*
* @returns {void}
*/
static player (context, position) {
context.shadowBlur = 5;
context.shadowColor = 'white';
// left foot
context.beginPath();
context.rect(20, -20 + (position * 35), 25, 40);
context.fillStyle = '#454B1B';
context.fill();
// right foot
context.beginPath();
context.rect(-40, -20 + (position * -35), 25, 40);
context.fillStyle = '#454B1B';
context.fill();
// left hand
context.rotate(30 * Math.PI / 180);
context.beginPath();
context.rect(40, -10, 20, 80);
context.fillStyle = '#7C815F';
context.fill();
context.rotate(-30 * Math.PI / 180);
// right hand
context.rotate(-50 * Math.PI / 180);
context.beginPath();
context.rect(-55, -20, 20, 45);
context.fillStyle = '#53777A';
context.fill();
context.rotate(50 * Math.PI / 180);
// left torso
context.beginPath();
context.rect(-60, - 30, 120, 60);
context.fillStyle = '#53777A';
context.fill();
// backpack
context.beginPath();
context.rect(-27, -47, 50, 50);
context.fillStyle = '#134F5C';
context.fill();
// right torso
context.beginPath();
context.rect(-60, - 30, 80, 60);
context.fillStyle = '#7C815F';
context.fill();
// gun
context.beginPath();
context.rect(-12.5, 30, 25, 70);
context.fillStyle = 'gray';
context.fill();
// head
context.beginPath();
context.arc(0, 0, 40, 0, 2 * Math.PI);
context.fillStyle = '#F1D4AF';
context.fill();
// hair
context.beginPath();
context.arc(0, 0, 22, 0, 2 * Math.PI);
context.fillStyle = 'rgba(58,35,0,0.5)';
context.fill();
// let sunglasses
context.beginPath();
context.rect(6, 31, 18, 7);
context.fillStyle = '#222222';
context.fill();
// bridge
context.beginPath();
context.rect(-8, 32, 15, 3);
context.fillStyle = '#222222';
context.fill();
// right sunglasses
context.beginPath();
context.rect(-24, 31, 18, 7);
context.fillStyle = '#222222';
context.fill();
// // left soulder
// context.beginPath();
// context.arc(49, 15, 6, 0, 2 * Math.PI);
// context.fillStyle = '#7C815F';
// context.fill();
// // right shoulder
// context.beginPath();
// context.arc(-49, 15, 6, 0, 2 * Math.PI);
// context.fillStyle = '#53777A';
// context.fill();
// helmet
context.rotate(-180 * Math.PI / 180);
context.beginPath();
context.arc(0, -6, 44, 6, 180 * Math.PI / 180);
context.fillStyle = '#454B1B';
context.fill();
context.rotate(180 * Math.PI / 180);
}
/**
* Draw dead player.
*
* @param {CanvasRenderingContext2D} context - the canvas context for rendering
* @returns {void}
*/
static deadPlayer (context) {
// left foot
context.beginPath();
context.rect(30, 20, 25, 40);
context.fillStyle = '#454B1B';
context.fill();
// right foot
context.beginPath();
context.rect(-25, -30 -35, 25, 40);
context.fillStyle = '#454B1B';
context.fill();
// left hand
context.rotate(25 * Math.PI / 180);
context.beginPath();
context.rect(40, -5, 20, 80);
context.fillStyle = '#C02942';
context.fill();
context.rotate(-25 * Math.PI / 180);
// right hand
context.rotate(-60 * Math.PI / 180);
context.beginPath();
context.rect(-40, 20, 20, 45);
context.fillStyle = '#C02942';
context.fill();
context.rotate(60 * Math.PI / 180);
// torso
context.beginPath();
context.rect(-60, - 30, 120, 60);
context.fillStyle = '#53777A';
context.fill();
// head
context.beginPath();
context.arc(20, 10, 35, 0, 2 * Math.PI);
context.fillStyle = '#F1D4AF';
context.fill();
// hair
context.rotate(-170 * Math.PI / 180);
context.beginPath();
context.arc(0, 0, 44, 0, 180 * Math.PI / 180);
context.fillStyle = '#4d2600';
context.fill();
context.rotate(170 * Math.PI / 180);
}
/**
* Draw enemy.
*
* @param {CanvasRenderingContext2D} context - the canvas context for rendering
* @param {number} position - the entity's position for feet animation
* @param {Object} color - the colors for the components
*
* @returns {void}
*/
static enemy (context, position, color) {
context.shadowBlur = 10;
context.shadowColor = '#8fce00';
// left foot
context.beginPath();
context.rect(20, -20 + (position * 35), 25, 40);
context.fillStyle = color.feet;
context.fill();
// right foot
context.beginPath();
context.rect(-40, -20 + (position * -35), 25, 40);
context.fillStyle = color.feet;
context.fill();
// left hand
context.beginPath();
context.rect(-50, -10, 20, 90);
context.fillStyle = color.hands;
context.fill();
// right hand
context.beginPath();
context.rect(30, -10, 20, 85);
context.fillStyle = color.hands;
context.fill();
// torso
context.beginPath();
context.rect(-60, - 30, 120, 60);
context.fillStyle = color.torso;
context.fill();
// head
context.beginPath();
context.arc(0, 0, 40, 0, 2 * Math.PI);
context.fillStyle = '#CFF09E';
context.fill();
// hair
context.rotate(-180 * Math.PI / 180);
context.beginPath();
context.arc(0, 0, 37, 0, 180 * Math.PI / 180);
context.fillStyle = '#880808';
context.fill();
context.rotate(180 * Math.PI / 180);
}
/**
* Draw dead enemy.
*
* @param {CanvasRenderingContext2D} context - the canvas context for rendering
* @param {Object} color - the colors for the components
*
* @returns {void}
*/
static deadEnemy (context, color) {
// left foot
context.beginPath();
context.rect(52, -30, 25, 40);
context.fillStyle = color.feet;
context.fill();
// right foot
context.beginPath();
context.rect(26, -40, 25, 40);
context.fillStyle = color.feet;
context.fill();
// left hand
context.beginPath();
context.rect(-25, 35, 20, 90);
context.fillStyle = color.hands;
context.fill();
// right hand
context.beginPath();
context.rect(35, -40, 20, 85);
context.fillStyle = color.hands;
context.fill();
// torso
context.beginPath();
context.rect(-42, -20, 120, 60);
context.fillStyle = color.torso;
context.fill();
// head
context.beginPath();
context.arc(10, 5, 35, 0, 2 * Math.PI);
context.fillStyle = '#CFF09E';
context.fill();
// hair
context.rotate(-170 * Math.PI / 180);
context.beginPath();
context.arc(0, 0, 25, 0, 180 * Math.PI / 180);
context.fillStyle = '#4d2600';
context.fill();
context.rotate(170 * Math.PI / 180);
}
/**
* Draw entity health bar.
*
* @param {CanvasRenderingContext2D} context - the canvas context for rendering
* @param {number} x - the entity x-coordinate
* @param {number} y - the entity y-coordinate
* @param {number} health - the entity's health value
*
* @returns {void}
*/
static health (context, x, y, health) {
context.beginPath();
context.rect(x - 50, y + 60, 100, 5);
context.strokeStyle = 'black';
context.stroke();
let color;
if (health <= 35) {
color = 'red';
} else if (health <= 75) {
color = 'orange';
} else {
color = '#50ffb0';
}
context.beginPath();
context.rect(x - 50, y + 60, health, 5);
context.fillStyle = color;
context.fill();
}
}
Source