3D游戏编程_作业三_牧师与魔鬼

1、简答并用程序验证

游戏对象运动的本质是什么?
游戏对象运动的本质是,在每次帧刷新时,对象的坐标位置发生变化,即对象的transform.postion属性变化;

public class Move : MonoBehaviour {

    public int speed = 2;
	// Use this for initialization
	void Start () {

	}
	
	// Update is called once per frame
	void Update () {
		this.transform.position =  Vector3.MoveTowards (this.transform.position, new Vector3(7,7,0), 2 * Time.deltaTime);
	}
}

请用三种方法以上方法,实现物体的抛物线运动。(如,修改Transform属性,使用向量Vector3的方法…)

方法一:修改Transform属性:
定义两个方向上的速度,水平速度恒定,垂直方向速度匀加速:

public class Move_para : MonoBehaviour {

    public int x_speed = 3;
	public int y_speed = 0;
	// Use this for initialization
	void Start () {

	}
	
	// Update is called once per frame
	void Update () {
		this.transform.position +=  Vector3.down *Time.deltaTime *(y_speed/100) ;
		this.transform.position +=  Vector3.left *Time.deltaTime * x_speed;
		y_speed ++;
	}
}

方法二:使用向量Vector3:

每次更新都加一个Vector3向量,该向量x轴上的值不变,y轴上的取值持续增长:

public class Move_para : MonoBehaviour {

    public int x_speed = 3;
	public int y_speed = 80;
	// Use this for initialization
	void Start () {

	}
	
	// Update is called once per frame
	void Update () {
		this.transform.position +=  new Vector3(Time.deltaTime * x_speed,Time.deltaTime *(y_speed/100),0);
		y_speed --;
	}
}

三:使用translate

public class Move_para : MonoBehaviour {

    public int x_speed = 3;
	public int y_speed = 80;
	// Use this for initialization
	void Start () {
	}
	
	// Update is called once per frame
	void Update () {
		this.transform.Translate(new Vector3(Time.deltaTime * x_speed,Time.deltaTime *(y_speed/100),0));
		--y_speed;
	}
}

写一个程序,实现一个完整的太阳系, 其他星球围绕太阳的转速必须不一样,且不在一个法平面上。

1:使用圆球制作太阳系行星的预制:
在这里插入图片描述
2:为每个行星编写运行代码:
比如太阳的代码:太阳只需要自转;因此只使用了函数Rotate;

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

public class Sun : MonoBehaviour
{
    public Transform sun;
    // Start is called before the first frame update
    void Start()
    {
        sun.position = Vector3.zero;
    }

    // Update is called once per frame
    void Update()
    {
        sun.Rotate(Vector3.up*10*Time.deltaTime);
    }
}

i地球和其他行星除了需要自转外,还需要绕着太阳公转;因此有两个动作分别对应Rotate()和Rotate Around():依次为其它行星编写运行代码:

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

public class Earth : MonoBehaviour
{
    public Transform earth;
    // Start is called before the first frame update
    void Start()
    {
        earth.position = new Vector3 (8, 0, 0);
    }

    // Update is called once per frame
    void Update()
    {
        earth.RotateAround (Vector3.zero, Vector3.up, 10 * Time.deltaTime);
        earth.Rotate (Vector3.up * 30 * Time.deltaTime);
    }
}

3:将预制添加成游戏对象,并为它们添加相应的脚本,运行:
在这里插入图片描述

在这里插入图片描述

2.编程实践:牧师与魔鬼:

1:列出游戏中提及的事物(Objects)

牧师、恶魔、船、水、左河岸、右河岸

2:用表格列出玩家动作表(规则表),注意,动作越少越好。

状态玩家动作结果
角色在岸边,船上有空位玩家点击角色角色上船
角色在船上,船靠岸玩家点击角色角色上岸
游戏结束点击restart游戏重新开始

3:编程:

1.MVC编程结构:

按照要求,本次编程我们需要使用MVC架构。MVC架构即就是Model,View和Controller。在牧师与魔鬼游戏中,我们的所有GameObject可以说就是Model,包括 牧师、魔鬼、船等。每个Model就由对应的Controller控制。例如船就受到控制船的Controller的控制。在脚本文件中,我们定义了Boat_controller、Bank_controller等多个controller。而View就是展示给用户的游戏界面,以及可供用户操作的各种方式。比如船点击就能动,牧师和魔鬼一点击就可以上船或下船等。这些功能在User_GUI和Click_GUI文件中实现。
本次编程的代码文件:
所有的游戏对象都由代码动态生成,我们进需要创建一个空的游戏对象,然后将脚本Click_GUI、User_GUI、scen_controller文件添加到空游戏对象中即可运行。
在这里插入图片描述

