public void AddObjectInside(ShiftABGameObject obj) { _underObjectsHeight += obj.GetBounds().size.y; }
public bool Equals(ShiftABGameObject otherGen) { // if (ReferenceEquals(null, otherGen)) return false; // if (ReferenceEquals(this, otherGen)) return true; return (Label == otherGen.Label && IsDouble == otherGen.IsDouble && Type == otherGen.Type); }
List<int> GetStackableObjects(ShiftABGameObject objectBelow) { List<int> stackableObjects = new List<int>(); for(int i = 0; i < GameWorld.Instance.Templates.Length; i++) { int currentObjType = GetTypeByTag(GameWorld.Instance.Templates[i].tag); if(_gameObjectsDependencyGraph[currentObjType, objectBelow.Type] == 1) stackableObjects.Add(i); } return stackableObjects; }
ShiftABGameObject GenerateObject(ref LinkedList<ShiftABGameObject> stack) { // Generate next object in the stack ShiftABGameObject nextObject = new ShiftABGameObject(); if(!DefineObjectLabel(ref nextObject, ref stack)) return null; return nextObject; }
bool DefineObjectLabel(ref ShiftABGameObject nextObject, ref LinkedList<ShiftABGameObject> stack) { ShiftABGameObject objectBelow = null; if(stack.Count > 0) { objectBelow = stack.Last.Value; } else { // If the object below is the ground nextObject.Label = Random.Range(0, GameWorld.Instance.Templates.Length); // There is a chance to double the object if(nextObject.Type != (int)BlockTypes.Podium && nextObject.Type != (int)BlockTypes.Circle && Random.value < _duplicateProbability) nextObject.IsDouble = true; return true; } // Get list of objects that can be stacked List<int> stackableObjects = GetStackableObjects(objectBelow); while(stackableObjects.Count > 0) { nextObject.UnderObjectsHeight = 0f; nextObject.IsDouble = false; nextObject.Label = stackableObjects[Random.Range(0, stackableObjects.Count - 1)]; // Check if there is no stability problems if(nextObject.Type == (int)BlockTypes.Box) { // If next object is a box, check if it can enclose the underneath objects LinkedListNode<ShiftABGameObject> currentObj = stack.Last; float underObjectsHeight = 0f; while(currentObj != null) { Bounds objBelowBounds = currentObj.Value.GetBounds(); if(objBelowBounds.size.x < nextObject.GetEmptyScapeInside().x) { if(underObjectsHeight + objBelowBounds.size.y < nextObject.GetEmptyScapeInside().y) { nextObject.AddObjectInside(currentObj.Value); underObjectsHeight += objBelowBounds.size.y; currentObj = currentObj.Previous; } else break; } else break; } nextObject.UnderObjectsHeight = underObjectsHeight; // Holding object is the ground, so it is safe if(currentObj == null) return true; // Holding object is bigger, so it is safe if(currentObj.Value.GetArea() >= nextObject.GetArea()) return true; } else { // There is a chance to double the object if(objectBelow.GetBounds().size.x >= 2f * nextObject.GetBounds().size.x) if(nextObject.Type != (int)BlockTypes.Podium && nextObject.Type != (int)BlockTypes.Circle && Random.value < _duplicateProbability) nextObject.IsDouble = true; if(objectBelow.GetArea() > nextObject.GetArea()) return true; } stackableObjects.Remove(nextObject.Label); } return false; }
protected void InsertPigs(ref LinkedList<ShiftABGameObject> stack) { int pigsAdded = 0; if(stack.Count == 0) return; for (LinkedListNode<ShiftABGameObject> obj = stack.First; obj != stack.Last.Next; obj = obj.Next) { if(obj.Value.Type == (int)BlockTypes.Box && !obj.Value.IsDouble) { if(pigsAdded > 0 && Random.value < 0.5f) continue; // Check if pig dimensions fit inside the box if(Mathf.Abs (obj.Value.GetEmptyScapeInside().y - obj.Value.UnderObjectsHeight) > GameWorld.Instance._pig.GetComponent<Renderer>().bounds.size.y) { ShiftABGameObject pig = new ShiftABGameObject(); pig.Label = GameWorld.Instance.Templates.Length; LinkedListNode<ShiftABGameObject> pigNode = new LinkedListNode<ShiftABGameObject>(pig); if(obj.Value.UnderObjectsHeight > 0f) { stack.AddBefore(obj, pigNode); } else { if(obj.Value != stack.First.Value) stack.AddAfter(obj.Previous, pigNode); else stack.AddFirst(pigNode); } pigsAdded++; obj.Value.AddObjectInside(pig); } } if(obj == stack.Last) { if(pigsAdded > 0 && Random.value < 0.5f) continue; // If last element in stack is already a circle, replace it with a pig if(stack.Last.Value.Type == (int)BlockTypes.Circle) { ShiftABGameObject pig = new ShiftABGameObject(); pig.Label = GameWorld.Instance.Templates.Length; stack.Last.Value = pig; pigsAdded++; } else { if(pigsAdded > 0) break; ShiftABGameObject pig = new ShiftABGameObject(); pig.Label = GameWorld.Instance.Templates.Length; LinkedListNode<ShiftABGameObject> pigNode = new LinkedListNode<ShiftABGameObject>(pig); stack.AddLast(pigNode); pigsAdded++; break; } } } }
protected LinkedList<ShiftABGameObject> CopyStack(LinkedList<ShiftABGameObject> shiftGameObjects) { LinkedList<ShiftABGameObject> newStack = new LinkedList<ShiftABGameObject>(); if(shiftGameObjects.Count == 0) return newStack; for (LinkedListNode<ShiftABGameObject> obj = shiftGameObjects.First; obj != shiftGameObjects.Last.Next; obj = obj.Next) { ShiftABGameObject newAbGameObject = new ShiftABGameObject(); newAbGameObject.Label = obj.Value.Label; newAbGameObject.IsDouble = obj.Value.IsDouble; newAbGameObject.Position = obj.Value.Position; newAbGameObject.UnderObjectsHeight = obj.Value.UnderObjectsHeight; newStack.AddLast(newAbGameObject); } return newStack; }