首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

【Unity3D游戏教程】记忆翻牌游戏

  • 23-09-15 22:19
  • 2169
  • 7732
blog.csdn.net

游戏引擎:Unity3D - 5.4.1

脚本编辑器:Visual Studio 2012

脚本语言:C#

【随便聊聊】

  已经很久没写博客了。因为感觉一直没有太好的东西分享给大家,最近写了比较完整的小例子,这里分享给大家。

【这里是正文】

一. 策划部分

游戏说明:

  游戏两两翻牌,一样则记成功一对;不一样,则两张都恢复初始状态。当所有卡牌配对成功后即获得胜利。

游戏流程:

1、玩家点击开始游戏后进入游戏;

2、系统初始化一组卡牌显示到界面上;

3、系统计时;

4、玩家点击卡牌将卡牌翻开;

5、系统检测到当翻开的卡牌为两张时进行评判,若相同则增加计数并判断是否达到指定数量,若不同则两张卡牌均恢复为原始状态。

具体规则:

1、需在规定时间内完成游戏,否则系统提示游戏失败;

2、当有两张卡牌被翻开时,需等待2秒后才能对其他卡牌进行点击,在2秒内对其他卡牌的点击都是无效的。

基于以上的流程和规则,我们罗列出以下主要技术点(其中括号中均为简写):

1、搭建界面,卡牌池使用自动布局(Grid Layout Group和Content Size Fitter组件);

2、构建GameManager类;

3、构建Card类;

4、配置卡牌列表,随机排列卡牌(List,Random.Range);

5、生成卡牌作为卡牌子物体(Local相关属性配置)

6、设置计时器(Time.deltaTime);

7、翻牌添加到数组(List);

8、两张翻牌时,使玩家点击失效2秒(协同程序)。

9、配对成功不可再点击(Button interactable=false)

二. 开发部分

搭建界面:

  我们创建工程,在场景中创建Panel,为其添加Gird Layout Group组件和Content Size Fitter组件。Gird Layout Group组件可对Panel的子元素进行排列布局,我们这里要用到的是Padding下面的四个属性(元素距离四边的像素距离)、Cell Size(元素的宽高像素)、Spacing(元素间横向与纵向间隔)以及Constraint(行列约束)。Content Size Fitter组件用来约束当前Panel的尺寸。这两个组件一般搭配使用。

我们进行如图设置。

这里写图片描述

  我们指定了子元素的大小和间距,以及与父元素边界距离,并指定以列为基准一共四列;最后设置横纵的尺寸都按照最小来自适应,就会按照我们之前的设置来自动布置当前Panel的大小。此时可以做个测试,在Panel下疯狂创建Image(也不用特别疯狂,创建一个Image后选中它ctrl+d就行。。。)创建十二个Image,发现会自动布局成我们想要的效果。

这里写图片描述

  大家也可以根据自己的审美风格来调整比例和大小。开始界面和结束界面这些在此处不再赘述,非常简单,大家可以尝试自己制作。

设计Card类,制作卡牌Prefab:

1、属性设计

(1)卡牌需有唯一标识id,利用同种卡牌id相同,不同卡牌id不同的原理对卡牌配对是否成功做出判断;

(2)卡牌会有三种显示情况:未被翻开状态,被翻开状态,配对成功状态。这三种状态用不同的图片来区分,均为Sprite类型;

(3)基于(2)中的不同状态图片,都需要指定给卡牌的Image组件才能显示,所以我们需要声明Image类型的字段来获取Image组件对象;

(4)根据游戏机制,卡牌存在不能点击的时刻,此时我们需要获取到卡牌Button组件中的属性来设置卡牌能否被点击。

2、方法设计

(1)卡牌需要有初始化方法,用来初始化Card类的各项属性。由于初始化需要传参和外部调用,这里我们自己写一个带四个属性参数的InitCard方法;

(2)牌被点击,设置卡牌不可被点击,显示图片为frontImg,需要实现SetFanPai方法,即设置翻拍(这里由于亦泽的词汇量达到了顶峰,所以用拼音了。。。);

(3)两张牌相同,设置卡牌显示图片为successImg,这里需要实现SetSuccess,即设置匹配成功;

(4)两张牌不同,则设置卡牌显示图片为backImg,并设置卡牌可以点击,需要实现SetRecover方法。

新建Card类,添加如下代码:

using UnityEngine;
using UnityEngine.UI;
using System.Collections;

public class Card : MonoBehaviour {

    public int ID
    {
        get
        {
            return id;
        }
    }
    private int id;

    private Sprite frontImg;
    private Sprite backImg;
    private Sprite successImg;

    private Image showImg;
    public Button cardBtn;

