|
|
- GameMath = GameMath or {}
- local GameMath = GameMath
- local math = math
- function GameMath.IsPointNear(p1x, p1y, p2x, p2y, near_val)
- near_val = near_val or 1.0
-
- local x_step = p1x - p2x
- local y_step = p1y - p2y
- local val = x_step*x_step + y_step*y_step
- return val <= near_val*near_val
- end
-
- --检查两个点是否在x或y方向上接近
- --用来判断p2是否在距离p1
- function GameMath.IsPointNearRect(p1x, p1y, p2x, p2y, near_val)
- if math.abs(p1x - p2x) > near_val then
- return false
- end
- if math.abs(p1y - p2y) > near_val then
- return false
- end
- return true
- end
-
- function GameMath.IsPointNearAbs(p1, p2, val)
- val = val or 1
- return (math.abs(p1.x - p2.x) <= val) and (math.abs(p1.y - p2.y) <= val)
- end
-
- function GameMath.Round(x)
- local val, pt = math.modf(x)
- if pt > 0.5 then
- val = val + 1
- end
-
- return val
- end
-
- --检测某点是否处于矩形内
- function GameMath.IsInRect(px, py, rect_x, rect_y, rect_width, rect_height)
- if px < rect_x - rect_width / 2 or px >= rect_x + rect_width / 2
- or py < rect_y - rect_height / 2 or py >= rect_y + rect_height / 2 then
- return false
- end
- return true
- end
-
-
- --检测某点是否处于矩形内
- function GameMath.HitRectTest(px, py, rect_x, rect_y, rect_width, rect_height)
- if px < rect_x or px >= rect_x + rect_width
- or py < rect_y or py >= rect_y + rect_height then
- return false
- end
- return true
- end
-
- --检测某点o是否a,b,c,d四个点组成的菱形内
- function GameMath.inDiamond(o, a, b, c, d)
- local l1 = co.Vector2(a.x - o.x,a.y - o.y)
- local l2 = co.Vector2(b.x - o.x,b.y - o.y)
- local l3 = co.Vector2(c.x - o.x,c.y - o.y)
- local l4 = co.Vector2(d.x - o.x,d.y - o.y)
- l1:normalise()
- l2:normalise()
- l3:normalise()
- l4:normalise()
- local total_degree = 0
- total_degree = total_degree + math.acos(l2:dotProduct(l1))
- total_degree = total_degree + math.acos(l3:dotProduct(l2))
- total_degree = total_degree + math.acos(l4:dotProduct(l3))
- total_degree = total_degree + math.acos(l1:dotProduct(l4))
- if math.abs(total_degree / 2 - math.pi) <= 0.001 then
- return true
- end
- return false
- end
-
- --[[
- 求距离公式
- @param need_sqrt 是否需要开方运算(不开方可以减少不必要的运算)
- @x_mult,y_mult 距离倍率,小于1,两点距离扩大x_mult,y_mult倍 ,大于1,距离缩小x_mult,y_mult倍
- ]]--
- function GameMath.GetDistance(p1x, p1y, p2x, p2y, need_sqrt,x_mult,y_mult)
- local x_step_mult = x_mult or 1
- local y_step_mult = y_mult or 1
-
- local x_step = p1x - p2x
- local y_step = p1y - p2y
- local val = x_step*x_step*x_step_mult + y_step*y_step*y_step_mult
-
- if need_sqrt then
- return math.pow(val,0.5)
- end
-
- return val
- end
-
- --[[
- 求距离公式
- @param need_sqrt 是否需要开方运算(不开方可以减少不必要的运算)
- @x_mult,y_mult 距离倍率,小于1,两点距离扩大x_mult,y_mult倍 ,大于1,距离缩小x_mult,y_mult倍
- ]]--
- function GameMath.GetDistance3D(p1x, p1y,p1z,p2x, p2y,p2z, need_sqrt,x_mult,y_mult)
- local x_step_mult = x_mult or 1
- local y_step_mult = y_mult or 1
-
- local x_step = p1x - p2x
- local y_step = p1y - p2y
- local val = x_step*x_step*x_step_mult + y_step*y_step*y_step_mult
-
- if need_sqrt then
- return math.pow(val,0.5)
- end
-
- return val
- end
-
- --[[
- 求距离公式 椭圆
- @param need_sqrt 是否需要开方运算(不开方可以减少不必要的运算)
- ]]--
- function GameMath.GetEllipseDistance(p1x, p1y, p2x, p2y, need_sqrt)
-
- local x_step = p1x - p2x
- local y_step = p1y - p2y
- local val = x_step*x_step + y_step*y_step * 4
-
- if need_sqrt then
- return math.pow(val,0.5)
- end
-
- return val
- end
-
-
- --把正圆的值转化成椭圆不同方向的值
- function GameMath.ChangeEllipseValue(dir, value, ratio, type)
- if dir then
- ratio = ratio or 0.5
- local radian = 0
- if dir.x == 0 then
- if dir.y > 0 then
- radian = 90 / 180 * math.pi
- elseif dir.y == 0 then
- radian = 0
- elseif dir.y < 0 then
- radian = -270 / 180 * math.pi
- end
- else
- radian = math.atan(dir.y / dir.x) --先计算夹角
- end
-
- local func = nil
- if type == nil or type == 1 then --1为x方向较长 2 为y方向较长的椭圆
- func = math.cos
- else
- func = math.sin
- end
-
- --椭圆处理
- return value * ratio + math.abs(func(radian)) * value * (1 - ratio)
- else
- return value
- end
- end
- --[[
- 取最近的点
- @param point_list 坐标数组
- @param px 参照点x坐标
- @param py 参照点y坐标
- @param get_point_func 从数组中的一个对象取出坐标,return x,y
- ]]--
- function GameMath.GetNearestPoint(point_list,px,py,get_point_func)
-
- local result
- local prev_distance = -1
-
- for _, point in pairs(point_list) do
- local curr_distance
- if get_point_handler == nil then
- curr_distance = GameMath.GetDistance(px, py, point.x, point.y)
- else
- curr_distance = GameMath.GetDistance(px, py, get_point_func(point))
- end
-
- if prev_distance == -1 or prev_distance > curr_distance then
- result = point
- prev_distance = curr_distance
- end
- end
-
- return result
- end
-
-
- --判断点和直线的距离
- function GameMath.DistancePointToLine(dir, pos, need_sqrt)
- local x0, y0 = pos.x, pos.y --目标点相对于直线起点的相对坐标
- local A, B = dir.y, -dir.x --直线方程的系数
- local d1 = (A*x0 + B*y0)
- local d = (d1*d1) / (A*A + B*B) --目标点和直线的距离的平方
-
- if need_sqrt then
- d = math.pow(d, 0.5)
- end
- return d
- end
-
-
- --二维角度值转成二维标准向量
- function GameMath.AngleToDirection(angle)
- local radian = angle / 180 * math.pi
- local dir = co.TableXY(math.cos(radian), math.sin(radian))
- co.NormaliseXYTable(dir)
- return dir
- end
-
- function GameMath.Smooth(from, to, vel, smoothTime, timeDelta)
- local omega = 2.0 / smoothTime
- local x = omega * timeDelta
- local exp = 1.0 / (1.0 + x + 0.48*x*x + 0.235*x*x*x)
- local change = from - to
- local temp = (vel + change * omega) * timeDelta
- local new_vel = (vel - temp * omega) * exp
- vel = new_vel
- return to + (change + temp) * exp, vel
- end
-
-
- function GameMath.Lerp(from,to,t)
- if t > 1 then
- t = 1
- elseif t < 0 then
- t = 0
- end
- local delta = to - from
- return from + delta * t
- end
-
-
- function GameMath.EaseOutQuad(from,to,value)
- to = to - from
- return -to * value * (value - 2) + from
- end
-
- function GameMath.EaseInQuad(from,to,value)
- to = to - from
- return to * value * value + from
- end
-
- function GameMath.EaseInOutQuad(from,to,value)
- value = value /0.5
- to = to - from
- if (value < 1) then return to * 0.5 * value * value + from end
- value = value - 1
- return - to * 0.5 * (value * (value - 2) - 1) + from
- end
-
- function GameMath.EaseInOutQuart(from,to,value)
- value = value /0.5
- to = to - from
- if (value < 1) then return to * 0.5 * value * value * value + from end
- value = value - 1
- return - to * 0.5 * (value * value * (value - 2) - 1) + from
- end
-
-
-
- function GameMath.EaseInOutCubic(from,to,value)
- value = value /0.5
- to = to - from
- if value < 1 then
- return to * 0.5 * value * value * value + from
- end
-
- value = value - 2
- return to * 0.5 * (value * value * value + 2) + from
-
- end
-
- --获取中心点为x, y, 半径为dist的圆上的一个点
- function GameMath.GetPosByCeterPoint(x, y, dist)
- local angle = math.random(0, 360)
- local dir = GameMath.AngleToDirection(angle)
- local end_pos = co.TableXY((x + dir.x * dist), (y + dir.y * dist))
- return end_pos
- end
-
- --[[
- /**
- *计算两点p1,p2连线上位置为pp的垂线上的某点,该点与连线的距离为l
- * @param p1 起点
- * @param p2 终点
- * @param pp 0到1,表示p1到p2连线上的位置
- * @param l 所求点与p1,p2连线的距离,可有正负
- */ ]]
- function GameMath.GetVerticlePoint(p1, p2, pp, l)
- local offset_x = p2.x-p1.x == 0 and 1 or p2.x-p1.x
- local dir = co.Vector2((p1.y-p2.y)/offset_x, 1)
- dir:normalise()
- local p3 = p1 * (1-pp) + p2 * pp
- p3 = p3 + dir * l
- return p3
- end
-
- function GameMath.Bezier(list, t)
-
- local point_list = DeepCopy(list)
- local function lerp_xyz(from,to,t)
- local x = GameMath.Lerp(from.x,to.x,t)
- local y = GameMath.Lerp(from.y,to.y,t)
- local z = GameMath.Lerp(from.z,to.z,t)
- from.x = x
- from.y = y
- from.z = z
- return from
- end
-
- local function calc_fun()
- local lenth = #point_list
- for i = 1, lenth-1 do
- point_list[i] = lerp_xyz(point_list[i], point_list[i+1], t)
- end
- point_list[lenth] = nil
- end
- while #point_list > 2 do
- calc_fun()
- end
- return GameMath.LerpXYZ(point_list[1], point_list[2], t)
- end
- function GameMath.LerpXYZ(from,to,t)
-
- local x = GameMath.Lerp(from.x,to.x,t)
- local y = GameMath.Lerp(from.y,to.y,t)
- local z = GameMath.Lerp(from.z,to.z,t)
-
- return co.TableXYZ(x,y,z)
- end
- function GameMath.GetDistanceXYZ(p1x,p1y,p1z,p2x,p2y,p2z)
- local x_step = p1x - p2x
- local y_step = p1y - p2y
- local z_step = p1z - p2z
- local val = x_step*x_step + y_step*y_step + z_step*z_step
-
- return math.pow(val,0.5)
- end
-
- function GameMath.IsPointInDiamondRect(point,A,B,C,D)
- local a = (B.x - A.x) * (point.y - A.y) - (B.y - A.y) * (point.x - A.x)
- local b = (C.x - B.x) * (point.y - B.y) - (C.y - B.y) * (point.x - B.x)
- local c = (D.x - C.x) * (point.y - C.y) - (D.y - C.y) * (point.x - C.x)
- local d = (A.x - D.x) * (point.y - D.y) - (A.y - D.y) * (point.x - D.x)
-
- if (a > 0 and b > 0 and c > 0 and d > 0) or (a < 0 and b < 0 and c < 0 and d < 0) then
- return true
- end
-
- return false
- end
- -- 判断点是否在多边形
- function GameMath.IsPointInPolygonRect(checkPoint,polygonPoints)
- local inside = false
- local pointCount = #polygonPoints
- local p1,p2
- local i,j = 1,pointCount
- for i = 1,pointCount do
- p1 = polygonPoints[i]
- p2 = polygonPoints[j]
- if checkPoint.y < p2.y then
- if p1.y <= checkPoint.y then
- if ((checkPoint.y - p1.y) * (p2.x - p1.x) > (checkPoint.x - p1.x) * (p2.y - p1.y)) then
- inside = not inside
- end
- end
- elseif checkPoint.y < p1.y then
- if ((checkPoint.y - p1.y) * (p2.x - p1.x) < (checkPoint.x - p1.x) * (p2.y - p1.y)) then
- inside = not inside
- end
- end
- j = i
- end
- return inside
- end
- --判断直线 AB 是否与线段CD 相交
- function GameMath.LineIntersectSide(A,B,C,D)
- local fC = (C.y - A.y) * (A.x - B.x) - (C.x - A.x) * (A.y - B.y)
- local fD = (D.y - A.y) * (A.x - B.x) - (D.x - A.x) * (A.y - B.y)
-
- if fC * fD > 0 then
- return false
- end
-
- return true
- end
-
- local GameMath_LineIntersectSide = GameMath.LineIntersectSide
-
- function GameMath.SideIntersectSide(A,B,C,D)
- if not GameMath_LineIntersectSide(A,B,C,D) then
- return false
- end
- if not GameMath_LineIntersectSide(C,D,A,B) then
- return false
- end
- return true
- end
-
- function GameMath.PreciseDecimal(num, n)
-
- n = n or 0
- local nDecimal = 1/(10 ^ n)
- local nLeft = num % nDecimal
- local ret_val = num - nLeft
-
- if nLeft*(10^n) >= 0.5 then
- ret_val = ret_val + nDecimal
- end
-
- return ret_val
- end
-
- --两个向量之间的线性插值
- function GameMath.GetVecLerp( v1, v2, alpha )
- local result = {}
- result.x = v1.x*(1 - alpha) + v2.x*alpha
- result.y = v1.y*(1 - alpha) + v2.y*alpha
- return result
- end
-
- function GameMath.PointRotate( p1, p2 )
- local result = {}
- result.x = p1.x*p2.x - p1.y*p2.y
- result.y = p1.x*p2.y + p1.y*p2.x
- return result
- end
-
- --vec向量以pivot为中心旋转angle角
- function GameMath.RotateByAngle( vec, pivot, angle )
- local Rad2Deg = 57.29578
- angle = angle/Rad2Deg
- local vec_angle = {x=math.cos(angle), y=math.sin(angle)}
- local result = {}
- result.x = vec.x - pivot.x
- result.y = vec.y - pivot.y
- result = GameMath.PointRotate(result, vec_angle)
- result.x = result.x + pivot.x
- result.y = result.y + pivot.y
- return result
- end
|