예제 #1
0
파일: Entity.cs 프로젝트: RyanB156/Tribe
        // Make the entity do its action. Checks if the action was completed.
        // If so, trys to set a new one from the stack or set to default WanderAction.
        public virtual void CarryOutAction(ObjectMesh objectMesh, GameTime gameTime)
        {
            if (Action != null) // Entity controller can set actions to null or change them if it wants.
            {
                if (Action is ICheckNearbyObjectsWithTime ct)
                {
                    ct.DoWithSearchAndTime(this, objectMesh, gameTime);
                }
                else if (Action is EntityTimeAction t)
                {
                    t.DoWithTime(this, gameTime);
                }
                else if (Action is ICheckNearbyObjects c)
                {
                    c.DoWithSearch(this, objectMesh);
                }
                else // Action is normal EntityAction.
                {
                    Action.Do(this);
                }

                if (!Action.IsActive) // The action has reached an ending condition.
                {
                    ActionLocked = false;
                    CanMove      = true; // Allow the person to move here just in case I forget to reset this inside of an action...
                    Action       = null;
                }
            }
        }
예제 #2
0
        public void DoWithSearch(Entity entity, ObjectMesh objectMesh)
        {
            List <GameObject> nearbyObjects = objectMesh.GetObjectsInRange((int)entity.Position.X, (int)entity.Position.Y, 100);

            foreach (GameObject o in nearbyObjects)
            {
                if (o is Person p && p.Sex == Sex.Female)
                {
                    entity.SetColor(Color.Red);
                    return;
                }
            }

            entity.SetBaseColor();
        }
예제 #3
0
        public void DoWithSearch(Entity entity, ObjectMesh objectMesh)
        {
            List <Plant> plants = objectMesh.GetTypedObjectsInRange <Plant>(entity, entity.Size);

            foreach (Plant plant in plants)
            {
                if (entity.GetRectangle().IntersectsWith(plant.GetRectangle())) // Entity needs to be touching the tree.
                {
                    plant.Harvest();
                }
            }


            IsActive = false;
        }
예제 #4
0
        public void DoWithSearch(Entity entity, ObjectMesh objectMesh)
        {
            List <IMortal> nearbyObjects = objectMesh.GetMortalObjectsInRange(entity, entity.AttackRange);

            foreach (IMortal m in nearbyObjects)
            {
                // People can only attack animals and animals can only attack people.
                if (m != entity && (entity is Person && m is Animal || entity is Animal && m is Person))
                {
                    entity.Attack(m);
                    //Console.WriteLine($"Health = {m.GetHealth()}");
                }
            }

            End();
        }
예제 #5
0
        public void DoWithSearch(Entity entity, ObjectMesh objectMesh)
        {
            if (entity is Person person)
            {
                List <Item> pickups = objectMesh.GetTypedObjectsInRange <Item>(entity, entitySize);

                foreach (Item p in pickups)
                {
                    if (person.GetRectangleF().IntersectsWith(p.GetRectangleF()))
                    {
                        person.Pickup(p);
                    }
                }
            }

            End();
        }
예제 #6
0
        public void DoWithSearchAndTime(Entity entity, ObjectMesh objectMesh, GameTime time)
        {
            if (timerEnabled && stopTime != null)
            {
                if (time >= stopTime)
                {
                    entity.SetCanMove(true);
                    End();
                }
                return;
            }

            if (entity is Person person)
            {
                int range            = Person.mateRange;
                int mateRangeSquared = Person.mateRange * Person.mateRange;
                // Search all nearbyObjects for people to mate with. Then mate with all of them that are in range.
                List <GameObject> nearbyObjects = objectMesh.GetObjectsInRange(person.Position.X, person.Position.Y, range);
                foreach (GameObject gameObject in nearbyObjects)
                {
                    if (gameObject is Person mate && mate.Sex != person.Sex && !person.IsPregnant && !mate.IsPregnant &&
                        Utilities.SquaredDistance(person.Position, mate.Position) < mateRangeSquared)
                    {
                        person.ReproduceWith(mate);
                        // Start timer. Initialize stopTime to the current time plus x number of seconds. Start checking time to allow player to move.
                        if (!timerEnabled)
                        {
                            timerEnabled = true;
                            person.SetCanMove(false);
                            stopTime = time.Copy();
                            stopTime.AddSeconds(Person.mateTime);
                        }
                    }
                }
            }

            if (!timerEnabled)
            {
                End();
            }
        }
