/**
* @license GPL-3.0-only
*
* @author Mark Mayes / mm-dev
*
*
* @module AddedLayer
*
* @description
* ## Draw added detail layers on top of some obstacles and sometimes the player
* **Measurements for details such as sizes, thicknesses etc are given as a proportion of the item radius.**
* - This allows the layers to scale with the different-sized items
* - A value of `1` is equal to the item radius
* - `_target` params will either be obstacles or the player
*/
import * as GAME from "./PD/GAME.js";
import { Display } from "./Display.js";
import { degreesToVector } from "./utils.js";
class AddedLayer {}
/**
* @function drawTriangles
* @static
*
* @description
* ##### Stylised cracks effect based on several random overlapping triangles
*
* @param {number} _x - X coordinate of the item centre
* @param {number} _y - Y coordinate of the item centre
* @param {object} _target - The item to draw on top of
* @param {object} _data
* @param {number} _data.color Main color
* @param {number} _data.thickness Line thickness
* @param {number} _data.triangle_ar Array of triangle points
*/
AddedLayer.drawTriangles = function (_x, _y, _target, _data) {
var i,
j,
vec,
x1,
y1,
x2,
y2,
trianglePoints = 3,
currentPoint,
currentTriangle_ar;
Display.ctx.beginPath();
for (i = 0; i < _data.triangle_ar.length; i++) {
currentTriangle_ar = _data.triangle_ar[i];
for (j = 0; j < trianglePoints; j++) {
currentPoint = currentTriangle_ar[j];
vec = degreesToVector(_target.rotation + currentPoint.degrees);
x1 = _x + vec.x * _target.radius * currentPoint.distance;
y1 = _y + vec.y * _target.radius * currentPoint.distance;
if (j === 0) {
Display.ctx.moveTo(x1, y1);
x2 = x1;
y2 = y1;
} else {
Display.ctx.lineTo(x1, y1);
}
}
Display.ctx.lineTo(x2, y2);
}
Display.ctx.lineWidth = Math.ceil(_data.thickness * _target.radius);
Display.ctx.lineCap = "butt";
Display.ctx.strokeStyle = _data.color;
Display.ctx.stroke();
};
/**
* @function drawDot
* @static
*
* @description
* ##### Simple dot/circle
*
* @param {number} _x - X coordinate of the item centre
* @param {number} _y - Y coordinate of the item centre
* @param {object} _target - The item to draw on top of
* @param {object} _data
* @param {number} _data.color Main color
* @param {number} _data.extension How far the dot extends from the centre
*/
AddedLayer.drawDot = function (_x, _y, _target, _data) {
Display.ctx.beginPath();
Display.ctx.arc(_x, _y, _data.extension * _target.radius, 0, GAME.PIx2);
if (_data.useDefaultStroke) {
Shape.defaultStrokeCurrentPath();
}
Display.ctx.fillStyle = _data.color;
Display.ctx.fill();
};
/**
* @function drawSpokes
* @static
*
* @description
* ##### Spokes eg for bicycle wheels
*
* @param {number} _x - X coordinate of the item centre
* @param {number} _y - Y coordinate of the item centre
* @param {object} _target - The item to draw on top of
* @param {object} _data
* @param {number} _data.color Main color
* @param {number} _data.thickness Spoke thickness
* @param {number} _data.extension How far the spokes extend from the centre
*/
AddedLayer.drawSpokes = function (_x, _y, _target, _data) {
var i,
vec,
angleStep = 360 / _data.total;
Display.ctx.lineWidth = Math.ceil(_data.thickness * _target.radius);
Display.ctx.lineCap = "butt";
Display.ctx.strokeStyle = _data.color;
Display.ctx.beginPath();
for (i = 0; i < _data.total; i++) {
Display.ctx.moveTo(_x, _y);
vec = degreesToVector(angleStep * i + _target.rotation);
Display.ctx.lineTo(
_x + vec.x * _target.radius * _data.extension,
_y + vec.y * _target.radius * _data.extension
);
}
Display.ctx.stroke();
};
/**
* @function drawStem
* @static
*
* @description
* ##### Stem for leaves
*
* @param {number} _x - X coordinate of the item centre
* @param {number} _y - Y coordinate of the item centre
* @param {object} _target - The item to draw on top of
* @param {object} _data
* @param {number} _data.color Main color
* @param {number} _data.offsetFront Distance from the centre of the front/tip
* @param {number} _data.offsetRear Distance from the centre of the rear/butt
* @param {number} _data.degreeSpanFront Thickness of the front part of the stem, given as degrees of arc
* @param {number} _data.degreeSpanRear Thickness of the rear part of the stem, given as degrees of arc
*/
AddedLayer.drawStem = function (_x, _y, _target, _data) {
var vec,
x1,
y1,
x2,
y2,
x3,
y3,
x4,
y4,
rearAngle = _target.rotation - 180;
Display.ctx.fillStyle = _data.color;
Display.ctx.beginPath();
vec = degreesToVector(_target.rotation - _data.degreeSpanFront / 2);
x1 = _x + vec.x * _target.radius * _data.offsetFront;
y1 = _y + vec.y * _target.radius * _data.offsetFront;
vec = degreesToVector(_target.rotation + _data.degreeSpanFront / 2);
x2 = _x + vec.x * _target.radius * _data.offsetFront;
y2 = _y + vec.y * _target.radius * _data.offsetFront;
vec = degreesToVector(rearAngle - _data.degreeSpanRear / 2);
x3 = _x + vec.x * _target.radius * _data.offsetRear;
y3 = _y + vec.y * _target.radius * _data.offsetRear;
vec = degreesToVector(rearAngle + _data.degreeSpanRear / 2);
x4 = _x + vec.x * _target.radius * _data.offsetRear;
y4 = _y + vec.y * _target.radius * _data.offsetRear;
Display.ctx.moveTo(x1, y1);
Display.ctx.lineTo(x2, y2);
Display.ctx.lineTo(x3, y3);
Display.ctx.lineTo(x4, y4);
Display.ctx.closePath();
Display.ctx.fill();
};
/**
* @function drawMouth
* @static
*
* @description
* ##### Mouth for character
*
* @param {number} _x - X coordinate of the item centre
* @param {number} _y - Y coordinate of the item centre
* @param {object} _target - The item to draw on top of
* @param {number} [_target.stretch] How far open the mouth is
* @param {object} _data
* @param {number} _data.color Main color
* @param {number} _data.offsetFromCenter Distance of the mouth from the centre of the target
*/
AddedLayer.drawMouth = function (_x, _y, _target, _data) {
var vec, x1, y1, x2, y2, x3, y3, x4, y4;
Display.ctx.lineWidth = _data.thickness * _target.radius;
Display.ctx.lineCap = "round";
Display.ctx.strokeStyle = _data.color;
Display.ctx.fillStyle = _data.color;
Display.ctx.beginPath();
vec = degreesToVector(_target.rotation - _data.degreeSpan / 2);
x1 = _x + vec.x * _target.radius * _data.offsetFromCenter;
y1 = _y + vec.y * _target.radius * _data.offsetFromCenter;
vec = degreesToVector(_target.rotation + _data.degreeSpan / 2);
x2 = _x + vec.x * _target.radius * _data.offsetFromCenter;
y2 = _y + vec.y * _target.radius * _data.offsetFromCenter;
vec = degreesToVector(_target.rotation);
x3 = _x + vec.x * _target.radius * _data.offsetFromCenter;
y3 = _y + vec.y * _target.radius * _data.offsetFromCenter;
Display.ctx.moveTo(x1, y1);
Display.ctx.bezierCurveTo(x1, y1, x3, y3, x2, y2);
if (_target.stretch) {
x4 = _x + vec.x * _target.radius * _data.offsetFromCenter * _target.stretch;
y4 = _y + vec.y * _target.radius * _data.offsetFromCenter * _target.stretch;
Display.ctx.moveTo(x1, y1);
Display.ctx.bezierCurveTo(x1, y1, x4, y4, x2, y2);
}
Display.ctx.fill();
};
/**
* @function drawStetson
* @static
*
* @description
* ##### Stetson-style hat
*
* @param {number} _x - X coordinate of the item centre
* @param {number} _y - Y coordinate of the item centre
* @param {object} _target - The item to draw on top of
* @param {object} _data
* @param {number} _data.offsetFromCenter Distance of the hat from the centre of the target
* @param {number} _data.thickness Overall size of the hat
* @param {number} _data.colorOuter Outer/rim colour
* @param {number} _data.colorInner Inner colour
*/
AddedLayer.drawStetson = function (_x, _y, _target, _data) {
var vec, x1, y1;
vec = degreesToVector(_target.rotation);
x1 = _x - vec.x * _target.radius * _data.offsetFromCenter;
y1 = _y - vec.y * _target.radius * _data.offsetFromCenter;
Display.ctx.beginPath();
Display.ctx.arc(x1, y1, _data.thickness * _target.radius, 0, GAME.PIx2);
Display.ctx.fillStyle = _data.colorOuter;
Display.ctx.fill();
Display.ctx.beginPath();
// TODO magic
Display.ctx.arc(x1, y1, (_data.thickness / 2) * _target.radius, 0, GAME.PIx2);
Display.ctx.fillStyle = _data.colorInner;
Display.ctx.fill();
};
/**
* @function drawBowler
* @static
*
* @description
* ##### Bowler-style hat
*
* @param {number} _x - X coordinate of the item centre
* @param {number} _y - Y coordinate of the item centre
* @param {object} _target - The item to draw on top of
* @param {object} _data
* @param {number} _data.offsetFromCenter Distance of the hat from the centre of the target
* @param {number} _data.thickness Overall size of the hat
* @param {number} _data.colorOuter Outer/rim colour
* @param {number} _data.colorInner Inner colour
*/
AddedLayer.drawBowler = function (_x, _y, _target, _data) {
var vec, x1, y1;
vec = degreesToVector(_target.rotation);
x1 = _x - vec.x * _target.radius * _data.offsetFromCenter;
y1 = _y - vec.y * _target.radius * _data.offsetFromCenter;
Display.ctx.beginPath();
Display.ctx.arc(x1, y1, _data.thickness * _target.radius, 0, GAME.PIx2);
Display.ctx.fillStyle = _data.colorOuter;
Display.ctx.fill();
vec = degreesToVector(_target.rotation);
x1 = _x - vec.x * _target.radius * _data.offsetFromCenter;
y1 = _y - vec.y * _target.radius * _data.offsetFromCenter;
Display.ctx.beginPath();
// TODO magic
Display.ctx.arc(
x1,
y1,
(_data.thickness / 1.4) * _target.radius,
0,
GAME.PIx2
);
Display.ctx.fillStyle = _data.colorInner;
Display.ctx.fill();
};
/**
* @function drawEyes
* @static
*
* @description
* ##### Eyes for a character
*
* @param {number} _x - X coordinate of the item centre
* @param {number} _y - Y coordinate of the item centre
* @param {object} _target - The item to draw on top of
* @param {object} _data
* @param {number} _data.color Main color
* @param {number} _data.offsetFromCenter Distance of eyes from the centre of the target
* @param {number} _data.degreeSpan How far apart the eyes are
* @param {number} _data.thickness Size of eyes
*/
AddedLayer.drawEyes = function (_x, _y, _target, _data) {
var vec, x1, y1;
Display.ctx.fillStyle = _data.color;
Display.ctx.beginPath();
vec = degreesToVector(_target.rotation - _data.degreeSpan / 2);
x1 = _x + vec.x * _target.radius * _data.offsetFromCenter;
y1 = _y + vec.y * _target.radius * _data.offsetFromCenter;
Display.ctx.arc(x1, y1, _data.thickness * _target.radius, 0, GAME.PIx2);
vec = degreesToVector(_target.rotation + _data.degreeSpan / 2);
x1 = _x + vec.x * _target.radius * _data.offsetFromCenter;
y1 = _y + vec.y * _target.radius * _data.offsetFromCenter;
Display.ctx.arc(x1, y1, _data.thickness * _target.radius, 0, GAME.PIx2);
Display.ctx.fill();
};
/**
* @function drawHelicopterTailPropeller
* @static
*
* @description
* ##### Rotating top-down propeller
*
* @param {number} _x - X coordinate of the item centre
* @param {number} _y - Y coordinate of the item centre
* @param {object} _target - The item to draw on top of
* @param {object} _data
* @param {number} _data.color Main color
* @param {number} _data.extension Span of propeller
* @param {number} _data.thickness Thickness of propeller
*/
AddedLayer.drawHelicopterTailPropeller = function (_x, _y, _target, _data) {
var vec;
Display.ctx.lineWidth = _data.thickness * _target.radius;
Display.ctx.lineCap = "butt";
Display.ctx.strokeStyle = _data.color;
Display.ctx.beginPath();
vec = degreesToVector(0 + _target.rotation);
Display.ctx.moveTo(_x, _y - vec.y * _target.radius * _data.extension);
Display.ctx.lineTo(_x, _y + vec.y * _target.radius * _data.extension);
Display.ctx.stroke();
};
export { AddedLayer };