How can I convert floats to Vectors?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By OiKeTTLe

I’m trying to have the player move towards an object in the game, and am using this piece of code to do it:

motion.x = (self.position.x - $Chain/Tip.position.x).normalized() * speed * chain_velocity

However, when I try to run it, it gives me this error:

Invalid call. Nonexistent function 'normalized' in base 'float'.

Any idea why, or how I can fix it?

:bust_in_silhouette: Reply From: Yuminous

normalized() is a Vector math operation (only for complete vectors), but what it does is actually a very simple calculation: vector / vector.length(), so maybe try:

motion.x = (self.position.x - $Chain/Tip.position.x) / motion.length() * speed * chain_velocity

Also to answer the question title, converting Floats to Vectors is nice and straight-forward, you can simply go: var vector = Vector2(vector.x, vector.y)

So another way you might be able to solve your problem is to write:

motion = Vector2((self.position.x - $Chain/Tip.position.x) * speed * chain_velocity, motion.y).normalized()

Hope it helps!

Thanks for the answer, a lot more helpful than the people on Reddit. I tried the second solution and got this issue:

Invalid type in 'Vector2' constructor. Cannot convert argument 1 from Nil to float.

I’m assuming it doesn’t detect any movement in the x vector or something?

OiKeTTLe | 2021-07-15 04:54

My mistake, I included an extra bracket that shouldn’t be there, try this instead:
motion = Vector2((self.position.x - $Chain/Tip.position.x) * speed * chain_velocity, motion.y).normalized()

Out of curiosity, did the first solution work at all…?

Yuminous | 2021-07-15 05:08

Same issue it would seem: Invalid type in ‘Vector2’ constructor. Cannot convert argument 1 from Nil to float.

OiKeTTLe | 2021-07-15 05:14

Oh, hello again! Haha.

It seems the Vector doesn’t like taking self.property as a value. Declare all those values as variables immediately before the Vector assignment, like this:

var a = self.position.x - $Chain/Tip.position.x
motion = Vector2(a * speed * chain_velocity, motion.y).normalized()

Yuminous | 2021-07-15 05:21

You’ve got some great ideas and I really appreciate, but it still doesn’t seem to be working. Same error as always;

Invalid type in 'Vector2' constructor. Cannot convert argument 1 from Nil to float.

I think it has something to do with the x axis not having a value? Or something like that. I don’t see how, but it could be a possibility.

OiKeTTLe | 2021-07-15 05:42

