简介及其他
魔鬼与牧师游戏规则相对来说简单,对象也不多,适合于做一开始的练习,想玩游戏的点这里
我做的最终效果如图,红色代表魔鬼,白色代表牧师,看起来还是蛮好懂的哈,并没有美术素材,希望懂得找资源和添加方法的同学教教我
做这个游戏过程中,难度和重要程度划分如下:
- 单实例的应用
- 一些细节,比如创建光源等的学习
- 游戏逻辑实现
其中游戏逻辑实现是最简单的,可以用list也可以用stack,根据制定的不同的游戏动作规则表有各种各样的实现方法。
而重要的在于单实例的理解和应用;
我们用三个文件来实现MVC的结构:
- Basecode.cs V
- GenGameObjects M
- Actions C
如何运行
最终只要将这三个文件挂载在 main camera 上就好了,代码中有规定camera位置,以及创建光源,所以并不需要在别的地方在添加或者修改东西
在BaseCode中我们定义了命名空间来实现单实例
namespace Com.Mygame {
public enum WinOrLose {Win,Lose,Gaming};
public interface ImyAction { //这是定义的接口ImyAction
void DevilGoOnBoat();
void DevilGoOffBoat ();
void PriestGoOnBoat();
void PriestGoOffBoat();
void BoatGo ();
}
public class GameSceneController:System.Object, ImyAction {
// 定义了GameSceneController来管理View层,以下的类都是单实例的,只能实例化一次
private static GameSceneController _instance;
private BaseCode _base_code;
private GenGameObjects _gen_game_object;
public WinOrLose wl = WinOrLose.Gaming;
public static GameSceneController GetInstance(){
if (null == _instance) {
_instance = new GameSceneController ();
}
return _instance;
}
public BaseCode getBaseCode(){
return _base_code;
}
internal void setBaseCode(BaseCode bc){
if (null == _base_code) {
_base_code = bc;
}
}
public GenGameObjects getGenGameObject(){
return _gen_game_object;
}
internal void setGenGameObject(GenGameObjects g){
if (_gen_game_object == null){
_gen_game_object = g;
}
}
//这下面是接口函数,里面调用的_gen_game_object方法必须是 public 的,否则无法使用
public void DevilGoOnBoat(){
_gen_game_object.DevilGoOnBoat ();
}
public void DevilGoOffBoat (){
_gen_game_object.DevilGoOffBoat ();
}
public void PriestGoOnBoat(){
_gen_game_object.PriestGoOnBoat ();
}
public void PriestGoOffBoat(){
_gen_game_object.PriestGoOffBoat ();
}
public void BoatGo (){
_gen_game_object.BoatGo ();
}
}
}
GenGameObjects用于创建各个对象并实例化他们
这里需要创建一个GameSceneController,然后将自己注入到其中,使用setGenGameobject方法,同时寒添加Com.Mygame,也就是自己定义的命名空间。
代码没有什么好说的,每个人有每个人的实现方法。这次给我经验就是不用怕设置很多的变量,但是一定要区分模块,将主体分割成一部分一部分的功能。不然越做越乱。
注意,在unity中,设定相对位置localposition,是要考虑父对象的scale的,如果父对象缩小了2倍,那么移动单位距离时,就要乘以2!
同时网上各种查不到的脚本添加光源方法,这里也记一下:
GameObject light = new GameObject("The light");
Light lightComp = light.AddComponent<Light> ();
lightComp.type = LightType.Directional;//添加的光源还可以是其他的类型
//但是平行光的话一定要成角度,一下是转化角度的方式
Quaternion Q;
Q = Quaternion.Euler (20.0f,0.0f,0.0f); //这个方法可以将欧拉角度转化为4元组的角度,比较实用
light.transform.rotation = Q;
同理在Action里,写入GUI函数,并添加接口函数就可以了
void OnGUI(){
if(GUI.Button(new Rect(firstBx,firstBy,BottonW,BottonH), "魔鬼上船")){
actions.DevilGoOnBoat ();
}
if(GUI.Button(new Rect(firstBx+BottonW+blank,firstBy,BottonW,BottonH), "魔鬼下船")){
actions.DevilGoOffBoat ();
}
if(GUI.Button(new Rect(firstBx,firstBy+BottonH+blank,BottonW,BottonH), "牧师上船")){
actions.PriestGoOnBoat ();
}
if(GUI.Button(new Rect(firstBx+BottonW+blank,firstBy+BottonH+blank,BottonW,BottonH), "牧师下船")){
actions.PriestGoOffBoat ();
}
if(GUI.Button(new Rect(firstBx,firstBy+(BottonH+blank)*2,BottonW*2+blank,BottonH*2), "开船!")){
actions.BoatGo ();
if (mygame.wl == WinOrLose.Gaming) str = "点击重置!";
else if (mygame.wl == WinOrLose.Lose) str = "输了...重来!";
else if (mygame.wl == WinOrLose.Win) str = "赢了!再来!";
}
if(GUI.Button(new Rect(Screen.width-BottonW/2,firstBy,BottonW/2,BottonH),str)){
Application.LoadLevel (Application.loadedLevelName);
mygame.wl = WinOrLose.Gaming;
}
//GUI.Label (new Rect (firstBx,firstBy-BottonH,BottonW*2,BottonH), str);
}
完整代码如下,本人为编程渣渣,所以在逻辑实现部分显得很繁琐,= =,如果大家有更好的实现方法,多多交流啦~
完整代码
BaseCode.cs
using UnityEngine;
using System.Collections;
using Com.Mygame;
namespace Com.Mygame {
public enum WinOrLose {Win,Lose,Gaming};
public interface ImyAction {
void DevilGoOnBoat();
void DevilGoOffBoat ();
void PriestGoOnBoat();
void PriestGoOffBoat();
void BoatGo ();
}
public class GameSceneController:System.Object, ImyAction {
private static GameSceneController _instance;
private BaseCode _base_code;
private GenGameObjects _gen_game_object;
public WinOrLose wl = WinOrLose.Gaming;
public static GameSceneController GetInstance(){
if (null == _instance) {
_instance = new GameSceneController ();
}
return _instance;
}
public BaseCode getBaseCode(){
return _base_code;
}
internal void setBaseCode(BaseCode bc){
if (null == _base_code) {
_base_code = bc;
}
}
public GenGameObjects getGenGameObject(){
return _gen_game_object;
}
internal void setGenGameObject(GenGameObjects g){
if (_gen_game_object == null){
_gen_game_object = g;
}
}
public void DevilGoOnBoat(){
_gen_game_object.DevilGoOnBoat ();
}
public void DevilGoOffBoat (){
_gen_game_object.DevilGoOffBoat ();
}
public void PriestGoOnBoat(){
_gen_game_object.PriestGoOnBoat ();
}
public void PriestGoOffBoat(){
_gen_game_object.PriestGoOffBoat ();
}
public void BoatGo (){
_gen_game_object.BoatGo ();
}
}
}
public class BaseCode : MonoBehaviour {
public string gameName;
public string gameRule;
// Use this for initialization
void Start () {
this.transform.position = new Vector3 (0.0f,5.0f,-12.0f);
GameSceneController mygame = GameSceneController.GetInstance ();
mygame.setBaseCode (this);
}
// Update is called once per frame
void Update () {
}
}
GenGameObjects.cs
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Com.Mygame;
public class GenGameObjects : MonoBehaviour {
GameSceneController mygame;
//boat
int state = 0;
GameObject Boat;
Vector3 boatscale = new Vector3(4.0f,0.3f,2.0f); //boat's size;
Vector3 boatStartpos = new Vector3(-6.0f,0.0f,0.0f);
Vector3 boatEndpos = new Vector3(6.0f,0.0f,0.0f);
// sits on the boat
Vector3 boatsit1 = new Vector3 (-0.25f,3.45f,0.0f); // localposition is care with the scale
Vector3 boatsit2 = new Vector3 (0.25f,3.45f,0.0f);
// others about boats
float boatspeed = 1.0f;
int boatnumber = 0;
int Ifboatsit1have = 0;
int Ifboatsit2have = 0;
//river
//Devils
List<GameObject> devils = new List<GameObject>();
Vector3[] devilStartpos = new Vector3[3]{
new Vector3(-10f,1.15f,-3f),
new Vector3(-10f,1.15f,-2f),
new Vector3(-10f,1.15f,-1f)
};
Vector3[] devilEndpos = new Vector3[3]{
new Vector3(10f,1.15f,-3f),
new Vector3(10f,1.15f,-2f),
new Vector3(10f,1.15f,-1f)
};
Vector3[] devilScale = new Vector3[3]{
new Vector3(),
new Vector3(),
new Vector3()
};
int[] DevilsState = new int[3]{0,0,0}; // 0-startside 1-endside 2-onboat
int[] Devilssite = new int[3]{0,0,0}; //0表示 nosite 1-1site 2-2site
int devilStartside = 3;
int devilEndside = 0;
//Priest
List<GameObject> priests = new List<GameObject>();
Vector3[] priestStartpos = new Vector3[3]{
new Vector3(-10f,1.15f,1f),
new Vector3(-10f,1.15f,2f),
new Vector3(-10f,1.15f,3f)
};
Vector3[] prisetEndpos = new Vector3[3]{
new Vector3(10f,1.15f,1f),
new Vector3(10f,1.15f,2f),
new Vector3(10f,1.15f,3f)
};
Vector3[] priestScale = new Vector3[3]{
new Vector3(),
new Vector3(),
new Vector3()
};
int[] PriestState = new int[3]{0,0,0}; // 0-startside 1-endside 2-onboat
int[] Priestsite = new int[3]{0,0,0};
int priestStartside = 3;
int priestEndside = 0;
// startside
GameObject startside;
Vector3 startsidepos = new Vector3 (-10.0f,0.0f,0.0f);
Vector3 startsidescale = new Vector3(4f,0.3f,8f);
// endside
GameObject endside;
Vector3 endsidepos = new Vector3 (10.0f,0.0f,0.0f);
Vector3 endsidescale = new Vector3(4f,0.3f,8f);
// Use this for initialization
void Start () {
mygame = GameSceneController.GetInstance ();
mygame.setGenGameObject (this);
InsAll ();
}
// Update is called once per frame
void Update () {
float step = boatspeed * Time.deltaTime;
if(state == 2){
Boat.transform.position = Vector3.MoveTowards (Boat.transform.position,boatEndpos,boatspeed);
if(Boat.transform.position == boatEndpos) state = 1;
} else if (state == 3){
Boat.transform.position = Vector3.MoveTowards (Boat.transform.position,boatStartpos,boatspeed);
if(Boat.transform.position == boatStartpos) state = 0;
}
}
// ins all gameobjects
void InsAll(){
//sides
startside = GameObject.CreatePrimitive(PrimitiveType.Cube);
startside.transform.localScale = startsidescale;
startside.transform.position = startsidepos;
startside.GetComponent<Renderer> ().material.color = Color.green;
endside = GameObject.CreatePrimitive (PrimitiveType.Cube);
endside.transform.localScale = endsidescale;
endside.transform.position = endsidepos;
endside.GetComponent<Renderer> ().material.color = Color.green;
//boat
Boat = GameObject.CreatePrimitive(PrimitiveType.Cube);
Boat.transform.position = boatStartpos;
Boat.transform.localScale = boatscale;
Boat.GetComponent<Renderer> ().material.color = Color.grey;
//devils and Priests
for(int i = 0;i<3;i++){
GameObject devil = GameObject.CreatePrimitive (PrimitiveType.Cylinder);
devil.GetComponent<Renderer> ().material.color = Color.red;
devil.transform.position = devilStartpos [i];
devils.Add (devil);
GameObject priest = GameObject.CreatePrimitive (PrimitiveType.Cylinder);
priest.transform.position = priestStartpos [i];
priests.Add (priest);
}
//light !!cool
GameObject light = new GameObject("The light");
Light lightComp = light.AddComponent<Light> ();
lightComp.type = LightType.Directional;
light.transform.position = new Vector3 ();
Quaternion Q;
Q = Quaternion.Euler (20.0f,0.0f,0.0f);
light.transform.rotation = Q;
}
public void DevilGoOnBoat(){ // must write by public ,or the interface can not use it
if (state == 0) { //startside
if (boatnumber != 2) {
for (int i = 0; i < 3; i++) {
if (DevilsState [i] == 0) {
DevilsState [i] = 2;//mean now this devil's state is on boat
devils [i].transform.parent = Boat.transform;
if (Ifboatsit1have == 0 && Ifboatsit2have == 0) {
devils [i].transform.localPosition = boatsit1;
Devilssite [i] = 1;
Ifboatsit1have = 1;
} else if (Ifboatsit1have == 1 && Ifboatsit2have == 0) {
devils [i].transform.localPosition = boatsit2;
Devilssite [i] = 2;
Ifboatsit2have = 1;
} else if (Ifboatsit1have == 0 && Ifboatsit2have == 1) {
devils [i].transform.localPosition = boatsit1;
Devilssite [i] = 1;
Ifboatsit1have = 1;
}
devilStartside--;
boatnumber++;
break;
}
}
}
} else if (state == 1) { // endside
if (boatnumber != 2) {
for (int i = 0; i < 3; i++) {
if (DevilsState [i] == 1) {
DevilsState [i] = 2;//mean now this devil's state is on boat
devils [i].transform.parent = Boat.transform;
if (Ifboatsit1have == 0 && Ifboatsit2have == 0) {
devils [i].transform.localPosition = boatsit1;
Devilssite [i] = 1;
Ifboatsit1have = 1;
} else if (Ifboatsit1have == 1 && Ifboatsit2have == 0) {
devils [i].transform.localPosition = boatsit2;
Devilssite [i] = 2;
Ifboatsit2have = 1;
} else if (Ifboatsit1have == 0 && Ifboatsit2have == 1) {
devils [i].transform.localPosition = boatsit1;
Devilssite [i] = 1;
Ifboatsit1have = 1;
}
devilEndside--;
boatnumber++;
break;
}
}
}
}
}
public void DevilGoOffBoat(){
if (state == 0) { // startside
for (int i = 0; i < 3; i++) {
if(DevilsState[i] == 2){
devils [i].transform.parent = null;
devils[i].transform.position = devilStartpos[i];
DevilsState[i] = 0;
if (Devilssite [i] == 1)
Ifboatsit1have = 0;
else if (Devilssite [i] == 2)
Ifboatsit2have = 0;
Devilssite [i] = 0;
devilStartside++;
boatnumber--;
break;
}
}
} else if (state == 1) { // endside
for (int i = 0; i < 3; i++) {
if(DevilsState[i] == 2){
devils [i].transform.parent = null;
devils[i].transform.position = devilEndpos[i];
DevilsState[i] = 1;
if (Devilssite [i] == 1)
Ifboatsit1have = 0;
else if (Devilssite [i] == 2)
Ifboatsit2have = 0;
Devilssite [i] = 0;
devilEndside++;
boatnumber--;
break;
}
}
}
}
public void PriestGoOnBoat(){
if (state == 0) { //startside
if (boatnumber != 2) {
for (int i = 0; i < 3; i++) {
if (PriestState [i] == 0) {
PriestState [i] = 2;//mean now this devil's state is on boat
priests [i].transform.parent = Boat.transform;
if (Ifboatsit1have == 0 && Ifboatsit2have == 0) {
priests [i].transform.localPosition = boatsit1;
Priestsite [i] = 1;
Ifboatsit1have = 1;
} else if (Ifboatsit1have == 1 && Ifboatsit2have == 0) {
priests [i].transform.localPosition = boatsit2;
Priestsite [i] = 2;
Ifboatsit2have = 1;
} else if (Ifboatsit1have == 0 && Ifboatsit2have == 1) {
priests [i].transform.localPosition = boatsit1;
Priestsite [i] = 1;
Ifboatsit1have = 1;
}
priestStartside--;
boatnumber++;
break;
}
}
}
} else if (state == 1) { // endside
if (boatnumber != 2) {
for (int i = 0; i < 3; i++) {
if (PriestState [i] == 1) {
PriestState [i] = 2;//mean now this devil's state is on boat
priests [i].transform.parent = Boat.transform;
if (Ifboatsit1have == 0 && Ifboatsit2have == 0) {
priests [i].transform.localPosition = boatsit1;
Priestsite [i] = 1;
Ifboatsit1have = 1;
} else if (Ifboatsit1have == 1 && Ifboatsit2have == 0) {
priests [i].transform.localPosition = boatsit2;
Priestsite [i] = 2;
Ifboatsit2have = 1;
} else if (Ifboatsit1have == 0 && Ifboatsit2have == 1) {
priests [i].transform.localPosition = boatsit1;
Priestsite [i] = 1;
Ifboatsit1have = 1;
}
priestEndside--;
boatnumber++;
break;
}
}
}
}
}
public void PriestGoOffBoat(){
if (state == 0) { // startside
for (int i = 0; i < 3; i++) {
if(PriestState[i] == 2){
priests [i].transform.parent = null;
priests[i].transform.position = priestStartpos[i];
PriestState[i] = 0;
if (Priestsite [i] == 1)
Ifboatsit1have = 0;
else if (Priestsite [i] == 2)
Ifboatsit2have = 0;
Priestsite [i] = 0;
priestStartside++;
boatnumber--;
break;
}
}
} else if (state == 1) { // endside
for (int i = 0; i < 3; i++) {
if(PriestState[i] == 2){
priests [i].transform.parent = null;
priests[i].transform.position = prisetEndpos[i];
PriestState[i] = 1;
if (Priestsite [i] == 1)
Ifboatsit1have = 0;
else if (Priestsite [i] == 2)
Ifboatsit2have = 0;
Priestsite [i] = 0;
priestEndside++;
boatnumber--;
break;
}
}
}
}
public void BoatGo(){
if(boatnumber != 0){
check ();
if (state == 0) {
// from startpos to endpos,move
state = 2;
} else if (state == 1){
state = 3;
// form endpos to startpos,move
}
}
}
public void check(){
//lose check
print(devilStartside);
print (devilEndside);
print (priestStartside);
print (priestEndside);
if (state == 0) {
if ((devilStartside > priestStartside && priestStartside!=0) || ((3 - devilStartside) > (3 - priestStartside) && (3-priestStartside)!=0)) {
mygame.wl = WinOrLose.Lose;
return;
}
} else if (state == 1) {
if ((devilEndside > priestEndside && priestEndside!=0 ) || ((3 - devilEndside) > (3 - priestEndside) && (3-priestEndside)!=0)) {
mygame.wl = WinOrLose.Lose;
return;
}
}
//win check
if(devilStartside == 0 && priestStartside == 0) mygame.wl = WinOrLose.Win;
}
}
Actions.cs
using UnityEngine;
using System.Collections;
using Com.Mygame;
public class Actions : MonoBehaviour {
GameSceneController mygame;
ImyAction actions;
float BottonW = Screen.width/4;
float BottonH = Screen.height/16;
float firstBx = Screen.width/4;
float firstBy = Screen.height/8;
float blank = 5;
private string str = "点击重置!";
// Use this for initialization
void Start () {
mygame = GameSceneController.GetInstance();
actions = GameSceneController.GetInstance () as ImyAction;
}
void OnGUI(){
if(GUI.Button(new Rect(firstBx,firstBy,BottonW,BottonH), "魔鬼上船")){
actions.DevilGoOnBoat ();
}
if(GUI.Button(new Rect(firstBx+BottonW+blank,firstBy,BottonW,BottonH), "魔鬼下船")){
actions.DevilGoOffBoat ();
}
if(GUI.Button(new Rect(firstBx,firstBy+BottonH+blank,BottonW,BottonH), "牧师上船")){
actions.PriestGoOnBoat ();
}
if(GUI.Button(new Rect(firstBx+BottonW+blank,firstBy+BottonH+blank,BottonW,BottonH), "牧师下船")){
actions.PriestGoOffBoat ();
}
if(GUI.Button(new Rect(firstBx,firstBy+(BottonH+blank)*2,BottonW*2+blank,BottonH*2), "开船!")){
actions.BoatGo ();
if (mygame.wl == WinOrLose.Gaming) str = "点击重置!";
else if (mygame.wl == WinOrLose.Lose) str = "输了...重来!";
else if (mygame.wl == WinOrLose.Win) str = "赢了!再来!";
}
if(GUI.Button(new Rect(Screen.width-BottonW/2,firstBy,BottonW/2,BottonH),str)){
Application.LoadLevel (Application.loadedLevelName);
mygame.wl = WinOrLose.Gaming;
}
//GUI.Label (new Rect (firstBx,firstBy-BottonH,BottonW*2,BottonH), str);
}
}