Lining up sprites with scale and rotation around arbitrary point - c#

I have 2 sprites which when drawn together make up the correct image on the screen. Drawing them both at the same time is not an option.
Imagine this class:
class MyImage
{
Vector2 drawOffset; // this gets added before the image is drawn
Vector2 sourceRect; // this is where it is on the source texturepage
void Draw(Vector2 position)
{
position = position + drawOffset;
spriteBatch.Draw(sourceTexture, position, sourceRect, Color.White);
}
}
And this code calling into it:
MyImage a = new MyImage(); // assume they get initialised correctly
MyImage b = new MyImage(); // with different drawOffsets and sourceRects
a.Draw(position); // this composes the final
b.Draw(position); // screen image from the 2 source images
Now I'd like to add scale and rotation to the Draw() function, but am having real trouble getting the parameters to the SpriteBatch.Draw function correct. This would be the version which takes scale, rotation and an origin. I need the final composed image to scale and rotate correctly (around some arbitrary centre) but can't for the life of me work out how to manipulate the scale, rotation and origin parameters to make the 2 images appear to scale and rotate in concert. Has anyone done something like this before? Happy to mod the question based on feedback if anything's unclear. If images would help I can get them posted somewhere...
I've looked at rotation around point xna 2D but am still stumped.
Cheers,
Charlie.
Thanks so much for the answer below - using it I've managed to get the images rendering correctly. One other issue remains, which is that I seem to need to use a lot of spritebatch.Begin/End pairs (one per image render). I don't have a way to measure performance on this device yet and the framerate's not chugging so I guess it's not a problem.
Here's my code:
// gr is the graphic object:
// gr.position is the location of the image in the atlas
// gr.DrawOffset is the draw offset so the image is placed correctly in it's virtual box
// gr.pageIndex is the index into the texture/atlas array
// hw,hh are half the width/height of the image (it always rotates around it's centre in fact)
Matrix m = Matrix.CreateTranslation(-hw, -hh, 0) *
Matrix.CreateRotationZ(rotation) * // rotation : parameter
Matrix.CreateScale(scale) * // scale : parameter
Matrix.CreateTranslation(pos.X + hw, pos.Y + hh, 0); // pos : parameter!
spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, m);
spriteBatch.Draw(page[gr.pageIndex].texture, gr.DrawOffset, gr.position, color);
spriteBatch.End();

If you are going to work with the SpriteBatch.Draw to draw the textures I would suggest that you forgo trying to manipulate the origin, scale arguments to try an achieve this, simply I doubt it can be done this way. But you do have an alternative, you can manipulate the SpriteBatch Matrix.
Here is a quick and dirty example, note that the texture I used here is 128x96 so I hard coded the values for that image size. Do not look for any best practices in this code, I wrote it to try and show the concept as cleanly as possible.
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace WindowsGame1
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
private Texture2D _texture;
private MyImage _image1;
private MyImage _image2;
// Attributes of the composed sprite
private float _angle = 0.0f;
private Vector2 _position = new Vector2(100, 100);
private Vector2 _rotationPoint = new Vector2(96, 48);
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);
_texture = Content.Load<Texture2D>("Gravitar");
// Create the two MyImage instances
_image1 = new MyImage(_texture, Vector2.Zero, Vector2.Zero);
_image2 = new MyImage(_texture, new Vector2(64, 0), new Vector2(64, 0));
}
/// <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();
float elapsedTime = (float)gameTime.ElapsedGameTime.TotalSeconds;
_angle += 0.5f * elapsedTime;
if (Mouse.GetState().LeftButton == ButtonState.Pressed)
{
_angle = 0.0f;
}
if (Keyboard.GetState().IsKeyDown(Keys.Left))
_position += new Vector2(-10, 0)*elapsedTime;
if (Keyboard.GetState().IsKeyDown(Keys.Right))
_position += new Vector2(10, 0) * elapsedTime;
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);
// Setup the sprite batch matrix
// Notice that we first translate to the point or rotation
// then rotate and when we translate to the desired position we
// need to compensate for the first translation so that the texture
// appears at the correct location
Matrix m =
Matrix.CreateScale(1.5f)
* Matrix.CreateTranslation(-_rotationPoint.X, -_rotationPoint.Y, 0)
* Matrix.CreateRotationZ(_angle)
* Matrix.CreateTranslation(_position.X + _rotationPoint.X, _position.Y + _rotationPoint.Y, 0);
// Begin the SpriteBatch passing the matrix
spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, m);
_image1.Draw(spriteBatch);
_image2.Draw(spriteBatch);
spriteBatch.End();
base.Draw(gameTime);
}
class MyImage
{
Vector2 _drawOffset;
Vector2 _sourcePoint;
Texture2D _sourceTexture;
public MyImage(Texture2D sourceTexture, Vector2 sourcePoint, Vector2 drawOffset)
{
_drawOffset = drawOffset;
_sourcePoint = sourcePoint;
_sourceTexture = sourceTexture;
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(_sourceTexture, _drawOffset,
new Rectangle((int)_sourcePoint.X, (int)_sourcePoint.Y, 64, 96),
Color.White);
}
}
}
}

