@where-stars-drift/core 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +143 -0
  3. package/dist/src/base/bounded-body.d.ts +8 -0
  4. package/dist/src/base/bounded-body.js +10 -0
  5. package/dist/src/base/celestial-body.d.ts +12 -0
  6. package/dist/src/base/celestial-body.js +11 -0
  7. package/dist/src/base/hoverable.d.ts +10 -0
  8. package/dist/src/base/hoverable.js +4 -0
  9. package/dist/src/base/massive-body.d.ts +8 -0
  10. package/dist/src/base/massive-body.js +10 -0
  11. package/dist/src/config/effects.d.ts +14 -0
  12. package/dist/src/config/effects.js +14 -0
  13. package/dist/src/config/grid.d.ts +10 -0
  14. package/dist/src/config/grid.js +10 -0
  15. package/dist/src/config/panel.d.ts +26 -0
  16. package/dist/src/config/panel.js +26 -0
  17. package/dist/src/config/simulation.d.ts +21 -0
  18. package/dist/src/config/simulation.js +23 -0
  19. package/dist/src/controllers/clan-controller.d.ts +7 -0
  20. package/dist/src/controllers/clan-controller.js +12 -0
  21. package/dist/src/controllers/debug-controller.d.ts +45 -0
  22. package/dist/src/controllers/debug-controller.js +82 -0
  23. package/dist/src/controllers/effects-controller.d.ts +17 -0
  24. package/dist/src/controllers/effects-controller.js +71 -0
  25. package/dist/src/controllers/hover-controller.d.ts +11 -0
  26. package/dist/src/controllers/hover-controller.js +107 -0
  27. package/dist/src/controllers/layer-controller.d.ts +16 -0
  28. package/dist/src/controllers/layer-controller.js +64 -0
  29. package/dist/src/controllers/physics-controller.d.ts +14 -0
  30. package/dist/src/controllers/physics-controller.js +152 -0
  31. package/dist/src/controllers/star-controller.d.ts +12 -0
  32. package/dist/src/controllers/star-controller.js +38 -0
  33. package/dist/src/controllers/starship-controller.d.ts +17 -0
  34. package/dist/src/controllers/starship-controller.js +58 -0
  35. package/dist/src/draw-debug-line.d.ts +9 -0
  36. package/dist/src/draw-debug-line.js +29 -0
  37. package/dist/src/entities/black-hole-factory.d.ts +15 -0
  38. package/dist/src/entities/black-hole-factory.js +23 -0
  39. package/dist/src/entities/black-hole-shapes.d.ts +9 -0
  40. package/dist/src/entities/black-hole-shapes.js +224 -0
  41. package/dist/src/entities/black-hole.d.ts +69 -0
  42. package/dist/src/entities/black-hole.js +210 -0
  43. package/dist/src/entities/clan-manager.d.ts +12 -0
  44. package/dist/src/entities/clan-manager.js +22 -0
  45. package/dist/src/entities/clans.d.ts +15 -0
  46. package/dist/src/entities/clans.js +76 -0
  47. package/dist/src/entities/comet.d.ts +27 -0
  48. package/dist/src/entities/comet.js +81 -0
  49. package/dist/src/entities/docking-point.d.ts +20 -0
  50. package/dist/src/entities/docking-point.js +22 -0
  51. package/dist/src/entities/fleet.d.ts +45 -0
  52. package/dist/src/entities/fleet.js +374 -0
  53. package/dist/src/entities/formations.d.ts +51 -0
  54. package/dist/src/entities/formations.js +340 -0
  55. package/dist/src/entities/meteor.d.ts +26 -0
  56. package/dist/src/entities/meteor.js +48 -0
  57. package/dist/src/entities/nebula.d.ts +18 -0
  58. package/dist/src/entities/nebula.js +43 -0
  59. package/dist/src/entities/orbit.d.ts +23 -0
  60. package/dist/src/entities/orbit.js +43 -0
  61. package/dist/src/entities/pulsar.d.ts +18 -0
  62. package/dist/src/entities/pulsar.js +41 -0
  63. package/dist/src/entities/ring.d.ts +13 -0
  64. package/dist/src/entities/ring.js +26 -0
  65. package/dist/src/entities/ringed-planet.d.ts +21 -0
  66. package/dist/src/entities/ringed-planet.js +68 -0
  67. package/dist/src/entities/sector-grid.d.ts +16 -0
  68. package/dist/src/entities/sector-grid.js +70 -0
  69. package/dist/src/entities/star-factory.d.ts +29 -0
  70. package/dist/src/entities/star-factory.js +47 -0
  71. package/dist/src/entities/star.d.ts +48 -0
  72. package/dist/src/entities/star.js +167 -0
  73. package/dist/src/entities/starship-classes.d.ts +0 -0
  74. package/dist/src/entities/starship-classes.js +2 -0
  75. package/dist/src/entities/starship.d.ts +91 -0
  76. package/dist/src/entities/starship.js +760 -0
  77. package/dist/src/entities/supernova.d.ts +26 -0
  78. package/dist/src/entities/supernova.js +54 -0
  79. package/dist/src/index.d.ts +20 -0
  80. package/dist/src/index.js +19 -0
  81. package/dist/src/lib/energy-stream.d.ts +5 -0
  82. package/dist/src/lib/energy-stream.js +98 -0
  83. package/dist/src/lib/quadtree.d.ts +31 -0
  84. package/dist/src/lib/quadtree.js +124 -0
  85. package/dist/src/lib/simplified-stream.d.ts +6 -0
  86. package/dist/src/lib/simplified-stream.js +19 -0
  87. package/dist/src/types.d.ts +14 -0
  88. package/dist/src/types.js +1 -0
  89. package/dist/src/ui/black-holes-panel.d.ts +2 -0
  90. package/dist/src/ui/black-holes-panel.js +76 -0
  91. package/dist/src/ui/clans-panel.d.ts +2 -0
  92. package/dist/src/ui/clans-panel.js +20 -0
  93. package/dist/src/ui/debug-panel-controller.d.ts +41 -0
  94. package/dist/src/ui/debug-panel-controller.js +285 -0
  95. package/dist/src/ui/fleets-panel.d.ts +2 -0
  96. package/dist/src/ui/fleets-panel.js +127 -0
  97. package/dist/src/ui/formations-panel.d.ts +3 -0
  98. package/dist/src/ui/formations-panel.js +129 -0
  99. package/dist/src/ui/panel-config.d.ts +26 -0
  100. package/dist/src/ui/panel-config.js +26 -0
  101. package/dist/src/ui/ships-panel.d.ts +12 -0
  102. package/dist/src/ui/ships-panel.js +61 -0
  103. package/dist/src/ui/stars-panel.d.ts +2 -0
  104. package/dist/src/ui/stars-panel.js +120 -0
  105. package/dist/src/where-stars-drift.d.ts +71 -0
  106. package/dist/src/where-stars-drift.js +440 -0
  107. package/dist/tsconfig.tsbuildinfo +1 -0
  108. package/package.json +35 -0
  109. package/src/base/bounded-body.ts +14 -0
  110. package/src/base/celestial-body.ts +20 -0
  111. package/src/base/hoverable.ts +11 -0
  112. package/src/base/massive-body.ts +14 -0
  113. package/src/config/effects.ts +15 -0
  114. package/src/config/grid.ts +11 -0
  115. package/src/config/panel.ts +26 -0
  116. package/src/config/simulation.ts +25 -0
  117. package/src/controllers/clan-controller.ts +19 -0
  118. package/src/controllers/debug-controller.ts +112 -0
  119. package/src/controllers/effects-controller.ts +86 -0
  120. package/src/controllers/hover-controller.ts +128 -0
  121. package/src/controllers/layer-controller.ts +78 -0
  122. package/src/controllers/physics-controller.ts +173 -0
  123. package/src/controllers/star-controller.ts +51 -0
  124. package/src/controllers/starship-controller.ts +76 -0
  125. package/src/draw-debug-line.ts +37 -0
  126. package/src/entities/black-hole-factory.ts +28 -0
  127. package/src/entities/black-hole-shapes.ts +276 -0
  128. package/src/entities/black-hole.ts +246 -0
  129. package/src/entities/clan-manager.ts +33 -0
  130. package/src/entities/clans.ts +98 -0
  131. package/src/entities/comet.ts +102 -0
  132. package/src/entities/docking-point.ts +34 -0
  133. package/src/entities/fleet.ts +446 -0
  134. package/src/entities/formations.ts +423 -0
  135. package/src/entities/meteor.ts +59 -0
  136. package/src/entities/nebula.ts +50 -0
  137. package/src/entities/orbit.ts +53 -0
  138. package/src/entities/pulsar.ts +64 -0
  139. package/src/entities/ring.ts +42 -0
  140. package/src/entities/ringed-planet.ts +85 -0
  141. package/src/entities/sector-grid.ts +81 -0
  142. package/src/entities/star-factory.ts +59 -0
  143. package/src/entities/star.ts +222 -0
  144. package/src/entities/starship-classes.ts +1 -0
  145. package/src/entities/starship.ts +906 -0
  146. package/src/entities/supernova.ts +75 -0
  147. package/src/index.ts +24 -0
  148. package/src/lib/energy-stream.ts +127 -0
  149. package/src/lib/quadtree.ts +159 -0
  150. package/src/lib/simplified-stream.ts +28 -0
  151. package/src/types.ts +16 -0
  152. package/src/ui/black-holes-panel.ts +91 -0
  153. package/src/ui/clans-panel.ts +27 -0
  154. package/src/ui/debug-panel-controller.ts +339 -0
  155. package/src/ui/fleets-panel.ts +153 -0
  156. package/src/ui/formations-panel.ts +155 -0
  157. package/src/ui/panel-config.ts +26 -0
  158. package/src/ui/ships-panel.ts +85 -0
  159. package/src/ui/stars-panel.ts +146 -0
  160. package/src/where-stars-drift.ts +542 -0
