Skip to content

Commit

Permalink
More rxjsification
Browse files Browse the repository at this point in the history
  • Loading branch information
Half-Shot committed Jan 16, 2025
1 parent 8174064 commit c532485
Show file tree
Hide file tree
Showing 34 changed files with 701 additions and 787 deletions.
4 changes: 1 addition & 3 deletions src/entities/phys/bazookaShell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ export class BazookaShell extends TimedExplosive {
BazookaShell.create(
parent,
gameWorld,
Coordinate.fromWorld(
new Vector2(state.tra.x, state.tra.y),
),
Coordinate.fromWorld(new Vector2(state.tra.x, state.tra.y)),
new Vector2(0, 0),
);
}
Expand Down
6 changes: 3 additions & 3 deletions src/entities/phys/homingMissile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ const ACTIVATION_TIME_MS = 65;
const ADJUSTMENT_TIME_MS = 6;
const forceMult = new Vector2(7, 7);

export interface HomingMissileRecordedState extends TimedExplosiveRecordedState {
export interface HomingMissileRecordedState
extends TimedExplosiveRecordedState {
target: {
x: number;
y: number;
}
};
hasActivated: boolean;
}


/**
* Homing missile that attempts to hit a point target.
*/
Expand Down
9 changes: 8 additions & 1 deletion src/entities/phys/physicsEntity.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { UPDATE_PRIORITY, Sprite, Point } from "pixi.js";
import { IPhysicalEntity, OnDamageOpts } from "../entity";
import { Water } from "../water";
import { BodyWireframe } from "../../mixins/bodyWireframe.";
import { BodyWireframe } from "../../mixins/bodyWireframe";
import globalFlags, { DebugLevel } from "../../flags";
import { IMediaInstance, Sound } from "@pixi/sound";
import { GameWorld, PIXELS_PER_METER, RapierPhysicsObject } from "../../world";
Expand All @@ -10,6 +10,7 @@ import { magnitude, MetersValue, mult, sub } from "../../utils";
import { AssetPack } from "../../assets";
import type { RecordedEntityState } from "../../state/model";
import { CameraLockPriority } from "../../camera";
import { BehaviorSubject, distinct, Observable } from "rxjs";

