Created
October 1, 2012 19:40
-
-
Save jonbro/3813982 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Vec2 = class(function(vec,x,y) | |
| vec.x = x | |
| vec.y = y | |
| end) | |
| function Vec2:set(v) | |
| self.x = v.x | |
| self.y = v.y | |
| return self | |
| end | |
| function Vec2:add(v) | |
| self.x = self.x + v.x; | |
| self.y = self.y + v.y; | |
| return self | |
| end | |
| function Vec2:add(v) | |
| self.x = self.x + v.x; | |
| self.y = self.y + v.y; | |
| return self | |
| end | |
| function Vec2.det(x1,y1, x2,y2) | |
| return x1*y2 - y1*x2 | |
| end | |
| function Vec2:mult(s) -- by scalar | |
| self.x = self.x * s; | |
| self.y = self.y * s; | |
| return self | |
| end | |
| function Vec2:sub(v) | |
| self.x = self.x - v.x; | |
| self.y = self.y - v.y; | |
| return self | |
| end | |
| function Vec2:length() | |
| return math.sqrt(self.x*self.x + self.y * self.y) | |
| end | |
| function Vec2:normalize() | |
| length = math.sqrt(self.x*self.x + self.y*self.y) | |
| if length > 0 then | |
| self.x = self.x/length | |
| self.y = self.y/length | |
| else | |
| self.x = 0 | |
| self.y = 0 | |
| end | |
| return self | |
| end | |
| function Vec2:rotate(a) | |
| local px = self.x*math.cos(a) - self.y*math.sin(a) | |
| local py = self.x*math.sin(a) + self.y*math.cos(a) | |
| self.x, self.y = px, py | |
| return self | |
| end | |
| function Vec2:copy() | |
| return Vec2(self.x, self.y) | |
| end | |
| function Vec2:angle() | |
| return math.atan2(self.x, self.y) | |
| end | |
| function Vec2:distance(v) | |
| if not v then | |
| print(debug.traceback()) | |
| end | |
| return math.sqrt((self.x-v.x)^2 + (self.y-v.y)^2) | |
| end | |
| function Vec2:distanceSq(v) | |
| if not v then | |
| print(debug.traceback()) | |
| end | |
| return (self.x-v.x)^2 + (self.y-v.y)^2 | |
| end | |
| function Vec2:distanceSq(v) | |
| if not v then | |
| print(debug.traceback()) | |
| end | |
| return (self.x-v.x)^2 + (self.y-v.y)^2 | |
| end | |
| function Vec2:__eq(b) | |
| return self.x == b.x and self.y == b.y | |
| end | |
| function Vec2:__tostring() | |
| return "Vector: " .. self.x .. ", " .. self.y | |
| end | |
| Line2d = class(function(line,x1,y1,x2,y2) | |
| line.v1 = Vec2(x1,y1) | |
| line.v2 = Vec2(x2,y2) | |
| end) | |
| -- http://www.angelfire.com/fl/houseofbartlett/solutions/lineinter2d.html | |
| function Line2d:check_tri_clock_dir(v1,v2,v3) | |
| test = (((v2.x - v1.x)*(v3.y - v1.y)) - ((v3.x - v1.x)*(v2.y - v1.y))); | |
| if (test > 0) then return 0 -- counter clockwise | |
| elseif(test < 0) then return 1 -- clockwise | |
| else return 3 end -- line | |
| end | |
| function Line2d:check_intersection(l2) | |
| test1_a = self:check_tri_clock_dir(self.v1,self.v2,l2.v1) | |
| test1_b = self:check_tri_clock_dir(self.v1,self.v2,l2.v2) | |
| if(test1_a ~= test1_b) then | |
| test2_a = self:check_tri_clock_dir(l2.v1,l2.v2,self.v1) | |
| test2_b = self:check_tri_clock_dir(l2.v1,l2.v2,self.v2) | |
| if(test2_a ~= test2_b) then | |
| return true | |
| end | |
| end | |
| return false | |
| end | |
| -- Rectangle Class | |
| Rectangle = class(function(rect, x, y, w, h) | |
| rect.w = w | |
| rect.h = h | |
| rect.pos = Vec2(0,0) | |
| rect.x1 = 0 | |
| rect.y1 = 0 | |
| rect.x2 = 0 | |
| rect.y2 = 0 | |
| rect.red = 0; | |
| rect.green = 0; | |
| rect.blue = 0; | |
| rect.tint = {r=255, g=255, b=255, a=255} | |
| Rectangle.setPosition(rect, x, y) | |
| rect.layer = 0 | |
| end) | |
| function Rectangle:setPosition(x,y) | |
| -- added some type coersion | |
| self.pos.x = x+0 | |
| self.pos.y = y+0 | |
| self.x1 = x+0 | |
| self.y1 = y+0 | |
| self.x2 = x+self.w | |
| self.y2 = y+self.h | |
| end | |
| function Rectangle:setColor(r,g,b) | |
| self.red = r; | |
| self.green = g; | |
| self.blue = b; | |
| Object.setColor(self, r,g,b) | |
| end | |
| function Rectangle:sync() | |
| end | |
| function Rectangle:draw() | |
| -- draw the box | |
| local c = {self.pos.x, self.pos.y, self.w, self.h} | |
| local tl = {c[1], c[2]} | |
| local tr = {c[1]+c[3], c[2]} | |
| local bl = {c[1], c[2]+c[4]} | |
| local br = {c[1]+c[3], c[2]+c[4]} | |
| sheets["ui"]:addCornerTile(sprites["ui"]["white.png"], tl[1],tl[2], tr[1],tr[2], br[1],br[2], bl[1],bl[2], self.layer, self.tint.r, self.tint.g, self.tint.b, self.tint.a) | |
| end | |
| function Rectangle:drawDrop(s, color) | |
| -- draw the dropshadow | |
| local c = {self.pos.x, self.pos.y, self.w, self.h} | |
| local tl = {c[1], c[2]} | |
| local tr = {c[1]+c[3], c[2]} | |
| local bl = {c[1], c[2]+c[4]} | |
| local br = {c[1]+c[3], c[2]+c[4]} | |
| local h = s | |
| if not retina then h=h/2 end | |
| tl = {bl[1], bl[2]} | |
| tr = {br[1], br[2]} | |
| bl = {bl[1]+h/2, bl[2]+h} | |
| br = {br[1]-h/2, br[2]+h} | |
| sheets["ui"]:addCornerTile(sprites["ui"]["white.png"], tl[1],tl[2], tr[1],tr[2], br[1],br[2], bl[1],bl[2], self.layer, color.r,color.g,color.b,255) | |
| self:draw() | |
| end | |
| function Rectangle:drawTopDrop(h) | |
| local c = {self.pos.x, self.pos.y, self.w, self.h} | |
| local tl = {c[1], c[2]} | |
| local tr = {c[1]+c[3], c[2]} | |
| local bl = {c[1], c[2]+c[4]} | |
| local br = {c[1]+c[3], c[2]+c[4]} | |
| if not retina then h=h/2 end | |
| tl = {tl[1], tl[2]} | |
| tr = {tr[1], tr[2]} | |
| bl = {tl[1], tl[2]-h} | |
| br = {tr[1], tr[2]-h} | |
| sheet:addCornerTile(sprites["white.png"], tl[1],tl[2], tr[1],tr[2], br[1],br[2], bl[1],bl[2], self.layer, 159,155,140,255) | |
| self:draw() | |
| end | |
| function Rectangle:drawOutline() | |
| -- tl to tr | |
| lb:addLine(self.pos.x, self.pos.y, self.pos.x+self.w, self.pos.y) | |
| -- tr to br | |
| lb:addLine(self.pos.x+self.w, self.pos.y, self.pos.x+self.w, self.pos.y+self.h) | |
| -- br to bl | |
| lb:addLine(self.pos.x+self.w, self.pos.y+self.h, self.pos.x, self.pos.y+self.h) | |
| -- bl to tl | |
| lb:addLine(self.pos.x, self.pos.y+self.h, self.pos.x, self.pos.y) | |
| end | |
| function Rectangle:doesPointTouch(v) | |
| if (v.x >= self.pos.x and v.x < self.pos.x+self.w) then | |
| if (v.y >= self.pos.y and v.y < self.pos.y+self.h) then | |
| return true | |
| end | |
| end | |
| return false | |
| end | |
| function Rectangle:doesRectangleTouch(r) | |
| return | |
| (r.pos.x + r.w > self.pos.x) and | |
| (r.pos.x < self.pos.x+self.w) and | |
| (r.pos.y + r.h > self.pos.y) and | |
| (r.pos.y < self.pos.y + self.h) | |
| end | |
| function Rectangle:whatSideDoesLineTouch(line, velocity) | |
| -- check the top and bottom intersections | |
| if velocity.y > 0 then | |
| side = Line2d(self.x1,self.y1,self.x2,self.y1) | |
| if(line:check_intersection(side)) then | |
| return 1 | |
| end | |
| elseif velocity.y < 0 then | |
| side = Line2d(self.x1,self.y2,self.x2,self.y2) | |
| if(line:check_intersection(side)) then | |
| return 3 | |
| end | |
| end | |
| -- check the left and right intersections | |
| if velocity.x > 0 then | |
| side = Line2d(self.x1,self.y1,self.x1,self.y2) | |
| if(line:check_intersection(side)) then | |
| return 4 | |
| end | |
| elseif velocity.x < 0 then | |
| side = Line2d(self.x2,self.y1,self.x2,self.y2) | |
| if(line:check_intersection(side)) then | |
| return 2 | |
| end | |
| end | |
| return 0 | |
| end | |
| -- returns if there is an intersection and the distance to the intersection | |
| function Rectangle:raycast(o, d) | |
| local ox, oy = o.x, o.y | |
| local dx, dy = d.x, d.y | |
| local tx_min, ty_min, tx_max, ty_max | |
| local a = 1/dx | |
| local mMin = self.pos | |
| local mMax = Vec2(self.pos.x+self.w, self.pos.y+self.h) | |
| -- x intersection | |
| if a >= 0 then | |
| tx_min = (mMin.x-ox)*a; | |
| tx_max = (mMax.x-ox)*a; | |
| else | |
| tx_min = (mMax.x-ox)*a; | |
| tx_max = (mMin.x-ox)*a; | |
| end | |
| local b = 1/dy | |
| if b >= 0 then | |
| ty_min = (mMin.y-oy)*b; | |
| ty_max = (mMax.y-oy)*b; | |
| else | |
| ty_min = (mMax.y-oy)*b; | |
| ty_max = (mMin.y-oy)*b; | |
| end | |
| local t0 = math.max(tx_min, ty_min) | |
| local t1 = math.min(tx_max, ty_max) | |
| if t0 < t1 and t1 > 0 then | |
| return true, t0 | |
| end | |
| return false | |
| end | |
| local a, b = {max={}, min={}}, {max={}, min={}} | |
| local va, vb = Vec2(0,0), Vec2(0,0) | |
| local u_0 = Vec2(0,0) | |
| local u_1, displacement = Vec2(1, 1), Vec2(0,0) | |
| -- tests if two moving rectangles intersect with each other, and if so at what point | |
| function Rectangle:sweepTest(r2, r1Movement, r2Movement) | |
| a.max.x, a.min.x, a.max.y, a.min.y = self.pos.x+self.w, self.pos.x, self.pos.y+self.h, self.pos.y | |
| b.max.x, b.min.x, b.max.y, b.min.y = r2.pos.x+r2.w, r2.pos.x, r2.pos.y+r2.h, r2.pos.y | |
| va.x, vb.x = r1Movement.x, r1Movement.y | |
| vb.x, vb.y = r2Movement.x, r2Movement.y | |
| -- get the displacement from the perspective of the first box | |
| displacement.x, displacement.y = vb.x-va.x, vb.y-va.y | |
| u_0.x, u_0.y = 0,0 | |
| u_1.x, u_1.y = 1, 1 | |
| -- if the objects were overlapping at the start of the frame | |
| if (Object.overlap(self, r2)) then | |
| return true, 0, 0 | |
| end | |
| -- check on each axis | |
| for i,v in ipairs({"x", "y"}) do | |
| if a.max[v]<b.min[v] and displacement[v]<0 then | |
| u_0[v] = (a.max[v] - b.min[v]) / displacement[v]; | |
| elseif b.max[v]<a.min[v] and displacement[v]>0 then | |
| u_0[v] = (a.min[v] - b.max[v]) / displacement[v]; | |
| end | |
| if b.max[v]>a.min[v] and displacement[v]<0 then | |
| u_1[v] = (a.min[v] - b.max[v]) / displacement[v]; | |
| elseif a.max[v]>b.min[v] and displacement[v]>0 then | |
| u_1[v] = (a.max[v] - b.min[v]) / displacement[v]; | |
| end | |
| end | |
| local u0 = math.max(u_0.x, u_0.y) | |
| local u1 = math.min(u_1.x, u_1.y) | |
| return u0<=u1, u0, u1 | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment