Grid/Destruction/DebrisVisualPoolcs.cs
using Sandbox;
using System;
using System.Collections.Generic;
using static Sandbox.Services.Inventory;
namespace Sandbox.Sboku;
public sealed class DebrisVisualPool : Component
{
private sealed class ColumnItem
{
public GameObject Go;
public ModelRenderer Renderer;
public Vector3 StartPos;
public Vector3 EndPos;
public float Time;
}
private readonly Queue<ColumnItem> columnPool = new();
private readonly List<ColumnItem> activeColumns = new();
[Property] public int MaxColumns { get; set; } = 8;
[Property] public Model DebrisModel { get; set; }
[Property] public Material BaseMaterial { get; set; }
[Property] public int MaxInstances { get; set; } = 256;
[Property] public float Lifetime { get; set; } = 1.5f;
// 🔑 Yksi debris-instanssi
private sealed class DebrisItem
{
public ModelRenderer Renderer;
public Vector3 Velocity;
public float SpawnTime;
}
private readonly Queue<DebrisItem> pool = new();
private readonly List<DebrisItem> active = new();
protected override void OnStart()
{
//Debris
for (int i = 0; i < MaxInstances; i++)
{
var go = new GameObject(true, "debris_instance");
go.SetParent(GameObject, false);
var mr = go.Components.Create<ModelRenderer>();
mr.Model = DebrisModel;
mr.MaterialOverride = BaseMaterial;
mr.Enabled = false;
pool.Enqueue(new DebrisItem
{
Renderer = mr
});
}
//Pylväät
for (int i = 0; i < MaxColumns; i++)
{
var go = new GameObject(true, "falling_column");
go.SetParent(GameObject, false);
var mr = go.Components.Create<ModelRenderer>();
mr.Model = Model.Load("models/dev/box.vmdl");
mr.Enabled = false;
columnPool.Enqueue(new ColumnItem
{
Go = go,
Renderer = mr
});
}
}
private const float fallDuration = 0.6f;
int verticalSlices = 3;
int horizontalSlices = 1;
public void SpawnColumnDebris(
Vector3 columnBaseWorld,
int heightInCells,
float cellSize,
int hitCellZ,
Material wallMaterial
)
{
if (pool.Count == 0)
return;
const float modelUnitScale = 0.02f;
float widthWorld = cellSize;
int fallingCells = heightInCells - hitCellZ - 1;
if (fallingCells <= 0)
return;
float totalHeightWorld = fallingCells * cellSize;
float sliceHeight = totalHeightWorld / verticalSlices;
float sliceWidth = widthWorld / horizontalSlices;
float startZ = columnBaseWorld.z-cellSize/2; //+ (hitCellZ) * cellSize;
for (int z = 0; z < verticalSlices; z++)
{
for (int xy = 0; xy < horizontalSlices; xy++)
{
if (pool.Count == 0)
return;
var item = pool.Dequeue();
var go = item.Renderer.GameObject;
item.Renderer.MaterialOverride = wallMaterial ?? BaseMaterial;
item.Renderer.Enabled = true;
float h = sliceHeight * Game.Random.Float(0.85f, 1.15f);
float w = sliceWidth * Game.Random.Float(0.75f, 1.1f);
go.Transform.Scale = new Vector3(
w * modelUnitScale,
w * modelUnitScale,
h * modelUnitScale
);
Vector3 sideOffset =
Vector3.Random.WithZ(0).Normal *
Game.Random.Float(0f, sliceWidth * 0.35f);
float zPos =
startZ +
(z + 0.5f) / verticalSlices * totalHeightWorld
- h * 0.5f;
go.Transform.Position =
new Vector3(columnBaseWorld.x, columnBaseWorld.y, zPos)
+ sideOffset;
go.Transform.Rotation = Rotation.Identity;
item.Velocity =
Vector3.Down * Game.Random.Float(140f, 240f) +
sideOffset.Normal * Game.Random.Float(40f, 90f);
item.SpawnTime = Time.Now;
active.Add(item);
}
}
}
protected override void OnUpdate()
{
// 🔽 Falling columns
for (int i = activeColumns.Count - 1; i >= 0; i--)
{
var item = activeColumns[i];
item.Time += Time.Delta;
float t = item.Time / fallDuration;
if (t >= 1f)
{
item.Renderer.Enabled = false;
activeColumns.RemoveAt(i);
columnPool.Enqueue(item);
continue;
}
float eased = t * t; // raskas tunne
item.Go.WorldPosition =
Vector3.Lerp(item.StartPos, item.EndPos, eased);
}
for (int i = active.Count - 1; i >= 0; i--)
{
var item = active[i];
var go = item.Renderer.GameObject;
float age = Time.Now - item.SpawnTime;
if (age > Lifetime)
{
item.Renderer.Enabled = false;
active.RemoveAt(i);
pool.Enqueue(item);
continue;
}
// 🔽 Raskaampi painovoima
item.Velocity += Vector3.Down * 1800f * Time.Delta;
// 🧲 Ilmanvastus (tämä tekee "painon")
item.Velocity *= MathF.Pow(0.15f, Time.Delta);
go.Transform.Position += item.Velocity * Time.Delta;
// 🔄 Pyöriminen riippuu nopeudesta
float spin = item.Velocity.Length * 0.02f;
go.Transform.Rotation *= Rotation.FromYaw(spin * Time.Delta);
}
}
}