## vector 2 class?

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Citizen
Posts: 72
Joined: Wed Oct 28, 2015 11:18 pm

### vector 2 class?

can someone explain to be how to do the following with my vector class?
I am not very sufficient in math because of neglecting school when I was a kid, but I want to have the following functions and operator support in this class..

Code: Select all

require("class")

--Construct vec2 class
Vec2 = Class:inherit("Vec2");

function Vec2:create(x,y)
self.x = x or 0;
self.y = y or 0;
end

function Vec2:normalize()
self.x = self.x / self:getLength();
self.y = self.y / self:getLength();
return self;
end

-- did some research and took a guess that this is how this function works
function Vec2:getLength()
return math.sqrt(self.x * self.x + self.y * self.y)
end
function Vec2:setLength(length)    end
function Vec2:getDirection()       end
function Vec2:setDirection(length) end

--wondering if there might be operator support for doing..
--local vec2a = Vec2(1,0)
--local vec2b = Vec2(4,3)
--local vec2c = vec2a * vec2b



Sir_Silver
Party member
Posts: 286
Joined: Mon Aug 22, 2016 2:25 pm

### Re: vector 2 class?

Not sure how your class system works but lets just pretend that Vec2 is just a regular old table, here's how I would do it.

Code: Select all

local Vec2 = {}
Vec2.__index = Vec2

setmetatable(Vec2, {
__call = function(_, x, y)
return setmetatable({
x = x or 0,
y = y or 0
}, Vec2)
end
})

--Allows two Vec2 objects to be multiplied together, to produce a new Vec2 object.
function Vec2:__mul(vec2)
return Vec2(self.x * vec2.x, self.y * vec2.y)
end

local vec2a = Vec2(1,0)
local vec2b = Vec2(4,3)
local vec2c = vec2a * vec2b

print(vec2c.x, vec2c.y)
If you need help understanding metatables: http://lua-users.org/wiki/MetamethodsTutorial

Citizen
Posts: 72
Joined: Wed Oct 28, 2015 11:18 pm

### Re: vector 2 class?

thankyou sir_silver that was my fault for not providing the class code sorry

anyways..
what about getting and setting length and direction?
how does that work?

EDIT: also would it be possible to use vec2 variables like this..

Code: Select all

local vec2 = Vec2(1, 1);
vec2.length = 3    -- Modifies x and y also
local newlength = vec2.length; --
instead of having to update them in a my game loop?

ivan
Party member
Posts: 1548
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

### Re: vector 2 class?

I believe that there is a small bug here:

Code: Select all

function Vec2:normalize()
self.x = self.x / self:getLength(); -- the vector's length changes at this line
self.y = self.y / self:getLength();
return self;
end  
Should become:

Code: Select all

function Vec2:normalize()
local len = self:getLength();
self.x = self.x / len;
self.y = self.y / len;
return self;
end  
If you know the length, you can do:

Code: Select all

function vec2.setLength(newLength)
local a = math.atan2(self.y, self.x)
self.x = math.cos(a)*newLength
self.y = math.sin(a)*newLength
end
Yes, you can make ".length" work too using metatables.

Sir_Silver
Party member
Posts: 286
Joined: Mon Aug 22, 2016 2:25 pm

### Re: vector 2 class?

I spent a good little while trying to make .length thing work the way you mentioned it. I don't think I would recommend doing things this way, but here is the code if you're interested in seeing it!

Code: Select all

local Vec2 = {}

function Vec2.__index(t, k)
if k == "length" then
return t:getLength()
end

return rawget(Vec2, k) or rawget(t.t, k)
end

function Vec2.__newindex(t, k, v)
if k == "length" then
t:setLength(v)
end

rawset(t.t, k, v)
end

setmetatable(Vec2, {
__call = function(_, x, y)
return setmetatable({
t = {
x = x or 0,
y = y or 0
}
}, Vec2)
end
})

function Vec2:setLength(length)
self:normalize()
rawset(self.t, "length", length)

self.x = self.x * length
self.y = self.y * length
end

function Vec2:getLength()
local length = rawget(self.t, "length")

if length then
return length
end

rawset(self.t, "length", math.sqrt(self.x ^ 2 + self.y ^ 2))
return self.length
end

function Vec2:normalize()
local length = self:getLength()
self.x = self.x / length
self.y = self.y / length
end

local vec2c = Vec2(0, 1)
print(vec2c.x, vec2c.y)  --Starting x and y values
print(vec2c.length)

vec2c.length = 4

print(vec2c.x, vec2c.y)  --New x and y values
print(vec2c.length)


ivan
Party member
Posts: 1548
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

### Re: vector 2 class?

Looks good, for simplicity's sake here it is without storing/rawset-ting the length:

Code: Select all

function Vec2:normalize(unit)
unit = unit or 1
local length = self:getLength()
if length > 0 then -- division by zero check
local n = (1/length)*unit
self.x = self.x*n
self.y = self.y*n
end
return length
end

function Vec2:setLength(length)
self:normalize(length)
end

function Vec2:getLength()
local x, y = self.x, self.y
return math.sqrt(x*x + y*y)
end
The problem with storing "length" is that it may get out of sync when you modify .x or .y.

Citizen
Posts: 72
Joined: Wed Oct 28, 2015 11:18 pm

### Re: vector 2 class?

thankyou ivan and sir_silver

@ivan: i will fix that thankyou. it was like that originally I just attempted to make it shorter. >.< also thankyou for the the help on the setLength function
@sir_silver: ya that looks complicated I think I will just stick to get and set methods.

how would I go about setting and getting direction?

### Who is online

Users browsing this forum: No registered users and 11 guests