3d遊戲第三次作業
3d遊戲第三次作業
1、簡答並用程式驗證【建議做】
遊戲物件運動的本質是什麼?
是遊戲物體隨著時間的變化而引起空間的變化。具體來說就是當重新整理幀的時候,遊戲物體transorm引數變化,具體包括position和rotation的變化。
請用三種方法以上方法,實現物體的拋物線運動。(如,修改Transform屬性,使用向量Vector3的方法…)
拋物線運動是水平勻速,豎直方向加速。第一種方法可以直接在update修改每一幀的時候直接更新transform的屬性:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Move : MonoBehaviour
{
private float speedx = 5;
private float speedy = 0;
private float g = 10;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
transform.position += Vector3.right * speedx * Time.deltaTime;
transform.position += Vector3.down * speedy * Time.deltaTime;
speedy += g * Time.deltaTime;
}
}
也可以使用Vector3來間接修改(在上面程式碼基礎上修改如下程式碼段):
void Update()
{
speedy += g * Time.deltaTime;
Vector3 temp = new Vector3(speedx * Time.deltaTime, -speedy * Time.deltaTime, 0);
transform.position += temp;
}
還可以修改物體的重力屬性來實現:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Move : MonoBehaviour
{
void Start()
{
gameObject.AddComponent<Rigidbody>();
gameObject.GetComponent<Rigidbody>().velocity = new Vector3(1, 0, 0);
}
void Update() { }
}
寫一個程式,實現一個完整的太陽系, 其他星球圍繞太陽的轉速必須不一樣,且不在一個法平面上。
建立太陽系:
指令碼:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class solarSystem : MonoBehaviour
{
public Transform sun;
public Transform mercury;
public Transform venus;
public Transform earth;
public Transform mars;
public Transform jupiter;
public Transform saturn;
public Transform uranus;
public Transform neptune;
void Start() { }
void Update()
{
sun.Rotate(Vector3.up, Time.deltaTime * 10);
mercury.RotateAround(this.transform.position, new Vector3(1, 10, 0), 50 * Time.deltaTime);
mercury.Rotate(Vector3.up, Time.deltaTime * 100);
venus.RotateAround(this.transform.position, new Vector3(1, 13, 0), 40 * Time.deltaTime);
venus.Rotate(Vector3.up, Time.deltaTime * 100);
earth.RotateAround(this.transform.position, new Vector3(1, 15, 0), 35 * Time.deltaTime);
earth.Rotate(Vector3.up, Time.deltaTime * 100);
mars.RotateAround(this.transform.position, new Vector3(2, 10, 0), 30 * Time.deltaTime);
mars.Rotate(Vector3.up, Time.deltaTime * 100);
jupiter.RotateAround(this.transform.position, new Vector3(2, 13, 0), 20 * Time.deltaTime);
jupiter.Rotate(Vector3.up, Time.deltaTime * 100);
saturn.RotateAround(this.transform.position, new Vector3(2, 15, 0), 15 * Time.deltaTime);
saturn.Rotate(Vector3.up, Time.deltaTime * 100);
uranus.RotateAround(this.transform.position, new Vector3(3, 10, 0), 10 * Time.deltaTime);
uranus.Rotate(Vector3.up, Time.deltaTime * 100);
neptune.RotateAround(this.transform.position, new Vector3(3, 15, 0), 9 * Time.deltaTime);
neptune.Rotate(Vector3.up, Time.deltaTime * 100);
}
}
2、程式設計實踐
閱讀以下游戲指令碼
Priests and Devils
Priests
and Devils is a puzzle game in which you will help the Priests and Devils to cross the river within the time limit. There are 3 priests and 3 devils at one side of the river. They all want to get to the other side of this river, but there is only one boat and this boat can only carry two persons each time. And there must be one person steering the boat from one side to the other side. In the flash game, you can click on them to move them and click the go button to move the boat to the other direction. If the priests are out numbered by the devils on either side of the river, they get killed and the game is over. You can try it in many > ways. Keep all priests alive! Good luck!
程式需要滿足的要求:
- play the game ( http://www.flash-game.net/game/2535/priests-and-devils.html )
- 列出遊戲中提及的事物(Objects)
- 用表格列出玩家動作表(規則表),注意,動作越少越好
- 請將遊戲中物件做成預製
- 在場景控制器 LoadResources 方法中載入並初始化 長方形、正方形、球 及其色彩代表遊戲中的物件。
- 使用 C# 集合型別 有效組織物件
- 整個遊戲僅 主攝像機 和 一個 Empty 物件, 其他物件必須程式碼動態生成!!! 。 整個遊戲不許出現 Find 遊戲物件, SendMessage 這類突破程式結構的 通訊耦合 語句。 違背本條準則,不給分
- 請使用課件架構圖程式設計,不接受非 MVC 結構程式
- 注意細節,例如:船未靠岸,牧師與魔鬼上下船運動中,均不能接受使用者事件!
遊戲中的物件:牧師、魔鬼、小船、河岸、河水
玩家動作表(規則表)
動作 | 條件 | 結果 |
---|---|---|
點選岸上的牧師或者魔鬼 | 船未滿並且在岸邊 | 點選的牧師或者魔鬼上船 |
點選小船 | 船上有牧師或者魔鬼 | 移動到另一岸 |
點選船上的牧師或魔鬼 | 船在岸邊 | 牧師或者魔鬼上岸 |
建立預製,將牧師做成淺黃方塊,惡魔做成深紅方塊
見上圖,資源被整合成材料、預製和指令碼三個資料夾。
- 執行前的遊戲物件
- 執行後的遊戲物件
使用MVC架構: - 模型(Model):資料物件及關係
所有的GameObject - 控制器(Controller):接受使用者事件,控制模型的變化
Director類,FirstController類,Move類,RolesController類,CoastController類,BoatController類 - 介面(View):顯示模型,將人機互動事件交給控制器處理
UserGUI和ClickGUI指令碼
主要的一些類的解釋:
Director
獲取當前遊戲的場景
控制場景執行、切換、入棧與出棧
暫停、恢復、退出
管理遊戲全域性狀態
設定遊戲的配置
設定遊戲全域性檢視
public class Director : System.Object {
private static Director _instance;
public SceneController currentSceneController { get; set; }
public static Director getInstance() {
if (_instance == null) {
_instance = new Director ();
}
return _instance;
}
}
可以看到無論何時呼叫getInstance()都會得到同一個例項,這保證了導演類的唯一性,也能保證導演類控制場記的作用。
四個控制類
Moveable
控制遊戲物體的移動
RolesController
控制牧師或者魔鬼
CoastController
控制河岸
BoatController
控制小船
public class Moveable: MonoBehaviour {
readonly float move_speed = 30;
int moving_status; // 0->not moving, 1->moving end middle, 2->moving end dest
Vector3 dest;
Vector3 middle;
void Update() {
if (moving_status == 1) {
transform.position = Vector3.MoveTowards (transform.position, middle, move_speed * Time.deltaTime);
if (transform.position == middle) {
moving_status = 2;
}
} else if (moving_status == 2) {
transform.position = Vector3.MoveTowards (transform.position, dest, move_speed * Time.deltaTime);
if (transform.position == dest) {
moving_status = 0;
}
}
}
public void setDestination(Vector3 _dest) {
dest = _dest;
middle = _dest;
if (_dest.y == transform.position.y)
moving_status = 2;
else if (_dest.y < transform.position.y)
middle.y = transform.position.y;
else
middle.x = transform.position.x;
moving_status = 1;
}
public void reset() {
moving_status = 0;
}
}
public class RolesController {
readonly GameObject character;
readonly Moveable moveableScript;
readonly ClickGUI clickGUI;
readonly int RoleType; // 0->priest, 1->devil
// change frequently
bool _isOnBoat;
CoastController coastController;
public RolesController(string which_character) {
if (which_character == "priest") {
character = Object.Instantiate (Resources.Load ("Perfabs/Priest", typeof(GameObject)), Vector3.zero, Quaternion.identity, null) as GameObject;
RoleType = 0;
} else {
character = Object.Instantiate (Resources.Load ("Perfabs/Devil", typeof(GameObject)), Vector3.zero, Quaternion.identity, null) as GameObject;
RoleType = 1;
}
moveableScript = character.AddComponent (typeof(Moveable)) as Moveable;
clickGUI = character.AddComponent (typeof(ClickGUI)) as ClickGUI;
clickGUI.setController (this);
}
public void setName(string name) {
character.name = name;
}
public void setPosition(Vector3 pos) {
character.transform.position = pos;
}
public void moveToPosition(Vector3 destination) {
moveableScript.setDestination(destination);
}
public int getType() { // 0->priest, 1->devil
return RoleType;
}
public string getName() {
return character.name;
}
public void getOnBoat(BoatController boatCtrl) {
coastController = null;
character.transform.parent = boatCtrl.getGameobj().transform;
_isOnBoat = true;
}
public void getOnCoast(CoastController coastCtrl) {
coastController = coastCtrl;
character.transform.parent = null;
_isOnBoat = false;
}
public bool isOnBoat() {
return _isOnBoat;
}
public CoastController getCoastController() {
return coastController;
}
public void reset() {
moveableScript.reset ();
coastController = (Director.getInstance ().currentSceneController as FirstController).bankbegin;
getOnCoast (coastController);
setPosition (coastController.getEmptyPosition ());
coastController.getOnCoast (this);
}
}
public class CoastController {
readonly GameObject coast;
readonly Vector3 from_pos = new Vector3(9,1,0);
readonly Vector3 to_pos = new Vector3(-9,1,0);
readonly Vector3[] positions;
readonly int postion; // end->-1, begin->1
// change frequently
RolesController[] passengerPlaner;
public CoastController(string _postion) {
positions = new Vector3[] {
new Vector3(6.5F,2.25F,0),
new Vector3(7.5F,2.25F,0),
new Vector3(8.5F,2.25F,0),
new Vector3(9.5F,2.25F,0),
new Vector3(10.5F,2.25F,0),
new Vector3(11.5F,2.25F,0)};
passengerPlaner = new RolesController[6];
if (_postion == "begin") {
coast = Object.Instantiate (Resources.Load ("Perfabs/Bank", typeof(GameObject)), from_pos, Quaternion.identity, null) as GameObject;
coast.name = "begin";
postion = 1;
} else {
coast = Object.Instantiate (Resources.Load ("Perfabs/Bank", typeof(GameObject)), to_pos, Quaternion.identity, null) as GameObject;
coast.name = "end";
postion = -1;
}
}
public int getEmptyIndex() {
for (int i = 0; i < passengerPlaner.Length; i++)
if (passengerPlaner [i] == null)
return i;
return -1;
}
public Vector3 getEmptyPosition() {
Vector3 pos = positions [getEmptyIndex ()];
pos.x *= postion;
return pos;
}
public void getOnCoast(RolesController characterCtrl) {
int index = getEmptyIndex ();
passengerPlaner [index] = characterCtrl;
}
public RolesController getOffCoast(string passenger_name) { // 0->priest, 1->devil
for (int i = 0; i < passengerPlaner.Length; i++)
if (passengerPlaner [i] != null && passengerPlaner [i].getName () == passenger_name) {
RolesController charactorCtrl = passengerPlaner [i];
passengerPlaner [i] = null;
return charactorCtrl;
}
Debug.Log ("cant find passenger on coast: " + passenger_name);
return null;
}
public int where() {
return postion;
}
public int[] getRoleNum() {
int[] count = {0, 0};
for (int i = 0; i < passengerPlaner.Length; i++) {
if (passengerPlaner [i] == null)
continue;
if (passengerPlaner [i].getType () == 0) // 0->priest, 1->devil
count[0]++;
else
count[1]++;
}
return count;
}
public void reset() {
passengerPlaner = new RolesController[6];
}
}
public class BoatController {
readonly GameObject boat;
readonly Moveable moveableScript;
readonly Vector3 fromPosition = new Vector3 (5, 1, 0);
readonly Vector3 toPosition = new Vector3 (-5, 1, 0);
readonly Vector3[] beginPostion;
readonly Vector3[] endPostion;
// change frequently
int postion; // end->-1; begin->1
RolesController[] passenger = new RolesController[2];
public BoatController() {
postion = 1;
beginPostion = new Vector3[] { new Vector3 (4.5F, 1.5F, 0), new Vector3 (5.5F, 1.5F, 0) };
endPostion = new Vector3[] { new Vector3 (-5.5F, 1.5F, 0), new Vector3 (-4.5F, 1.5F, 0) };
boat = Object.Instantiate (Resources.Load ("Perfabs/Boat", typeof(GameObject)), fromPosition, Quaternion.identity, null) as GameObject;
boat.name = "boat";
moveableScript = boat.AddComponent (typeof(Moveable)) as Moveable;
boat.AddComponent (typeof(ClickGUI));
}
public void Move() {
if (postion == -1) {
moveableScript.setDestination(fromPosition);
postion = 1;
} else {
moveableScript.setDestination(toPosition);
postion = -1;
}
}
public int getEmptyIndex() {
for (int i = 0; i < passenger.Length; i++)
if (passenger [i] == null)
return i;
return -1;
}
public bool isEmpty() {
for (int i = 0; i < passenger.Length; i++)
if (passenger [i] != null)
return false;
return true;
}
public Vector3 getEmptyPosition() {
Vector3 pos;
int emptyIndex = getEmptyIndex ();
if (postion == -1)
pos = endPostion[emptyIndex];
else
pos = beginPostion[emptyIndex];
return pos;
}
public void GetOnBoat(RolesController characterCtrl) {
int index = getEmptyIndex ();
passenger [index] = characterCtrl;
}
public RolesController GetOffBoat(string passenger_name) {
for (int i = 0; i < passenger.Length; i++)
if (passenger [i] != null && passenger [i].getName () == passenger_name) {
RolesController charactorCtrl = passenger [i];
passenger [i] = null;
return charactorCtrl;
}
Debug.Log ("Cant find passenger in boat: " + passenger_name);
return null;
}
public GameObject getGameobj() {
return boat;
}
public int where() { // end->-1; begin->1
return postion;
}
public int[] getRoleNum() {
int[] count = {0, 0};
for (int i = 0; i < passenger.Length; i++) {
if (passenger [i] == null)
continue;
if (passenger [i].getType () == 0) // 0->priest, 1->devil
count[0]++;
else
count[1]++;
}
return count;
}
public void reset() {
moveableScript.reset ();
if (postion == -1)
Move ();
passenger = new RolesController[2];
}
}
}
ClickGUI
相應玩家的點選,將該動作傳給相應類實現操作
public class ClickGUI : MonoBehaviour {
UserAction action;
RolesController characterController;
public void setController(RolesController rolectrl) {
characterController = rolectrl;
}
void Start() {
action = Director.getInstance ().currentSceneController as UserAction;
}
void OnMouseDown() {
if (gameObject.name == "boat") {
action.moveBoat ();
} else {
action.characterIsClicked (characterController);
}
}
}
執行遊戲的方法1:
下載asset替換自己新建的專案,並將兩個GUI指令碼掛載到空物件中,將firstconctroller指令碼掛載到攝影機上。
執行遊戲的方法2:
直接開啟asset中的priestAndDevil.unity。
3、思考題【選做】
使用向量與變換,實現並擴充套件 Tranform 提供的方法,如 Rotate、RotateAround 等
對於i、j、k本身的幾何意義可以理解為一種旋轉,其中i旋轉代表X軸與Y軸相交平面中X軸正向向Y軸正向的旋轉,j旋轉代表Z軸與X軸相交平面中Z軸正向向X軸正向的旋轉,k旋轉代表Y軸與Z軸相交平面中Y軸正向向Z軸正向的旋轉,見下圖:
靜態方法 Quaternion.Euler(x,y,z),直觀上按 z、x、y 軸旋轉的一個序列。因為旋轉矩陣連乘得到複合旋轉,故 q = qy * qx * qz
Rotation
public void Rotate(Transform trans,float anglex, float angley, float anglez){
Quaternion p1 = Quaternion.AngleAxis(anglez, Vector3.forward);
Quaternion p2 = Quaternion.AngleAxis(anglex, Vector3.right);
Quaternion p3 = Quaternion.AngleAxis(angley, Vector3.up);
trans.rotation *= p3 * p2 * p1;
}
RotateAround
圍繞通過世界座標中點的軸旋轉變換角度
public void RotateAround(Transform trans,Vector3 point, Vector3 axis, float angle){
Quaternion p = Quaternion.AngleAxis(angle,axis);
Vector3 distance = myTransform.position - point;
trans.position = p * myTransform.position;
trans.rotation *= p;
}
相關文章
- 3D遊戲程式設計作業93D遊戲程式設計
- 3D遊戲-作業三-空間與運動3D遊戲
- 第三次作業
- 製作3D小汽車遊戲(下)3D遊戲
- 製作3D小汽車遊戲(上)3D遊戲
- 3D遊戲角色模型建模| ZBrush製作3D獸人3D遊戲模型ZBrush
- 第三次部落格作業
- OOP第三次Blog作業OOP
- java第三次作業(1)Java
- 3D遊戲程式設計作業第九章 UI系統3D遊戲程式設計UI
- OPP第三次部落格作業
- OO第三次部落格作業
- OOP第三次部落格作業OOP
- 軟體工程第三次作業軟體工程
- 軟體基礎第三次作業
- 資料採集第三次作業
- 23201829OO第三次blog作業
- 使用THREE.js製作一款3D遊戲JS3D遊戲
- 徐冰岩 徐業欽 的第三次作業
- 陳志俠 李想 第三次作業
- 趙尚好 李柯銳第三次作業
- 王俊嘉 陳丹霞 第三次作業
- 張丁霽 劉崢 第三次作業
- 徐歡 朱秋逸 第三次作業
- outside_的第三次部落格作業IDE
- 資料採集實踐第三次作業
- 裘立帆 曾亨瑾第三次作業
- 林宏蕊 黃欣雨 第三次作業
- 陳柯烽 龍祖維 第三次作業
- 潘嘉敏 侯錦秀 第三次作業
- 王文彧 陳宇聰 第三次作業
- 幹盛輝 郝宇航的第三次作業
- 資料採集第三次實踐作業
- 3D遊戲:五、與遊戲世界互動3D遊戲
- 軟工實踐第三次作業(結對第二次作業)軟工
- 高階語言程式設計第三次作業程式設計
- 人工智慧教育技術學第三次作業人工智慧
- 作為遊戲特效師、遊戲從業者以及生活裡的老威遊戲特效