三、空间与运动

1、简答并用程序验证【建议做】

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

游戏对象运动的本质是位移,也就是坐标的变换。一个对象的位置由(x,y,z,w)确定,当使用矩阵变换(平移、旋转、缩放)改变了其中的某个值,游戏对象就实现了运动。

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

  1. 直接修改Transform部件的Position属性
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class parabolicV : MonoBehaviour
{
    public float dTime = 0f;//已经过去的时间
    public float speedx0 = 5.0f;
    public float speedy0 = 1.0f;
    public float ay = 1.0f;
    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        float time = dTime + Time.deltaTime;
        float dx = speedx0 * Time.deltaTime;
        float dy = (float)(speedy0 * Time.deltaTime + 0.5 * ay * (time * time - dTime * dTime));
        this.transform.position += Vector3.right * dx;
        this.transform.position += Vector3.down * dy;
        dTime = time;
    }
}

  1. 声明创建一个Vector3变量,用这个变量修改Transform部件的Position值
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class parabolicV : MonoBehaviour
{
    public float dTime = 0f;//已经过去的时间
    public float speedx0 = 5.0f;
    public float speedy0 = 1.0f;
    public float ay = 1.0f;
    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        float time = dTime + Time.deltaTime;
        float dx = speedx0 * Time.deltaTime;
        float dy = (float)(speedy0 * Time.deltaTime + 0.5 * ay * (time * time - dTime * dTime));
        this.transform.position += new Vector3(dx, -dy);
        dTime = time;
    }
}

  1. 利用transform中的translate函数来进行改变position,也要传入一个Vector3变量
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class parabolicTRANS : MonoBehaviour
{
    public float dTime = 0f;//已经过去的时间
    public float speedx0 = 5.0f;
    public float speedy0 = 1.0f;
    public float ay = 1.0f;
    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        float time = dTime + Time.deltaTime;
        float dx = speedx0 * Time.deltaTime;
        float dy = (float)(speedy0 * Time.deltaTime + 0.5 * ay * (time * time - dTime * dTime));
        this.transform.Translate(new Vector3(dx, -dy));
        dTime = time;
    }
}

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

利用TransForm 部件中的两个函数

  • public void Rotate(Vector3 eulers, Space relativeTo = Space.Self);
    eulers:旋转的欧拉角,欧拉角(eulerAngles):x、y和z角表示围绕z轴的旋转z度、围绕x轴的旋转x度和围绕y轴的旋转y度。
    relativeTo决定旋转相对于Space.Self(the local space and axes of the GameObject)还是Space.World(the space and axes in relation to the /Scene/)
    用于实现星球自转
  • public void RotateAround(Vector3 point, Vector3 axis, float angle);
    围绕穿过point点的axis轴以angle速度转动
    用于实现星球公转
  1. 创建星球
  • 创建材料
    在这里插入图片描述

  • 创建游戏对象(按星球大小排序)
    在这里插入图片描述
    太阳系中对象组成空间树

使用预定义的材料在这里插入图片描述

调整每个对象的大小
在这里插入图片描述

  1. 用程序规定对象的行为,实现一个完整的太阳系
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RoundSun : MonoBehaviour{

    public Transform Sun, Mercury, Venus, Earth, Moon, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto;
    Vector3 axisMercury, axisVenus, axisEarth, axisMoon, axisMars, axisJupiter, axisSaturn, axisUranus, axisNeptune, axisPluto;

    // Use this for initialization
    void Start()
    {
        Sun.position = Vector3.zero;
        Mercury.position = new Vector3(8, 0, 0);
        Venus.position = new Vector3(10, 0, 0);
        Earth.position = new Vector3(15, 0, 0);
        Moon.position = new Vector3((float)(17.05), 0, 0);
        Mars.position = new Vector3(24, 0, 0);
        Jupiter.position = new Vector3(34, 0, 0);
        Saturn.position = new Vector3(44, 0, 0);
        Uranus.position = new Vector3(51, 0, 0);
        Neptune.position = new Vector3(55, 0, 0);
        Pluto.position = new Vector3(58, 0, 0);
        axisMercury = new Vector3(3, 11, 0);
        axisVenus = new Vector3(2, 3, 0);
        axisEarth = new Vector3(0, 1, 0);
        axisMoon = Vector3.up;
        axisMars = new Vector3(1, 5, 0);
        axisJupiter = new Vector3(1, 5, 0);
        axisSaturn = new Vector3(1, 9, 0);
        axisUranus = new Vector3(2, 7, 0);
        axisNeptune = new Vector3(1, 5, 0);
        axisPluto = new Vector3(1, 3, 0);
    }


    // Update is called once per frame
    void Update()
    {
        Mercury.RotateAround(Sun.position, axisMercury, 10 * Time.deltaTime);
        Venus.RotateAround(Sun.position, axisVenus, 30 * Time.deltaTime);
        Earth.RotateAround(Sun.position, axisEarth, 20 * Time.deltaTime);
        Moon.RotateAround(Earth.position, Vector3.up, 359 * Time.deltaTime);
        Mars.RotateAround(Sun.position, axisMars, 60 * Time.deltaTime);
        Jupiter.RotateAround(Sun.position, axisJupiter, 5 * Time.deltaTime);
        Saturn.RotateAround(Sun.position, axisSaturn, 6 * Time.deltaTime);
        Uranus.RotateAround(Sun.position, axisUranus, 35 * Time.deltaTime);
        Neptune.RotateAround(Sun.position, axisNeptune, 10 * Time.deltaTime);
        Pluto.RotateAround(Sun.position, axisPluto, 20 * Time.deltaTime);

        Mercury.Rotate(Vector3.up * 600 * Time.deltaTime);
        Venus.Rotate(Vector3.up * 400 * Time.deltaTime);
        Earth.Rotate(Vector3.up * 360 * Time.deltaTime);                     //自转
        Moon.Rotate(Vector3.up * 1000 * Time.deltaTime);
        Mars.Rotate(Vector3.up * 300 * Time.deltaTime);
        Jupiter.Rotate(Vector3.up * 300 * Time.deltaTime);
        Saturn.Rotate(Vector3.up * 200 * Time.deltaTime);
        Uranus.Rotate(Vector3.up * 400 * Time.deltaTime);
        Neptune.Rotate(Vector3.up * 500 * Time.deltaTime);
        Pluto.Rotate(Vector3.up * 400 * Time.deltaTime);
    }
}

