3 using Microsoft.Xna.Framework;
4 using Microsoft.Xna.Framework.Graphics;
6 using System.Collections.Generic;
11 partial class LevelObjectManager
13 private readonly List<LevelObject> visibleObjectsBack =
new List<LevelObject>();
14 private readonly List<LevelObject> visibleObjectsMid =
new List<LevelObject>();
15 private readonly List<LevelObject> visibleObjectsFront =
new List<LevelObject>();
17 private double NextRefreshTime;
21 const int MaxVisibleObjects = 600;
27 partial
void RemoveProjSpecific()
29 visibleObjectsBack.Clear();
30 visibleObjectsMid.Clear();
31 visibleObjectsFront.Clear();
34 partial
void UpdateProjSpecific(
float deltaTime)
40 foreach (LevelObject obj
in visibleObjectsMid)
42 obj.Update(deltaTime);
44 foreach (LevelObject obj
in visibleObjectsFront)
46 obj.Update(deltaTime);
52 return visibleObjectsBack.Union(visibleObjectsMid).Union(visibleObjectsFront);
58 private void RefreshVisibleObjects(Rectangle currentIndices,
float zoom)
60 visibleObjectsBack.Clear();
61 visibleObjectsMid.Clear();
62 visibleObjectsFront.Clear();
64 float minSizeToDraw = MathHelper.Lerp(10.0f, 5.0f, Math.Min(zoom * 20.0f, 1.0f));
68 int midIndexX = (currentIndices.X + currentIndices.Width) / 2;
69 int midIndexY = (currentIndices.Y + currentIndices.Height) / 2;
70 CheckIndex(midIndexX, midIndexY);
72 for (
int x = currentIndices.X; x <= currentIndices.Width; x++)
74 for (
int y = currentIndices.Y; y <= currentIndices.Height; y++)
76 if (x != midIndexX || y != midIndexY) { CheckIndex(x, y); }
80 void CheckIndex(
int x,
int y)
82 if (objectGrid[x, y] ==
null) {
return; }
83 foreach (LevelObject obj
in objectGrid[x, y])
85 if (!obj.CanBeVisible) {
continue; }
86 if (obj.Prefab.HideWhenBroken && obj.Health <= 0.0f) {
continue; }
91 if ((obj.Sprite !=
null && Math.Min(obj.Sprite.size.X * zoom, obj.Sprite.size.Y * zoom) < 5.0f) ||
92 (obj.ActivePrefab?.DeformableSprite !=
null && Math.Min(obj.ActivePrefab.DeformableSprite.Sprite.size.X * zoom, obj.ActivePrefab.DeformableSprite.Sprite.size.Y * zoom) < minSizeToDraw))
97 float zCutoff = MathHelper.Lerp(5000.0f, 500.0f, (0.05f - zoom) * 20.0f);
98 if (obj.Position.Z > zCutoff)
105 obj.Position.Z >= 0 ?
107 (obj.Position.Z < -1 ? visibleObjectsFront : visibleObjectsMid);
108 if (objectList.Count >= MaxVisibleObjects) {
continue; }
110 int drawOrderIndex = 0;
111 for (
int i = 0; i < objectList.Count; i++)
113 if (objectList[i] == obj)
119 if (objectList[i].
Position.Z > obj.Position.Z)
125 drawOrderIndex = i + 1;
126 if (drawOrderIndex >= MaxVisibleObjects) {
break; }
130 if (drawOrderIndex >= 0 && drawOrderIndex < MaxVisibleObjects)
132 objectList.Insert(drawOrderIndex, obj);
140 visibleObjectsBack.Reverse();
141 visibleObjectsMid.Reverse();
142 visibleObjectsFront.Reverse();
144 currentGridIndices = currentIndices;
152 DrawObjects(spriteBatch, cam, visibleObjectsBack);
160 DrawObjects(spriteBatch, cam, visibleObjectsMid);
168 DrawObjects(spriteBatch, cam, visibleObjectsFront);
171 private void DrawObjects(SpriteBatch spriteBatch,
Camera cam, List<LevelObject> objectList)
174 indices.X = (int)Math.Floor(cam.
WorldView.X / (
float)GridSize);
175 if (indices.X >= objectGrid.GetLength(0)) {
return; }
176 indices.Y = (int)Math.Floor((cam.
WorldView.Y - cam.
WorldView.Height - Level.Loaded.BottomPos) / (float)GridSize);
177 if (indices.Y >= objectGrid.GetLength(1)) {
return; }
179 indices.Width = (int)Math.Floor(cam.
WorldView.Right / (
float)GridSize) + 1;
180 if (indices.Width < 0) {
return; }
181 indices.Height = (int)Math.Floor((cam.
WorldView.Y - Level.Loaded.BottomPos) / (float)GridSize) + 1;
182 if (indices.Height < 0) {
return; }
184 indices.X = Math.Max(indices.X, 0);
185 indices.Y = Math.Max(indices.Y, 0);
186 indices.Width = Math.Min(indices.Width, objectGrid.GetLength(0) - 1);
187 indices.Height = Math.Min(indices.Height, objectGrid.GetLength(1) - 1);
192 RefreshVisibleObjects(indices, cam.
Zoom);
197 NextRefreshTime = Timing.TotalTime + MathHelper.Lerp(1.0f, 0.0f, cam.
Zoom * 10.0f);
201 foreach (LevelObject obj
in objectList)
203 Vector2 camDiff =
new Vector2(obj.Position.X, obj.Position.Y) - cam.
WorldViewCenter;
204 camDiff.Y = -camDiff.Y;
206 Sprite activeSprite = obj.Sprite;
209 new Vector2(obj.Position.X, -obj.Position.Y) - camDiff * obj.Position.Z * ParallaxStrength,
210 Color.Lerp(obj.Prefab.SpriteColor, obj.Prefab.SpriteColor.Multiply(Level.Loaded.BackgroundTextureColor), obj.Position.Z / 3000.0f),
217 if (obj.ActivePrefab.DeformableSprite !=
null)
219 if (obj.CurrentSpriteDeformation !=
null)
221 obj.ActivePrefab.DeformableSprite.Deform(obj.CurrentSpriteDeformation);
225 obj.ActivePrefab.DeformableSprite.Reset();
227 obj.ActivePrefab.DeformableSprite?.Draw(cam,
228 new Vector3(
new Vector2(obj.Position.X, obj.Position.Y) - camDiff * obj.Position.Z * ParallaxStrength, z * 10.0f),
229 obj.ActivePrefab.DeformableSprite.Origin,
232 Color.Lerp(obj.Prefab.SpriteColor, obj.Prefab.SpriteColor.Multiply(Level.Loaded.BackgroundTextureColor), obj.Position.Z / 5000.0f));
236 if (GameMain.DebugDraw)
238 GUI.DrawRectangle(spriteBatch,
new Vector2(obj.Position.X, -obj.Position.Y),
new Vector2(10.0f, 10.0f), GUIStyle.Red,
true);
240 if (obj.Triggers ==
null) {
continue; }
241 foreach (LevelTrigger trigger
in obj.Triggers)
243 if (trigger.PhysicsBody ==
null)
continue;
244 GUI.DrawLine(spriteBatch,
new Vector2(obj.Position.X, -obj.Position.Y),
new Vector2(trigger.WorldPosition.X, -trigger.WorldPosition.Y), Color.Cyan, 0, 3);
246 Vector2 flowForce = trigger.GetWaterFlowVelocity();
247 if (flowForce.LengthSquared() > 1)
249 flowForce.Y = -flowForce.Y;
250 GUI.DrawLine(spriteBatch,
new Vector2(trigger.WorldPosition.X, -trigger.WorldPosition.Y),
new Vector2(trigger.WorldPosition.X, -trigger.WorldPosition.Y) + flowForce * 10, GUIStyle.Orange, 0, 5);
252 trigger.PhysicsBody.UpdateDrawPosition();
253 trigger.PhysicsBody.DebugDraw(spriteBatch, trigger.IsTriggered ? Color.Cyan : Color.DarkCyan);
264 objects[objIndex].ClientRead(msg);
void Update(float deltaTime)
bool ForceRefreshVisibleObjects
void ClientEventRead(IReadMessage msg, float sendingTime)
void DrawObjectsBack(SpriteBatch spriteBatch, Camera cam)
Draw the objects behind the level walls
void DrawObjectsFront(SpriteBatch spriteBatch, Camera cam)
Draw the objects in front of the level walls and characters
void DrawObjectsMid(SpriteBatch spriteBatch, Camera cam)
Draw the objects in front of the level walls, but behind characters
IEnumerable< LevelObject > GetVisibleObjects()
int ReadRangedInteger(int min, int max)