记忆翻牌

游戏试玩

游戏已经关闭随机卡片功能,连续点击即可快速消除
当听歌就挺好

游玩方法:

  1. 点击 StartGame
  2. 等1s或者几秒的,加载一下游戏框架
  3. 再次点击 StartGame
  4. 再等几秒钟,加载一下游戏内容
  5. 游戏就开了

(好像场景的排版有问题,直接用空白占位好了,懒得调整了)

           

实现要点

  1. 卡片的排列和卡片池的生成
  2. 洗牌(即随机生成)
  3. 卡片状态的设计
  4. 卡片的配对

卡片的排列和卡片池生成

  1. 用三行四列的方法生成
  2. 使用数组来保存卡牌数据

根据目测,得到如下的信息

SharedScreenshot.jpg

代码实现,使用Instantiate配合transform就好

void ArrangeCard()
{
    for (int i = 0; i < gridCols; i++)
        for (int j = 0; j < gridRows; j++)
        {
            GameObject tmpCard;
            tmpCard = Instantiate(card) as GameObject;
            float posX = (offsetX * i) + originalX;
            float posY = (offsetY * j) + originalY;
            tmpCard.transform.position = new Vector3(posX, posY, 0);

        }
}

洗牌

拿个列表保存一下索引,然后打散就好。

我称下面的方法叫瞎几把打乱法,效率比较低

int[] numbers = {0,0,1,1,2,2,3,3,4,4,5,5};
int[] SuffleCard(int[] numbers){
    int[] tmpNums = numbers.Clone() as int[];
    for(int i=0;i<tmpNums.Length;i++){
        int tmp = tmpNums[i];
        int r =Random.Range(i,tmpNums.Length);
        tmpNums[i] = tmpNums[r];
        tmpNums[r] = tmp;
    }
    return tmpNums;
}

实现不同的牌

创建一个card脚本,实现保存两个状态的图片的函数,并给之前的card挂上。

并修改ArrangeCard的初始化脚本,通过调用card中的函数经行图片的修改。

修改图片的函数

this.GetComponent<SpriteRenderer>().sprite = cardBackImage;

卡牌的状态设计

卡牌有三种状态:

  1. 未翻开
  2. 翻开
  3. 配对成功

其逻辑如下:

逻辑框图

下面给出了一种实现方法

Code

    public void CardReveal(MemoryCard card){
        step++;
        stepText.text = "Step: "+ step;

        if(firstRevealCard == null){
            firstRevealCard = card;
        }else{
            secondRevealCard = card;
            StartCoroutine(CheckMatch());
        }
        

    }

    public bool canReveal(){
        return secondRevealCard == null;
    }

    private IEnumerator CheckMatch(){
        if(firstRevealCard.getID() == secondRevealCard.getID()){
            firstRevealCard.Matched();
            secondRevealCard.Matched();
            score++;
            scoreText.text = "Score: "+score;
            Debug.Log("配对成功");
            yield return new WaitForSeconds(0.3f);
            firstRevealCard.gameObject.SetActive(false);
            secondRevealCard.gameObject.SetActive(false);
            Vitory();
        }else{
            yield return new WaitForSeconds(1f);

            firstRevealCard.Unreveal();
            secondRevealCard.Unreveal();
            Debug.Log("配对失败");
            
        }

        firstRevealCard = null;
        secondRevealCard = null;
    }
    
    void Vitory(){
        if(score == (gridRows*gridCols)/2){
            vitoryImage.gameObject.SetActive(true);
            
            Destroy(vitoryImage,1f);
            Destroy(scoreText,1f);
            Destroy(stepText,1f);
        }
    }

实现翻牌

  1. 给卡牌添加collider 2D属性
  2. 然后在card脚本中使用OnMouseDown()

    如果当前的状态合法,则修改图片为背面

    判断状态需要两三个函数,上面的代码已经实现了管理函数中的内容,只需要在牌面上添加对应的两个函数就好了。

实现如下:

Code

    public void OnMouseDown(){
        if(cardState == CardState.Unreveal && cardState != CardState.Matched && sceneManger.canReveal()){
            Reveal();
            sceneManger.CardReveal(this);
        }


    }

    void Start()
    {
        
        sceneManger = GameObject.FindObjectOfType<SceneManger>();
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    public void InitCardImage(int id,Sprite image){
        ID = id;
        cardImage = image;


    }

    public void Unreveal(){
        GetComponent<SpriteRenderer>().sprite = cardBackImage;
        cardState = CardState.Unreveal;

    }

    public void Reveal(){
        GetComponent<SpriteRenderer>().sprite = cardImage;
        cardState = CardState.Reveal;
    }

    public void Matched(){
        cardState = CardState.Matched;
    }

    public int getID(){
        return ID;
    }

实现计数和计步

开两个int

在上面翻牌子的时候step++,如果成功翻拍则score++

然后同步修改text就好了

重新加载

重新加载场景就好了

UnityEngine.SceneManagement.SceneManager.LoadScene(0);
Last modification:March 19th, 2020 at 12:47 am
Compared with money, your comment could inspire me more.
相较于钱财,你的留言更能激发我创作的灵感