@@ -0,0 +1,85 @@
1
+
2
+ /**
3
+ * @fileoverview Defines the RingedPlanet class, a specialized type of Star.
4
+ */
5
+
6
+ import { Star, STAR_CONFIG } from './star';
7
+ import { DockingPoint } from './docking-point';
8
+ import { Ring } from './ring';
9
+
10
+ // --- Ringed Planet Configuration ---
11
+ export const RINGED_PLANET_CONFIG = {
12
+ RING_COUNT_MIN: 1,
13
+ RING_COUNT_MAX: 2,
14
+ RING_RADIUS_MULTIPLIER_MIN: 2.2,
15
+ RING_RADIUS_MULTIPLIER_MAX: 2.8,
16
+ RING_THICKNESS_MIN: 0.2,
17
+ RING_THICKNESS_MAX: 0.8,
18
+ RING_ALPHA: 0.7,
19
+ RING_DOTTED_CHANCE: 0.3, // Chance for a ring to be dotted
20
+ DOCKING_POINTS_PER_RING: 4,
21
+ };
22
+
23
+ let ringedPlanetCounter = 0;
24
+
25
+ export class RingedPlanet extends Star {
26
+ rings: Ring[];
27
+
28
+ constructor(x: number, y: number, ringCount?: number) {
29
+ super(x, y);
30
+ this.name = `RP-${++ringedPlanetCounter}`;
31
+ this.rings = [];
32
+ this.dockingPoints = []; // A planet itself has no docking points, they are on rings/orbits.
33
+ this.orbits = []; // Clear star-generated orbits
34
+ this.hasAura = Math.random() < STAR_CONFIG.AURA_CHANCE;
35
+
36
+ const finalRingCount = ringCount !== undefined
37
+ ? ringCount
38
+ : Math.floor(Math.random() * (RINGED_PLANET_CONFIG.RING_COUNT_MAX - RINGED_PLANET_CONFIG.RING_COUNT_MIN + 1)) +
39
+ RINGED_PLANET_CONFIG.RING_COUNT_MIN;
40
+
41
+ let maxRingRadius = this.radius;
42
+ for (let i = 0; i < finalRingCount; i++) {
43
+ const radiusMultiplier =
44
+ (Math.random() * (RINGED_PLANET_CONFIG.RING_RADIUS_MULTIPLIER_MAX - RINGED_PLANET_CONFIG.RING_RADIUS_MULTIPLIER_MIN) +
45
+ RINGED_PLANET_CONFIG.RING_RADIUS_MULTIPLIER_MIN) + i * 3.0; // Stagger rings
46
+
47
+ const ringRadius = this.radius * radiusMultiplier;
48
+ maxRingRadius = Math.max(maxRingRadius, ringRadius);
49
+ const ringColor = this.color.startsWith('rgba')
50
+ ? this.color.replace(/, [0-9\.]+$/, `, ${RINGED_PLANET_CONFIG.RING_ALPHA})`)
51
+ : `rgba(255, 255, 255, ${RINGED_PLANET_CONFIG.RING_ALPHA})`;
52
+ const isDotted = Math.random() < RINGED_PLANET_CONFIG.RING_DOTTED_CHANCE;
53
+
54
+ const ring = new Ring(this, ringRadius, Math.random() * (RINGED_PLANET_CONFIG.RING_THICKNESS_MAX - RINGED_PLANET_CONFIG.RING_THICKNESS_MIN) + RINGED_PLANET_CONFIG.RING_THICKNESS_MIN, ringColor, isDotted);
55
+ this.rings.push(ring);
56
+
57
+ // Add docking points along the rings
58
+ const pointsOnRing = RINGED_PLANET_CONFIG.DOCKING_POINTS_PER_RING;
59
+ for(let j = 0; j < pointsOnRing; j++) {
60
+ const angle = (j / pointsOnRing) * Math.PI * 2;
61
+ const dx = Math.cos(angle) * ringRadius;
62
+ const dy = Math.sin(angle) * ringRadius;
63
+ this.dockingPoints.push(new DockingPoint(this, dx, dy));
64
+ }
65
+ }
66
+
67
+ // Update hoverRadius to encompass the rings
68
+ this.hoverRadius = maxRingRadius + 10;
69
+ }
70
+
71
+ draw(ctx: CanvasRenderingContext2D, pulseTime: number) {
72
+ // Call the parent draw method to draw the planet body itself on top
73
+ this.drawBase(ctx, pulseTime);
74
+
75
+ // Draw rings
76
+ this.rings.forEach(ring => {
77
+ ring.draw(ctx);
78
+ });
79
+
80
+ // Draw orbits
81
+ this.orbits.forEach(orbit => {
82
+ orbit.draw(ctx);
83
+ });
84
+ }
85
+ }
@@ -0,0 +1,81 @@
1
+ /**
2
+ * @fileoverview Defines the SectorGrid class for the background grid.
3
+ */
4
+ import { CelestialBody } from '../base/celestial-body';
5
+ import { GRID_CONFIG } from '../config/grid';
6
+
7
+ export class SectorGrid extends CelestialBody {
8
+ private numCols: number = 0;
9
+ private numRows: number = 0;
10
+ private sectorWidth: number = 0;
11
+ private sectorHeight: number = 0;
12
+ private width: number = 0;
13
+ private height: number = 0;
14
+
15
+ constructor(width: number, height: number) {
16
+ super(0, 0);
17
+ this.resize(width, height);
18
+ }
19
+
20
+ public resize(width: number, height: number) {
21
+ this.width = width;
22
+ this.height = height;
23
+ this.numCols = Math.ceil(width / GRID_CONFIG.SECTOR_SIZE);
24
+ this.numRows = Math.ceil(height / GRID_CONFIG.SECTOR_SIZE);
25
+ this.sectorWidth = width / this.numCols;
26
+ this.sectorHeight = height / this.numRows;
27
+ }
28
+
29
+ update(context: CanvasRenderingContext2D, width: number, height: number) {
30
+ // update width/height in case it changed and resize wasn't called (defensive)
31
+ if (this.width !== width || this.height !== height) {
32
+ this.resize(width, height);
33
+ }
34
+ }
35
+
36
+ draw(ctx: CanvasRenderingContext2D) {
37
+ if (this.width === 0 || this.height === 0) return;
38
+
39
+ ctx.save();
40
+ ctx.strokeStyle = GRID_CONFIG.LINE_COLOR;
41
+ ctx.lineWidth = GRID_CONFIG.LINE_WIDTH;
42
+ ctx.setLineDash([2, 4]);
43
+
44
+ // Draw vertical lines
45
+ for (let i = 1; i < this.numCols; i++) {
46
+ const x = i * this.sectorWidth;
47
+ ctx.beginPath();
48
+ ctx.moveTo(x, 0);
49
+ ctx.lineTo(x, this.height);
50
+ ctx.stroke();
51
+ }
52
+
53
+ // Draw horizontal lines
54
+ for (let i = 1; i < this.numRows; i++) {
55
+ const y = i * this.sectorHeight;
56
+ ctx.beginPath();
57
+ ctx.moveTo(0, y);
58
+ ctx.lineTo(this.width, y);
59
+ ctx.stroke();
60
+ }
61
+
62
+ ctx.setLineDash([]);
63
+
64
+ // Draw sector names
65
+ ctx.fillStyle = GRID_CONFIG.FONT_COLOR;
66
+ ctx.font = GRID_CONFIG.FONT;
67
+ ctx.textAlign = 'center';
68
+ ctx.textBaseline = 'middle';
69
+
70
+ for (let row = 0; row < this.numRows; row++) {
71
+ for (let col = 0; col < this.numCols; col++) {
72
+ const sectorName = `${String.fromCharCode(65 + row)}-${col + 1}`;
73
+ const centerX = col * this.sectorWidth + this.sectorWidth / 2;
74
+ const centerY = row * this.sectorHeight + this.sectorHeight / 2;
75
+ ctx.fillText(sectorName, centerX, centerY);
76
+ }
77
+ }
78
+
79
+ ctx.restore();
80
+ }
81
+ }
@@ -0,0 +1,59 @@
1
+
2
+ import { Star, STAR_CONFIG } from './star';
3
+ import { Pulsar, PULSAR_CONFIG } from './pulsar';
4
+ import { RingedPlanet, RINGED_PLANET_CONFIG } from './ringed-planet';
5
+
6
+ interface StarOptions {
7
+ radius?: number;
8
+ hasAura?: boolean;
9
+ }
10
+
11
+ interface RingedPlanetOptions {
12
+ ringCount?: number;
13
+ }
14
+
15
+ export class StarFactory {
16
+ /**
17
+ * Creates a star of a random type (Standard, Pulsar, or Ringed Planet).
18
+ */
19
+ createRandomStar(x: number, y: number): Star {
20
+ const rand = Math.random();
21
+ if (rand < 0.02) {
22
+ return this.createPulsar(x, y);
23
+ } else if (rand < 0.02 + 0.03) {
24
+ return this.createRingedPlanet(x, y);
25
+ } else {
26
+ return this.createStar(x, y);
27
+ }
28
+ }
29
+
30
+ /**
31
+ * Creates a standard star.
32
+ */
33
+ createStar(x: number, y: number, options: StarOptions = {}): Star {
34
+ const star = new Star(x, y);
35
+ if (options.radius) {
36
+ star.radius = options.radius;
37
+ star.baseRadius = options.radius;
38
+ }
39
+ if (options.hasAura !== undefined) {
40
+ star.hasAura = options.hasAura;
41
+ }
42
+ return star;
43
+ }
44
+
45
+ /**
46
+ * Creates a pulsar star.
47
+ */
48
+ createPulsar(x: number, y: number): Pulsar {
49
+ return new Pulsar(x, y);
50
+ }
51
+
52
+ /**
53
+ * Creates a ringed planet.
54
+ */
55
+ createRingedPlanet(x: number, y: number, options: RingedPlanetOptions = {}): RingedPlanet {
56
+ const planet = new RingedPlanet(x, y, options.ringCount);
57
+ return planet;
58
+ }
59
+ }
@@ -0,0 +1,222 @@
1
+
2
+ /**
3
+ * @fileoverview Defines the Star class for the night sky simulation.
4
+ */
5
+
6
+ import { MassiveBody } from '../base/massive-body';
7
+ import { DockingPoint } from './docking-point';
8
+ import { Orbit, ORBIT_CONFIG } from './orbit';
9
+ import type { Hoverable } from '../base/hoverable';
10
+ import { DEBUG_CONFIG } from '../config/simulation';
11
+ import type { BlackHole } from './black-hole';
12
+
13
+ // --- Star Configuration ---
14
+ export const STAR_CONFIG = {
15
+ RARE_STAR_CHANCE: 0.1,
16
+ RARE_STAR_COLORS: ['#FFD700', '#ADD8E6', '#FFB6C1', '#87CEEB', '#DDA0DD', '#ffabab', '#a6d9ff'],
17
+ AURA_CHANCE: 0.15,
18
+ RINGED_PLANET_CHANCE: 0.03, // Chance to spawn a ringed planet
19
+ MIN_RADIUS: 0.5,
20
+ RADIUS_VARIANCE: 1.1,
21
+ INITIAL_VELOCITY_RANGE: 0.05,
22
+ INTERACTION_ACCELERATION: 0.02,
23
+ VELOCITY_DECAY: 0.96,
24
+ HOVER_RADIUS_MULTIPLIER: 8,
25
+ HOVER_GLOW_COLOR: 'rgba(255, 255, 255, 0.7)',
26
+ HOVER_TIMEOUT: 120, // 2 seconds in frames
27
+ };
28
+
29
+ let starCounter = 0;
30
+
31
+ export class Star extends MassiveBody implements Hoverable {
32
+ id: number;
33
+ name: string;
34
+ radius: number;
35
+ baseRadius: number;
36
+ ivx: number;
37
+ ivy: number;
38
+ color: string;
39
+ hasAura: boolean;
40
+ dockingPoints: DockingPoint[];
41
+ orbits: Orbit[];
42
+ isHovered: boolean = false;
43
+ hoverRadius: number;
44
+ hoverTimer: number;
45
+ respawnTimer: number;
46
+
47
+ constructor(x: number, y: number) {
48
+ const radius = Math.random() * STAR_CONFIG.RADIUS_VARIANCE + STAR_CONFIG.MIN_RADIUS;
49
+ const mass = radius * radius; // Mass is proportional to the square of the radius
50
+ super(x, y, radius, mass);
51
+
52
+ this.id = ++starCounter;
53
+ this.name = `S-${this.id}`;
54
+ this.radius = radius;
55
+ this.baseRadius = this.radius;
56
+ this.ivx = Math.random() * STAR_CONFIG.INITIAL_VELOCITY_RANGE * 2 - STAR_CONFIG.INITIAL_VELOCITY_RANGE;
57
+ this.ivy = Math.random() * STAR_CONFIG.INITIAL_VELOCITY_RANGE * 2 - STAR_CONFIG.INITIAL_VELOCITY_RANGE;
58
+ this.hasAura = Math.random() < STAR_CONFIG.AURA_CHANCE;
59
+
60
+ const isRare = Math.random() < STAR_CONFIG.RARE_STAR_CHANCE;
61
+ this.color = isRare
62
+ ? STAR_CONFIG.RARE_STAR_COLORS[Math.floor(Math.random() * STAR_CONFIG.RARE_STAR_COLORS.length)]
63
+ : 'rgba(255, 255, 255, 0.8)';
64
+
65
+ this.dockingPoints = [];
66
+ this.orbits = [];
67
+
68
+ this.hoverTimer = 0;
69
+ this.respawnTimer = 0;
70
+
71
+
72
+ const orbitCount = Math.floor(Math.random() * (ORBIT_CONFIG.COUNT_MAX - ORBIT_CONFIG.COUNT_MIN + 1)) + ORBIT_CONFIG.COUNT_MIN;
73
+ let maxOrbitRadius = this.radius;
74
+ for (let i = 0; i < orbitCount; i++) {
75
+ const radiusMultiplier = (Math.random() * (ORBIT_CONFIG.RADIUS_MULTIPLIER_MAX - ORBIT_CONFIG.RADIUS_MULTIPLIER_MIN) + ORBIT_CONFIG.RADIUS_MULTIPLIER_MIN);
76
+ const orbitRadius = this.radius * radiusMultiplier;
77
+ maxOrbitRadius = Math.max(maxOrbitRadius, orbitRadius);
78
+ const orbitColor = this.color.startsWith('rgba')
79
+ ? this.color.replace(/, [0-9\.]+$/, `, ${ORBIT_CONFIG.ALPHA})`)
80
+ : `rgba(255, 255, 255, ${ORBIT_CONFIG.ALPHA})`;
81
+
82
+ const orbit = new Orbit(this, orbitRadius, ORBIT_CONFIG.THICKNESS, orbitColor);
83
+ this.orbits.push(orbit);
84
+ this.dockingPoints.push(...orbit.dockingPoints);
85
+ }
86
+
87
+ this.hoverRadius = maxOrbitRadius + 10;
88
+ }
89
+
90
+ isEatenBy(blackHole: BlackHole): boolean {
91
+ const dx = blackHole.x - this.x;
92
+ const dy = blackHole.y - this.y;
93
+ const distance = Math.sqrt(dx * dx + dy * dy);
94
+ return distance < blackHole.radius;
95
+ }
96
+
97
+ respawn(newX: number, newY: number): void {
98
+ this.x = newX;
99
+ this.y = newY;
100
+ this.vx = 0;
101
+ this.vy = 0;
102
+ this.ivx = Math.random() * STAR_CONFIG.INITIAL_VELOCITY_RANGE * 2 - STAR_CONFIG.INITIAL_VELOCITY_RANGE;
103
+ this.ivy = Math.random() * STAR_CONFIG.INITIAL_VELOCITY_RANGE * 2 - STAR_CONFIG.INITIAL_VELOCITY_RANGE;
104
+ this.respawnTimer = 60; // 60 frames = ~1 second
105
+ }
106
+
107
+
108
+ update(
109
+ ctx: CanvasRenderingContext2D,
110
+ width: number,
111
+ height: number,
112
+ mouse: { dx: number; dy: number },
113
+ interactive: boolean,
114
+ isMouseInside: boolean,
115
+ pulseTime?: number,
116
+ ) {
117
+ if (this.respawnTimer > 0) {
118
+ this.respawnTimer--;
119
+ return;
120
+ }
121
+
122
+ if (interactive && isMouseInside) {
123
+ const acc = STAR_CONFIG.INTERACTION_ACCELERATION;
124
+ this.vx += mouse.dx * acc;
125
+ this.vy += mouse.dy * acc;
126
+ }
127
+
128
+ this.vx *= STAR_CONFIG.VELOCITY_DECAY;
129
+ this.vy *= STAR_CONFIG.VELOCITY_DECAY;
130
+
131
+ this.x += this.vx + this.ivx;
132
+ this.y += this.vy + this.ivy;
133
+
134
+ if (this.x < 0) this.x = width;
135
+ if (this.x > width) this.x = 0;
136
+ if (this.y < 0) this.y = height;
137
+ if (this.y > height) this.y = 0;
138
+ }
139
+
140
+ private drawDebugInfo(ctx: CanvasRenderingContext2D) {
141
+ const startX = this.x + this.hoverRadius + 15;
142
+ const boxPadding = 10;
143
+ const lineHeight = 14;
144
+ const infoLines = [
145
+ `Name: ${this.name}`,
146
+ `Type: ${this.constructor.name}`,
147
+ `Radius: ${this.radius.toFixed(2)}`,
148
+ `Mass: ${this.mass.toFixed(2)}`,
149
+ `Color: ${this.color}`,
150
+ `Position: (${this.x.toFixed(0)}, ${this.y.toFixed(0)})`,
151
+ `Velocity: (${this.vx.toFixed(2)}, ${this.vy.toFixed(2)})`,
152
+ `Orbits: ${this.orbits.length}`,
153
+ `Docking Points: ${this.dockingPoints.length}`,
154
+ ];
155
+
156
+ const boxHeight = infoLines.length * lineHeight + boxPadding * 2;
157
+ const boxWidth = Math.max(...infoLines.map(line => ctx.measureText(line).width)) + boxPadding * 2;
158
+ const boxY = this.y - boxHeight / 2;
159
+
160
+ ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';
161
+ ctx.strokeStyle = this.color;
162
+ ctx.lineWidth = 1;
163
+ ctx.beginPath();
164
+ ctx.roundRect(startX, boxY, boxWidth, boxHeight, 5);
165
+ ctx.fill();
166
+ ctx.stroke();
167
+
168
+ ctx.fillStyle = 'white';
169
+ ctx.font = '10px "Roboto Mono", monospace';
170
+ ctx.textAlign = 'left';
171
+ ctx.textBaseline = 'top';
172
+
173
+ infoLines.forEach((line, index) => {
174
+ ctx.fillText(line, startX + boxPadding, boxY + boxPadding + index * lineHeight);
175
+ });
176
+ }
177
+
178
+ // A new base drawing function that can be called by subclasses
179
+ drawBase(ctx: CanvasRenderingContext2D, pulseTime: number) {
180
+ // Orbits are drawn first, behind the star
181
+ this.orbits.forEach(orbit => orbit.draw(ctx));
182
+
183
+ // Draw hover effect if hovered
184
+ this.isHovered = this.hoverTimer > 0;
185
+ if (this.isHovered) {
186
+ ctx.strokeStyle = STAR_CONFIG.HOVER_GLOW_COLOR;
187
+ ctx.lineWidth = 0.5;
188
+ ctx.shadowColor = STAR_CONFIG.HOVER_GLOW_COLOR;
189
+ ctx.shadowBlur = 10;
190
+ ctx.beginPath();
191
+ ctx.arc(this.x, this.y, this.hoverRadius, 0, Math.PI * 2);
192
+ ctx.stroke();
193
+ ctx.shadowBlur = 0;
194
+
195
+ if (DEBUG_CONFIG.SHOW_DEBUG_INFO && DEBUG_CONFIG.SHOW_ENTITY_HOVER_INFO) {
196
+ this.drawDebugInfo(ctx);
197
+ }
198
+ }
199
+
200
+ ctx.save();
201
+ ctx.fillStyle = this.color;
202
+
203
+ ctx.beginPath();
204
+ if (this.hasAura && !this.isHovered) { // Apply aura only if not hovered to avoid conflicting glows
205
+ ctx.shadowColor = this.color;
206
+ ctx.shadowBlur = 20;
207
+ }
208
+
209
+ ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
210
+ ctx.fill();
211
+ ctx.restore();
212
+
213
+ // Reset shadow blur after drawing the main body
214
+ if (this.hasAura || this.isHovered) {
215
+ ctx.shadowBlur = 0;
216
+ }
217
+ }
218
+
219
+ draw(ctx: CanvasRenderingContext2D, pulseTime: number) {
220
+ this.drawBase(ctx, pulseTime);
221
+ }
222
+ }
@@ -0,0 +1 @@
1
+ // This file is intentionally left empty after its contents were merged into starship.ts to resolve a build issue.