3
\$\begingroup\$

Sorry if this has been asked before, but I can't seem to find it here. I'm trying to make an asteroids clone in XNA. I took the Game State Management project and am making new classes for things like the player and placing them in the GameplayScreen class. For some reason my ship isn't being draw correctly.

GameplayScreen's Draw method:

 public override void Draw(GameTime gameTime)
    {
        ScreenManager.GraphicsDevice.Clear(ClearOptions.Target,
                                           Color.CornflowerBlue, 0, 0);

        SpriteBatch spriteBatch = ScreenManager.SpriteBatch;

        spriteBatch.Begin();
        //draw fps
        if(showFPS)
            spriteBatch.DrawString(framerateFont, "FPS: " + frameRate, new Vector2(15, 15), Color.White);


        player.Draw(spriteBatch);

        spriteBatch.End();

        // If the game is transitioning on or off, fade it out to black.
        if (TransitionPosition > 0 || pauseAlpha > 0)
        {
            float alpha = MathHelper.Lerp(1f - TransitionAlpha, 1f, pauseAlpha / 2);

            ScreenManager.FadeBackBufferToBlack(alpha);
        }
    }

And my ship's drawing code:

 public PlayerShip(Game game)
    {
        this.game = game;
        Viewport view = game.GraphicsDevice.Viewport;
        center = new Vector2(view.Width / 2, view.Height /2);
        sourceRectangle = new Rectangle();
        Reset(center);
    }

    public void Reset(Vector2 position)
    {
        this.position = position;
    }

    public void LoadContent()
    {
        ship = game.Content.Load<Texture2D>("ship");
        sourceRectangle = new Rectangle(0, 0, ship.Width,
            ship.Height);
        origin = new Vector2(ship.Width / 2, ship.Height);
    }

    public void Update(GameTime gameTime)
    {
        HandleInput();

    }

    //handles all keyboard input by user. rotates ship based on current rotation.
    private void HandleInput()
    {
        input = Keyboard.GetState();
        float x = position.X;
        float y = position.Y;
        Matrix m = Matrix.CreateRotationZ(rotation);

        if (input.IsKeyDown(Keys.Right))
            rotation += turnFactor;
        else if (input.IsKeyDown(Keys.Left))
            rotation -= turnFactor;
        else if (input.IsKeyDown(Keys.Up))
        {
            x += m.M12 * directionFactor;
            y -= m.M11 * directionFactor;
        }
        else if (input.IsKeyDown(Keys.Down))
        {
            x -= m.M12 * directionFactor;
            y += m.M11 * directionFactor;
        }
        position.X = x;
        position.Y = y;
        Console.WriteLine("Y: {0} ", y);
        Console.WriteLine("X: {0} ", x);
    }

    public void Draw(SpriteBatch sb)
    {
        Vector2 origin = new Vector2(ship.Width / 2, ship.Height);
        sb.Draw(ship, ship.Bounds, null, Color.White, rotation, origin, SpriteEffects.None, 0f);
    }

I hooked the project up to a console window and it seems that the X and Y positions are updating correctly code wise, but not visually. It seems to update where it is rotationally, but going up or down doesn't draw correctly.

Image of what it's doing http://imgur.com/4cKBk

\$\endgroup\$
2
  • \$\begingroup\$ Is it not drawing at all? Or is it drawing, but distorted or in a wrong place? A screenshot of the problem would help. \$\endgroup\$ Feb 28, 2012 at 23:12
  • \$\begingroup\$ @LuisEstrada I edited my post to include a picture and some more code. It's only rotating around the top left corner on the screen, but the X and Y positions are being updated on the console. \$\endgroup\$
    – mooles
    Feb 28, 2012 at 23:21

1 Answer 1

2
\$\begingroup\$

The problem is that when you're using the following version of SpriteBatch.Draw:

public void Draw (
     Texture2D texture,
     Rectangle destinationRectangle,         // Destination rectangle on _screen_
     Nullable<Rectangle> sourceRectangle,
     Color color,
     float rotation,
     Vector2 origin,
     SpriteEffects effects,
     float layerDepth
)

And calling it with the following parameters:

// Wrong version
sb.Draw(ship, ship.Bounds, null, Color.White, rotation, origin, SpriteEffects.None, 0f);

The second parameter is expecting the destinationRectangle where the sprite should be drawn on screen but you're passing it the sprite's ship.Bounds which is simply a Rectangle like (0, 0, ship.Width, ship.Height). That's why the sprite is always stuck to the corner of the screen.

This is a simple fix. Just change that line to:

// Correct version
sb.Draw(ship, position, null, Color.White, rotation, origin, 1f, SpriteEffects.None, 0f);

And if everything else is correct, it should work. That's just another version of SpriteBatch.Draw that goes like this:

public void Draw (
     Texture2D texture,
     Vector2 position,
     Nullable<Rectangle> sourceRectangle,
     Color color,
     float rotation,
     Vector2 origin,
     float scale,
     SpriteEffects effects,
     float layerDepth
)
\$\endgroup\$
5
  • \$\begingroup\$ facepalm I uploaded the wrong set of code, that was me testing around with SpriteBatches. I updating the code in the original post with the code that works the most, all of my other tries have made the sprite invisible on the screen. \$\endgroup\$
    – mooles
    Feb 28, 2012 at 23:24
  • \$\begingroup\$ @mooles Oh okay, I thought it was strange. I see what the problem is on your new code, I'll update my answer. \$\endgroup\$ Feb 28, 2012 at 23:24
  • \$\begingroup\$ @mooles Okay, updated. (edited over the previous comment completely). \$\endgroup\$ Feb 28, 2012 at 23:30
  • \$\begingroup\$ Ugh, I probably could've figured that out. I was looking over some code from another game and it was using null for the sourceRectangle parameter, so I figured it wasn't important. \$\endgroup\$
    – mooles
    Feb 28, 2012 at 23:43
  • \$\begingroup\$ @mooles Some clarification. Using null for sourceRectangle is normal. It just means "draw the entire texture". The problem was your misuse of the destinationRectangle parameter, which is basically a way to mix a position and a non-uniform scale into a single value, meaning that you can use it to set the position of your sprite and specify its size at the same time. When you don't need to control the sprite's size explicitly, it's easier to just use the position and scale parameters instead. \$\endgroup\$ Feb 29, 2012 at 0:16

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .