particles/ParticleSimulation/ParticleSimulationScene.cs

168 lines
6.1 KiB
C#

using Godot;
using Particles.ParticleSimulation;
// ReSharper disable once CheckNamespace
// ReSharper disable once ClassNeverInstantiated.Global
public class ParticleSimulationScene : Node2D
{
private Node2D _particleNodes;
private Camera2D _camera;
private Tween _cameraTween;
private Vector2 _cameraZoomTarget;
private Vector2 _cameraPosTarget;
private float _maxZoom;
private Vector2 _spaceSize;
private const float CameraZoomSpeed = 0.5f;
private ParticleSimulation _particleSimulation;
public float PhysicsInterpolationFraction;
public void Initialize(int seed, int nParticles, float zoom)
{
_maxZoom = zoom;
_camera = GetNode<Camera2D>("Camera2D");
_cameraTween = GetNode<Tween>("CameraTween");
_particleNodes = GetNode<Node2D>("ParticleNodes");
_cameraZoomTarget = _camera.Zoom;
_cameraPosTarget = _camera.Position;
GD.Seed((ulong)seed);
GD.Print("Last Seed: " + seed);
var viewSize = GetViewportRect().Size;
_camera.Zoom = new Vector2(zoom, zoom);
var spaceSize = viewSize * zoom;
_spaceSize = spaceSize;
_particleSimulation = new ParticleSimulation
{
SpaceSize = spaceSize
};
_particleSimulation.Initialize(nParticles);
foreach (var id in _particleSimulation.LastParticlesAdded) CreateParticleNode(id);
}
public override void _Process(float delta)
{
// Game state inputs
if (Input.IsActionJustPressed("quit"))
GetParent<Main>().ExitToMenu();
if (Input.IsActionJustPressed("reset"))
GetParent<Main>().RestartSimulation();
var shouldTweenStop = false;
if (Input.IsActionJustReleased("zoom_in"))
{
shouldTweenStop = true;
// Zoom
_cameraZoomTarget -= new Vector2(0.1f, 0.1f);
// Movement
var mousePos = GetGlobalMousePosition();
var posDelta = _cameraPosTarget - mousePos;
posDelta = posDelta.Clamped(500f);
_cameraPosTarget -= posDelta * 0.2f;
}
if (Input.IsActionJustReleased("zoom_out"))
{
shouldTweenStop = true;
// Zoom
_cameraZoomTarget += new Vector2(0.1f, 0.1f);
// Movement
var mousePos = GetGlobalMousePosition();
var posDelta = _cameraPosTarget - mousePos;
posDelta = posDelta.Clamped(500f);
_cameraPosTarget += posDelta * 0.2f;
}
var cameraDir = new Vector2();
if (Input.IsActionPressed("up"))
cameraDir += new Vector2(0, -1);
if (Input.IsActionPressed("down"))
cameraDir += new Vector2(0, 1);
if (Input.IsActionPressed("left"))
cameraDir += new Vector2(-1, 0);
if (Input.IsActionPressed("right"))
cameraDir += new Vector2(1, 0);
if (cameraDir.LengthSquared() != 0)
{
shouldTweenStop = true;
cameraDir = cameraDir.Normalized();
_cameraPosTarget += cameraDir * 1000f * delta;
}
if (Input.IsActionPressed("key_zoom_in"))
{
shouldTweenStop = true;
_cameraZoomTarget -= new Vector2(0.01f, 0.01f) * (delta * 60f);
}
if (Input.IsActionPressed("key_zoom_out"))
{
shouldTweenStop = true;
_cameraZoomTarget += new Vector2(0.01f, 0.01f) * (delta * 60f);
}
if (shouldTweenStop)
{
_cameraTween.StopAll();
_cameraZoomTarget.x = Mathf.Clamp(_cameraZoomTarget.x, 0.01f, _maxZoom);
_cameraZoomTarget.y = Mathf.Clamp(_cameraZoomTarget.y, 0.01f, _maxZoom);
_cameraPosTarget.x = Mathf.Clamp(_cameraPosTarget.x,
0f - (_maxZoom - _cameraZoomTarget.x) * (_spaceSize.x / (Mathf.Sqrt2 * 2)),
0f + (_maxZoom - _cameraZoomTarget.x) * (_spaceSize.x / (Mathf.Sqrt2 * 2)));
_cameraPosTarget.y = Mathf.Clamp(_cameraPosTarget.y,
0f - (_maxZoom - _cameraZoomTarget.y) * (_spaceSize.y / (Mathf.Sqrt2 * 2)),
0f + (_maxZoom - _cameraZoomTarget.y) * (_spaceSize.y / (Mathf.Sqrt2 * 2)));
_cameraTween.InterpolateProperty(_camera, "zoom", _camera.Zoom, _cameraZoomTarget, CameraZoomSpeed,
Tween.TransitionType.Quint, Tween.EaseType.Out);
_cameraTween.InterpolateProperty(_camera, "position", _camera.Position, _cameraPosTarget, CameraZoomSpeed,
Tween.TransitionType.Quint, Tween.EaseType.Out);
_cameraTween.Start();
}
PhysicsInterpolationFraction = Engine.GetPhysicsInterpolationFraction();
}
public override void _PhysicsProcess(float delta)
{
_particleSimulation.Update();
foreach (var id in _particleSimulation.LastParticlesRemoved)
{
var particleNode = _particleNodes.GetNode<ParticleNode>(id.ToString());
particleNode.Free();
}
foreach (var id in _particleSimulation.LastParticlesAdded) CreateParticleNode(id);
var particleNodes = _particleNodes.GetChildren();
foreach (ParticleNode particleNode in particleNodes)
{
var simulationParticle = _particleSimulation.GetParticle(particleNode.SimulationId);
particleNode.LastSimulationPosition = particleNode.Position;
particleNode.CurrentSimulationPosition = simulationParticle.Position - (_spaceSize / 2.0f);
particleNode.SetColor(simulationParticle.Type.Hue, simulationParticle.Health,
Mathf.Clamp(simulationParticle.AverageSpeed / 1.5f, 1f, 1f));
particleNode.WasTeleportedLast = simulationParticle.WasTeleportedLast;
}
}
private void CreateParticleNode(int id)
{
var particleScene = GD.Load<PackedScene>("res://ParticleSimulation/ParticleNode.tscn");
var particleNode = particleScene.Instance<ParticleNode>();
particleNode.Name = id.ToString();
particleNode.SimulationId = id;
_particleNodes.AddChild(particleNode);
}
}