Related

C# MonoGame: Moving Sprite Image Up and Down Using Xbox 360 GamePad

Here is the code from my MonoGame project where I have one player image in the bottom left corner and another player image in the top right. The goal is to use the left thumbstick on an Xbox 360 controller to move the player 1 on the left up and down. I used a break point and found that my controller is connected, but nothing happens when I use the thumbstick. Here is my code:
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace _2PersonShooterGame_v0._1
{
/// <summary>
/// This is the main type for your game.
/// </summary>
public class Game1 : Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
// GamePad support
const float THUMB_STICK_DEFELCTION = 100;
//Window Resolution support
const int WINDOW_WIDTH = 1200;
const int WINDOW_HEIGHT = 800;
// player images and their rectabgles support
Texture2D player1;
Rectangle drawRect1;
Texture2D player2;
Rectangle drawRect2;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
// Change resolution to 1200, 800
graphics.PreferredBackBufferWidth = WINDOW_WIDTH;
graphics.PreferredBackBufferHeight = WINDOW_HEIGHT;
}
/// <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);
// Load sprites
player1 = Content.Load<Texture2D>(#"graphics\sprite_player1");
player2 = Content.Load<Texture2D>(#"graphics\sprite_player2");
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// game-specific 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)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
// Move player1 up and down using the thumbstick on an Xbox 360 remote
GamePadState gamepad = GamePad.GetState(PlayerIndex.One);
if (gamepad.IsConnected)
{
drawRect1.Y -= (int)(gamepad.ThumbSticks.Left.Y * THUMB_STICK_DEFELCTION);
}
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);
// Drawing sprites in their respective rectangles
spriteBatch.Begin();
// Place player one in the bottom left corner and player two in the top right corner
drawRect1 = new Rectangle(0, WINDOW_HEIGHT - player1.Height, player1.Width, player1.Height);
drawRect2 = new Rectangle(WINDOW_WIDTH - player2.Width, 0, player2.Width, player2.Height);
spriteBatch.Draw(player1, drawRect1, Color.White);
spriteBatch.Draw(player2, drawRect2, Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
}
}
The problem is that you're setting drawRect1.Y property in the Update(...) method but then again you're overriding this rectangle in your Draw(...) method.
// update
if (gamepad.IsConnected)
{
drawRect1.Y -= (int)(gamepad.ThumbSticks.Left.Y * THUMB_STICK_DEFELCTION);
}
// draw
drawRect1 = new Rectangle(0, WINDOW_HEIGHT - player1.Height, player1.Width, player1.Height);
What you should do i to just update rectangle in your Update(...) method and use the same ( updated ) value in Draw(...) call.
To fix this just remove this line : drawRect1 = new Rectangle(0, WINDOW_HEIGHT - player1.Height, player1.Width, player1.Height); from your Draw(...) method.

Bloom in MonoGame

I want to add bloom effect in my MonoGame project, I found out about this: http://xbox.create.msdn.com/en-US/education/catalog/sample/bloom and I tried to add it to my project, but for some reason it told me "Could not load BloomExtract asset as a non-content file!" when I tried to run the project. I tried every solution I could find, including making it copy always. After that I found out that MonoGame can't load .fx files, so I converted them to .mgfxo, after that I changed the build action for it to embedded resource and added this code:
Stream s = Assembly.GetExecutingAssembly().GetManifestResourceStream("Morior.Content.BloomExtract.mgfxo");
BinaryReader Reader = new BinaryReader(s);
bloomExtractEffect = new Effect(GraphicsDevice, Reader.ReadBytes((int)Reader.BaseStream.Length));
But now it throws "This MGFX effect was built for a different platform" when I try to run it, so I'm really out of options, how can I add simple bloom??
edit: I managed to convert it to directx 11 without errors, but now for some reason theres a blank back screen\red screen in my game. sigh, seems like I wont be able to make it work.
EDIT: I think i figured the problems out, but the bloom itself wont work, here is the draw of bloom:
#region Using Statements
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using System.IO;
#endregion
namespace BloomPostprocess
{
public class BloomComponent : DrawableGameComponent
{
#region Fields
SpriteBatch spriteBatch;
Effect bloomExtractEffect;
Effect bloomCombineEffect;
Effect gaussianBlurEffect;
RenderTarget2D renderTarget1;
RenderTarget2D renderTarget2;
// 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>
public void LoadContent(GraphicsDevice g, ContentManager theContentManager)
{
spriteBatch = new SpriteBatch(g);
bloomExtractEffect = theContentManager.Load<Effect>("BloomExtract");
bloomCombineEffect = theContentManager.Load<Effect>("BloomCombine");
gaussianBlurEffect = theContentManager.Load<Effect>("GaussianBlur");
// Look up the resolution and format of our main backbuffer.
PresentationParameters pp = g.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.
// 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(g, width, height, false, format, DepthFormat.Depth24);
renderTarget2 = new RenderTarget2D(g, width, height, false, format, DepthFormat.Depth24);
}
/// <summary>
/// Unload your graphics content.
/// </summary>
public void UnloadContent(ContentManager theContentManager)
{
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(RenderTarget2D renderTarget)
{
if (Visible)
{
GraphicsDevice.SetRenderTarget(renderTarget);
}
}
/// <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 void Draw(GameTime gameTime, RenderTarget2D renderTarget)
{
// 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(renderTarget, 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] = renderTarget;
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
}
}
here is the main:
protected override void Draw(GameTime gameTime)
{
bloom.Draw(gameTime, renderTarget);
GraphicsDevice.Clear(Color.Black);
DrawSceneToTexture(renderTarget,gameTime);
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend,
SamplerState.LinearClamp, DepthStencilState.Default,
RasterizerState.CullNone);
spriteBatch.Draw(renderTarget, rec, Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
protected void DrawSceneToTexture(RenderTarget2D renderTarget,GameTime gametime)
{
GraphicsDevice.SetRenderTarget(renderTarget);
GraphicsDevice.DepthStencilState = new DepthStencilState() { DepthBufferEnable = true };
// Draw the scene
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin(SpriteSortMode.Deferred,
BlendState.AlphaBlend,
SamplerState.PointClamp,
null, null, null, null);
bloom.BeginDraw(renderTarget);
mLeavusSprite.Draw(this.spriteBatch);
b.Draw(this.spriteBatch);
spriteBatch.Draw(cursorTex, cursorPos, cursorSource,
Color.White, 0.0f, Vector2.Zero, 3f, SpriteEffects.None, 0);
spriteBatch.End();
// Drop the render target
GraphicsDevice.SetRenderTarget(null);
}

C#, showing a variable on screen

The game that i am making using C# is Square Chase. You mouse over the block and click it before it moves. The timer will count down in the back ground and the score will be raised by 1 each "tag" on the block. You can do the Project on XNA 4.0 Game Development by Example. This is 2010 C# and The project type is Windows Game (4.0).
Now I want to add extra stuff to it. I want take away 5 seconds of time every time they click on the block, but I don't know if its working so I need to make the time remaining visible. I want to make it smaller every time you hit the square.
Code: (under update and the if statement I have already done the subtraction on the time but would want to make sure its working by making it visible) Thank You
I need to find out how to sink and in large an image, I need to know how to show a float on the screen.
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;
namespace RFSquareChase
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Random rand = new Random ();
Texture2D squareTexture;
Rectangle currentSquare;
int playerScore = 0;
float timeRemaining = 0.0f;
const float TimePerSquare = 0.75f;
Color [] colors = new Color[3] { Color.Red, Color.Green, Color.Blue };
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();
this.IsMouseVisible = true;
}
/// <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);
squareTexture = Content.Load<Texture2D>(#"SQUARE");
// 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
if (timeRemaining == 0.0f)
{
currentSquare = new Rectangle(
rand.Next(0, this.Window.ClientBounds.Width - 25),
rand.Next(0, this.Window.ClientBounds.Height - 25),
25, 25);
timeRemaining = TimePerSquare;
}
MouseState mouse = Mouse.GetState();
if ((mouse.LeftButton == ButtonState.Pressed) &&
(currentSquare.Contains(mouse.X, mouse.Y)))
{
playerScore++;
timeRemaining = 0.0f;
timeRemaining = timeRemaining - 5;
}
timeRemaining = MathHelper.Max(0, timeRemaining - (float)gameTime.ElapsedGameTime.TotalSeconds);
this.Window.Title = "Score : " + playerScore.ToString();
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.Gray);
spriteBatch.Begin();
spriteBatch.Draw(
squareTexture,
currentSquare,
colors[playerScore % 3]);
spriteBatch.End();
// TODO: Add your drawing code here
base.Draw(gameTime);
}
}
}
To show a float on screen you simply use spriteBatch.DrawString, and could be useful Math.Round to show only the decimal you want. As you can see here.
To change the dimension of a sprite you can set the scale parameter in your spriteBatch.Draw. As you can see here

Code required for a walk cycle? XNA Visual Studio C#

So I just started learning C# code a few months ago and I want to get a sprite in a full walk cycle.
I've got my walk cycle on a PNG image. Which is obviously a series of separate images showing the different stages of a walk cycle. Now I've got that into my Project/Solution I'm doing it as a Windows Game 4.0 in visual studio 2010.
And I'm fairly far on, so I've started trying to do srcRect and destRect set up. But all i've managed to get on screen is the image flicking left to right very fast and then infinitely going right. I achieved this by using the srcRect.X += srcRect.width line.
But what I want to do is have this move much slower. I want the destRect to move right on the screen when the thumbstick is pushed right and as this is happening I want it to flick right through my walk cycle.
I'm getting very muddled and I'm a beginner so any help with this would be great appreciated! Below is my code so far!
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;
namespace fra_walk
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
GamePadState pad1, oldpad1;
Rectangle srcRect;
struct Rect
{
public Rectangle destRect;
public Rectangle frame;
public Point velocity;
}
Rect destRect;
struct Wright
{
public Texture2D txr;
public Rectangle frame;
}
Wright walkright;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
graphics.PreferredBackBufferWidth = 800;
graphics.PreferredBackBufferHeight = 600;
}
/// <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
destRect.velocity = new Point(0, 0);
destRect.frame = new Rectangle(400, 400, 83, 170);
srcRect = new Rectangle(0, 0, 64, 170);
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);
walkright.txr = Content.Load<Texture2D>("walk right");
// 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
GamePadState pad1 = GamePad.GetState(PlayerIndex.One);
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
srcRect.X += srcRect.Width;
// if ((pad1.ThumbSticks.Left.X == 1.0f)
// && (oldpad1.ThumbSticks.Left.X == 1.0f))
// {
// srcRect.X += destRect.frame.Width;
// }
oldpad1 = pad1;
// 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(walkright.txr, destRect.frame, srcRect, Color.White);
spriteBatch.End();
// TODO: Add your drawing code here
base.Draw(gameTime);
}
}
}
An easy way to do what you're wanting would probably be to implement a counter.
Add something like public double animCounter = 0 to the top of your code.
Then around the srcRect.X += srcRect.Width; line add something to the effect of:
if (animCounter > 0)
{
animCounter -= gameTime.ElapsedGameTime.TotalSeconds;
}
else
{
srcRect.X += srcRect.Width;
animCounter = 0.5f;
}
Again, this is the easy way to do what you're wanting to do, but not necessarily the best. For one, += srcRect.Width will quickly exceed the width of your sprite sheet, so you'd need to check for that and correct it. As itsme86 suggested, you should search Google for some tutorials.
This one isn't a bad start:
http://msdn.microsoft.com/en-us/library/bb203866.aspx

"nullreferenceexception was unhandled" in body.cs of farseer physics engine

I'm a c++ programmer trying out c#. I've done a lot with box2d in c++, but this is my first time with c#. So, I'm trying to make a simple game with farseer physics engine. When I try to compile my code (I'm using visual studio c# 2010 express and xna game studio 4.0), it stops in body.cs at IBroadPhase broadPhase = World.ContactManager.BroadPhase; With this error: nullreferenceexception was unhandled. I believe the problem is in my Player class, so here's the code for that:
public class Player : Entity
{
Vector2 position;
SpriteBatch spriteBatch;
Texture2D texture;
Rectangle rectangle;
Body body;
CircleShape shape;
Fixture fixture;
public Player()
{
// TODO: Construct any child components here
}
///
/// Allows the game component to perform any initialization it needs to before starting
/// to run. This is where it can query for any required services and load content.
///
public override void Initialize(World world, SpriteBatch spriteBatch, Texture2D texture)
{
// TODO: Add your initialization code here
this.spriteBatch = spriteBatch;
this.texture = texture;
rectangle = new Rectangle(0, 0, 11, 14);
body = BodyFactory.CreateBody(world);
body.BodyType = BodyType.Dynamic;
body.Position = new Vector2(0, 0);
shape = new CircleShape(1.0f, 1.0f);
fixture = body.CreateFixture(shape);
base.Initialize(world, spriteBatch, texture);
}
///
/// Allows the game component to update itself.
///
/// <param name="gameTime" />Provides a snapshot of timing values.
public override void Update(GameTime gameTime)
{
// TODO: Add your update code here
base.Update(gameTime);
}
public override void Draw(GameTime gameTime)
{
spriteBatch.Begin();
spriteBatch.Draw(texture, new Vector2(body.WorldCenter.X * 10, body.WorldCenter.Y * 10), rectangle, Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
}
The farseer testbed runs fine, so I'm pretty sure my code is the problem, and not farseer. Let me know if you need to see more of my code. I've also posted this in the farseer forums, so If I get an answer there, I'll let you guys know. Thanks in advance.
Someone asked me to show the code of Game1.cs, and found the problem. The problem was that I had never constructed the world before initializing my player. It was fixed by adding world = new World(Vector2.Zero); before I initialized the player.

Categories