@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.
- package/LICENSE +20 -0
- package/README.md +143 -0
- package/dist/src/base/bounded-body.d.ts +8 -0
- package/dist/src/base/bounded-body.js +10 -0
- package/dist/src/base/celestial-body.d.ts +12 -0
- package/dist/src/base/celestial-body.js +11 -0
- package/dist/src/base/hoverable.d.ts +10 -0
- package/dist/src/base/hoverable.js +4 -0
- package/dist/src/base/massive-body.d.ts +8 -0
- package/dist/src/base/massive-body.js +10 -0
- package/dist/src/config/effects.d.ts +14 -0
- package/dist/src/config/effects.js +14 -0
- package/dist/src/config/grid.d.ts +10 -0
- package/dist/src/config/grid.js +10 -0
- package/dist/src/config/panel.d.ts +26 -0
- package/dist/src/config/panel.js +26 -0
- package/dist/src/config/simulation.d.ts +21 -0
- package/dist/src/config/simulation.js +23 -0
- package/dist/src/controllers/clan-controller.d.ts +7 -0
- package/dist/src/controllers/clan-controller.js +12 -0
- package/dist/src/controllers/debug-controller.d.ts +45 -0
- package/dist/src/controllers/debug-controller.js +82 -0
- package/dist/src/controllers/effects-controller.d.ts +17 -0
- package/dist/src/controllers/effects-controller.js +71 -0
- package/dist/src/controllers/hover-controller.d.ts +11 -0
- package/dist/src/controllers/hover-controller.js +107 -0
- package/dist/src/controllers/layer-controller.d.ts +16 -0
- package/dist/src/controllers/layer-controller.js +64 -0
- package/dist/src/controllers/physics-controller.d.ts +14 -0
- package/dist/src/controllers/physics-controller.js +152 -0
- package/dist/src/controllers/star-controller.d.ts +12 -0
- package/dist/src/controllers/star-controller.js +38 -0
- package/dist/src/controllers/starship-controller.d.ts +17 -0
- package/dist/src/controllers/starship-controller.js +58 -0
- package/dist/src/draw-debug-line.d.ts +9 -0
- package/dist/src/draw-debug-line.js +29 -0
- package/dist/src/entities/black-hole-factory.d.ts +15 -0
- package/dist/src/entities/black-hole-factory.js +23 -0
- package/dist/src/entities/black-hole-shapes.d.ts +9 -0
- package/dist/src/entities/black-hole-shapes.js +224 -0
- package/dist/src/entities/black-hole.d.ts +69 -0
- package/dist/src/entities/black-hole.js +210 -0
- package/dist/src/entities/clan-manager.d.ts +12 -0
- package/dist/src/entities/clan-manager.js +22 -0
- package/dist/src/entities/clans.d.ts +15 -0
- package/dist/src/entities/clans.js +76 -0
- package/dist/src/entities/comet.d.ts +27 -0
- package/dist/src/entities/comet.js +81 -0
- package/dist/src/entities/docking-point.d.ts +20 -0
- package/dist/src/entities/docking-point.js +22 -0
- package/dist/src/entities/fleet.d.ts +45 -0
- package/dist/src/entities/fleet.js +374 -0
- package/dist/src/entities/formations.d.ts +51 -0
- package/dist/src/entities/formations.js +340 -0
- package/dist/src/entities/meteor.d.ts +26 -0
- package/dist/src/entities/meteor.js +48 -0
- package/dist/src/entities/nebula.d.ts +18 -0
- package/dist/src/entities/nebula.js +43 -0
- package/dist/src/entities/orbit.d.ts +23 -0
- package/dist/src/entities/orbit.js +43 -0
- package/dist/src/entities/pulsar.d.ts +18 -0
- package/dist/src/entities/pulsar.js +41 -0
- package/dist/src/entities/ring.d.ts +13 -0
- package/dist/src/entities/ring.js +26 -0
- package/dist/src/entities/ringed-planet.d.ts +21 -0
- package/dist/src/entities/ringed-planet.js +68 -0
- package/dist/src/entities/sector-grid.d.ts +16 -0
- package/dist/src/entities/sector-grid.js +70 -0
- package/dist/src/entities/star-factory.d.ts +29 -0
- package/dist/src/entities/star-factory.js +47 -0
- package/dist/src/entities/star.d.ts +48 -0
- package/dist/src/entities/star.js +167 -0
- package/dist/src/entities/starship-classes.d.ts +0 -0
- package/dist/src/entities/starship-classes.js +2 -0
- package/dist/src/entities/starship.d.ts +91 -0
- package/dist/src/entities/starship.js +760 -0
- package/dist/src/entities/supernova.d.ts +26 -0
- package/dist/src/entities/supernova.js +54 -0
- package/dist/src/index.d.ts +20 -0
- package/dist/src/index.js +19 -0
- package/dist/src/lib/energy-stream.d.ts +5 -0
- package/dist/src/lib/energy-stream.js +98 -0
- package/dist/src/lib/quadtree.d.ts +31 -0
- package/dist/src/lib/quadtree.js +124 -0
- package/dist/src/lib/simplified-stream.d.ts +6 -0
- package/dist/src/lib/simplified-stream.js +19 -0
- package/dist/src/types.d.ts +14 -0
- package/dist/src/types.js +1 -0
- package/dist/src/ui/black-holes-panel.d.ts +2 -0
- package/dist/src/ui/black-holes-panel.js +76 -0
- package/dist/src/ui/clans-panel.d.ts +2 -0
- package/dist/src/ui/clans-panel.js +20 -0
- package/dist/src/ui/debug-panel-controller.d.ts +41 -0
- package/dist/src/ui/debug-panel-controller.js +285 -0
- package/dist/src/ui/fleets-panel.d.ts +2 -0
- package/dist/src/ui/fleets-panel.js +127 -0
- package/dist/src/ui/formations-panel.d.ts +3 -0
- package/dist/src/ui/formations-panel.js +129 -0
- package/dist/src/ui/panel-config.d.ts +26 -0
- package/dist/src/ui/panel-config.js +26 -0
- package/dist/src/ui/ships-panel.d.ts +12 -0
- package/dist/src/ui/ships-panel.js +61 -0
- package/dist/src/ui/stars-panel.d.ts +2 -0
- package/dist/src/ui/stars-panel.js +120 -0
- package/dist/src/where-stars-drift.d.ts +71 -0
- package/dist/src/where-stars-drift.js +440 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +35 -0
- package/src/base/bounded-body.ts +14 -0
- package/src/base/celestial-body.ts +20 -0
- package/src/base/hoverable.ts +11 -0
- package/src/base/massive-body.ts +14 -0
- package/src/config/effects.ts +15 -0
- package/src/config/grid.ts +11 -0
- package/src/config/panel.ts +26 -0
- package/src/config/simulation.ts +25 -0
- package/src/controllers/clan-controller.ts +19 -0
- package/src/controllers/debug-controller.ts +112 -0
- package/src/controllers/effects-controller.ts +86 -0
- package/src/controllers/hover-controller.ts +128 -0
- package/src/controllers/layer-controller.ts +78 -0
- package/src/controllers/physics-controller.ts +173 -0
- package/src/controllers/star-controller.ts +51 -0
- package/src/controllers/starship-controller.ts +76 -0
- package/src/draw-debug-line.ts +37 -0
- package/src/entities/black-hole-factory.ts +28 -0
- package/src/entities/black-hole-shapes.ts +276 -0
- package/src/entities/black-hole.ts +246 -0
- package/src/entities/clan-manager.ts +33 -0
- package/src/entities/clans.ts +98 -0
- package/src/entities/comet.ts +102 -0
- package/src/entities/docking-point.ts +34 -0
- package/src/entities/fleet.ts +446 -0
- package/src/entities/formations.ts +423 -0
- package/src/entities/meteor.ts +59 -0
- package/src/entities/nebula.ts +50 -0
- package/src/entities/orbit.ts +53 -0
- package/src/entities/pulsar.ts +64 -0
- package/src/entities/ring.ts +42 -0
- package/src/entities/ringed-planet.ts +85 -0
- package/src/entities/sector-grid.ts +81 -0
- package/src/entities/star-factory.ts +59 -0
- package/src/entities/star.ts +222 -0
- package/src/entities/starship-classes.ts +1 -0
- package/src/entities/starship.ts +906 -0
- package/src/entities/supernova.ts +75 -0
- package/src/index.ts +24 -0
- package/src/lib/energy-stream.ts +127 -0
- package/src/lib/quadtree.ts +159 -0
- package/src/lib/simplified-stream.ts +28 -0
- package/src/types.ts +16 -0
- package/src/ui/black-holes-panel.ts +91 -0
- package/src/ui/clans-panel.ts +27 -0
- package/src/ui/debug-panel-controller.ts +339 -0
- package/src/ui/fleets-panel.ts +153 -0
- package/src/ui/formations-panel.ts +155 -0
- package/src/ui/panel-config.ts +26 -0
- package/src/ui/ships-panel.ts +85 -0
- package/src/ui/stars-panel.ts +146 -0
- package/src/where-stars-drift.ts +542 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Defines the RingedPlanet class, a specialized type of Star.
|
|
3
|
+
*/
|
|
4
|
+
import { Star, STAR_CONFIG } from './star';
|
|
5
|
+
import { DockingPoint } from './docking-point';
|
|
6
|
+
import { Ring } from './ring';
|
|
7
|
+
// --- Ringed Planet Configuration ---
|
|
8
|
+
export const RINGED_PLANET_CONFIG = {
|
|
9
|
+
RING_COUNT_MIN: 1,
|
|
10
|
+
RING_COUNT_MAX: 2,
|
|
11
|
+
RING_RADIUS_MULTIPLIER_MIN: 2.2,
|
|
12
|
+
RING_RADIUS_MULTIPLIER_MAX: 2.8,
|
|
13
|
+
RING_THICKNESS_MIN: 0.2,
|
|
14
|
+
RING_THICKNESS_MAX: 0.8,
|
|
15
|
+
RING_ALPHA: 0.7,
|
|
16
|
+
RING_DOTTED_CHANCE: 0.3, // Chance for a ring to be dotted
|
|
17
|
+
DOCKING_POINTS_PER_RING: 4,
|
|
18
|
+
};
|
|
19
|
+
let ringedPlanetCounter = 0;
|
|
20
|
+
export class RingedPlanet extends Star {
|
|
21
|
+
constructor(x, y, ringCount) {
|
|
22
|
+
super(x, y);
|
|
23
|
+
this.name = `RP-${++ringedPlanetCounter}`;
|
|
24
|
+
this.rings = [];
|
|
25
|
+
this.dockingPoints = []; // A planet itself has no docking points, they are on rings/orbits.
|
|
26
|
+
this.orbits = []; // Clear star-generated orbits
|
|
27
|
+
this.hasAura = Math.random() < STAR_CONFIG.AURA_CHANCE;
|
|
28
|
+
const finalRingCount = ringCount !== undefined
|
|
29
|
+
? ringCount
|
|
30
|
+
: Math.floor(Math.random() * (RINGED_PLANET_CONFIG.RING_COUNT_MAX - RINGED_PLANET_CONFIG.RING_COUNT_MIN + 1)) +
|
|
31
|
+
RINGED_PLANET_CONFIG.RING_COUNT_MIN;
|
|
32
|
+
let maxRingRadius = this.radius;
|
|
33
|
+
for (let i = 0; i < finalRingCount; i++) {
|
|
34
|
+
const radiusMultiplier = (Math.random() * (RINGED_PLANET_CONFIG.RING_RADIUS_MULTIPLIER_MAX - RINGED_PLANET_CONFIG.RING_RADIUS_MULTIPLIER_MIN) +
|
|
35
|
+
RINGED_PLANET_CONFIG.RING_RADIUS_MULTIPLIER_MIN) + i * 3.0; // Stagger rings
|
|
36
|
+
const ringRadius = this.radius * radiusMultiplier;
|
|
37
|
+
maxRingRadius = Math.max(maxRingRadius, ringRadius);
|
|
38
|
+
const ringColor = this.color.startsWith('rgba')
|
|
39
|
+
? this.color.replace(/, [0-9\.]+$/, `, ${RINGED_PLANET_CONFIG.RING_ALPHA})`)
|
|
40
|
+
: `rgba(255, 255, 255, ${RINGED_PLANET_CONFIG.RING_ALPHA})`;
|
|
41
|
+
const isDotted = Math.random() < RINGED_PLANET_CONFIG.RING_DOTTED_CHANCE;
|
|
42
|
+
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);
|
|
43
|
+
this.rings.push(ring);
|
|
44
|
+
// Add docking points along the rings
|
|
45
|
+
const pointsOnRing = RINGED_PLANET_CONFIG.DOCKING_POINTS_PER_RING;
|
|
46
|
+
for (let j = 0; j < pointsOnRing; j++) {
|
|
47
|
+
const angle = (j / pointsOnRing) * Math.PI * 2;
|
|
48
|
+
const dx = Math.cos(angle) * ringRadius;
|
|
49
|
+
const dy = Math.sin(angle) * ringRadius;
|
|
50
|
+
this.dockingPoints.push(new DockingPoint(this, dx, dy));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// Update hoverRadius to encompass the rings
|
|
54
|
+
this.hoverRadius = maxRingRadius + 10;
|
|
55
|
+
}
|
|
56
|
+
draw(ctx, pulseTime) {
|
|
57
|
+
// Call the parent draw method to draw the planet body itself on top
|
|
58
|
+
this.drawBase(ctx, pulseTime);
|
|
59
|
+
// Draw rings
|
|
60
|
+
this.rings.forEach(ring => {
|
|
61
|
+
ring.draw(ctx);
|
|
62
|
+
});
|
|
63
|
+
// Draw orbits
|
|
64
|
+
this.orbits.forEach(orbit => {
|
|
65
|
+
orbit.draw(ctx);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Defines the SectorGrid class for the background grid.
|
|
3
|
+
*/
|
|
4
|
+
import { CelestialBody } from '../base/celestial-body';
|
|
5
|
+
export declare class SectorGrid extends CelestialBody {
|
|
6
|
+
private numCols;
|
|
7
|
+
private numRows;
|
|
8
|
+
private sectorWidth;
|
|
9
|
+
private sectorHeight;
|
|
10
|
+
private width;
|
|
11
|
+
private height;
|
|
12
|
+
constructor(width: number, height: number);
|
|
13
|
+
resize(width: number, height: number): void;
|
|
14
|
+
update(context: CanvasRenderingContext2D, width: number, height: number): void;
|
|
15
|
+
draw(ctx: CanvasRenderingContext2D): void;
|
|
16
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
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
|
+
export class SectorGrid extends CelestialBody {
|
|
7
|
+
constructor(width, height) {
|
|
8
|
+
super(0, 0);
|
|
9
|
+
this.numCols = 0;
|
|
10
|
+
this.numRows = 0;
|
|
11
|
+
this.sectorWidth = 0;
|
|
12
|
+
this.sectorHeight = 0;
|
|
13
|
+
this.width = 0;
|
|
14
|
+
this.height = 0;
|
|
15
|
+
this.resize(width, height);
|
|
16
|
+
}
|
|
17
|
+
resize(width, height) {
|
|
18
|
+
this.width = width;
|
|
19
|
+
this.height = height;
|
|
20
|
+
this.numCols = Math.ceil(width / GRID_CONFIG.SECTOR_SIZE);
|
|
21
|
+
this.numRows = Math.ceil(height / GRID_CONFIG.SECTOR_SIZE);
|
|
22
|
+
this.sectorWidth = width / this.numCols;
|
|
23
|
+
this.sectorHeight = height / this.numRows;
|
|
24
|
+
}
|
|
25
|
+
update(context, width, height) {
|
|
26
|
+
// update width/height in case it changed and resize wasn't called (defensive)
|
|
27
|
+
if (this.width !== width || this.height !== height) {
|
|
28
|
+
this.resize(width, height);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
draw(ctx) {
|
|
32
|
+
if (this.width === 0 || this.height === 0)
|
|
33
|
+
return;
|
|
34
|
+
ctx.save();
|
|
35
|
+
ctx.strokeStyle = GRID_CONFIG.LINE_COLOR;
|
|
36
|
+
ctx.lineWidth = GRID_CONFIG.LINE_WIDTH;
|
|
37
|
+
ctx.setLineDash([2, 4]);
|
|
38
|
+
// Draw vertical lines
|
|
39
|
+
for (let i = 1; i < this.numCols; i++) {
|
|
40
|
+
const x = i * this.sectorWidth;
|
|
41
|
+
ctx.beginPath();
|
|
42
|
+
ctx.moveTo(x, 0);
|
|
43
|
+
ctx.lineTo(x, this.height);
|
|
44
|
+
ctx.stroke();
|
|
45
|
+
}
|
|
46
|
+
// Draw horizontal lines
|
|
47
|
+
for (let i = 1; i < this.numRows; i++) {
|
|
48
|
+
const y = i * this.sectorHeight;
|
|
49
|
+
ctx.beginPath();
|
|
50
|
+
ctx.moveTo(0, y);
|
|
51
|
+
ctx.lineTo(this.width, y);
|
|
52
|
+
ctx.stroke();
|
|
53
|
+
}
|
|
54
|
+
ctx.setLineDash([]);
|
|
55
|
+
// Draw sector names
|
|
56
|
+
ctx.fillStyle = GRID_CONFIG.FONT_COLOR;
|
|
57
|
+
ctx.font = GRID_CONFIG.FONT;
|
|
58
|
+
ctx.textAlign = 'center';
|
|
59
|
+
ctx.textBaseline = 'middle';
|
|
60
|
+
for (let row = 0; row < this.numRows; row++) {
|
|
61
|
+
for (let col = 0; col < this.numCols; col++) {
|
|
62
|
+
const sectorName = `${String.fromCharCode(65 + row)}-${col + 1}`;
|
|
63
|
+
const centerX = col * this.sectorWidth + this.sectorWidth / 2;
|
|
64
|
+
const centerY = row * this.sectorHeight + this.sectorHeight / 2;
|
|
65
|
+
ctx.fillText(sectorName, centerX, centerY);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
ctx.restore();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Star } from './star';
|
|
2
|
+
import { Pulsar } from './pulsar';
|
|
3
|
+
import { RingedPlanet } from './ringed-planet';
|
|
4
|
+
interface StarOptions {
|
|
5
|
+
radius?: number;
|
|
6
|
+
hasAura?: boolean;
|
|
7
|
+
}
|
|
8
|
+
interface RingedPlanetOptions {
|
|
9
|
+
ringCount?: number;
|
|
10
|
+
}
|
|
11
|
+
export declare class StarFactory {
|
|
12
|
+
/**
|
|
13
|
+
* Creates a star of a random type (Standard, Pulsar, or Ringed Planet).
|
|
14
|
+
*/
|
|
15
|
+
createRandomStar(x: number, y: number): Star;
|
|
16
|
+
/**
|
|
17
|
+
* Creates a standard star.
|
|
18
|
+
*/
|
|
19
|
+
createStar(x: number, y: number, options?: StarOptions): Star;
|
|
20
|
+
/**
|
|
21
|
+
* Creates a pulsar star.
|
|
22
|
+
*/
|
|
23
|
+
createPulsar(x: number, y: number): Pulsar;
|
|
24
|
+
/**
|
|
25
|
+
* Creates a ringed planet.
|
|
26
|
+
*/
|
|
27
|
+
createRingedPlanet(x: number, y: number, options?: RingedPlanetOptions): RingedPlanet;
|
|
28
|
+
}
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Star } from './star';
|
|
2
|
+
import { Pulsar } from './pulsar';
|
|
3
|
+
import { RingedPlanet } from './ringed-planet';
|
|
4
|
+
export class StarFactory {
|
|
5
|
+
/**
|
|
6
|
+
* Creates a star of a random type (Standard, Pulsar, or Ringed Planet).
|
|
7
|
+
*/
|
|
8
|
+
createRandomStar(x, y) {
|
|
9
|
+
const rand = Math.random();
|
|
10
|
+
if (rand < 0.02) {
|
|
11
|
+
return this.createPulsar(x, y);
|
|
12
|
+
}
|
|
13
|
+
else if (rand < 0.02 + 0.03) {
|
|
14
|
+
return this.createRingedPlanet(x, y);
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
return this.createStar(x, y);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Creates a standard star.
|
|
22
|
+
*/
|
|
23
|
+
createStar(x, y, options = {}) {
|
|
24
|
+
const star = new Star(x, y);
|
|
25
|
+
if (options.radius) {
|
|
26
|
+
star.radius = options.radius;
|
|
27
|
+
star.baseRadius = options.radius;
|
|
28
|
+
}
|
|
29
|
+
if (options.hasAura !== undefined) {
|
|
30
|
+
star.hasAura = options.hasAura;
|
|
31
|
+
}
|
|
32
|
+
return star;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Creates a pulsar star.
|
|
36
|
+
*/
|
|
37
|
+
createPulsar(x, y) {
|
|
38
|
+
return new Pulsar(x, y);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Creates a ringed planet.
|
|
42
|
+
*/
|
|
43
|
+
createRingedPlanet(x, y, options = {}) {
|
|
44
|
+
const planet = new RingedPlanet(x, y, options.ringCount);
|
|
45
|
+
return planet;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Defines the Star class for the night sky simulation.
|
|
3
|
+
*/
|
|
4
|
+
import { MassiveBody } from '../base/massive-body';
|
|
5
|
+
import { DockingPoint } from './docking-point';
|
|
6
|
+
import { Orbit } from './orbit';
|
|
7
|
+
import type { Hoverable } from '../base/hoverable';
|
|
8
|
+
import type { BlackHole } from './black-hole';
|
|
9
|
+
export declare const STAR_CONFIG: {
|
|
10
|
+
RARE_STAR_CHANCE: number;
|
|
11
|
+
RARE_STAR_COLORS: string[];
|
|
12
|
+
AURA_CHANCE: number;
|
|
13
|
+
RINGED_PLANET_CHANCE: number;
|
|
14
|
+
MIN_RADIUS: number;
|
|
15
|
+
RADIUS_VARIANCE: number;
|
|
16
|
+
INITIAL_VELOCITY_RANGE: number;
|
|
17
|
+
INTERACTION_ACCELERATION: number;
|
|
18
|
+
VELOCITY_DECAY: number;
|
|
19
|
+
HOVER_RADIUS_MULTIPLIER: number;
|
|
20
|
+
HOVER_GLOW_COLOR: string;
|
|
21
|
+
HOVER_TIMEOUT: number;
|
|
22
|
+
};
|
|
23
|
+
export declare class Star extends MassiveBody implements Hoverable {
|
|
24
|
+
id: number;
|
|
25
|
+
name: string;
|
|
26
|
+
radius: number;
|
|
27
|
+
baseRadius: number;
|
|
28
|
+
ivx: number;
|
|
29
|
+
ivy: number;
|
|
30
|
+
color: string;
|
|
31
|
+
hasAura: boolean;
|
|
32
|
+
dockingPoints: DockingPoint[];
|
|
33
|
+
orbits: Orbit[];
|
|
34
|
+
isHovered: boolean;
|
|
35
|
+
hoverRadius: number;
|
|
36
|
+
hoverTimer: number;
|
|
37
|
+
respawnTimer: number;
|
|
38
|
+
constructor(x: number, y: number);
|
|
39
|
+
isEatenBy(blackHole: BlackHole): boolean;
|
|
40
|
+
respawn(newX: number, newY: number): void;
|
|
41
|
+
update(ctx: CanvasRenderingContext2D, width: number, height: number, mouse: {
|
|
42
|
+
dx: number;
|
|
43
|
+
dy: number;
|
|
44
|
+
}, interactive: boolean, isMouseInside: boolean, pulseTime?: number): void;
|
|
45
|
+
private drawDebugInfo;
|
|
46
|
+
drawBase(ctx: CanvasRenderingContext2D, pulseTime: number): void;
|
|
47
|
+
draw(ctx: CanvasRenderingContext2D, pulseTime: number): void;
|
|
48
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Defines the Star class for the night sky simulation.
|
|
3
|
+
*/
|
|
4
|
+
import { MassiveBody } from '../base/massive-body';
|
|
5
|
+
import { Orbit, ORBIT_CONFIG } from './orbit';
|
|
6
|
+
import { DEBUG_CONFIG } from '../config/simulation';
|
|
7
|
+
// --- Star Configuration ---
|
|
8
|
+
export const STAR_CONFIG = {
|
|
9
|
+
RARE_STAR_CHANCE: 0.1,
|
|
10
|
+
RARE_STAR_COLORS: ['#FFD700', '#ADD8E6', '#FFB6C1', '#87CEEB', '#DDA0DD', '#ffabab', '#a6d9ff'],
|
|
11
|
+
AURA_CHANCE: 0.15,
|
|
12
|
+
RINGED_PLANET_CHANCE: 0.03, // Chance to spawn a ringed planet
|
|
13
|
+
MIN_RADIUS: 0.5,
|
|
14
|
+
RADIUS_VARIANCE: 1.1,
|
|
15
|
+
INITIAL_VELOCITY_RANGE: 0.05,
|
|
16
|
+
INTERACTION_ACCELERATION: 0.02,
|
|
17
|
+
VELOCITY_DECAY: 0.96,
|
|
18
|
+
HOVER_RADIUS_MULTIPLIER: 8,
|
|
19
|
+
HOVER_GLOW_COLOR: 'rgba(255, 255, 255, 0.7)',
|
|
20
|
+
HOVER_TIMEOUT: 120, // 2 seconds in frames
|
|
21
|
+
};
|
|
22
|
+
let starCounter = 0;
|
|
23
|
+
export class Star extends MassiveBody {
|
|
24
|
+
constructor(x, y) {
|
|
25
|
+
const radius = Math.random() * STAR_CONFIG.RADIUS_VARIANCE + STAR_CONFIG.MIN_RADIUS;
|
|
26
|
+
const mass = radius * radius; // Mass is proportional to the square of the radius
|
|
27
|
+
super(x, y, radius, mass);
|
|
28
|
+
this.isHovered = false;
|
|
29
|
+
this.id = ++starCounter;
|
|
30
|
+
this.name = `S-${this.id}`;
|
|
31
|
+
this.radius = radius;
|
|
32
|
+
this.baseRadius = this.radius;
|
|
33
|
+
this.ivx = Math.random() * STAR_CONFIG.INITIAL_VELOCITY_RANGE * 2 - STAR_CONFIG.INITIAL_VELOCITY_RANGE;
|
|
34
|
+
this.ivy = Math.random() * STAR_CONFIG.INITIAL_VELOCITY_RANGE * 2 - STAR_CONFIG.INITIAL_VELOCITY_RANGE;
|
|
35
|
+
this.hasAura = Math.random() < STAR_CONFIG.AURA_CHANCE;
|
|
36
|
+
const isRare = Math.random() < STAR_CONFIG.RARE_STAR_CHANCE;
|
|
37
|
+
this.color = isRare
|
|
38
|
+
? STAR_CONFIG.RARE_STAR_COLORS[Math.floor(Math.random() * STAR_CONFIG.RARE_STAR_COLORS.length)]
|
|
39
|
+
: 'rgba(255, 255, 255, 0.8)';
|
|
40
|
+
this.dockingPoints = [];
|
|
41
|
+
this.orbits = [];
|
|
42
|
+
this.hoverTimer = 0;
|
|
43
|
+
this.respawnTimer = 0;
|
|
44
|
+
const orbitCount = Math.floor(Math.random() * (ORBIT_CONFIG.COUNT_MAX - ORBIT_CONFIG.COUNT_MIN + 1)) + ORBIT_CONFIG.COUNT_MIN;
|
|
45
|
+
let maxOrbitRadius = this.radius;
|
|
46
|
+
for (let i = 0; i < orbitCount; i++) {
|
|
47
|
+
const radiusMultiplier = (Math.random() * (ORBIT_CONFIG.RADIUS_MULTIPLIER_MAX - ORBIT_CONFIG.RADIUS_MULTIPLIER_MIN) + ORBIT_CONFIG.RADIUS_MULTIPLIER_MIN);
|
|
48
|
+
const orbitRadius = this.radius * radiusMultiplier;
|
|
49
|
+
maxOrbitRadius = Math.max(maxOrbitRadius, orbitRadius);
|
|
50
|
+
const orbitColor = this.color.startsWith('rgba')
|
|
51
|
+
? this.color.replace(/, [0-9\.]+$/, `, ${ORBIT_CONFIG.ALPHA})`)
|
|
52
|
+
: `rgba(255, 255, 255, ${ORBIT_CONFIG.ALPHA})`;
|
|
53
|
+
const orbit = new Orbit(this, orbitRadius, ORBIT_CONFIG.THICKNESS, orbitColor);
|
|
54
|
+
this.orbits.push(orbit);
|
|
55
|
+
this.dockingPoints.push(...orbit.dockingPoints);
|
|
56
|
+
}
|
|
57
|
+
this.hoverRadius = maxOrbitRadius + 10;
|
|
58
|
+
}
|
|
59
|
+
isEatenBy(blackHole) {
|
|
60
|
+
const dx = blackHole.x - this.x;
|
|
61
|
+
const dy = blackHole.y - this.y;
|
|
62
|
+
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
63
|
+
return distance < blackHole.radius;
|
|
64
|
+
}
|
|
65
|
+
respawn(newX, newY) {
|
|
66
|
+
this.x = newX;
|
|
67
|
+
this.y = newY;
|
|
68
|
+
this.vx = 0;
|
|
69
|
+
this.vy = 0;
|
|
70
|
+
this.ivx = Math.random() * STAR_CONFIG.INITIAL_VELOCITY_RANGE * 2 - STAR_CONFIG.INITIAL_VELOCITY_RANGE;
|
|
71
|
+
this.ivy = Math.random() * STAR_CONFIG.INITIAL_VELOCITY_RANGE * 2 - STAR_CONFIG.INITIAL_VELOCITY_RANGE;
|
|
72
|
+
this.respawnTimer = 60; // 60 frames = ~1 second
|
|
73
|
+
}
|
|
74
|
+
update(ctx, width, height, mouse, interactive, isMouseInside, pulseTime) {
|
|
75
|
+
if (this.respawnTimer > 0) {
|
|
76
|
+
this.respawnTimer--;
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (interactive && isMouseInside) {
|
|
80
|
+
const acc = STAR_CONFIG.INTERACTION_ACCELERATION;
|
|
81
|
+
this.vx += mouse.dx * acc;
|
|
82
|
+
this.vy += mouse.dy * acc;
|
|
83
|
+
}
|
|
84
|
+
this.vx *= STAR_CONFIG.VELOCITY_DECAY;
|
|
85
|
+
this.vy *= STAR_CONFIG.VELOCITY_DECAY;
|
|
86
|
+
this.x += this.vx + this.ivx;
|
|
87
|
+
this.y += this.vy + this.ivy;
|
|
88
|
+
if (this.x < 0)
|
|
89
|
+
this.x = width;
|
|
90
|
+
if (this.x > width)
|
|
91
|
+
this.x = 0;
|
|
92
|
+
if (this.y < 0)
|
|
93
|
+
this.y = height;
|
|
94
|
+
if (this.y > height)
|
|
95
|
+
this.y = 0;
|
|
96
|
+
}
|
|
97
|
+
drawDebugInfo(ctx) {
|
|
98
|
+
const startX = this.x + this.hoverRadius + 15;
|
|
99
|
+
const boxPadding = 10;
|
|
100
|
+
const lineHeight = 14;
|
|
101
|
+
const infoLines = [
|
|
102
|
+
`Name: ${this.name}`,
|
|
103
|
+
`Type: ${this.constructor.name}`,
|
|
104
|
+
`Radius: ${this.radius.toFixed(2)}`,
|
|
105
|
+
`Mass: ${this.mass.toFixed(2)}`,
|
|
106
|
+
`Color: ${this.color}`,
|
|
107
|
+
`Position: (${this.x.toFixed(0)}, ${this.y.toFixed(0)})`,
|
|
108
|
+
`Velocity: (${this.vx.toFixed(2)}, ${this.vy.toFixed(2)})`,
|
|
109
|
+
`Orbits: ${this.orbits.length}`,
|
|
110
|
+
`Docking Points: ${this.dockingPoints.length}`,
|
|
111
|
+
];
|
|
112
|
+
const boxHeight = infoLines.length * lineHeight + boxPadding * 2;
|
|
113
|
+
const boxWidth = Math.max(...infoLines.map(line => ctx.measureText(line).width)) + boxPadding * 2;
|
|
114
|
+
const boxY = this.y - boxHeight / 2;
|
|
115
|
+
ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';
|
|
116
|
+
ctx.strokeStyle = this.color;
|
|
117
|
+
ctx.lineWidth = 1;
|
|
118
|
+
ctx.beginPath();
|
|
119
|
+
ctx.roundRect(startX, boxY, boxWidth, boxHeight, 5);
|
|
120
|
+
ctx.fill();
|
|
121
|
+
ctx.stroke();
|
|
122
|
+
ctx.fillStyle = 'white';
|
|
123
|
+
ctx.font = '10px "Roboto Mono", monospace';
|
|
124
|
+
ctx.textAlign = 'left';
|
|
125
|
+
ctx.textBaseline = 'top';
|
|
126
|
+
infoLines.forEach((line, index) => {
|
|
127
|
+
ctx.fillText(line, startX + boxPadding, boxY + boxPadding + index * lineHeight);
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
// A new base drawing function that can be called by subclasses
|
|
131
|
+
drawBase(ctx, pulseTime) {
|
|
132
|
+
// Orbits are drawn first, behind the star
|
|
133
|
+
this.orbits.forEach(orbit => orbit.draw(ctx));
|
|
134
|
+
// Draw hover effect if hovered
|
|
135
|
+
this.isHovered = this.hoverTimer > 0;
|
|
136
|
+
if (this.isHovered) {
|
|
137
|
+
ctx.strokeStyle = STAR_CONFIG.HOVER_GLOW_COLOR;
|
|
138
|
+
ctx.lineWidth = 0.5;
|
|
139
|
+
ctx.shadowColor = STAR_CONFIG.HOVER_GLOW_COLOR;
|
|
140
|
+
ctx.shadowBlur = 10;
|
|
141
|
+
ctx.beginPath();
|
|
142
|
+
ctx.arc(this.x, this.y, this.hoverRadius, 0, Math.PI * 2);
|
|
143
|
+
ctx.stroke();
|
|
144
|
+
ctx.shadowBlur = 0;
|
|
145
|
+
if (DEBUG_CONFIG.SHOW_DEBUG_INFO && DEBUG_CONFIG.SHOW_ENTITY_HOVER_INFO) {
|
|
146
|
+
this.drawDebugInfo(ctx);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
ctx.save();
|
|
150
|
+
ctx.fillStyle = this.color;
|
|
151
|
+
ctx.beginPath();
|
|
152
|
+
if (this.hasAura && !this.isHovered) { // Apply aura only if not hovered to avoid conflicting glows
|
|
153
|
+
ctx.shadowColor = this.color;
|
|
154
|
+
ctx.shadowBlur = 20;
|
|
155
|
+
}
|
|
156
|
+
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
|
|
157
|
+
ctx.fill();
|
|
158
|
+
ctx.restore();
|
|
159
|
+
// Reset shadow blur after drawing the main body
|
|
160
|
+
if (this.hasAura || this.isHovered) {
|
|
161
|
+
ctx.shadowBlur = 0;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
draw(ctx, pulseTime) {
|
|
165
|
+
this.drawBase(ctx, pulseTime);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Defines all starship classes, shapes, and properties, and the Starship class itself.
|
|
3
|
+
*/
|
|
4
|
+
import { BoundedBody } from '../base/bounded-body';
|
|
5
|
+
import type { Star } from './star';
|
|
6
|
+
import type { DockingPoint } from './docking-point';
|
|
7
|
+
import type { Orbit } from './orbit';
|
|
8
|
+
import type { Hoverable } from '../base/hoverable';
|
|
9
|
+
import type { Fleet } from './fleet';
|
|
10
|
+
import { DebugController } from '../controllers/debug-controller';
|
|
11
|
+
export declare const SHAPES: Record<string, ((ctx: CanvasRenderingContext2D, r: number) => void)[]>;
|
|
12
|
+
export interface ShipClass {
|
|
13
|
+
name: string;
|
|
14
|
+
category: 'Capital' | 'Cruiser' | 'Escort' | 'Support' | 'Small Craft' | 'Exploration & Science' | 'Commerce & Logistics' | 'Resource Extraction' | 'Diplomatic & Civil';
|
|
15
|
+
shape: (ctx: CanvasRenderingContext2D, r: number) => void;
|
|
16
|
+
radius: number;
|
|
17
|
+
color: string;
|
|
18
|
+
accentColor: string;
|
|
19
|
+
}
|
|
20
|
+
export declare const SHIP_CLASS_TEMPLATES: Record<string, Omit<ShipClass, 'shape' | 'accentColor'> & {
|
|
21
|
+
shapeKey: keyof typeof SHAPES;
|
|
22
|
+
}>;
|
|
23
|
+
/**
|
|
24
|
+
* Returns a random ship class with a specific shape variant selected.
|
|
25
|
+
* @returns {ShipClass} A random ship class instance.
|
|
26
|
+
*/
|
|
27
|
+
export declare function getRandomShipClass(): ShipClass;
|
|
28
|
+
export declare const STARSHIP_CONFIG: {
|
|
29
|
+
COUNT: number;
|
|
30
|
+
MIN_SPEED: number;
|
|
31
|
+
MAX_SPEED: number;
|
|
32
|
+
ACCELERATION: number;
|
|
33
|
+
DOCKING_DISTANCE: number;
|
|
34
|
+
DOCK_DURATION_MIN: number;
|
|
35
|
+
DOCK_DURATION_VARIANCE: number;
|
|
36
|
+
TRAIL_LENGTH: number;
|
|
37
|
+
WARP_CHANCE: number;
|
|
38
|
+
WARP_SPEED_MULTIPLIER: number;
|
|
39
|
+
WARP_TRAIL_LENGTH_MULTIPLIER: number;
|
|
40
|
+
FORMATION_PADDING: number;
|
|
41
|
+
FLEE_DISTANCE: number;
|
|
42
|
+
FLEE_ACCELERATION: number;
|
|
43
|
+
FLEE_DURATION: number;
|
|
44
|
+
HOVER_RADIUS_MULTIPLIER: number;
|
|
45
|
+
HOVER_GLOW_COLOR: string;
|
|
46
|
+
HOVER_GLOW_WIDTH: number;
|
|
47
|
+
HOVER_TIMEOUT: number;
|
|
48
|
+
REFORM_ACCELERATION: number;
|
|
49
|
+
REFORM_SPEED_MULTIPLIER: number;
|
|
50
|
+
};
|
|
51
|
+
export type ShipState = 'IDLE' | 'TRAVELING' | 'DOCKING' | 'WARPING' | 'ORBITING' | 'FLEEING' | 'IN_FORMATION';
|
|
52
|
+
export declare class Starship extends BoundedBody implements Hoverable {
|
|
53
|
+
id: number;
|
|
54
|
+
name: string;
|
|
55
|
+
shipClass: ShipClass;
|
|
56
|
+
radius: number;
|
|
57
|
+
target: DockingPoint | null;
|
|
58
|
+
rotation: number;
|
|
59
|
+
state: ShipState;
|
|
60
|
+
stateTimer: number;
|
|
61
|
+
currentMaxSpeed: number;
|
|
62
|
+
isHovered: boolean;
|
|
63
|
+
hoverRadius: number;
|
|
64
|
+
hoverTimer: number;
|
|
65
|
+
fleet: Fleet | null;
|
|
66
|
+
private debugController;
|
|
67
|
+
orbit: Orbit | null;
|
|
68
|
+
orbitAngle: number;
|
|
69
|
+
orbitSpeed: number;
|
|
70
|
+
private warpTotalDistance;
|
|
71
|
+
private warpDistanceTraveled;
|
|
72
|
+
constructor(x: number, y: number, debugController: DebugController);
|
|
73
|
+
private getNewMaxSpeed;
|
|
74
|
+
isAvailable(): boolean;
|
|
75
|
+
private getNewIdleTime;
|
|
76
|
+
findNewTarget(starsWithDocks: Star[]): void;
|
|
77
|
+
enterWarpState(target: DockingPoint): void;
|
|
78
|
+
private updateDocking;
|
|
79
|
+
private updateOrbiting;
|
|
80
|
+
accelerateToPosition(targetX: number, targetY: number): void;
|
|
81
|
+
private updateTraveling;
|
|
82
|
+
private updateWarping;
|
|
83
|
+
private updateFleeing;
|
|
84
|
+
update(ctx: CanvasRenderingContext2D, width: number, height: number, mouse: {
|
|
85
|
+
x: number;
|
|
86
|
+
y: number;
|
|
87
|
+
}, deltaTime: number): void;
|
|
88
|
+
private drawWarpTrail;
|
|
89
|
+
private drawDebugInfo;
|
|
90
|
+
draw(ctx: CanvasRenderingContext2D): void;
|
|
91
|
+
}
|