2.创建预制:

在Resources文件夹下创建预制:
在这里插入图片描述

3.代码:

3.1 以下的代码都在文件 controller.cs中的同一个命名空间controller下:
1.Director:

我们需要一名导演来获取游戏场景;以及控制场景的切换,管理游戏状态:

    public class Director : System.Object{
        private static Director _instance;
        public  ISceneController currentSceneController {get ;set ;}

        public static Director getInstance() {
		    if (_instance == null) {
				_instance = new Director ();
			}
			return _instance;
		}
    }
2.接口:
	public interface ISceneController {
		void load_resource ();
	}

	public interface IUserAction {
		void S_Boating();
		void Click_char(chara_controller characterCtrl);
		void Restart();
	}
3.牧师以及魔鬼游戏对象的controller,以及它们的运动组件:

//charact_move 
//牧师和魔鬼的运动模块:
public class charact_move : MonoBehaviour{

    int char_moveable;  //运动使能,为1时才运动
    int status;    //0 ->移动到起始点,1->移动到船上,2-》移动到终点
    Vector3  free;  //要移动到的目标位置
    void Update() {
        if(char_moveable == 1){

        if(status == 1){

            if(transform.position.x > 0){  //从出发点移动到船上
                if(transform.position.x > 7)
                  transform.position = Vector3.MoveTowards (transform.position, new Vector3(7,3,0), 2 * Time.deltaTime);
                else
                {
                     transform.position = Vector3.MoveTowards (transform.position, free , 2 * Time.deltaTime);
                }

                if(transform.position == free){
                    char_moveable = 0;
                    
                }
            }

            else{  //从终点移动到船上
                if(transform.position.x < -7)
                  transform.position = Vector3.MoveTowards (transform.position, new Vector3(-7,3,0), 2 * Time.deltaTime);
                else
                {
                     transform.position = Vector3.MoveTowards (transform.position, free , 2 * Time.deltaTime);
                }
                if(transform.position == free){
                    char_moveable = 0;
                    
                }
            }
          }
          else{
            if(transform.position.x > 0){  //移动到起始岸边
                if(transform.position.x < 7)
                  transform.position = Vector3.MoveTowards (transform.position, new Vector3(7,3,0), 2 * Time.deltaTime);
                else
                {
                     transform.position = Vector3.MoveTowards (transform.position, free , 2 * Time.deltaTime);
                }

                if(transform.position == free){
                    char_moveable = 0;
                    
                }
            }

            else{   //移动到终点岸边
                if(transform.position.x > -7)
                  transform.position = Vector3.MoveTowards (transform.position, new Vector3(-7,3,0), 2 * Time.deltaTime);
                else
                {
                     transform.position = Vector3.MoveTowards (transform.position, free , 2 * Time.deltaTime);
                }
                if(transform.position == free){
                    char_moveable = 0;
                    
                }
            }
          }
        }
    }

    public void set_char_mov(int istatus,Vector3 t_free)   
    {
        char_moveable = 1 ;
        status = istatus;
        free = t_free ;
    }


    public void init()
    {
        char_moveable = 0;
    }
}




