vector 2 class?

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.
Post Reply
Shadowblitz16
Citizen
Posts: 73
Joined: Wed Oct 28, 2015 11:18 pm

vector 2 class?

Post by Shadowblitz16 »

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



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

Re: vector 2 class?

Post by Sir_Silver »

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
Some more info on the metamethods: http://lua-users.org/wiki/MetatableEvents
Shadowblitz16
Citizen
Posts: 73
Joined: Wed Oct 28, 2015 11:18 pm

Re: vector 2 class?

Post by Shadowblitz16 »

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?
User avatar
ivan
Party member
Posts: 1911
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: vector 2 class?

Post by ivan »

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.
User avatar
Sir_Silver
Party member
Posts: 286
Joined: Mon Aug 22, 2016 2:25 pm
Contact:

Re: vector 2 class?

Post by Sir_Silver »

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)
User avatar
ivan
Party member
Posts: 1911
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: vector 2 class?

Post by ivan »

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.
Shadowblitz16
Citizen
Posts: 73
Joined: Wed Oct 28, 2015 11:18 pm

Re: vector 2 class?

Post by Shadowblitz16 »

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?
Post Reply

Who is online

Users browsing this forum: No registered users and 24 guests