Moving a sprite in the direction it is facing, why does my attempt not work? - xna

I am using MonoGame to develop a Windows 8 store app/game (not for phone). I am also using the project with XAML, however this problem is not XAML related.
I am trying to get a ship to move in the direction it is facing, and the direction can be changed by pressing left and right keys to rotate the ship. The upwards key is used to move the ship in the direction it is facing.
The ship's image/texture is initially faced downwards(imagine an arrow facing downwards) when the game starts, so when I press the up key I want to move it downwards, however it moves to the right. I have gathered this is something to do with the rotation?
I have googled how to solve my problem and tried various methods, and this is my best attempt, however it does not work.
My parent sprite class:
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ship_Meteor_Game_V1
{
abstract class cSprite
{
#region Properties
Texture2D spriteTexture;
Rectangle spriteRectangle;
Vector2 spritePosition;
public Texture2D SpriteTexture { get { return spriteTexture; } set { spriteTexture = value; } }
public Rectangle SpriteRectangle { get { return spriteRectangle; } set { spriteRectangle = value; } }
public Vector2 SpritePosition { get { return spritePosition; } set { spritePosition = value; } }
#endregion
abstract public void Update(GameTime gameTime);
abstract public void Draw(SpriteBatch spriteBatch);
}
}
My player class:
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ship_Meteor_Game_V1
{
class cPlayer : cSprite
{
Vector2 origin;
float rotation;
float speed;
public cPlayer()
{
}
public cPlayer(Texture2D newTexture2D, Vector2 newPosition)
{
SpriteTexture = newTexture2D;
SpritePosition = newPosition;
speed = 2;
rotation = 0;
}
public override void Update(GameTime gameTime)
{
if(Keyboard.GetState().IsKeyDown(Keys.Right))
{
rotation = rotation + 0.1f;
}
if(Keyboard.GetState().IsKeyDown(Keys.Left))
{
rotation = rotation - 0.1f;
}
if (Keyboard.GetState().IsKeyDown(Keys.Up))
{
Move();
}
}
public override void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(SpriteTexture, SpritePosition, null, Color.White, rotation, origin, 0.2f, SpriteEffects.None, 0f);
}
public void Move()
{
Vector2 direction = new Vector2( (float)Math.Cos(rotation), (float)Math.Sin(rotation));
direction.Normalize();
SpritePosition = SpritePosition + (direction * speed);
}
}
}
Basically I want a ship to move in the direction it is facing but instead it is constantly moving sideways in whatever direction it is facing and I have no clue how to solve it. I can show you any extra classes/code you want if I have it.
PS: Anyone know a variable/type that can accept both mouse and keyboard input?

Can't see anything obvious wrong with that code.
A guess would be you're using a ship graphic in your content manager that isn't facing upwards.
If that's the case you'll have to rotate it in an image editor, or modify your starting rotation.
My bet would be it's facing right, which would be an understandable confusion as in regular maths for radians 0 would be facing right. In Xna however 0 is up.

Related

XNA mouse 'position relative-to' changes every build