chara_controller
    public class chara_controller {
        GameObject character;
        int char_type;  //0-priest;1-devil
        int status; //0- start;1->on boat; 2->on dest
        int char_moveable;  //运动使能
        int rank ; //排位
        Vector3 position; //位置
        Vector3 free;  //移动的目标地址
		readonly Click_GUI click_GUI;
        Bank_controller bank_con;
        Boat_controller boat_con ;
        charact_move chara_movscr;  //运动模块
        public chara_controller(int irank,int itype)
        {
          if (itype == 0) {
                position = new Vector3(7+irank,2,0);
                rank = irank;
                status = 0;
                char_type = 0;
				character = Object.Instantiate (Resources.Load ("Perfabs/Priest", typeof(GameObject)), position, Quaternion.identity, null) as GameObject;
			} else {
                position = new Vector3(7+irank,2,0);
                rank = irank;
                status = 0;
                char_type = 1;
				character = Object.Instantiate (Resources.Load ("Perfabs/Devil", typeof(GameObject)), position, Quaternion.identity, null) as GameObject;
			}
            chara_movscr = character.AddComponent (typeof(charact_move)) as charact_move;
			click_GUI = character.AddComponent (typeof(Click_GUI)) as Click_GUI;
			click_GUI.setController (this);
        }
 //角色运动控制函数
        public void charac_action(int start_end,Vector3 ifree)
        {
            if(status == 0 || status == 2 )
            {
                chara_movscr.set_char_mov(start_end,ifree);
                status = 1;
            }
            else {
                chara_movscr.set_char_mov(start_end,ifree);
                status = start_end;
            }
        }





        public void set_position(Vector3 pos)
        {
            character.transform.position = pos;
            position = pos;
        }

		public void setName(string name) {
			character.name = name;
		}
        public Vector3 get_position()
        {
            return position;
        }

        public int get_type(){
            return char_type;
        }

        public int get_rank(){
            return rank ;
        }

        public int get_status(){
            return status;
        }
         
 
        public void set_free(Vector3 free_posi){
            free = free_posi;
        }


       public void get_on_boat(Boat_controller boat_c)
       {
           bank_con = null;
           boat_con = boat_c;
           character.transform.parent = boat_c.get_Object().transform;
       }

       public void get_on_bank(Bank_controller ban_c)
       {
           bank_con = ban_c;
           character.transform.parent = null;
           boat_con = null;
       }
      
      public Bank_controller get_bank(){
          return bank_con;
      }

      public  void init() {  //初始化
                position = new Vector3(7+rank,2,0);
                character.transform.position = position ;
                status = 0;
			    bank_con = (Director.getInstance ().currentSceneController as scen_controller).start_bank;
			    get_on_bank (bank_con);
                chara_movscr.init();
        }

    }
4.boat对象的控制函数和运动模块:

public class boat_move : MonoBehaviour{    //船的运动模块;

    int status;  //0-> 在起始位置  1-> 在终点位置
    int boat_movable;   //运动使能

    Vector3 start_pos = new Vector3(5.2F,1,0);  //船的起始位置
    Vector3 desti_pos = new Vector3(-5.2F,1,0); //船的的终点位置
    void Update() {

        if(boat_movable == 1)
           {
                if(status == 0 && boat_movable == 1)  //从起点移动到终点
                {
                    transform.position = Vector3.MoveTowards (transform.position,desti_pos,5*Time.deltaTime);
                    if(transform.position == desti_pos)
                    {
                        status = 1;//
                        boat_movable = 0;
                    }
                        
                }
                else if(status == 1 && boat_movable == 1){  //从终点移动到起始点
                    transform.position = Vector3.MoveTowards (transform.position,start_pos,5*Time.deltaTime);
                    if(transform.position == desti_pos)
                    {
                        status = 0;//
                        boat_movable = 0;
                    }
                }
           }
    }


    public void set_boat_action(int stat,int moveable) //设置状态和运动时能
    {
        status =stat;
         boat_movable  = moveable; 
    }
    public void init()  //初始化
    {
        status = 0;
        boat_movable = 0;
    }
}


public class Boat_controller{
    GameObject boat;
    Vector3 start_pos = new Vector3(5.2F,1,0);
    Vector3 desti_pos = new Vector3(-5.2F,1,0);
    boat_move  boat_moscri;
    int status ;  //0->at_start,1->at_dest; 2->boating

    int boat_movable;//0->不移动  1-->移动
    chara_controller [] passenger = new chara_controller [2];  //船上的乘客

    public Boat_controller() {
        status = 0;
        boat_movable = 0;
        boat = Object.Instantiate(Resources.Load ("Perfabs/Boat",typeof(GameObject)),start_pos,Quaternion.identity,null) as GameObject;
        boat.name = "boat";
        boat.AddComponent(typeof(Click_GUI));
        boat_moscri = boat.AddComponent (typeof(boat_move)) as boat_move;
    }
    

public void boating()
{
    if(status == 0)
    {
        boat_moscri.set_boat_action(0,1);
        status = 1;
    }
    else if(status == 1)
    {
        boat_moscri.set_boat_action(1,1);
        status = 0;       
    }
}
    public int get_free() {//获取船上的空闲位置
        if(passenger[0] == null)  return 0;
        if(passenger[1] == null)  return 1;
        return -1;
    }


    public void get_on_boat(chara_controller chara_c) { //将角色加入船的乘客队列
       int free_i = get_free ();
       passenger [free_i] = chara_c;
    }


    public chara_controller get_off_boat(int rank_i) {//将角色从队列中除去;
        for(int i = 0; i < 2; ++i){
           if(passenger[i]!= null && passenger[i].get_rank() == rank_i) {
            chara_controller chara_c = passenger [i];
            passenger [i] = null;
            return chara_c ;
        }
      }   
      return null;       
    }

    public GameObject get_Object() {
        return boat;
    }

