evotars 0.0.9 → 0.0.11

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 (61) hide show
  1. package/dist/evotars.js +26284 -0
  2. package/dist/evotars.umd.cjs +1147 -0
  3. package/dist/index.d.ts +175 -0
  4. package/package.json +22 -2
  5. package/.editorconfig +0 -13
  6. package/.prettierrc.json +0 -3
  7. package/index.html +0 -13
  8. package/playground/main.ts +0 -48
  9. package/playground/styles.css +0 -17
  10. package/public/evotars/agent/data.json +0 -18
  11. package/public/evotars/agent/sprite.json +0 -166
  12. package/public/evotars/agent/sprite.png +0 -0
  13. package/public/evotars/cat/data.json +0 -18
  14. package/public/evotars/cat/sprite.json +0 -231
  15. package/public/evotars/cat/sprite.png +0 -0
  16. package/public/evotars/dude/data.json +0 -18
  17. package/public/evotars/dude/sprite.json +0 -231
  18. package/public/evotars/dude/sprite.png +0 -0
  19. package/public/evotars/girl/data.json +0 -18
  20. package/public/evotars/girl/sprite.json +0 -231
  21. package/public/evotars/girl/sprite.png +0 -0
  22. package/public/evotars/nerd/data.json +0 -18
  23. package/public/evotars/nerd/sprite.json +0 -231
  24. package/public/evotars/nerd/sprite.png +0 -0
  25. package/public/evotars/senior/data.json +0 -18
  26. package/public/evotars/senior/sprite.json +0 -231
  27. package/public/evotars/senior/sprite.png +0 -0
  28. package/public/evotars/set.json +0 -10
  29. package/public/evotars/sith/data.json +0 -18
  30. package/public/evotars/sith/sprite.json +0 -166
  31. package/public/evotars/sith/sprite.png +0 -0
  32. package/public/evotars/sponge/data.json +0 -18
  33. package/public/evotars/sponge/sprite.json +0 -231
  34. package/public/evotars/sponge/sprite.png +0 -0
  35. package/public/fonts/Rubik.ttf +0 -0
  36. package/public/sounds/jump.mp3 +0 -0
  37. package/src/app.ts +0 -71
  38. package/src/config/constants.ts +0 -1
  39. package/src/entities/EmoteSpitter.ts +0 -102
  40. package/src/entities/Evotar.ts +0 -468
  41. package/src/entities/Message.ts +0 -164
  42. package/src/entities/Name.ts +0 -33
  43. package/src/entities/SpriteContainer.ts +0 -65
  44. package/src/entities/TrailEffect.ts +0 -73
  45. package/src/evotars.ts +0 -75
  46. package/src/evotarsManager.ts +0 -313
  47. package/src/helpers/timer.ts +0 -43
  48. package/src/helpers/types.ts +0 -4
  49. package/src/index.ts +0 -1
  50. package/src/services/soundService.ts +0 -30
  51. package/src/services/spriteService.ts +0 -167
  52. package/src/types/dto/action.ts +0 -79
  53. package/src/types/dto/chatter.ts +0 -4
  54. package/src/types/dto/event.ts +0 -9
  55. package/src/types/dto/index.ts +0 -6
  56. package/src/types/dto/message.ts +0 -8
  57. package/src/types/dto/settings.ts +0 -5
  58. package/src/types/dto/user.ts +0 -13
  59. package/src/types/index.ts +0 -1
  60. package/tsconfig.json +0 -23
  61. package/vite.config.js +0 -26
