@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.
- package/dist/classes/bindings/toggle.d.ts +4 -4
- package/dist/classes/bindings/trigger.d.ts +4 -4
- package/dist/classes/bindings/value.d.ts +4 -4
- package/dist/classes/entity.d.ts +2 -2
- package/dist/classes/eventBus.d.ts +1 -1
- package/dist/classes/gameEngine.d.ts +8 -8
- package/dist/classes/input/gamepad.d.ts +1 -1
- package/dist/classes/input/keyboard.d.ts +1 -1
- package/dist/classes/input/mouse.d.ts +1 -1
- package/dist/classes/input/readers/gamepad.d.ts +1 -1
- package/dist/classes/input/readers/keyboard.d.ts +1 -1
- package/dist/classes/input/readers/mouse.d.ts +1 -1
- package/dist/classes/loggers/consoleBackend.d.ts +1 -1
- package/dist/classes/loggers/nullBackend.d.ts +1 -1
- package/dist/engines/scene.d.ts +2 -2
- package/dist/interfaces/binding.d.ts +4 -11
- package/dist/interfaces/entity.d.ts +5 -5
- package/dist/interfaces/game.d.ts +2 -2
- package/dist/managers/binding.d.ts +5 -5
- package/dist/managers/entity.d.ts +7 -7
- package/dist/managers/game.d.ts +5 -5
- package/dist/managers/input.d.ts +3 -3
- package/dist/managers/level.d.ts +1 -2
- package/dist/sage.d.ts +16 -14
- package/dist/sage.es.js +129 -71
- package/dist/sage.es.js.map +1 -1
- package/dist/sage.umd.js +1 -1
- package/dist/sage.umd.js.map +1 -1
- package/dist/utils/graphics.d.ts +1 -1
- package/dist/utils/logger.d.ts +3 -3
- package/package.json +11 -7
- package/src/classes/bindings/toggle.ts +0 -261
- package/src/classes/bindings/trigger.ts +0 -211
- package/src/classes/bindings/value.ts +0 -227
- package/src/classes/entity.ts +0 -256
- package/src/classes/eventBus.ts +0 -259
- package/src/classes/gameEngine.ts +0 -125
- package/src/classes/input/gamepad.ts +0 -388
- package/src/classes/input/keyboard.ts +0 -189
- package/src/classes/input/mouse.ts +0 -276
- package/src/classes/input/readers/gamepad.ts +0 -179
- package/src/classes/input/readers/keyboard.ts +0 -123
- package/src/classes/input/readers/mouse.ts +0 -133
- package/src/classes/loggers/consoleBackend.ts +0 -135
- package/src/classes/loggers/nullBackend.ts +0 -51
- package/src/engines/scene.ts +0 -112
- package/src/images/sage_logo.svg +0 -172
- package/src/images/sage_logo_shape.svg +0 -146
- package/src/interfaces/action.ts +0 -30
- package/src/interfaces/binding.ts +0 -191
- package/src/interfaces/entity.ts +0 -21
- package/src/interfaces/game.ts +0 -44
- package/src/interfaces/input.ts +0 -221
- package/src/interfaces/logger.ts +0 -118
- package/src/managers/binding.ts +0 -729
- package/src/managers/entity.ts +0 -252
- package/src/managers/game.ts +0 -111
- package/src/managers/input.ts +0 -233
- package/src/managers/level.ts +0 -261
- package/src/sage.ts +0 -122
- package/src/types/global.d.ts +0 -11
- package/src/utils/capabilities.ts +0 -16
- package/src/utils/graphics.ts +0 -148
- package/src/utils/logger.ts +0 -225
- package/src/utils/physics.ts +0 -16
- 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
|
-
//----------------------------------------------------------------------------------------------------------------------
|
package/src/classes/entity.ts
DELETED
|
@@ -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
|
-
|