Last active
April 2, 2025 05:37
-
-
Save w0wca7a/6cf54ad9a68671aad4b3f295de6b7496 to your computer and use it in GitHub Desktop.
Script provides Camera Shaking in Stride Game Engine
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copyright (c) Stride contributors (https://stride3d.net). | |
// Distributed under the MIT license. | |
using Stride.Core.Mathematics; | |
using Stride.Engine; | |
using Stride.Input; | |
using System; | |
using System.Threading; | |
using System.Threading.Tasks; | |
public class CameraShake : AsyncScript | |
{ | |
// Default Shake Settings / Настройки тряски по умолчанию | |
// Shaking intensity / Интенсивность тряски | |
public float ShakeIntensity { get; set; } = 0.1f; | |
// Shaking duration (seconds) / Длительность тряски (секунды) | |
public float ShakeDuration { get; set; } = 0.5f; | |
// Shaking attenuation / Затухание тряски (0-1) | |
public float ShakeDamping { get; set; } = 0.9f; | |
// Shaking frequency / Частота тряски | |
public float ShakeFrequency { get; set; } = 25f; | |
private Vector3 originalPosition; | |
private Random random = new Random(); | |
private bool isShaking = false; | |
private CancellationTokenSource shakeCancellation; | |
public override async Task Execute() | |
{ | |
while (Game.IsRunning) | |
{ | |
// For the test, we start shaking when we press the space bar / Для теста - запускаем тряску при нажатии пробела | |
if (Input.IsKeyPressed(Keys.Space)) | |
{ | |
await ShakeAsync(); | |
} | |
await Script.NextFrame(); | |
} | |
} | |
// Basic shaking method / Основной метод тряски | |
// For start shaking from another place we can use: | |
// var cameraShake = cameraEntity.Get<CameraShake>(); | |
// await cameraShake.ShakeAsync(); | |
public async Task ShakeAsync() | |
{ | |
await ShakeAsync(ShakeIntensity, ShakeDuration, ShakeDamping); | |
} | |
// Shaking method with parameters / Метод тряски с параметрами | |
// We can use shaking from another place with parameters: | |
// await cameraShake.ShakeAsync(0.2f, 1f, 0.8f); | |
public async Task ShakeAsync(float intensity, float duration, float damping = 0.9f) | |
{ | |
// Save camera position / Сохраняем текущую позицию перед началом тряски | |
originalPosition = Entity.Transform.Position; | |
// Stop previous shaking if it`s active/ Отменяем предыдущую тряску, если она активна | |
if (isShaking) | |
{ | |
shakeCancellation?.Cancel(); | |
shakeCancellation?.Dispose(); | |
} | |
isShaking = true; | |
shakeCancellation = new CancellationTokenSource(); | |
var token = shakeCancellation.Token; | |
try | |
{ | |
float remainingDuration = duration; | |
float currentIntensity = intensity; | |
while (remainingDuration > 0 && !token.IsCancellationRequested) | |
{ | |
// Вычисляем силу тряски с учетом затухания | |
float shakeAmount = currentIntensity * (remainingDuration / duration); | |
// Генерируем случайные смещения | |
Vector3 randomOffset = new Vector3( | |
(float)(random.NextDouble() * 2 - 1), | |
(float)(random.NextDouble() * 2 - 1), | |
(float)(random.NextDouble() * 2 - 1)) * shakeAmount; | |
// Применяем тряску с учетом частоты | |
float timeFactor = (float)Math.Sin(Game.UpdateTime.Total.TotalSeconds * ShakeFrequency); | |
Entity.Transform.Position = originalPosition + randomOffset * timeFactor; | |
// Тут можно запустить воспроизведение | |
// Подробнее: https://doc.stride3d.net/latest/en/manual/audio/non-spatialized-audio.html | |
// Обновляем параметры тряски | |
remainingDuration -= (float)Game.UpdateTime.Elapsed.TotalSeconds; | |
currentIntensity *= damping; | |
await Script.NextFrame(); | |
} | |
// Restore camera to original position / Возвращаем камеру в исходное положение | |
Entity.Transform.Position = originalPosition; | |
} | |
catch (TaskCanceledException) | |
{ | |
Entity.Transform.Position = originalPosition; | |
} | |
finally | |
{ | |
isShaking = false; | |
shakeCancellation?.Dispose(); | |
shakeCancellation = null; | |
} | |
} | |
// immediately shaking stop / Метод для немедленной остановки тряски | |
public void StopShake() | |
{ | |
if (isShaking) | |
{ | |
shakeCancellation?.Cancel(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment