I'm a little noob with XNA and I've encountered a problem. I have one texture called "dot", that I use to draw a line across the screen. Then I have a texture that I call "tool", that I want to move around when I touch it with my finger. The problem I have is that for the tool to be cleared and redrawn I call the graphicsDevice.Clear-method in XNA. But when I do that, my lines also disappears. So my question is how can i move around the tool, without causing my lines to disappear? Is there a way to only redraw the tool, without redrawing the lines? Heres a snippet of my code, first update-method:
protected override void Update (GameTime gameTime)
{
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
TouchCollection touchCollection = TouchPanel.GetState ();
foreach (TouchLocation tl in touchCollection) {
if ((tl.State == TouchLocationState.Pressed) || (tl.State == TouchLocationState.Moved)) {
toolPos = touchCollection [0].Position;
}
}
base.Update (gameTime);
}
And the draw-method:
protected override void Draw (GameTime gameTime)
{
graphics.GraphicsDevice.Clear (Color.Black);
newVector = nextVector (oldVector);
spriteBatch.Begin ();
DrawEvenlySpacedSprites (dot, oldVector, newVector, 0.9f);
spriteBatch.Draw (tool, toolPos, Color.White);
spriteBatch.End ();
oldVector = new Vector2 (newVector.X, newVector.Y);
base.Draw (gameTime);
}
Try using a RenderTarget2D with RenderTargetUsage.PreserveContents. If you didn't use render targets yet, here's a tutorial: http://rbwhitaker.wikidot.com/render-to-texture
All you have to do is to specify RenderTargetUsage.PreserveContents in target's constructor, draw dots to it, and draw the target and tool to the screen. It should look like this:
protected override void Draw (GameTime gameTime)
{
graphics.GraphicsDevice.Clear (Color.Black);
newVector = nextVector (oldVector);
GraphicsDevice.SetRenderTarget(renderTarget);
spriteBatch.Begin ();
DrawEvenlySpacedSprites (dot, oldVector, newVector, 0.9f);
spriteBatch.End ();
GraphicsDevice.SetRenderTarget(null);
spriteBatch.Begin();
spriteBatch.Draw(renderTarget, new Vector2(), Color.White);
spriteBatch.Draw (tool, toolPos, Color.White);
spriteBatch.End()
oldVector = new Vector2 (newVector.X, newVector.Y);
base.Draw (gameTime);
}
Related
This is a simple project created from MonoGame Cross-Platform Desktop template. I created a ball Texture2D and tried to make it move.So I added some code to the Update function.
position.X += 3;
And then in the Draw function
_spriteBatch.Begin();
_spriteBatch.Draw(ballTexture, position, Color.White);
_spriteBatch.End();
I can see the ball flashing sometimes.
Why is that and what can I do to make it not skip frames?
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace SimpleTest
{
public class Game1 : Game
{
private GraphicsDeviceManager _graphics;
private SpriteBatch _spriteBatch;
private Texture2D dirtTexture;
private Vector2 position;
private int direction = 1;
public Game1()
{
_graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
IsMouseVisible = true;
}
protected override void Initialize()
{
// TODO: Add your initialization logic here
base.Initialize();
}
protected override void LoadContent()
{
_spriteBatch = new SpriteBatch(GraphicsDevice);
// TODO: use this.Content to load your game content here
dirtTexture = Content.Load<Texture2D>("dirt");
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
// TODO: Add your update logic here
base.Update(gameTime);
if (position.X > 600)
direction = -1;
else if (position.X < 100)
direction = 1;
position.X = position.X + direction * 3;
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
// TODO: Add your drawing code here
_spriteBatch.Begin();
_spriteBatch.Draw(dirtTexture, position, Color.White);
_spriteBatch.End();
base.Draw(gameTime);
}
}
}
I think base.Update(gameTime); should only be placed at the very end of the Update() Method, Just like base.Draw(gameTime);. That way it won't skip any lines.
I guess your PC might be running slowly which is the problem, and not your code. To test it, you can replace your Draw method as follows:
protected override void Draw(GameTime gameTime)
{
Color color=gameTime.IsRunningSlowly?Color.Red:Color.CornflowerBlue;
GraphicsDevice.Clear(color);
// TODO: Add your drawing code here
_spriteBatch.Begin();
_spriteBatch.Draw(dirtTexture, position, Color.White);
_spriteBatch.End();
base.Draw(gameTime);
}
Everything is the same, except now we are colouring the screen as Red instead of the usual blue only if the game is in fact running slow (Which is due to your PC). We can know this by the gameTime variable as shown in the first two lines of the method. Test it out and see if you can see the game background going red when the "frame-skipping" happens.
I did test your exact code in my PC and it was working fine. Needless to say, I did use some other png I had instead of the "dirt" Texture2D you used but I don't think that it should be necessary.
Perhaps it's due to GC. You could use my -almost- garbage free build to verify.
You can install the updated SDK from here or the nuget package.
In my XNA game I need, at the beginning, to load some image and then Draw a lot of images to be used later in the game. I wanted to draw a loader that shows the progress, but I faced the problem that I can't draw while another spritebatch is already drawing.
It is something like:
I trait this as a thread:
public void DrawCache
{
progress = 0; // I can get this variable from outside
foreach (SpriteToBeCached in AllSprites)
{
graphicsDevice.SetRenderTarget(SpriteToBeCached.MyCachedTexture);
spriteBatch.Begin();
spriteBatch.Draw( ... );
spriteBatch.End();
graphicsDevice.SetRenderTarget(null);
++progress;
}
}
The Update menu state:
...
if (!loading)
{
var loading_thread = new Thread(DrawCache);
loading = false;
}
...
The Draw menu state:
...
GraphicsDevice.Clear(Color.Black);
spriteBatch.Begin();
spriteBatch.DrawString(font, progress, position, Color.White);
spriteBatch.End();
...
How can I solve this?
I have an 2d array of Texture2D, it holds the different parts of the map in this array. I have a problem though, when I run the game, the map is drawn correctly but for some reason the array[0, 0] texture overlaps all my textures including my player texture and mouse texture. Every other texture works as my mouse and player texture correctly overlaps the map.
I'm really confused right now as the map textures are being drawn together using a nested for loop.
Here is my draw method for my map which I call in the Game's Draw method:
public void Draw()
{
// Draws the Map from a 2D Array
for (int row = 0; row < mapTexture.GetLength(0); row++)
{
for (int col = 0; col < mapTexture.GetLength(1); col++)
{
spriteBatch.Draw(mapTexture[row, col], mapPosition[row, col], Color.White);
}//end for
}//end for
}//end Draw()
My actual draw method:
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend);
spriteBatch.Draw(mouseIcon, mouseIconPosition, Color.White);
player.Draw();
map.Draw();
spriteBatch.End();
base.Draw(gameTime);
}//end Draw()
Try inverting the order that they're drawn, AND use SpriteSortMode.Deferred
You can try use overloaded SpriteBatch.Draw method with depth. As example:
SpriteBatch.Draw (Texture2D, Vector2, Nullable, Color, Single, Vector2, Single, SpriteEffects, Single) Adds a sprite to the batch of sprites to be rendered, specifying the texture, screen position, optional source rectangle, color tint, rotation, origin, scale, effects, and sort depth.
or can try change order for drawing:
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend);
map.Draw(); // first
player.Draw(); // second
spriteBatch.Draw(mouseIcon, mouseIconPosition, Color.White); // third
spriteBatch.End();
base.Draw(gameTime);
}//end Draw()
(its for SpriteSortMode.Deferred)
P.S. Sorry for google-translating
oops... I have not updated comments before responding
Interesting problem! Basically I have a timer for my UI that counts down from 99. Everything works fine save for the fact its drawing the new time on top of the old time. (The previous time is not clearing) There is a clear happening within the GameplayScreens draw call though... its just weird.
Here are my related functions:
GameplayScreen.cs (or our usual Game1)
public override void Update(GameTime gameTime)
{
m_GameUI.Update(gameTime);
m_GameCam.lookAt(m_Hero.Position);//feeds the camera's lookAt function the players vector2 position
m_GameUI.lookAt(m_GameCam.Position); //Look at the camera's position :D
}
public override void Draw(GameTime gameTime)
{
ScreenManager.GraphicsDevice.Clear(ClearOptions.Target,
Color.CornflowerBlue, 0, 0);
SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
m_BackgroundManager.Draw(spriteBatch, m_GameCam);
//Begin the Spritebatch Drawing
spriteBatch.Begin(SpriteSortMode.Immediate, null,
null,
null,
null,
null, m_GameCam.ViewMatrix);
//Call EntityManager.DrawAllEntities()
EntityManager.Instance.DrawAllEntities(gameTime, spriteBatch);
//End the spritebatch drawing
spriteBatch.End();
spriteBatch.Begin();
m_GameUI.Draw(gameTime, spriteBatch);
m_PlayerUI.Draw(gameTime, spriteBatch);
spriteBatch.End();
}
GameUI.cs
SpriteFont m_Font;
double m_Timer;
public virtual void Update(GameTime gameTime)
{
m_Timer -= gameTime.ElapsedGameTime.TotalSeconds;
}
public virtual void Draw(GameTime gameTime, SpriteBatch spriteBatch)
{
spriteBatch.Draw(UITexture, Position, Color.White);
spriteBatch.DrawString(m_Font, "" + (int)m_Timer + "", new Vector2(380, 45), Color.White);
}
Ended up being a really silly mistake, I had a class deriving from the UI that was calling base.draw() so both the updated clock and the original value were being displayed on the screen at once. Basically poor code design, everyone is a newbie when they start out right?
Thanks for looking into it :)
i'm just beginning to code in C# / XNA
I've made a very simple little program in XNA, its a drawn rectangle, with 3 randomly generated balls inside,
the balls are defined in their own class and I've been following this tutorial
http://www.bluerosegames.com/brg/xna101.aspx
the balls are generated using
int ballCount = 3;
and what i wanted to do is make it so a mouse click would increase the int by 1, adding another ball to the screen
my code looks like this, but I'm not sure if it's right / possible
mouseStateCurrent = Mouse.GetState();
if (mouseStateCurrent.LeftButton == ButtonState.Pressed &&
mouseStatePrevious.LeftButton == ButtonState.Released)
{
ballCount = ballCount+1;
}
mouseStatePrevious = mouseStateCurrent;
any help advice would be helpful :)
i am using a code to draw the balls already that looks like this
spriteBatch.Begin();
spriteBatch.Draw(debugColor, TextBox, Color.White);
spriteBatch.Draw(background, backgroundRectangle, Color.White);
foreach (BouncingBall ball in balls)
{
ball.Draw(spriteBatch);
}
spriteBatch.End();
base.Draw(gameTime);
is it possible to edit this to get the "click to add balls" effect?
If balls is defined as a List<BouncingBall> that is accessible to the Game class, in your MouseClick event you can use balls.Add(new BouncingBall());. Because you are using a foreach loop, it will increment the number of balls each loop and your Draw code will already cater for any new balls added.
In your draw method you can do something like
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
for(var i=0;i<ballcount;i++)
{
spriteBatch.Draw()
}
spriteBatch.End();
base.Draw(gameTime);
}