/// <summary> /// 当寻路需要RCPF的时候,调用这个继续寻路 /// This Move is used when the pathing finding requires continues finding /// </summary> /// <param name="x"></param> /// <param name="y"></param> void Move(int x, int y) { int sx, sy; Map.GetMapCoord(longtitude, latitude, out sx, out sy); destX = x; destY = y; finder.Reset(); currentPath = finder.FindPath(sx, sy, x, y); currentNode = 0; nodeMotionProgress = 0; }
public override void Update(GameTime dt) { float ddt = (float)dt.ElapsedGameTimeSeconds; #region 装货卸货 // Process the loading/unloading if (isLoading && exRes != null) { if (harvStorage < props.Storage) { // 计算开矿倍数,保证能够完成卸货 // calculate the loading/unloading ratio, to ensure with this speed multiplier // the harvester can finish the job in time. float scale = props.Storage / (RulesTable.HarvLoadingSpeed * RulesTable.HarvLoadingTime); harvStorage += exRes.Exploit(RulesTable.HarvLoadingSpeed * ddt * scale); } loadingTime -= ddt; // 开矿loadingTime时间之后,停止并引发事件 // when the time runs out, stop to raise the event if (loadingTime < 0) { isFullLoaded = harvStorage >= props.Storage; isLoading = false; if (GotThere != null) GotThere(this, EventArgs.Empty); } } //else //{ // isFullLoaded = true; // loadingTime = 0; // if (GotThere != null) // GotThere(this, EventArgs.Empty); //} if (isUnloading) { // 计算开矿倍数,保证能够完成卸货 // calculate the loading/unloading ratio, to ensure with this speed multiplier // the harvester can finish the job in time. float scale = props.Storage / (RulesTable.HarvLoadingSpeed * RulesTable.HarvLoadingTime); float change = RulesTable.HarvLoadingSpeed * ddt * scale; // 检查车上的存量是否足够 // check if remaining storage is enough if (harvStorage - change > 0) { // 足够时定量卸下 // unload all when enough harvStorage -= change; // 并且通知城市得到资源 // and tell the city the amount of resource obtained parent.NotifyGotResource(change); } else { // 不够时把剩下的都卸了 // otherwise, unload all the remains parent.NotifyGotResource(harvStorage); harvStorage = 0; } loadingTime -= ddt; // 一定时间后停止 // when the time runs out, stop to raise the event if (loadingTime < 0) { isUnloading = false; if (GotHome != null) GotHome(this, EventArgs.Empty); } } #endregion float altitude = map.GetHeight(longtitude, latitude); if (currentPath != null) { int nextNode = currentNode + 1; if (nextNode >= currentPath.NodeCount) { #region 寻路完毕,状态转换 // when the path following is finished, by reaching the final node // switch to new state nextNode = 0; nodeMotionProgress = 0; if (currentPath.RequiresPathFinding) { // continues path finding Move(destX, destY); } else { // stop by setting null currentPath = null; if (movePurpose == MovePurpose.Gather) { isLoading = true; loadingTime = RulesTable.HarvLoadingTime; } else if (movePurpose == MovePurpose.Home) { isUnloading = true; loadingTime = RulesTable.HarvLoadingTime; } } #endregion } else { #region 路径节点插值 // calculate the interpolation between 2 nodes // 采集车在每两个节点之间移动都是一定过程 // 其位置/朝向是插值结果。差值参数为nodeMotionProgress // The locomotion of harvester between 2 MoveNode is a process in time. // Its position and orientation is the result of interpolation, where // nodeMotionProgress is the interpolation amount. Point cp = currentPath[currentNode]; Point np = currentPath[nextNode]; // 在一开始就尝试获取下一节点位置 // Check if the position in the next 2 MoveNodes need to be updated, // as parameters to calculate translation if (!stateUpdated) { if (isAdjustingDirection) { // 在调整方向时,车是位置不动的 // The car does not move when changing direction Map.GetCoord(np.X, np.Y, out src.Longitude, out src.Latitude); src.Alt = map.GetHeight(src.Longitude, src.Latitude); target.Longitude = src.Longitude; target.Latitude = src.Latitude; target.Alt = src.Alt; } else { Map.GetCoord(cp.X, cp.Y, out src.Longitude, out src.Latitude); Map.GetCoord(np.X, np.Y, out target.Longitude, out target.Latitude); src.Alt = map.GetHeight(src.Longitude, src.Latitude); target.Alt = map.GetHeight(target.Longitude, target.Latitude); } stateUpdated = true; } // 在进行了一半之后开始获取下一节点朝向 // When the interpolation amount run over 0.5, update the // information for orientation of the next 2 nodes, as parameters to calculate // turning. if (nodeMotionProgress > 0.5f && !rotUpdated) { if (isAdjustingDirection) { target.Ori = GetOrientation(cp, np); } else { if (nextNode < currentPath.NodeCount - 1) { src.Ori = GetOrientation(cp, np); target.Ori = GetOrientation(np, currentPath[nextNode + 1]); } else { target.Ori = GetOrientation(cp, np); src.Ori = target.Ori; } } rotUpdated = true; } if (!isAdjustingDirection) { float x = MathEx.LinearInterpose(cp.X, np.X, nodeMotionProgress); float y = MathEx.LinearInterpose(cp.Y, np.Y, nodeMotionProgress); Map.GetCoord(x, y, out longtitude, out latitude); } altitude = MathEx.LinearInterpose(src.Alt, target.Alt, nodeMotionProgress); #region 动画控制 // Animate by changing the index // Car have a different look when on water if (altitude < 0) mdlIndex++; else mdlIndex--; if (mdlIndex < 0) mdlIndex = 0; if (mdlIndex >= NumModels) mdlIndex = NumModels - 1; if (model != null) { if (parent.Owner != null) { if (parent.Type == CityType.Oil) { ModelL0 = model_bad[mdlIndex]; } else { ModelL0 = model[mdlIndex]; } } else { ModelL0 = null; } } #endregion // 采集车不会潜水 // Keep the car not diving if (altitude < 0) altitude = 0; // 球面插值,计算出朝向 // Spherical interpolation for direction Orientation = Matrix.RotationQuaternion( Quaternion.Slerp(src.Ori, target.Ori, nodeMotionProgress > 0.5f ? nodeMotionProgress - 0.5f : nodeMotionProgress + 0.5f)); if (isAdjustingDirection) { nodeMotionProgress += 0.5f * ddt; } else { // 挺进节点插值进度 // Progress the interpolation between 2 nodes nodeMotionProgress += 0.05f * acceleration; } // 检查节点之间插值是否完成 // Check if the interpolation is done if (nodeMotionProgress > 1) { nodeMotionProgress = 0; if (isAdjustingDirection) // 我们只允许调整方向一次,调整这次不会让车在节点上移动,currentNode不变 // We only allow adjust the direction once isAdjustingDirection = false; else currentNode++; rotUpdated = false; stateUpdated = false; } #endregion } #region 加速度计算 // Calculate the acceleration if (currentPath != null) { // 检查是否是最后一个节点了 // Check if this is the last node if (nextNode == currentPath.NodeCount - 1) { // 开始减速 // Deceleration acceleration -= ddt * 1.5f; // 防止减速的过慢 // Set the minimum if (acceleration < 0.33f) acceleration = 0.33f; } else if (!isAdjustingDirection) { // 平时都是加速到最大为止 // otherwise, increase to full speed acceleration += ddt * 1.5f; if (acceleration > 1) acceleration = 1; } } #endregion } else { acceleration = 0; } //Orientation *= PlanetEarth.GetOrientation(longtitude, latitude); // 通过插值计算的经纬度得到坐标 // The position is obtained by the interpolated long-lat coordinate Position = PlanetEarth.GetPosition(longtitude, latitude, PlanetEarth.PlanetRadius + altitude); base.Update(dt); BattleField field = map.Field; if (parent != null && parent.Owner != null && parent.Owner.Type == PlayerType.LocalHuman) { field.Fog.LightArea(longtitude, latitude, MathEx.Degree2Radian(5)); } Visibility = field.Fog.GetVisibility(longtitude, latitude); //if (IsSelected && IsInVisibleRange) //{ // IsSelected = false; //} }
/// <summary> /// 让采集车移动到有经纬度确定的地点 /// Ask the harvester to move to a given location, which is represented /// by longtitude and latitude /// </summary> /// <param name="lng"></param> /// <param name="lat"></param> public void Move(float lng, float lat) { //IsAuto = false; movePurpose = MovePurpose.None; int sx, sy; Map.GetMapCoord(longtitude, latitude, out sx, out sy); int tx, ty; Map.GetMapCoord(lng, lat, out tx, out ty); destX = tx; destY = ty; finder.Reset(); currentPath = finder.FindPath(sx, sy, tx, ty); // 新的动作要先调整朝向 // Adjust direction before going isAdjustingDirection = true; currentNode = 0; nodeMotionProgress = 0; }