Files
Markus Isberg 077917fa5d Build 0.18.2.0
2022-05-19 23:43:21 +09:00

162 lines
5.1 KiB
C#

using FarseerPhysics;
using FarseerPhysics.Dynamics;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using Voronoi2;
using System.Linq;
#if CLIENT
using Microsoft.Xna.Framework.Graphics;
#endif
namespace Barotrauma
{
partial class LevelWall : IDisposable
{
public List<VoronoiCell> Cells { get; private set; }
public Body Body { get; private set; }
protected readonly Level level;
private readonly List<Vector2[]> triangles;
private readonly Color color;
private float moveState;
private float moveLength;
private Vector2 moveAmount;
public Vector2 MoveAmount
{
get { return moveAmount; }
set
{
moveAmount = value;
moveLength = moveAmount.Length();
}
}
private float wallDamageOnTouch;
public float WallDamageOnTouch
{
get { return wallDamageOnTouch; }
set
{
Cells.ForEach(c => c.DoesDamage = !MathUtils.NearlyEqual(value, 0.0f));
wallDamageOnTouch = value;
}
}
public float MoveSpeed;
private Vector2? originalPos;
public float MoveState
{
get { return moveState; }
set { moveState = MathHelper.Clamp(value, 0.0f, MathHelper.TwoPi); }
}
public LevelWall(List<Vector2> vertices, Color color, Level level, bool giftWrap = false, bool createBody = true)
{
this.level = level;
this.color = color;
List<Vector2> originalVertices = new List<Vector2>(vertices);
if (giftWrap) { vertices = MathUtils.GiftWrap(vertices); }
if (vertices.Count < 3)
{
throw new ArgumentException("Failed to generate a wall (not enough vertices). Original vertices: " + string.Join(", ", originalVertices.Select(v => v.ToString())));
}
VoronoiCell wallCell = new VoronoiCell(vertices.ToArray());
for (int i = 0; i < wallCell.Edges.Count; i++)
{
wallCell.Edges[i].Cell1 = wallCell;
wallCell.Edges[i].IsSolid = true;
}
Cells = new List<VoronoiCell>() { wallCell };
if (createBody)
{
Body = CaveGenerator.GeneratePolygons(Cells, level, out triangles);
if (triangles.Count == 0)
{
throw new ArgumentException("Failed to generate a wall (not enough triangles). Original vertices: " + string.Join(", ", originalVertices.Select(v => v.ToString())));
}
#if CLIENT
GenerateVertices();
#endif
}
}
public LevelWall(List<Vector2> edgePositions, Vector2 extendAmount, Color color, Level level)
{
this.level = level;
this.color = color;
Cells = new List<VoronoiCell>();
for (int i = 0; i < edgePositions.Count - 1; i++)
{
Vector2[] vertices = new Vector2[4];
vertices[0] = edgePositions[i];
vertices[1] = edgePositions[i + 1];
vertices[2] = vertices[1] + extendAmount;
vertices[3] = vertices[0] + extendAmount;
VoronoiCell wallCell = new VoronoiCell(vertices)
{
CellType = CellType.Solid
};
wallCell.Edges[0].Cell1 = wallCell;
wallCell.Edges[1].Cell1 = wallCell;
wallCell.Edges[2].Cell1 = wallCell;
wallCell.Edges[3].Cell1 = wallCell;
wallCell.Edges[0].IsSolid = true;
if (i > 1)
{
wallCell.Edges[3].Cell2 = Cells[i - 1];
Cells[i - 1].Edges[1].Cell2 = wallCell;
}
Cells.Add(wallCell);
}
Body = CaveGenerator.GeneratePolygons(Cells, level, out triangles);
Body.CollisionCategories = Physics.CollisionLevel;
#if CLIENT
GenerateVertices();
#endif
}
public virtual void Update(float deltaTime)
{
if (Body.BodyType == BodyType.Static) { return; }
Vector2 bodyPos = ConvertUnits.ToDisplayUnits(Body.Position);
Cells.ForEach(c => c.Translation = bodyPos);
if (!originalPos.HasValue) { originalPos = bodyPos; }
if (moveLength > 0.0f && MoveSpeed > 0.0f)
{
moveState += MoveSpeed / moveLength * deltaTime;
moveState %= MathHelper.TwoPi;
Vector2 targetPos = ConvertUnits.ToSimUnits(originalPos.Value + moveAmount * (float)Math.Sin(moveState));
Body.ApplyForce((targetPos - Body.Position).ClampLength(1.0f) * Body.Mass);
}
}
public bool IsPointInside(Vector2 point)
{
return Cells.Any(c => c.IsPointInside(point));
}
public void Dispose()
{
#if CLIENT
VertexBuffer?.Dispose();
VertexBuffer = null;
#endif
}
}
}