Scaling problems in XNA - xna

Here's the thing. I'm in a team where we're trying to develop a Asteroid like game and my part of the game was everything related to images. I understood everything, but scaling. My problem is that when I scale the image it slightly moves from the position that was originally assign. But, I want it to stay in the same place when it's been scaled. Tried replacing vectors with rectangles and it didn't work. Here's my code:
public class Game1 : Microsoft.Xna.Framework.Game
{
Texture2D texture;
Vector2 position = new Vector2(525, 325);
float scale = 0.3f;
Texture2D texture2;
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
// Frame rate is 30 fps by default for Windows Phone.
TargetElapsedTime = TimeSpan.FromTicks(333333);
// Extend battery life under lock.
InactiveSleepTime = TimeSpan.FromSeconds(1);
}
/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
/// </summary>
protected override void Initialize()
{
// TODO: Add your initialization logic here
base.Initialize();
}
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
texture = Content.Load<Texture2D>("Spacenebula_Backround_");
texture2 = Content.Load<Texture2D>("PressureSphere");
// TODO: use this.Content to load your game content here
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
/// <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>
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
// TODO: Add your update logic here
base.Update(gameTime);
}
/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
spriteBatch.Draw(texture, Vector2.Zero, Color.Wheat);
spriteBatch.Draw(texture2,position, null, Color.Wheat, 0, new Vector2(0, 0), scale, SpriteEffects.None, 0);
spriteBatch.End();
// TODO: Add your drawing code here
base.Draw(gameTime);
}
} }
the smallest scale is 0.3f and the largest 1.3f.
When the scale is at 0.3f looks like this :
When the scale is at 1.3f looks like this:
see what I mean? I need it to be at the same position every time the scale is changed. I would gladly appreciate if anyone helps me.

As part of the spriteBatch.Draw method, you specify the origin of the image. ("new Vector(0,0)")
Currently, you appear to be setting it as the top left corner of the image which means any scaling efforts are going to "grow" from the top left of the image as well.
Try setting the origin to the center of your image(s) instead.
This will ensure the image gets scaled correctly without it appearing to move / get displaced by scaling.

If you are using collision detection, make sure you also use scale parameter into calculation. Height and width of sprite is still same, no matter how you scale it. as well change radius if using circle collision.

Related

How do I create a copy of this class and then use it's functions inside XNA (Gamedrawable Component)

