So far, this is my first XNA game and I'm having real trouble trying to learn this.
I'm following a tutorial from Microsoft, found here: XNA Xbox Live Indie Games
Every now and again, the code breaks. Admittedly, I have taken a couple of bits out that I didn't think I'd need and I've created two enemy classes rather than just the one, but I don't think I hit any major faultlines with my adjustments.
In the Draw() method in the main Game1.cs file, I've had to include a for loop that will iterate through a list of available enemies and draw them upon update. However, the line of code flags up as incorrect, and I have absolutely no idea why. I followed the tutorial, and it looks like it should work, but it doesn't. Here's the entire Draw() method:
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.ForestGreen);
backRect.Width = 800;
backRect.Height = 480;
// TODO: Add your drawing code here
// Start drawing
spriteBatch.Begin();
spriteBatch.Draw(backgroundTexture, backRect, Color.White);
// Draw the Player
player.Draw(spriteBatch);
for (int i = 0; i < goblins.Count; i++)
{
goblins[i].Draw(spriteBatch);
}
// Stop drawing
spriteBatch.End();
base.Draw(gameTime);
}
It's the code inside the for loop that won't work. Any ideas how to fix it and/or any suggestions for a better tutorial?
I like this tutorial a lot:
http://xbox.create.msdn.com/en-US/education/tutorial/2dgame/getting_started
It got me started off pretty well.
You always need to call SpriteBatch.Begin() and SpriteBatch.End() on your sprite-batches. I am not sure about mixing them, but try to avoid it and use as few spritebatches as possible.
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.ForestGreen);
backRect.Width = 800;
backRect.Height = 480;
// TODO: Add your drawing code here
// Start drawing
spriteBatch.Begin();
spriteBatch.Draw(backgroundTexture, backRect, Color.White);
// Draw the Player
spriteBatch.Draw(playerTexture, playerRect, Color.White);
for (int i = 0; i < goblins.Count; i++)
{
spriteBatch.Draw(goblins[i].Texture, goblins[i].Rect, Color.White);
}
// Stop drawing
spriteBatch.End();
base.Draw(gameTime);
}
See here for the documentation.
Related
I'm creating a game in monogame, and I've loaded tiles in my game inside the Draw() function like so:
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
spriteBatch.Draw(danChar, charPosition, Color.White);
// loop below loads the 'grass' tiles only
// assuming gameworld size of 770x450
for (int i = 0; i < 770; i += 31) // adds 31 to i (per tile)
{
position = new Vector2(i, 392); // places incrementation into vector position
spriteBatch.Draw(gameTile, position, Color.White); // draws the tile each time
if (i == 744)
{
i = i + 26; // fills last space between 744 and 770
position = new Vector2(i, 392);
}
spriteBatch.Draw(gameTile, position, Color.White);
}
// loop below loads the brick tiles only (ones without grass)
spriteBatch.End(); // ends the spriteBatch call
base.Draw(gameTime);
}
However I would prefer that this was a separate class rather than being placed directly into the draw function, however I'm not too sure how to do this and would appreciate any help given.
Thanks in advance!
If you just want to move the code as is to another class, create your class (e.g. something like GameWorld seems to appropriate for your code)
public class GameWorld
{
// You may wish to move your gameTile definition into this class if it is the only
// class that uses it, and handle the content loading for it in here.
// e.g. if you're currently loading the texture in the LoadContent method in your game
// class, create a LoadContent method here and pass in ContentManger as a parameter.
// I've passed in the texture as a parameter to the Draw method in this example to
// simplify as I'm not sure how you're managing your textures.
public void Draw(SpriteBatch spriteBatch, GameTime gameTime, Texture2D gameTile)
{
// loop below loads the 'grass' tiles only
// assuming gameworld size of 770x450
for (int i = 0; i < 770; i += 31) // adds 31 to i (per tile)
{
Vector2 position = new Vector2(i, 392); // places incrementation into vector position
spriteBatch.Draw(gameTile, position, Color.White); // draws the tile each time
if (i == 744)
{
i = i + 26; // fills last space between 744 and 770
position = new Vector2(i, 392);
}
spriteBatch.Draw(gameTile, position, Color.White);
}
// loop below loads the brick tiles only (ones without grass)
}
}
Then the Draw method in your Game class would look like
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
spriteBatch.Draw(danChar, charPosition, Color.White);
// Assuming you've created/loaded an instance of the GameWorld class
// called gameWorld in Initialize/LoadContent
gameWorld.Draw(spriteBatch, gameTime, gameTile);
spriteBatch.End(); // ends the spriteBatch call
base.Draw(gameTime);
}
Just make sure you're calling the Draw methods in the correct order. e.g. you want your player to appear above any background tiles.
I believe the default SpriteSortMode is Deferred which draws in the order the calls are made (i.e. from the back to the front).
You can specify a different SpriteSortMode in your call to spriteBatch.Begin() if you need to but for a simple game just move the Draw calls around.
More info on SpriteSortMode at MSDN if needed.
Similarly you can chain your Update, LoadContent methods into these classes if you wish, making sure to pass in anything you need as arguments.
Update:
To define gameWorld as an instance of the GameWorld class, you define it near the top of your game class, then typically initialize it in the Initialize method.
So your game class will look something like
public class MyGameName : Microsoft.Xna.Framework.Game
{
private SpriteBatch spriteBatch;
// other variable declarations
// Add a declaration for gameWorld
private GameWorld gameWorld;
protected override Initialize()
{
// Add the following line to initialize your gameWorld instance
gameWorld = new GameWorld();
}
// other existing code - your LoadContent, Update, Draw methods etc.
}
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
I'm having trouble with touch/multitouch input.
I want to draw a small rectangle, 100x100 in dimensions, wherever the user presses (mission accomplished) but I also want them to move as the user moves his fingers (that's not happening atm).
I'm also getting weird behaviour besides the not-moving part, let's say I touch first with my thumb, then with my middle finger. Two cubes appear bellow each finger, but if I remove the finger I place first (thumb in this scenario) the cube under the finger I placed second (middle finger) will disappear and the one where my thumb was will still be there. I guess this issue will solve itself once I get this to update correctly whenever there is movement.
This are the Draw and Update snippets. Any help appreciated:
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
TouchCollection touchLocations = TouchPanel.GetState();
i = 0;
foreach (TouchLocation touchLocation in touchLocations)
{
if (touchLocation.State == TouchLocationState.Pressed)
{
pos[i] = touchLocation.Position;
}
i++;
}
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
for (j = 0; j < i; j++)
{
spriteBatch.Draw(whiteRectangle, new Rectangle(((int)pos[j].X - 50), ((int)pos[j].Y - 50), 100, 100), Color.Chocolate);
}
spriteBatch.End();
base.Draw(gameTime);
}
I would recommend using a Dictionary assuming you want to associate touch locations to their position. The key should be the TouchLocation.Id
TouchLocation.Id will remain the same for a given interaction. There is no guarantee that the order of TouchLocations will be the same from one frame to another, so you have to use their ID and not the order they appear in the collection.
I'm a bit late on this, but well here is what was wrong and how I solve it...
foreach (TouchLocation touchLocation in touchLocations)
{
if (touchLocation.State == TouchLocationState.Pressed)
{
pos[i] = touchLocation.Position;
}
i++;
}
I guess I was sleepy when I wrote this part of the code (nothing good happens after 2 AM... not even good code) I don't know why I was checking if the location state was pressed... that's why it didn't move when I move... first frame it is indeed pressed but once you start moving it it's .Moved ... all in all, removed that if and it works like a charm...
foreach (TouchLocation touchLocation in touchLocations)
{
pos[i] = touchLocation.Position;
i++;
}
All in all now it behaves as intended.
Cheers!
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);
}