@vpmedia/phaser 1.0.1 → 1.0.2

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 (107) hide show
  1. package/dist/phaser.cjs.LICENSE.txt +1 -1
  2. package/dist/phaser.js.LICENSE.txt +1 -1
  3. package/package.json +2 -3
  4. package/src/index.js +99 -0
  5. package/src/phaser/core/animation.js +355 -0
  6. package/src/phaser/core/animation_manager.js +238 -0
  7. package/src/phaser/core/animation_parser.js +130 -0
  8. package/src/phaser/core/array_set.js +108 -0
  9. package/src/phaser/core/cache.js +558 -0
  10. package/src/phaser/core/const.js +106 -0
  11. package/src/phaser/core/device.js +67 -0
  12. package/src/phaser/core/device_util.js +386 -0
  13. package/src/phaser/core/dom.js +207 -0
  14. package/src/phaser/core/event_manager.js +243 -0
  15. package/src/phaser/core/factory.js +74 -0
  16. package/src/phaser/core/frame.js +75 -0
  17. package/src/phaser/core/frame_data.js +84 -0
  18. package/src/phaser/core/frame_util.js +31 -0
  19. package/src/phaser/core/game.js +412 -0
  20. package/src/phaser/core/input.js +401 -0
  21. package/src/phaser/core/input_button.js +102 -0
  22. package/src/phaser/core/input_handler.js +687 -0
  23. package/src/phaser/core/input_mouse.js +289 -0
  24. package/src/phaser/core/input_mspointer.js +197 -0
  25. package/src/phaser/core/input_pointer.js +427 -0
  26. package/src/phaser/core/input_touch.js +157 -0
  27. package/src/phaser/core/loader.js +946 -0
  28. package/src/phaser/core/loader_parser.js +105 -0
  29. package/src/phaser/core/raf.js +46 -0
  30. package/src/phaser/core/raf_fb.js +75 -0
  31. package/src/phaser/core/raf_to.js +34 -0
  32. package/src/phaser/core/scale_manager.js +806 -0
  33. package/src/phaser/core/scene.js +66 -0
  34. package/src/phaser/core/scene_manager.js +310 -0
  35. package/src/phaser/core/signal.js +175 -0
  36. package/src/phaser/core/signal_binding.js +69 -0
  37. package/src/phaser/core/sound.js +538 -0
  38. package/src/phaser/core/sound_manager.js +365 -0
  39. package/src/phaser/core/stage.js +108 -0
  40. package/src/phaser/core/time.js +203 -0
  41. package/src/phaser/core/timer.js +276 -0
  42. package/src/phaser/core/timer_event.js +21 -0
  43. package/src/phaser/core/tween.js +329 -0
  44. package/src/phaser/core/tween_data.js +258 -0
  45. package/src/phaser/core/tween_easing.js +316 -0
  46. package/src/phaser/core/tween_manager.js +185 -0
  47. package/src/phaser/core/world.js +18 -0
  48. package/src/phaser/display/bitmap_text.js +322 -0
  49. package/src/phaser/display/button.js +194 -0
  50. package/src/phaser/display/canvas/buffer.js +36 -0
  51. package/src/phaser/display/canvas/graphics.js +227 -0
  52. package/src/phaser/display/canvas/masker.js +39 -0
  53. package/src/phaser/display/canvas/pool.js +121 -0
  54. package/src/phaser/display/canvas/renderer.js +123 -0
  55. package/src/phaser/display/canvas/tinter.js +141 -0
  56. package/src/phaser/display/canvas/util.js +151 -0
  57. package/src/phaser/display/display_object.js +597 -0
  58. package/src/phaser/display/graphics.js +723 -0
  59. package/src/phaser/display/graphics_data.js +27 -0
  60. package/src/phaser/display/graphics_data_util.js +14 -0
  61. package/src/phaser/display/group.js +227 -0
  62. package/src/phaser/display/image.js +288 -0
  63. package/src/phaser/display/sprite_batch.js +15 -0
  64. package/src/phaser/display/sprite_util.js +248 -0
  65. package/src/phaser/display/text.js +1089 -0
  66. package/src/phaser/display/webgl/abstract_filter.js +25 -0
  67. package/src/phaser/display/webgl/base_texture.js +68 -0
  68. package/src/phaser/display/webgl/blend_manager.js +35 -0
  69. package/src/phaser/display/webgl/earcut.js +647 -0
  70. package/src/phaser/display/webgl/earcut_node.js +28 -0
  71. package/src/phaser/display/webgl/fast_sprite_batch.js +242 -0
  72. package/src/phaser/display/webgl/filter_manager.js +46 -0
  73. package/src/phaser/display/webgl/filter_texture.js +61 -0
  74. package/src/phaser/display/webgl/graphics.js +618 -0
  75. package/src/phaser/display/webgl/graphics_data.js +42 -0
  76. package/src/phaser/display/webgl/mask_manager.js +36 -0
  77. package/src/phaser/display/webgl/render_texture.js +81 -0
  78. package/src/phaser/display/webgl/renderer.js +234 -0
  79. package/src/phaser/display/webgl/shader/complex.js +74 -0
  80. package/src/phaser/display/webgl/shader/fast.js +97 -0
  81. package/src/phaser/display/webgl/shader/normal.js +225 -0
  82. package/src/phaser/display/webgl/shader/primitive.js +72 -0
  83. package/src/phaser/display/webgl/shader/strip.js +77 -0
  84. package/src/phaser/display/webgl/shader_manager.js +89 -0
  85. package/src/phaser/display/webgl/sprite_batch.js +320 -0
  86. package/src/phaser/display/webgl/stencil_manager.js +170 -0
  87. package/src/phaser/display/webgl/texture.js +117 -0
  88. package/src/phaser/display/webgl/texture_util.js +32 -0
  89. package/src/phaser/display/webgl/util.js +74 -0
  90. package/src/phaser/geom/circle.js +186 -0
  91. package/src/phaser/geom/ellipse.js +65 -0
  92. package/src/phaser/geom/line.js +190 -0
  93. package/src/phaser/geom/matrix.js +147 -0
  94. package/src/phaser/geom/point.js +164 -0
  95. package/src/phaser/geom/polygon.js +141 -0
  96. package/src/phaser/geom/rectangle.js +306 -0
  97. package/src/phaser/geom/rounded_rectangle.js +36 -0
  98. package/src/phaser/geom/util/circle.js +115 -0
  99. package/src/phaser/geom/util/ellipse.js +30 -0
  100. package/src/phaser/geom/util/line.js +130 -0
  101. package/src/phaser/geom/util/matrix.js +48 -0
  102. package/src/phaser/geom/util/point.js +276 -0
  103. package/src/phaser/geom/util/polygon.js +24 -0
  104. package/src/phaser/geom/util/rectangle.js +212 -0
  105. package/src/phaser/geom/util/rounded_rectangle.js +28 -0
  106. package/src/phaser/util/math.js +279 -0
  107. package/src/phaser/util/string.js +26 -0
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @author Andras Csizmadia <andras@vpmedia.hu>
3
+ * @author Richard Davey <rich@photonstorm.com>
4
+ * @author Mat Groves http://matgroves.com/ @Doormat23
5
+ * @copyright Copyright (c) 2018-present Richard Davey, Photon Storm Ltd., Andras Csizmadia <andras@vpmedia.hu> (www.vpmedia.hu)
6
+ */
7
+ import { create, removeByCanvas } from './pool';
8
+
9
+ export default class {
10
+
11
+ constructor(width, height) {
12
+ this.width = width;
13
+ this.height = height;
14
+ this.canvas = create(this, this.width, this.height);
15
+ this.context = this.canvas.getContext('2d');
16
+ this.canvas.width = width;
17
+ this.canvas.height = height;
18
+ }
19
+
20
+ clear() {
21
+ this.context.setTransform(1, 0, 0, 1, 0, 0);
22
+ this.context.clearRect(0, 0, this.width, this.height);
23
+ }
24
+
25
+ resize(width, height) {
26
+ this.width = width;
27
+ this.height = height;
28
+ this.canvas.width = width;
29
+ this.canvas.height = height;
30
+ }
31
+
32
+ destroy() {
33
+ removeByCanvas(this.canvas);
34
+ }
35
+
36
+ }
@@ -0,0 +1,227 @@
1
+ /**
2
+ * @author Andras Csizmadia <andras@vpmedia.hu>
3
+ * @author Richard Davey <rich@photonstorm.com>
4
+ * @author Mat Groves http://matgroves.com/ @Doormat23
5
+ * @copyright Copyright (c) 2018-present Richard Davey, Photon Storm Ltd., Andras Csizmadia <andras@vpmedia.hu> (www.vpmedia.hu)
6
+ */
7
+ import { GEOM_POLYGON, GEOM_RECTANGLE, GEOM_CIRCLE, GEOM_ELLIPSE, GEOM_ROUNDED_RECTANGLE } from '../../core/const';
8
+
9
+ /**
10
+ *
11
+ * @param graphics
12
+ */
13
+ export function updateGraphicsTint(graphics) {
14
+ if (graphics.tint === 0xFFFFFF) {
15
+ return;
16
+ }
17
+ const tintR = (graphics.tint >> 16 & 0xFF) / 255;
18
+ const tintG = (graphics.tint >> 8 & 0xFF) / 255;
19
+ const tintB = (graphics.tint & 0xFF) / 255;
20
+ for (let i = 0; i < graphics.graphicsData.length; i += 1) {
21
+ const data = graphics.graphicsData[i];
22
+ const fillColor = data.fillColor | 0;
23
+ const lineColor = data.lineColor | 0;
24
+ data._fillTint = (((fillColor >> 16 & 0xFF) / 255 * tintR * 255 << 16) + ((fillColor >> 8 & 0xFF) / 255 * tintG * 255 << 8) + (fillColor & 0xFF) / 255 * tintB * 255);
25
+ data._lineTint = (((lineColor >> 16 & 0xFF) / 255 * tintR * 255 << 16) + ((lineColor >> 8 & 0xFF) / 255 * tintG * 255 << 8) + (lineColor & 0xFF) / 255 * tintB * 255);
26
+ }
27
+ }
28
+
29
+ /**
30
+ *
31
+ * @param graphics
32
+ * @param context
33
+ */
34
+ export function renderGraphics(graphics, context) {
35
+ const worldAlpha = graphics.worldAlpha;
36
+ if (graphics.dirty) {
37
+ updateGraphicsTint(graphics);
38
+ graphics.dirty = false;
39
+ }
40
+ for (let i = 0; i < graphics.graphicsData.length; i += 1) {
41
+ const data = graphics.graphicsData[i];
42
+ const shape = data.shape;
43
+ const fillColor = data._fillTint;
44
+ const lineColor = data._lineTint;
45
+ context.lineWidth = data.lineWidth;
46
+ if (data.type === GEOM_POLYGON) {
47
+ context.beginPath();
48
+ const points = shape.points;
49
+ context.moveTo(points[0], points[1]);
50
+ for (let j = 1; j < points.length / 2; j += 1) {
51
+ context.lineTo(points[j * 2], points[j * 2 + 1]);
52
+ }
53
+ if (shape.closed) {
54
+ context.lineTo(points[0], points[1]);
55
+ }
56
+ // if the first and last point are the same close the path - much neater :)
57
+ if (points[0] === points[points.length - 2] && points[1] === points[points.length - 1]) {
58
+ context.closePath();
59
+ }
60
+ if (data.fill) {
61
+ context.globalAlpha = data.fillAlpha * worldAlpha;
62
+ context.fillStyle = '#' + ('00000' + (fillColor | 0).toString(16)).substr(-6);
63
+ context.fill();
64
+ }
65
+ if (data.lineWidth) {
66
+ context.globalAlpha = data.lineAlpha * worldAlpha;
67
+ context.strokeStyle = '#' + ('00000' + (lineColor | 0).toString(16)).substr(-6);
68
+ context.stroke();
69
+ }
70
+ } else if (data.type === GEOM_RECTANGLE) {
71
+ if (data.fillColor || data.fillColor === 0) {
72
+ context.globalAlpha = data.fillAlpha * worldAlpha;
73
+ context.fillStyle = '#' + ('00000' + (fillColor | 0).toString(16)).substr(-6);
74
+ context.fillRect(shape.x, shape.y, shape.width, shape.height);
75
+ }
76
+ if (data.lineWidth) {
77
+ context.globalAlpha = data.lineAlpha * worldAlpha;
78
+ context.strokeStyle = '#' + ('00000' + (lineColor | 0).toString(16)).substr(-6);
79
+ context.strokeRect(shape.x, shape.y, shape.width, shape.height);
80
+ }
81
+ } else if (data.type === GEOM_CIRCLE) {
82
+ context.beginPath();
83
+ context.arc(shape.x, shape.y, shape.radius, 0, 2 * Math.PI);
84
+ context.closePath();
85
+ if (data.fill) {
86
+ context.globalAlpha = data.fillAlpha * worldAlpha;
87
+ context.fillStyle = '#' + ('00000' + (fillColor | 0).toString(16)).substr(-6);
88
+ context.fill();
89
+ }
90
+ if (data.lineWidth) {
91
+ context.globalAlpha = data.lineAlpha * worldAlpha;
92
+ context.strokeStyle = '#' + ('00000' + (lineColor | 0).toString(16)).substr(-6);
93
+ context.stroke();
94
+ }
95
+ } else if (data.type === GEOM_ELLIPSE) {
96
+ // ellipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas
97
+ const w = shape.width * 2;
98
+ const h = shape.height * 2;
99
+ const x = shape.x - w / 2;
100
+ const y = shape.y - h / 2;
101
+ context.beginPath();
102
+ const kappa = 0.5522848;
103
+ const ox = (w / 2) * kappa; // control point offset horizontal
104
+ const oy = (h / 2) * kappa; // control point offset vertical
105
+ const xe = x + w; // x-end
106
+ const ye = y + h; // y-end
107
+ const xm = x + w / 2; // x-middle
108
+ const ym = y + h / 2; // y-middle
109
+ context.moveTo(x, ym);
110
+ context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y);
111
+ context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym);
112
+ context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye);
113
+ context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym);
114
+ context.closePath();
115
+ if (data.fill) {
116
+ context.globalAlpha = data.fillAlpha * worldAlpha;
117
+ context.fillStyle = '#' + ('00000' + (fillColor | 0).toString(16)).substr(-6);
118
+ context.fill();
119
+ }
120
+ if (data.lineWidth) {
121
+ context.globalAlpha = data.lineAlpha * worldAlpha;
122
+ context.strokeStyle = '#' + ('00000' + (lineColor | 0).toString(16)).substr(-6);
123
+ context.stroke();
124
+ }
125
+ } else if (data.type === GEOM_ROUNDED_RECTANGLE) {
126
+ const rx = shape.x;
127
+ const ry = shape.y;
128
+ const width = shape.width;
129
+ const height = shape.height;
130
+ let radius = shape.radius;
131
+ const maxRadius = Math.min(width, height) / 2 | 0;
132
+ radius = radius > maxRadius ? maxRadius : radius;
133
+ context.beginPath();
134
+ context.moveTo(rx, ry + radius);
135
+ context.lineTo(rx, ry + height - radius);
136
+ context.quadraticCurveTo(rx, ry + height, rx + radius, ry + height);
137
+ context.lineTo(rx + width - radius, ry + height);
138
+ context.quadraticCurveTo(rx + width, ry + height, rx + width, ry + height - radius);
139
+ context.lineTo(rx + width, ry + radius);
140
+ context.quadraticCurveTo(rx + width, ry, rx + width - radius, ry);
141
+ context.lineTo(rx + radius, ry);
142
+ context.quadraticCurveTo(rx, ry, rx, ry + radius);
143
+ context.closePath();
144
+ if (data.fillColor || data.fillColor === 0) {
145
+ context.globalAlpha = data.fillAlpha * worldAlpha;
146
+ context.fillStyle = '#' + ('00000' + (fillColor | 0).toString(16)).substr(-6);
147
+ context.fill();
148
+ }
149
+ if (data.lineWidth) {
150
+ context.globalAlpha = data.lineAlpha * worldAlpha;
151
+ context.strokeStyle = '#' + ('00000' + (lineColor | 0).toString(16)).substr(-6);
152
+ context.stroke();
153
+ }
154
+ }
155
+ }
156
+ }
157
+
158
+ /**
159
+ *
160
+ * @param graphics
161
+ * @param context
162
+ */
163
+ export function renderGraphicsMask(graphics, context) {
164
+ const len = graphics.graphicsData.length;
165
+ if (len === 0) {
166
+ return;
167
+ }
168
+ context.beginPath();
169
+ for (let i = 0; i < len; i += 1) {
170
+ const data = graphics.graphicsData[i];
171
+ const shape = data.shape;
172
+ if (data.type === GEOM_POLYGON) {
173
+ const points = shape.points;
174
+ context.moveTo(points[0], points[1]);
175
+ for (let j = 1; j < points.length / 2; j += 1) {
176
+ context.lineTo(points[j * 2], points[j * 2 + 1]);
177
+ }
178
+ // if the first and last point are the same close the path - much neater :)
179
+ if (points[0] === points[points.length - 2] && points[1] === points[points.length - 1]) {
180
+ context.closePath();
181
+ }
182
+ } else if (data.type === GEOM_RECTANGLE) {
183
+ context.rect(shape.x, shape.y, shape.width, shape.height);
184
+ context.closePath();
185
+ } else if (data.type === GEOM_CIRCLE) {
186
+ context.arc(shape.x, shape.y, shape.radius, 0, 2 * Math.PI);
187
+ context.closePath();
188
+ } else if (data.type === GEOM_ELLIPSE) {
189
+ // ellipse code taken from: http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas
190
+ const w = shape.width * 2;
191
+ const h = shape.height * 2;
192
+ const x = shape.x - w / 2;
193
+ const y = shape.y - h / 2;
194
+ const kappa = 0.5522848;
195
+ const ox = (w / 2) * kappa; // control point offset horizontal
196
+ const oy = (h / 2) * kappa; // control point offset vertical
197
+ const xe = x + w; // x-end
198
+ const ye = y + h; // y-end
199
+ const xm = x + w / 2; // x-middle
200
+ const ym = y + h / 2; // y-middle
201
+ context.moveTo(x, ym);
202
+ context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y);
203
+ context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym);
204
+ context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye);
205
+ context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym);
206
+ context.closePath();
207
+ } else if (data.type === GEOM_ROUNDED_RECTANGLE) {
208
+ const rx = shape.x;
209
+ const ry = shape.y;
210
+ const width = shape.width;
211
+ const height = shape.height;
212
+ let radius = shape.radius;
213
+ const maxRadius = Math.min(width, height) / 2 | 0;
214
+ radius = radius > maxRadius ? maxRadius : radius;
215
+ context.moveTo(rx, ry + radius);
216
+ context.lineTo(rx, ry + height - radius);
217
+ context.quadraticCurveTo(rx, ry + height, rx + radius, ry + height);
218
+ context.lineTo(rx + width - radius, ry + height);
219
+ context.quadraticCurveTo(rx + width, ry + height, rx + width, ry + height - radius);
220
+ context.lineTo(rx + width, ry + radius);
221
+ context.quadraticCurveTo(rx + width, ry, rx + width - radius, ry);
222
+ context.lineTo(rx + radius, ry);
223
+ context.quadraticCurveTo(rx, ry, rx, ry + radius);
224
+ context.closePath();
225
+ }
226
+ }
227
+ }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * @author Andras Csizmadia <andras@vpmedia.hu>
3
+ * @author Richard Davey <rich@photonstorm.com>
4
+ * @author Mat Groves http://matgroves.com/ @Doormat23
5
+ * @copyright Copyright (c) 2018-present Richard Davey, Photon Storm Ltd., Andras Csizmadia <andras@vpmedia.hu> (www.vpmedia.hu)
6
+ */
7
+ import { renderGraphicsMask } from './graphics';
8
+
9
+ /**
10
+ *
11
+ * @param maskData
12
+ * @param renderSession
13
+ */
14
+ export function pushMask(maskData, renderSession) {
15
+ const context = renderSession.context;
16
+ context.save();
17
+ const cacheAlpha = maskData.alpha;
18
+ const transform = maskData.worldTransform;
19
+ const resolution = renderSession.resolution;
20
+ context.setTransform(
21
+ transform.a * resolution,
22
+ transform.b * resolution,
23
+ transform.c * resolution,
24
+ transform.d * resolution,
25
+ transform.tx * resolution,
26
+ transform.ty * resolution,
27
+ );
28
+ renderGraphicsMask(maskData, context);
29
+ context.clip();
30
+ maskData.worldAlpha = cacheAlpha;
31
+ }
32
+
33
+ /**
34
+ *
35
+ * @param renderSession
36
+ */
37
+ export function popMask(renderSession) {
38
+ renderSession.context.restore();
39
+ }
@@ -0,0 +1,121 @@
1
+ /**
2
+ * @author Andras Csizmadia <andras@vpmedia.hu>
3
+ * @author Richard Davey <rich@photonstorm.com>
4
+ * @author Mat Groves http://matgroves.com/ @Doormat23
5
+ * @copyright Copyright (c) 2018-present Richard Davey, Photon Storm Ltd., Andras Csizmadia <andras@vpmedia.hu> (www.vpmedia.hu)
6
+ */
7
+
8
+ /**
9
+ *
10
+ */
11
+ export function getPool() {
12
+ if (!window.PhaserRegistry) {
13
+ window.PhaserRegistry = {};
14
+ }
15
+ if (!window.PhaserRegistry.CANVAS_POOL) {
16
+ window.PhaserRegistry.CANVAS_POOL = [];
17
+ }
18
+ return window.PhaserRegistry.CANVAS_POOL;
19
+ }
20
+
21
+ /**
22
+ *
23
+ */
24
+ export function getFirst() {
25
+ const pool = getPool();
26
+ for (let i = 0; i < pool.length; i += 1) {
27
+ if (!pool[i].parent) {
28
+ return i;
29
+ }
30
+ }
31
+ return -1;
32
+ }
33
+
34
+ /**
35
+ *
36
+ * @param parent
37
+ */
38
+ export function remove(parent) {
39
+ const pool = getPool();
40
+ for (let i = 0; i < pool.length; i += 1) {
41
+ if (pool[i].parent === parent) {
42
+ pool[i].parent = null;
43
+ pool[i].canvas.width = 1;
44
+ pool[i].canvas.height = 1;
45
+ }
46
+ }
47
+ }
48
+
49
+ /**
50
+ *
51
+ * @param canvas
52
+ */
53
+ export function removeByCanvas(canvas) {
54
+ const pool = getPool();
55
+ for (let i = 0; i < pool.length; i += 1) {
56
+ if (pool[i].canvas === canvas) {
57
+ pool[i].parent = null;
58
+ pool[i].canvas.width = 1;
59
+ pool[i].canvas.height = 1;
60
+ }
61
+ }
62
+ }
63
+
64
+ /**
65
+ *
66
+ */
67
+ export function getTotal() {
68
+ const pool = getPool();
69
+ let c = 0;
70
+ for (let i = 0; i < pool.length; i += 1) {
71
+ if (pool[i].parent) {
72
+ c += 1;
73
+ }
74
+ }
75
+ return c;
76
+ }
77
+
78
+ /**
79
+ *
80
+ */
81
+ export function getFree() {
82
+ const pool = getPool();
83
+ let c = 0;
84
+ for (let i = 0; i < pool.length; i += 1) {
85
+ if (!pool[i].parent) {
86
+ c += 1;
87
+ }
88
+ }
89
+ return c;
90
+ }
91
+
92
+ /**
93
+ *
94
+ * @param parent
95
+ * @param width
96
+ * @param height
97
+ */
98
+ export function create(parent, width, height) {
99
+ if (parent === undefined) {
100
+ console.warn('Created CanvasPool element with undefined parent.');
101
+ }
102
+ const idx = getFirst();
103
+ const pool = getPool();
104
+ let canvas;
105
+ if (idx === -1) {
106
+ const container = {
107
+ parent,
108
+ canvas: document.createElement('canvas'),
109
+ };
110
+ pool.push(container);
111
+ canvas = container.canvas;
112
+ } else {
113
+ pool[idx].parent = parent;
114
+ canvas = pool[idx].canvas;
115
+ }
116
+ if (width !== undefined) {
117
+ canvas.width = width;
118
+ canvas.height = height;
119
+ }
120
+ return canvas;
121
+ }
@@ -0,0 +1,123 @@
1
+ /**
2
+ * @author Andras Csizmadia <andras@vpmedia.hu>
3
+ * @author Richard Davey <rich@photonstorm.com>
4
+ * @author Mat Groves http://matgroves.com/ @Doormat23
5
+ * @copyright Copyright (c) 2018-present Richard Davey, Photon Storm Ltd., Andras Csizmadia <andras@vpmedia.hu> (www.vpmedia.hu)
6
+ */
7
+ import { RENDER_CANVAS, SCALE_LINEAR, BLEND_NORMAL, BLEND_ADD, BLEND_MULTIPLY, BLEND_SCREEN, BLEND_OVERLAY, BLEND_DARKEN, BLEND_LIGHTEN, BLEND_COLOR_DODGE, BLEND_COLOR_BURN, BLEND_HARD_LIGHT, BLEND_SOFT_LIGHT, BLEND_DIFFERENCE, BLEND_EXCLUSION, BLEND_HUE, BLEND_SATURATION, BLEND_COLOR, BLEND_LUMINOSITY } from '../../core/const';
8
+ import { getSmoothingPrefix } from './util';
9
+ import { detectCapabilities } from './tinter';
10
+ import * as CanvasMaskManager from './masker';
11
+
12
+ export default class {
13
+
14
+ constructor(game) {
15
+ detectCapabilities();
16
+ this.type = RENDER_CANVAS;
17
+ this.resolution = game.config.resolution;
18
+ this.clearBeforeRender = game.config.clearBeforeRender;
19
+ this.transparent = game.config.transparent;
20
+ this.autoResize = false;
21
+ this.width = game.width * this.resolution;
22
+ this.height = game.height * this.resolution;
23
+ this.view = game.canvas;
24
+ this.context = this.view.getContext('2d', { alpha: this.transparent });
25
+ if (!this.context) {
26
+ throw new Error('Error creating Canvas 2D context.');
27
+ }
28
+ this.refresh = true;
29
+ this.count = 0;
30
+ this.renderSession = {
31
+ context: this.context,
32
+ maskManager: CanvasMaskManager,
33
+ scaleMode: null,
34
+ smoothProperty: getSmoothingPrefix(this.context),
35
+ roundPixels: false,
36
+ };
37
+ this.mapBlendModes();
38
+ this.resize(this.width, this.height);
39
+ window.PhaserRegistry.DEFAULT_RENDERER = this;
40
+ }
41
+
42
+ render(root) {
43
+ if (!this.context) {
44
+ return;
45
+ }
46
+ this.context.setTransform(1, 0, 0, 1, 0, 0);
47
+ this.context.globalAlpha = 1;
48
+ this.renderSession.currentBlendMode = 0;
49
+ this.renderSession.shakeX = 0;
50
+ this.renderSession.shakeY = 0;
51
+ this.context.globalCompositeOperation = 'source-over';
52
+ if (navigator.isCocoonJS && this.view.screencanvas) {
53
+ this.context.fillStyle = 'black';
54
+ this.context.clear();
55
+ }
56
+ if (this.clearBeforeRender) {
57
+ if (this.transparent) {
58
+ this.context.clearRect(0, 0, this.width, this.height);
59
+ } else if (root._bgColor) {
60
+ this.context.fillStyle = root._bgColor.rgba;
61
+ this.context.fillRect(0, 0, this.width, this.height);
62
+ }
63
+ }
64
+ this.renderDisplayObject(root);
65
+ }
66
+
67
+ destroy(removeView = true) {
68
+ if (removeView && this.view.parent) {
69
+ this.view.parent.removeChild(this.view);
70
+ }
71
+ this.view = null;
72
+ this.context = null;
73
+ this.renderSession = null;
74
+ window.PhaserRegistry.DEFAULT_RENDERER = null;
75
+ }
76
+
77
+ resize(width, height) {
78
+ this.width = width * this.resolution;
79
+ this.height = height * this.resolution;
80
+ this.view.width = this.width;
81
+ this.view.height = this.height;
82
+ if (this.autoResize) {
83
+ this.view.style.width = this.width / this.resolution + 'px';
84
+ this.view.style.height = this.height / this.resolution + 'px';
85
+ }
86
+ if (this.renderSession.smoothProperty) {
87
+ this.context[this.renderSession.smoothProperty] = (this.renderSession.scaleMode === SCALE_LINEAR);
88
+ }
89
+ }
90
+
91
+ renderDisplayObject(displayObject, context, matrix) {
92
+ this.renderSession.context = context || this.context;
93
+ this.renderSession.resolution = this.resolution;
94
+ displayObject.renderCanvas(this.renderSession, matrix);
95
+ }
96
+
97
+ mapBlendModes() {
98
+ if (window.PhaserRegistry.blendModesCanvas) {
99
+ return;
100
+ }
101
+ const b = [];
102
+ const useNew = window.PhaserRegistry.CAN_CANVAS_USE_MULTIPLY;
103
+ b[BLEND_NORMAL] = 'source-over';
104
+ b[BLEND_ADD] = 'lighter';
105
+ b[BLEND_MULTIPLY] = (useNew) ? 'multiply' : 'source-over';
106
+ b[BLEND_SCREEN] = (useNew) ? 'screen' : 'source-over';
107
+ b[BLEND_OVERLAY] = (useNew) ? 'overlay' : 'source-over';
108
+ b[BLEND_DARKEN] = (useNew) ? 'darken' : 'source-over';
109
+ b[BLEND_LIGHTEN] = (useNew) ? 'lighten' : 'source-over';
110
+ b[BLEND_COLOR_DODGE] = (useNew) ? 'color-dodge' : 'source-over';
111
+ b[BLEND_COLOR_BURN] = (useNew) ? 'color-burn' : 'source-over';
112
+ b[BLEND_HARD_LIGHT] = (useNew) ? 'hard-light' : 'source-over';
113
+ b[BLEND_SOFT_LIGHT] = (useNew) ? 'soft-light' : 'source-over';
114
+ b[BLEND_DIFFERENCE] = (useNew) ? 'difference' : 'source-over';
115
+ b[BLEND_EXCLUSION] = (useNew) ? 'exclusion' : 'source-over';
116
+ b[BLEND_HUE] = (useNew) ? 'hue' : 'source-over';
117
+ b[BLEND_SATURATION] = (useNew) ? 'saturation' : 'source-over';
118
+ b[BLEND_COLOR] = (useNew) ? 'color' : 'source-over';
119
+ b[BLEND_LUMINOSITY] = (useNew) ? 'luminosity' : 'source-over';
120
+ window.PhaserRegistry.blendModesCanvas = b;
121
+ }
122
+
123
+ }
@@ -0,0 +1,141 @@
1
+ /**
2
+ * @author Andras Csizmadia <andras@vpmedia.hu>
3
+ * @author Richard Davey <rich@photonstorm.com>
4
+ * @author Mat Groves http://matgroves.com/ @Doormat23
5
+ * @copyright Copyright (c) 2018-present Richard Davey, Photon Storm Ltd., Andras Csizmadia <andras@vpmedia.hu> (www.vpmedia.hu)
6
+ */
7
+ import CanvasBuffer from './buffer';
8
+ import { create, removeByCanvas } from './pool';
9
+ import { hex2rgb } from '../../util/math';
10
+
11
+ /**
12
+ *
13
+ * @param sprite
14
+ * @param color
15
+ */
16
+ export function getTintedTexture(sprite, color) {
17
+ const canvas = sprite.tintedTexture || create('CanvasTinter');
18
+ window.PhaserRegistry.CANVAS_TINT_METHOD(sprite.texture, color, canvas);
19
+ return canvas;
20
+ }
21
+
22
+ /**
23
+ *
24
+ * @param texture
25
+ * @param color
26
+ * @param canvas
27
+ */
28
+ export function tintWithMultiply(texture, color, canvas) {
29
+ const context = canvas.getContext('2d');
30
+ const crop = texture.crop;
31
+ if (canvas.width !== crop.width || canvas.height !== crop.height) {
32
+ canvas.width = crop.width;
33
+ canvas.height = crop.height;
34
+ }
35
+ context.clearRect(0, 0, crop.width, crop.height);
36
+ context.fillStyle = '#' + ('00000' + (color | 0).toString(16)).substr(-6);
37
+ context.fillRect(0, 0, crop.width, crop.height);
38
+ context.globalCompositeOperation = 'multiply';
39
+ context.drawImage(texture.baseTexture.source, crop.x, crop.y, crop.width, crop.height, 0, 0, crop.width, crop.height);
40
+ context.globalCompositeOperation = 'destination-atop';
41
+ context.drawImage(texture.baseTexture.source, crop.x, crop.y, crop.width, crop.height, 0, 0, crop.width, crop.height);
42
+ }
43
+
44
+ /**
45
+ *
46
+ * @param texture
47
+ * @param color
48
+ * @param canvas
49
+ */
50
+ export function tintWithPerPixel(texture, color, canvas) {
51
+ const context = canvas.getContext('2d');
52
+ const crop = texture.crop;
53
+ canvas.width = crop.width;
54
+ canvas.height = crop.height;
55
+ context.globalCompositeOperation = 'copy';
56
+ context.drawImage(texture.baseTexture.source, crop.x, crop.y, crop.width, crop.height, 0, 0, crop.width, crop.height);
57
+ const rgbValues = hex2rgb(color);
58
+ const r = rgbValues[0];
59
+ const g = rgbValues[1];
60
+ const b = rgbValues[2];
61
+ const pixelData = context.getImageData(0, 0, crop.width, crop.height);
62
+ const pixels = pixelData.data;
63
+ for (let i = 0; i < pixels.length; i += 4) {
64
+ pixels[i + 0] *= r;
65
+ pixels[i + 1] *= g;
66
+ pixels[i + 2] *= b;
67
+ const canHandleAlpha = window.PhaserRegistry.CAN_CANVAS_HANDLE_ALPHA;
68
+ if (!canHandleAlpha) {
69
+ const alpha = pixels[i + 3];
70
+ pixels[i + 0] /= 255 / alpha;
71
+ pixels[i + 1] /= 255 / alpha;
72
+ pixels[i + 2] /= 255 / alpha;
73
+ }
74
+ }
75
+ context.putImageData(pixelData, 0, 0);
76
+ }
77
+
78
+ /**
79
+ *
80
+ */
81
+ export function checkInverseAlpha() {
82
+ const canvas = new CanvasBuffer(2, 1);
83
+ canvas.context.fillStyle = 'rgba(10, 20, 30, 0.5)';
84
+ // Draw a single pixel
85
+ canvas.context.fillRect(0, 0, 1, 1);
86
+ // Get the color values
87
+ const s1 = canvas.context.getImageData(0, 0, 1, 1);
88
+ if (s1 === null) {
89
+ return false;
90
+ }
91
+ // Plot them to x2
92
+ canvas.context.putImageData(s1, 1, 0);
93
+ // Get those values
94
+ const s2 = canvas.context.getImageData(1, 0, 1, 1);
95
+ // Compare and return
96
+ return (s2.data[0] === s1.data[0] && s2.data[1] === s1.data[1] && s2.data[2] === s1.data[2] && s2.data[3] === s1.data[3]);
97
+ }
98
+
99
+ /**
100
+ *
101
+ */
102
+ export function canUseNewCanvasBlendModes() {
103
+ if (document === undefined) {
104
+ return false;
105
+ }
106
+ const pngHead = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAABAQMAAADD8p2OAAAAA1BMVEX/';
107
+ const pngEnd = 'AAAACklEQVQI12NgAAAAAgAB4iG8MwAAAABJRU5ErkJggg==';
108
+ const magenta = new Image();
109
+ magenta.src = pngHead + 'AP804Oa6' + pngEnd;
110
+ const yellow = new Image();
111
+ yellow.src = pngHead + '/wCKxvRF' + pngEnd;
112
+ const canvas = create('CanvasTinter', 6, 1);
113
+ const context = canvas.getContext('2d');
114
+ context.globalCompositeOperation = 'multiply';
115
+ context.drawImage(magenta, 0, 0);
116
+ context.drawImage(yellow, 2, 0);
117
+ if (!context.getImageData(2, 0, 1, 1)) {
118
+ return false;
119
+ }
120
+ const data = context.getImageData(2, 0, 1, 1).data;
121
+ removeByCanvas(canvas);
122
+ return (data[0] === 255 && data[1] === 0 && data[2] === 0);
123
+ }
124
+
125
+ /**
126
+ *
127
+ */
128
+ export function detectCapabilities() {
129
+ if (!window.PhaserRegistry) {
130
+ window.PhaserRegistry = {};
131
+ }
132
+ if (!window.PhaserRegistry.CAN_CANVAS_HANDLE_ALPHA) {
133
+ window.PhaserRegistry.CAN_CANVAS_HANDLE_ALPHA = checkInverseAlpha();
134
+ }
135
+ if (!window.PhaserRegistry.CAN_CANVAS_USE_MULTIPLY) {
136
+ window.PhaserRegistry.CAN_CANVAS_USE_MULTIPLY = canUseNewCanvasBlendModes();
137
+ }
138
+ if (!window.PhaserRegistry.CANVAS_TINT_METHOD) {
139
+ window.PhaserRegistry.CANVAS_TINT_METHOD = window.PhaserRegistry.CAN_CANVAS_USE_MULTIPLY ? tintWithMultiply : tintWithPerPixel;
140
+ }
141
+ }