Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help,
read this.

Shadowblitz16
 Citizen
 Posts: 72
 Joined: Wed Oct 28, 2015 11:18 pm
Post
by Shadowblitz16 » Fri Jan 19, 2018 12:02 am
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
Post
by Sir_Silver » Fri Jan 19, 2018 1:59 am
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://luausers.org/wiki/MetamethodsTutorial
Some more info on the metamethods:
http://luausers.org/wiki/MetatableEvents

Shadowblitz16
 Citizen
 Posts: 72
 Joined: Wed Oct 28, 2015 11:18 pm
Post
by Shadowblitz16 » Fri Jan 19, 2018 2:54 am
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:
Post
by ivan » Fri Jan 19, 2018 5:52 am
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
Post
by Sir_Silver » Fri Jan 19, 2018 6:59 am
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:
Post
by ivan » Fri Jan 19, 2018 7:50 am
Looks good, for simplicity's sake here it is without storing/rawsetting 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.

Shadowblitz16
 Citizen
 Posts: 72
 Joined: Wed Oct 28, 2015 11:18 pm
Post
by Shadowblitz16 » Sun Jan 21, 2018 3:57 am
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?
Users browsing this forum: No registered users and 11 guests