2017-04-14 70 views
0

我正在創建一個tcg(交易卡遊戲),我想知道如何在玩遊戲時更改卡的佈局。我的意思是,這些牌將在畫布上垂直和水平地排列在屏幕中心線上,當我繪製/解散牌時,我希望牌可以填充空間並在遊戲中重新對齊。我怎樣才能做到這一點?有任何想法嗎?我想到了一個關於什麼時候輪到你開始的解決方案(從屏幕中心開始,然後退後一步X的數量/ 2,然後產生一個接一個的牌),但我無法弄清楚如果您在解除其中一個卡時未將其中一個全部重新加載,則如何更改卡的對齊方式... Image for example對齊遊戲中的卡陣列

回答

0

使用與初始位置相同的方法,您應該可以獲取新的位置。現在你有兩個職位:oldPosnewPos

您的卡已經實例化。他們的職位儲存在Transform.position。你的目標是從oldPos移到newPos。最簡單的方法是:

myCard.transform.position = newPos; 

這會立即將你的卡移動到新的位置。然而,傳送你的物體並不常見,因爲它不會給用戶帶來好感。更好的解決方案是平滑地將物體從一個位置移動到另一個位置。

爲此,您可以通過transform.Translate(new Vector3());移動現有對象,其中Vector3將決定其移動速度。方法Translate()正在做你想象中的position += movementDirection * movementAmount

移動框架上的任何對象稱爲Animation。有動畫技術可以讓動作看起來更好(看起來比實際速度還快,或者看起來很自然)。數學中常見的一種方法稱爲線性插值,或lerp。使用lerp,您可以輕鬆計算兩個終端位置之間的中間點,並且如果沿着您計算的點放置對象,它會顯得很自然和美觀。我相信這是你正在尋找的。

========

編輯:

這裏有一個如何這可以實現的例子。請注意,在此示例中,卡片以每幀相同的距離移動。使用lerp(緩入,緩出等),你可以使這個動畫更好。

我想請你注意的另一點是我在做if (Vector2.Distance(nextPosition, transform.position) < 10)而不是if(oldPosition.equals(newPosition))。原因是equals()是不安全的比較floats,因爲它們通常存儲爲0.49999990.50001而不是0.50.5。因此,檢查floats的最佳方法是測試它們是否相互「足夠」。

最後,你可以改進下面的代碼,可以在中改進很多不同的網絡方式。對於instnace:

  1. Destroy()Instantiate()是很慢的操作,你 應該使用Object Pooling因爲你知道你會不斷地執行這些 操作。
  2. Card的運動可以通過更好的動畫技術如lerp來改善。
  3. 有可能是存儲List<Card> Cards
  4. OnCardClick()使用FindObjectOfType<CardSpawner>().OnCardDeleted(this)的其他方式,這需要Card瞭解CardSpawner。這被稱爲Tight Coupling,這被稱爲邪惡。有很多討論你可以找到爲什麼這是不好的。推薦的解決方案是使用event(在Unity3d中更好的UnityEvent)。

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

我必須說,我有點糊塗了,你可以refrase你的答案的psudo代碼的形式?運動的邏輯是什麼?我的意思是,假設我從中間撤消一張卡片,我如何將這個邏輯應用於每張卡片,以便他們移動到屏幕中間的「引力點」? –

+0

我上面編輯了我的答案。讓我知道如果這有效! – BrokenBacon