using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
namespace TileEngine
{
class Renderer : DrawableGameComponent
{
SpriteBatch spriteBatch;
public Renderer(Game game)
: base(game)
{
// TODO: Construct any child components here
}
protected override void LoadContent()
{
// base.LoadContent();
}
public override void Draw(GameTime gameTime)
{
base.Draw(gameTime);
}
public override void Update(GameTime gameTime)
{
base.Update(gameTime);
}
public override void Initialize()
{
base.Initialize();
}
public RenderTarget2D new_texture(int width, int height)
{
Texture2D TEX = new Texture2D(GraphicsDevice, width, height); //create the texture to render to
RenderTarget2D Mine = new RenderTarget2D(GraphicsDevice, width, height);
GraphicsDevice.SetRenderTarget(Mine); //set the render device to the reference provided
//maybe base.draw can be used with spritebatch. Idk. We'll see if the order of operation
//works out. Wish I could call base.draw here.
return Mine; //I'm hoping that this returns the same instance and not a copy.
}
public void draw_texture(int width, int height, RenderTarget2D Mine)
{
GraphicsDevice.SetRenderTarget(null); //Set the renderer to render to the backbuffer again
Rectangle drawrect = new Rectangle(0, 0, width, height); //Set the rendering size to what we want
spriteBatch.Begin(); //This uses spritebatch to draw the texture directly to the screen
spriteBatch.Draw(Mine, drawrect, Color.White); //This uses the color white
spriteBatch.End(); //ends the spritebatch
//Call base.draw after this since it doesn't seem to recognize inside the function
//maybe base.draw can be used with spritebatch. Idk. We'll see if the order of operation
//works out. Wish I could call base.draw here.
}
public GraphicsDevice myDevice { get; set; }
}
}
I still can't call this class as an object in XNA
Here is the working code in the initialize function where I try to create it.
But in my draw code it still doesn't let me go:
tileclipping.draw_texture(...);
Here's the full code from game1
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.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using TileEngine;
namespace TileEngine
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
public GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
TileMap myMap = new TileMap();
int squaresAcross = 12;
int squaresDown = 12;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
/// </summary>
protected override void Initialize()
{
// tileClipping = new Renderer();
// TODO: Add your initialization logic here
Renderer tileclipping = new Renderer(this) ;
//Components.Add(tileclippping);
base.Initialize();
}
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
Tile.TileSetTexture = Content.Load<Texture2D>(#"Textures\TileSets\part1_tileset");
// TODO: use this.Content to load your game content here
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
/// <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>
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
KeyboardState ks = Keyboard.GetState();
if (ks.IsKeyDown(Keys.Left))
{
Camera.Location.X = MathHelper.Clamp(Camera.Location.X - 8, 0, (myMap.MapWidth - squaresAcross) * 32);
}
if (ks.IsKeyDown(Keys.Right))
{
Camera.Location.X = MathHelper.Clamp(Camera.Location.X + 8, 0, (myMap.MapWidth - squaresAcross) * 32);
}
if (ks.IsKeyDown(Keys.Up))
{
Camera.Location.Y = MathHelper.Clamp(Camera.Location.Y - 8, 0, (myMap.MapHeight - squaresDown) * 32);
}
if (ks.IsKeyDown(Keys.Down))
{
Camera.Location.Y = MathHelper.Clamp(Camera.Location.Y + 8, 0, (myMap.MapHeight - squaresDown) * 32);
}
// TODO: Add your update logic here
base.Update(gameTime);
}
/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
//use the instance of renderer called tileclipping to generate a new texture of a specified size for tiles
//this surface is 200 pixels by 200 pixels for the reason that it's the same as the clipping i'll choose
Texture2D mytexture = new Texture2D(GraphicsDevice, 200, 200);
RenderTarget2D Mine = new RenderTarget2D(graphics.GraphicsDevice, 200, 200);
//Mine = tileclipping.new_texture(200, 200);
spriteBatch.Begin();
Vector2 firstSquare = new Vector2(Camera.Location.X / 32, Camera.Location.Y / 32);
int firstX = (int)firstSquare.X;
int firstY = (int)firstSquare.Y;
Vector2 squareOffset = new Vector2(Camera.Location.X % 32, Camera.Location.Y % 32);
int offsetX = (int)squareOffset.X;
int offsetY = (int)squareOffset.Y;
for (int y = 0; y < squaresDown; y++)
{
for (int x = 0; x < squaresAcross; x++)
{
spriteBatch.Draw(
Tile.TileSetTexture,
new Rectangle((x * 32) - offsetX, (y * 32) - offsetY, 32, 32),
Tile.GetSourceRectangle(myMap.Rows[y + firstY].Columns[x + firstX].TileID),
Color.White);
}
}
spriteBatch.End();
// TODO: Add your drawing code here
//There are two instances of mine
//A new one is made each time tileclipping.new_texture is called
//This function can re use the copy created by new texture
//hopefully this saves on memory
base.Draw(gameTime);
}
public CubeMapFace Tex2d { get; set; }
internal Renderer tileClipping { get; set; }
public IGameComponent tileclippping { get; set; }
}
}
I'm sorry if it isn't clear what i'm trying to do.
I'm trying to capture a 2d texture (or create one) OUTSIDE my game class
I'm trying to use a class as a handler, to pass these texture2d's back and forth between GAME1
and my Renderer
I don't WANT to have all my textures inside my main class.
Also another thing with this is that I'm trying to basically have a generic
texture2d CREATOR.
Aka this isn't for something simple like rendering sprites.
The function of RENDERER is to either create a new TEXTURE2D object with a NEW render target object
based on parameters fed to this function:
public RenderTarget2D new_texture(int width, int height)
{
Texture2D TEX = new Texture2D(GraphicsDevice, width, height); //create the texture to render to
RenderTarget2D Mine = new RenderTarget2D(GraphicsDevice, width, height);
GraphicsDevice.SetRenderTarget(Mine); //set the render device to the reference provided
//maybe base.draw can be used with spritebatch. Idk. We'll see if the order of operation
//works out. Wish I could call base.draw here.
return Mine; //I'm hoping that this returns the same instance and not a copy.
}
I need a way of creating a copy of the renderer class WITHOUT having it in the gamecomponents list.
The reason is because XNA won't let me access Graphics device, which is a required parameter OF a texture2D object.
So basically i'm doing all this stuff as a work around just becuase Texture2D requires graphics device as a parameter and I can't willy nilly pass GraphicsDevice INTO an instance of my renderer class i've already tried that and it fails.
So there will be situations in my game where say
if (Camera_zoom==1){
scaling_texture.dispose();
scaling_texture = tileclipping.new_texture(camera_width*camera_zoom, camera_height*camera_zoom);
// call a refresh command here
this.refresh_scene(...) //Inside here is a ton of sprite batches because the render target is now set to NEW scaling_texture
//after that we do the drawing using spritebatch inside draw function of main game class
//expecting that a render texture is provided for us by these pre requisites.
//then after that we call the render command
//it returns the render target to the screen
//then in the draw command AFTER the sprite batches were drawn TO the target surface called scaling_texture
//We use various parameters to tell it to draw this scaling_texture as a spritebatch.draw() inside the
//game1 draw class
//So basically I want to do things in this order
/// Create new texture of variable size
// use it as render target
// Do all my spritebatch
// call another spritebatch
//draw the contents of said texture on the screen as the rendering target
//Dispose of the texture object
//Check the scaling size of it
//Re create the scaling texture with a NEW resolution (each frame)
//Select it as a render target
//Do the spritebatchy stuff all over again repeat above for all game loop
//BUT I want parts of this, mainly the creation of this Texture2D object, and the drawing of it to the backbuffer
//To all happen inside my Renderer class
//but for all main game spritebatches to happen inside my main game class
//This is a problem for me and XNA doesn't seem to want to let me organize it this way
//Unless i'm missing something which is why i'm making this lengthy post
//ANY and all help is appreciated.
//Thanks again and I hope I explained myself well enough this time IE my intentions.
//PLEASE NOTE I am SET on doing things THIS way. I will NEED a texture 2d rendering target that is NON static
//During MOST of my GAME project.
//That said.. IT HAS TO have function to wrap it inside Renderer. THere is no way in hell I'm going to do this
//In a spaghetti code fashion Inside GAME1 with nested if statements.
//Thanks all
}
I just took the time to read it completely, and if I understand correctly, you want to have all your textures into a manager to be able to acess them from everywhere in your program ?
what I normally do is have a Class like this one :
Class Images
{
public static Texture2d Ball;
public static Texture2d Hero;
public static void loadContent(Content content)
{
Ball = content.load<Texture2d>("/GFX/GameObject/Ball");
Hero = content.load<Texture2d>("/GFX/SpriteSheet/Hero");
}
}
This class allow you to use Image.Hero or Image.Ball from everywhere in your code. All you have to do is to set it in your game loadcontent sub :
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
Images.LoadContent(GraphicsDeviceManager.Content);
Sounds.LoadContent(GraphicsDeviceManager.Content);
Tile.TileSetTexture = Content.Load<Texture2D>(#"Textures\TileSets\part1_tileset");
// TODO: use this.Content to load your game content here
}
From here, if you need to recreate or reload the texture in your own renderer class, you could set images.ball getter or setter differently and handle it how you want, or just create a new function to clone these texture and do what you need for your renderer class. Edit : I'm not 100% sure about if the class itself is static or not, I dont have the code in front of me and I didnt touch it in a long time.
I'm not home, so I cant find the tutorial I had about splash screen. but it also let you load a delegate instead of an asset, and that delegate lets you do some actions instead : as the 1st item to load, you load all the texture and fonts needed for your splash screen, as well as a background music that you start playing right away. If you want, let me know and I'll add in the link once I get home.

