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.
- package/lib/asset/audio.js +25 -7
- package/lib/asset/audio.js.map +1 -1
- package/lib/dom/dom-particle.js +23 -74
- package/lib/dom/dom-particle.js.map +1 -1
- package/lib/node/core/game-object.js +1 -4
- package/lib/node/core/game-object.js.map +1 -1
- package/lib/node/core/renderable.js +6 -4
- package/lib/node/core/renderable.js.map +1 -1
- package/lib/node/core/transformable.js +11 -42
- package/lib/node/core/transformable.js.map +1 -1
- package/lib/node/ext/animated-sprite.js +1 -8
- package/lib/node/ext/animated-sprite.js.map +1 -1
- package/lib/node/ext/bitmap-text.js +4 -61
- package/lib/node/ext/bitmap-text.js.map +1 -1
- package/lib/node/ext/circle.js +1 -2
- package/lib/node/ext/circle.js.map +1 -1
- package/lib/node/ext/particle.js +15 -65
- package/lib/node/ext/particle.js.map +1 -1
- package/lib/node/ext/rectangle.js +1 -2
- package/lib/node/ext/rectangle.js.map +1 -1
- package/lib/renderer/camera.js +0 -8
- package/lib/renderer/camera.js.map +1 -1
- package/lib/renderer/renderer.js +2 -7
- package/lib/renderer/renderer.js.map +1 -1
- package/lib/types/asset/audio.d.ts +8 -0
- package/lib/types/asset/audio.d.ts.map +1 -1
- package/lib/types/dom/dom-particle.d.ts +0 -1
- package/lib/types/dom/dom-particle.d.ts.map +1 -1
- package/lib/types/node/core/game-object.d.ts +1 -3
- package/lib/types/node/core/game-object.d.ts.map +1 -1
- package/lib/types/node/core/renderable.d.ts +1 -0
- package/lib/types/node/core/renderable.d.ts.map +1 -1
- package/lib/types/node/core/transformable.d.ts.map +1 -1
- package/lib/types/node/ext/animated-sprite.d.ts.map +1 -1
- package/lib/types/node/ext/bitmap-text.d.ts.map +1 -1
- package/lib/types/node/ext/circle.d.ts.map +1 -1
- package/lib/types/node/ext/particle.d.ts +0 -1
- package/lib/types/node/ext/particle.d.ts.map +1 -1
- package/lib/types/node/ext/rectangle.d.ts.map +1 -1
- package/lib/types/renderer/camera.d.ts.map +1 -1
- package/lib/types/renderer/renderer.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/asset/audio.ts +28 -7
- package/src/dom/dom-particle.ts +24 -91
- package/src/node/core/game-object.ts +2 -10
- package/src/node/core/renderable.ts +5 -4
- package/src/node/core/transformable.ts +11 -49
- package/src/node/ext/animated-sprite.ts +1 -10
- package/src/node/ext/bitmap-text.ts +4 -70
- package/src/node/ext/circle.ts +1 -2
- package/src/node/ext/particle.ts +16 -80
- package/src/node/ext/rectangle.ts +1 -2
- package/src/renderer/camera.ts +0 -6
- 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":"AACA,OAAO,EAAE,cAAc,IAAI,kBAAkB,EAAe,MAAM,SAAS,CAAA;AAC3E,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AAErF,OAAO,EAAE,UAAU,EAAqB,MAAM,qBAAqB,CAAA;AAQnE,MAAM,OAAO,kBAA4C,SAAQ,UAE/D;IACA,IAAI,CAAQ;IACZ,MAAM,CAAO;IACb,UAAU,CAAQ;IAElB,QAAQ,CAAS;IACjB,MAAM,CAAc;IACpB,OAAO,CAAqB;IAC5B,QAAQ,GAAG,EAAE,CAAA;IAEb,
|
|
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
|
-
|
|
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.#
|
|
78
|
-
|
|
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"]}
|
package/lib/node/ext/circle.js
CHANGED
|
@@ -5,8 +5,7 @@ export class CircleNode extends TransformableNode {
|
|
|
5
5
|
#fill;
|
|
6
6
|
#stroke;
|
|
7
7
|
constructor(options) {
|
|
8
|
-
|
|
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,
|
|
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"]}
|
package/lib/node/ext/particle.js
CHANGED
|
@@ -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 =
|
|
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
|
-
|
|
113
|
-
|
|
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
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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
|
-
|
|
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,
|
|
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"]}
|
package/lib/renderer/camera.js
CHANGED
|
@@ -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,
|
|
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}"]}
|
package/lib/renderer/renderer.js
CHANGED
|
@@ -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
|
|
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;;;
|
|
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"}
|
|
@@ -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;
|
|
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
|
|
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;
|