/**
* Abstract class for any physical object in the world. The
Expand Down Expand Up @@ -49,6 +50,9 @@ export abstract class PhysicsEntity<
return this.physObject.body;
}

private readonly bodyMoving: BehaviorSubject<boolean>;
public readonly bodyMoving$: Observable<boolean>;

constructor(
public readonly sprite: Sprite,
protected physObject: RapierPhysicsObject,
Expand All @@ -61,6 +65,8 @@ export abstract class PhysicsEntity<
globalFlags.on("toggleDebugView", (level: DebugLevel) => {
this.wireframe.enabled = level >= DebugLevel.BasicOverlay;
});
this.bodyMoving = new BehaviorSubject(false);
this.bodyMoving$ = this.bodyMoving.pipe(distinct());
}

destroy(): void {
Expand All @@ -73,6 +79,7 @@ export abstract class PhysicsEntity<
}

update(dt: number): void {
this.bodyMoving.next(this.body.isMoving());
const pos = this.physObject.body.translation();
const rotation = this.physObject.body.rotation() + this.rotationOffset;
this.sprite.updateTransform({
Expand Down
4 changes: 3 additions & 1 deletion src/entities/phys/timedExplosive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ export interface TimedExplosiveRecordedState extends RecordedEntityState {
* Any projectile type that can explode after a set timer. Implementing classes
* must include their own timer.
*/
export abstract class TimedExplosive<T extends TimedExplosiveRecordedState = TimedExplosiveRecordedState>
export abstract class TimedExplosive<
T extends TimedExplosiveRecordedState = TimedExplosiveRecordedState,
>
extends PhysicsEntity<T>
implements IWeaponEntity
{
Expand Down
44 changes: 23 additions & 21 deletions src/entities/playable/playable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ import { Viewport } from "pixi-viewport";
import { handleDamageInRadius } from "../../utils/damage";
import { RecordedEntityState } from "../../state/model";
import { HEALTH_CHANGE_TENSION_TIMER } from "../../consts";
import Logger from "../../log";

const logger = new Logger("Playable");
import { first, skip, Subscription } from "rxjs";

interface Opts {
explosionRadius: MetersValue;
Expand All @@ -44,24 +42,14 @@ export abstract class PlayableEntity extends PhysicsEntity<RecordedState> {
protected healthTextBox: Graphics;

private visibleHealth: number;
private healthTarget: number;
private healthChangeTensionTimer: number | null = null;

get position() {
return this.physObject.body.translation();
}

get health() {
return this.wormIdent.health;
}

set health(v: number) {
this.wormIdent.health = v;
logger.info(
`Worm (${this.wormIdent.uuid}, ${this.wormIdent.name}) health adjusted`,
);
// Potentially further delay until the player has stopped moving.
this.healthChangeTensionTimer = HEALTH_CHANGE_TENSION_TIMER;
}
private readonly healthSub: Subscription;

constructor(
sprite: Sprite,
Expand All @@ -82,15 +70,28 @@ export abstract class PlayableEntity extends PhysicsEntity<RecordedState> {
align: "center",
},
});
this.visibleHealth = -1;
this.healthTarget = -1;
this.healthText = new Text({
text: this.health,
text: this.visibleHealth,
style: {
...DefaultTextStyle,
fill: fg,
align: "center",
},
});
this.visibleHealth = this.health;

this.wormIdent.health$.pipe(first()).subscribe((h) => {
this.healthTarget = h;
this.visibleHealth = h;
this.healthText.text = h;
});

this.healthSub = this.wormIdent.health$.pipe(skip(1)).subscribe((h) => {
this.healthTarget = h;
// TODO: Potentially further delay until the player has stopped moving.
this.healthChangeTensionTimer = HEALTH_CHANGE_TENSION_TIMER;
});

this.nameText.position.set(0, -5);
this.healthTextBox = new Graphics();
Expand Down Expand Up @@ -174,12 +175,12 @@ export abstract class PlayableEntity extends PhysicsEntity<RecordedState> {

// If the timer is null, decrease the rendered health if nessacery.
if (this.healthChangeTensionTimer === null) {
if (this.visibleHealth > this.health) {
if (this.visibleHealth > this.healthTarget) {
this.onHealthTensionTimerExpired(true);
this.visibleHealth--;
this.healthText.text = this.visibleHealth;
this.setHealthTextPosition();
if (this.visibleHealth <= this.health) {
if (this.visibleHealth <= this.healthTarget) {
this.onHealthTensionTimerExpired(false);
}
}
Expand Down Expand Up @@ -213,7 +214,7 @@ export abstract class PlayableEntity extends PhysicsEntity<RecordedState> {
): boolean {
if (super.onCollision(otherEnt, contactPoint)) {
if (this.isSinking) {
this.wormIdent.health = 0;
this.wormIdent.setHealth(0);
this.healthTextBox.destroy();
this.physObject.body.setRotation(DEG_TO_RAD * 180, false);
}
Expand All @@ -235,7 +236,7 @@ export abstract class PlayableEntity extends PhysicsEntity<RecordedState> {
opts.maxDamage ?? 100,
Math.round((forceMag / 20) * this.opts.damageMultiplier),
);
this.health = Math.max(0, this.health - damage);
this.wormIdent.setHealth(this.wormIdent.health - damage);
const force = mult(
sub(point, bodyTranslation),
new Vector2(-forceMag, -forceMag),
Expand All @@ -251,6 +252,7 @@ export abstract class PlayableEntity extends PhysicsEntity<RecordedState> {
}

public destroy(): void {
this.healthSub.unsubscribe();
super.destroy();
if (!this.healthTextBox.destroyed) {
this.healthTextBox.destroy();
Expand Down
64 changes: 32 additions & 32 deletions src/entities/playable/testDummy.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Sprite, Texture, UPDATE_PRIORITY } from "pixi.js";
import { Sprite, Texture } from "pixi.js";
import { AssetPack } from "../../assets";
import {
collisionGroupBitmask,
Expand All @@ -16,6 +16,7 @@ import { WormInstance } from "../../logic/teams";
import { PlayableEntity } from "./playable";
import { Viewport } from "pixi-viewport";
import { EntityType } from "../type";
import { combineLatest, Subscription } from "rxjs";

/**
* Test dummy entity that may be associated with a worm identity. These
Expand Down Expand Up @@ -43,7 +44,8 @@ export class TestDummy extends PlayableEntity {
private static texture_damage_3: Texture;
private static texture_damage_blush_3: Texture;

priority = UPDATE_PRIORITY.LOW;
private readonly textureSub: Subscription;

private static readonly collisionBitmask = collisionGroupBitmask(
[CollisionGroups.WorldObjects],
[CollisionGroups.Terrain, CollisionGroups.WorldObjects],
Expand Down Expand Up @@ -87,40 +89,38 @@ export class TestDummy extends PlayableEntity {
explosionRadius: new MetersValue(3),
damageMultiplier: 250,
});
}

private getTexture() {
const isBlush = this.health < 100 && this.physObject.body.isMoving();

if (this.health >= 80) {
return isBlush ? TestDummy.texture_blush : TestDummy.texture_normal;
} else if (this.health >= 60) {
return isBlush
? TestDummy.texture_damage_blush_1
: TestDummy.texture_damage_1;
} else if (this.health >= 25) {
return isBlush
? TestDummy.texture_damage_blush_2
: TestDummy.texture_damage_2;
} else {
return isBlush
? TestDummy.texture_damage_blush_3
: TestDummy.texture_damage_3;
}
}

public update(dt: number): void {
const expectedTexture = this.getTexture();
if (this.sprite.texture !== expectedTexture) {
this.sprite.texture = expectedTexture;
}
super.update(dt);
this.textureSub = combineLatest([
this.bodyMoving$,
this.wormIdent.health$,
]).subscribe(([moving, health]) => {
const isBlush = health < 100 && moving;
let expectedTexture;
if (health >= 80) {
expectedTexture = isBlush
? TestDummy.texture_blush
: TestDummy.texture_normal;
} else if (health >= 60) {
expectedTexture = isBlush
? TestDummy.texture_damage_blush_1
: TestDummy.texture_damage_1;
} else if (health >= 25) {
expectedTexture = isBlush
? TestDummy.texture_damage_blush_2
: TestDummy.texture_damage_2;
} else {
expectedTexture = isBlush
? TestDummy.texture_damage_blush_3
: TestDummy.texture_damage_3;
}
if (this.sprite.texture !== expectedTexture) {
this.sprite.texture = expectedTexture;
}
});
}

public destroy(): void {
super.destroy();
this.parent.plugins.remove("follow");
this.parent.snap(800, 0);
this.textureSub.unsubscribe();
}

public recordState() {
Expand Down
27 changes: 17 additions & 10 deletions src/entities/playable/worm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import { CameraLockPriority } from "../../camera";
import { OnDamageOpts } from "../entity";
import Logger from "../../log";
import { WormState, InnerWormState } from "./wormState";
import { filter, first } from "rxjs";

export enum EndTurnReason {
TimerElapsed = 0,
Expand Down Expand Up @@ -204,6 +205,21 @@ export class Worm extends PlayableEntity {
});
this.targettingGfx = new Graphics({ visible: false });
this.updateTargettingGfx();
this.wormIdent.health$
.pipe(
filter((v) => v === 0),
first(),
)
.subscribe(() => {
// Generic death
this.toaster?.pushToast(
templateRandomText(WormDeathGeneric, {
WormName: this.wormIdent.name,
TeamName: this.wormIdent.team.name,
}),
3000,
);
});
}

public selectWeapon(weapon: IWeaponDefiniton) {
Expand Down Expand Up @@ -715,7 +731,7 @@ export class Worm extends PlayableEntity {
//this.body.setGravityScale(0, false);
if (this.impactVelocity > Worm.minImpactForDamage) {
const damage = this.impactVelocity * Worm.impactDamageMultiplier;
this.health -= damage;
this.wormIdent.setHealth(this.wormIdent.health - damage);
this.state.transition(InnerWormState.Inactive);
this.turnEndedReason = EndTurnReason.FallDamage;
}
Expand Down Expand Up @@ -767,15 +783,6 @@ export class Worm extends PlayableEntity {
3000,
);
// Sinking death
} else if (this.health === 0) {
// Generic death
this.toaster?.pushToast(
templateRandomText(WormDeathGeneric, {
WormName: this.wormIdent.name,
TeamName: this.wormIdent.team.name,
}),
3000,
);
}
}
}
2 changes: 1 addition & 1 deletion src/frontend/components/menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ export function Menu({
} else if (currentMenu === GameMenu.Lobby) {
const onOpenIngame = (gameInstance: RunningNetGameInstance) => {
// TODO: Hardcoded level.
onNewGame("netGame", gameInstance, "levels_testing");
onNewGame("netGameTest", gameInstance, "levels_testing");
};
if (!currentLobbyId) {
throw Error("Current Lobby ID must be set!");
Expand Down
Loading

0 comments on commit c532485

Please sign in to comment.