/// <summary> /// Sent when another object enters a trigger collider attached to this /// object (2D physics only). /// </summary> /// <param name="other">The other Collider2D involved in this collision.</param> void OnTriggerEnter2D(Collider2D other) { if (other.gameObject.tag == "Collectable") { ICollectable collectable = other.gameObject.GetComponent <ICollectable>(); if (collectable == null) { return; } collectable.OnCollect(Inventory); } }
private void CollectIfNearEnough(ICollectable collectable) { var distance = gameObject.transform.position - collectable.GetRigidbody().position; if (distance.magnitude <= collectionRange) { _collectablesInSuckRange.Remove(collectable); collectable.OnCollect(); inventory.Store(collectable); collectionSound.Play(); } }
private void OnTriggerEnter2D(Collider2D other) { ICollectable col = other.GetComponent <ICollectable>(); if (col != null) { CollectableSO so = col.OnCollect(); if (so == null) { return; } if (mInventory.AddItem(so)) { mAudioSource.Play(); Destroy(other.gameObject); } else { col.IsCollected = false; } } }
public override void Update(GameTime gameTime) { // Nur wenn Komponente aktiviert wurde. if (!Enabled) { return; } // Nur berechnen, falls eine Welt aktiv ist. if (World == null) { return; } List <Action> transfers = new List <Action>(); foreach (var area in World.Areas) { // Schleife über alle sich aktiv bewegenden Spiel-Elemente foreach (var character in area.Items.OfType <Character>().ToArray()) { // Tote Charactere ignorieren if (character is IAttackable && (character as IAttackable).Hitpoints <= 0) { continue; } // KI Update if (character.Ai != null && Mode != SimulationMode.Client) { character.Ai.Update(area, gameTime); } // Neuberechnung der Character-Position. character.move += character.Velocity * (float)gameTime.ElapsedGameTime.TotalSeconds; // Attacker identifizieren IAttacker attacker = null; if (character is IAttacker) { attacker = (IAttacker)character; attacker.AttackableItems.Clear(); // Recovery-Time aktualisieren attacker.Recovery -= gameTime.ElapsedGameTime; if (attacker.Recovery < TimeSpan.Zero) { attacker.Recovery = TimeSpan.Zero; } } // Interactor identifizieren IInteractor interactor = null; if (character is IInteractor) { interactor = (IInteractor)character; interactor.InteractableItems.Clear(); } // Kollisionsprüfung mit allen restlichen Items. foreach (var item in area.Items) { // Kollision mit sich selbst ausschließen if (item == character) { continue; } // Distanz berechnen Vector2 distance = (item.Position + item.move) - (character.Position + character.move); // Ermittlung der angreifbaren Items. if (attacker != null && item is IAttackable && distance.Length() - attacker.AttackRange - item.Radius < 0f) { attacker.AttackableItems.Add(item as IAttackable); } // Ermittlung der interagierbaren Items. if (interactor != null && item is IInteractable && distance.Length() - interactor.InteractionRange - item.Radius < 0f) { interactor.InteractableItems.Add(item as IInteractable); } // Überschneidung berechnen & darauf reagieren float overlap = item.Radius + character.Radius - distance.Length(); if (overlap > 0f) { Vector2 resolution = distance * (overlap / distance.Length()); if (item.Fixed && !character.Fixed) { // Item fixiert character.move -= resolution; } else if (!item.Fixed && character.Fixed) { // Character fixiert item.move += resolution; } else if (!item.Fixed && !character.Fixed) { // keiner fixiert float totalMass = item.Mass + character.Mass; character.move -= resolution * (item.Mass / totalMass); item.move += resolution * (character.Mass / totalMass); } // Kombination aus Collectable und Iventory if (item is ICollectable && character is IInventory) { ICollectable collectable = item as ICollectable; // -> Character sammelt Item ein if (Mode != SimulationMode.Client) { transfers.Add(() => { if (area.Items.Contains(item)) { area.Items.Remove(item); } IInventory inventory = character as IInventory; if (!inventory.Inventory.Contains(item)) { inventory.Inventory.Add(item); item.Position = Vector2.Zero; } }); } // Event aufrufen if (collectable.OnCollect != null) { collectable.OnCollect(this, item); } } } } } // Kollision mit blockierten Zellen foreach (var item in area.Items.ToArray()) { bool collision = false; int loops = 0; // Standard-Update für das Item if (item.Update != null) { item.Update(game, area, item, gameTime); } do { // Grenzbereiche für die zu überprüfenden Zellen ermitteln Vector2 position = item.Position + item.move; int minCellX = (int)(position.X - item.Radius); int maxCellX = (int)(position.X + item.Radius); int minCellY = (int)(position.Y - item.Radius); int maxCellY = (int)(position.Y + item.Radius); collision = false; float minImpact = 2f; int minAxis = 0; // Schleife über alle betroffenen Zellen zur Ermittlung der ersten Kollision for (int x = minCellX; x <= maxCellX; x++) { for (int y = minCellY; y <= maxCellY; y++) { // Zellen ignorieren die den Spieler nicht blockieren if (!area.IsCellBlocked(x, y)) { continue; } // Zellen ignorieren die vom Spieler nicht berührt werden if (position.X - item.Radius > x + 1 || position.X + item.Radius < x || position.Y - item.Radius > y + 1 || position.Y + item.Radius < y) { continue; } collision = true; // Kollisionszeitpunkt auf X-Achse ermitteln float diffX = float.MaxValue; if (item.move.X > 0) { diffX = position.X + item.Radius - x + gap; } if (item.move.X < 0) { diffX = position.X - item.Radius - (x + 1) - gap; } float impactX = 1f - (diffX / item.move.X); // Kollisionszeitpunkt auf Y-Achse ermitteln float diffY = float.MaxValue; if (item.move.Y > 0) { diffY = position.Y + item.Radius - y + gap; } if (item.move.Y < 0) { diffY = position.Y - item.Radius - (y + 1) - gap; } float impactY = 1f - (diffY / item.move.Y); // Relevante Achse ermitteln // Ergibt sich aus dem spätesten Kollisionszeitpunkt int axis = 0; float impact = 0; if (impactX > impactY) { axis = 1; impact = impactX; } else { axis = 2; impact = impactY; } // Ist diese Kollision eher als die bisher erkannten if (impact < minImpact) { minImpact = impact; minAxis = axis; } } } // Im Falle einer Kollision in diesem Schleifendurchlauf... if (collision) { // X-Anteil ab dem Kollisionszeitpunkt kürzen if (minAxis == 1) { item.move *= new Vector2(minImpact, 1f); } // Y-Anteil ab dem Kollisionszeitpunkt kürzen if (minAxis == 2) { item.move *= new Vector2(1f, minImpact); } } loops++; }while(collision && loops < 2); // Finaler Move-Vektor auf die Position anwenden. item.Position += item.move; item.move = Vector2.Zero; // Portal anwenden (nur Player) if (area.Portals != null && item is Player) { Player player = item as Player; bool inPortal = false; foreach (var portal in area.Portals) { if (item.Position.X > portal.Box.Left && item.Position.X <= portal.Box.Right && item.Position.Y > portal.Box.Top && item.Position.Y <= portal.Box.Bottom) { inPortal = true; if (player.InPortal) { continue; } // Ziel-Area und Portal finden Area destinationArea = World.Areas.First(a => a.Name.Equals(portal.DestinationArea)); Portal destinationPortal = destinationArea.Portals.First(p => p.DestinationArea.Equals(area.Name)); // Neue Position des Spielers finden Vector2 position = new Vector2( destinationPortal.Box.X + (destinationPortal.Box.Width / 2f), destinationPortal.Box.Y + (destinationPortal.Box.Height / 2f)); // Transfer in andere Area vorbereiten if (Mode != SimulationMode.Client) { transfers.Add(() => { if (area.Items.Contains(item)) { area.Items.Remove(item); } if (!destinationArea.Items.Contains(item)) { destinationArea.Items.Add(item); item.Position = position; } }); } } } player.InPortal = inPortal; } // Interaktionen durchführen if (item is IInteractor) { IInteractor interactor = item as IInteractor; if (interactor.InteractSignal) { // Alle Items in der Nähe aufrufen foreach (var interactable in interactor.InteractableItems) { if (interactable.OnInteract != null) { interactable.OnInteract(this, interactor, interactable); } } } interactor.InteractSignal = false; } // Angriff durchführen if (item is IAttacker) { IAttacker attacker = item as IAttacker; if (attacker.AttackSignal && attacker.Recovery <= TimeSpan.Zero) { // Alle Items in der Nähe schlagen foreach (var attackable in attacker.AttackableItems) { attackable.Hitpoints -= attacker.AttackValue; if (attackable.OnHit != null) { attackable.OnHit(this, attacker, attackable); } } // Schlagerholung anstoßen attacker.Recovery = attacker.TotalRecovery; } attacker.AttackSignal = false; } } } // Transfers durchführen if (Mode != SimulationMode.Client) { foreach (var transfer in transfers) { transfer(); } } }