Beispiel #1
0
		public void		restart()
		{
			this.is_ended = false;
			this.t        = -1.0f;
			this.distance = 0.0f;
			this.cv       = new ControlVertex();
		}
Beispiel #2
0
        // カーブ上の点を求める.
        public ControlVertex    calcVertex(float t)
        {
            ControlVertex cv = null;

            int segment_index = Mathf.FloorToInt(t);

            if (segment_index < 0)
            {
                cv = this.cvs[0];
            }
            else if (this.cvs.Count - 1 <= segment_index)
            {
                cv = this.cvs[this.cvs.Count - 1];
            }
            else
            {
                float[] pos_k = new float[4];
                float[] tan_k = new float[4];

                ControlVertex cv0 = this.cvs[segment_index];
                ControlVertex cv1 = this.cvs[segment_index + 1];

                float local_param = t - (float)segment_index;

                Curve.calc_konst(pos_k, tan_k, local_param);

                cv = Curve.lerp(cv0, cv1, pos_k, tan_k);
            }

            return(cv);
        }
Beispiel #3
0
 public void             restart()
 {
     this.is_ended = false;
     this.t        = -1.0f;
     this.distance = 0.0f;
     this.cv       = new ControlVertex();
 }
Beispiel #4
0
        // カーブの総道のりを計算する.
        public float    calcTotalDistance()
        {
            float distance = 0.0f;

            ControlVertex cv_prev = this.calcVertex(0.0f);

            float t     = 0.0f;
            float dt    = 0.1f;
            float t_max = (float)(this.cvs.Count - 1);

            int safe_count = Mathf.CeilToInt(t_max / dt) + 1;

            for (int i = 0; i < safe_count; i++)
            {
                ControlVertex cv_current = this.calcVertex(t);

                distance += Vector3.Distance(cv_prev.position, cv_current.position);

                if (t >= t_max)
                {
                    break;
                }

                t += dt;

                t = Mathf.Min(t, t_max);

                cv_prev = cv_current;
            }

            return(distance);
        }
Beispiel #5
0
        // ================================================================ //

        // 区間を補間する.
        public static ControlVertex    lerp(ControlVertex cv0, ControlVertex cv1, float[] pos_k, float[] tan_k)
        {
            ControlVertex dest = new ControlVertex();

            dest.position = cv0.position * pos_k[0] + cv1.position * pos_k[1] + cv0.tangent * cv0.tension * pos_k[2] + cv1.tangent * cv1.tension * pos_k[3];
            dest.tangent  = cv0.position * tan_k[0] + cv1.position * tan_k[1] + cv0.tangent * cv0.tension * tan_k[2] + cv1.tangent * cv1.tension * tan_k[3];

            return(dest);
        }
        // ================================================================ //
        // 구간을 보간한다.
        public static ControlVertex lerp(ControlVertex cv0, ControlVertex cv1, float[] pos_k, float[] tan_k)
        {
            ControlVertex dest = new ControlVertex();

            dest.position = cv0.position * pos_k[0] + cv1.position * pos_k[1] + cv0.tangent * cv0.tension * pos_k[2] + cv1.tangent * cv1.tension * pos_k[3];
            dest.tangent = cv0.position * tan_k[0] + cv1.position * tan_k[1] + cv0.tangent * cv0.tension * tan_k[2] + cv1.tangent * cv1.tension * tan_k[3];

            return (dest);
        }
Beispiel #7
0
        public void             appendCV(Vector3 position, Vector3 slope)
        {
            ControlVertex cv = new ControlVertex();

            cv.index    = this.cvs.Count;
            cv.position = position;
            cv.tension  = slope.magnitude;
            cv.tangent  = slope.normalized;

            this.cvs.Add(cv);
        }
        public void appendCV(Vector3 position, Vector3 slope)
        {
            ControlVertex cv = new ControlVertex();

            cv.index = this.cvs.Count;
            cv.position = position;
            cv.tension = slope.magnitude;
            cv.tangent = slope.normalized;

            this.cvs.Add(cv);
        }
