• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

excaliburjs / Excalibur / 14804036802

02 May 2025 09:58PM UTC coverage: 5.927% (-83.4%) from 89.28%
14804036802

Pull #3404

github

web-flow
Merge 5c103d7f8 into 0f2ccaeb2
Pull Request #3404: feat: added Graph module to Math

234 of 8383 branches covered (2.79%)

229 of 246 new or added lines in 1 file covered. (93.09%)

13145 existing lines in 208 files now uncovered.

934 of 15759 relevant lines covered (5.93%)

4.72 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/engine/Debug/DebugConfig.ts
1
import { ColorBlindFlags } from './DebugFlags';
2
import { Engine } from '../Engine';
3
import { Color } from '../Color';
4
import { CollisionContact } from '../Collision/Detection/CollisionContact';
5
import { StandardClock, TestClock } from '../Util/Clock';
6

7
/**
8
 * Debug stats containing current and previous frame statistics
9
 */
10
export interface DebugStats {
11
  currFrame: FrameStats;
12
  prevFrame: FrameStats;
13
}
14

15
/**
16
 * Represents a frame's individual statistics
17
 */
18
export interface FrameStatistics {
19
  /**
20
   * The number of the frame
21
   */
22
  id: number;
23

24
  /**
25
   * Gets the frame's delta (time since last frame scaled by {@apilink Engine.timescale}) (in ms)
26
   *
27
   * Excalibur extension depends on this
28
   */
29
  elapsedMs: number;
30

31
  /**
32
   * Gets the frame's frames-per-second (FPS)
33
   */
34
  fps: number;
35

36
  /**
37
   * Duration statistics (in ms)
38
   */
39
  duration: FrameDurationStats;
40

41
  /**
42
   * Actor statistics
43
   */
44
  actors: FrameActorStats;
45

46
  /**
47
   * Physics statistics
48
   */
49
  physics: PhysicsStatistics;
50

51
  /**
52
   * Graphics statistics
53
   */
54
  graphics: GraphicsStatistics;
55
}
56

57
/**
58
 * Represents actor stats for a frame
59
 */
60
export interface FrameActorStats {
61
  /**
62
   * Gets the frame's number of actors (alive)
63
   */
64
  alive: number;
65

66
  /**
67
   * Gets the frame's number of actors (killed)
68
   */
69
  killed: number;
70

71
  /**
72
   * Gets the frame's number of remaining actors (alive - killed)
73
   */
74
  remaining: number;
75

76
  /**
77
   * Gets the frame's number of UI actors
78
   */
79
  ui: number;
80

81
  /**
82
   * Gets the frame's number of total actors (remaining + UI)
83
   */
84
  total: number;
85
}
86

87
/**
88
 * Represents duration stats for a frame
89
 */
90
export interface FrameDurationStats {
91
  /**
92
   * Gets the frame's total time to run the update function (in ms)
93
   */
94
  update: number;
95

96
  /**
97
   * Gets the frame's total time to run the draw function (in ms)
98
   */
99
  draw: number;
100

101
  /**
102
   * Gets the frame's total render duration (update + draw duration) (in ms)
103
   */
104
  total: number;
105
}
106

107
/**
108
 * Represents physics stats for the current frame
109
 */
110
export interface PhysicsStatistics {
111
  /**
112
   * Gets the number of broadphase collision pairs which
113
   */
114
  pairs: number;
115

116
  /**
117
   * Gets the number of actual collisions
118
   */
119
  collisions: number;
120

121
  /**
122
   * Copy of the current frame contacts (only updated if debug is toggled on)
123
   */
124
  contacts: Map<string, CollisionContact>;
125

126
  /**
127
   * Gets the number of fast moving bodies using raycast continuous collisions in the scene
128
   */
129
  fastBodies: number;
130

131
  /**
132
   * Gets the number of bodies that had a fast body collision resolution
133
   */
134
  fastBodyCollisions: number;
135

136
  /**
137
   * Gets the time it took to calculate the broadphase pairs
138
   */
139
  broadphase: number;
140

141
  /**
142
   * Gets the time it took to calculate the narrowphase
143
   */
144
  narrowphase: number;
145
}
146

