private GameObject unChainCubePrefab = null; //枝未完成協調表示のためのオブジェクト #endregion Fields #region Methods public void AddObj(Node node, _eLinkDir linkTo) { //Log.Debug("AddObj : " + node + "/" + linkTo); //リストに同じものがあれば新規作成はしないように UnChainObject uc = unChainCubeList.Find(x => { if (x.linkVec == linkTo && x.nodeVec.x == node.NodeID.x && x.nodeVec.y == node.NodeID.y) return true; else return false; }); if (uc != null) { //同じ物だったらチェック済にして消さないように uc.bChecked = true; return; } //なかった場合、リストに追加 GameObject newCube = Instantiate(unChainCubePrefab); newCube.transform.position = new Vector3(0.0f, linkDistance, 0.0f); float rotAngle = 60.0f * (int)linkTo + 30.0f; newCube.transform.RotateAround(new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 0.0f, 1.0f), -rotAngle); newCube.transform.position += node.transform.position; newCube.transform.SetParent(transform); //tween等で出現時アニメーション UnChainObject uco = newCube.GetComponent<UnChainObject>(); uco.linkVec = linkTo; uco.nodeVec = node.NodeID; unChainCubeList.Add(uco); // 1つ目の cube の material を取得 if(unChainCubeList.Count <= 1) { unChainCubeMaterial = unChainCubeList[0].GetComponent<SpriteRenderer>().sharedMaterial; } }
//位置と方向から、指定ノードに隣り合うノードのrowとcolを返す //なければ、(-1,-1)を返す // フレームノードを除く public Vec2Int GetDirNodeRemoveFrame(Vec2Int nodeID, _eLinkDir toDir) { return GetDirNodeRemoveFrame(nodeID.x, nodeID.y, toDir); }
//位置と方向から、指定ノードに隣り合うノードのrowとcolを返す //なければ、(-1,-1)を返す // フレームノードを除く public Vec2Int GetDirNodeRemoveFrame(int x, int y, _eLinkDir toDir) { Vec2Int id = GetDirNode(x, y, toDir); if (id.x <= 0 || id.x >= AdjustRow(id.y) - 1 || id.y <= 0 || id.y >= col - 1) { id.x = -1; id.y = -1; } return id; }
//位置と方向から、指定ノードに隣り合うノードのrowとcolを返す //なければ、(-1,-1)を返す public Vec2Int GetDirNode(int x, int y, _eLinkDir toDir) { //走査方向のノードのcolとrow Vec2Int nextNodeID; nextNodeID.x = x; nextNodeID.y = y; bool Odd = ((y % 2) == 0) ? true : false; //次のノード番号の計算 switch (toDir) { case _eLinkDir.RU: if (!Odd) nextNodeID.x++; nextNodeID.y++; break; case _eLinkDir.R: nextNodeID.x++; break; case _eLinkDir.RD: if (!Odd) nextNodeID.x++; nextNodeID.y--; break; case _eLinkDir.LD: if (Odd) nextNodeID.x--; nextNodeID.y--; break; case _eLinkDir.L: nextNodeID.x--; break; case _eLinkDir.LU: if (Odd) nextNodeID.x--; nextNodeID.y++; break; } if (nextNodeID.x < 0 || nextNodeID.x > AdjustRow(nextNodeID.y) - 1 || nextNodeID.y < 0 || nextNodeID.y > col - 1) { nextNodeID.x = -1; nextNodeID.y = -1; } return nextNodeID; }
// リンク方向の端のノードIDを算出する(フレームノードを除く) Vec2Int SearchLimitNodeRemoveFrame(int x, int y, _eLinkDir dir) { //Log.Debug("SearchLimitNodeRemoveFrame : " + x + "/" + y); return SearchLimitNodeRemoveFrame(new Vec2Int(x, y), dir); }
// リンク方向の端のノードIDを算出する(フレームノードを除く) Vec2Int SearchLimitNodeRemoveFrame(Vec2Int id, _eLinkDir dir) { //Log.Debug("SearchLimitNodeRemoveFrame : " + id + "/" + dir); Vec2Int limitNodeID = id; Vec2Int limitNodeIDTmp = GetDirNodeRemoveFrame(limitNodeID, dir); while (limitNodeIDTmp.x > -1) { limitNodeID = limitNodeIDTmp; limitNodeIDTmp = GetDirNodeRemoveFrame(limitNodeID, dir); } return limitNodeID; }
// リンク方向の端のノードIDを算出する Vec2Int SearchLimitNode(int x, int y, _eLinkDir dir) { //Log.Debug("SerchLimitNode : " + x + "/" + y + "/" + dir); return SearchLimitNode(new Vec2Int(x, y), dir); }
// リンク方向の逆方向を求める _eLinkDir ReverseDirection(_eLinkDir dir) { _eLinkDir reverse = _eLinkDir.NONE; switch (dir) { case _eLinkDir.L: reverse = _eLinkDir.R; break; case _eLinkDir.R: reverse = _eLinkDir.L; break; case _eLinkDir.LU: reverse = _eLinkDir.RD; break; case _eLinkDir.LD: reverse = _eLinkDir.RU; break; case _eLinkDir.RU: reverse = _eLinkDir.LD; break; case _eLinkDir.RD: reverse = _eLinkDir.LU; break; } return reverse; }
// _eLinkDir を _eSlideDir に変換する _eSlideDir ConvertLinkDirToSlideDir(_eLinkDir dir) { _eSlideDir convert = _eSlideDir.NONE; switch (dir) { case _eLinkDir.L: convert = _eSlideDir.LEFT; break; case _eLinkDir.R: convert = _eSlideDir.RIGHT; break; case _eLinkDir.LU: convert = _eSlideDir.LEFTUP; break; case _eLinkDir.LD: convert = _eSlideDir.LEFTDOWN; break; case _eLinkDir.RU: convert = _eSlideDir.RIGHTUP; break; case _eLinkDir.RD: convert = _eSlideDir.RIGHTDOWN; break; } return convert; }
// 隣接判定、ノードごとの処理 public void NodeCheckAction(NodeController.NodeLinkTaskChecker Tc, _eLinkDir Link) { NodeDebugLog += "NodeCheckAction. CheckerID : " + Tc.ID + "\n"; // チェック済みでスキップ if (bChecked) { Tc.Branch--; return; } // 各種変数定義 bool bBranch = false; bChecked = true; Tc.SumNode++; bChain = false; // お隣さんを更新 UpdateNegibor(); // 状態表示 Tc += (ToString() + "Action \n Link : " + bitLink.ToStringEx() + "\nNegibor : " + Negibor.ToStringEx()); Tc += Tc.NotFin + " : " + Tc.Branch.ToString(); // チェックスタート // 接地判定(根本のみ) if (Link == _eLinkDir.NONE) // 根本か確認 { if (!bitLink[(int)_eLinkDir.RD] && !bitLink[(int)_eLinkDir.LD]) // 下方向チェック { Tc.Branch--; Tc.SumNode--; bChecked = false; return; // 繋がってないなら未チェックとして処理終了 } // 繋がっている Tc += ("Ground"); } // この時点で枝が繋がっている事が確定 bChain = true; Tc.NodeList.Add(this); // チェッカに自身を登録しておく // 終端ノードであれば、周囲チェック飛ばす var TempBit = new BitArray(6); // 除外方向設定 TempBit.SetAll(false); if (Link == _eLinkDir.NONE) { TempBit.Set((int)_eLinkDir.RD, true); TempBit.Set((int)_eLinkDir.LD, true); } else { TempBit.Set((int)Link, true); } TempBit.And(bitLink).Xor(bitLink); // 自身の道とAND後、自身の道とXOR。 if (TempBit.isZero()) // 比較して一致なら除外方向以外に道がない = XOR後に全0なら終端 { Tc.Branch--; // 終端ノードであればそこで終了 return; } // 周囲のチェック // この時点で、TempBitは先が壁の道を除いた自分の道を示している。 Tc += "ExcludeFrom MyWay : " + TempBit.ToStringEx(); for (int n = 0; n < (int)_eLinkDir.MAX; n++) { var TempBit2 = new BitArray(6); // 隣接ノードのうち、道が無い場所に自分の道が伸びてたらそこは途切れている。 TempBit2 = TempBit.retAnd(Negibor.retNot()); // ノード繋がってない if (TempBit2[n]) { nodeControllerScript.unChainController.AddObj(this, (_eLinkDir)n); Tc.NotFin = true; // 隣と繋がってないので、枝未完成として登録 } } Tc += ("Negibor : " + Negibor.ToStringEx()); TempBit.And(Negibor); // 隣接ノードと繋がっている場所を特定 Tc += "Linked : " + TempBit.ToStringEx(); for (int n = 0; n < (int)_eLinkDir.MAX; n++) { if (!TempBit[n]) { continue; } // ビット立ってないならスキップ // お隣さんと繋がっているので、処理引き渡しの準備 bChain = true; // デバック表示 Tc += ("Linked [" + LinkDirToString(n) + "]"); // 接続先がおかしいならノーカンで Vec2Int Target = nodeControllerScript.GetDirNode(nodeID, (_eLinkDir)n); if (Target.x == -1) { continue; } // 分岐を検出してカウント if (!bBranch) { bBranch = true; // 一回目ならノーカン } else { Tc.Branch++; // 二回目以降は分岐なので、枝カウンタを+1 } // 次へ引き渡す Node TgtNode = nodeControllerScript.GetNodeScript(Target); if (TgtNode.IsOutPuzzle) { Tc.Branch--; // 接続先が壁なら処理飛ばして枝解決 } else { // 周囲のActionをトリガーさせる Observable .Return(TgtNode) .Subscribe(_ => { TgtNode.NodeCheckAction(Tc, (_eLinkDir)((n + 3 >= 6) ? (n + 3 - 6) : (n + 3))); }).AddTo(this); } } if (Tc.NotFin && Tc.Branch > 0) { Tc.Branch--; } }
// 隣と繋がっているかのANDがめんどくさかったんで関数化。 public bool LinkedNegibor(_eLinkDir n) { return LinkedNegibor((int)n); }
public string LinkDirToString(_eLinkDir n) { string[] DbgLinkStr = { "RU", "R ", "RD", "LD", "L ", "LU" }; return DbgLinkStr[(int)n]; }
public bool GetLinkDir(_eLinkDir parentDir) { return bitLink[(int)parentDir]; }