Beispiel #9
0
    // ================================================================ //

    // 制御点を更新する(自分の子供から).
    public void             createControlVertices()
    {
        this.curve.cvs.Clear();

        foreach (var i in System.Linq.Enumerable.Range(0, this.transform.childCount))
        {
            GameObject child = this.transform.GetChild(i).gameObject;

            var cv = new SimpleSpline.ControlVertex();

            cv.index    = i;
            cv.position = child.transform.position;
            cv.tangent  = child.transform.TransformDirection(Vector3.forward) * child.transform.localScale.z;
            cv.tension  = 10.0f;

            this.curve.cvs.Add(cv);
        }
    }
Beispiel #10
0
	// ================================================================ //

	// 제어점을 갱신합니다(자신의 자식에서부터).
	public void		createControlVertices()
	{
		this.curve.cvs.Clear();

		foreach(var i in System.Linq.Enumerable.Range(0, this.transform.childCount)) {

			GameObject		child = this.transform.GetChild(i).gameObject;

			var	cv = new SimpleSpline.ControlVertex();

			cv.index    = i;
			cv.position = child.transform.position;
			cv.tangent  = child.transform.TransformDirection(Vector3.forward)*child.transform.localScale.z;
			cv.tension  = 10.0f;

			this.curve.cvs.Add(cv);
		}
	}
Beispiel #11
0
		// 현재 위치에서 나아간다(파라미터 지정).
		public void		proceed(float dt)
		{
			if(!this.is_ended) {

				if(this.t < 0.0f) {

					this.t = 0.0f;

				} else {

					this.t += dt;
				}

				if(this.t >= this.curve.getEnd()) {

					this.t = this.curve.getEnd();
					this.is_ended = true;
				}

				this.cv = this.curve.calcVertex(this.t);
			}
		}
Beispiel #12
0
        // 現在位置から進む(パラメーター指定).
        public void             proceed(float dt)
        {
            if (!this.is_ended)
            {
                if (this.t < 0.0f)
                {
                    this.t = 0.0f;
                }
                else
                {
                    this.t += dt;
                }

                if (this.t >= this.curve.getEnd())
                {
                    this.t        = this.curve.getEnd();
                    this.is_ended = true;
                }

                this.cv = this.curve.calcVertex(this.t);
            }
        }
Beispiel #13
0
		// 현재 위치에서 나아간다(현재 위치로부터의 거리).
		public void		proceedByDistance(float dist)
		{
			do {

				if(this.is_ended) {

					break;
				}

				ControlVertex	cv0;

				if(this.t < 0.0f) {

					this.t = 0.0f;
				}

				cv0 = this.curve.calcVertex(this.t);
				this.cv = cv0;

				//

				float		dt  = dist/this.curve.calcTotalDistance()*this.curve.getEnd();
				float		sdt = dt >= 0.0f ? 1.0f : -1.0f;
							dt  = Mathf.Abs(dt);
				float		dt0 = dt;
				float		t0  = this.t;

				float		advanced  = 0.0f;
				float		advanced0 = advanced;
				int			i;

				// 최대 반복 횟수.
				int			max_times = Mathf.CeilToInt(this.curve.getEnd()/dt);

				max_times = max_times >= 1 ? max_times : 1;

				for(i = 0;i < max_times;i++) {

					t0 = this.t;
					this.t += sdt*dt;

					if(this.t >= this.curve.getEnd() && sdt >= 0.0f) {
	
						this.t = this.curve.getEnd();

						if(dt < dt0) {

							this.is_ended = true;
						}

						dt = Mathf.Max(0.0f, this.t - t0);

					} else if(this.t < 0.0f && sdt < 0.0f) {

						this.t = 0.0f;

						if(dt < dt0) {

							this.is_ended = true;
						}

						dt = Mathf.Max(0.0f, Mathf.Abs(this.t - t0));
					}

					this.cv = this.curve.calcVertex(this.t);

					advanced0 = advanced;
					advanced += Vector3.Distance(cv0.position, this.cv.position);

					if(this.is_ended) {

						break;
					}

					if(advanced >= Mathf.Abs(dist)) {

						// 너무 지나친 경우.
						// 진행 거리를 반으로 나눠서 직전 장소부터 다시 함.

						dt *= 0.5f;

						if(dt < dt0/100.0f) {

							break;
						}

						this.t = t0;
						advanced = advanced0;

					} else {

						cv0 = this.cv;
					}
				}

			} while(false);
		}
