OldBlueWater/BlueWater/Assets/AssetKits/ParticleImage/Runtime/Particle.cs
2023-08-09 16:47:55 +09:00

624 lines
28 KiB
C#

// Version: 1.1.0
using System.Collections.Generic;
using AssetKits.ParticleImage.Enumerations;
using UnityEngine;
using UnityEngine.UI;
using Random = UnityEngine.Random;
namespace AssetKits.ParticleImage {
public class Particle
{
private ParticleImage _source;
private Vector2 _modifiedPosition;
private Vector2 _position;
private Vector2 _startVelocity;
private Vector2 _noiseVelocity;
private Vector2 _veloVelocity;
private Vector2 _gravityVelocity;
private Vector2 _finalVelocity;
private Vector3 _startRotation;
private Vector3 _startSize;
private Vector3 _size;
private float _time;
private Color _color;
private Color _startColor;
private Transform _transform;
private List<SpriteSheet> _sheetsList;
private float _lifetime;
private float _sizeLerp;
private float _colorLerp;
private float _rotateLerp;
private float _attractorLerp;
private float _gravityLerp;
private float _vortexLerp;
private float _frameOverTimeLerp;
private float _velocityXLerp;
private float _velocityYLerp;
private float _speedLerp;
private float _startFrameLerp;
private float _ratioRandom;
private Vector3 rot;
private Vector2 _attractorTargetPoint;
private Vector3 _lastPosition;
private Quaternion _lastRotation;
private Vector3 _deltaRotation;
private Vector2 _lastPos;
private Vector2 _deltaPosition;
private Vector2 _trailLastPos;
private Vector2 _trailDeltaPos;
private Vector2 _lastPoint;
private Vector3 _direction;
private float _frameDelta;
private int _frameId;
private int _sheetId;
private List<TrailPoint> _trailPoints = new List<TrailPoint>();
public List<TrailPoint> trailPoints
{
get => _trailPoints;
}
private VertexHelper _trailHelper;
public struct TrailPoint
{
public Vector2 point;
public float time;
public TrailPoint(Vector2 p, float t)
{
point = p;
time = t;
}
}
public Particle(ParticleImage source, Vector2 pos, Vector3 rot, Vector2 vel, Color col, Vector3 siz, float life)
{
_source = source;
_transform = source.transform;
_position = pos;
_startVelocity = vel;
_startColor = col;
_startSize = siz;
_startRotation = rot;
_sizeLerp = Random.value;
_colorLerp = Random.value;
_rotateLerp = Random.value;
_attractorLerp = Random.value;
_gravityLerp = Random.value;
_vortexLerp = Random.value;
_startFrameLerp = Random.value;
_frameOverTimeLerp = Random.value;
_velocityXLerp = Random.value;
_velocityYLerp = Random.value;
_speedLerp = Random.value;
_ratioRandom = Random.value;
_attractorTargetPoint = new Vector2(Random.value, Random.value);
_lifetime = life;
_sheetsList = new List<SpriteSheet>();
_lastPosition = _transform.position;
if (source.textureSheetEnabled)
{
for (int i = source.textureTile.y-1; i > -1; i--)
{
for (int j = 0; j < source.textureTile.x; j++)
{
_sheetsList.Add(new SpriteSheet(new Vector2(1f/source.textureTile.x * (j+1),1f/source.textureTile.y * (i+1)), new Vector2(1f/source.textureTile.x * j,1f/source.textureTile.y * i)));
}
}
}
else
{
_sheetsList.Add(new SpriteSheet(new Vector2(1f,1f), new Vector2(0f,0f)));
}
_frameId += (int)source.textureSheetStartFrame.Evaluate(_time.Remap(0f, _lifetime, 0f, 1f), _startFrameLerp);
_lastPoint = _position;
_modifiedPosition = _position;
_lastPos = _position;
_trailLastPos = _position;
_trailHelper = new VertexHelper();
if (_source.trailsEnabled)
{
_trailPoints.Add(new TrailPoint(_position, 0f));
}
}
public void Animate()
{
_time += (_source.timeScale == TimeScale.Normal) ? Time.deltaTime : Time.unscaledDeltaTime;
if (_time > _lifetime) return;
_finalVelocity = _startVelocity * _source.speedOverLifetime.Evaluate(_time.Remap(0f, _lifetime, 0f, 1f), _speedLerp);
if (_source.space == Simulation.World)
{
_modifiedPosition += new Vector2(
_transform.InverseTransformPoint(_lastPosition).x,
_transform.InverseTransformPoint(_lastPosition).y);
_deltaRotation = Quaternion.Inverse(_source.transform.rotation).eulerAngles-Quaternion.Inverse(_lastRotation).eulerAngles;
_modifiedPosition = new Vector2(
RotatePointAroundCenter(_modifiedPosition, _deltaRotation).x,
RotatePointAroundCenter(_modifiedPosition, _deltaRotation).y);
_startVelocity = new Vector2(
RotatePointAroundCenter(_startVelocity, _deltaRotation).x,
RotatePointAroundCenter(_startVelocity, _deltaRotation).y);
_lastPosition = _transform.position;
_lastRotation = _source.transform.rotation;
}
#region VELOCITY
if (_source.velocityEnabled)
{
if(_source.velocitySpace == Simulation.World)
{
_veloVelocity = new Vector2(
RotatePointAroundCenter(new Vector2(_source.velocityOverLifetime.xCurve.Evaluate(_time.Remap(0f, _lifetime, 0f, 1f), _velocityXLerp),_source.velocityOverLifetime.yCurve.Evaluate(_time.Remap(0f, _lifetime, 0f, 1f), _velocityYLerp)), Quaternion.Inverse(_source.transform.rotation).eulerAngles).x,
RotatePointAroundCenter(new Vector2(_source.velocityOverLifetime.xCurve.Evaluate(_time.Remap(0f, _lifetime, 0f, 1f), _velocityXLerp),_source.velocityOverLifetime.yCurve.Evaluate(_time.Remap(0f, _lifetime, 0f, 1f), _velocityYLerp)), Quaternion.Inverse(_source.transform.rotation).eulerAngles).y
);
}
else
{
if (_source.velocityOverLifetime.separated)
{
_veloVelocity = new Vector2(_source.velocityOverLifetime.xCurve.Evaluate(_time.Remap(0f, _lifetime, 0f, 1f), _velocityXLerp),_source.velocityOverLifetime.yCurve.Evaluate(_time.Remap(0f, _lifetime, 0f, 1f), _velocityYLerp));
}
else
{
_veloVelocity = new Vector2(_source.velocityOverLifetime.mainCurve.Evaluate(_time.Remap(0f, _lifetime, 0f, 1f), _velocityXLerp),0);
}
}
}
#endregion
#region GRAVITY
if (_source.gravityEnabled)
{
//Apply gravity
_gravityVelocity += new Vector2(
RotatePointAroundCenter(new Vector3(0,_source.gravity.Evaluate(_time.Remap(0f, _lifetime, 0f, 1f),_gravityLerp),0), Quaternion.Inverse(_source.transform.rotation).eulerAngles).x,
RotatePointAroundCenter(new Vector3(0,_source.gravity.Evaluate(_time.Remap(0f, _lifetime, 0f, 1f),_gravityLerp),0), Quaternion.Inverse(_source.transform.rotation).eulerAngles).y) * ((_source.timeScale == TimeScale.Normal) ? Time.deltaTime : Time.unscaledDeltaTime);
}
#endregion
#region NOISE
if (_source.noiseEnabled)
{
float noise = 0f;
if (_source.space == Simulation.Local)
{
noise = _source.noise.GetNoise(_position.x, _position.y);
}
else
{
noise = _source.noise.GetNoise((_position + new Vector2(_source.transform.localPosition.x, _source.transform.localPosition.y)).x,
(_position + new Vector2(_source.transform.localPosition.x, _source.transform.localPosition.y)).y);
}
_noiseVelocity = new Vector2(
Mathf.Cos(noise * Mathf.PI),
Mathf.Sin(noise * Mathf.PI)) * _source.noiseStrength;
}
#endregion
_finalVelocity += _veloVelocity + _noiseVelocity + _gravityVelocity;
_modifiedPosition += _finalVelocity * (((_source.timeScale == TimeScale.Normal) ? Time.deltaTime : Time.unscaledDeltaTime) * 100);
#region VORTEX
if (_source.vortexEnabled)
{
_modifiedPosition = RotatePointAroundCenter(_modifiedPosition, new Vector3(0,0,_source.vortexStrength.Evaluate(_time.Remap(0f, _lifetime, 0f, 1f), _vortexLerp) * ((_source.timeScale == TimeScale.Normal) ? Time.deltaTime : Time.unscaledDeltaTime) * 100));
}
#endregion
#region ATTRACTOR
if (_source.attractorTarget && _source.attractorEnabled)
{
Vector3 canPos = Vector3.zero;
if (_source.attractorTarget is RectTransform)
{
canPos = _transform.InverseTransformPoint(_source.attractorTarget.position);
}
else
{
Vector3 viewportPos = _source.WorldToViewportPoint(_source.attractorTarget.position);
_source.attractorType = AttractorType.Pivot;
if (_source.canvas.renderMode == RenderMode.ScreenSpaceCamera)
{
canPos = new Vector3(
((viewportPos.x.Remap(0.5f, 1.5f,0f,_source.canvasRect.rect.width) - _source.canvasRect.InverseTransformPoint(_transform.position).x + _source.canvasRect.localPosition.x) / _transform.lossyScale.x) * _source.canvasRect.localScale.x,
((viewportPos.y.Remap(0.5f, 1.5f,0f,_source.canvasRect.rect.height) - _source.canvasRect.InverseTransformPoint(_transform.position).y + _source.canvasRect.localPosition.y) / _transform.lossyScale.y) * _source.canvasRect.localScale.y,
0);
}
else
{
canPos = new Vector3(
(viewportPos.x.Remap(0.5f, 1.5f, 0f, _source.canvasRect.rect.width) -
_source.canvasRect.InverseTransformPoint(_transform.position).x) / _transform.lossyScale.x * _source.canvasRect.localScale.x,
(viewportPos.y.Remap(0.5f, 1.5f, 0f, _source.canvasRect.rect.height) -
_source.canvasRect.InverseTransformPoint(_transform.position).y) / _transform.lossyScale.y * _source.canvasRect.localScale.y,
0);
}
}
if(_source.attractorType == AttractorType.Pivot)
_position = Vector3.LerpUnclamped(_modifiedPosition, canPos, _source.attractorLerp.Evaluate(_time.Remap(0f, _lifetime, 0f, 1f), _attractorLerp));
else
{
var rt = _source.attractorTarget as RectTransform;
_position = Vector3.LerpUnclamped(_modifiedPosition,
new Vector2(
canPos.x + _attractorTargetPoint.x.Remap(0f, 1f, -rt.sizeDelta.x / 2, rt.sizeDelta.x / 2),
canPos.y + _attractorTargetPoint.y.Remap(0f, 1f, -rt.sizeDelta.y / 2, rt.sizeDelta.y / 2)),
_source.attractorLerp.Evaluate(_time.Remap(0f, _lifetime, 0f, 1f), _attractorLerp));
}
}
else
{
_position = _modifiedPosition;
}
#endregion
_deltaPosition = _position - _lastPos;
_lastPos = _position;
if (_source.trailsEnabled && _ratioRandom <= _source.trailRatio)
{
_trailDeltaPos = _trailLastPos - _position;
if (_trailDeltaPos.magnitude > _source.minimumVertexDistance)
{
_trailLastPos = _position;
_trailPoints.Add(new TrailPoint(_position, _time));
}
}
Color c = _source.colorOverLifetime.Evaluate(_time.Remap(0f, _lifetime, 0f, 1f), _colorLerp);
//_color = _startColor * c * _source.colorBySpeed.Evaluate(_finalVelocity.magnitude.Remap(_source.colorSpeedRange.from, _source.colorSpeedRange.to, 0f, 1f));
var _normalizedSpeed = _deltaPosition.magnitude * (1f / Time.deltaTime) / 100f;
_color = _startColor * c * _source.colorBySpeed.Evaluate(_normalizedSpeed.Remap(_source.colorSpeedRange.from, _source.colorSpeedRange.to, 0f, 1f));
Vector3 sol = Vector3.one;
if (_source.sizeOverLifetime.separated)
{
sol = new Vector3(_source.sizeOverLifetime.xCurve.Evaluate(_time.Remap(0f, _lifetime, 0f, 1f), _sizeLerp),
_source.sizeOverLifetime.yCurve.Evaluate(_time.Remap(0f, _lifetime, 0f, 1f), _sizeLerp),
_source.sizeOverLifetime.zCurve.Evaluate(_time.Remap(0f, _lifetime, 0f, 1f), _sizeLerp));
}
else
{
sol = new Vector3(_source.sizeOverLifetime.mainCurve.Evaluate(_time.Remap(0f, _lifetime, 0f, 1f), _sizeLerp),
_source.sizeOverLifetime.mainCurve.Evaluate(_time.Remap(0f, _lifetime, 0f, 1f), _sizeLerp),
_source.sizeOverLifetime.mainCurve.Evaluate(_time.Remap(0f, _lifetime, 0f, 1f), _sizeLerp));
}
Vector3 sbs = Vector3.one;
if (_source.sizeBySpeed.separated)
{
sbs = new Vector3(_source.sizeBySpeed.xCurve.Evaluate(_normalizedSpeed.Remap(_source.sizeSpeedRange.from, _source.sizeSpeedRange.to, 0f, 1f), _sizeLerp),
_source.sizeBySpeed.yCurve.Evaluate(_normalizedSpeed.Remap(_source.sizeSpeedRange.from, _source.sizeSpeedRange.to, 0f, 1f), _sizeLerp),
_source.sizeBySpeed.zCurve.Evaluate(_normalizedSpeed.Remap(_source.sizeSpeedRange.from, _source.sizeSpeedRange.to, 0f, 1f), _sizeLerp));
}
else
{
sbs = new Vector3(_source.sizeBySpeed.mainCurve.Evaluate(_normalizedSpeed.Remap(_source.sizeSpeedRange.from, _source.sizeSpeedRange.to, 0f, 1f), _sizeLerp),
_source.sizeBySpeed.mainCurve.Evaluate(_normalizedSpeed.Remap(_source.sizeSpeedRange.from, _source.sizeSpeedRange.to, 0f, 1f), _sizeLerp),
_source.sizeBySpeed.mainCurve.Evaluate(_normalizedSpeed.Remap(_source.sizeSpeedRange.from, _source.sizeSpeedRange.to, 0f, 1f), _sizeLerp));
}
_size = _startSize;
_size = new Vector3(_size.x*sol.x,_size.y*sol.y,_size.z*sol.z);
_size = new Vector3(_size.x*sbs.x,_size.y*sbs.y,_size.z*sbs.z);
//source.SizeBySpeed.Evaluate(m_Velocity.magnitude.Remap(source.SizeSpeedRange.start,source.SizeSpeedRange.to, 0f, 1f))
}
public void Render(VertexHelper vh)
{
if (_source.trailsEnabled && _ratioRandom <= _source.trailRatio)
{
_trailHelper.Clear();
if (_trailPoints.Count > 1)
{
TrailPoint tp = new TrailPoint(_position, _trailPoints[_trailPoints.Count-1].time);
_trailPoints[_trailPoints.Count - 1] = tp;
if (_time >= _trailPoints[0].time+_source.trailLifetime)
{
_trailPoints.RemoveAt(0);
}
}
for (var j = 0; j < _trailPoints.Count; j++)
{
Vector2 v = _trailPoints[j].point;
if (j < _trailPoints.Count - 1)
{
v = _trailPoints[j + 1].point - _trailPoints[j].point;
}
Vector2 mid = _trailPoints[j].point; // the mid-point between start and end.
Vector2 perp = Vector2.Perpendicular(v.normalized); // vector of length 1 perpendicular to v.
var vertex = UIVertex.simpleVert;
if (_source.inheritParticleColor)
{
vertex.color = _color * _source.trailColorOverTrail.Evaluate(((float)j).Remap(0, _trailPoints.Count, 1f, 0f)) *
_source.trailColorOverLifetime.Evaluate(_time.Remap(0f, _lifetime, 0f, 1f),_colorLerp);
}
else
{
vertex.color = _source.trailColorOverTrail.Evaluate(((float)j).Remap(0, _trailPoints.Count, 1f, 0f)) *
_source.trailColorOverLifetime.Evaluate(_time.Remap(0f, _lifetime, 0f, 1f),_colorLerp);
}
var width = _size.x * _source.trailWidth.Evaluate(((float)j).Remap(0, _trailPoints.Count, 1f, 0f));
// move half the thickness away from the mid-point.
vertex.position = mid + (perp * width) / 2;
vertex.uv0 = new Vector2(0, 1f / _trailPoints.Count * j);
_trailHelper.AddVert(vertex);
// move half the thickness away from the mid-point in the opposite direction.
vertex.position = mid - (perp * width) / 2;
vertex.uv0 = new Vector2(1, 1f / _trailPoints.Count * j);
_trailHelper.AddVert(vertex);
}
for (var v = 0; v + 2 < _trailHelper.currentVertCount; v += 2)
{
_trailHelper.AddTriangle(v, v + 2, v + 1);
}
for (var v = 0; v + 3 < _trailHelper.currentVertCount; v += 2)
{
_trailHelper.AddTriangle(v + 1, v + 2, v + 3);
}
List<UIVertex> verts = new List<UIVertex>();
List<UIVertex> verts2 = new List<UIVertex>();
_trailHelper.GetUIVertexStream(verts);
_source.particleTrailRenderer.vertexHelper.GetUIVertexStream(verts2);
verts.AddRange(verts2);
_source.particleTrailRenderer.vertexHelper.AddUIVertexTriangleStream(verts);
}
if (_time > _lifetime)
{
if (_source.dieWithParticle || _trailPoints.Count <= 1)
{
_trailPoints.Clear();
}
return;
}
_direction = (_position - _lastPoint);
if (_direction.magnitude == 0f)
{
_direction = _finalVelocity;
}
_direction = _direction.normalized;
_lastPoint = _position;
var i = vh.currentVertCount;
UIVertex vert = new UIVertex();
//sheetId = Random.Range(0, sheets.Count);
switch (_source.textureSheetType)
{
case SheetType.Speed:
_frameId = (int)_finalVelocity.magnitude.Remap(_source.textureSheetFrameSpeedRange.from, _source.textureSheetFrameSpeedRange.to, 0f, _sheetsList.Count);
break;
case SheetType.Lifetime:
_frameId = (int)(_source.textureSheetFrameOverTime.Evaluate(_time.Remap(0, _lifetime, 0f, 1f),
_frameOverTimeLerp)*_source.textureSheetCycles)+(int)_source.textureSheetStartFrame.Evaluate(_time.Remap(0f, _lifetime, 0f, 1f), _startFrameLerp);
break;
case SheetType.FPS:
float dur = 1f / _source.textureSheetFPS;
_frameDelta += ((_source.timeScale == TimeScale.Normal) ? Time.deltaTime : Time.unscaledDeltaTime);
while(_frameDelta >= dur)
{
_frameDelta -= dur;
_frameId ++;
}
break;
}
_sheetId = (int)Mathf.Repeat(_frameId, _sheetsList.Count);
Vector3 rol = Vector3.zero;
if (_source.rotationOverLifetime.separated)
{
float x = 0f;
float y = 0f;
float z = 0f;
if (_source.rotationOverLifetime.xCurve.mode == ParticleSystemCurveMode.Constant ||
_source.rotationOverLifetime.xCurve.mode == ParticleSystemCurveMode.TwoConstants)
{
x = _time.Remap(0f, _lifetime, 0f,
_source.rotationOverLifetime.xCurve.Evaluate(_rotateLerp, _rotateLerp));
}
else
{
x = _source.rotationOverLifetime.xCurve.Evaluate(((float)_time).Remap(0f, _lifetime, 0f, 1f),
_rotateLerp);
}
if (_source.rotationOverLifetime.yCurve.mode == ParticleSystemCurveMode.Constant ||
_source.rotationOverLifetime.yCurve.mode == ParticleSystemCurveMode.TwoConstants)
{
y = _time.Remap(0f, _lifetime, 0f,
_source.rotationOverLifetime.yCurve.Evaluate(_rotateLerp, _rotateLerp));
}
else
{
y = _source.rotationOverLifetime.yCurve.Evaluate(((float)_time).Remap(0f, _lifetime, 0f, 1f),
_rotateLerp);
}
if (_source.rotationOverLifetime.zCurve.mode == ParticleSystemCurveMode.Constant ||
_source.rotationOverLifetime.zCurve.mode == ParticleSystemCurveMode.TwoConstants)
{
z = _time.Remap(0f, _lifetime, 0f,
_source.rotationOverLifetime.zCurve.Evaluate(_rotateLerp, _rotateLerp));
}
else
{
z = _source.rotationOverLifetime.zCurve.Evaluate(((float)_time).Remap(0f, _lifetime, 0f, 1f),
_rotateLerp);
}
rol = new Vector3(x, y, z);
if (!_source.alignToDirection)
{
rol += Quaternion.Inverse(_source.transform.rotation).eulerAngles;
}
}
else
{
switch (_source.rotationOverLifetime.mainCurve.mode)
{
case ParticleSystemCurveMode.Constant:
case ParticleSystemCurveMode.TwoConstants:
rol = new Vector3(0, 0, _time.Remap(0f,_lifetime,0f,_source.rotationOverLifetime.mainCurve.Evaluate(((float)_time).Remap(0f, _lifetime, 0f, 1f),
_rotateLerp)));
break;
case ParticleSystemCurveMode.Curve:
case ParticleSystemCurveMode.TwoCurves:
rol = new Vector3(0, 0, _source.rotationOverLifetime.mainCurve.Evaluate(((float)_time).Remap(0f, _lifetime, 0f, 1f),
_rotateLerp));
break;
}
if (!_source.alignToDirection)
{
rol += new Vector3(0,0,Quaternion.Inverse(_source.transform.rotation).eulerAngles.z);
}
}
Vector3 rbs = Vector3.zero;
if (_source.rotationBySpeed.separated)
{
rbs = new Vector3(_time.Remap(0f,_lifetime,0f,_source.rotationBySpeed.xCurve.Evaluate(_finalVelocity.magnitude.Remap(_source.rotationSpeedRange.from, _source.rotationSpeedRange.to, 0f, 1f), _rotateLerp)),
_time.Remap(0f,_lifetime,0f,_source.rotationBySpeed.yCurve.Evaluate(_finalVelocity.magnitude.Remap(_source.rotationSpeedRange.from, _source.rotationSpeedRange.to, 0f, 1f), _rotateLerp)),
_time.Remap(0f,_lifetime,0f,_source.rotationBySpeed.zCurve.Evaluate(_finalVelocity.magnitude.Remap(_source.rotationSpeedRange.from, _source.rotationSpeedRange.to, 0f, 1f), _rotateLerp)));
}
else
{
rbs = new Vector3(0,0, _time.Remap(0f, _lifetime, 0f, _source.rotationBySpeed.mainCurve.Evaluate(_finalVelocity.magnitude.Remap(_source.rotationSpeedRange.from, _source.rotationSpeedRange.to, 0f, 1f), _rotateLerp)));
}
if (_source.alignToDirection)
{
Quaternion q = Quaternion.FromToRotation(Vector3.up, _direction);
rot = _startRotation + Quaternion.Euler(new Vector3(0,0, q.eulerAngles.z)).eulerAngles;
}
else
{
rot = _startRotation;
}
vert.color = _color;
vert.position = RotatePointAroundPivot(new Vector3(_position.x - (_size.x/2), _position.y - (_size.y/2)), _position, rot + rol + rbs);
vert.uv0 = _sheetsList[_sheetId].pos;
vh.AddVert(vert);
vert.position = RotatePointAroundPivot(new Vector3(_position.x + (_size.x/2), _position.y - (_size.y/2)), _position, rot + rol + rbs);
vert.uv0 = new Vector2(_sheetsList[_sheetId].size.x,_sheetsList[_sheetId].pos.y);
vh.AddVert(vert);
vert.position = RotatePointAroundPivot(new Vector3(_position.x + (_size.x/2), _position.y + (_size.y/2)), _position, rot + rol + rbs);
vert.uv0 = _sheetsList[_sheetId].size;
vh.AddVert(vert);
vert.position = RotatePointAroundPivot(new Vector3(_position.x - (_size.x/2), _position.y + (_size.y/2)), _position, rot + rol + rbs);
vert.uv0 = new Vector2(_sheetsList[_sheetId].pos.x,_sheetsList[_sheetId].size.y);
vh.AddVert(vert);
vh.AddTriangle(i+0,i+2,i+1);
vh.AddTriangle(i+3,i+2,i+0);
}
private Vector3 RotatePointAroundPivot(Vector3 point, Vector3 pivot, Vector3 angles)
{
return Quaternion.Euler(angles) * (point - pivot) + pivot;
}
private Vector3 RotatePointAroundCenter(Vector3 point, Vector3 angles)
{
return Quaternion.Euler(angles) * (point);
}
public Vector2 Position => _position;
public Vector2 Velocity => _finalVelocity;
public Vector2 Size => new Vector2(_size.x, _size.y);
public float TimeSinceBorn => _time;
public float Lifetime => _lifetime;
public Color Color => _color;
}
struct SpriteSheet
{
public Vector2 size;
public Vector2 pos;
public SpriteSheet(Vector2 s, Vector2 p)
{
size = s;
pos = p;
}
}
}