UNPKG

@moderrkowo/jsgl

Version:

Client-side JavaScript library for creating web 2D games. Focusing at objective game.

417 lines (416 loc) 16.7 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Renderer = void 0; var Vector2_1 = require("../structs/Vector2"); var DrawSettings_1 = require("../structs/DrawSettings"); var MathUtils_1 = require("../utils/math/MathUtils"); var RotationStyle_1 = require("../enums/RotationStyle"); var Rotation_1 = require("../structs/Rotation"); /** * Class represents Game Renderer. * @group Important Classes */ var Renderer = /** @class */ (function () { /** * Constructs new Renderer. * @param handler The {@link Game} reference */ function Renderer(handler) { /** * How many pixels have one grid unit. */ this.gridSize = 0; /** * The decimal midpoint of parent element size. */ this.canvasParentSize = 1; this.handler = handler; } /** * Resizes canvas to parent element size by canvasParentSize (decimal midpoint). * @method * @example * renderer.resizeCanvas(); */ Renderer.prototype.resizeCanvas = function () { if (!(this.handler.canvas instanceof HTMLCanvasElement)) throw new Error('Cannot resize undefined canvas!'); var canvas = this.handler.canvas; var parent = canvas.parentElement; if (parent == null) throw new Error('Parent cannot be null!'); var maxWidth = parent.clientWidth; var maxHeight = parent.clientHeight; var width = (maxWidth * this.canvasParentSize) / this.handler.grid.x; var height = (maxHeight * this.canvasParentSize) / this.handler.grid.y; this.gridSize = Math.floor(Math.min(width, height)); this.canvasWidth = this.handler.grid.x * this.gridSize; this.canvasHeight = this.handler.grid.y * this.gridSize; }; Object.defineProperty(Renderer.prototype, "canvasWidth", { /** * Gets canvas width in pixels. */ get: function () { return this.handler.canvas.width; }, /** * Sets canvas width in pixels. * @param width The new width */ set: function (width) { this.handler.canvas.width = width; }, enumerable: false, configurable: true }); Object.defineProperty(Renderer.prototype, "canvasHeight", { /** * Gets canvas height in pixels. */ get: function () { return this.handler.canvas.height; }, /** * Sets canvas height in pixels. * @param height The new height */ set: function (height) { this.handler.canvas.height = height; }, enumerable: false, configurable: true }); Object.defineProperty(Renderer.prototype, "ctx", { /** * Gets the {@link CanvasRenderingContext2D}. */ get: function () { var context = this.handler.canvas.getContext('2d'); if (context == null) throw new Error('There was a problem during getting the context'); return context; }, enumerable: false, configurable: true }); Object.defineProperty(Renderer.prototype, "canvasSize", { /** * Gets the Vector2 of width and height in pixels. */ get: function () { return new Vector2_1.Vector2(this.canvasWidth, this.canvasHeight); }, enumerable: false, configurable: true }); /** * Scales number from client coordinate to grid coordinate. * @method * @param a - The client coordinate * @returns The scaled number * @example * const scaledToGrid = renderer.scale(5); */ Renderer.prototype.scale = function (a) { return a * this.gridSize; }; /** * Combines given draw settings with default draw settings. * @method * @param drawSettings - The given draw settings * @returns The combined draw settings * @example * const drawSettings = renderer.combineDrawSettings({ color: 'red' }); */ Renderer.prototype.combineDrawSettings = function (drawSettings) { return __assign(__assign({}, DrawSettings_1.defaultDrawSettings), drawSettings); }; /** * Sets canvas context properties to given settings. * @param drawSettings - The draw settings */ Renderer.prototype.setContextSettings = function (drawSettings) { var _a, _b, _c, _d; if (drawSettings.color !== undefined) this.ctx.fillStyle = drawSettings.color; if (drawSettings.borderColor !== undefined) this.ctx.strokeStyle = drawSettings.borderColor; if (drawSettings.borderSize !== undefined) this.ctx.lineWidth = this.scale(drawSettings.borderSize / 64); if (drawSettings.alpha !== undefined) this.ctx.globalAlpha = (0, MathUtils_1.Clamp01)(drawSettings.alpha); if (((_a = drawSettings.shadow) === null || _a === void 0 ? void 0 : _a.color) !== undefined) this.ctx.shadowColor = drawSettings.shadow.color; if (((_b = drawSettings.shadow) === null || _b === void 0 ? void 0 : _b.offsetX) !== undefined) this.ctx.shadowOffsetX = this.scale(drawSettings.shadow.offsetX); if (((_c = drawSettings.shadow) === null || _c === void 0 ? void 0 : _c.offsetY) !== undefined) this.ctx.shadowOffsetY = this.scale(drawSettings.shadow.offsetY); if (((_d = drawSettings.shadow) === null || _d === void 0 ? void 0 : _d.blur) !== undefined) this.ctx.shadowBlur = this.scale(drawSettings.shadow.blur); }; /** * Draws a rect. * @method * @param worldX - The X-coordinate * @param worldY - The Y-coordinate * @param worldWidth - The width * @param worldHeight - The height * @param drawSettings - The draw settings * @example * renderer.drawRectangle(5, 2, 1, 1, { color: 'green', border: true }); */ Renderer.prototype.drawRectangle = function (worldX, worldY, worldWidth, worldHeight, drawSettings) { drawSettings = this.combineDrawSettings(drawSettings); var dx = this.scale(worldX - this.handler.canvasViewOffset.x); var dy = this.scale(worldY - this.handler.canvasViewOffset.y); var dw = this.scale(worldWidth); var dh = this.scale(worldHeight); this.ctx.save(); this.ctx.translate(dx + dw / 2, dy + dh / 2); if (drawSettings.angle !== undefined) { if (drawSettings.rotationStyle === RotationStyle_1.RotationStyle.allAround) { this.ctx.rotate(Rotation_1.Rotation.ToRadians(drawSettings.angle)); } } this.ctx.translate(-dx - dw / 2, -dy - dh / 2); this.setContextSettings(drawSettings); // if (drawSettings.fill) this.ctx.fillRect(dx, dy, dw, dh); if (drawSettings.border) this.ctx.strokeRect(dx, dy, dw, dh); // this.ctx.restore(); }; /** * Draws a circle. * @method * @param worldX - The X-coordinate * @param worldY - The Y-coordinate * @param diameter - The diameter * @param drawSettings - The draw settings * @example * renderer.drawCircle(0, 0, 1, { color: 'yellow' }); */ Renderer.prototype.drawCircle = function (worldX, worldY, diameter, drawSettings) { drawSettings = this.combineDrawSettings(drawSettings); var dx = this.scale(worldX - this.handler.canvasViewOffset.x); var dy = this.scale(worldY - this.handler.canvasViewOffset.y); var dr = this.scale(diameter / 2); this.setContextSettings(drawSettings); // this.ctx.beginPath(); this.ctx.arc(dx + dr, dy + dr, dr, 0, 2 * Math.PI); this.ctx.closePath(); if (drawSettings.fill) this.ctx.fill(); if (drawSettings.border) this.ctx.stroke(); }; /** * Draws line from position to another position. * @method * @param fromWorldX - From X-coordinate * @param fromWorldY - From Y-coordinate * @param toWorldX - To X-coordinate * @param toWorldY - To Y-coordinate * @param drawSettings - The draw settings * @example * renderer.drawLine(2, 3, 3, 4); */ Renderer.prototype.drawLine = function (fromWorldX, fromWorldY, toWorldX, toWorldY, drawSettings) { drawSettings = this.combineDrawSettings(drawSettings); this.setContextSettings(drawSettings); this.ctx.beginPath(); this.ctx.moveTo(this.scale(fromWorldX - this.handler.canvasViewOffset.x), this.scale(fromWorldY - this.handler.canvasViewOffset.y)); this.ctx.lineTo(this.scale(toWorldX - this.handler.canvasViewOffset.x), this.scale(toWorldY - this.handler.canvasViewOffset.y)); this.ctx.closePath(); this.ctx.stroke(); }; /** * Draws arrow from position to another position. * @method * @param fromWorldX - From X-coordinate * @param fromWorldY - From Y-coordinate * @param toWorldX - To X-coordinate * @param toWorldY - To Y-coordinate * @param drawSettings - The draw settings * @example * renderer.drawArrow(2, 3, 3, 4); */ Renderer.prototype.drawArrow = function (fromWorldX, fromWorldY, toWorldX, toWorldY, drawSettings) { drawSettings = this.combineDrawSettings(drawSettings); // Scaling var size = this.gridSize / 16; this.ctx.lineWidth = this.gridSize / 64; this.setContextSettings(drawSettings); var p1 = new Vector2_1.Vector2((fromWorldX - this.handler.canvasViewOffset.x) * this.gridSize, (fromWorldY - this.handler.canvasViewOffset.y) * this.gridSize); var p2 = new Vector2_1.Vector2((toWorldX - this.handler.canvasViewOffset.x) * this.gridSize, (toWorldY - this.handler.canvasViewOffset.y) * this.gridSize); // Angle var angle = Math.atan2(p2.y - p1.y, p2.x - p1.x); var hyp = Math.sqrt((p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y)); // Rotate this.ctx.save(); this.ctx.translate(p1.x, p1.y); this.ctx.rotate(angle); // Line this.ctx.beginPath(); this.ctx.moveTo(0, 0); this.ctx.lineTo(hyp - size, 0); this.ctx.closePath(); this.ctx.stroke(); // Triangle this.ctx.beginPath(); this.ctx.lineTo(hyp - size, size); this.ctx.lineTo(hyp, 0); this.ctx.lineTo(hyp - size, -size); this.ctx.closePath(); this.ctx.fill(); this.ctx.restore(); }; /** * Clears the canvas. * @method * @example * renderer.clearFrame(); */ Renderer.prototype.clearFrame = function () { this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight); }; /** * Fills the canvas with color property from settings. * @param drawSettings - The settings * @deprecated */ Renderer.prototype.fillFrame = function (drawSettings) { drawSettings = this.combineDrawSettings(drawSettings); this.setContextSettings(drawSettings); this.ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight); }; /** * Fills canvas with image. * @param image - The image * @deprecated */ Renderer.prototype.fillImageFrame = function (image) { this.ctx.drawImage(image, 0, 0, this.canvasWidth, this.canvasHeight); }; /** * Fills canvas with content. * @method * @param content - The color, image or {@link DrawSettings} * @example * renderer.fill('white'); * renderer.fill({ color: 'white' }) * renderer.fill(game.GetImage('background')); */ Renderer.prototype.fill = function (content) { if (content instanceof HTMLCanvasElement) { this.setContextSettings(DrawSettings_1.defaultDrawSettings); this.ctx.drawImage(content, 0, 0, this.canvasWidth, this.canvasHeight); return; } else if (typeof content === 'string') { this.setContextSettings(this.combineDrawSettings({ color: content })); } else { this.setContextSettings(this.combineDrawSettings(content)); } this.ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight); }; /** * Draws image. * @method * @param image - The image * @param worldX - The X-coordinate * @param worldY - The Y-coordinate * @param worldWidth - The width * @param worldHeight - The height * @param drawSettings - The draw settings * @example * renderer.drawImage(game.GetImage('player'), 0, 0, 1, 1, { angle: 45 }); */ Renderer.prototype.drawImage = function (image, worldX, worldY, worldWidth, worldHeight, drawSettings) { drawSettings = this.combineDrawSettings(drawSettings); var dx = this.scale(worldX - this.handler.canvasViewOffset.x); var dy = this.scale(worldY - this.handler.canvasViewOffset.y); var dw = this.scale(worldWidth); var dh = this.scale(worldHeight); this.ctx.save(); this.ctx.translate(dx + dw / 2, dy + dh / 2); if (drawSettings.angle !== undefined) { if (drawSettings.rotationStyle === RotationStyle_1.RotationStyle.allAround) { this.ctx.rotate(Rotation_1.Rotation.ToRadians(drawSettings.angle)); } } this.ctx.translate(-dx - dw / 2, -dy - dh / 2); this.ctx.drawImage(image, dx, dy, dw, dh); this.ctx.restore(); }; /** * Draws sprite texture. * @method * @param sprite - The sprite * @returns is success? * @example * const exampleSprite = ...; * renderer.drawSprite(exampleSprite); */ Renderer.prototype.drawSprite = function (sprite) { if (sprite.texture === undefined || sprite.texture === null) { console.warn('The Sprite ', sprite, ' has not assigned texture!'); return false; } if (!(sprite.texture instanceof HTMLImageElement)) { console.warn("Texture ".concat(sprite.name, "[").concat(sprite.id, "] cannot be ").concat(typeof sprite.texture, "!")); return false; } this.drawImage(sprite.texture, sprite.transform.position.x, sprite.transform.position.y, sprite.transform.scale.x, sprite.transform.scale.y, { angle: sprite.transform.eulerAngles, rotationStyle: sprite.rotationStyle, }); return true; }; /** * Draws hitbox with direction arrow. * @method * @param clickableObject - The clickable game object * @example * const exampleClickableObject = ...; * renderer.drawHitbox(exampleClickableObject); */ Renderer.prototype.drawHitbox = function (clickableObject) { if (!clickableObject.showHitbox) return; var pos = clickableObject.transform.position; var center = clickableObject.transform.positionCenter; var scale = clickableObject.transform.scale; this.drawRectangle(pos.x, pos.y, scale.x, scale.y, { borderColor: 'red', fill: false, border: true, }); this.drawLine(pos.x, pos.y, pos.x + scale.x, pos.y + scale.y, { borderColor: 'red', }); this.drawLine(pos.x + scale.x, pos.y, pos.x, pos.y + scale.y, { borderColor: 'red', }); var angle = Rotation_1.Rotation.ToRadians(clickableObject.transform.eulerAngles); this.drawArrow(center.x, center.y, center.x + (scale.x / 2) * Math.cos(angle), center.y + (scale.y / 2) * Math.sin(angle), { color: 'red', borderColor: 'red' }); }; return Renderer; }()); exports.Renderer = Renderer;