tactica 0.0.1

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 ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md ADDED
@@ -0,0 +1,446 @@
1
+ # Tactica
2
+
3
+ A mobile-first, browser-based 2D game engine built with TypeScript. Designed for touch-enabled devices with a focus on performance, accessibility, and developer experience.
4
+
5
+ ## Features
6
+
7
+ - **Mobile-First Input** - Touch gestures, multi-touch, haptic feedback, virtual joystick, action buttons
8
+ - **Canvas Rendering** - Hardware-accelerated 2D graphics with camera, sprites, tilemaps, layer management
9
+ - **Camera Effects** - Shake, flash, fade, zoom effects for visual polish
10
+ - **Entity System** - Flexible entity-component architecture
11
+ - **Scene Management** - Multiple scenes with smooth transitions (fade, slide, zoom, wipe)
12
+ - **Physics & Collision** - Simple physics with spatial partitioning
13
+ - **Particle System** - Particle emitters with configurable behaviors
14
+ - **Tweening** - Smooth animations with 30+ easing functions
15
+ - **UI Components** - Canvas-based UI: buttons, sliders, panels, progress bars, toasts, modals, tooltips
16
+ - **Audio System** - Sound playback, volume control, crossfade
17
+ - **State Management** - Reactive stores with undo/redo support
18
+ - **Persistence** - LocalStorage and IndexedDB backends with data migrations
19
+ - **Timer System** - Game-time-aware timers with pause/resume support
20
+ - **Performance** - Frame budget tracking, debug overlay, screenshot capture
21
+ - **PWA Support** - Installable, offline-capable
22
+ - **Accessibility** - Screen reader announcements, reduced motion support
23
+
24
+ ## Installation
25
+
26
+ ```bash
27
+ npm install tactica
28
+ ```
29
+
30
+ ## Quick Start
31
+
32
+ ```typescript
33
+ import {
34
+ createEngine,
35
+ createScene,
36
+ createEntity,
37
+ createInputSystem,
38
+ } from 'tactica'
39
+
40
+ // Create canvas
41
+ const canvas = document.getElementById('game') as HTMLCanvasElement
42
+
43
+ // Initialize engine
44
+ const engine = createEngine({
45
+ canvas,
46
+ width: 480,
47
+ height: 800,
48
+ backgroundColor: '#1a1a2e',
49
+ })
50
+
51
+ // Create input system
52
+ const input = createInputSystem(canvas)
53
+
54
+ // Create a scene
55
+ const gameScene = createScene({ name: 'game' })
56
+
57
+ // Create player entity
58
+ const player = createEntity({
59
+ id: 'player',
60
+ x: 240,
61
+ y: 700,
62
+ width: 40,
63
+ height: 40,
64
+ })
65
+
66
+ gameScene.addEntity(player)
67
+
68
+ // Handle touch input
69
+ input.onTap((x, y) => {
70
+ player.setPosition(x, y)
71
+ })
72
+
73
+ // Start game loop
74
+ engine.onBeforeUpdate((deltaTime) => {
75
+ gameScene.update(deltaTime)
76
+ })
77
+
78
+ engine.onBeforeRender((ctx) => {
79
+ gameScene.render(ctx)
80
+ })
81
+
82
+ engine.start()
83
+ ```
84
+
85
+ ## Documentation
86
+
87
+ For comprehensive documentation, see the [Tactica Guide](./guides/tactica.md).
88
+
89
+ ## Development
90
+
91
+ ```bash
92
+ # Clone repository
93
+ git clone https://github.com/mikesaintsg/tactica.git
94
+ cd tactica
95
+
96
+ # Install dependencies
97
+ npm install
98
+
99
+ # Start development server
100
+ npm run dev
101
+
102
+ # Run type checking
103
+ npm run check
104
+
105
+ # Run tests
106
+ npm test
107
+
108
+ # Build library
109
+ npm run build
110
+
111
+ # Build showcase
112
+ npm run show
113
+ ```
114
+
115
+ ## Factory Functions
116
+
117
+ ### Core Engine
118
+
119
+ | Function | Description |
120
+ |--------------------------------------------------|-------------------------------------------|
121
+ | `createEngine(options)` | Create game engine with canvas |
122
+ | `createScene(options)` | Create a game scene |
123
+ | `createSceneManager(options)` | Manage multiple scenes |
124
+ | `createEntity(options)` | Create game entities |
125
+ | `createTimerManager(options)` | Game-time timers |
126
+
127
+ ### Rendering
128
+
129
+ | Function | Description |
130
+ |--------------------------------------------------|-------------------------------------------|
131
+ | `createCamera(options)` | Create camera with follow/shake |
132
+ | `createCameraEffects(camera)` | Camera effects (shake, flash, fade, zoom) |
133
+ | `createRenderer(context, options)` | Create renderer with batching |
134
+ | `createViewport(options)` | Viewport with scaling modes |
135
+ | `createSpriteSheet(options)` | Sprite sheet for animations |
136
+ | `createAnimationPlayer(options)` | Animation playback controller |
137
+ | `createTilemap(options)` | Tile-based level rendering |
138
+ | `createLayerManager(options)` | Render layer management |
139
+ | `createSpriteBatch(context, assets, options)` | Batched sprite rendering |
140
+ | `createTrailRenderer(options)` | Visual trails behind objects |
141
+ | `createShapeRenderer(options)` | Geometric primitive drawing |
142
+ | `createPostProcessManager(options)` | Screen-wide visual effects |
143
+ | `createCullingSystem(options)` | Frustum/distance culling |
144
+ | `createLODSystem(options)` | Level of detail management |
145
+ | `createTransitionManager(sceneManager, options)` | Screen transitions |
146
+
147
+ ### Input
148
+
149
+ | Function | Description |
150
+ |--------------------------------------------------|-------------------------------------------|
151
+ | `createInputSystem(canvas, options)` | Touch/mouse input handling |
152
+ | `createKeyboardManager(options)` | Keyboard input with combos |
153
+ | `createGamepadManager(options)` | Controller input support |
154
+ | `createInputActionSystem(options)` | Unified input with rebinding |
155
+ | `createVirtualJoystick(options)` | Virtual joystick for mobile |
156
+ | `createActionButton(options)` | Touch action button with cooldown |
157
+
158
+ ### Audio
159
+
160
+ | Function | Description |
161
+ |--------------------------------------------------|-------------------------------------------|
162
+ | `createAudioManager(options)` | Sound playback |
163
+ | `createMusicPlaylist(options)` | Sequential music playback |
164
+ | `createSoundVariantPool(options)` | Random sound variations |
165
+ | `createAudioZoneManager(options)` | Spatial audio zones |
166
+
167
+ ### Physics & Animation
168
+
169
+ | Function | Description |
170
+ |--------------------------------------------------|-------------------------------------------|
171
+ | `createPhysicsWorld(options)` | Physics simulation |
172
+ | `createCollisionSystem()` | Collision detection |
173
+ | `createTweenManager(options)` | Animation tweens |
174
+ | `createParticleSystem(options)` | Particle effects |
175
+
176
+ ### UI Components
177
+
178
+ | Function | Description |
179
+ |--------------------------------------------------|-------------------------------------------|
180
+ | `createUIManager(options)` | Canvas-based UI components |
181
+ | `createToastManager(options)` | Toast notifications |
182
+ | `createModal(options)` | Individual modal dialog |
183
+ | `createModalManager(options)` | Modal dialogs (alert/confirm/prompt) |
184
+ | `createTooltipManager(options)` | Tooltip system |
185
+ | `createTextInput(options)` | Text input field |
186
+ | `createRadialMenu(options)` | Circular selection menu |
187
+ | `createMinimap(options)` | World overview minimap |
188
+ | `createNotificationManager(options)` | In-game notifications |
189
+
190
+ ### Storage & State
191
+
192
+ | Function | Description |
193
+ |--------------------------------------------------|-------------------------------------------|
194
+ | `createStore(options)` | Reactive state management |
195
+ | `createComputed(compute)` | Derived state values |
196
+ | `createDatabase(config)` | IndexedDB database wrapper |
197
+ | `createStateManager(config)` | Game state with save/load |
198
+ | `createSchema(options)` | Data validation schema |
199
+ | `createLocalStorageBackend(options)` | localStorage persistence |
200
+ | `createIndexedDBBackend(options)` | IndexedDB persistence |
201
+ | `createMigrationRunner(options)` | Data migrations |
202
+ | `createTabSyncManager(channelName)` | Cross-tab synchronization |
203
+
204
+ ### Platform & Assets
205
+
206
+ | Function | Description |
207
+ |--------------------------------------------------|-------------------------------------------|
208
+ | `createAssetManager(options)` | Asset loading |
209
+ | `createMobileManager(options)` | Mobile device features |
210
+ | `createAccessibilityManager(options)` | Accessibility support |
211
+ | `createPWAManager(options)` | PWA install/update |
212
+ | `createNetworkManager(options)` | Network/multiplayer client |
213
+
214
+ ### Debug & Performance
215
+
216
+ | Function | Description |
217
+ |--------------------------------------------------|-------------------------------------------|
218
+ | `createPerformanceMonitor(options)` | FPS and metrics |
219
+ | `createDebugTools()` | Debug logging |
220
+ | `createDebugOverlay(options)` | Visual debug overlay |
221
+ | `createFrameBudget(options)` | Frame timing budget |
222
+ | `createScreenshotManager(canvas)` | Screenshot capture |
223
+ | `createEntityInspector(options)` | Entity property inspector |
224
+ | `createCommandConsole(options)` | Developer command console |
225
+
226
+ ### Game Systems
227
+
228
+ | Function | Description |
229
+ |--------------------------------------------------|-------------------------------------------|
230
+ | `createBuffSystem(options)` | Stackable buffs/debuffs with duration |
231
+ | `createHealthSystem(options)` | Entity health, damage, invincibility |
232
+ | `createFloatingTextSystem(options)` | Animated damage/pickup text |
233
+ | `createCollectibleSystem(options)` | Pickups with drop tables and magnetism |
234
+ | `createSpawnerSystem(options)` | Entity spawning with zones and waves |
235
+ | `createEffectZoneSystem(options)` | Areas that trigger effects on entry |
236
+ | `createExperienceSystem(options)` | XP tracking and level progression |
237
+ | `createStatisticsSystem(options)` | Game stats and milestone tracking |
238
+ | `createObjectiveSystem(options)` | Goals and progress tracking |
239
+ | `createStateMachine(options)` | State transitions for game flow |
240
+ | `createBackgroundSystem(options)` | Layered backgrounds with parallax |
241
+ | `createCrosshairSystem(options)` | Desktop aiming cursor |
242
+ | `createEntityRendererRegistry()` | Procedural entity rendering registry |
243
+ | `createInventorySystem(options)` | Item and equipment management |
244
+ | `createDialogueSystem(options)` | Conversation trees with branching |
245
+ | `createQuestSystem(options)` | Quest tracking with objectives |
246
+ | `createCraftingSystem(options)` | Item crafting with recipes |
247
+
248
+ ### Helper Functions
249
+
250
+ Tactica includes a comprehensive set of helper functions for game development:
251
+
252
+ #### Type Guards
253
+
254
+ | Function | Description |
255
+ |---------------------------|--------------------------------------|
256
+ | `isString(value)` | Check if value is a string |
257
+ | `isNonEmptyString(value)` | Check if value is a non-empty string |
258
+ | `isNumber(value)` | Check if value is a number (not NaN) |
259
+ | `isFiniteNumber(value)` | Check if value is a finite number |
260
+ | `isBoolean(value)` | Check if value is a boolean |
261
+ | `isNullish(value)` | Check if value is null or undefined |
262
+ | `isDefined(value)` | Check if value is defined |
263
+ | `isObject(value)` | Check if value is a plain object |
264
+ | `isArray(value)` | Check if value is an array |
265
+ | `isNonEmptyArray(value)` | Check if value is a non-empty array |
266
+ | `isFunction(value)` | Check if value is a function |
267
+ | `isOk(result)` | Check if result is successful |
268
+ | `isErr(result)` | Check if result is an error |
269
+
270
+ #### Browser & Storage Guards
271
+
272
+ | Function | Description |
273
+ |--------------------------------|---------------------------------------|
274
+ | `hasDeviceMemory(nav)` | Check for deviceMemory API |
275
+ | `hasGetBattery(nav)` | Check for Battery API |
276
+ | `hasNetworkConnection(nav)` | Check for Network Information API |
277
+ | `hasVibrate(nav)` | Check for Vibration API |
278
+ | `hasIndexedDB()` | Check if IndexedDB is available |
279
+ | `isIDBValidKey(value)` | Check if value is valid IndexedDB key |
280
+ | `hasId(obj)` | Check if object has id property |
281
+ | `hasVersion(obj)` | Check if object has version property |
282
+ | `hasTimestamp(obj)` | Check if object has timestamp |
283
+
284
+ #### Distance & Vectors
285
+
286
+ | Function | Description |
287
+ |-----------------------------------|---------------------------------------|
288
+ | `distance(x1, y1, x2, y2)` | Calculate distance between two points |
289
+ | `distanceSquared(x1, y1, x2, y2)` | Squared distance (faster, no sqrt) |
290
+ | `distanceVec(a, b)` | Distance between two vectors |
291
+ | `distanceVecSquared(a, b)` | Squared distance between two vectors |
292
+ | `normalize(x, y)` | Normalize a vector to unit length |
293
+ | `normalizeVec(v)` | Normalize a vector object |
294
+ | `magnitude(x, y)` | Get the length of a vector |
295
+ | `magnitudeVec(v)` | Get the length of a vector object |
296
+ | `angleBetween(x1, y1, x2, y2)` | Angle between two points in radians |
297
+ | `angleOf(x, y)` | Angle from origin to point |
298
+ | `fromAngle(angle, length)` | Create vector from angle and length |
299
+ | `addVec(a, b)` | Add two vectors |
300
+ | `subVec(a, b)` | Subtract vector b from a |
301
+ | `scaleVec(v, scalar)` | Scale a vector |
302
+ | `dotVec(a, b)` | Dot product of two vectors |
303
+ | `crossVec(a, b)` | Cross product (z-component) |
304
+ | `rotateVec(v, angle)` | Rotate a vector by angle |
305
+ | `perpVec(v)` | Get perpendicular vector |
306
+ | `reflectVec(v, normal)` | Reflect vector off surface |
307
+
308
+ #### Interpolation & Easing
309
+
310
+ | Function | Description |
311
+ |----------------------------------------------|--------------------------------------|
312
+ | `lerp(start, end, t)` | Linear interpolation |
313
+ | `lerpVec(a, b, t)` | Linear interpolation between vectors |
314
+ | `smoothstep(t)` | Smooth step (ease in-out) |
315
+ | `smootherstep(t)` | Ken Perlin's smoother step |
316
+ | `inverseLerp(a, b, value)` | Find t given value between a and b |
317
+ | `remap(value, inMin, inMax, outMin, outMax)` | Remap value between ranges |
318
+ | `approach(current, target, step)` | Approach target by fixed step |
319
+ | `damp(current, target, smoothing, dt)` | Damped approach (exponential decay) |
320
+ | `dampVec(current, target, smoothing, dt)` | Damped approach for vectors |
321
+
322
+ #### Clamping & Bounds
323
+
324
+ | Function | Description |
325
+ |--------------------------------------------------|-------------------------------------------|
326
+ | `clamp(value, min, max)` | Clamp number between min and max |
327
+ | `clampToRectangle(x, y, minX, minY, maxX, maxY)` | Clamp position to rectangle |
328
+ | `clampToWorld(x, y, entitySize, width, height)` | Clamp position accounting for entity size |
329
+ | `wrap(value, min, max)` | Wrap value within range |
330
+ | `wrapToWorld(x, y, width, height)` | Wrap position within world bounds |
331
+
332
+ #### Random
333
+
334
+ | Function | Description |
335
+ |-----------------------------------------------------|-----------------------------------|
336
+ | `randomRange(min, max)` | Random float between min and max |
337
+ | `randomInt(min, max)` | Random integer (inclusive) |
338
+ | `randomElement(array)` | Random element from array |
339
+ | `randomPosition(minX, maxX, minY, maxY)` | Random position in rectangle |
340
+ | `randomEdgePosition(width, height, margin, offset)` | Random position on rectangle edge |
341
+ | `randomInCircle(cx, cy, radius)` | Random point inside circle |
342
+ | `randomOnCircle(cx, cy, radius)` | Random point on circle edge |
343
+ | `randomDirection()` | Random unit vector |
344
+ | `randomSign()` | Random -1 or 1 |
345
+ | `randomBool(probability)` | Random boolean |
346
+
347
+ #### Collision Detection
348
+
349
+ | Function | Description |
350
+ |-----------------------------------------------------|---------------------------------------|
351
+ | `circlesOverlap(x1, y1, r1, x2, y2, r2)` | Check if two circles overlap |
352
+ | `pointInCircle(px, py, cx, cy, radius)` | Check if point is in circle |
353
+ | `pointInRectangle(px, py, rx, ry, rw, rh)` | Check if point is in rectangle |
354
+ | `rectsOverlap(x1, y1, w1, h1, x2, y2, w2, h2)` | Check if rectangles overlap |
355
+ | `circleRectangleOverlap(cx, cy, r, rx, ry, rw, rh)` | Check if circle and rectangle overlap |
356
+
357
+ #### Angle Utilities
358
+
359
+ | Function | Description |
360
+ |------------------------------------------|------------------------------------|
361
+ | `degToRad(degrees)` | Convert degrees to radians |
362
+ | `radToDeg(radians)` | Convert radians to degrees |
363
+ | `normalizeAngle(angle)` | Normalize angle to [-π, π] |
364
+ | `angleDifference(from, to)` | Shortest angular distance |
365
+ | `lerpAngle(from, to, t)` | Interpolate angles (shortest path) |
366
+ | `rotateToward(current, target, maxStep)` | Rotate toward target by max step |
367
+
368
+ #### Utility Functions
369
+
370
+ | Function | Description |
371
+ |-------------------------------------------|-----------------------------------|
372
+ | `generateId()` | Generate UUID v4 |
373
+ | `now()` | Current timestamp in milliseconds |
374
+ | `deepClone(obj)` | Deep clone object (JSON-safe) |
375
+ | `shallowEqual(a, b)` | Shallow equality check |
376
+ | `debounce(fn, delay)` | Debounce a function |
377
+ | `throttle(fn, limit)` | Throttle a function |
378
+ | `createSpacing(value)` | Create UI spacing object |
379
+ | `createError(path, message, code, value)` | Create validation error |
380
+ | `validateField(field, value, path)` | Validate field against definition |
381
+
382
+ ## Project Structure
383
+
384
+ ```
385
+ tactica/
386
+ ├── src/
387
+ │ ├── index.ts # Public API exports
388
+ │ ├── factories.ts # Factory functions
389
+ │ ├── types.ts # Type definitions (source of truth)
390
+ │ ├── constants.ts # Default values
391
+ │ ├── helpers.ts # Utility functions
392
+ │ ├── core/
393
+ │ │ ├── engine/ # Engine, Scene, Entity, SceneManager, TimerManager, TransitionManager
394
+ │ │ ├── rendering/ # Camera, Renderer, Sprites, Tilemap, LayerManager, SpriteBatch, CameraEffects, TrailRenderer, ShapeRenderer, PostProcessManager, CullingSystem, LODSystem, Viewport
395
+ │ │ ├── input/ # InputSystem, KeyboardManager, GamepadManager, InputActionSystem
396
+ │ │ ├── audio/ # AudioManager, MusicPlaylist, SoundVariantPool, AudioZoneManager
397
+ │ │ ├── physics/ # PhysicsWorld, CollisionSystem, Quadtree, SpatialGrid
398
+ │ │ ├── animation/ # AnimationPlayer, TweenManager, ParticleSystem
399
+ │ │ ├── gameplay/ # BuffSystem, HealthSystem, FloatingTextSystem, CollectibleSystem, SpawnerSystem, EffectZoneSystem, BackgroundSystem, ExperienceSystem, StatisticsSystem, ObjectiveSystem, StateMachine, CrosshairSystem, EntityRendererRegistry, InventorySystem, DialogueSystem, QuestSystem, CraftingSystem
400
+ │ │ ├── ui/ # UIManager, Button, Slider, Panel, ProgressBar, Text, Checkbox, Toggle, UIImage, TextInput, ToastManager, Modal, ModalManager, TooltipManager, VirtualJoystick, ActionButton, RadialMenu, Minimap, NotificationManager
401
+ │ │ ├── storage/ # Store, Computed, StateManager, Database, Schema, TabSyncManager, LocalStorageBackend, IndexedDBBackend, MigrationRunner, Cache
402
+ │ │ ├── asset/ # AssetManager, ResourceManager, ObjectPool
403
+ │ │ ├── platform/ # MobileManager, AccessibilityManager, PWAManager
404
+ │ │ ├── debug/ # DebugTools, DebugOverlay, PerformanceMonitor, ScreenshotManager, FrameBudget, EntityInspector, CommandConsole
405
+ │ │ └── network/ # NetworkManager
406
+ │ └── schemas/ # State validation schemas (PlayerState, WorldState, InventoryState, SettingsState)
407
+ ├── tests/ # Unit tests (mirrors src/)
408
+ ├── showcase/ # Demo game
409
+ ├── configs/ # Build configs
410
+ └── guides/ # Documentation
411
+ ```
412
+
413
+ ## Development
414
+
415
+ ```bash
416
+ # Type check
417
+ npm run check
418
+
419
+ # Lint and format
420
+ npm run format
421
+
422
+ # Run tests
423
+ npm test
424
+
425
+ # Build library
426
+ npm run build
427
+
428
+ # Development server (showcase)
429
+ npm run dev
430
+
431
+ # Build showcase to single HTML
432
+ npm run show
433
+ ```
434
+
435
+ ## Browser Support
436
+
437
+ - Chrome 80+
438
+ - Firefox 78+
439
+ - Safari 14+
440
+ - Edge 80+
441
+
442
+ Mobile browsers with touch support are the primary target.
443
+
444
+ ## License
445
+
446
+ MIT