Files
EcoSim/Assets/GameAssets/Scripts/NutrientController.cs
T
Alex 0c0af9e6a6 Expanded nutrient usage to a 2d grid based on size of plant
TODO apply usage to nutrient map centered at plant location
2025-08-08 18:40:40 -07:00

171 lines
5.0 KiB
C#

using System;
using UnityEditor.TextCore.Text;
using UnityEngine;
using static UnityEngine.GraphicsBuffer;
using static UnityEngine.UIElements.UxmlAttributeDescription;
public class NutrientController : MonoBehaviour
{
private float[,] nutrientMap;
[SerializeField, Range(10, 256)] int sizeX;
[SerializeField, Range(10, 256)] int sizeY;
[SerializeField] MeshRenderer meshRenderer;
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
nutrientMap = new float[sizeX, sizeY];
for(int r = 0; r < sizeX; r ++)
{
for(int c = 0; c < sizeY; c++)
{
nutrientMap[r, c] = 1;
}
}
}
// Update is called once per frame
void Update()
{
}
public bool PlantNutrientUse(float x, float y, float radius, float nutrientsNeeded)
{
int locX = Mathf.FloorToInt(x * sizeX);
int locY = Mathf.FloorToInt(y * sizeY);
int flooredRadius = Mathf.FloorToInt(radius);
float totalNutrients = nutrientMap[locX, locY];
float[,] nutrientsAvailable = new float[flooredRadius * 2 + 1, flooredRadius * 2 + 1];
for (int r = -flooredRadius; r <= flooredRadius; r++)
{
int currentLocX = locX + r;
for(int c = -flooredRadius; c <= flooredRadius; c++)
{
int currentLocY = locY + c;
if(r == 0 && c == 0)
{
nutrientsAvailable[flooredRadius, flooredRadius] = nutrientMap[currentLocX, currentLocY];
}
else
{
nutrientsAvailable[flooredRadius + r, flooredRadius + c] = nutrientMap[currentLocX, currentLocY] / ((Mathf.Abs(r) + Mathf.Abs(c)) * 2);
totalNutrients += nutrientMap[currentLocX, currentLocY] / ((Mathf.Abs(r) + Mathf.Abs(c)) * 2);
}
}
}
if (totalNutrients < nutrientsNeeded)
{
return false;
}
float[,] amountToUse = new float[flooredRadius * 2 + 1, flooredRadius * 2 + 1];
for(int r = 0; r < nutrientsAvailable.GetLength(0); r++)
{
for (int c = 0; c < nutrientsAvailable.GetLength(1); c++)
{
amountToUse[r, c] = (nutrientsAvailable[r, c] / totalNutrients) * nutrientsNeeded;
}
}
string output2 = "NUTRIENTS TO USE\n";
for (int r = 0; r < amountToUse.GetLength(0); r++)
{
for (int c = 0; c < amountToUse.GetLength(1); c++)
{
output2 += amountToUse[r, c] + " ";
}
output2 += "\n";
}
Debug.Log(output2);
return true;
}
public float GetNutrients(float x, float y, float radius)
{
int locX = Mathf.FloorToInt(x * sizeX);
int locY = Mathf.FloorToInt(y * sizeY);
int ceilRad = Mathf.CeilToInt(radius);
float totalNutrients = 0;
for(int r = -ceilRad; r < ceilRad; r++)
{
for (int c = -ceilRad; c < ceilRad; c++)
{
if((locX + ceilRad > 0 && locX + ceilRad < sizeX) && (locY + ceilRad > 0 && locY + ceilRad < sizeY))
{
int fraction = Mathf.Abs(r) + Mathf.Abs(c);
if(fraction == 0)
{
totalNutrients += nutrientMap[locX + ceilRad, locY + ceilRad];
}
else
{
totalNutrients += nutrientMap[locX + ceilRad, locY + ceilRad] / (fraction * 2);
}
}
}
}
return totalNutrients;
}
public void UseNutrients(float x, float y, float radius, float used)
{
int locX = Mathf.FloorToInt(x * sizeX);
int locY = Mathf.FloorToInt(y * sizeY);
nutrientMap[locX, locY] -= used;
}
public void AddNutrients(float x, float y, float added)
{
int locX = Mathf.FloorToInt(x * sizeX);
int locY = Mathf.FloorToInt(y * sizeY);
nutrientMap[locX, locY] += added;
}
private void Render()
{
Texture2D texture = new Texture2D(sizeX, sizeY);
for (int r = 0; r < sizeX; r++)
{
for (int c = 0; c < sizeY; c++)
{
float colorValue = nutrientMap[r, c];
texture.SetPixel(r, c, new Color(colorValue, colorValue, colorValue, 0.5f));
}
}
texture.Apply();
meshRenderer.material.mainTexture = texture;
meshRenderer.gameObject.SetActive(true);
}
#if UNITY_EDITOR
[UnityEditor.CustomEditor(typeof(NutrientController))]
public class NutrientControllerEditor: UnityEditor.Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
if (GUILayout.Button("Sample Button"))
{
(target as NutrientController).Render();
}
}
}
#endif
}