# Cannon barrel recoil?

**6**Member

Hello, I have programmed a turret cannon node that will rotate and has rotation limits. I am trying to add a recoil function so it will the barrel will recoil along its axis and then return. It is simply two nodes the barrel and the base that are siblings in a cannon container node(area2d's with a sprite).

I have a function that will recoil and return the barrel but when the barrel is rotated it just moves the barrel up and down.

func recoil(delta_time):

if is_recoiling == false:

$cannon_barrel.translate(Vector2(0,RECOIL_SPEED * delta_time))

if $cannon_barrel.get_position().y > MAX_RECOIL:

is_recoiling = true

elif is_recoiling == true:

$cannon_barrel.translate(Vector2(0,-RECOIL_SPEED * delta_time))

if $cannon_barrel.get_position().y < RETURN_POSITION:

is_recoiling = false

I call this in the process function. I can see the problem is just moving the y coordinate relative to the parent down and up. What function will move the y back along its own axis?

Tags :

## Answers

6Memberalso I tried adding gdscript tags with but it didn't work

982AdminYou need to use

`Vector2(cos(rotation), sin(rotation))`

to convert your rotation into a position around a unit circle, and then use that position to move your cannon.The code would look something like this:

Keep in mind you are going to need to use something other than checking the y position to move the cannon back and forth. I would suggest using a timer (whether it be the node or just a variable) to track when to move the cannon to and from the desired positions.

Regardless, using you need to use sin and cos to convert the rotation into a vector, and then use that vector to move the cannon. You may need to swap

`cos`

and`sin`

to get the proper results, as I can never remember which goes where and so they’ll likely need to be swapped.(Ironically I’ve bee working so much with 3D rotation and relative vectors, that I’ve had to rewrite this like four times because I keep writing it like it’s for 3D )

6MemberI must admit this got deep fast. The x and y coordinates of the cannon barrel are presumably in the center of the area2d which is a box. We get the rotation and then find the unit vector on the unit circle and move it back(theoretically). I have tried using the code with both the cosine and sine swapped and it never moves it back along the axis. I don't exactly understand what translate does, it seemed to make sense when I was using it.

6Memberthanks for the help.

982AdminYour welcome! I'll try to answer the new questions:

(Let me know if something doesn't make sense, and I'll try to explain in more detail and/or better )

To move backwards you just need to multiply the above vector by negative one, then it should move backwards. So to move backwards using the above code, you need something like this:

`$cannon_barrel.translate(unit_circle_pos * RECOIL_SPEED * delta_time * -1)`

(That's assuming I remember correctly. It's been awhile since I've worked in 2D.)

Translate moves a node by the inputted amount (relative to the node's position). If you are at position

`X:4 Y:4`

and call`translate(Vector2(-1, 2))`

then you'll get a position of`X:3 Y:6`

. Translate is primiarlly used to move nodes around without having to do a more messy bit of code to get the same result (otherwise you'd have to do`node.position = node.position + translate_vector`

instead of`node.translate(translate_vector)`

).Maybe this page from the docs will help? It's a little long and can be overwhelming, but it explains how the coordinate system works in Godot (you can skip the 3D stuff if you want)

Also, I was just looking at this topic on the forums where I helped someone with a similar problem. There he is using velocity and then adding the velocity to his position instead of using

`translate`

. You may want to try using`$cannon_barrel.position += (unit_circle_pos * RECOIL_SPEED * delta_time)`

or`$cannon_barrel.global_translate(unit_circle_pos * RECOIL_SPEED * delta_time * -1)`

instead and see if one of those work better, because then it will be moving in global space as opposed to local space.1,048AdminDon't forget to select TwistedTwigleg's reply as an answer.

6MemberHello, TwistedTwigleg, I am sure there is more to do but it is a lot closer. I used input keys (instead of a recoil function)

to test it and what I had to do is rotate the "unit_circle_vector" by 90 degrees (A trick I learned from a youtube tutorial) and now

when I press the up key and down key it will indeed slide up and down it axis.

The only problem I have now is I can fly it off its base even though it is doing it from the local coordinates of the parent node.

982AdminI'm glad you got it at least somewhat working! (I totally forgot about rotating the unit circle by 90 degrees so that it starts with a position pointing upwards )

The reason it's moving beyond the base is because you do not have an

`if`

check (at least in the code above). There are many ways to go about this, and honestly I'm not sure what the 'best' solution is. Here's what I would do if I needed to solve this problem:(NOTE: The reason there is "-|" before every line is that I'm trying to format the post a little so it's easier to read)

-| I would store the initial position of the Cannon in a variable called something like

`initial_pos`

. That way you can find out-| how far the cannon barrel is from it's starting position. We'll use this position as the farthest position we can pull the cannon

-| back to. You'll need to declare the variable outside of

`_ready`

, and put something like-|

`initial_pos = $cannon_barrel.position`

in your`_ready`

function-|

-| Next I would then make a constant for how far you want to be able to move the cannon barrel away from that initial

-| position. Something like

`const MAX_FORWARD_DISTANCE = 2`

for example-|

-| Then before you move the barrel, you just need to do a check like this:

This should (in theory) stop the cannon barrel from moving farther than

`MAX_FORWARD_DISTANCE`

distance away from the starting position. I have not tested the code though, so it may not work. Let me know if it doesn't and I'll make an example project so I can test my solutions before posting them.6MemberHello, yes that worked with the distance_to() function. distance_squared_to() seemed to give a small distance.

Phew more programming than I expected. I think the ultimate solution is to move the children nodes(sprite and collision shape) of the barrel area2d

so they will be comparing to a stable point on the whole structure and moving in a straight line.

982AdminWhoops! Sorry about that. I couldn't remember which of the two would give the desired result. Looking on it now it makes sense that

`distance_to`

is the correct choiceEven the most simple things generally have a fair amount of code behind them. Thankfully it gets programming gets easier the more you do it (at least for the simpler stuff).

Moving the children nodes should work. I'm glad you have found a solution