1:3D游戏作业四:牧师与魔鬼动作分离版:
1:要求:
在原来设计的基础上添加一个裁判类,当游戏达到结束条件时,通知场景控制器游戏结束。
2:编程:
本次编程依然是使用MVC编程,只是添加了一个定义裁判类的Judger.cs文件。:
2.创建预制:
在Resources文件夹下创建预制:
3.代码:
3.1 以下的代码都在文件 controller.cs中的同一个命名空间controller下:
0:主要改动:Judger:
添加了一个Judger类,为了方便引用,定义在一个命名空间里。它主要用来分析当前河岸和船上的角色信息,如果某个河岸的魔鬼比牧师的数量多,就判定游戏结束:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using controller;
namespace judger_controller{
public class Judger : System.Object {
private static Judger _instance;
public static Judger getInstance() {
if(_instance == null) _instance = new Judger();
return _instance;
}
public int check_game_over(Bank_controller start_bank,Bank_controller dest_bank, Boat_controller boat) {
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; //游戏继续
}
}
}
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
场记:创建初始化游戏对象,切换各游戏对象以及游戏的状态,负责管理各游戏对象的交换动作。在这个版本中,将游戏状态判断的部分转移到了Judger类中,通过调用Judger判断游戏是否结束:
using System.Collections.Generic;
using UnityEngine;
using controller;
using judger_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 ;
public Judger judger;
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 ();
judger = Judger.getInstance();
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 = judger.check_game_over (start_bank, dest_bank,boat);/
}
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 = judger.check_game_over (start_bank, dest_bank,boat);///
}
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