147
export interface GraphicsStatistics {
148
  drawCalls: number;
149
  drawnImages: number;
150
}
151

152
/**
153
 * Debug statistics and flags for Excalibur. If polling these values, it would be
154
 * best to do so on the `postupdate` event for {@apilink Engine}, after all values have been
155
 * updated during a frame.
156
 */
157
export class DebugConfig {
158
  private _engine: Engine;
159

160
  constructor(engine: Engine) {
UNCOV
161
    this._engine = engine;
×
162

UNCOV
163
    this.colorBlindMode = new ColorBlindFlags(this._engine);
×
164
  }
165

166
  /**
167
   * Switch the current excalibur clock with the {@apilink TestClock} and return
168
   * it in the same running state.
169
   *
170
   * This is useful when you need to debug frame by frame.
171
   */
172
  public useTestClock(): TestClock {
UNCOV
173
    const clock = this._engine.clock;
×
UNCOV
174
    const wasRunning = clock.isRunning();
×
UNCOV
175
    clock.stop();
×
176

UNCOV
177
    const testClock = clock.toTestClock();
×
UNCOV
178
    if (wasRunning) {
×
179
      testClock.start();
×
180
    }
UNCOV
181
    this._engine.clock = testClock;
×
UNCOV
182
    return testClock;
×
183
  }
184

185
  /**
186
   * Switch the current excalibur clock with the {@apilink StandardClock} and
187
   * return it in the same running state.
188
   *
189
   * This is useful when you need to switch back to normal mode after
190
   * debugging.
191
   */
192
  public useStandardClock(): StandardClock {
UNCOV
193
    const currentClock = this._engine.clock;
×
UNCOV
194
    const wasRunning = currentClock.isRunning();
×
UNCOV
195
    currentClock.stop();
×
196

UNCOV
197
    const standardClock = currentClock.toStandardClock();
×
UNCOV
198
    if (wasRunning) {
×
199
      standardClock.start();
×
200
    }
UNCOV
201
    this._engine.clock = standardClock;
×
UNCOV
202
    return standardClock;
×
203
  }
204

205
  /**
206
   * Performance statistics
207
   */
UNCOV
208
  public stats: DebugStats = {
×
209
    /**
210
     * Current frame statistics. Engine reuses this instance, use {@apilink FrameStats.clone} to copy frame stats.
211
     * Best accessed on {@apilink postframe} event. See {@apilink FrameStats}
212
     */
213
    currFrame: new FrameStats(),
214

215
    /**
216
     * Previous frame statistics. Engine reuses this instance, use {@apilink FrameStats.clone} to copy frame stats.
217
     * Best accessed on {@apilink preframe} event. Best inspected on engine event `preframe`. See {@apilink FrameStats}
218
     */
219
    prevFrame: new FrameStats()
220
  };
221

222
  /**
223
   * Correct or simulate color blindness using {@apilink ColorBlindnessPostProcessor}.
224
   * @warning Will reduce FPS.
225
   */
226
  public colorBlindMode: ColorBlindFlags;
227

228
  /**
229
   * Filter debug context to named entities or entity ids
230
   */
UNCOV
231
  public filter: { useFilter: boolean; nameQuery: string; ids: number[] } = {
×
232
    /**
233
     * Toggle filter on or off (default off) must be on for DebugDraw to use filters
234
     */
235
    useFilter: false,
236
    /**
237
     * Query for entities by name, if the entity name contains `nameQuery` it will be included
238
     */
239
    nameQuery: '',
240
    /**
241
     * Query for Entity ids, if the id matches it will be included
242
     */
243
    ids: []
244
  };
245

246
  /**
247
   * Entity debug settings
248
   */
UNCOV
249
  public entity = {
×
250
    showAll: false,
251
    showId: false,
252
    showName: false
253
  };
254

255
  /**
256
   * Transform component debug settings
257
   */
UNCOV
258
  public transform = {
×
259
    showAll: false,
260

261
    debugZIndex: 10_000_000,
262
    showPosition: false,
263
    showPositionLabel: false,
264
    positionColor: Color.Yellow,
265

266
    showZIndex: false,
267

268
    showScale: false,
269
    scaleColor: Color.Green,
270

271
    showRotation: false,
272
    rotationColor: Color.Blue
273
  };
274

275
  /**
276
   * Graphics component debug settings
277
   */
UNCOV
278
  public graphics = {
×
279
    showAll: false,
280

281
    showBounds: false,
282
    boundsColor: Color.Yellow
283
  };
284

285
  /**
286
   * Collider component debug settings
287
   */
UNCOV
288
  public collider = {
×
289
    showAll: false,
290

291
    showBounds: false,
292
    boundsColor: Color.Blue,
293

294
    showOwner: false,
295

296
    showGeometry: true,
297
    geometryColor: Color.Green,
298
    geometryLineWidth: 1,
299
    geometryPointSize: 0.5
300
  };
301

302
  /**
303
   * Physics simulation debug settings
304
   */
UNCOV
305
  public physics = {
×
306
    showAll: false,
307

308
    showBroadphaseSpacePartitionDebug: false,
309

310
    showCollisionNormals: false,
311
    collisionNormalColor: Color.Cyan,
312

313
    showCollisionContacts: true,
314
    contactSize: 2,
315
    collisionContactColor: Color.Red
316
  };
317

318
  /**
319
   * Motion component debug settings
320
   */
UNCOV
321
  public motion = {
×
322
    showAll: false,
323

324
    showVelocity: false,
325
    velocityColor: Color.Yellow,
326

327
    showAcceleration: false,
328
    accelerationColor: Color.Red
329
  };
330

331
  /**
332
   * Body component debug settings
333
   */
UNCOV
334
  public body = {
×
335
    showAll: false,
336

337
    showCollisionGroup: false,
338
    showCollisionType: false,
339
    showSleeping: false,
340
    showMotion: false,
341
    showMass: false
342
  };
343

344
  /**
345
   * Camera debug settings
346
   */
UNCOV
347
  public camera = {
×
348
    showAll: false,
349

350
    showFocus: false,
351
    focusColor: Color.Red,
352

353
    showZoom: false
354
  };
355

UNCOV
356
  public tilemap = {
×
357
    showAll: false,
358

359
    showGrid: false,
360
    gridColor: Color.Red,
361
    gridWidth: 0.5,
362
    showSolidBounds: false,
363
    solidBoundsColor: Color.fromHex('#8080807F'), // grayish
364
    showColliderGeometry: true
365
  };
366

UNCOV
367
  public isometric = {
×
368
    showAll: false,
369
    showPosition: false,
370
    positionColor: Color.Yellow,
371
    positionSize: 1,
372
    showGrid: false,
373
    gridColor: Color.Red,
374
    gridWidth: 1,
375
    showColliderGeometry: true
376
  };
377
}
378

