Compare commits

5 Commits

Author SHA1 Message Date
9a36418d23 activated activateneighbors experiment 2025-05-01 23:46:18 +02:00
f932ae1bcd refactoring 2025-05-01 23:34:31 +02:00
c41cdd57c4 fixed activate not set on copy 2025-05-01 23:06:46 +02:00
e653f23a42 dirt shall only move downwards 2025-05-01 23:01:42 +02:00
6acccefa0a diffuse in both directions 2025-05-01 22:51:39 +02:00
5 changed files with 94 additions and 44 deletions

View File

@@ -1,5 +1,3 @@
using System.Reflection;
using FOU.Scripts;
using Godot;
public partial class SettingsController : VBoxContainer

View File

@@ -13,7 +13,6 @@ public class Chunk {
public Chunk NeighborS = null;
public Chunk NeighborW = null;
private readonly Image image;
private readonly int sizeX;
private readonly int sizeY;
private readonly HashSet<Element> activeElements;
@@ -33,9 +32,6 @@ public class Chunk {
}
activeElements = new HashSet<Element>(sizeX * sizeY);
image = Image.CreateEmpty(sizeX, sizeY, false, Image.Format.Rgb8);
image.Fill(Colors.Black);
}
public void Update() {
@@ -61,7 +57,7 @@ public class Chunk {
}
public void SetElementActive(Element e, bool active) {
if (e.GetType() == typeof(Element) && active) return;
if (e.GetType() == typeof(Element)) return;
if (active) AddToChunk(e);
else RemoveFromChunk(e);
@@ -90,10 +86,6 @@ public class Chunk {
return activeElements.Count;
}
public void Swap(Element what, Vector2I pos) {
Swap(what, Get(pos));
}
public Element Get(Vector2I pos) {
Element e = null;
@@ -129,6 +121,10 @@ public class Chunk {
return Get(pos)?.GetType() == typeof(Element);
}
public void Swap(Element what, Vector2I pos) {
Swap(what, Get(pos));
}
private void Swap(Element what, Element swapTo) {
if (what == null || swapTo == null) {
GD.PrintErr("Trying to swap null");
@@ -155,8 +151,16 @@ public class Chunk {
what.Active = true;
what.Moved();
if (what.IsEmpty())
what.ActivateNeighbors();
swapTo.Active = true;
swapTo.Moved();
if (swapTo.IsEmpty())
swapTo.ActivateNeighbors();
// TODO:
// if either "what" or "swapTo" is empty, re-activate all neighbors of the now empty ones
}
public override string ToString() {

View File

@@ -6,48 +6,51 @@ public class Element{
public Chunk Chunk;
public Vector2I Position;
public int Density;
protected int Density;
protected int DiffuseSpeed = 10;
protected Color color = Colors.Black;
protected const int MAX_DIFFUSE_SPEED = 100;
protected const int STEPS_UNTIL_INACTIVE = 500;
protected const float MAX_COLOR_VARIANCE = 0.1f;
protected static readonly Vector2I VERTICAL_OPPOSITE = new Vector2I(-1, 1);
private const float MAX_COLOR_VARIANCE = 0.1f;
private bool active = false;
private bool markedForUpdate = true;
private int lastUpdate = -1;
private int lastMove = 0;
private Color originalColor;
private bool markedForUpdate = false;
public Element(Element e) {
Position = e.Position;
Chunk = e.Chunk;
lastMove = Engine.GetFramesDrawn();
Active = e.active;
lastMove = e.lastMove;
lastUpdate = e.lastUpdate;
Chunk.SetElementActive(this, Active);
}
public Element(int x, int y, Chunk chunk) {
Position.X = x;
Position.Y = y;
Chunk = chunk;
Active = true;
lastMove = Engine.GetFramesDrawn();
Chunk.SetElementActive(this, Active);
}
public bool Active {
get => active;
set {
if (active == value) return;
active = value;
Chunk.SetElementActive(this, value);
lastMove = Engine.GetFramesDrawn();
if (!active)
ResetColor();
else
if (active) {
Moved();
} else {
ResetColor();
}
}
}
@@ -68,7 +71,6 @@ public class Element{
return false; // already updated this frame
lastUpdate = frame;
return true;
}
@@ -76,24 +78,7 @@ public class Element{
return $"{GetType()} {Position}[{Chunk.Index}] {active}";
}
protected virtual void Tick() {
Vector2I randomDirection = RandomDirectionDown();
if (Chunk.IsEmpty(Position + Vector2I.Down))
Chunk.Swap(this, Position + Vector2I.Down);
else if (Chunk.IsEmpty(Position + randomDirection))
Chunk.Swap(this, Position + randomDirection);
else if (Chunk.IsEmpty(Position + randomDirection * VERTICAL_OPPOSITE))
Chunk.Swap(this, Position + randomDirection * VERTICAL_OPPOSITE);
// density check
if (Chunk.Get(Position + Vector2I.Down)?.Density < Density)
Chunk.Swap(this, Position + Vector2I.Down);
else if (Chunk.Get(Position + Vector2I.Down + randomDirection)?.Density < Density)
Chunk.Swap(this, Position + Vector2I.Down + randomDirection);
}
protected virtual void Tick() { }
protected Vector2I RandomDirectionDown() {
int randomDirection = GD.Randi() % 2 != 0 ? 1 : -1;
@@ -146,4 +131,23 @@ public class Element{
public bool IsEmpty() {
return GetType() == typeof(Element);
}
public virtual void ActivateNeighbors() {
Element n = Chunk.Get(Position + Vector2I.Up);
if (n != null && !n.IsEmpty())
n.Active = true;
//
// Element e = Chunk.Get(Position + Vector2I.Right);
// if (e != null && !e.IsEmpty())
// e.Active = true;
//
// Element s = Chunk.Get(Position + Vector2I.Down);
// if (null != s && !s.IsEmpty())
// s.Active = true;
//
// Element w = Chunk.Get(Position + Vector2I.Left);
// if (null != w && !w.IsEmpty())
// w.Active = true;
}
}

View File

@@ -17,18 +17,37 @@ public abstract class Liquid : Element {
return true; // not necessarily end, subclasses could do some more things
}
protected override void Tick() {
protected virtual void Tick() {
Vector2I randomDirection = RandomDirectionDown();
if (randomDirection.Y != 0)
randomDirection *= Vector2I.Left * (int)(GD.Randi() % MAX_VERTICAL_SPREAD);
if (Chunk.IsEmpty(Position + Vector2I.Down))
Chunk.Swap(this, Position + Vector2I.Down);
else if (Chunk.IsEmpty(Position + randomDirection))
Chunk.Swap(this, Position + randomDirection);
else if (Chunk.IsEmpty(Position + randomDirection * VERTICAL_OPPOSITE))
Chunk.Swap(this, Position + randomDirection * VERTICAL_OPPOSITE);
else if (Chunk.IsEmpty(Position + randomDirection))
Chunk.Swap(this, Position + Vector2I.Right * randomDirection);
Chunk.Swap(this, Position + Vector2I.Right + randomDirection);
else if (Chunk.IsEmpty(Position - randomDirection))
Chunk.Swap(this, Position + Vector2I.Right + randomDirection * VERTICAL_OPPOSITE);
}
else if (Chunk.IsEmpty(Position + randomDirection))
Chunk.Swap(this, Position + Vector2I.Right * randomDirection * VERTICAL_OPPOSITE);
public override void ActivateNeighbors() {
Element n = Chunk.Get(Position + Vector2I.Up);
if (n != null && !n.IsEmpty())
n.Active = true;
// only activate liquids left or right
Element e = Chunk.Get(Position + Vector2I.Right);
if (e != null && e.GetType() == typeof(Liquid))
e.Active = true;
Element s = Chunk.Get(Position + Vector2I.Down);
if (null != s && s.GetType() == typeof(Liquid))
s.Active = true;
}
}

View File

@@ -14,4 +14,29 @@ public abstract class Solid : Element {
return true; // not necessarily end, subclasses could do some more things
}
protected virtual void Tick() {
Vector2I randomDirection = RandomDirectionDown();
// fall speed reduction:
if (GD.Randi() % MAX_DIFFUSE_SPEED > DiffuseSpeed) return; // descend slower
if (Chunk.IsEmpty(Position + Vector2I.Down))
Chunk.Swap(this, Position + Vector2I.Down);
else if (Chunk.IsEmpty(Position + Vector2I.Down + randomDirection))
Chunk.Swap(this, Position + Vector2I.Down + randomDirection);
else if (Chunk.IsEmpty(Position + Vector2I.Down + randomDirection * VERTICAL_OPPOSITE))
Chunk.Swap(this, Position + Vector2I.Down + randomDirection * VERTICAL_OPPOSITE);
// density check
if (Chunk.Get(Position + Vector2I.Down)?.Density < Density)
Chunk.Swap(this, Position + Vector2I.Down);
else if (Chunk.Get(Position + Vector2I.Down + randomDirection)?.Density < Density)
Chunk.Swap(this, Position + Vector2I.Down + randomDirection);
else if (Chunk.Get(Position + Vector2I.Down + randomDirection * VERTICAL_OPPOSITE)?.Density < Density)
Chunk.Swap(this, Position + Vector2I.Down + randomDirection * VERTICAL_OPPOSITE);
}
}