卡牌小游戏

<p>
  一个卡片消除小游戏,主要是用来熟悉unity的基本用法,功能比较简单,完成了随机发牌以及卡牌对比消除功能~
</p>
--

一、代码的主体思路:

代码包括两块:

  • 用来做初始化模板的卡牌
     这里包括卡牌自身的属性字段,以及使用方法,包括:卡牌的序号(id),卡背,设置卡牌的方法(SetCard),卡牌点击方法(OnMouseDown),卡背消失方法(SetBack)。
  • 游戏中,用来负责卡牌发送,点击判断等处理的卡牌管理代码。
     这是用来对整个游戏做管理的代码,包括:卡牌的数量(CARD_NUMBER),所有卡牌的ID,以及所有卡牌的图片(sprite)和卡牌之间的间隔(offsetX,offsetY);
     方法包括:卡牌序号的随机初始化(ArrayInit),接收卡牌方法(ReceiveCard),卡牌比较方法(Macth)

<pre>
上面是整体代码的结构,下面会根据自己开发的思路一步一步完成。
</pre>

二、开发步骤:
  • 1.先把需要的卡牌拖入到hierarchy中,并且将卡背作为卡牌的子对象:
1.png

完成后记得把卡背的z轴坐标调整为-2,让卡背在前。

  • 2.完成卡牌模板后,给卡片添加script组件Card,以及碰撞组件(collider 2d):

<pre>
这里先实现基本功能,卡背,卡牌的ID,卡牌点击方法(先完成点点击卡背消失)
</pre>

private int id;                  //卡片的序号id
public GameObject cardBack;     //卡背对象,在unity拖拽赋值

//鼠标点击事件需要在对象上添加collider组件
void OnMouseDown()
{
cardBack.SetActive(false);
}

  • 3.有了模板卡牌后,可以完成卡牌的随机分发功能了:
     为了完成随机分发,需要用到卡牌的设置方法还有随机数组:
//首先在卡牌的script组件中,添加卡牌的设置方法SetCard,有两个参数,一个是id,一个是sprite

 public void SetCard(int id, Sprite fruit)
    {
        this.id = id;
        this.GetComponent<SpriteRenderer>().sprite = fruit;
    }


然后在hierarchy中创建一个空对象,用来挂CardManage脚本,来负责整个游戏的处理:

2.png
//设置卡牌的数量,和精灵的数量,精灵用拖拽赋值;
    private const int CARD_NUMBER = 10;
    int[] cardId=new int[CARD_NUMBER];
    public Sprite[] fruitSprites=new Sprite[5];

//在CardManage中写上生成随机数组的方法
void ArrayInit(int[] array)
    {
        //给数组每一个元素赋值,分别为0,0,1,1,2,2,3,3,4,4,5,5
        for (int i = 0; i < array.Length; i++)
        {
            array[i] = i/2;
        }

        //对有了初值的数组做乱序处理,从最后一个元素往前和随机的元素调换位置。
        int swap, temp;
        for (int i = array.Length-1; i > 0; i--)
        {
            swap = Random.Range(0, i);
            temp = array[swap];
            array[swap] = array[i];
            array[i] = temp;
        }      
    }

完成之后再CardManage中的Star方法中,开始生成随机卡牌:

//声明初始的卡牌和后续用到的实例化的卡牌对象
    public Card oriCard;
    private Card cloneCard;

