3D游戏编程_作业三_牧师与魔鬼
1、简答并用程序验证2.编程实践:牧师与魔鬼:1:列出游戏中提及的事物(Objects)2:用表格列出玩家动作表(规则表),注意,动作越少越好。3:编程:1.MVC编程结构:2.创建预制:3.代码:3.1 以下的代码都在文件 controller.cs中的同一个命名空间controller下:1.Director:2.接口:3.牧师以及魔鬼游戏对象的controller,以及它们的运动组件:4.boat对象的控制函数和运动模块:5.河岸的控制函数:
3.2 User_GUI负责处理玩家动作;在游戏结束时点击按键重新游戏:3.3scen_controller `在这里插入代码片`场记:创建初始化游戏对象,切换各游戏对象以及游戏的状态,负责管理各游戏对象的交换动作。3.4 处理游戏对象点击的类 Click_GUI
4.游戏运行:1:运行截图:2:演示视频:
项目链接地址
1、简答并用程序验证
游戏对象运动的本质是什么? 游戏对象运动的本质是,在每次帧刷新时,对象的坐标位置发生变化,即对象的transform.postion属性变化;
public class Move : MonoBehaviour {
public int speed
= 2;
void Start
() {
}
void Update
() {
this.transform
.position
= Vector3
.MoveTowards
(this.transform
.position
, new Vector3(7,7,0), 2 * Time
.deltaTime
);
}
}
请用三种方法以上方法,实现物体的抛物线运动。(如,修改Transform属性,使用向量Vector3的方法…)
方法一:修改Transform属性: 定义两个方向上的速度,水平速度恒定,垂直方向速度匀加速:
public class Move_para : MonoBehaviour {
public int x_speed
= 3;
public int y_speed
= 0;
void Start
() {
}
void Update
() {
this.transform
.position
+= Vector3
.down
*Time
.deltaTime
*(y_speed
/100) ;
this.transform
.position
+= Vector3
.left
*Time
.deltaTime
* x_speed
;
y_speed
++;
}
}
方法二:使用向量Vector3:
每次更新都加一个Vector3向量,该向量x轴上的值不变,y轴上的取值持续增长:
public class Move_para : MonoBehaviour {
public int x_speed
= 3;
public int y_speed
= 80;
void Start
() {
}
void Update
() {
this.transform
.position
+= new Vector3(Time
.deltaTime
* x_speed
,Time
.deltaTime
*(y_speed
/100),0);
y_speed
--;
}
}
三:使用translate
public class Move_para : MonoBehaviour {
public int x_speed
= 3;
public int y_speed
= 80;
void Start
() {
}
void Update
() {
this.transform
.Translate(new Vector3(Time
.deltaTime
* x_speed
,Time
.deltaTime
*(y_speed
/100),0));
--y_speed
;
}
}
写一个程序,实现一个完整的太阳系, 其他星球围绕太阳的转速必须不一样,且不在一个法平面上。
1:使用圆球制作太阳系行星的预制: 2:为每个行星编写运行代码: 比如太阳的代码:太阳只需要自转;因此只使用了函数Rotate;
using System
.Collections
;
using System
.Collections
.Generic
;
using UnityEngine
;
public class Sun : MonoBehaviour
{
public Transform sun
;
void Start()
{
sun
.position
= Vector3
.zero
;
}
void Update()
{
sun
.Rotate(Vector3
.up
*10*Time
.deltaTime
);
}
}
i地球和其他行星除了需要自转外,还需要绕着太阳公转;因此有两个动作分别对应Rotate()和Rotate Around():依次为其它行星编写运行代码:
using System
.Collections
;
using System
.Collections
.Generic
;
using UnityEngine
;
public class Earth : MonoBehaviour
{
public Transform earth
;
void Start()
{
earth
.position
= new Vector3 (8, 0, 0);
}
void Update()
{
earth
.RotateAround
(Vector3
.zero
, Vector3
.up
, 10 * Time
.deltaTime
);
earth
.Rotate
(Vector3
.up
* 30 * Time
.deltaTime
);
}
}
3:将预制添加成游戏对象,并为它们添加相应的脚本,运行:
2.编程实践:牧师与魔鬼:
1:列出游戏中提及的事物(Objects)
牧师、恶魔、船、水、左河岸、右河岸
2:用表格列出玩家动作表(规则表),注意,动作越少越好。
状态玩家动作结果
角色在岸边,船上有空位玩家点击角色角色上船角色在船上,船靠岸玩家点击角色角色上岸游戏结束点击restart游戏重新开始
3:编程:
1.MVC编程结构:
按照要求,本次编程我们需要使用MVC架构。MVC架构即就是Model,View和Controller。在牧师与魔鬼游戏中,我们的所有GameObject可以说就是Model,包括 牧师、魔鬼、船等。每个Model就由对应的Controller控制。例如船就受到控制船的Controller的控制。在脚本文件中,我们定义了Boat_controller、Bank_controller等多个controller。而View就是展示给用户的游戏界面,以及可供用户操作的各种方式。比如船点击就能动,牧师和魔鬼一点击就可以上船或下船等。这些功能在User_GUI和Click_GUI文件中实现。 本次编程的代码文件: 所有的游戏对象都由代码动态生成,我们进需要创建一个空的游戏对象,然后将脚本Click_GUI、User_GUI、scen_controller文件添加到空游戏对象中即可运行。
2.创建预制:
在Resources文件夹下创建预制:
3.代码:
3.1 以下的代码都在文件 controller.cs中的同一个命名空间controller下:
1.Director:
我们需要一名导演来获取游戏场景;以及控制场景的切换,管理游戏状态:
public class Director : System.Object{
private static Director _instance
;
public ISceneController currentSceneController
{get ;set ;}
public static Director getInstance() {
if (_instance
== null) {
_instance
= new Director ();
}
return _instance
;
}
}
2.接口:
public interface ISceneController {
void load_resource
();
}
public interface IUserAction {
void S_Boating();
void Click_char(chara_controller characterCtrl
);
void Restart();
}
3.牧师以及魔鬼游戏对象的controller,以及它们的运动组件:
public class charact_move
: MonoBehaviour
{
int char_moveable
;
int status
;
Vector3 free
;
void Update() {
if(char_moveable
== 1){
if(status
== 1){
if(transform
.position
.x
> 0){
if(transform
.position
.x
> 7)
transform
.position
= Vector3
.MoveTowards
(transform
.position
, new Vector3(7,3,0), 2 * Time
.deltaTime
);
else
{
transform
.position
= Vector3
.MoveTowards
(transform
.position
, free
, 2 * Time
.deltaTime
);
}
if(transform
.position
== free
){
char_moveable
= 0;
}
}
else{
if(transform
.position
.x
< -7)
transform
.position
= Vector3
.MoveTowards
(transform
.position
, new Vector3(-7,3,0), 2 * Time
.deltaTime
);
else
{
transform
.position
= Vector3
.MoveTowards
(transform
.position
, free
, 2 * Time
.deltaTime
);
}
if(transform
.position
== free
){
char_moveable
= 0;
}
}
}
else{
if(transform
.position
.x
> 0){
if(transform
.position
.x
< 7)
transform
.position
= Vector3
.MoveTowards
(transform
.position
, new Vector3(7,3,0), 2 * Time
.deltaTime
);
else
{
transform
.position
= Vector3
.MoveTowards
(transform
.position
, free
, 2 * Time
.deltaTime
);
}
if(transform
.position
== free
){
char_moveable
= 0;
}
}
else{
if(transform
.position
.x
> -7)
transform
.position
= Vector3
.MoveTowards
(transform
.position
, new Vector3(-7,3,0), 2 * Time
.deltaTime
);
else
{
transform
.position
= Vector3
.MoveTowards
(transform
.position
, free
, 2 * Time
.deltaTime
);
}
if(transform
.position
== free
){
char_moveable
= 0;
}
}
}
}
}
public void set_char_mov(int istatus
,Vector3 t_free
)
{
char_moveable
= 1 ;
status
= istatus
;
free
= t_free
;
}
public void init()
{
char_moveable
= 0;
}
}
public class chara_controller
{
GameObject character
;
int char_type
;
int status
;
int char_moveable
;
int rank
;
Vector3 position
;
Vector3 free
;
readonly Click_GUI click_GUI
;
Bank_controller bank_con
;
Boat_controller boat_con
;
charact_move chara_movscr
;
public chara_controller(int irank
,int itype
)
{
if (itype
== 0) {
position
= new Vector3(7+irank
,2,0);
rank
= irank
;
status
= 0;
char_type
= 0;
character
= Object
.Instantiate
(Resources
.Load
("Perfabs/Priest", typeof(GameObject
)), position
, Quaternion
.identity
, null) as GameObject
;
} else {
position
= new Vector3(7+irank
,2,0);
rank
= irank
;
status
= 0;
char_type
= 1;
character
= Object
.Instantiate
(Resources
.Load
("Perfabs/Devil", typeof(GameObject
)), position
, Quaternion
.identity
, null) as GameObject
;
}
chara_movscr
= character
.AddComponent
(typeof(charact_move
)) as charact_move
;
click_GUI
= character
.AddComponent
(typeof(Click_GUI
)) as Click_GUI
;
click_GUI
.setController
(this);
}
public void charac_action(int start_end
,Vector3 ifree
)
{
if(status
== 0 || status
== 2 )
{
chara_movscr
.set_char_mov(start_end
,ifree
);
status
= 1;
}
else {
chara_movscr
.set_char_mov(start_end
,ifree
);
status
= start_end
;
}
}
public void set_position(Vector3 pos
)
{
character
.transform
.position
= pos
;
position
= pos
;
}
public void setName(string name
) {
character
.name
= name
;
}
public Vector3 get_position()
{
return position
;
}
public int get_type(){
return char_type
;
}
public int get_rank(){
return rank
;
}
public int get_status(){
return status
;
}
public void set_free(Vector3 free_posi
){
free
= free_posi
;
}
public void get_on_boat(Boat_controller boat_c
)
{
bank_con
= null;
boat_con
= boat_c
;
character
.transform
.parent
= boat_c
.get_Object().transform
;
}
public void get_on_bank(Bank_controller ban_c
)
{
bank_con
= ban_c
;
character
.transform
.parent
= null;
boat_con
= null;
}
public Bank_controller get_bank(){
return bank_con
;
}
public void init() {
position
= new Vector3(7+rank
,2,0);
character
.transform
.position
= position
;
status
= 0;
bank_con
= (Director
.getInstance
().currentSceneController
as scen_controller
).start_bank
;
get_on_bank
(bank_con
);
chara_movscr
.init();
}
}
4.boat对象的控制函数和运动模块:
public class boat_move
: MonoBehaviour
{
int status
;
int boat_movable
;
Vector3 start_pos
= new Vector3(5.2F,1,0);
Vector3 desti_pos
= new Vector3(-5.2F,1,0);
void Update() {
if(boat_movable
== 1)
{
if(status
== 0 && boat_movable
== 1)
{
transform
.position
= Vector3
.MoveTowards
(transform
.position
,desti_pos
,5*Time
.deltaTime
);
if(transform
.position
== desti_pos
)
{
status
= 1;
boat_movable
= 0;
}
}
else if(status
== 1 && boat_movable
== 1){
transform
.position
= Vector3
.MoveTowards
(transform
.position
,start_pos
,5*Time
.deltaTime
);
if(transform
.position
== desti_pos
)
{
status
= 0;
boat_movable
= 0;
}
}
}
}
public void set_boat_action(int stat
,int moveable
)
{
status
=stat
;
boat_movable
= moveable
;
}
public void init()
{
status
= 0;
boat_movable
= 0;
}
}
public class Boat_controller{
GameObject boat
;
Vector3 start_pos
= new Vector3(5.2F,1,0);
Vector3 desti_pos
= new Vector3(-5.2F,1,0);
boat_move boat_moscri
;
int status
;
int boat_movable
;
chara_controller
[] passenger
= new chara_controller
[2];
public Boat_controller() {
status
= 0;
boat_movable
= 0;
boat
= Object
.Instantiate(Resources
.Load
("Perfabs/Boat",typeof(GameObject
)),start_pos
,Quaternion
.identity
,null) as GameObject
;
boat
.name
= "boat";
boat
.AddComponent(typeof(Click_GUI
));
boat_moscri
= boat
.AddComponent
(typeof(boat_move
)) as boat_move
;
}
public void boating()
{
if(status
== 0)
{
boat_moscri
.set_boat_action(0,1);
status
= 1;
}
else if(status
== 1)
{
boat_moscri
.set_boat_action(1,1);
status
= 0;
}
}
public int get_free() {
if(passenger
[0] == null) return 0;
if(passenger
[1] == null) return 1;
return -1;
}
public void get_on_boat(chara_controller chara_c
) {
int free_i
= get_free
();
passenger
[free_i
] = chara_c
;
}
public chara_controller
get_off_boat(int rank_i
) {
for(int i
= 0; i
< 2; ++i
){
if(passenger
[i
]!= null && passenger
[i
].get_rank() == rank_i
) {
chara_controller chara_c
= passenger
[i
];
passenger
[i
] = null;
return chara_c
;
}
}
return null;
}
public GameObject get_Object() {
return boat
;
}
public int get_status() {
return status
;
}
public void set_boat_move(int t
)
{
boat_movable
= t
;
}
public int [] count_chara() {
int [] count
= {0,0,0};
for(int i
= 0; i
< 2; i
++)
{
if(passenger
[i
] == null)
continue;
else if(passenger
[i
].get_type() == 0)
count
[0] ++;
else{
count
[1] ++;
}
}
count
[2] = count
[0] +count
[1];
return count
;
}
public void init() {
if(status
== 1)
{
boating();
}
passenger
= new chara_controller
[2];
}
}
5.河岸的控制函数:
public class Bank_controller{
GameObject bank
;
Vector3 position
;
int type
;
chara_controller
[] characters
;
public Bank_controller(int itype
)
{
position
= new Vector3(10*itype
,1,0);
bank
= Object
.Instantiate
(Resources
.Load("Perfabs/bank",typeof(GameObject
)),position
,Quaternion
.identity
,null) as GameObject
;
type
= itype
;
characters
= new chara_controller
[6];
}
public void get_on_bank(chara_controller chara_c
) {
int irank
= chara_c
.get_rank();
characters
[irank
] = chara_c
;
}
public chara_controller
get_off_bank(int irank
){
chara_controller ichara
= characters
[irank
];
characters
[irank
] = null;
return ichara
;
}
public int get_type() {
return type
;
}
public int [] count_chara() {
int [] count
= { 0 , 0};
for(int i
= 0; i
< 6; ++i
)
{
if(characters
[i
] == null)
continue ;
if(characters
[i
].get_type() == 0)
count
[0] ++;
else if(characters
[i
].get_type() == 1)
count
[1] ++;
}
return count
;
}
public void init() {
characters
= new chara_controller
[6];
}
}
3.2 User_GUI负责处理玩家动作;在游戏结束时点击按键重新游戏:
using System
.Collections
;
using System
.Collections
.Generic
;
using UnityEngine
;
using controller
;
public class User_GUI : MonoBehaviour {
private IUserAction action
;
public int status
= 0;
GUIStyle style
;
GUIStyle buttonStyle
;
void Start() {
action
= Director
.getInstance
().currentSceneController
as IUserAction
;
style
= new GUIStyle();
style
.fontSize
= 40;
style
.normal
.textColor
= new Color(100, 155, 255);
style
.alignment
= TextAnchor
.MiddleCenter
;
buttonStyle
= new GUIStyle("button");
buttonStyle
.fontSize
= 30;
buttonStyle
.normal
.textColor
= new Color(100, 155, 255);
}
void OnGUI() {
if (status
== 1) {
GUI
.Label(new Rect(Screen
.width
/2-50, Screen
.height
/2-85, 100, 50), "Gameover!", style
);
if (GUI
.Button(new Rect(Screen
.width
/2-70, Screen
.height
/2, 140, 70), "Restart", buttonStyle
)) {
status
= 0;
action
.Restart
();
}
} else if(status
== 2) {
GUI
.Label(new Rect(Screen
.width
/2-50, Screen
.height
/2-85, 100, 50), "You win!", style
);
if (GUI
.Button(new Rect(Screen
.width
/2-70, Screen
.height
/2, 140, 70), "Restart", buttonStyle
)) {
status
= 0;
action
.Restart
();
}
}
}
}
3.3scen_controller 在这里插入代码片场记:创建初始化游戏对象,切换各游戏对象以及游戏的状态,负责管理各游戏对象的交换动作。
using System
.Collections
;
using System
.Collections
.Generic
;
using UnityEngine
;
using controller
;
public class scen_controller
: MonoBehaviour
, ISceneController
, IUserAction
{
User_GUI user_GUI
;
public Bank_controller start_bank
;
public Bank_controller dest_bank
;
public Boat_controller boat
;
public chara_controller
[] characters
;
void Awake() {
Director director
= Director
.getInstance
();
director
.currentSceneController
= this;
user_GUI
= gameObject
.AddComponent <User_GUI>() as User_GUI
;
characters
= new chara_controller
[6];
load_resource();
}
public void load_resource() {
start_bank
= new Bank_controller(1) ;
dest_bank
= new Bank_controller (-1);
GameObject water
= Instantiate
(Resources
.Load
("Perfabs/Water", typeof(GameObject
)), new Vector3(0,0.5F,0), Quaternion
.identity
, null) as GameObject
;
boat
= new Boat_controller ();
for(int i
= 0; i
< 6; ++i
){
if(i
< 3)
{
chara_controller chara_t
= new chara_controller
(i
,0);
chara_t
.setName("priest" + i
);
chara_t
.get_on_bank(start_bank
);
start_bank
.get_on_bank(chara_t
);
characters
[i
] = chara_t
;
}
else{
chara_controller chara_t
= new chara_controller
(i
,1);
int t
= i
- 3;
chara_t
.setName("devil" +t
);
chara_t
.get_on_bank(start_bank
);
start_bank
.get_on_bank(chara_t
);
characters
[i
] = chara_t
;
}
}
}
public void S_Boating() {
int [] count_i
= boat
.count_chara();
if(count_i
[2] == 0)
{
Debug
.Log("boat_empty");
return;
}
boat
.boating();
Debug
.Log("set_boat");
user_GUI
.status
= check_game_over
();
}
public void Click_char(chara_controller char_i
) {
if(char_i
.get_status() == 1){
if(boat
.get_status() == 0)
{
char_i
.get_on_bank(start_bank
);
start_bank
.get_on_bank(char_i
);
int t_rank
= char_i
.get_rank();
boat
.get_off_boat(t_rank
);
Vector3 free_pos
= new Vector3(7+t_rank
,2,0);
char_i
.charac_action(0,free_pos
);
}
if(boat
.get_status() == 1)
{
char_i
.get_on_bank(dest_bank
);
dest_bank
.get_on_bank(char_i
);
int t_rank
= char_i
.get_rank();
boat
.get_off_boat(t_rank
);
Vector3 free_pos
= new Vector3(-7-t_rank
,2,0);
char_i
.charac_action(2,free_pos
);
}
}
else{
Bank_controller bank_i
= char_i
.get_bank();
if(boat
.get_free() == -1)
return ;
if((bank_i
.get_type() == 1 && boat
.get_status() == 0))
{
bank_i
.get_off_bank(char_i
.get_rank());
int index
= (boat
.get_free())*2-1;
Vector3 free_pos
= new Vector3(5+index
,1.5F,0);
char_i
.charac_action(1,free_pos
);
char_i
.get_on_boat
(boat
);
boat
.get_on_boat(char_i
);
}
else if ((bank_i
.get_type() == -1 && boat
.get_status() == 1))
{
bank_i
.get_off_bank(char_i
.get_rank());
int index
= (boat
.get_free())*2-1;
Vector3 free_pos
= new Vector3(-5+index
,1.5F,0);
char_i
.charac_action(1,free_pos
);
char_i
.get_on_boat
(boat
);
boat
.get_on_boat(char_i
);
}
else {return ;}
}
user_GUI
.status
= check_game_over();
}
int check_game_over() {
int start_priest
= 0;
int start_devil
= 0;
int dest_priest
= 0;
int dest_devil
= 0;
int[] start
= start_bank
.count_chara();
int[] dest
= dest_bank
.count_chara();
int[] boat_count
= boat
.count_chara();
if(dest
[0] +dest
[1] == 6) return 2;
if(boat
.get_status() == 0){
start_priest
= start
[0] + boat_count
[0];
start_devil
= start
[1] + boat_count
[1];
dest_priest
= dest
[0];
dest_devil
= dest
[1];
}
else{
start_priest
= start
[0] ;
start_devil
= start
[1] ;
dest_priest
= dest
[0]+ boat_count
[0];
dest_devil
= dest
[1]+ boat_count
[1];
}
Debug
.Log("start:"+start
[0]+start
[1]);
Debug
.Log("dest:" +dest
[0]+dest
[1]);
Debug
.Log("boat:"+ boat_count
[0]+boat_count
[1]+boat_count
[2]);
Debug
.Log("start_p"+start_priest
+start_devil
+dest_priest
+dest_devil
);
if((start_priest
< start_devil
&& start_priest
!=0) || (dest_priest
< dest_devil
&& dest_priest
!= 0))
return 1;
return 0;
}
public void Restart(){
start_bank
.init();
dest_bank
.init();
boat
.init();
for(int i
= 0; i
< 6; ++i
)
{
characters
[i
].init();
start_bank
.get_on_bank(characters
[i
]);
}
}
}
3.4 处理游戏对象点击的类 Click_GUI
using System
.Collections
;
using System
.Collections
.Generic
;
using UnityEngine
;
using controller
;
public class Click_GUI : MonoBehaviour {
IUserAction action
;
chara_controller characterController
;
public void setController(chara_controller characterCtrl
) {
characterController
= characterCtrl
;
}
void Start() {
action
= Director
.getInstance
().currentSceneController
as IUserAction
;
}
void OnMouseDown() {
if (gameObject
.name
== "boat") {
action
.S_Boating();
} else {
action
.Click_char(characterController
);
}
}
}
4.游戏运行:
1:运行截图:
2:演示视频:
priest and devil
项目链接地址