Skip to content

Commit

Permalink
Merge pull request #179 from JernejHabjan/movement-system
Browse files Browse the repository at this point in the history
Movement system
  • Loading branch information
JernejHabjan authored Feb 11, 2024
2 parents df7bd2e + 796d1a7 commit 044adb9
Show file tree
Hide file tree
Showing 27 changed files with 829 additions and 266 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import { getSceneInitializers, getSceneService } from "../scenes/components/scene-component-helpers";
import { NavigationService } from "../scenes/services/navigation.service";
import { Vector2Simple } from "@fuzzy-waddle/api-interfaces";
import { filter, first } from "rxjs";

export function getGameObjectBounds(gameObject: Phaser.GameObjects.GameObject): Phaser.Geom.Rectangle | null {
const boundsComponent = gameObject as unknown as Phaser.GameObjects.Components.GetBounds;
if (boundsComponent.getBounds === undefined) return null;
Expand All @@ -9,3 +14,51 @@ export function getGameObjectDepth(gameObject: Phaser.GameObjects.GameObject): n
if (depthComponent.depth === undefined) return null;
return depthComponent.depth;
}

export function getGameObjectTransform(
gameObject: Phaser.GameObjects.GameObject
): Phaser.GameObjects.Components.Transform | null {
const transformComponent = gameObject as unknown as Phaser.GameObjects.Components.Transform;
if (transformComponent.x === undefined || transformComponent.y === undefined) return null;
return transformComponent;
}

export async function getGameObjectTileInNavigableRadius(
gameObject: Phaser.GameObjects.GameObject,
radius: number
): Promise<Vector2Simple | undefined> {
const navigationService = getSceneService(gameObject.scene, NavigationService);
if (!navigationService) throw new Error("NavigationService not found");

const currentTile = getGameObjectCurrentTile(gameObject);
if (!currentTile) return;
return await navigationService.randomTileInNavigableRadius(currentTile, radius);
}

export function getGameObjectTileInRadius(
gameObject: Phaser.GameObjects.GameObject,
radius: number
): Vector2Simple | undefined {
const navigationService = getSceneService(gameObject.scene, NavigationService);
if (!navigationService) throw new Error("NavigationService not found");

const currentTile = getGameObjectCurrentTile(gameObject);
if (!currentTile) return;
return navigationService.randomTileInRadius(currentTile, radius);
}

export function getGameObjectCurrentTile(gameObject: Phaser.GameObjects.GameObject): Vector2Simple | undefined {
const navigationService = getSceneService(gameObject.scene, NavigationService);
if (!navigationService) return;

return navigationService.getCenterTileCoordUnderObject(gameObject);
}

export function onScenePostCreate(scene: Phaser.Scene, callback: () => void, scope: any) {
getSceneInitializers(scene)
.postCreate.pipe(
filter((created) => created),
first()
)
.subscribe(() => callback.call(scope));
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,28 @@
import GameObject = Phaser.GameObjects.GameObject;
import { getGameObjectBounds, getGameObjectDepth } from "../../../data/game-object-helper";
import { getActorSystem } from "../../../data/actor-system";
import { MovementSystem } from "../../systems/movement.system";
import { Subscription } from "rxjs";
import Phaser from "phaser";

export class SelectableComponent {
private selected: boolean = false;
private selectionCircle!: any;
private selectionCircle!: Phaser.GameObjects.Graphics;
private actorMovedSubscription?: Subscription;
constructor(private readonly gameObject: GameObject) {
this.createSelectionCircle();
gameObject.once(Phaser.GameObjects.Events.DESTROY, this.destroy);
gameObject.once(Phaser.GameObjects.Events.ADDED_TO_SCENE, this.init);
}

private init = () => {
this.subscribeActorMove();
};

private subscribeActorMove() {
const movementSystem = getActorSystem(this.gameObject, MovementSystem);
if (!movementSystem) return;
this.actorMovedSubscription = movementSystem.actorMoved.subscribe(this.update);
}

private createSelectionCircle() {
Expand All @@ -32,11 +48,10 @@ export class SelectableComponent {
return this.selected;
}

update() {
// todo use
private update = () => {
this.setPosition();
this.setDepth();
}
};

private setPosition() {
const transform = this.gameObject as unknown as Phaser.GameObjects.Components.Transform;
Expand All @@ -51,5 +66,6 @@ export class SelectableComponent {

private destroy = () => {
this.selectionCircle.destroy();
this.actorMovedSubscription?.unsubscribe();
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,7 @@ export class HealthComponent {
}

setCurrentHealth(newHealth: number, damageInitiator?: Phaser.GameObjects.GameObject) {
if (this.currentHealth <= 0) {
return;
}
if (this.currentHealth <= 0) return;
this.currentHealth = newHealth;
this.healthChanged.emit(this.currentHealth);
if (this.currentHealth <= 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { HealthComponent } from "./health-component";
import { getActorComponent } from "../../../data/actor-component";
import { Subscription } from "rxjs";
import { getGameObjectBounds, getGameObjectDepth } from "../../../data/game-object-helper";
import { MovementSystem } from "../../systems/movement.system";
import { getActorSystem } from "../../../data/actor-system";

export class HealthUiComponent {
private healthComponent?: HealthComponent;
Expand All @@ -15,6 +17,7 @@ export class HealthUiComponent {
private orangeThreshold = 0.5;
private yellowThreshold = 0.7;
private changedSubscription?: Subscription;
private actorMovedSubscription?: Subscription;

private readonly healthColors = {
red: 0xff0000,
Expand Down Expand Up @@ -50,6 +53,7 @@ export class HealthUiComponent {
this.changedSubscription = this.healthComponent.armorChanged.subscribe(() => this.draw());
break;
}
this.subscribeActorMove();

//bar width should be 50% of gameObject width or min 25px
const bounds = getGameObjectBounds(this.gameObject);
Expand All @@ -60,6 +64,14 @@ export class HealthUiComponent {
this.draw();
}

private subscribeActorMove() {
const movementSystem = getActorSystem(this.gameObject, MovementSystem);
if (!movementSystem) return;
this.actorMovedSubscription = movementSystem.actorMoved.subscribe(() => {
this.draw();
});
}

private get percentage() {
if (!this.healthComponent) return 0;
switch (this.type) {
Expand All @@ -86,24 +98,17 @@ export class HealthUiComponent {
return [x, y];
}

private get barDepth() {
// set depth to be above player
return (getGameObjectDepth(this.gameObject) ?? 0) + 1;
}

/**
* move bar with player
* todo - listen to some event instead of updating every frame
* set depth to be above player
*/
update() {
this.bar.depth = this.barDepth;
const [x, y] = this.barXY;
this.bar.setPosition(x, y);
private get barDepth() {
return (getGameObjectDepth(this.gameObject) ?? 0) + 1;
}

destroy() {
this.bar.destroy();
this.changedSubscription?.unsubscribe();
this.actorMovedSubscription?.unsubscribe();
}

private draw() {
Expand Down Expand Up @@ -148,6 +153,11 @@ export class HealthUiComponent {
const barFilledWidth = Math.floor((this.barWidth - 2 * this.barBorder) * this.percentage);

this.bar.fillRect(x + this.barBorder, y + this.barBorder, barFilledWidth, this.barHeight - 2 * this.barBorder);
this.setBarDepth();
}

private setBarDepth() {
this.bar.depth = this.barDepth;
}

setVisibility(visibility: boolean) {
Expand Down
Loading

0 comments on commit 044adb9

Please sign in to comment.