自制巡逻兵小游戏
- 这次的作业是制作巡逻兵小游戏,以加深我们对模型和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; } } }
动作分离用的类都是以前的,下面是巡逻兵的动作
巡逻兵巡逻。
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); }
追捕英雄
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