Skip to content

Instantly share code, notes, and snippets.

@al-arz
Created August 22, 2024 13:01
Show Gist options
  • Save al-arz/2d40ef777f1292e4b6504e1b9782564e to your computer and use it in GitHub Desktop.
Save al-arz/2d40ef777f1292e4b6504e1b9782564e to your computer and use it in GitHub Desktop.
An excerpt of player movement processing logic in a turn-based roguelite game, utilizing chain of responisbility pattern.
// Somewhere within the main gameplay controller class
private processHeroMove(nextPos: GlobalGridCoords) {
const interaction = new InteractionHandler(gameState);
const movement = new MovementHandler(gameState);
const combat = new CombatHandler(gameState);
const start = interaction;
interaction.next = movement;
movement.next = combat;
start.process(nextPos);
}
// Handlers that can be chained to process player's move
export interface MoveHandler {
process(nextPos: GlobalGridCoords): void;
}
export abstract class BaseMoveHandler implements MoveHandler {
protected dungeon: Dungeon; // Game state object
public next: MoveHandler;
constructor(dungeon: Dungeon) {
this.dungeon = dungeon;
}
public process(nextPos: GlobalGridCoords) {
if (this.next) {
this.next.process(nextPos);
}
}
}
export class CombatHandler extends BaseMoveHandler {
constructor(dungeon: Dungeon) {
super(dungeon);
}
public process(nextPos: GlobalGridCoords): void {
const monsters = this.dungeon.findMonstersAround(this.dungeon.hero);
if (monsters.length > 0) {
EventBus.emit(DUNGEON_EVENTS.monstersContacted, monsters);
return;
} else {
super.process(nextPos);
}
}
}
export class InteractionHandler extends BaseMoveHandler {
constructor(dungeon: Dungeon) {
super(dungeon);
}
public process(nextPos: GlobalGridCoords): void {
const interactable = this.dungeon.findInteractable(nextPos);
if (interactable) {
const interactionResult = interactable.heroInteraction(this.dungeon.hero);
if (!interactionResult.move) {
return;
}
}
super.process(nextPos);
}
}
export class MovementHandler extends BaseMoveHandler {
constructor(dungeon: Dungeon) {
super(dungeon);
}
public process(nextPos: GlobalGridCoords): void {
const tileToMoveTo = dungeon.findTileToMove(dungeon.hero, nextPos);
if (tileToMoveTo) {
this.dungeon.hero.moveTo(nextPos);
EventBus.emit(PROGRESS_EVENTS.stepTaken);
EventBus.emit("PLAY_SOUND", "step");
EventBus.emit(DUNGEON_EVENTS.heroMoved);
}
super.process(nextPos);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment