kiwiengine 0.7.0 → 1.0.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 (54) hide show
  1. package/lib/asset/audio.js +25 -7
  2. package/lib/asset/audio.js.map +1 -1
  3. package/lib/dom/dom-particle.js +23 -74
  4. package/lib/dom/dom-particle.js.map +1 -1
  5. package/lib/node/core/game-object.js +1 -4
  6. package/lib/node/core/game-object.js.map +1 -1
  7. package/lib/node/core/renderable.js +6 -4
  8. package/lib/node/core/renderable.js.map +1 -1
  9. package/lib/node/core/transformable.js +11 -42
  10. package/lib/node/core/transformable.js.map +1 -1
  11. package/lib/node/ext/animated-sprite.js +1 -8
  12. package/lib/node/ext/animated-sprite.js.map +1 -1
  13. package/lib/node/ext/bitmap-text.js +4 -61
  14. package/lib/node/ext/bitmap-text.js.map +1 -1
  15. package/lib/node/ext/circle.js +1 -2
  16. package/lib/node/ext/circle.js.map +1 -1
  17. package/lib/node/ext/particle.js +15 -65
  18. package/lib/node/ext/particle.js.map +1 -1
  19. package/lib/node/ext/rectangle.js +1 -2
  20. package/lib/node/ext/rectangle.js.map +1 -1
  21. package/lib/renderer/camera.js +0 -8
  22. package/lib/renderer/camera.js.map +1 -1
  23. package/lib/renderer/renderer.js +2 -7
  24. package/lib/renderer/renderer.js.map +1 -1
  25. package/lib/types/asset/audio.d.ts +8 -0
  26. package/lib/types/asset/audio.d.ts.map +1 -1
  27. package/lib/types/dom/dom-particle.d.ts +0 -1
  28. package/lib/types/dom/dom-particle.d.ts.map +1 -1
  29. package/lib/types/node/core/game-object.d.ts +1 -3
  30. package/lib/types/node/core/game-object.d.ts.map +1 -1
  31. package/lib/types/node/core/renderable.d.ts +1 -0
  32. package/lib/types/node/core/renderable.d.ts.map +1 -1
  33. package/lib/types/node/core/transformable.d.ts.map +1 -1
  34. package/lib/types/node/ext/animated-sprite.d.ts.map +1 -1
  35. package/lib/types/node/ext/bitmap-text.d.ts.map +1 -1
  36. package/lib/types/node/ext/circle.d.ts.map +1 -1
  37. package/lib/types/node/ext/particle.d.ts +0 -1
  38. package/lib/types/node/ext/particle.d.ts.map +1 -1
  39. package/lib/types/node/ext/rectangle.d.ts.map +1 -1
  40. package/lib/types/renderer/camera.d.ts.map +1 -1
  41. package/lib/types/renderer/renderer.d.ts.map +1 -1
  42. package/package.json +1 -1
  43. package/src/asset/audio.ts +28 -7
  44. package/src/dom/dom-particle.ts +24 -91
  45. package/src/node/core/game-object.ts +2 -10
  46. package/src/node/core/renderable.ts +5 -4
  47. package/src/node/core/transformable.ts +11 -49
  48. package/src/node/ext/animated-sprite.ts +1 -10
  49. package/src/node/ext/bitmap-text.ts +4 -70
  50. package/src/node/ext/circle.ts +1 -2
  51. package/src/node/ext/particle.ts +16 -80
  52. package/src/node/ext/rectangle.ts +1 -2
  53. package/src/renderer/camera.ts +0 -6
  54. package/src/renderer/renderer.ts +2 -9
