// 移動を終了するノードの位置を調整する void AdjustNodeStop() { ////Log.Debug("AdjustNodeStop"); Vec2Int nearNodeID = SearchNearNode(gameNodePrefabs[tapNodeID.y][tapNodeID.x].transform.position); Vec2Int nextNodeID = SearchLimitNode(tapNodeID, ConvertSlideDirToLinkDir(slideDir)); _eSlideDir reverseDir = ReverseDirection(slideDir); Vector2 pos = new Vector2(gameNodePrefabs[tapNodeID.y][tapNodeID.x].transform.position.x, gameNodePrefabs[tapNodeID.y][tapNodeID.x].transform.position.y); Vector2 standardPos = new Vector2(nodePlacePosList[nearNodeID.y][nearNodeID.x].x, nodePlacePosList[nearNodeID.y][nearNodeID.x].y); // スライド方向を更新 if (pos.x != standardPos.x || pos.y != standardPos.y) { _eSlideDir checkDir = CheckSlideDir(pos, standardPos); if (slideDir != checkDir) { slideDir = checkDir; Vec2Int tmp = slidingLimitNodeID; slidingLimitNodeID = slidingReverseLimitNodeID; slidingReverseLimitNodeID = tmp; } } // スライド方向のノードに、スライド終了を通知 while (nextNodeID.x > -1) { gameNodeScripts[nextNodeID.y][nextNodeID.x].EndSlide(); nextNodeID = GetDirNode(nextNodeID, reverseDir); } // 回り込み処理 CheckSlideOutLimitNode(); LoopBackNode(); // 移動処理 switch (slideDir) { case _eSlideDir.LEFT: case _eSlideDir.RIGHT: pos = standardPos; // タップしているノードを移動 gameNodeScripts[tapNodeID.y][tapNodeID.x].SlideNode(slideDir, standardPos); // タップしているノードより左側のノードを移動 nextNodeID = GetDirNode(tapNodeID, _eLinkDir.L); for (int i = 1; nextNodeID.x > -1; ++i) { pos.x = standardPos.x - moveNodeDistAbs.x * i; gameNodeScripts[nextNodeID.y][nextNodeID.x].SlideNode(slideDir, pos); nextNodeID = GetDirNode(nextNodeID, _eLinkDir.L); } // タップしているノードより右側のノードを移動 nextNodeID = GetDirNode(tapNodeID, _eLinkDir.R); for (int i = 1; nextNodeID.x > -1; ++i) { pos.x = standardPos.x + moveNodeDistAbs.x * i; gameNodeScripts[nextNodeID.y][nextNodeID.x].SlideNode(slideDir, pos); nextNodeID = GetDirNode(nextNodeID, _eLinkDir.R); } break; case _eSlideDir.LEFTUP: case _eSlideDir.RIGHTDOWN: // タップしているノードを移動 gameNodeScripts[tapNodeID.y][tapNodeID.x].SlideNode(slideDir, standardPos); // タップしているノードより左上側のノードを移動 nextNodeID = GetDirNode(tapNodeID, _eLinkDir.LU); for (int i = 1; nextNodeID.x > -1; ++i) { pos.x = standardPos.x - moveNodeDistAbs.x * i; pos.y = standardPos.y + moveNodeDistAbs.y * i; gameNodeScripts[nextNodeID.y][nextNodeID.x].SlideNode(slideDir, pos); nextNodeID = GetDirNode(nextNodeID, _eLinkDir.LU); } // タップしているノードより右下側のノードを移動 nextNodeID = GetDirNode(tapNodeID, _eLinkDir.RD); for (int i = 1; nextNodeID.x > -1; ++i) { pos.x = standardPos.x + moveNodeDistAbs.x * i; pos.y = standardPos.y - moveNodeDistAbs.y * i; gameNodeScripts[nextNodeID.y][nextNodeID.x].SlideNode(slideDir, pos); nextNodeID = GetDirNode(nextNodeID, _eLinkDir.RD); } break; case _eSlideDir.RIGHTUP: case _eSlideDir.LEFTDOWN: // タップしているノードを移動 gameNodeScripts[tapNodeID.y][tapNodeID.x].SlideNode(slideDir, standardPos); // タップしているノードより右上側のノードを移動 nextNodeID = GetDirNode(tapNodeID, _eLinkDir.RU); for (int i = 1; nextNodeID.x > -1; ++i) { pos.x = standardPos.x + moveNodeDistAbs.x * i; pos.y = standardPos.y + moveNodeDistAbs.y * i; gameNodeScripts[nextNodeID.y][nextNodeID.x].SlideNode(slideDir, pos); nextNodeID = GetDirNode(nextNodeID, _eLinkDir.RU); } // タップしているノードより左下側のノードを移動 nextNodeID = GetDirNode(tapNodeID, _eLinkDir.LD); for (int i = 1; nextNodeID.x > -1; ++i) { pos.x = standardPos.x - moveNodeDistAbs.x * i; pos.y = standardPos.y - moveNodeDistAbs.y * i; gameNodeScripts[nextNodeID.y][nextNodeID.x].SlideNode(slideDir, pos); nextNodeID = GetDirNode(nextNodeID, _eLinkDir.LD); } break; default: break; } }
//移動したいノードを確定 //ドラッグを算出し移動したい方向列を確定 //ドラッグされている間、列ごと移動、 //タップ点からスワイプ地点まで座標の差分を算出し //列のすべてのノードをその位置へ移動させる //離すと一番近いノード確定位置まで調整 public void StartSlideNodes(Vec2Int nextNodeID, _eSlideDir newSlideDir) { ////Log.Debug("StartSlideNodes : " + nextNodeID + " / " + newSlideDir); moveNodeDist = new Vector2(gameNodePrefabs[nextNodeID.y][nextNodeID.x].transform.position.x, gameNodePrefabs[nextNodeID.y][nextNodeID.x].transform.position.y) - new Vector2(gameNodePrefabs[tapNodeID.y][tapNodeID.x].transform.position.x, gameNodePrefabs[tapNodeID.y][tapNodeID.x].transform.position.y); // スライド方向ベクトル兼移動量を算出 moveNodeInitPos = gameNodePrefabs[tapNodeID.y][tapNodeID.x].transform.position; // ノードの移動開始位置を保存 // スライド方向を設定 slideDir = newSlideDir; // 絶対値を算出 moveNodeDistAbs.x = Mathf.Abs(moveNodeDist.x); moveNodeDistAbs.y = Mathf.Abs(moveNodeDist.y); // スライド開始準備 Vec2Int nextID = SearchLimitNode(tapNodeID, ConvertSlideDirToLinkDir(slideDir)); _eSlideDir reverseDir = ReverseDirection(slideDir); while (nextID.x > -1) { gameNodeScripts[nextID.y][nextID.x].StartSlide(); nextID = GetDirNode(nextID, reverseDir); } // スライド方向の端のノードIDを算出 slidingLimitNodeID = SearchLimitNode(tapNodeID, ConvertSlideDirToLinkDir(slideDir)); slidingReverseLimitNodeID = SearchLimitNode(tapNodeID, ConvertSlideDirToLinkDir(ReverseDirection(slideDir))); // タップしているノードの位置と、タップしている位置との距離を算出 tapPosMoveNodePosDist = moveNodeDist.normalized * Vector2.Dot(moveNodeDist.normalized, startTapPos - moveNodeInitPos); }
// タップ位置から、タップしているノードの、移動ライン上の座標を算出する Vector2 AdjustNodeLinePosition(_eSlideDir dir) { //Log.Debug("AdjustNodeLinePosition : " + dir); Vector2 adjustPos = tapPos; Vector2 slideDist = tapPos - startTapPos; // スライド量 Vector2 moveDist = moveNodeDist.normalized * Vector2.Dot(moveNodeDist.normalized, slideDist); // 斜め移動量 switch (slideDir) { case _eSlideDir.LEFT: case _eSlideDir.RIGHT: // タップしているノードの位置を調整 //adjustPos = AdjustGameScreen(tapPos); adjustPos.y = gameNodePrefabs[tapNodeID.y][tapNodeID.x].transform.position.y; break; case _eSlideDir.LEFTUP: case _eSlideDir.RIGHTDOWN: // タップしているノードの位置を調整 Vec2Int lu = SearchLimitNode(tapNodeID, _eLinkDir.LU); Vec2Int rd = SearchLimitNode(tapNodeID, _eLinkDir.RD); adjustPos = moveNodeInitPos + moveDist + tapPosMoveNodePosDist; if (adjustPos.x < nodePlacePosList[lu.y][lu.x].x) adjustPos.x = nodePlacePosList[lu.y][lu.x].x; if (adjustPos.x > nodePlacePosList[rd.y][rd.x].x) adjustPos.x = nodePlacePosList[rd.y][rd.x].x; if (adjustPos.y > nodePlacePosList[lu.y][lu.x].y) adjustPos.y = nodePlacePosList[lu.y][lu.x].y; if (adjustPos.y < nodePlacePosList[rd.y][rd.x].y) adjustPos.y = nodePlacePosList[rd.y][rd.x].y; break; case _eSlideDir.RIGHTUP: case _eSlideDir.LEFTDOWN: // タップしているノードの位置を調整 Vec2Int ru = SearchLimitNode(tapNodeID, _eLinkDir.RU); Vec2Int ld = SearchLimitNode(tapNodeID, _eLinkDir.LD); adjustPos = moveNodeInitPos + moveDist + tapPosMoveNodePosDist; if (adjustPos.x > nodePlacePosList[ru.y][ru.x].x) adjustPos.x = nodePlacePosList[ru.y][ru.x].x; if (adjustPos.x < nodePlacePosList[ld.y][ld.x].x) adjustPos.x = nodePlacePosList[ld.y][ld.x].x; if (adjustPos.y > nodePlacePosList[ru.y][ru.x].y) adjustPos.y = nodePlacePosList[ru.y][ru.x].y; if (adjustPos.y < nodePlacePosList[ld.y][ld.x].y) adjustPos.y = nodePlacePosList[ld.y][ld.x].y; break; default: break; } return adjustPos; }
//位置と方向から、指定ノードに隣り合うノードのrowとcolを返す //なければ、(-1,-1)を返す // フレームノードを除く public Vec2Int GetDirNodeRemoveFrame(int x, int y, _eSlideDir toSlideDir) { _eLinkDir toDir = ConvertSlideDirToLinkDir(toSlideDir); return GetDirNodeRemoveFrame(x, y, toDir); }
//位置と方向から、指定ノードに隣り合うノードのrowとcolを返す //なければ、(-1,-1)を返す // フレームノードを除く public Vec2Int GetDirNodeRemoveFrame(Vec2Int nodeID, _eSlideDir toSlideDir) { return GetDirNodeRemoveFrame(nodeID.x, nodeID.y, toSlideDir); }
// Use this for initialization void Start() { ////Log.Debug("Start"); //音声データを取得 添字をenum化すべきか audioSources = GetComponents<AudioSource>(); /*if (audioSources.Length != (int)_eAudioNumber.MAX) print("音声取得に失敗");*/ // ----- プレハブデータを Resources から取得 gameNodePrefab = Resources.Load<GameObject>(gameNodePrefabPath); frameNodePrefab = Resources.Load<GameObject>(frameNodePrefabPath); gameArrowPrefab = Resources.Load<GameObject>(gameArrowPrefabPath); // ----- スプライトデータを Resources から取得 gameNodeSprite = Resources.LoadAll<Sprite>(gameNodeSpritePath); nodeMaskSprite = Resources.LoadAll<Sprite>(nodeMaskSpritePath); frameNodeSprite = Resources.LoadAll<Sprite>(frameNodeSpritePath); // GameEffect スクリプトを取得 gameEffect = transform.GetComponent<GameEffect>(); // ----- ノード準備 NodeTemplate.AllCalc(NodeTemp); InitNode(); //開始演出が終わるまでは操作を受け付けない SetSlideAll(true); // スライドベクトルの垂線を算出 Vector3 leftUp = gameNodePrefabs[0][1].transform.position - gameNodePrefabs[0][0].transform.position; Vector3 leftDown = gameNodePrefabs[1][1].transform.position - gameNodePrefabs[0][0].transform.position; Matrix4x4 mtx = Matrix4x4.identity; mtx.SetTRS(new Vector3(0.0f, 0.0f, 0.0f), Quaternion.Euler(0.0f, 0.0f, 90.0f), new Vector3(1.0f, 1.0f, 1.0f)); leftUp = mtx.MultiplyVector(leftUp).normalized; leftDown = mtx.MultiplyVector(leftDown).normalized; slideLeftUpPerNorm = new Vector2(leftUp.x, leftUp.y); slideLeftDownPerNorm = new Vector2(leftDown.x, leftDown.y); // SE準備 cumSlideIntervalPlaySE = 0.0f; // ----- インプット処理 Observable .EveryUpdate() .Where(_ => Input.GetMouseButton(0)) .Subscribe(_ => { // タップに成功していなければ未処理 if (!isTap) { return; } Vector3 worldTapPos = Camera.main.ScreenToWorldPoint(Input.mousePosition); // スライド処理 if (isSlide) { prevTapPos = tapPos; tapPos = new Vector2(worldTapPos.x, worldTapPos.y); SlideNodes(); CheckSlideOutLimitNode(); LoopBackNode(); return; } // スライド判定 if (tapNodeID.x > -1 && startTapPos != (Vector2)worldTapPos) { _eSlideDir dir = CheckSlideDir(startTapPos, new Vector2(worldTapPos.x, worldTapPos.y)); Vec2Int nextNodeID = GetDirNode(tapNodeID, dir); if (nextNodeID.x > -1) { if (Vector3.Distance(gameNodePrefabs[tapNodeID.y][tapNodeID.x].transform.position, worldTapPos) > Vector3.Distance(gameNodePrefabs[nextNodeID.y][nextNodeID.x].transform.position, worldTapPos)) { isSlide = true; _isNodeAction = true; StartSlideNodes(nextNodeID, dir); } } } }) .AddTo(this.gameObject); Observable .EveryUpdate() .Where(_ => Input.GetMouseButtonDown(0)) .Subscribe(_ => { // スライド中なら未処理 if (isSlide) return; if (pauseScript.pauseState == _ePauseState.PAUSE) return; if (levelControllerScript.LevelState != _eLevelState.STAND) return; // タップ成功 isTap = true; ////Log.Debug("MouseButtonDown"); Vector3 worldTapPos = Camera.main.ScreenToWorldPoint(Input.mousePosition); startTapPos = new Vector2(worldTapPos.x, worldTapPos.y); // タップしているノードのIDを検索 tapNodeID = SearchNearNodeRemoveFrame(worldTapPos); }) .AddTo(this.gameObject); Observable .EveryUpdate() .Where(_ => Input.GetMouseButtonUp(0)) .Subscribe(_ => TapRelease()/*{ // タップに成功していなければ未処理 if (!isTap) return; // タップ終了 isTap = false; //Log.Debug("MouseButtonUp"); if (isSlide) { AdjustNodeStop(); isSlideEnd = true; tapNodeID = Vec2Int.zero; } else { if (tapNodeID.x > -1) { audioSources[(int)_eAudioNumber.ROTATE].Play(); gameNodeScripts[tapNodeID.y][tapNodeID.x].RotationNode(); _isNodeAction = true; } } }*/) .AddTo(gameObject); // ノードのアニメーション終了と同時に接続チェック Observable .EveryUpdate() .Select(x => !(IsNodeAction) && !(isNodeLock)) .DistinctUntilChanged() .Where(x => x) .ThrottleFrame(3) .Subscribe(x => { CheckLink(); }) .AddTo(gameObject); // ノードがアクション中かチェック Observable .EveryUpdate() .Where(_ => _isNodeAction) .Subscribe(_ => { for (int i = 0; i < col; ++i) { foreach (var nodes in gameNodeScripts[i]) { if (nodes.IsAction) return; } } _isNodeAction = false; }) .AddTo(gameObject); // ノードがスライド終了処理中かチェック Observable .EveryUpdate() .Where(_ => isSlideEnd) .Subscribe(_ => { for (int i = 0; i < col; ++i) { foreach (var nodes in gameNodeScripts[i]) { if (nodes.IsSlideEnd) { return; } } } isSlideEnd = false; if (isSlide) { isSlide = false; slideDir = _eSlideDir.NONE; cumSlideIntervalPlaySE = 0.0f; } }) .AddTo(gameObject); // SE再生処理 Observable .EveryUpdate() .Where(_ => isSlide) .Subscribe(_ => { if(cumSlideIntervalPlaySE > slideIntervalPlaySE) { audioSources[(int)_eAudioNumber.SLIDE].Play(); cumSlideIntervalPlaySE = 0.0f; } }) .AddTo(gameObject); Observable .NextFrame() .Subscribe(_ => CheckLink(true, true)) .AddTo(this); }
// ノードのスライド移動処理 void SlideNodes() { ////Log.Debug("SlideNodes"); // スライド対象となるノードの準備 Vector2 deltaSlideDist = tapPos - prevTapPos; // 前回フレームからのスライド量 float checkDir = 0.0f; // スライド方向チェック用 switch (slideDir) { case _eSlideDir.LEFT: case _eSlideDir.RIGHT: // スライド方向を再計算 if (tapPos.x - prevTapPos.x < 0.0f) { // スライド方向が前フレームと違ったら更新 if (slideDir != _eSlideDir.LEFT) { Vec2Int tmp = slidingLimitNodeID; slidingLimitNodeID = slidingReverseLimitNodeID; slidingReverseLimitNodeID = tmp; slideDir = _eSlideDir.LEFT; } } else if (tapPos.x - prevTapPos.x > 0.0f) { if (slideDir != _eSlideDir.RIGHT) { Vec2Int tmp = slidingLimitNodeID; slidingLimitNodeID = slidingReverseLimitNodeID; slidingReverseLimitNodeID = tmp; slideDir = _eSlideDir.RIGHT; } } break; case _eSlideDir.LEFTUP: case _eSlideDir.RIGHTDOWN: // スライド方向を再計算 checkDir = AddVectorFunctions.Vec2Cross(deltaSlideDist, slideLeftUpPerNorm); if (checkDir < 0.0f) { if (slideDir != _eSlideDir.LEFTUP) { Vec2Int tmp = slidingLimitNodeID; slidingLimitNodeID = slidingReverseLimitNodeID; slidingReverseLimitNodeID = tmp; slideDir = _eSlideDir.LEFTUP; } } else if (checkDir > 0.0f) { if (slideDir != _eSlideDir.RIGHTDOWN) { Vec2Int tmp = slidingLimitNodeID; slidingLimitNodeID = slidingReverseLimitNodeID; slidingReverseLimitNodeID = tmp; slideDir = _eSlideDir.RIGHTDOWN; } } break; case _eSlideDir.RIGHTUP: case _eSlideDir.LEFTDOWN: // スライド方向を再計算 checkDir = AddVectorFunctions.Vec2Cross(deltaSlideDist, slideLeftDownPerNorm); if (checkDir < 0.0f) { if (slideDir != _eSlideDir.LEFTDOWN) { Vec2Int tmp = slidingLimitNodeID; slidingLimitNodeID = slidingReverseLimitNodeID; slidingReverseLimitNodeID = tmp; slideDir = _eSlideDir.LEFTDOWN; } } else if (checkDir > 0.0f) { if (slideDir != _eSlideDir.RIGHTUP) { Vec2Int tmp = slidingLimitNodeID; slidingLimitNodeID = slidingReverseLimitNodeID; slidingReverseLimitNodeID = tmp; slideDir = _eSlideDir.RIGHTUP; } } break; default: break; } // ノードを移動 AdjustSlideNodePosition(); }
// スライド方向の逆方向を求める _eSlideDir ReverseDirection(_eSlideDir dir) { _eSlideDir reverse = _eSlideDir.NONE; switch (dir) { case _eSlideDir.LEFT: reverse = _eSlideDir.RIGHT; break; case _eSlideDir.RIGHT: reverse = _eSlideDir.LEFT; break; case _eSlideDir.LEFTUP: reverse = _eSlideDir.RIGHTDOWN; break; case _eSlideDir.LEFTDOWN: reverse = _eSlideDir.RIGHTUP; break; case _eSlideDir.RIGHTUP: reverse = _eSlideDir.LEFTDOWN; break; case _eSlideDir.RIGHTDOWN: reverse = _eSlideDir.LEFTUP; break; } return reverse; }
// _eSlideDir を _eLinkDir に変換する _eLinkDir ConvertSlideDirToLinkDir(_eSlideDir dir) { _eLinkDir convert = _eLinkDir.NONE; switch (dir) { case _eSlideDir.LEFT: convert = _eLinkDir.L; break; case _eSlideDir.RIGHT: convert = _eLinkDir.R; break; case _eSlideDir.LEFTUP: convert = _eLinkDir.LU; break; case _eSlideDir.LEFTDOWN: convert = _eLinkDir.LD; break; case _eSlideDir.RIGHTUP: convert = _eLinkDir.RU; break; case _eSlideDir.RIGHTDOWN: convert = _eLinkDir.RD; break; } return convert; }
// ノード移動処理 public void SlideNode(_eSlideDir dir, Vector2 pos) { // スライド方向が指定されていなければ未処理 if (dir == _eSlideDir.NONE) return; // アクション開始 IsSlide = true; transform.DOKill(); float time = 0.0f; if (IsSlideStart) { time = slideStartTime; transform.DOMoveZ(IN_ACTION_POSZ, 0.0f); } else if (IsSlideEnd) { time = slideEndTime; } else { time = slideTime; } transform.DOMoveX(pos.x, time) .OnComplete(() => { IsSlide = false; if (IsSlideStart) IsSlideStart = false; if (IsSlideEnd) { IsSlideEnd = false; transform.DOMoveZ(0.0f, 0.0f); } }); transform.DOMoveY(pos.y, time); }