2017-04-14 4 views
0

Ich erstelle ein tcg (Sammelkartenspiel) und würde gerne wissen, wie ich das Layout der Karten während des Spielens ändern kann. Ich meine, dass die Karten in einer Linie auf der Mitte des Bildschirms verteilt werden, sowohl vertikal als auch horizontal, auf einer Leinwand, und wenn ich eine Karte ziehe/verlasse, möchte ich, dass die Karten das Feld ausfüllen und sich im Spiel neu ausrichten. Wie kann ich das machen? irgendwelche Ideen? Ich dachte über eine Lösung nach, wenn du an der Reihe warst (Beginne von der Mitte des Bildschirms, dann schreite die Länge eines Schritts X zurück, die Anzahl der Karten/2 und spawne die Karten nacheinander), aber ich kann nicht herausfinden wie man die Ausrichtung von Karten ändert, wenn man eine von ihnen ablehnt, ohne sie alle wieder zu laden ... Image for exampleAusrichten eines Kartenarrays im Spiel

Antwort

0

Mit der gleichen Methode, die Sie für die Anfangsposition verwendet haben, sollten Sie in der Lage sein, die neue Position zu bekommen. Jetzt haben Sie zwei Positionen für jede Karte: oldPos und newPos.

Ihre Karten sind bereits instanziiert. Ihre Positionen sind in Transform.position gespeichert. Ihr Ziel ist es, von oldPos zu newPos zu bewegen. Der einfachste Weg wäre:

myCard.transform.position = newPos; 

Dies wird Ihre Karten sofort auf ihre neue Position verschieben. Es ist jedoch nicht üblich, Objekte zu teleportieren, da diese den Benutzern oft keine guten Gefühle vermitteln. Eine bessere Lösung besteht darin, das Objekt sanft von einer Position zu einer anderen zu bewegen.

Um dies zu tun, können Sie ein vorhandenes Objekt um transform.Translate(new Vector3()); verschieben, wobei Vector3 seine Bewegungsgeschwindigkeit entscheidet. Die Methode Translate() macht position += movementDirection * movementAmount, wie Sie es erwartet hätten.

Das Verschieben eines Objekts über Frames wird Animation genannt. Es gibt Techniken für Animationen, um Bewegungen besser aussehen zu lassen (schneller aussehen als es ist oder natürlich aussehen). Eine übliche Methode aus der Mathematik nennt man lineare Interpolation oder lerp. Mit lerp können Sie Zwischenpunkte zwischen zwei Endpositionen einfach berechnen, und es wird natürlich und schön aussehen, wenn Sie Ihre Objekte entlang der berechneten Punkte platzieren. Ich glaube, das ist es wonach Sie suchen.

========

Edit:

Hier ist ein Beispiel dafür, wie dies erreicht werden könnte. Beachten Sie, dass sich die Karte in diesem Beispiel um den gleichen Abstand pro Bild bewegt. Mit Hilfe von Lerp (Leichtigkeit, Leichtigkeit, usw.) können Sie diese Animation noch besser machen.

Ein weiterer Punkt, den ich möchte, dass Sie beachten, ist, dass ich if (Vector2.Distance(nextPosition, transform.position) < 10), nicht if(oldPosition.equals(newPosition)) mache. Der Grund ist, dass equals() nicht sicher ist, floats zu vergleichen, weil sie oft als 0.4999999 und 0.50001 anstelle von 0.5 und 0.5 gespeichert werden. Die beste Art, floats zu überprüfen, besteht darin, zu testen, ob sie "Close Enough" sind.

