巡逻兵小游戏

自制巡逻兵小游戏

  • 这次的作业是制作巡逻兵小游戏,以加深我们对模型和Animator的理解。
  • 首先是游戏的规则:

    1. 创建一个地图和若干巡逻兵(使用动画);
    2. 每个巡逻兵走一个3~5个边的凸多边型,位置数据是相对地址。即每次确定下一个目标位置,用自己当前位置为原点计算;
    3. 巡逻兵碰撞到障碍物,则会自动选下一个点为目标;
    4. 巡逻兵在设定范围内感知到玩家,会自动追击玩家;
    5. 失去玩家目标后,继续巡逻;
    6. 计分:玩家每次甩掉一个巡逻兵计一分,与巡逻兵碰撞游戏结束;
    
  • 游戏模式:

    1. 工厂模式
    2. 观察者与订阅者模式
    
  • 下面说一下具体的实现:

    • 订阅者与发布者模式

      通过发布者实现游戏中GameStatus(游戏状态)和CanvasStatus(分数和游戏界面显示) 的交流。这里使用了委托,myGameScoreAction加上事件gamescore和gameover。

          public class CanvasStatus : MonoBehaviour {
              private int score = 0;
              private int textType;  
      
              void Start () {
                  distinguishText();
              }
      
              void Update () {
              }
              void distinguishText() {
                  if (gameObject.name.Contains ("Score"))
                      textType = 0;
                  else {
                      Debug.Log (gameObject.name);
                      textType = 1;
                  }
              }
              void OnEnable() {
                  GameStatus.myGameScoreAction += gameScore;
                  GameStatus.myGameOverAction += gameOver;
              }
      
              void OnDisable() {
                  GameStatus.myGameScoreAction -= gameScore;
                  GameStatus.myGameOverAction -= gameOver;
              }
      
              void gameScore() {
                  if (textType == 0 && this.gameObject.name.Contains("Score")) {
                      score++;
                      this.gameObject.GetComponent<Text>().text = "Score: " + score;
                  }
              } 
      
              void gameOver() {
                  if (textType == 1) {
                      this.gameObject.GetComponent<Text> ().text = "Game Over!";
      
                  }
              }
          }
      
    • 工厂模式

      在工厂中生产巡逻兵和英雄

          namespace Com.Patrols {
              public class PatrolFactory : System.Object {
                  private static PatrolFactory instance;
                  private GameObject PatrolItem;
                  private GameObject HeroItem;
      
                  private Vector3[] PatrolPosSet = new Vector3[] { new Vector3(-6, 0, 16), new Vector3(-1, 0, 19),
                      new Vector3(6, 0, 16), new Vector3(-5, 0, 7), new Vector3(0, 0, 7), new Vector3(6, 0, 7)};
      
                  public static PatrolFactory getInstance() {
                      if (instance == null)
                          instance = new PatrolFactory();
                      return instance;
                  }
      
                  public void initPatrol(GameObject _PatrolItem) {
                      PatrolItem = _PatrolItem;
                  }
                  public void initHero(GameObject _Hero){
                      HeroItem = _Hero;
                  }
                  public GameObject getPatrol() {
                      GameObject newPatrol = Camera.Instantiate(PatrolItem);
                      return newPatrol;
                  }
                  public GameObject getHero(){
                      GameObject newHero = Camera.Instantiate (HeroItem);
                      return newHero;
                  }
                  public Vector3[] getPosSet() {
                      return PatrolPosSet;
                  }
              }
          }
      
    • 动作分离用的类都是以前的,下面是巡逻兵的动作

      1. 巡逻兵巡逻。

            int getRandomDirection(int index, bool isActive) {
                int randomDir = Random.Range(-1, 3);
                if (!isActive) {    //当碰撞时,不走同方向
                    while (PatrolLastDir[index] == randomDir || PatrolOutOfArea(index, randomDir)) {
                        randomDir = Random.Range(-1, 3);
                    }
                }
                else {              //当非碰撞时,不走反方向
                    while (PatrolLastDir[index] == 0 && randomDir == 2 
                        || PatrolLastDir[index] == 2 && randomDir == 0
                        || PatrolLastDir[index] == 1 && randomDir == -1
                        || PatrolLastDir[index] == -1 && randomDir == 1
                        || PatrolOutOfArea(index, randomDir)) {
                        randomDir = Random.Range(-1, 3);
                    }
                }
                return randomDir;
            }  
            public void addRandomMovement(GameObject sourceObj, bool isActive) {
                if (ifStop == 1)
                    return;
                int index = getIndexOfObj(sourceObj);
                int randomDir = getRandomDirection(index, isActive);
                PatrolLastDir[index] = randomDir;
        
                sourceObj.transform.rotation = Quaternion.Euler(new Vector3(0, randomDir * 90, 0));
                Vector3 target = sourceObj.transform.position;
                switch (randomDir) {
                    case Diretion.UP:
                        target += new Vector3(0, 0, 1);
                        break;
                    case Diretion.DOWN:
                        target += new Vector3(0, 0, -1);
                        break;
                    case Diretion.LEFT:
                        target += new Vector3(-1, 0, 0);
                        break;
                    case Diretion.RIGHT:
                        target += new Vector3(1, 0, 0);
                        break;
                }
                addSingleMoving(sourceObj, target, PERSON_SPEED_NORMAL, false);
            }
        
      2. 追捕英雄

        public void addDirectMovement(GameObject sourceObj) {
            if (ifStop == 1)
                return;
            int index = getIndexOfObj(sourceObj);
            PatrolLastDir[index] = -2;
        
            sourceObj.transform.LookAt(sourceObj.transform);
            Vector3 oriTarget = myHero.transform.position - sourceObj.transform.position;
            Vector3 target = new Vector3(oriTarget.x / 4.0f, 0, oriTarget.z / 4.0f);
            target += sourceObj.transform.position;
            //Debug.Log("addDirectMovement: " + target);
            addSingleMoving(sourceObj, target, PERSON_SPEED_CATCHING, true);
        }
        
    • 视频演示:https://pan.baidu.com/s/15JNB0NHiA0dXdgDSarWCwg,密码:14wp

    • 参考资料:https://blog.csdn.net/qq_33000225/article/details/70045292

    • 源码地址:https://github.com/ZhaoJle/3dgame/tree/master/Homework6

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值