Ok, heres the code bit… Some parts of it are just for moving lights and loading textures, but I included it all so it will compile if you simply copy-paste the whole thing… The parts you are after, are commented, and mostly in the Draw() method, and a SEPERATE draw_colors method… Am posting used textures
in next post…
NOTE: while this code runs, its pretty jumbled from tons of editing and testing…
The way it looks now may not be my coolest results, but they demonstrate the colored lights, and some other fun and simple stuff…
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
namespace Game3
{
public class Game1 : Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
// These are just the lights... So I can move them around.
static List<Vector2> positions = new List<Vector2>();
static List<Vector2> directions = new List<Vector2>();
static List<Color> colors = new List<Color>();
static Texture2D light_gradient;
static Texture2D stones;
static Texture2D dust_layer;
static Texture2D deep_shadows;
RenderTarget2D darkness;
RenderTarget2D reflectiveness;
RenderTarget2D colorness;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
graphics.PreferredBackBufferWidth = 900;
graphics.PreferredBackBufferHeight = 600;
}
//Just for counting lights....
static int itemCount = 0;
static int StartingCount = 0;
protected override void Initialize()
{
var pp = GraphicsDevice.PresentationParameters;
darkness = new RenderTarget2D( GraphicsDevice, pp.BackBufferWidth, pp.BackBufferHeight);
reflectiveness = new RenderTarget2D(GraphicsDevice, pp.BackBufferWidth, pp.BackBufferHeight);
colorness = new RenderTarget2D(GraphicsDevice, pp.BackBufferWidth, pp.BackBufferHeight);
positions.Add(new Vector2(100,200));
directions.Add( new Vector2(-1.5f,-1.2f));
colors.Add(new Color(0,0,255,255));
positions.Add(new Vector2(400, 300));
directions.Add(new Vector2(-1.2f, 1.6f));
colors.Add(Color.Red);
positions.Add(new Vector2(250, 400));
directions.Add(new Vector2(-0.51f, 1.0f));
colors.Add(Color.Green);
foreach (Vector2 pos in positions)
{
StartingCount++;
}
itemCount = StartingCount;
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
light_gradient = Content.Load<Texture2D>("light");
stones = Content.Load<Texture2D>("stones");
dust_layer = Content.Load<Texture2D>("stones_dust");
deep_shadows = Content.Load<Texture2D>("cracks");
}
// All the update does, is run a counter that cycles through my lists of pos_vectors, and moves them by the
//corresponding dir_vectors.... It bounces them around when they hit the edges...
protected override void Update(GameTime gameTime)
{
itemCount = StartingCount;
while (itemCount > 0)
{
itemCount--;
positions[itemCount] += directions[itemCount];
if (directions[itemCount].X > -(itemCount+1) && positions[itemCount].X > GraphicsDevice.PresentationParameters.BackBufferWidth-128)
directions[itemCount] = new Vector2(directions[itemCount].X - 0.009f, directions[itemCount].Y);
else if (directions[itemCount].X < itemCount+1 && positions[itemCount].X < 128)
directions[itemCount] = new Vector2(directions[itemCount].X + 0.009f, directions[itemCount].Y);
if (directions[itemCount].Y > -(itemCount+1) && positions[itemCount].Y > GraphicsDevice.PresentationParameters.BackBufferHeight-128)
directions[itemCount] = new Vector2(directions[itemCount].X , directions[itemCount].Y - 0.009f);
else if (directions[itemCount].Y < itemCount+1 && positions[itemCount].Y < 128)
directions[itemCount] = new Vector2(directions[itemCount].X , directions[itemCount].Y + 0.009f);
}
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
//------------- COLORED LIGHTS--------------------------------------
// first, I draw my color layer to its own rendertarget, and save it for later...
//You can comment this out for standard white lights....
Draw_Color();
//------------- THE DARKNESS--------------------------------------
//then I draw the darknes to ITS own rendertarget, as in previous post....
GraphicsDevice.SetRenderTarget(darkness);
GraphicsDevice.Clear(new Color(0, 0, 0, 255));
//-------------- LIGHTS IN THE DARKNESS----------------------------------------------------
//now I blend the lights with the darkness, to give me the basic "black with holes" layer....
//first set the blendstate,
var blend = new BlendState
{
AlphaBlendFunction = BlendFunction.ReverseSubtract,
AlphaSourceBlend = Blend.One,
AlphaDestinationBlend = Blend.One,
};
// then draw the lights using the blendstate above...
spriteBatch.Begin(blendState: blend);
foreach (Vector2 pos in positions)
{
spriteBatch.Draw(light_gradient, pos, null, Color.Black * 0.6f, 0, new Vector2(128, 128), 1.5f, SpriteEffects.None, 0);
spriteBatch.Draw(light_gradient, pos, null, Color.Black * 0.15f, 0, new Vector2(128, 128), 0.8f, SpriteEffects.None, 0);
spriteBatch.Draw(light_gradient, pos, null, Color.Black * 0.05f, 0, new Vector2(128, 128), 0.6f, SpriteEffects.None, 0);
}
spriteBatch.End();
// set the render target back to the backbuffer..... And draw all the render-targets and textures....
GraphicsDevice.SetRenderTarget(null);
GraphicsDevice.Clear(Color.Black);
spriteBatch.Begin();
//first the raw stone wall....
spriteBatch.Draw(stones, new Vector2(0, 0), Color.White);
//what to draw on top of the stones, and in what order, is all fun and tweaking games...
spriteBatch.Draw(colorness, Vector2.Zero, Color.White);
// the dust layer is drawn before the darkness (and thus the lights) but after the color...
// in this way, the way the wall reflects color varies from place to place....
spriteBatch.Draw(dust_layer, new Vector2(0, 0), Color.White);
spriteBatch.Draw(darkness, Vector2.Zero, Color.White * 0.99f);
//Deep shadows and cracks are drawn last, because nothing should be reflecting off them...
spriteBatch.Draw(deep_shadows, new Vector2(0, 0), Color.Black * 1f);
spriteBatch.End();
base.Draw(gameTime);
}
private void Draw_Color()
{
GraphicsDevice.SetRenderTarget(colorness);
GraphicsDevice.Clear(new Color(0, 0, 0, 255));
var blend = new BlendState
{
AlphaBlendFunction = BlendFunction.ReverseSubtract,
AlphaSourceBlend = Blend.One,
AlphaDestinationBlend = Blend.One,
ColorBlendFunction = BlendFunction.Add,
ColorDestinationBlend = Blend.InverseSourceColor,
};
spriteBatch.Begin(blendState : blend);
for (int i = 0; i < StartingCount; i++)
{
spriteBatch.Draw(light_gradient, positions[i], null, colors[i] , 0, new Vector2(128, 128), 1.6f, SpriteEffects.None, 0);
}
spriteBatch.End();
}
}
}