abc
This commit is contained in:
parent
f04752d09c
commit
6b81ddd34c
2 changed files with 92 additions and 26 deletions
|
|
@ -4,17 +4,39 @@ using Microsoft.Xna.Framework.Input;
|
||||||
using MonoGame.Extended;
|
using MonoGame.Extended;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace Orpticon.MonoGameLighting
|
namespace Orpticon.MonoGameLighting
|
||||||
{
|
{
|
||||||
public static class Lighting
|
public static class Lighting
|
||||||
{
|
{
|
||||||
|
public static Rectangle Extend(this Rectangle rect, float factor)
|
||||||
|
{
|
||||||
|
int extensionX = (int)(rect.Width * factor - rect.Width);
|
||||||
|
int extensionY = (int)(rect.Height * factor - rect.Height);
|
||||||
|
rect.X -= extensionX / 2;
|
||||||
|
rect.Y -= extensionY / 2;
|
||||||
|
rect.Width += extensionX;
|
||||||
|
rect.Height += extensionY;
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
public static RectangleF Extend(this RectangleF rect, float factor)
|
||||||
|
{
|
||||||
|
float extensionX = (rect.Width * factor - rect.Width);
|
||||||
|
float extensionY = (rect.Height * factor - rect.Height);
|
||||||
|
rect.X -= extensionX / 2;
|
||||||
|
rect.Y -= extensionY / 2;
|
||||||
|
rect.Width += extensionX;
|
||||||
|
rect.Height += extensionY;
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
private static Texture2D pixelTexture;
|
private static Texture2D pixelTexture;
|
||||||
public static float MaxOpacity { get; set; } = 0.5f; // Maximum opacity
|
public static float MaxOpacity { get; set; } = 0.5f; // Maximum opacity
|
||||||
public static float BaseDarkness { get; set; } = 0.95f;
|
public static float BaseDarkness { get; set; } = 0.95f;
|
||||||
private static Rectangle CameraRect;
|
private static Rectangle CameraRect;
|
||||||
private static float[] alphaMap;
|
//public static float CalculationExtensionFactor = 2;
|
||||||
|
public static float[] AlphaMap;
|
||||||
public static void Initialize(GraphicsDeviceManager graphicsDevice, Rectangle cameraRect)
|
public static void Initialize(GraphicsDeviceManager graphicsDevice, Rectangle cameraRect)
|
||||||
{
|
{
|
||||||
// TODO: Add your initialization logic here
|
// TODO: Add your initialization logic here
|
||||||
|
|
@ -23,18 +45,40 @@ namespace Orpticon.MonoGameLighting
|
||||||
pixelTexture.SetData(new Color[] { Color.White });
|
pixelTexture.SetData(new Color[] { Color.White });
|
||||||
|
|
||||||
CameraRect = cameraRect;
|
CameraRect = cameraRect;
|
||||||
|
//CameraRect = CameraRect.Extend(CalculationExtensionFactor);
|
||||||
|
|
||||||
alphaMap = new float[CameraRect.Width * CameraRect.Height];
|
AlphaMap = new float[CameraRect.Width * CameraRect.Height];
|
||||||
Array.Fill(alphaMap, 1f);
|
Array.Fill(AlphaMap, 1f);
|
||||||
|
}
|
||||||
|
public static bool IsLit(Matrix camera, Vector2 point, bool allowCheckNearby = false) => IsLit(camera, point, out float darkness, allowCheckNearby);
|
||||||
|
public static bool IsLit(Matrix camera, Vector2 point, out float darkness, bool allowCheckNearby = false)
|
||||||
|
{
|
||||||
|
var pos = point.ToPoint() - CameraRect.Location;
|
||||||
|
darkness = 1;
|
||||||
|
if (!allowCheckNearby && !CameraRect.Contains(point)) return false;
|
||||||
|
if (pos.X < 0 || pos.Y < 0 || pos.X >= CameraRect.Width || pos.Y >= CameraRect.Height)
|
||||||
|
{
|
||||||
|
if (!allowCheckNearby) return false;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (pos.X < 0) pos.X++;
|
||||||
|
while (pos.Y < 0) pos.Y++;
|
||||||
|
while (pos.X >= CameraRect.Width) pos.X--;
|
||||||
|
while (pos.Y >= CameraRect.Height) pos.Y--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Debug.WriteLine(pos);
|
||||||
|
var alpha = AlphaMap[pos.Y * CameraRect.Width + pos.X];
|
||||||
|
darkness = alpha;
|
||||||
|
return alpha < 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void RenderCone(SpriteBatch _spriteBatch, Vector2 originPoint, float radius) => RenderCone(_spriteBatch, originPoint, new Vector2(0, -1), radius, 360, new List<RectangleF>(), Color.White);
|
public static void RenderCone(SpriteBatch _spriteBatch, Vector2 originPoint, float radius) => RenderCone(_spriteBatch, originPoint, new Vector2(0, -1), radius, 360, new List<RectangleF>(), Color.White);
|
||||||
public static void RenderCone(SpriteBatch _spriteBatch, Vector2 originPoint, float radius, Color color) => RenderCone(_spriteBatch, originPoint, new Vector2(0, -1), radius, 360, new List<RectangleF>(), color);
|
public static void RenderCone(SpriteBatch _spriteBatch, Vector2 originPoint, float radius, Color color) => RenderCone(_spriteBatch, originPoint, new Vector2(0, -1), radius, 360, new List<RectangleF>(), color);
|
||||||
public static void RenderCone(SpriteBatch _spriteBatch, Vector2 originPoint, float radius, List<RectangleF> collisionBoxes) => RenderCone(_spriteBatch, originPoint, new Vector2(0, -1), radius, 360, collisionBoxes, Color.White);
|
public static void RenderCone(SpriteBatch _spriteBatch, Vector2 originPoint, float radius, IEnumerable<RectangleF> collisionBoxes) => RenderCone(_spriteBatch, originPoint, new Vector2(0, -1), radius, 360, collisionBoxes, Color.White);
|
||||||
public static void RenderCone(SpriteBatch _spriteBatch, Vector2 originPoint, float radius, List<RectangleF> collisionBoxes, Color color) => RenderCone(_spriteBatch, originPoint, new Vector2(0, -1), radius, 360, collisionBoxes, color);
|
public static void RenderCone(SpriteBatch _spriteBatch, Vector2 originPoint, float radius, IEnumerable<RectangleF> collisionBoxes, Color color) => RenderCone(_spriteBatch, originPoint, new Vector2(0, -1), radius, 360, collisionBoxes, color);
|
||||||
public static void RenderCone(SpriteBatch _spriteBatch, Vector2 originPoint, Vector2 direction, float coneRadius, float coneAngleInDegrees) => RenderCone(_spriteBatch, originPoint, direction, coneRadius, coneAngleInDegrees, new List<RectangleF>(), Color.White);
|
public static void RenderCone(SpriteBatch _spriteBatch, Vector2 originPoint, Vector2 direction, float coneRadius, float coneAngleInDegrees) => RenderCone(_spriteBatch, originPoint, direction, coneRadius, coneAngleInDegrees, new List<RectangleF>(), Color.White);
|
||||||
public static void RenderCone(SpriteBatch _spriteBatch, Vector2 originPoint, Vector2 direction, float coneRadius, float coneAngleInDegrees, List<RectangleF> collisionBoxes) => RenderCone(_spriteBatch, originPoint, direction, coneRadius, coneAngleInDegrees, collisionBoxes, Color.White);
|
public static void RenderCone(SpriteBatch _spriteBatch, Vector2 originPoint, Vector2 direction, float coneRadius, float coneAngleInDegrees, IEnumerable<RectangleF> collisionBoxes) => RenderCone(_spriteBatch, originPoint, direction, coneRadius, coneAngleInDegrees, collisionBoxes, Color.White);
|
||||||
public static void RenderCone(SpriteBatch _spriteBatch, Vector2 originPoint, Vector2 notNormalizedDirection, float coneRadius, float coneAngleInDegrees, List<RectangleF> collisionBoxes, Color color)
|
public static void RenderCone(SpriteBatch _spriteBatch, Vector2 originPoint, Vector2 notNormalizedDirection, float coneRadius, float coneAngleInDegrees, IEnumerable<RectangleF> collisionBoxes, Color color)
|
||||||
{
|
{
|
||||||
float halfAngle = MathHelper.ToRadians(coneAngleInDegrees) / 2;
|
float halfAngle = MathHelper.ToRadians(coneAngleInDegrees) / 2;
|
||||||
Vector2 normalizedDirection = Vector2.Normalize(notNormalizedDirection);
|
Vector2 normalizedDirection = Vector2.Normalize(notNormalizedDirection);
|
||||||
|
|
@ -54,7 +98,7 @@ namespace Orpticon.MonoGameLighting
|
||||||
foreach (var collisionBox in collisionBoxes)
|
foreach (var collisionBox in collisionBoxes)
|
||||||
{
|
{
|
||||||
Vector2 boxCenter = new Vector2(collisionBox.Center.X, collisionBox.Center.Y);
|
Vector2 boxCenter = new Vector2(collisionBox.Center.X, collisionBox.Center.Y);
|
||||||
Vector2 directionToBox = Vector2.Normalize(boxCenter - originPoint);
|
Vector2 directionToBox = boxCenter - originPoint;
|
||||||
float distanceToBoxCenter = Vector2.Distance(originPoint, boxCenter);
|
float distanceToBoxCenter = Vector2.Distance(originPoint, boxCenter);
|
||||||
if (distanceToBoxCenter > coneRadius + maxBoundingCircleRadius)
|
if (distanceToBoxCenter > coneRadius + maxBoundingCircleRadius)
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -80,14 +124,13 @@ namespace Orpticon.MonoGameLighting
|
||||||
{
|
{
|
||||||
for (float x = startingPoint.X; x < originPoint.X + coneRadius; x += 1)
|
for (float x = startingPoint.X; x < originPoint.X + coneRadius; x += 1)
|
||||||
{
|
{
|
||||||
if(!CameraRect.Contains(x, y)) continue;
|
if (!CameraRect.Contains(x, y)) continue;
|
||||||
Vector2 blockCenter = new Vector2(x + 1 / 2, y + 1 / 2);
|
Vector2 blockCenter = new Vector2(x + 1 / 2, y + 1 / 2);
|
||||||
Vector2 toBlock = blockCenter - originPoint;
|
Vector2 toBlock = blockCenter - originPoint;
|
||||||
if (toBlock.LengthSquared() > radiusSquared)
|
if (toBlock.LengthSquared() > radiusSquared)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Vector2 directionToBlock = Vector2.Normalize(toBlock);
|
float angleToBlock = (float)Math.Atan2(toBlock.Y, toBlock.X);
|
||||||
float angleToBlock = (float)Math.Atan2(directionToBlock.Y, directionToBlock.X);
|
|
||||||
if (angleToBlock < 0)
|
if (angleToBlock < 0)
|
||||||
angleToBlock += MathHelper.TwoPi;
|
angleToBlock += MathHelper.TwoPi;
|
||||||
|
|
||||||
|
|
@ -124,7 +167,7 @@ namespace Orpticon.MonoGameLighting
|
||||||
private static void DrawFilledRectangle(int x, int y, float opacity)
|
private static void DrawFilledRectangle(int x, int y, float opacity)
|
||||||
{
|
{
|
||||||
int i = (y - CameraRect.Y) * CameraRect.Width + (x - CameraRect.X);
|
int i = (y - CameraRect.Y) * CameraRect.Width + (x - CameraRect.X);
|
||||||
alphaMap[i] *= (1 - opacity);
|
AlphaMap[i] *= (1 - opacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool PointInCone(Vector2 point, Vector2 originPoint, Vector2 endPoint, float coneRadius, float angleOffset)
|
private static bool PointInCone(Vector2 point, Vector2 originPoint, Vector2 endPoint, float coneRadius, float angleOffset)
|
||||||
|
|
@ -147,36 +190,53 @@ namespace Orpticon.MonoGameLighting
|
||||||
}
|
}
|
||||||
private static bool RayIntersectsRectangle(Vector2 rayStart, Vector2 rayEnd, RectangleF rectangle)
|
private static bool RayIntersectsRectangle(Vector2 rayStart, Vector2 rayEnd, RectangleF rectangle)
|
||||||
{
|
{
|
||||||
|
// Calculate direction and its inverse
|
||||||
Vector2 direction = rayEnd - rayStart;
|
Vector2 direction = rayEnd - rayStart;
|
||||||
float invDirX = 1.0f / direction.X;
|
float invDirX = 1.0f / direction.X;
|
||||||
float invDirY = 1.0f / direction.Y;
|
float invDirY = 1.0f / direction.Y;
|
||||||
|
|
||||||
float tNearX = (rectangle.Left - rayStart.X) * invDirX;
|
// Pre-compute intersection times for x and y boundaries
|
||||||
float tNearY = (rectangle.Top - rayStart.Y) * invDirY;
|
float t1 = (rectangle.Left - rayStart.X) * invDirX;
|
||||||
float tFarX = (rectangle.Right - rayStart.X) * invDirX;
|
float t2 = (rectangle.Right - rayStart.X) * invDirX;
|
||||||
float tFarY = (rectangle.Bottom - rayStart.Y) * invDirY;
|
float t3 = (rectangle.Top - rayStart.Y) * invDirY;
|
||||||
|
float t4 = (rectangle.Bottom - rayStart.Y) * invDirY;
|
||||||
|
|
||||||
if (tNearX > tFarX) (tNearX, tFarX) = (tFarX, tNearX);
|
// Sort near and far times
|
||||||
if (tNearY > tFarY) (tNearY, tFarY) = (tFarY, tNearY);
|
if (t1 > t2) { var temp = t1; t1 = t2; t2 = temp; }
|
||||||
|
if (t3 > t4) { var temp = t3; t3 = t4; t4 = temp; }
|
||||||
|
|
||||||
if (tNearX > tFarY || tNearY > tFarX)
|
// Check if the ray misses the rectangle
|
||||||
return false;
|
if (t1 > t4 || t3 > t2) return false;
|
||||||
|
|
||||||
float tNear = Math.Max(tNearX, tNearY);
|
// Calculate the times of intersection
|
||||||
float tFar = Math.Min(tFarX, tFarY);
|
float tNear = Math.Max(t1, t3);
|
||||||
|
float tFar = Math.Min(t2, t4);
|
||||||
|
|
||||||
|
// Return true if there's a valid intersection range
|
||||||
return tNear >= 0 && tFar >= 0 && tNear <= 1;
|
return tNear >= 0 && tFar >= 0 && tNear <= 1;
|
||||||
}
|
}
|
||||||
public static void ApplyAlphaMap(SpriteBatch _spriteBatch)
|
public static void ApplyAlphaMap(SpriteBatch _spriteBatch)
|
||||||
{
|
{
|
||||||
for(int x = 0; x < CameraRect.Width; x++)
|
// Create a new texture with the same dimensions as the CameraRect
|
||||||
|
Texture2D texture = new Texture2D(_spriteBatch.GraphicsDevice, CameraRect.Width, CameraRect.Height);
|
||||||
|
|
||||||
|
// Create an array to hold the color data
|
||||||
|
Color[] colorData = new Color[CameraRect.Width * CameraRect.Height];
|
||||||
|
|
||||||
|
// Set the color data based on the AlphaMap
|
||||||
|
for (int x = 0; x < CameraRect.Width; x++)
|
||||||
{
|
{
|
||||||
for(int y = 0; y < CameraRect.Height; y++)
|
for (int y = 0; y < CameraRect.Height; y++)
|
||||||
{
|
{
|
||||||
int i = y * CameraRect.Width + x;
|
int i = y * CameraRect.Width + x;
|
||||||
_spriteBatch.Draw(pixelTexture, new Rectangle(x + CameraRect.X, y + CameraRect.Y, 1, 1), Color.Black * BaseDarkness * alphaMap[i]);
|
colorData[i] = Color.Black * BaseDarkness * AlphaMap[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the color data for the texture
|
||||||
|
texture.SetData(colorData);
|
||||||
|
|
||||||
|
_spriteBatch.Draw(texture, new Rectangle(CameraRect.X, CameraRect.Y, CameraRect.Width, CameraRect.Height), Color.White);
|
||||||
}
|
}
|
||||||
//protected override void Draw(GameTime gameTime)
|
//protected override void Draw(GameTime gameTime)
|
||||||
//{
|
//{
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,12 @@
|
||||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||||
<ApplicationIcon>Icon.ico</ApplicationIcon>
|
<ApplicationIcon>Icon.ico</ApplicationIcon>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
<DebugType>embedded</DebugType>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
|
<DebugType>embedded</DebugType>
|
||||||
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Remove="Icon.ico" />
|
<None Remove="Icon.ico" />
|
||||||
<None Remove="Icon.bmp" />
|
<None Remove="Icon.bmp" />
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue