diff --git a/sjplayer/src/sjplayer/CircleElement.d b/sjplayer/src/sjplayer/CircleElement.d index b801555..783eb99 100644 --- a/sjplayer/src/sjplayer/CircleElement.d +++ b/sjplayer/src/sjplayer/CircleElement.d @@ -7,7 +7,8 @@ import std.algorithm, import gl4d; import sjplayer.ElementDrawer, - sjplayer.ElementInterface; + sjplayer.ElementInterface, + sjplayer.util.linalg; /// class CircleElement : ElementInterface { @@ -36,34 +37,14 @@ class CircleElement : ElementInterface { if (!alive) return DamageCalculationResult(0, 0); const m = matrix.inverse; - const a = (m * vec3(p1, 1)).xy; const b = (m * vec3(p2, 1)).xy; - const s = b - a; + const d = CalculateDistanceOriginAndLineSegment(a, b); - const s_length = s.length; - if (s_length == 0) { - // TODO: nearness calculation - return DamageCalculationResult(a.length < 1? damage: 0, 0); + if (d <= 1) { + return DamageCalculationResult(damage, 0); } - - const d = cross(vec3(s, 0), vec3(a, 0)).length / s_length; - if (d > 1) { - const nearness = (1 - (d-1).min(1f)).pow(2); - return DamageCalculationResult(0, nearness * nearness_coe); - } - - const a_length = a.length; - const b_length = b.length; - - const hit = - a.dot(s) * b.dot(s) <= 0 || - a_length < 1 || - b_length < 1; - if (hit) return DamageCalculationResult(damage, 0); - - // TODO: nearness calculation - return DamageCalculationResult(0, 0); + return DamageCalculationResult(0, 1 - (d-1).clamp(0, 1)); } /// diff --git a/sjplayer/src/sjplayer/util/linalg.d b/sjplayer/src/sjplayer/util/linalg.d new file mode 100644 index 0000000..83196ac --- /dev/null +++ b/sjplayer/src/sjplayer/util/linalg.d @@ -0,0 +1,32 @@ +/// License: MIT +module sjplayer.util.linalg; + +import std.algorithm; + +import gl4d; + +/// +float CalculateDistanceOriginAndLineSegment(vec2 a, vec2 b) { + const s = b - a; + const s_len = s.length; + + if (s_len == 0) return a.length; + + if (dot(a, s) * dot(b, s) < 0) { + return cross(vec3(s, 0), vec3(a, 0)).length / s_len; + } + return min(a.length, b.length); +} +/// +unittest { + import std; + assert(CalculateDistanceOriginAndLineSegment( + vec2(0, 0), vec2(0, 0)).approxEqual(0f)); + + assert(CalculateDistanceOriginAndLineSegment( + vec2(-1, 1), vec2(1, 1)).approxEqual(1f)); + assert(CalculateDistanceOriginAndLineSegment( + vec2(1, 1), vec2(2, 1)).approxEqual(sqrt(2f))); + assert(CalculateDistanceOriginAndLineSegment( + vec2(-2, 1), vec2(-1, 1)).approxEqual(sqrt(2f))); +}