将建立好的游戏对象赋给脚本中的变量
在这里插入图片描述
在这里插入图片描述

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 结构程序
  • 注意细节,例如:船未靠岸,牧师与魔鬼上下船运动中,均不能接受用户事件!

列出游戏中提及的事物(Objects)

左岸、右岸、船、牧师、恶魔

玩家动作表(规则表)

玩家动作 (事件)条件结果(游戏对象动作)
点击岸上的角色船靠角色所在岸且船上有空位角色上船
点击船上的角色角色上岸
点击船船上有角色船开向对岸
重启游戏游戏回到初始状态

将游戏中对象做成预制

在这里插入图片描述

LoadResources 方法动态加载游戏对象

GameObject bank = Instantiate<GameObject>(Resources.Load("Prefabs/bank"), new Vector3(-12, -1, 0), Quaternion.identity) as GameObject;
bank.name=leftbank;

以此类推

使用课件架构图编程

在这里插入图片描述

  • 组织游戏资源
    在这里插入图片描述
  • 创建场景启动对象和控制器
    在这里插入图片描述
    构造 Main 空对象,并挂载 FirstController 代码,使得游戏加载行为在你的控制下。

注意细节,例如:船未靠岸,牧师与魔鬼上下船运动中,均不能接受用户事件!

在SSDirector类内添加成员
public bool moving=false;
移动开始时设为true,结束设为false

在UserGUI中,仅当游戏未结束且moving值为false时才接受用户事件
(但是不知道为什么没起作用

程序设计

使用MVC架构

  • 模型(Model):场景中的所有GameObject
  • 控制器(Controller):接受用户事件,控制模型的变化
    • Director是最高层的控制器,通过一个抽象的场景接口访问不同场景,管理游戏全局状态
    • 一个场景一个主控制器(XXXSceneController,例如 FirstSceneController),管理本次场景所有的游戏对象,响应外部输入事件
    • 每个游戏对象由其控制器管理(“GameObject”+Controller)
    • 至少实现与玩家交互的接口(IUserAction)
    • 实现或管理运动(Move)
  • 界面(View):显示模型,将人机交互事件交给控制器处理(UserGUI)
    • 处收 Input 事件
    • 渲染 GUI ,接收事件

接口

  1. public interface ISceneController 定义场景的操作(加载资源、暂停、恢复等)
    由不同的XXXSceneController多态实现并调用
  2. public interface IUserAction 为用户与游戏交互的接口,定义用户能进行的所有操作
    被XXXGUI调用,由XXXSceneController 实现

SSDirector
职责如下

  • 获取当前游戏的场景
  • 控制场景运行、切换、入栈与出栈
  • 暂停、恢复、退出
  • 管理游戏全局状态
  • 设定游戏的配置
  • 设定游戏全局视图

它是单实例的。具有典型单实例类编程特征
它拥有一些全局属性,如 running,fps等,这样可以让任何地方的代码访问它
它继承至 C# 根对象,所以不会受 Unity 引擎管理,也不要加载
它通过一个抽象的场景接口访问不同场的场记(控制器)
例如:它不知道每个场景需要加载哪些资源
它可以与实现ISceneController的不同场记对话

FirstController

  • 实现接口ISceneController, IUserAction中定义的所有函数
  • 动态加载本场景中的所有游戏对象,通过对应的控制器(“GameObject”+Controller)管理本次场景所有的游戏对象
  • 响应外部输入事件,渲染GUI (利用UserGUI)

"GameObject"+Controller

  • 包括CharactersControllerBoatControllerBankController
  • 每个类中包含一个GameObject变量,即该控制器管理的游戏对象
  • 包含控制所管理的游戏对象的逻辑(方法)
  • 游戏对象之间的通讯只能由其各自的控制器通过FirstController进行消息传递

UserGUI
用户交互界面,接收用户传递的信息,将信息交由控制器处理,渲染 GUI,呈现结果

Move
用于挂载脚本组件,抽象出来的一个类,实现角色的移动功能(上船、下船)

在这里插入图片描述

代码传送门

失败
在这里插入图片描述
成功
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值