public RGatheredBall(List <RBall> balls, City dockCity, List <City> path) { state = State.WaitingGathering; subBalls = balls; goPath = path; sourceCity = dockCity; position = GetRGBallPosition(dockCity, dockCity.CurrentFacing); float lineCount = (float)Math.Sqrt(balls.Count); float span = (MathEx.PIf * 2) / lineCount; ballOffsets = new List <Vector3>(balls.Count); for (int i = 0; i < balls.Count; i++) { float row = (float)i / lineCount; float col = (float)Math.IEEERemainder(i, lineCount); float radLng = col * span; float radLat = (2 * row - lineCount) * span; Vector3 positionInGBall = PlanetEarth.GetPosition(radLng, radLat, GBallRadius); Quaternion oriInGBall = Quaternion.RotationMatrix(PlanetEarth.GetOrientation(radLng, radLat)); ballOffsets.Add(positionInGBall); balls[i].Gather(this, positionInGBall + position, oriInGBall); } throwSound = (Normal3DSoundObject)SoundManager.Instance.MakeSoundObjcet("throw", null, 1500); catchSound = (Normal3DSoundObject)SoundManager.Instance.MakeSoundObjcet("catch", null, 1500); }
public override void Parse(GameConfigurationSection sect) { base.Parse(sect); Radius = sect.GetSingle("Radius"); float radLng = MathEx.Degree2Radian(Longitude); float radLat = MathEx.Degree2Radian(Latitude); stdPosition = PlanetEarth.GetPosition(radLng, radLat, PlanetEarth.PlanetRadius); }
public override void InitalizeGraphics(RenderSystem rs) { ForestInfo info; info.Latitude = Latitude; info.Longitude = Longitude; info.Radius = Radius; info.Amount = CurrentAmount; //info.Plants = TreeModelLibrary.Instance.Get(0); model = TreeBatchModelManager.Instance.CreateInstance(rs, info); model.Touch(); Transformation = model.GetWeakResource().Transformation; BoundingSphere = model.GetWeakResource().BoundingVolume; sound = SoundManager.Instance.MakeSoundObjcet("forest", null, BoundingSphere.Radius); sound.Position = BoundingSphere.Center; { float radLng = MathEx.Degree2Radian(Longitude); float radLat = MathEx.Degree2Radian(Latitude); float alt = TerrainData.Instance.QueryHeight(radLng, radLat); stdPosition = PlanetEarth.GetPosition(radLng, radLat, alt * TerrainMeshManager.PostHeightScale + PlanetEarth.PlanetRadius); stdTransform = PlanetEarth.GetOrientation(radLng, radLat); stdTransform.TranslationValue = stdPosition; selectionSphere.Center = stdPosition; selectionSphere.Radius = 200; } FileLocation fl = FileSystem.Instance.Locate("wooden_board_green.mesh", GameFileLocs.Model); board = new Model(ModelManager.Instance.CreateInstance(rs, fl)); board.CurrentAnimation.Clear(); board.CurrentAnimation.Add( new NoAnimaionPlayer( Matrix.Translation(0, 0, 25) * Matrix.Scaling(2.7f, 2.7f, 2.7f) * Matrix.RotationX(-MathEx.PiOver2) * Matrix.RotationY((-MathEx.PIf * 7.0f) / 8.0f) )); }
public override void Parse(GameConfigurationSection sect) { base.Parse(sect); modelName = sect["Model"]; scale = sect.GetSingle("Radius", 1); rot = sect.GetSingle("Amount", 0); float radLng = MathEx.Degree2Radian(Longitude); float radLat = MathEx.Degree2Radian(Latitude); float alt = TerrainData.Instance.QueryHeight(radLng, radLat); Position = PlanetEarth.GetPosition(radLng, radLat, PlanetEarth.PlanetRadius + alt * TerrainMeshManager.PostHeightScale); Orientation = PlanetEarth.GetOrientation(radLng, radLat); }
/// <summary> /// 有两个Map的坐标计算采集车朝向 /// Calculate the orientation by the given 2 points in Map's coordinate, /// which can be converted from long-lat by Map.GetMapCoord /// </summary> /// <param name="pa"></param> /// <param name="pb"></param> /// <returns></returns> Quaternion GetOrientation(Point pa, Point pb) { float alng; float alat; float blng; float blat; // 先得到两个点的经纬度 // first convert the coord to long-lat Map.GetCoord(pa.X, pa.Y, out alng, out alat); Map.GetCoord(pb.X, pb.Y, out blng, out blat); // 法向 // calculate the normal vector(up vector) Vector3 n = PlanetEarth.GetNormal(alng, alat); // 高度 // elevation float altA = map.GetHeight(alng, alat); Vector3 posA = PlanetEarth.GetPosition(alng, alat, altA + PlanetEarth.PlanetRadius); float altB = map.GetHeight(blng, blat); Vector3 posB = PlanetEarth.GetPosition(blng, blat, altB + PlanetEarth.PlanetRadius); Vector3 dir = posB - posA; dir.Normalize(); Vector3 bi = Vector3.Cross(n, dir); bi.Normalize(); n = Vector3.Cross(dir, bi); // 采集车旋转World矩阵由向量基构建 // constitute a final world matrix using these vectors Matrix result = Matrix.Identity; result.Right = bi; result.Up = n; result.Forward = -dir; return(Quaternion.RotationMatrix(result)); }
public OceanWaterTile(RenderSystem rs, OceanWaterDataManager manager, int @long, int lat) : base(false) { renderSystem = rs; PlanetEarth.TileCoord2CoordNew(@long, lat, out tileCol, out tileLat); material = new Material(rs); FileLocation fl = FileSystem.Instance.Locate("WaterNormal.tex", GameFileLocs.Nature); ResourceHandle <Texture> map = TextureManager.Instance.CreateInstance(fl); material.SetTexture(1, map); fl = FileSystem.Instance.Locate("WaterDudv.tex", GameFileLocs.Nature); map = TextureManager.Instance.CreateInstance(fl); material.SetTexture(0, map); material.SetEffect(EffectManager.Instance.GetModelEffect(WaterEffectFactory.Name)); material.IsTransparent = true; material.ZWriteEnabled = false; material.ZEnabled = true; material.CullMode = CullMode.CounterClockwise; material.PriorityHint = RenderPriority.Third; data0 = manager.GetData(Lod0Size, tileLat); //data1 = manager.GetData(Lod1Size, tileLat); float radtc = MathEx.Degree2Radian(tileCol); float radtl = MathEx.Degree2Radian(tileLat); float rad5 = PlanetEarth.DefaultTileSpan * 0.5f; BoundingSphere.Center = PlanetEarth.GetPosition(radtc + rad5, radtl - rad5); BoundingSphere.Radius = PlanetEarth.GetTileHeight(rad5 * 2); Transformation = Matrix.RotationY(radtc); }
protected override void UpdateLocation() { float radLong = MathEx.Degree2Radian(this.Longitude); float radLat = MathEx.Degree2Radian(this.Latitude); float altitude = TerrainData.Instance.QueryHeight(radLong, radLat); IsInOcean = false; if (altitude < 0) { altitude = 0; IsInOcean = true; } this.Position = PlanetEarth.GetPosition(radLong, radLat, PlanetEarth.PlanetRadius + TerrainMeshManager.PostHeightScale * altitude); this.Transformation = PlanetEarth.GetOrientation(radLong, radLat); //this.InvTransformation = Matrix.Invert(Transformation); this.Transformation.TranslationValue = this.Position; // TranslationValue = pos; BoundingSphere.Radius = RulesTable.CityRadius; BoundingSphere.Center = this.Position; }
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; //} }
public OceanWaterData(RenderSystem rs, int size, float lat) { this.Size = size; geoData = new GeomentryData(); ObjectFactory fac = rs.ObjectFactory; vtxDecl = fac.CreateVertexDeclaration(WaterVertex.Elements); int len = size - 1; int vertexCount = size * size; vertexBuffer = fac.CreateVertexBuffer(vertexCount, vtxDecl, BufferUsage.Static); float rad10 = PlanetEarth.DefaultTileSpan; float radtl = MathEx.Degree2Radian(lat); #region 顶点数据 WaterVertex[] vtxArray = new WaterVertex[vertexCount]; float cellAngle = rad10 / (float)len; float invSize = 1 / (float)size; // i为经度方向 for (int i = 0; i < size; i++) { // j为纬度方向 for (int j = 0; j < size; j++) { Vector3 pos = PlanetEarth.GetPosition(j * cellAngle, radtl - i * cellAngle); pos.Normalize(); pos *= PlanetEarth.PlanetRadius; int index = i * size + j; vtxArray[index].Position = pos; vtxArray[index].NormalCoord = new Vector2(i * invSize, j * invSize); // = index; } } vertexBuffer.SetData <WaterVertex>(vtxArray); #endregion #region 索引数据 int indexCount = MathEx.Sqr(len) * 2 * 3; int[] indexArray = new int[indexCount]; indexBuffer = fac.CreateIndexBuffer(IndexBufferType.Bit32, indexCount, BufferUsage.WriteOnly); for (int i = 0, index = 0; i < len; i++) { for (int j = 0; j < len; j++) { int x = i; int y = j; indexArray[index++] = y * size + x; indexArray[index++] = y * size + (x + 1); indexArray[index++] = (y + 1) * size + (x + 1); indexArray[index++] = y * size + x; indexArray[index++] = (y + 1) * size + (x + 1); indexArray[index++] = (y + 1) * size + x; } } indexBuffer.SetData <int>(indexArray); #endregion #region 构造GeomentryData geoData = new GeomentryData(); geoData.VertexDeclaration = vtxDecl; geoData.VertexSize = WaterVertex.Size; geoData.VertexBuffer = vertexBuffer; geoData.IndexBuffer = indexBuffer; geoData.PrimCount = MathEx.Sqr(len) * 2; geoData.VertexCount = MathEx.Sqr(size); geoData.PrimitiveType = RenderPrimitiveType.TriangleList; geoData.BaseVertex = 0; #endregion }
public override void InitalizeGraphics(RenderSystem rs) { float radLng = MathEx.Degree2Radian(Longitude); float radLat = MathEx.Degree2Radian(Latitude); bool isOcean = false; float alt = TerrainData.Instance.QueryHeight(radLng, radLat); if (alt < 0) { alt = 0; isOcean = true; } frameIdx = Randomizer.GetRandomInt(FrameCount - 1); float scale = Game.ObjectScale * 3.7f;// 2.2f; if (isOcean) { model = new Model[FrameCount]; for (int i = 0; i < FrameCount; i++) { FileLocation fl = FileSystem.Instance.Locate("oilderricksea" + i.ToString("D2") + ".mesh", GameFileLocs.Model); model[i] = new Model(ModelManager.Instance.CreateInstance(rs, fl)); model[i].CurrentAnimation.Clear(); model[i].CurrentAnimation.Add(new NoAnimaionPlayer( Matrix.Scaling(scale, scale, scale) * Matrix.Translation(0, 18, 0) * Matrix.RotationY(-MathEx.PiOver4))); } } else { model = new Model[FrameCount]; for (int i = 0; i < FrameCount; i++) { FileLocation fl = FileSystem.Instance.Locate("oilderrick" + i.ToString("D2") + ".mesh", GameFileLocs.Model); model[i] = new Model(ModelManager.Instance.CreateInstance(rs, fl)); model[i].CurrentAnimation.Clear(); model[i].CurrentAnimation.Add(new NoAnimaionPlayer( Matrix.Scaling(scale, scale, scale) * Matrix.RotationY(-MathEx.PiOver4))); } } Position = PlanetEarth.GetPosition(radLng, radLat, PlanetEarth.PlanetRadius + alt * TerrainMeshManager.PostHeightScale); BoundingSphere.Center = position; BoundingSphere.Radius = 200; Orientation = PlanetEarth.GetOrientation(radLng, radLat); sound = SoundManager.Instance.MakeSoundObjcet("oil", null, BoundingSphere.Radius * 8.0f / 3.0f); sound.Position = position; FileLocation fl2 = FileSystem.Instance.Locate("wooden_board_oil.mesh", GameFileLocs.Model); board = new Model(ModelManager.Instance.CreateInstance(rs, fl2)); board.CurrentAnimation.Clear(); board.CurrentAnimation.Add( new NoAnimaionPlayer( Matrix.Translation(-50, 25, 23) * Matrix.Scaling(2.7f, 2.7f, 2.7f) * Matrix.RotationX(-MathEx.PiOver2) * Matrix.RotationY((-MathEx.PIf * 7.0f) / 8.0f) )); }