stride/samples/Particles/ParticlesSample/ParticlesSample.Game/CameraOrbitScript.cs

99 lines
4.4 KiB
C#
Raw Normal View History

2021-04-19 03:49:55 +00:00
// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
2018-06-19 09:06:54 +00:00
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
using System;
using System.Linq;
using System.Threading.Tasks;
2020-04-14 14:37:41 +00:00
using Stride.Engine;
using Stride.Input;
using Stride.Core.Mathematics;
2018-06-19 09:06:54 +00:00
namespace ParticlesSample
{
/// <summary>
/// Script that update the position of the camera.
/// </summary>
public class CameraOrbitScript : AsyncScript
{
private readonly Vector3 lookAtPosition = new Vector3(0, 0, 0);
private float lookAtAngle = 90f;
private float lookAtAngleY = 10f;
private const float lookFromDistance = 8f;
private const float MinimumCameraHeight = 0f;
private const float MaximumCameraHeight = 50f;
private const float AbsoluteMaxSpeedX = 5f;
private const float AbsoluteMaxSpeedY = 2f;
private const float Friction = 0.9f;
private const float Frametime = 1 / 60.0f;
private float timeToProcess;
private float movingSpeedX;
private float movingSpeedY;
private bool userIsTouchingScreen;
public override async Task Execute()
{
while (Game.IsRunning)
{
var elapsedTime = (float)Game.UpdateTime.Elapsed.TotalSeconds;
timeToProcess = Math.Max(timeToProcess + elapsedTime, 1.0f);
// determine if the user is currently touching the screen.
if (Input.PointerEvents.Count > 0)
userIsTouchingScreen = Input.Pointer.DownPointers.Any(x=>x.IsDown);
// calculate the current speed of the camera
if (userIsTouchingScreen)
{
movingSpeedX += -AbsoluteMaxSpeedX * Input.PointerEvents.Sum(x => x.DeltaPosition.X);
if (Math.Abs(movingSpeedX) > AbsoluteMaxSpeedX)
{
movingSpeedX = AbsoluteMaxSpeedX * Math.Sign(movingSpeedX);
}
movingSpeedY += AbsoluteMaxSpeedY * Input.PointerEvents.Sum(y => y.DeltaPosition.Y);
if (Math.Abs(movingSpeedY) > AbsoluteMaxSpeedY)
{
movingSpeedY = AbsoluteMaxSpeedY * Math.Sign(movingSpeedY);
}
timeToProcess = timeToProcess % Frametime;
UpdatePosition(movingSpeedX * 2, movingSpeedY * 2);
}
else
{
while (timeToProcess >= Frametime)
{
timeToProcess -= Frametime;
var previousSpeedX = movingSpeedX;
movingSpeedX = (float)(movingSpeedX * Math.Pow(Friction, Frametime));
var previousSpeedY = movingSpeedY;
movingSpeedY = (float)(movingSpeedY * Math.Pow(Friction, Frametime));
UpdatePosition(previousSpeedX + movingSpeedX, previousSpeedY + movingSpeedY);
}
}
// wait until next frame
await Script.NextFrame();
}
}
private void UpdatePosition(float speedX, float speedY)
{
lookAtAngle = lookAtAngle + (speedX) * 7.5f * Frametime;
lookAtAngleY = lookAtAngleY + (speedY) * 1.5f * Frametime;
lookAtAngleY = MathUtil.Clamp(lookAtAngleY, MinimumCameraHeight, MaximumCameraHeight);
var maxDistance = lookFromDistance*(1 + (float) Math.Sin(MathUtil.DegreesToRadians(lookAtAngleY)));
var distance = maxDistance * (float)Math.Cos(MathUtil.DegreesToRadians(lookAtAngleY));
Entity.Transform.Position.X = (float)Math.Sin(MathUtil.DegreesToRadians(lookAtAngle)) * distance;
Entity.Transform.Position.Z = (float)Math.Cos(MathUtil.DegreesToRadians(lookAtAngle)) * distance;
Entity.Transform.Position.Y = maxDistance*(float) Math.Sin(MathUtil.DegreesToRadians(lookAtAngleY));
Entity.Transform.Position += lookAtPosition;
Entity.Transform.Rotation = Quaternion.RotationAxis(new Vector3(1, 0, 0), MathUtil.DegreesToRadians(-lookAtAngleY)) *
Quaternion.RotationAxis(new Vector3(0, 1, 0), MathUtil.DegreesToRadians(lookAtAngle));
}
}
}