A stealth-based 2D platformer where you don't have to kill anyone unless you want to. https://www.semicolin.games
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

139 lines
5.3 KiB

  1. using Microsoft.Xna.Framework;
  2. using Microsoft.Xna.Framework.Graphics;
  3. using System;
  4. using System.Collections.Generic;
  5. namespace SemiColinGames {
  6. public sealed class TreeScene : IScene {
  7. const int MAX_SEGMENTS = 1000;
  8. const int MAX_VERTICES = MAX_SEGMENTS * 6; // 2 triangles per segment
  9. private readonly Color backgroundColor = Color.SkyBlue;
  10. private readonly GraphicsDevice graphics;
  11. private readonly BasicEffect basicEffect;
  12. private VertexPositionColor[] vertices;
  13. private VertexBuffer vertexBuffer;
  14. public TreeScene(GraphicsDevice graphics) {
  15. this.graphics = graphics;
  16. basicEffect = new BasicEffect(graphics) {
  17. World = Matrix.CreateTranslation(0, 0, 0),
  18. View = Matrix.CreateLookAt(Vector3.Backward, Vector3.Zero, Vector3.Up),
  19. VertexColorEnabled = true,
  20. Projection = Matrix.CreateOrthographicOffCenter(-1920 / 2, 1920 / 2, -1080 / 4, 1080 * 3 / 4, -1, 1)
  21. };
  22. vertices = new VertexPositionColor[MAX_VERTICES];
  23. vertexBuffer = new VertexBuffer(
  24. graphics, typeof(VertexPositionColor), MAX_VERTICES, BufferUsage.WriteOnly);
  25. }
  26. ~TreeScene() {
  27. Dispose();
  28. }
  29. public void Dispose() {
  30. vertexBuffer.Dispose();
  31. GC.SuppressFinalize(this);
  32. }
  33. public struct Trapezoid {
  34. public Vector2 p1, p2, p3, p4;
  35. }
  36. public class TreeNode {
  37. public float Orientation; // relative to parent
  38. public float Length;
  39. public float InWidth;
  40. public float OutWidth;
  41. public readonly List<TreeNode> Children;
  42. public Vector2 Position;
  43. public TreeNode(float orientation, float length, float inWidth, float outWidth) :
  44. this(orientation, length, inWidth, outWidth, new List<TreeNode>()) {
  45. }
  46. public TreeNode(float orientation, float length, float inWidth, float outWidth, TreeNode child) :
  47. this(orientation, length, inWidth, outWidth, new List<TreeNode>() { child }) {
  48. }
  49. public TreeNode(float orientation, float length, float inWidth, float outWidth, TreeNode child1, TreeNode child2) :
  50. this(orientation, length, inWidth, outWidth, new List<TreeNode>() { child1, child2 }) {
  51. }
  52. public TreeNode(float orientation, float length, float inWidth, float outWidth, TreeNode child1, TreeNode child2, TreeNode child3) :
  53. this(orientation, length, inWidth, outWidth, new List<TreeNode>() { child1, child2, child3 }) {
  54. }
  55. public TreeNode(float orientation, float length, float inWidth, float outWidth, List<TreeNode> children) {
  56. Orientation = orientation;
  57. Length = length;
  58. InWidth = inWidth;
  59. OutWidth = outWidth;
  60. Children = children;
  61. Position = Vector2.Zero;
  62. }
  63. }
  64. public void Draw(bool isRunningSlowly, IWorld iworld, bool paused) {
  65. var tree =
  66. new TreeNode(-0.2f, 100, 10, 6,
  67. new TreeNode(-0.2f, 100, 10, 6,
  68. new TreeNode(-0.2f, 100, 10, 6,
  69. new TreeNode(-0.3f, 100, 6, 4,
  70. new TreeNode(-0.1f, 100, 6, 4,
  71. new TreeNode(-0.3f, 150, 4, 2),
  72. new TreeNode(0.2f, 200, 4, 2),
  73. new TreeNode(0.5f, 100, 4, 2))),
  74. new TreeNode(0.5f, 100, 6, 4,
  75. new TreeNode(-0.1f, 100, 6, 4,
  76. new TreeNode(-0.1f, 150, 4, 2),
  77. new TreeNode(0.2f, 200, 4, 2))))));
  78. graphics.Clear(backgroundColor);
  79. var segments = new List<Trapezoid>();
  80. LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
  81. queue.AddLast(tree);
  82. while (queue.Count > 0) {
  83. TreeNode parent = queue.First.Value;
  84. queue.RemoveFirst();
  85. Vector2 outVector = new Vector2(0, parent.Length).Rotate(parent.Orientation);
  86. Vector2 outPosition = Vector2.Add(parent.Position, outVector);
  87. Trapezoid t = new Trapezoid();
  88. t.p1 = new Vector2(parent.Position.X - parent.InWidth, parent.Position.Y);
  89. t.p2 = new Vector2(parent.Position.X + parent.InWidth, parent.Position.Y);
  90. t.p3 = new Vector2(outPosition.X - parent.OutWidth, outPosition.Y);
  91. t.p4 = new Vector2(outPosition.X + parent.OutWidth, outPosition.Y);
  92. segments.Add(t);
  93. foreach (TreeNode child in parent.Children) {
  94. child.Position = outPosition;
  95. child.Orientation += parent.Orientation;
  96. queue.AddLast(child);
  97. }
  98. }
  99. Color color = Color.SaddleBrown;
  100. for (int i = 0; i < segments.Count; i++) {
  101. Trapezoid t = segments[i];
  102. vertices[i * 6] = new VertexPositionColor(new Vector3(t.p1.X, t.p1.Y, 0), color);
  103. vertices[i * 6 + 1] = new VertexPositionColor(new Vector3(t.p2.X, t.p2.Y, 0), color);
  104. vertices[i * 6 + 2] = new VertexPositionColor(new Vector3(t.p3.X, t.p3.Y, 0), color);
  105. vertices[i * 6 + 3] = new VertexPositionColor(new Vector3(t.p2.X, t.p2.Y, 0), color);
  106. vertices[i * 6 + 4] = new VertexPositionColor(new Vector3(t.p3.X, t.p3.Y, 0), color);
  107. vertices[i * 6 + 5] = new VertexPositionColor(new Vector3(t.p4.X, t.p4.Y, 0), color);
  108. }
  109. graphics.SetVertexBuffer(vertexBuffer);
  110. vertexBuffer.SetData(vertices);
  111. foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes) {
  112. pass.Apply();
  113. graphics.DrawPrimitives(PrimitiveType.TriangleList, 0, segments.Count * 2);
  114. }
  115. }
  116. }
  117. }