本文总阅读量次
一. 简答并用程序验证【建议做】
游戏对象运动的本质是什么?
游戏对象的运动,实质上是游戏对象相对于原点位置的改变,或者相对于其他游戏对象位置的改变,通过transform组件中的position属性数值的改变可以实现游戏对象的运动。
请用三种以上的方法实现物体的抛物线运动。(如,修改Transform属性,使用向量Vector3的方法)
直接改变Transform的Position
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22public float Vx;
public float Vy;
private float nowVy;
private Transform originTransform;
// Use this for initialization
void Start () {
nowVy = Vy;
originTransform = this.transform;
}
// Update is called once per frame
void Update () {
if (nowVy+Vy > 0.00001) {
this.transform.position += Vector3.up * Time.deltaTime * nowVy;
this.transform.position += Vector3.left * Time.deltaTime * Vx;
nowVy -= 10 * Time.deltaTime;
} else {
}
}通过使用Vector3.MoveTowards
1
2
3
4
5
6
7
8
9
10
11// Update is called once per frame
void Update () {
Debug.Log (nowVy + Vy);
if (nowVy+Vy > 0.00001) {
Vector3 target = this.transform.position + Vector3.up * Time.deltaTime * nowVy + Vector3.left * Time.deltaTime * Vx;
this.transform.position = Vector3.MoveTowards (this.transform.position, target, Time.deltaTime);
nowVy -= 10 * Time.deltaTime;
} else {
}
}通过使用transform.Translate
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23public float Vx;
public float Vy;
private float nowVy;
private Vector3 speed;
private Vector3 Gravity;
// Use this for initialization
void Start () {
Gravity = Vector3.zero;
speed = new Vector3 (Vx, Vy, 0);
}
// Update is called once per frame
void Update () {
if (2*Vy+Gravity.y > 0.00001) {
Gravity.y -= 10 * Time.fixedDeltaTime;
this.transform.Translate (speed*Time.fixedDeltaTime);
this.transform.Translate (Gravity*Time.fixedDeltaTime);
} else {
}
}
写一个程序,实现一个完整的太阳系,其他星球围绕太阳转速必须不一样,且不在一个法平面上
实现过程
创建游戏对象,并根据太阳系天体图片大致排列出各个星球的位置和大小
素材是上网找图片就好了
所有其他星球是sun的子类,moon又是earth的子类
创建script并挂载到sun上,将各个星球拖到对应的transform上
项目在Github
实现效果
二. 编程实践
阅读以下游戏脚本
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)
牧师,魔鬼,船,go按钮,出发岸,结束岸,水 - 玩家动作表
| 动作 | 规则 |
| ---- | ---- |
| 开船 | 船停靠在岸边且穿上至少有一人 |
| 上船 | 船停靠在岸边,船上有空位且岸上有人 |
| 下船 | 船停靠在岸边且船上有人 |
- 请将游戏中对象做成预制
- 在 GenGameObjects 中创建 长方形、正方形、球 及其色彩代表游戏中的对象。
- 使用 C# 集合类型 有效组织对象
- 整个游戏仅 主摄像机 和 一个 Empty 对象, 其他对象必须代码动态生成!!! 。 整个游戏不许出现 Find 游戏对象, SendMessage 这类突破程序结构的 通讯耦合 语句。 违背本条准则,不给分
- 请使用课件架构图编程,不接受非 MVC 结构程序
- 注意细节,例如:船未靠岸,牧师与魔鬼上下船运动中,均不能接受用户事件!
实现过程
做好预制(Priests,Devil,Water,Boat,Shore)
可以先去做一些materials,去网上搜图片
然后把对应的material拖到prefab的属性栏里
创建scripts文件夹并编写代码
目录结构如图所示
代码写好后把对应的脚本拖到Scene的Object中,我把ClickGUI拖到了Main Camera下面,然后创建一个空对象并把FirstController拖到下面
实现代码
MVC架构
- Model:游戏中的GameObject
- View:UserGUI,Click GUI
- Controller:SSDirector(最高级别的Controller),FirstController,以及其他基础的Controller(BoatController,MyCharacterController,ShoreController)
游戏接口定义
游戏中定义了两个接口类型,分别负责场景控制和用户交互,这两个接口不能直接实例化,而是要通过继承这两个接口来实现相应的功能
1 | public interface SceneController{ |
View定义
ClickGUI
ClickGUI用来检测用户的点击行为,并利用SceneController中的方法进行处理
1 | using System.Collections; |
UserGUI
UserGUI 类用来显示游戏中的开始/暂停按钮、游戏状态和倒计时等元素,也是用户控制游戏开始和暂停的入口。
Controller定义
BoatController定义
1 | readonly GameObject boat;//对象 |
FirstController
- 导入游戏资源,搭建游戏场景
- 处理玩家请求(谁上船,开船,谁下船)
- 监听游戏是否已经结束
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134//初始化游戏场景和配置
void Awake()
{
SSDirector director = SSDirector.getInstance();
director.currentSceneController = this;
userGUI = gameObject.AddComponent<UserGUI>() as UserGUI;
characters = new MyCharacterController[6];
director.setFPS(60);
director.leaveSeconds = director.totalSeconds;
director.currentSceneController.loadResources();
}
```
```c
//创建对象,导入各种预制体资源
public void loadResources()
{
GameObject water = Instantiate(Resources.Load("Prefabs/Water",
typeof(GameObject)), new Vector3(0, 0.5F, 0), Quaternion.identity, null) as GameObject;
water.name = "water";
//设置控制器
fromShore = new ShoreController("from");
toShore = new ShoreController("to");
boat = new BoatController();
//导入游戏人物对象并设置控制器
for (int i = 0; i < 3; i++)
{
MyCharacterController cha = new MyCharacterController("priest");
cha.setName("priest" + i);
cha.setPosition(fromShore.getEmptyPosition());
cha.getOnShore(fromShore);
fromShore.getOnShore(cha);
characters[i] = cha;
}
for (int i = 0; i < 3; i++)
{
MyCharacterController cha = new MyCharacterController("devil");
cha.setName("devil" + i);
cha.setPosition(fromShore.getEmptyPosition());
cha.getOnShore(fromShore);
fromShore.getOnShore(cha);
characters[i + 3] = cha;
}
}
```
```c
//如果点了某个人物判断其是在船上还是在岸上,
//如果在船上就上岸,如果在岸上就下船
public void characterIsClicked(MyCharacterController characterCtrl)
{
if (characterCtrl.isOnBoat())
{
ShoreController whichShore;
if (boat.get_to_or_from() == -1)
{ // to->-1; from->1
whichShore = toShore;
}
else
{
whichShore = fromShore;
}
boat.GetOffBoat(characterCtrl.getName());
characterCtrl.moveToPosition(whichShore.getEmptyPosition());
characterCtrl.getOnShore(whichShore);
whichShore.getOnShore(characterCtrl);
}
else
{ // character on shore
ShoreController whichShore = characterCtrl.getShoreController();
if (boat.getEmptyIndex() == -1)
{ // boat is full
return;
}
if (whichShore.get_to_or_from() != boat.get_to_or_from()) // boat is not on the side of character
return;
whichShore.getOffShore(characterCtrl.getName());
characterCtrl.moveToPosition(boat.getEmptyPosition());
characterCtrl.getOnBoat(boat);
boat.GetOnBoat(characterCtrl);
}
userGUI.status = check_game_over();
}
```
```c
int check_game_over()
{ // 0->not finish, 1->lose, 2->win
int from_priest = 0;
int from_devil = 0;
int to_priest = 0;
int to_devil = 0;
//获取右边对应的人数
int[] fromCount = fromShore.getCharacterNum();
from_priest += fromCount[0];
from_devil += fromCount[1];
//获取左边对应的人数
int[] toCount = toShore.getCharacterNum();
to_priest += toCount[0];
to_devil += toCount[1];
//如果左边有六个人就是安全过河,即游戏胜利
if (to_priest + to_devil == 6) // win
return 2;
//船上的人数目加上去
int[] boatCount = boat.getCharacterNum();
if (boat.get_to_or_from() == -1)
{ // boat at toShore
to_priest += boatCount[0];
to_devil += boatCount[1];
}
else
{ // boat at fromShore
from_priest += boatCount[0];
from_devil += boatCount[1];
}
//如果任意一边的牧师人数少于魔鬼就是输了
//如果时间结束仍没有胜利,就是未完成游戏
if (from_priest < from_devil && from_priest > 0)
{ // lose
return 1;
}
if (to_priest < to_devil && to_priest > 0)
{
return 1;
}
return 0; // not finish
}