njin
Engine 2D gọn nhẹ để tự tay làm game theo ý mình. Vibe coding cũng ổn luôn
Loading...
Searching...
No Matches
_collide.h
1#pragma once
2#include "_math.h"
3
4namespace njin {
7
12struct contact {
13 bool hit = false;
15 f32 depth = 0.0f;
16};
17
23constexpr bool point_in_rect(vec2 p, rect r) {
24 return p.x >= r.pos.x && p.x < r.pos.x + r.size.x && p.y >= r.pos.y &&
25 p.y < r.pos.y + r.size.y;
26}
27
32constexpr bool point_in_circle(vec2 p, circle c) {
33 return length_sq(p - c.center) <= c.radius * c.radius;
34}
35
40constexpr bool rects_overlap(rect a, rect b) {
41 return a.pos.x < b.pos.x + b.size.x && b.pos.x < a.pos.x + a.size.x &&
42 a.pos.y < b.pos.y + b.size.y && b.pos.y < a.pos.y + a.size.y;
43}
44
49constexpr bool circles_overlap(circle a, circle b) {
50 const f32 r = a.radius + b.radius;
51 return length_sq(b.center - a.center) < r * r;
52}
53
58constexpr vec2 closest_point(rect r, vec2 p) {
59 return clamp(p, r.pos, r.pos + r.size);
60}
61
66constexpr bool circle_rect_overlap(circle c, rect r) {
67 return length_sq(c.center - closest_point(r, c.center)) < c.radius * c.radius;
68}
69
75 const f32 x0 = a.pos.x > b.pos.x ? a.pos.x : b.pos.x;
76 const f32 y0 = a.pos.y > b.pos.y ? a.pos.y : b.pos.y;
77 const f32 x1 = a.pos.x + a.size.x < b.pos.x + b.size.x ? a.pos.x + a.size.x
78 : b.pos.x + b.size.x;
79 const f32 y1 = a.pos.y + a.size.y < b.pos.y + b.size.y ? a.pos.y + a.size.y
80 : b.pos.y + b.size.y;
81 if (x1 <= x0 || y1 <= y0)
82 return rect{{x0, y0}, {0.0f, 0.0f}};
83 return rect{{x0, y0}, {x1 - x0, y1 - y0}};
84}
85
90constexpr contact collide_rects(rect a, rect b) {
91 if (!rects_overlap(a, b))
92 return {};
93 const vec2 ca = rect_center(a);
94 const vec2 cb = rect_center(b);
95 const f32 ox = (a.size.x + b.size.x) * 0.5f - (ca.x > cb.x ? ca.x - cb.x : cb.x - ca.x);
96 const f32 oy = (a.size.y + b.size.y) * 0.5f - (ca.y > cb.y ? ca.y - cb.y : cb.y - ca.y);
97 if (ox < oy)
98 return {true, {ca.x < cb.x ? -1.0f : 1.0f, 0.0f}, ox};
99 return {true, {0.0f, ca.y < cb.y ? -1.0f : 1.0f}, oy};
100}
101
107 const vec2 d = a.center - b.center;
108 const f32 r = a.radius + b.radius;
109 const f32 dist_sq = length_sq(d);
110 if (dist_sq >= r * r)
111 return {};
112 const f32 dist = std::sqrt(dist_sq);
113 // Trùng tâm: không có hướng nào tự nhiên, chọn lên trên.
114 const vec2 n = dist > 0.0f ? d / dist : vec2{0.0f, -1.0f};
115 return {true, n, r - dist};
116}
117
123 const vec2 p = closest_point(r, c.center);
124 const vec2 d = c.center - p;
125 const f32 dist_sq = length_sq(d);
126 if (dist_sq >= c.radius * c.radius)
127 return {};
128 if (dist_sq > 0.0f) {
129 const f32 dist = std::sqrt(dist_sq);
130 return {true, d / dist, c.radius - dist};
131 }
132 // Tâm nằm trong hình chữ nhật: đẩy ra theo cạnh gần nhất.
133 const f32 left = c.center.x - r.pos.x;
134 const f32 right = r.pos.x + r.size.x - c.center.x;
135 const f32 top = c.center.y - r.pos.y;
136 const f32 bottom = r.pos.y + r.size.y - c.center.y;
137 f32 best = left;
138 vec2 n{-1.0f, 0.0f};
139 if (right < best) {
140 best = right;
141 n = {1.0f, 0.0f};
142 }
143 if (top < best) {
144 best = top;
145 n = {0.0f, -1.0f};
146 }
147 if (bottom < best) {
148 best = bottom;
149 n = {0.0f, 1.0f};
150 }
151 return {true, n, best + c.radius};
152}
153
158constexpr vec2 reflect(vec2 velocity, vec2 normal) {
159 return velocity - normal * (2.0f * dot(velocity, normal));
160}
161
162} // namespace njin
contact collide_circle_rect(circle c, rect r)
Va chạm hình tròn với hình chữ nhật.
Definition _collide.h:122
constexpr vec2 reflect(vec2 velocity, vec2 normal)
Phản xạ vận tốc qua một pháp tuyến, như bóng nảy khỏi tường.
Definition _collide.h:158
constexpr bool circles_overlap(circle a, circle b)
Hai hình tròn có chồng nhau không.
Definition _collide.h:49
constexpr bool rects_overlap(rect a, rect b)
Hai hình chữ nhật có chồng nhau không.
Definition _collide.h:40
constexpr bool point_in_circle(vec2 p, circle c)
Điểm có nằm trong hình tròn không.
Definition _collide.h:32
constexpr rect rect_intersection(rect a, rect b)
Phần giao của hai hình chữ nhật.
Definition _collide.h:74
contact collide_circles(circle a, circle b)
Va chạm hai hình tròn.
Definition _collide.h:106
constexpr bool circle_rect_overlap(circle c, rect r)
Hình tròn và hình chữ nhật có chồng nhau không.
Definition _collide.h:66
constexpr vec2 closest_point(rect r, vec2 p)
Điểm trong r gần p nhất.
Definition _collide.h:58
constexpr bool point_in_rect(vec2 p, rect r)
Điểm có nằm trong hình chữ nhật không.
Definition _collide.h:23
constexpr contact collide_rects(rect a, rect b)
Va chạm hai hình chữ nhật, đẩy a ra theo trục chồng ít nhất.
Definition _collide.h:90
constexpr f32 length_sq(vec2 v)
Bình phương độ dài.
Definition _math.h:58
constexpr f32 clamp(f32 v, f32 lo, f32 hi)
Giới hạn v trong khoảng [lo, hi].
Definition _math.h:165
constexpr f32 dot(vec2 a, vec2 b)
Tích vô hướng.
Definition _math.h:47
constexpr vec2 rect_center(rect r)
Tâm của hình chữ nhật.
Definition _math.h:222
float f32
Số thực 32 bit.
Definition _types.h:28
Hình tròn.
Definition _math.h:19
vec2 center
Tâm.
Definition _math.h:20
f32 radius
Bán kính.
Definition _math.h:21
Kết quả của một phép va chạm có đẩy ra.
Definition _collide.h:12
vec2 normal
Hướng đẩy vật thứ nhất ra, độ dài 1.
Definition _collide.h:14
bool hit
Hai hình có chồng nhau không.
Definition _collide.h:13
f32 depth
Độ sâu chồng nhau theo hướng normal.
Definition _collide.h:15
Hình chữ nhật thẳng trục: pos là góc trên trái, size là rộng và cao.
Definition _math.h:13
vec2 pos
Góc trên trái.
Definition _math.h:14
vec2 size
Chiều rộng (x) và chiều cao (y).
Definition _math.h:15
Vector 2 chiều. Dùng cho vị trí, kích thước, độ dời.
Definition _types.h:39
f32 y
Thành phần dọc (trong không gian màn hình, y tăng khi đi xuống).
Definition _types.h:41
f32 x
Thành phần ngang.
Definition _types.h:40