379
/**
380
 * Implementation of a frame's stats. Meant to have values copied via {@apilink FrameStats.reset}, avoid
381
 * creating instances of this every frame.
382
 */
383
export class FrameStats implements FrameStatistics {
UNCOV
384
  private _id: number = 0;
×
UNCOV
385
  private _elapsedMs: number = 0;
×
UNCOV
386
  private _fps: number = 0;
×
UNCOV
387
  private _actorStats: FrameActorStats = {
×
388
    alive: 0,
389
    killed: 0,
390
    ui: 0,
391
    get remaining() {
UNCOV
392
      return this.alive - this.killed;
×
393
    },
394
    get total() {
UNCOV
395
      return this.remaining + this.ui;
×
396
    }
397
  };
UNCOV
398
  private _durationStats: FrameDurationStats = {
×
399
    update: 0,
400
    draw: 0,
401
    get total() {
UNCOV
402
      return this.update + this.draw;
×
403
    }
404
  };
405

UNCOV
406
  private _physicsStats: PhysicsStats = new PhysicsStats();
×
407

UNCOV
408
  private _graphicsStats: GraphicsStatistics = {
×
409
    drawCalls: 0,
410
    drawnImages: 0
411
  };
412

413
  /**
414
   * Zero out values or clone other IFrameStat stats. Allows instance reuse.
415
   * @param [otherStats] Optional stats to clone
416
   */
417
  public reset(otherStats?: FrameStatistics) {
UNCOV
418
    if (otherStats) {
×
UNCOV
419
      this.id = otherStats.id;
×
UNCOV
420
      this.elapsedMs = otherStats.elapsedMs;
×
UNCOV
421
      this.fps = otherStats.fps;
×
UNCOV
422
      this.actors.alive = otherStats.actors.alive;
×
UNCOV
423
      this.actors.killed = otherStats.actors.killed;
×
UNCOV
424
      this.actors.ui = otherStats.actors.ui;
×
UNCOV
425
      this.duration.update = otherStats.duration.update;
×
UNCOV
426
      this.duration.draw = otherStats.duration.draw;
×
UNCOV
427
      this._physicsStats.reset(otherStats.physics);
×
UNCOV
428
      this.graphics.drawCalls = otherStats.graphics.drawCalls;
×
UNCOV
429
      this.graphics.drawnImages = otherStats.graphics.drawnImages;
×
430
    } else {
UNCOV
431
      this.id = this.elapsedMs = this.fps = 0;
×
UNCOV
432
      this.actors.alive = this.actors.killed = this.actors.ui = 0;
×
UNCOV
433
      this.duration.update = this.duration.draw = 0;
×
UNCOV
434
      this._physicsStats.reset();
×
UNCOV
435
      this.graphics.drawnImages = this.graphics.drawCalls = 0;
×
436
    }
437
  }
438

439
  /**
440
   * Provides a clone of this instance.
441
   */
442
  public clone(): FrameStats {
UNCOV
443
    const fs = new FrameStats();
×
444

UNCOV
445
    fs.reset(this);
×
446

UNCOV
447
    return fs;
×
448
  }
449

450
  /**
451
   * Gets the frame's id
452
   */
453
  public get id() {
UNCOV
454
    return this._id;
×
455
  }
456

457
  /**
458
   * Sets the frame's id
459
   */
460
  public set id(value: number) {
UNCOV
461
    this._id = value;
×
462
  }
463

464
  /**
465
   * Gets the frame's delta (time since last frame)
466
   */
467
  public get elapsedMs() {
UNCOV
468
    return this._elapsedMs;
×
469
  }
470

471
  /**
472
   * Sets the frame's delta (time since last frame). Internal use only.
473
   * @internal
474
   */
475
  public set elapsedMs(value: number) {
UNCOV
476
    this._elapsedMs = value;
×
477
  }
478

479
  /**
480
   * Gets the frame's frames-per-second (FPS)
481
   */
482
  public get fps() {
UNCOV
483
    return this._fps;
×
484
  }
485

486
  /**
487
   * Sets the frame's frames-per-second (FPS). Internal use only.
488
   * @internal
489
   */
490
  public set fps(value: number) {
UNCOV
491
    this._fps = value;
×
492
  }
493

494
  /**
495
   * Gets the frame's actor statistics
496
   */
497
  public get actors() {
UNCOV
498
    return this._actorStats;
×
499
  }
500

501
  /**
502
   * Gets the frame's duration statistics
503
   */
504
  public get duration() {
UNCOV
505
    return this._durationStats;
×
506
  }
507

508
  /**
509
   * Gets the frame's physics statistics
510
   */
511
  public get physics() {
UNCOV
512
    return this._physicsStats;
×
513
  }
514

515
  /**
516
   * Gets the frame's graphics statistics
517
   */
518
  public get graphics() {
UNCOV
519
    return this._graphicsStats;
×
520
  }
521
}
522

