3d游戏——巡逻兵

实验要求

  • 游戏设计要求 
    • 创建一个地图和若干巡逻兵(使用动画);
    • 每个巡逻兵走一个3~5个边的凸多边型,位置数据是相对地址。即每次确定下一个目标位置,用自己当前位置为原点计算;
    • 巡逻兵碰撞到障碍物,则会自动选下一个点为目标;
    • 巡逻兵在设定范围内感知到玩家,会自动追击玩家;
    • 失去玩家目标后,继续巡逻;
  • 程序设计要求 
    • 必须使用订阅与发布模式传消息
    • subject:OnLostGoal
    • Publisher: ?
    • Subscriber: ?
    • 工厂模式生产巡逻兵

相关代码

场景

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


public class GameController :  SSActionManager, ISSActionCallback
{
    Vector3[] posset = new Vector3[] { new Vector3(1, 0.25f, 1), new Vector3(1, 0.25f, -1), new Vector3(-1, 0.25f, -1), new Vector3(-1, 0.25f, 1) };
    Vector3[] Random = new Vector3[] { new Vector3(3, 0, 0), new Vector3(0, 0, 3), new Vector3(-3, 0, 0), new Vector3(0, 0, -3) };
    int rollnum = 0;
    private static GameController instance;
    public bool isOver = false;

    public GameObject player, guard,environment;
    private GameObject _player, scene;
    private List<GameObject> GuardSet;
    
    // Use this for initialization
    new void Start () {
        _player = Instantiate(player);
        _player.name = "player";
        scene = Instantiate(environment);
        instance = this;
        initGuard();
    }
    
    
    public static GameController getInstance()
    {
        return instance;
    }
    void initGuard()
    {
        GuardSet = new List<GameObject>(4);
        for(int i=0;i<4;i++)
        {
            GameObject newone = Instantiate(guard);
            newone.name = "guard" + i;
            newone.transform.position = posset[i];
        }
        
    }
	// Update is called once per frame
	
    public int getPlayerArea()
    {
        return _player.GetComponent<playerStatus>().areaIndex;
    }
    public void goCatch(GameObject guard)
    {
        addSingleMoving(guard, _player.transform.position, 0.05f, false);
    }
    public void goBack(GameObject guard,bool aaa)
    {
        
        string name = guard.gameObject.name;
        char cindex = name[name.Length - 1];
        int index = cindex - '0';
        addSingleMoving(guard, posset[index], 0.05f, false);
    }
    public void goarround(GameObject guard, int dir)
    {
        string name = guard.gameObject.name;
        char cindex = name[name.Length - 1];
        int index = cindex - '0';
        Vector3 oriTarget = Random[dir];
        oriTarget += guard.transform.position   ;
        
        addSingleMoving(guard, oriTarget, 0.05f, false);
        
    }
    void addSingleMoving(GameObject sourceObj, Vector3 target, float speed, bool isCatching)
    {
        this.runAction(sourceObj, CCMoveToAction.CreateSSAction(target, speed, isCatching), this);
    }
    public bool nearby(Vector3 a,Vector3 b)
    {
        float x1, x2, z1, z2;
        x1 = a.x;
        x2 = b.x;
        z1 = a.z;
        z2 = b.z;
        

        if (Math.Abs(x1 - x2) < 0.9f && Math.Abs(z1 - z2) < 0.9f)
        {
            //Debug.Log("pos:" + Math.Abs(x1 - x2) + "," + Math.Abs(z1 - z2));
            return true;
        } 
        else return false;
    }
    public void patrolHitHeroAndGameover()
    {
        isOver = true;
    }
    public void SSActionEvent(SSAction source, SSActionEventType eventType = SSActionEventType.Completed, SSActionTargetType intParam = SSActionTargetType.Normal, string strParam = null, object objParam = null)
    {
        //throw new NotImplementedException();
    }
}

巡逻兵

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

public class guardStatus : MonoBehaviour {
    Vector3[] posset = new Vector3[] { new Vector3(1, 0.25f, 1), new Vector3(1, 0.25f, -1), new Vector3(-1, 0.25f, -1), new Vector3(-1, 0.25f, 1) };
    Vector3[] Random = new Vector3[] { new Vector3(3, 0, 0), new Vector3(0, 0, 3), new Vector3(-3, 0, 0), new Vector3(0, 0, -3) };
    Vector3 prepos;

