回到clojure,我写了这个小东西来检查两个盒子是否发生碰撞,检查一个盒子的顶点是否在另一个盒子里面:
(defn around
[val radius]
(let [half (/ radius 2)
low (- val half)
high (+ val half)]
[low high]))
(defn colliding?
[this that]
(let [[this-x1 this-x2] (around (:x this) (:w this))
[this-y1 this-y2] (around (:y this) (:h this))
[this-z1 this-z2] (around (:z this) (:l this))
[that-x1 that-x2] (around (:x that) (:w that))
[that-y1 that-y2] (around (:y that) (:h that))
[that-z1 that-z2] (around (:z that) (:l that))]
(or (and (or (<= that-x1 this-x1 that-x2)
(<= that-x1 this-x2 that-x2))
(or (<= that-y1 this-y1 that-y2)
(<= that-y1 this-y2 that-y2))
(or (<= that-z1 this-z1 that-z2)
(<= that-z1 this-z2 that-z2)))
(and (or (<= this-x1 that-x1 this-x2)
(<= this-x1 that-x2 this-x2))
(or (<= this-y1 that-y1 this-y2)
(<= this-y1 that-y2 this-y2))
(or (<= this-z1 that-z1 this-z2)
(<= this-z1 that-z2 this-z2))))))
由于重复,这闻起来很糟糕,但我不确定清理它的最佳方法是什么。有更好的方法吗?
答案 0 :(得分:1)
您可以使用在一个方向上发生碰撞的事实来简化代码,除非一个对象的起始坐标高于另一个对象的结束坐标。 即足够的测试是
(not (or (> this-x1 that-x2)
(> that-x1 this-x2)))
相当于
(and (<= this-x1 that-x2)
(<= that-x1 this-x2))
使用此功能,您的colliding?
可能会简化为
(defn colliding?
[this that]
(let [[this-x1 this-x2] (around (:x this) (:w this))
[this-y1 this-y2] (around (:y this) (:h this))
[this-z1 this-z2] (around (:z this) (:l this))
[that-x1 that-x2] (around (:x that) (:w that))
[that-y1 that-y2] (around (:y that) (:h that))
[that-z1 that-z2] (around (:z that) (:l that))]
(and (<= this-x1 that-x2)
(<= that-x1 this-x2)
(<= this-y1 that-y2)
(<= that-y1 this-y2)
(<= this-z1 that-z2)
(<= that-z1 this-z2))))
如果您然后分解出检查一维中重叠的函数conflicting?
,
(defn conflicting?
[this that coordinate size]
(let [[this-c1 this-c2] (around (coordinate this) (size this))
[that-c1 that-c2] (around (coordinate that) (size that))]
(and (<= this-c1 that-c2)
(<= that-c1 this-c2)))
通过使用尺寸和大小的映射可以进一步简化 colliding?
:
(defn colliding?
[this that]
(every? true? (map #(conflicting? this that %1 %2)
[:x :y :z]
[:w :h :l])))
修改强>
此外,conflicting?
可以简化为
(defn conflicting?
[this that coordinate size]
(<= (math/abs (- (coordinate this) (coordinate that)))
(/ (+ (size this) (size that)) 2)))
使函数around
过时以便检测冲突。