@skewedaspect/sage 0.5.0 → 0.5.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.
Files changed (66) hide show
  1. package/dist/classes/bindings/toggle.d.ts +4 -4
  2. package/dist/classes/bindings/trigger.d.ts +4 -4
  3. package/dist/classes/bindings/value.d.ts +4 -4
  4. package/dist/classes/entity.d.ts +2 -2
  5. package/dist/classes/eventBus.d.ts +1 -1
  6. package/dist/classes/gameEngine.d.ts +8 -8
  7. package/dist/classes/input/gamepad.d.ts +1 -1
  8. package/dist/classes/input/keyboard.d.ts +1 -1
  9. package/dist/classes/input/mouse.d.ts +1 -1
  10. package/dist/classes/input/readers/gamepad.d.ts +1 -1
  11. package/dist/classes/input/readers/keyboard.d.ts +1 -1
  12. package/dist/classes/input/readers/mouse.d.ts +1 -1
  13. package/dist/classes/loggers/consoleBackend.d.ts +1 -1
  14. package/dist/classes/loggers/nullBackend.d.ts +1 -1
  15. package/dist/engines/scene.d.ts +2 -2
  16. package/dist/interfaces/binding.d.ts +4 -11
  17. package/dist/interfaces/entity.d.ts +5 -5
  18. package/dist/interfaces/game.d.ts +2 -2
  19. package/dist/managers/binding.d.ts +5 -5
  20. package/dist/managers/entity.d.ts +7 -7
  21. package/dist/managers/game.d.ts +5 -5
  22. package/dist/managers/input.d.ts +3 -3
  23. package/dist/managers/level.d.ts +1 -2
  24. package/dist/sage.d.ts +16 -14
  25. package/dist/sage.es.js +129 -71
  26. package/dist/sage.es.js.map +1 -1
  27. package/dist/sage.umd.js +1 -1
  28. package/dist/sage.umd.js.map +1 -1
  29. package/dist/utils/graphics.d.ts +1 -1
  30. package/dist/utils/logger.d.ts +3 -3
  31. package/package.json +11 -7
  32. package/src/classes/bindings/toggle.ts +0 -261
  33. package/src/classes/bindings/trigger.ts +0 -211
  34. package/src/classes/bindings/value.ts +0 -227
  35. package/src/classes/entity.ts +0 -256
  36. package/src/classes/eventBus.ts +0 -259
  37. package/src/classes/gameEngine.ts +0 -125
  38. package/src/classes/input/gamepad.ts +0 -388
  39. package/src/classes/input/keyboard.ts +0 -189
  40. package/src/classes/input/mouse.ts +0 -276
  41. package/src/classes/input/readers/gamepad.ts +0 -179
  42. package/src/classes/input/readers/keyboard.ts +0 -123
  43. package/src/classes/input/readers/mouse.ts +0 -133
  44. package/src/classes/loggers/consoleBackend.ts +0 -135
  45. package/src/classes/loggers/nullBackend.ts +0 -51
  46. package/src/engines/scene.ts +0 -112
  47. package/src/images/sage_logo.svg +0 -172
  48. package/src/images/sage_logo_shape.svg +0 -146
  49. package/src/interfaces/action.ts +0 -30
  50. package/src/interfaces/binding.ts +0 -191
  51. package/src/interfaces/entity.ts +0 -21
  52. package/src/interfaces/game.ts +0 -44
  53. package/src/interfaces/input.ts +0 -221
  54. package/src/interfaces/logger.ts +0 -118
  55. package/src/managers/binding.ts +0 -729
  56. package/src/managers/entity.ts +0 -252
  57. package/src/managers/game.ts +0 -111
  58. package/src/managers/input.ts +0 -233
  59. package/src/managers/level.ts +0 -261
  60. package/src/sage.ts +0 -122
  61. package/src/types/global.d.ts +0 -11
  62. package/src/utils/capabilities.ts +0 -16
  63. package/src/utils/graphics.ts +0 -148
  64. package/src/utils/logger.ts +0 -225
  65. package/src/utils/physics.ts +0 -16
  66. package/src/utils/version.ts +0 -11
