This commit is contained in:
orosmatthew 2021-12-27 14:58:33 -05:00
parent 1d487a5462
commit 22ae297532
4 changed files with 116 additions and 11 deletions

84
Main.cs
View File

@ -10,12 +10,17 @@ public class Main : Node2D
private readonly List<ParticleType> _particleTypes = new List<ParticleType>(); private readonly List<ParticleType> _particleTypes = new List<ParticleType>();
private List<Particle> _particles; private List<Particle> _particles;
private const int MaxParticles = 700;
private const float HealthDelta = 0.002f;
private const float PositiveHealthMultiplier = 2f;
public override void _Ready() public override void _Ready()
{ {
GD.Randomize(); GD.Randomize();
InitializeParticleTypes(10); InitializeParticleTypes(12);
InitializeParticles(700); InitializeParticles(MaxParticles);
_particles = GetNode<Node2D>("Particles").GetChildren().Cast<Particle>().ToList();
} }
public override void _Process(float delta) public override void _Process(float delta)
@ -41,8 +46,10 @@ public class Main : Node2D
} }
foreach (var type1 in _particleTypes) foreach (var type1 in _particleTypes)
foreach (var type2 in _particleTypes) foreach (var type2 in _particleTypes)
type1.AddRelationship(type2, 20, (float) GD.RandRange(25, 60), (float) GD.RandRange(-0.33 * 2f, 0.35 * 2f)); type1.AddRelationship(type2,
new ParticleRelationshipProps(20, (float) GD.RandRange(25, 60),
(float) GD.RandRange(-0.33 * 2f, 0.35 * 2f)));
} }
private void InitializeParticles(int nParticles) private void InitializeParticles(int nParticles)
@ -55,6 +62,7 @@ public class Main : Node2D
GetNode<Node2D>("Particles").AddChild(particle); GetNode<Node2D>("Particles").AddChild(particle);
particle.Position = GetRandomParticlePosition(); particle.Position = GetRandomParticlePosition();
particle.Type = _particleTypes[typeCount]; particle.Type = _particleTypes[typeCount];
particle.Health = 1f;
if (typeCount < _particleTypes.Count - 1) if (typeCount < _particleTypes.Count - 1)
typeCount++; typeCount++;
@ -63,6 +71,23 @@ public class Main : Node2D
} }
} }
private void CreateParticle(ParticleType type)
{
var particleScene = GD.Load<PackedScene>("res://Particle.tscn");
var particle = particleScene.Instance<Particle>();
GetNode<Node2D>("Particles").AddChild(particle);
particle.Position = GetRandomParticlePosition();
particle.Type = type;
particle.Health = 1f;
}
private void CreateRandomParticle()
{
var randomIndex = (int)(GD.Randi() % _particleTypes.Count);
var type = _particleTypes[randomIndex];
CreateParticle(type);
}
private Vector2 GetRandomParticlePosition() private Vector2 GetRandomParticlePosition()
{ {
var viewportRect = GetViewportRect(); var viewportRect = GetViewportRect();
@ -74,27 +99,60 @@ public class Main : Node2D
private void UpdateParticles() private void UpdateParticles()
{ {
_particles = GetNode<Node2D>("Particles").GetChildren().Cast<Particle>().ToList();
var tasks = new Task[_particles.Count]; var tasks = new Task[_particles.Count];
var viewportRect = GetViewportRect(); var viewportRect = GetViewportRect();
for (var i = 0; i < _particles.Count; i++) tasks[i] = Task.Factory.StartNew(UpdateParticle, _particles[i]); for (var i = 0; i < _particles.Count; i++) tasks[i] = Task.Factory.StartNew(UpdateParticle, _particles[i]);
Task.WaitAll(tasks); Task.WaitAll(tasks);
var deletedParticle = false;
foreach (var p in _particles) foreach (var p in _particles)
{ {
if (deletedParticle == false && p.Health == 0f)
{
if (GD.Randf() < 0.2f)
{
p.Free();
deletedParticle = true;
continue;
}
}
var position = p.Position; var position = p.Position;
p.Velocity = p.Velocity.Clamped(3f * 2f); p.Velocity = p.Velocity.Clamped(3f * 4f);
position += p.Velocity; position += p.Velocity;
p.Velocity *= 0.85f; p.Velocity *= 0.875f; // friction
position.x = Mathf.Clamp(position.x, ParticleScreenPadding, viewportRect.Size.x - ParticleScreenPadding); position.x = Mathf.Clamp(position.x, ParticleScreenPadding, viewportRect.Size.x - ParticleScreenPadding);
position.y = Mathf.Clamp(position.y, ParticleScreenPadding, viewportRect.Size.y - ParticleScreenPadding); position.y = Mathf.Clamp(position.y, ParticleScreenPadding, viewportRect.Size.y - ParticleScreenPadding);
p.AddAverageSpeedValue(p.Position.DistanceTo(position));
if (p.AverageSpeed < 0.3f)
p.Health -= HealthDelta * 1.5f;
else
p.Health += HealthDelta;
if (deletedParticle == false && p.Health == 0f)
{
if (GD.Randf() < 0.2f)
{
p.Free();
deletedParticle = true;
continue;
}
}
p.Position = position; p.Position = position;
} }
if (_particles.Count < MaxParticles)
if (GD.Randf() < 0.3f)
CreateRandomParticle();
} }
private void UpdateParticle(object particle) private void UpdateParticle(object particle)
{ {
var p1 = (Particle) particle; var p1 = (Particle) particle;
var closeCount = 0;
foreach (var p2 in _particles) foreach (var p2 in _particles)
{ {
var viewportRect = GetViewportRect(); var viewportRect = GetViewportRect();
@ -105,6 +163,12 @@ public class Main : Node2D
continue; continue;
var direction = p1.Position.DirectionTo(p2.Position); var direction = p1.Position.DirectionTo(p2.Position);
if (distance < 70)
{
closeCount++;
}
// collision force // collision force
if (distance < 20) if (distance < 20)
{ {
@ -121,5 +185,11 @@ public class Main : Node2D
props.Force; props.Force;
p1.Velocity += direction * particleForce; p1.Velocity += direction * particleForce;
} }
if (closeCount < 3 || closeCount > 35)
p1.Health -= HealthDelta * 1.5f;
else
p1.Health += HealthDelta;
} }
} }

View File

@ -3,9 +3,23 @@ using Godot;
public class Particle : Node2D public class Particle : Node2D
{ {
private Sprite _spriteNode; private Sprite _spriteNode;
private Label _labelNode;
private ParticleType _type; private ParticleType _type;
private float _health = 0f;
private float _averageSpeed = 1f;
public Vector2 Velocity { get; set; } public Vector2 Velocity { get; set; }
public float AverageSpeed { get => _averageSpeed; }
public float Health
{
get => _health;
set
{
_health = Mathf.Clamp(value, 0f, 1f);
_spriteNode.Modulate = Color.FromHsv(_type.Hue, Health, 1);
}
}
public ParticleType Type public ParticleType Type
{ {
@ -13,12 +27,23 @@ public class Particle : Node2D
set set
{ {
_type = value; _type = value;
_spriteNode.Modulate = Color.FromHsv(_type.Hue, 1, 1); _spriteNode.Modulate = Color.FromHsv(_type.Hue, Health, 1);
} }
} }
public override void _Ready() public override void _Ready()
{ {
_spriteNode = GetNode<Sprite>("Sprite"); _spriteNode = GetNode<Sprite>("Sprite");
_labelNode = GetNode<Label>("Label");
}
public void AddAverageSpeedValue(float speed)
{
_averageSpeed = (0.99f * _averageSpeed) + (0.01f * speed);
}
public void SetLabelText(string text)
{
_labelNode.Text = text;
} }
} }

View File

@ -9,3 +9,14 @@ script = ExtResource( 2 )
[node name="Sprite" type="Sprite" parent="."] [node name="Sprite" type="Sprite" parent="."]
scale = Vector2( 0.25, 0.25 ) scale = Vector2( 0.25, 0.25 )
texture = ExtResource( 1 ) texture = ExtResource( 1 )
[node name="Label" type="Label" parent="."]
visible = false
margin_left = -18.0
margin_top = -23.0
margin_right = 18.0
margin_bottom = -9.0
text = "0.05"
__meta__ = {
"_edit_use_anchors_": false
}

View File

@ -28,11 +28,10 @@ public class ParticleType
set => _hue = Mathf.Clamp(value, 0, 1); set => _hue = Mathf.Clamp(value, 0, 1);
} }
public void AddRelationship(ParticleType type, float minRadius, float maxRadius, float force) public void AddRelationship(ParticleType type, ParticleRelationshipProps props)
{ {
if (_particleRelationships.ContainsKey(type)) if (_particleRelationships.ContainsKey(type))
return; return;
var props = new ParticleRelationshipProps(minRadius, maxRadius, force);
_particleRelationships[type] = props; _particleRelationships[type] = props;
} }