“抓住神经猫”的2D游戏创作

经过一阵子的学习,再次上传一份小游戏,叫“抓住神经猫”的游戏,通过二维数组,实例化出场景并进行游戏,直到围住神经猫或者让它逃脱为止。

首先呢,我把用到的图片上传,然后感兴趣的朋友可以保存图片然后复制代码进行游戏,各种函数都有介绍,希望大家能够喜欢以及支持我,以后会更新更多的自己学会的游戏并上传代码进行解说的,谢谢。

首先,我们打开Unity创建好2D 工程之后,建立一个空物体命名为GameController,然后添加场景,把背景图片拖入GameController中,如下,是一张背景图片:

1.1 游戏背景图片

这是游戏开始、游戏胜利、游戏失败、游戏重新开始的图片,我们把它也作为GameController的子物体拖入:

1.2 游戏开始图片


1.3 游戏胜利图片


1.4 游戏失败图片

1.5 游戏重新开始的图片

把这些图片都拖入GameController之后,我们把上面出背景之外的所有对象全部取消渲染,然后添加两个预设体pot1和pot2,(在2D工程中设置预设体的方法:把图片先从文件夹拖入场景中,然后设置完毕之后再把场景中的图片拖入工程文件夹里,这样就能得到预设体了)。

                                                                                                                                                                            

        1.6  pot1图片               1.7  pot2图片

之后对我们的主角神经猫进行图片的切割,然后制作成动画Animation,然后把神经猫也设置成预设体:


1.8  神经猫图片

之后,我们就可以开始编码啦,首先,编写控制pot的类脚本Item,来控制游戏场景中的位移与pot的被点击事件,代码如下:

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


public class Item : MonoBehaviour
{
    public GameController gameController;


    public int rowIndex;
    public int columnIndex;
    //po1t的偏移量
    public float xoff = -2.65f;
    public float yoff = -3.3f;


    public bool moveAble = true;                //用于检验是否可以移动


    //更新位置
    private void UpdatePosition()
    {
        Vector3 v = new Vector3(0, 0, 0);
        v.x = xoff + 0.6f * columnIndex;
        if (rowIndex % 2 == 0)
            v.x = xoff + 0.6f * columnIndex + 0.25f;
        v.y = yoff + 0.5f * rowIndex;
        transform.position = v;
    }


    //移动的函数,把对象移动到形参设置的位置上
    public void Goto(int rowIndex,int columnIndex)
    {
        this.rowIndex = rowIndex;
        this.columnIndex = columnIndex;
        UpdatePosition();
    }


    //鼠标点击后执行Select函数
    private void OnMouseDown()
    {
        gameController.Select(this);
    }
}

之后,再通过每次的点击事件来执行GameController脚本中的函数来实现游戏效果,脚本中都有注释,如果有问题的朋友可以提出来大家一起探讨,我就不一一解释了。

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


public class GameController : MonoBehaviour
{
    public GameObject pot1;
    public GameObject pot2;
    public GameObject cat;              //神经猫


    public GameObject startScreen;      //开始按钮
    public GameObject victory;          //胜利图标
    public GameObject failed;           //失败图标
    public GameObject replay;           //重玩图标


    //可点击的矩阵大小
    public int rowNum = 9;
    public int columnNum = 9;
    //设置两个储存pot1和pot2的数组
    private ArrayList potArr;
    private ArrayList pot2Arr;
    //两个判断游戏是否开始与结束的bool变量
    private bool started = false;
    private bool gameOver = false;


    // 初始化pot1,建立二维数组
    void Start()
    {
        startScreen.GetComponent<StartGame>().gameControlller = this;
        replay.GetComponent<StartGame>().gameControlller = this;
        //初始化pot2的数组
        pot2Arr = new ArrayList();
        //初始化pot的数组
        potArr = new ArrayList();


        //建立一个pot的二维数组
        for (int columnIndex = 0; columnIndex < columnNum; columnIndex++)
        {
            ArrayList temp = new ArrayList();
            for (int rowIndex = 0; rowIndex < rowNum; rowIndex++)
            {
                Item item = CreatePot(pot1, rowIndex, columnIndex);
                temp.Add(item);
            }
            potArr.Add(temp);
        }
    }


    //游戏开始,设置游戏开始时的所有状态
    public void StartGame()
    {
        //游戏开始的状态
        started = true;
        startScreen.SetActive(false);
        //游戏结束的状态,关闭其他几个可视化窗口
        failed.SetActive(false);
        victory.SetActive(false);
        replay.SetActive(false);
        gameOver = false;
        //初始化猫的位置
        cat.SetActive(true);
        MoveCat(Random.Range(3, rowNum - 3), Random.Range(3, columnNum - 3));       //随机设置神经猫的生成点
        //恢复所有pot1的点
        for(int rowIndex=0;rowIndex<rowNum;rowIndex++)
        {
            for(int columnIndex=0;columnIndex<columnNum;columnIndex++)
            {
                Item item = GetPot(rowIndex, columnIndex);
                item.moveAble = true;
            }
        }
        //移除所有的pot2
        foreach(Item item2 in pot2Arr)
        {
            Destroy(item2.gameObject);
        }
        //清空pot2的所有实例化对象
        pot2Arr.Clear();
    }


    //从potArr数组中获取点的Item信息
    Item GetPot(int rowIndex,int columnIndex)
    {
        //判断pot是否超出了数组的范围,已经离开了游戏场景
        if (rowIndex < 0 || rowIndex > rowNum - 1 || columnIndex < 0 || columnIndex > columnNum - 1)
            return null;


        ArrayList temp = potArr[rowIndex] as ArrayList;
        Item item = temp[columnIndex] as Item;
        return item;
    }