@@ -1,227 +0,0 @@
1
- //----------------------------------------------------------------------------------------------------------------------
2
- // Value Binding
3
- //----------------------------------------------------------------------------------------------------------------------
4
-
5
- import type { GameEventBus } from '../eventBus.ts';
6
-
7
- // Interfaces
8
- import type { Action } from '../../interfaces/action.ts';
9
- import type { Binding, ValueBindingDefinition } from '../../interfaces/binding.ts';
10
- import type { DeviceValueReader, InputState } from '../../interfaces/input.ts';
11
-
12
- //----------------------------------------------------------------------------------------------------------------------
13
-
14
- /**
15
- * Options for configuring a value binding
16
- */
17
- export interface ValueBindingOptions
18
- {
19
- /**
20
- * Factor to scale the input value by (1.0 = no scaling)
21
- */
22
- scale ?: number;
23
-
24
- /**
25
- * Value to add to the input value after scaling
26
- */
27
- offset ?: number;
28
-
29
- /**
30
- * Whether to invert the input value (multiply by -1)
31
- */
32
- invert ?: boolean;
33
-
34
- /**
35
- * Optional context name this binding belongs to
36
- */
37
- context ?: string;
38
-
39
- /**
40
- * If true, only emit values when they change
41
- * If false, always emit values on each process call
42
- */
43
- emitOnChange ?: boolean;
44
-
45
- /**
46
- * Deadzone threshold (0.0 to 1.0)
47
- * Input values below this threshold will be treated as 0
48
- */
49
- deadzone ?: number;
50
-
51
- /**
52
- * Value to emit when the input is digital and true
53
- * Only used when action is digital
54
- */
55
- onValue ?: boolean | number;
56
-
57
- /**
58
- * Value to emit when the input is digital and false
59
- * Only used when action is digital
60
- */
61
- offValue ?: boolean | number;
62
-
63
- /**
64
- * Minimum value to clamp output to
65
- */
66
- min ?: number;
67
-
68
- /**
69
- * Maximum value to clamp output to
70
- */
71
- max ?: number;
72
- }
73
-
74
- /**
75
- * Implementation of a value binding, which directly converts an analog input
76
- * to an analog output with optional scaling, offset, and clamping.
77
- * Can handle both digital and analog inputs/outputs based on action type.
78
- */
79
- export class ValueBinding implements Binding
80
- {
81
- public readonly type = 'value' as const;
82
- public readonly action : Action;
83
- public readonly context ?: string;
84
- public readonly deviceID : string;
85
- public readonly reader : DeviceValueReader;
86
-
87
- // Value-specific options
88
- private readonly _scale : number;
89
- private readonly _offset : number;
90
- private readonly _invert : boolean;
91
- private readonly _emitOnChange : boolean;
92
- private readonly _deadzone : number;
93
- private readonly _onValue : boolean | number;
94
- private readonly _offValue : boolean | number;
95
- private readonly _min : number;
96
- private readonly _max : number;
97
-
98
- // State tracking
99
- private _lastValue : number | boolean | undefined;
100
-
101
- //------------------------------------------------------------------------------------------------------------------
102
-
103
- /**
104
- * Get the current options for this value binding.
105
- *
106
- * @returns The current options for this value binding
107
- */
108
- get options() : ValueBindingOptions
109
- {
110
- return {
111
- scale: this._scale,
112
- offset: this._offset,
113
- invert: this._invert,
114
- emitOnChange: this._emitOnChange,
115
- deadzone: this._deadzone,
116
- onValue: this._onValue,
117
- offValue: this._offValue,
118
- min: this._min,
119
- max: this._max,
120
- };
121
- }
122
-
123
- //------------------------------------------------------------------------------------------------------------------
124
-
125
- /**
126
- * Create a new value binding
127
- *
128
- * @param action - Action to emit values for
129
- * @param deviceID - Device ID this binding is for
130
- * @param reader - Input reader to read values from
131
- * @param options - Binding configuration options
132
- */
133
- constructor(
134
- action : Action,
135
- deviceID : string,
136
- reader : DeviceValueReader,
137
- options : ValueBindingOptions = {}
138
- )
139
- {
140
- this.action = action;
141
- this.deviceID = deviceID;
142
- this.reader = reader;
143
- this.context = options.context;
144
-
145
- // Common options that apply to both analog and digital
146
- this._scale = options.scale ?? 1.0;
147
- this._offset = options.offset ?? 0.0;
148
- this._invert = options.invert ?? false;
149
- this._emitOnChange = options.emitOnChange ?? true;
150
- this._deadzone = options.deadzone ?? 0.0;
151
-
152
- // For digital actions, these control the output value
153
- // For analog actions, these are not used
154
- this._onValue = options.onValue ?? true;
155
- this._offValue = options.offValue ?? false;
156
-
157
- // Store min/max values explicitly
158
- const defaultMin = this.action.type === 'analog'
159
- ? this.action.minValue ?? Number.NEGATIVE_INFINITY
160
- : Number.NEGATIVE_INFINITY;
161
- this._min = options.min ?? defaultMin;
162
-
163
- const defaultMax = this.action.type === 'analog'
164
- ? this.action.maxValue ?? Number.POSITIVE_INFINITY
165
- : Number.POSITIVE_INFINITY;
166
- this._max = options.max ?? defaultMax;
167
- }
168
-
169
- //------------------------------------------------------------------------------------------------------------------
170
- // Public Methods
171
- //------------------------------------------------------------------------------------------------------------------
172
-
173
- /**
174
- * Process input state and emit an action value
175
- *
176
- * @param state - Current input state
177
- * @param eventBus - Event bus to emit action events to
178
- * @returns True if a value was emitted, false otherwise
179
- */
180
- public process(state : InputState, eventBus : GameEventBus) : void
181
- {
182
- const rawValue = this.reader.getValue(state);
183
- if(rawValue === undefined) { return; }
184
-
185
- const numericValue = typeof rawValue === 'boolean' ? (rawValue ? 1.0 : 0.0) : rawValue;
186
- if(numericValue === undefined) { return; }
187
-
188
- let value = this._deadzone > 0 && Math.abs(numericValue) < this._deadzone ? 0 : numericValue;
189
- value = ((this._invert ? -value : value) * this._scale) + this._offset;
190
-
191
- // Apply min/max clamping
192
- value = Math.max(this._min, Math.min(this._max, value));
193
-
194
- if(this._emitOnChange && this._lastValue === value) { return; }
195
- this._lastValue = value;
196
-
197
- eventBus.publish({
198
- type: `action:${ this.action.name }`,
199
- payload: {
200
- value,
201
- deviceId: this.deviceID,
202
- context: this.context,
203
- },
204
- });
205
- }
206
-
207
- /**
208
- * Returns a JSON-serializable representation of this value binding
209
- *
210
- * @returns A simple object representation that can be converted to JSON
211
- */
212
- public toJSON() : ValueBindingDefinition
213
- {
214
- return {
215
- type: this.type,
216
- action: this.action.name,
217
- input: {
218
- deviceID: this.deviceID,
219
- ...this.reader.toJSON(),
220
- },
221
- context: this.context,
222
- options: this.options,
223
- };
224
- }
225
- }
226
-
227
- //----------------------------------------------------------------------------------------------------------------------
@@ -1,256 +0,0 @@
1
- //----------------------------------------------------------------------------------------------------------------------
2
- // Game Entity
3
- //----------------------------------------------------------------------------------------------------------------------
4
-
5
- import type { GameEntityBehaviorConstructor } from '../interfaces/entity.ts';
6
- import { type GameEvent, GameEventBus } from './eventBus.ts';
7
-
8
- //----------------------------------------------------------------------------------------------------------------------
9
-
10
- /**
11
- * Interface representing a subscription to a game event.
12
- */
13
- interface GameEventSubscription
14
- {
15
- count : number;
16
- unsubscribe : () => void;
17
- }
18
-
19
- /**
20
- * Interface representing the context of a game entity.
21
- * @template EntityState - The type of the state object.
22
- */
23
- interface SimpleGameEntity<EntityState extends object = object>
24
- {
25
- id : string;
26
- type : string;
27
- state : EntityState;
28
- eventBus : GameEventBus;
29
- }
30
-
31
- //----------------------------------------------------------------------------------------------------------------------
32
-
33
- /**
34
- * Base class for game entity behaviors.
35
- */
36
- export abstract class GameEntityBehavior<RequiredState extends object = object>
37
- {
38
- abstract name : string;
39
- abstract eventSubscriptions : string[];
40
-
41
- protected entity : SimpleGameEntity | null = null;
42
-
43
- //------------------------------------------------------------------------------------------------------------------
44
- // Internal API
45
- //------------------------------------------------------------------------------------------------------------------
46
-
47
- $emit(event : GameEvent) : void
48
- {
49
- if(!this.entity)
50
- {
51
- throw new Error('Entity is not set for this behavior.');
52
- }
53
-
54
- event.senderID = this.entity.id;
55
- this.entity.eventBus.publish(event);
56
- }
57
-
58
- /**
59
- * Sets the entity for this behavior.
60
- * @param entity - The entity to set.
61
- */
62
- $setEntity(entity : SimpleGameEntity | null) : void
63
- {
64
- this.entity = entity;
65
- }
66
-
67
- //------------------------------------------------------------------------------------------------------------------
68
- // Implementation API
69
- //------------------------------------------------------------------------------------------------------------------
70
-
71
- abstract processEvent(event : GameEvent, state : RequiredState) : Promise<boolean> | boolean;
72
-
73
- update?(dt : number, state : RequiredState) : void;
74
-
75
- destroy?() : Promise<void>;
76
- }
77
-
78
- //----------------------------------------------------------------------------------------------------------------------
79
-
80
- /**
81
- * Base class for game entities.
82
- * @template EntityState - The type of the state object.
83
- */
84
- export class GameEntity<EntityState extends object = object> implements SimpleGameEntity<EntityState>
85
- {
86
- /** The unique identifier of the entity. */
87
- public readonly id : string;
88
-
89
- /** The type of the entity. */
90
- public readonly type : string;
91
-
92
- /** The state of the entity. */
93
- public state : EntityState;
94
-
95
- /** A map of behaviors attached to the entity. */
96
- public behaviors : Map<string, GameEntityBehavior> = new Map<string, GameEntityBehavior>();
97
-
98
- /** The event bus for the entity. */
99
- public eventBus : GameEventBus;
100
-
101
- /** The event subscriptions for the entity. */
102
- private subscriptions : Map<string, GameEventSubscription> = new Map<string, GameEventSubscription>();
103
-
104
- /**
105
- * Creates an instance of GameEntityBase.
106
- * @param type - The type of the entity.
107
- * @param initialState - The initial state of the entity.
108
- * @param behaviors - An array of behaviors to attach to the entity.
109
- * @param eventBus
110
- */
111
- constructor(
112
- type : string,
113
- eventBus : GameEventBus,
114
- initialState : EntityState,
115
- behaviors : GameEntityBehaviorConstructor[]
116
- )
117
- {
118
- this.id = crypto.randomUUID();
119
- this.type = type;
120
- this.state = initialState;
121
- this.eventBus = eventBus;
122
-
123
- // Attach behaviors
124
- for(const behaviorCtor of behaviors)
125
- {
126
- this.attachBehavior(new behaviorCtor());
127
- }
128
- }
129
-
130
- //------------------------------------------------------------------------------------------------------------------
131
- // Internal Methods
132
- //------------------------------------------------------------------------------------------------------------------
133
-
134
- /**
135
- * Processes a game event by passing it to the entity's behaviors.
136
- * @param event - The game event to process.
137
- * @returns A promise that resolves when the event has been processed.
138
- */
139
- async $processEvent(event : GameEvent) : Promise<void>
140
- {
141
- for(const behavior of this.behaviors.values())
142
- {
143
- // eslint-disable-next-line no-await-in-loop
144
- const result = await behavior.processEvent(event, this.state);
145
- if(result)
146
- {
147
- // If the behavior returns true, stop other behaviors from processing the event.
148
- break;
149
- }
150
- }
151
- }
152
-
153
- /**
154
- * Updates the entity by calling the update method of its behaviors.
155
- * @param dt - The delta time since the last update.
156
- */
157
- $update(dt : number) : void
158
- {
159
- for(const behavior of this.behaviors.values())
160
- {
161
- behavior.update?.(dt, this.state);
162
- }
163
- }
164
-
165
- /**
166
- * Destroys the entity by calling the destroy method of its behaviors.
167
- * @returns A promise that resolves when the entity has been destroyed.
168
- */
169
- async $destroy() : Promise<void>
170
- {
171
- for(const behavior of this.behaviors.values())
172
- {
173
- behavior.destroy?.();
174
- }
175
-
176
- // Unsubscribe from all event subscriptions
177
- for(const subscription of this.subscriptions.values())
178
- {
179
- subscription.unsubscribe();
180
- }
181
-
182
- this.behaviors.clear();
183
- this.subscriptions.clear();
184
- }
185
-
186
- //------------------------------------------------------------------------------------------------------------------
187
- // Public Methods
188
- //------------------------------------------------------------------------------------------------------------------
189
-
190
- /**
191
- * Attaches a behavior to the entity.
192
- * @param behavior - The behavior to attach.
193
- * @throws Will throw an error if the behavior is already attached.
194
- */
195
- attachBehavior(behavior : GameEntityBehavior) : void
196
- {
197
- if(this.behaviors.has(behavior.name))
198
- {
199
- throw new Error(`Behavior ${ behavior.name } is already attached to this entity.`);
200
- }
201
-
202
- // Subscribe to the behavior's event subscriptions
203
- for(const event of behavior.eventSubscriptions)
204
- {
205
- // Check if the event is already subscribed
206
- const existingSubscription = this.subscriptions.get(event);
207
- if(existingSubscription)
208
- {
209
- existingSubscription.count++;
210
- }
211
- else
212
- {
213
- // Create a new subscription
214
- const unsubscribe = this.eventBus.subscribe(event, this.$processEvent.bind(this));
215
- this.subscriptions.set(event, { count: 1, unsubscribe });
216
- }
217
- }
218
-
219
- // Attach the behavior
220
- this.behaviors.set(behavior.name, behavior);
221
- behavior.$setEntity(this);
222
- }
223
-
224
- /**
225
- * Detaches a behavior from the entity.
226
- * @param behaviorName - The behavior to detach.
227
- */
228
- detachBehavior(behaviorName : string) : void
229
- {
230
- const behavior = this.behaviors.get(behaviorName);
231
- if(behavior)
232
- {
233
- // Remove the behavior's event subscriptions
234
- for(const event of behavior.eventSubscriptions)
235
- {
236
- const subscription = this.subscriptions.get(event);
237
- if(subscription)
238
- {
239
- subscription.count--;
240
- if(subscription.count <= 0)
241
- {
242
- subscription.unsubscribe();
243
- this.subscriptions.delete(event);
244
- }
245
- }
246
- }
247
-
248
- // Remove the behavior
249
- this.behaviors.delete(behavior.name);
250
- behavior.$setEntity(null);
251
- }
252
- }
253
- }
254
-
255
- //----------------------------------------------------------------------------------------------------------------------
256
-