0
\$\begingroup\$

I want my arrow to chase the minion that I just rightclicked on. I have a Minion Class and an Arrow Class. These are the constructors:

    /// <summary>
    ///  Constructs a minion
    /// </summary>
   public Minion(Texture2D sprite, int x, int y, int windowWidth, int windowHeight, bool isFriendly, int minionHealth)

    /// <summary>
    /// Constructor of the bullet from champion to minion
    /// </summary>
   public Arrow(Texture2D sprite, Vector2 sourceEntity, Vector2 targetEntity, float arrowSpeed, int arrowAttackSpeed, int damageDone, bool isArrowActive)

In the Game1 I have the standard if-click structure and I check if the click is on the minions. But I check this with

    foreach (Minion minion in enemyMinions)

So - I want to mark somehow the minion I clicked on and then to send the arrow directly to its moving location.

How to do that?

Update:

        //checks if rightmouse button was clicked to activate the arrow
        if (mouse.RightButton == ButtonState.Released && previousButtonState == ButtonState.Pressed)
        {
            //checks if the right mouse click was on a minion and the minion is in champion's range
            for (int i = 0; i < enemyMinions.Count; i++)
            {
                if (enemyMinions[i].CollisionRectangle.Contains(mouse.X, mouse.Y) 
                    && (Math.Abs(mouse.X - enemyMinions[i].X) < vayne.ChampionRange) ||
                    Math.Abs(mouse.Y - enemyMinions[i].Y) < vayne.ChampionRange)
                {
                    //mark the minion that the click was made on
                    theCurrentTarget = enemyMinions[i];

                    //sets the arrow.targetEntity to that particular minion
                    arrow.TargetX = theCurrentTarget.X;
                    arrow.TargetY = theCurrentTarget.Y;

                    arrow.IsArrowActive = true;
                }
            }
        }
        previousButtonState = mouse.RightButton;
\$\endgroup\$
  • \$\begingroup\$ You mean you want to visually represent the clicked minion? Like a selected unit indicator? \$\endgroup\$ – MichaelHouse Feb 19 '14 at 21:55
  • \$\begingroup\$ Well untill now I only succeeded in sending the arrow to the mouse location after a click. But I want to send it to a moving target. And its one moving target from several moving targets. So I want to mark the minion I clicked on. So then I can extract the minion.X and minion.Y of one entity - the target. The foreach structure does everything for all of the minions in the list. Cant use it. \$\endgroup\$ – I.Hristov Feb 19 '14 at 22:01
  • \$\begingroup\$ @I.Hristov I think I know what you mean. What you would want to do, is create a variable that is of the same type as your entities. Then, whenever the entity is clicked, set that variable (reference) to the clicked entity. \$\endgroup\$ – Lysol Feb 19 '14 at 22:04
  • 1
    \$\begingroup\$ OK... Remember to use tags wisely. Your original question just had "textures" as a tag. That makes things pretty confusing. To answer your question, instead of passing a Vector2 for the targetEntity pass a reference to the entity, then you can just get the position at any time straight from the entity. \$\endgroup\$ – MichaelHouse Feb 19 '14 at 22:13
  • \$\begingroup\$ Important question: Do you want a "homing arrow" that will follow them anywhere (not necessarily a straight line), or do you want to do a simple prediction of where they are going and target the arrow at those co-ordinates (a straight line)? \$\endgroup\$ – David Cummins Feb 21 '14 at 1:54
1
\$\begingroup\$

From what I have understood from your original post and the other clarifications, I think you want to create an Arrow at the position of sourceEntity and make it move with constant arrowSpeed towards the position of targetEntity until it reaches it, position which may have changed from the creation of the Arrow. Correct me if I am wrong.

I see that you are using a float for the Speed of your arrow, instead of a vector. You can use a 2D vector equal to the difference between the target position and the current arrow position, calculate it's magnitude(or length), and then add to Arrow.currentPosition a fraction of v vector equal to arrowSpeed / length :

Vector2 v = targetEntity.currentPosition - Arrow.currentPosition;

float length = sqrt( v.x*v.x + v.y*v.y );

Arrow.currentPosition += ( v * ( arrowSpeed / length ) );

When updating the Arrow's current position, you may want to have the targetEntity passed by reference, so you will have access to the targetEntity's current position. If you don't pass it by reference, the targetEntity's position will always remain the same and your Arrow will stop at targetEntity's original position.

