Skip to content

Commit

Permalink
Add various small features (#50)
Browse files Browse the repository at this point in the history
* add particle background in the game scene

* Mouse now keep track of the scrolling of the page.

* Update the tutorial section of the game

* update readme service list

* add game shortcut
  • Loading branch information
MounirAia authored Sep 3, 2024
1 parent 6cd0794 commit 8d28b8c
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 11 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ Most of the drawbacks of the Service Locator relate to automated testing. Howeve
| **CollideManager** | Manages collisions between sprites that can collide | WaveManager, GeneratedSpriteManager |
| **EventManager** | Sprites can register for specific events and get notified when triggered | None |
| **UtilManager** | Provides a set of utility functions accessible throughout the code | None |
| **KeyboardManager** | Manage Keyboard Key Listening | None |
| **GameStatManager** | Manage Stat that are useful to keep track of during the game | None |

### Sprite

Expand Down
12 changes: 9 additions & 3 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,15 @@ <h1 class="header">Web Shoot'em UP</h1>
<canvas id="canvas" width="1280" height="720" style="background-color: #cccccc"></canvas>
<ul>
<li>Use 'wasd' keys (or zqsd in azerty keyboards) to move the player</li>
<li>Use the space bar to shoot</li>
<li>Press 'H' to buy skills</li>
<li>Press 'escape' to pause the game</li>
<li>Use the 'Space Bar' to shoot</li>
<li>Press 'H' to buy skills in game</li>
<li>
Press 'U', 'I', 'O', or 'P' to quickly upgrade <br /><br />
Special, Effect, Support Skills, or Player's Boost
</li>

<li>Press 'T' to toggle timer in game</li>
<li>Press 'Escape' to pause the game</li>
<li>Goal is to finish a 100 rounds as fast as possible</li>
</ul>
</div>
Expand Down
10 changes: 9 additions & 1 deletion src/Keyboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,11 @@ type PossibleCommands =
| 'OpenShopMenu'
| 'CloseShopMenu'
| 'CloseOptionMenu'
| 'ToggleInGameTimer';
| 'ToggleInGameTimer'
| 'UpgradeSpecialSkillInGameShortcut'
| 'UpgradeEffectSkillInGameShortcut'
| 'UpgradeSupportSkillInGameShortcut'
| 'UpgradeBoostInGameShortcut';
export interface IServiceKeyboardManager {
GetCommandState(parameters: { command: PossibleCommands }): Key;
}
Expand All @@ -189,6 +193,10 @@ export class ServiceKeyboardManager implements IServiceKeyboardManager {
this.commandsStates.set('CloseShopMenu', Keyboard['KeyH']);
this.commandsStates.set('CloseOptionMenu', Keyboard['Escape']);
this.commandsStates.set('ToggleInGameTimer', Keyboard['KeyT']);
this.commandsStates.set('UpgradeSpecialSkillInGameShortcut', Keyboard['KeyU']);
this.commandsStates.set('UpgradeEffectSkillInGameShortcut', Keyboard['KeyI']);
this.commandsStates.set('UpgradeSupportSkillInGameShortcut', Keyboard['KeyO']);
this.commandsStates.set('UpgradeBoostInGameShortcut', Keyboard['KeyP']);

ServiceLocator.AddService('KeyboardManager', this);
}
Expand Down
26 changes: 23 additions & 3 deletions src/Mouse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,12 @@ export class Mouse {
}

canvas.addEventListener('mousemove', (e) => {
const { clientX, clientY } = e;
const { pageX, pageY } = e;

Mouse.X = clientX - canvas.offsetLeft;
Mouse.Y = clientY - canvas.offsetTop;
const x = pageX - canvas.offsetLeft;
const y = pageY - canvas.offsetTop;
Mouse.X = x;
Mouse.Y = y;

Mouse.IsPressed = false;
});
Expand All @@ -50,3 +52,21 @@ canvas.addEventListener('mouseup', (e) => {
canvas.addEventListener('mousedown', (e) => {
if (e.button === 0) Mouse.IsPressed = true;
});

/* Prevent Mouse Scrolling When the Game is Focused */
// Function to prevent scrolling
function preventScroll(event) {
event.preventDefault(); // Prevent the default scroll behavior
}

// Enable scroll prevention on canvas click
canvas.addEventListener('click', () => {
document.addEventListener('wheel', preventScroll, { passive: false });
});

// Re-enable scrolling only when clicking outside the canvas
document.addEventListener('click', (event) => {
if (!canvas.contains(event.target as Node)) {
document.removeEventListener('wheel', preventScroll);
}
});
93 changes: 89 additions & 4 deletions src/Scenes/GameScene.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import { CANVA_SCALEX, CANVA_SCALEY, canvas, FRAME_RATE } from '../ScreenConstan
import { ServiceLocator } from '../ServiceLocator';
import { DrawGeneratedSpritesManager, UpdateGeneratedSpritesManager } from '../Sprites/GeneratedSpriteManager';
import { DrawPlayer, IServicePlayer, UpdatePlayer } from '../Sprites/Player';
import { PossibleSkillLevel, SkillsTypeName } from '../Sprites/PlayerSkills/Skills';
import { Sprite } from '../Sprites/Sprite';
import { GetSpriteStaticInformation } from '../SpriteStaticInformation/SpriteStaticInformationManager';
import { IServiceUtilManager } from '../UtilManager';
import { DrawWaveManager, IServiceWaveManager, UpdateWaveManager } from '../WaveManager/WaveManager';
import { BaseField } from './BaseUserInterface/BaseField';
Expand Down Expand Up @@ -416,8 +418,6 @@ class ParticleManager {
this.baseTimeBeforeNewParticles = (this.particleWidth * dt) / this.particleSpeed;
this.timeRemainingBeforeNewParticles = this.baseTimeBeforeNewParticles;

console.log(this.baseTimeBeforeNewParticles, this.particleSpeed, this.particleWidth);

const lines = Math.floor((320 * CANVA_SCALEX) / this.particleWidth);

for (let i = 0; i < lines; i++) {
Expand Down Expand Up @@ -446,8 +446,6 @@ class ParticleManager {
this.generateParticlesOnALine({ x: canvas.width });
this.timeRemainingBeforeNewParticles = this.baseTimeBeforeNewParticles;
}

console.log(this.particles.length);
}

public Draw(ctx: CanvasRenderingContext2D): void {
Expand Down Expand Up @@ -477,12 +475,97 @@ class ParticleManager {
}
}

class ShortcutSkillManager {
private skillPricePerLevel: Map<PossibleSkillLevel, number>;
private boostPrice: number;

constructor() {
/* TEMPORARY */
const rocketSprite = GetSpriteStaticInformation({ sprite: 'Rocket' });
const priceSkillLevel1 = rocketSprite.constant[0]['Skill Price'];
const priceSkillLevel2 = rocketSprite.constant[1]['Skill Price'];
const priceSkillLevel3 = rocketSprite.constant[2]['Skill Price'];
this.skillPricePerLevel = new Map([
[1, priceSkillLevel1],
[2, priceSkillLevel2],
[3, priceSkillLevel3],
]);

this.boostPrice = GetSpriteStaticInformation({ sprite: 'PlayerBoost' }).constant['Boost Price'];
}

Update(dt: number) {
const keyboardManager = ServiceLocator.GetService<IServiceKeyboardManager>('KeyboardManager');
// U for special skill
if (keyboardManager.GetCommandState({ command: 'UpgradeSpecialSkillInGameShortcut' }).IsPressed) {
this.quickUpgrade({ fieldType: 'special' });
}
// I for effect skill
if (keyboardManager.GetCommandState({ command: 'UpgradeEffectSkillInGameShortcut' }).IsPressed) {
this.quickUpgrade({ fieldType: 'effect' });
}
// O for support skill
if (keyboardManager.GetCommandState({ command: 'UpgradeSupportSkillInGameShortcut' }).IsPressed) {
this.quickUpgrade({ fieldType: 'support' });
}
// P for boost
if (keyboardManager.GetCommandState({ command: 'UpgradeBoostInGameShortcut' }).IsPressed) {
this.quickUpgrade({ fieldType: 'Boost' });
}
}

private quickUpgrade(parameters: { fieldType: SkillsTypeName | 'Boost' }) {
const { fieldType } = parameters;

if (fieldType === 'Boost') {
this.upgradeBoost();
} else {
this.upgradeSkill({ skillType: fieldType });
}
}

private upgradeBoost() {
const player = ServiceLocator.GetService<IServicePlayer>('Player');
let playerBalance = player.MoneyInWallet;

// 1) verify if the player has already reached the max number of boost
if (player.GetIsMaxNumberBoostAttained()) return;

// 2) verify if the player has enough money to buy the skill
if (playerBalance - this.boostPrice < 0) return;

player.MakeTransactionOnWallet(-this.boostPrice);

player.UpgradeBoost();
}

private upgradeSkill(parameters: { skillType: SkillsTypeName }) {
const { skillType } = parameters;
const player = ServiceLocator.GetService<IServicePlayer>('Player');
let playerBalance = player.MoneyInWallet;
const skillLevel = player.GetSkillLevel({ skillType: skillType });
const isMaxLevelReach = player.GetIsMaxLevelReachedForSpecificSkillType({ skillType: skillType });

// 1) Verify if the player did not reach the maximum level for this skill
if (isMaxLevelReach) return;

const selectedSkillPrice = this.skillPricePerLevel.get((skillLevel + 1) as PossibleSkillLevel)!;
// 2) verify if the player has enough money to buy the skill
if (playerBalance - selectedSkillPrice < 0) return;

player.MakeTransactionOnWallet(-selectedSkillPrice);

player.UpgradeSkillLevel({ skillType: skillType });
}
}

export class GameScene implements IScene {
private cityBackgroundManager: CityBackgroundManager;
private particleEffectOnMap: ParticleManager;
private userStateUI: UserStateUI;
private timerIsToggled: boolean;
private inGameTimer: InGameTimer;
private shortcutSkillManager: ShortcutSkillManager;

Load() {
this.timerIsToggled = false;
Expand Down Expand Up @@ -526,13 +609,15 @@ export class GameScene implements IScene {
this.particleEffectOnMap = new ParticleManager();
this.userStateUI = new UserStateUI();
this.inGameTimer = new InGameTimer();
this.shortcutSkillManager = new ShortcutSkillManager();
}

private updateUI(dt: number) {
this.cityBackgroundManager.Update(dt);
this.userStateUI.Update(dt);
this.inGameTimer.Update(dt);
this.particleEffectOnMap.Update(dt);
this.shortcutSkillManager.Update(dt);
}

private drawUI(ctx: CanvasRenderingContext2D) {
Expand Down
13 changes: 13 additions & 0 deletions src/Sprites/Player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export interface IServicePlayer {
UpgradeSkillLevel(parameters: { skillType: SkillsTypeName }): void; // Update a specific skill level
UpgradeBoost(): void;
GetIsMaxNumberBoostAttained(): boolean;
GetIsMaxLevelReachedForSpecificSkillType(parameters: { skillType: SkillsTypeName }): boolean;
MaxHealth: number;
CurrentHealth: number;
MoneyInWallet: number;
Expand Down Expand Up @@ -404,6 +405,18 @@ class Player extends Sprite implements IServicePlayer, ISpriteWithSpeed, ISprite
);
}

GetIsMaxLevelReachedForSpecificSkillType(parameters: { skillType: SkillsTypeName }): boolean {
const { skillType } = parameters;
if (skillType === 'special') {
return this.SpecialSkillLevel > 2;
} else if (skillType === 'effect') {
return this.EffectSkillLevel > 2;
} else if (skillType === 'support') {
return this.SupportSkillLevel > 2;
}
return false;
}

get CurrentHitbox(): RectangleHitbox[] {
return this.hitboxes;
}
Expand Down

0 comments on commit 8d28b8c

Please sign in to comment.