3D游戏编程与设计第二次作业

阅读: 评论:0

3D游戏编程与设计第二次作业

3D游戏编程与设计第二次作业

作业内容

简答题

1.游戏对象运动的本质是什么?

游戏对象运动的本质是游戏对象每一帧在空间上的变化,例如位置发生变化(Position),或者发生了旋转(Rotation)。

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

平抛运动:水平方向速度保持不变,竖直方向速度公式为vt = gt

  1. 新建一个Vector3变量,为change,水平方向上的变化每一帧都是固定的,水平速度 * 时间间隔,竖直方向上为竖直速度 * 时间间隔,z方向为0。
     using System.Collections;using System.Collections.Generic;using UnityEngine;public class HPM2 : MonoBehaviour {// Use this for initializationvoid Start () {}private float verticalSpeed = 0.00f;public float horizontalSpeed = 5.00f;const float g = 0.098f;// Update is called once per framevoid Update () {Vector3 change = new Vector3 (Time.deltaTime * horizontalSpeed, -Time.deltaTime * verticalSpeed, 0.0f);ansform.position += change;verticalSpeed += g;}}
    
  2. 与1类似,但是不调用position,而是调用Translate函数
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;public class HPM3 : MonoBehaviour {// Use this for initializationvoid Start () {}private float verticalSpeed = 0.00f;public float horizontalSpeed = 5.00f;const float g = 0.098f;// Update is called once per framevoid Update () {Vector3 change = new Vector3 (Time.deltaTime * horizontalSpeed, -Time.deltaTime * verticalSpeed, 0.0f);ansform.Translate (change);verticalSpeed += g;}
    }
    
  3. 直接运用position的加减来完成
     using System.Collections;using System.Collections.Generic;using UnityEngine;public class HPM1 : MonoBehaviour {// Use this for initializationvoid Start () {}private float verticalSpeed = 0.00f;public float horizontalSpeed = 5.00f;const float g = 0.098f;// Update is called once per framevoid Update () {ansform.position += Vector3.right * Time.deltaTime * ansform.position += Vector3.down * Time.deltaTime * verticalSpeed;verticalSpeed += g;Debug.Log (verticalSpeed);}}

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

  • 下载所需要的贴图资源,添加到Assets中

    太阳系贴图下载链接

  • 创建游戏对象

    这里这里建议使用2D操作,比较好调整星球间的位置关系,调整好后,只需要将Assets中对应的图片拖到对应星球上即可。

  • 建立游戏对象关系树

    这里说明一下,EarthClone是一个空对象,和Earth一样,有公转行为,但是没有自转行为。Moon做为EarthClone的子对象,是因为如果作为Earth的子对象,将会影响Moon的公转行为:此时Moon的旋转位置的移动是自身的公转叠加Earth的自转。Sun与SunClone是同理的。

  • 编写代码
    • 作用在SunClone上的代码

      using System.Collections;
      using System.Collections.Generic;
      using UnityEngine;public class SolarSystem : MonoBehaviour {// Use this for initializationvoid Start () {}// Update is called once per framevoid Update () {//Rotationfloat rotationStandarTime = 20.0f;GameObject.Find ("Mercury").transform.Rotate (Vector3.down * Time.deltaTime * (rotationStandarTime / 58.65f));GameObject.Find ("Venus").transform.Rotate (Vector3.up * Time.deltaTime * (rotationStandarTime / 224.7f));GameObject.Find ("Earth").transform.Rotate (Vector3.down * Time.deltaTime * (rotationStandarTime / 1.0f));GameObject.Find ("Moon").transform.Rotate (Vector3.down * Time.deltaTime * (rotationStandarTime / 27.32f));GameObject.Find ("Mars").transform.Rotate (Vector3.down * Time.deltaTime * (rotationStandarTime / 1.0f));GameObject.Find ("Jupiter").transform.Rotate (Vector3.down * Time.deltaTime * (rotationStandarTime / 0.24f));GameObject.Find ("Saturn").transform.Rotate (Vector3.down * Time.deltaTime * (rotationStandarTime / 0.24f));GameObject.Find ("Uranus").transform.Rotate (Vector3.up * Time.deltaTime * (rotationStandarTime / 0.71f));GameObject.Find ("Neptune").transform.Rotate (Vector3.down * Time.deltaTime * (rotationStandarTime / 0.67f));//Orbital revolutionTransform center = ansform;float reStandarTime = 360.0f;GameObject.Find ("Mercury").transform.RotateAround(center.position, new Vector3(0.1f, -1, 0), reStandarTime / 88.0f);GameObject.Find ("Venus").transform.RotateAround(center.position, new Vector3(0.2f, -1, 0), reStandarTime / 224.7f);GameObject.Find ("Earth").transform.RotateAround(center.position, new Vector3(0.3f, -1, 0), reStandarTime / 365.25f);GameObject.Find ("EarthClone").transform.RotateAround(center.position, new Vector3(0.3f, -1, 0), reStandarTime / 365.25f);GameObject.Find ("Moon").transform.RotateAround(GameObject.Find("EarthClone").transform.position, new Vector3(0, -1, 0), reStandarTime / 27.32f);GameObject.Find ("Mars").transform.RotateAround(center.position, new Vector3(0.5f, -1, 0), reStandarTime / 686.98f);GameObject.Find ("Jupiter").transform.RotateAround(center.position, new Vector3(0.6f, -1, 0), reStandarTime / 4328.9f);GameObject.Find ("Saturn").transform.RotateAround(center.position, new Vector3(0.7f, -1, 0), reStandarTime / 10767.5f);GameObject.Find ("Uranus").transform.RotateAround(center.position, new Vector3(0.8f, -1, 0), reStandarTime / 30776.8f);GameObject.Find ("Neptune").transform.RotateAround(center.position, new Vector3(0.9f, -1, 0), reStandarTime / 60152.0f);}
      }
      

      这里说明一下:GameObject.Find ("name")函数是找到拥有“name”的名字对象;Rotate函数是用来实现物体自转的函数,参数里面的Vector3.down 表示逆时针方向进行旋转;在RotateAround函数里,第一个参数是中心点所在的位置,第二个参数是法平面,第三个参数是转速。

    • 作用在Sun上的代码

      using System.Collections;
      using System.Collections.Generic;
      using UnityEngine;public class Sun : MonoBehaviour {// Use this for initializationvoid Start () {}// Update is called once per framevoid Update () {float rotationStandarTime = 20.ansform.Rotate (Vector3.down * Time.deltaTime * (rotationStandarTime / 25.05f));}
      }
      
  • 运行效果

游戏编程

  • 阅读以下游戏脚本

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!

  • 程序需要满足的要求:
  1. play the game (.html )
  2. 列出游戏中提及的事物(Objects)
  3. 用表格列出玩家动作表(规则表),注意,动作越少越好
  4. 请将游戏中对象做成预制
  5. 在 GenGameObjects 中创建 长方形、正方形、球 及其色彩代表游戏中的对象。
  6. 使用 C# 集合类型 有效组织对象
  7. 整个游戏仅 主摄像机 和 一个 Empty 对象,其他对象必须代码动态生成!!! 。 整个游戏不许出现 Find 游戏对象, SendMessage 这类突破程序结构的 通讯耦合 语句。 违背本条准则,不给分
  8. 请使用课件架构图编程,不接受非 MVC 结构程序
  9. 注意细节,例如:船未靠岸,牧师与魔鬼上下船运动中,均不能接受用户事件!
  • 游戏中提及的事物
    Priest、Devil、Boat、Two sides of the river(start、finish)、Go button
  • 用表格列出玩家动作表(规则表)
动作发生条件
点击GO按钮船上有人且船在某一岸边
牧师上船牧师与船在同一岸,且船有空位
恶魔上船恶魔与船在同一岸,且船有空位
牧师下船船靠岸、有牧师在船上
恶魔下船船靠岸、有恶魔在船上
  • 将游戏中对象做成预制

  • 编写代码

    代码由三个部分组成,Model.cs、View.cs、Controller.cs。其中Model.cs处理数据对象及关系;View.cs负责显示模型,提供用户交互的界面,将人机交互事件交给控制器处理等;Controller.cs负责接受用户事件,控制模型的变化,判断游戏胜负等等。

    Model.cs
     using System.Collections;using System.Collections.Generic;using UnityEngine;using game;public class Model : MonoBehaviour {//存放左边的牧师Stack<GameObject> leftPriests = new Stack<GameObject>();//存放右边的牧师Stack<GameObject> rightPriests = new Stack<GameObject>();//存放左边的恶魔Stack<GameObject> leftDevils = new Stack<GameObject>();//存放右边的恶魔Stack<GameObject> rightDevils = new Stack<GameObject>();//船上的两个位置GameObject[] ship = new GameObject[2];GameObject ship_obj;public float speed = 5.0f;SSDirector s1;Vector3 shipLeftPostion = new Vector3(-3f, 0.5f, 0.0f);Vector3 shipRightPostion = new Vector3(3f, 0.5f, 0);Vector3 sideLeftPostion = new Vector3(-14f, -5f, 0);Vector3 sideRightPostion = new Vector3(14f, -5f, 0);Vector3 priestsLeftPostion = new Vector3(-19f, 2.2f, 0);Vector3 priestsRightPostion = new Vector3(16f, 2.2f, 0);Vector3 DevilsLeftPostion = new Vector3(-12f, 2.0f, 0);Vector3 DevilsRightPostion = new Vector3(7f, 2.0f, 0);Vector3 waterPostion = new Vector3(0f, -5f, 0);void load(){//加载两岸Instantiate(Resources.Load("Side"), sideLeftPostion, Quaternion.identity);Instantiate(Resources.Load("Side"), sideRightPostion, Quaternion.identity);//加载水Instantiate(Resources.Load("Water"), waterPostion, Quaternion.identity);//加载船ship_obj = Instantiate(Resources.Load("Ship"), shipLeftPostion, Quaternion.identity) as GameObject;//加载牧师和恶魔for (int i = 0; i < 3; i++) {leftPriests.Push (Instantiate (Resources.Load ("Priest")) as GameObject);leftDevils.Push (Instantiate (Resources.Load ("Devil")) as GameObject);}}//用于设置牧师和恶魔的位置void setTargetPosition(Stack<GameObject> target, Vector3 position){GameObject[] temp = target.ToArray ();for (int i = 0; i < target.Count; i++) {temp [i].transform.position = position + new Vector3 (2.0f * i, 0f, 0f);}}//判断船上有没有空位以及空位的位置int shipEmpty(){int empty = 0;for (int i = 0; i < 2; i++) {if (ship [i] == null) {empty++;}}return empty;}//上船操作void getOnShip(GameObject obj){ansform.parent = ansform;if (shipEmpty () != 0) {if (ship [0] == null) {ship [0] = obj;if (obj.name == "Priest(Clone)") {ansform.localPosition = new Vector3 (-0.3f, 2.9f, 0);} else {ansform.localPosition = new Vector3 (-0.4f, 2.5f, 0);}} else {ship [1] = obj;if (obj.name == "Priest(Clone)") {ansform.localPosition = new Vector3 (0.3f, 2.9f, 0);} else {ansform.localPosition = new Vector3 (0.4f, 2.5f, 0);}}}}//船移动public void shipMove(){//有人在船上才能移动if (shipEmpty () != 2) {if (s1.state == State.Left) {s1.state = State.LTR;}else if (s1.state == State.Right) {s1.state = State.RTL;}}}//下船public void offShip(int side){if (ship [side] != null) {ship [side].transform.parent = null;if (s1.state == State.Left) {if (ship [side].name == "Priest(Clone)") {leftPriests.Push (ship [side]);}else{leftDevils.Push (ship [side]);}}else if(s1.state == State.Right){if (ship [side].name == "Priest(Clone)") {rightPriests.Push (ship [side]);}else{rightDevils.Push (ship [side]);}}ship [side] = null;}}public void restart(){s1.state = State.Left;ansform.position = shipLeftPostion;int rightNumPriest = rightPriests.Count;int rightNumDevil = rightDevils.Count;for (int i = 0; i < rightNumPriest; i++) {leftPriests.Push (rightPriests.Pop ());}for (int i = 0; i < rightNumDevil; i++) {leftDevils.Push (rightDevils.Pop ());}offShip (0);offShip (1);}//检查游戏是否结束void check(){//全都达到右岸if (rightPriests.Count == 3 && rightDevils.Count == 3) {s1.state = State.Win;return;}//某一边恶魔多余牧师int numShipPriest = 0;int numLeftPriest = 0;int numRightPriest = 0;int numShipDevil = 0;int numLeftDevil = 0;int numRightDevil = 0;for (int i = 0; i < 2; i++) {if (ship [i] != null && ship [i].name == "Priest(Clone)") {numShipPriest++;}else if (ship [i] != null && ship [i].name == "Devil(Clone)") {numShipDevil++;}}if (s1.state == State.Left) {numLeftPriest = leftPriests.Count + numShipPriest;numRightPriest = rightPriests.Count;numLeftDevil = leftDevils.Count + numShipDevil;numRightDevil = rightDevils.Count;}else if(s1.state == State.Right) {numLeftPriest = leftPriests.Count;numRightPriest = rightPriests.Count + numShipPriest;numLeftDevil = leftDevils.Count;numRightDevil = rightDevils.Count + numShipDevil;}if ((numLeftPriest != 0 && numLeftPriest < numLeftDevil) || (numRightPriest != 0 && numRightPriest < numRightDevil)) {s1.state = State.Lose;}}//从岸到船public void priestLeftOnBoat (){if (leftPriests.Count != 0 && shipEmpty() != 0 && s1.state == State.Left) {getOnShip (leftPriests.Pop ());}}public void priestRightOnBoat (){if (rightPriests.Count != 0 && shipEmpty() != 0 && s1.state == State.Right) {getOnShip (rightPriests.Pop ());}}public void devilLeftOnBoat (){if (leftDevils.Count != 0 && shipEmpty() != 0 && s1.state == State.Left) {getOnShip (leftDevils.Pop ());}}public void devilRightOnBoat (){if (rightDevils.Count != 0 && shipEmpty() != 0 && s1.state == State.Right) {getOnShip (rightDevils.Pop ());}}// Use this for initializationvoid Start () {s1 = Instance ();s1.setModel (this);load ();}// Update is called once per framevoid Update () {setTargetPosition (leftPriests, priestsLeftPostion);setTargetPosition (rightPriests, priestsRightPostion);setTargetPosition (leftDevils, DevilsLeftPostion);setTargetPosition (rightDevils, DevilsRightPostion);if (s1.state == State.LTR) {ansform.position = Vector3.MoveTowards (ansform.position, shipRightPostion, Time.deltaTime * speed);if (ansform.position == shipRightPostion) {s1.state = State.Right;}} else if (s1.state == State.RTL) {ansform.position = Vector3.MoveTowards (ansform.position, shipLeftPostion, Time.deltaTime * speed);if (ansform.position == shipLeftPostion) {s1.state = State.Left;}}else {check ();}}}
    
    View.cs
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using game;public class View : MonoBehaviour {SSDirector s1;Action action;// Use this for initializationvoid Start () {s1 = Instance ();action = Instance () as Action;}// Update is called once per framevoid Update () {}void OnGUI(){GUI.skin.label.fontSize = 30;if (s1.state == State.Win) {if (GUI.Button (new Rect (235, 150, 300, 100), "You win!(*^_^*)nClick here to restart")) {start ();}}if (s1.state == State.Lose) {if (GUI.Button (new Rect (235, 150, 300, 100), "You lose./(ㄒoㄒ)/~~nClick here to restart")) {start ();}}if (GUI.Button (new Rect (330, 40, 100, 50), "GO")) {action.shipMove ();}if (GUI.Button (new Rect (300, 250, 80, 40), "Left OFF") && s1.state != State.LTR && s1.state != State.RTL) {action.offShipLeft ();}if (GUI.Button (new Rect (400, 250, 80, 40), "Right OFF") && s1.state != State.LTR && s1.state != State.RTL) {action.offShipRight ();}if (GUI.Button (new Rect (50, 90, 75, 40), "Priest ON")) {action.priestLeftOnBoat ();}if (GUI.Button (new Rect (650, 90, 75, 40), "Priest ON")) {action.priestRightOnBoat ();}if (GUI.Button (new Rect (190, 90, 75, 40), "Devil ON")) {action.devilLeftOnBoat ();}if (GUI.Button (new Rect (500, 90, 75, 40), "Devil ON")) {action.devilRightOnBoat ();}}
    }
    
    Controller.cs
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using game;namespace game{public enum State{Left, Right, LTR, RTL, Win, Lose};public interface Action{//船移动void shipMove ();//角色在岸左边下船void offShipLeft ();//角色在岸右边下船void offShipRight ();//重新开始void restart ();//牧师在岸左边上船void priestLeftOnBoat ();//牧师在岸右边上船void priestRightOnBoat ();//恶魔在岸左边上船void devilLeftOnBoat ();//恶魔在岸右边上船void devilRightOnBoat ();}public class SSDirector : System.Object, Action{private static SSDirector instance;private Model obj;public Controller controller;public State state = State.Left;public static SSDirector getInstance(){if (instance == null) {instance = new SSDirector ();}return instance;}public Model getModel(){return obj;}internal void setModel(Model obj2){if(obj == null){obj = obj2;}}public void shipMove (){obj.shipMove ();}public void offShipLeft (){obj.offShip (0);}public void offShipRight (){obj.offShip (1);}public void restart(){start ();}public void priestLeftOnBoat (){obj.priestLeftOnBoat ();}public void priestRightOnBoat (){obj.priestRightOnBoat ();}public void devilLeftOnBoat (){obj.devilLeftOnBoat ();}public void devilRightOnBoat (){obj.devilRightOnBoat ();}}
    }public class Controller : MonoBehaviour {// Use this for initializationvoid Start () {SSDirector s1 = Instance ();}// Update is called once per framevoid Update () {}
    }
    
  • 效果演示



本博客所有代码请查看GitHub:项目传送门

本文发布于:2024-01-27 18:55:05,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/17063529012009.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:作业   游戏
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23