Sign in to follow this  
RoyP

Need help getting a child object to orbit a parent object ...

Recommended Posts

I'm trying to figure out how to make a child object orbit around a parent object.  In my situation, I'm trying to create a parent ship that rotates waypoints with it when it rotates.  A smaller child ship will park itself in a waypoint to maintain it's position within the fleet.  

 

Here are a couple of images showing what I'm going for:

 

io0tbm.png 33kd3s6.png 

 

The child ship must keep it's position relative to the parent ship so it maintains it's position within the fleet.

 

i've tried learning enough about matrices to do it, but I'm screwing something up.  I've got my child ship orbiting the origin point of the screen instead of the parent ship.

 

Here's the code I'm using when I press a key:

parentShipRotationRadians += MathHelper.ToRadians(15);
childShipRotationRadians += MathHelper.ToRadians(15);
                    
Matrix.CreateRotationZ(parentShipRotationRadians, out childShipRotationMatrix);

childShipPositionPoint = Vector2.Transform(childShipPositionPoint, childShipRotationMatrix);

 

 

How do I rotate the child ship's center point around the parent ship's center point with matrices?  

 

Please break it down for me and help me understand what you're doing.  I've tried researching it and I just can't find the info.

 

Roy

Share this post


Link to post
Share on other sites

This looks like a conceptual glitch.

The worldview for your parentship should not be the same as for your child ship, for what you're trying to achieve.

Remember that your childship has a worldview dependency on the way parentship gets projected.

In short, the worldview matrix of childship keeps changing according to parentship view matrix.

Share this post


Link to post
Share on other sites

I'm not doing anything with a matrix for the parent ship.  I'm just assigning it's rotation a value in the Update method and using that value to change the angle the texture is rendered at in the Draw method.  The parent ship's texture is just rotating at the center point of the screen.

 

Roy

Share this post


Link to post
Share on other sites

[quote name='RoyP' timestamp='1357140875' post='5016709']
I'm not doing anything with a matrix for the parent ship.
[/quote]

 

That's why I am saying that you need to do something about it, to achieve what you're looking for. In mathematical terms, what you need to implement is something like Lorentz Transformation.

Share this post


Link to post
Share on other sites

So how would I go about doing that?  This is my first adventure with matrices, so I need some help understanding what I'm supposed to do and why.

 

Roy

Share this post


Link to post
Share on other sites

Ok, I understand what you're saying conceptually.  How do I actually implement that in XNA?  Can you break it down step-by-step for me?  It would really help me learn it since this is my first time doing anything like this.

 

Roy

Share this post


Link to post
Share on other sites

Here's the class code from my Game1.cs file.  The only thing I left out was the using statements and the namespace.

 

public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        float inputDelay;
        float maxInputDelay = 0.2f;

        Texture2D shipTexture;
        Vector2 shipTextureOriginPoint;
        
        Texture2D dotTexture;
        Vector2 dotTextureOriginPoint;

        Vector2 dotPositionPoint;

        Vector2 parentShipPositionPoint;
        float parentShipRotationRadians;
        
        Vector2 childShipPositionPoint;
        float childShipRotationRadians;
        Matrix childShipMatrix;
        Matrix childShipRotationMatrix;        
        
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }
 
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            graphics.PreferredBackBufferWidth = 1280;
            graphics.PreferredBackBufferHeight = 720;
            IsMouseVisible = true;

            base.Initialize();
        }
        
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: use this.Content to load your game content here
            shipTexture = Content.Load<Texture2D>(@"textures\ship_with_outline");
            dotTexture = Content.Load<Texture2D>(@"textures\dot");

            shipTextureOriginPoint = new Vector2(shipTexture.Width / 2, shipTexture.Height / 2);
            dotTextureOriginPoint = new Vector2(dotTexture.Width / 2, dotTexture.Height / 2);

            dotPositionPoint = new Vector2(GraphicsDevice.Viewport.Width / 2, 
                                           GraphicsDevice.Viewport.Height / 2);

            parentShipPositionPoint = new Vector2(GraphicsDevice.Viewport.Width / 2,                      
                                                  GraphicsDevice.Viewport.Height / 2);
            parentShipRotationRadians = 0;

            childShipPositionPoint = new Vector2(parentShipPositionPoint.X - 47, 
                                                 parentShipPositionPoint.Y - 47);
            childShipRotationRadians = 0;

            childShipMatrix = new Matrix();
            childShipMatrix.Translation = new Vector3(childShipPositionPoint.X, 
                                                      childShipPositionPoint.Y, 
                                                      0);

            childShipRotationMatrix = new Matrix();            
        }
                
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }
                
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            // TODO: Add your update logic here
            if (inputDelay > 0)
                inputDelay -= (float)gameTime.ElapsedGameTime.TotalSeconds;

            if (inputDelay < 0)
                inputDelay = 0;

            if (inputDelay == 0)
            {
                if (Keyboard.GetState().IsKeyDown(Keys.Right))
                {
                    parentShipRotationRadians += MathHelper.ToRadians(15);
                    childShipRotationRadians += MathHelper.ToRadians(15);
                                                            
                    Matrix.CreateRotationZ(parentShipRotationRadians, out childShipRotationMatrix);

                    childShipPositionPoint = Vector2.Transform(childShipPositionPoint, 
                                                               childShipRotationMatrix);
                                        
                    inputDelay = maxInputDelay;
                }       
            }

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

            // TODO: Add your drawing code here
            spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend);

            spriteBatch.Draw(dotTexture, 
                             dotPositionPoint, 
                             null, 
                             Color.Yellow, 
                             0, 
                             dotTextureOriginPoint, 
                             0.6f, 
                             SpriteEffects.None, 
                             0.001f);

            spriteBatch.Draw(shipTexture, 
                             parentShipPositionPoint, 
                             null, 
                             Color.BlueViolet, 
                             parentShipRotationRadians, 
                             shipTextureOriginPoint, 
                             2.0f, 
                             SpriteEffects.None, 
                             0.301f);

            spriteBatch.Draw(shipTexture, 
                             childShipPositionPoint, 
                             null, 
                             Color.Orange, 
                             childShipRotationRadians, 
                             shipTextureOriginPoint, 
                             1.0f, 
                             SpriteEffects.None, 
                             0.300f);

            spriteBatch.End();

            base.Draw(gameTime);
        }
    }

 

I basically want to rotate the parent ship by 15 degrees when I press the right key and have the child ship stay in the correct formation to it.  I also want to rotate the parent ship by -15 degrees when I press the left key and have the child ship stay in the correct formation to it.

 

This is just a really simple sandbox I'm using to learn how to implement this.

 

Roy

Share this post


Link to post
Share on other sites

Try changing shipTextureOriginPoint to dotTextureOriginPoint in below code and let me know what you see is as per your requirement or no. Snapshot would be nice.

 

spriteBatch.Draw(shipTexture, 
                             childShipPositionPoint, 
                             null, 
                             Color.Orange, 
                             childShipRotationRadians, 
                             shipTextureOriginPoint, // Change this one
                             1.0f, 
                             SpriteEffects.None, 
                             0.300f);

Share this post


Link to post
Share on other sites

That's not going to do anything.  Those are just the center points on the actual textures themselves so I can rotate the texture around the texture's center point instead of the top left corner.  They have nothing to do with world space.  The coordinates that deal with the ship positions in world space are childShipPositionPoint and parentShipPositionPoint.

 

Roy 

Share this post


Link to post
Share on other sites

[quote]Or, I think your can comment out this line of code and try once :

 

childShipRotationRadians += MathHelper.ToRadians(15);[/quote]

 

That just rotates the texture itself, so commenting it out just keeps the child ship pointing straight up.  It doesn't affect it's position in world space, so the child ship is still rotating around the 0,0 world origin.

 

Roy

Share this post


Link to post
Share on other sites

Sorry bud, can't help out much unless I can figure out the exact outcome you desire.

You're telling me that this code will do this and that code will do that, where I am expecting that this is what you're looking for.

Well, I tried my best and gave you the exact concepts to solve the problem.

ow you might have to do some digging on your own and build up on the solution yourself.

Goodluck!

Share this post


Link to post
Share on other sites

Let me try explaining exactly what I'm trying to do.  I might not be making it as clear as I thought.

 

Here's an image showing what I'm trying to do:

 

33ngf2t.jpg

 

The purple ship is the parent ship.  The orange ship is the child ship.

 

1 - I'm starting with a parent ship at (640, 320) in world space (center of the view port).  I set the child ship's position with an offset of (-47, -47) from the parent ship's position.  Both ships start with a rotation of 0 degrees (I convert all the degrees to radians with the MathHelper.ToRadians method).  The only thing I do with the rotation amount is to use it for the SpriteBatch.Draw call in the game's Draw method and use it to pass the rotation value to the Matrix.CreateRotationZ method.

 

2 - When I hit the right arrow, I want to rotate the parent ship 15 degrees clockwise and compute the new center point for the child ship in relation to the parent ship.  The goal is to have the child ship rotate with the parent ship while maintaining it's position within the fleet.  (My eventual goal is to turn the concept into a waypoint system so I can park different child ships at the waypoints.)

 

3 to 7 -  I need to repeat step 2 over and over again, so that the child ship keeps orbiting the parent ship while maintaining it's fleet formation.  I want it to orbit in a complete circle.

 

When I press the left arrow key, I want to do the same thing, but in the counter clockwise direction.

 

Does that make it any clearer?

 

I know that I need to use matrix transformations to do it, but I need help understanding how to actually do the matrix transformations.  I've never done it before and I need someone to walk me through it step-by-step so that I can learn what I'm doing.

 

I have a basic understanding of matrix and vector math, but I'm having trouble applying the abstract concepts to a concrete implementation in XNA.

 

Roy

Edited by RoyP

Share this post


Link to post
Share on other sites

What you have to do is transform the difference vector between parent and child, not the child position itself.

Rotations matrices always rotate about the origin, so the easiest thing is to (temporarily) change your coordinate system so the parent ship's position is the origin:

 

 

Vector2 d = childShipPositionPoint - parentShipPositionPoint;
d = Vector2.Transform(d, Matrix.CreateRotationZ(15));
childShipPositionPoint = parentShipPositionPoint + d;

 

Let me know if this is what you are looking for.

Share this post


Link to post
Share on other sites

It might be just me, but even now, the snapshot that you have provided and your problem statement seem to be complementing each other.

In simple words, I think you're trying to achieve what you already have in this snapshot.

Perhaps, an altered snapshot with expected behaviour might help.

Share this post


Link to post
Share on other sites
It might be just me, but even now, the snapshot that you have provided and your problem statement seem to be complementing each other.

In simple words, I think you're trying to achieve what you already have in this snapshot.

Perhaps, an altered snapshot with expected behaviour might help.

 

The snapshot shows the expected behaviour. He wrote that the parent ship rotates about the origin instead.

Share this post


Link to post
Share on other sites

@FromShadow ... you are a genius. :-)  It does exactly what I needed.  Thanks for explaining it to me and providing the code to do it. 

 

@NewDisplayName ... thanks for trying to help.  I appreciate it.

 

Roy

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this