Client LuaCsForBarotrauma
BarotraumaShared/SharedSource/Map/Levels/LevelWall.cs
1 using FarseerPhysics;
2 using FarseerPhysics.Dynamics;
3 using Microsoft.Xna.Framework;
4 using System;
5 using System.Collections.Generic;
6 using Voronoi2;
7 using System.Linq;
8 #if CLIENT
9 using Microsoft.Xna.Framework.Graphics;
10 #endif
11 
12 namespace Barotrauma
13 {
14  partial class LevelWall : IDisposable
15  {
16  public List<VoronoiCell> Cells { get; private set; }
17 
18  public Body Body { get; private set; }
19 
20  protected readonly Level level;
21 
22  private readonly List<Vector2[]> triangles;
23  private readonly Color color;
24 
25  private float moveState;
26  private float moveLength;
27 
28  private Vector2 moveAmount;
29  public Vector2 MoveAmount
30  {
31  get { return moveAmount; }
32  set
33  {
34  moveAmount = value;
35  moveLength = moveAmount.Length();
36  }
37  }
38 
39  private float wallDamageOnTouch;
40  public float WallDamageOnTouch
41  {
42  get { return wallDamageOnTouch; }
43  set
44  {
45  Cells.ForEach(c => c.DoesDamage = !MathUtils.NearlyEqual(value, 0.0f));
46  wallDamageOnTouch = value;
47  }
48  }
49 
50  public float MoveSpeed;
51 
52  private Vector2? originalPos;
53 
54  public float MoveState
55  {
56  get { return moveState; }
57  set { moveState = MathHelper.Clamp(value, 0.0f, MathHelper.TwoPi); }
58  }
59 
60  public LevelWall(List<Vector2> vertices, Color color, Level level, bool giftWrap = false, bool createBody = true)
61  {
62  this.level = level;
63  this.color = color;
64  List<Vector2> originalVertices = new List<Vector2>(vertices);
65  if (giftWrap) { vertices = MathUtils.GiftWrap(vertices); }
66  if (vertices.Count < 3)
67  {
68  throw new ArgumentException("Failed to generate a wall (not enough vertices). Original vertices: " + string.Join(", ", originalVertices.Select(v => v.ToString())));
69  }
70  VoronoiCell wallCell = new VoronoiCell(vertices.ToArray());
71  for (int i = 0; i < wallCell.Edges.Count; i++)
72  {
73  wallCell.Edges[i].Cell1 = wallCell;
74  wallCell.Edges[i].IsSolid = true;
75  }
76  Cells = new List<VoronoiCell>() { wallCell };
77  if (createBody)
78  {
79  Body = CaveGenerator.GeneratePolygons(Cells, level, out triangles);
80  if (triangles.Count == 0)
81  {
82  throw new ArgumentException("Failed to generate a wall (not enough triangles). Original vertices: " + string.Join(", ", originalVertices.Select(v => v.ToString())));
83  }
84 #if CLIENT
86 #endif
87  }
88  }
89 
90  public LevelWall(List<Vector2> edgePositions, Vector2 extendAmount, Color color, Level level)
91  {
92  this.level = level;
93  this.color = color;
94  Cells = new List<VoronoiCell>();
95  for (int i = 0; i < edgePositions.Count - 1; i++)
96  {
97  Vector2[] vertices = new Vector2[4];
98  vertices[0] = edgePositions[i];
99  vertices[1] = edgePositions[i + 1];
100  vertices[2] = vertices[1] + extendAmount;
101  vertices[3] = vertices[0] + extendAmount;
102 
103  VoronoiCell wallCell = new VoronoiCell(vertices)
104  {
105  CellType = CellType.Solid
106  };
107  wallCell.Edges[0].Cell1 = wallCell;
108  wallCell.Edges[1].Cell1 = wallCell;
109  wallCell.Edges[2].Cell1 = wallCell;
110  wallCell.Edges[3].Cell1 = wallCell;
111  wallCell.Edges[0].IsSolid = true;
112 
113  if (i > 1)
114  {
115  wallCell.Edges[3].Cell2 = Cells[i - 1];
116  Cells[i - 1].Edges[1].Cell2 = wallCell;
117  }
118 
119  Cells.Add(wallCell);
120  }
121 
122  Body = CaveGenerator.GeneratePolygons(Cells, level, out triangles);
123  Body.CollisionCategories = Physics.CollisionLevel;
124 #if CLIENT
126 #endif
127  }
128 
129  public virtual void Update(float deltaTime)
130  {
131  if (Body.BodyType == BodyType.Static) { return; }
132 
133  Vector2 bodyPos = ConvertUnits.ToDisplayUnits(Body.Position);
134  Cells.ForEach(c => c.Translation = bodyPos);
135 
136  if (!originalPos.HasValue) { originalPos = bodyPos; }
137 
138  if (moveLength > 0.0f && MoveSpeed > 0.0f)
139  {
140  moveState += MoveSpeed / moveLength * deltaTime;
141  moveState %= MathHelper.TwoPi;
142 
143  Vector2 targetPos = ConvertUnits.ToSimUnits(originalPos.Value + moveAmount * (float)Math.Sin(moveState));
144  Body.ApplyForce((targetPos - Body.Position).ClampLength(1.0f) * Body.Mass);
145  }
146  }
147 
148  public bool IsPointInside(Vector2 point)
149  {
150  return Cells.Any(c => c.IsPointInside(point));
151  }
152 
153  public void Dispose()
154  {
155 #if CLIENT
157  VertexBuffer = null;
158 #endif
159  }
160  }
161 }
LevelWall(List< Vector2 > edgePositions, Vector2 extendAmount, Color color, Level level)
LevelWall(List< Vector2 > vertices, Color color, Level level, bool giftWrap=false, bool createBody=true)
List< GraphEdge > Edges