    private int ownIndex = -1;
    public bool isCatching;
    public bool isIdle;
    int dir = 0;
    public GameController _controller;
    
    // Use this for initialization
    void Start () {
        ownIndex = getOwnIndex();
        dir = ownIndex;
        if (dir == 3) dir = 1;
        else if (dir == 1) dir = 3;
        isCatching = false;
        isIdle = true;
        _controller = GameController.getInstance() as GameController;
    }
	
	// Update is called once per frame
	void Update () {
        checkPlayerCome();
        
    }
    int getOwnIndex()
    {
        string name = this.gameObject.name;
        char cindex = name[name.Length - 1];
        int result = cindex - '0';
        return result;
    }
    void checkPlayerCome()
    {

        if (_controller.getPlayerArea() == ownIndex)
        {    //只有当走进自己的区域
            if (!isCatching)
            {
                isCatching = true;
                isIdle = false;
            }
            _controller.goCatch(this.gameObject);
        }
        else
        {
            if (isCatching)
            {    //刚才为捕捉状态,但此时hero已经走出所属区域
                //gameStatusOp.heroEscapeAndScore();
                isCatching = false;
                resetdir();
                _controller.goBack(this.gameObject, isIdle);
            }
            else
            {
                //gameStatusOp.heroEscapeAndScore();
            }
            if(!isIdle)
            {
                checkIsIdle();
            }
            else
            {
                if(this.transform.position == prepos + Random[dir])
                {
                    turn();
                    prepos = transform.position;
                    _controller.goarround(this.gameObject, dir);
                }
                    
            }
        }
    }
    void OnCollisionStay(Collision e)
    {
        
        //撞击hero,游戏结束
        if (e.gameObject.name.Contains("player"))
        {
            _controller.patrolHitHeroAndGameover();
            Debug.Log("Game Over!");
        }
    }
    void resetdir()
    {
        dir = ownIndex;
        if (dir == 3) dir = 1;
        else if (dir == 1) dir = 3;

    }
    void checkIsIdle()
    {
        Vector3 a = this.transform.position;
        Vector3 b = posset[ownIndex];
        if (a == b)
        {
            isIdle = true;
            prepos = posset[ownIndex];
            _controller.goarround(this.gameObject, dir);
        }
        
    }
    public void turn()
    {
        dir++;
        if (dir > 3) dir = 0;
        Debug.Log(dir + "turn");
    }
}

UI

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

public class UI : MonoBehaviour {

	// Use this for initialization
	void Start () {
		
	}
    public class Diretion
    {
        public const int UP = 0;
        public const int DOWN = 2;
        public const int LEFT = -1;
        public const int RIGHT = 1;
    }
    // Update is called once per frame
    void Update () {
        if (Input.GetKey(KeyCode.UpArrow))
        {
            heroMove(Diretion.UP);
        }
        if (Input.GetKey(KeyCode.DownArrow))
        {
            heroMove(Diretion.DOWN);
        }
        if (Input.GetKey(KeyCode.LeftArrow))
        {
            heroMove(Diretion.LEFT);
        }
        if (Input.GetKey(KeyCode.RightArrow))
        {
            heroMove(Diretion.RIGHT);
        }
    }
    public void heroMove(int dir)
    {
        transform.rotation = Quaternion.Euler(new Vector3(0, dir * 90, 0));
        switch (dir)
        {
            case Diretion.UP:
                transform.position += new Vector3(0, 0, 0.1f);
                break;
            case Diretion.DOWN:
                transform.position += new Vector3(0, 0, -0.1f);
                break;
            case Diretion.LEFT:
                transform.position += new Vector3(-0.1f, 0, 0);
                break;
            case Diretion.RIGHT:
                transform.position += new Vector3(0.1f, 0, 0);
                break;
        }
    }
}

大致是这样,详情请看GitHub

https://github.com/wakaka001/3d-game-learning/tree/master/Homework6

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值