     public int get_status() {
         return status ;
     }
     public void set_boat_move(int t)
     {
          boat_movable = t;
     }
    public int [] count_chara() {  //统计乘客的数量和类型
        int [] count = {0,0,0};
        for(int i = 0; i< 2; i++)
        {
            if(passenger[i] == null)
              continue;
              else if(passenger[i].get_type() == 0)
              count[0] ++;
               else{
                   count[1] ++;
               }
        }
        count[2] = count[0] +count[1];
        return count;
    }

    public void init() {
        if(status == 1)
          {
              boating();
          }

        passenger = new chara_controller[2];
    }


  }
5.河岸的控制函数:
    public class Bank_controller{
        GameObject bank;
        Vector3 position;
        int type ; //1->start  -1->destination

        chara_controller [] characters ;

        public  Bank_controller(int itype)
        {
            position = new Vector3(10*itype,1,0);
            bank = Object.Instantiate (Resources.Load("Perfabs/bank",typeof(GameObject)),position ,Quaternion.identity,null) as GameObject;
            type = itype;
            characters = new chara_controller [6];
        }
       
        public void get_on_bank(chara_controller chara_c) {
           int irank = chara_c.get_rank();
           characters[irank] = chara_c ;
        }
        public chara_controller get_off_bank(int irank){
            chara_controller ichara = characters[irank];
            characters[irank]  = null;
            return ichara ;
        }


        public int get_type() {
            return type;
        }

        public int [] count_chara() {
            int [] count = { 0 , 0};
            for(int i = 0; i< 6; ++i)
            {
                if(characters[i] == null)
                  continue ;
                if(characters[i].get_type() == 0)
                  count[0] ++;
                else if(characters[i].get_type() == 1)
                   count[1] ++;
            }
            return count ;
        }

        public void init() {
            characters = new chara_controller[6];
        }
    }

3.2 User_GUI负责处理玩家动作;在游戏结束时点击按键重新游戏:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using controller;

public class User_GUI : MonoBehaviour {
	private IUserAction action;
	public int status = 0;
	GUIStyle style;
	GUIStyle buttonStyle;


    void Start() {//
    	action = Director.getInstance ().currentSceneController as IUserAction;
        style = new GUIStyle();
		style.fontSize = 40;
        style.normal.textColor = new Color(100, 155, 255);
		style.alignment = TextAnchor.MiddleCenter;

		buttonStyle = new GUIStyle("button");
		buttonStyle.fontSize = 30;
		buttonStyle.normal.textColor = new Color(100, 155, 255);


    }
	void OnGUI() {
		if (status == 1) {
			GUI.Label(new Rect(Screen.width/2-50, Screen.height/2-85, 100, 50), "Gameover!", style);
			if (GUI.Button(new Rect(Screen.width/2-70, Screen.height/2, 140, 70), "Restart", buttonStyle)) {
				status = 0;
				action.Restart ();
			}
		} else if(status == 2) {
			GUI.Label(new Rect(Screen.width/2-50, Screen.height/2-85, 100, 50), "You win!", style);
			if (GUI.Button(new Rect(Screen.width/2-70, Screen.height/2, 140, 70), "Restart", buttonStyle)) {
				status = 0;
				action.Restart ();
			}
		}
	}
}
3.3scen_controller 在这里插入代码片场记:创建初始化游戏对象,切换各游戏对象以及游戏的状态,负责管理各游戏对象的交换动作。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using controller;

public class scen_controller : MonoBehaviour, ISceneController, IUserAction {

    User_GUI user_GUI;
    public Bank_controller start_bank;
    public Bank_controller dest_bank;
    public Boat_controller boat;
    public chara_controller [] characters ;
    
    void Awake() {
        Director director = Director.getInstance ();
        director.currentSceneController = this;
        user_GUI = gameObject.AddComponent <User_GUI>() as User_GUI;
		characters = new chara_controller[6];
        load_resource();
    }
   
    public void load_resource() {

        start_bank = new Bank_controller(1) ;
        dest_bank = new Bank_controller (-1);
        GameObject water = Instantiate (Resources.Load ("Perfabs/Water", typeof(GameObject)), new Vector3(0,0.5F,0), Quaternion.identity, null) as GameObject;
        boat = new Boat_controller ();
  
        for(int i = 0; i < 6; ++i){
            if(i < 3)
            {
                chara_controller chara_t = new chara_controller (i,0);
                chara_t.setName("priest" + i);
                chara_t.get_on_bank(start_bank);
                start_bank.get_on_bank(chara_t);
                characters[i] = chara_t;
            }
            else{
                chara_controller chara_t = new chara_controller (i,1);
                int t = i - 3;
                chara_t.setName("devil" +t);
                chara_t.get_on_bank(start_bank);
                start_bank.get_on_bank(chara_t);
                characters[i] = chara_t;
            }
        }

    }



