diff --git a/src/nitro/room/object/visualization/pet/ExperienceData.ts b/src/nitro/room/object/visualization/pet/ExperienceData.ts new file mode 100644 index 00000000..c424adfd --- /dev/null +++ b/src/nitro/room/object/visualization/pet/ExperienceData.ts @@ -0,0 +1,79 @@ +import { RenderTexture, Resource, Texture } from '@pixi/core'; +import { Container } from '@pixi/display'; +import { Sprite } from '@pixi/sprite'; +import { Text } from '@pixi/text'; +import { TextureUtils } from '../../../../../room'; +import { Nitro } from '../../../../Nitro'; + +export class ExperienceData +{ + private _sprite: Sprite; + private _texture: RenderTexture; + private _amount: number; + private _alpha: number; + + constructor(texture: Texture) + { + this._sprite = new Sprite(texture); + this._texture = null; + this._amount = -1; + this._alpha = 0; + } + + public renderBubble(amount: number): RenderTexture + { + if(!this._sprite || (this._amount === amount)) return null; + + const container = new Container(); + + container.addChild(this._sprite); + + const text = new Text(('+' + amount), { + fontFamily: 'Arial', + fontSize: 9, + fill: 0xFFFFFF, + align: 'center' + }); + + text.anchor.x = 0.5; + + text.x = (this._sprite.width / 2); + text.y = 19; + + container.addChild(text); + + if(!this._texture) + { + this._texture = TextureUtils.generateTexture(container); + } + else + { + Nitro.instance.renderer.render(container, { + renderTexture: this._texture, + clear: true + }); + } + + return this._texture; + } + + public get amount(): number + { + return this._amount; + } + + public set amount(amount: number) + { + this._amount = amount; + } + + public get alpha(): number + { + return this._alpha; + } + + public set alpha(alpha: number) + { + this._alpha = alpha; + } +} diff --git a/src/nitro/room/object/visualization/pet/PetVisualization.ts b/src/nitro/room/object/visualization/pet/PetVisualization.ts index 3051ea03..1bc4042b 100644 --- a/src/nitro/room/object/visualization/pet/PetVisualization.ts +++ b/src/nitro/room/object/visualization/pet/PetVisualization.ts @@ -1,6 +1,8 @@ +import { Resource, Texture } from '@pixi/core'; import { IObjectVisualizationData } from '../../../../../room/object/visualization/IRoomObjectVisualizationData'; import { IGraphicAsset } from '../../../../../room/object/visualization/utils/IGraphicAsset'; import { IRoomGeometry } from '../../../../../room/utils/IRoomGeometry'; +import { Nitro } from '../../../../Nitro'; import { RoomObjectVariable } from '../../RoomObjectVariable'; import { RoomObjectVisualizationType } from '../../RoomObjectVisualizationType'; import { AnimationData } from '../data/AnimationData'; @@ -9,21 +11,22 @@ import { DirectionData } from '../data/DirectionData'; import { LayerData } from '../data/LayerData'; import { FurnitureAnimatedVisualization } from '../furniture/FurnitureAnimatedVisualization'; import { FurnitureVisualizationData } from '../furniture/FurnitureVisualizationData'; +import { ExperienceData } from './ExperienceData'; import { PetVisualizationData } from './PetVisualizationData'; export class PetVisualization extends FurnitureAnimatedVisualization { public static TYPE: string = RoomObjectVisualizationType.PET_ANIMATED; - private static HEAD: string = 'head'; - private static SADDLE: string = 'saddle'; - private static HAIR: string = 'hair'; - private static ADDITIONAL_SPRITE_COUNT: number = 1; - private static EXPERIENCE_BUBBLE_VISIBLE_IN_MS: number = 1000; - private static PET_EXPERIENCE_BUBBLE_PNG: string = 'pet_experience_bubble_png'; - private static POSTURE_ANIMATION_INDEX: number = 0; - private static GESTURE_ANIMATION_INDEX: number = 1; - private static ANIMATION_INDEX_COUNT: number = 2; + private static HEAD: string = 'head'; + private static SADDLE: string = 'saddle'; + private static HAIR: string = 'hair'; + private static ADDITIONAL_SPRITE_COUNT: number = 1; + private static EXPERIENCE_BUBBLE_VISIBLE_IN_MS: number = 1000; + private static PET_EXPERIENCE_BUBBLE: string = 'pet_experience_bubble'; + private static POSTURE_ANIMATION_INDEX: number = 0; + private static GESTURE_ANIMATION_INDEX: number = 1; + private static ANIMATION_INDEX_COUNT: number = 2; protected _data: PetVisualizationData; @@ -43,6 +46,9 @@ export class PetVisualization extends FurnitureAnimatedVisualization private _customPaletteIds: number[]; private _isRiding: boolean; private _color: number; + private _experience: number; + private _experienceTimestamp: number; + private _experienceData: ExperienceData; private _previousAnimationDirection: number; private _animationStates: AnimationStateData[]; @@ -69,6 +75,9 @@ export class PetVisualization extends FurnitureAnimatedVisualization this._customPaletteIds = []; this._isRiding = false; this._color = 0xFFFFFF; + this._experience = 0; + this._experienceTimestamp = 0; + this._experienceData = null; this._previousAnimationDirection = -1; this._animationStates = []; @@ -80,6 +89,13 @@ export class PetVisualization extends FurnitureAnimatedVisualization { if(!(data instanceof PetVisualizationData)) return false; + const texture = this.getPetAdditionAsset(PetVisualization.PET_EXPERIENCE_BUBBLE); + + if(texture) + { + this._experienceData = new ExperienceData(texture); + } + return super.initialize(data); } @@ -111,7 +127,53 @@ export class PetVisualization extends FurnitureAnimatedVisualization { super.update(geometry, time, update, skipUpdate); - // update experience + this.updateExperienceBubble(time); + } + + protected updateExperienceBubble(time: number): void + { + if(!this._experienceData) return; + + this._experienceData.alpha = 0; + + if(this._experienceTimestamp) + { + const difference = (time - this._experienceTimestamp); + + if(difference < PetVisualization.EXPERIENCE_BUBBLE_VISIBLE_IN_MS) + { + this._experienceData.alpha = (Math.sin(((difference / PetVisualization.EXPERIENCE_BUBBLE_VISIBLE_IN_MS) * Math.PI)) * 0xFF); + } + else + { + this._experienceTimestamp = 0; + } + + const sprite = this.getSprite((this.totalSprites - 1)); + + if(sprite) + { + if(this._experienceData.alpha > 0) + { + const texture = this._experienceData.renderBubble(this._experience); + + if(texture) + { + sprite.texture = texture; + sprite.offsetX = -20; + sprite.offsetY = -80; + sprite.alpha = this._experienceData.alpha; + sprite.visible = true; + sprite.relativeDepth = -0.2; + + return; + } + } + + sprite.texture = null; + sprite.visible = false; + } + } } protected updateModel(scale: number): boolean @@ -176,6 +238,9 @@ export class PetVisualization extends FurnitureAnimatedVisualization this._headDirection = this.object.getDirection().x; } + this._experience = (model.getValue(RoomObjectVariable.FIGURE_GAINED_EXPERIENCE)); + this._experienceTimestamp = (model.getValue(RoomObjectVariable.FIGURE_EXPERIENCE_TIMESTAMP)); + const customPaletteIndex = model.getValue(RoomObjectVariable.PET_PALETTE_INDEX); const customLayerIds = model.getValue(RoomObjectVariable.PET_CUSTOM_LAYER_IDS); const customPartIds = model.getValue(RoomObjectVariable.PET_CUSTOM_PARTS_IDS); @@ -557,4 +622,11 @@ export class PetVisualization extends FurnitureAnimatedVisualization return posture; } + + public getPetAdditionAsset(name: string): Texture + { + const url = (Nitro.instance.getConfiguration('images.url') + '/additions/' + name + '.png'); + + return Nitro.instance.core.asset.getTexture(url); + } }