3 using Microsoft.Xna.Framework;
4 using Microsoft.Xna.Framework.Graphics;
6 using System.Collections.Generic;
16 private VertexPositionColorTexture[] wallVertices;
17 private VertexPositionColorTexture[] wallEdgeVertices;
25 public LevelWallVertexBuffer(VertexPositionTexture[] wallVertices, VertexPositionTexture[] wallEdgeVertices, Texture2D wallTexture, Texture2D edgeTexture, Color color)
27 if (wallVertices.Length == 0)
29 throw new ArgumentException(
"Failed to instantiate a LevelWallVertexBuffer (no wall vertices).");
31 if (wallVertices.Length == 0)
33 throw new ArgumentException(
"Failed to instantiate a LevelWallVertexBuffer (no wall edge vertices).");
36 WallBuffer =
new VertexBuffer(
GameMain.
Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, wallVertices.Length, BufferUsage.WriteOnly);
37 WallBuffer.SetData(this.wallVertices);
41 WallEdgeBuffer =
new VertexBuffer(
GameMain.
Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, wallEdgeVertices.Length, BufferUsage.WriteOnly);
43 EdgeTexture = edgeTexture;
46 public void Append(VertexPositionTexture[] wallVertices, VertexPositionTexture[] wallEdgeVertices, Color color)
49 WallBuffer =
new VertexBuffer(
GameMain.
Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration,
this.wallVertices.Length + wallVertices.Length, BufferUsage.WriteOnly);
50 int originalWallVertexCount = this.wallVertices.Length;
51 Array.Resize(ref this.wallVertices, originalWallVertexCount + wallVertices.Length);
53 WallBuffer.SetData(this.wallVertices);
56 WallEdgeBuffer =
new VertexBuffer(
GameMain.
Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration,
this.wallEdgeVertices.Length + wallEdgeVertices.Length, BufferUsage.WriteOnly);
57 int originalWallEdgeVertexCount = this.wallEdgeVertices.Length;
58 Array.Resize(ref this.wallEdgeVertices, originalWallEdgeVertexCount + wallEdgeVertices.Length);
67 WallBuffer?.Dispose();
73 private static BasicEffect wallEdgeEffect, wallCenterEffect;
75 private Vector2 waterParticleOffset;
76 private Vector2 waterParticleVelocity;
78 private float flashCooldown;
79 private float flashTimer;
82 private readonly RasterizerState cullNone;
84 private readonly
Level level;
86 private readonly List<LevelWallVertexBuffer> vertexBuffers =
new List<LevelWallVertexBuffer>();
88 private float chromaticAberrationStrength;
91 get {
return chromaticAberrationStrength; }
92 set { chromaticAberrationStrength = MathHelper.Clamp(value, 0.0f, 100.0f); }
108 cullNone =
new RasterizerState() { CullMode = CullMode.None };
110 if (wallEdgeEffect ==
null)
114 DiffuseColor =
new Vector3(0.8f, 0.8f, 0.8f),
115 VertexColorEnabled =
true,
116 TextureEnabled =
true,
119 wallEdgeEffect.CurrentTechnique = wallEdgeEffect.Techniques[
"BasicEffect_Texture"];
122 if (wallCenterEffect ==
null)
126 VertexColorEnabled =
true,
127 TextureEnabled =
true,
130 wallCenterEffect.CurrentTechnique = wallCenterEffect.Techniques[
"BasicEffect_Texture"];
138 level.GenerationParams.WallEdgeSprite.ReloadTexture();
139 wallEdgeEffect.Texture = level.GenerationParams.WallEdgeSprite.Texture;
140 level.GenerationParams.WallSprite.ReloadTexture();
141 wallCenterEffect.Texture = level.GenerationParams.WallSprite.Texture;
160 if (level.GenerationParams.FlashInterval.Y > 0)
162 flashCooldown -= deltaTime;
163 if (flashCooldown <= 0.0f)
166 if (level.GenerationParams.FlashSound !=
null)
168 level.GenerationParams.FlashSound.Play(1.0f,
"default");
170 flashCooldown = Rand.Range(level.GenerationParams.FlashInterval.X, level.GenerationParams.FlashInterval.Y, Rand.RandSync.Unsynced);
172 if (flashTimer > 0.0f)
174 float brightness = flashTimer * 1.1f - PerlinNoise.GetPerlin((
float)Timing.TotalTime, (
float)Timing.TotalTime * 0.66f) * 0.1f;
175 FlashColor = level.GenerationParams.FlashColor.Multiply(MathHelper.Clamp(brightness, 0.0f, 1.0f));
176 flashTimer -= deltaTime * 0.5f;
186 Vector2 currentWaterParticleVel = level.GenerationParams.WaterParticleVelocity;
187 foreach (
LevelObject levelObject
in level.LevelObjectManager.GetVisibleObjects())
189 if (levelObject.
Triggers ==
null) {
continue; }
191 Vector2 objectMaxFlow = Vector2.Zero;
195 if (vel.LengthSquared() > objectMaxFlow.LengthSquared())
200 currentWaterParticleVel += objectMaxFlow;
203 waterParticleVelocity = Vector2.Lerp(waterParticleVelocity, currentWaterParticleVel, deltaTime);
207 if (level.GenerationParams.WaterParticles !=
null)
209 Vector2 waterTextureSize = level.GenerationParams.WaterParticles.size * level.GenerationParams.WaterParticleScale;
210 waterParticleOffset +=
new Vector2(waterParticleVelocity.X, -waterParticleVelocity.Y) * level.GenerationParams.WaterParticleScale * deltaTime;
211 while (waterParticleOffset.X <= -waterTextureSize.X) { waterParticleOffset.X += waterTextureSize.X; }
212 while (waterParticleOffset.X >= waterTextureSize.X){ waterParticleOffset.X -= waterTextureSize.X; }
213 while (waterParticleOffset.Y <= -waterTextureSize.Y) { waterParticleOffset.Y += waterTextureSize.Y; }
214 while (waterParticleOffset.Y >= waterTextureSize.Y) { waterParticleOffset.Y -= waterTextureSize.Y; }
218 public static VertexPositionColorTexture[]
GetColoredVertices(VertexPositionTexture[] vertices, Color color)
220 VertexPositionColorTexture[] verts =
new VertexPositionColorTexture[vertices.Length];
221 for (
int i = 0; i < vertices.Length; i++)
223 verts[i] =
new VertexPositionColorTexture(vertices[i].Position, color, vertices[i].TextureCoordinate);
228 public void SetVertices(VertexPositionTexture[] wallVertices, VertexPositionTexture[] wallEdgeVertices, Texture2D wallTexture, Texture2D edgeTexture, Color color)
230 var existingBuffer = vertexBuffers.Find(vb => vb.WallTexture == wallTexture && vb.EdgeTexture == edgeTexture);
231 if (existingBuffer !=
null)
233 existingBuffer.Append(wallVertices, wallEdgeVertices,color);
237 vertexBuffers.Add(
new LevelWallVertexBuffer(wallVertices, wallEdgeVertices, wallTexture, edgeTexture, color));
246 spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, SamplerState.LinearWrap);
250 backgroundPos.Y = -backgroundPos.Y;
251 backgroundPos *= 0.05f;
253 if (level.GenerationParams.BackgroundTopSprite !=
null)
255 int backgroundSize = (int)level.GenerationParams.BackgroundTopSprite.size.Y;
256 if (backgroundPos.Y < backgroundSize)
258 if (backgroundPos.Y < 0)
260 var backgroundTop = level.GenerationParams.BackgroundTopSprite;
261 backgroundTop.SourceRect =
new Rectangle((
int)backgroundPos.X, (
int)backgroundPos.Y, backgroundSize, (
int)Math.Min(-backgroundPos.Y, backgroundSize));
263 color: level.BackgroundTextureColor);
267 var background = level.GenerationParams.BackgroundSprite;
268 background.SourceRect =
new Rectangle((
int)backgroundPos.X, (
int)Math.Max(backgroundPos.Y, 0), backgroundSize, backgroundSize);
269 background.DrawTiled(spriteBatch,
270 (backgroundPos.Y < 0) ?
new Vector2(0.0f, (
int)-backgroundPos.Y) : Vector2.Zero,
271 new Vector2(
GameMain.
GraphicsWidth, (
int)Math.Min(Math.Ceiling(backgroundSize - backgroundPos.Y), backgroundSize)),
272 color: level.BackgroundTextureColor);
279 spriteBatch.Begin(SpriteSortMode.Deferred,
280 BlendState.NonPremultiplied,
281 SamplerState.LinearWrap, DepthStencilState.DepthRead,
null,
null,
284 backgroundSpriteManager?.DrawObjectsBack(spriteBatch, cam);
285 if (cam.
Zoom > 0.05f)
287 backgroundCreatureManager?.Draw(spriteBatch, cam);
290 if (level.GenerationParams.WaterParticles !=
null && cam.
Zoom > 0.05f)
292 float textureScale = level.GenerationParams.WaterParticleScale;
296 Vector2 offset = -origin + waterParticleOffset;
297 while (offset.X <= -srcRect.Width * textureScale) offset.X += srcRect.Width * textureScale;
298 while (offset.X > 0.0f) offset.X -= srcRect.Width * textureScale;
299 while (offset.Y <= -srcRect.Height * textureScale) offset.Y += srcRect.Height * textureScale;
300 while (offset.Y > 0.0f) offset.Y -= srcRect.Height * textureScale;
301 for (
int i = 0; i < 4; i++)
303 float scale = (1.0f - i * 0.2f);
306 float alpha = (cam.
Zoom * scale) < 0.1f ? (cam.
Zoom * scale - 0.05f) * 20.0f : 1.0f;
307 if (alpha <= 0.0f)
continue;
309 Vector2 offsetS = offset * scale
311 -
new Vector2(256.0f * i);
313 float texScale = scale * textureScale;
315 while (offsetS.X <= -srcRect.Width * texScale) offsetS.X += srcRect.Width * texScale;
316 while (offsetS.X > 0.0f) offsetS.X -= srcRect.Width * texScale;
317 while (offsetS.Y <= -srcRect.Height * texScale) offsetS.Y += srcRect.Height * texScale;
318 while (offsetS.Y > 0.0f) offsetS.Y -= srcRect.Height * texScale;
320 level.GenerationParams.WaterParticles.DrawTiled(
321 spriteBatch, origin + offsetS,
323 color: level.GenerationParams.WaterParticleColor * alpha, textureScale:
new Vector2(texScale));
333 spriteBatch.Begin(SpriteSortMode.Deferred,
334 BlendState.NonPremultiplied,
335 SamplerState.LinearClamp, DepthStencilState.DepthRead,
null,
null,
337 backgroundSpriteManager?.DrawObjectsMid(spriteBatch, cam);
343 spriteBatch.Begin(SpriteSortMode.Deferred,
344 BlendState.NonPremultiplied,
345 SamplerState.LinearClamp, DepthStencilState.DepthRead,
null,
null,
347 backgroundSpriteManager?.DrawObjectsFront(spriteBatch, cam);
358 GUI.DrawRectangle(spriteBatch,
new Vector2(cell.
Center.X - 10.0f, -cell.
Center.Y - 10.0f),
new Vector2(20.0f, 20.0f), Color.Cyan,
true);
360 GUI.DrawLine(spriteBatch,
372 GUI.DrawLine(spriteBatch,
381 GUI.DrawRectangle(spriteBatch,
new Vector2(point.X + cell.
Translation.X, -(point.Y + cell.
Translation.Y)),
new Vector2(10.0f, 10.0f), Color.White,
true);
396 foreach (var abyssIsland
in level.AbyssIslands)
398 GUI.DrawRectangle(spriteBatch,
new Vector2(abyssIsland.Area.X, -abyssIsland.Area.Y - abyssIsland.Area.Height), abyssIsland.Area.Size.ToVector2(), Color.Cyan, thickness: 5);
401 foreach (var ruin
in level.Ruins)
403 ruin.DebugDraw(spriteBatch);
407 Vector2 pos =
new Vector2(0.0f, -level.Size.Y);
410 int topBarrierWidth = level.GenerationParams.WallEdgeSprite.Texture.Width;
411 int topBarrierHeight = level.GenerationParams.WallEdgeSprite.Texture.Height;
413 pos.X = cam.
WorldView.X - topBarrierWidth;
414 int width = (int)(Math.Ceiling(cam.
WorldView.Width / 1024 + 4.0f) * topBarrierWidth);
416 GUI.DrawRectangle(spriteBatch,
new Rectangle(
417 (
int)MathUtils.Round(pos.X, topBarrierWidth),
423 spriteBatch.Draw(level.GenerationParams.WallEdgeSprite.Texture,
424 new Rectangle((
int)MathUtils.Round(pos.X, topBarrierWidth), (
int)(pos.Y - topBarrierHeight + level.GenerationParams.WallEdgeExpandOutwardsAmount), width, topBarrierHeight),
425 new Rectangle(0, 0, width, -topBarrierHeight),
428 SpriteEffects.None, 0.0f);
433 int bottomBarrierWidth = level.GenerationParams.WallEdgeSprite.Texture.Width;
434 int bottomBarrierHeight = level.GenerationParams.WallEdgeSprite.Texture.Height;
435 pos =
new Vector2(cam.
WorldView.X - bottomBarrierWidth, -level.BottomPos);
436 int width = (int)(Math.Ceiling(cam.
WorldView.Width / bottomBarrierWidth + 4.0f) * bottomBarrierWidth);
438 GUI.DrawRectangle(spriteBatch,
new Rectangle(
439 (
int)(MathUtils.Round(pos.X, bottomBarrierWidth)),
440 -(level.BottomPos - 60),
445 spriteBatch.Draw(level.GenerationParams.WallEdgeSprite.Texture,
446 new Rectangle((
int)MathUtils.Round(pos.X, bottomBarrierWidth), -level.BottomPos - (
int)level.GenerationParams.WallEdgeExpandOutwardsAmount, width, bottomBarrierHeight),
447 new Rectangle(0, 0, width, -bottomBarrierHeight),
450 SpriteEffects.FlipVertically, 0.0f);
457 if (!vertexBuffers.Any()) {
return; }
459 var defaultRasterizerState = graphicsDevice.RasterizerState;
464 graphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;
465 graphicsDevice.RasterizerState = cullNone;
468 for (
int i = 0; i < 2; i++)
470 var wallList = i == 0 ? level.ExtraWalls : level.UnsyncedExtraWalls;
476 wallCenterEffect.Texture = level.GenerationParams.DestructibleWallSprite?.Texture ?? level.GenerationParams.WallSprite.Texture;
477 wallCenterEffect.World = wall.
GetTransform() * transformMatrix;
478 wallCenterEffect.Alpha = wall.
Alpha;
479 wallCenterEffect.CurrentTechnique.Passes[0].Apply();
480 graphicsDevice.SetVertexBuffer(wall.
WallBuffer);
481 graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (
int)Math.Floor(wall.
WallBuffer.VertexCount / 3.0f));
483 if (destructibleWall.Damage > 0.0f)
485 wallCenterEffect.Texture = level.GenerationParams.WallSpriteDestroyed.Texture;
486 wallCenterEffect.Alpha = MathHelper.Lerp(0.2f, 1.0f, destructibleWall.Damage / destructibleWall.MaxHealth) * wall.
Alpha;
487 wallCenterEffect.CurrentTechnique.Passes[0].Apply();
488 graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (
int)Math.Floor(wall.
WallEdgeBuffer.VertexCount / 3.0f));
491 wallEdgeEffect.Texture = level.GenerationParams.DestructibleWallEdgeSprite?.Texture ?? level.GenerationParams.WallEdgeSprite.Texture;
492 wallEdgeEffect.World = wall.
GetTransform() * transformMatrix;
493 wallEdgeEffect.Alpha = wall.
Alpha;
494 wallEdgeEffect.CurrentTechnique.Passes[0].Apply();
496 graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (
int)Math.Floor(wall.
WallEdgeBuffer.VertexCount / 3.0f));
500 wallEdgeEffect.Alpha = 1.0f;
501 wallCenterEffect.Alpha = 1.0f;
503 wallCenterEffect.World = transformMatrix;
504 wallEdgeEffect.World = transformMatrix;
507 foreach (var vertexBuffer
in vertexBuffers)
509 wallCenterEffect.Texture = vertexBuffer.WallTexture;
510 wallCenterEffect.CurrentTechnique.Passes[0].Apply();
511 graphicsDevice.SetVertexBuffer(vertexBuffer.WallBuffer);
512 graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (
int)Math.Floor(vertexBuffer.WallBuffer.VertexCount / 3.0f));
514 wallEdgeEffect.Texture = vertexBuffer.EdgeTexture;
515 wallEdgeEffect.CurrentTechnique.Passes[0].Apply();
516 graphicsDevice.SetVertexBuffer(vertexBuffer.WallEdgeBuffer);
517 graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (
int)Math.Floor(vertexBuffer.WallEdgeBuffer.VertexCount / 3.0f));
520 wallCenterEffect.Texture = level.GenerationParams.WallSprite.Texture;
521 wallEdgeEffect.Texture = level.GenerationParams.WallEdgeSprite.Texture;
524 for (
int i = 0; i < 2; i++)
526 var wallList = i == 0 ? level.ExtraWalls : level.UnsyncedExtraWalls;
530 if (!wall.
IsVisible(cam.WorldView)) {
continue; }
532 wallCenterEffect.World = wall.
GetTransform() * transformMatrix;
533 wallCenterEffect.Alpha = wall.
Alpha;
534 wallCenterEffect.CurrentTechnique.Passes[0].Apply();
535 graphicsDevice.SetVertexBuffer(wall.
WallBuffer);
536 graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (
int)Math.Floor(wall.
WallBuffer.VertexCount / 3.0f));
538 wallEdgeEffect.World = wall.
GetTransform() * transformMatrix;
539 wallEdgeEffect.Alpha = wall.
Alpha;
540 wallEdgeEffect.CurrentTechnique.Passes[0].Apply();
542 graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (
int)Math.Floor(wall.
WallEdgeBuffer.VertexCount / 3.0f));
546 graphicsDevice.RasterizerState = defaultRasterizerState;
551 foreach (var vertexBuffer
in vertexBuffers)
553 vertexBuffer.Dispose();
555 vertexBuffers.Clear();
static int GraphicsHeight
static Lights.LightManager LightManager
static ParticleManager ParticleManager
LevelGenerationParams GenerationParams
List< LevelTrigger > Triggers
void DrawForeground(SpriteBatch spriteBatch, Camera cam, LevelObjectManager backgroundSpriteManager=null)
static VertexPositionColorTexture[] GetColoredVertices(VertexPositionTexture[] vertices, Color color)
Vector2 CollapseEffectOrigin
void RenderWalls(GraphicsDevice graphicsDevice, Camera cam)
float CollapseEffectStrength
float ChromaticAberrationStrength
void DrawBackground(SpriteBatch spriteBatch, Camera cam, LevelObjectManager backgroundSpriteManager=null, BackgroundCreatureManager backgroundCreatureManager=null, ParticleManager particleManager=null)
LevelRenderer(Level level)
void DrawDebugOverlay(SpriteBatch spriteBatch, Camera cam)
void SetVertices(VertexPositionTexture[] wallVertices, VertexPositionTexture[] wallEdgeVertices, Texture2D wallTexture, Texture2D edgeTexture, Color color)
void Update(float deltaTime, Camera cam)
Vector2 GetWaterFlowVelocity(Vector2 viewPosition)
bool IsVisible(Rectangle worldView)
VertexBuffer WallEdgeBuffer
LevelWallVertexBuffer(VertexPositionTexture[] wallVertices, VertexPositionTexture[] wallEdgeVertices, Texture2D wallTexture, Texture2D edgeTexture, Color color)
VertexBuffer WallEdgeBuffer
void Append(VertexPositionTexture[] wallVertices, VertexPositionTexture[] wallEdgeVertices, Color color)
readonly Texture2D WallTexture
void Draw(SpriteBatch spriteBatch, bool inWater, bool? inSub, ParticleBlendState blendState, bool? background=false)
void ScrollWater(Vector2 vel, float deltaTime)
static WaterRenderer Instance
Vector2 GetNormal(VoronoiCell cell)
Returns the normal of the edge that points outwards from the specified cell
List< Vector2 > BodyVertices