Okay so I'm starting to make a main menu for a small flash game and to do this I want to use the mouse to click on buttons etc. I have a button class in which I create two rectangles: a rectangle for the button and a rectangle for the mouse based on its X and Y, 1 pixel by 1 pixel. I use Rectangle.Intersects to check if they are touching before seeing if left mouse button is down. Problem is, the thing the mouse position is relative to changes every time so no matter where the mouse button is on the screen, it's never the same co-ordinates as in a different build in that exact same position. I seriously just need ideas now as I'm running out. If I didn't explain it very well or you need further details to help please ask - I WOULD BE SO GRATEFUL.
Will post back if I find an answer
Update - Okay here's the button class
class OnScreenButton
{
public Texture2D texture;
Vector2 position;
Rectangle rectangle;
Color colour = new Color(255, 255, 255, 255);
public Vector2 size;
public OnScreenButton(Texture2D newtexture, GraphicsDevice graphics)
{
texture = newtexture;
// ScreenW = 500, ScreenH = 600
// Img W = 80, Img H = 20
size = new Vector2(graphics.Viewport.Width / 10, graphics.Viewport.Height / 30);
size = new Vector2(texture.Width, texture.Height);
}
bool down;
public bool isClicked;
public void Update(MouseState mouseState)
{
rectangle = new Rectangle((int)position.X, (int)position.Y, (int)size.X, (int)size.Y);
Rectangle mouseRectangle = new Rectangle(mouseState.X, mouseState.Y, 1, 1);
if (mouseRectangle.Intersects(rectangle))
{
if (colour.A == 255)
{
down = false;
}
if (colour.A == 0)
{
down = true;
}
if (down)
{
colour.A += 3;
}
else
{
colour.A -= 3;
}
if (mouseState.LeftButton == ButtonState.Pressed)
{
isClicked = true;
}
}
else if (colour.A < 255)
{
colour.A += 3;
isClicked = false;
colour.A = (255);
}
}
public void SetPosition(Vector2 newPos)
{
position = newPos;
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(texture, rectangle, colour);
}
}
}
(Sorry for weird formatting, brand new to stack overflow and the posting is still a little confusing)
Here is some other code I think is relevent...
Game.1 initializing stuff
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
protected override void Initialize()
{
// TODO: Add your initialization logic here
Mouse.WindowHandle = Window.Handle;
base.Initialize();
}
public Main()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
KeyboardState keyboardState;
MouseState mouseState;
Main menu update routine...
private void UpdateMainMenu(GameTime gameTime)
{
// Button options
if (buttonPlay.isClicked == true)
{
CreateNewGame();
currentGameState = GameState.playing;
}
buttonPlay.Update(mouseState);
if (buttonExit.isClicked == true)
{
this.Exit();
}
buttonExit.Update(mouseState);
// Press enter to play
if (keyboardState.IsKeyDown(Keys.Enter))
{
CreateNewGame();
currentGameState = GameState.playing;
}
}
Here's thee draw routine for main menu...
public void DrawMainMenu()
{
spriteBatch.Draw(mainMenuBackground, new Vector2(0, 0), Color.White);
buttonPlay.Draw(spriteBatch);
buttonExit.Draw(spriteBatch);
spriteBatch.DrawString(playerAmmoFont, String.Format("{0}", mouseState), new Vector2(0, 0), Color.White);
}
okay that's all I can think of
UPDATE - Okay so I know a few things that aren't the problem...
The whole of my button class is fine, I made a new project and inserted all the relevant code into it and it worked absolutely perfectly so I'm starting to think its something to do with the code positioning and the graphics device stuff although I still don't have a clue how to fix it.
the window appears at the same spot every time
there is no pattern to the change in coordinates at all
this is really annoying
UPDATE - OKAY. I spent a long time writing down the coordinates that I got each time I ran the code and stuck to cursor in the top right corner of the screen. Here is what I got.
(-203, -225)
(-253, -275)
(-53, -75)
(-103, -125)
(-153, -175)
(-203, -225)
(-253, -275)
(-53, -75)
(-103, -125)
(-153, -175)
(-203, -225)
(-253, -275)
(-53, -75)
(-103, -125)
(-153, -175)
(-203, -225)
(-253, -275)
(-53, -75)
(-103, -125)
(-153, -175)
(-203, -225)
(-78, -100)
(-128, -150)
(-178, -200)
(-228, -250)
(-28, -50)
(-53, -75)
(-103, -125)
(-153, -175) < AND FROM HERE THE PATTERN LOOPS ROUND.
I just don't get how the same code can execute a different bug on different executions like this.
Also, mouse.Wheel doesn't go up or down whereas it works on the project that I made to test the relevant code where the mouse position was relevant to the top left pixel of the game window.
UPDATE - EVEN MORE DAMN COMPLICATIONS - So I just rand it a few times again and the offset values are offset... the increase is the same but I got values like (-178, -200) then (-228, -250). I have also discovered that the mouse is not relative to the game window what so ever, if I jam the mouse in the top right corner of the screen and check the coordinates, then move the game window and do the same again, the coordinates don't change. Please please please help me, or tell me if I'm being stupid, or something. Thanks.
The mouse coordinates are relative to the monitor. Here is my general button class to try and work for your situation.
public class Button
{
public event EventHandler<EventArgs> Clicked;
public Vector2 Position { get; set;}
public Texture2D Texture { get; set;}
public Color Tint { get; set; }
public float Scale { get; set; }
public float Rotation { get; set; }
public int Width
{
get
{
if (texture == null)
return 0;
else
return texture.Width;
}
}
public int Height
{
get
{
if (texture == null)
return 0;
else
return texture.Height;
}
}
private void OnClick()
{
if (Clicked != null)
Clicked(this, EventArgs.Empty);
}
public Button(Vector2 position, Texture2D texture)
: base(parent)
{
Position = position;
Texture = texture;
Tint = Color.White;
Scale = 1.0f;
Rotation = 0.0f;
}
public bool HandleClick(Vector2 vector)
{
if (vector.X >= Position.X)
{
if (vector.X <= Position.X + Width)
{
if (vector.Y >= Position.Y)
{
if (vector.Y <= Position.Y + Height)
{
OnClick();
return true;
}
}
}
}
return false;
}
public bool HandleEntered(Vector2 vector)
{
if (vector.X >= Position.X)
{
if (vector.X <= Position.X + Width)
{
if (vector.Y >= Position.Y)
{
if (vector.Y <= Position.Y + Height)
{
return true;
}
}
}
}
return false;
}
public override void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(Texture, Position, null, Tint, Rotation, Vector2.Zero, Scale, SpriteEffects.None, 0.0f);
}
Declare a button:
Button btn = new Button(position where you want the button, texture for the button);
btn.Clicked += () => { /* Handle button clicked code here */ };
In your update method inside your main game:
public void Update (GameTime gameTime)
{
MouseState mouseState = Mouse.GetState();
if(mouseState.LeftButton == ButtonState.Pressed) // check if mouse is clicked
{
btn.HandleClicked(new Vector2(mouseState.X, mouseState.Y)); // If true then the button clicked event will fire
// Here you can also change the color of the button if the button is currently clicked
}
// Here you can change the color of the button if the mouse is hover over the control
// Example:
btn.Tint = btn.HandleEntered(new Vector2(mouseState.X, mouseState.Y)) ? Color.White * 0.75f : Color.White;
}
Note: You can also use a rectangle for the button to adjust its size instead of strictly using the textures dimensions. Hope this gives some insight.
So here's what was going on: I had a bullet class in my game for every bullet shot. In this class I check whether the bullets hits nothing, hits the asteroid, or destroys the asteroids. If the latter is true then I would increment playerScore by 5. PlayerScore was a Game1 attribute so I thought the easiest way to do this would be to create a new Game1 in bullet.cs to allow me to refer to the variable. Deleting the "Main mainGame = new Main():" in Bullet.cs fixed this issue and I think the issue was coming from a new graphics device being made every single time I fired a single bullet.

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.