The Arrow will eventually end the chase and hit targetEntity.

EDIT:

For the code you are using, Arrow.TargetX and Arrow.TargetY need to be pointers, instead of floats. Then, you do it like this:

//mark the minion that the click was made on
theCurrentTarget = &enemyMinions[i];

//sets the arrow.targetEntity to that particular minion
arrow.TargetX = &theCurrentTarget->X;
arrow.TargetY = &theCurrentTarget->Y;

Notice that theCurrentTarget also needs to be a pointer.

You will need to make some changes in how you create an arrow, using the constructor:

Say you have 2 objects of class Minion: Entity1 and Entity2. Entity1 is the source of the arrow and always stays in the same spot. Entity2 is the target of the arrow and it is moving.

public Arrow(Texture2D sprite, Vector2 sourceEntity, Vector2 targetEntity, float arrowSpeed, int arrowAttackSpeed, int damageDone, bool isArrowActive)

Say you create an Arrow object, like this: Arrow chasingArrow( some_sprite, Entity1.position, Entity2.position, ...(the rest of the arguments are irrelevant) )

When you call this constructor, the object of class Arrow that you create will save the value of the targetEntity vector as it is now and that value (which is inside the Arrow object) will never change, even if the value of the vector inside the Entity2 object will change. You need to link the vector in Entity2 with the targetEntity vector in chasingArrow. You do that by not copying the value, but by copying the pointer. That way, the targetEntity pointer in chasingArrow will always point to the current position of Entity2.

Change the constructor like this:

public Arrow(Texture2D sprite, Vector2 sourceEntity, Vector2* targetEntity, float arrowSpeed, int arrowAttackSpeed, int damageDone, bool isArrowActive)

Notice the only modification: Vector2* targetEntity. Now it will take a pointer to a vector as a parameter instead of a vector.

And when you create an Arrow object, do it like this:

Arrow chasingArrow( some_sprite, Entity1.position, &Entity2.position, ...(the rest of the arguments are irrelevant) )

You can also pass Entity1.position by reference, but it works as it is now, since the sourceEntity only matters at the moment the Arrow is created.

If you have any other questions, just ask.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ OK now the most stupid question of all follows - how to pass it by refference? :-) I updated the question with the code I use atm. \$\endgroup\$ – I.Hristov Feb 22 '14 at 20:02
  • \$\begingroup\$ OK I understand the concept now. But I am missing some basic knowledge probably as the compiler now is shouting smth for using pointers in unsafe context. Do I need to change the code in the Properties section of the Arrow clas that is currently: ' /// <summary> /// Sets the X position of the target entity for the arrow to go to /// </summary> public int TargetX { set { targetEntity.X = value; } } /// <summary> /// Sets the Y position of the target entity for the arrow to go to /// </summary> public int TargetY { set { targetEntity.Y = value; } }' \$\endgroup\$ – I.Hristov Feb 23 '14 at 9:29
  • \$\begingroup\$ Hmm... you're saying you've got errors? Post them here so I can have a look. \$\endgroup\$ – Lighthink Feb 23 '14 at 9:31
  • \$\begingroup\$ "Type expected" error at "&" here: //create arrow(bullet) within the Champion arrow = new Arrow(Content.Load<Texture2D>("bullet"), new Vector2((int)(vayne.X), (int)(vayne.Y)), new &Vector2((int)(vayne.X), (int)(vayne.Y)), 20, 10, 50, false); \$\endgroup\$ – I.Hristov Feb 23 '14 at 9:34
  • \$\begingroup\$ "Pointers and fixed size buffers may only be used in an unsafe context" error at * here: 'public Arrow(Texture2D sprite, Vector2 sourceEntity, Vector2* targetEntity, float arrowSpeed, int arrowAttackSpeed, int damageDone, bool isArrowActive) { this.sprite = sprite; this.arrowSpeed = arrowSpeed; this.arrowAttackSpeed = arrowAttackSpeed; this.damageDone = damageDone; this.isArrowActive = isArrowActive; this.sourceEntity = sourceEntity;' \$\endgroup\$ – I.Hristov Feb 23 '14 at 9:36
3
\$\begingroup\$

Assuming the target entity is moving (since you used the word 'chase'), you would have to pass the target entity's location into an update method for your arrow, and adjust the arrow's velocity based on the vector between it's and the target's location.

It's hard to be more specific considering we only know your constructors.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.