2
\$\begingroup\$

I have a projecile(Hook) and the tail of the projectile(yellow balls)

TailProjectile class draws a ball at the exact position of the projectile(hook) and let it there until the projectile ends

I'd like to draw the ball at the start of the hook(red circle) because by now it draws at the projectile image position(blue point)

How can I do it independent of the rotation of the hook?

enter image description here

This is how I calculate the rotation of the projectile

distanceY = endPosition.Y - initialPosition.Y;
        distanceX = endPosition.X - initialPosition.X;

        if (distanceX < 0)
            animation.SprtEffects = SpriteEffects.FlipVertically;
        animation.Rotation = (float)Math.Atan2(distanceY, distanceX);

Then I pass the projectile to the tail and draw the ball

        if (hasTail)
            tail.Update(gameTime,  position , animation.Rotation,animation.SprtEffects);

And at the TailProjectile update class :

  public void Update(GameTime gameTime,Vector2 p,float rotation,SpriteEffects sprtEffect)
    {
        if (Vector2.Distance(animations[animations.Count - 1].Position, p) > distanceBetween)
        {
            Animation tempAnimation = new Animation();
            tempAnimation.LoadContent(content, image, "", p);
            tempAnimation.Rotation = rotation;
            tempAnimation.SprtEffects = sprtEffect;
            tempAnimation.DrawColor = color;
            animations.Add(tempAnimation);
        }

And the Animation Draw:

spriteBatch.Draw(image, position + origin, sourcRect, drawColor * alpha, rotation, origin, scale, sprtEffects, 0.0f);

Edit: Using rotation matrix solve half of the problem :

enter image description here

My problem now is how can I calculate it for angles higher than 90º ? (third picture of the image)

 double xO, yO;
        xO = originpoint.X * Math.Cos(rotation) - originpoint.Y * Math.Sin(rotation);
        yO = originpoint.X * Math.Sin(rotation) + originpoint.Y * Math.Cos(rotation);
        initialAnimation.Position = new Vector2((float)xO + initialAnimation.Position.X, (float)yO + initialAnimation.Position.Y);
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

I think you might be overcomplicating things - why not just set the "origin" of the hook to

new Vector2(0, hookTexture.Height / 2)

If you simply draw it like this:

spriteBatch.Draw(hookTexture, position, null, Color.White, rotation, new Vector2(0, hookTexture.Height / 2), 1.0f, SpriteEffects.None, 0.0f);

That way the hook is drawn and rotated around where it would connect to the balls.

Hope this helps! If I misunderstood anything, please comment. Thanks! :)

Edit: Here's some sample code for a small demo of what I mean:

(just copy-paste it into a new c# xna project, import your hook and ball images, and run the program)

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;

namespace demoforgamedev
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        MouseState M = new MouseState();

        Vector2 TailStartSpot;
        Vector2 HookPosition;
        Texture2D hookTexture;
        Texture2D ballTexture;

        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }
        protected override void Initialize()
        {
            base.Initialize();
        }
        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);

            hookTexture = Content.Load<Texture2D>("hook");
            ballTexture = Content.Load<Texture2D>("ball");
        }
        protected override void UnloadContent()
        {

        }
        protected override void Update(GameTime gameTime)
        {
            M = Mouse.GetState();
            TailStartSpot.X = graphics.GraphicsDevice.Viewport.Width / 2; // The tail of the projectile will start at the center
            TailStartSpot.Y = graphics.GraphicsDevice.Viewport.Height / 2; // of the screen, just for demonstration purposes.

            HookPosition = new Vector2(M.X, M.Y); // The projectile will be drawn at the mouse position, just for demonstration purposes.

            base.Update(gameTime);
        }
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.White);

            DrawProjectile(spriteBatch, true, TailStartSpot, HookPosition);

            base.Draw(gameTime);
        }
        public void DrawProjectile(SpriteBatch spritebatch, bool hasTail, Vector2 point1, Vector2 point2)
        {
            // Given a start point and an end point, draw a projectile (possibly) with a trail.

            float rotation = (float)Math.Atan2(point2.X - point1.X, -point2.Y + point1.Y) - (float)(Math.PI / 2); // Find the rotation

            spritebatch.Begin();

            Vector2 plusequals = (point2 - point1) / 9;
            spriteBatch.Draw(hookTexture, HookPosition, null, Color.White, rotation, new Vector2(0, hookTexture.Height / 2), 1.0f, SpriteEffects.None, 0.0f);
            for (int i = 0; i < 10; i++)
            {
                spritebatch.Draw(ballTexture, new Rectangle((int)point1.X, (int)point1.Y, (int)ballTexture.Width, (int)ballTexture.Height), Color.White);
                point1 += plusequals;
            }

            spritebatch.End();
        }
    }
}
\$\endgroup\$
9
  • \$\begingroup\$ If I understood, the tail should be draw at the hook's origin.I think it doesn't works because spriteBatch will rotate and the origin of the hook will be outdated to the tail \$\endgroup\$ Commented Jul 1, 2015 at 16:38
  • \$\begingroup\$ Not quite. By the pictures you've provided it looks like you're trying to align the balls to the hook, rather than trying to align the hook to the balls. Currently it looks like you're drawing the hook with an origin of (0, 0), which is the top left corner. I'm suggesting you change that origin to (0, hookTexture.Height / 2) to align the hook to the balls. Changing the origin of the texture will change the point it rotates around and where it is drawn. \$\endgroup\$
    – Superdoggy
    Commented Jul 1, 2015 at 17:17
  • \$\begingroup\$ Actually the origin of the hook is its center( origin = new Vector2(sourcRect.Width / 2, sourcRect.Height / 2); spriteBatch.Draw(image, position + origin, sourcRect, drawColor * alpha, rotation, origin, scale, sprtEffects, 0.0f);) sorry I should have post this code before \$\endgroup\$ Commented Jul 1, 2015 at 17:22
  • \$\begingroup\$ Hmm... I'm not sure you're understanding. One sec and I'll whip up a working code demo to explain what I mean. :P \$\endgroup\$
    – Superdoggy
    Commented Jul 1, 2015 at 17:31
  • \$\begingroup\$ Oh, sorry.Think I catch it now. It makes sense, if I make it rotate from the point the balls should connect it'll works properly, thanks a lot and sorry for being so slow \$\endgroup\$ Commented Jul 1, 2015 at 17:54

You must log in to answer this question.

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