Dealing with game cursor, not windows cursor

Earlier, I had an issue with my Windows cursor being uncoordinated with the game and asked here how I could solve this. A member suggested me to hide the Windows cursor and create a custom game cursor, so I did this. However, a new problem occurred.
My game cursor is usually offset to the right of the Windows mouse, so when I want to move the game cursor to the left side of the window and click my left mouse button, it causes a disturbance to the game, such as bringing an application in the background to the top.
Here is a picture of what I mean: http://i.imgur.com/nChwToh.png
As you can see, the game cursor is offset to the right of the Windows cursor, and if I use game cursor to click on something on the left side of the window, the application in the background (Google Chrome in this case), will be brought up to the front, causing disturbance to the game.
Is there anything I can do to use my game cursor without any disturbances?
I have just tried to move everything out of their classes, all into the main Game class.
This fixed the problem, but does not give me an answer to WHY this happens.
The code is exactly the same, it's just organized to separate classes.
So, does anyone know why this is?
Why is using object-oriented programming instead of putting everything in the game class going mess up my mouse coordination and stuff?
Normally, you would have a texture for you in-game cursor where, for instance, the pixel at [16,16] is where you are "aiming" (the center of a crosshair, for instance). What you owuld to to draw this centered on the mouse is to use Mouse.GetState() to get the position, and then offset the drawing of your mouse-texture by the negative of the "center" of the "aim"-point.
so let's say we make a custom Mouse-Class:
public class GameMouse
{
public Vector2 Position = Vector2.Zero;
private Texture2D Texture { get; set; }
private Vector2 CenterPoint = Vector2.Zero;
public MouseState State { get; set; }
public MouseState PreviousState { get; set; }
//Returns true if left button is pressed (true as long as you hold button)
public Boolean LeftDown
{
get { return State.LeftButton == ButtonState.Pressed; }
}
//Returns true if left button has been pressed since last update (only once per click)
public Boolean LeftPressed
{
get { return (State.LeftButton == ButtonState.Pressed) &&
(PreviousState.LeftButton == ButtonState.Released); }
}
//Initialize texture and states.
public GameMouse(Texture2D texture, Vector2 centerPoint)
{
Texture = texture;
CenterPoint = centerPoint;
State = Mouse.GetState();
//Calling Update will set previousstate and update Position.
Update();
}
public void Update()
{
PreviousState = State;
State = Mouse.GetState();
Position.X = State.X;
Position.Y = State.Y;
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Begin();
spriteBatch.Draw(Texture, Position - CenterPoint, Color.White);
spriteBatch.End();
}
}

