空间与运动-作业与练习

空间与运动-作业与练习

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

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

游戏对象的运动过程本质上就是游戏对象的空间位置(Position)、旋转角度(Rotation)、大小(Scale)三个属性随着时间在做某种特定的变化。

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

方法1:复合运动
先向左,在向下
下面展示一些 内联代码片

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

public class MoveLeft : MonoBehaviour
{
    public int speed = 5;
    void Start()
    {      
    }
    void Update()
    {
        this.transform.position += speed * Vector3.left
        * Time.deltaTime;
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MoveDown : MonoBehaviour
{

    public float speed = 5;
    void Start()
    {     
    }
    void Update()
    {
        this.transform.position += speed * Vector3.down * Time.deltaTime;
        speed += 0.1f;
    }
}

将两个脚本挂在同一个物体上,应该可以实现抛物线运动。

方法二:使用Vector3

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

public class Move : MonoBehaviour
{

    public int speedx = 5;
    public int speedy = 1;
    void Start()
    { 
    }
    void Update()
    {
        transform.position += new Vector3(speedx * Time.deltaTime, 1 * speedy * Time.deltaTime, 0);
        speedy += 1;
    }
}

方法三:transform.Translate

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

public class Move : MonoBehaviour
{

    public int speedx = 5;
    public int speedy = 1;
    void Start()
    {
    }
    void Update()
    {
        transform.Translate(new Vector3(speedx * Time.deltaTime, 1 * speedy * Time.deltaTime, 0));
        speedy += 1;
    }
}

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

在这里插入图片描述
先把太阳系各行星摆放好。贴图来自 红动网
在这里插入图片描述
设计思路与课程代码类似,只是要求所有行星不在同一个法平面内。

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

public class Round : MonoBehaviour
{
    public Transform center;
    public int y,z,speed;
    // Start is called before the first frame update
    void Start()
    {
        y = Random.Range(-10, 10);
        z = Random.Range(-10, 10);
        speed = Random.Range(10, 100);
    }

    // Update is called once per frame
    void Update()
    {
        transform.RotateAround(center.transform.position, new Vector3(0, y, z), speed * 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!

简而言之就是保证无时无刻恶魔的人数不能大于神父,在这个条件下完成过河。
原游戏
通关过程:先送一个魔鬼上对岸;再送第二个魔鬼过去(此时需要两个魔鬼过去);然后两个牧师过河,牧师带一个魔鬼回去;两个牧师过对岸,最终让魔鬼把剩下的两个魔鬼运过去。

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

牧师,恶魔,船,河流,两岸

用表格列出玩家动作表(规则表),注意,动作越少越好

当前状态玩家操作结果
船上有空位点击靠近船一侧岸上的人物对应人物上岸
有人在船上点击船上人物对应人物上岸
有人在船上点击船船行驶到对岸

请将游戏中对象做成预制

在这里插入图片描述

设计过程

MVC结构程序的模板可以参考课件中的,但是那个只是太阳系的简单模板。
由于这个游戏有互动部分,所以需要加入与人物,船的接口,以及状态判断接口。
随即对UserGUI里面的OnGUI函数稍作修改。

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

public class UserGUI : MonoBehaviour {

	private IUserAction action;
	public string gameMessage;

	void Start () {
		action = SSDirector.getInstance ().currentSceneController as IUserAction;
	}

	void OnGUI() {  
		float width = Screen.width / 6;  
		float height = Screen.height / 12;

		action.Check();
		GUIStyle style = new GUIStyle();
        style.normal.textColor = Color.red;
        style.fontSize = 30;
		GUI.Label(new Rect(320,100,50,200),gameMessage,style);

		if (GUI.Button(new Rect(0, 0, width, height), "Restart")) {  
			action.Restart();  
		} 

		string paused_title = SSDirector.getInstance ().Paused ? "Resume" : "Pause!"; 
		if (GUI.Button(new Rect(width, 0, width, height), paused_title)) { 
			SSDirector.getInstance ().Paused = !SSDirector.getInstance ().Paused;
		} 
	}
}

FirstController的设计:

//当前游戏的各个状态变量
	private LandModelController landRoleController;
	private BoatController boatRoleController;
	private RoleModelController[] roleModelControllers;
	private MoveController moveController;
	private bool isRuning;
	private int leftPriestNum;
	private int leftDevilNum;
	private int rightPriestNum;
	private int rightDevilNum;
	//修改原来的LoadResources函数
		public void LoadResources () {
		landRoleController=new LandModelController();
		landRoleController.CreateLand();
		roleModelControllers=new RoleModelController[6];
		for(int i=0;i<6;i++){
			roleModelControllers[i]=new RoleModelController();
			roleModelControllers[i].CreateRole(i<3? true:false,i);
			roleModelControllers[i].GetRoleModel().role.transform.localPosition=landRoleController.AddRole(roleModelControllers[i].GetRoleModel());
		}
		boatRoleController=new BoatController();
		boatRoleController.CreateBoat();
		moveController=new MoveController();
		leftPriestNum=leftDevilNum=3;
		rightPriestNum=rightDevilNum=0;
		isRuning=true;
	}
	#region IUserAction implementation
	public void MoveBoat(){
		if(!isRuning||moveController.GetIsMoving()) return;
		if(boatRoleController.GetBoatModel().isRight){
			moveController.SetMove(new Vector3(3,-0.3f,-30),boatRoleController.GetBoatModel().boat);
			leftPriestNum+=boatRoleController.GetBoatModel().priestNum;
			leftDevilNum+=boatRoleController.GetBoatModel().devilNum;
			rightPriestNum-=boatRoleController.GetBoatModel().priestNum;
			rightDevilNum-=boatRoleController.GetBoatModel().devilNum;
		}
		else{
			moveController.SetMove(new Vector3(7.5f,-0.3f,-30),boatRoleController.GetBoatModel().boat);
			leftPriestNum-=boatRoleController.GetBoatModel().priestNum;
			leftDevilNum-=boatRoleController.GetBoatModel().devilNum;
			rightPriestNum+=boatRoleController.GetBoatModel().priestNum;
			rightDevilNum+=boatRoleController.GetBoatModel().devilNum;
		}
		boatRoleController.GetBoatModel().isRight=!boatRoleController.GetBoatModel().isRight;
	}
	public void MoveRole(RoleModel roleModel){
		if(!isRuning||moveController.GetIsMoving()) return;
		if(roleModel.isInBoat){
			roleModel.isRight=boatRoleController.GetBoatModel().isRight;
			moveController.SetMove(landRoleController.AddRole(roleModel),roleModel.role);
			boatRoleController.RemoveRole(roleModel);
		}
		else if(boatRoleController.GetBoatModel().isRight==roleModel.isRight){
			landRoleController.RemoveRole(roleModel);
			moveController.SetMove(boatRoleController.AddRole(roleModel),roleModel.role);
		}
	}
	public void Restart ()
	{
		landRoleController.CreateLand();
		for(int i=0;i<6;i++){
			roleModelControllers[i].CreateRole(i<3? true:false,i);
			roleModelControllers[i].GetRoleModel().role.transform.localPosition=landRoleController.AddRole(roleModelControllers[i].GetRoleModel());
		}
		boatRoleController.CreateBoat();
		leftPriestNum=leftDevilNum=3;
		rightPriestNum=rightDevilNum=0;
		isRuning=true;
		this.gameObject.GetComponent<UserGUI>().gameMessage="";
	}
	public void Check(){
		if(!isRuning) return;
		this.gameObject.GetComponent<UserGUI>().gameMessage="";
		if(rightPriestNum==3&&rightDevilNum==3){
			this.gameObject.GetComponent<UserGUI>().gameMessage="You Win!!";
			isRuning=false;
		}
		else if((leftPriestNum!=0&&leftPriestNum<leftDevilNum)||(rightPriestNum!=0&&rightPriestNum<rightDevilNum)){
			this.gameObject.GetComponent<UserGUI>().gameMessage="Game Over!!";
			isRuning=false;
		}
	}
	#endregion

接口ClickAction:

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

public interface ClickAction
{
    void DealClick();
}

move函数:

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

public class Move : MonoBehaviour
{

    public bool isMoving=false;
    public float speed=3;
    public Vector3 des;

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        if(transform.localPosition==des){
            isMoving=false;
            return;
        }
        isMoving=true;
        transform.localPosition=Vector3.MoveTowards(transform.localPosition,des,speed*Time.deltaTime);
    }
}

以船的实现为例子:

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

public class BoatController : ClickAction
{

    BoatModel boatModel;
    IUserAction userAction;

    public BoatController(){
        userAction=SSDirector.getInstance().currentSceneController as IUserAction;
    }
    public void CreateBoat(){
        if(boatModel!=null) Object.DestroyImmediate(boatModel.boat);
        boatModel=new BoatModel();
        boatModel.boat.GetComponent<Click>().setClickAction(this);
    }
    public BoatModel GetBoatModel(){
        return boatModel;
    }
    public Vector3 AddRole(RoleModel roleModel){
        if(boatModel.roles[0]==null){
            boatModel.roles[0]=roleModel;
            roleModel.isInBoat=true;
            roleModel.role.transform.parent=boatModel.boat.transform;
            if(roleModel.isPriest) boatModel.priestNum++;
            else boatModel.devilNum++;
            return new Vector3(-0.2f,0.2f,0.5f);
        }
        if(boatModel.roles[1]==null){
            boatModel.roles[1]=roleModel;
            roleModel.isInBoat=true;
            roleModel.role.transform.parent=boatModel.boat.transform;
            if(roleModel.isPriest) boatModel.priestNum++;
            else boatModel.devilNum++;
            return new Vector3(-0.2f,0.2f,-0.6f);
        }
        return roleModel.role.transform.localPosition;
    }
    public void RemoveRole(RoleModel roleModel){
        roleModel.role.transform.parent=null;
        if(boatModel.roles[0]==roleModel){
            boatModel.roles[0]=null;
            if(roleModel.isPriest) boatModel.priestNum--;
            else boatModel.devilNum--;
        }
        else if(boatModel.roles[1]==roleModel){
            boatModel.roles[1]=null;
            if(roleModel.isPriest) boatModel.priestNum--;
            else boatModel.devilNum--;
        }
    }
    public void DealClick(){
        if(boatModel.roles[0]!=null||boatModel.roles[1]!=null){
            userAction.MoveBoat();
        }
    }

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

这里是有关船的事件。

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

public class BoatModel
{

    public GameObject boat;
    public RoleModel[] roles;
    public bool isRight;
    public int priestNum,devilNum;

    public BoatModel(){
        priestNum=devilNum=0;
        roles=new RoleModel[2];
        boat=GameObject.Instantiate(Resources.Load("WoodBoat", typeof(GameObject))) as GameObject;
        boat.transform.position=new Vector3(3,-0.3f,-30);
        boat.AddComponent<BoxCollider>();
        boat.AddComponent<Click>();
        boat.GetComponent<BoxCollider>().size=new Vector3(1.5f,0.6f,2.5f);
        isRight=false;
    }

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

这里是船模型的生成。
其他的实现与之相似,详见代码。
在这里插入图片描述
(我。。。尽力了)

源代码点我!(master分支)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值