3D游戏编程与设计作业五
生活随笔
收集整理的這篇文章主要介紹了
3D游戏编程与设计作业五
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
第五次3D編程作業:飛碟射擊游戲
本次作業源代碼鏈接:點擊此處進行跳轉
游戲視頻
一.、作業要求
-
游戲內容
– 游戲有 n 個 round,每個 round 都包括10 次 trial;
– 每個 trial 的飛碟的色彩、大小、發射位置、速度、角度、同時出現的個數都可能不同, 由該 round 的 ruler 控制;
– 每個 trial 的飛碟有隨機性,總體難度隨 round 上升; -
游戲要求
– 使用帶緩存的工廠模式管理不同飛碟的生產與回收,該工廠必須是場景單實例的!
– 盡可能使用前面 MVC 結構實現人機交互與游戲模型分離
二、游戲內容簡述
單發:綠/藍/紅——2/3/4
連發:綠/藍/紅——1/2/3
且隨著回合數增加,高速度飛碟的生成概率會變大
三、游戲實現
作業代碼較多,此博客只挑選重要部分進行展示,完整代碼請點擊此鏈接下載查看
1. 工廠模式: DiskData.cs DiskFactory.cs
DiskData.cs:記錄飛碟的基本信息
public class DiskData : MonoBehaviour {public int color{set;get;}// 1—綠 2—藍 3—紅public float speed{set;get;}// 飛碟的加速比例public int hp{set;get;}// 飛碟血量,可以來調節游戲難度public DiskData(int c, float s, int h){color = c;speed = s;hp = h;} }DiskFactory.cs:飛碟工廠,控制飛碟的生成和回收
// 單實例模板 public class Singleton<T> : MonoBehaviour where T : MonoBehaviour {protected static T instance;public static T Instance{get{if(instance==null){instance = (T)FindObjectOfType(typeof(T));if(instance==null){Debug.LogError("An instance of " + typeof(T) + " is needed in the scene, but there is none");}}return instance;}} }// 飛碟工廠 public class DiskFactory : MonoBehaviour {public GameObject disk_prefab;private List<DiskData> used;private List<DiskData> free;// Start is called before the first frame updatevoid Start(){disk_prefab = Resources.Load<GameObject>("hw_5/Disk");used = new List<DiskData>();free = new List<DiskData>();}// 獲取飛碟public DiskData get_disk(int color){DiskData d = null;int free_size = free.Count;// 尋找符合空閑飛碟for(int i = 0; i < free_size;i++){ if(free[i].color==color){d = free[i];free.RemoveAt(i);break;}}// 若沒有符合要求的空閑飛碟,則需要生成新的if( d == null ){d = Instantiate<GameObject>(disk_prefab).AddComponent<DiskData>();d.color = color;d.speed = color*1.0f;}if(color==1){ d.gameObject.GetComponent<MeshRenderer>().material.color = Color.green;}if(color==2){d.gameObject.GetComponent<MeshRenderer>().material.color = Color.blue;}if(color==3){d.gameObject.GetComponent<MeshRenderer>().material.color = Color.red; }d.hp = 1;// 重置飛盤血量used.Add(d);d.gameObject.SetActive(true); return d;}// 釋放飛碟public void free_disk(GameObject disk){int used_size = used.Count;for(int i = 0; i < used_size; i++){if(disk==used[i].gameObject){free.Add(disk.GetComponent<DiskData>());used.RemoveAt(i);break;}}} }2. 第一人稱玩家: PlayControl.cs
這部分代碼由上一次作業的第一人稱玩家代碼修改而來
public interface IPlayer {void shoot(GameObject g,int shoot_status);int get_game_status(); } public class PlayControl : MonoBehaviour {float cameraAngle; //攝像機(頭)旋轉的角度float bodyAngle; //身體旋轉的角度float min,max;private CharacterController player;private Vector3 speed;private float dy;private Camera camera;private int jump_times;private IPlayer controller;private int bullet;// 當前子彈數private bool Ring;// 是否在裝彈private int shoot_status;//0—連發 1—點射private AudioSource gun_sound;private AudioSource reload_sound;private AudioSource switch_sound;private float shoot_time;// 控制連發的射擊速度private float reload_time;// 控制裝彈速度// Start is called before the first frame updatevoid Start(){player = this.gameObject.AddComponent<CharacterController>();player.skinWidth = 0.01f;speed = Vector3.zero;cameraAngle = 0;bodyAngle = 0;min = -55;max = 60;camera = new GameObject().AddComponent<Camera>();camera.gameObject.transform.parent = this.gameObject.transform;camera.gameObject.transform.localPosition = new Vector3(0,1,0);camera.gameObject.AddComponent<AudioListener>();// 槍聲音源gun_sound = new GameObject().AddComponent<AudioSource>();gun_sound.gameObject.transform.parent = this.gameObject.transform;gun_sound.gameObject.transform.localPosition = new Vector3(0,0.5f,0);gun_sound.clip = Resources.Load<AudioClip>("hw_5/gun");gun_sound.pitch = 2;gun_sound.volume = 0.5f;// 換彈聲音源reload_sound = new GameObject().AddComponent<AudioSource>();reload_sound.gameObject.transform.parent = this.gameObject.transform;reload_sound.gameObject.transform.localPosition = new Vector3(0,0.5f,0);reload_sound.clip = Resources.Load<AudioClip>("hw_5/reload");// 切換模式音源switch_sound = new GameObject().AddComponent<AudioSource>();switch_sound.gameObject.transform.parent = this.gameObject.transform;switch_sound.gameObject.transform.localPosition = new Vector3(0,0.5f,0);switch_sound.clip = Resources.Load<AudioClip>("hw_5/switch");Skybox sky = camera.gameObject.AddComponent<Skybox>();sky.material = Resources.Load<Material>("hw_5/sky_material");jump_times = 0;Physics.autoSyncTransforms = true;bullet = 45;reload_time = 0;shoot_status = 0;shoot_time = 0;}// Update is called once per framevoid Update(){// 若游戲狀態為未開始或已結束,則無法操控第一人稱玩家int game_status = controller.get_game_status();if(game_status==0||game_status==2) return;reload();switch_status();shoot();turn();jump();move(); reset();}void jump(){if(player.isGrounded)jump_times = 0;if(Input.GetButtonDown("Jump")){if(jump_times == 0){dy = 3;jump_times += 1;}else if(jump_times == 1){dy = 3;jump_times += 1;}}dy -= Time.deltaTime*9.8f;}void move(){float dx = Input.GetAxis("Horizontal")*2;float dz = Input.GetAxis("Vertical")*2;if(Input.GetButton("Fire3")){dx *= 3;dz *= 3;}speed = new Vector3(dx,dy,dz) * Time.deltaTime;player.Move(Quaternion.AngleAxis(bodyAngle,Vector3.up)*speed);}void turn(){bodyAngle = (bodyAngle + Input.GetAxis("Mouse X")) % 360;this.gameObject.transform.rotation = Quaternion.AngleAxis(bodyAngle,Vector3.up); cameraAngle = Mathf.Clamp(cameraAngle += Input.GetAxis("Mouse Y"), min, max);camera.gameObject.transform.localRotation = Quaternion.AngleAxis(cameraAngle,Vector3.left);}void shoot(){ if(Ring) return;if(bullet==0) {reload_sound.Play();Ring = true;reload_time = 0f;return;}//單發模式if( shoot_status==1 && Input.GetMouseButtonDown(0)){gun_sound.Play();cameraAngle += 1.1f;// 槍口上抬bullet--;Ray ray = camera.ScreenPointToRay(Input.mousePosition);RaycastHit hit;if(Physics.Raycast(ray, out hit)){GameObject hit_object = hit.collider.gameObject;if(hit_object.GetComponent<DiskData>() != null)// 若命中飛碟{controller.shoot(hit_object,shoot_status);}}}// 連發模式if( shoot_status==0 && Input.GetMouseButton(0)){shoot_time += Time.deltaTime;if(shoot_time > 0.1f){shoot_time=0;gun_sound.Play();cameraAngle += 1.5f;// 槍口上抬bullet--;Ray ray = camera.ScreenPointToRay(Input.mousePosition);RaycastHit hit;if(Physics.Raycast(ray, out hit)){GameObject hit_object = hit.collider.gameObject;if(hit_object.GetComponent<DiskData>() != null)// 若命中飛碟{controller.shoot(hit_object,shoot_status);}}}}}// 換彈void reload(){if(Ring){reload_time += Time.deltaTime;if(reload_time>1) {Ring = false;bullet = 45;}}if(Input.GetKeyUp(KeyCode.R)){reload_sound.Play();Ring = true;reload_time = 0;}}// 切換射擊模式void switch_status(){if(Ring) return;if(Input.GetKeyUp(KeyCode.E)){switch_sound.Play();shoot_status = (shoot_status+1)%2;}}public int get_bullct(){return bullet;}public int get_shoot_status(){return shoot_status;}public void reset(){if(gameObject.transform.position.y<-5 || gameObject.transform.position.z > -25){gameObject.transform.position = new Vector3(0,1,-30);}}public void set_controller(IPlayer c){controller = c;}}3. 飛碟飛行: DiskFly.cs
public class DiskFly : SSAction {public Vector3 start;public float vx;// 水平速度public float vy;// 垂直速度public float dy;// 垂直加速度public static DiskFly GetDiskFly(Vector3 start,float vx, float vy, float dy){DiskFly action = ScriptableObject.CreateInstance<DiskFly>();action.start = start;action.vx = vx;action.vy = vy;action.dy = dy;return action;}// Start is called before the first frame updatepublic override void Start(){this.game_object.transform.position = start;}// Update is called once per framepublic override void Update(){if(this.game_object.transform.position.y > -5 && this.game_object.transform.position.x < 35f && this.game_object.active){vy += Time.deltaTime*dy;this.game_object.transform.position += Time.deltaTime*new Vector3(vx,vy,0);this.game_object.transform.rotation = Quaternion.AngleAxis(Mathf.Atan(vy/vx)*180/Mathf.PI,Vector3.forward);}else// 飛碟出界或落地{this.destroy = true;// 銷毀該動作this.callback.SSActionEvent(this);// 通知動作管理器} } }4. 場景控制:RoundController.cs
public class RoundController : MonoBehaviour,IUserAction, IPlayer, ISceneController {DiskFactory disk_factory;private ScoreController score_controller;public CCActionManger action_manager{set;get;}private UserGUI gui;private PlayControl player;private float gaming_time;// 游戲時間private float waiting_time;// 回合等待時間private int round,trail;private int game_status;//0—未開始 1—游戲中 2—結束 3—回合過渡中// Start is called before the first frame updatevoid Start(){disk_factory = Singleton<DiskFactory>.Instance;score_controller = new ScoreController();action_manager = new GameObject().AddComponent<CCActionManger>();gui = action_manager.gameObject.AddComponent<UserGUI>();gui.set_controller(this);game_status = 0;gaming_time = 0f;waiting_time = 0f;round = 1;trail = 1;SSDirector director = SSDirector.get_instance();director.current_controller = this;Instantiate<GameObject>(Resources.Load<GameObject>("hw_5/land"),new Vector3(0,0,-35),Quaternion.Euler(90,0,0));Instantiate<GameObject>(Resources.Load<GameObject>("hw_5/Wall"),new Vector3(0,0,0),Quaternion.Euler(90,0,0));Instantiate<GameObject>(Resources.Load<GameObject>("hw_5/Wall"),new Vector3(30,0,0),Quaternion.Euler(0,90,0));// 右墻Instantiate<GameObject>(Resources.Load<GameObject>("hw_5/Wall"),new Vector3(-30,0,0),Quaternion.Euler(0,-90,0));// 左墻player = Instantiate<GameObject>(Resources.Load<GameObject>("hw_5/Man"),new Vector3(0,1,-30),Quaternion.Euler(0,0,0)).AddComponent<PlayControl>();player.set_controller(this);Cursor.lockState = CursorLockMode.None;}// Update is called once per framevoid Update(){if(game_status==0)// 未開始{}if(game_status==1)// 游戲中{game();}if(game_status==2)// 結束{}if(game_status==3)// 回合過渡中{waiting_time += Time.deltaTime;if(waiting_time > 2){game_status = 1;// 進入游戲中狀態round += 1;trail = 1;waiting_time = 0;gaming_time = 0;}}}void create_one_disk(float small,float mid){float y_bia = Random.Range(0f,10f);// 隨機設置飛出高度float z_bia = Random.Range(-5f,5f);float sample = Random.Range(0.0f,1.0f);float vx = Random.Range(15f,20f);float vy = Random.Range(6f,7f);float dy = -4f;Vector3 start = new Vector3(-35,y_bia,z_bia);DiskData disk = null;if(sample <= small)disk = disk_factory.get_disk(1);else if(sample <= mid)disk = disk_factory.get_disk(2);elsedisk = disk_factory.get_disk(3);action_manager.RunAction(disk.gameObject,DiskFly.GetDiskFly(start,vx*disk.speed,vy,dy),action_manager);}void game(){if(trail <= 10)// 一個回合還沒結束{gaming_time += Time.deltaTime; if(gaming_time < 2) return;if(round == 1){if(gaming_time>=1){create_one_disk(1,1);create_one_disk(1,1);create_one_disk(1,1);gaming_time = 0f;trail += 1;}}if(round == 2){if(gaming_time>=1){create_one_disk(0.5f,1);create_one_disk(0.5f,1);create_one_disk(0.5f,1);gaming_time = 0f;trail += 1;}}if(round == 3){if(gaming_time>=1){create_one_disk(0.3f,0.8f);create_one_disk(0.3f,0.8f);create_one_disk(0.3f,0.8f);gaming_time = 0f;trail += 1;}}if(round == 4){if(gaming_time>=1){create_one_disk(-0.1f,0.5f);create_one_disk(-0.1f,0.5f);create_one_disk(-0.1f,0.5f);gaming_time = 0f;trail += 1;}}if(round == 5){if(gaming_time>=1){create_one_disk(-0.1f,-0.1f);create_one_disk(-0.1f,-0.1f);create_one_disk(-0.1f,-0.1f);gaming_time = 0f;trail += 1;}}}else if(action_manager.get_action_num()==0)// 一個回合已經結束{if(round < 5){game_status = 3;// 進入回合間等待waiting_time = 0;gaming_time = 0;}else// 所有回合已結束{Cursor.lockState = CursorLockMode.None;game_status = 2;}}}public void free_disk(GameObject disk){disk_factory.free_disk(disk);}void reset(){round = 1;trail = 1;game_status = 1;gaming_time = 0;waiting_time = 0;score_controller.clear_score();Cursor.lockState = CursorLockMode.Locked;}public void start(){reset();}public void restart(){reset();}public int get_game_status(){return game_status;}public void shoot(GameObject g,int shoot_status){DiskData disk = g.GetComponent<DiskData>();disk.hp--;if(disk.hp < 1){g.SetActive(false);g.transform.position = new Vector3(g.transform.position.x,-5,0);score_controller.record(disk.color,shoot_status);}}public int get_score(){return score_controller.get_score();}public int get_bullct(){return player.get_bullct();}int get_shoot_status(){return player.get_shoot_status();}int IUserAction.get_shoot_status(){return player.get_shoot_status();} }5. 其他代碼
動作分離控制:CCActionManger.cs、SSAction.cs、SSActionManager.cs
MVC::SSDirector.cs、UserGUI.cs
記錄分數:ScoreController.cs
四、游戲游玩
游戲游玩視頻請點擊該鏈接查看
總結
以上是生活随笔為你收集整理的3D游戏编程与设计作业五的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: matlab两个力的合成与分解,[转帖]
- 下一篇: MySQL中character的意思_m