设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 15172|回复: 87
打印 上一主题 下一主题

[RMVA发布] 全新配套ACT系统——开创RM潜力计划~~2016.11.13更新

[复制链接]

Lv3.寻梦者

梦石
0
星屑
4583
在线时间
1205 小时
注册时间
2016-4-7
帖子
982

开拓者

1
发表于 2016-9-15 12:39:00 | 显示全部楼层
嘛 代码直接上github好了
附庸的附庸不是我的附庸,女儿的女儿还是我的女儿。CK2沉迷ing
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
4583
在线时间
1205 小时
注册时间
2016-4-7
帖子
982

开拓者

2
发表于 2016-9-25 21:43:16 | 显示全部楼层
斜坡的碰撞是用三角形做的拟合?
附庸的附庸不是我的附庸,女儿的女儿还是我的女儿。CK2沉迷ing
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
4583
在线时间
1205 小时
注册时间
2016-4-7
帖子
982

开拓者

3
发表于 2016-9-26 00:49:37 | 显示全部楼层
本帖最后由 shitake 于 2016-9-27 00:10 编辑

RUBY 代码复制
  1. #encoding: utf-8
  2. #author: shitake
  3. #data: 16-9-26
  4.  
  5. class Range
  6.   # 判断两个范围是否相交。
  7.   def intersects(range)
  8.     !(self.last < range.first || self.first > range.last)
  9.   end
  10. end
  11.  
  12. module Math
  13.   def self.a2r(angle)
  14.     angle * Math::PI / 180 if angle.kind_of? Numeric
  15.   end
  16. end
  17.  
  18. # 表示二维坐标系上点的对象
  19. class Point
  20.  
  21.   attr_accessor :x
  22.   attr_accessor :y
  23.  
  24.   def initialize(x = 0, y = x)
  25.     @x = x
  26.     @y = y
  27.   end
  28.  
  29.   # 二维坐标下两点距离
  30.   def distance(point)
  31.     Math.hypot(@x - point.x, @y - point.y)
  32.   end
  33.  
  34.   # 二维坐标下两点解析距离
  35.   def distance_axis(point)
  36.     [point.x - @x,point.y - @y]
  37.   end
  38.  
  39.   def set(x = 0, y = x)
  40.     @x = x
  41.     @y = y
  42.   end
  43.  
  44. end
  45.  
  46. class Vector2
  47.  
  48.   attr_accessor :x
  49.   attr_accessor :y
  50.  
  51.   def initialize(x, y)
  52.     @x = x || 0
  53.     @y = y || 0
  54.   end
  55.  
  56.   #点乘
  57.   def dot_product(vector2)
  58.     @x * vector2.x + @y * vector2.y
  59.   end
  60.  
  61.   #模
  62.   def module
  63.     Math.hypot(@x, @y)
  64.   end
  65.  
  66. end
  67.  
  68. class Axes
  69.  
  70.   attr_accessor :origin
  71.   attr_accessor :radian
  72.   attr_reader :x
  73.   attr_reader :y
  74.  
  75.   #origin:原点,radian:偏转弧度
  76.   def initialize(origin, radian)
  77.     @origin = origin
  78.     @radian = radian
  79.     set_axes(@radian)
  80.   end
  81.  
  82.   def radian=(value)
  83.     return if @radian == value
  84.     @radian = value
  85.     set_axes(value)
  86.   end
  87.  
  88.   def set_axes(radian)
  89.     @x = Vector2.new(Math.cos(radian), Math.sin(radian))
  90.     @y = Vector2.new(-1 * Math.sin(radian), Math.cos(radian))
  91.   end
  92.  
  93.   #返回逆坐标系
  94.   def a_axes
  95.     Axes.new(Point.new(- @origin.x, - @origin.y), -radian)
  96.   end
  97.  
  98.   #返回向量在当前坐标系下的投影
  99.   def shadow(vector2)
  100.     x = vector2.dot_product(@x)
  101.     y = vector2.dot_product(@y)
  102.     Vector2.new(x, y)
  103.   end
  104.  
  105.   #返回点在当前坐标系下的坐标
  106.   def point(point)
  107.     vector2 = shadow(Vector2.new(point.x - @origin.x, point.y - @origin.y))
  108.     Point.new(vector2.x, vector2.y)
  109.   end
  110.  
  111. end
  112.  
  113. class AABB
  114.  
  115.   attr_reader :x
  116.   attr_reader :y
  117.   attr_reader :width
  118.   attr_reader :height
  119.   attr_reader :center
  120.   attr_reader :width_range
  121.   attr_reader :height_range
  122.  
  123.   def initialize(x = 0, y = 0, width = 0, height = 0)
  124.     @x = x
  125.     @y = y
  126.     @width = width
  127.     @height = height
  128.     create
  129.   end
  130.  
  131.   def create
  132.     @width_range = Range.new(@x, @x + @width)
  133.     @height_range = Range.new(@y, @y + @height)
  134.     @center = Point.new(@width_range / 2, @height_range / 2)
  135.   end
  136.  
  137.   def points
  138.     [
  139.         Point.new(@x, @y), #左上
  140.         Point.new(@x + @width, @y), #右上
  141.         Point.new(@x, @y + @height), #左下
  142.         Point.new(@x + @width, @y + @height) #右下
  143.     ]
  144.   end
  145.  
  146.   def x=(value)
  147.     return if @x == value
  148.     @x = value
  149.     create
  150.   end
  151.  
  152.   def y=(value)
  153.     return if @y == value
  154.     @y = value
  155.     create
  156.   end
  157.  
  158.   def width=(value)
  159.     return if @width == value
  160.     @width = value
  161.     create
  162.   end
  163.  
  164.   def height=(value)
  165.     return if @height == value
  166.     @height = value
  167.     create
  168.   end
  169.  
  170.   def collision(obj)
  171.     case obj.class
  172.       when Point
  173.         point_collision(obj)
  174.       when AABB
  175.         aabb_collision(obj)
  176.       when OBB
  177.         obb_collision(obj)
  178.       when Sphere
  179.         sphere_collision(obj)
  180.       else
  181.         raise "TypeError:不正确类型#{obj.class}!"
  182.     end
  183.   end
  184.  
  185.   # point 相交测试
  186.   def point_collision(point)
  187.     @width_range.eql?(point.x) && @height_range.eql?(point.y)
  188.   end
  189.  
  190.   # aabb 相交测试
  191.   def aabb_collision(aabb)
  192.     @width_range.intersects(aabb.width_range) && @height_range.intersects(aabb.height_range)
  193.   end
  194.  
  195.   # obb 相交测试
  196.   def obb_collision(obb)
  197.     return aabb_collision(obb.obb2aabb) if obb.angle % 90 == 0
  198.     obb.obb_collision(aabb2obb)
  199.   end
  200.  
  201.   def sphere_collision(sphere)
  202.     sphere.aabb_collision(self)
  203.   end
  204.  
  205.   def aabb2obb
  206.     OBB.new(@center, @width, @height, 0)
  207.   end
  208.  
  209.   def aabb2sphere
  210.     radius = Math.sqrt((@width / 2) ** 2 + (@height / 2) ** 2).ceil
  211.     Sphere.new(@x, @y, radius)
  212.   end
  213.  
  214. end
  215.  
  216. class OBB
  217.  
  218.   attr_reader :center
  219.   attr_reader :width
  220.   attr_reader :height
  221.   attr_reader :angle
  222.   attr_reader :width_range
  223.   attr_reader :height_range
  224.   attr_reader :center
  225.   attr_reader :axes
  226.  
  227.   def initialize(center, width = 0, height = 0, angle)
  228.     @center = center
  229.     @width = width
  230.     @height = height
  231.     value = angle % 360
  232.     @angle = value > 180 ? value - 180 : value
  233.     create
  234.   end
  235.  
  236.  
  237.  
  238.   def create
  239.     @axes = Axes.new(@center, Math.a2r(@angle))
  240.     @width_range = Range(-@width / 2, @width / 2)
  241.     @height_range = Range(-@height / 2, @height / 2)
  242.   end
  243.  
  244.   def center=(value)
  245.     return if @center == value
  246.     @center = value
  247.     create
  248.   end
  249.  
  250.   def width=(value)
  251.     return if @width == value
  252.     @width = value
  253.     create
  254.   end
  255.  
  256.   def height=(value)
  257.     return if @height == value
  258.     @height = value
  259.     create
  260.   end
  261.  
  262.   def radian=(value)
  263.     value = value % 360
  264.     return if @angle == (value > 180 ? value - 180 : value)
  265.     @angle = value
  266.     create
  267.   end
  268.  
  269.   def points
  270.     [
  271.         Point.new(@center.x - @width / 2, @center.y - @height / 2),
  272.         Point.new(@center.x - @width / 2, @center.y + @height / 2),
  273.         Point.new(@center.x + @width / 2, @center.y - @height / 2),
  274.         Point.new(@center.x + @width / 2, @center.y + @height / 2),
  275.     ]
  276.   end
  277.  
  278.   def collision(obj)
  279.     case obj.class
  280.       when Point
  281.         point_collision(obj)
  282.       when AABB
  283.         aabb_collision(obj)
  284.       when OBB
  285.         obb_collision(obj)
  286.       when Sphere
  287.         sphere_collision(obj)
  288.       else
  289.         raise "TypeError:不正确类型#{obj.class}!"
  290.     end
  291.   end
  292.  
  293.   # point 相交测试
  294.   def point_collision(point)
  295.     point = @axes.point(point)
  296.     width_range.eql?(point.x) && height_range.eql?(point.y)
  297.   end
  298.  
  299.   # aabb 相交测试
  300.   def aabb_collision(aabb)
  301.     aabb.obb_collision(self)
  302.   end
  303.  
  304.   # obb 相交测试,分离轴定理
  305.   def obb_collision(obb)
  306.     this_in_obb_center = obb.axes.point(@center)
  307.     obb_in_this_center = axes.point(obb.center)
  308.     ow_range = Range.new(obb_in_this_center.x - obb.width / 2, obb_in_this_center.x + obb.width / 2)
  309.     oh_range = Range.new(obb_in_this_center.y - obb.height / 2, obb_in_this_center.y + obb.height / 2)
  310.     w_o_range = Range.new(this_in_obb_center.x - @width / 2, this_in_obb_center.x + @width / 2)
  311.     h_o_range = Range.new(obb_in_this_center.y - @height / 2, obb_in_this_center.y + @height / 2)
  312.     width_range.intersects(ow_range) && height_range.intersects(oh_range) && obb.width_range.intersects(w_o_range) && obb.height_range.intersects(h_o_range)
  313.   end
  314.  
  315.   def sphere_collision(sphere)
  316.     sphere.obb_collision(self)
  317.   end
  318.  
  319.   def obb2aabb
  320.     return AABB.new(@center.x - @width / 2, @center.y, @width, @height) if @radian == 0
  321.     return AABB.new(@center.x - @height / 2, @center.y, @height, @width) if @angle == 90 && @angle == 180
  322.     AABB.new(points.min_by(&:x), points.min_by(&:y), points.max_by(&:x), points.max_by(&:y))
  323.   end
  324.  
  325.   def obb2sphere
  326.     radius = Math.sqrt((@width / 2) ** 2 + (@height / 2) ** 2).ceil
  327.     Sphere.new(@center.x, @center.y, radius)
  328.   end
  329.  
  330. end
  331.  
  332. class Sphere
  333.  
  334.   attr_reader :x
  335.   attr_reader :y
  336.   attr_reader :radius
  337.   attr_reader :center
  338.   attr_reader :width_range
  339.   attr_reader :height_range
  340.  
  341.   def initialize(x, y, radius)
  342.     @x = x
  343.     @y = y
  344.     @radius = radius
  345.     create
  346.   end
  347.  
  348.   def x=(value)
  349.     return if @x == value
  350.     @x = value
  351.     create
  352.   end
  353.  
  354.   def y=(value)
  355.     return if @y == value
  356.     @y = value
  357.     create
  358.   end
  359.  
  360.   def radius=(value)
  361.     return if @radius == value
  362.     @radius = value
  363.     create
  364.   end
  365.  
  366.   def create
  367.     @center = Point.new(@x, @y)
  368.     @width_range = Range.new(@x - @radius, @x + @radius)
  369.     @height_range = Range.new(@y - @radius, @y + @radius)
  370.   end
  371.  
  372.   def collision(obj)
  373.     case obj.class
  374.       when Point
  375.         point_collision(obj)
  376.       when AABB
  377.         aabb_collision(obj)
  378.       when OBB
  379.         obb_collision(obj)
  380.       when Sphere
  381.         sphere_collision(obj)
  382.       else
  383.         raise "TypeError:不正确类型#{obj.class}!"
  384.     end
  385.   end
  386.  
  387.   def point_collision(point)
  388.     (point.x - @x) ** 2 + (point.y - @y) ** 2 <= @radius ** 2
  389.   end
  390.  
  391.   def sphere_collision(sphere)
  392.     point_collision(sphere.point)
  393.   end
  394.  
  395.   def aabb_collision(aabb)
  396.     # [url]http://www.zhihu.com/question/24251545/answer/27184960[/url]
  397.     vx, vy = (@x - aabb.center.x).abs,(@y - aabb.center.y).abs
  398.     hx, hy = (aabb.points[1].x - aabb.center.x).abs, (aabb.points[1].y - aabb.center.y).abs
  399.     ux = vx - hx > 0 ? vx - hx : 0
  400.     uy = vy - hy > 0 ? vy - hy : 0
  401.     ux ** 2 + uy ** 2 <= @radius ** 2
  402.   end
  403.  
  404.   def obb_collision(obb)
  405.     point = obb.axes.point(@center)
  406.     vx, vy = point.x.abs, point.y.abs
  407.     hx, hy = obb.width / 2, obb.height / 2
  408.     ux = vx - hx > 0 ? vx - hx : 0
  409.     uy = vy - hy > 0 ? vy - hy : 0
  410.     ux ** 2 + uy ** 2 <= @radius ** 2
  411.   end
  412.  
  413.   def sphere2aabb
  414.     AABB.new(@x - @radius, @y - @radius, @radius * 2, @radius * 2)
  415.   end
  416.  
  417.   def sphere2obb
  418.     sphere2aabb.aabb2obb
  419.   end
  420.  
  421. end

