Game_unity-hw3

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

  • 游戏对象运动的本质是什么?
    游戏对象运动的本质就是对于某个游戏对象其在不同帧的空间位置的变化。

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

  1. 利用position
    设水平初速度v0为5,垂直初速度为向上10,重力加速度为9.8向下。
    直接将两个方向的变化体现在position中
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ParabolicMotion : MonoBehaviour
{
    private float g = 9.8f;
    private float v0 = 5;
    private float vy = -10;
    
    void Update()
    {
        vy += g* Time.deltaTime;
        float x_distance = v0* Time.deltaTime;
        float y_distance = vy* Time.deltaTime;

        this.transform.position -= Vector3.up * y_distance;
        this.transform.position += Vector3.right * x_distance;
    }
}
  1. 利用三维向量Vector3
    利用Vector3表示每帧位置的变换。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ParabolicMotion : MonoBehaviour
{
    private float g = 9.8f;
    private float v0 = 5;
    private float vy = -10;
    
    void Update()
    {
        vy += g* Time.deltaTime;
        float x_distance = v0* Time.deltaTime;
        float y_distance = vy* Time.deltaTime;

        Vector3 delta_pos = new Vector3(x_distance,-y_distance,0);
        this.transform.position += delta_pos;
    }
}
  1. 利用translate
    将Vector3表示每帧位置的变换,然后利用Translate将变换体现出来。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ParabolicMotion : MonoBehaviour
{
    private float g = 9.8f;
    private float v0 = 5;
    private float vy = -10;
    
    void Update()
    {
        vy += g* Time.deltaTime;
        float x_distance = v0* Time.deltaTime;
        float y_distance = vy* Time.deltaTime;

        Vector3 delta_pos = new Vector3(x_distance,-y_distance,0);
        this.transform.Translate(delta_pos);
    }
}
  • 写一个程序,实现一个完整的太阳系, 其他星球围绕太阳的转速必须不一样,且不在一个法平面上。
    创建游戏对象:
    在这里插入图片描述
    创建后改变每个行星的大小和起始位置。

行星编程代码;v是旋转速度,在各个行星的Inspector中输入

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class NewBehaviourScript : MonoBehaviour
{
    public float v;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
  
       float n = this.transform.position.x/this.transform.position.y;
       Vector3 axis = new Vector3(-1,n,0);
        this.transform.RotateAround(this.transform.position,Vector3.up,2);
        this.transform.RotateAround(new Vector3(0,0,0),axis,v);
    }
}

月亮代码,将earth拖入到Inspector的对应对象中。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class NewBehaviourScript1 : MonoBehaviour
{
    public Transform earth;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        float n = (this.transform.position.x-earth.position.x)/(this.transform.position.y-earth.position.y);
        Vector3 axis = new Vector3(-1,n,0);
        this.transform.RotateAround(this.transform.position,Vector3.up,2);
        this.transform.RotateAround(earth.position,axis,2);
    }
}

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!

Objects

Objects个数Resource
牧师3白色胶囊
恶魔3红色胶囊
1黑色长方体
2绿色长方体

规则表

玩家动作条件结果
点击船船靠岸且船上至少一个牧师或恶魔船移动到对岸
点击devils getoff船靠岸,且船上至少有一只恶魔一只恶魔上岸
点击priests getoff船靠岸,且船上至少有一个牧师一只牧师上岸
点击devils geton船靠岸,船上至少一个空位,且船所在岸至少有一只恶魔船所在岸上的一只恶魔上船
点击priests geton船靠岸,船上至少一个空位,且船所在岸至少有一个恶魔船所在岸上的一个牧师上船
点击Go船靠岸,且船上至少有一个牧师或一只恶魔船移动到对岸

C# 集合类型

采用List< GameObject >来保存恶魔和牧师,简化了调度和计算的过程。

预制

采用了UI的文本预制,在游戏出现结果时输出获胜情况。

 		void showGameText(string textContent) {
            GameObject Canvas = Camera.Instantiate(Resources.Load("Prefab/Canvas")) as GameObject;
            GameObject GameText = Camera.Instantiate(Resources.Load("Prefab/GameText"), Canvas.transform) as GameObject;
            GameText.transform.position = Canvas.transform.position;
            GameText.GetComponent<Text>().text = textContent;
        }

BaseCode 脚本

由于需要使用单例模式,所以先声明一个命名空间Com.MyGame。然后在里面定义单例类mainSceneController。由于仅定义了一个单例类,所以并不需要挂载到Main Camera上。
每个脚本在开始时都要声明一个gameJudge来调用BaseCode的函数。

gameJudge = mainSceneController.getInstance() as IGameJudge;

生成游戏对象