Newly loaded sprites not behaving properly in XNA 4.0

Here is the code for a project im working on, where an enemy moves back and forth at the bottom of the screen.
class enemy1
{
Texture2D texture;
public Vector2 position;
bool isAlive = false;
Random rand;
int whichSide;
public enemy1(Texture2D texture, Vector2 position)
{
this.texture = texture;
this.position = position;
}
public void Update()
{
if (isAlive)
{
if (whichSide == 1)
{
position.X += 4;
if (position.X > 1000 + texture.Width)
isAlive = false;
}
if (whichSide == 2)
{
position.X -= 4;
if (position.X < 0)
isAlive = false;
}
}
else
{
rand = new Random();
whichSide = rand.Next(1, 3);
SetInStartPosition();
}
}
private void SetInStartPosition()
{
isAlive = true;
if (whichSide == 1)
position = new Vector2(0 - texture.Width, 563 - texture.Height);
if (whichSide == 2)
position = new Vector2(1000 + texture.Width, 563 - texture.Height);
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(texture, position, Color.White);
}
}
Now i want there to be a few enemys going back and forth but they start at differant positions so it looks like there is a few enemys going back and forth at the bottom of the screen. I have managed to draw a few other enemies on the screen, except they do not behave like the first enemy. They just are pictures on a screen not moving anywhere. So now all i have is the hero moving around and one enemy at the bottom of the screen, along with 5 other enemys sitting at the top of the screen doing nothing. How do i easily add a new sprite from a class that has the same behavior, at any time, while not making a billion variables to store them in?
Generally it's a good idea to have similar logic contained within the proper class, so if all Sprites where to do the same thing, then all you would need to do is put your movement code inside a public method and then call that method inside Update().
So, if your Sprite class looks something like this:
public class Sprite
{
private Vector2 Position;
public Sprite(Texture2D texture, Vector2 position)
{
Position = position;
}
//then just add this
public void MoveSprite(int amount)
{
position.X += amount;
}
}
Now, the object name "Sprite" is pretty generic, you will more than likely have many "Sprites" in your game.
So you're going to want to follow good OOP practices and maybe name this specific sprite something different and then have it derive from this class we're looking at right now. (But i'm not going to make design decisions for you)
This was a vague question, but that's my best shot at an answer for you.

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

Resources