dopaminejs 2.1.0 → 2.2.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/dist/dopamine.js +166 -93
- package/dist/dopamine.umd.cjs +2 -2
- package/package.json +6 -3
- package/src/dopamine/core/RewardSystem.js +81 -7
- package/src/index.js +6 -0
- package/src/systems/Input.js +8 -4
- package/src/systems/Loader.js +7 -3
- package/src/systems/Physics.js +7 -3
- package/src/systems/deprecate.js +38 -0
- package/types/index.d.ts +588 -0
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,588 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type declarations for dopaminejs.
|
|
3
|
+
*
|
|
4
|
+
* Hand-written to match src/index.js. The runtime is plain JavaScript with
|
|
5
|
+
* JSDoc; these exist so TypeScript consumers get completion and checking
|
|
6
|
+
* without the project adopting TypeScript.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// Reward system
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
|
|
13
|
+
export interface PlayerStreak {
|
|
14
|
+
current: number;
|
|
15
|
+
longest: number;
|
|
16
|
+
/** Local calendar day, YYYY-MM-DD. Not UTC. */
|
|
17
|
+
lastPlayDate: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface UnlockedAchievement {
|
|
21
|
+
unlockedAt: number;
|
|
22
|
+
seen: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface Player {
|
|
26
|
+
name: string;
|
|
27
|
+
xp: number;
|
|
28
|
+
level: number;
|
|
29
|
+
totalGamesPlayed: number;
|
|
30
|
+
createdAt: number;
|
|
31
|
+
lastPlayedAt: number;
|
|
32
|
+
streak: PlayerStreak;
|
|
33
|
+
achievements: Record<string, UnlockedAchievement>;
|
|
34
|
+
/** Per-game stats. Games add their own keys. */
|
|
35
|
+
stats: Record<string, Record<string, number>>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface AchievementDefinition {
|
|
39
|
+
name: string;
|
|
40
|
+
description?: string;
|
|
41
|
+
/** Rendered as HTML, so an <img> or inline SVG is allowed here. */
|
|
42
|
+
icon?: string;
|
|
43
|
+
/** Omitted means 0. Never undefined at runtime. */
|
|
44
|
+
xp?: number;
|
|
45
|
+
check(player: Player, gameName?: string, result?: GameResult): boolean;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface GameResult {
|
|
49
|
+
score?: number;
|
|
50
|
+
[metric: string]: number | undefined;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface XPProgress {
|
|
54
|
+
/** Total XP marking the next level. */
|
|
55
|
+
total: number;
|
|
56
|
+
/** XP still required, floored at 0. */
|
|
57
|
+
needed: number;
|
|
58
|
+
/** Position within the current level band, 0 to 1 inclusive. */
|
|
59
|
+
progress: number;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface AddXPResult {
|
|
63
|
+
leveledUp: boolean;
|
|
64
|
+
newLevel: number;
|
|
65
|
+
xpGained: number;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface RewardSystemConfig {
|
|
69
|
+
achievements?: Record<string, AchievementDefinition>;
|
|
70
|
+
/** Mirror reward events onto a kernel EventBus. */
|
|
71
|
+
events?: EventBus;
|
|
72
|
+
/** Alternative to `events`; the kernel's bus is used. */
|
|
73
|
+
kernel?: DopamineKernel;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export type RewardEvent =
|
|
77
|
+
| 'xp_gained'
|
|
78
|
+
| 'level_up'
|
|
79
|
+
| 'achievement_unlocked'
|
|
80
|
+
| 'new_high_score';
|
|
81
|
+
|
|
82
|
+
export class EventEmitter {
|
|
83
|
+
on(event: string, callback: (data?: unknown) => void): () => void;
|
|
84
|
+
off(event: string, callback: (data?: unknown) => void): void;
|
|
85
|
+
emit(event: string, data?: unknown): void;
|
|
86
|
+
clear(): void;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export class RewardSystem extends EventEmitter {
|
|
90
|
+
constructor(dataService: DataService, config?: RewardSystemConfig);
|
|
91
|
+
|
|
92
|
+
player: Player | null;
|
|
93
|
+
achievements: Record<string, AchievementDefinition>;
|
|
94
|
+
/** Kernel bus events are mirrored onto, if one was supplied. */
|
|
95
|
+
events: EventBus | null;
|
|
96
|
+
|
|
97
|
+
init(): Promise<Player>;
|
|
98
|
+
save(): Promise<void>;
|
|
99
|
+
|
|
100
|
+
/** @throws TypeError if `amount` is not finite. */
|
|
101
|
+
addXP(amount: number, reason?: string): Promise<AddXPResult>;
|
|
102
|
+
getXPForNextLevel(): XPProgress;
|
|
103
|
+
|
|
104
|
+
/** Persists once for the whole call, not once per internal mutation. */
|
|
105
|
+
recordGame(gameName: string, result: GameResult): Promise<void>;
|
|
106
|
+
|
|
107
|
+
checkAchievements(gameName: string, result: GameResult): Promise<AchievementDefinition[]>;
|
|
108
|
+
unlockAchievement(achievementId: string): Promise<boolean>;
|
|
109
|
+
getUnlockedAchievements(): Array<AchievementDefinition & UnlockedAchievement & { id: string }>;
|
|
110
|
+
getUnseenAchievements(): Array<AchievementDefinition & UnlockedAchievement & { id: string }>;
|
|
111
|
+
markAchievementsSeen(achievementIds: string[]): Promise<void>;
|
|
112
|
+
getStreakMultiplier(): number;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// ---------------------------------------------------------------------------
|
|
116
|
+
// Persistence
|
|
117
|
+
// ---------------------------------------------------------------------------
|
|
118
|
+
|
|
119
|
+
export interface StorageLike {
|
|
120
|
+
getItem(key: string): string | null;
|
|
121
|
+
setItem(key: string, value: string): void;
|
|
122
|
+
removeItem(key: string): void;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export interface DataServiceConfig {
|
|
126
|
+
/** Defaults to localStorage, falling back to an in-memory store. */
|
|
127
|
+
storage?: StorageLike;
|
|
128
|
+
/** Key prefix, default 'dopamine_'. */
|
|
129
|
+
prefix?: string;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export class DataService {
|
|
133
|
+
constructor(config?: DataServiceConfig);
|
|
134
|
+
storage: StorageLike;
|
|
135
|
+
prefix: string;
|
|
136
|
+
save(key: string, data: unknown): Promise<boolean>;
|
|
137
|
+
load<T = unknown>(key: string, defaultValue?: T | null): Promise<T | null>;
|
|
138
|
+
clear(key: string): Promise<void>;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** Storage backed by a Map. Used when localStorage is absent or blocked. */
|
|
142
|
+
export function createMemoryStorage(): StorageLike;
|
|
143
|
+
/** localStorage if present and writable, otherwise an in-memory store. */
|
|
144
|
+
export function resolveStorage(): StorageLike;
|
|
145
|
+
|
|
146
|
+
// ---------------------------------------------------------------------------
|
|
147
|
+
// UI
|
|
148
|
+
// ---------------------------------------------------------------------------
|
|
149
|
+
|
|
150
|
+
export interface SummaryData {
|
|
151
|
+
score: number | string;
|
|
152
|
+
/** Label to value pairs. Rendered as text. */
|
|
153
|
+
metrics?: Record<string, number | string>;
|
|
154
|
+
/** Defaults to reloading the page. */
|
|
155
|
+
onReplay?: () => void;
|
|
156
|
+
/** Exit button is omitted when this is not supplied. */
|
|
157
|
+
onExit?: () => void;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export class GameUI {
|
|
161
|
+
constructor(particleSystem: ParticleSystem);
|
|
162
|
+
|
|
163
|
+
container: HTMLElement | null;
|
|
164
|
+
|
|
165
|
+
updateXP(current: number, needed: number, total: number): void;
|
|
166
|
+
updateLevel(level: number): void;
|
|
167
|
+
updateStreak(days: number): void;
|
|
168
|
+
|
|
169
|
+
showAchievement(achievement: AchievementDefinition): void;
|
|
170
|
+
showLevelUp(oldLevel: number, newLevel: number): void;
|
|
171
|
+
showFloatingText(text: string, x: number, y: number, color?: string, size?: string): void;
|
|
172
|
+
showCombo(multiplier: number, x: number, y: number): void;
|
|
173
|
+
showNearMiss(x: number, y: number): void;
|
|
174
|
+
showLuckyMoment(multiplier: number, x: number, y: number): void;
|
|
175
|
+
showNotification(message: string, type?: 'normal' | 'rare' | 'legendary'): void;
|
|
176
|
+
showSummary(data: SummaryData): HTMLElement;
|
|
177
|
+
|
|
178
|
+
/** Removes the overlay, any transient popups, and all pending timers. */
|
|
179
|
+
destroy(): void;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// ---------------------------------------------------------------------------
|
|
183
|
+
// Particles
|
|
184
|
+
// ---------------------------------------------------------------------------
|
|
185
|
+
|
|
186
|
+
export interface ParticleSystemConfig {
|
|
187
|
+
/** Element or selector. Defaults to document.body. */
|
|
188
|
+
container?: HTMLElement | string;
|
|
189
|
+
canvasId?: string;
|
|
190
|
+
zIndex?: string;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export interface ParticleConfig {
|
|
194
|
+
x: number;
|
|
195
|
+
y: number;
|
|
196
|
+
count?: number;
|
|
197
|
+
color?: string;
|
|
198
|
+
size?: number;
|
|
199
|
+
life?: number;
|
|
200
|
+
decay?: number;
|
|
201
|
+
gravity?: number;
|
|
202
|
+
spread?: number;
|
|
203
|
+
speed?: number;
|
|
204
|
+
type?: string;
|
|
205
|
+
sprite?: string;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export class ParticleSystem {
|
|
209
|
+
constructor(config?: ParticleSystemConfig);
|
|
210
|
+
|
|
211
|
+
canvas: HTMLCanvasElement;
|
|
212
|
+
/** Width in CSS pixels. The backing store is scaled by devicePixelRatio. */
|
|
213
|
+
width: number;
|
|
214
|
+
height: number;
|
|
215
|
+
isAnimating: boolean;
|
|
216
|
+
|
|
217
|
+
registerSprite(key: string, url: string): void;
|
|
218
|
+
registerEffect(name: string, callback: (x: number, y: number, ...args: unknown[]) => void): void;
|
|
219
|
+
play(name: string, x: number, y: number, ...args: unknown[]): void;
|
|
220
|
+
emit(config: ParticleConfig): void;
|
|
221
|
+
|
|
222
|
+
confetti(x: number, y: number, count?: number): void;
|
|
223
|
+
coinShower(x: number, y: number, count?: number): void;
|
|
224
|
+
sparkle(x: number, y: number, count?: number, color?: string): void;
|
|
225
|
+
fire(x: number, y: number, count?: number): void;
|
|
226
|
+
starBurst(x: number, y: number, count?: number): void;
|
|
227
|
+
|
|
228
|
+
clear(): void;
|
|
229
|
+
/** Stops animation, detaches resize handling, removes the canvas. */
|
|
230
|
+
destroy(): void;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// ---------------------------------------------------------------------------
|
|
234
|
+
// Audio
|
|
235
|
+
// ---------------------------------------------------------------------------
|
|
236
|
+
|
|
237
|
+
export interface SoundManagerConfig {
|
|
238
|
+
storageKey?: string;
|
|
239
|
+
storage?: StorageLike;
|
|
240
|
+
/** Master volume 0 to 1, default 1. */
|
|
241
|
+
volume?: number;
|
|
242
|
+
/** Key to URL map, preloaded on construction. */
|
|
243
|
+
customSounds?: Record<string, string>;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export class SoundManager {
|
|
247
|
+
constructor(config?: SoundManagerConfig);
|
|
248
|
+
|
|
249
|
+
muted: boolean;
|
|
250
|
+
assets: Map<string, AudioBuffer>;
|
|
251
|
+
customSounds: Record<string, string>;
|
|
252
|
+
|
|
253
|
+
/** Returns false when no Web Audio API is available, rather than throwing. */
|
|
254
|
+
initAudio(): boolean;
|
|
255
|
+
setVolume(value: number): number;
|
|
256
|
+
getVolume(): number;
|
|
257
|
+
toggleMute(): boolean;
|
|
258
|
+
|
|
259
|
+
registerSound(key: string, url: string): void;
|
|
260
|
+
preloadSounds(soundMap: Record<string, string>): Promise<void>;
|
|
261
|
+
loadSound(key: string, url: string): Promise<void>;
|
|
262
|
+
play(key: string): Promise<void>;
|
|
263
|
+
playTone(frequency: number, duration: number, type?: OscillatorType, volume?: number): void;
|
|
264
|
+
|
|
265
|
+
playJump(force?: boolean): void;
|
|
266
|
+
playScore(force?: boolean): void;
|
|
267
|
+
playGameOver(force?: boolean): void;
|
|
268
|
+
playClick(force?: boolean): void;
|
|
269
|
+
playSuccess(force?: boolean): void;
|
|
270
|
+
playError(force?: boolean): void;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// ---------------------------------------------------------------------------
|
|
274
|
+
// Kernel
|
|
275
|
+
// ---------------------------------------------------------------------------
|
|
276
|
+
|
|
277
|
+
export interface EventBusEvents {
|
|
278
|
+
TICK: 'tick';
|
|
279
|
+
FIXED_UPDATE: 'fixed_update';
|
|
280
|
+
RENDER: 'render';
|
|
281
|
+
COLLISION_ENTER: 'collision_enter';
|
|
282
|
+
COLLISION_EXIT: 'collision_exit';
|
|
283
|
+
XP_GAINED: 'xp_gained';
|
|
284
|
+
LEVEL_UP: 'level_up';
|
|
285
|
+
ACHIEVEMENT_UNLOCKED: 'achievement_unlocked';
|
|
286
|
+
NEW_HIGH_SCORE: 'new_high_score';
|
|
287
|
+
STREAK_UPDATED: 'streak_updated';
|
|
288
|
+
SYSTEM_REGISTERED: 'system_registered';
|
|
289
|
+
SYSTEM_UNREGISTERED: 'system_unregistered';
|
|
290
|
+
PLUGIN_LOADED: 'plugin_loaded';
|
|
291
|
+
PLUGIN_UNLOADED: 'plugin_unloaded';
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
export class EventBus {
|
|
295
|
+
static readonly Events: EventBusEvents;
|
|
296
|
+
|
|
297
|
+
/** Higher priority runs first. */
|
|
298
|
+
on(event: string, callback: (data?: any) => void, priority?: number): this;
|
|
299
|
+
once(event: string, callback: (data?: any) => void): this;
|
|
300
|
+
/** Removes every registration of `callback` for `event`. */
|
|
301
|
+
off(event: string, callback: (data?: any) => void): this;
|
|
302
|
+
/** A throwing listener is logged and does not abort the remaining ones. */
|
|
303
|
+
emit(event: string, data?: any): void;
|
|
304
|
+
clear(event?: string): void;
|
|
305
|
+
hasListeners(event: string): boolean;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
export interface ISystemLike {
|
|
309
|
+
init?(kernel: DopamineKernel): void;
|
|
310
|
+
update?(dt: number): void;
|
|
311
|
+
fixedUpdate?(dt: number): void;
|
|
312
|
+
destroy?(): void;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
export interface SystemRegisterOptions {
|
|
316
|
+
/** Higher runs earlier. Default 0. */
|
|
317
|
+
priority?: number;
|
|
318
|
+
/** Names of systems that must update first. */
|
|
319
|
+
dependencies?: string[];
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
export class SystemRegistry {
|
|
323
|
+
constructor(kernel: DopamineKernel);
|
|
324
|
+
register(name: string, system: ISystemLike, options?: SystemRegisterOptions): this;
|
|
325
|
+
get<T = ISystemLike>(name: string): T | undefined;
|
|
326
|
+
has(name: string): boolean;
|
|
327
|
+
unregister(name: string): boolean;
|
|
328
|
+
update(dt: number): void;
|
|
329
|
+
fixedUpdate(dt: number): void;
|
|
330
|
+
getSystemNames(): string[];
|
|
331
|
+
clear(): void;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
export interface Plugin {
|
|
335
|
+
name: string;
|
|
336
|
+
version?: string;
|
|
337
|
+
init(kernel: DopamineKernel): void | Promise<void>;
|
|
338
|
+
destroy?(): void;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
export class PluginRegistry {
|
|
342
|
+
constructor(kernel: DopamineKernel);
|
|
343
|
+
use(plugin: Plugin): this;
|
|
344
|
+
useAsync(plugin: Plugin): Promise<this>;
|
|
345
|
+
remove(name: string): boolean;
|
|
346
|
+
get(name: string): Plugin | undefined;
|
|
347
|
+
has(name: string): boolean;
|
|
348
|
+
getPluginNames(): string[];
|
|
349
|
+
getLoadOrder(): string[];
|
|
350
|
+
clear(): void;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
export interface KernelConfig {
|
|
354
|
+
width?: number;
|
|
355
|
+
height?: number;
|
|
356
|
+
backgroundColor?: string;
|
|
357
|
+
canvas?: HTMLCanvasElement;
|
|
358
|
+
renderer?: Record<string, unknown>;
|
|
359
|
+
/** Seconds per fixed update. Default 1/60. */
|
|
360
|
+
fixedTimestep?: number;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
export class DopamineKernel {
|
|
364
|
+
constructor(config?: KernelConfig);
|
|
365
|
+
|
|
366
|
+
config: KernelConfig;
|
|
367
|
+
events: EventBus;
|
|
368
|
+
systems: SystemRegistry;
|
|
369
|
+
plugins: PluginRegistry;
|
|
370
|
+
fixedTimestep: number;
|
|
371
|
+
|
|
372
|
+
readonly physics: Physics;
|
|
373
|
+
readonly input: Input;
|
|
374
|
+
readonly loader: Loader;
|
|
375
|
+
readonly renderer: Renderer;
|
|
376
|
+
readonly ticker: Ticker;
|
|
377
|
+
|
|
378
|
+
start(): void;
|
|
379
|
+
stop(): void;
|
|
380
|
+
destroy(): void;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// ---------------------------------------------------------------------------
|
|
384
|
+
// Engine core
|
|
385
|
+
// ---------------------------------------------------------------------------
|
|
386
|
+
|
|
387
|
+
export class Vector2 {
|
|
388
|
+
constructor(x?: number, y?: number);
|
|
389
|
+
x: number;
|
|
390
|
+
y: number;
|
|
391
|
+
add(v: Vector2): Vector2;
|
|
392
|
+
sub(v: Vector2): Vector2;
|
|
393
|
+
scale(s: number): Vector2;
|
|
394
|
+
distance(v: Vector2): number;
|
|
395
|
+
normalize(): Vector2;
|
|
396
|
+
clone(): Vector2;
|
|
397
|
+
static distance(a: Vector2, b: Vector2): number;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
export class Component {
|
|
401
|
+
gameObject: GameObject | null;
|
|
402
|
+
kernel: DopamineKernel | null;
|
|
403
|
+
onAttach(): void;
|
|
404
|
+
onDetach(): void;
|
|
405
|
+
update(dt: number): void;
|
|
406
|
+
render(ctx: CanvasRenderingContext2D): void;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
export interface Bounds {
|
|
410
|
+
x: number;
|
|
411
|
+
y: number;
|
|
412
|
+
width: number;
|
|
413
|
+
height: number;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
export class Collider extends Component {
|
|
417
|
+
constructor(type?: 'box' | 'circle', width?: number, height?: number, radius?: number);
|
|
418
|
+
type: 'box' | 'circle';
|
|
419
|
+
width: number;
|
|
420
|
+
height: number;
|
|
421
|
+
radius: number;
|
|
422
|
+
getBounds(): Bounds;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
export class Sprite extends Component {
|
|
426
|
+
constructor(image: HTMLImageElement | HTMLCanvasElement);
|
|
427
|
+
setFrame(x: number, y: number, w: number, h: number): void;
|
|
428
|
+
setTexture(image: HTMLImageElement | HTMLCanvasElement): void;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
export class Animator extends Component {
|
|
432
|
+
addAnimation(name: string, frames: unknown[], fps?: number, loop?: boolean): void;
|
|
433
|
+
play(name: string): void;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
export class GameObject {
|
|
437
|
+
constructor(x?: number, y?: number);
|
|
438
|
+
position: Vector2;
|
|
439
|
+
rotation: number;
|
|
440
|
+
scale: Vector2;
|
|
441
|
+
components: Component[];
|
|
442
|
+
children: GameObject[];
|
|
443
|
+
kernel: DopamineKernel | null;
|
|
444
|
+
tag?: string;
|
|
445
|
+
addChild(child: GameObject): GameObject;
|
|
446
|
+
addComponent<T extends Component>(component: T): T;
|
|
447
|
+
getComponent<T extends Component>(type: new (...args: any[]) => T): T | undefined;
|
|
448
|
+
update(dt: number): void;
|
|
449
|
+
render(ctx: CanvasRenderingContext2D): void;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
export class Scene {
|
|
453
|
+
gameObjects: GameObject[];
|
|
454
|
+
kernel: DopamineKernel | null;
|
|
455
|
+
onEnter(): void;
|
|
456
|
+
onExit(): void;
|
|
457
|
+
add(gameObject: GameObject): GameObject;
|
|
458
|
+
remove(gameObject: GameObject): void;
|
|
459
|
+
update(dt: number): void;
|
|
460
|
+
render(ctx: CanvasRenderingContext2D): void;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
export class Renderer {
|
|
464
|
+
constructor(options?: Record<string, unknown>);
|
|
465
|
+
canvas: HTMLCanvasElement;
|
|
466
|
+
ctx: CanvasRenderingContext2D;
|
|
467
|
+
clear(): void;
|
|
468
|
+
resize(width: number, height: number): void;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
export class Ticker {
|
|
472
|
+
add(callback: (dt: number) => void): void;
|
|
473
|
+
remove(callback: (dt: number) => void): void;
|
|
474
|
+
/** Cancels any pending frame first, so restarting cannot double-step. */
|
|
475
|
+
start(): void;
|
|
476
|
+
stop(): void;
|
|
477
|
+
running: boolean;
|
|
478
|
+
callbacks: Set<(dt: number) => void>;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
export class Loader {
|
|
482
|
+
init(kernel: DopamineKernel): void;
|
|
483
|
+
destroy(): void;
|
|
484
|
+
loadImage(key: string, url: string): Promise<HTMLImageElement>;
|
|
485
|
+
get(key: string): HTMLImageElement | undefined;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
export class Input {
|
|
489
|
+
init(kernel: DopamineKernel): void;
|
|
490
|
+
destroy(): void;
|
|
491
|
+
isKeyDown(key: string): boolean;
|
|
492
|
+
isMouseButtonDown(button?: number): boolean;
|
|
493
|
+
mouse: { x: number; y: number };
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
export class Physics {
|
|
497
|
+
init(kernel: DopamineKernel): void;
|
|
498
|
+
fixedUpdate(dt: number): void;
|
|
499
|
+
destroy(): void;
|
|
500
|
+
add(collider: Collider): void;
|
|
501
|
+
remove(collider: Collider): void;
|
|
502
|
+
step(): void;
|
|
503
|
+
checkOverlap(source: Collider, targetTag: string): GameObject | null;
|
|
504
|
+
addBody(body: Collider): void;
|
|
505
|
+
removeBody(body: Collider): void;
|
|
506
|
+
checkCollision(a: Collider, b: Collider): boolean;
|
|
507
|
+
/** Not implemented. Always null. */
|
|
508
|
+
raycast(origin: Vector2, direction: Vector2, distance: number): null;
|
|
509
|
+
/** Not implemented. */
|
|
510
|
+
setGravity(x: number, y: number): void;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
export class Director {
|
|
514
|
+
constructor(game: Game);
|
|
515
|
+
run(scene: Scene): void;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
export class Game {
|
|
519
|
+
constructor(config?: KernelConfig);
|
|
520
|
+
kernel: DopamineKernel;
|
|
521
|
+
scene: Scene | null;
|
|
522
|
+
start(): void;
|
|
523
|
+
stop(): void;
|
|
524
|
+
setScene(newScene: Scene): void;
|
|
525
|
+
destroy(): void;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
export class TextureGenerator {
|
|
529
|
+
static createGround(width: number, height: number, color?: string): HTMLCanvasElement;
|
|
530
|
+
static createCharacterSheet(colorBody: string, colorDetail: string): HTMLCanvasElement;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
export class ParticleEmitter extends Component {
|
|
534
|
+
constructor(particleSystem: ParticleSystem);
|
|
535
|
+
play(effectName: string, options?: Record<string, unknown>): void;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
export class ScreenShake extends Component {
|
|
539
|
+
shake(intensity?: number, duration?: number): void;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
/** Deprecated singletons kept for v1 compatibility. Prefer kernel.<system>. */
|
|
543
|
+
export const GlobalLoader: Loader;
|
|
544
|
+
export const GlobalInput: Input;
|
|
545
|
+
export const GlobalPhysics: Physics;
|
|
546
|
+
|
|
547
|
+
// ---------------------------------------------------------------------------
|
|
548
|
+
// Interfaces
|
|
549
|
+
// ---------------------------------------------------------------------------
|
|
550
|
+
|
|
551
|
+
export const ISystem: Record<string, unknown>;
|
|
552
|
+
export const System: Record<string, unknown>;
|
|
553
|
+
export const IPhysicsSystem: Record<string, unknown>;
|
|
554
|
+
export const IAudioSystem: Record<string, unknown>;
|
|
555
|
+
export const IParticleSystem: Record<string, unknown>;
|
|
556
|
+
|
|
557
|
+
// ---------------------------------------------------------------------------
|
|
558
|
+
// Facade
|
|
559
|
+
// ---------------------------------------------------------------------------
|
|
560
|
+
|
|
561
|
+
export interface DopamineConfig {
|
|
562
|
+
data?: DataServiceConfig;
|
|
563
|
+
rewards?: RewardSystemConfig;
|
|
564
|
+
sound?: SoundManagerConfig;
|
|
565
|
+
particles?: ParticleSystemConfig;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
export interface DopamineSubsystems {
|
|
569
|
+
rewardSystem: RewardSystem;
|
|
570
|
+
gameUI: GameUI;
|
|
571
|
+
particleSystem: ParticleSystem;
|
|
572
|
+
soundManager: SoundManager;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* Wires DataService, RewardSystem, SoundManager, ParticleSystem and GameUI
|
|
577
|
+
* together and binds the UI to reward events.
|
|
578
|
+
*/
|
|
579
|
+
export default class Dopamine {
|
|
580
|
+
constructor(config?: DopamineConfig);
|
|
581
|
+
config: DopamineConfig;
|
|
582
|
+
dataService: DataService;
|
|
583
|
+
rewardSystem: RewardSystem;
|
|
584
|
+
soundManager: SoundManager;
|
|
585
|
+
particleSystem: ParticleSystem;
|
|
586
|
+
gameUI: GameUI;
|
|
587
|
+
init(): Promise<DopamineSubsystems>;
|
|
588
|
+
}
|