• XNA Bullet Problem
    8 replies, posted
When I fire my Bullet just stays in the top left corner... It doesn't move or anything... Player Class [CODE] using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; namespace Whole_Loada_Bullets { class Player { public Vector2 Position; private Bullet mBullet = new Bullet(); private Texture2D sprite; private float rotation; private Vector2 origin; private List<Bullet> bulletlist = new List<Bullet>(); public void LoadContent(ContentManager theContent) { sprite = theContent.Load<Texture2D>("images/player"); origin = new Vector2(sprite.Width / 2, sprite.Height / 2); Position = new Vector2(128, 128); mBullet.LoadContent(theContent); } public void Update(GameTime theGameTime) { KeyboardState currentState = Keyboard.GetState(); #region Ship Movement #region Rotate if (currentState.IsKeyDown(Keys.Left) == true) { rotation -= (float)theGameTime.ElapsedGameTime.TotalSeconds * 5; } else if (currentState.IsKeyDown(Keys.Right) == true) { rotation += (float)theGameTime.ElapsedGameTime.TotalSeconds * 5; } #endregion Move(currentState); #endregion #region Bullet Movement if (currentState.IsKeyDown(Keys.Space)) { mBullet.Position.Y += ((float)(Math.Cos(rotation))); mBullet.Position.X += ((float)(Math.Cos(rotation))); bulletlist.Add(mBullet); } #endregion } private void Move(KeyboardState currentState) { #region Move if(currentState.IsKeyDown(Keys.W) == true) { Position.Y -= 4; } else if (currentState.IsKeyDown(Keys.S) == true) { Position.Y += 4; } if (currentState.IsKeyDown(Keys.D) == true) { Position.X += 4; } else if (currentState.IsKeyDown(Keys.A) == true) { Position.X -= 4; } #endregion } public void Draw(SpriteBatch theBatch) { theBatch.Draw(sprite, new Rectangle((int)Position.X, (int)Position.Y, sprite.Width, sprite.Height), null, Color.White, rotation, origin, SpriteEffects.None, 1); foreach (Bullet i in bulletlist) { mBullet.Draw(theBatch); } } } } [/CODE] Bullet Class [CODE] using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Storage; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; namespace Whole_Loada_Bullets { class Bullet : Sprite { const string BULLET_ASSETNAME = "images/bullet"; private float mSpeed = 10.0f; public Vector2 Position; public float Angle; public void LoadContent(ContentManager theContent) { base.LoadContent(theContent, BULLET_ASSETNAME); } public void Update(GameTime theGameTime) { Angle = this.Direction; base.Update(theGameTime, mSpeed, Angle); } } } [/CODE] Sprite Class [CODE] using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; namespace Whole_Loada_Bullets { class Sprite { public Vector2 Position = new Vector2(0, 0); public string AssetName; public float Direction; private Rectangle size; private Texture2D mTexture; public void LoadContent(ContentManager theContent, string theAssetName) { mTexture = theContent.Load<Texture2D>(theAssetName); size = new Rectangle(0, 0, mTexture.Width, mTexture.Height); AssetName = theAssetName; } public void Update(GameTime theGameTime, float Speed, float mDirection) { mDirection = this.Direction; Position.Y = Direction * Speed * theGameTime.ElapsedGameTime.Seconds; Position.X = Direction * Speed * theGameTime.ElapsedGameTime.Seconds; } public void Draw(SpriteBatch theBatch) { theBatch.Draw(mTexture, Position, new Rectangle(0, 0, mTexture.Width, mTexture.Height), Color.White, Direction, Vector2.Zero, 1, SpriteEffects.None, 0); } } } [/CODE]
[QUOTE=Loli;20048383]When I fire my Bullet just stays in the top left corner... It doesn't move or anything... Sprite Class [CODE] using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; namespace Whole_Loada_Bullets { class Sprite { public Vector2 Position = new Vector2(0, 0); public string AssetName; public float Direction; private Rectangle size; private Texture2D mTexture; public void LoadContent(ContentManager theContent, string theAssetName) { mTexture = theContent.Load<Texture2D>(theAssetName); size = new Rectangle(0, 0, mTexture.Width, mTexture.Height); AssetName = theAssetName; } public void Update(GameTime theGameTime, float Speed, float mDirection) { mDirection = this.Direction; Position.Y = Direction * Speed * theGameTime.ElapsedGameTime.Seconds; Position.X = Direction * Speed * theGameTime.ElapsedGameTime.Seconds; } public void Draw(SpriteBatch theBatch) { theBatch.Draw(mTexture, Position, new Rectangle(0, 0, mTexture.Width, mTexture.Height), Color.White, Direction, Vector2.Zero, 1, SpriteEffects.None, 0); } } } [/CODE][/QUOTE] [code] Position.Y = Direction * Speed * theGameTime.ElapsedGameTime.Seconds; Position.X = Direction * Speed * theGameTime.ElapsedGameTime.Seconds; [/code] You are setting the position (both x and y) to an almost zero position (Your elapsed time will be a tiny value, presumably bringing the result to something that is being reounded to (0,0) when drawn to the screen), and you code also does not make much sense. I am assuming that 'Direction' is the angle the bullet is moving in, and because it is an angle, you need to use trig to resolve it into x,y components. This can be slow, so normally the velocity of an object would be stored using a Vector2 (as the position is) and taking a step forward in time is as simple as Position.x += Velocity.x*ElapsedTime Here is what your code should look like (I've never used C# before, so you will need to check the proper function names of the trig, and if they use radians or degrees). (Edited) [code] Position.Y += Math.sin(Direction) * Speed * theGameTime.ElapsedGameTime.Seconds; Position.X += Math.cos(Direction) * Speed * theGameTime.ElapsedGameTime.Seconds; [/code]
It's Math.Sin, and you should use Math.Cos for X and Sin for Y. Or the opposite, can't recall, but not the same.
Thanks guys, I'll have to give it a try [editline]11:09AM[/editline] No luck... I changed my sprite class to this... [CODE] Position.Y = (float)(Math.Cos(Direction)) * Speed * theGameTime.ElapsedGameTime.Seconds; Position.X = (float)(Math.Sin(Direction)) * Speed * theGameTime.ElapsedGameTime.Seconds; [/CODE]
Yeah, cos for X and sin for Y. Also did you check if the sin and cos functions use degrees or radians? And what is the type of the X and Y members of position? If they are int then they are probably being rounded back down to 0 after every step (not enough is being added to them to be rounded up).
I changed alot, and started it in a new project to test things... My Bullet now spawns at the players location yet doesn't move and only draws 1 at a time... Any suggestions? Player Class [CODE] using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; namespace Shooter { class Player { private Texture2D mSprite; private Texture2D mBulletSprite; private Vector2 mPosition; private Vector2 mSpeed; private float mRotation; private Vector2 mOrigin; private Bullet mBullet; private List<Bullet> mBulletList = new List<Bullet>(); public byte Lives; public Rectangle Rect; public void LoadContent(ContentManager theContent) { mBullet = new Bullet(); mBulletSprite = theContent.Load<Texture2D>("Sprites/Bullet"); mSprite = theContent.Load<Texture2D>("Sprites/Player"); Rect = new Rectangle(0, 0, mSprite.Width, mSprite.Height); mOrigin = new Vector2(mSprite.Width/2, mSprite.Height/2); mPosition = new Vector2(512, 389); Lives = 4; } public void Update(GameTime theGameTime) { KeyboardState aCurrentKeyboardState = Keyboard.GetState(); UpdateMovement(aCurrentKeyboardState); } public void UpdateMovement(KeyboardState aCurrentKeyboardState) { #region Rotation if (aCurrentKeyboardState.IsKeyDown(Keys.A)) { mRotation -= 0.25f; } else if (aCurrentKeyboardState.IsKeyDown(Keys.D)) { mRotation += 0.25f; } #endregion #region Move #region Get Speed mSpeed = new Vector2((float)Math.Cos(mRotation), (float)Math.Sin(mRotation)) * 5.0f; #endregion if (aCurrentKeyboardState.IsKeyDown(Keys.W)) { mPosition += mSpeed; } if (aCurrentKeyboardState.IsKeyDown(Keys.S)) { mPosition -= mSpeed; } #endregion #region Fire Bullets if (aCurrentKeyboardState.IsKeyDown(Keys.Space)) { mBulletList.Add(mBullet); foreach(Bullet i in mBulletList) { mBullet.Position = mPosition - mBullet.Origin; mBullet.Speed = new Vector2((float)Math.Cos(mRotation), (float)Math.Sin(mRotation)) * 10.0f; UpdateBullets(); } } #endregion } public void UpdateBullets() { mBullet.Position += mBullet.Speed; } public void Draw(SpriteBatch theBatch) { theBatch.Draw(mSprite, mPosition, new Rectangle(0, 0, mSprite.Width, mSprite.Height), Color.White, mRotation, mOrigin, 1, SpriteEffects.None, 0); #region Draw Bullets foreach (Bullet i in mBulletList) { theBatch.Draw(mBulletSprite, mBullet.Position, Color.White); } #endregion } } } [/CODE] Bullet Class [Code] using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; namespace Shooter { class Bullet { private Texture2D mSprite; public Vector2 Speed; public Vector2 Position; public Vector2 Origin; public bool Alive = false; public void LoadContent(ContentManager theContent) { mSprite = theContent.Load<Texture2D>("Sprites/bullet"); Origin = new Vector2(mSprite.Width/2, mSprite.Height/2); } } } [/code]
[QUOTE=Loli;20056986]Thanks guys, I'll have to give it a try [editline]11:09AM[/editline] No luck... I changed my sprite class to this... [CODE] Position.Y = (float)(Math.Cos(Direction)) * Speed * theGameTime.ElapsedGameTime.Seconds; Position.X = (float)(Math.Sin(Direction)) * Speed * theGameTime.ElapsedGameTime.Seconds; [/CODE][/QUOTE] You are always setting the position to the same value. ElapsedGameTime returns the time elapsed since the last update, it should always be the same in your case. (Like a few milliseconds) You have to, as it was already said here, change the code to: [CODE] Position.Y += (float)(Math.Cos(Direction)) * Speed * theGameTime.ElapsedGameTime.Milliseconds; Position.X += (float)(Math.Sin(Direction)) * Speed * theGameTime.ElapsedGameTime.Milliseconds; [/CODE] That way it always adds a little bit to your position, even though as I already said, use Milliseconds instead of Seconds, since the value would be something like 0.001 then.
[QUOTE=s0ul0r;20112074]You are always setting the position to the same value. ElapsedGameTime returns the time elapsed since the last update, it should always be the same in your case. (Like a few milliseconds) You have to, as it was already said here, change the code to: [CODE] Position.Y += (float)(Math.Cos(Direction)) * Speed * theGameTime.ElapsedGameTime.Seconds; Position.X += (float)(Math.Sin(Direction)) * Speed * theGameTime.ElapsedGameTime.Seconds; [/CODE] That way it always adds a little bit to your position, even though as I already said, use Milliseconds instead of Seconds, since the value would be something like 0.001 then.[/QUOTE] This man is right. Took you guys long enough to spot that. Mattz333 already gave the right answer, Loli just overlooked it.
Thanks guys. got it working...
Sorry, you need to Log In to post a reply to this thread.