2D的aabb和obb的简单实现ORZ
碰撞检测部分可略做参考


9.27 更新 添加 Sphere

点评

呸 说错,obb是分离轴定理(SAT这个也能做多边形凸包,只不过运算时间随边数是指数级增长的)  发表于 2016-9-27 00:15
更复杂的还有GJK,方法更通用(任意多边形凸包)只不过我一直没太搞懂support函数(http://www.dyn4j.org/2010/04/gjk-gilbert-johnson-keerthi/)  发表于 2016-9-27 00:05
方法的话AABB和你的应该一样,obb就是简单的轴向分离法(http://www.cnblogs.com/iamzhanglei/archive/2012/06/07/2539751.html)  发表于 2016-9-27 00:04
已更新,添加Sphere。代码长一是因为面向对象,接口实现就得写不少。二是多了一些东西(比如vector2/axes等)  发表于 2016-9-27 00:02
不过也谢谢你的意见啦,以后有意见还请多多提出来,我会参考每个人的意见来做这个系统的。  发表于 2016-9-26 11:08

评分

参与人数 1星屑 +260 收起 理由
丿梁丶小柒 + 260 我很赞同

查看全部评分

附庸的附庸不是我的附庸,女儿的女儿还是我的女儿。CK2沉迷ing
回复 支持 1 反对 0

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-5-6 17:38

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表