Using Bloom effect makes black background blue/indigo in MonoGame (Xna)

My game, made in MonoGame (Xna clone to Mac), needs to use the Bloom effect. I followed the code in the sample over at MSDN (http://xbox.create.msdn.com/en-US/education/catalog/sample/bloom). When I put this effect into my 2D game, it made the background a bluish indigo purple thing. I looked around on Google of why this is, I'm not sure why. I couldn't find an answer. I found this StackOverflow question, they said something about Pre-Bloom, which I'm guessing this is what this is. I put my draw code in a component. My Draw code is:
spriteBatch.Begin();
((Pump)Game).bloomComponent.BeginDraw();
grid.DrawPeices(spriteBatch);
spriteBatch.End();
The DrawPeices method just goes through a list and draws each sprite normally. My BloomComponent class, which I initialized the component in my main Game class, is:
#region File Description
//-----------------------------------------------------------------------------
// BloomComponent.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion
#region Using Statements
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using System.IO;
using System.Reflection;
#endregion
namespace Pump.Libraries.Bloom
{
public class BloomComponent : DrawableGameComponent
{
#region Fields
SpriteBatch spriteBatch;
Effect bloomExtractEffect;
Effect bloomCombineEffect;
Effect gaussianBlurEffect;
RenderTarget2D sceneRenderTarget;
RenderTarget2D renderTarget1;
RenderTarget2D renderTarget2;
RenderTarget2D finalRenderTarget;
public RenderTarget2D FinalRenderTarget { get { return finalRenderTarget; } }
byte[] shaderCode;
// Choose what display settings the bloom should use.
public BloomSettings Settings
{
get { return settings; }
set { settings = value; }
}
BloomSettings settings = BloomSettings.PresetSettings[0];
// Optionally displays one of the intermediate buffers used
// by the bloom postprocess, so you can see exactly what is
// being drawn into each rendertarget.
public enum IntermediateBuffer
{
PreBloom,
BlurredHorizontally,
BlurredBothWays,
FinalResult,
}
public IntermediateBuffer ShowBuffer
{
get { return showBuffer; }
set { showBuffer = value; }
}
IntermediateBuffer showBuffer = IntermediateBuffer.FinalResult;
#endregion
#region Initialization
public BloomComponent(Game game)
: base(game)
{
if (game == null)
throw new ArgumentNullException("game");
}
/// <summary>
/// Load your graphics content.
/// </summary>
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
//LOAD ALL THE SHADERS
var assembly = Assembly.GetExecutingAssembly();
var stream = assembly.GetManifestResourceStream("Pump.Shaders.BloomExtract.mgfxo");
using (var ms = new MemoryStream())
{
stream.CopyTo(ms);
shaderCode = ms.ToArray();
}
stream.Close();
bloomExtractEffect = new Effect(GraphicsDevice, shaderCode);
assembly = Assembly.GetExecutingAssembly();
stream = assembly.GetManifestResourceStream("Pump.Shaders.BloomCombine.mgfxo");
using (var ms = new MemoryStream())
{
stream.CopyTo(ms);
shaderCode = ms.ToArray();
}
stream.Close();
bloomCombineEffect = new Effect(GraphicsDevice, shaderCode);
assembly = Assembly.GetExecutingAssembly();
stream = assembly.GetManifestResourceStream("Pump.Shaders.GaussianBlur.mgfxo");
using (var ms = new MemoryStream())
{
stream.CopyTo(ms);
shaderCode = ms.ToArray();
}
stream.Close();
gaussianBlurEffect = new Effect(GraphicsDevice, shaderCode);
/*bloomExtractEffect = Game.Content.Load<Effect>("BloomExtract");
bloomCombineEffect = Game.Content.Load<Effect>("BloomCombine");
gaussianBlurEffect = Game.Content.Load<Effect>("GaussianBlur");*/
// Look up the resolution and format of our main backbuffer.
PresentationParameters pp = GraphicsDevice.PresentationParameters;
int width = pp.BackBufferWidth;
int height = pp.BackBufferHeight;
SurfaceFormat format = pp.BackBufferFormat;
// Create a texture for rendering the main scene, prior to applying bloom.
sceneRenderTarget = new RenderTarget2D(GraphicsDevice, width, height, false,
format, pp.DepthStencilFormat, pp.MultiSampleCount,
RenderTargetUsage.DiscardContents);
finalRenderTarget = new RenderTarget2D(GraphicsDevice, width, height, false,
format, pp.DepthStencilFormat, pp.MultiSampleCount,
RenderTargetUsage.DiscardContents);
// Create two rendertargets for the bloom processing. These are half the
// size of the backbuffer, in order to minimize fillrate costs. Reducing
// the resolution in this way doesn't hurt quality, because we are going
// to be blurring the bloom images in any case.
width /= 2;
height /= 2;
renderTarget1 = new RenderTarget2D(GraphicsDevice, width, height, false, format, DepthFormat.None);
renderTarget2 = new RenderTarget2D(GraphicsDevice, width, height, false, format, DepthFormat.None);
}
/// <summary>
/// Unload your graphics content.
/// </summary>
protected override void UnloadContent()
{
sceneRenderTarget.Dispose();
renderTarget1.Dispose();
renderTarget2.Dispose();
}
#endregion
#region Draw
/// <summary>
/// This should be called at the very start of the scene rendering. The bloom
/// component uses it to redirect drawing into its custom rendertarget, so it
/// can capture the scene image in preparation for applying the bloom filter.
/// </summary>
public void BeginDraw()
{
if (Visible)
{
GraphicsDevice.SetRenderTarget(sceneRenderTarget);
}
}
/// <summary>
/// This is where it all happens. Grabs a scene that has already been rendered,
/// and uses postprocess magic to add a glowing bloom effect over the top of it.
/// </summary>
public override void Draw(GameTime gameTime)
{
GraphicsDevice.SamplerStates[1] = SamplerState.LinearClamp;
// Pass 1: draw the scene into rendertarget 1, using a
// shader that extracts only the brightest parts of the image.
bloomExtractEffect.Parameters["BloomThreshold"].SetValue(
Settings.BloomThreshold);
DrawFullscreenQuad(sceneRenderTarget, renderTarget1,
bloomExtractEffect,
IntermediateBuffer.PreBloom);
// Pass 2: draw from rendertarget 1 into rendertarget 2,
// using a shader to apply a horizontal gaussian blur filter.
SetBlurEffectParameters(1.0f / (float)renderTarget1.Width, 0);
DrawFullscreenQuad(renderTarget1, renderTarget2,
gaussianBlurEffect,
IntermediateBuffer.BlurredHorizontally);
// Pass 3: draw from rendertarget 2 back into rendertarget 1,
// using a shader to apply a vertical gaussian blur filter.
SetBlurEffectParameters(0, 1.0f / (float)renderTarget1.Height);
DrawFullscreenQuad(renderTarget2, renderTarget1,
gaussianBlurEffect,
IntermediateBuffer.BlurredBothWays);
// Pass 4: draw both rendertarget 1 and the original scene
// image back into the main backbuffer, using a shader that
// combines them to produce the final bloomed result.
GraphicsDevice.SetRenderTarget(null);
EffectParameterCollection parameters = bloomCombineEffect.Parameters;
parameters["BloomIntensity"].SetValue(Settings.BloomIntensity);
parameters["BaseIntensity"].SetValue(Settings.BaseIntensity);
parameters["BloomSaturation"].SetValue(Settings.BloomSaturation);
parameters["BaseSaturation"].SetValue(Settings.BaseSaturation);
GraphicsDevice.Textures[1] = sceneRenderTarget;
Viewport viewport = GraphicsDevice.Viewport;
DrawFullscreenQuad(renderTarget1,
viewport.Width, viewport.Height,
bloomCombineEffect,
IntermediateBuffer.FinalResult);
}
/// <summary>
/// Helper for drawing a texture into a rendertarget, using
/// a custom shader to apply postprocessing effects.
/// </summary>
void DrawFullscreenQuad(Texture2D texture, RenderTarget2D renderTarget,
Effect effect, IntermediateBuffer currentBuffer)
{
GraphicsDevice.SetRenderTarget(renderTarget);
DrawFullscreenQuad(texture,
renderTarget.Width, renderTarget.Height,
effect, currentBuffer);
}
/// <summary>
/// Helper for drawing a texture into the current rendertarget,
/// using a custom shader to apply postprocessing effects.
/// </summary>
void DrawFullscreenQuad(Texture2D texture, int width, int height,
Effect effect, IntermediateBuffer currentBuffer)
{
// If the user has selected one of the show intermediate buffer options,
// we still draw the quad to make sure the image will end up on the screen,
// but might need to skip applying the custom pixel shader.
if (showBuffer < currentBuffer)
{
effect = null;
}
spriteBatch.Begin(0, BlendState.Opaque, null, null, null, effect);
spriteBatch.Draw(texture, new Rectangle(0, 0, width, height), Color.White);
spriteBatch.End();
}
/// <summary>
/// Computes sample weightings and texture coordinate offsets
/// for one pass of a separable gaussian blur filter.
/// </summary>
void SetBlurEffectParameters(float dx, float dy)
{
// Look up the sample weight and offset effect parameters.
EffectParameter weightsParameter, offsetsParameter;
weightsParameter = gaussianBlurEffect.Parameters["SampleWeights"];
offsetsParameter = gaussianBlurEffect.Parameters["SampleOffsets"];
// Look up how many samples our gaussian blur effect supports.
int sampleCount = weightsParameter.Elements.Count;
// Create temporary arrays for computing our filter settings.
float[] sampleWeights = new float[sampleCount];
Vector2[] sampleOffsets = new Vector2[sampleCount];
// The first sample always has a zero offset.
sampleWeights[0] = ComputeGaussian(0);
sampleOffsets[0] = new Vector2(0);
// Maintain a sum of all the weighting values.
float totalWeights = sampleWeights[0];
// Add pairs of additional sample taps, positioned
// along a line in both directions from the center.
for (int i = 0; i < sampleCount / 2; i++)
{
// Store weights for the positive and negative taps.
float weight = ComputeGaussian(i + 1);
sampleWeights[i * 2 + 1] = weight;
sampleWeights[i * 2 + 2] = weight;
totalWeights += weight * 2;
// To get the maximum amount of blurring from a limited number of
// pixel shader samples, we take advantage of the bilinear filtering
// hardware inside the texture fetch unit. If we position our texture
// coordinates exactly halfway between two texels, the filtering unit
// will average them for us, giving two samples for the price of one.
// This allows us to step in units of two texels per sample, rather
// than just one at a time. The 1.5 offset kicks things off by
// positioning us nicely in between two texels.
float sampleOffset = i * 2 + 1.5f;
Vector2 delta = new Vector2(dx, dy) * sampleOffset;
// Store texture coordinate offsets for the positive and negative taps.
sampleOffsets[i * 2 + 1] = delta;
sampleOffsets[i * 2 + 2] = -delta;
}
// Normalize the list of sample weightings, so they will always sum to one.
for (int i = 0; i < sampleWeights.Length; i++)
{
sampleWeights[i] /= totalWeights;
}
// Tell the effect about our new filter settings.
weightsParameter.SetValue(sampleWeights);
offsetsParameter.SetValue(sampleOffsets);
}
/// <summary>
/// Evaluates a single point on the gaussian falloff curve.
/// Used for setting up the blur filter weightings.
/// </summary>
float ComputeGaussian(float n)
{
float theta = Settings.BlurAmount;
return (float)((1.0 / Math.Sqrt(2 * Math.PI * theta)) *
Math.Exp(-(n * n) / (2 * theta * theta)));
}
#endregion
}
}
And finally, BloomSettings.cs:
#region File Description
//-----------------------------------------------------------------------------
// BloomSettings.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion
namespace Pump.Libraries.Bloom
{
/// <summary>
/// Class holds all the settings used to tweak the bloom effect.
/// </summary>
public class BloomSettings
{
#region Fields
// Name of a preset bloom setting, for display to the user.
public readonly string Name;
// Controls how bright a pixel needs to be before it will bloom.
// Zero makes everything bloom equally, while higher values select
// only brighter colors. Somewhere between 0.25 and 0.5 is good.
public readonly float BloomThreshold;
// Controls how much blurring is applied to the bloom image.
// The typical range is from 1 up to 10 or so.
public readonly float BlurAmount;
// Controls the amount of the bloom and base images that
// will be mixed into the final scene. Range 0 to 1.
public readonly float BloomIntensity;
public readonly float BaseIntensity;
// Independently control the color saturation of the bloom and
// base images. Zero is totally desaturated, 1.0 leaves saturation
// unchanged, while higher values increase the saturation level.
public readonly float BloomSaturation;
public readonly float BaseSaturation;
#endregion
/// <summary>
/// Constructs a new bloom settings descriptor.
/// </summary>
public BloomSettings(string name, float bloomThreshold, float blurAmount,
float bloomIntensity, float baseIntensity,
float bloomSaturation, float baseSaturation)
{
Name = name;
BloomThreshold = bloomThreshold;
BlurAmount = blurAmount;
BloomIntensity = bloomIntensity;
BaseIntensity = baseIntensity;
BloomSaturation = bloomSaturation;
BaseSaturation = baseSaturation;
}
/// <summary>
/// Table of preset bloom settings, used by the sample program.
/// </summary>
public static BloomSettings[] PresetSettings =
{
// Name Thresh Blur Bloom Base BloomSat BaseSat
new BloomSettings("Default", 0.25f, 4, 1.25f, 1, 1, 1),
new BloomSettings("Soft", 0, 3, 1, 1, 1, 1),
new BloomSettings("Desaturated", 0.5f, 8, 2, 1, 0, 1),
new BloomSettings("Saturated", 0.25f, 4, 2, 1, 2, 0),
new BloomSettings("Blurry", 0, 2, 1, 0.1f, 1, 1),
new BloomSettings("Subtle", 0.5f, 2, 1, 1, 1, 1),
};
}
}
Can somebody explain why the screen is blue/indigo, and how I can fix it? My original background was black, if you should need to know. Oh, and I have a screenshot:
In looking at your screenshot and code it does appear that you are not clearing your rendertagets, I would modify your BeginDraw code to call Clear so that your targets are initialized to a known value before you draw to them.
/// <summary>
/// This should be called at the very start of the scene rendering. The bloom
/// component uses it to redirect drawing into its custom rendertarget, so it
/// can capture the scene image in preparation for applying the bloom filter.
/// </summary>
public void BeginDraw()
{
if (Visible)
{
GraphicsDevice.SetRenderTarget(renderTarget1);
GraphicsDevice.Clear(Color.Black);
GraphicsDevice.SetRenderTarget(renderTarget2);
GraphicsDevice.Clear(Color.Black);
GraphicsDevice.SetRenderTarget(FinalRenderTarget);
GraphicsDevice.Clear(Color.Black);
GraphicsDevice.SetRenderTarget(sceneRenderTarget);
}
}

