feat(#8): modularizing
This commit is contained in:
parent
f300fe1be7
commit
32dd2ad599
11 changed files with 271 additions and 94 deletions
12
modules/game-objects/camera.js
Normal file
12
modules/game-objects/camera.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
import { GameObject } from "./game-object.js";
|
||||
|
||||
export class Camera extends GameObject {
|
||||
constructor({ map, x = 0, y = 0, width = 320, height = 240 }) {
|
||||
super({ x, y });
|
||||
this.map = map;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
}
|
50
modules/game-objects/canvas-resizer.js
Normal file
50
modules/game-objects/canvas-resizer.js
Normal file
|
@ -0,0 +1,50 @@
|
|||
import { GameObject } from "./game-object.js";
|
||||
|
||||
export class CanvasResizer extends GameObject {
|
||||
/**
|
||||
* Creates a new instance of `CanvasResizer` class.
|
||||
* @param {Object} config - The configuration options for the class.
|
||||
* @param {HTMLCanvasElement} config.canvas - The canvas element to resize.
|
||||
* @param {number} config.width - The native width.
|
||||
* @param {number} config.height - The native height.
|
||||
* @param {number} config.percentage - The percentage of the screen size to use for the canvas.
|
||||
*/
|
||||
constructor({ canvas, width, height, percentage }) {
|
||||
super();
|
||||
this.canvas = canvas;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.percentage = percentage;
|
||||
|
||||
this.canvas.width = this.width;
|
||||
this.canvas.height = this.height;
|
||||
}
|
||||
|
||||
load() {
|
||||
if (this.loaded) {
|
||||
return;
|
||||
}
|
||||
return new Promise((resolve) => {
|
||||
["load", "resize"].map((item) =>
|
||||
window.addEventListener(item, () => {
|
||||
this._resize();
|
||||
if (item === "load") {
|
||||
resolve();
|
||||
this.loaded = true;
|
||||
}
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
_resize() {
|
||||
let canvasWidth = Math.floor(window.innerWidth * this.percentage);
|
||||
let canvasHeight = Math.floor(canvasWidth / (this.width / this.height));
|
||||
if (canvasHeight >= window.innerHeight * this.percentage) {
|
||||
canvasHeight = Math.floor(window.innerHeight * this.percentage);
|
||||
canvasWidth = Math.floor(canvasHeight / (this.height / this.width));
|
||||
}
|
||||
this.canvas.style.width = canvasWidth + "px";
|
||||
this.canvas.style.height = canvasHeight + "px";
|
||||
}
|
||||
}
|
40
modules/game-objects/debug.js
Normal file
40
modules/game-objects/debug.js
Normal file
|
@ -0,0 +1,40 @@
|
|||
import { COLS, ROWS, TILE_SIZE } from "../constants.js";
|
||||
import { GameObject } from "./game-object.js";
|
||||
|
||||
export class Debug extends GameObject {
|
||||
constructor({ debug = false }) {
|
||||
super();
|
||||
this.debug = debug;
|
||||
this.fps = 0;
|
||||
}
|
||||
|
||||
toggle() {
|
||||
this.debug = !this.debug;
|
||||
}
|
||||
|
||||
update(delta) {
|
||||
this.fps = Math.floor(1 / delta);
|
||||
}
|
||||
|
||||
render(ctx) {
|
||||
if (!this.debug) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (let row = 0; row < ROWS; row++) {
|
||||
for (let col = 0; col < COLS; col++) {
|
||||
ctx.strokeRect(col * TILE_SIZE, row * TILE_SIZE, TILE_SIZE, TILE_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
ctx.fillStyle = "Red";
|
||||
ctx.font = "normal 16pt Arial";
|
||||
ctx.fillText(this.fps + " fps", 10, 26);
|
||||
}
|
||||
|
||||
onMouseClick(elementId) {
|
||||
if (elementId === "debug") {
|
||||
this.toggle();
|
||||
}
|
||||
}
|
||||
}
|
50
modules/game-objects/game-object.js
Normal file
50
modules/game-objects/game-object.js
Normal file
|
@ -0,0 +1,50 @@
|
|||
export class GameObject {
|
||||
/**
|
||||
* Initializes a new instance of the GameObject class.
|
||||
*
|
||||
* @param {Object} options - An object containing the initial properties of the game object.
|
||||
* @param {number} [options.x=0] - The initial x-coordinate of the game object.
|
||||
* @param {number} [options.y=0] - The initial y-coordinate of the game object.
|
||||
* @param {GameObject[]} [options.gameObjects=[]] - An array of child game objects.
|
||||
*/
|
||||
constructor(options = {}) {
|
||||
const { x = 0, y = 0, gameObjects = [] } = options;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.gameObjects = gameObjects;
|
||||
}
|
||||
|
||||
async load() {
|
||||
await Promise.all(
|
||||
this.gameObjects.map((item) => {
|
||||
item.load();
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
update(delta) {
|
||||
this.gameObjects.forEach((item) => {
|
||||
item.update(delta);
|
||||
});
|
||||
}
|
||||
|
||||
render(ctx) {
|
||||
this.gameObjects.forEach((item) => {
|
||||
item.render(ctx);
|
||||
});
|
||||
}
|
||||
|
||||
onKeyReleased(key) {
|
||||
this.gameObjects.forEach((item) => {
|
||||
item.onKeyReleased(key);
|
||||
});
|
||||
}
|
||||
|
||||
onMouseClick(elementId) {
|
||||
this.gameObjects.forEach((item) => {
|
||||
item.onMouseClick(elementId);
|
||||
});
|
||||
}
|
||||
|
||||
onCollide() {}
|
||||
}
|
6
modules/game-objects/index.js
Normal file
6
modules/game-objects/index.js
Normal file
|
@ -0,0 +1,6 @@
|
|||
export { Camera } from "./camera.js";
|
||||
export { CanvasResizer } from "./canvas-resizer.js";
|
||||
export { Debug } from "./debug.js";
|
||||
export { GameObject } from "./game-object.js";
|
||||
export { MapManagement } from "./map-management.js";
|
||||
export { Map } from "./map.js";
|
47
modules/game-objects/map-management.js
Normal file
47
modules/game-objects/map-management.js
Normal file
|
@ -0,0 +1,47 @@
|
|||
import { GameObject } from "./game-object.js";
|
||||
import { Map } from "./map.js";
|
||||
|
||||
export class MapManagement extends GameObject {
|
||||
constructor({ maps = [] }) {
|
||||
super();
|
||||
this.gameObjects = maps.map((item) => new Map(item));
|
||||
this.elementsId = this.gameObjects.map((item) => item.elementId);
|
||||
}
|
||||
|
||||
get selected() {
|
||||
return this.gameObjects.find((item) => item.selected);
|
||||
}
|
||||
|
||||
set selected(name) {
|
||||
this.gameObjects.forEach((item) => {
|
||||
item.selected = item.name === name;
|
||||
});
|
||||
}
|
||||
|
||||
update(delta) {
|
||||
this.gameObjects.forEach((item) => {
|
||||
if (item.selected) {
|
||||
item.update(delta);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
render(ctx) {
|
||||
this.gameObjects.forEach((item) => {
|
||||
if (item.selected) {
|
||||
item.render(ctx);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onMouseClick(elementId) {
|
||||
if (
|
||||
!this.elementsId.includes(elementId) ||
|
||||
this.selected.elementId === elementId
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const map = this.gameObjects.find((item) => item.elementId === elementId);
|
||||
this.selected = map.name;
|
||||
}
|
||||
}
|
46
modules/game-objects/map.js
Normal file
46
modules/game-objects/map.js
Normal file
|
@ -0,0 +1,46 @@
|
|||
import { COLS, ROWS, TILE_SIZE } from "../constants.js";
|
||||
import { GameObject } from "./game-object.js";
|
||||
|
||||
export class Map extends GameObject {
|
||||
constructor({ name, imageId, elementId, selected = false }) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.imageId = imageId;
|
||||
this.image = document.getElementById(imageId);
|
||||
this.selected = selected;
|
||||
this.elementId = elementId;
|
||||
}
|
||||
|
||||
async load() {
|
||||
const level = await fetch("/resources/" + this.name + ".json");
|
||||
this.level = await level.json();
|
||||
return true;
|
||||
}
|
||||
|
||||
render(ctx) {
|
||||
if (!this.level) {
|
||||
return;
|
||||
}
|
||||
const levelImage = this.image;
|
||||
const level = this.level;
|
||||
const layer = level.layers[0];
|
||||
const data = layer.data;
|
||||
|
||||
for (let row = 0; row < ROWS; row++) {
|
||||
for (let col = 0; col < COLS; col++) {
|
||||
const tile = data[row * COLS + col] - 1;
|
||||
ctx.drawImage(
|
||||
levelImage,
|
||||
(tile * TILE_SIZE) % levelImage.width,
|
||||
Math.floor((tile * TILE_SIZE) / levelImage.width) * TILE_SIZE,
|
||||
TILE_SIZE,
|
||||
TILE_SIZE,
|
||||
col * TILE_SIZE,
|
||||
row * TILE_SIZE,
|
||||
TILE_SIZE,
|
||||
TILE_SIZE
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue