MVC模式--背包拖拽(一)

      实现功能:4*4的背包格子,有游戏时间和步数显示,游戏开始打乱图片顺序,鼠标拖拽一个图片和另一个图片交换,完成拼图,游戏结束不能拖拽,时间暂停



























1.准备素材;

找一张这样400*400的图片,命名img,在unity中改变它的Texture Type为Sprite2D,Sprite Mode改成Multiple,点击Sprite Editor,设置切割的图片大小100*100,应用就可以了,自动把我们的图片切割成了16张小图片

     

还有一张背景图

 

2.在场景中创建Panel,把Canvas的名字改成Knapsack,标签也改成Knapsack,Panvel的名字改成ImageList,给其添加一个自动布局组件Grid Layout Group,设置一下CellSize都是100,Spacing都是1,按住Ctrl把锚点设成Center,宽和高都是403,给其添加脚本ImageListManager。

3.在ImageList下创建Image,改名为Cell,标签改成Cell,sprite图片是背景图片,它的大小是100*100,;在Cell下再创建一个Image,大小也是100*100,改名为Food,标签改成Food,添加一个Canvas Group组件用于射线检测,把Cell拖成预设体,场景中删除,把预设体拖给ImageListManager,再给其添加一个脚本FoodController。

4.时间和步数的显示其实很简单了,在一个Panel上添加两个Text,分别把时间参数和步数参数传给这两个Text中的text。


ImageList上挂载的脚本如下:

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

public class ImageListManager : MonoBehaviour
{
    //获取所有的图片
    public List<Sprite> sprites;
    //所有的格子
    List<Transform> cells;
    //预设体
    public GameObject prefab;
    //单例
    public static ImageListManager Instance;

    public int steps;
    public float timer;
    public Text StepText;
    public Text TimerText;
    public bool isGameOver;
    void Awake()
    {
        Instance = this;
    }
    //将图片打乱
    void RandomSprites()
    {
        int num;
        Sprite spriteTemp;
        for (int i = 0; i < sprites.Count; i++)
        {
            //从后面随机抽一张图片放到i的位置上
            num = Random.Range(i, sprites.Count);
            spriteTemp = sprites[i];
            sprites[i] = sprites[num];
            sprites[num] = spriteTemp;
        }
    }
    //初始化游戏
    void Init()
    {
        cells = new List<Transform>();
        //每张图片实例化一个格子,格子用来存放图片
        for (int i = 0; i < sprites.Count; i++)
        {
            Transform cell = ((GameObject)Instantiate(prefab)).transform;
            cell.GetChild(0).GetComponent<Image>().sprite = sprites[i];
            cell.SetParent(transform);
            cell.name = "img_" + i.ToString();
            cells.Add(cell);
        }
        timer = 0;
        steps = 0;
        isGameOver = false;
    }

    public bool IsOK()
    {
        for (int i = 0; i < cells.Count; i++)
        {
            string name = cells[i].GetChild(0).GetComponent<Image>().sprite.name;
            if (cells[i].name != name)
            {
                return false;
            }
        }
        return true;
    }

    void Start()
    {
        RandomSprites();
        Init();
        print(IsOK());
    }
    void Update()
    {
        if (!isGameOver)
        {
            timer += Time.deltaTime;
        }
        TimerText.text = "timer: " + ((int)timer).ToString();
        StepText.text = "steps: " + steps.ToString();
    }
}


Food上挂载的脚本如下:

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

public class FoodController : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{


    //1.
    RectTransform foodRF;
    RectTransform knapsackRF;
    RectTransform cellRF; //表示物品当前的父物体

    //2.拖拽中的新位置
    Vector3 foodNewPosition;
    //3.原来的位置
    Vector3 foodOldPosition;
    //4.
    CanvasGroup cg;
    //5.
    bool isDrag;


    void Awake()
    {
        foodRF = GetComponent<RectTransform>();
        knapsackRF = GameObject.FindWithTag("Knapsack").GetComponent<RectTransform>();
        cg = GetComponent<CanvasGroup>();
    }



    //开始拖拽
    public void OnBeginDrag(PointerEventData eventData)
    {
        if (!ImageListManager.Instance.isGameOver)
        {
            //每次开始拖拽前记录它的原始父物体
            cellRF = foodRF.parent as RectTransform;
            //每次开始拖拽后改变它的父物体为knapsack
            foodRF.SetParent(knapsackRF);
            //开始拖拽之后,不能被射线检测到
            cg.blocksRaycasts = false;
            //开始拖拽
            isDrag = true;
        }

    }
    //拖拽中
    public void OnDrag(PointerEventData eventData)
    {
        if (isDrag)
        {
            RectTransformUtility.ScreenPointToWorldPointInRectangle(foodRF, Input.mousePosition, eventData.pressEventCamera, out foodNewPosition);
            foodRF.position = foodNewPosition;
        }

    }
    //结束拖拽
    public void OnEndDrag(PointerEventData eventData)
    {
        if (isDrag)
        {
            GameObject enter = eventData.pointerEnter;
            //如果拖拽到空的地方
            if (enter == null)
            {
                //cellRF指的是原来的父物体
                SetParent(foodRF, cellRF);
            }
            else
            {
                switch (enter.tag)
                {
                    case "Cell":
                        SetParent(foodRF, enter.transform);
                        break;
                    case "Food":
                        SetParent(foodRF, enter.transform.parent);
                        SetParent(enter.transform, cellRF);
                        break;
                    default:
                        SetParent(foodRF, cellRF);
                        break;
                }
                ImageListManager.Instance.steps++;

                if (ImageListManager.Instance.IsOK())
                {
                    ImageListManager.Instance.isGameOver = true;
                    print("步数" + ImageListManager.Instance.steps);
                }
            }


            //结束拖拽之后,能被射线检测到
            cg.blocksRaycasts = true;
            //结束拖拽
            isDrag = false;
        }

    }
    //建立父子关系的方法
    void SetParent(Transform son, Transform parent)
    {
        son.SetParent(parent);
        son.localPosition = Vector3.zero;
    }

}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值