Why spritebatch.Draw shows blank output?

In my code below, I think it's correctly done. But idk, the image called by _bg is does not shown up. The screen only show White. Weirdly, there is 0 error message when I run it.
(The RenderTarget2D is for default-ing my view into landscape mode)
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace GameName2
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Game
{
GraphicsDeviceManager _graphics;
SpriteBatch _spriteBatch;
Texture2D _bg;
RenderTarget2D finalImageTarget;
public Game1()
{
_graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
/// </summary>
protected override void Initialize()
{
// TODO: Add your initialization logic here
base.Initialize();
}
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
_spriteBatch = new SpriteBatch(GraphicsDevice);
_bg = Content.Load<Texture2D>(#"background");
finalImageTarget = new RenderTarget2D(GraphicsDevice, 1280, 720);
// TODO: use this.Content to load your game content here
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
/// <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>
protected override void Update(GameTime gameTime)
{
// TODO: Add your update logic here
base.Update(gameTime);
}
/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.SetRenderTarget(finalImageTarget);
GraphicsDevice.Clear(Color.White);
// TODO: Add your drawing code here
_spriteBatch.Begin();
_spriteBatch.Draw(_bg,
new Rectangle(0, 0, Window.ClientBounds.Width, Window.ClientBounds.Height),
null,
Color.White,
0,
Vector2.Zero,
SpriteEffects.None,
0);
_spriteBatch.End();
GraphicsDevice.SetRenderTarget(null);
_spriteBatch.Begin();
_spriteBatch.Draw(finalImageTarget,
new Vector2(720,0),
null,
Color.White,
MathHelper.PiOver2,
Vector2.Zero,
Vector2.One,
SpriteEffects.None,
0f);
_spriteBatch.End();
base.Draw(gameTime);
}
}
}
I use xnb file. And I put it in Content folder in the project. I've set 'Content' and 'Copy if newer' to the file property.
This is the .png file I use before converted into xnb : https://imageshack.us/scaled/large/15/loadingo.png
Or maybe the problem is in my .png file?
Any idea? Thanks
That second sprite batch call is rather curious. It looks to me like you are moving and / or rotating the image off-screen.
Since you are using this overload of draw you are effectively doing this:
Texture2D texture = finalImageTarget;
Vector2 position = new Vector2(720,0);
Rectangle? sourceRectangle = null;
Color color = Color.White;
float rotation = MathHelper.PiOver2;
Vector2 origin = Vector2.Zero;
Vector2 scale = Vector2.One;
SpriteEffects effects = SpriteEffects.None;
float layerDepth = 0f;
_spriteBatch.Draw (texture,position,sourceRectangle,color,rotation,origin,scale,effects,layerDepth,layerDepth);
So that means you are positioning your image 720 pixels to the right of the upper left corner of the screen, then rotating it around the upper left corner of the image 90 degrees.
My suggestion is to start simple and work your way up to what you want to achieve. Use a single sprite batch call without a render target and use source and destination rectangles without rotation.
Edit: Use the debugger to make sure all of the variables are coming out with the values you expect to see. For example, Window.ClientBounds.Width / Height might be coming out as zeros. I think I saw this once when porting to Android and had to change it to use the Viewport Width and Height.
GraphicsDevice.SetRenderTarget(finalImageTarget);
GraphicsDevice.Clear(Color.White);
// TODO: Add your drawing code here
_spriteBatch.Begin();
_spriteBatch.Draw(_bg,
new Rectangle(0, 0, Window.ClientBounds.Width, Window.ClientBounds.Height),
null,
Color.White,
0,
Vector2.Zero,
SpriteEffects.None,
0);
_spriteBatch.End();
This code is not being drawn to the screen you see. It is being draw to the finalImageTarget render target. That what a render target is a place to draw to that doesn't show up on screen. Setting it to GraphicsDevice.SetRenderTarget(null); tells XNA to draw to the visible screen.
Why are you using Render2D? is there a specific reason?
if not then i would change the resolution of the window by using
_graphics.PreferredBackBuffer.Width = 720;
_graphics.PreferredBackbuffer.Height = 1280;
in your constructor.
then you have you freedom to place your Texture2D image using the below;
_spriteBatch.Begin();
_spriteBatch.Draw(_bg,
new Rectangle(0, 0, Window.ClientBounds.Width, Window.ClientBounds.Height),
null,
Color.Black,
0,
Vector2.Zero,
SpriteEffects.None,
0);
_spriteBatch.End();
If your worried about placement over and under the background image then try using layers in your spriteBatch calls.
As i said im not sure why you want it this way so i could be wrong but doing it this simple way will workout whether or not its your texture file or something else.
EDIT
Based upon your comment, id say to try out just positioning the texture2D via coordinates
e.g.
_spriteBatch.Draw(_bg, new vector2(0,0), color.black);
or
_spriteBatch.Draw(_bg, new vector2(screen.width/2,screen.height/2), color.black);
if you still cant see it id suggest maybe looking at the properties of the file or changing the file to a jpg for testing.
This is the solution (The same question, I posted on different site)
https://gamedev.stackexchange.com/questions/54672/why-spritebatch-draw-shows-blank-output