예제 #7
0
        public void DoWithSearch(Entity entity, ObjectMesh objectMesh)
        {
            if (entity is Person person)
            {
                List <Item> pickups = objectMesh.GetTypedObjectsInRange <Item>(entity, entitySize);

                foreach (Item p in pickups)
                {
                    if (person.GetRectangleF().IntersectsWith(p.GetRectangleF()))
                    {
                        person.Pickup(p);
                    }
                }

                // If the person is inside the house, request the house's selected item.
                if (person.GetRectangleF().IntersectsWith(house.GetRectangleF()) && housePickup != null)
                {
                    person.RequestItemByType(housePickup.Type);
                }
            }

            End();
        }
예제 #8
0
        // Update Cycle.
        public void EntityUpdate(GameTime gameTime, ObjectMesh objectMesh, int mouseX, int mouseY)
        {
            entityCount = Entities.Count;
            UpdateData();

            if (Utilities.Rng.NextDouble() < animalSpawnChance && entityCount < maxEntityCount)
            {
                SpawnRandomAnimal();
            }

            List <Entity> deadEntities = new List <Entity>();

            // Player updates.
            if (Player.BasePerson != null)
            {
                if (Player.BasePerson.Hunger <= 0.0)
                {
                    //Player.BasePerson.TakeDamage(1, null);
                }

                if (Player.IsAlive && Player.BasePerson.Health <= 0)
                {
                    Player.OnCancelData(); // Player is dead and does not have data to display.
                    Player.Kill();
                    deadEntities.Add(Player.BasePerson);
                    Player.Move();
                }
                else
                {
                    Player.CarryOutAction(objectMesh, GameTime);
                    Player.Move();
                    Player.UpdateData();
                }
            }

            // Updates for the entities in the list.
            for (int i = 0; i < Entities.Count; i++)
            {
                Entity e = Entities[i];

                List <GameObject> nearbyObjects = objectMesh
                                                  .GetObjectsInRange(e.Position.X, e.Position.Y, e.VisionRange)
                                                  .Where(o => o != e)
                                                  .ToList();

                if (e.GetHealth() <= 0)
                {
                    deadEntities.Add(e);
                    if (e is Person person)
                    {
                        person.DropAllItems(false);
                        person.OnCancelData();
                    }
                    else if (e is Animal animal)
                    {
                        animal.OnCancelData();
                    }
                }
                else
                {
                    // -- Person Updates --
                    if (e is Person p && personBrainCounter == 0) // Only decide action after a certain period of time. 1 / personBrainPeriod times.
                    {
                        if (e.Hunger <= 0.0)
                        {
                            e.TakeDamage(1, null);
                        }

                        p.UpdateNeeds();
                        p.UpdateData();

                        // People that are close together will decrease their social need.
                        if (nearbyObjects.OneSatisfies(g => g.ObjectID != p.ObjectID && g is Person))
                        {
                            p.DecreaseSocialNeed();
                        }

                        // People close to a campfire will be warmed up.
                        if (nearbyObjects.OneSatisfies(g => g is Campfire))
                        {
                            p.DecreaseWarmthNeed();
                        }

                        if (!e.ActionLocked) // Locked actions will not be overwritten. Used to make entity wait.
                        {
                            personBrain.DecideAction(p, nearbyObjects, PersonCount, GetItemCount(ItemType.Apple), mouseX, mouseY);
                        }
                    }

                    // -- Animal Updates --
                    if (e is Animal a && animalBrainCounter == 0)
                    {
                        if (!a.ActionLocked)
                        {
                            animalBrain.DecideAction(a, nearbyObjects);
                        }
                        a.UpdateNeeds();
                    }
                    e.CarryOutAction(objectMesh, GameTime);
                }
            }

            // Update brain counters after all entities have been updated.
            personBrainCounter = (personBrainCounter + 1) % personBrainPeriod;
            animalBrainCounter = (animalBrainCounter + 1) % animalBrainPeriod;

            foreach (Entity e in deadEntities)
            {
                EntitiesRemove(e);
            }

            GameTime = gameTime;
        }
예제 #9
0
        // Update Cycle.
        // Apply logic updates to everything in the world.
        public void Update(GameTime time, int mouseX, int mouseY)
        {
            GameTime = time;

            List <GameObject> allObjects = EntityController.Entities
                                           .Concat(new GameObject[] { EntityController.House })
                                           .Concat(PlantController.Plants.Select(x => (GameObject)x))
                                           .Concat(Items.Select(x => (GameObject)x))
                                           .Concat(Miscellaneous)
                                           .ToList();

            if (EntityController.Player.IsAlive)
            {
                allObjects.Add(EntityController.Player.BasePerson);
            }

            ObjectMesh = new ObjectMesh(Utilities.WorldWidth, Utilities.WorldHeight, gridSize, allObjects);

            // Send game time and object grid to entity controller to apply decision making and updates.
            Parallel.Invoke(new Action[] { () =>
                                           {
                                               EntityController.EntityUpdate(GameTime, ObjectMesh, mouseX, mouseY);
                                               PlantController.PlantUpdate(GameTime);
                                           } });

            // --- PickupArea ---

            // Spawn in pickups in random locations.
            if (++pickupSpawnCounter > 1000)
            {
                SpawnItem(ItemType.Apple);
                SpawnItem(ItemType.Rock);
                pickupSpawnCounter = 0;
            }

            // Check collisions on Items. Only people can pick up pickups.
            Stack <Item> clearedItems = new Stack <Item>();

            foreach (Item pi in Items)
            {
                // O(n) action now. People pickup items, which removes some or all of the value of the pickup.
                //  This part checks all pickups and removes those that have no value left.
                if (pi.Amount <= 0)
                {
                    pi.SetPickedUp();
                    clearedItems.Push(pi); // Stack of pickups to remove.
                }
            }
            // Remove pickups from the list.
            while (clearedItems.Count > 0)
            {
                Item p = clearedItems.Pop();
                Items.Remove(p);
            }

            // --- ScheduleArea ---

            // Check the schedule to apply actions. These are global events that are tied to the gametime.

            while (ScheduleQueue.Length > 0)
            {
                ActionGroup group = ScheduleQueue.PopMin();

                if (group.time <= time)
                {
                    // Apply scheduled action to entities.
                    if (group.gameObject is Entity en && group.action is EntityAction ea)
                    {
                        // Entity actions done just once.
                        en.TrySetAction(ea, true);
                    }

                    if (group.gameObject is Plant pl && group.action is PlantAction pa)
                    {
                        //Console.WriteLine("Assigning scheduled action to plant using pattern matching");
                        pl.TrySetAction(pa);
                    }

                    if (group.gameObject is Effect ef && group.action is EffectAction efa)
                    {
                        //Console.WriteLine("Assigning scheduled action to effect using pattern matching");
                        ef.TrySetAction(efa);
                    }
                }
                else
                {
                    ScheduleQueue.Insert(group); // Put action group back into the schedule.
                    break;
                }
            }

            // Force clear effects that have expired.
            if (GameTime > ClearEffectTime)
            {
                Effects.Clear();
                ClearEffectTime.AddSeconds(10);
            }
        }