//每张卡牌的间隔
    private int offsetX = 2;
    private int offsetY = 2;

    // Use this for initialization
    void Start()
    {
    //给oriCard赋值并且记录初始卡牌的位置信息(startpoz)
        oriCard = GameObject.Find("Card").GetComponent<Card>();
        Vector3 startPoz = oriCard.transform.position;
        ArrayInit(cardId);

    //通过for循环给所有的卡牌赋值并设置位置
        for (int i = 0; i < CARD_NUMBER; i++)
        {
            if (i == 0)
            {
                cloneCard = oriCard;
            }
            else
            {
                cloneCard = Instantiate(oriCard);//实例化卡牌
            }
            //通过setCard方法设置每张卡牌的精灵。
            cloneCard.SetCard(cardId[i], fruitSprites[cardId[i]]);
            //设置每张卡牌的位置
            cloneCard.transform.position = new Vector3(startPoz.x + offsetX * (i % 5), startPoz.y - offsetY * (i / 5), startPoz.z);
        }
    }
  • 4.随机卡牌生成完成之后,就是对点击的卡牌进行比较,这个功能也是在CardManage中完成:
    这个功能分为两个步骤:
    a,首先是接收鼠标点击了的卡牌;
    b,对存储了的卡牌进行比较(这里可以通过卡牌的ID来进行比较)。
    //接收鼠标点击的卡牌,这个在CardManage中完成:
    //声明两个空对象用来接收点击的卡牌
    public Card first = null;  
    public Card second = null;
    //接收方法
    public void ReceiveCard(Card card)
    {
        if(first==null)
        {
            first = card;
        }
        else
        {
            second = card;
            //开启一个协程,当两张卡牌进行比较的时候,如果不一致,延迟执行卡背恢复的操作。
            StartCoroutine(Macth(first, second));
        }
    }
//写好接收的方法后,在Card中,进行调用:
//首先实例化CardManage中的脚本
CardManage manage;
private void Awake()
 {
 manage = GameObject.Find("CardManage").GetComponent<CardManage>();
 }

    //然后在鼠标点击事件调用接收方法:
    //鼠标点击事件要记得加collider
    void OnMouseDown()
    {
        //接收的条件为,当第二个接收的卡牌对象为空,并且该次点击的卡牌是没有被点击过的。
        if(manage.second==null&&cardBack.activeSelf)
        {
            cardBack.SetActive(false);
            manage.ReceiveCard(this);
        }    
    }

完成接收后,可以进行比较了,这里用到了:
 设置卡背消失方法,这个是在Card中实现.
 比较方法,这个是在CardManage中实现,

    //设置卡背方法
    public void SetBack(bool isTurn)
    {
        cardBack.SetActive(isTurn);
    }
    //比较方法,由开启了协程,所以需要返回IEnumerator类型的方法
    IEnumerator Macth(Card fir,Card sec)
    {
        if(fir.GetId!=sec.GetId)
        {
            //程序执行到这里的时候会等待1秒后在执行
            yield return new WaitForSeconds(1);
            fir.SetBack(true);
            sec.SetBack(true);
        }
      //比较完毕后,清空接受的卡牌
        first = null;
        second = null;
    }

  • 5.游戏结束
     当卡牌全部翻转过来的时候,则结束游戏。
//结束的思路是,首先设置一个判定值,每成功比较出一对,加1,当判定值达到了,则结束。
//判定值,从0开始计数
int index = 0;
//游戏胜利时条件
int end = CARD_NUMBER / 2;

//在比较方法中添加一个判断,当成功时,index+1;
 IEnumerator Macth(Card fir,Card sec)
    {
        if (fir.GetId == sec.GetId)
        {
            index++;
            
        }
}

//最后在Update方法中,实时进行判断是否满足胜利条件。
void Update () {
        if(index==end)
        {
           print("游戏胜利~");
           index = 0;
        }
    }

写到这里主体的功能也就完成啦,有兴趣的话可以增加更多的关卡。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 173,556评论 25 708
  • 千里之行,始于足下,只有掌握UGUI才能更好的运用. 项目二:制作VR的UI界面(包括血条制作,介绍界面,包裹界面...
    元宇宙协会阅读 1,524评论 7 2
  • 我伸出手 要擎住夏天的热泪 在迷濛中,亲吻 吧嗒,吧嗒 这悦耳的响动 拽着心漫向深处 四周的芦苇扭晃着身子 不解风...
    Cactussnow阅读 372评论 2 0
  • 来到波兰小镇,随时随地的美!
    与姝会友阅读 184评论 0 0
  • 我们人类是一个视觉动物,这是基因里面决定的,当我们看到一个人走过来的时候,我们首先会根据视觉上看到的东西,有一个第...
    刻意练习社区阅读 430评论 2 4