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"); _cameraTween = GetNode("CameraTween"); _particleNodes = GetNode("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
().ExitToMenu(); if (Input.IsActionJustPressed("reset")) GetParent
().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(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("res://ParticleSimulation/ParticleNode.tscn"); var particleNode = particleScene.Instance(); particleNode.Name = id.ToString(); particleNode.SimulationId = id; _particleNodes.AddChild(particleNode); } }