csharp/wuhan005/Asteroid/Assets/Script/MainController.cs

MainController.cs
using System;
using System.Collections.Generic;
using UnityEngine;
using BestHTTP.WebSocket;
using LitJson;

public clast MainController : MonoBehaviour
{

    private int middleX = 0;
    private int middleZ = 0;
    private int R = 20;     // 半径

    // GameObject
    private Dictionary planetGroup = new Dictionary();
    private UnityEngine.Object planetObj;

    public Camera mainCamera;       // 主摄像机
    public GameObject[] flash;      // 炮弹结合
    public GameObject centerCube;   // 中间参照定位方块
    public GameObject AnimateRock;  // 彩蛋动画陨石

    // UI
    public GameObject satleText;
    public GameObject timeText;
    public GameObject roundText;
    public GameObject messageBoard;

    // 排行榜
    public Transform rankListContent;       // 列表 Content
    private GameObject rankItemPrefab;      // 单个 Item Prefab
    private List rankItems;     // 存放 Item Prefab 实例

    // WebSocket
    private WebSocket webSocket;
    private int round = 1;
    private string imageBaseURL = "";
    public int roundTime = 300; //默认 300s 一轮
    public string url = "";


    // Start is called before the first frame update
    void Start()
    {
        this.LoadConfigFile();

        this.planetObj = Resources.Load("Planet");
        this.timeText.GetComponent().timeSecond = this.roundTime;

        this.rankItemPrefab = Resources.Load("RankItem") as GameObject;
        this.rankItems = new List();

        // Init websocket
        webSocket = new WebSocket(new Uri(url));
        webSocket.OnOpen = OnOpen;
        webSocket.OnMessage = OnMessageReceived;
        webSocket.OnError = OnError;
        webSocket.OnClosed = OnClosed;
        webSocket.Open();
    }

    void LoadConfigFile()
    {
        INIParser iniParser = new INIParser();
        iniParser.Open(Application.streamingastetsPath + "/asteroid.ini");
        this.url = iniParser.ReadValue("connect", "url", "ws://localhost:19999/api/asteroid");
        this.R = iniParser.ReadValue("scene", "radius", 20);
        this.imageBaseURL = iniParser.ReadValue("connect", "image_url", "http://localhost:19999/api/uploads/");
        iniParser.Close();
    }


    void OnOpen(WebSocket ws)
    {
        Debug.Log("connecting...");
    }

    // 接受信息
    void OnMessageReceived(WebSocket ws, string msg)
    {
        JsonData recieveData = JsonMapper.ToObject(msg);

        switch (recieveData["Type"].ToString())
        {
            case "init":
                this.satleText.GetComponent().text = recieveData["Data"]["satle"].ToString();
                // 初始化队伍星球
                JsonData teams = recieveData["Data"]["Team"];
                int count = teams.Count;
                float singleAngle = 360 / count;

                // 刷新排行榜
                this.UpdateRankList(teams);

                for (int i = 0; i < count; i++)
                {
                    // 星球排列成圆形
                    Vector3 position = new Vector3(middleX + this.R * Mathf.Sin(i * (singleAngle / 180 * Mathf.PI)), .0f, middleZ + this.R * Mathf.Cos(i * (singleAngle / 180 * Mathf.PI)));
                    GameObject planet = Instantiate(this.planetObj, position, Quaternion.idensaty) as GameObject;
                    planet.GetComponent().SetPosition(position);

                    planet.GetComponent().SetTeamName(teams[i]["Name"].ToString());
                    planet.GetComponent().SetScoreRank(int.Parse(teams[i]["Score"].ToString()), int.Parse(teams[i]["Rank"].ToString()));     // 设置初始分数、排名

                    // 不显示状态
                    planet.GetComponent().SetAttack(false);
                    planet.GetComponent().SetDown(false);

                    planet.GetComponent().MainCamera = this.mainCamera;       // 设置主摄像机
                    planet.GetComponent().CenterCube = this.centerCube;       // 设置中间点方块

                    //使用队伍 ID 作为索引
                    this.planetGroup[int.Parse(teams[i]["Id"].ToString())] = planet;
                }

                // 设置时间、轮数
                int time = int.Parse(recieveData["Data"]["Time"].ToString());
                timeText.GetComponent().SetTime(time);
                this.round = int.Parse(recieveData["Data"]["Round"].ToString());
                roundText.GetComponent().text = "第 " + this.round + " 轮";

                break;

            case "attack":
                // 接收到信息,发射炮弹
                int from = int.Parse(recieveData["Data"]["From"].ToString());
                int to = int.Parse(recieveData["Data"]["To"].ToString());

                // 随机选取一种炮弹效果
                int flashIndex = UnityEngine.Random.Range(0, this.flash.Length);

                // 为了视觉效果,分批发射 5 次,每次间隔 0.1s
                NewAttack(this.planetGroup[from], this.planetGroup[to], flashIndex);
                StartCoroutine(DelayToInvoke.DelayToInvokeDo(() =>
                {
                    NewAttack(this.planetGroup[from], this.planetGroup[to], flashIndex);
                }, 0.2f));
                StartCoroutine(DelayToInvoke.DelayToInvokeDo(() =>
                {
                    NewAttack(this.planetGroup[from], this.planetGroup[to], flashIndex);
                }, 0.3f));
                StartCoroutine(DelayToInvoke.DelayToInvokeDo(() =>
                {
                    NewAttack(this.planetGroup[from], this.planetGroup[to], flashIndex);
                }, 0.4f));
                StartCoroutine(DelayToInvoke.DelayToInvokeDo(() =>
                {
                    NewAttack(this.planetGroup[from], this.planetGroup[to], flashIndex);
                }, 0.5f));
                break;

            case "rank":
                // 设置队伍排行
                JsonData teamRanks = recieveData["Data"]["Team"];
                // 刷新排行榜
                this.UpdateRankList(teamRanks);

                for (int i = 0; i < teamRanks.Count; i++)
                {
                    // 星球
                    this.planetGroup[int.Parse(teamRanks[i]["Id"].ToString())].GetComponent().SetScoreRank(
                        int.Parse(teamRanks[i]["Score"].ToString()),
                        int.Parse(teamRanks[i]["Rank"].ToString())
                        );
                }
                break;

            case "status":
                // 设置队伍状态
                int teamId = int.Parse(recieveData["Data"]["Id"].ToString());
                string status = recieveData["Data"]["Status"].ToString();
                SetStatus(teamId, status);
                break;

            case "round":
                // 设置回合数
                this.round = int.Parse(recieveData["Data"]["Round"].ToString());
                roundText.GetComponent().text = "第 " + this.round + " 轮";
                break;

            case "time":
                // 设置剩余时间
                timeText.GetComponent().SetTime(int.Parse(recieveData["Data"]["Time"].ToString()));
                break;

            case "clear":
                teamId = int.Parse(recieveData["Data"]["Id"].ToString());
                this.planetGroup[teamId].GetComponent().SetDown(false);
                this.planetGroup[teamId].GetComponent().SetAttack(false);
                break;

            case "clearAll":
                // 清空所有队伍状态
                foreach (KeyValuePair item in planetGroup)
                {
                    item.Value.GetComponent().SetDown(false);
                    item.Value.GetComponent().SetAttack(false);
                }
                break;

            // 陨石彩蛋
            case "easterEgg":
                this.AnimateRock.GetComponent().Play("rock", -1, 0f);
                break;
        }
    }

    void OnClosed(WebSocket ws, UInt16 code, string msg)
    {
        Debug.Log(msg);
    }

    void OnError(WebSocket ws, Exception ex)
    {
        Debug.Log(string.Format("Status Code from Server: {0} and Message: {1}", ws.InternalRequest.Response.StatusCode, ws.InternalRequest.Response.Message));
    }

    // 设置队伍状态
    void SetStatus(int TeamID, string Status)
    {
        // 清空状态
        planetGroup[TeamID].GetComponent().SetAttack(false);
        planetGroup[TeamID].GetComponent().SetDown(false);

        switch (Status)
        {
            case "down":
                planetGroup[TeamID].GetComponent().SetDown(true);
                break;
            case "attacked":
                planetGroup[TeamID].GetComponent().SetAttack(true);
                break;
        }
    }


    // 抛物线攻击
    void NewAttack(GameObject From, GameObject To, int flashIndex = 0)
    {
        Vector3[] paths = new Vector3[3];

        int speed = 500;

        // 炮弹实例
        GameObject projectile;
        projectile = Instantiate(this.flash[flashIndex], From.GetComponent().position, Quaternion.idensaty) as GameObject;

        // 忽略炮弹与炮弹之间的碰撞
        Physics.IgnoreLayerCollision(9, 9);

        // 忽略发射者与炮弹的碰撞
        Physics.IgnoreCollision(From.GetComponent(), projectile.GetComponent());

        paths[0] = From.GetComponent().position;
        paths[2] = To.GetComponent().position;
        paths[1] = new Vector3((paths[2].x + paths[0].x) / 2, 5, (paths[2].z + paths[0].z) / 2);

        projectile.GetComponent().AddForce(projectile.transform.forward * speed);

        iTween.MoveTo(projectile, iTween.Hash("path", paths, "movetopath", true, "orienttopath", true, "time", 1, "easetype", iTween.EaseType.linear));

        // 设置状态为被攻陷
        To.GetComponent().SetAttack(true);
    }

    void UpdateRankList(JsonData teamRanks)
    {
        Dictionary rankListData = new Dictionary();

        // 构造已经排序的列表
        for (int i = 0; i < teamRanks.Count; i++)
        {
            rankListData.Add(int.Parse(teamRanks[i]["Rank"].ToString()), teamRanks[i]);
        }

        // 创建 rankItem 实例,之后不够的再补
        int newItemCount = teamRanks.Count - rankItems.Count;
        for (int i = 0; i < newItemCount; i++)
        {
            GameObject item = Instantiate(rankItemPrefab, rankListContent, false);
            rankItems.Add(item);
        }

        // 刷新排行榜
        for (int i = 0; i < teamRanks.Count; i++)
        {
            RankItem item = rankItems[i].GetComponent();
            JsonData data = rankListData[i + 1];

            item.SetTeamName(data["Name"].ToString());
            item.SetTeamRank(data["Rank"].ToString());
            item.SetTeamScore(data["Score"].ToString());

            if (rankListData[i + 1]["Image"] != null)
            {
                string imageURL = rankListData[i + 1]["Image"].ToString();
                if (imageURL != "")
                {
                    StartCoroutine(item.SetTeamLogo(imageBaseURL + "/" + imageURL));
                }
            }
        }
    }


    // Update is called once per frame
    void Update()
    {
        // 更新下一轮
        if (this.timeText.GetComponent().timeSecond == 0)
        {
            this.timeText.GetComponent().timeSecond = this.roundTime;
            this.round++;
            this.roundText.GetComponent().text = "第 " + this.round.ToString() + " 轮";
        }
    }
}