override public void Render(DwarfTime gameTime, ChunkManager chunks, Camera camera, SpriteBatch spriteBatch, GraphicsDevice graphicsDevice, Shader effect, bool renderingForWater) { base.Render(gameTime, chunks, camera, spriteBatch, graphicsDevice, effect, renderingForWater); if (Debugger.Switches.DrawRailNetwork) { //Drawer3D.DrawBox(GetContainingVoxel().GetBoundingBox(), Color.White, 0.01f, true); //Drawer3D.DrawLine(GetContainingVoxel().GetBoundingBox().Center(), GlobalTransform.Translation, Color.White, 0.01f); var transform = Matrix.CreateRotationY((float)Math.PI * 0.5f * (float)Piece.Orientation) * GlobalTransform; if (Library.GetRailPiece(Piece.RailPiece).HasValue(out var piece)) { foreach (var spline in piece.SplinePoints) { for (var i = 1; i < spline.Count; ++i) { Drawer3D.DrawLine(Vector3.Transform(spline[i - 1], transform), Vector3.Transform(spline[i], transform), Color.Purple, 0.1f); } } foreach (var connection in piece.EnumerateConnections()) { Drawer3D.DrawLine(Vector3.Transform(connection.Item1, transform) + new Vector3(0.0f, 0.2f, 0.0f), Vector3.Transform(connection.Item2, transform) + new Vector3(0.0f, 0.2f, 0.0f), Color.Brown, 0.1f); } //foreach (var neighborConnection in NeighborRails) //{ // var neighbor = Manager.FindComponent(neighborConnection.NeighborID); // if (neighbor == null) // Drawer3D.DrawLine(Position, Position + Vector3.UnitY, Color.CornflowerBlue, 0.1f); // else // Drawer3D.DrawLine(Position + new Vector3(0.0f, 0.5f, 0.0f), (neighbor as Body).Position + new Vector3(0.0f, 0.5f, 0.0f), Color.Teal, 0.1f); //} } } if (!IsVisible) { return; } if (Primitive == null) { var bounds = Vector4.Zero; var uvs = Sheet.GenerateTileUVs(Frame, out bounds); if (Library.GetRailPiece(Piece.RailPiece).HasValue(out var rawPiece)) { var transform = Matrix.CreateRotationY((float)Math.PI * 0.5f * (float)Piece.Orientation); var realShape = 0; if (rawPiece.AutoSlope) { var transformedConnections = GetTransformedConnections(); var matchingNeighbor1 = NeighborRails.FirstOrDefault(n => (n.Position - transformedConnections[0].Item1 - new Vector3(0.0f, 1.0f, 0.0f)).LengthSquared() < 0.001f); var matchingNeighbor2 = NeighborRails.FirstOrDefault(n => (n.Position - transformedConnections[1].Item1 - new Vector3(0.0f, 1.0f, 0.0f)).LengthSquared() < 0.001f); if (matchingNeighbor1 != null && matchingNeighbor2 != null) { realShape = 3; } else if (matchingNeighbor1 != null) { realShape = 1; } else if (matchingNeighbor2 != null) { realShape = 2; } } Primitive = new RawPrimitive(); Primitive.AddVertex(new ExtendedVertex(Vector3.Transform(new Vector3(-0.5f, VertexHeightOffsets[realShape, 0], 0.5f), transform), Color.White, Color.White, uvs[0], bounds)); Primitive.AddVertex(new ExtendedVertex(Vector3.Transform(new Vector3(0.5f, VertexHeightOffsets[realShape, 1], 0.5f), transform), Color.White, Color.White, uvs[1], bounds)); Primitive.AddVertex(new ExtendedVertex(Vector3.Transform(new Vector3(0.5f, VertexHeightOffsets[realShape, 2], -0.5f), transform), Color.White, Color.White, uvs[2], bounds)); Primitive.AddVertex(new ExtendedVertex(Vector3.Transform(new Vector3(-0.5f, VertexHeightOffsets[realShape, 3], -0.5f), transform), Color.White, Color.White, uvs[3], bounds)); Primitive.AddIndicies(new short[] { 0, 1, 3, 1, 2, 3 }); var sideBounds = Vector4.Zero; Vector2[] sideUvs = null; sideUvs = Sheet.GenerateTileUVs(new Point(3, 4), out sideBounds); AddScaffoldGeometry(transform, sideBounds, sideUvs, -1.0f, false); if (realShape == 3) { AddScaffoldGeometry(transform, sideBounds, sideUvs, 0.0f, false); } else if (realShape == 1) { sideUvs = Sheet.GenerateTileUVs(new Point(0, 4), out sideBounds); AddScaffoldGeometry(transform, sideBounds, sideUvs, 0.0f, true); } else if (realShape == 2) { sideUvs = Sheet.GenerateTileUVs(new Point(0, 4), out sideBounds); AddScaffoldGeometry(transform, sideBounds, sideUvs, 0.0f, false); } // Todo: Make these static and avoid recalculating them constantly. var bumperBackBounds = Vector4.Zero; var bumperBackUvs = Sheet.GenerateTileUVs(new Point(0, 5), out bumperBackBounds); var bumperFrontBounds = Vector4.Zero; var bumperFrontUvs = Sheet.GenerateTileUVs(new Point(1, 5), out bumperFrontBounds); var bumperSideBounds = Vector4.Zero; var bumperSideUvs = Sheet.GenerateTileUVs(new Point(2, 5), out bumperSideBounds); foreach (var connection in GetTransformedConnections()) { var matchingNeighbor = NeighborRails.FirstOrDefault(n => (n.Position - connection.Item1).LengthSquared() < 0.001f); if (matchingNeighbor == null && rawPiece.AutoSlope) { matchingNeighbor = NeighborRails.FirstOrDefault(n => (n.Position - connection.Item1 - new Vector3(0.0f, 1.0f, 0.0f)).LengthSquared() < 0.001f); } if (matchingNeighbor == null) { var bumperOffset = connection.Item1 - GlobalTransform.Translation; var bumperGap = Vector3.Normalize(bumperOffset) * 0.1f; var bumperAngle = AngleBetweenVectors(new Vector2(bumperOffset.X, bumperOffset.Z), new Vector2(0, 0.5f)); var xDiag = bumperOffset.X <-0.001f || bumperOffset.X> 0.001f; var zDiag = bumperOffset.Z <-0.001f || bumperOffset.Z> 0.001f; if (xDiag && zDiag) { var y = bumperOffset.Y; bumperOffset *= sqrt2; bumperOffset.Y = y; var endBounds = Vector4.Zero; var endUvs = Sheet.GenerateTileUVs(new Point(6, 2), out endBounds); Primitive.AddQuad( Matrix.CreateRotationY((float)Math.PI * 1.25f) * Matrix.CreateRotationY(bumperAngle) // This offset would not be correct if diagonals could slope. * Matrix.CreateTranslation(new Vector3(Sign(bumperOffset.X), 0.0f, Sign(bumperOffset.Z))), Color.White, Color.White, endUvs, endBounds); } Primitive.AddQuad( Matrix.CreateRotationX(-(float)Math.PI * 0.5f) * Matrix.CreateTranslation(0.0f, 0.3f, -0.2f) * Matrix.CreateRotationY(bumperAngle) * Matrix.CreateTranslation(bumperOffset + bumperGap), Color.White, Color.White, bumperBackUvs, bumperBackBounds); Primitive.AddQuad( Matrix.CreateRotationX(-(float)Math.PI * 0.5f) * Matrix.CreateTranslation(0.0f, 0.3f, -0.2f) * Matrix.CreateRotationY(bumperAngle) * Matrix.CreateTranslation(bumperOffset), Color.White, Color.White, bumperFrontUvs, bumperFrontBounds); var firstVoxelBelow = VoxelHelpers.FindFirstVoxelBelow(GetContainingVoxel()); if (firstVoxelBelow.IsValid && firstVoxelBelow.RampType == RampType.None) // if (VoxelHelpers.FindFirstVoxelBelow(GetContainingVoxel()).RampType == RampType.None) { Primitive.AddQuad( Matrix.CreateRotationX(-(float)Math.PI * 0.5f) * Matrix.CreateRotationY(-(float)Math.PI * 0.5f) * Matrix.CreateTranslation(0.3f, 0.3f, 0.18f) * Matrix.CreateRotationY(bumperAngle) * Matrix.CreateTranslation(bumperOffset), Color.White, Color.White, bumperSideUvs, bumperSideBounds); Primitive.AddQuad( Matrix.CreateRotationX(-(float)Math.PI * 0.5f) * Matrix.CreateRotationY(-(float)Math.PI * 0.5f) * Matrix.CreateTranslation(-0.3f, 0.3f, 0.18f) * Matrix.CreateRotationY(bumperAngle) * Matrix.CreateTranslation(bumperOffset), Color.White, Color.White, bumperSideUvs, bumperSideBounds); } } } } } // Everything that draws should set it's tint, making this pointless. var under = new VoxelHandle(chunks, GlobalVoxelCoordinate.FromVector3(Position)); if (under.IsValid) { Color color = new Color(under.Sunlight ? 255 : 0, 255, 0); LightRamp = color; } else { LightRamp = new Color(200, 255, 0); } Color origTint = effect.VertexColorTint; if (!Active) { DoStipple(effect); } effect.VertexColorTint = VertexColor; effect.LightRamp = LightRamp; effect.World = GlobalTransform; effect.MainTexture = Sheet.GetTexture(); effect.EnableWind = false; foreach (EffectPass pass in effect.CurrentTechnique.Passes) { pass.Apply(); Primitive.Render(graphicsDevice); } effect.VertexColorTint = origTint; if (!Active) { EndDraw(effect); } }
public override IEnumerable <Status> Run() { Creature.CurrentCharacterMode = Creature.CharacterMode.Walking; Creature.OverrideCharacterMode = false; while (true) { // ERROR CHECKS / INITIALIZING Agent.Physics.Orientation = Physics.OrientMode.RotateY; //Agent.Physics.CollideMode = Physics.CollisionMode.UpDown; List <Creature.MoveAction> path = GetPath(); if (path == null) { SetPath(null); Creature.DrawIndicator(IndicatorManager.StandardIndicators.Question); yield return(Status.Fail); break; } else if (path.Count > 0) { TargetVoxel = path.ElementAt(0).Voxel; } else { yield return(Status.Success); break; } Creature.MoveAction currentAction = path.ElementAt(0); // IF WE ARE MOVING if (TargetVoxel != null) { Agent.Physics.IsSleeping = false; Agent.LocalControlTimeout.Update(DwarfTime.LastTime); ValidPathTimer.Update(DwarfTime.LastTime); // Check if the path has been made invalid if (ValidPathTimer.HasTriggered && !IsPathValid(path)) { Creature.DrawIndicator(IndicatorManager.StandardIndicators.Question); yield return(Status.Fail); } if (Agent.LocalControlTimeout.HasTriggered) { Vector3 target = TargetVoxel.Position + new Vector3(.5f, .5f, .5f); float distToTarget = (target - Agent.Position).Length(); while (distToTarget > 0.1f) { Agent.Position = 0.9f * Agent.Position + 0.1f * target; distToTarget = (target - Agent.Position).Length(); yield return(Status.Running); } Agent.LocalControlTimeout.Reset(Agent.LocalControlTimeout.TargetTimeSeconds); Creature.DrawIndicator(IndicatorManager.StandardIndicators.Question); yield return(Status.Running); } if (PreviousTargetVoxel == null) { LocalTarget = TargetVoxel.Position + new Vector3(0.5f, 0.5f, 0.5f); } else { LocalTarget = MathFunctions.ClosestPointToLineSegment(Agent.Position, PreviousTargetVoxel.Position, TargetVoxel.Position, 0.25f) + new Vector3(0.5f, 0.5f, 0.5f); } Vector3 desiredVelocity = (LocalTarget - Agent.Position); desiredVelocity.Normalize(); desiredVelocity *= Creature.Stats.MaxSpeed; Vector3 output = Agent.Creature.Controller.GetOutput((float)DwarfTime.LastTime.ElapsedGameTime.TotalSeconds, desiredVelocity, Creature.Physics.Velocity); output.Y = 0.0f; Agent.Creature.Physics.ApplyForce(output * 0.25f, (float)DwarfTime.LastTime.ElapsedGameTime.TotalSeconds); float yDifference = (LocalTarget - Agent.Position).Y; if (yDifference > 0.25f) { Agent.Jump(DwarfTime.LastTime); } if (Agent.DrawPath) { Drawer3D.DrawLineList( new List <Vector3> { LocalTarget, Agent.Creature.Physics.GlobalTransform.Translation }, Color.White, 0.01f); List <Vector3> points = path.Select(v => v.Voxel.Position + new Vector3(0.5f, 0.5f, 0.5f)).ToList(); Drawer3D.DrawLineList(points, Color.Red, 0.1f); } bool goToNextNode; if (path.Count > 1) { goToNextNode = (yDifference < 0.05 && (LocalTarget - Agent.Creature.Physics.GlobalTransform.Translation).Length() < 0.5f); } else { goToNextNode = (LocalTarget - Agent.Creature.Physics.GlobalTransform.Translation).Length() < 0.25f; } if (goToNextNode) { if (path.Count > 0) { PreviousTargetVoxel = TargetVoxel; Agent.LocalControlTimeout.Reset(Agent.LocalControlTimeout.TargetTimeSeconds); TargetVoxel = path[0].Voxel; path.RemoveAt(0); } else { PreviousTargetVoxel = null; SetPath(null); yield return(Status.Success); break; } } } else { PreviousTargetVoxel = null; Creature.DrawIndicator(IndicatorManager.StandardIndicators.Question); yield return(Status.Fail); break; } yield return(Status.Running); } }