@@ -1 +1 @@
1
- {"version":3,"file":"animated-sprite.js","sourceRoot":"","sources":["../../../src/node/ext/animated-sprite.ts"],"names":[],"mappings":"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","sourcesContent":["import { EventMap } from '@webtaku/event-emitter'\nimport { AnimatedSprite as PixiAnimatedSprite, Spritesheet } from 'pixi.js'\nimport { getCachedAtlasId, spritesheetLoader } from '../../asset/loaders/spritesheet'\nimport { Atlas } from '../../types/atlas'\nimport { GameObject, GameObjectOptions } from '../core/game-object'\n\nexport type AnimatedSpriteNodeOptions = {\n src: string\n atlas: Atlas\n animation: string\n} & GameObjectOptions\n\nexport class AnimatedSpriteNode<E extends EventMap = {}> extends GameObject<E & {\n animationend: (animation: string) => void\n}> {\n #src: string\n #atlas: Atlas\n #animation: string\n\n #atlasId!: string\n #sheet?: Spritesheet\n #sprite?: PixiAnimatedSprite\n #baseFps = 60\n\n // [성능 최적화] 이전 worldTimeScale 캐시 - 변경 시에만 animationSpeed 업데이트\n #prevWorldTimeScale = NaN\n\n constructor(options: AnimatedSpriteNodeOptions) {\n super(options)\n this.#src = options.src\n this.#atlas = options.atlas\n this.#animation = options.animation\n this.#load()\n }\n\n async #load() {\n this.#atlasId = getCachedAtlasId(this.#src, this.#atlas)\n\n if (spritesheetLoader.checkCached(this.#atlasId)) {\n this.#sheet = spritesheetLoader.getCached(this.#atlasId)\n } else {\n console.info(`Spritesheet not preloaded. Loading now: ${this.#atlasId}`)\n this.#sheet = await spritesheetLoader.load(this.#atlasId, this.#src, this.#atlas)\n }\n\n this.#updateAnimation()\n }\n\n #updateAnimation() {\n this.#sprite?.destroy()\n this.#sprite = undefined\n\n if (!this.#sheet) return\n\n if (!this.#sheet.animations[this.#animation]) {\n console.error(`Animation not found: ${this.#animation}`)\n return\n }\n\n const a = this.#atlas.animations[this.#animation]\n const s = new PixiAnimatedSprite(this.#sheet.animations[this.#animation])\n\n s.anchor.set(0.5, 0.5)\n s.zIndex = -999999\n s.loop = a.loop\n this.#baseFps = a.fps\n s.animationSpeed = (a.fps / 60) * this.worldTimeScale\n this.#prevWorldTimeScale = this.worldTimeScale\n s.play()\n s.onLoop = () => (this as any).emit('animationend', this.#animation)\n s.onComplete = () => (this as any).emit('animationend', this.#animation)\n\n this._pixiContainer.addChild(s)\n this.#sprite = s\n }\n\n set src(src) {\n if (this.#src !== src) {\n spritesheetLoader.release(this.#atlasId)\n this.#src = src\n this.#load()\n }\n }\n\n get src() { return this.#src }\n\n set atlas(atlas) {\n if (this.#atlas !== atlas) {\n spritesheetLoader.release(this.#atlasId)\n this.#atlas = atlas\n this.#load()\n }\n }\n\n get atlas() { return this.#atlas }\n\n set animation(animation) {\n if (this.#animation !== animation) {\n this.#animation = animation\n this.#updateAnimation()\n }\n }\n\n get animation() { return this.#animation }\n\n protected override update(dt: number) {\n super.update(dt)\n\n // [성능 최적화] worldTimeScale이 변경된 경우에만 animationSpeed 업데이트\n // 기존: 매 프레임 animationSpeed 재설정\n // 개선: 캐시된 값과 비교하여 변경 시에만 업데이트\n if (this.#sprite && this.worldTimeScale !== this.#prevWorldTimeScale) {\n this.#sprite.animationSpeed = (this.#baseFps / 60) * this.worldTimeScale\n this.#prevWorldTimeScale = this.worldTimeScale\n }\n }\n\n override remove() {\n spritesheetLoader.release(this.#atlasId)\n super.remove()\n }\n}\n"]}
1
+ {"version":3,"file":"animated-sprite.js","sourceRoot":"","sources":["../../../src/node/ext/animated-sprite.ts"],"names":[],"mappings":"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","sourcesContent":["import { EventMap } from '@webtaku/event-emitter'\nimport { AnimatedSprite as PixiAnimatedSprite, Spritesheet } from 'pixi.js'\nimport { getCachedAtlasId, spritesheetLoader } from '../../asset/loaders/spritesheet'\nimport { Atlas } from '../../types/atlas'\nimport { GameObject, GameObjectOptions } from '../core/game-object'\n\nexport type AnimatedSpriteNodeOptions = {\n src: string\n atlas: Atlas\n animation: string\n} & GameObjectOptions\n\nexport class AnimatedSpriteNode<E extends EventMap = {}> extends GameObject<E & {\n animationend: (animation: string) => void\n}> {\n #src: string\n #atlas: Atlas\n #animation: string\n\n #atlasId!: string\n #sheet?: Spritesheet\n #sprite?: PixiAnimatedSprite\n #baseFps = 60\n\n constructor(options: AnimatedSpriteNodeOptions) {\n super(options)\n this.#src = options.src\n this.#atlas = options.atlas\n this.#animation = options.animation\n this.#load()\n }\n\n async #load() {\n this.#atlasId = getCachedAtlasId(this.#src, this.#atlas)\n\n if (spritesheetLoader.checkCached(this.#atlasId)) {\n this.#sheet = spritesheetLoader.getCached(this.#atlasId)\n } else {\n console.info(`Spritesheet not preloaded. Loading now: ${this.#atlasId}`)\n this.#sheet = await spritesheetLoader.load(this.#atlasId, this.#src, this.#atlas)\n }\n\n this.#updateAnimation()\n }\n\n #updateAnimation() {\n this.#sprite?.destroy()\n this.#sprite = undefined\n\n if (!this.#sheet) return\n\n if (!this.#sheet.animations[this.#animation]) {\n console.error(`Animation not found: ${this.#animation}`)\n return\n }\n\n const a = this.#atlas.animations[this.#animation]\n const s = new PixiAnimatedSprite(this.#sheet.animations[this.#animation])\n\n s.anchor.set(0.5, 0.5)\n s.zIndex = -999999\n s.loop = a.loop\n this.#baseFps = a.fps\n s.animationSpeed = (a.fps / 60) * this.worldTimeScale\n s.play()\n s.onLoop = () => (this as any).emit('animationend', this.#animation)\n s.onComplete = () => (this as any).emit('animationend', this.#animation)\n\n this._pixiContainer.addChild(s)\n this.#sprite = s\n }\n\n set src(src) {\n if (this.#src !== src) {\n spritesheetLoader.release(this.#atlasId)\n this.#src = src\n this.#load()\n }\n }\n\n get src() { return this.#src }\n\n set atlas(atlas) {\n if (this.#atlas !== atlas) {\n spritesheetLoader.release(this.#atlasId)\n this.#atlas = atlas\n this.#load()\n }\n }\n\n get atlas() { return this.#atlas }\n\n set animation(animation) {\n if (this.#animation !== animation) {\n this.#animation = animation\n this.#updateAnimation()\n }\n }\n\n get animation() { return this.#animation }\n\n protected override update(dt: number) {\n super.update(dt)\n if (this.#sprite) {\n this.#sprite.animationSpeed = (this.#baseFps / 60) * this.worldTimeScale\n }\n }\n\n override remove() {\n spritesheetLoader.release(this.#atlasId)\n super.remove()\n }\n}\n"]}
@@ -7,11 +7,6 @@ export class BitmapTextNode extends GameObject {
7
7
  #text;
8
8
  #font;
9
9
  #sprites = [];
10
- // [성능 최적화] 글리프 텍스처 캐시 - charCode → PixiTexture 매핑
11
- // 동일 폰트에서 같은 문자에 대해 텍스처를 재생성하지 않음
12
- #glyphTextureCache = new Map();
13
- // [성능 최적화] 스프라이트 풀 - 재사용으로 GC 부담 감소
14
- #spritePool = [];
15
10
  constructor(options) {
16
11
  super(options);
17
12
  this.#fnt = options.fnt;
@@ -19,43 +14,9 @@ export class BitmapTextNode extends GameObject {
19
14
  this.#text = options.text;
20
15
  this.#load();
21
16
  }
22
- // [성능 최적화] 글리프 텍스처 가져오기 (캐시 활용)
23
- #getGlyphTexture(charCode) {
24
- if (!this.#font)
25
- return undefined;
26
- let texture = this.#glyphTextureCache.get(charCode);
27
- if (texture)
28
- return texture;
29
- const c = this.#font.chars[charCode];
30
- if (!c)
31
- return undefined;
32
- const frame = new PixiRectangle(c.x, c.y, c.width, c.height);
33
- texture = new PixiTexture({ source: this.#font.texture.source, frame });
34
- this.#glyphTextureCache.set(charCode, texture);
35
- return texture;
36
- }
37
- // [성능 최적화] 풀에서 스프라이트 가져오거나 새로 생성
38
- #acquireSprite(texture) {
39
- let sprite = this.#spritePool.pop();
40
- if (sprite) {
41
- sprite.texture = texture;
42
- sprite.visible = true;
43
- }
44
- else {
45
- sprite = new PixiSprite({ texture, zIndex: -999999 });
46
- }
47
- return sprite;
48
- }
49
- // [성능 최적화] 스프라이트를 풀로 반환
50
- #releaseSprite(sprite) {
51
- sprite.visible = false;
52
- this._pixiContainer.removeChild(sprite);
53
- this.#spritePool.push(sprite);
54
- }
55
17
  #updateText() {
56
- // [성능 최적화] 기존 스프라이트를 풀로 반환 (destroy 대신)
57
18
  for (const sprite of this.#sprites) {
58
- this.#releaseSprite(sprite);
19
+ sprite.destroy();
59
20
  }
60
21
  this.#sprites = [];
61
22
  if (!this.#font || !this.#text)
@@ -73,12 +34,9 @@ export class BitmapTextNode extends GameObject {
73
34
  const c = this.#font.chars[charCode];
74
35
  if (!c)
75
36
  continue;
76
- // [성능 최적화] 캐시된 텍스처 사용
77
- const texture = this.#getGlyphTexture(charCode);
78
- if (!texture)
79
- continue;
80
- // [성능 최적화] 풀에서 스프라이트 재사용
81
- const sprite = this.#acquireSprite(texture);
37
+ const frame = new PixiRectangle(c.x, c.y, c.width, c.height);
38
+ const texture = new PixiTexture({ source: this.#font.texture.source, frame });
39
+ const sprite = new PixiSprite({ texture, zIndex: -999999 });
82
40
  const x0 = xPos + c.xoffset;
83
41
  const y0 = yPos + c.yoffset;
84
42
  sprite.x = x0;
@@ -120,8 +78,6 @@ export class BitmapTextNode extends GameObject {
120
78
  console.info(`Bitmap font not preloaded. Loading now: ${this.#fnt}`);
121
79
  this.#font = await bitmapFontLoader.load(this.#fnt, this.#src);
122
80
  }
123
- // 폰트가 바뀌면 글리프 캐시 초기화
124
- this.#glyphTextureCache.clear();
125
81
  this.#updateText();
126
82
  }
127
83
  changeFont(fnt, src) {
@@ -133,9 +89,6 @@ export class BitmapTextNode extends GameObject {
133
89
  }
134
90
  }
135
91
  set text(text) {
136
- // [성능 최적화] 동일 텍스트면 스킵
137
- if (this.#text === text)
138
- return;
139
92
  this.#text = text;
140
93
  this.#updateText();
141
94
  }
@@ -143,16 +96,6 @@ export class BitmapTextNode extends GameObject {
143
96
  return this.#text;
144
97
  }
145
98
  remove() {
146
- // 풀에 있는 스프라이트도 정리
147
- for (const sprite of this.#spritePool) {
148
- sprite.destroy();
149
- }
150
- this.#spritePool.length = 0;
151
- // 글리프 텍스처 캐시 정리
152
- for (const texture of this.#glyphTextureCache.values()) {
153
- texture.destroy();
154
- }
155
- this.#glyphTextureCache.clear();
156
99
  bitmapFontLoader.release(this.#fnt);
157
100
  super.remove();
158
101
  }
@@ -1 +1 @@
1
- {"version":3,"file":"bitmap-text.js","sourceRoot":"","sources":["../../../src/node/ext/bitmap-text.ts"],"names":[],"mappings":"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","sourcesContent":["import { EventMap } from '@webtaku/event-emitter'\nimport { Rectangle as PixiRectangle, Sprite as PixiSprite, Texture as PixiTexture } from 'pixi.js'\nimport { bitmapFontLoader } from '../../asset/loaders/bitmap-font'\nimport { BitmapFont } from '../../types/bitmap-font'\nimport { GameObject, GameObjectOptions } from '../core/game-object'\n\nexport type BitmapTextNodeOptions = {\n fnt: string\n src: string\n text?: string\n} & GameObjectOptions\n\nexport class BitmapTextNode<E extends EventMap = {}> extends GameObject<E> {\n #fnt: string\n #src: string\n #text?: string\n\n #font?: BitmapFont\n #sprites: PixiSprite[] = []\n\n // [성능 최적화] 글리프 텍스처 캐시 - charCode → PixiTexture 매핑\n // 동일 폰트에서 같은 문자에 대해 텍스처를 재생성하지 않음\n #glyphTextureCache = new Map<number, PixiTexture>()\n\n // [성능 최적화] 스프라이트 풀 - 재사용으로 GC 부담 감소\n #spritePool: PixiSprite[] = []\n\n constructor(options: BitmapTextNodeOptions) {\n super(options)\n this.#fnt = options.fnt\n this.#src = options.src\n this.#text = options.text\n this.#load()\n }\n\n // [성능 최적화] 글리프 텍스처 가져오기 (캐시 활용)\n #getGlyphTexture(charCode: number): PixiTexture | undefined {\n if (!this.#font) return undefined\n\n let texture = this.#glyphTextureCache.get(charCode)\n if (texture) return texture\n\n const c = this.#font.chars[charCode]\n if (!c) return undefined\n\n const frame = new PixiRectangle(c.x, c.y, c.width, c.height)\n texture = new PixiTexture({ source: this.#font.texture.source, frame })\n this.#glyphTextureCache.set(charCode, texture)\n\n return texture\n }\n\n // [성능 최적화] 풀에서 스프라이트 가져오거나 새로 생성\n #acquireSprite(texture: PixiTexture): PixiSprite {\n let sprite = this.#spritePool.pop()\n\n if (sprite) {\n sprite.texture = texture\n sprite.visible = true\n } else {\n sprite = new PixiSprite({ texture, zIndex: -999999 })\n }\n\n return sprite\n }\n\n // [성능 최적화] 스프라이트를 풀로 반환\n #releaseSprite(sprite: PixiSprite) {\n sprite.visible = false\n this._pixiContainer.removeChild(sprite)\n this.#spritePool.push(sprite)\n }\n\n #updateText() {\n // [성능 최적화] 기존 스프라이트를 풀로 반환 (destroy 대신)\n for (const sprite of this.#sprites) {\n this.#releaseSprite(sprite)\n }\n this.#sprites = []\n\n if (!this.#font || !this.#text) return\n\n let xPos = 0, yPos = 0\n let minX = Infinity, minY = Infinity\n let maxX = -Infinity, maxY = -Infinity\n\n for (let i = 0; i < this.#text.length; i++) {\n const charCode = this.#text.charCodeAt(i)\n\n if (charCode === 10) {\n xPos = 0\n yPos += this.#font.lineHeight\n continue\n }\n\n const c = this.#font.chars[charCode]\n if (!c) continue\n\n // [성능 최적화] 캐시된 텍스처 사용\n const texture = this.#getGlyphTexture(charCode)\n if (!texture) continue\n\n // [성능 최적화] 풀에서 스프라이트 재사용\n const sprite = this.#acquireSprite(texture)\n\n const x0 = xPos + c.xoffset\n const y0 = yPos + c.yoffset\n\n sprite.x = x0\n sprite.y = y0\n\n this.#sprites.push(sprite)\n\n const x1 = x0 + c.width\n const y1 = y0 + c.height\n\n if (x0 < minX) minX = x0\n if (y0 < minY) minY = y0\n if (x1 > maxX) maxX = x1\n if (y1 > maxY) maxY = y1\n\n xPos += c.xadvance\n }\n\n if (minX === Infinity) {\n minX = 0\n minY = 0\n }\n\n if (maxX === -Infinity) {\n maxX = 0\n maxY = 0\n }\n\n const cx = (minX + maxX) / 2\n const cy = (minY + maxY) / 2\n\n for (const s of this.#sprites) {\n s.x -= cx\n s.y -= cy\n this._pixiContainer.addChild(s)\n }\n }\n\n async #load() {\n if (bitmapFontLoader.checkCached(this.#fnt)) {\n this.#font = bitmapFontLoader.getCached(this.#fnt)\n } else {\n console.info(`Bitmap font not preloaded. Loading now: ${this.#fnt}`)\n this.#font = await bitmapFontLoader.load(this.#fnt, this.#src)\n }\n\n // 폰트가 바뀌면 글리프 캐시 초기화\n this.#glyphTextureCache.clear()\n\n this.#updateText()\n }\n\n changeFont(fnt: string, src: string) {\n if (this.#fnt !== fnt || this.#src !== src) {\n bitmapFontLoader.release(this.#fnt)\n this.#fnt = fnt\n this.#src = src\n this.#load()\n }\n }\n\n set text(text: string | undefined) {\n // [성능 최적화] 동일 텍스트면 스킵\n if (this.#text === text) return\n this.#text = text\n this.#updateText()\n }\n\n get text() {\n return this.#text\n }\n\n override remove() {\n // 풀에 있는 스프라이트도 정리\n for (const sprite of this.#spritePool) {\n sprite.destroy()\n }\n this.#spritePool.length = 0\n\n // 글리프 텍스처 캐시 정리\n for (const texture of this.#glyphTextureCache.values()) {\n texture.destroy()\n }\n this.#glyphTextureCache.clear()\n\n bitmapFontLoader.release(this.#fnt)\n super.remove()\n }\n}\n"]}
1
+ {"version":3,"file":"bitmap-text.js","sourceRoot":"","sources":["../../../src/node/ext/bitmap-text.ts"],"names":[],"mappings":"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","sourcesContent":["import { EventMap } from '@webtaku/event-emitter'\nimport { Rectangle as PixiRectangle, Sprite as PixiSprite, Texture as PixiTexture } from 'pixi.js'\nimport { bitmapFontLoader } from '../../asset/loaders/bitmap-font'\nimport { BitmapFont } from '../../types/bitmap-font'\nimport { GameObject, GameObjectOptions } from '../core/game-object'\n\nexport type BitmapTextNodeOptions = {\n fnt: string\n src: string\n text?: string\n} & GameObjectOptions\n\nexport class BitmapTextNode<E extends EventMap = {}> extends GameObject<E> {\n #fnt: string\n #src: string\n #text?: string\n\n #font?: BitmapFont\n #sprites: PixiSprite[] = []\n\n constructor(options: BitmapTextNodeOptions) {\n super(options)\n this.#fnt = options.fnt\n this.#src = options.src\n this.#text = options.text\n this.#load()\n }\n\n #updateText() {\n for (const sprite of this.#sprites) {\n sprite.destroy()\n }\n this.#sprites = []\n\n if (!this.#font || !this.#text) return\n\n let xPos = 0, yPos = 0\n let minX = Infinity, minY = Infinity\n let maxX = -Infinity, maxY = -Infinity\n\n for (let i = 0; i < this.#text.length; i++) {\n const charCode = this.#text.charCodeAt(i)\n\n if (charCode === 10) {\n xPos = 0\n yPos += this.#font.lineHeight\n continue\n }\n\n const c = this.#font.chars[charCode]\n if (!c) continue\n\n const frame = new PixiRectangle(c.x, c.y, c.width, c.height)\n const texture = new PixiTexture({ source: this.#font.texture.source, frame })\n const sprite = new PixiSprite({ texture, zIndex: -999999 })\n\n const x0 = xPos + c.xoffset\n const y0 = yPos + c.yoffset\n\n sprite.x = x0\n sprite.y = y0\n\n this.#sprites.push(sprite)\n\n const x1 = x0 + c.width\n const y1 = y0 + c.height\n\n if (x0 < minX) minX = x0\n if (y0 < minY) minY = y0\n if (x1 > maxX) maxX = x1\n if (y1 > maxY) maxY = y1\n\n xPos += c.xadvance\n }\n\n if (minX === Infinity) {\n minX = 0\n minY = 0\n }\n\n if (maxX === -Infinity) {\n maxX = 0\n maxY = 0\n }\n\n const cx = (minX + maxX) / 2\n const cy = (minY + maxY) / 2\n\n for (const s of this.#sprites) {\n s.x -= cx\n s.y -= cy\n this._pixiContainer.addChild(s)\n }\n }\n\n async #load() {\n if (bitmapFontLoader.checkCached(this.#fnt)) {\n this.#font = bitmapFontLoader.getCached(this.#fnt)\n } else {\n console.info(`Bitmap font not preloaded. Loading now: ${this.#fnt}`)\n this.#font = await bitmapFontLoader.load(this.#fnt, this.#src)\n }\n\n this.#updateText()\n }\n\n changeFont(fnt: string, src: string) {\n if (this.#fnt !== fnt || this.#src !== src) {\n bitmapFontLoader.release(this.#fnt)\n this.#fnt = fnt\n this.#src = src\n this.#load()\n }\n }\n\n set text(text: string | undefined) {\n this.#text = text\n this.#updateText()\n }\n\n get text() {\n return this.#text\n }\n\n override remove() {\n bitmapFontLoader.release(this.#fnt)\n super.remove()\n }\n}\n"]}
@@ -5,8 +5,7 @@ export class CircleNode extends TransformableNode {
5
5
  #fill;
6
6
  #stroke;
7
7
  constructor(options) {
8
- // [성능 최적화] Graphics 자식 노드를 가지지 않으므로 sortableChildren 불필요
9
- super(new Graphics(), options);
8
+ super(new Graphics({ sortableChildren: true }), options);
10
9
  this.#radius = options.radius;
11
10
  this.#fill = options.fill;
12
11
  this.#stroke = options.stroke;
@@ -1 +1 @@
1
- {"version":3,"file":"circle.js","sourceRoot":"","sources":["../../../src/node/ext/circle.ts"],"names":[],"mappings":"AACA,OAAO,EAAa,QAAQ,EAAe,MAAM,SAAS,CAAA;AAC1D,OAAO,EAAE,iBAAiB,EAA4B,MAAM,uBAAuB,CAAA;AAQnF,MAAM,OAAO,UAAW,SAAQ,iBAAqC;IACnE,OAAO,CAAQ;IACf,KAAK,CAAY;IACjB,OAAO,CAAc;IAErB,YAAY,OAA0B;QACpC,0DAA0D;QAC1D,KAAK,CAAC,IAAI,QAAQ,EAAE,EAAE,OAAO,CAAC,CAAA;QAE9B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAA;QAC7B,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,IAAI,CAAA;QACzB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAA;QAE7B,IAAI,CAAC,KAAK,EAAE,CAAA;IACd,CAAC;IAED,KAAK;QACH,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;QACtD,IAAI,IAAI,CAAC,KAAK;YAAE,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACpD,IAAI,IAAI,CAAC,OAAO;YAAE,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAC5D,CAAC;IAED,IAAI,MAAM,CAAC,CAAC;QACV,IAAI,CAAC,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC;YACvB,IAAI,CAAC,OAAO,GAAG,CAAC,CAAA;YAChB,IAAI,CAAC,KAAK,EAAE,CAAA;QACd,CAAC;IACH,CAAC;IACD,IAAI,MAAM,KAAK,OAAO,IAAI,CAAC,OAAO,CAAA,CAAC,CAAC;IAEpC,IAAI,IAAI,CAAC,CAAC;QACR,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC;YACrB,IAAI,CAAC,KAAK,GAAG,CAAC,CAAA;YACd,IAAI,CAAC,KAAK,EAAE,CAAA;QACd,CAAC;IACH,CAAC;IACD,IAAI,IAAI,KAAK,OAAO,IAAI,CAAC,KAAK,CAAA,CAAC,CAAC;IAEhC,IAAI,MAAM,CAAC,CAAC;QACV,IAAI,CAAC,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC;YACvB,IAAI,CAAC,OAAO,GAAG,CAAC,CAAA;YAChB,IAAI,CAAC,KAAK,EAAE,CAAA;QACd,CAAC;IACH,CAAC;IACD,IAAI,MAAM,KAAK,OAAO,IAAI,CAAC,OAAO,CAAA,CAAC,CAAC;CACrC","sourcesContent":["import { EventMap } from '@webtaku/event-emitter'\nimport { FillInput, Graphics, StrokeInput } from 'pixi.js'\nimport { TransformableNode, TransformableNodeOptions } from '../core/transformable'\n\nexport type CircleNodeOptions = {\n radius: number\n fill?: FillInput\n stroke?: StrokeInput\n} & TransformableNodeOptions\n\nexport class CircleNode extends TransformableNode<Graphics, EventMap> {\n #radius: number\n #fill?: FillInput\n #stroke?: StrokeInput\n\n constructor(options: CircleNodeOptions) {\n // [성능 최적화] Graphics 자식 노드를 가지지 않으므로 sortableChildren 불필요\n super(new Graphics(), options)\n\n this.#radius = options.radius\n this.#fill = options.fill\n this.#stroke = options.stroke\n\n this.#draw()\n }\n\n #draw() {\n this._pixiContainer.clear().circle(0, 0, this.#radius)\n if (this.#fill) this._pixiContainer.fill(this.#fill)\n if (this.#stroke) this._pixiContainer.stroke(this.#stroke)\n }\n\n set radius(v) {\n if (v !== this.#radius) {\n this.#radius = v\n this.#draw()\n }\n }\n get radius() { return this.#radius }\n\n set fill(v) {\n if (v !== this.#fill) {\n this.#fill = v\n this.#draw()\n }\n }\n get fill() { return this.#fill }\n\n set stroke(v) {\n if (v !== this.#stroke) {\n this.#stroke = v\n this.#draw()\n }\n }\n get stroke() { return this.#stroke }\n}\n"]}
1
+ {"version":3,"file":"circle.js","sourceRoot":"","sources":["../../../src/node/ext/circle.ts"],"names":[],"mappings":"AACA,OAAO,EAAa,QAAQ,EAAe,MAAM,SAAS,CAAA;AAC1D,OAAO,EAAE,iBAAiB,EAA4B,MAAM,uBAAuB,CAAA;AAQnF,MAAM,OAAO,UAAW,SAAQ,iBAAqC;IACnE,OAAO,CAAQ;IACf,KAAK,CAAY;IACjB,OAAO,CAAc;IAErB,YAAY,OAA0B;QACpC,KAAK,CAAC,IAAI,QAAQ,CAAC,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,CAAC,CAAA;QAExD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAA;QAC7B,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,IAAI,CAAA;QACzB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAA;QAE7B,IAAI,CAAC,KAAK,EAAE,CAAA;IACd,CAAC;IAED,KAAK;QACH,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;QACtD,IAAI,IAAI,CAAC,KAAK;YAAE,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACpD,IAAI,IAAI,CAAC,OAAO;YAAE,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAC5D,CAAC;IAED,IAAI,MAAM,CAAC,CAAC;QACV,IAAI,CAAC,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC;YACvB,IAAI,CAAC,OAAO,GAAG,CAAC,CAAA;YAChB,IAAI,CAAC,KAAK,EAAE,CAAA;QACd,CAAC;IACH,CAAC;IACD,IAAI,MAAM,KAAK,OAAO,IAAI,CAAC,OAAO,CAAA,CAAC,CAAC;IAEpC,IAAI,IAAI,CAAC,CAAC;QACR,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC;YACrB,IAAI,CAAC,KAAK,GAAG,CAAC,CAAA;YACd,IAAI,CAAC,KAAK,EAAE,CAAA;QACd,CAAC;IACH,CAAC;IACD,IAAI,IAAI,KAAK,OAAO,IAAI,CAAC,KAAK,CAAA,CAAC,CAAC;IAEhC,IAAI,MAAM,CAAC,CAAC;QACV,IAAI,CAAC,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC;YACvB,IAAI,CAAC,OAAO,GAAG,CAAC,CAAA;YAChB,IAAI,CAAC,KAAK,EAAE,CAAA;QACd,CAAC;IACH,CAAC;IACD,IAAI,MAAM,KAAK,OAAO,IAAI,CAAC,OAAO,CAAA,CAAC,CAAC;CACrC","sourcesContent":["import { EventMap } from '@webtaku/event-emitter'\nimport { FillInput, Graphics, StrokeInput } from 'pixi.js'\nimport { TransformableNode, TransformableNodeOptions } from '../core/transformable'\n\nexport type CircleNodeOptions = {\n radius: number\n fill?: FillInput\n stroke?: StrokeInput\n} & TransformableNodeOptions\n\nexport class CircleNode extends TransformableNode<Graphics, EventMap> {\n #radius: number\n #fill?: FillInput\n #stroke?: StrokeInput\n\n constructor(options: CircleNodeOptions) {\n super(new Graphics({ sortableChildren: true }), options)\n\n this.#radius = options.radius\n this.#fill = options.fill\n this.#stroke = options.stroke\n\n this.#draw()\n }\n\n #draw() {\n this._pixiContainer.clear().circle(0, 0, this.#radius)\n if (this.#fill) this._pixiContainer.fill(this.#fill)\n if (this.#stroke) this._pixiContainer.stroke(this.#stroke)\n }\n\n set radius(v) {\n if (v !== this.#radius) {\n this.#radius = v\n this.#draw()\n }\n }\n get radius() { return this.#radius }\n\n set fill(v) {\n if (v !== this.#fill) {\n this.#fill = v\n this.#draw()\n }\n }\n get fill() { return this.#fill }\n\n set stroke(v) {\n if (v !== this.#stroke) {\n this.#stroke = v\n this.#draw()\n }\n }\n get stroke() { return this.#stroke }\n}\n"]}
@@ -18,9 +18,6 @@ export class ParticleSystem extends GameObject {
18
18
  #texture;
19
19
  #loadTexturePromise;
20
20
  #particles = [];
21
- // [성능 최적화] 오브젝트 풀 - 스프라이트 재사용으로 GC 부담 감소
22
- #spritePool = [];
23
- #poolSize;
24
21
  constructor(options) {
25
22
  super(options);
26
23
  this.#textureSrc = options.texture;
@@ -33,7 +30,6 @@ export class ParticleSystem extends GameObject {
33
30
  this.#fadeRate = options.fadeRate;
34
31
  this.#orientToVelocity = options.orientToVelocity;
35
32
  this.#blendMode = options.blendMode;
36
- this.#poolSize = options.poolSize ?? 100;
37
33
  this.#loadTexturePromise = this.#loadTexture();
38
34
  }
39
35
  async #loadTexture() {
@@ -45,44 +41,6 @@ export class ParticleSystem extends GameObject {
45
41
  this.#texture = await textureLoader.load(this.#textureSrc);
46
42
  }
47
43
  }
48
- // [성능 최적화] 풀에서 스프라이트 가져오거나 새로 생성
49
- #acquireSprite(x, y, scale, angle) {
50
- let sprite = this.#spritePool.pop();
51
- if (sprite) {
52
- // 풀에서 가져온 스프라이트 재설정
53
- sprite.x = x;
54
- sprite.y = y;
55
- sprite.scale.set(scale, scale);
56
- sprite.alpha = this.#startAlpha ?? 1;
57
- sprite.rotation = this.#orientToVelocity ? angle : 0;
58
- sprite.visible = true;
59
- }
60
- else {
61
- // 풀이 비어있으면 새로 생성
62
- sprite = new PixiSprite({
63
- x, y,
64
- texture: this.#texture,
65
- anchor: { x: 0.5, y: 0.5 },
66
- scale: { x: scale, y: scale },
67
- alpha: this.#startAlpha,
68
- blendMode: this.#blendMode,
69
- rotation: this.#orientToVelocity ? angle : undefined,
70
- });
71
- this._pixiContainer.addChild(sprite);
72
- }
73
- return sprite;
74
- }
75
- // [성능 최적화] 스프라이트를 풀로 반환 (destroy 대신)
76
- #releaseSprite(sprite) {
77
- if (this.#spritePool.length < this.#poolSize) {
78
- sprite.visible = false;
79
- this.#spritePool.push(sprite);
80
- }
81
- else {
82
- // 풀이 가득 차면 destroy
83
- sprite.destroy();
84
- }
85
- }
86
44
  async burst({ x, y }) {
87
45
  if (!this.#texture)
88
46
  await this.#loadTexturePromise;
@@ -94,53 +52,45 @@ export class ParticleSystem extends GameObject {
94
52
  const cos = Math.cos(angle);
95
53
  const velocity = random(this.#velocity.min, this.#velocity.max);
96
54
  const scale = random(this.#scale.min, this.#scale.max);
97
- const sprite = this.#acquireSprite(x, y, scale, angle);
55
+ const sprite = new PixiSprite({
56
+ x, y,
57
+ texture: this.#texture,
58
+ anchor: { x: 0.5, y: 0.5 },
59
+ scale: { x: scale, y: scale },
60
+ alpha: this.#startAlpha,
61
+ blendMode: this.#blendMode,
62
+ rotation: this.#orientToVelocity ? angle : undefined,
63
+ });
98
64
  this.#particles.push({
99
65
  sprite,
100
- active: true,
101
66
  age: 0,
102
67
  lifespan,
103
68
  velocityX: velocity * cos,
104
69
  velocityY: velocity * sin,
105
70
  fadeRate: this.#fadeRate,
106
71
  });
72
+ this._pixiContainer.addChild(sprite);
107
73
  }
108
74
  }
109
75
  update(dt) {
110
76
  super.update(dt);
111
77
  const ps = this.#particles;
112
- // [성능 최적화] swap-and-pop 패턴으로 O(n) splice 비용 제거
113
- // 기존: splice(i, 1)은 배열 요소를 이동시켜 O(n) 비용 발생
114
- // 개선: 마지막 요소와 교체 후 pop()으로 O(1) 제거
115
- let writeIdx = 0;
116
- for (let readIdx = 0; readIdx < ps.length; readIdx++) {
117
- const p = ps[readIdx];
78
+ for (let i = 0; i < ps.length; i++) {
79
+ const p = ps[i];
118
80
  const g = p.sprite;
119
81
  p.age += dt;
120
82
  if (p.age > p.lifespan) {
121
- // [성능 최적화] destroy 대신 풀로 반환
122
- this.#releaseSprite(g);
123
- p.active = false;
83
+ g.destroy({ children: true });
84
+ ps.splice(i, 1);
85
+ i--;
124
86
  continue;
125
87
  }
126
88
  g.x += p.velocityX * dt;
127
89
  g.y += p.velocityY * dt;
128
90
  g.alpha += p.fadeRate * dt;
129
- // 활성 파티클을 앞으로 이동
130
- if (writeIdx !== readIdx) {
131
- ps[writeIdx] = p;
132
- }
133
- writeIdx++;
134
91
  }
135
- // 비활성 파티클 제거 (한 번에 배열 크기 조정)
136
- ps.length = writeIdx;
137
92
  }
138
93
  remove() {
139
- // 풀에 있는 스프라이트도 정리
140
- for (const sprite of this.#spritePool) {
141
- sprite.destroy();
142
- }
143
- this.#spritePool.length = 0;
144
94
  textureLoader.release(this.#textureSrc);
145
95
  super.remove();
146
96
  }
@@ -1 +1 @@
1
- {"version":3,"file":"particle.js","sourceRoot":"","sources":["../../../src/node/ext/particle.ts"],"names":[],"mappings":"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","sourcesContent":["import { BLEND_MODES, Sprite as PixiSprite, Texture as PixiTexture } from 'pixi.js'\nimport { textureLoader } from '../../asset/loaders/texture'\nimport { GameObject, GameObjectOptions } from '../core/game-object'\n\ntype RandomRange = { min: number, max: number }\n\nexport type ParticleSystemOptions = {\n texture: string\n\n count: RandomRange\n lifespan: RandomRange\n angle: RandomRange\n velocity: RandomRange\n particleScale: RandomRange\n\n startAlpha?: number\n fadeRate: number\n orientToVelocity: boolean\n\n blendMode?: BLEND_MODES // ex) 'screen', 'multiply'\n\n // [성능 최적화] 오브젝트 풀 크기 설정 (기본값: 100)\n // 풀 크기를 늘리면 메모리를 더 사용하지만 GC 스파이크를 줄일 수 있음\n poolSize?: number\n} & GameObjectOptions\n\ninterface Particle {\n sprite: PixiSprite\n\n // [성능 최적화] 활성 상태 플래그 - 풀링에서 재사용 여부 판단\n active: boolean\n\n age: number\n lifespan: number\n\n velocityX: number\n velocityY: number\n\n fadeRate: number\n}\n\nfunction random(min: number, max: number) {\n return Math.random() * (max - min) + min\n}\n\nexport class ParticleSystem extends GameObject {\n #textureSrc: string\n #count: RandomRange\n #lifespan: RandomRange\n #angle: RandomRange\n #velocity: RandomRange\n #scale: RandomRange\n #startAlpha?: number\n #fadeRate: number\n #orientToVelocity: boolean\n #blendMode?: BLEND_MODES\n\n #texture?: PixiTexture\n #loadTexturePromise: Promise<void>\n #particles: Particle[] = []\n\n // [성능 최적화] 오브젝트 풀 - 스프라이트 재사용으로 GC 부담 감소\n #spritePool: PixiSprite[] = []\n #poolSize: number\n\n constructor(options: ParticleSystemOptions) {\n super(options)\n\n this.#textureSrc = options.texture\n this.#count = options.count\n this.#lifespan = options.lifespan\n this.#angle = options.angle\n this.#velocity = options.velocity\n this.#scale = options.particleScale\n this.#startAlpha = options.startAlpha\n this.#fadeRate = options.fadeRate\n this.#orientToVelocity = options.orientToVelocity\n this.#blendMode = options.blendMode\n this.#poolSize = options.poolSize ?? 100\n\n this.#loadTexturePromise = this.#loadTexture()\n }\n\n async #loadTexture() {\n if (textureLoader.checkCached(this.#textureSrc)) {\n this.#texture = textureLoader.getCached(this.#textureSrc)\n } else {\n console.info(`Texture not preloaded. Loading now: ${this.#textureSrc}`)\n this.#texture = await textureLoader.load(this.#textureSrc)\n }\n }\n\n // [성능 최적화] 풀에서 스프라이트 가져오거나 새로 생성\n #acquireSprite(x: number, y: number, scale: number, angle: number): PixiSprite {\n let sprite = this.#spritePool.pop()\n\n if (sprite) {\n // 풀에서 가져온 스프라이트 재설정\n sprite.x = x\n sprite.y = y\n sprite.scale.set(scale, scale)\n sprite.alpha = this.#startAlpha ?? 1\n sprite.rotation = this.#orientToVelocity ? angle : 0\n sprite.visible = true\n } else {\n // 풀이 비어있으면 새로 생성\n sprite = new PixiSprite({\n x, y,\n texture: this.#texture,\n anchor: { x: 0.5, y: 0.5 },\n scale: { x: scale, y: scale },\n alpha: this.#startAlpha,\n blendMode: this.#blendMode,\n rotation: this.#orientToVelocity ? angle : undefined,\n })\n this._pixiContainer.addChild(sprite)\n }\n\n return sprite\n }\n\n // [성능 최적화] 스프라이트를 풀로 반환 (destroy 대신)\n #releaseSprite(sprite: PixiSprite) {\n if (this.#spritePool.length < this.#poolSize) {\n sprite.visible = false\n this.#spritePool.push(sprite)\n } else {\n // 풀이 가득 차면 destroy\n sprite.destroy()\n }\n }\n\n async burst({ x, y }: { x: number; y: number }) {\n if (!this.#texture) await this.#loadTexturePromise\n\n const count = random(this.#count.min, this.#count.max)\n for (let i = 0; i < count; i++) {\n const lifespan = random(this.#lifespan.min, this.#lifespan.max)\n const angle = random(this.#angle.min, this.#angle.max)\n const sin = Math.sin(angle)\n const cos = Math.cos(angle)\n const velocity = random(this.#velocity.min, this.#velocity.max)\n const scale = random(this.#scale.min, this.#scale.max)\n\n const sprite = this.#acquireSprite(x, y, scale, angle)\n\n this.#particles.push({\n sprite,\n active: true,\n age: 0,\n lifespan,\n velocityX: velocity * cos,\n velocityY: velocity * sin,\n fadeRate: this.#fadeRate,\n })\n }\n }\n\n protected override update(dt: number) {\n super.update(dt)\n\n const ps = this.#particles\n\n // [성능 최적화] swap-and-pop 패턴으로 O(n) splice 비용 제거\n // 기존: splice(i, 1)은 배열 요소를 이동시켜 O(n) 비용 발생\n // 개선: 마지막 요소와 교체 후 pop()으로 O(1) 제거\n let writeIdx = 0\n for (let readIdx = 0; readIdx < ps.length; readIdx++) {\n const p = ps[readIdx]\n const g = p.sprite\n\n p.age += dt\n\n if (p.age > p.lifespan) {\n // [성능 최적화] destroy 대신 풀로 반환\n this.#releaseSprite(g)\n p.active = false\n continue\n }\n\n g.x += p.velocityX * dt\n g.y += p.velocityY * dt\n g.alpha += p.fadeRate * dt\n\n // 활성 파티클을 앞으로 이동\n if (writeIdx !== readIdx) {\n ps[writeIdx] = p\n }\n writeIdx++\n }\n\n // 비활성 파티클 제거 (한 번에 배열 크기 조정)\n ps.length = writeIdx\n }\n\n override remove() {\n // 풀에 있는 스프라이트도 정리\n for (const sprite of this.#spritePool) {\n sprite.destroy()\n }\n this.#spritePool.length = 0\n\n textureLoader.release(this.#textureSrc)\n super.remove()\n }\n}\n"]}
1
+ {"version":3,"file":"particle.js","sourceRoot":"","sources":["../../../src/node/ext/particle.ts"],"names":[],"mappings":"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","sourcesContent":["import { BLEND_MODES, Sprite as PixiSprite, Texture as PixiTexture } from 'pixi.js'\nimport { textureLoader } from '../../asset/loaders/texture'\nimport { GameObject, GameObjectOptions } from '../core/game-object'\n\ntype RandomRange = { min: number, max: number }\n\nexport type ParticleSystemOptions = {\n texture: string\n\n count: RandomRange\n lifespan: RandomRange\n angle: RandomRange\n velocity: RandomRange\n particleScale: RandomRange\n\n startAlpha?: number\n fadeRate: number\n orientToVelocity: boolean\n\n blendMode?: BLEND_MODES // ex) 'screen', 'multiply'\n} & GameObjectOptions\n\ninterface Particle {\n sprite: PixiSprite\n\n age: number\n lifespan: number\n\n velocityX: number\n velocityY: number\n\n fadeRate: number\n}\n\nfunction random(min: number, max: number) {\n return Math.random() * (max - min) + min\n}\n\nexport class ParticleSystem extends GameObject {\n #textureSrc: string\n #count: RandomRange\n #lifespan: RandomRange\n #angle: RandomRange\n #velocity: RandomRange\n #scale: RandomRange\n #startAlpha?: number\n #fadeRate: number\n #orientToVelocity: boolean\n #blendMode?: BLEND_MODES\n\n #texture?: PixiTexture\n #loadTexturePromise: Promise<void>\n #particles: Particle[] = []\n\n constructor(options: ParticleSystemOptions) {\n super(options)\n\n this.#textureSrc = options.texture\n this.#count = options.count\n this.#lifespan = options.lifespan\n this.#angle = options.angle\n this.#velocity = options.velocity\n this.#scale = options.particleScale\n this.#startAlpha = options.startAlpha\n this.#fadeRate = options.fadeRate\n this.#orientToVelocity = options.orientToVelocity\n this.#blendMode = options.blendMode\n\n this.#loadTexturePromise = this.#loadTexture()\n }\n\n async #loadTexture() {\n if (textureLoader.checkCached(this.#textureSrc)) {\n this.#texture = textureLoader.getCached(this.#textureSrc)\n } else {\n console.info(`Texture not preloaded. Loading now: ${this.#textureSrc}`)\n this.#texture = await textureLoader.load(this.#textureSrc)\n }\n }\n\n async burst({ x, y }: { x: number; y: number }) {\n if (!this.#texture) await this.#loadTexturePromise\n\n const count = random(this.#count.min, this.#count.max)\n for (let i = 0; i < count; i++) {\n const lifespan = random(this.#lifespan.min, this.#lifespan.max)\n const angle = random(this.#angle.min, this.#angle.max)\n const sin = Math.sin(angle)\n const cos = Math.cos(angle)\n const velocity = random(this.#velocity.min, this.#velocity.max)\n const scale = random(this.#scale.min, this.#scale.max)\n\n const sprite = new PixiSprite({\n x, y,\n texture: this.#texture,\n anchor: { x: 0.5, y: 0.5 },\n scale: { x: scale, y: scale },\n alpha: this.#startAlpha,\n blendMode: this.#blendMode,\n rotation: this.#orientToVelocity ? angle : undefined,\n })\n\n this.#particles.push({\n sprite,\n age: 0,\n lifespan,\n velocityX: velocity * cos,\n velocityY: velocity * sin,\n fadeRate: this.#fadeRate,\n })\n\n this._pixiContainer.addChild(sprite)\n }\n }\n\n protected override update(dt: number) {\n super.update(dt)\n\n const ps = this.#particles\n for (let i = 0; i < ps.length; i++) {\n const p = ps[i]\n const g = p.sprite\n\n p.age += dt\n if (p.age > p.lifespan) {\n g.destroy({ children: true })\n ps.splice(i, 1)\n i--\n continue\n }\n\n g.x += p.velocityX * dt\n g.y += p.velocityY * dt\n g.alpha += p.fadeRate * dt\n }\n }\n\n override remove() {\n textureLoader.release(this.#textureSrc)\n super.remove()\n }\n}\n"]}
@@ -6,8 +6,7 @@ export class RectangleNode extends TransformableNode {
6
6
  #fill;
7
7
  #stroke;
8
8
  constructor(options) {
9
- // [성능 최적화] Graphics 자식 노드를 가지지 않으므로 sortableChildren 불필요
10
- super(new Graphics(), options);
9
+ super(new Graphics({ sortableChildren: true }), options);
11
10
  this.#width = options.width;
12
11
  this.#height = options.height;
13
12
  this.#fill = options.fill;
@@ -1 +1 @@
1
- {"version":3,"file":"rectangle.js","sourceRoot":"","sources":["../../../src/node/ext/rectangle.ts"],"names":[],"mappings":"AACA,OAAO,EAAa,QAAQ,EAAe,MAAM,SAAS,CAAA;AAC1D,OAAO,EAAE,iBAAiB,EAA4B,MAAM,uBAAuB,CAAA;AASnF,MAAM,OAAO,aAAc,SAAQ,iBAAqC;IACtE,MAAM,CAAQ;IACd,OAAO,CAAQ;IACf,KAAK,CAAY;IACjB,OAAO,CAAc;IAErB,YAAY,OAA6B;QACvC,0DAA0D;QAC1D,KAAK,CAAC,IAAI,QAAQ,EAAE,EAAE,OAAO,CAAC,CAAA;QAE9B,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,KAAK,CAAA;QAC3B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAA;QAC7B,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,IAAI,CAAA;QACzB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAA;QAE7B,IAAI,CAAC,KAAK,EAAE,CAAA;IACd,CAAC;IAED,KAAK;QACH,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC,IAAI,CAC9B,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAChB,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,EACjB,IAAI,CAAC,MAAM,EACX,IAAI,CAAC,OAAO,CACb,CAAA;QACD,IAAI,IAAI,CAAC,KAAK;YAAE,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACpD,IAAI,IAAI,CAAC,OAAO;YAAE,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAC5D,CAAC;IAED,IAAI,KAAK,CAAC,CAAC;QACT,IAAI,CAAC,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;YACtB,IAAI,CAAC,MAAM,GAAG,CAAC,CAAA;YACf,IAAI,CAAC,KAAK,EAAE,CAAA;QACd,CAAC;IACH,CAAC;IACD,IAAI,KAAK,KAAK,OAAO,IAAI,CAAC,MAAM,CAAA,CAAC,CAAC;IAElC,IAAI,MAAM,CAAC,CAAC;QACV,IAAI,CAAC,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC;YACvB,IAAI,CAAC,OAAO,GAAG,CAAC,CAAA;YAChB,IAAI,CAAC,KAAK,EAAE,CAAA;QACd,CAAC;IACH,CAAC;IACD,IAAI,MAAM,KAAK,OAAO,IAAI,CAAC,OAAO,CAAA,CAAC,CAAC;IAEpC,IAAI,IAAI,CAAC,CAAC;QACR,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC;YACrB,IAAI,CAAC,KAAK,GAAG,CAAC,CAAA;YACd,IAAI,CAAC,KAAK,EAAE,CAAA;QACd,CAAC;IACH,CAAC;IACD,IAAI,IAAI,KAAK,OAAO,IAAI,CAAC,KAAK,CAAA,CAAC,CAAC;IAEhC,IAAI,MAAM,CAAC,CAAC;QACV,IAAI,CAAC,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC;YACvB,IAAI,CAAC,OAAO,GAAG,CAAC,CAAA;YAChB,IAAI,CAAC,KAAK,EAAE,CAAA;QACd,CAAC;IACH,CAAC;IACD,IAAI,MAAM,KAAK,OAAO,IAAI,CAAC,OAAO,CAAA,CAAC,CAAC;CACrC","sourcesContent":["import { EventMap } from '@webtaku/event-emitter'\nimport { FillInput, Graphics, StrokeInput } from 'pixi.js'\nimport { TransformableNode, TransformableNodeOptions } from '../core/transformable'\n\nexport type RectangleNodeOptions = {\n width: number\n height: number\n fill?: FillInput\n stroke?: StrokeInput\n} & TransformableNodeOptions\n\nexport class RectangleNode extends TransformableNode<Graphics, EventMap> {\n #width: number\n #height: number\n #fill?: FillInput\n #stroke?: StrokeInput\n\n constructor(options: RectangleNodeOptions) {\n // [성능 최적화] Graphics 자식 노드를 가지지 않으므로 sortableChildren 불필요\n super(new Graphics(), options)\n\n this.#width = options.width\n this.#height = options.height\n this.#fill = options.fill\n this.#stroke = options.stroke\n\n this.#draw()\n }\n\n #draw() {\n this._pixiContainer.clear().rect(\n -this.#width / 2,\n -this.#height / 2,\n this.#width,\n this.#height,\n )\n if (this.#fill) this._pixiContainer.fill(this.#fill)\n if (this.#stroke) this._pixiContainer.stroke(this.#stroke)\n }\n\n set width(v) {\n if (v !== this.#width) {\n this.#width = v\n this.#draw()\n }\n }\n get width() { return this.#width }\n\n set height(v) {\n if (v !== this.#height) {\n this.#height = v\n this.#draw()\n }\n }\n get height() { return this.#height }\n\n set fill(v) {\n if (v !== this.#fill) {\n this.#fill = v\n this.#draw()\n }\n }\n get fill() { return this.#fill }\n\n set stroke(v) {\n if (v !== this.#stroke) {\n this.#stroke = v\n this.#draw()\n }\n }\n get stroke() { return this.#stroke }\n}\n"]}
1
+ {"version":3,"file":"rectangle.js","sourceRoot":"","sources":["../../../src/node/ext/rectangle.ts"],"names":[],"mappings":"AACA,OAAO,EAAa,QAAQ,EAAe,MAAM,SAAS,CAAA;AAC1D,OAAO,EAAE,iBAAiB,EAA4B,MAAM,uBAAuB,CAAA;AASnF,MAAM,OAAO,aAAc,SAAQ,iBAAqC;IACtE,MAAM,CAAQ;IACd,OAAO,CAAQ;IACf,KAAK,CAAY;IACjB,OAAO,CAAc;IAErB,YAAY,OAA6B;QACvC,KAAK,CAAC,IAAI,QAAQ,CAAC,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,CAAC,CAAA;QAExD,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,KAAK,CAAA;QAC3B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAA;QAC7B,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,IAAI,CAAA;QACzB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAA;QAE7B,IAAI,CAAC,KAAK,EAAE,CAAA;IACd,CAAC;IAED,KAAK;QACH,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC,IAAI,CAC9B,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAChB,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,EACjB,IAAI,CAAC,MAAM,EACX,IAAI,CAAC,OAAO,CACb,CAAA;QACD,IAAI,IAAI,CAAC,KAAK;YAAE,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACpD,IAAI,IAAI,CAAC,OAAO;YAAE,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAC5D,CAAC;IAED,IAAI,KAAK,CAAC,CAAC;QACT,IAAI,CAAC,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;YACtB,IAAI,CAAC,MAAM,GAAG,CAAC,CAAA;YACf,IAAI,CAAC,KAAK,EAAE,CAAA;QACd,CAAC;IACH,CAAC;IACD,IAAI,KAAK,KAAK,OAAO,IAAI,CAAC,MAAM,CAAA,CAAC,CAAC;IAElC,IAAI,MAAM,CAAC,CAAC;QACV,IAAI,CAAC,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC;YACvB,IAAI,CAAC,OAAO,GAAG,CAAC,CAAA;YAChB,IAAI,CAAC,KAAK,EAAE,CAAA;QACd,CAAC;IACH,CAAC;IACD,IAAI,MAAM,KAAK,OAAO,IAAI,CAAC,OAAO,CAAA,CAAC,CAAC;IAEpC,IAAI,IAAI,CAAC,CAAC;QACR,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC;YACrB,IAAI,CAAC,KAAK,GAAG,CAAC,CAAA;YACd,IAAI,CAAC,KAAK,EAAE,CAAA;QACd,CAAC;IACH,CAAC;IACD,IAAI,IAAI,KAAK,OAAO,IAAI,CAAC,KAAK,CAAA,CAAC,CAAC;IAEhC,IAAI,MAAM,CAAC,CAAC;QACV,IAAI,CAAC,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC;YACvB,IAAI,CAAC,OAAO,GAAG,CAAC,CAAA;YAChB,IAAI,CAAC,KAAK,EAAE,CAAA;QACd,CAAC;IACH,CAAC;IACD,IAAI,MAAM,KAAK,OAAO,IAAI,CAAC,OAAO,CAAA,CAAC,CAAC;CACrC","sourcesContent":["import { EventMap } from '@webtaku/event-emitter'\nimport { FillInput, Graphics, StrokeInput } from 'pixi.js'\nimport { TransformableNode, TransformableNodeOptions } from '../core/transformable'\n\nexport type RectangleNodeOptions = {\n width: number\n height: number\n fill?: FillInput\n stroke?: StrokeInput\n} & TransformableNodeOptions\n\nexport class RectangleNode extends TransformableNode<Graphics, EventMap> {\n #width: number\n #height: number\n #fill?: FillInput\n #stroke?: StrokeInput\n\n constructor(options: RectangleNodeOptions) {\n super(new Graphics({ sortableChildren: true }), options)\n\n this.#width = options.width\n this.#height = options.height\n this.#fill = options.fill\n this.#stroke = options.stroke\n\n this.#draw()\n }\n\n #draw() {\n this._pixiContainer.clear().rect(\n -this.#width / 2,\n -this.#height / 2,\n this.#width,\n this.#height,\n )\n if (this.#fill) this._pixiContainer.fill(this.#fill)\n if (this.#stroke) this._pixiContainer.stroke(this.#stroke)\n }\n\n set width(v) {\n if (v !== this.#width) {\n this.#width = v\n this.#draw()\n }\n }\n get width() { return this.#width }\n\n set height(v) {\n if (v !== this.#height) {\n this.#height = v\n this.#draw()\n }\n }\n get height() { return this.#height }\n\n set fill(v) {\n if (v !== this.#fill) {\n this.#fill = v\n this.#draw()\n }\n }\n get fill() { return this.#fill }\n\n set stroke(v) {\n if (v !== this.#stroke) {\n this.#stroke = v\n this.#draw()\n }\n }\n get stroke() { return this.#stroke }\n}\n"]}
@@ -7,19 +7,11 @@ export class Camera extends EventEmitter {
7
7
  get y() { return this.#y; }
8
8
  get scale() { return this.#scale; }
9
9
  setPosition(x, y) {
10
- // [성능 최적화] 값이 변경된 경우에만 이벤트 emit
11
- // 기존: 매번 positionChanged 이벤트 발생 → 불필요한 월드 트랜스폼 업데이트
12
- // 개선: 값 비교 후 변경 시에만 emit
13
- if (this.#x === x && this.#y === y)
14
- return;
15
10
  this.#x = x;
16
11
  this.#y = y;
17
12
  this.emit('positionChanged');
18
13
  }
19
14
  setScale(scale) {
20
- // [성능 최적화] 값이 변경된 경우에만 이벤트 emit
21
- if (this.#scale === scale)
22
- return;
23
15
  this.#scale = scale;
24
16
  this.emit('scaleChanged');
25
17
  }
@@ -1 +1 @@
1
- {"version":3,"file":"camera.js","sourceRoot":"","sources":["../../src/renderer/camera.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AAErD,MAAM,OAAO,MAAO,SAAQ,YAG1B;IACA,EAAE,GAAG,CAAC,CAAA;IACN,EAAE,GAAG,CAAC,CAAA;IACN,MAAM,GAAG,CAAC,CAAA;IAEV,IAAI,CAAC,KAAK,OAAO,IAAI,CAAC,EAAE,CAAA,CAAC,CAAC;IAC1B,IAAI,CAAC,KAAK,OAAO,IAAI,CAAC,EAAE,CAAA,CAAC,CAAC;IAC1B,IAAI,KAAK,KAAK,OAAO,IAAI,CAAC,MAAM,CAAA,CAAC,CAAC;IAElC,WAAW,CAAC,CAAS,EAAE,CAAS;QAC9B,gCAAgC;QAChC,oDAAoD;QACpD,yBAAyB;QACzB,IAAI,IAAI,CAAC,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,EAAE,KAAK,CAAC;YAAE,OAAM;QAC1C,IAAI,CAAC,EAAE,GAAG,CAAC,CAAA;QACX,IAAI,CAAC,EAAE,GAAG,CAAC,CAAA;QACX,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;IAC9B,CAAC;IAED,QAAQ,CAAC,KAAa;QACpB,gCAAgC;QAChC,IAAI,IAAI,CAAC,MAAM,KAAK,KAAK;YAAE,OAAM;QACjC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;QACnB,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAA;IAC3B,CAAC;CACF","sourcesContent":["import { EventEmitter } from '@webtaku/event-emitter'\n\nexport class Camera extends EventEmitter<{\n positionChanged: () => void\n scaleChanged: () => void\n}> {\n #x = 0\n #y = 0\n #scale = 1\n\n get x() { return this.#x }\n get y() { return this.#y }\n get scale() { return this.#scale }\n\n setPosition(x: number, y: number) {\n // [성능 최적화] 값이 변경된 경우에만 이벤트 emit\n // 기존: 매번 positionChanged 이벤트 발생 → 불필요한 월드 트랜스폼 업데이트\n // 개선: 값 비교 후 변경 시에만 emit\n if (this.#x === x && this.#y === y) return\n this.#x = x\n this.#y = y\n this.emit('positionChanged')\n }\n\n setScale(scale: number) {\n // [성능 최적화] 값이 변경된 경우에만 이벤트 emit\n if (this.#scale === scale) return\n this.#scale = scale\n this.emit('scaleChanged')\n }\n}"]}
1
+ {"version":3,"file":"camera.js","sourceRoot":"","sources":["../../src/renderer/camera.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AAErD,MAAM,OAAO,MAAO,SAAQ,YAG1B;IACA,EAAE,GAAG,CAAC,CAAA;IACN,EAAE,GAAG,CAAC,CAAA;IACN,MAAM,GAAG,CAAC,CAAA;IAEV,IAAI,CAAC,KAAK,OAAO,IAAI,CAAC,EAAE,CAAA,CAAC,CAAC;IAC1B,IAAI,CAAC,KAAK,OAAO,IAAI,CAAC,EAAE,CAAA,CAAC,CAAC;IAC1B,IAAI,KAAK,KAAK,OAAO,IAAI,CAAC,MAAM,CAAA,CAAC,CAAC;IAElC,WAAW,CAAC,CAAS,EAAE,CAAS;QAC9B,IAAI,CAAC,EAAE,GAAG,CAAC,CAAA;QACX,IAAI,CAAC,EAAE,GAAG,CAAC,CAAA;QACX,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;IAC9B,CAAC;IAED,QAAQ,CAAC,KAAa;QACpB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;QACnB,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAA;IAC3B,CAAC;CACF","sourcesContent":["import { EventEmitter } from '@webtaku/event-emitter'\n\nexport class Camera extends EventEmitter<{\n positionChanged: () => void\n scaleChanged: () => void\n}> {\n #x = 0\n #y = 0\n #scale = 1\n\n get x() { return this.#x }\n get y() { return this.#y }\n get scale() { return this.#scale }\n\n setPosition(x: number, y: number) {\n this.#x = x\n this.#y = y\n this.emit('positionChanged')\n }\n\n setScale(scale: number) {\n this.#scale = scale\n this.emit('scaleChanged')\n }\n}"]}
@@ -132,16 +132,11 @@ export class Renderer extends RenderableNode {
132
132
  this._isSizeDirty = true;
133
133
  }
134
134
  #render(dt) {
135
- // [성능 최적화] 렌더러가 준비되지 않은 경우 불필요한 업데이트 스킵
136
- if (!this.#pixiRenderer)
137
- return;
138
135
  const scaledDt = dt * this.timeScale;
139
136
  this.update(scaledDt);
140
- // [성능 최적화] 2-pass → 1-pass로 통합
141
- // 기존: _updateWorldTransform() + _resetWorldTransformDirty() 별도 호출
142
- // 개선: _updateWorldTransform() 내부에서 dirty 리셋까지 처리
143
137
  this._updateWorldTransform();
144
- this.#pixiRenderer.render(this._pixiContainer);
138
+ this._resetWorldTransformDirty();
139
+ this.#pixiRenderer?.render(this._pixiContainer);
145
140
  this.fpsDisplay?.update();
146
141
  this._isSizeDirty = false;
147
142
  }
@@ -1 +1 @@
1
- {"version":3,"file":"renderer.js","sourceRoot":"","sources":["../../src/renderer/renderer.ts"],"names":[],"mappings":"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","sourcesContent":["import { EventMap } from '@webtaku/event-emitter'\nimport { AutoDetectOptions, autoDetectRenderer, ColorSource, Container as PixiContainer, Renderer as PixiRenderer } from 'pixi.js'\nimport { debugMode } from '../debug'\nimport { setStyle } from '../dom/dom-utils'\nimport { RenderableNode } from '../node/core/renderable'\nimport { Camera } from './camera'\nimport { RendererContainerManager } from './container-manager'\nimport { FpsDisplay } from './fps-display'\nimport { Layer } from './layer'\nimport { Ticker } from './ticker'\n\nexport type RendererOptions = {\n fixedWidth?: number\n fixedHeight?: number\n logicalWidth?: number\n logicalHeight?: number\n backgroundColor?: ColorSource\n backgroundAlpha?: number\n layers?: { name: string; drawOrder: number }[]\n}\n\nexport class Renderer extends RenderableNode<PixiContainer, {\n resize: (width: number, height: number) => void\n}> {\n #containerManager: RendererContainerManager\n #ticker = new Ticker((dt) => this.#render(dt))\n camera = new Camera()\n fpsDisplay?: FpsDisplay\n timeScale = 1\n\n #fixedWidth?: number\n #fixedHeight?: number\n logicalWidth?: number\n logicalHeight?: number\n #backgroundColor?: ColorSource\n #backgroundAlpha?: number\n\n #pixiRenderer?: PixiRenderer\n #layers: { [name: string]: Layer } = {}\n _isSizeDirty = false\n\n canvasWidth = 0\n canvasHeight = 0\n canvasLeft = 0\n canvasTop = 0\n viewportScale = 1\n centerX = 0\n centerY = 0\n\n constructor(public container: HTMLElement, options?: RendererOptions) {\n super(new PixiContainer({ sortableChildren: true }))\n this.renderer = this\n\n this.worldTransform.x.v = 0\n this.worldTransform.y.v = 0\n this.worldTransform.resetDirty()\n\n this.#containerManager = new RendererContainerManager(container)\n this.#containerManager.on('resize', (width, height) => this.#updateSize(width, height))\n\n this.camera.on('positionChanged', () => this.#updatePosition())\n this.camera.on('scaleChanged', () => this.#updatePosition())\n\n if (options) {\n if (options.fixedWidth !== undefined) this.#fixedWidth = options.fixedWidth\n if (options.fixedHeight !== undefined) this.#fixedHeight = options.fixedHeight\n if (options.logicalWidth !== undefined) this.logicalWidth = options.logicalWidth\n if (options.logicalHeight !== undefined) this.logicalHeight = options.logicalHeight\n if (options.backgroundColor !== undefined) this.#backgroundColor = options.backgroundColor\n if (options.backgroundAlpha !== undefined) this.#backgroundAlpha = options.backgroundAlpha\n\n if (options.layers) {\n for (const layerOption of options.layers) {\n const layer = new Layer(layerOption.drawOrder)\n this._pixiContainer.addChild(layer._pixiContainer)\n this.#layers[layerOption.name] = layer\n }\n }\n }\n\n if (debugMode) {\n this.fpsDisplay = new FpsDisplay(container)\n }\n\n this.init()\n }\n\n private async init() {\n const options: Partial<AutoDetectOptions> = {\n eventMode: 'none',\n resolution: window.devicePixelRatio,\n }\n\n if (this.#fixedWidth) options.width = this.#fixedWidth\n if (this.#fixedHeight) options.height = this.#fixedHeight\n if (this.logicalWidth) options.width = this.logicalWidth\n if (this.logicalHeight) options.height = this.logicalHeight\n if (this.#backgroundColor !== undefined) options.backgroundColor = this.#backgroundColor\n if (this.#backgroundAlpha !== undefined) options.backgroundAlpha = this.#backgroundAlpha\n\n const pr = await autoDetectRenderer(options)\n\n setStyle(pr.canvas, {\n position: 'absolute',\n touchAction: 'auto',\n })\n this.container.appendChild(pr.canvas)\n\n this.#pixiRenderer = pr\n\n const cr = this.container.getBoundingClientRect()\n this.#updateSize(cr.width, cr.height)\n }\n\n #updatePosition() {\n const S = this.camera.scale\n this._pixiContainer.scale = S\n this._pixiContainer.position.set(\n this.centerX - this.camera.x * S,\n this.centerY - this.camera.y * S\n )\n }\n\n #updateSize(containerWidth: number, containerHeight: number) {\n if (this.#fixedWidth) containerWidth = this.#fixedWidth\n if (this.#fixedHeight) containerHeight = this.#fixedHeight\n\n const canvasWidth = this.logicalWidth ?? containerWidth\n const canvasHeight = this.logicalHeight ?? containerHeight\n this.canvasWidth = canvasWidth\n this.canvasHeight = canvasHeight\n\n this.centerX = canvasWidth / 2\n this.centerY = canvasHeight / 2\n this.#updatePosition()\n\n const S = Math.min(containerWidth / canvasWidth, containerHeight / canvasHeight)\n this.viewportScale = S\n\n const displayWidth = canvasWidth * S\n const displayHeight = canvasHeight * S\n\n const canvasLeft = (containerWidth - displayWidth) / 2\n const canvasTop = (containerHeight - displayHeight) / 2\n this.canvasLeft = canvasLeft\n this.canvasTop = canvasTop\n\n if (this.#pixiRenderer) {\n this.#pixiRenderer.resize(canvasWidth, canvasHeight)\n\n setStyle(this.#pixiRenderer.canvas, {\n width: `${displayWidth}px`,\n height: `${displayHeight}px`,\n left: `${canvasLeft}px`,\n top: `${canvasTop}px`,\n })\n\n this.emit('resize', canvasWidth, canvasHeight)\n }\n\n this._isSizeDirty = true\n }\n\n #render(dt: number) {\n // [성능 최적화] 렌더러가 준비되지 않은 경우 불필요한 업데이트 스킵\n if (!this.#pixiRenderer) return\n\n const scaledDt = dt * this.timeScale\n this.update(scaledDt)\n\n // [성능 최적화] 2-pass → 1-pass로 통합\n // 기존: _updateWorldTransform() + _resetWorldTransformDirty() 별도 호출\n // 개선: _updateWorldTransform() 내부에서 dirty 리셋까지 처리\n this._updateWorldTransform()\n\n this.#pixiRenderer.render(this._pixiContainer)\n this.fpsDisplay?.update()\n\n this._isSizeDirty = false\n }\n\n _addToLayer(node: RenderableNode<PixiContainer, EventMap>, layerName: string) {\n const layer = this.#layers[layerName]\n if (!layer) throw new Error(`Layer ${layerName} does not exist.`)\n layer._pixiContainer.addChild(node._pixiContainer)\n }\n\n override remove() {\n this.#containerManager.remove()\n this.#ticker.remove()\n this.#pixiRenderer?.destroy()\n this.fpsDisplay?.remove()\n super.remove()\n }\n\n screenToWorld(screenX: number, screenY: number) {\n const x = (screenX - this.canvasLeft) / this.viewportScale - this.canvasWidth / 2\n const y = (screenY - this.canvasTop) / this.viewportScale - this.canvasHeight / 2\n return { x, y }\n }\n}\n"]}
1
+ {"version":3,"file":"renderer.js","sourceRoot":"","sources":["../../src/renderer/renderer.ts"],"names":[],"mappings":"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","sourcesContent":["import { EventMap } from '@webtaku/event-emitter'\nimport { AutoDetectOptions, autoDetectRenderer, ColorSource, Container as PixiContainer, Renderer as PixiRenderer } from 'pixi.js'\nimport { debugMode } from '../debug'\nimport { setStyle } from '../dom/dom-utils'\nimport { RenderableNode } from '../node/core/renderable'\nimport { Camera } from './camera'\nimport { RendererContainerManager } from './container-manager'\nimport { FpsDisplay } from './fps-display'\nimport { Layer } from './layer'\nimport { Ticker } from './ticker'\n\nexport type RendererOptions = {\n fixedWidth?: number\n fixedHeight?: number\n logicalWidth?: number\n logicalHeight?: number\n backgroundColor?: ColorSource\n backgroundAlpha?: number\n layers?: { name: string; drawOrder: number }[]\n}\n\nexport class Renderer extends RenderableNode<PixiContainer, {\n resize: (width: number, height: number) => void\n}> {\n #containerManager: RendererContainerManager\n #ticker = new Ticker((dt) => this.#render(dt))\n camera = new Camera()\n fpsDisplay?: FpsDisplay\n timeScale = 1\n\n #fixedWidth?: number\n #fixedHeight?: number\n logicalWidth?: number\n logicalHeight?: number\n #backgroundColor?: ColorSource\n #backgroundAlpha?: number\n\n #pixiRenderer?: PixiRenderer\n #layers: { [name: string]: Layer } = {}\n _isSizeDirty = false\n\n canvasWidth = 0\n canvasHeight = 0\n canvasLeft = 0\n canvasTop = 0\n viewportScale = 1\n centerX = 0\n centerY = 0\n\n constructor(public container: HTMLElement, options?: RendererOptions) {\n super(new PixiContainer({ sortableChildren: true }))\n this.renderer = this\n\n this.worldTransform.x.v = 0\n this.worldTransform.y.v = 0\n this.worldTransform.resetDirty()\n\n this.#containerManager = new RendererContainerManager(container)\n this.#containerManager.on('resize', (width, height) => this.#updateSize(width, height))\n\n this.camera.on('positionChanged', () => this.#updatePosition())\n this.camera.on('scaleChanged', () => this.#updatePosition())\n\n if (options) {\n if (options.fixedWidth !== undefined) this.#fixedWidth = options.fixedWidth\n if (options.fixedHeight !== undefined) this.#fixedHeight = options.fixedHeight\n if (options.logicalWidth !== undefined) this.logicalWidth = options.logicalWidth\n if (options.logicalHeight !== undefined) this.logicalHeight = options.logicalHeight\n if (options.backgroundColor !== undefined) this.#backgroundColor = options.backgroundColor\n if (options.backgroundAlpha !== undefined) this.#backgroundAlpha = options.backgroundAlpha\n\n if (options.layers) {\n for (const layerOption of options.layers) {\n const layer = new Layer(layerOption.drawOrder)\n this._pixiContainer.addChild(layer._pixiContainer)\n this.#layers[layerOption.name] = layer\n }\n }\n }\n\n if (debugMode) {\n this.fpsDisplay = new FpsDisplay(container)\n }\n\n this.init()\n }\n\n private async init() {\n const options: Partial<AutoDetectOptions> = {\n eventMode: 'none',\n resolution: window.devicePixelRatio,\n }\n\n if (this.#fixedWidth) options.width = this.#fixedWidth\n if (this.#fixedHeight) options.height = this.#fixedHeight\n if (this.logicalWidth) options.width = this.logicalWidth\n if (this.logicalHeight) options.height = this.logicalHeight\n if (this.#backgroundColor !== undefined) options.backgroundColor = this.#backgroundColor\n if (this.#backgroundAlpha !== undefined) options.backgroundAlpha = this.#backgroundAlpha\n\n const pr = await autoDetectRenderer(options)\n\n setStyle(pr.canvas, {\n position: 'absolute',\n touchAction: 'auto',\n })\n this.container.appendChild(pr.canvas)\n\n this.#pixiRenderer = pr\n\n const cr = this.container.getBoundingClientRect()\n this.#updateSize(cr.width, cr.height)\n }\n\n #updatePosition() {\n const S = this.camera.scale\n this._pixiContainer.scale = S\n this._pixiContainer.position.set(\n this.centerX - this.camera.x * S,\n this.centerY - this.camera.y * S\n )\n }\n\n #updateSize(containerWidth: number, containerHeight: number) {\n if (this.#fixedWidth) containerWidth = this.#fixedWidth\n if (this.#fixedHeight) containerHeight = this.#fixedHeight\n\n const canvasWidth = this.logicalWidth ?? containerWidth\n const canvasHeight = this.logicalHeight ?? containerHeight\n this.canvasWidth = canvasWidth\n this.canvasHeight = canvasHeight\n\n this.centerX = canvasWidth / 2\n this.centerY = canvasHeight / 2\n this.#updatePosition()\n\n const S = Math.min(containerWidth / canvasWidth, containerHeight / canvasHeight)\n this.viewportScale = S\n\n const displayWidth = canvasWidth * S\n const displayHeight = canvasHeight * S\n\n const canvasLeft = (containerWidth - displayWidth) / 2\n const canvasTop = (containerHeight - displayHeight) / 2\n this.canvasLeft = canvasLeft\n this.canvasTop = canvasTop\n\n if (this.#pixiRenderer) {\n this.#pixiRenderer.resize(canvasWidth, canvasHeight)\n\n setStyle(this.#pixiRenderer.canvas, {\n width: `${displayWidth}px`,\n height: `${displayHeight}px`,\n left: `${canvasLeft}px`,\n top: `${canvasTop}px`,\n })\n\n this.emit('resize', canvasWidth, canvasHeight)\n }\n\n this._isSizeDirty = true\n }\n\n #render(dt: number) {\n const scaledDt = dt * this.timeScale\n this.update(scaledDt)\n this._updateWorldTransform()\n this._resetWorldTransformDirty()\n this.#pixiRenderer?.render(this._pixiContainer)\n this.fpsDisplay?.update()\n\n this._isSizeDirty = false\n }\n\n _addToLayer(node: RenderableNode<PixiContainer, EventMap>, layerName: string) {\n const layer = this.#layers[layerName]\n if (!layer) throw new Error(`Layer ${layerName} does not exist.`)\n layer._pixiContainer.addChild(node._pixiContainer)\n }\n\n override remove() {\n this.#containerManager.remove()\n this.#ticker.remove()\n this.#pixiRenderer?.destroy()\n this.fpsDisplay?.remove()\n super.remove()\n }\n\n screenToWorld(screenX: number, screenY: number) {\n const x = (screenX - this.canvasLeft) / this.viewportScale - this.canvasWidth / 2\n const y = (screenY - this.canvasTop) / this.viewportScale - this.canvasHeight / 2\n return { x, y }\n }\n}\n"]}
@@ -17,6 +17,10 @@ declare class MusicPlayer {
17
17
  enable(): void;
18
18
  disable(): void;
19
19
  toggle(): void;
20
+ get temporarilyDisabled(): boolean;
21
+ set temporarilyDisabled(v: boolean);
22
+ temporaryDisable(): void;
23
+ temporaryEnable(): void;
20
24
  get volume(): number;
21
25
  set volume(volume: number);
22
26
  play(src: string): void;
@@ -31,6 +35,10 @@ declare class SfxPlayer {
31
35
  enable(): void;
32
36
  disable(): void;
33
37
  toggle(): void;
38
+ get temporarilyDisabled(): boolean;
39
+ set temporarilyDisabled(v: boolean);
40
+ temporaryDisable(): void;
41
+ temporaryEnable(): void;
34
42
  get volume(): number;
35
43
  set volume(volume: number);
36
44
  play(src: string): void;
@@ -1 +1 @@
1
- {"version":3,"file":"audio.d.ts","sourceRoot":"","sources":["../../../src/asset/audio.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,YAAY,cAAoE,CAAA;AAoE7F,qBAAa,KAAK;;IAChB,GAAG,EAAE,MAAM,CAAA;gBAeC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO;IAOtD,IAAI,MAAM,IACS,MAAM,CADW;IACpC,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,EAGxB;IAEK,IAAI;IA0DV,KAAK;IAaL,IAAI;CAOL;AAED,cAAM,WAAW;;;IA2Bf,IAAI,OAAO,IACI,OAAO,CADgB;IACtC,IAAI,OAAO,CAAC,CAAC,EAAE,OAAO,EAkBrB;IAED,MAAM;IACN,OAAO;IACP,MAAM;IAEN,IAAI,MAAM,IACS,MAAM,CADW;IACpC,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,EAIxB;IAED,IAAI,CAAC,GAAG,EAAE,MAAM;IAehB,KAAK;IAIL,IAAI;CAML;AAED,cAAM,SAAS;;;IAYb,IAAI,OAAO,IACI,OAAO,CADgB;IACtC,IAAI,OAAO,CAAC,CAAC,EAAE,OAAO,EAGrB;IAED,MAAM;IACN,OAAO;IACP,MAAM;IAEN,IAAI,MAAM,IACS,MAAM,CADW;IACpC,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,EAGxB;IAED,IAAI,CAAC,GAAG,EAAE,MAAM;IAMhB,UAAU,CAAC,GAAG,IAAI,EAAE,MAAM,EAAE;CAI7B;AAED,eAAO,MAAM,WAAW,aAAoB,CAAA;AAC5C,eAAO,MAAM,SAAS,WAAkB,CAAA"}
1
+ {"version":3,"file":"audio.d.ts","sourceRoot":"","sources":["../../../src/asset/audio.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,YAAY,cAAoE,CAAA;AAoE7F,qBAAa,KAAK;;IAChB,GAAG,EAAE,MAAM,CAAA;gBAeC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO;IAOtD,IAAI,MAAM,IACS,MAAM,CADW;IACpC,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,EAGxB;IAEK,IAAI;IA0DV,KAAK;IAaL,IAAI;CAOL;AAED,cAAM,WAAW;;;IA4Bf,IAAI,OAAO,IACI,OAAO,CADgB;IACtC,IAAI,OAAO,CAAC,CAAC,EAAE,OAAO,EAkBrB;IAED,MAAM;IACN,OAAO;IACP,MAAM;IAEN,IAAI,mBAAmB,IACI,OAAO,CAD4B;IAC9D,IAAI,mBAAmB,CAAC,CAAC,EAAE,OAAO,EAOjC;IAED,gBAAgB;IAChB,eAAe;IAEf,IAAI,MAAM,IACS,MAAM,CADW;IACpC,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,EAIxB;IAED,IAAI,CAAC,GAAG,EAAE,MAAM;IAehB,KAAK;IAIL,IAAI;CAML;AAED,cAAM,SAAS;;;IAab,IAAI,OAAO,IACI,OAAO,CADgB;IACtC,IAAI,OAAO,CAAC,CAAC,EAAE,OAAO,EAGrB;IAED,MAAM;IACN,OAAO;IACP,MAAM;IAEN,IAAI,mBAAmB,IACI,OAAO,CAD4B;IAC9D,IAAI,mBAAmB,CAAC,CAAC,EAAE,OAAO,EAAmC;IAErE,gBAAgB;IAChB,eAAe;IAEf,IAAI,MAAM,IACS,MAAM,CADW;IACpC,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,EAGxB;IAED,IAAI,CAAC,GAAG,EAAE,MAAM;IAMhB,UAAU,CAAC,GAAG,IAAI,EAAE,MAAM,EAAE;CAI7B;AAED,eAAO,MAAM,WAAW,aAAoB,CAAA;AAC5C,eAAO,MAAM,SAAS,WAAkB,CAAA"}
@@ -15,7 +15,6 @@ export type DomParticleSystemOptions = {
15
15
  fadeRate: number;
16
16
  orientToVelocity: boolean;
17
17
  blendMode?: BLEND_MODES;
18
- poolSize?: number;
19
18
  } & DomGameObjectOptions;
20
19
  export declare class DomParticleSystem extends DomGameObject {
21
20
  #private;
@@ -1 +1 @@
1
- {"version":3,"file":"dom-particle.d.ts","sourceRoot":"","sources":["../../../src/dom/dom-particle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AACrC,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAIvE,KAAK,WAAW,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAA;AAE/C,MAAM,MAAM,wBAAwB,GAAG;IACrC,OAAO,EAAE,MAAM,CAAA;IAEf,KAAK,EAAE,WAAW,CAAA;IAClB,QAAQ,EAAE,WAAW,CAAA;IACrB,KAAK,EAAE,WAAW,CAAA;IAClB,QAAQ,EAAE,WAAW,CAAA;IACrB,aAAa,EAAE,WAAW,CAAA;IAE1B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,gBAAgB,EAAE,OAAO,CAAA;IAEzB,SAAS,CAAC,EAAE,WAAW,CAAA;IAGvB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,GAAG,oBAAoB,CAAA;AAwBxB,qBAAa,iBAAkB,SAAQ,aAAa;;gBAoBtC,OAAO,EAAE,wBAAwB;IAyEvC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE;cA6B3B,MAAM,CAAC,EAAE,EAAE,MAAM;IAqC3B,MAAM;CAUhB"}
1
+ {"version":3,"file":"dom-particle.d.ts","sourceRoot":"","sources":["../../../src/dom/dom-particle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AACrC,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAIvE,KAAK,WAAW,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAA;AAE/C,MAAM,MAAM,wBAAwB,GAAG;IACrC,OAAO,EAAE,MAAM,CAAA;IAEf,KAAK,EAAE,WAAW,CAAA;IAClB,QAAQ,EAAE,WAAW,CAAA;IACrB,KAAK,EAAE,WAAW,CAAA;IAClB,QAAQ,EAAE,WAAW,CAAA;IACrB,aAAa,EAAE,WAAW,CAAA;IAE1B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,gBAAgB,EAAE,OAAO,CAAA;IAEzB,SAAS,CAAC,EAAE,WAAW,CAAA;CACxB,GAAG,oBAAoB,CAAA;AAkBxB,qBAAa,iBAAkB,SAAQ,aAAa;;gBAgBtC,OAAO,EAAE,wBAAwB;IA2BvC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE;cAwC3B,MAAM,CAAC,EAAE,EAAE,MAAM;IAwB3B,MAAM;CAIhB"}
@@ -1,9 +1,7 @@
1
1
  import { EventMap } from '@webtaku/event-emitter';
2
2
  import { Container as PixiContainer } from 'pixi.js';
3
3
  import { TransformableNode, TransformableNodeOptions } from './transformable';
4
- export type GameObjectOptions = {
5
- sortableChildren?: boolean;
6
- } & TransformableNodeOptions;
4
+ export type GameObjectOptions = {} & TransformableNodeOptions;
7
5
  export declare class GameObject<E extends EventMap = {}> extends TransformableNode<PixiContainer, E> {
8
6
  constructor(options?: GameObjectOptions);
9
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"game-object.d.ts","sourceRoot":"","sources":["../../../../src/node/core/game-object.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACjD,OAAO,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,SAAS,CAAA;AACpD,OAAO,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAA;AAE7E,MAAM,MAAM,iBAAiB,GAAG;IAI9B,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B,GAAG,wBAAwB,CAAA;AAE5B,qBAAa,UAAU,CAAC,CAAC,SAAS,QAAQ,GAAG,EAAE,CAAE,SAAQ,iBAAiB,CAAC,aAAa,EAAE,CAAC,CAAC;gBAC9E,OAAO,CAAC,EAAE,iBAAiB;CAMxC"}
1
+ {"version":3,"file":"game-object.d.ts","sourceRoot":"","sources":["../../../../src/node/core/game-object.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACjD,OAAO,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,SAAS,CAAA;AACpD,OAAO,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAA;AAE7E,MAAM,MAAM,iBAAiB,GAAG,EAAE,GAAG,wBAAwB,CAAA;AAE7D,qBAAa,UAAU,CAAC,CAAC,SAAS,QAAQ,GAAG,EAAE,CAAE,SAAQ,iBAAiB,CAAC,aAAa,EAAE,CAAC,CAAC;gBAC9E,OAAO,CAAC,EAAE,iBAAiB;CAGxC"}
@@ -16,6 +16,7 @@ export declare abstract class RenderableNode<C extends PixiContainer, E extends
16
16
  add(...children: GameNode<EventMap>[]): void;
17
17
  remove(): void;
18
18
  _updateWorldTransform(): void;
19
+ _resetWorldTransformDirty(): void;
19
20
  set tint(t: number);
20
21
  get tint(): number;
21
22
  hide(): void;