//Awwww sweet DFS with backtracking, for real bool MonstersAreConnected(ref Atom3D maStart, ref Atom3D maEnd) { if (maStart == maEnd) { return(true); } maStart.visitState = (int)Atom3D.DFSState.visiting; foreach (Atom3D neighbour in maStart.neighbours) { Atom3D neighbourRef = neighbour; if (neighbourRef.visitState == (int)Atom3D.DFSState.unvisited) { atomPath.Push(neighbourRef); if (MonstersAreConnected(ref neighbourRef, ref maEnd)) { return(true); } } } maStart.visitState = (int)Atom3D.DFSState.visited; Atom3D curr; while (atomPath.Count > 0) { curr = atomPath.Pop(); if (curr == maStart) { break; } } return(false); }
//public GameObject pathHighlighter; // Use this for initialization public virtual void Awake() { self = this; visitState = (int)DFSState.unvisited; if (Application.loadedLevelName == "AnchorDemo") { neighbours = new List <Atom3D>(); } //by default, path color is white pathColor = Color.white; }
public void ClearPath() { while (path.Count > 0) { Atom3D node = path[0]; if (node != null) { //node.pathHighlighter.SetActive(false); //node.GetComponent<MeshRenderer>().material.color = node.normalColor; } path.RemoveAt(0); } }
public void UpdateAtomBtnWithStock(Atom3D newlyAddedAtom) { if (Application.loadedLevelName == "AnchorDemo") { AtomUIData atomUIData = AtomStaticData.AtomDataMap[newlyAddedAtom.name]; atomUIData.btnText.text = newlyAddedAtom.name + " (" + atomUIData.remainingStock + ")"; if (atomUIData.remainingStock <= 0) { atomUIData.btn.interactable = false; } } }
// Use this for initialization void Start() { clickIsForAddingAtom = true; lastClickTime = -1.0f; atomComp = GetComponent <Atom3D>(); monsterAtomComp = gameObject.AddComponent <MonsterAtom3D>() as MonsterAtom3D; if (atomComp.charge > 0) { monsterAtomComp.charge = 6; } else { monsterAtomComp.charge = -6; } monsterAtomComp.InitColorsByCharge(); monsterAtomComp.enabled = false; atomComp.enabled = true; }
//register atom and stuff void FinishAddingAtom() { atomToAdd.name = "Atom" + atomToAdd.GetInstanceID().ToString(); //add to NaCl list Atom3D atom = atomToAdd.GetComponent <Atom3D>(); atom.Kick(); //for diff prototypes if (AtomPhysics3D.self != null) { AtomPhysics3D.self.Ions.Add(atomToAdd); } if (Application.loadedLevelName == "AnchorDemo") { //Atom2D.remainingStock -= 1; AtomStaticData.DecrementStock(atom.name); //atom.GetComponent<AudioSource>().Play(); } if (Application.loadedLevelName == "AnchorDemo") { if (AtomStaticData.totalRemainingStock <= 0) { //end of game gameState = (int)GameState.Ended; } else { gameState = (int)GameState.Running; } } else { gameState = (int)GameState.Running; } totalAtomsUsed += 1; UIControl3D.self.EnableAtomBtns(); UIControl3D.self.UpdateAtomBtnWithStock(atom); }
// Update is called once per frame void FixedUpdate() { for (int i = 0; i < Ions.Count; i++) { if (Ions[i] == null) { Ions.Remove(Ions[i]); continue; } Atom3D atom = Ions[i].GetComponent <Atom3D>(); atom.totalForce = Vector3.zero; atom.Kick(); //check if atoms out of viewport, if so, destroy /* * bool withinViewport = atom.WithinViewport(); * if(!withinViewport){ * //Destroy(atom.gameObject); * Ions.Remove(atom.gameObject); * * Destroy(atom.gameObject); * } */ } Atom3D curr; Atom3D other; for (int i = 0; i < Ions.Count; i++) { Rigidbody rb = Ions[i].GetComponent <Rigidbody>(); if (rb.velocity.magnitude < 1f) { rb.gameObject.GetComponent <Atom3D>().Kick(); } } for (int i = 0; i < Ions.Count; i++) { curr = Ions[i].GetComponent <Atom3D>(); Rigidbody currRb = Ions[i].GetComponent <Rigidbody>(); for (int j = i + 1; j < Ions.Count; j++) { other = Ions[j].GetComponent <Atom3D>(); float distance = Vector3.Distance(curr.gameObject.transform.position, other.gameObject.transform.position); //repel //current to other Vector3 forceDireciton = curr.gameObject.transform.position - other.gameObject.transform.position; //attract if (curr.charge * other.charge < 0) { forceDireciton *= -1; } float otherToCurr = 9 * Mathf.Pow(10, 9) * 1.602f * 1.602f * Mathf.Abs(other.charge) * Mathf.Abs(curr.charge) * Mathf.Pow(10, -8); float currToOther = otherToCurr; //Vector3 force = (currRb.mass * currRb.velocity - otherRb.mass * otherRb.velocity)/Time.deltaTime; forceDireciton.Normalize(); //ft = m * deltaV //deltaV = sqrt(2C/m) //ft = sqrt(2cm) curr.totalForce += forceDireciton * otherToCurr / distance / distance; //Debug.Log(otherRb.velocity); other.totalForce += -forceDireciton * currToOther / distance / distance; } /* * if(temperature > 0.0f ){ * if(!curr.pathHighlighter.activeSelf){ * //curr atom is not in a path * curr.lastRandWalkForce = RandDirection(curr.totalForce) * Mathf.Sqrt(2f*(temperature/1000f) *currRb.mass)/Time.fixedDeltaTime; * curr.totalForce += curr.lastRandWalkForce; * } * * * } */ currRb.velocity = Vector3.zero; if (currRb.gameObject.tag == "AnchorAtom" || currRb.gameObject.tag == "MonsterAnchor") { } else { currRb.AddForce(curr.totalForce); } } }
IEnumerator CheckMonsterAtomConnections() { while (true) { yield return(new WaitForSeconds(0.04f)); totalConnections = 0; foreach (MonsterAtomConnection mac in atomConnections) { Atom3D maStart = mac.start; Atom3D maEnd = mac.end; //clear visited flags foreach (MonsterAtom3D ma3D in monsterAnchors) { ma3D.visitState = (int)Atom3D.DFSState.unvisited; } foreach (GameObject atom in AtomPhysics3D.self.Ions) { atom.GetComponent <Atom3D>().visitState = (int)Atom3D.DFSState.unvisited; } //DFS bool areConnected = BacktrackMonstersMonsters(ref maStart, ref maEnd); if (areConnected) { /* * Debug.DrawLine(maStart.transform.position, maEnd.transform.position, * Color.white, 2.0f); * * Debug.Log(maStart.gameObject.name + " and " + maEnd.gameObject.name + " are connected!"); */ if (!mac.HasPath()) { //from not having path to having path, plus score GameControl3D.self.UpdateScoreBy(100.0f); } //clear old path rendering mac.ClearPath(); bool pathBroken = false; //if has path, copy path from atom path to mac.path while (atomPath.Count > 0 && !pathBroken) { Atom3D atomNode = atomPath.Pop(); if (atomNode == null) { //this happens when an atom moves out of viewport //and has been destroyed //which means the path is now broken pathBroken = true; } else { mac.path.Add(atomNode); //atomNode.GetComponent<MeshRenderer>().material.color = Color.white; //atomNode.pathHighlighter.SetActive(true); } } if (pathBroken) { mac.ClearPath(); mac.taskToggle.isOn = false; } else { mac.taskToggle.isOn = true; totalConnections += 1; } } else { //if had path last frame but no longer has it if (mac.HasPath()) { //from having path to not having path //minus score GameControl3D.self.UpdateScoreBy(-100.0f); Debug.Log("minus totalConnections"); totalConnections -= 1; } //no path, clear last path,restore normal atom colors mac.ClearPath(); mac.taskToggle.isOn = false; } } if (totalConnections >= atomConnections.Count) { GameControl3D.self.gameState = (int)GameControl3D.GameState.Ended; } } }
//dfs with backtracking wrapper bool BacktrackMonstersMonsters(ref Atom3D maStart, ref Atom3D maEnd) { atomPath.Clear(); atomPath.Push(maStart); return(MonstersAreConnected(ref maStart, ref maEnd)); }