Why Vector2 (from XNA's library) uses float not int?

Why Vector2 (from XNA's library) uses float not int?
Position on computer screen is given in pixels so that cursor position can be defined by two integers. There is no such a thing like half a pixel. Why we use floats then?
In SpriteBatch class I've found 7 overloaded methods called Draw. Two of them:
public void Draw(Texture2D texture, Rectangle destinationRectangle, Color color);
public void Draw(Texture2D texture, Vector2 position, Color color);
So we can see that Draw accepts both int and float coordinates.
I came across this problem when I've been implementing screen coordinates of my game's objects. I assumed that Rectangle is good choice to hold object's size and screen coordinates. But now I'm not sure...
Mathematically, a vector is a motion, not a position. While a position on the screen might not technically be able to be between integers, a motion definitely can. If a vector used ints then the slowest you could move would be (1, 1). With floats you can move (.1, .1), (.001, .001), and so on.
(Notice also that the XNA struct Point does actually use ints.)
You could use both Vector2 and Rectangle to represent your objects coordinates. I usually do it like this:
public class GameObject
{
Texture2D _texture;
public Vector2 Position { get; set; }
public int Width { get; private set; } //doesn't have to be private
public int Height { get; private set; } //but it's nicer when it doesn't change :)
public Rectangle PositionRectangle
{
get
{
return new Rectangle((int)Position.X, (int)Position.Y, Width, Height);
}
}
public GameObject(Texture2D texture)
{
this._texture = texture;
this.Width = texture.Width;
this.Height = texture.Height;
}
}
To move objects, just set their Position property to a new value.
_player.Position = new Vector2(_player.Position.X, 100);
You don't have to worry about the rectangle, as it's value depends directly on Position.
My game objects also usually contain methods to draw themselves, such as
public void Draw(SpriteBatch spriteBatch, GameTime gameTime)
{
spriteBatch.Draw(this._texture, this.Position, Color.White);
}
Collision detection code in your Game.Update() could just use the PositionRectangle to test for collisions
//_player and _enemy are of type GameObject (or one that inherits it)
if(_player.PositionRectangle.Intersects(_enemy.PositionRectangle))
{
_player.Lives--;
_player.InvurnerabilityPeriod = 2000;
//or something along these lines;
}
You could also call the spriteBatch.Draw() with PositionRectangle, you shouldn't notice much difference.
There is such a thing as "half a pixel." Using float coordinates that aren't pixel-aligned will cause your sprites to be rendered at sub-pixel coordinates. This is often necessary to make objects appear to scroll smoothly, but it can also produce an unpleasant shimmering effect in some circumstances.
See here for a summary of the basic idea: Subpixel rendering

XNA 3.1 Laggy movement

I have Windows XP SP3.
I created the default XNA project in version 3.1 and added these simple lines to the pregenerated code:
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Rectangle rectangle = new Rectangle(80, 80, 100, 100);
Texture2D textureTrain;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
//TargetElapsedTime = new TimeSpan(0, 0, 0, 0, 10);
}
...
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
// TODO: use this.Content to load your game content here
textureTrain = Content.Load<Texture2D>("MyBitmap1");
}
...
/// <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>
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
// TODO: Add your update logic here
rectangle.X = rectangle.X + 1;
rectangle.Y = rectangle.Y + 1;
base.Update(gameTime);
}
/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
// TODO: Add your drawing code here
spriteBatch.Begin();
spriteBatch.Draw(textureTrain, rectangle, Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
}
as simple as this ! But the movement is very laggy, it flickers, I can't even look at it.
If I compare it to some flash games it's incomparable. Why is this? What am I doing wrong?
Because your are using the X and Y components of the Rectangle, your calculation will be rounded to the nearest whole number. You want granularity in this case, fine, precise movements.
i.e.
Vector2 position = new Vector2(0.1f, 0.1f);
//Some Arbitrary movement
float speed = 0.008f;
position.X += (float)((speed * position.X);
position.Y += (float)((speed * position.Y);
spriteBatch.Begin();
spriteBatch.Draw(textureTrain, position, rectangle, Color.White);
spriteBatch.End();

Resources