From 62110ea34481391534645f1027108237bae050a4 Mon Sep 17 00:00:00 2001 From: Justin Young <62815737+jyoung4242@users.noreply.github.com> Date: Wed, 31 Jul 2024 15:39:18 -0400 Subject: [PATCH] feat: Flash Action (#3142) --- src/engine/Actions/Action/Flash.ts | 84 ++++++++++++++++++++++++++++++ src/engine/Actions/Index.ts | 1 + 2 files changed, 85 insertions(+) create mode 100644 src/engine/Actions/Action/Flash.ts diff --git a/src/engine/Actions/Action/Flash.ts b/src/engine/Actions/Action/Flash.ts new file mode 100644 index 000000000..45b39b47d --- /dev/null +++ b/src/engine/Actions/Action/Flash.ts @@ -0,0 +1,84 @@ +import { GraphicsComponent } from '../../Graphics/GraphicsComponent'; +import { Entity } from '../../EntityComponentSystem/Entity'; +import { Action, nextActionId } from '../Action'; +import { Actor } from '../../Actor'; +import { Material } from '../../Graphics/Context/material'; +import { Shader, Color } from '../../excalibur'; + +export class Flash implements Action { + id = nextActionId(); + private _graphics: GraphicsComponent; + private _duration: number; + private _stopped: boolean = false; + private _started: boolean = false; + private _entity: Entity; + private _material: Material | undefined; + private _total: number = 0; + private _currentDuration: number = 0; + + constructor(entity: Entity, color: Color, duration: number = 1000) { + this._graphics = entity.get(GraphicsComponent); + this._duration = duration; + this._entity = entity; + this._material = entity.scene?.engine.graphicsContext.createMaterial({ + name: 'flash-material', + color, + fragmentSource: `#version 300 es + + precision mediump float; + uniform float u_blend; + uniform sampler2D u_graphic; + uniform vec4 u_color; + + in vec2 v_uv; + out vec4 color; + + void main() { + vec4 textureColor = texture(u_graphic, v_uv); + color = mix(textureColor, u_color, u_blend * textureColor.a); + color.rgb = color.rgb * color.a; + }` + }) as Material; + this._total = duration; + } + + public update(delta: number): void { + if (!this._started) { + this._started = true; + this._total = this._duration; + this._currentDuration = this._duration; + (this._entity as Actor).graphics.material = this._material as Material; + } + if (!this._graphics) { + return; + } + + this._currentDuration -= delta; + + if (this._graphics) { + this._material?.update((shader: Shader) => { + shader.trySetUniformFloat('u_blend', this._currentDuration / this._total); + }); + } + + if (this.isComplete()) { + (this._entity as Actor).graphics.material = null; + } + } + + public isComplete(): boolean { + return this._stopped || this._currentDuration <= 0; + } + + public stop(): void { + if (this._graphics) { + this._graphics.visible = true; + } + this._stopped = true; + } + + public reset() { + this._started = false; + this._stopped = false; + } +} diff --git a/src/engine/Actions/Index.ts b/src/engine/Actions/Index.ts index 1e7491eba..eff76c4c7 100644 --- a/src/engine/Actions/Index.ts +++ b/src/engine/Actions/Index.ts @@ -22,6 +22,7 @@ export * from './Action/RotateTo'; export * from './Action/ScaleBy'; export * from './Action/ScaleTo'; export * from './Action/Delay'; +export * from './Action/Flash'; export * from './ActionsComponent'; export * from './ActionsSystem';