evotars 0.0.1 → 0.0.3

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 +19 -0
  2. package/dist/config/config.d.ts +22 -0
  3. package/dist/config/constants.d.ts +1 -0
  4. package/dist/entities/EmoteSpitter.d.ts +15 -0
  5. package/dist/entities/Evotar.d.ts +79 -0
  6. package/dist/entities/Message.d.ts +27 -0
  7. package/dist/entities/Name.d.ts +14 -0
  8. package/dist/entities/SpriteContainer.d.ts +16 -0
  9. package/dist/entities/TrailEffect.d.ts +15 -0
  10. package/dist/evotars.d.ts +14 -0
  11. package/dist/evotars.js +789 -0
  12. package/dist/evotars.umd.cjs +1 -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/assetsLoader.d.ts +14 -0
  17. package/dist/services/evotarsManager.d.ts +30 -0
  18. package/dist/services/soundService.d.ts +12 -0
  19. package/dist/services/spriteProvider.d.ts +33 -0
  20. package/dist/types/dto/action.d.ts +49 -0
  21. package/{src/types/dto/chatter.ts → dist/types/dto/chatter.d.ts} +2 -2
  22. package/dist/types/dto/event.d.ts +9 -0
  23. package/dist/types/dto/message.d.ts +8 -0
  24. package/dist/types/dto/settings.d.ts +5 -0
  25. package/dist/types/dto/user.d.ts +12 -0
  26. package/package.json +30 -3
  27. package/.editorconfig +0 -13
  28. package/.prettierrc.json +0 -3
  29. package/index.html +0 -13
  30. package/public/fonts/Rubik.ttf +0 -0
  31. package/public/sounds/jump.mp3 +0 -0
  32. package/public/sprites/agent/agent.json +0 -166
  33. package/public/sprites/agent/agent.png +0 -0
  34. package/public/sprites/cat/cat.json +0 -231
  35. package/public/sprites/cat/cat.png +0 -0
  36. package/public/sprites/dude/dude.json +0 -231
  37. package/public/sprites/dude/dude.png +0 -0
  38. package/public/sprites/girl/girl.json +0 -231
  39. package/public/sprites/girl/girl.png +0 -0
  40. package/public/sprites/nerd/nerd.json +0 -231
  41. package/public/sprites/nerd/nerd.png +0 -0
  42. package/public/sprites/senior/senior.json +0 -231
  43. package/public/sprites/senior/senior.png +0 -0
  44. package/public/sprites/sith/sith.json +0 -166
  45. package/public/sprites/sith/sith.png +0 -0
  46. package/src/app.ts +0 -63
  47. package/src/config/config.ts +0 -133
  48. package/src/config/constants.ts +0 -1
  49. package/src/dudes.ts +0 -71
  50. package/src/entities/Dude.ts +0 -453
  51. package/src/entities/DudeEmoteSpitter.ts +0 -60
  52. package/src/entities/DudeMessage.ts +0 -163
  53. package/src/entities/DudeName.ts +0 -39
  54. package/src/entities/DudeSpriteContainer.ts +0 -68
  55. package/src/entities/DudeTrailEffect.ts +0 -72
  56. package/src/helpers/timer.ts +0 -43
  57. package/src/helpers/types.ts +0 -11
  58. package/src/index.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,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();