@@ -1,65 +0,0 @@
1
- import * as PIXI from 'pixi.js';
2
- import { FIXED_DELTA_TIME } from '../config/constants';
3
- import { Point } from '../helpers/types';
4
- import { EvotarLayerSprites } from '../services/spriteService';
5
-
6
- export type EvotarSpriteContainerProps = {
7
- color: {
8
- [key in string]?: PIXI.Color;
9
- };
10
- scale: Point;
11
- play: boolean;
12
- };
13
-
14
- export class EvotarSpriteContainer {
15
- public container: PIXI.Container = new PIXI.Container();
16
-
17
- public sprites: EvotarLayerSprites;
18
-
19
- constructor(sprites: EvotarLayerSprites) {
20
- this.sprites = sprites;
21
-
22
- this.container.sortableChildren = true;
23
-
24
- let zIndex = 0;
25
-
26
- for (const layer in this.sprites) {
27
- const sprite = this.sprites[layer];
28
- this.container.addChild(sprite);
29
-
30
- sprite.zIndex = ++zIndex;
31
- sprite.anchor.set(0.5, 0);
32
- sprite.autoUpdate = false;
33
- sprite.play();
34
- }
35
- }
36
-
37
- public update(props: EvotarSpriteContainerProps): void {
38
- for (const layer in this.sprites) {
39
- const sprite = this.sprites[layer];
40
-
41
- if (props.play) {
42
- sprite.update(FIXED_DELTA_TIME * 0.06);
43
- }
44
-
45
- if (props.color) {
46
- for (const colorLayer in props.color) {
47
- if (colorLayer == layer) {
48
- const color = props.color[colorLayer];
49
-
50
- if (color) {
51
- sprite.alpha = color.alpha;
52
- sprite.tint = color;
53
- }
54
- }
55
- }
56
- }
57
-
58
- if (props.scale.x) {
59
- sprite.animationSpeed = 4 / Math.abs(props.scale.x);
60
- }
61
- }
62
-
63
- this.container.scale.set(props.scale.x, props.scale.y);
64
- }
65
- }
@@ -1,73 +0,0 @@
1
- import * as PIXI from 'pixi.js';
2
- import { app } from '../app';
3
- import { Timer } from '../helpers/timer';
4
- import { EvotarSpriteContainer } from './SpriteContainer';
5
-
6
- export type EvotarTrailEffectProps = {
7
- play: boolean;
8
- };
9
-
10
- export class EvotarTrailEffect {
11
- public container: PIXI.Container = new PIXI.Container();
12
-
13
- private timer?: Timer;
14
-
15
- private sprite?: EvotarSpriteContainer;
16
-
17
- private opacityStep = 0.1;
18
-
19
- private shadowStep = 50;
20
-
21
- constructor() {
22
- app.stage.addChild(this.container);
23
- }
24
-
25
- public setSprite(sprite: EvotarSpriteContainer) {
26
- this.sprite = sprite;
27
- }
28
-
29
- public update(props: EvotarTrailEffectProps): void {
30
- for (const child of this.container.children) {
31
- if (child.alpha > 0) {
32
- child.alpha = child.alpha - this.opacityStep;
33
- }
34
- }
35
-
36
- if (this.timer && !this.timer.isCompleted) {
37
- this.timer.tick();
38
- } else if (props.play) {
39
- this.timer = new Timer(this.shadowStep);
40
-
41
- const container = new PIXI.Container();
42
-
43
- if (this.sprite) {
44
- for (const layer in this.sprite.sprites) {
45
- const sprite = this.sprite.sprites[layer];
46
- const texture = sprite.texture.clone();
47
- const trailSprite = new PIXI.Sprite(texture);
48
-
49
- trailSprite.anchor.set(0.5, 0);
50
- trailSprite.alpha = sprite.alpha;
51
- trailSprite.tint = sprite.tint;
52
-
53
- container.addChild(trailSprite);
54
-
55
- container.scale.set(
56
- this.sprite.container.scale.x,
57
- this.sprite.container.scale.y,
58
- );
59
-
60
- container.pivot.set(
61
- this.sprite.container.pivot.x,
62
- this.sprite.container.pivot.y,
63
- );
64
-
65
- const globalPosition = this.sprite.container.getGlobalPosition();
66
- container.position.set(globalPosition.x, globalPosition.y);
67
- }
68
- }
69
-
70
- this.container.addChild(container);
71
- }
72
- }
73
- }
package/src/evotars.ts DELETED
@@ -1,75 +0,0 @@
1
- import { AppOptions, app } from './app';
2
- import { evotarsManager } from './evotarsManager';
3
- import {
4
- MessageEntity,
5
- RaidData,
6
- SettingsEntity,
7
- TwitchChatterEntity,
8
- UserActionEntity,
9
- } from './types';
10
-
11
- export class Evotars {
12
- private isRendered = false;
13
-
14
- constructor(
15
- private readonly root: HTMLElement,
16
- private readonly options: AppOptions,
17
- ) {}
18
-
19
- processMessage = (data: MessageEntity) => evotarsManager.processMessage(data);
20
-
21
- processAction = (data: UserActionEntity) =>
22
- evotarsManager.processAction(data);
23
-
24
- processChatters = (data: TwitchChatterEntity[]) =>
25
- evotarsManager.processChatters(data);
26
-
27
- processRaid = (data: RaidData) => evotarsManager.processRaid(data);
28
-
29
- updateSettings(data: SettingsEntity) {
30
- app.updateSettings(data);
31
- }
32
-
33
- async run() {
34
- if (this.isRendered) {
35
- return;
36
- }
37
-
38
- this.isRendered = true;
39
-
40
- const init = async (): Promise<void> => {
41
- await app.initialize(this.root, this.options);
42
-
43
- let lastTime = performance.now();
44
- let lastFrame = -1;
45
-
46
- const maxFps = 60;
47
-
48
- const minElapsedMS = 1000 / maxFps;
49
- const maxElapsedMS = 100;
50
-
51
- requestAnimationFrame(animate);
52
-
53
- function animate(currentTime = performance.now()): void {
54
- let elapsedMS = currentTime - lastTime;
55
-
56
- if (elapsedMS > maxElapsedMS) {
57
- elapsedMS = maxElapsedMS;
58
- }
59
-
60
- const delta = (currentTime - lastFrame) | 0;
61
-
62
- if (delta > minElapsedMS) {
63
- lastFrame = currentTime - (delta % minElapsedMS);
64
- lastTime = currentTime;
65
-
66
- app.update();
67
- }
68
-
69
- requestAnimationFrame(animate);
70
- }
71
- };
72
-
73
- await init();
74
- }
75
- }
@@ -1,313 +0,0 @@
1
- import {
2
- MessageEntity,
3
- RaidData,
4
- TwitchChatterEntity,
5
- UserActionEntity,
6
- isColorUserActionEntity,
7
- isDashUserActionEntity,
8
- isGrowUserActionEntity,
9
- isJumpUserActionEntity,
10
- isSpriteUserActionEntity,
11
- } from './types';
12
- import * as PIXI from 'pixi.js';
13
- import tinycolor from 'tinycolor2';
14
- import { app } from './app';
15
- import { Evotar, EvotarProps } from './entities/Evotar';
16
- import { timers } from './helpers/timer';
17
-
18
- type EvotarsManagerSubscription = {
19
- onAdd: (evotar: Evotar) => void;
20
- onDelete: (evotar: Evotar) => void;
21
- };
22
-
23
- const EVOTAR_DESPAWN_TIMER = 1000 * 60 * 5;
24
-
25
- class EvotarsManager {
26
- private viewers: Record<string, Evotar | undefined> = {};
27
-
28
- private raiders: Evotar[] = [];
29
-
30
- private lastEvotarActivity: Record<string, number | undefined> = {};
31
-
32
- private subscriptions: EvotarsManagerSubscription[] = [];
33
-
34
- public subscribe(subscription: EvotarsManagerSubscription) {
35
- this.subscriptions.push(subscription);
36
- }
37
-
38
- public update() {
39
- for (const id in this.viewers) {
40
- const viewer = this.viewers[id];
41
-
42
- if (viewer) {
43
- viewer.update();
44
- }
45
- }
46
-
47
- for (const evotar of this.raiders) {
48
- evotar.update();
49
- }
50
- }
51
-
52
- public processRaid(data: RaidData) {
53
- if (!app.settings.fallingRaiders) {
54
- return;
55
- }
56
-
57
- const time = (1 / data.viewers) * 5000;
58
-
59
- for (let i = 0; i < data.viewers; i++) {
60
- const evotar = new Evotar();
61
-
62
- evotar.setProps({
63
- isAnonymous: true,
64
- zIndex: -1,
65
- sprite: 'agent',
66
- color: new PIXI.Color(data.broadcaster.info.color),
67
- });
68
-
69
- timers.add(time * i, () => {
70
- this.addRaider(evotar);
71
- evotar.spawn({ isFalling: true });
72
- });
73
-
74
- timers.add(i * time + 30000, () => {
75
- evotar.despawn({
76
- onComplete: () => {
77
- this.deleteRaider(evotar);
78
- },
79
- });
80
- });
81
- }
82
-
83
- const evotar = this.viewers[data.broadcaster.id];
84
-
85
- const props: EvotarProps = {
86
- ...this.prepareEvotarProps(
87
- data.broadcaster.info.displayName,
88
- data.broadcaster.info.color,
89
- ),
90
- scale: 8,
91
- };
92
-
93
- const spawnBroadcaster = () => {
94
- const evotar = new Evotar();
95
- evotar.setProps(props);
96
- this.addViewer(data.broadcaster.id, evotar);
97
- evotar.spawn({ isFalling: true, positionX: 0.5 });
98
- };
99
-
100
- this.lastEvotarActivity[data.broadcaster.id] = performance.now();
101
-
102
- if (!evotar) {
103
- spawnBroadcaster();
104
- } else {
105
- evotar.despawn({
106
- onComplete: () => {
107
- spawnBroadcaster();
108
- },
109
- });
110
- }
111
- }
112
-
113
- public async processChatters(data: TwitchChatterEntity[]) {
114
- for (const id in this.viewers) {
115
- const lastMessageTime = this.lastEvotarActivity[id];
116
- const spawnedRecently =
117
- !!lastMessageTime &&
118
- performance.now() - lastMessageTime < EVOTAR_DESPAWN_TIMER;
119
-
120
- if (data.every((chatter) => chatter.userId != id) && !spawnedRecently) {
121
- const evotar = this.viewers[id];
122
-
123
- if (evotar) {
124
- evotar.despawn({
125
- onComplete: () => {
126
- this.deleteViewer(id, evotar);
127
- },
128
- });
129
- }
130
- }
131
- }
132
-
133
- if (app.settings.showAnonymousEvotars) {
134
- for (const chatter of data) {
135
- const evotar = this.viewers[chatter.userId];
136
-
137
- if (!evotar) {
138
- const props = {
139
- name: chatter.name,
140
- isAnonymous: !this.hasActivity(chatter.userId),
141
- };
142
-
143
- const evotar = new Evotar();
144
- await evotar.setProps(props);
145
- evotar.spawn();
146
-
147
- this.addViewer(chatter.userId, evotar);
148
- }
149
- }
150
- }
151
- }
152
-
153
- private hasActivity = (userId: string): boolean =>
154
- !!this.lastEvotarActivity[userId];
155
-
156
- public doAction(action: UserActionEntity, evotar: Evotar) {
157
- if (isJumpUserActionEntity(action)) {
158
- evotar.jump({
159
- velocityX: action.data.velocityX,
160
- velocityY: action.data.velocityY,
161
- cooldown: action.cooldown,
162
- });
163
- }
164
-
165
- if (isDashUserActionEntity(action)) {
166
- evotar.dash({ force: action.data.force, cooldown: action.cooldown });
167
- }
168
-
169
- if (isColorUserActionEntity(action)) {
170
- const color = tinycolor(action.data.color);
171
-
172
- if (color && color.isValid()) {
173
- evotar.setUserProps({ color: new PIXI.Color(action.data.color) });
174
- }
175
- }
176
-
177
- if (isGrowUserActionEntity(action)) {
178
- evotar.scale({
179
- value: action.data.scale,
180
- duration: action.data.duration,
181
- cooldown: action.cooldown,
182
- });
183
- }
184
-
185
- if (isSpriteUserActionEntity(action)) {
186
- evotar.setSprite(action.data.sprite);
187
- }
188
- }
189
-
190
- private prepareEvotarProps(
191
- name: string,
192
- color?: string,
193
- sprite?: string,
194
- ): EvotarProps {
195
- const props: EvotarProps = {
196
- name,
197
- isAnonymous: false,
198
- };
199
-
200
- if (sprite) {
201
- props.sprite = sprite;
202
- }
203
-
204
- if (color) {
205
- try {
206
- props.color = new PIXI.Color(color);
207
- } catch (e) {}
208
- }
209
-
210
- return props;
211
- }
212
-
213
- public async processAction(action: UserActionEntity): Promise<void> {
214
- const evotar = this.viewers[action.userId];
215
-
216
- const props: EvotarProps = this.prepareEvotarProps(
217
- action.info.displayName,
218
- action.info.color,
219
- action.info.sprite,
220
- );
221
-
222
- if (!evotar) {
223
- const evotar = new Evotar();
224
- await evotar.setProps(props);
225
-
226
- evotar.spawn({
227
- onComplete: () => {
228
- const evotar = this.viewers[action.userId];
229
- if (evotar) {
230
- this.doAction(action, evotar);
231
- }
232
- },
233
- });
234
-
235
- this.addViewer(action.userId, evotar);
236
- } else {
237
- await evotar.setProps(props);
238
- this.doAction(action, evotar);
239
- }
240
- }
241
-
242
- public async processMessage(data: MessageEntity): Promise<void> {
243
- const props: EvotarProps = this.prepareEvotarProps(
244
- data.info.displayName,
245
- data.info.color,
246
- data.info.sprite,
247
- );
248
-
249
- let evotar = this.viewers[data.userId];
250
-
251
- if (!evotar) {
252
- const isFalling = app.settings.fallingEvotars
253
- ? !this.hasActivity(data.userId)
254
- : false;
255
-
256
- evotar = new Evotar();
257
- await evotar.setProps(props);
258
- evotar.spawn({ isFalling });
259
-
260
- this.addViewer(data.userId, evotar);
261
- } else {
262
- evotar.setProps(props);
263
- }
264
-
265
- this.lastEvotarActivity[data.userId] = performance.now();
266
-
267
- if (data.message) {
268
- evotar.addMessage(data.message);
269
- }
270
-
271
- if (data.emotes.length > 0) {
272
- evotar.spitEmotes(data.emotes);
273
- }
274
- }
275
-
276
- public addViewer(id: string, evotar: Evotar): void {
277
- this.subscriptions.forEach((s) => s.onAdd(evotar));
278
- this.viewers[id] = evotar;
279
- }
280
-
281
- public deleteViewer(id: string, evotar: Evotar): void {
282
- this.subscriptions.forEach((s) => s.onDelete(evotar));
283
- delete this.viewers[id];
284
- }
285
-
286
- public addRaider(evotar: Evotar): void {
287
- this.subscriptions.forEach((s) => s.onAdd(evotar));
288
- this.raiders.push(evotar);
289
- }
290
-
291
- public deleteRaider(evotar: Evotar): void {
292
- this.subscriptions.forEach((s) => s.onDelete(evotar));
293
- this.raiders = this.raiders.filter((raider) => raider != evotar);
294
- }
295
-
296
- public zIndexEvotarMax(from: number) {
297
- return Object.values(this.viewers).reduce((zIndex, evotar) => {
298
- return evotar && zIndex <= evotar.container.zIndex
299
- ? evotar.container.zIndex + 1
300
- : zIndex;
301
- }, from);
302
- }
303
-
304
- public zIndexEvotarMin(from: number) {
305
- return Object.values(this.viewers).reduce((zIndex, evotar) => {
306
- return evotar && zIndex >= evotar.container.zIndex
307
- ? evotar.container.zIndex - 1
308
- : zIndex;
309
- }, from);
310
- }
311
- }
312
-
313
- export const evotarsManager = new EvotarsManager();
@@ -1,43 +0,0 @@
1
- import { FIXED_DELTA_TIME } from '../config/constants';
2
-
3
- export class Timer {
4
- public isCompleted = false;
5
-
6
- constructor(public current = 0, private onComplete?: () => void) {}
7
-
8
- tick(delta: number = FIXED_DELTA_TIME) {
9
- if (this.isCompleted) {
10
- return;
11
- }
12
-
13
- this.current -= delta;
14
-
15
- if (this.current < 0) {
16
- this.isCompleted = true;
17
- this.onComplete?.();
18
- }
19
- }
20
- }
21
-
22
- class Timers {
23
- private timers: Timer[] = [];
24
-
25
- public add(current?: number, onComplete?: () => void) {
26
- this.timers.push(new Timer(current, onComplete));
27
- }
28
-
29
- public tick(delta: number = FIXED_DELTA_TIME) {
30
- const uncompleted = [];
31
-
32
- for (const timer of this.timers) {
33
- if (!timer.isCompleted) {
34
- timer.tick(delta);
35
- uncompleted.push(timer);
36
- }
37
- }
38
-
39
- this.timers = uncompleted;
40
- }
41
- }
42
-
43
- export const timers = new Timers();
@@ -1,4 +0,0 @@
1
- export type Point = {
2
- x?: number;
3
- y?: number;
4
- };
package/src/index.ts DELETED
@@ -1 +0,0 @@
1
- export * from './evotars';
@@ -1,30 +0,0 @@
1
- export type SoundOptions = {
2
- jump?: {
3
- src: string;
4
- };
5
- };
6
-
7
- class SoundService {
8
- assets: { [key: string]: HTMLAudioElement } = {};
9
-
10
- async initialize(options?: SoundOptions) {
11
- this.assets = Object.fromEntries(
12
- Array.from(Object.entries(options ?? {})).map(([key, value]) => {
13
- return [key, new Audio(value.src)];
14
- }),
15
- );
16
- }
17
-
18
- play(name: string) {
19
- const audio = this.assets[name];
20
-
21
- if (audio) {
22
- audio.volume = 0.2;
23
- audio.pause();
24
- audio.currentTime = 0;
25
- audio.play();
26
- }
27
- }
28
- }
29
-
30
- export const soundService = new SoundService();