523
export class PhysicsStats implements PhysicsStatistics {
UNCOV
524
  private _pairs: number = 0;
×
UNCOV
525
  private _collisions: number = 0;
×
UNCOV
526
  private _contacts: Map<string, CollisionContact> = new Map();
×
UNCOV
527
  private _fastBodies: number = 0;
×
UNCOV
528
  private _fastBodyCollisions: number = 0;
×
UNCOV
529
  private _broadphase: number = 0;
×
UNCOV
530
  private _narrowphase: number = 0;
×
531

532
  /**
533
   * Zero out values or clone other IPhysicsStats stats. Allows instance reuse.
534
   * @param [otherStats] Optional stats to clone
535
   */
536
  public reset(otherStats?: PhysicsStatistics) {
UNCOV
537
    if (otherStats) {
×
UNCOV
538
      this.pairs = otherStats.pairs;
×
UNCOV
539
      this.collisions = otherStats.collisions;
×
UNCOV
540
      this.contacts = otherStats.contacts;
×
UNCOV
541
      this.fastBodies = otherStats.fastBodies;
×
UNCOV
542
      this.fastBodyCollisions = otherStats.fastBodyCollisions;
×
UNCOV
543
      this.broadphase = otherStats.broadphase;
×
UNCOV
544
      this.narrowphase = otherStats.narrowphase;
×
545
    } else {
UNCOV
546
      this.pairs = this.collisions = this.fastBodies = 0;
×
UNCOV
547
      this.fastBodyCollisions = this.broadphase = this.narrowphase = 0;
×
UNCOV
548
      this.contacts.clear();
×
549
    }
550
  }
551

552
  /**
553
   * Provides a clone of this instance.
554
   */
555
  public clone(): PhysicsStatistics {
556
    const ps = new PhysicsStats();
×
557

558
    ps.reset(this);
×
559

560
    return ps;
×
561
  }
562

563
  public get pairs(): number {
UNCOV
564
    return this._pairs;
×
565
  }
566

567
  public set pairs(value: number) {
UNCOV
568
    this._pairs = value;
×
569
  }
570

571
  public get collisions(): number {
UNCOV
572
    return this._collisions;
×
573
  }
574

575
  public set collisions(value: number) {
UNCOV
576
    this._collisions = value;
×
577
  }
578

579
  public get contacts(): Map<string, CollisionContact> {
UNCOV
580
    return this._contacts;
×
581
  }
582

583
  public set contacts(contacts: Map<string, CollisionContact>) {
UNCOV
584
    this._contacts = contacts;
×
585
  }
586

587
  public get fastBodies(): number {
UNCOV
588
    return this._fastBodies;
×
589
  }
590

591
  public set fastBodies(value: number) {
UNCOV
592
    this._fastBodies = value;
×
593
  }
594

595
  public get fastBodyCollisions(): number {
UNCOV
596
    return this._fastBodyCollisions;
×
597
  }
598

599
  public set fastBodyCollisions(value: number) {
UNCOV
600
    this._fastBodyCollisions = value;
×
601
  }
602

603
  public get broadphase(): number {
UNCOV
604
    return this._broadphase;
×
605
  }
606

607
  public set broadphase(value: number) {
UNCOV
608
    this._broadphase = value;
×
609
  }
610

611
  public get narrowphase(): number {
UNCOV
612
    return this._narrowphase;
×
613
  }
614

615
  public set narrowphase(value: number) {
UNCOV
616
    this._narrowphase = value;
×
617
  }
618
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc