WOWCube Docs logo
WOWCube Docs
Mission Control
Section Shortcuts
APIExamplesSourceWOWConnectChangelog
Filters
SDK and language defaults persist in cookies.
SDK version
Navigation Tree
Collapsed by default, focused on the active path.
Made byMcKay Seamons
GitHub
  1. Home
  2. Docs
  3. Source
  4. physics.inc
Mission NodeSDK 6.1Pawnphysics.inc

physics.inc

SDK Source File: physics.inc

Source / SDK 6.1 / Pawn / Core

physics.inc

physics.inc
CPP
1/****s* PawnLibs/physics/PHYSICS_CIRCLE_DATA
2 * Summary
3 * Array with named fields which represents a round object.
4 * Synopsis
5 */
6#define PHYSICS_CIRCLE_DATA .posX, .posY, .simplePosX, .simplePosY, .spdX, .spdY, .mass, .radius, .CoR, .module, .screen, .moduleT, .screenT,
7/*
8 * Description
9 * Fields:
10 * * posX - circle position on X axis (fixed point)
11 * * posY - circle position on Y axis (fixed point)
12 * * simplePosX - circle position on X axis
13 * * simplePosY - circle position on Y axis
14 * * spdX - circle X speed
15 * * spdY - circle Y speed
16 * * mass - circle mass (fixed point)
17 * * radius - circle radius
18 * * CoR - Coefficient of restitution (fixed point)
19 * * module - module owner of this circle
20 * * screen - screen owner of this circle
21 * * moduleT - module transfer, last module owner. Can be used for resending messages
22 * * screenT - screen transfer, last screen owner. Can be used for resending messages
23 ******/
24
25#include "math.inc"
26
27/****f* PawnLibs/physics/Physics_Overlap
28 * Summary
29 * TBD: inner function
30 * Synopsis
31 */
32stock Physics_Overlap(overlap, positionDifference, distance)
33/*
34 * Source
35 */
36{
37 if (distance != 0) {
38 return overlap * positionDifference / distance;
39 } else {
40 return overlap * positionDifference;
41 }
42}
43/******/
44
45/****f* PawnLibs/physics/Physics_Circle_Vs_Circle_obj
46 * Summary
47 * Check if there is a collision between two round objects.
48 * Synopsis
49 */
50stock Physics_Circle_Vs_Circle_obj(circle1[PHYSICS_CIRCLE_DATA], circle2[PHYSICS_CIRCLE_DATA])
51/*
52 * Inputs
53 * * circle1, circle2 - objects for whom collision is checked
54 * Return value
55 * True if collision happens, false otherwise.
56 * See also
57 * * Physics_Res_CvC_Coll_Mass()
58 * * Physics_Res_CvC_Coll_Massless()
59 * Source
60 */
61{
62 new r = (circle1.radius + circle2.radius) * (circle1.radius + circle2.radius);
63 return r > CheapDistance(circle1.simplePosX - circle2.simplePosX, circle1.simplePosY - circle2.simplePosY);
64}
65/******/
66
67/****f* PawnLibs/physics/Physics_Circle_vs_AABB_obj
68 * Summary
69 * Check if there is a collision between round object and the axis-aligned
70 * bounding box.
71 * Synopsis
72 */
73stock Physics_Circle_vs_AABB_obj(circle[PHYSICS_CIRCLE_DATA], rectX, rectY, rectWidth, rectHeight, fakeCircle[PHYSICS_CIRCLE_DATA] = 0)
74/*
75 * Inputs
76 * * circle - an object for whom collision is checked
77 * * rectX, rectY, - coordinates of the AABB object
78 * * rectWidth, rectHeight - dimensions of the AABB object
79 * Outputs
80 * * fakeCircle - collision point, can be used for resolving collision
81 * Return value
82 * True if collision happens, false otherwise.
83 * See also
84 * * Physics_Res_CvC_Coll_Mass()
85 * * Physics_Res_CvC_Coll_Massless()
86 * Source
87 */
88{
89 new x = Max(rectX, Min(circle.simplePosX, rectX + rectWidth));
90 new y = Max(rectY, Min(circle.simplePosY, rectY + rectHeight));
91 new distance = CheapDistance(x - circle.simplePosX, y - circle.simplePosY);
92 if (distance < (circle.radius * circle.radius)) {
93 fakeCircle.spdX = -circle.spdX;
94 fakeCircle.spdY = -circle.spdY;
95 fakeCircle.mass = (circle.mass * 230) >> 8;
96 fakeCircle.radius = 1;
97 fakeCircle.CoR = 256;
98
99 new dotProd = 0;
100
101 new toPointX = x - circle.simplePosX;
102 new toPointY = y - circle.simplePosY;
103
104 if ((x == circle.simplePosX) && (y == circle.simplePosY)) {
105 if (circle.spdX > 0) {
106 x = rectX;
107 } else {
108 x = rectX + rectWidth;
109 }
110 if (circle.spdY > 0) {
111 y = rectY;
112 } else {
113 y = rectY + rectHeight;
114 }
115 toPointX = circle.simplePosX - x;
116 toPointY = circle.simplePosY - y;
117 }
118 dotProd = Vector2D_Dot_Product(toPointX, toPointY, circle.spdX, circle.spdY);
119 fakeCircle.simplePosX = x;
120 fakeCircle.simplePosY = y;
121 // If not it's unnecessary do further calculations
122 return (dotProd > 0);
123 }
124 return 0;
125}
126/******/
127
128/****f* PawnLibs/physics/Physics_Circle_Vs_LineSegment
129 * Summary
130 * Check if there is a collision between round object and the line.
131 * Synopsis
132 */
133stock Physics_Circle_Vs_LineSegment(circle[PHYSICS_CIRCLE_DATA], lineSX, lineSY, lineEX, lineEY, fakeCircle[PHYSICS_CIRCLE_DATA] = 0)
134/*
135 * Inputs
136 * * circle - an object for whom collision is checked
137 * * lineSX, lineSY, lineEX, lineEY - the line start and end coordinates
138 * Outputs
139 * * fakeCircle - collision point, can be used for resolving collision
140 * Return value
141 * True if collision happens, false otherwise.
142 * See also
143 * * Physics_Res_CvC_Coll_Mass()
144 * * Physics_Res_CvC_Coll_Massless()
145 * Source
146 */
147{
148 new lineX1 = lineEX - lineSX;
149 new lineY1 = lineEY - lineSY;
150
151 new lineX2 = circle.simplePosX - lineSX;
152 new lineY2 = circle.simplePosY - lineSY;
153
154 new boundaryLength = lineX1 * lineX1 + lineY1 * lineY1;
155
156 // Sort of coeficient that shows how deep our circle penetrate line segment, values from 0 - 1 (in fixed point representation)
157 new t = (Max(0, Min(boundaryLength, (lineX1 * lineX2 + lineY1 * lineY2))) << 8) / boundaryLength;
158
159 new closestPointX = lineSX + (t * lineX1 >> 8);
160 new closestPointY = lineSY + (t * lineY1 >> 8);
161
162 new distance = Distance(circle.simplePosX - closestPointX, circle.simplePosY - closestPointY);
163
164 // 1 is thickness of line segment
165 if (distance <= (circle.radius + 1)) {
166
167 // We treat collision point as a unmoveble circle
168 fakeCircle.simplePosX = closestPointX;
169 fakeCircle.simplePosY = closestPointY;
170 // Need to make a bounce
171 fakeCircle.spdX = -circle.spdX;
172 fakeCircle.spdY = -circle.spdY;
173 fakeCircle.mass = (circle.mass * 230) >> 8;
174 fakeCircle.radius = 1;
175 fakeCircle.CoR = 256;
176
177 // Find if we moving toward the segment
178 new dotProd = 0;
179 if ((lineX1 * lineY2 - lineX2 * lineY1) > 0) {
180 // Left
181 dotProd = Vector2D_Dot_Product(-lineY1, lineX1, circle.spdX, circle.spdY);
182 } else {
183 // Right
184 dotProd = Vector2D_Dot_Product(lineY1, -lineX1, circle.spdX, circle.spdY);
185 }
186
187 // If not it's unnecessary do further calculations
188 return (dotProd < 0);
189 }
190 return 0;
191}
192/******/
193
194/****f* PawnLibs/physics/Physics_Res_CvC_Coll_Massless
195 * Summary
196 * Resolve collision without mass.
197 * Synopsis
198 */
199stock Physics_Res_CvC_Coll_Massless(circle1[PHYSICS_CIRCLE_DATA], circle2[PHYSICS_CIRCLE_DATA])
200/*
201 * Outputs
202 * * circle1, circle2 - objects for whom collision is resolved
203 * See also
204 * * Physics_Res_CvC_Coll_Mass()
205 * Source
206 */
207{
208
209 new diffX = circle1.simplePosX - circle2.simplePosX;
210 new diffY = circle1.simplePosY - circle2.simplePosY;
211
212 new magnitude = Distance(diffX, diffY);
213
214 // Overlap
215 new overlap = ((magnitude - circle1.radius - circle2.radius) >> 1) + 1;
216
217 circle1.posX = (circle1.simplePosX -= Physics_Overlap(overlap, diffX, magnitude)) << 8;
218 circle1.posY = (circle1.simplePosY -= Physics_Overlap(overlap, diffY, magnitude)) << 8;
219 circle2.posX = (circle2.simplePosX += Physics_Overlap(overlap, diffX, magnitude)) << 8;
220 circle2.posY = (circle2.simplePosY += Physics_Overlap(overlap, diffY, magnitude)) << 8;
221
222 // Normal
223 if (magnitude == 0) {
224 magnitude = 1;
225 }
226 new normalX = ((diffX << 8) / magnitude);
227 new normalY = ((diffY << 8) / magnitude);
228
229 new relativeVelocityX = circle1.spdX - circle2.spdX;
230 new relativeVelocityY = circle1.spdY - circle2.spdY;
231
232 new speed = relativeVelocityX * normalX + relativeVelocityY * normalY;
233
234 circle1.spdX -= (speed * normalX) >> 16;
235 circle1.spdY -= (speed * normalY) >> 16;
236
237 circle2.spdX += (speed * normalX) >> 16;
238 circle2.spdY += (speed * normalY) >> 16;
239}
240/******/
241
242/****f* PawnLibs/physics/Physics_Res_CvC_Coll_Mass
243 * Summary
244 * Resolve collision with mass
245 * Synopsis
246 */
247stock Physics_Res_CvC_Coll_Mass(circle1[PHYSICS_CIRCLE_DATA], circle2[PHYSICS_CIRCLE_DATA])
248/*
249 * Outputs
250 * * circle1, circle2 - objects for whom collision is resolved
251 * See also
252 * * Physics_Res_CvC_Coll_Massless()
253 * Source
254 */
255{
256 new diffX = circle1.simplePosX - circle2.simplePosX;
257 new diffY = circle1.simplePosY - circle2.simplePosY;
258
259 new magnitude = Distance(diffX, diffY);
260
261 // Overlap
262 new overlap = ((magnitude - circle1.radius - circle2.radius) >> 1) + 1;
263
264 circle1.posX = (circle1.simplePosX -= Physics_Overlap(overlap, diffX, magnitude)) << 8;
265 circle1.posY = (circle1.simplePosY -= Physics_Overlap(overlap, diffY, magnitude)) << 8;
266
267 circle2.posX = (circle2.simplePosX += Physics_Overlap(overlap, diffX, magnitude)) << 8;
268 circle2.posY = (circle2.simplePosY += Physics_Overlap(overlap, diffY, magnitude)) << 8;
269
270 // Normal
271 if (magnitude == 0) {
272 magnitude = 1;
273 }
274 new normalX = (diffX << 8) / magnitude;
275 new normalY = (diffY << 8) / magnitude;
276
277 new relativeVelocityX = circle1.spdX - circle2.spdX;
278 new relativeVelocityY = circle1.spdY - circle2.spdY;
279
280 new speed = relativeVelocityX * normalX + relativeVelocityY * normalY;
281
282 speed = (speed * Min(circle1.CoR, circle2.CoR)) >> 8;
283
284 new impulse = ((speed << 1) << 8) / (circle1.mass + circle2.mass)
285
286 circle1.spdX -= ((impulse * circle2.mass >> 16) * normalX) >> 8;
287 circle1.spdY -= ((impulse * circle2.mass >> 16) * normalY) >> 8;
288
289 circle2.spdX += ((impulse * circle1.mass >> 16) * normalX) >> 8;
290 circle2.spdY += ((impulse * circle1.mass >> 16) * normalY) >> 8;
291}
292/******/
293
294/****f* PawnLibs/physics/Physics_DeserializeCircle
295 * Summary
296 * Deserialize circle object data received from network.
297 * Synopsis
298 */
299stock Physics_DeserializeCircle(serializedData_1, serializedData_2, circle[PHYSICS_CIRCLE_DATA])
300/*
301 * Inputs
302 * * serializedData_1, serializedData_2 - data to deserialize
303 * Outputs
304 * * circle - deserialized data
305 * See also
306 * * Physics_SerializeCircle()
307 * * ON_Message()
308 * Source
309 */
310{
311 new negativeFlags = serializedData_2 & 0xF;
312 circle.posY = (circle.simplePosY = ( serializedData_1 & 0xFF) * ((negativeFlags & 1) ? (-1) : (1))) << 8;
313 circle.posX = (circle.simplePosX = ((serializedData_1 >> 8) & 0xFF) * ((negativeFlags & 2) ? (-1) : (1))) << 8;
314 circle.spdY = ((serializedData_1 >> 16) & 0xFF) * ((negativeFlags & 4) ? (-1) : (1));
315 circle.spdX = ((serializedData_1 >> 24) & 0xFF) * ((negativeFlags & 8) ? (-1) : (1));
316 circle.mass = ((serializedData_2 >> 4) & 0xF) << 8;
317 circle.radius = ((serializedData_2 >> 8) & 0x3F);
318 circle.screen = ((serializedData_2 >> 14) & 0x3);
319 circle.module = ((serializedData_2 >> 16) & 0x7);
320 circle.screenT = ((serializedData_2 >> 19) & 0x3);
321 circle.moduleT = ((serializedData_2 >> 21) & 0x7);
322}
323/******/
324
325/****f* PawnLibs/physics/Physics_SerializeCircle
326 * Summary
327 * Serialize circle object data to send it over network.
328 * Synopsis
329 */
330stock Physics_SerializeCircle(obj[PHYSICS_CIRCLE_DATA], &serializedData_1, &serializedData_2)
331/*
332 * Inputs
333 * * obj - an object to serialize
334 * Outputs
335 * * serializedData_1, serializedData_2 - serialized data
336 * See also
337 * * Physics_DeserializeCircle()
338 * * broadcastMessage()
339 * Source
340 */
341{
342 new posX = obj.simplePosX;
343 new posY = obj.simplePosY;
344 new spdX = obj.spdX;
345 new spdY = obj.spdY;
346 new negativeFlags = 0;
347 if (posY < 0) {
348 posY = -posY;
349 negativeFlags |= 1;
350 }
351 if (posX < 0) {
352 posX = -posX;
353 negativeFlags |= 2;
354 }
355 if (spdY < 0) {
356 spdY = -spdY;
357 negativeFlags |= 4;
358 }
359 if (spdX < 0) {
360 spdX = -spdX;
361 negativeFlags |= 8;
362 }
363 serializedData_1 = (spdX << 24) | (spdY << 16) | (posX << 8) | posY;
364 serializedData_2 = (obj.moduleT << 21) | (obj.screenT << 19) | (obj.module << 16) | (obj.screen << 14) | (obj.radius << 8) | ((obj.mass >> 8) << 4) | negativeFlags
365}
366/******/
367
368
Wrapped for easier reading. Turn wrap off to inspect exact line lengths.
Context Rail

Related nodes

fixed.inc
Source / SDK 6.1 / Pawn / Core
graphics.inc
Source / SDK 6.1 / Pawn / Core
leaderboard.inc
Source / SDK 6.1 / Pawn / Core
log.inc
Source / SDK 6.1 / Pawn / Core
Previous Node
network.inc
Source / SDK 6.1 / Pawn / Core
Next Node
save.inc
Source / SDK 6.1 / Pawn / Core