改进飞碟游戏
- 游戏内容要求:
- 按 adapter模式 设计图修改飞碟游戏
- 使它同时支持物理运动与运动学(变换)运动
要求是使用adapter模式修改飞碟游戏,但是我的代码并不适合这样修改。
适合使用adapter模式有三种情况:
- 系统需要使用现有的类,而此类的接口不符合系统的需要。
- 想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作,这些源类不一定有一致的接口。
- 通过接口转换,将一个类插入另一个类系中。
对于放飞飞碟,我是用一个moveable类赋予飞碟运动的能力,这个moveable类并没有上层接口,其本身是一种能力。飞碟通过拥有一个moveable的实例获得了运动学运动的能力。其中moveable的代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Moveable: MonoBehaviour {
int move_speed = 1;
// change frequently
int moving_status; // 0->not moving, 1->moving to middle, 2->moving to dest
Vector3 dest;
Vector3 middle;
void Update() {
if (moving_status == 1) {
// Debug.Log(transform.position);
moveTo(transform.position, dest, move_speed * Time.deltaTime);
// ufoAction.moveTo(this.gameObject,transform.position, dest, move_speed * Time.deltaTime);
// transform.position = Vector3.MoveTowards (transform.position, dest, move_speed * Time.deltaTime);
if (transform.position == dest) {
moving_status = 0;
}
}
}
void moveTo(Vector3 pos, Vector3 des, float speed){
this.transform.position = Vector3.MoveTowards (pos, des, speed);
}
public void setDestination(Vector3 _dest,int speed) {
move_speed = speed;
dest = _dest;
moving_status = 1;
}
public void reset() {
moving_status = 0;
}
}
使用moveable的示例如下:
public class UFO {
public GameObject ufo;
public Moveable ms;
void start(){
ufo = Object.Instantiate (Resources.Load ("Prefabs/disk1", typeof(GameObject)), Vector3.zero, Quaternion.identity, null) as GameObject;
ms = ufo.AddComponent(typeof(Moveable)) as Moveable;
ms.setDestination(new Vector3(0,0,0),10);
}
}
这种情况下要满足题目第二个条件并不适合用适配器模式,因为Moveable本身不依赖于任何一个GameObject,也没有上层接口。
不过,要让游戏同时支持物理运动与运动学(变换)运动在我的代码中非常容易实现,这也是我不想强行使用适配器模式的原因之一。为了满足要求,我们只需要增添一个physicMoveable类即可,飞碟类同时拥有moveable的一个实例和physicMoveable的一个实例,也就是说,飞碟类同时拥有了物理运动和变换运动的能力。只需要在Fly函数中决定使用哪一种运动能力即可。
因此,整份代码需要修改的地方只有两处。
- 增加一个physicMoveable类,采用物理运动的方式
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class physicMoveable : MonoBehaviour
{
public float r_speed;
public float u_speed;
void start(){
r_speed = 0.0f;
u_speed = 0.0f;
}
void setSpeed(float R_speed,float U_speed){
this.r_speed = R_speed;
this.u_speed = U_speed;
}
public void moveTo(Vector3 pos, Vector3 des, float speed){
float disX = des.x -pos.x;
float disY = Mathf.Abs( pos.y -des.y);
float disF = disX * disX + disY * disY;
float dis = Mathf.Sqrt(disF);
float speedX = speed * (disX / dis / 2);
float speedY = speed * (disY / dis / 2);
setSpeed(speedX,speedY);
}
void FixedUpdate(){
if(!this.gameObject.GetComponent<Rigidbody>()){
this.gameObject.AddComponent<Rigidbody>();
}
Rigidbody rigid = this.gameObject.GetComponent<Rigidbody>();
if(rigid){
rigid.useGravity = false;
rigid.AddForce(Vector3.right * r_speed);
rigid.AddForce(Vector3.up * u_speed);
}else{
Debug.Log("no rigid");
}
}
}
- 在UFO类中增加一个physicMoveable的实例,只需要增加几行代码即可,具体增加代码的位置请看注释。
public class UFO {
public GameObject ufo;
public int type;
public int speed;
public int score = 1;
public Moveable ms;
// 增加physicMoveable实例pt
public physicMoveable pt;
public UFO(int ufo_type){
type = ufo_type;
Debug.Log("right here UFO 1");
if (type == 1) {
speed = 5;
ufo = Object.Instantiate (Resources.Load ("Prefabs/disk1", typeof(GameObject)), Vector3.zero, Quaternion.identity, null) as GameObject;
} else if (type == 2) {
speed = 8;
score = 2;
ufo = Object.Instantiate (Resources.Load ("Prefabs/disk2", typeof(GameObject)), Vector3.zero, Quaternion.identity, null) as GameObject;
} else {
speed = 10;
score = 3;
ufo = Object.Instantiate (Resources.Load ("Prefabs/disk3", typeof(GameObject)), Vector3.zero, Quaternion.identity, null) as GameObject;
}
ms = ufo.AddComponent(typeof(Moveable)) as Moveable;
// 添加physicMoveable组件
pt = ufo.AddComponent(typeof(physicMoveable)) as physicMoveable;
}
public void Fly(){
int fy0 = Random.Range(-10,10);
ufo.transform.position = new Vector3(0,fy0,0);
int fy = Random.Range(-10,10);
Vector3 des = new Vector3(20,fy,0);
Vector3 start = ufo.transform.position;
// 选择哪个就取消哪个的注释
pt.moveTo(start,des,speed);
// ms.setDestination(des,speed);
}
}
这样实现的好处有以下几点:
-
代码复用率高,因此工作量小。上个版本所有的代码都可以复用,只需要增加一个类以及修改一个类即可
-
更改运动模式方便。只需要注释一行代码以及取消一行注释就可以实现(以下代码选自BaseCode.cs中的UFO类):
// 选择哪个就取消哪个的注释 pt.moveTo(start,des,speed); // ms.setDestination(des,speed);