9 Commits

Author SHA1 Message Date
a119e92bf6 fixed brush drawing across chunk borders 2025-04-27 15:16:10 +02:00
da3afd22fc fixed drawpixel optimization
minor class refactoring
2025-04-27 15:05:40 +02:00
abf948a310 adjusted debug mode 2025-04-27 14:15:14 +02:00
2cd6a757dc fixed memory leak
fixed trying to draw out of bounds
2025-04-27 14:00:54 +02:00
4ce265e722 fixed unnecessary write to texture if no changes happened 2025-04-27 13:49:35 +02:00
572e02956c fixed benchmark placement 2025-04-27 13:18:18 +02:00
de99d54ad6 fixed brush Y dimension 2025-04-27 13:04:06 +02:00
2bcdeecb81 Merge branch 'performance-improvements' 2025-04-21 18:57:20 +02:00
7b2845ee01 added benchmark function
added .txt for benchmark results
fixed generating level message
2024-10-27 14:08:19 +01:00
7 changed files with 79 additions and 51 deletions

View File

@@ -3,13 +3,10 @@ using Godot;
public partial class PerfDetails : Label
{
[Export]
public bool ShowDetails = true;
public override void _Process(double delta)
{
Text = "";
if (!ShowDetails) return;
if (!Main.Instance.DebugMode) return;
int activeElements = 0;
foreach (Chunk c in Main.Instance.Level.GetChunks())

View File

@@ -7,7 +7,7 @@
[node name="Main" type="Node2D"]
script = ExtResource("1_k1i8e")
DebugVisualization = true
DebugMode = true
BrushSize = 2
RainAmount = 1.0

View File

@@ -2,7 +2,7 @@
namespace FOU.Scripts.Elements;
public class Element {
public class Element{
public Chunk Chunk;
public Vector2I Position;
@@ -15,11 +15,12 @@ public class Element {
protected const float MAX_COLOR_VARIANCE = 0.1f;
protected static readonly Vector2I VERTICAL_OPPOSITE = new Vector2I(-1, 1);
protected int lastMove = 0;
private bool active = false;
private int lastUpdate = -1;
private int lastMove = 0;
private Color originalColor;
private bool markedForUpdate = false;
public Element(Element e) {
Position = e.Position;
@@ -42,7 +43,10 @@ public class Element {
active = value;
Chunk.SetElementActive(this, value);
// SetDebugColor(value, new Color(0.2f, 0.2f, 0.2f));
if (!active)
ResetColor();
else
Moved();
}
}
@@ -56,8 +60,13 @@ public class Element {
public virtual bool Update() {
if (!Active) return false;
if (lastUpdate == Engine.GetFramesDrawn()) return false; // already updated this frame
lastUpdate = Engine.GetFramesDrawn();
int frame = Engine.GetFramesDrawn();
if (lastMove + STEPS_UNTIL_INACTIVE < frame)
Active = false;
if (lastUpdate == frame)
return false; // already updated this frame
lastUpdate = frame;
return true;
}
@@ -103,15 +112,25 @@ public class Element {
public void ResetColor() {
color = originalColor;
MarkForUpdate();
}
public void SetDebugColor(Color color) {
if (!Main.Instance.DebugVisualization) return;
if (!Main.Instance.DebugMode) return;
this.color = color;
}
public void Moved() {
lastMove = Engine.GetFramesDrawn();
MarkForUpdate();
}
public bool MarkedForUpdate() {
return markedForUpdate;
}
public void MarkForUpdate(bool mark = true) {
markedForUpdate = true;
}
}

View File

@@ -5,11 +5,12 @@ namespace FOU.Scripts.Elements;
public abstract class Liquid : Element {
public const int MAX_VERTICAL_SPREAD = 3;
protected Liquid(int x, int y, ref Chunk chunk) : base(x, y, chunk) { }
protected Liquid(int x, int y, ref Chunk chunk) : base(x, y, chunk) {
MarkForUpdate();
}
public override bool Update() {
if (!base.Update()) return false;
if (lastMove + STEPS_UNTIL_INACTIVE < Engine.GetFramesDrawn()) Active = false;
Tick();

View File

@@ -3,11 +3,12 @@
namespace FOU.Scripts.Elements;
public abstract class Solid : Element {
protected Solid(int x, int y, ref Chunk chunk) : base(x, y, chunk) { }
protected Solid(int x, int y, ref Chunk chunk) : base(x, y, chunk) {
MarkForUpdate();
}
public override bool Update() {
if (!base.Update()) return false;
if (lastMove + STEPS_UNTIL_INACTIVE < Engine.GetFramesDrawn()) Active = false;
Tick();

View File

@@ -69,7 +69,7 @@ public class Level {
GD.Print("benchmark");
for (int x = 0; x < chunksPerX; x++) {
for (int y = 0; y < chunksPerY; y++) {
WritePixel<Dirt>(x * chunkResX/2, y * chunkResY/2, 100);
WritePixel<Dirt>((x * chunkResX) + chunkResX/2, (y * chunkResY) + chunkResY/2, 100);
}
}
}
@@ -92,64 +92,73 @@ public class Level {
public void WritePixel<T>(int x, int y, int size) {
int halfsize = size/2;
int startPtX = x % chunkResX;
int startPtY = y % chunkResY;
for (int i = -halfsize; i <= halfsize; i++) {
for (int j = 0; j < 1; j++) {
// for (int j = -halfsize; j <= halfsize; j++) {
for (int j = -halfsize; j <= halfsize; j++) {
// calculate in-chunk coordinates
int inChunkX = x % chunkResX;
int inChunkY = y % chunkResY;
int brushX = i;
int brushY = j;
int iteratorX = i;
int iteratorY = j;
int ptX = startPtX;
int ptY = startPtY;
// calculate chunk to write to
int chunkX = x/chunkResX;
if (inChunkX + i < 0) {
// left of chunk
if (startPtX + iteratorX < 0) {
chunkX--;
// 320 -22
brushX = chunkResX + inChunkX + i;
inChunkX = chunkResX - inChunkX;
} else if (inChunkX + i >= chunkResX) {
iteratorX = chunkResX + startPtX + iteratorX;
ptX = startPtX + iteratorX;
} else {
ptX = startPtX + iteratorX;
}
if (startPtX + iteratorX >= chunkResX) {
chunkX++;
inChunkX = 0;
brushX = i % chunkResX;
ptX = startPtX + iteratorX - chunkResX;
}
inChunkX += brushX;
if (chunkX < 0 || chunkX >= chunksPerX) {
GD.PrintErr($"Trying to write out of bounds: {x}:{y}");
return;
}
int chunkY = y/chunkResY;
if (inChunkY + j < 0) {
// above chunk
if (startPtY + iteratorY < 0) {
chunkY--;
brushY = chunkResY - (inChunkY + j);
inChunkY = chunkResY - inChunkY;
} else if (inChunkY + j >= chunkResY) {
ptY = chunkResY + (startPtY + iteratorY);
} else {
ptY = startPtY + iteratorY;
}
if (startPtY + iteratorY >= chunkResY) {
chunkY++;
inChunkY = 0;
brushY = j % chunkResY;
}
inChunkY += brushY;
if (chunkY < 0 || chunkY >= chunksPerY) {
GD.PrintErr($"Trying to write out of bounds: {x}:{y}");
return;
ptY = startPtY + iteratorY - chunkResY;
}
chunks[chunkX, chunkY].WritePixel<T>(inChunkX, inChunkY);
// ignore everything outside
if (chunkX < 0) continue;
if (chunkX >= chunksPerX) continue;
if (chunkY < 0) continue;
if (chunkY >= chunksPerY) continue;
chunks[chunkX, chunkY].WritePixel<T>(ptX, ptY);
}
}
}
public Image DrawLevel() {
// chunk
for (int cx = 0; cx < chunksPerX; cx++) {
for (int cy = 0; cy < chunksPerY; cy++) {
// pixel in chunk
for (int x = 0; x < chunkResX; x++) {
for (int y = 0; y < chunkResY; y++) {
// TODO: multithreading here! use Chunk.DrawLevel() and stitch images together
image.SetPixel(cx*chunkResX + x, cy*chunkResY + y, chunks[cx,cy].Elements[x, y].Color);
if (chunks[cx, cy].Elements[x, y].MarkedForUpdate()) {
image.SetPixel(cx * chunkResX + x, cy * chunkResY + y, chunks[cx, cy].Elements[x, y].Color);
chunks[cx, cy].Elements[x, y].MarkForUpdate(false);
}
}
}
}

View File

@@ -3,7 +3,7 @@ using FOU.Scripts.Elements;
using Godot;
public partial class Main : Node2D {
[Export] public bool DebugVisualization = false;
[Export] public bool DebugMode = false;
[Export] public int BrushSize = 5;
[Export] public float TextureResolution = 0.5f;
@@ -32,6 +32,7 @@ public partial class Main : Node2D {
}
public override void _Process(double delta) {
mLevelDrawer.Texture?.Dispose();
mLevelDrawer.Texture = ImageTexture.CreateFromImage(Level.DrawLevel());
}