Beispiel #14
0
    public override void    execute()
    {
        CameraControl camera = CameraControl.get();

        // ---------------------------------------------------------------- //
        // 다음 상태로 이동할지 체크합니다.

        switch (this.step.do_transition())
        {
        // 이벤트 시작.
        case STEP.START:
        {
            this.step.set_next(STEP.OPEN_DOOR);
            //camera.module.parallelMoveTo(this.get_locator_position("cam_loc_0"));

            Debug.Log("Name:" + this.player.controll.account_name);

            foreach (ItemManager.ItemState istate in GlobalParam.get().item_table.Values)
            {
                Debug.Log("Item:" + istate.item_id + " Own:" + istate.owner + " State:" + istate.state);

                if (istate.owner == this.player.controll.account_name &&
                    istate.state == ItemController.State.Picked)
                {
                    // 이미 아이템을 획득했다면 가지고 갈 수 있게 합니다.
                    ItemManager.get().activeItme(istate.item_id, true);
                    ItemManager.get().finishGrowingItem(istate.item_id);
                    QueryItemPick query = this.player.controll.cmdItemQueryPick(istate.item_id, false, true);
                    if (query != null)
                    {
                        query.is_anon = true;
                        query.set_done(true);
                        query.set_success(true);
                    }
                    ItemManager.get().setVisible(istate.item_id, true);
                }
            }

            // 리모트에서 이사 중은 로컬도 이사합니다.
            do
            {
                MovingData moving = GlobalParam.get().remote_moving;
                if (!moving.moving)
                {
                    break;
                }

                chrController remote = CharacterRoot.get().findCharacter(moving.characterId);
                if (remote == null)
                {
                    break;
                }

                chrBehaviorNet remote_player = remote.behavior as chrBehaviorNet;
                if (remote_player == null)
                {
                    break;
                }

                chrBehaviorNPC_House house = CharacterRoot.getInstance().findCharacter <chrBehaviorNPC_House>(moving.houseId);
                if (house == null)
                {
                    break;
                }

                Debug.Log("House move event call:" + moving.characterId + ":" + moving.houseId);

                remote_player.beginHouseMove(house);

                // '이사중~' 말풍선 표시.
                house.startHouseMove();
            } while(false);
        }
        break;

        // 배추가 옆으로 움직이고 & 대야를 타고 플레이어가 등장.
        case STEP.OPEN_DOOR:
        {
            if (this.hakusai_fcurve.isDone() && this.tarai_fcurve.isDone())
            {
                this.step.set_next(STEP.GET_OFF_TARAI_0);
            }
        }
        break;

        // 대야에서 내립니다(기슭으로 점프).
        case STEP.GET_OFF_TARAI_0:
        {
            if (!this.player_jump.isMoving())
            {
                this.step.set_next(STEP.GET_OFF_TARAI_1);
            }
        }
        break;

        // 대야에서 내립니다(조금 걷기).
        case STEP.GET_OFF_TARAI_1:
        {
            if (!this.player_move.isMoving())
            {
                this.step.set_next(STEP.CLOSE_DOOR);
            }
        }
        break;


        // 배추가 돌아오고 & 대야가 밖으로 이동.
        case STEP.CLOSE_DOOR:
        {
            if (this.hakusai_fcurve.isDone() && this.tarai_fcurve.isDone())
            {
                this.step.set_next(STEP.END);
            }
        }
        break;

        case STEP.END:
        {
            camera.module.popPosture();

            this.step.set_next(STEP.IDLE);
        }
        break;
        }

        // ---------------------------------------------------------------- //
        // 상태가 전환됐을 때의 초기화.

        while (this.step.get_next() != STEP.NONE)
        {
            dbwin.console().print(this.step.ToString());

            switch (this.step.do_initialize())
            {
            // 이벤트 시작.
            case STEP.START:
            {
                camera.module.pushPosture();

                this.player.beginOuterControll();
                this.player.controll.cmdSetPosition(this.tarai_leave_spline.curve.cvs.back().position);

                this.tarai_fune.transform.position = this.tarai_leave_spline.curve.cvs.back().position;

                if (!this.is_local_player)
                {
                    SoundManager.get().playSE(Sound.ID.SMN_JINGLE01);
                }
            }
            break;

            // 배추가 옆으로 이동하고 & 대야를 타고 플레이어가 등장.
            case STEP.OPEN_DOOR:
            {
                this.hakusai_set.setControl(true);
                this.hakusai_fcurve.setSlopeAngle(10.0f, 10.0f);
                this.hakusai_fcurve.setDuration(4.0f);
                this.hakusai_fcurve.start();
                this.hakusai_tracer.restart();

                this.tarai_fcurve.setSlopeAngle(60.0f, 5.0f);
                this.tarai_fcurve.setDuration(3.5f);
                this.tarai_fcurve.setDelay(0.5f);
                this.tarai_fcurve.start();
            }
            break;

            // 대야에서 내립니다(기슭으로 점프).
            case STEP.GET_OFF_TARAI_0:
            {
                Vector3 start = this.player.controll.getPosition();
                Vector3 goal  = this.get_locator_position("chr_loc_0");

                this.player_jump.start(start, goal, 1.0f);
            }
            break;

            // 대야에서 내립니다(조금 걷기).
            case STEP.GET_OFF_TARAI_1:
            {
                this.player_move.position.start = this.player.controll.getPosition();
                this.player_move.position.goal  = this.get_locator_position("chr_loc_1");
                this.player_move.startConstantVelocity(chrBehaviorLocal.MOVE_SPEED);
            }
            break;

            // 배추가 돌아오고 & 대야가 밖으로 이동.
            case STEP.CLOSE_DOOR:
            {
                this.hakusai_fcurve.setSlopeAngle(10.0f, 10.0f);
                this.hakusai_fcurve.setDuration(4.0f);
                this.hakusai_fcurve.setDelay(1.0f);
                this.hakusai_fcurve.start();
                this.hakusai_tracer.restart();
                this.hakusai_tracer.setCurrentByDistance(this.hakusai_tracer.curve.calcTotalDistance());

                this.tarai_tracer.attach(this.tarai_enter_spline.curve);
                this.tarai_tracer.restart();
                this.tarai_fcurve.reset();
                this.tarai_fcurve.setSlopeAngle(10.0f, 60.0f);
                this.tarai_fcurve.setDuration(2.5f);
                this.tarai_fcurve.start();

                this.ripple_effect.is_created = false;
            }
            break;

            case STEP.END:
            {
                // 이벤트 종료.
                this.hakusai_set.reset();
                this.hakusai_set.setControl(false);

                this.player.endOuterControll();

                this.player = null;
            }
            break;
            }
        }

        // ---------------------------------------------------------------- //
        // 각 상태에서의 실행 처리.

        switch (this.step.do_execution(Time.deltaTime))
        {
        // 배추가 옆으로 움직인다 & 대야를 타고 플레이어가 등장..
        case STEP.OPEN_DOOR:
        {
            this.hakusai_fcurve.execute(Time.deltaTime);
            this.hakusai_tracer.proceedToDistance(this.hakusai_tracer.curve.calcTotalDistance() * this.hakusai_fcurve.getValue());
            this.hakusai_set.setPosition(this.hakusai_tracer.cv.position);

            this.tarai_fcurve.execute(Time.deltaTime);
            this.tarai_tracer.proceedToDistance(this.tarai_tracer.curve.calcTotalDistance() * (1.0f - this.tarai_fcurve.getValue()));

            SimpleSpline.ControlVertex cv = this.tarai_tracer.getCurrent();

            this.tarai_fune.setPosition(cv.position);
            this.player.controll.cmdSetPosition(cv.position);
            this.player.controll.cmdSmoothHeadingTo(cv.position - cv.tangent.Y(0.0f));

            if (this.tarai_fcurve.isTriggerDone())
            {
                this.ripple_effect.is_created = false;
            }
        }
        break;

        // 대야에서 내립니다(기슭을 향해 점프).
        case STEP.GET_OFF_TARAI_0:
        {
            this.player_jump.execute(Time.deltaTime);
            this.player.controll.cmdSetPosition(this.player_jump.position);
            this.player.controll.cmdSmoothHeadingTo(this.player_jump.goal);
        }
        break;

        // 대야에서 내립니다(조금 걷는다).
        case STEP.GET_OFF_TARAI_1:
        {
            this.player_move.execute(Time.deltaTime);
            this.player.controll.cmdSetPosition(this.player_move.position.current);
            this.player.controll.cmdSmoothHeadingTo(this.player_move.position.goal);
            this.player.playWalkMotion();
        }
        break;

        // 배추가 돌아옵니다 & 대야가 밖으로 이동.
        case STEP.CLOSE_DOOR:
        {
            this.hakusai_fcurve.execute(Time.deltaTime);
            this.hakusai_tracer.proceedToDistance(this.hakusai_tracer.curve.calcTotalDistance() * (1.0f - this.hakusai_fcurve.getValue()));
            this.hakusai_set.setPosition(this.hakusai_tracer.getCurrent().position);

            this.tarai_fcurve.execute(Time.deltaTime);
            this.tarai_tracer.proceedToDistance(this.tarai_tracer.curve.calcTotalDistance() * (1.0f - this.tarai_fcurve.getValue()));
            this.tarai_fune.transform.position = this.tarai_tracer.getCurrent().position;
            this.player.stopWalkMotion();
        }
        break;
        }

        // 대야 뒤에 나오는 물결.
        if (!this.ripple_effect.is_created || Vector3.Distance(this.ripple_effect.last_position, this.tarai_fune.getPosition()) > 2.0f)
        {
            this.ripple_effect.is_created    = true;
            this.ripple_effect.last_position = this.tarai_fune.transform.position;

            EffectRoot.get().createRipple(this.ripple_effect.last_position);
        }

        // ---------------------------------------------------------------- //
    }
Beispiel #15
0
        // 現在位置から進む(現在位置からの道のり).
        public void             proceedByDistance(float dist)
        {
            do
            {
                if (this.is_ended)
                {
                    break;
                }

                ControlVertex cv0;

                if (this.t < 0.0f)
                {
                    this.t = 0.0f;
                }

                cv0     = this.curve.calcVertex(this.t);
                this.cv = cv0;

                //

                float dt  = dist / this.curve.calcTotalDistance() * this.curve.getEnd();
                float sdt = dt >= 0.0f ? 1.0f : -1.0f;
                dt = Mathf.Abs(dt);
                float dt0 = dt;
                float t0  = this.t;

                float advanced  = 0.0f;
                float advanced0 = advanced;
                int   i;

                // 差大繰り返し回数.
                int max_times = Mathf.CeilToInt(this.curve.getEnd() / dt);

                max_times = max_times >= 1 ? max_times : 1;

                for (i = 0; i < max_times; i++)
                {
                    t0      = this.t;
                    this.t += sdt * dt;

                    if (this.t >= this.curve.getEnd() && sdt >= 0.0f)
                    {
                        this.t = this.curve.getEnd();

                        if (dt < dt0)
                        {
                            this.is_ended = true;
                        }

                        dt = Mathf.Max(0.0f, this.t - t0);
                    }
                    else if (this.t < 0.0f && sdt < 0.0f)
                    {
                        this.t = 0.0f;

                        if (dt < dt0)
                        {
                            this.is_ended = true;
                        }

                        dt = Mathf.Max(0.0f, Mathf.Abs(this.t - t0));
                    }

                    this.cv = this.curve.calcVertex(this.t);

                    advanced0 = advanced;
                    advanced += Vector3.Distance(cv0.position, this.cv.position);

                    if (this.is_ended)
                    {
                        break;
                    }

                    if (advanced >= Mathf.Abs(dist))
                    {
                        // 行き過ぎた場合.
                        // 進む距離を半分にして、直前の場所からやり直し.

                        dt *= 0.5f;

                        if (dt < dt0 / 100.0f)
                        {
                            break;
                        }

                        this.t   = t0;
                        advanced = advanced0;
                    }
                    else
                    {
                        cv0 = this.cv;
                    }
                }
            } while(false);
        }
