0
\$\begingroup\$

I've been struggling a lot to learn how to use vectors in programming. Now I've successfully made my own vector class but I still can't use vectors for movement.

This is my class :

class MyVector2(object):

    def __init__(self, x, y):
        self.x, self.y = x, y
        self.tuple = (self.x, self.y)

    def __str__(self):
        return f"({self.x}, {self.y})"

    @property
    def magnitude(self):
        return math.sqrt(self.x**2 + self.y**2)

    def normalize(self):
        self.x /= self.magnitude
        self.y /= self.magnitude

    @staticmethod
    def create_path(destination, pos):
        return MyVector2(destination.x - pos.x, destination.y - pos.y)

    @staticmethod
    def dot(v1, v2):
        return v1.x * v2.x + v1.y * v2.y

(there are also other methods for the operations (+/*-) that I don't need to copy here)

My problem with movement is that the object I want to move doesn't stop at the destination but continues moving infinitely :

class Obj(object):
    def __init__(self):
        self.x, self.y = 100, 80
        self.speed = 0.1
        self.pos = MyVector2(self.x, self.y)
        self.img = img
        self.moving = True

    def blit(self):
        screen.blit(self.img, (self.pos.tuple))

obj = Obj()
dest = MyVector2(150, 130)
path = MyVector2.create_path(dest, obj.pos)
path.normalize()
while True:
    obj.blit()
    if obj.moving:
        obj.pos += path * obj.speed
    if dest == obj.pos:
        obj.moving = False

I also think that my way of using vectors to move objects is bad, so please provide me with a professional one.

\$\endgroup\$
12
  • 2
    \$\begingroup\$ You're overshooting; you need to check if the path * obj.speed brings you further away from your destination, and if it does, stop at your destination... \$\endgroup\$
    – Vaillancourt
    Commented Dec 23, 2021 at 14:56
  • 1
    \$\begingroup\$ Try what DMGregory suggests, if this condition is "True" then you've reached your destination, and you should set the obj.pos directly to dest instead of adding a translation. \$\endgroup\$
    – Vaillancourt
    Commented Dec 23, 2021 at 15:42
  • 1
    \$\begingroup\$ Also, please note that, in general, comparing floating point values (like dest == obj.pos) is rarely useful/relevant in game programming because of how data is stored internally by the computer. You should use something like an equivalent or approximately function which lets you decide if they're "close enough" for your needs (some implementations have three parameters: the two values to compare and the "range" (epsilon), which is often set to a default value). \$\endgroup\$
    – Vaillancourt
    Commented Dec 23, 2021 at 15:49
  • 1
    \$\begingroup\$ Yes, I understand that, though their internal values are floats, so assuming that you create a function that will handle floats such as this (pseudocode): equivalent(a, b, epsilon = 0.00001) : return abs(a - b) < epsilon, you can add an equivalent function to your vector class such as this (pseudocode): equivalent(self, other, epsilon = 0.00001) : return equivalent(self.x, other.x, epsilon) and equivalent(self.y, other.y, epsilon). \$\endgroup\$
    – Vaillancourt
    Commented Dec 23, 2021 at 16:01
  • 2
    \$\begingroup\$ If you tried another approach, please update the question so that we know what you've tried a bit more clearly. \$\endgroup\$
    – Vaillancourt
    Commented Dec 23, 2021 at 16:02

1 Answer 1

1
\$\begingroup\$

A friend of mine has found the issue for my code and it was related to the Vector class :

def normalize(self):
    self.x /= self.magnitude
    self.y /= self.magnitude

Here in the normalize() function, once the self.x value gets divided by the magnitude, the magnitude changes as it is related to it. So this means the self.y value will be then divided by the 'new' magnitude and this will lead to a disorder.

Therefore, the solution is this :

def normalize(self):
    m = self.magnitude
    self.x /= m
    self.y /= m

That will prevent the problem from happening by saving the magnitude in a variable inside the normalize() function. And after trying this, everything worked well and I successfully implemented vector movement in pygame !

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Thanks for coming back and posting this, you might consider accepting the answer! \$\endgroup\$
    – Vaillancourt
    Commented Mar 6, 2022 at 16:18

You must log in to answer this question.

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