2 using Microsoft.Xna.Framework;
3 using Microsoft.Xna.Framework.Graphics;
5 using System.Collections.Generic;
13 const float MaxDepth = 10000.0f;
15 const float CheckWallsInterval = 5.0f;
21 private readonly List<SpriteDeformation> uniqueSpriteDeformations =
new List<SpriteDeformation>();
22 private readonly List<SpriteDeformation> spriteDeformations =
new List<SpriteDeformation>();
23 private readonly List<SpriteDeformation> lightSpriteDeformations =
new List<SpriteDeformation>();
25 private Vector2 position;
27 private Vector3 velocity;
31 private float alpha = 1.0f;
35 private float checkWallsTimer, flashTimer;
37 private float wanderZPhase;
38 private Vector2 obstacleDiff;
39 private float obstacleDist;
58 get {
return FarseerPhysics.ConvertUnits.ToSimUnits(position); }
63 get {
return position; }
68 get {
return new Vector2(velocity.X, velocity.Y); }
80 this.position = position;
82 drawPosition = position;
86 velocity =
new Vector3(
87 Rand.Range(-prefab.
Speed, prefab.
Speed, Rand.RandSync.ClientOnly),
88 Rand.Range(-prefab.
Speed, prefab.
Speed, Rand.RandSync.ClientOnly),
89 Rand.Range(0.0f, prefab.
WanderZAmount, Rand.RandSync.ClientOnly));
91 checkWallsTimer = Rand.Range(0.0f, CheckWallsInterval, Rand.RandSync.ClientOnly);
93 foreach (var subElement
in prefab.Config.Elements())
95 List<SpriteDeformation> deformationList =
null;
96 switch (subElement.Name.ToString().ToLowerInvariant())
98 case "deformablesprite":
99 deformationList = spriteDeformations;
101 case "deformablelightsprite":
102 deformationList = lightSpriteDeformations;
107 foreach (XElement animationElement
in subElement.Elements())
110 int sync = animationElement.GetAttributeInt(
"sync", -1);
113 string typeName = animationElement.GetAttributeString(
"type",
"").ToLowerInvariant();
114 deformation = uniqueSpriteDeformations.Find(d => d.TypeName == typeName && d.Sync == sync);
116 if (deformation ==
null)
119 if (deformation !=
null)
121 uniqueSpriteDeformations.Add(deformation);
124 if (deformation !=
null)
126 deformationList.Add(deformation);
134 position +=
new Vector2(velocity.X, velocity.Y) * deltaTime;
135 depth = MathHelper.Clamp(depth + velocity.Z * deltaTime,
Prefab.MinDepth,
Prefab.MaxDepth * 10);
137 if (
Prefab.FlashInterval > 0.0f)
139 flashTimer -= deltaTime;
140 if (flashTimer > 0.0f)
147 alpha = (float)Math.Sin(-flashTimer /
Prefab.FlashDuration * MathHelper.Pi) * PerlinNoise.GetPerlin((
float)Timing.TotalTime * 0.1f, (float)Timing.TotalTime * 0.2f);
148 if (flashTimer < -
Prefab.FlashDuration)
150 flashTimer =
Prefab.FlashInterval;
155 checkWallsTimer -= deltaTime;
156 if (checkWallsTimer <= 0.0f &&
Level.
Loaded !=
null)
158 checkWallsTimer = CheckWallsInterval;
160 obstacleDiff = Vector2.Zero;
163 obstacleDiff = Vector2.UnitY;
165 else if (position.Y < 0.0f)
167 obstacleDiff = -Vector2.UnitY;
169 else if (position.X < 0.0f)
171 obstacleDiff = -Vector2.UnitX;
175 obstacleDiff = Vector2.UnitX;
185 Vector2 diff = cell.Center - position;
186 if (diff.LengthSquared() > 5000.0f * 5000.0f) {
continue; }
187 obstacleDiff += diff;
192 obstacleDiff /= cellCount;
193 obstacleDist = obstacleDiff.Length();
194 obstacleDiff = Vector2.Normalize(obstacleDiff);
203 float midPointDist = Vector2.Distance(
SimPosition, midPoint) * 100.0f;
211 if (
Prefab.WanderAmount > 0.0f)
213 steeringManager.SteeringWander(
Prefab.Speed);
216 if (obstacleDiff != Vector2.Zero)
218 steeringManager.SteeringManual(deltaTime, -obstacleDiff * (1.0f - obstacleDist / 5000.0f) *
Prefab.Speed);
221 steeringManager.Update(
Prefab.Speed);
223 if (
Prefab.WanderZAmount > 0.0f)
225 wanderZPhase += Rand.Range(-
Prefab.WanderZAmount,
Prefab.WanderZAmount);
226 velocity.Z = (float)Math.Sin(wanderZPhase) *
Prefab.Speed;
229 velocity = Vector3.Lerp(velocity,
new Vector3(
Steering.X,
Steering.Y, velocity.Z), deltaTime);
231 UpdateDeformations(deltaTime);
251 if (sprite ==
null && deformableSprite ==
null) {
return; }
252 if (color.A == 0) {
return; }
254 float rotation = 0.0f;
257 rotation = MathUtils.VectorToAngle(
new Vector2(velocity.X, -velocity.Y));
258 if (velocity.X < 0.0f) { rotation -= MathHelper.Pi; }
264 sprite?.
Draw(spriteBatch,
265 new Vector2(drawPosition.X, -drawPosition.Y),
270 Math.Min(depth / MaxDepth, 1.0f));
272 if (deformableSprite !=
null)
274 if (currentSpriteDeformation !=
null)
276 deformableSprite.
Deform(currentSpriteDeformation);
280 deformableSprite.
Reset();
282 deformableSprite?.
Draw(cam,
283 new Vector3(drawPosition.X, drawPosition.Y, Math.Min(depth / 10000.0f, 1.0f)),
298 drawPosition -= camOffset * depth / MaxDepth;
305 return Math.Max(1.0f - depth / MaxDepth, 0.05f) *
Prefab.Scale;
314 GetSpriteExtents(
Prefab.Sprite, ref min, ref max);
315 GetSpriteExtents(
Prefab.LightSprite, ref min, ref max);
316 GetSpriteExtents(
Prefab.DeformableSprite?.Sprite, ref min, ref max);
317 GetSpriteExtents(
Prefab.DeformableLightSprite?.Sprite, ref min, ref max);
319 return new Rectangle(min.ToPoint(), (max - min).ToPoint());
321 void GetSpriteExtents(
Sprite sprite, ref Vector2 min, ref Vector2 max)
323 if (sprite ==
null) {
return; }
326 max.X = Math.Max(max.X, max.X + sprite.
size.X * (1.0f - sprite.
RelativeOrigin.X) * scale);
327 max.Y = Math.Max(max.Y, max.Y + sprite.
size.Y * (1.0f - sprite.
RelativeOrigin.Y) * scale);
331 private void UpdateDeformations(
float deltaTime)
335 deformation.
Update(deltaTime);
337 if (spriteDeformations.Count > 0)
341 if (lightSpriteDeformations.Count > 0)
357 if (
Members.Count == 0)
return Vector2.Zero;
359 Vector2 midPoint = Vector2.Zero;
373 if (
Members.Count == 0)
return Vector2.Zero;
375 Vector2 avgVel = Vector2.Zero;
384 public Swarm(List<BackgroundCreature> members,
float maxDistance,
float cohesion)
391 bgSprite.
Swarm =
this;
Vector2 GetDrawPosition(Camera cam)
void Update(float deltaTime)
Vector2[,] CurrentSpriteDeformation
Vector2[,] CurrentLightSpriteDeformation
void Draw(SpriteBatch spriteBatch, Camera cam)
void DrawLightSprite(SpriteBatch spriteBatch, Camera cam)
Rectangle GetExtents(Camera cam)
BackgroundCreature(BackgroundCreaturePrefab prefab, Vector2 position)
readonly BackgroundCreaturePrefab Prefab
readonly DeformableSprite DeformableSprite
List< VoronoiCell > GetCells(Vector2 worldPos, int searchDepth=2)
Vector2 RelativeOrigin
0 - 1
void Draw(ISpriteBatch spriteBatch, Vector2 pos, float rotate=0.0f, float scale=1.0f, SpriteEffects spriteEffect=SpriteEffects.None)
List< BackgroundCreature > Members
readonly float MaxDistance
Swarm(List< BackgroundCreature > members, float maxDistance, float cohesion)