Beispiel #16
0
    public override void    execute()
    {
        CameraControl camera = CameraControl.get();

        // ---------------------------------------------------------------- //
        // 다음 상태로 이행할지 체크합니다..

        switch (this.step.do_transition())
        {
        // 이벤트 시작.
        case STEP.START:
        {
            this.step.set_next(STEP.OPEN_DOOR);
            //camera.module.parallelMoveTo(this.get_locator_position("cam_loc_0"));

            // 맵에 연관되지 않은 아이템은 가지고 돌아감.
            bool           isPickingup = false;
            string         current_map = MapCreator.get().getCurrentMapName();
            ItemController itemYuzu    = ItemManager.get().findItem("Yuzu");
            if (itemYuzu != null && itemYuzu.isActive())
            {
                if (current_map != itemYuzu.getProduction())
                {
                    // 가지고 돌아기는 아이템이 있었다.
                    this.player.controll.cmdItemQueryPick(itemYuzu.name, true, true);
                    isPickingup = true;
                }
            }

            ItemController itemNegi = ItemManager.get().findItem("Negi");
            if (itemNegi != null && itemNegi.isActive())
            {
                if (current_map != itemNegi.getProduction())
                {
                    // 가지고 돌아가는 아이템이 있었다.
                    this.player.controll.cmdItemQueryPick(itemNegi.name, true, true);
                    isPickingup = true;
                }
            }

            if (this.player.controll.item_carrier.isCarrying() && isPickingup == false)
            {
                ItemController item = this.player.controll.item_carrier.getItem();
                if (item.isExportable() == false)
                {
                    // 가지고 나갈 수 없는 것은 두고 갑니다.
                    QueryItemDrop query_drop = this.player.controll.cmdItemQueryDrop();

                    query_drop.is_drop_done = true;

                    this.player.controll.cmdItemDrop(this.player.controll.account_name);
                }
            }
        }
        break;

        // 배추가 옆으로 움직이고 & 대야가 등장.
        case STEP.OPEN_DOOR:
        {
            if (this.hakusai_fcurve.isDone() && this.tarai_fcurve.isDone())
            {
                this.step.set_next(STEP.RIDE_TARAI_0);
            }
        }
        break;

        // 대야를 탑니다(기슭까지 걷는다).
        case STEP.RIDE_TARAI_0:
        {
            if (!this.player_move.isMoving())
            {
                this.step.set_next(STEP.RIDE_TARAI_1);
            }
        }
        break;

        // 대야를 탑니다(대야를 향해 점프).
        case STEP.RIDE_TARAI_1:
        {
            if (!this.player_jump.isMoving())
            {
                this.step.set_next(STEP.CLOSE_DOOR);
            }
        }
        break;

        // 배추가 돌아오고 & 대야가 밖을 향해 이동.
        case STEP.CLOSE_DOOR:
        {
            if (this.hakusai_fcurve.isDone() && this.tarai_fcurve.isDone())
            {
                this.step.set_next(STEP.END);
            }
        }
        break;

        case STEP.END:
        {
            camera.module.popPosture();

            this.step.set_next(STEP.IDLE);
        }
        break;
        }

        // ---------------------------------------------------------------- //
        // 상태가 전환할 때의 초기화.

        while (this.step.get_next() != STEP.NONE)
        {
            dbwin.console().print(this.step.ToString());

            switch (this.step.do_initialize())
            {
            // 이벤트 시작.
            case STEP.START:
            {
                camera.module.pushPosture();

                this.player.beginOuterControll();
                this.tarai_fune.transform.position = this.tarai_enter_spline.curve.cvs.front().position;
            }
            break;

            // 배추가 옆으로 움직이고 & 대야가 등장.
            case STEP.OPEN_DOOR:
            {
                this.hakusai_set.setControl(true);
                this.hakusai_fcurve.setSlopeAngle(10.0f, 10.0f);
                this.hakusai_fcurve.setDuration(4.0f);
                this.hakusai_fcurve.start();
                this.hakusai_tracer.restart();

                this.tarai_fcurve.setSlopeAngle(60.0f, 10.0f);
                this.tarai_fcurve.setDuration(2.0f);
                this.tarai_fcurve.setDelay(2.0f);
                this.tarai_fcurve.start();
            }
            break;

            // 대야를 탑니다(기슭까지 걷는다).
            case STEP.RIDE_TARAI_0:
            {
                this.player_move.position.start = this.player.controll.getPosition();
                this.player_move.position.goal  = this.get_locator_position("chr_loc_0");
                this.player_move.startConstantVelocity(chrBehaviorLocal.MOVE_SPEED);
            }
            break;

            // 대야를 탑니다(대야를 향해서 점프).
            case STEP.RIDE_TARAI_1:
            {
                Vector3 start = this.player.controll.getPosition();
                Vector3 goal  = this.tarai_enter_spline.curve.cvs.back().position;

                this.player_jump.start(start, goal, 1.0f);
            }
            break;

            // 배추가 돌아오고 & 대야가 밖을 향해 이동.
            case STEP.CLOSE_DOOR:
            {
                this.hakusai_fcurve.setSlopeAngle(10.0f, 10.0f);
                this.hakusai_fcurve.setDuration(4.0f);
                this.hakusai_fcurve.start();
                this.hakusai_tracer.restart();
                this.hakusai_tracer.setCurrentByDistance(this.hakusai_tracer.curve.calcTotalDistance());

                this.tarai_tracer.attach(this.tarai_leave_spline.curve);
                this.tarai_tracer.restart();
                this.tarai_fcurve.reset();
                this.tarai_fcurve.setSlopeAngle(20.0f, 60.0f);
                this.tarai_fcurve.setDuration(2.0f);
                this.tarai_fcurve.start();
            }
            break;

            case STEP.END:
            {
                // 이벤트 종료.
                this.hakusai_set.reset();
                this.hakusai_set.setControl(false);

                if (this.is_local_player)
                {
                    if (this.is_map_change)
                    {
                        GlobalParam.get().skip_enter_event = false;
                        GlobalParam.get().fadein_start     = false;

                        if (GlobalParam.get().is_in_my_home)
                        {
                            GameRoot.get().step.set_next(GameRoot.STEP.VISIT);
                        }
                        else
                        {
                            GameRoot.get().step.set_next(GameRoot.STEP.GO_HOME);
                        }

                        // 정원 이동을 알림.
                        if (GlobalParam.get().request_move_home)
                        {
                            Debug.Log("NotifyFieldMoving Leave END.");
                            GameRoot.get().NotifyFieldMoving();
                        }
                    }
                    else
                    {
                        GlobalParam.get().is_in_my_home = !GlobalParam.get().is_in_my_home;
                        this.player.controll.cmdSetPosition(this.initial_player_position);
                        this.player.endOuterControll();
                    }
                }
                else
                {
                    // 아이템을 비활성화하고 나서 드롭하지 않으면 재생합니다.

                    ItemBehaviorFruit fruit = this.player.controll.getCarriedItem <ItemBehaviorFruit>();

                    if (fruit != null)
                    {
                        fruit.activeItem(false);
                    }

                    // 맵 이동이 없을 때 아이템을 가지고 돌아온 경우 아이템의 게임 오브젝트를.
                    // 폐기하지 않게 하고자 아이템을 버립니다.
                    this.player.controll.cmdItemDrop(this.player.name);

                    CharacterRoot.get().deletaCharacter(this.player.controll);
                }

                this.player = null;
            }
            break;
            }
        }

        // ---------------------------------------------------------------- //
        // 각 상태에서의 실행 처리.

        switch (this.step.do_execution(Time.deltaTime))
        {
        // 배추가 옆으로 움직이고 & 대야가 등장.
        case STEP.OPEN_DOOR:
        {
            this.hakusai_fcurve.execute(Time.deltaTime);
            this.hakusai_tracer.proceedToDistance(this.hakusai_tracer.curve.calcTotalDistance() * this.hakusai_fcurve.getValue());
            this.hakusai_set.setPosition(this.hakusai_tracer.getCurrent().position);

            this.tarai_fcurve.execute(Time.deltaTime);
            this.tarai_tracer.proceedToDistance(this.tarai_tracer.curve.calcTotalDistance() * this.tarai_fcurve.getValue());
            this.tarai_fune.setPosition(this.tarai_tracer.getCurrent().position);

            if (this.tarai_fcurve.isTriggerDone())
            {
                this.ripple_effect.is_created = false;
            }
        }
        break;

        // 대야를 탑니다(기슭까지 걷는다).
        case STEP.RIDE_TARAI_0:
        {
            this.player_move.execute(Time.deltaTime);
            this.player.controll.cmdSetPosition(this.player_move.position.current);
            this.player.controll.cmdSmoothHeadingTo(this.player_move.position.goal);
            this.player.playWalkMotion();
        }
        break;

        // 대야를 탑니다(대야를 향해서 점프).
        case STEP.RIDE_TARAI_1:
        {
            this.player_jump.execute(Time.deltaTime);
            this.player.controll.cmdSetPosition(this.player_jump.position);
            this.player.controll.cmdSmoothHeadingTo(this.player_jump.goal);
            this.player.stopWalkMotion();

            if (this.player_jump.is_trigger_bounce && this.player_jump.bounce_count == 1)
            {
                this.ripple_effect.is_created = false;
            }
        }
        break;

        // 배추가 돌아오고 & 대야가 밖을 향해 이동.
        case STEP.CLOSE_DOOR:
        {
            this.hakusai_fcurve.execute(Time.deltaTime);
            this.hakusai_tracer.proceedToDistance(this.hakusai_tracer.curve.calcTotalDistance() * (1.0f - this.hakusai_fcurve.getValue()));
            this.hakusai_set.setPosition(this.hakusai_tracer.cv.position);

            this.tarai_fcurve.execute(Time.deltaTime);
            this.tarai_tracer.proceedToDistance(this.tarai_tracer.curve.calcTotalDistance() * this.tarai_fcurve.getValue());

            SimpleSpline.ControlVertex cv = this.tarai_tracer.getCurrent();

            this.tarai_fune.setPosition(cv.position);
            this.player.controll.cmdSetPosition(cv.position);
            this.player.controll.cmdSmoothHeadingTo(cv.position + cv.tangent.Y(0.0f));
            this.player.stopWalkMotion();
        }
        break;
        }

        // 대야 뒤에 나오는 물결.
        if (!this.ripple_effect.is_created || Vector3.Distance(this.ripple_effect.last_position, this.tarai_fune.getPosition()) > 2.0f)
        {
            this.ripple_effect.is_created    = true;
            this.ripple_effect.last_position = this.tarai_fune.transform.position;

            EffectRoot.get().createRipple(this.ripple_effect.last_position);
        }

        // ---------------------------------------------------------------- //
    }