Schließlich könnten Sie den folgenden Code verbessert verbessern könnte in VIELE DIFFERNET WEGE. Für instnace:

  1. Destroy() und Instantiate() ist sehr langsam Operationen und Sie sollten Object Pooling verwenden, weil Sie wissen, führen Sie diese Operationen ständig.
  2. Die Bewegung von Card könnte durch bessere Animationstechnik wie lerp verbessert werden.
  3. Es können auch andere Möglichkeiten, von OnCardClick()List<Card> Cards
  4. Speicherung verwendet FindObjectOfType<CardSpawner>().OnCardDeleted(this) und dies erfordert CardCardSpawner darüber wissen. Dies nennt man Tight Coupling, was als böse bekannt ist. Es gibt viele Diskussionen, die Sie finden können, warum das schlecht ist. Eine empfohlene Lösung wäre die Verwendung von event (besser UnityEvent in Unity3d).

CardSpawner.cs

using System.Collections; 
using System.Collections.Generic; 
using UnityEngine; 

public class CardSpawner : MonoBehaviour 
{ 
    [SerializeField] GameObject CardParent; 
    [SerializeField] GameObject CardPrefab; 
    Vector2 DefaultSpawnPosition = new Vector2(Screen.width/2f, Screen.height/10f); 

    List<Card> Cards = new List<Card>(); 

    public void OnClickButton() 
    { 
     SpawnNewCard(); 
     AssignNewPositions(); 
     AnimateCards(); 
    } 

    public void OnCardDeleted(Card removedCard) 
    { 
     Cards.Remove(removedCard); 
     AssignNewPositions(); 
     AnimateCards(); 
    } 

    void SpawnNewCard() 
    { 
     GameObject newCard = (GameObject)Instantiate(CardPrefab, DefaultSpawnPosition, new Quaternion(), CardParent.GetComponent<Transform>()); 
     Cards.Add(newCard.GetComponent<Card>()); 
    } 

    void AssignNewPositions() 
    { 
     int n = Cards.Count; 
     float widthPerCard = 100; 
     float widthEmptySpaceBetweenCards = widthPerCard * .2f; 
     float totalWidthAllCards = (widthPerCard * n) + (widthEmptySpaceBetweenCards * (n-1)); 
     float halfWidthAllCards = totalWidthAllCards/2f; 

     float centreX = Screen.width/2f; 
     float leftX = centreX - halfWidthAllCards; 

     for (int i = 0; i < n; i++) 
     { 
      if (i == 0) 
       Cards[i].nextPosition = new Vector2(leftX + widthPerCard/2f, Screen.height/2f); 
      else 
       Cards[i].nextPosition = new Vector2(leftX + widthPerCard/2f + ((widthPerCard + widthEmptySpaceBetweenCards) * i), Screen.height/2f); 
     } 
    } 

    void AnimateCards() 
    { 
     foreach (Card card in Cards) 
      card.StartMoving(); 
    } 
} 

Card.cs

using System; 
using System.Collections; 
using System.Collections.Generic; 
using UnityEngine; 

public class Card : MonoBehaviour 
{ 
    public Vector2 oldPosition; 
    public Vector2 nextPosition; 
    bool IsMoving; 

    void Update() 
    { 
     if (IsMoving) 
     { 
      int steps = 10; 
      Vector2 delta = (nextPosition - oldPosition)/steps; 
      transform.Translate(delta); 

      if (Vector2.Distance(nextPosition, transform.position) < 10) 
       IsMoving = false; 
     } 
    } 

    public void StartMoving() 
    { 
     IsMoving = true; 
     oldPosition = transform.position; 
    } 

    public void OnCardClick() 
    { 
     UnityEngine.Object.Destroy(this.gameObject); 
     Debug.Log("AfterDestroy"); 
     FindObjectOfType<CardSpawner>().OnCardDeleted(this); 
    } 
} 
+0

Ich muss sagen, dass ich ein wenig verwirrt haben, können Sie Ihre Antwort in Form von psudo Code refrase? Und was wird die Logik der Bewegung sein? Ich meine, sagen wir, ich verlasse eine Karte aus der Mitte, wie verwende ich diese Logik für jede Karte, um sie zum "Gravitationspunkt" in der Mitte des Bildschirms zu bewegen? –

+0

Ich habe meine Antwort oben bearbeitet. Lass es mich wissen, wenn das funktioniert! – BrokenBacon