源战役客户端
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

449 Zeilen
11 KiB

  1. GameMath = GameMath or {}
  2. local GameMath = GameMath
  3. local math = math
  4. function GameMath.IsPointNear(p1x, p1y, p2x, p2y, near_val)
  5. near_val = near_val or 1.0
  6. local x_step = p1x - p2x
  7. local y_step = p1y - p2y
  8. local val = x_step*x_step + y_step*y_step
  9. return val <= near_val*near_val
  10. end
  11. --检查两个点是否在x或y方向上接近
  12. --用来判断p2是否在距离p1
  13. function GameMath.IsPointNearRect(p1x, p1y, p2x, p2y, near_val)
  14. if math.abs(p1x - p2x) > near_val then
  15. return false
  16. end
  17. if math.abs(p1y - p2y) > near_val then
  18. return false
  19. end
  20. return true
  21. end
  22. function GameMath.IsPointNearAbs(p1, p2, val)
  23. val = val or 1
  24. return (math.abs(p1.x - p2.x) <= val) and (math.abs(p1.y - p2.y) <= val)
  25. end
  26. function GameMath.Round(x)
  27. local val, pt = math.modf(x)
  28. if pt > 0.5 then
  29. val = val + 1
  30. end
  31. return val
  32. end
  33. --检测某点是否处于矩形内
  34. function GameMath.IsInRect(px, py, rect_x, rect_y, rect_width, rect_height)
  35. if px < rect_x - rect_width / 2 or px >= rect_x + rect_width / 2
  36. or py < rect_y - rect_height / 2 or py >= rect_y + rect_height / 2 then
  37. return false
  38. end
  39. return true
  40. end
  41. --检测某点是否处于矩形内
  42. function GameMath.HitRectTest(px, py, rect_x, rect_y, rect_width, rect_height)
  43. if px < rect_x or px >= rect_x + rect_width
  44. or py < rect_y or py >= rect_y + rect_height then
  45. return false
  46. end
  47. return true
  48. end
  49. --检测某点o是否a,b,c,d四个点组成的菱形内
  50. function GameMath.inDiamond(o, a, b, c, d)
  51. local l1 = co.Vector2(a.x - o.x,a.y - o.y)
  52. local l2 = co.Vector2(b.x - o.x,b.y - o.y)
  53. local l3 = co.Vector2(c.x - o.x,c.y - o.y)
  54. local l4 = co.Vector2(d.x - o.x,d.y - o.y)
  55. l1:normalise()
  56. l2:normalise()
  57. l3:normalise()
  58. l4:normalise()
  59. local total_degree = 0
  60. total_degree = total_degree + math.acos(l2:dotProduct(l1))
  61. total_degree = total_degree + math.acos(l3:dotProduct(l2))
  62. total_degree = total_degree + math.acos(l4:dotProduct(l3))
  63. total_degree = total_degree + math.acos(l1:dotProduct(l4))
  64. if math.abs(total_degree / 2 - math.pi) <= 0.001 then
  65. return true
  66. end
  67. return false
  68. end
  69. --[[
  70. @param need_sqrt
  71. @x_mult,y_mult 1x_mult,y_mult倍 1x_mult,y_mult倍
  72. ]]--
  73. function GameMath.GetDistance(p1x, p1y, p2x, p2y, need_sqrt,x_mult,y_mult)
  74. local x_step_mult = x_mult or 1
  75. local y_step_mult = y_mult or 1
  76. local x_step = p1x - p2x
  77. local y_step = p1y - p2y
  78. local val = x_step*x_step*x_step_mult + y_step*y_step*y_step_mult
  79. if need_sqrt then
  80. return math.pow(val,0.5)
  81. end
  82. return val
  83. end
  84. --[[
  85. @param need_sqrt
  86. @x_mult,y_mult 1x_mult,y_mult倍 1x_mult,y_mult倍
  87. ]]--
  88. function GameMath.GetDistance3D(p1x, p1y,p1z,p2x, p2y,p2z, need_sqrt,x_mult,y_mult)
  89. local x_step_mult = x_mult or 1
  90. local y_step_mult = y_mult or 1
  91. local x_step = p1x - p2x
  92. local y_step = p1y - p2y
  93. local val = x_step*x_step*x_step_mult + y_step*y_step*y_step_mult
  94. if need_sqrt then
  95. return math.pow(val,0.5)
  96. end
  97. return val
  98. end
  99. --[[
  100. @param need_sqrt
  101. ]]--
  102. function GameMath.GetEllipseDistance(p1x, p1y, p2x, p2y, need_sqrt)
  103. local x_step = p1x - p2x
  104. local y_step = p1y - p2y
  105. local val = x_step*x_step + y_step*y_step * 4
  106. if need_sqrt then
  107. return math.pow(val,0.5)
  108. end
  109. return val
  110. end
  111. --把正圆的值转化成椭圆不同方向的值
  112. function GameMath.ChangeEllipseValue(dir, value, ratio, type)
  113. if dir then
  114. ratio = ratio or 0.5
  115. local radian = 0
  116. if dir.x == 0 then
  117. if dir.y > 0 then
  118. radian = 90 / 180 * math.pi
  119. elseif dir.y == 0 then
  120. radian = 0
  121. elseif dir.y < 0 then
  122. radian = -270 / 180 * math.pi
  123. end
  124. else
  125. radian = math.atan(dir.y / dir.x) --先计算夹角
  126. end
  127. local func = nil
  128. if type == nil or type == 1 then --1为x方向较长 2 为y方向较长的椭圆
  129. func = math.cos
  130. else
  131. func = math.sin
  132. end
  133. --椭圆处理
  134. return value * ratio + math.abs(func(radian)) * value * (1 - ratio)
  135. else
  136. return value
  137. end
  138. end
  139. --[[
  140. @param point_list
  141. @param px x坐标
  142. @param py y坐标
  143. @param get_point_func return x,y
  144. ]]--
  145. function GameMath.GetNearestPoint(point_list,px,py,get_point_func)
  146. local result
  147. local prev_distance = -1
  148. for _, point in pairs(point_list) do
  149. local curr_distance
  150. if get_point_handler == nil then
  151. curr_distance = GameMath.GetDistance(px, py, point.x, point.y)
  152. else
  153. curr_distance = GameMath.GetDistance(px, py, get_point_func(point))
  154. end
  155. if prev_distance == -1 or prev_distance > curr_distance then
  156. result = point
  157. prev_distance = curr_distance
  158. end
  159. end
  160. return result
  161. end
  162. --判断点和直线的距离
  163. function GameMath.DistancePointToLine(dir, pos, need_sqrt)
  164. local x0, y0 = pos.x, pos.y --目标点相对于直线起点的相对坐标
  165. local A, B = dir.y, -dir.x --直线方程的系数
  166. local d1 = (A*x0 + B*y0)
  167. local d = (d1*d1) / (A*A + B*B) --目标点和直线的距离的平方
  168. if need_sqrt then
  169. d = math.pow(d, 0.5)
  170. end
  171. return d
  172. end
  173. --二维角度值转成二维标准向量
  174. function GameMath.AngleToDirection(angle)
  175. local radian = angle / 180 * math.pi
  176. local dir = co.TableXY(math.cos(radian), math.sin(radian))
  177. co.NormaliseXYTable(dir)
  178. return dir
  179. end
  180. function GameMath.Smooth(from, to, vel, smoothTime, timeDelta)
  181. local omega = 2.0 / smoothTime
  182. local x = omega * timeDelta
  183. local exp = 1.0 / (1.0 + x + 0.48*x*x + 0.235*x*x*x)
  184. local change = from - to
  185. local temp = (vel + change * omega) * timeDelta
  186. local new_vel = (vel - temp * omega) * exp
  187. vel = new_vel
  188. return to + (change + temp) * exp, vel
  189. end
  190. function GameMath.Lerp(from,to,t)
  191. if t > 1 then
  192. t = 1
  193. elseif t < 0 then
  194. t = 0
  195. end
  196. local delta = to - from
  197. return from + delta * t
  198. end
  199. function GameMath.EaseOutQuad(from,to,value)
  200. to = to - from
  201. return -to * value * (value - 2) + from
  202. end
  203. function GameMath.EaseInQuad(from,to,value)
  204. to = to - from
  205. return to * value * value + from
  206. end
  207. function GameMath.EaseInOutQuad(from,to,value)
  208. value = value /0.5
  209. to = to - from
  210. if (value < 1) then return to * 0.5 * value * value + from end
  211. value = value - 1
  212. return - to * 0.5 * (value * (value - 2) - 1) + from
  213. end
  214. function GameMath.EaseInOutQuart(from,to,value)
  215. value = value /0.5
  216. to = to - from
  217. if (value < 1) then return to * 0.5 * value * value * value + from end
  218. value = value - 1
  219. return - to * 0.5 * (value * value * (value - 2) - 1) + from
  220. end
  221. function GameMath.EaseInOutCubic(from,to,value)
  222. value = value /0.5
  223. to = to - from
  224. if value < 1 then
  225. return to * 0.5 * value * value * value + from
  226. end
  227. value = value - 2
  228. return to * 0.5 * (value * value * value + 2) + from
  229. end
  230. --获取中心点为x, y, 半径为dist的圆上的一个点
  231. function GameMath.GetPosByCeterPoint(x, y, dist)
  232. local angle = math.random(0, 360)
  233. local dir = GameMath.AngleToDirection(angle)
  234. local end_pos = co.TableXY((x + dir.x * dist), (y + dir.y * dist))
  235. return end_pos
  236. end
  237. --[[
  238. /**
  239. *p1,p2连线上位置为pp的垂线上的某点线l
  240. * @param p1
  241. * @param p2
  242. * @param pp 01p1到p2连线上的位置
  243. * @param l p1,p2连线的距离
  244. */ ]]
  245. function GameMath.GetVerticlePoint(p1, p2, pp, l)
  246. local offset_x = p2.x-p1.x == 0 and 1 or p2.x-p1.x
  247. local dir = co.Vector2((p1.y-p2.y)/offset_x, 1)
  248. dir:normalise()
  249. local p3 = p1 * (1-pp) + p2 * pp
  250. p3 = p3 + dir * l
  251. return p3
  252. end
  253. function GameMath.Bezier(list, t)
  254. local point_list = DeepCopy(list)
  255. local function lerp_xyz(from,to,t)
  256. local x = GameMath.Lerp(from.x,to.x,t)
  257. local y = GameMath.Lerp(from.y,to.y,t)
  258. local z = GameMath.Lerp(from.z,to.z,t)
  259. from.x = x
  260. from.y = y
  261. from.z = z
  262. return from
  263. end
  264. local function calc_fun()
  265. local lenth = #point_list
  266. for i = 1, lenth-1 do
  267. point_list[i] = lerp_xyz(point_list[i], point_list[i+1], t)
  268. end
  269. point_list[lenth] = nil
  270. end
  271. while #point_list > 2 do
  272. calc_fun()
  273. end
  274. return GameMath.LerpXYZ(point_list[1], point_list[2], t)
  275. end
  276. function GameMath.LerpXYZ(from,to,t)
  277. local x = GameMath.Lerp(from.x,to.x,t)
  278. local y = GameMath.Lerp(from.y,to.y,t)
  279. local z = GameMath.Lerp(from.z,to.z,t)
  280. return co.TableXYZ(x,y,z)
  281. end
  282. function GameMath.GetDistanceXYZ(p1x,p1y,p1z,p2x,p2y,p2z)
  283. local x_step = p1x - p2x
  284. local y_step = p1y - p2y
  285. local z_step = p1z - p2z
  286. local val = x_step*x_step + y_step*y_step + z_step*z_step
  287. return math.pow(val,0.5)
  288. end
  289. function GameMath.IsPointInDiamondRect(point,A,B,C,D)
  290. local a = (B.x - A.x) * (point.y - A.y) - (B.y - A.y) * (point.x - A.x)
  291. local b = (C.x - B.x) * (point.y - B.y) - (C.y - B.y) * (point.x - B.x)
  292. local c = (D.x - C.x) * (point.y - C.y) - (D.y - C.y) * (point.x - C.x)
  293. local d = (A.x - D.x) * (point.y - D.y) - (A.y - D.y) * (point.x - D.x)
  294. 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
  295. return true
  296. end
  297. return false
  298. end
  299. -- 判断点是否在多边形
  300. function GameMath.IsPointInPolygonRect(checkPoint,polygonPoints)
  301. local inside = false
  302. local pointCount = #polygonPoints
  303. local p1,p2
  304. local i,j = 1,pointCount
  305. for i = 1,pointCount do
  306. p1 = polygonPoints[i]
  307. p2 = polygonPoints[j]
  308. if checkPoint.y < p2.y then
  309. if p1.y <= checkPoint.y then
  310. if ((checkPoint.y - p1.y) * (p2.x - p1.x) > (checkPoint.x - p1.x) * (p2.y - p1.y)) then
  311. inside = not inside
  312. end
  313. end
  314. elseif checkPoint.y < p1.y then
  315. if ((checkPoint.y - p1.y) * (p2.x - p1.x) < (checkPoint.x - p1.x) * (p2.y - p1.y)) then
  316. inside = not inside
  317. end
  318. end
  319. j = i
  320. end
  321. return inside
  322. end
  323. --判断直线 AB 是否与线段CD 相交
  324. function GameMath.LineIntersectSide(A,B,C,D)
  325. local fC = (C.y - A.y) * (A.x - B.x) - (C.x - A.x) * (A.y - B.y)
  326. local fD = (D.y - A.y) * (A.x - B.x) - (D.x - A.x) * (A.y - B.y)
  327. if fC * fD > 0 then
  328. return false
  329. end
  330. return true
  331. end
  332. local GameMath_LineIntersectSide = GameMath.LineIntersectSide
  333. function GameMath.SideIntersectSide(A,B,C,D)
  334. if not GameMath_LineIntersectSide(A,B,C,D) then
  335. return false
  336. end
  337. if not GameMath_LineIntersectSide(C,D,A,B) then
  338. return false
  339. end
  340. return true
  341. end
  342. function GameMath.PreciseDecimal(num, n)
  343. n = n or 0
  344. local nDecimal = 1/(10 ^ n)
  345. local nLeft = num % nDecimal
  346. local ret_val = num - nLeft
  347. if nLeft*(10^n) >= 0.5 then
  348. ret_val = ret_val + nDecimal
  349. end
  350. return ret_val
  351. end
  352. --两个向量之间的线性插值
  353. function GameMath.GetVecLerp( v1, v2, alpha )
  354. local result = {}
  355. result.x = v1.x*(1 - alpha) + v2.x*alpha
  356. result.y = v1.y*(1 - alpha) + v2.y*alpha
  357. return result
  358. end
  359. function GameMath.PointRotate( p1, p2 )
  360. local result = {}
  361. result.x = p1.x*p2.x - p1.y*p2.y
  362. result.y = p1.x*p2.y + p1.y*p2.x
  363. return result
  364. end
  365. --vec向量以pivot为中心旋转angle角
  366. function GameMath.RotateByAngle( vec, pivot, angle )
  367. local Rad2Deg = 57.29578
  368. angle = angle/Rad2Deg
  369. local vec_angle = {x=math.cos(angle), y=math.sin(angle)}
  370. local result = {}
  371. result.x = vec.x - pivot.x
  372. result.y = vec.y - pivot.y
  373. result = GameMath.PointRotate(result, vec_angle)
  374. result.x = result.x + pivot.x
  375. result.y = result.y + pivot.y
  376. return result
  377. end