作业要求游戏中的对象在脚本中动态生成。
以生成恶魔为例,要为每个恶魔生成一个新的胶囊对象,并且设置他的颜色(红)和位置等信息,其中需要设置标签信息以用于对象的统计以判断胜负。我们事先将需要用到的位置都存放在LOCATION_SET中。
恶魔生成代码如下:

        Devils = new List<GameObject>();
        for (int i = 0; i < 3; i++) {
            GameObject devils = GameObject.CreatePrimitive(PrimitiveType.Capsule);//生成胶囊对象
            devils.name = "Devil " + (i + 1);
            devils.tag = "Devil";//设置对象标签
            devils.GetComponent<MeshRenderer>().material.color = Color.red;//设置颜色
            devils.AddComponent<PersonStatus>();
            Devils.Add(devils);
        }
        //设置位置
        Devils[0].transform.position = LOCATION_SET.devils_1_LOC;
        Devils[1].transform.position = LOCATION_SET.devils_2_LOC;
        Devils[2].transform.position = LOCATION_SET.devils_3_LOC;

生成对象的脚本是GenGameObjects,要挂载在MainCamera上。

玩家操作

玩家的操作主要有五个:牧师上船,牧师上岸,恶魔上船,恶魔上岸,开船。五个操作交由五个接口负责。当按下相关的按钮,游戏则会进行相对应的操作。

void OnGUI() {
        if (GUI.Button(new Rect(5, 500, btnWidth, btnHeight), "Priests GetOn")) {
            myActions.priestsGetOn();
        }
        if (GUI.Button(new Rect(300, 500, btnWidth, btnHeight), "Priests GetOff")) {
            myActions.priestsGetOff();
        }
        if (GUI.Button(new Rect(595, 500, btnWidth, btnHeight), "Go!")) {
            myActions.boatMove();
        }
        if (GUI.Button(new Rect(890, 500, btnWidth, btnHeight), "Devils GetOn")) {
            myActions.devilsGetOn();
        }
        if (GUI.Button(new Rect(1185, 500, btnWidth, btnHeight), "Devils GetOff")) {
            myActions.devilsGetOff();
        }
 
    }

船和人的控制

脚本BoatBehaviour主要用于监视和改变船的当前状况,当在移动和有对象上下岸时改变其对应的状态。
以检测是否靠岸为例:

    //检测靠岸
    private bool isMovingToEdge() {
        if (moveDir.x < 0 && this.transform.position.x <= LOCATION_SET.boat_left_LOC.x) {  //向左,已到
            gameJudge.judgeTheGame(DIRECTION.Left);
            isMoving = false;
            atLeftSide = DIRECTION.Left;
            moveDir = new Vector3(-moveDir.x, 0, 0);
            return true;
        }
        else if (moveDir.x > 0 && this.transform.position.x >= LOCATION_SET.boat_right_LOC.x) {  //向右,已到
            gameJudge.judgeTheGame(DIRECTION.Right);
            isMoving = false;
            atLeftSide = DIRECTION.Right;
            moveDir = new Vector3(-moveDir.x, 0, 0);
            return true;
        }
        else {  //还没靠岸
            return false;
        }
    }

人物的控制主要体现在某个人物的登船情况。当其上岸或上船时要调用对应的函数,改变岸和船的人数统计。
以人物上船为例:

    public void personSeatOnBoat(bool boatAtLeft, bool seatAtLeft) {
        if (seatAtLeft) {
            if (boatAtLeft)
                this.transform.position = LOCATION_SET.boatLeft_Pos_1;
            else
                this.transform.position = LOCATION_SET.boatRight_Pos_1;
            onBoatLeft = true;
        }
        else {
            if (boatAtLeft)
                this.transform.position = LOCATION_SET.boatLeft_Pos_2;
            else
                this.transform.position = LOCATION_SET.boatRight_Pos_2;
            onBoatRight = true;
        }
        onBankLeft = false;
        onBankRight = false;
 
        if (this.tag.Equals("Priest")) {
            gameJudge.modifyBoatPriestsNum(MODIFICATION.Add);
            gameJudge.modifyBankPriestsNum(boatAtLeft, MODIFICATION.Sub);
        }
        else {
            gameJudge.modifyBoatDevilsNum(MODIFICATION.Add);
            gameJudge.modifyBankDevilsNum(boatAtLeft, MODIFICATION.Sub);
        }
    }

胜负判断

每次有牧师或恶魔上下船都会更新岸和船的牧师和恶魔的数量,根据这个数量,可以判断游戏胜或败。

        public void judgeTheGame(bool isBoatLeft) {
            if (isBoatLeft) {
                if ((BankLeftPriestsNum + BoatPriestsNum > 0 
                    && BankLeftDevilsNum + BoatDevilsNum > BankLeftPriestsNum + BoatPriestsNum)
                    || (BankRightDevilsNum > BankRightPriestsNum && BankRightPriestsNum > 0)) {
                    showGameText("Failed !");
                    Debug.Log("F");
                }
 
                if (BankLeftDevilsNum + BoatDevilsNum == 3 && BankLeftPriestsNum + BoatPriestsNum == 3) {
                    showGameText("Victory !");
                    Debug.Log("V");
                }
            }
            else {
                if ((BankRightPriestsNum + BoatPriestsNum > 0
                    && BankRightDevilsNum + BoatDevilsNum > BankRightPriestsNum + BoatPriestsNum)
                    || (BankLeftDevilsNum > BankLeftPriestsNum && BankLeftPriestsNum > 0)) {
                    showGameText("Failed !");
                    Debug.Log("F");
                }
            }
        }

游戏截图

在这里插入图片描述

完整代码

完整代码和说明见链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值