@@ -139,6 +139,283 @@ bool TrajectoryPointer::Save(PhobosStreamWriter& Stm) const
139
139
140
140
// ------------------------------------------------------------------------------ //
141
141
142
+ // A rectangular shape with a custom width from the current frame to the next frame in length.
143
+ std::vector<CellClass*> PhobosTrajectoryType::GetCellsInProximityRadius (BulletClass* pBullet, Leptons trajectoryProximityRange)
144
+ {
145
+ // Seems like the y-axis is reversed, but it's okay.
146
+ const CoordStruct walkCoord { static_cast <int >(pBullet->Velocity .X ), static_cast <int >(pBullet->Velocity .Y ), 0 };
147
+ const auto sideMult = trajectoryProximityRange / walkCoord.Magnitude ();
148
+
149
+ const CoordStruct cor1Coord { static_cast <int >(walkCoord.Y * sideMult), static_cast <int >((-walkCoord.X ) * sideMult), 0 };
150
+ const CoordStruct cor4Coord { static_cast <int >((-walkCoord.Y ) * sideMult), static_cast <int >(walkCoord.X * sideMult), 0 };
151
+ const auto thisCell = CellClass::Coord2Cell (pBullet->Location );
152
+
153
+ auto cor1Cell = CellClass::Coord2Cell ((pBullet->Location + cor1Coord));
154
+ auto cor4Cell = CellClass::Coord2Cell ((pBullet->Location + cor4Coord));
155
+
156
+ const auto off1Cell = cor1Cell - thisCell;
157
+ const auto off4Cell = cor4Cell - thisCell;
158
+ const auto nextCell = CellClass::Coord2Cell ((pBullet->Location + walkCoord));
159
+
160
+ auto cor2Cell = nextCell + off1Cell;
161
+ auto cor3Cell = nextCell + off4Cell;
162
+
163
+ // Arrange the vertices of the rectangle in order from bottom to top.
164
+ int cornerIndex = 0 ;
165
+ CellStruct corner[4 ] = { cor1Cell, cor2Cell, cor3Cell, cor4Cell };
166
+
167
+ for (int i = 1 ; i < 4 ; ++i)
168
+ {
169
+ if (corner[cornerIndex].Y > corner[i].Y )
170
+ cornerIndex = i;
171
+ }
172
+
173
+ cor1Cell = corner[cornerIndex];
174
+ ++cornerIndex %= 4 ;
175
+ cor2Cell = corner[cornerIndex];
176
+ ++cornerIndex %= 4 ;
177
+ cor3Cell = corner[cornerIndex];
178
+ ++cornerIndex %= 4 ;
179
+ cor4Cell = corner[cornerIndex];
180
+
181
+ std::vector<CellStruct> recCells = PhobosTrajectoryType::GetCellsInRectangle (cor1Cell, cor4Cell, cor2Cell, cor3Cell);
182
+ std::vector<CellClass*> recCellClass;
183
+ recCellClass.reserve (recCells.size ());
184
+
185
+ for (const auto & pCells : recCells)
186
+ {
187
+ if (CellClass* pRecCell = MapClass::Instance->TryGetCellAt (pCells))
188
+ recCellClass.push_back (pRecCell);
189
+ }
190
+
191
+ return recCellClass;
192
+ }
193
+
194
+ // Can ONLY fill RECTANGLE. Record cells in the order of "draw left boundary, draw right boundary, fill middle, and move up one level".
195
+ std::vector<CellStruct> PhobosTrajectoryType::GetCellsInRectangle (CellStruct bottomStaCell, CellStruct leftMidCell, CellStruct rightMidCell, CellStruct topEndCell)
196
+ {
197
+ std::vector<CellStruct> recCells;
198
+ const auto cellNums = (std::abs (topEndCell.Y - bottomStaCell.Y ) + 1 ) * (std::abs (rightMidCell.X - leftMidCell.X ) + 1 );
199
+ recCells.reserve (cellNums);
200
+ recCells.push_back (bottomStaCell);
201
+
202
+ if (bottomStaCell == leftMidCell || bottomStaCell == rightMidCell) // A straight line
203
+ {
204
+ auto middleCurCell = bottomStaCell;
205
+
206
+ const auto middleTheDist = topEndCell - bottomStaCell;
207
+ const CellStruct middleTheUnit { static_cast <short >(Math::sgn (middleTheDist.X )), static_cast <short >(Math::sgn (middleTheDist.Y )) };
208
+ const CellStruct middleThePace { static_cast <short >(middleTheDist.X * middleTheUnit.X ), static_cast <short >(middleTheDist.Y * middleTheUnit.Y ) };
209
+ auto mTheCurN = static_cast <float >((middleThePace.Y - middleThePace.X ) / 2.0 );
210
+
211
+ while (middleCurCell != topEndCell)
212
+ {
213
+ if (mTheCurN > 0 )
214
+ {
215
+ mTheCurN -= middleThePace.X ;
216
+ middleCurCell.Y += middleTheUnit.Y ;
217
+ recCells.push_back (middleCurCell);
218
+ }
219
+ else if (mTheCurN < 0 )
220
+ {
221
+ mTheCurN += middleThePace.Y ;
222
+ middleCurCell.X += middleTheUnit.X ;
223
+ recCells.push_back (middleCurCell);
224
+ }
225
+ else
226
+ {
227
+ mTheCurN += middleThePace.Y - middleThePace.X ;
228
+ middleCurCell.X += middleTheUnit.X ;
229
+ recCells.push_back (middleCurCell);
230
+ middleCurCell.X -= middleTheUnit.X ;
231
+ middleCurCell.Y += middleTheUnit.Y ;
232
+ recCells.push_back (middleCurCell);
233
+ middleCurCell.X += middleTheUnit.X ;
234
+ recCells.push_back (middleCurCell);
235
+ }
236
+ }
237
+ }
238
+ else // Complete rectangle
239
+ {
240
+ auto leftCurCell = bottomStaCell;
241
+ auto rightCurCell = bottomStaCell;
242
+ auto middleCurCell = bottomStaCell;
243
+
244
+ bool leftNext = false ;
245
+ bool rightNext = false ;
246
+ bool leftSkip = false ;
247
+ bool rightSkip = false ;
248
+ bool leftContinue = false ;
249
+ bool rightContinue = false ;
250
+
251
+ const auto left1stDist = leftMidCell - bottomStaCell;
252
+ const CellStruct left1stUnit { static_cast <short >(Math::sgn (left1stDist.X )), static_cast <short >(Math::sgn (left1stDist.Y )) };
253
+ const CellStruct left1stPace { static_cast <short >(left1stDist.X * left1stUnit.X ), static_cast <short >(left1stDist.Y * left1stUnit.Y ) };
254
+ auto left1stCurN = static_cast <float >((left1stPace.Y - left1stPace.X ) / 2.0 );
255
+
256
+ const auto left2ndDist = topEndCell - leftMidCell;
257
+ const CellStruct left2ndUnit { static_cast <short >(Math::sgn (left2ndDist.X )), static_cast <short >(Math::sgn (left2ndDist.Y )) };
258
+ const CellStruct left2ndPace { static_cast <short >(left2ndDist.X * left2ndUnit.X ), static_cast <short >(left2ndDist.Y * left2ndUnit.Y ) };
259
+ auto left2ndCurN = static_cast <float >((left2ndPace.Y - left2ndPace.X ) / 2.0 );
260
+
261
+ const auto right1stDist = rightMidCell - bottomStaCell;
262
+ const CellStruct right1stUnit { static_cast <short >(Math::sgn (right1stDist.X )), static_cast <short >(Math::sgn (right1stDist.Y )) };
263
+ const CellStruct right1stPace { static_cast <short >(right1stDist.X * right1stUnit.X ), static_cast <short >(right1stDist.Y * right1stUnit.Y ) };
264
+ auto right1stCurN = static_cast <float >((right1stPace.Y - right1stPace.X ) / 2.0 );
265
+
266
+ const auto right2ndDist = topEndCell - rightMidCell;
267
+ const CellStruct right2ndUnit { static_cast <short >(Math::sgn (right2ndDist.X )), static_cast <short >(Math::sgn (right2ndDist.Y )) };
268
+ const CellStruct right2ndPace { static_cast <short >(right2ndDist.X * right2ndUnit.X ), static_cast <short >(right2ndDist.Y * right2ndUnit.Y ) };
269
+ auto right2ndCurN = static_cast <float >((right2ndPace.Y - right2ndPace.X ) / 2.0 );
270
+
271
+ while (leftCurCell != topEndCell || rightCurCell != topEndCell)
272
+ {
273
+ while (leftCurCell != topEndCell) // Left
274
+ {
275
+ if (!leftNext) // Bottom Left Side
276
+ {
277
+ if (left1stCurN > 0 )
278
+ {
279
+ left1stCurN -= left1stPace.X ;
280
+ leftCurCell.Y += left1stUnit.Y ;
281
+
282
+ if (leftCurCell == leftMidCell)
283
+ {
284
+ leftNext = true ;
285
+ }
286
+ else
287
+ {
288
+ recCells.push_back (leftCurCell);
289
+ break ;
290
+ }
291
+ }
292
+ else
293
+ {
294
+ left1stCurN += left1stPace.Y ;
295
+ leftCurCell.X += left1stUnit.X ;
296
+
297
+ if (leftCurCell == leftMidCell)
298
+ {
299
+ leftNext = true ;
300
+ leftSkip = true ;
301
+ }
302
+ }
303
+ }
304
+ else // Top Left Side
305
+ {
306
+ if (left2ndCurN >= 0 )
307
+ {
308
+ if (leftSkip)
309
+ {
310
+ leftSkip = false ;
311
+ left2ndCurN -= left2ndPace.X ;
312
+ leftCurCell.Y += left2ndUnit.Y ;
313
+ }
314
+ else
315
+ {
316
+ leftContinue = true ;
317
+ break ;
318
+ }
319
+ }
320
+ else
321
+ {
322
+ left2ndCurN += left2ndPace.Y ;
323
+ leftCurCell.X += left2ndUnit.X ;
324
+ }
325
+ }
326
+
327
+ if (leftCurCell != rightCurCell) // Avoid double counting cells.
328
+ recCells.push_back (leftCurCell);
329
+ }
330
+
331
+ while (rightCurCell != topEndCell) // Right
332
+ {
333
+ if (!rightNext) // Bottom Right Side
334
+ {
335
+ if (right1stCurN > 0 )
336
+ {
337
+ right1stCurN -= right1stPace.X ;
338
+ rightCurCell.Y += right1stUnit.Y ;
339
+
340
+ if (rightCurCell == rightMidCell)
341
+ {
342
+ rightNext = true ;
343
+ }
344
+ else
345
+ {
346
+ recCells.push_back (rightCurCell);
347
+ break ;
348
+ }
349
+ }
350
+ else
351
+ {
352
+ right1stCurN += right1stPace.Y ;
353
+ rightCurCell.X += right1stUnit.X ;
354
+
355
+ if (rightCurCell == rightMidCell)
356
+ {
357
+ rightNext = true ;
358
+ rightSkip = true ;
359
+ }
360
+ }
361
+ }
362
+ else // Top Right Side
363
+ {
364
+ if (right2ndCurN >= 0 )
365
+ {
366
+ if (rightSkip)
367
+ {
368
+ rightSkip = false ;
369
+ right2ndCurN -= right2ndPace.X ;
370
+ rightCurCell.Y += right2ndUnit.Y ;
371
+ }
372
+ else
373
+ {
374
+ rightContinue = true ;
375
+ break ;
376
+ }
377
+ }
378
+ else
379
+ {
380
+ right2ndCurN += right2ndPace.Y ;
381
+ rightCurCell.X += right2ndUnit.X ;
382
+ }
383
+ }
384
+
385
+ if (rightCurCell != leftCurCell) // Avoid double counting cells.
386
+ recCells.push_back (rightCurCell);
387
+ }
388
+
389
+ middleCurCell = leftCurCell;
390
+ middleCurCell.X += 1 ;
391
+
392
+ while (middleCurCell.X < rightCurCell.X ) // Center
393
+ {
394
+ recCells.push_back (middleCurCell);
395
+ middleCurCell.X += 1 ;
396
+ }
397
+
398
+ if (leftContinue) // Continue Top Left Side
399
+ {
400
+ leftContinue = false ;
401
+ left2ndCurN -= left2ndPace.X ;
402
+ leftCurCell.Y += left2ndUnit.Y ;
403
+ recCells.push_back (leftCurCell);
404
+ }
405
+
406
+ if (rightContinue) // Continue Top Right Side
407
+ {
408
+ rightContinue = false ;
409
+ right2ndCurN -= right2ndPace.X ;
410
+ rightCurCell.Y += right2ndUnit.Y ;
411
+ recCells.push_back (rightCurCell);
412
+ }
413
+ }
414
+ }
415
+
416
+ return recCells;
417
+ }
418
+
142
419
bool PhobosTrajectoryType::Load (PhobosStreamReader& Stm, bool RegisterForChange)
143
420
{
144
421
Stm
0 commit comments