TIme to start printing stuff.
Put all these in just before so that we know what the null value actually is:
print("self.position.x = " + str(self.position.x))
print("speed = " + str(speed))
print("chain_velocity = " + str(chain_velocity))
print("motion.y = motion.y + str(motion.y))

And what node is this particular script attached to? self refers to the node of which the script is attached to, so Control nodes don’t use position as a value, for example.

Yuminous | 2021-07-15 05:52

Here’s the output:
-73.738403 self position
300 speed
(0, 0) chain velocity
0 motion.y

The node this script is attached to is the player; $Chain is an instanced node set as a child of the player. $Chain/Tip is the physical part of the chain that moves, and is what I want to drag the player towards.

OiKeTTLe | 2021-07-15 05:58

Okay, so chain_velocity is actually a Vector2 and can’t be calculated as is with floats, which is what’s causing this particular problem.

I assume this chain can go all over the place (thus it’s necessary to have a vector)?

We can put an equation in to precombine the X and Y velocities if so

Yuminous | 2021-07-15 06:04

Fuuuuuck, I need it to stay as a Vector2. Thanks for the help again :confused: I’m not sure if this one can be solved. Thanks for the help so far, I’d be fine if you want to stop

OiKeTTLe | 2021-07-15 06:07

Don’t worry, we can calculate this!
This is a basic equation to combine the velocity vector, it does have a minor flaw but at least it will work!

(chain_velocity.x + chain_velocity.y) / 2

So, in the script:

var a = self.position.x - $Chain/Tip.position.x
motion = Vector2(a * speed * (chain_velocity.x + chain_velocity.y) / 2, motion.y).normalized()

Yuminous | 2021-07-15 06:15

Thanks! It managed to solve the error, but I’m still not getting any movement on the x axis… maybe my other movement commands are overriding it?

OiKeTTLe | 2021-07-15 06:21

Yes, because even though we’re calculating the vector, when the chain has no velocity:
(0, 0) chain velocity

It multiplies the whole movement equation by 0, and since 0 × anything = 0, you have no movement. One way you could solve this is by adding 1 to the chain velocity after the vector equation, which means that at 0 speed the movement is unchanged (since 1 × anything = anything). Like this:

(chain_velocity.x + chain_velocity.y) / 2 + 1

Yuminous | 2021-07-15 06:27

After putting that solution both before and after the equation, it still prints out (0, 0) chain velocity, even if the print command is placed after the equation.

OiKeTTLe | 2021-07-15 06:34

The chain_velocity itself isn’t changed. To see the change you have to put the equation inside the print command. Or put the equation in a variable:

var a = self.position.x - $Chain/Tip.position.x
var b = (chain_velocity.x + chain_velocity.y) / 2 + 1
motion = Vector2(a * speed * b, motion.y).normalized()
print("New chain velocity (multiplier): " + str(b))

Yuminous | 2021-07-15 06:40

Also one other thing OiKeTTLe, there seems to be a lot of tiny little issues in your project which are amounting to bigger problems that stump us all. It would be really useful if you could somehow upload your whole project somewhere for us to tinker with when you have a big question that need solving.

Like the AnimationPlayer issue, I want to try solving that but all the ideas I would have tried already don’t work, so I would have no idea where to start without more info.
And I also think that many more people would start opening up to solve your questions if they could simply download the whole project and see the issue in action for themselves.

You don’t have to because I’m sure you’re changing your project all the time, and your questions will probably still get answered eventually, but I just think that some people would jump to answer your questions with such files included (^◡^)

Yuminous | 2021-07-15 06:51

I’m dumb lol, sorry. It shows the change now. However, I’m still not getting any movement on the X axis. There’s probably something else I forgot to do.

OiKeTTLe | 2021-07-15 06:52

print to the rescue!
As a general rule, when something isn’t working with no obvious cause, print everything even tangentially related:

print("self.position.x = " + str(self.position.x))
print("speed = " + str(speed))
print("chain_velocity = " + str(chain_velocity))
print("motion.y = " + str(motion.y))
print("New chain velocity (multiplier) = " + str(b))
print("Vector X calculation = " + str(a * speed * b))
print("Vector2 = " + str(Vector2(a * speed * b, motion.y).normalized()))

Yuminous | 2021-07-15 06:59

Here are the results (chain velocity seems to still be at zero):

-73.738403 self position
300 speed
0 motion.y
New chain velocity (multiplier): 100
self.position.x = -73.738403
speed = 300
chain_velocity = (0, 0)
motion.y = 0
New chain velocity (multiplier) = 100
Vector X calculation = -4424304.199219
Vector2 = (-1, 0)

OiKeTTLe | 2021-07-15 07:08

Alright, back to the start.
Since we know what was going wrong the first time round, comment out the Vector2 and try this solution again:
motion.x = a.normalized() * speed * b

Yuminous | 2021-07-15 07:16

Tried plugging it in, received this: Invalid call. Nonexistent function ‘normalized’ in base ‘float’.

OiKeTTLe | 2021-07-15 07:19

Ahh, I’m mixing stuff up. Here, retry:

motion.x = a / motion.length() * speed * b

Yuminous | 2021-07-15 07:22

Error is gone, but still no movement on the x axis. Interesting to note, if there’s no movement on the x axis on my part, the game crashes.
Here are the results:

-123.738403 self position
300 speed
0 motion.y
New chain velocity (multiplier): 100
self.position.x = -123.738403
speed = 300
chain_velocity = (0, 0)
motion.y = 0
New chain velocity (multiplier) = 100
Vector X calculation = -7424304.199219
Vector2 = (-1, 0)

OiKeTTLe | 2021-07-15 07:34

Okay, so errors solved, except kind of… not at all.
Alright so… how is the player input meant to work? You press right, and…?
As far as I’m seeing it, the motion equation here is just running off its own values. Which is why we have some patently ridiculous values (X = -7424304.199219 wat).

At this stage — and I know you’ve done a lot to get to this stage, but you need to consider the current implementation is too complex to handle.

Yuminous | 2021-07-15 07:55

Character movement along the x axis is really simple here;

if Input.is_action_pressed:
motion.x = speed (where speed = 500)

if left:
motion.x = -speed

OiKeTTLe | 2021-07-15 08:01

…before all this, did you ever have your movement system working? When did it stop working?

I have other questions: what’s wrong with the chain_velocity equation that it outputs 100? (0 + 0) / 2 + 1 doesn’t equal 100 that doesn’t make sense…

Recommendations:
Keep this:
if Input.is_action_pressed( left ):
motion.x = -speed
if Input.is_action_pressed( right ):
motion.x = speed

Delete or comment all chain movement and replace it with this, maybe it will… you could maybe see something at least
motion = $Chain/Tip.position * chain_velocity

Please try it again… and if it doesn’t work, please consider uploading the project to Google Drive or Github or some file sharing website so I or someone can see what’s happening to it

Yuminous | 2021-07-15 08:20

Sorry, I changed the 1 in (0 + 0) / 2 + 1 to a 100, to see if it would affect anything. The movement system has always been fine, I’m trying to implement a grappling hook system. It calculates the y axis well enough, but it doesn’t pull the player towards it, just keeps it stationary. That’s the main issue I’m struggling with. I will upload the project to github and link it here.

OiKeTTLe | 2021-07-15 08:27

This should lead to my project. IDK, haven’t uploaded to GitHub before. GitHub - oiKeTTLe/GrapplingHook

OiKeTTLe | 2021-07-15 08:35

In the upper-right of the webpage click the + icon and New repository, name it, then in the new blank repository (project) page drag and drop your entire project folder. Then once it uploads to that page click the green button Commit changes

Yuminous | 2021-07-15 08:40

Were you able to access the link?

OiKeTTLe | 2021-07-15 08:42

Unfortunately, no…

Yuminous | 2021-07-15 08:43

Maybe it’s too soon for me to check?

Yuminous | 2021-07-15 08:45

Alright, it should work now

OiKeTTLe | 2021-07-15 08:46

Yup, thanks! I’ll have a look!

Yuminous | 2021-07-15 08:46

Hey, um, did you compile everything?

Unfortunately every script file and the project are in binary — I haven’t quite learned how to read that yet, haha… When uploading you can make a ZIP if need be, but otherwise just upload the actual project folder, like this one for example, you can see all the raw project files.

Yuminous | 2021-07-15 08:52

Uhh no, I have not. I’m still pretty new to this… if you look again I’ve uploaded the actual project folder

OiKeTTLe | 2021-07-15 08:58

Open—! Yay!

enter image description here
By the way, you must have found a fix for the animation player only playing on one side?

Yuminous | 2021-07-15 09:09

I guess you could call it that lol… I just made a new animation that mirrored the old one, and would play if the attack button was triggered and the player’s sprite was flipped.

OiKeTTLe | 2021-07-15 09:10

I have some preliminary results for you:

In _physics_process right under elif Input.is_action_pressed("p1_left"): in the following code your motion.x is being set to 0:

else:
motion.x = 0 <<< comment this out to move on x !
$AnimatedSprite.play("Idle")
friction = true

Standby for more, I’ll provide an actual fix for it soon

Yuminous | 2021-07-15 09:21

Awesome, thanks

OiKeTTLe | 2021-07-15 09:32

You can replace it with

if not InputEventMouseButton:
motion.x = 0

So that it doesn’t set the motion when the player is clicking, but when I have it commented out it doesn’t seem to change anything anyway, but it’s all up to you.

By the way, I love how this grappling system can pick up such insane speeds on the Y axis. It’s really fun to play with! It’d be even more so (but probably OP) if you copied the Y axis movement for the X system.

Yuminous | 2021-07-15 09:38

Thanks! That’s the idea! I want to develop a 2d movement shooter, similar to Soldat

OiKeTTLe | 2021-07-15 09:47

HOLY SHIT IT ACTUALLY WORKS NOW. Thank you so much for the help, and spotting that bit of code; I would never have noticed it. You’re a life saver, again.

OiKeTTLe | 2021-07-15 09:55

Alright— yeah! That’s super awesome!

I’ve also just found a way to fix the AnimationPlayer issue that only requires minor code tweaking, then won’t have to make two sets of animations for left and right from here on!

Yuminous | 2021-07-15 10:09

That would be great!

OiKeTTLe | 2021-07-15 10:15

I’m working on an answer for that question now.

With this question/answer, I’m just going to leave my answer as is since what we were discussing ended up being pretty different to the OP, and both me and Imaginaryzero covered that pretty well.

Once again though, what you’re making looks really fun so far. And your code looks great! Honestly. But you just keep setting up mystery traprooms for yourself ● ‿↼

Yuminous | 2021-07-15 10:29

Thanks :slight_smile: lol

OiKeTTLe | 2021-07-15 10:34

Hi, sorry it some time but I have completed the other answer.
I just wanted to make sure that the solution would definitely work in your project (it did!). Feel free to comment here or there if you need more details regarding its implementation — though the answer covers everything I think you need.

Yuminous | 2021-07-15 12:08

:bust_in_silhouette: Reply From: imaginaryzero

(Assuming you’re using 2D) Vector2 is simply two floats.
motion.x and motion.y are floats, and motion is a Vector2. The same is true for Vector3.
You would have to normalize motion itself.
This might solve the error:

 motion.x = ((self.position.x - $Chain/Tip.position.x) * speed * chain_velocity)
 motion = motion.normalized()

Received this error: Invalid set index ‘x’ (on base: ‘Vector2’) with value of type ‘Vector2’.

OiKeTTLe | 2021-07-15 07:53