3D游戏编程与设计-模型与动画
智能巡逻兵
- 游戏设计要求:
- 创建一个地图和若干巡逻兵(使用动画);
- 每个巡逻兵走一个3~5个边的凸多边型,位置数据是相对地址。即每次确定下一个目标位置,用自己当前位置为原点计算;
- 巡逻兵碰撞到障碍物,则会自动选下一个点为目标;
- 巡逻兵在设定范围内感知到玩家,会自动追击玩家;
- 失去玩家目标后,继续巡逻;
- 计分:玩家每次甩掉一个巡逻兵计一分,与巡逻兵碰撞游戏结束;
- 程序设计要求:
- 必须使用订阅与发布模式传消息
- subject:OnLostGoal
- Publisher: ?
- Subscriber: ?
- 工厂模式生产巡逻兵
- 必须使用订阅与发布模式传消息
- 友善提示1:生成 3~5个边的凸多边型
- 随机生成矩形
- 在矩形每个边上随机找点,可得到 3 - 4 的凸多边型
- 5 ?
友善提示2:参考以前博客,给出自己新玩法
关键部分代码(项目地址)
控制玩家移动
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42public void MovePlayer(float translationX, float translationZ)
{
if(!game_over)
{
if (translationX != 0 || translationZ != 0)
{
player.GetComponent<Animator>().SetBool("run", true);
}
else
{
player.GetComponent<Animator>().SetBool("run", false);
}
//移动和旋转
if (translationZ > 0) {
player.transform.rotation = Quaternion.LookRotation(new Vector3(0, 0, 100));
player.transform.Translate(0, 0, translationZ * player_speed * Time.deltaTime);
}
else if(translationZ < 0) {
player.transform.rotation = Quaternion.LookRotation(new Vector3(0,0,-100));
player.transform.Translate(0, 0, -translationZ * player_speed * Time.deltaTime);
}
if (translationX > 0) {
player.transform.rotation = Quaternion.LookRotation(new Vector3(100, 0, 0));
player.transform.Translate(0, 0, translationX * player_speed * Time.deltaTime);
}
else if(translationX < 0) {
player.transform.rotation = Quaternion.LookRotation(new Vector3(-100,0,0));
player.transform.Translate(0, 0, -translationX * player_speed * Time.deltaTime);
}
//防止碰撞带来的移动
if (player.transform.localEulerAngles.x != 0 || player.transform.localEulerAngles.z != 0)
{
player.transform.localEulerAngles = new Vector3(0, player.transform.localEulerAngles.y, 0);
}
if (player.transform.position.y != 0)
{
player.transform.position = new Vector3(player.transform.position.x, 0, player.transform.position.z);
}
}
}相机跟随玩家移动
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18public class CameraFlow : MonoBehaviour
{
public GameObject follow; //跟随的物体
public float smothing = 5f; //相机跟随的速度
Vector3 offset; //相机与物体相对偏移位置
void Start()
{
offset = transform.position - follow.transform.position;
}
void FixedUpdate()
{
Vector3 target = follow.transform.position + offset;
//摄像机自身位置到目标位置平滑过渡
transform.position = Vector3.Lerp(transform.position, target, smothing * Time.deltaTime);
}
}工厂模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45public class SpiderFactory : MonoBehaviour
{
private GameObject spider = null; //spider
private List<GameObject> used = new List<GameObject>(); //正在被使用的spider
private Vector3[] vec = new Vector3[9]; //保存每个spider的初始位置
public FirstSceneController sceneControler; //场景控制器
//返回spider列表
public List<GameObject> GetSpiders()
{
int[] pos_x = { -8, 4, 13 };
int[] pos_z = { 8, -3, -13 };
int index = 0;
//生成不同的spider初始位置
for(int i=0;i < 3;i++)
{
for(int j=0;j < 3;j++)
{
vec[index] = new Vector3(pos_x[j], 0, pos_z[i]);
index++;
}
}
//加载spider
for(int i=0; i < 9; i++)
{
spider = Instantiate(Resources.Load<GameObject>("Prefabs/Spider"));
spider.transform.position = vec[i];
spider.GetComponent<SpiderData>().sign = i + 1;
spider.GetComponent<SpiderData>().start_position = vec[i];
used.Add(spider);
}
return used;
}
//停止巡逻
public void StopSpider()
{
//切换所有spiders的动画
for (int i = 0; i < used.Count; i++)
{
used[i].gameObject.GetComponent<Animator>().SetBool("run", false);
}
}
}追捕与逃跑
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20public class SpiderCollide : MonoBehaviour
{
void OnTriggerEnter(Collider collider)
{
if (collider.gameObject.tag == "Player")
{
//玩家进入spider追捕范围
this.gameObject.transform.parent.GetComponent<SpiderData>().follow_player = true;
this.gameObject.transform.parent.GetComponent<SpiderData>().player = collider.gameObject;
}
}
void OnTriggerExit(Collider collider)
{
if (collider.gameObject.tag == "Player")
{
this.gameObject.transform.parent.GetComponent<SpiderData>().follow_player = false;
this.gameObject.transform.parent.GetComponent<SpiderData>().player = null;
}
}
}追捕成功
1
2
3
4
5
6
7
8
9
10
11
12
13
14public class PlayerCollide : MonoBehaviour
{
void OnCollisionEnter(Collision other)
{
//当玩家与spider相撞
if (other.gameObject.tag == "Player")
{
other.gameObject.GetComponent<Animator>().SetTrigger("death");
this.GetComponent<Animator>().SetTrigger("attack");
Singleton<GameEventManager>.Instance.PlayerGameover();
}
}
}运行效果