Skip to content

Commit e9be8f1

Browse files
committed
refactor: improve project structure and add JSDocs
- Refactored code across multiple files for better readability and maintainability. - Added JSDoc comments to enhance documentation and developer understanding. - Ensured consistency and clarity in the project's structure.
1 parent c3c8376 commit e9be8f1

10 files changed

+818
-124
lines changed

src/class/UI.class.ts

+36-39
Original file line numberDiff line numberDiff line change
@@ -15,72 +15,69 @@ export class UI implements IUI {
1515
liveImage: HTMLImageElement;
1616

1717
draw(ctx: CanvasRenderingContext2D, deltaTime: number) {
18+
const { game, fontSize, fontFamily, liveImage } = this;
19+
const { width, height, fontColor, lives, score, isGameOver, isGameReset } = game;
20+
1821
ctx.save();
1922
ctx.shadowOffsetX = 2;
2023
ctx.shadowOffsetY = 2;
2124
ctx.shadowColor = "white";
2225
ctx.shadowBlur = 0;
23-
ctx.font = `${this.fontSize}px ${this.fontFamily}`;
26+
ctx.font = `${fontSize}px ${fontFamily}`;
2427
ctx.textAlign = "left";
25-
ctx.fillStyle = this.game.fontColor;
26-
//debug score
27-
if (this.game.debug) ctx.fillText(`Score: ${this.game.score}`, 20, 85);
28-
// lives
29-
for (let index = 0; index < this.game.lives; index++) {
30-
ctx.drawImage(this.liveImage, 25 * index + 20, 20, 25, 25);
28+
ctx.fillStyle = fontColor;
29+
30+
// debug UI
31+
if (game.debug) {
32+
const fps = Math.round(1000 / deltaTime);
33+
ctx.fillText(`FPS: ${fps}`, game.width - 130, 60);
34+
ctx.fillText(`Time: ${(game.time / 1000).toFixed(1)}`, game.width - 130, 90);
35+
ctx.fillText(`Score: ${score}`, game.width - 130, 120);
3136
}
32-
//debug - FPS - TIMER
33-
if (this.game.debug) {
34-
//fps
35-
ctx.font = `${this.fontSize * 0.8}px Arial`;
36-
ctx.fillText(`FPS: ${Math.round(1000 / deltaTime)}`, this.game.width - 150, 40);
37-
//timer
38-
ctx.fillText(`Time: ${(this.game.time * 0.001).toFixed(1)}`, this.game.width - 150, 80);
37+
38+
// lives
39+
for (let index = 0; index < lives; index++) {
40+
ctx.drawImage(liveImage, 25 * index + 20, 20, 25, 25);
3941
}
42+
4043
//game reset
41-
if (this.game.isGameReset) {
44+
if (isGameReset) {
4245
hideMobileControls();
4346
toggleMenu("main-menu");
44-
ctx.clearRect(0, 0, this.game.width, this.game.height);
47+
ctx.clearRect(0, 0, width, height);
4548
}
4649

4750
//game over messages
48-
if (this.game.isGameOver) {
51+
if (isGameOver) {
4952
ctx.textAlign = "center";
50-
ctx.font = `${this.fontSize * 2}px ${this.fontFamily}`;
51-
if (this.game.score >= this.game.minScore && this.game.lives > 0) {
53+
ctx.font = `${fontSize * 2}px ${fontFamily}`;
54+
if (score >= game.minScore && lives > 0) {
5255
ctx.save();
5356
ctx.shadowColor = "rgba(192, 0, 0, 0.8)";
54-
ctx.fillText("Boo-yah", this.game.width * 0.5, this.game.height * 0.5 - 20);
55-
ctx.font = `${this.fontSize * 0.7}px ${this.fontFamily}`;
56-
ctx.fillText(
57-
"What are creatures of the night afraid of? YOU!!",
58-
this.game.width * 0.5,
59-
this.game.height * 0.5 + 20
60-
);
57+
ctx.fillText("Boo-yah", width * 0.5, height * 0.5 - 20);
58+
ctx.font = `${fontSize * 0.7}px ${fontFamily}`;
59+
ctx.fillText("What are creatures of the night afraid of? YOU!!", width * 0.5, height * 0.5 + 20);
6160
ctx.restore();
62-
hideMobileControls();
6361
const intervalId = setInterval(() => {
64-
this.game.stop();
65-
this.game.reset();
66-
this.game.isGameOver = false;
67-
ctx.clearRect(0, 0, this.game.width, this.game.height);
62+
game.stop();
63+
game.reset();
64+
game.isGameOver = false;
65+
ctx.clearRect(0, 0, width, height);
6866
toggleMenu("main-menu");
6967
clearInterval(intervalId);
7068
}, 3250);
7169
} else {
7270
ctx.save();
7371
ctx.shadowColor = "rgba(192, 0, 0, 0.8)";
74-
ctx.fillText("Love at first bite?", this.game.width * 0.5, this.game.height * 0.5 - 20);
75-
ctx.font = `${this.fontSize * 0.7}px ${this.fontFamily}`;
76-
ctx.fillText("Nope, better luck next time!", this.game.width * 0.5, this.game.height * 0.5 + 20);
72+
ctx.fillText("Love at first bite?", width * 0.5, height * 0.5 - 20);
73+
ctx.font = `${fontSize * 0.7}px ${fontFamily}`;
74+
ctx.fillText("Nope, better luck next time!", width * 0.5, height * 0.5 + 20);
7775
ctx.restore();
78-
hideMobileControls();
7976
const intervalId = setInterval(() => {
80-
this.game.stop();
81-
this.game.reset();
82-
this.game.isGameOver = false;
83-
ctx.clearRect(0, 0, this.game.width, this.game.height);
77+
game.stop();
78+
game.reset();
79+
game.isGameOver = false;
80+
ctx.clearRect(0, 0, width, height);
8481
toggleMenu("main-menu");
8582
clearInterval(intervalId);
8683
}, 3250);

src/class/collisionAnimation.class.ts

+42-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,37 @@ import { ICollisionAnimation, IGame, ISound } from "../types/shadowhound";
22
import { getImage } from "../utils/misc";
33
import { Explosion } from "./sounds.class";
44

5+
/**
6+
* Collision animation class.
7+
*
8+
* @class CollisionAnimation
9+
* @implements {ICollisionAnimation}
10+
* @property {IGame} game - The game object.
11+
* @property {HTMLImageElement} image - The image element for the collision animation.
12+
* @property {number} spriteWidth - The width of the collision animation sprite.
13+
* @property {number} spriteHeight - The height of the collision animation sprite.
14+
* @property {number} sizeModifier - The size modifier for the collision animation.
15+
* @property {number} width - The width of the collision animation.
16+
* @property {number} height - The height of the collision animation.
17+
* @property {number} y - The y position of the collision animation.
18+
* @property {number} x - The x position of the collision animation.
19+
* @property {number} frameX - The x position of the current frame of the collision animation.
20+
* @property {number} frameY - The y position of the current frame of the collision animation.
21+
* @property {number} fps - The frames per second of the collision animation.
22+
* @property {number} frameInterval - The frame interval of the collision animation in milliseconds.
23+
* @property {number} frameTimer - The frame timer of the collision animation.
24+
* @property {number} maxFrame - The maximum frame of the collision animation.
25+
* @property {boolean} markedForDelection - The flag to check if the collision animation is marked for deletion.
26+
* @property {ISound} sound - The sound effect for the collision animation.
27+
*/
528
export class CollisionAnimation implements ICollisionAnimation {
29+
/**
30+
* Constructor for the collision animation class.
31+
*
32+
* @param {IGame} game - The game object.
33+
* @param {number} x - The x position of the collision animation.
34+
* @param {number} y - The y position of the collision animation.
35+
*/
636
constructor(game: IGame, x: number, y: number) {
737
this.game = game;
838
this.image = getImage("collision");
@@ -32,15 +62,20 @@ export class CollisionAnimation implements ICollisionAnimation {
3262
height: number;
3363
y: number;
3464
x: number;
65+
maxFrame: number;
66+
markedForDelection: boolean;
3567
frameX: number;
3668
frameY: number;
3769
fps: number;
3870
frameInterval: number;
3971
frameTimer: number;
40-
maxFrame: number;
41-
markedForDelection: boolean;
4272
sound: ISound;
4373

74+
/**
75+
* Draws the collision animation.
76+
*
77+
* @param {CanvasRenderingContext2D} ctx - The canvas context.
78+
*/
4479
draw(ctx: CanvasRenderingContext2D) {
4580
ctx.drawImage(
4681
this.image,
@@ -55,6 +90,11 @@ export class CollisionAnimation implements ICollisionAnimation {
5590
);
5691
}
5792

93+
/**
94+
* Updates the collision animation.
95+
*
96+
* @param {number} deltaTime - The delta time.
97+
*/
5898
update(deltaTime: number) {
5999
this.x -= this.game.speed;
60100
if (this.frameX === 0) this.sound.start();

src/class/enemies.class.ts

+106-18
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,32 @@
1-
import { IClimbingEnemy, IEnemy, IFlyingEnemy, IGame } from "../types/shadowhound";
1+
import { IEnemy, IGame, IFlyingEnemy, IClimbingEnemy, IBoss } from "../types/shadowhound";
22
import { getImage } from "../utils/misc";
33
import { FireBall } from "./particles.class";
44

5+
/**
6+
* @class Enemy
7+
* @implements {IEnemy}
8+
* @property {IGame} game - The game object.
9+
* @property {number} width - The width of the enemy.
10+
* @property {number} height - The height of the enemy.
11+
* @property {number} x - The x position of the enemy.
12+
* @property {number} y - The y position of the enemy.
13+
* @property {HTMLImageElement} image - The image element for the enemy.
14+
* @property {number} speedX - The x speed of the enemy.
15+
* @property {number} speedY - The y speed of the enemy.
16+
* @property {number} maxFrame - The maximum frame of the enemy.
17+
* @property {number} frameX - The x position of the frame of the enemy.
18+
* @property {number} frameY - The y position of the frame of the enemy.
19+
* @property {number} fps - The frames per second of the enemy.
20+
* @property {number} frameInterval - The frame interval of the enemy in milliseconds.
21+
* @property {number} frameTimer - The frame timer of the enemy.
22+
* @property {boolean} markedForDeletion - The flag to check if the enemy is marked for deletion.
23+
* @property {number} lives - The lives of the enemy.
24+
*/
525
class Enemy implements IEnemy {
26+
/**
27+
* @constructor
28+
* @param {IGame} game - The game object.
29+
*/
630
constructor(game: IGame) {
731
this.game = game;
832
this.width = 0;
@@ -38,36 +62,50 @@ class Enemy implements IEnemy {
3862
markedForDeletion: boolean;
3963
lives: number;
4064

65+
/**
66+
* Updates the enemy.
67+
* @param {number} deltaTime - The delta time.
68+
*/
4169
update(deltaTime: number): void {
4270
this.x -= this.speedX + this.game.speed;
4371
this.y += this.speedY;
72+
73+
this.frameTimer += deltaTime;
74+
4475
if (this.frameTimer > this.frameInterval) {
4576
this.frameTimer = 0;
77+
4678
if (this.frameX < this.maxFrame) this.frameX++;
4779
else this.frameX = 0;
48-
} else this.frameTimer += deltaTime;
80+
}
4981

50-
// check if off screen
51-
if (this.x + this.width < 0) this.markedForDeletion = true;
82+
if (this.x + this.width < 0) {
83+
this.markedForDeletion = true;
84+
}
5285
}
5386

87+
/**
88+
* Draws the enemy.
89+
* @param {CanvasRenderingContext2D} ctx - The canvas context.
90+
*/
5491
draw(ctx: CanvasRenderingContext2D): void {
5592
if (this.game.debug) ctx.strokeRect(this.x, this.y, this.width, this.height);
56-
ctx.drawImage(
57-
this.image,
58-
this.frameX * this.width,
59-
0,
60-
this.width,
61-
this.height,
62-
this.x,
63-
this.y,
64-
this.width,
65-
this.height
66-
);
93+
ctx.drawImage(this.image, this.frameX * this.width, 0, this.width, this.height, this.x, this.y, this.width, this.height);
6794
}
6895
}
6996

97+
/**
98+
* @class FlyingEnemy
99+
* @extends {Enemy}
100+
* @implements {IFlyingEnemy}
101+
* @property {number} angle - The angle of the enemy.
102+
* @property {number} va - The vertical angle of the enemy.
103+
*/
70104
export class FlyingEnemy extends Enemy implements IFlyingEnemy {
105+
/**
106+
* @constructor
107+
* @param {IGame} game - The game object.
108+
*/
71109
constructor(game: IGame) {
72110
super(game);
73111
this.width = 60;
@@ -81,18 +119,31 @@ export class FlyingEnemy extends Enemy implements IFlyingEnemy {
81119
this.angle = 0;
82120
this.va = Math.random() * 0.1 + 0.1;
83121
}
84-
85122
angle: number;
86123
va: number;
87124

125+
/**
126+
* Updates the enemy.
127+
* @param {number} deltaTime - The delta time.
128+
*/
88129
update(deltaTime: number): void {
89130
super.update(deltaTime);
90131
this.angle += this.va;
91132
this.y += Math.sin(this.angle);
92133
}
93134
}
94135

136+
/**
137+
* @class GroundEnemy
138+
* @extends {Enemy}
139+
* @property {number} angle - The angle of the enemy.
140+
* @property {number} va - The vertical angle of the enemy.
141+
*/
95142
export class GroundEnemy extends Enemy {
143+
/**
144+
* @constructor
145+
* @param {IGame} game - The game object.
146+
*/
96147
constructor(game: IGame) {
97148
super(game);
98149
this.width = 60;
@@ -104,7 +155,18 @@ export class GroundEnemy extends Enemy {
104155
}
105156
}
106157

158+
/**
159+
* @class ClimbingEnemy
160+
* @extends {Enemy}
161+
* @implements {IClimbingEnemy}
162+
* @property {number} angle - The angle of the enemy.
163+
* @property {number} va - The vertical angle of the enemy.
164+
*/
107165
export class ClimbingEnemy extends Enemy implements IClimbingEnemy {
166+
/**
167+
* @constructor
168+
* @param {IGame} game - The game object.
169+
*/
108170
constructor(game: IGame) {
109171
super(game);
110172
this.width = 120;
@@ -116,12 +178,20 @@ export class ClimbingEnemy extends Enemy implements IClimbingEnemy {
116178
this.maxFrame = 5;
117179
}
118180

181+
/**
182+
* Updates the enemy.
183+
* @param {number} deltaTime - The delta time.
184+
*/
119185
update(deltaTime: number): void {
120186
super.update(deltaTime);
121187
if (this.y > this.game.height - this.height - this.game.groundMargin) this.speedY *= -1;
122188
if (this.y < -this.height) this.markedForDeletion = true;
123189
}
124190

191+
/**
192+
* Draws the enemy.
193+
* @param {CanvasRenderingContext2D} ctx - The canvas context.
194+
*/
125195
draw(ctx: CanvasRenderingContext2D): void {
126196
super.draw(ctx);
127197
ctx.beginPath();
@@ -131,7 +201,19 @@ export class ClimbingEnemy extends Enemy implements IClimbingEnemy {
131201
}
132202
}
133203

134-
export class Boss extends FlyingEnemy {
204+
/**
205+
* @class Boss
206+
* @extends {FlyingEnemy}
207+
* @property {number} attackTimer - The timer for the boss's attack.
208+
* @property {number} attackInterval - The interval for the boss's attack in milliseconds.
209+
* @property {number} lives - The lives of the boss.
210+
* @property {boolean} hit - The flag to check if the boss is hit.
211+
*/
212+
export class Boss extends FlyingEnemy implements IBoss {
213+
/**
214+
* @constructor
215+
* @param {IGame} game - The game object.
216+
*/
135217
constructor(game: IGame) {
136218
super(game);
137219
this.width = 238;
@@ -146,15 +228,21 @@ export class Boss extends FlyingEnemy {
146228

147229
attackTimer: number;
148230
attackInterval: number;
149-
lives: number;
150231
hit: boolean;
151232

233+
/**
234+
* Updates the enemy.
235+
* @param {number} deltaTime - The delta time.
236+
*/
152237
update(deltaTime: number): void {
153238
super.update(deltaTime);
154239
if (this.x < this.game.width - this.width - 50) this.x = this.game.width - this.width - 50;
155240
else this.speedX = 0;
156241
}
157242

243+
/**
244+
* Attacks the player.
245+
*/
158246
attack() {
159247
const playerCenterX = this.game.player.x + this.game.player.width / 2;
160248
const playerCenterY = this.game.player.y + this.game.player.height / 2;

0 commit comments

Comments
 (0)