evotars 0.0.2 → 0.0.4

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