ridder
Version:
A straightforward game engine for simple data-driven games in JavaScript
211 lines (210 loc) • 6.53 kB
JavaScript
import { getCameraPosition, getCameraShake, getCameraZoom } from "./camera.js";
import { canvas, ctx, scale } from "./canvas.js";
import { getFont } from "./fonts.js";
import { getSprite } from "./sprites.js";
import { getTexture } from "./textures.js";
import { toRadians } from "./utils.js";
const DEFAULT_LINE_SEGMENTS = [];
let background = "black";
let font = "16px sans-serif";
/**
* Clear the background using the set `background` color.
*
* @see {@link setBackgroundColor}
*/
export function clearBackground() {
ctx.resetTransform();
ctx.fillStyle = background;
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
/**
* Reset the transformation matrix, also known as the identity matrix.
*/
export function resetTransform() {
ctx.setTransform(scale.x, 0, 0, scale.y, 0, 0);
}
/**
* Move the origin of the transformation matrix by the given x and y values.
*/
export function translateTransform(x, y) {
ctx.translate(x, y);
}
/**
* Additionally scale the transformation matrix by the given x and y values.
*/
export function scaleTransform(x, y) {
ctx.scale(x, y);
}
/**
* Rotate the transformation matrix by the given degrees.
*/
export function rotateTransform(degrees) {
ctx.rotate(toRadians(degrees));
}
/**
* Add the camera transform (position, shake) to the current transformation matrix.
* @param scrollX - The scrolling factor for the x-axis, you can add a parallax effect by setting this to a value between 0 and 1.
* @param scrollY - The scrolling factor for the y-axis, you can add a parallax effect by setting this to a value between 0 and 1.
*/
export function applyCameraTransform(scrollX = 1, scrollY = 1) {
const camera = getCameraPosition();
const shake = getCameraShake();
const zoom = getCameraZoom();
const x = camera.x + shake.x / zoom;
const y = camera.y + shake.y / zoom;
ctx.scale(zoom, zoom);
ctx.translate(-x * scrollX, -y * scrollY);
}
/**
* Draw a texture from the cache onto the canvas.
*/
export function drawTexture(id, x, y) {
ctx.drawImage(getTexture(id), x, y);
}
/**
* Draw a sprite (a region within a texture) from the cache onto the canvas.
*/
export function drawSprite(id, x, y) {
const sprite = getSprite(id);
const texture = getTexture(sprite.textureId);
ctx.drawImage(texture, sprite.x, sprite.y, sprite.w, sprite.h, x, y, sprite.w, sprite.h);
}
/**
* Draw text onto the canvas.
* @param color - A color value, e.g. `white` or `#ffffff`
* @param align - The horizontal alignment of the text
* @param baseline - The vertical alignment of the text
*/
export function drawText(text, x, y, color = "white", align = "left", baseline = "top") {
ctx.font = font;
ctx.textAlign = align;
ctx.textBaseline = baseline;
ctx.fillStyle = color;
ctx.fillText(text, x, y);
}
/**
* Draw outlined text onto the canvas.
* @param color - A color value, e.g. `white` or `#ffffff`
* @param outlineColor - A color value, e.g. `white` or `#ffffff`
* @param outlineMode - The mode of the outline. Either "circle" or "square".
* @param align - The horizontal alignment of the text
* @param baseline - The vertical alignment of the text
*/
export function drawTextOutlined(text, x, y, color = "white", outlineColor = "black", outlineMode = "circle", align = "left", baseline = "top") {
drawText(text, x, y - 1, outlineColor, align, baseline);
drawText(text, x + 1, y, outlineColor, align, baseline);
drawText(text, x, y + 1, outlineColor, align, baseline);
drawText(text, x - 1, y, outlineColor, align, baseline);
if (outlineMode === "square") {
drawText(text, x - 1, y - 1, outlineColor, align, baseline);
drawText(text, x + 1, y - 1, outlineColor, align, baseline);
drawText(text, x + 1, y + 1, outlineColor, align, baseline);
drawText(text, x - 1, y + 1, outlineColor, align, baseline);
}
drawText(text, x, y, color, align, baseline);
}
/**
* Draw a rectangle onto the canvas.
*/
export function drawRect(x, y, w, h, color = "white", fill = false) {
if (fill) {
ctx.fillStyle = color;
ctx.fillRect(x, y, w, h);
}
else {
ctx.strokeStyle = color;
ctx.strokeRect(x, y, w, h);
}
}
/**
* Draw a rectangle onto the canvas.
*/
export function drawRectInstance(r, color = "white", fill = false) {
drawRect(r.x, r.y, r.w, r.h, color, fill);
}
/**
* Draw a circle onto the canvas.
*/
export function drawCircle(x, y, r, color = "white", fill = false) {
ctx.beginPath();
ctx.arc(x, y, r, 0, 2 * Math.PI);
ctx.closePath();
if (fill) {
ctx.fillStyle = color;
ctx.fill();
}
else {
ctx.strokeStyle = color;
ctx.stroke();
}
}
/**
* Draw a circle onto the canvas.
*/
export function drawCircleInstance(c, color = "white", fill = false) {
drawCircle(c.x, c.y, c.r, color, fill);
}
/**
* Draw a polygon onto the canvas.
*/
export function drawPolygon(x, y, points, color = "white", fill = false) {
if (points.length < 3)
return;
ctx.beginPath();
ctx.moveTo(x + points[0].x, y + points[0].y);
for (let i = 1; i < points.length; i++) {
ctx.lineTo(x + points[i].x, y + points[i].y);
}
ctx.closePath();
if (fill) {
ctx.fillStyle = color;
ctx.fill();
}
else {
ctx.strokeStyle = color;
ctx.stroke();
}
}
/**
* Draw a polygon onto the canvas.
*/
export function drawPolygonInstance(p, color = "white", fill = false) {
drawPolygon(p.x, p.y, p.calcPoints, color, fill);
}
/**
* Draw a line onto the canvas.
*/
export function drawLine(x1, y1, x2, y2, color = "white", segments = DEFAULT_LINE_SEGMENTS) {
ctx.beginPath();
ctx.setLineDash(segments);
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.strokeStyle = color;
ctx.stroke();
}
/**
* Set the background color of the canvas.
*/
export function setBackgroundColor(color) {
background = color;
}
/**
* Use a font from the cache for the upcoming text rendering.
*/
export function setFont(id) {
font = getFont(id);
}
/**
* Set the alpha for the upcoming drawings.
*/
export function setAlpha(alpha) {
ctx.globalAlpha = alpha;
}
/**
* Set the blend mode for the upcoming drawings.
*
* For an overview of blend modes, see the bottom of [this](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation) MDN page.
*/
export function setBlendMode(mode) {
ctx.globalCompositeOperation = mode;
}