    //移动神经猫
    void MoveCat(int rowIndex ,int columnIndex)
    {
        Item item = cat.GetComponent<Item>();
        item.Goto(rowIndex, columnIndex);
    }


    //判断该坐标是否可以移动
    bool MoveAble(Vector2 vec2)
    {
        Item item = GetPot((int)vec2.x, (int)vec2.y);
        if (item == null)
            return false;
        return item.moveAble;
    }


    //判断神经猫是否逃离至边界
    bool Escaped()
    {
        //获取神经猫的Item并取行列的值
        Item item = cat.GetComponent<Item>();
        int rowIndex = item.rowIndex;
        int columnIndex = item.columnIndex;
        //如果神经猫跑到边界了则返回真
        if (rowIndex == 0 || rowIndex == rowNum - 1 || columnIndex == 0 || columnIndex == columnNum - 1)
            return true;
        return false;
    }


    //设置点击事件发生后的一系列相应事件
    public void Select(Item item)
    {
        if (!started || gameOver) return;       //如果游戏还没开始,则不能进行点击
        if (item.moveAble)
        {
            //获取神经猫的Item并取行列的值
            Item item2 = CreatePot(pot2, item.rowIndex, item.columnIndex);
            pot2Arr.Add(item2);
            item.moveAble = false;
            ArrayList steps = FindSteps();
            //如果神经猫还可以移动
            if (steps.Count > 0)
            {
                //随机移动神经猫
                int index = Random.Range(0, steps.Count);
                Vector2 temp = (Vector2)steps[index];
                MoveCat((int)temp.y, (int)temp.x);
                //如果神经猫已经逃离到了边界
                if (Escaped())
                {
                    gameOver = true;
                    failed.SetActive(true);
                    replay.SetActive(true);
                    print("Escaped");
                }
            }
            //如果神经猫已经没有可移动的pot了
            else
            {
                gameOver = true;
                victory.SetActive(true);
                replay.SetActive(true);
            }
        }
    }


    //寻找神经猫周围的可移动点,并返回可移动的点的数组
    ArrayList FindSteps()
    {
        //获取神经猫的Item并取行列的值
        Item item = cat.GetComponent<Item>();
        int rowIndex = item.rowIndex;
        int columnIndex = item.columnIndex;
        //用steps来储存可移动的pot,用vec2来储存可移动pot的行列值
        ArrayList steps = new ArrayList();
        Vector2 vec2 = new Vector2();


        //left
        vec2.y = rowIndex;
        vec2.x = columnIndex - 1;
        if (MoveAble(vec2))
        {
            steps.Add(vec2);
            //print("LEFT:" + vec2.y + "," + vec2.x);
        }
        //right
        vec2.y = rowIndex;
        vec2.x = columnIndex + 1;
        if (MoveAble(vec2))
        {
            steps.Add(vec2);
            //print("RIGHT:" + vec2.y + "," + vec2.x);
        }
        //top
        vec2.y = rowIndex + 1;
        vec2.x = columnIndex;
        if (MoveAble(vec2))
        {
            steps.Add(vec2);
            //print("TOP:" + vec2.y + "," + vec2.x);
        }
        //bottom
        vec2.y = rowIndex - 1;
        vec2.x = columnIndex;
        if (MoveAble(vec2))
        {
            steps.Add(vec2);
            //print("BOTTOM:" + vec2.y + "," + vec2.x);
        }
        //奇数行 topLeft  偶数行  topRight
        vec2.y = rowIndex + 1;
        if (rowIndex % 2 == 1)
            vec2.x = columnIndex - 1;
        else
            vec2.x = columnIndex + 1;
        if (MoveAble(vec2))
        {
            steps.Add(vec2);
            //print("TOPLEFT OR TOPRIGHT:" + vec2.y + "," + vec2.x);
        }
        //奇数行 bottomLeft  偶数行 bottomRight
        vec2.y = rowIndex - 1;
        if (rowIndex % 2 == 1)
            vec2.x = columnIndex - 1;
        else
            vec2.x = columnIndex + 1;
        if (MoveAble(vec2))
        {
            steps.Add(vec2);
            //print("BOTTOMLEFT OR BOTTOMRIGHT:" + vec2.y + "," + vec2.x);
        }
        
        return steps;
    }


    //创建pot
    Item CreatePot(GameObject pot, int rowIndex, int columnIndex)
    {
        GameObject obj = Instantiate(pot) as GameObject;
        obj.transform.parent = this.transform;                      //放在同一个父物体下,方便管理
        Item item = obj.GetComponent<Item>();                       //获取实例化pot上的Item属性
        item.Goto(rowIndex, columnIndex);                           //设置pot的位置
        item.gameController = this;                                 //令实例化的pot获取gameController属性,方便函数Select的调用
        return item;
    }
}

创作完毕之后我们再给游戏开始的图片和重新开始的图片添加BoxCollider2D来实现可点击效果,并添加下面这个脚本:

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

public class StartGame : MonoBehaviour {
    public GameController gameControlller;

    public void OnMouseDown()
    {
        gameControlller.StartGame();
    }
}

如此,我们的游戏功能就基本上都实现了,为了要让pot1可以被点击,记得给pot1添加碰撞体CircleCollider,并添加Item类脚本,为了让每一次实例化的pot都能够实现想要改变的功能,大家修改的时候可以直接修改预设体的信息。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值