private void CreateSpriteRendererAndAnimator( out IComponentSpriteRenderer spriteRenderer, out ClientComponentSpriteSheetAnimator componentAnimatorFlash, byte atlasRow, IProtoItemWeaponRanged protoWeapon, TextureAtlasResource muzzleFlashTextureAtlas) { var animationFrameDurationSeconds = this.animationDuration / (double)muzzleFlashTextureAtlas.AtlasSize.ColumnsCount; // create sprite renderer spriteRenderer = Api.Client.Rendering.CreateSpriteRenderer( this.SceneObject, textureResource: TextureResource.NoTexture, // draw in the same layer as the skeleton renderer // (cannot do Default+1 here as it will produce wrong result over other objects) drawOrder: DrawOrder.Default, rotationAngleRad: 0, // align sprite by left side and centered vertical spritePivotPoint: (0, 0.5), scale: (float)this.description.TextureScale); // to ensure muzzleflash rendering over skeleton renderer we do this offset // TODO: find a better way of prioritizing rendering of muzzle flash over skeleton renderer spriteRenderer.DrawOrderOffsetY = -0.2; // create animator for sprite renderer componentAnimatorFlash = this.SceneObject.AddComponent <ClientComponentSpriteSheetAnimator>(); componentAnimatorFlash.Setup( spriteRenderer, ClientComponentSpriteSheetAnimator.CreateAnimationFrames( muzzleFlashTextureAtlas, onlySpecificRow: atlasRow), animationFrameDurationSeconds); }
protected override void ClientInitialize(ClientInitializeData data) { base.ClientInitialize(data); // setup animation var animationFrameDurationSeconds = 1 / 8.0; var clientState = data.ClientState; var textureAtlas = SharedIsAlternativeVariant(data.GameObject.TilePosition) ? this.textureAtlas1 : this.textureAtlas2; data.GameObject .ClientSceneObject .AddComponent <ClientComponentSpriteSheetAnimator>() .Setup( clientState.Renderer, ClientComponentSpriteSheetAnimator.CreateAnimationFrames(textureAtlas), isLooped: true, frameDurationSeconds: animationFrameDurationSeconds, randomizeInitialFrame: true); if (!data.GameObject.OccupiedTile.StaticObjects.Any( o => o.ProtoStaticWorldObject is IProtoObjectExtractor)) { // create sound emitter as there is no extractor clientState.SoundEmitter = Client.Audio.CreateSoundEmitter( data.GameObject, SoundResourceActive, isLooped: true, volume: 0.5f, radius: 1.5f); clientState.SoundEmitter.CustomMaxDistance = 5; } }
protected override void ClientInitialize(ClientInitializeData data) { base.ClientInitialize(data); // setup animation var animationFrameDurationSeconds = 1 / 8.0; Client.Scene .GetSceneObject(data.GameObject) .AddComponent <ClientComponentSpriteSheetAnimator>() .Setup( data.ClientState.Renderer, ClientComponentSpriteSheetAnimator.CreateAnimationFrames( (ITextureAtlasResource)this.DefaultTexture), frameDurationSeconds: animationFrameDurationSeconds, randomizeInitialFrame: true); if (!data.GameObject.OccupiedTile.StaticObjects.Any( o => o.ProtoStaticWorldObject is IProtoObjectExtractor)) { // create sound emitter as there is no extractor data.ClientState.SoundEmitter = Client.Audio.CreateSoundEmitter( data.GameObject, SoundResourceActive, isLooped: true, volume: 0.5f, radius: 1.5f); data.ClientState.SoundEmitter.CustomMaxDistance = 5; } }
protected override void ClientInitialize(ClientInitializeData data) { base.ClientInitialize(data); data.ClientState.Renderer.DrawOrderOffsetY = 0.355; // add sprite sheet animation var sceneObject = data.GameObject.ClientSceneObject; sceneObject.AddComponent <ClientComponentSpriteSheetAnimator>() .Setup(data.ClientState.Renderer, ClientComponentSpriteSheetAnimator.CreateAnimationFrames(this.atlasTexture), isLooped: true, frameDurationSeconds: 3 / 60.0); // add light source at the firing fuse var lightSource = ClientLighting.CreateLightSourceSpot( sceneObject, LightColors.WoodFiring, size: (3, 3), logicalSize: 0, positionOffset: (0.7, 0.7)); // add light flickering sceneObject.AddComponent <ClientComponentLightSourceEffectFlickering>() .Setup(lightSource, flickeringPercents: 10, flickeringChangePercentsPerSecond: 70); }
protected override void ClientInitialize(ClientInitializeData data) { base.ClientInitialize(data); // setup animation var animationFrameDurationSeconds = 1 / 8.0; Client.Scene .GetSceneObject(data.GameObject) .AddComponent <ClientComponentSpriteSheetAnimator>() .Setup( data.ClientState.Renderer, ClientComponentSpriteSheetAnimator.CreateAnimationFrames( (ITextureAtlasResource)this.DefaultTexture), frameDurationSeconds: animationFrameDurationSeconds); // create sound emitter data.ClientState.SoundEmitter = Client.Audio.CreateSoundEmitter( data.GameObject, SoundResourceActive, isLooped: true, volume: 0.5f, radius: 1.5f); data.ClientState.SoundEmitter.CustomMaxDistance = 5; }
private void CreateSpriteRendererAndAnimator( out IComponentSpriteRenderer spriteRenderer, out ClientComponentSpriteSheetAnimator componentAnimatorFlash, byte atlasRow, TextureAtlasResource muzzleFlashTextureAtlas) { var animationFrameDurationSeconds = this.animationDuration / (double)muzzleFlashTextureAtlas.AtlasSize.ColumnsCount; // create sprite renderer spriteRenderer = Api.Client.Rendering.CreateSpriteRenderer( this.SceneObject, textureResource: TextureResource.NoTexture, // draw in the same layer as the skeleton renderer // (cannot do Default+1 here as it will produce wrong result over other objects) drawOrder: DrawOrder.Default, rotationAngleRad: 0, // align sprite by left side and centered vertical spritePivotPoint: (0, 0.5), scale: (float)this.description.TextureScale); // create animator for sprite renderer componentAnimatorFlash = this.SceneObject.AddComponent <ClientComponentSpriteSheetAnimator>(); componentAnimatorFlash.Setup( spriteRenderer, ClientComponentSpriteSheetAnimator.CreateAnimationFrames( muzzleFlashTextureAtlas, onlySpecificRow: atlasRow), isLooped: false, animationFrameDurationSeconds, isManualUpdate: true); }
protected override void ClientInitialize(ClientInitializeData data) { base.ClientInitialize(data); var renderer = data.ClientState.Renderer; renderer.DrawOrder = DrawOrder.Floor; var overlayRenderer = Client.Rendering.CreateSpriteRenderer( data.GameObject, TextureResource.NoTexture); this.ClientSetupRenderer(overlayRenderer); overlayRenderer.PositionOffset = renderer.PositionOffset + this.textureAltasAnimationDrawPositionWorldOffset; overlayRenderer.SpritePivotPoint = renderer.SpritePivotPoint; overlayRenderer.Scale = renderer.Scale; overlayRenderer.DrawOrder = renderer.DrawOrder + 1; Client.Scene .GetSceneObject(data.GameObject) .AddComponent <ClientComponentSpriteSheetBlendAnimator>() .Setup( overlayRenderer, ClientComponentSpriteSheetAnimator.CreateAnimationFrames(this.textureAtlasAnimation), frameDurationSeconds: this.textureAtlasAnimationFrameDurationSeconds); }
protected override void ClientInitialize(ClientInitializeData data) { base.ClientInitialize(data); var tilePosition = data.GameObject.TilePosition; var renderer = data.ClientState.Renderer; if (ClientGroundExplosionAnimationHelper.IsGroundSpriteFlipped(tilePosition)) { renderer.DrawMode = DrawMode.FlipHorizontally; } if (ClientGroundExplosionAnimationHelper.HasActiveExplosion(tilePosition)) { // this is a fresh charred ground, animate the ground sprite var animationDuration = ClientGroundExplosionAnimationHelper.ExplosionGroundDuration; var framesTextureResources = ClientComponentSpriteSheetAnimator.CreateAnimationFrames( ClientGroundExplosionAnimationHelper.ExplosionGroundTextureAtlas); var componentAnimator = renderer.SceneObject.AddComponent <ClientComponentSpriteSheetAnimator>(); componentAnimator.Setup(renderer, framesTextureResources, frameDurationSeconds: animationDuration / framesTextureResources.Length); componentAnimator.IsLooped = false; componentAnimator.Destroy(1.5 * animationDuration); } }
public static void Setup( IComponentSpriteRenderer spriteRenderer, ITextureAtlasResource textureAtlas, double totalDuration) { Setup(spriteRenderer, ClientComponentSpriteSheetAnimator.CreateAnimationFrames(textureAtlas), totalDuration); }
protected override void ClientInitialize(ClientInitializeData data) { base.ClientInitialize(data); var worldObject = data.GameObject; // create sound emitter data.ClientState.SoundEmitter = Client.Audio.CreateSoundEmitter( data.GameObject, SoundResourceActive, isLooped: true, volume: 0.5f, radius: 1.5f); data.ClientState.SoundEmitter.CustomMaxDistance = 4f; // add fan sprite renderers var randomizer = (int)(PositionHashHelper.GetHashUInt32(worldObject.TilePosition.X, worldObject.TilePosition.Y) % 128); AddFanRenderer((41 / 256.0, 253 / 256.0), frameOffset: randomizer, out var componentAnimator1); AddFanRenderer((137 / 256.0, 253 / 256.0), frameOffset: randomizer + 2, out var componentAnimator2); // sound and animation are played only if there is a power grid (a land claim area) var isActive = LandClaimSystem.SharedIsObjectInsideAnyArea(worldObject); componentAnimator1.IsEnabled = componentAnimator2.IsEnabled = data.ClientState.SoundEmitter.IsEnabled = isActive; void AddFanRenderer( Vector2D vector2D, int frameOffset, out ClientComponentSpriteSheetAnimator componentAnimator) { var overlaySpriteRenderer = Client.Rendering.CreateSpriteRenderer( worldObject, positionOffset: vector2D, spritePivotPoint: (0, 0), drawOrder: data.ClientState.Renderer.DrawOrder); overlaySpriteRenderer.DrawOrderOffsetY = -vector2D.Y - 0.01 + data.ClientState.Renderer.DrawOrderOffsetY; // add sprite sheet animation for fan sprite var sceneObject = worldObject.ClientSceneObject; componentAnimator = sceneObject.AddComponent <ClientComponentSpriteSheetAnimator>(); componentAnimator.Setup(overlaySpriteRenderer, ClientComponentSpriteSheetAnimator.CreateAnimationFrames( this.textureAtlasActive), isLooped: true, frameDurationSeconds: 5 / 60.0, initialFrameOffset: frameOffset); } }
protected virtual void ClientSetupExtractorActiveAnimation( IStaticWorldObject worldObject, ObjectManufacturerPublicState serverPublicState, ITextureAtlasResource textureAtlasResource, Vector2D positionOffset, double frameDurationSeconds, bool autoInverseAnimation = false, bool randomizeInitialFrame = false, bool playAnimationSounds = true, OnRefreshActiveState onRefresh = null) { var clientState = worldObject.GetClientState <StaticObjectClientState>(); var sceneObject = worldObject.ClientSceneObject; var overlayRenderer = Client.Rendering.CreateSpriteRenderer( sceneObject, TextureResource.NoTexture, DrawOrder.Default, positionOffset: positionOffset, spritePivotPoint: Vector2D.Zero); overlayRenderer.DrawOrderOffsetY = -positionOffset.Y - 0.01; var spriteSheetAnimator = sceneObject.AddComponent <ClientComponentSpriteSheetAnimator>(); spriteSheetAnimator.Setup( overlayRenderer, ClientComponentSpriteSheetAnimator.CreateAnimationFrames( textureAtlasResource, autoInverse: autoInverseAnimation), isLooped: true, frameDurationSeconds: frameDurationSeconds, randomizeInitialFrame: randomizeInitialFrame); // we play Active sound for pumping on both up and down position of the oil pump var componentActiveState = sceneObject.AddComponent <ClientComponentOilPumpActiveState>(); componentActiveState.Setup(overlayRenderer, spriteSheetAnimator, worldObject, playAnimationSounds); serverPublicState.ClientSubscribe( s => s.IsActive, callback: RefreshActiveState, subscriptionOwner: clientState); spriteSheetAnimator.IsEnabled = overlayRenderer.IsEnabled = false; RefreshActiveState(serverPublicState.IsActive); void RefreshActiveState(bool isActive) { // ReSharper disable once PossibleNullReferenceException componentActiveState.IsActive = isActive; onRefresh?.Invoke(isActive); } }
protected void ClientSetupManufacturerActiveAnimation( IStaticWorldObject worldObject, ObjectManufacturerPublicState serverPublicState, ITextureAtlasResource textureAtlasResource, Vector2D positionOffset, double frameDurationSeconds, double drawOrderOffsetY = 0, bool autoInverseAnimation = false, OnRefreshActiveState onRefresh = null) { var clientState = worldObject.GetClientState <StaticObjectClientState>(); var sceneObject = Client.Scene.GetSceneObject(worldObject); var overlayRenderer = Client.Rendering.CreateSpriteRenderer( sceneObject, TextureResource.NoTexture, DrawOrder.Default, positionOffset: positionOffset, spritePivotPoint: Vector2D.Zero); overlayRenderer.DrawOrderOffsetY = drawOrderOffsetY - positionOffset.Y - 0.01; var spriteSheetAnimator = sceneObject.AddComponent <ClientComponentSpriteSheetAnimator>(); spriteSheetAnimator.Setup( overlayRenderer, ClientComponentSpriteSheetAnimator.CreateAnimationFrames( textureAtlasResource, autoInverse: autoInverseAnimation), frameDurationSeconds: frameDurationSeconds); var soundEmitterActiveState = this.ClientCreateActiveStateSoundEmitterComponent(worldObject, sceneObject); serverPublicState.ClientSubscribe( s => s.IsManufacturingActive, callback: RefreshActiveState, subscriptionOwner: clientState); RefreshActiveState(serverPublicState.IsManufacturingActive); void RefreshActiveState(bool isActive) { overlayRenderer.IsEnabled = isActive; spriteSheetAnimator.IsEnabled = isActive; if (soundEmitterActiveState != null) { soundEmitterActiveState.IsEnabled = isActive; } onRefresh?.Invoke(isActive); } }
protected override void ClientInitialize(ClientInitializeData data) { base.ClientInitialize(data); var worldObject = data.GameObject; var publicState = data.PublicState; var renderer = data.ClientState.Renderer; var sceneObject = worldObject.ClientSceneObject; PowerGridSystem.ClientInitializeConsumerOrProducer(worldObject); var soundEmitter = Client.Audio.CreateSoundEmitter( worldObject, SoundResourceActive, is3D: true, volume: 1.0f, isLooped: true); soundEmitter.CustomMinDistance = 3.0f; soundEmitter.CustomMaxDistance = 6.0f; // add sprite sheet animation for fan sprite var componentAnimator = sceneObject.AddComponent <ClientComponentSpriteSheetAnimator>(); componentAnimator.Setup(renderer, ClientComponentSpriteSheetAnimator.CreateAnimationFrames(this.textureAtlasActive) .Skip(1) .ToArray(), isLooped: true, frameDurationSeconds: 6 / 60.0, randomizeInitialFrame: true); publicState.ClientSubscribe( _ => _.ElectricityConsumerState, _ => RefreshActiveState(), data.ClientState); RefreshActiveState(); void RefreshActiveState() { var isActive = publicState.ElectricityConsumerState == ElectricityConsumerState.PowerOnActive; componentAnimator.IsEnabled = isActive; soundEmitter.IsEnabled = isActive; if (!isActive) { // reset to default texture renderer.TextureResource = this.DefaultTexture; } } }
protected override void ClientSetupSkeletonAnimation( bool isActive, IItem item, ICharacter character, IComponentSkeleton skeletonRenderer, List <IClientComponent> skeletonComponents) { base.ClientSetupSkeletonAnimation(isActive, item, character, skeletonRenderer, skeletonComponents); if (!isActive) { return; } // create fire sprite renderer var sceneObject = skeletonRenderer.SceneObject; var fireRenderer = Client.Rendering.CreateSpriteRenderer( sceneObject, TextureResource.NoTexture, // draw origin is calculated so that the center // of the flame sprite will always stay on the end of the torch item spritePivotPoint: (0.5, 0.277), // please note: the torch X axis ("Weapon" slot) is oriented up because torch is held this way! positionOffset: (0.35, 0), scale: 0.9); var fireAnimator = sceneObject.AddComponent <ClientComponentSpriteSheetAnimator>(); fireAnimator.Setup( fireRenderer, ClientComponentSpriteSheetAnimator.CreateAnimationFrames(TextureAtlasFire), isLooped: true, frameDurationSeconds: 1 / 15.0, randomizeInitialFrame: true); var slotNameClone = "Weapon_Torch"; skeletonRenderer.CloneSlot("Weapon", slotNameClone); skeletonRenderer.SetAttachmentRenderer(slotNameClone, "WeaponMelee", fireRenderer, applyBoneRotation: false); skeletonRenderer.SetAttachment(slotNameClone, "WeaponMelee"); skeletonComponents.Add(fireRenderer); skeletonComponents.Add(fireAnimator); }
public WeaponHitSparksPreset Add( ObjectMaterial material, double texturePivotY, TextureAtlasResource texture, Color?lightColor = null, bool useScreenBlending = false, bool allowRandomizedHitPointOffset = true) { var frames = ClientComponentSpriteSheetAnimator.CreateAnimationFrames(texture); this.HitSparksPreset[material] = new HitSparksEntry(frames, lightColor, useScreenBlending, texturePivotY, allowRandomizedHitPointOffset); return(this); }
public void Setup( IComponentSpriteRenderer rocketRenderer, IComponentSpriteRenderer mast1Renderer, IComponentSpriteRenderer mast2Renderer, double timePassedSinceLaunch) { this.rocketRenderer = rocketRenderer; this.time = timePassedSinceLaunch - RocketLaunchAnimationStartDelay; this.mast1Renderer = mast1Renderer; this.mast2Renderer = mast2Renderer; this.defaultRocketRendererPositionOffset = rocketRenderer.PositionOffset; this.defaultRocketRendererDrawOrderOffsetY = rocketRenderer.DrawOrderOffsetY; this.defaultMast1RendererPositionOffset = mast1Renderer.PositionOffset; this.defaultMast2RendererPositionOffset = mast2Renderer.PositionOffset; var sceneObject = rocketRenderer.SceneObject; this.fireAnimators = new ClientComponentSpriteSheetAnimator[RocketFireOffsets.Length]; this.lightRenderers = new BaseClientComponentLightSource[RocketFireOffsets.Length]; for (var index = 0; index < this.fireAnimators.Length; index++) { var fireRenderer = Client.Rendering.CreateSpriteRenderer(sceneObject, TextureResourceRocketFireAnimation); this.fireAnimators[index] = sceneObject.AddComponent <ClientComponentSpriteSheetAnimator>(); this.fireAnimators[index].Setup(fireRenderer, ClientComponentSpriteSheetAnimator.CreateAnimationFrames( TextureResourceRocketFireAnimation), isLooped: true, frameDurationSeconds: 1 / 30.0, randomizeInitialFrame: true); var lightRender = ClientLighting.CreateLightSourceSpot(sceneObject, EngineLightSourceConfig); this.lightRenderers[index] = lightRender; } // toggle rocket renderer to ensure it's drawn on front rocketRenderer.IsEnabled = false; rocketRenderer.IsEnabled = true; this.Update(0); }
public WeaponHitSparksPreset SetDefault( double texturePivotY, TextureAtlasResource texture, Color?lightColor = null, bool useScreenBlending = false, bool allowRandomizedHitPointOffset = true) { var frames = ClientComponentSpriteSheetAnimator.CreateAnimationFrames(texture); foreach (var soundMaterial in AllSoundMaterials) { this.HitSparksPreset[soundMaterial] = new HitSparksEntry(frames, lightColor, useScreenBlending, texturePivotY, allowRandomizedHitPointOffset); } return(this); }
protected override void ClientInitialize(ClientInitializeData data) { base.ClientInitialize(data); data.ClientState.Renderer.DrawOrderOffsetY = 0.355; // add sprite sheet animation var sceneObject = Client.Scene.GetSceneObject(data.GameObject); sceneObject .AddComponent <ClientComponentSpriteSheetAnimator>() .Setup(data.ClientState.Renderer, ClientComponentSpriteSheetAnimator.CreateAnimationFrames(this.atlasTexture), frameDurationSeconds: 0.15f); // add light source at the firing fuse ClientLighting.CreateLightSourceSpot( sceneObject, Color.FromRgb(0xFF, 0x55, 0x22), size: (3, 3), positionOffset: (0.4, 0.4)); }
private void ClientSetupDoor(ClientInitializeData data) { var sceneObject = data.GameObject.ClientSceneObject; var publicState = data.PublicState; var clientState = data.ClientState; var isHorizontalDoor = publicState.IsHorizontalDoor; var isOpened = publicState.IsOpened; var atlas = isHorizontalDoor ? this.AtlasTextureHorizontal : this.AtlasTextureVertical; var renderer = Client.Rendering.CreateSpriteRenderer( sceneObject, atlas.Chunk(0, 0), drawOrder: DrawOrder.Default); renderer.PositionOffset = (0, isHorizontalDoor ? DrawWorldOffsetYHorizontalDoor : DrawWorldOffsetYVerticalDoor); renderer.DrawOrderOffsetY = isHorizontalDoor ? WallPatterns.DrawOffsetNormal - DrawWorldOffsetYHorizontalDoor : this.DoorSizeTiles + 0.1 - DrawWorldOffsetYVerticalDoor; var spriteSheetAnimator = sceneObject.AddComponent <ClientComponentDoorSpriteSheetAnimator>(); var atlasColumnsCount = atlas.AtlasSize.ColumnsCount; clientState.Renderer?.Destroy(); clientState.Renderer = renderer; clientState.SpriteAnimator?.Destroy(); clientState.SpriteAnimator = spriteSheetAnimator; clientState.DoorBaseRenderer?.Destroy(); clientState.DoorBaseRenderer = null; clientState.DoorVerticalFrontPartRenderer?.Destroy(); clientState.DoorVerticalFrontPartRenderer = null; if (isHorizontalDoor) { // add extra sprite renderer for horizontal door - door base clientState.DoorBaseRenderer = Client.Rendering.CreateSpriteRenderer( sceneObject, this.TextureBaseHorizontal, drawOrder: DrawOrder.Floor + 1, positionOffset: (0, DrawWorldOffsetYHorizontalDoor), spritePivotPoint: (0, 0)); } else { // add extra sprite renderer for vertical door - door base clientState.DoorBaseRenderer = Client.Rendering.CreateSpriteRenderer( sceneObject, atlas.Chunk((byte)(atlasColumnsCount - 1), 0), drawOrder: DrawOrder.Floor + 1, positionOffset: (0, DrawWorldOffsetYVerticalDoor)); // add extra sprite renderer for vertical door - side door front sprite clientState.DoorVerticalFrontPartRenderer = Client.Rendering.CreateSpriteRenderer( sceneObject, atlas.Chunk((byte)(atlasColumnsCount - 2), 0), drawOrder: DrawOrder.Default, positionOffset: (0, DrawWorldOffsetYVerticalDoor)); } var framesCount = isHorizontalDoor ? atlasColumnsCount : atlasColumnsCount - 2; spriteSheetAnimator.Setup( renderer, ClientComponentSpriteSheetAnimator.CreateAnimationFrames( atlas, columns: (byte)framesCount), frameDurationSeconds: this.DoorOpenCloseAnimationDuration / (double)framesCount); // refresh opened/closed state clientState.IsOpened = isOpened; // re-create physics this.SharedCreatePhysics(data.GameObject); spriteSheetAnimator.SetCurrentFrame(isOpened ? spriteSheetAnimator.FramesTextureResources.Length : 0); }