Files
LuaCsForBarotraumaEP/Subsurface/Source/Screens/GameScreen.cs
juanjp600 7e6ef65eb3 Improved LOS effect
It's pretty inefficient (I need to figure out how to set up new shaders), and it might let the player see too much, but it looks way better than pure black.
2016-10-12 16:54:41 -03:00

431 lines
17 KiB
C#

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Barotrauma.Lights;
using System.Diagnostics;
using Microsoft.Xna.Framework.Content;
namespace Barotrauma
{
class GameScreen : Screen
{
Camera cam;
readonly RenderTarget2D renderTargetBackground;
readonly RenderTarget2D renderTarget;
readonly RenderTarget2D renderTargetWater;
readonly RenderTarget2D renderTargetAir;
private BlurEffect lightBlur;
private Effect damageEffect;
private Texture2D damageStencil;
public BackgroundCreatureManager BackgroundCreatureManager;
public override Camera Cam
{
get { return cam; }
}
public GameScreen(GraphicsDevice graphics, ContentManager content)
{
cam = new Camera();
cam.Translate(new Vector2(-10.0f, 50.0f));
renderTargetBackground = new RenderTarget2D(graphics, GameMain.GraphicsWidth, GameMain.GraphicsHeight);
renderTarget = new RenderTarget2D(graphics, GameMain.GraphicsWidth, GameMain.GraphicsHeight);
renderTargetWater = new RenderTarget2D(graphics, GameMain.GraphicsWidth, GameMain.GraphicsHeight);
renderTargetAir = new RenderTarget2D(graphics, GameMain.GraphicsWidth, GameMain.GraphicsHeight);
var files = GameMain.SelectedPackage.GetFilesOfType(ContentType.BackgroundCreaturePrefabs);
if(files.Count > 0)
BackgroundCreatureManager = new BackgroundCreatureManager(files);
else
BackgroundCreatureManager = new BackgroundCreatureManager("Content/BackgroundSprites/BackgroundCreaturePrefabs.xml");
#if LINUX
var blurEffect = content.Load<Effect>("blurshader_opengl");
damageEffect = content.Load<Effect>("damageshader_opengl");
#else
var blurEffect = content.Load<Effect>("blurshader");
damageEffect = content.Load<Effect>("damageshader");
#endif
damageStencil = TextureLoader.FromFile("Content/Map/walldamage.png");
damageEffect.Parameters["xStencil"].SetValue(damageStencil);
damageEffect.Parameters["aMultiplier"].SetValue(50.0f);
damageEffect.Parameters["cMultiplier"].SetValue(200.0f);
lightBlur = new BlurEffect(blurEffect, 0.001f, 0.001f);
}
public override void Select()
{
base.Select();
if (Character.Controlled!=null)
{
cam.Position = Character.Controlled.WorldPosition;
}
else if (Submarine.MainSub != null)
{
cam.Position = Submarine.MainSub.WorldPosition;
}
foreach (MapEntity entity in MapEntity.mapEntityList)
entity.IsHighlighted = false;
}
public override void Deselect()
{
base.Deselect();
Sounds.SoundManager.LowPassHFGain = 1.0f;
}
/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
public override void Update(double deltaTime)
{
#if DEBUG
if (GameMain.GameSession != null && GameMain.GameSession.Level != null && GameMain.GameSession.Submarine != null)
{
var closestSub = Submarine.GetClosest(cam.WorldViewCenter);
if (closestSub == null) closestSub = GameMain.GameSession.Submarine;
Vector2 targetMovement = Vector2.Zero;
if (PlayerInput.KeyDown(Keys.I)) targetMovement.Y += 1.0f;
if (PlayerInput.KeyDown(Keys.K)) targetMovement.Y -= 1.0f;
if (PlayerInput.KeyDown(Keys.J)) targetMovement.X -= 1.0f;
if (PlayerInput.KeyDown(Keys.L)) targetMovement.X += 1.0f;
if (targetMovement != Vector2.Zero)
closestSub.ApplyForce(targetMovement * closestSub.SubBody.Body.Mass * 100.0f);
}
#endif
if (GameMain.GameSession != null) GameMain.GameSession.Update((float)deltaTime);
if (Level.Loaded != null) Level.Loaded.Update((float)deltaTime);
if (Character.Controlled != null && Character.Controlled.SelectedConstruction != null)
{
if (Character.Controlled.SelectedConstruction == Character.Controlled.ClosestItem)
{
Character.Controlled.SelectedConstruction.UpdateHUD(cam, Character.Controlled);
}
}
Character.UpdateAll(cam, (float)deltaTime);
BackgroundCreatureManager.Update(cam, (float)deltaTime);
GameMain.ParticleManager.Update((float)deltaTime);
StatusEffect.UpdateAll((float)deltaTime);
if (Character.Controlled != null && Lights.LightManager.ViewTarget != null)
{
cam.TargetPos = Lights.LightManager.ViewTarget.WorldPosition;
}
GameMain.LightManager.Update((float)deltaTime);
cam.MoveCamera((float)deltaTime);
foreach (Submarine sub in Submarine.Loaded)
{
sub.SetPrevTransform(sub.Position);
}
foreach (PhysicsBody pb in PhysicsBody.list)
{
pb.SetPrevTransform(pb.SimPosition, pb.Rotation);
}
MapEntity.UpdateAll(cam, (float)deltaTime);
Character.UpdateAnimAll((float)deltaTime);
Ragdoll.UpdateAll(cam, (float)deltaTime);
foreach (Submarine sub in Submarine.Loaded)
{
sub.Update((float)deltaTime);
}
GameMain.World.Step((float)deltaTime);
if (!PlayerInput.LeftButtonHeld())
{
Inventory.draggingSlot = null;
Inventory.draggingItem = null;
}
}
public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
{
cam.UpdateTransform(true);
DrawMap(graphics, spriteBatch);
spriteBatch.Begin();
if (Character.Controlled != null && Character.Controlled.SelectedConstruction != null)
{
if (Character.Controlled.SelectedConstruction == Character.Controlled.ClosestItem)
{
Character.Controlled.SelectedConstruction.DrawHUD(spriteBatch, cam, Character.Controlled);
}
else if (!Character.Controlled.SelectedConstruction.IsInPickRange(Character.Controlled.WorldPosition))
{
Character.Controlled.SelectedConstruction = null;
}
}
if (Character.Controlled != null && cam != null) Character.Controlled.DrawHUD(spriteBatch, cam);
if (GameMain.GameSession != null) GameMain.GameSession.Draw(spriteBatch);
if (Character.Controlled == null && Submarine.MainSub != null) DrawSubmarineIndicator(spriteBatch, Submarine.MainSub);
GUI.Draw((float)deltaTime, spriteBatch, cam);
spriteBatch.End();
}
public void DrawMap(GraphicsDevice graphics, SpriteBatch spriteBatch)
{
foreach (Submarine sub in Submarine.Loaded)
{
sub.UpdateTransform();
}
GameMain.ParticleManager.UpdateTransforms();
GameMain.LightManager.ObstructVision = Character.Controlled != null && Character.Controlled.ObstructVision;
GameMain.LightManager.UpdateLightMap(graphics, spriteBatch, cam, lightBlur.Effect);
if (Character.Controlled != null)
{
GameMain.LightManager.UpdateObstructVision(graphics, spriteBatch, cam, Character.Controlled.CursorWorldPosition);
}
//----------------------------------------------------------------------------------------
//1. draw the background, characters and the parts of the submarine that are behind them
//----------------------------------------------------------------------------------------
graphics.SetRenderTarget(renderTargetBackground);
if (Level.Loaded == null)
{
graphics.Clear(new Color(11, 18, 26, 255));
}
else
{
Level.Loaded.DrawBack(graphics, spriteBatch, cam, BackgroundCreatureManager);
}
spriteBatch.Begin(SpriteSortMode.BackToFront,
BlendState.AlphaBlend,
null, null, null, null,
cam.Transform);
Submarine.DrawBack(spriteBatch,false,s => s is Structure);
spriteBatch.End();
graphics.SetRenderTarget(renderTarget);
spriteBatch.Begin(SpriteSortMode.Deferred,
BlendState.Opaque);
spriteBatch.Draw(renderTargetBackground, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.White);
spriteBatch.End();
spriteBatch.Begin(SpriteSortMode.BackToFront,
BlendState.AlphaBlend,
null, null, null, null,
cam.Transform);
Submarine.DrawBack(spriteBatch, false, s => !(s is Structure));
foreach (Character c in Character.CharacterList) c.Draw(spriteBatch);
spriteBatch.End();
//----------------------------------------------------------------------------------------
//draw the rendertarget and particles that are only supposed to be drawn in water into renderTargetWater
graphics.SetRenderTarget(renderTargetWater);
spriteBatch.Begin(SpriteSortMode.Deferred,
BlendState.Opaque);
spriteBatch.Draw(renderTarget, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), new Color(0.75f, 0.8f, 0.9f, 1.0f));
spriteBatch.End();
#if LINUX
spriteBatch.Begin(SpriteSortMode.Deferred,
BlendState.NonPremultiplied,
null, DepthStencilState.DepthRead, null, null,
cam.Transform);
#else
spriteBatch.Begin(SpriteSortMode.Deferred,
BlendState.AlphaBlend,
null, DepthStencilState.DepthRead, null, null,
cam.Transform);
#endif
GameMain.ParticleManager.Draw(spriteBatch, true, Particles.ParticleBlendState.AlphaBlend);
spriteBatch.End();
spriteBatch.Begin(SpriteSortMode.Deferred,
BlendState.Additive,
null, DepthStencilState.Default, null, null,
cam.Transform);
GameMain.ParticleManager.Draw(spriteBatch, true, Particles.ParticleBlendState.Additive);
spriteBatch.End();
//----------------------------------------------------------------------------------------
//draw the rendertarget and particles that are only supposed to be drawn in air into renderTargetAir
graphics.SetRenderTarget(renderTargetAir);
spriteBatch.Begin(SpriteSortMode.Deferred,
BlendState.Opaque);
spriteBatch.Draw(renderTarget, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.White);
spriteBatch.End();
#if LINUX
spriteBatch.Begin(SpriteSortMode.Deferred,
BlendState.NonPremultiplied,
null, DepthStencilState.DepthRead, null, null,
cam.Transform);
#else
spriteBatch.Begin(SpriteSortMode.Deferred,
BlendState.AlphaBlend,
null, DepthStencilState.DepthRead, null, null,
cam.Transform);
#endif
GameMain.ParticleManager.Draw(spriteBatch, false, Particles.ParticleBlendState.AlphaBlend);
spriteBatch.End();
spriteBatch.Begin(SpriteSortMode.Deferred,
BlendState.Additive,
null, DepthStencilState.DepthRead, null, null,
cam.Transform);
GameMain.ParticleManager.Draw(spriteBatch, false, Particles.ParticleBlendState.Additive);
spriteBatch.End();
if (Character.Controlled != null)
{
graphics.SetRenderTarget(renderTarget);
spriteBatch.Begin(SpriteSortMode.Deferred,
BlendState.Opaque, null, null, null, lightBlur.Effect);
spriteBatch.Draw(renderTargetBackground, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.White);
spriteBatch.End();
spriteBatch.Begin(SpriteSortMode.BackToFront,
BlendState.AlphaBlend, SamplerState.LinearWrap,
null, null, null,
cam.Transform);
Submarine.DrawDamageable(spriteBatch, null);
spriteBatch.End();
GameMain.LightManager.DrawLOS(spriteBatch, lightBlur.Effect, true);
}
graphics.SetRenderTarget(null);
//----------------------------------------------------------------------------------------
//2. pass the renderTarget to the water shader to do the water effect
//----------------------------------------------------------------------------------------
Hull.renderer.RenderBack(spriteBatch, renderTargetWater);
Array.Clear(Hull.renderer.vertices, 0, Hull.renderer.vertices.Length);
Hull.renderer.PositionInBuffer = 0;
foreach (Hull hull in Hull.hullList)
{
hull.Render(graphics, cam);
}
Hull.renderer.Render(graphics, cam, renderTargetAir, Cam.ShaderTransform);
//----------------------------------------------------------------------------------------
//3. draw the sections of the map that are on top of the water
//----------------------------------------------------------------------------------------
spriteBatch.Begin(SpriteSortMode.BackToFront,
BlendState.AlphaBlend, SamplerState.LinearWrap,
null, null, null,
cam.Transform);
Submarine.DrawFront(spriteBatch);
spriteBatch.End();
spriteBatch.Begin(SpriteSortMode.Immediate,
BlendState.NonPremultiplied, SamplerState.LinearWrap,
null, null,
damageEffect,
cam.Transform);
Submarine.DrawDamageable(spriteBatch, damageEffect);
spriteBatch.End();
GameMain.LightManager.DrawLightMap(spriteBatch, lightBlur.Effect);
spriteBatch.Begin(SpriteSortMode.BackToFront,
BlendState.AlphaBlend, SamplerState.LinearWrap,
null, null, null,
cam.Transform);
if (Level.Loaded != null) Level.Loaded.DrawFront(spriteBatch);
foreach (Character c in Character.CharacterList) c.DrawFront(spriteBatch,cam);
spriteBatch.End();
if (Character.Controlled != null)
{
GameMain.LightManager.DrawLOS(spriteBatch, lightBlur.Effect,false);
spriteBatch.Begin(SpriteSortMode.Immediate,
BlendState.AlphaBlend);
float r = Math.Min(CharacterHUD.damageOverlayTimer * 0.03f, 0.04f);
spriteBatch.Draw(renderTarget, new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight),
new Color(0.04f + r, Math.Max(0.04f-r,0.0f), Math.Max(0.045f - r, 0.0f), 1.0f));
spriteBatch.End();
}
}
private void DrawSubmarineIndicator(SpriteBatch spriteBatch, Submarine submarine)
{
Vector2 subDiff = submarine.WorldPosition - cam.WorldViewCenter;
if (Math.Abs(subDiff.X) > cam.WorldView.Width || Math.Abs(subDiff.Y) > cam.WorldView.Height)
{
Vector2 normalizedSubDiff = Vector2.Normalize(subDiff);
Vector2 iconPos =
cam.WorldToScreen(cam.WorldViewCenter) +
new Vector2(normalizedSubDiff.X * GameMain.GraphicsWidth * 0.4f, -normalizedSubDiff.Y * GameMain.GraphicsHeight * 0.4f);
GUI.SubmarineIcon.Draw(spriteBatch, iconPos, Color.LightBlue * 0.5f);
Vector2 arrowOffset = normalizedSubDiff * GUI.SubmarineIcon.size.X * 0.7f;
arrowOffset.Y = -arrowOffset.Y;
GUI.Arrow.Draw(spriteBatch, iconPos + arrowOffset, Color.LightBlue * 0.5f, MathUtils.VectorToAngle(arrowOffset) + MathHelper.PiOver2);
}
}
}
}