1、简答并用程序验证
- 游戏对象运动的本质是什么?
游戏运动本质就是使用矩阵变换(平移、旋转、缩放)改变游戏对象的空间属性。
- 实现物体的抛物线运动。
public class move1 : MonoBehaviour
{
private float g = 0.25f;
private float vx = 2, vy = 1;
void Update()
{
this.transform.position += vx * Vector3.left * Time.deltaTime;
this.transform.position += vy * Vector3.up * Time.deltaTime;
vy -= g * Time.deltaTime;
}
}
2、编程实践
游戏中的事物:
- 河岸
- 河
- 牧师(priest)
- 魔鬼(devil)
- 船
玩家动作表:
游戏状态 | 动作 | 响应 |
已结束 | 左键单击重新开始按钮 | 重新开始游戏 |
进行中 | 左键单击人物 | 在船和其靠近的岸边之间移动(船上最多两人) |
左键单击船 | 如果船上有人物(牧师或魔鬼均可),则船移动到另一端 |
制作游戏预制:
(船、魔鬼、牧师的模型采用开源资源,分别来自:Lowpoly paper boats、Devil、Supercyan Character Pack Free Sample)
初始化代码:
public class Main : MonoBehaviour
{
public static MainController controller;
public static UI ui;
void Start()
{
Object.Instantiate<GameObject>(Resources.Load<GameObject>("Prefabs/Sea"), new Vector3(1.78064036f, 0.428083658f, -2.58708763f), Quaternion.identity);
controller = new MainController();
(gameObject.AddComponent(typeof(UI)) as UI).controller = controller;
}
}
MVC架构:
- Model:Entity、Boat
Entity为人物类,Devil类和Priest类继承人物类
public class Entity
{
private GameObject obj;
public int loc; // 位置,0:右岸,1:左岸,2:船上
public int n;
public Entity(GameObject obj, int n)
{
this.obj = obj;
this.n = n;
}
public void MoveTo(Vector3 vec)
{
obj.transform.position = vec;
}
public void Rotate()
{
if (loc == 0) obj.transform.rotation = Quaternion.Euler(new Vector3(0, -90, 0));
else if (loc == 1) obj.transform.rotation = Quaternion.Euler(new Vector3(0, 90, 0));
}
}
public class Devil : Entity
{
public Devil(GameObject obj, int n) : base(obj, n)
{ }
}
public class Priest : Entity
{
public Priest(GameObject obj, int n) : base(obj, n)
{ }
}
Boat为船类
public class Boat
{
public GameObject obj;
public int loc; // 位置,0:右边,1:左边
public Entity left, right;
public Vector3 leftLoc, rightLoc;
public Boat(GameObject obj, int loc, Vector3 rightLoc, Vector3 leftLoc)
{
this.obj = obj;
this.loc = loc;
this.leftLoc = leftLoc;
this.rightLoc = rightLoc;
}
public void DownEntity(Entity e)
{
if (e == left)
{
left = null;
}
else if (e == right)
{
right = null;
}
}
public bool Empty()
{
return left == null && right == null;
}
public void Move()
{
if (Empty()) return;
if (loc == 0)
{
obj.transform.position = leftLoc;
moveEntity();
loc = 1;
}
else
{
obj.transform.position = rightLoc;
moveEntity();
loc = 0;
}
}
public bool ToLeft(Entity e)
{
if (left == null)
{
left = e;
moveEntity();
return true;
}
return false;
}
public bool ToRight(Entity e)
{
if (right == null)
{
right = e;
moveEntity();
return true;
}
return false;
}
private void moveEntity()
{
if (left != null) left.MoveTo(obj.transform.position + new Vector3(0, 0, 0.5f));
if (right != null) right.MoveTo(obj.transform.position + new Vector3(0, 0, -0.5f));
}
public void Reset()
{
this.right = this.left = null;
this.loc = 0;
obj.transform.position = rightLoc;
}
}
- View:UI、ClickBoat、ClickEntity
用户交互界面,UI用于显示GUI以及侦听用户点击按钮事件,ClickBoat、ClickEntity用于侦听用户点击人物和船的事件
public class UI : MonoBehaviour
{
public MainController controller;
void OnGUI()
{
var style = new GUIStyle("button") { fontSize = 20 };
bool r;
if (controller.status == 1)
{
r = GUI.Button(new Rect(Screen.width / 2 - 130, Screen.height / 2 - 35, 260, 70), "成功! 单击此处重新开始", style);
}
else if (controller.status == 2)
{
r = GUI.Button(new Rect(Screen.width / 2 - 130, Screen.height / 2 - 35, 260, 70), "失败! 单击此处重新开始", style);
}
else return;
if (r) controller.Restart();
}
}
public class ClickEntityAction : MonoBehaviour
{
public MainController controller;
public Entity entity;
void OnMouseDown()
{
controller.MoveEntity(entity);
}
}
public class ClickBoatAction : MonoBehaviour
{
public MainController controller;
void OnMouseDown()
{
controller.MoveBoat();
}
}
- Controller:MainController
控制器,接受用户交互界面的输入并调用模型和视图去完成用户的需求
public class MainController
{
private const int NUM = 3;
public int status = 0; // 0:正常,1:成功,2:失败
private Devil[] devils;
private Priest[] priests;
private Vector3[] leftVector, rightVector;
private Vector3 leftBoat, rightBoat;
private int priestNum, devilNum;
private Boat boat;
public MainController()
{
devils = new Devil[NUM];
priests = new Priest[NUM];
leftVector = new Vector3[2 * NUM];
rightVector = new Vector3[2 * NUM];
rightBoat = new Vector3(3.7f, 0.5f, 0);
leftBoat = new Vector3(-3.6f, 0.5f, 0);
priestNum = 3;
devilNum = 3;
boat = new Boat(Object.Instantiate(
Resources.Load<GameObject>("Prefabs/Boat"),
rightBoat, Quaternion.identity) as GameObject, 0, rightBoat, leftBoat);
ClickBoatAction clickBoat = boat.obj.AddComponent(typeof(ClickBoatAction)) as ClickBoatAction;
clickBoat.controller = this;
for (int i = 0; i < 2 * NUM; i++)
{
int x = 7 + i;
rightVector[i] = new Vector3(x, 2, 0);
leftVector[i] = new Vector3(-x, 2, 0);
}
for (int i = 0; i < NUM; i++)
{
GameObject obj = Object.Instantiate(
Resources.Load<GameObject>("Prefabs/Priest"),
rightVector[i], Quaternion.Euler(0, -90, 0)) as GameObject;
ClickEntityAction click = obj.AddComponent(typeof(ClickEntityAction)) as ClickEntityAction;
priests[i] = new Priest(obj, i);
click.controller = this;
click.entity = priests[i];
obj = Object.Instantiate(
Resources.Load<GameObject>("Prefabs/Devil"),
rightVector[3 + i], Quaternion.Euler(0, -90, 0)) as GameObject;
click = obj.AddComponent(typeof(ClickEntityAction)) as ClickEntityAction;
devils[i] = new Devil(obj, 3 + i);
click.controller = this;
click.entity = devils[i];
}
}
public void Restart()
{
priestNum = 3;
devilNum = 3;
for (int i = 0; i < NUM; i++)
{
priests[i].loc = 0;
devils[i].loc = 0;
priests[i].MoveTo(rightVector[i]);
devils[i].MoveTo(rightVector[3 + i]);
priests[i].Rotate();
devils[i].Rotate();
}
this.boat.Reset();
status = 0;
}
private void moveToBoat(Entity e)
{
if(boat.ToLeft(e) || boat.ToRight(e))
{
e.loc = 2;
}
}
private void moveFromBoat(Entity e)
{
int loc = boat.loc;
Vector3[] vec = (loc == 0 ? rightVector : leftVector);
e.MoveTo(vec[e.n]);
e.loc = loc;
e.Rotate();
boat.DownEntity(e);
int leftPriestNum = NUM - priestNum, leftDevilNum = NUM - devilNum;
if (leftPriestNum == NUM && leftDevilNum == NUM && boat.Empty())
{
status = 1;
}
}
public void MoveBoat()
{
if (status != 0) return;
boat.Move();
int rightDeta = (boat.loc == 0 ? 1 : -1);
if (boat.left as Priest != null)
{
priestNum += rightDeta;
}
if (boat.right as Priest != null)
{
priestNum += rightDeta;
}
if (boat.left as Devil != null)
{
devilNum += rightDeta;
}
if (boat.right as Devil != null)
{
devilNum += rightDeta;
}
int leftPriestNum = NUM - priestNum, leftDevilNum = NUM - devilNum;
if ((devilNum > priestNum || leftDevilNum > leftPriestNum) && priestNum != NUM && leftPriestNum != NUM)
{
status = 2;
}
}
public void MoveEntity(Entity e)
{
if (status != 0) return;
if (e.loc == boat.loc)
{
moveToBoat(e);
}
else if (e.loc == 2)
{
moveFromBoat(e);
}
}
}
演示:
开始游戏
左键单击操作人物和船
游戏失败
游戏成功
文章来源地址https://uudwc.com/A/P3Xo文章来源:https://uudwc.com/A/P3Xo