From ce7a66d48be6db139d9d67870101d928a124c2ed Mon Sep 17 00:00:00 2001 From: Half-Shot Date: Thu, 30 Jan 2025 13:08:42 +0000 Subject: [PATCH] fix animations for player --- src/entities/phys/physicsEntity.ts | 4 +-- src/entities/playable/worm.ts | 42 ++++++++------------------- src/flags.ts | 3 ++ src/utils/tiledspriteanimated.ts | 46 ++++++++++++++++++++++++++++++ 4 files changed, 63 insertions(+), 32 deletions(-) create mode 100644 src/utils/tiledspriteanimated.ts diff --git a/src/entities/phys/physicsEntity.ts b/src/entities/phys/physicsEntity.ts index 18c79b3..478867f 100644 --- a/src/entities/phys/physicsEntity.ts +++ b/src/entities/phys/physicsEntity.ts @@ -1,4 +1,4 @@ -import { UPDATE_PRIORITY, Sprite, Point, ViewContainer } from "pixi.js"; +import { UPDATE_PRIORITY, Sprite, Point, ViewContainer, TilingSprite } from "pixi.js"; import { IPhysicalEntity, OnDamageOpts } from "../entity"; import { Water } from "../water"; import { BodyWireframe } from "../../mixins/bodyWireframe"; @@ -57,7 +57,7 @@ export abstract class PhysicsEntity< public readonly bodyMoving$: Observable; constructor( - public readonly sprite: ViewContainer, + public readonly sprite: Sprite|TilingSprite, protected physObject: RapierPhysicsObject, protected gameWorld: GameWorld, ) { diff --git a/src/entities/playable/worm.ts b/src/entities/playable/worm.ts index 122a544..39ab2f0 100644 --- a/src/entities/playable/worm.ts +++ b/src/entities/playable/worm.ts @@ -46,6 +46,7 @@ import Logger from "../../log"; import { WormState, InnerWormState } from "./wormState"; import { filter, first } from "rxjs"; import { TweenEngine } from "../../motion/tween"; +import { TiledSpriteAnimated } from "../../utils/tiledspriteanimated"; export enum EndTurnReason { TimerElapsed = 0, @@ -84,9 +85,6 @@ export interface WormRecordedState extends PlayableRecordedState { weapon: IWeaponCode; } -const ANIM_FRAME_RATE = 2; -const TILES_PER_SHEET = 0; - /** * Physical representation of a worm on the map. May be controlled. */ @@ -109,9 +107,6 @@ export class Worm extends PlayableEntity { private static idleAnim: Texture; private static impactDamageMultiplier = 0.75; private static minImpactForDamage = 12; - private tileCounter = 0; - private timeSinceLastAnim = 0; - protected fireWeaponDuration = 0; private currentWeapon: IWeaponDefinition = WeaponBazooka; protected state = new WormState(InnerWormState.Inactive); @@ -191,28 +186,27 @@ export class Worm extends PlayableEntity { private readonly toaster?: Toaster, private readonly recorder?: StateRecorder, ) { - console.log( - Worm.idleAnim - ) - const sprite = new TilingSprite({ + const sprite = new TiledSpriteAnimated({ texture: Worm.idleAnim, width: 96, height: 144, tileScale: {x: 1, y: 1}, - tilePosition: {x: 0, y: 0} + tilePosition: {x: 0, y: 0}, + scale: {x: 0.33, y: 0.33}, + anchor: {x: 0.5, y: 0.5}, + columns: 10, + tileCount: 120, + fps: 60, }); - sprite.scale.set(0.33,0.33); - sprite.anchor.set(0.5, 0.5); const body = world.createRigidBodyCollider( ColliderDesc.cuboid( - (sprite.width*0.33) / (PIXELS_PER_METER * 2), - (sprite.height*0.33) / (PIXELS_PER_METER * 2), + (sprite.width*sprite.scale.x) / (PIXELS_PER_METER * 2), + (sprite.height*sprite.scale.y) / (PIXELS_PER_METER * 2), ) .setActiveEvents(ActiveEvents.COLLISION_EVENTS) .setCollisionGroups(Worm.collisionBitmask) .setSolverGroups(Worm.collisionBitmask) .setFriction(0.1), - //.setMass(5), RigidBodyDesc.dynamic() .setTranslation(position.worldX, position.worldY) .lockRotations(), @@ -439,7 +433,7 @@ export class Worm extends PlayableEntity { this.fireAngle = Math.PI * 2 - this.fireAngle; } this.facingRight = !this.facingRight; - this.sprite.scale.x = this.facingRight ? 0.33 : -0.33; + this.sprite.scale.x = this.facingRight ? Math.abs(this.sprite.scale.x) : -Math.abs(this.sprite.scale.x); } this.state.transition( @@ -651,22 +645,10 @@ export class Worm extends PlayableEntity { update(dt: number, dMs: number): void { super.update(dt, dMs); - this.timeSinceLastAnim += dMs; - if (this.timeSinceLastAnim > 30) { - this.timeSinceLastAnim = 0; - this.tileCounter += 1; - const tile = (this.sprite as TilingSprite); - if (this.tileCounter % 10 === 0) { - this.tileCounter = 0; - tile.tilePosition.x += 0; - tile.tilePosition.y += tile.height; - } else { - tile.tilePosition.x += tile.width; - } - } if (this.sprite.destroyed) { return; } + (this.sprite as TiledSpriteAnimated).update(dMs); this.wireframe.setDebugText( `worm_state: ${this.state.stateName}, velocity: ${this.body.linvel().y} ${this.impactVelocity}, aim: ${this.fireAngle}`, ); diff --git a/src/flags.ts b/src/flags.ts index f98920e..1fcec27 100644 --- a/src/flags.ts +++ b/src/flags.ts @@ -10,6 +10,7 @@ export enum DebugLevel { class Flags extends EventEmitter { public DebugView: DebugLevel; public simulatePhysics = true; + public stepAnimationsId = ""; constructor() { super(); @@ -31,6 +32,8 @@ class Flags extends EventEmitter { (globalThis as any)["wormgineFlags"] = { toggleSimulatePhysics: () => (this.simulatePhysics = !this.simulatePhysics), + stepAnimation: (step = true) => + (this.stepAnimationsId = step ? Math.random().toString() : ""), }; } } diff --git a/src/utils/tiledspriteanimated.ts b/src/utils/tiledspriteanimated.ts new file mode 100644 index 0000000..6ca704c --- /dev/null +++ b/src/utils/tiledspriteanimated.ts @@ -0,0 +1,46 @@ +import { Texture, TilingSprite, TilingSpriteOptions } from "pixi.js"; +import Flags from "../flags"; + +interface TiledSpriteAnimatedOptions extends TilingSpriteOptions { + columns: number; + tileCount: number; + fps: number; +} + +export class TiledSpriteAnimated extends TilingSprite { + private tileCounter = 0; + private timeSinceLastAnim = 0; + private readonly targetFrameMs; + private readonly tileCount: number; + private readonly columns: number; + private debugStepAnim: string = ""; + constructor(opts: TiledSpriteAnimatedOptions) { + super(opts) + this.targetFrameMs = 1000 / opts.fps; + this.tileCount = opts.tileCount; + this.columns = opts.columns; + } + + public update(deltaMs: number) { + this.timeSinceLastAnim += deltaMs; + if (Flags.stepAnimationsId) { + if (this.debugStepAnim === Flags.stepAnimationsId) { + return; + } + this.debugStepAnim = Flags.stepAnimationsId; + } + else if (this.timeSinceLastAnim < this.targetFrameMs) { + return; + } + this.timeSinceLastAnim = 0; + this.tileCounter += 1; + if (this.tileCounter === this.tileCount) { + this.tileCounter = 0; + } + // XXX: This is buggy. Using max helped to stop gittery anims. + const tileColumn = Math.max(1, this.tileCounter % this.columns); + const tileRow = Math.floor(this.tileCounter / this.columns); + this.tilePosition.x = tileColumn * this.width; + this.tilePosition.y = tileRow * this.height; + } +} \ No newline at end of file