2 using Microsoft.Xna.Framework;
3 using Microsoft.Xna.Framework.Graphics;
5 using System.Collections.Generic;
15 private VertexPositionColorTexture[] wallVertices;
16 private VertexPositionColorTexture[] wallEdgeVertices;
24 public LevelWallVertexBuffer(VertexPositionTexture[] wallVertices, VertexPositionTexture[] wallEdgeVertices, Texture2D wallTexture, Texture2D edgeTexture, Color color)
26 if (wallVertices.Length == 0)
28 throw new ArgumentException(
"Failed to instantiate a LevelWallVertexBuffer (no wall vertices).");
30 if (wallVertices.Length == 0)
32 throw new ArgumentException(
"Failed to instantiate a LevelWallVertexBuffer (no wall edge vertices).");
35 WallBuffer =
new VertexBuffer(
GameMain.
Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, wallVertices.Length, BufferUsage.WriteOnly);
36 WallBuffer.SetData(this.wallVertices);
40 WallEdgeBuffer =
new VertexBuffer(
GameMain.
Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, wallEdgeVertices.Length, BufferUsage.WriteOnly);
42 EdgeTexture = edgeTexture;
45 public void Append(VertexPositionTexture[] wallVertices, VertexPositionTexture[] wallEdgeVertices, Color color)
48 WallBuffer =
new VertexBuffer(
GameMain.
Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration,
this.wallVertices.Length + wallVertices.Length, BufferUsage.WriteOnly);
49 int originalWallVertexCount = this.wallVertices.Length;
50 Array.Resize(ref this.wallVertices, originalWallVertexCount + wallVertices.Length);
52 WallBuffer.SetData(this.wallVertices);
55 WallEdgeBuffer =
new VertexBuffer(
GameMain.
Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration,
this.wallEdgeVertices.Length + wallEdgeVertices.Length, BufferUsage.WriteOnly);
56 int originalWallEdgeVertexCount = this.wallEdgeVertices.Length;
57 Array.Resize(ref this.wallEdgeVertices, originalWallEdgeVertexCount + wallEdgeVertices.Length);
66 WallBuffer?.Dispose();
72 private static BasicEffect wallEdgeEffect, wallCenterEffect;
74 private Vector2 waterParticleOffset;
75 private Vector2 waterParticleVelocity;
77 private float flashCooldown;
78 private float flashTimer;
81 private readonly RasterizerState cullNone;
83 private readonly
Level level;
85 private readonly List<LevelWallVertexBuffer> vertexBuffers =
new List<LevelWallVertexBuffer>();
87 private float chromaticAberrationStrength;
90 get {
return chromaticAberrationStrength; }
91 set { chromaticAberrationStrength = MathHelper.Clamp(value, 0.0f, 100.0f); }
107 cullNone =
new RasterizerState() { CullMode = CullMode.None };
109 if (wallEdgeEffect ==
null)
113 DiffuseColor =
new Vector3(0.8f, 0.8f, 0.8f),
114 VertexColorEnabled =
true,
115 TextureEnabled =
true,
118 wallEdgeEffect.CurrentTechnique = wallEdgeEffect.Techniques[
"BasicEffect_Texture"];
121 if (wallCenterEffect ==
null)
125 VertexColorEnabled =
true,
126 TextureEnabled =
true,
129 wallCenterEffect.CurrentTechnique = wallCenterEffect.Techniques[
"BasicEffect_Texture"];
137 level.GenerationParams.WallEdgeSprite.ReloadTexture();
138 wallEdgeEffect.Texture = level.GenerationParams.WallEdgeSprite.Texture;
139 level.GenerationParams.WallSprite.ReloadTexture();
140 wallCenterEffect.Texture = level.GenerationParams.WallSprite.Texture;
159 if (level.GenerationParams.FlashInterval.Y > 0)
161 flashCooldown -= deltaTime;
162 if (flashCooldown <= 0.0f)
165 if (level.GenerationParams.FlashSound !=
null)
167 level.GenerationParams.FlashSound.Play(1.0f,
"default");
169 flashCooldown = Rand.Range(level.GenerationParams.FlashInterval.X, level.GenerationParams.FlashInterval.Y, Rand.RandSync.Unsynced);
171 if (flashTimer > 0.0f)
173 float brightness = flashTimer * 1.1f - PerlinNoise.GetPerlin((
float)Timing.TotalTime, (
float)Timing.TotalTime * 0.66f) * 0.1f;
174 FlashColor = level.GenerationParams.FlashColor.Multiply(MathHelper.Clamp(brightness, 0.0f, 1.0f));
175 flashTimer -= deltaTime * 0.5f;
185 Vector2 currentWaterParticleVel = level.GenerationParams.WaterParticleVelocity;
186 foreach (
LevelObject levelObject
in level.LevelObjectManager.GetVisibleObjects())
188 if (levelObject.
Triggers ==
null) {
continue; }
190 Vector2 objectMaxFlow = Vector2.Zero;
194 if (vel.LengthSquared() > objectMaxFlow.LengthSquared())
199 currentWaterParticleVel += objectMaxFlow;
202 waterParticleVelocity = Vector2.Lerp(waterParticleVelocity, currentWaterParticleVel, deltaTime);
206 if (level.GenerationParams.WaterParticles !=
null)
208 Vector2 waterTextureSize = level.GenerationParams.WaterParticles.size * level.GenerationParams.WaterParticleScale;
209 waterParticleOffset +=
new Vector2(waterParticleVelocity.X, -waterParticleVelocity.Y) * level.GenerationParams.WaterParticleScale * deltaTime;
210 while (waterParticleOffset.X <= -waterTextureSize.X) { waterParticleOffset.X += waterTextureSize.X; }
211 while (waterParticleOffset.X >= waterTextureSize.X){ waterParticleOffset.X -= waterTextureSize.X; }
212 while (waterParticleOffset.Y <= -waterTextureSize.Y) { waterParticleOffset.Y += waterTextureSize.Y; }
213 while (waterParticleOffset.Y >= waterTextureSize.Y) { waterParticleOffset.Y -= waterTextureSize.Y; }
217 public static VertexPositionColorTexture[]
GetColoredVertices(VertexPositionTexture[] vertices, Color color)
219 VertexPositionColorTexture[] verts =
new VertexPositionColorTexture[vertices.Length];
220 for (
int i = 0; i < vertices.Length; i++)
222 verts[i] =
new VertexPositionColorTexture(vertices[i].Position, color, vertices[i].TextureCoordinate);
227 public void SetVertices(VertexPositionTexture[] wallVertices, VertexPositionTexture[] wallEdgeVertices, Texture2D wallTexture, Texture2D edgeTexture, Color color)
229 var existingBuffer = vertexBuffers.Find(vb => vb.WallTexture == wallTexture && vb.EdgeTexture == edgeTexture);
230 if (existingBuffer !=
null)
232 existingBuffer.Append(wallVertices, wallEdgeVertices,color);
236 vertexBuffers.Add(
new LevelWallVertexBuffer(wallVertices, wallEdgeVertices, wallTexture, edgeTexture, color));
244 spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, SamplerState.LinearWrap);
248 backgroundPos.Y = -backgroundPos.Y;
249 backgroundPos *= 0.05f;
251 if (level.GenerationParams.BackgroundTopSprite !=
null)
253 int backgroundSize = (int)level.GenerationParams.BackgroundTopSprite.size.Y;
254 if (backgroundPos.Y < backgroundSize)
256 if (backgroundPos.Y < 0)
258 var backgroundTop = level.GenerationParams.BackgroundTopSprite;
259 backgroundTop.SourceRect =
new Rectangle((
int)backgroundPos.X, (
int)backgroundPos.Y, backgroundSize, (
int)Math.Min(-backgroundPos.Y, backgroundSize));
261 color: level.BackgroundTextureColor);
265 var background = level.GenerationParams.BackgroundSprite;
266 background.SourceRect =
new Rectangle((
int)backgroundPos.X, (
int)Math.Max(backgroundPos.Y, 0), backgroundSize, backgroundSize);
267 background.DrawTiled(spriteBatch,
268 (backgroundPos.Y < 0) ?
new Vector2(0.0f, (
int)-backgroundPos.Y) : Vector2.Zero,
269 new Vector2(
GameMain.
GraphicsWidth, (
int)Math.Min(Math.Ceiling(backgroundSize - backgroundPos.Y), backgroundSize)),
270 color: level.BackgroundTextureColor);
277 spriteBatch.Begin(SpriteSortMode.Deferred,
278 BlendState.NonPremultiplied,
279 SamplerState.LinearWrap, DepthStencilState.DepthRead,
null,
null,
282 backgroundSpriteManager?.DrawObjectsBack(spriteBatch, cam);
283 if (cam.
Zoom > 0.05f)
285 backgroundCreatureManager?.Draw(spriteBatch, cam);
288 if (level.GenerationParams.WaterParticles !=
null && cam.
Zoom > 0.05f)
290 float textureScale = level.GenerationParams.WaterParticleScale;
294 Vector2 offset = -origin + waterParticleOffset;
295 while (offset.X <= -srcRect.Width * textureScale) offset.X += srcRect.Width * textureScale;
296 while (offset.X > 0.0f) offset.X -= srcRect.Width * textureScale;
297 while (offset.Y <= -srcRect.Height * textureScale) offset.Y += srcRect.Height * textureScale;
298 while (offset.Y > 0.0f) offset.Y -= srcRect.Height * textureScale;
299 for (
int i = 0; i < 4; i++)
301 float scale = (1.0f - i * 0.2f);
304 float alpha = (cam.
Zoom * scale) < 0.1f ? (cam.
Zoom * scale - 0.05f) * 20.0f : 1.0f;
305 if (alpha <= 0.0f)
continue;
307 Vector2 offsetS = offset * scale
309 -
new Vector2(256.0f * i);
311 float texScale = scale * textureScale;
313 while (offsetS.X <= -srcRect.Width * texScale) offsetS.X += srcRect.Width * texScale;
314 while (offsetS.X > 0.0f) offsetS.X -= srcRect.Width * texScale;
315 while (offsetS.Y <= -srcRect.Height * texScale) offsetS.Y += srcRect.Height * texScale;
316 while (offsetS.Y > 0.0f) offsetS.Y -= srcRect.Height * texScale;
318 level.GenerationParams.WaterParticles.DrawTiled(
319 spriteBatch, origin + offsetS,
321 color: level.GenerationParams.WaterParticleColor * alpha, textureScale:
new Vector2(texScale));
328 spriteBatch.Begin(SpriteSortMode.Deferred,
329 BlendState.NonPremultiplied,
330 SamplerState.LinearClamp, DepthStencilState.DepthRead,
null,
null,
332 backgroundSpriteManager?.DrawObjectsMid(spriteBatch, cam);
338 spriteBatch.Begin(SpriteSortMode.Deferred,
339 BlendState.NonPremultiplied,
340 SamplerState.LinearClamp, DepthStencilState.DepthRead,
null,
null,
342 backgroundSpriteManager?.DrawObjectsFront(spriteBatch, cam);
353 GUI.DrawRectangle(spriteBatch,
new Vector2(cell.
Center.X - 10.0f, -cell.
Center.Y - 10.0f),
new Vector2(20.0f, 20.0f), Color.Cyan,
true);
355 GUI.DrawLine(spriteBatch,
367 GUI.DrawLine(spriteBatch,
376 GUI.DrawRectangle(spriteBatch,
new Vector2(point.X + cell.
Translation.X, -(point.Y + cell.
Translation.Y)),
new Vector2(10.0f, 10.0f), Color.White,
true);
391 foreach (var abyssIsland
in level.AbyssIslands)
393 GUI.DrawRectangle(spriteBatch,
new Vector2(abyssIsland.Area.X, -abyssIsland.Area.Y - abyssIsland.Area.Height), abyssIsland.Area.Size.ToVector2(), Color.Cyan, thickness: 5);
396 foreach (var ruin
in level.Ruins)
398 ruin.DebugDraw(spriteBatch);
402 Vector2 pos =
new Vector2(0.0f, -level.Size.Y);
405 int topBarrierWidth = level.GenerationParams.WallEdgeSprite.Texture.Width;
406 int topBarrierHeight = level.GenerationParams.WallEdgeSprite.Texture.Height;
408 pos.X = cam.
WorldView.X - topBarrierWidth;
409 int width = (int)(Math.Ceiling(cam.
WorldView.Width / 1024 + 4.0f) * topBarrierWidth);
411 GUI.DrawRectangle(spriteBatch,
new Rectangle(
412 (
int)MathUtils.Round(pos.X, topBarrierWidth),
418 spriteBatch.Draw(level.GenerationParams.WallEdgeSprite.Texture,
419 new Rectangle((
int)MathUtils.Round(pos.X, topBarrierWidth), (
int)(pos.Y - topBarrierHeight + level.GenerationParams.WallEdgeExpandOutwardsAmount), width, topBarrierHeight),
420 new Rectangle(0, 0, width, -topBarrierHeight),
423 SpriteEffects.None, 0.0f);
428 int bottomBarrierWidth = level.GenerationParams.WallEdgeSprite.Texture.Width;
429 int bottomBarrierHeight = level.GenerationParams.WallEdgeSprite.Texture.Height;
430 pos =
new Vector2(cam.
WorldView.X - bottomBarrierWidth, -level.BottomPos);
431 int width = (int)(Math.Ceiling(cam.
WorldView.Width / bottomBarrierWidth + 4.0f) * bottomBarrierWidth);
433 GUI.DrawRectangle(spriteBatch,
new Rectangle(
434 (
int)(MathUtils.Round(pos.X, bottomBarrierWidth)),
435 -(level.BottomPos - 60),
440 spriteBatch.Draw(level.GenerationParams.WallEdgeSprite.Texture,
441 new Rectangle((
int)MathUtils.Round(pos.X, bottomBarrierWidth), -level.BottomPos - (
int)level.GenerationParams.WallEdgeExpandOutwardsAmount, width, bottomBarrierHeight),
442 new Rectangle(0, 0, width, -bottomBarrierHeight),
445 SpriteEffects.FlipVertically, 0.0f);
452 if (!vertexBuffers.Any()) {
return; }
454 var defaultRasterizerState = graphicsDevice.RasterizerState;
459 graphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;
460 graphicsDevice.RasterizerState = cullNone;
463 for (
int i = 0; i < 2; i++)
465 var wallList = i == 0 ? level.ExtraWalls : level.UnsyncedExtraWalls;
470 wallCenterEffect.Texture = level.GenerationParams.DestructibleWallSprite?.Texture ?? level.GenerationParams.WallSprite.Texture;
471 wallCenterEffect.World = wall.
GetTransform() * transformMatrix;
472 wallCenterEffect.Alpha = wall.
Alpha;
473 wallCenterEffect.CurrentTechnique.Passes[0].Apply();
474 graphicsDevice.SetVertexBuffer(wall.
WallBuffer);
475 graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (
int)Math.Floor(wall.
WallBuffer.VertexCount / 3.0f));
477 if (destructibleWall.Damage > 0.0f)
479 wallCenterEffect.Texture = level.GenerationParams.WallSpriteDestroyed.Texture;
480 wallCenterEffect.Alpha = MathHelper.Lerp(0.2f, 1.0f, destructibleWall.Damage / destructibleWall.MaxHealth) * wall.
Alpha;
481 wallCenterEffect.CurrentTechnique.Passes[0].Apply();
482 graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (
int)Math.Floor(wall.
WallEdgeBuffer.VertexCount / 3.0f));
485 wallEdgeEffect.Texture = level.GenerationParams.DestructibleWallEdgeSprite?.Texture ?? level.GenerationParams.WallEdgeSprite.Texture;
486 wallEdgeEffect.World = wall.
GetTransform() * transformMatrix;
487 wallEdgeEffect.Alpha = wall.
Alpha;
488 wallEdgeEffect.CurrentTechnique.Passes[0].Apply();
490 graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (
int)Math.Floor(wall.
WallEdgeBuffer.VertexCount / 3.0f));
494 wallEdgeEffect.Alpha = 1.0f;
495 wallCenterEffect.Alpha = 1.0f;
497 wallCenterEffect.World = transformMatrix;
498 wallEdgeEffect.World = transformMatrix;
501 foreach (var vertexBuffer
in vertexBuffers)
503 wallCenterEffect.Texture = vertexBuffer.WallTexture;
504 wallCenterEffect.CurrentTechnique.Passes[0].Apply();
505 graphicsDevice.SetVertexBuffer(vertexBuffer.WallBuffer);
506 graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (
int)Math.Floor(vertexBuffer.WallBuffer.VertexCount / 3.0f));
508 wallEdgeEffect.Texture = vertexBuffer.EdgeTexture;
509 wallEdgeEffect.CurrentTechnique.Passes[0].Apply();
510 graphicsDevice.SetVertexBuffer(vertexBuffer.WallEdgeBuffer);
511 graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (
int)Math.Floor(vertexBuffer.WallEdgeBuffer.VertexCount / 3.0f));
514 wallCenterEffect.Texture = level.GenerationParams.WallSprite.Texture;
515 wallEdgeEffect.Texture = level.GenerationParams.WallEdgeSprite.Texture;
518 for (
int i = 0; i < 2; i++)
520 var wallList = i == 0 ? level.ExtraWalls : level.UnsyncedExtraWalls;
525 wallCenterEffect.World = wall.
GetTransform() * transformMatrix;
526 wallCenterEffect.Alpha = wall.
Alpha;
527 wallCenterEffect.CurrentTechnique.Passes[0].Apply();
528 graphicsDevice.SetVertexBuffer(wall.
WallBuffer);
529 graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (
int)Math.Floor(wall.
WallBuffer.VertexCount / 3.0f));
531 wallEdgeEffect.World = wall.
GetTransform() * transformMatrix;
532 wallEdgeEffect.Alpha = wall.
Alpha;
533 wallEdgeEffect.CurrentTechnique.Passes[0].Apply();
535 graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, (
int)Math.Floor(wall.
WallEdgeBuffer.VertexCount / 3.0f));
539 graphicsDevice.RasterizerState = defaultRasterizerState;
544 foreach (var vertexBuffer
in vertexBuffers)
546 vertexBuffer.Dispose();
548 vertexBuffers.Clear();
static int GraphicsHeight
static Lights.LightManager LightManager
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
LevelRenderer(Level level)
void DrawBackground(SpriteBatch spriteBatch, Camera cam, LevelObjectManager backgroundSpriteManager=null, BackgroundCreatureManager backgroundCreatureManager=null)
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)
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 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