forked from nope5166/AtomCraft-2.28
418 lines
13 KiB
C#
418 lines
13 KiB
C#
using UnityEngine;
|
|
using System.Collections.Generic;
|
|
using System.Collections;
|
|
|
|
public class Atom : MonoBehaviour
|
|
{
|
|
|
|
public string elementName;
|
|
public string elementSymbol;
|
|
|
|
public int atomicNumber;
|
|
public float atomicWeight;
|
|
|
|
public int protonCount;
|
|
public Color protonColor;
|
|
|
|
public int neutronCount;
|
|
public Color neutronColor;
|
|
|
|
public int[] electronConfiguration;
|
|
public float electronShellSpacing = 0.5f;
|
|
public Color electronColor;
|
|
|
|
public bool spinElectrons = true;
|
|
public bool freezeNucleusMovementAfter5Seconds = true;
|
|
|
|
List<GameObject> shells = new List<GameObject>();
|
|
|
|
Transform nucleus;
|
|
private float electronFirstShellSpacing;
|
|
|
|
public void Start()
|
|
{
|
|
electronFirstShellSpacing = 0.26f;
|
|
//Assign Nucleus GameObject
|
|
nucleus = transform.GetChild(0);
|
|
|
|
//Nucleons
|
|
int pc = protonCount;
|
|
int nc = neutronCount;
|
|
|
|
float scaleCount = 0.2f;
|
|
|
|
generateProton(transform.position);
|
|
pc -= 1;
|
|
|
|
for (int i = 1; i <= nc + pc; i++)
|
|
{
|
|
int nucleonsToCreate = int.Parse((Mathf.Pow(2f, i - 1f) * 5f).ToString());
|
|
|
|
if (nc + pc >= nucleonsToCreate)
|
|
{
|
|
string s = createNucleons(nucleonsToCreate, scaleCount, pc, nc);
|
|
scaleCount += 0.2f;
|
|
pc -= int.Parse(s.Split(',')[0]);
|
|
nc -= int.Parse(s.Split(',')[1]);
|
|
}
|
|
else
|
|
{
|
|
string s = createNucleons(pc + nc, scaleCount, pc, nc);
|
|
scaleCount += 0.2f;
|
|
|
|
pc -= int.Parse(s.Split(',')[0]);
|
|
nc -= int.Parse(s.Split(',')[1]);
|
|
}
|
|
|
|
}
|
|
|
|
//Electrons
|
|
GameObject[] shellsGO = generateElectronShells();
|
|
|
|
for (int loop = 0; loop < electronConfiguration.Length; loop++)
|
|
{
|
|
int numPoints = electronConfiguration[loop];
|
|
|
|
for (int pointNum = 0; pointNum < numPoints; pointNum++)
|
|
{
|
|
float i = (float)(pointNum * 1.0) / numPoints;
|
|
float angle = i * Mathf.PI * 2;
|
|
float x = transform.position.x + (Mathf.Sin(angle) * (3 * (loop + 1)));
|
|
float z = transform.position.z + (Mathf.Cos(angle) * (3 * (loop + 1)));
|
|
Vector3 pos = new Vector3(x, transform.position.y, z);
|
|
|
|
generateElectron(pos, electronFirstShellSpacing + (electronShellSpacing * loop), loop + 1, shellsGO[loop]);
|
|
atomicNumber += 1;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
string createNucleons(int nPoints, float scale, int pcount, int ncount)
|
|
{
|
|
int npc = 0;
|
|
int nnc = 0;
|
|
|
|
float fPoints = (float)nPoints;
|
|
|
|
Vector3[] points = new Vector3[nPoints];
|
|
|
|
float inc = Mathf.PI * (3 - Mathf.Sqrt(5));
|
|
float off = 2 / fPoints;
|
|
|
|
for (int k = 0; k < nPoints; k++)
|
|
{
|
|
float y = k * off - 1 + (off / 2);
|
|
float r = Mathf.Sqrt(1 - y * y);
|
|
float phi = k * inc;
|
|
|
|
points[k] = new Vector3(Mathf.Cos(phi) * r, y, Mathf.Sin(phi) * r);
|
|
}
|
|
|
|
foreach (Vector3 point in points)
|
|
{
|
|
if (pcount > 0 && ncount > 0)
|
|
{
|
|
int borc = Random.Range(1, 10);
|
|
if (borc > 5 && pcount > 0)
|
|
{
|
|
GameObject outerSphere = generateProton(transform.position);
|
|
outerSphere.transform.position += point * scale;
|
|
npc += 1;
|
|
pcount -= 1;
|
|
}
|
|
else if (borc < 6 && ncount > 0)
|
|
{
|
|
GameObject outerSphere = generateNeutron(transform.position);
|
|
outerSphere.transform.position += point * scale;
|
|
nnc += 1;
|
|
ncount -= 1;
|
|
}
|
|
}
|
|
|
|
else if (pcount > 0 && ncount == 0)
|
|
{
|
|
GameObject outerSphere = generateProton(transform.position);
|
|
outerSphere.transform.position += point * scale;
|
|
npc += 1;
|
|
pcount -= 1;
|
|
}
|
|
|
|
else if (pcount == 0 && ncount > 0)
|
|
{
|
|
GameObject outerSphere = generateNeutron(transform.position);
|
|
outerSphere.transform.position += point * scale;
|
|
nnc += 1;
|
|
ncount -= 1;
|
|
}
|
|
}
|
|
|
|
return npc + "," + nnc;
|
|
}
|
|
|
|
public void AddParticel(string particle)
|
|
{
|
|
int nc = 0;
|
|
int pc = 0;
|
|
Debug.Log("Adding " + particle);
|
|
|
|
if (particle == "electron")
|
|
{
|
|
AddElectron();
|
|
}
|
|
else
|
|
{
|
|
if (particle == "proton")
|
|
pc = 1;
|
|
else if (particle == "neutron")
|
|
nc = 1;
|
|
|
|
float scaleCount = 0.2f;
|
|
|
|
for (int i = 1; i <= nc + pc; i++)
|
|
{
|
|
int nucleonsToCreate = int.Parse((Mathf.Pow(2f, i - 1f) * 5f).ToString());
|
|
|
|
if (nc + pc >= nucleonsToCreate)
|
|
{
|
|
string s = createNucleons(nucleonsToCreate, scaleCount, pc, nc);
|
|
scaleCount += 0.2f;
|
|
pc -= int.Parse(s.Split(',')[0]);
|
|
nc -= int.Parse(s.Split(',')[1]);
|
|
}
|
|
else
|
|
{
|
|
string s = createNucleons(pc + nc, scaleCount, pc, nc);
|
|
scaleCount += 0.2f;
|
|
|
|
pc -= int.Parse(s.Split(',')[0]);
|
|
nc -= int.Parse(s.Split(',')[1]);
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
private void AddElectron()
|
|
{
|
|
foreach (GameObject shell in shells)
|
|
{
|
|
Destroy(shell);
|
|
}
|
|
|
|
shells.Clear();
|
|
|
|
if (IsShellFull(electronConfiguration.Length, electronConfiguration[electronConfiguration.Length - 1]))
|
|
{
|
|
|
|
int[] newConfig = new int[electronConfiguration.Length + 1];
|
|
for (int i = 0; i < electronConfiguration.Length; i++)
|
|
{
|
|
newConfig[i] = electronConfiguration[i];
|
|
}
|
|
newConfig[electronConfiguration.Length] = 1;
|
|
electronConfiguration = newConfig;
|
|
Debug.Log("Shell full -- New electron configuration: " + newConfig);
|
|
}
|
|
else
|
|
{
|
|
electronConfiguration[electronConfiguration.Length - 1]++;
|
|
}
|
|
|
|
GameObject[] shellsGO = generateElectronShells();
|
|
|
|
for (int loop = 0; loop < electronConfiguration.Length; loop++)
|
|
{
|
|
int numPoints = electronConfiguration[loop];
|
|
|
|
for (int pointNum = 0; pointNum < numPoints; pointNum++)
|
|
{
|
|
float i = (float)(pointNum * 1.0) / numPoints;
|
|
float angle = i * Mathf.PI * 2;
|
|
float x = transform.position.x + (Mathf.Sin(angle) * (3 * (loop + 1)));
|
|
float z = transform.position.z + (Mathf.Cos(angle) * (3 * (loop + 1)));
|
|
Vector3 pos = new Vector3(x, transform.position.y, z);
|
|
|
|
generateElectron(pos, electronFirstShellSpacing + (electronShellSpacing * loop), loop + 1, shellsGO[loop]);
|
|
|
|
atomicNumber += 1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
bool IsShellFull(int shellNumber, int numElectrons)
|
|
{
|
|
// Calculate the maximum capacity of the given shell
|
|
int maxCapacity = 2 * shellNumber * shellNumber;
|
|
|
|
// Compare the number of electrons with the maximum capacity
|
|
return numElectrons == maxCapacity;
|
|
}
|
|
|
|
bool prevSpinElectrons = true;
|
|
|
|
public void Update()
|
|
{
|
|
Vector3 currentRotation = transform.eulerAngles;
|
|
float clampedYRotation = Mathf.Clamp(currentRotation.y, -90f, 90f);
|
|
transform.eulerAngles = new Vector3(-45f, clampedYRotation, currentRotation.z);
|
|
|
|
if (spinElectrons && !prevSpinElectrons)
|
|
{
|
|
foreach (GameObject e in FindObjectsOfType(typeof(GameObject)))
|
|
{
|
|
if (e.name == "Electron")
|
|
{
|
|
e.GetComponent<Electron>().enabled = true;
|
|
prevSpinElectrons = spinElectrons;
|
|
}
|
|
}
|
|
}
|
|
|
|
else if (!spinElectrons && prevSpinElectrons)
|
|
{
|
|
foreach (GameObject e in FindObjectsOfType(typeof(GameObject)))
|
|
{
|
|
if (e.name == "Electron")
|
|
{
|
|
e.GetComponent<Electron>().enabled = false;
|
|
prevSpinElectrons = spinElectrons;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void drawCircle(float radius, LineRenderer lr)
|
|
{
|
|
lr.positionCount = 361;
|
|
lr.useWorldSpace = false;
|
|
lr.startWidth = lr.endWidth = 0.01f;
|
|
lr.materials[0] = new Material(Shader.Find("Diffuse"));
|
|
lr.materials[0].SetColor("_Color", new Color32(128, 223, 255, 0));
|
|
|
|
float x, y = 0, z, angle = 0;
|
|
|
|
for (int i = 0; i < 361; i++)
|
|
{
|
|
x = Mathf.Sin(Mathf.Deg2Rad * angle) * radius;
|
|
z = Mathf.Cos(Mathf.Deg2Rad * angle) * radius;
|
|
|
|
lr.SetPosition(i, new Vector3(x, y, z));
|
|
|
|
angle += 1;
|
|
}
|
|
}
|
|
|
|
public GameObject generateProton(Vector3 pos)
|
|
{
|
|
GameObject proton = GameObject.CreatePrimitive(PrimitiveType.Sphere);
|
|
proton.name = "Proton";
|
|
proton.transform.position = pos;
|
|
proton.AddComponent<Rigidbody>().useGravity = false;
|
|
|
|
Renderer renderer = proton.GetComponent<Renderer>();
|
|
Material material = new Material(Shader.Find("Universal Render Pipeline/Lit"));
|
|
material.color = protonColor;
|
|
renderer.material = material;
|
|
|
|
proton.AddComponent<Nucleon>();
|
|
|
|
proton.transform.SetParent(nucleus);
|
|
proton.transform.localScale = new Vector3(0.25f, 0.25f, 0.25f);
|
|
|
|
return proton;
|
|
}
|
|
|
|
public GameObject generateNeutron(Vector3 pos)
|
|
{
|
|
GameObject neutron = GameObject.CreatePrimitive(PrimitiveType.Sphere);
|
|
neutron.name = "Neutron";
|
|
neutron.transform.position = pos;
|
|
neutron.AddComponent<Rigidbody>().useGravity = false;
|
|
|
|
Renderer renderer = neutron.GetComponent<Renderer>();
|
|
Material material = new Material(Shader.Find("Universal Render Pipeline/Lit"));
|
|
material.color = neutronColor;
|
|
renderer.material = material;
|
|
|
|
neutron.GetComponent<Renderer>().material.SetColor("_Color", neutronColor);
|
|
neutron.AddComponent<Nucleon>();
|
|
|
|
neutron.transform.SetParent(nucleus);
|
|
neutron.transform.localScale = new Vector3(0.25f, 0.25f, 0.25f);
|
|
|
|
return neutron;
|
|
}
|
|
|
|
public GameObject[] generateElectronShells()
|
|
{
|
|
|
|
for (int loop = 0; loop < electronConfiguration.Length; loop++)
|
|
{
|
|
GameObject shell = new GameObject();
|
|
shell.name = "Shell " + (loop + 1);
|
|
shell.transform.parent = transform;
|
|
shell.transform.localPosition = nucleus.localPosition;
|
|
LineRenderer lr = shell.AddComponent<LineRenderer>();
|
|
|
|
drawCircle(electronFirstShellSpacing + (electronShellSpacing * loop), lr);
|
|
|
|
shells.Add(shell);
|
|
}
|
|
|
|
return shells.ToArray();
|
|
}
|
|
|
|
public void generateElectron(Vector3 pos, float r, int shell, GameObject shellGO)
|
|
{
|
|
GameObject electron = GameObject.CreatePrimitive(PrimitiveType.Sphere);
|
|
electron.name = "Electron";
|
|
electron.transform.localScale = new Vector3(0.08f, 0.08f, 0.08f);
|
|
electron.transform.position = pos;
|
|
electron.transform.parent = shellGO.transform;
|
|
|
|
Renderer renderer = electron.GetComponent<Renderer>();
|
|
Material material = new Material(Shader.Find("Universal Render Pipeline/Lit"));
|
|
material.color = electronColor;
|
|
renderer.material = material;
|
|
|
|
Destroy(electron.GetComponent<SphereCollider>());
|
|
Electron e = electron.AddComponent<Electron>();
|
|
e.radius = r;
|
|
e.centre = transform;
|
|
e.rotationSpeed = 80 + (10 * shell);
|
|
}
|
|
|
|
public Vector3 getNucleusPosition()
|
|
{
|
|
return transform.position;
|
|
}
|
|
|
|
public Vector3 getShellPosition()
|
|
{
|
|
if (IsShellFull(electronConfiguration.Length, electronConfiguration[electronConfiguration.Length - 1]))
|
|
{
|
|
float x = transform.position.x + (Mathf.Sin(0) * (3 * (electronConfiguration.Length + 1)));
|
|
float z = transform.position.z + (Mathf.Cos(0) * (3 * (electronConfiguration.Length + 1)));
|
|
Vector3 result = new Vector3(x, transform.position.y, z);
|
|
|
|
float radius = electronFirstShellSpacing + (electronShellSpacing * (electronConfiguration.Length));
|
|
return (result - transform.position).normalized * radius + transform.position;
|
|
}
|
|
else
|
|
{
|
|
float x = transform.position.x + (Mathf.Sin(0) * (3 * (electronConfiguration.Length)));
|
|
float z = transform.position.z + (Mathf.Cos(0) * (3 * (electronConfiguration.Length)));
|
|
Vector3 result = new Vector3(x, transform.position.y, z);
|
|
|
|
float radius = electronFirstShellSpacing + (electronShellSpacing * (electronConfiguration.Length));
|
|
float radius2 = electronFirstShellSpacing + (electronShellSpacing * (electronConfiguration.Length - 1));
|
|
Debug.Log("Radius1 = " + radius + "; Radius2 = " + radius2);
|
|
return (result - transform.position).normalized * radius + transform.position;
|
|
}
|
|
}
|
|
}
|