打飞碟游戏

游戏介绍:

游戏共有5个回合,每个回合中会有随机产生的飞碟飞过屏幕,玩家需要做的事情就是用鼠标尽量快和多地点击飞碟。 每个飞碟对应一定的分数,目前的设置是: 【红色飞碟 3分】、【绿色飞碟 2分】、【蓝色飞碟 1分】

UML图介绍

代码介绍:
对象池代码:

DiskFactory.cs用于产生飞碟,并且用了两个队列来存储飞碟对象,used和free分别表示使用中的飞碟对象和空闲的飞碟对象。

GetDisk(int round)被主控制器调用,round(回合数)会影响所生产的飞碟的速度、大小等属性。 有两个列表used和free,存放的是飞碟属性(包括分数、速度),可以循环使用,提高飞碟的产生效率。

飞碟初始位置随机,可能为屏幕的四个角落之一。 根据飞碟的分数和回合数设置飞碟的大小和速度。

代码如下:

public class MyException : System.Exception
{
    public MyException() { }
    public MyException(string message) : base(message) { }
}
public class DiskAttributes : MonoBehaviour
{
    //public GameObject gameobj;
    public int score;
    public float speedX;
    public float speedY;
}
public class DiskFactory : MonoBehaviour
{
    
    List<GameObject> used;
    List<GameObject> free;
    System.Random rand;
​
    // Start is called before the first frame update
    void Start()
    {
        
        used = new List<GameObject>();
        free = new List<GameObject>();
        rand = new System.Random();
        //Disk disk = GetDisk(1); 
    }
​
   
    public GameObject GetDisk(int round) {
        GameObject disk;
        if (free.Count != 0) {
            disk = free[0];
            free.Remove(disk);
        }
        else {
            disk = GameObject.Instantiate(Resources.Load("Prefabs/disk", typeof(GameObject))) as GameObject;
            disk.AddComponent<DiskAttributes>();
        }
        
        //根据不同round设置diskAttributes的值
​
        //随意的旋转角度
        disk.transform.localEulerAngles = new Vector3(-rand.Next(20,40),0,0);
​
        DiskAttributes attri = disk.GetComponent<DiskAttributes>();
        attri.score = rand.Next(1,4);
        //由分数来决定速度、颜色、大小
        attri.speedX = (rand.Next(1,5) + attri.score + round) * 0.2f;
        attri.speedY = (rand.Next(1,5) + attri.score + round) * 0.2f;
        
        
        if (attri.score == 3) {
            disk.GetComponent<Renderer>().material.color = Color.red;
            disk.transform.localScale += new Vector3(-0.5f,0,-0.5f);
        }
        else if (attri.score == 2) {
            disk.GetComponent<Renderer>().material.color = Color.green;
            disk.transform.localScale += new Vector3(-0.2f,0,-0.2f);
        }
        else if (attri.score == 1) {
            disk.GetComponent<Renderer>().material.color = Color.blue;
            
        }
        
        //飞碟可从四个方向飞入(左上、左下、右上、右下)
        int direction = rand.Next(1,5);
     
        if (direction == 1) {
            disk.transform.Translate(Camera.main.ScreenToWorldPoint(new Vector3(0, Camera.main.pixelHeight * 1.5f, 8)));
            attri.speedY *= -1;
        }
        else if (direction == 2) {
            disk.transform.Translate(Camera.main.ScreenToWorldPoint(new Vector3(0, Camera.main.pixelHeight * 0f, 8)));
            
        }
        else if (direction == 3) {
            disk.transform.Translate(Camera.main.ScreenToWorldPoint(new Vector3(Camera.main.pixelWidth, Camera.main.pixelHeight * 1.5f, 8)));
            attri.speedX *= -1;
            attri.speedY *= -1;
        }
        else if (direction == 4) {
            disk.transform.Translate(Camera.main.ScreenToWorldPoint(new Vector3(Camera.main.pixelWidth, Camera.main.pixelHeight * 0f, 8)));
            attri.speedX *= -1;
        }
        used.Add(disk);
        disk.SetActive(true);
        Debug.Log("generate disk");
        return disk;
    }
​
    public void FreeDisk(GameObject disk) {
        disk.SetActive(false);
        //将位置和大小恢复到预制,这点很重要!
        disk.transform.position = new Vector3(0, 0,0);
        disk.transform.localScale = new Vector3(2f,0.1f,2f);
        if (!used.Contains(disk)) {
            throw new MyException("Try to remove a item from a list which doesn't contain it.");
        }
        Debug.Log("free disk");
        used.Remove(disk);
        free.Add(disk);
    }
}
接着需要单实例化飞碟对象池
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 CCFlyAction : SSAction
{
    public float speedX;
    public float speedY;
    public static CCFlyAction GetSSAction(float x, float y) {
        CCFlyAction action = ScriptableObject.CreateInstance<CCFlyAction>();
        action.speedX = x;
        action.speedY = y;
        return action;
    }
    // Start is called before the first frame update
    public override void Start()
    {
        
    }
​
    // Update is called once per frame
    public override void Update()
    {
        //Debug.Log("flyaction update");
        if (this.transform.gameObject.activeSelf == false) {//飞碟已经被"销毁"
            this.destroy = true;
            this.callback.SSActionEvent(this);
            return;
        }
        
        Vector3 vec3 = Camera.main.WorldToScreenPoint (this.transform.position);
        if (vec3.x < -100 || vec3.x > Camera.main.pixelWidth + 100 || vec3.y < -100 || vec3.y > Camera.main.pixelHeight + 100) {
            this.destroy = true;
            this.callback.SSActionEvent(this);
            return;
        }
        transform.position += new Vector3(speedX, speedY, 0) * Time.deltaTime * 2;
        
        
    }
}
动作管理类基类

新增了一个函数RemainActionCount(),用于判断每回合中剩余的动作数量(即飞碟数量),只有这个值为0才进入下一回合。

public class SSActionManager : MonoBehaviour
{
    private Dictionary<int, SSAction> actions = new Dictionary<int, SSAction>();
    private List<SSAction> waitingAdd = new List<SSAction>();
    private List<int> waitingDelete = new List<int>(); 
    // Start is called before the first frame update
    protected void Start()
    {
        
    }
​
    // Update is called once per frame
    protected void Update()
    {
        //Debug.Log("ssactionmanager update");
        foreach (SSAction ac in waitingAdd) {
            actions[ac.GetInstanceID()] = ac;
        }
        waitingAdd.Clear();
        //Debug.Log(actions.Count);
        foreach(KeyValuePair<int, SSAction> kv in actions) {
            SSAction ac = kv.Value;
            if (ac.destroy) {
                waitingDelete.Add(ac.GetInstanceID());
            } 
            else if (ac.enable) {
                //Debug.Log("ssactionmanager update");
                ac.Update();
            }
        }
​
        foreach(int key in waitingDelete) {
            SSAction ac = actions[key];
            actions.Remove(key);
            Destroy(ac);
        }
        waitingDelete.Clear();
    }
​
    public void RunAction(GameObject gameObject, SSAction action, IActionCallback manager) {
        //Debug.Log("run action");
        action.gameObject = gameObject;
        action.transform = gameObject.transform;
        action.callback = manager;
        waitingAdd.Add(action);
        action.Start();
    }
​
    public int RemainActionCount() {
        return actions.Count;
    }
}

其余基类代码可以查看github仓库查看,地址如下:

clement2048/ufo_game (github.com)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值