	public void S_Boating() {
		int [] count_i = boat.count_chara();
        if(count_i[2] == 0)
        {
            Debug.Log("boat_empty");
	       	return;
        }

		boat.boating();
        Debug.Log("set_boat");
		user_GUI.status = check_game_over ();
	}


    public void Click_char(chara_controller char_i) {
        if(char_i.get_status() == 1){  //在船上
             if(boat.get_status() == 0)//在开始地方
             {
                 
                 char_i.get_on_bank(start_bank);
                 start_bank.get_on_bank(char_i);
                 int t_rank = char_i.get_rank();
                 boat.get_off_boat(t_rank);
                 Vector3 free_pos = new Vector3(7+t_rank ,2,0);
                 char_i.charac_action(0,free_pos);
             }

            if(boat.get_status() == 1) //上终点河岸
                {
                    char_i.get_on_bank(dest_bank);
                    dest_bank.get_on_bank(char_i);
                    int t_rank = char_i.get_rank();
                    boat.get_off_boat(t_rank);
                    Vector3 free_pos = new Vector3(-7-t_rank ,2,0);
                    char_i.charac_action(2,free_pos);
                }
        }

        else{//在岸上
            Bank_controller bank_i = char_i.get_bank();

            if(boat.get_free() == -1)  
                 return ;

            if((bank_i.get_type() == 1 && boat.get_status() == 0)) ///在起点河岸上船
            {
                   bank_i.get_off_bank(char_i.get_rank());
                   int index = (boat.get_free())*2-1;           
                   Vector3 free_pos = new Vector3(5+index,1.5F,0);
                   char_i.charac_action(1,free_pos);
                   char_i.get_on_boat (boat);
                   boat.get_on_boat(char_i);
            }//在终点河岸上船:
             else if ((bank_i.get_type() == -1 && boat.get_status() == 1))
               {
                   bank_i.get_off_bank(char_i.get_rank());
                   int index = (boat.get_free())*2-1;           
                   Vector3 free_pos = new Vector3(-5+index,1.5F,0);
                   char_i.charac_action(1,free_pos);
                   char_i.get_on_boat (boat);
                   boat.get_on_boat(char_i);
               }
            else  {return ;}
        }

        user_GUI.status = check_game_over();
    }

    int check_game_over() {
       int start_priest = 0;
       int start_devil = 0;
       int dest_priest = 0;
       int dest_devil  = 0;
       
       int[] start = start_bank.count_chara();
       int[] dest = dest_bank.count_chara();
       int[] boat_count = boat.count_chara();

       if(dest[0] +dest[1] == 6)  return 2;   //赢


       if(boat.get_status() == 0){
           start_priest = start[0] + boat_count[0];
           start_devil =  start[1] + boat_count[1];
           dest_priest = dest[0];
           dest_devil =  dest[1];
       }
       else{
           start_priest = start[0] ;
           start_devil =  start[1] ;
           dest_priest = dest[0]+ boat_count[0];
           dest_devil =  dest[1]+ boat_count[1];
       }
       Debug.Log("start:"+start[0]+start[1]);
       Debug.Log("dest:" +dest[0]+dest[1]);
       Debug.Log("boat:"+ boat_count[0]+boat_count[1]+boat_count[2]);
       Debug.Log("start_p"+start_priest+start_devil+dest_priest+dest_devil);

       if((start_priest < start_devil && start_priest !=0) || (dest_priest < dest_devil && dest_priest != 0))
         return 1;   //游戏结束

       return 0;  //游戏继续

    }

public void Restart(){
    start_bank.init();
    dest_bank.init();
    boat.init();
    for(int i = 0; i < 6; ++i)
    {
        characters[i].init();
        start_bank.get_on_bank(characters[i]);
    }
} 

}
3.4 处理游戏对象点击的类 Click_GUI
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using controller;

public class Click_GUI : MonoBehaviour {
	IUserAction action;
	chara_controller characterController;

	public void setController(chara_controller characterCtrl) {
		characterController = characterCtrl;
	}

	void Start() {
		action = Director.getInstance ().currentSceneController as IUserAction;
	}

	void OnMouseDown() {
		if (gameObject.name == "boat") {
			action.S_Boating();
		} else {
			action.Click_char(characterController);
		}
	}
}

4.游戏运行:

1:运行截图:

在这里插入图片描述
在这里插入图片描述

2:演示视频:

priest and devil

项目链接地址

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值