    public void InitCard(int Id, Sprite FrontImg,Sprite BackImg,Sprite SuccessImg)
    {
        this.id = Id;
        this.frontImg = FrontImg;
        this.backImg = BackImg;
        this.successImg = SuccessImg;

        showImg = GetComponent();
        showImg.sprite = this.backImg;

        cardBtn = GetComponent

  我们在刚才疯狂创建的Image对象中,随便选一个,改名为CardPre,为其添加Button组件和Card脚本(其对象默认含有Image组件),将其Transition属性设置为None。这些做好后将其制作为Prefab,并将Panel下的子物体全部删除。

设计GameManger类:

1、属性设计

(1)整型常量字段winCardCouples,表示游戏胜利需要的卡牌对数,按照我们上述设计,这里制定为6;

(2)整型变量curCardCouples,用来记录当前已经匹配完成的卡牌对数;

(3)bool型变量canPlayerClick,用来控制宏观点击,即根据策划,当两张牌均翻开时等待两秒才会出现结果,此时所有卡牌均不可以点击,所以这里设置此变量;

(4)Sprite类型的backImg和successImg两属性用来存放背面图和成功图;

(5)Sprite类型的数组FrontSprites,用来存放6种不同的卡牌图片;

(6)GameObject类型的卡牌实例列表集合CardObjs,此数组本质作用是过度,即用6张图片来生成12张卡牌对象,将每个对象初始化好后存入当前数组,然后随机取出,做矫正设置后再指定给Panel作为子对象;

(7)Card类型的列表集合FaceCards,用来存放被翻开的卡牌;

(8)GameObject类型的CardPre;

(9)Transfrom类型的CardsView,用来存放Panel;

2、方法设计

(1)在Start方法中设置初始化卡牌属性,并将其乱序添加到Panel下;

(2)添加CardOnClick方法,作为卡牌被点击的监听事件;

(3)添加JugdeTwoCards方法,此方法为协同程序的方法,用于判断两张牌是否一致。

新建GameManager脚本,添加如下代码:

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

public class Card_GameManager : MonoBehaviour {

    private const int winCardCouples = 6;
    private int curCardCouples = 0;
    private bool canPlayerClick = true;

    public Sprite BackSprite;
    public Sprite SuccessSprite;
    public Sprite[] FrontSprites;

    public GameObject CardPre;
    public Transform CardsView;
    private List CardObjs;
    private List FaceCards;

    // Use this for initialization
    void Start () {

        CardObjs = new List();
        FaceCards = new List();

        //将12张卡牌制作完成后添加到CardObjs数组
        for (int i = 0; i < 6; i++)
        {
            Sprite FrontSprite = FrontSprites[i];
            for (int j = 0; j < 2; j++)
            {
                //实例化对象
                GameObject go = (GameObject)Instantiate(CardPre);
                //获取Card组件进行初始化,点击事件由游戏管理器统一处理
                //所以卡牌的点击事件的监听在管理器指定
                Card card = go.GetComponent();
                card.InitCard(i, FrontSprite, BackSprite, SuccessSprite);
                card.cardBtn.onClick.AddListener(() => CardOnClick(card));

                CardObjs.Add(go);
            }
        }

        while (CardObjs.Count > 0)
        {
            //取随机数,左闭右开区间
            int ran = Random.Range(0, CardObjs.Count);
            GameObject go = CardObjs[ran];
            //将对象指定给Panel作为子物体,这样就会被我们的组件自动布局
            go.transform.parent = CardsView;
            //local就表示相对于父物体的相对坐标系,此处做校正处理
            //有兴趣的同学可以把下面两句代码注释掉看看效果
            go.transform.localPosition = Vector3.zero;
            go.transform.localScale = Vector3.one;
            //从CardObjs列表中移除该索引指向对象,列表对象数量减少1个
            CardObjs.RemoveAt(ran);
        }
    }


    private void CardOnClick(Card card)
    {
        if (canPlayerClick)
        {
            //先判断是否可以点击,可点击则直接翻牌
            card.SetFanPai();
            //添加到比对数组中
            FaceCards.Add(card);
            //如果有两张牌了,则不可再点击,进入协同程序
            if (FaceCards.Count == 2)
            {
                canPlayerClick = false;
                StartCoroutine(JugdeTwoCards());
            }
        }
    }

    IEnumerator JugdeTwoCards()
    {
        //获取到两张卡牌对象
        Card card1 = FaceCards[0];
        Card card2 = FaceCards[1];
        //对ID进行比对
        if (card1.ID == card2.ID)
        {
            Debug.Log("Success......");
            //此时会在此处等待0.8秒后再执行下一条语句
            //协程不影响主程序的进行,这里可以做个小实验
            //将下面的0.8改成8秒,在Update中打印Time.time会发现不会有停顿的时候
            yield return new WaitForSeconds(0.8f);
            card1.SetSuccess();
            card2.SetSuccess();
            curCardCouples++;
            if (curCardCouples == winCardCouples)
            {
                //此处可以弹出游戏成功等字样的UI,同学们可以自由设定
                Debug.Log("Win!");
            }
        }
        else
        {
            Debug.Log("Failure......");
            //配对失败等待的时间要更长,因为要让玩家记忆更深刻
            yield return new WaitForSeconds(1.5f);
            card1.SetRecover();
            card2.SetRecover();
        }

        FaceCards = new List();
        canPlayerClick = true;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112

  新建空物体作为GameManager的对象,指定GameManager脚本,在属性面板设置其各项属性,如图所示。

这里写图片描述

  这里亦泽随便用了一些图放上去,运行游戏,效果如下若干图所示。做的不是很美观,有美术基础的读者可以将其更好的完善。

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
 
 

本文源码GitHub地址:

http://iyenn.com/index/link?url=https://github.com/Eazey/Unity3D_GameDemo/tree/master/RememberCard

注:本文转载自blog.csdn.net的Eazey丶亦泽的文章"https://blog.csdn.net/eazey_wj/article/details/54837198"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top