2016-01-09 04:03:45 +00:00
|
|
|
local current = (...):gsub('%.[^%.]+$', '');
|
|
|
|
|
2015-12-20 11:09:20 +00:00
|
|
|
local Node = {};
|
|
|
|
|
|
|
|
local FORCE_SPRING = -0.01;
|
|
|
|
local FORCE_CHARGE = 100000;
|
|
|
|
|
|
|
|
local FORCE_MAX = 4;
|
|
|
|
local NODE_SPEED = 8;
|
|
|
|
local DAMPING_FACTOR = 0.95;
|
|
|
|
|
2015-12-21 12:27:17 +00:00
|
|
|
local DEFAULT_MASS = 0.05;
|
|
|
|
|
2015-12-20 11:09:20 +00:00
|
|
|
---
|
|
|
|
-- @param id - A unique id which will be used to reference this node.
|
2016-01-03 01:43:33 +00:00
|
|
|
-- @param x - The x coordinate the Node should be spawned at (optional).
|
|
|
|
-- @param y - The y coordinate the Node should be spawned at (optional).
|
|
|
|
-- @param anchor - Wether the node should be locked in place or not (optional).
|
2015-12-20 11:09:20 +00:00
|
|
|
--
|
2016-01-09 04:10:38 +00:00
|
|
|
function Node.new( id, x, y, anchor, ... )
|
2015-12-20 11:09:20 +00:00
|
|
|
local self = {};
|
|
|
|
|
|
|
|
local px, py = x or 0, y or 0;
|
|
|
|
local ax, ay = 0, 0;
|
|
|
|
local vx, vy = 0, 0;
|
|
|
|
|
|
|
|
---
|
|
|
|
-- Clamps a value to a certain range.
|
|
|
|
-- @param min
|
|
|
|
-- @param val
|
|
|
|
-- @param max
|
|
|
|
--
|
|
|
|
local function clamp( min, val, max )
|
|
|
|
return math.max( min, math.min( val, max ) );
|
|
|
|
end
|
|
|
|
|
|
|
|
---
|
|
|
|
-- Calculates the new xy-acceleration for this node.
|
|
|
|
-- The values are clamped to keep the graph from "exploding".
|
|
|
|
-- @param fx - The force to apply in x-direction.
|
|
|
|
-- @param fy - The force to apply in y-direction.
|
|
|
|
--
|
|
|
|
local function applyForce( fx, fy )
|
|
|
|
ax = clamp( -FORCE_MAX, ax + fx, FORCE_MAX );
|
|
|
|
ay = clamp( -FORCE_MAX, ay + fy, FORCE_MAX );
|
|
|
|
end
|
|
|
|
|
2016-01-03 01:43:33 +00:00
|
|
|
---
|
|
|
|
-- Attract this node to another node.
|
|
|
|
-- @param node - The node to use for force calculation.
|
|
|
|
--
|
2015-12-20 11:09:20 +00:00
|
|
|
function self:attractTo( node )
|
|
|
|
local dx, dy = px - node:getX(), py - node:getY();
|
|
|
|
local distance = math.sqrt(dx * dx + dy * dy);
|
|
|
|
dx = dx / distance;
|
|
|
|
dy = dy / distance;
|
|
|
|
|
|
|
|
local strength = FORCE_SPRING * distance;
|
|
|
|
applyForce( dx * strength, dy * strength );
|
|
|
|
end
|
|
|
|
|
2016-01-03 01:43:33 +00:00
|
|
|
---
|
|
|
|
-- Repel this node from another node.
|
|
|
|
-- @param node - The node to use for force calculation.
|
|
|
|
--
|
2015-12-20 11:09:20 +00:00
|
|
|
function self:repelFrom( node )
|
|
|
|
local dx, dy = px - node:getX(), py - node:getY();
|
|
|
|
local distance = math.sqrt(dx * dx + dy * dy);
|
|
|
|
dx = dx / distance;
|
|
|
|
dy = dy / distance;
|
|
|
|
|
2015-12-21 12:27:17 +00:00
|
|
|
local strength = FORCE_CHARGE * (DEFAULT_MASS / (distance * distance));
|
2015-12-20 11:09:20 +00:00
|
|
|
applyForce(dx * strength, dy * strength);
|
|
|
|
end
|
|
|
|
|
|
|
|
---
|
|
|
|
-- Update the node's position based on the calculated velocity and
|
|
|
|
-- acceleration.
|
2016-01-03 01:43:33 +00:00
|
|
|
-- @param dt - The delta time between frames.
|
2015-12-20 11:09:20 +00:00
|
|
|
--
|
|
|
|
function self:move( dt )
|
|
|
|
vx = (vx + ax * dt * NODE_SPEED) * DAMPING_FACTOR;
|
|
|
|
vy = (vy + ay * dt * NODE_SPEED) * DAMPING_FACTOR;
|
|
|
|
px = px + vx;
|
|
|
|
py = py + vy;
|
|
|
|
ax, ay = 0, 0;
|
|
|
|
end
|
|
|
|
|
|
|
|
function self:getID()
|
|
|
|
return id;
|
|
|
|
end
|
|
|
|
|
|
|
|
function self:getX()
|
|
|
|
return px;
|
|
|
|
end
|
|
|
|
|
|
|
|
function self:getY()
|
|
|
|
return py;
|
|
|
|
end
|
|
|
|
|
|
|
|
function self:getPosition()
|
|
|
|
return px, py;
|
|
|
|
end
|
|
|
|
|
|
|
|
function self:setPosition( nx, ny )
|
|
|
|
px, py = nx, ny;
|
|
|
|
end
|
|
|
|
|
2016-01-02 14:17:20 +00:00
|
|
|
function self:setAnchor( nanchor )
|
|
|
|
anchor = nanchor;
|
|
|
|
end
|
|
|
|
|
|
|
|
function self:isAnchor()
|
|
|
|
return anchor;
|
|
|
|
end
|
|
|
|
|
2015-12-20 11:09:20 +00:00
|
|
|
return self;
|
|
|
|
end
|
|
|
|
|
|
|
|
return Node;
|