melonjs 10.7.0 → 10.9.0
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/dist/melonjs.js +1488 -666
- package/dist/melonjs.min.js +4 -4
- package/dist/melonjs.module.d.ts +929 -202
- package/dist/melonjs.module.js +1575 -777
- package/package.json +9 -9
- package/src/camera/camera2d.js +1 -1
- package/src/entity/entity.js +6 -7
- package/src/geometries/ellipse.js +10 -11
- package/src/geometries/line.js +3 -3
- package/src/geometries/path2d.js +319 -0
- package/src/geometries/poly.js +11 -11
- package/src/geometries/rectangle.js +15 -15
- package/src/geometries/roundrect.js +164 -0
- package/src/index.js +5 -1
- package/src/input/gamepad.js +2 -2
- package/src/input/pointerevent.js +1 -1
- package/src/lang/deprecated.js +1 -1
- package/src/level/tiled/TMXLayer.js +1 -1
- package/src/level/tiled/TMXObject.js +9 -12
- package/src/level/tiled/TMXTileMap.js +23 -4
- package/src/level/tiled/renderer/TMXHexagonalRenderer.js +1 -1
- package/src/level/tiled/renderer/TMXIsometricRenderer.js +1 -1
- package/src/level/tiled/renderer/TMXOrthogonalRenderer.js +1 -1
- package/src/level/tiled/renderer/TMXRenderer.js +1 -1
- package/src/level/tiled/renderer/TMXStaggeredRenderer.js +1 -1
- package/src/loader/loader.js +4 -4
- package/src/loader/loadingscreen.js +1 -1
- package/src/math/color.js +1 -1
- package/src/math/matrix2.js +1 -1
- package/src/math/matrix3.js +1 -1
- package/src/math/observable_vector2.js +1 -1
- package/src/math/observable_vector3.js +1 -1
- package/src/math/vector2.js +1 -1
- package/src/math/vector3.js +1 -1
- package/src/particles/emitter.js +23 -14
- package/src/particles/particle.js +3 -2
- package/src/physics/body.js +67 -51
- package/src/physics/bounds.js +8 -9
- package/src/physics/world.js +1 -1
- package/src/polyfill/index.js +1 -0
- package/src/polyfill/roundrect.js +235 -0
- package/src/renderable/collectable.js +9 -2
- package/src/renderable/colorlayer.js +1 -1
- package/src/renderable/container.js +1 -1
- package/src/renderable/imagelayer.js +1 -1
- package/src/renderable/renderable.js +2 -2
- package/src/renderable/sprite.js +2 -3
- package/src/renderable/trigger.js +10 -4
- package/src/state/stage.js +1 -1
- package/src/state/state.js +1 -1
- package/src/system/device.js +10 -8
- package/src/system/pooling.js +156 -149
- package/src/text/bitmaptext.js +1 -1
- package/src/text/text.js +1 -1
- package/src/utils/utils.js +2 -2
- package/src/video/canvas/canvas_renderer.js +83 -39
- package/src/video/renderer.js +36 -16
- package/src/video/texture.js +1 -1
- package/src/video/webgl/glshader.js +29 -193
- package/src/video/webgl/utils/attributes.js +16 -0
- package/src/video/webgl/utils/precision.js +11 -0
- package/src/video/webgl/utils/program.js +58 -0
- package/src/video/webgl/utils/string.js +16 -0
- package/src/video/webgl/utils/uniforms.js +87 -0
- package/src/video/webgl/webgl_compositor.js +1 -14
- package/src/video/webgl/webgl_renderer.js +124 -182
package/src/system/pooling.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
var objectClass = {};
|
|
2
|
-
var instance_counter = 0;
|
|
3
|
-
|
|
4
1
|
/**
|
|
2
|
+
* @classdesc
|
|
5
3
|
* This object is used for object pooling - a technique that might speed up your game if used properly.<br>
|
|
6
4
|
* If some of your classes will be instantiated and removed a lot at a time, it is a
|
|
7
5
|
* good idea to add the class to this object pool. A separate pool for that class
|
|
@@ -12,172 +10,181 @@ var instance_counter = 0;
|
|
|
12
10
|
* which means, that on level loading the engine will try to instantiate every object
|
|
13
11
|
* found in the map, based on the user defined name in each Object Properties<br>
|
|
14
12
|
* <img src="images/object_properties.png"/><br>
|
|
15
|
-
* @
|
|
13
|
+
* @see {@link pool} a default global instance of ObjectPool
|
|
16
14
|
*/
|
|
15
|
+
class ObjectPool {
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
17
|
+
constructor() {
|
|
18
|
+
this.objectClass = {};
|
|
19
|
+
this.instance_counter = 0;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* register an object to the pool. <br>
|
|
24
|
+
* Pooling must be set to true if more than one such objects will be created. <br>
|
|
25
|
+
* (Note: for an object to be poolable, it must implements a `onResetEvent` method)
|
|
26
|
+
* @param {string} className as defined in the Name field of the Object Properties (in Tiled)
|
|
27
|
+
* @param {object} classObj corresponding Class to be instantiated
|
|
28
|
+
* @param {boolean} [recycling=false] enables object recycling for the specified class
|
|
29
|
+
* @example
|
|
30
|
+
* // implement CherryEntity
|
|
31
|
+
* class CherryEntity extends Spritesheet {
|
|
32
|
+
* onResetEvent() {
|
|
33
|
+
* // reset object mutable properties
|
|
34
|
+
* this.lifeBar = 100;
|
|
35
|
+
* }
|
|
36
|
+
* };
|
|
37
|
+
* // add our users defined entities in the object pool and enable object recycling
|
|
38
|
+
* me.pool.register("cherryentity", CherryEntity, true);
|
|
39
|
+
*/
|
|
40
|
+
register(className, classObj, recycling = false) {
|
|
41
|
+
if (typeof (classObj) !== "undefined") {
|
|
42
|
+
this.objectClass[className] = {
|
|
43
|
+
"class" : classObj,
|
|
44
|
+
"pool" : (recycling ? [] : undefined)
|
|
45
|
+
};
|
|
46
|
+
} else {
|
|
47
|
+
throw new Error("Cannot register object '" + className + "', invalid class");
|
|
48
|
+
}
|
|
45
49
|
}
|
|
46
|
-
};
|
|
47
50
|
|
|
48
|
-
/**
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
obj;
|
|
51
|
+
/**
|
|
52
|
+
* Pull a new instance of the requested object (if added into the object pool)
|
|
53
|
+
* @param {string} name as used in {@link pool.register}
|
|
54
|
+
* @param {object} [...arguments] arguments to be passed when instantiating/reinitializing the object
|
|
55
|
+
* @returns {object} the instance of the requested object
|
|
56
|
+
* @example
|
|
57
|
+
* me.pool.register("bullet", BulletEntity, true);
|
|
58
|
+
* me.pool.register("enemy", EnemyEntity, true);
|
|
59
|
+
* // ...
|
|
60
|
+
* // when we need to manually create a new bullet:
|
|
61
|
+
* var bullet = me.pool.pull("bullet", x, y, direction);
|
|
62
|
+
* // ...
|
|
63
|
+
* // params aren't a fixed number
|
|
64
|
+
* // when we need new enemy we can add more params, that the object construct requires:
|
|
65
|
+
* var enemy = me.pool.pull("enemy", x, y, direction, speed, power, life);
|
|
66
|
+
* // ...
|
|
67
|
+
* // when we want to destroy existing object, the remove
|
|
68
|
+
* // function will ensure the object can then be reallocated later
|
|
69
|
+
* me.game.world.removeChild(enemy);
|
|
70
|
+
* me.game.world.removeChild(bullet);
|
|
71
|
+
*/
|
|
72
|
+
pull(name) {
|
|
73
|
+
var args = new Array(arguments.length);
|
|
74
|
+
for (var i = 0; i < arguments.length; i++) {
|
|
75
|
+
args[i] = arguments[i];
|
|
76
|
+
}
|
|
77
|
+
var className = this.objectClass[name];
|
|
78
|
+
if (className) {
|
|
79
|
+
var proto = className["class"],
|
|
80
|
+
poolArray = className.pool,
|
|
81
|
+
obj;
|
|
80
82
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
83
|
+
if (poolArray && ((obj = poolArray.pop()))) {
|
|
84
|
+
// pull an existing instance from the pool
|
|
85
|
+
args.shift();
|
|
86
|
+
// call the object onResetEvent function if defined
|
|
87
|
+
if (typeof(obj.onResetEvent) === "function") {
|
|
88
|
+
obj.onResetEvent.apply(obj, args);
|
|
89
|
+
}
|
|
90
|
+
this.instance_counter--;
|
|
87
91
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
obj.className = name;
|
|
92
|
+
else {
|
|
93
|
+
// create a new instance
|
|
94
|
+
args[0] = proto;
|
|
95
|
+
obj = new (proto.bind.apply(proto, args))();
|
|
96
|
+
if (poolArray) {
|
|
97
|
+
obj.className = name;
|
|
98
|
+
}
|
|
96
99
|
}
|
|
100
|
+
return obj;
|
|
97
101
|
}
|
|
98
|
-
|
|
102
|
+
throw new Error("Cannot instantiate object of type '" + name + "'");
|
|
99
103
|
}
|
|
100
|
-
throw new Error("Cannot instantiate object of type '" + name + "'");
|
|
101
|
-
};
|
|
102
104
|
|
|
103
|
-
/**
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
105
|
+
/**
|
|
106
|
+
* purge the object pool from any inactive object <br>
|
|
107
|
+
* Object pooling must be enabled for this function to work<br>
|
|
108
|
+
* note: this will trigger the garbage collector
|
|
109
|
+
*/
|
|
110
|
+
purge() {
|
|
111
|
+
for (var className in this.objectClass) {
|
|
112
|
+
if (this.objectClass[className]) {
|
|
113
|
+
this.objectClass[className].pool = [];
|
|
114
|
+
}
|
|
113
115
|
}
|
|
116
|
+
this.instance_counter = 0;
|
|
114
117
|
}
|
|
115
|
-
instance_counter = 0;
|
|
116
|
-
};
|
|
117
118
|
|
|
118
|
-
/**
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
119
|
+
/**
|
|
120
|
+
* Push back an object instance into the object pool <br>
|
|
121
|
+
* Object pooling for the object class must be enabled,
|
|
122
|
+
* and object must have been instantiated using {@link pool#pull},
|
|
123
|
+
* otherwise this function won't work
|
|
124
|
+
* @throws will throw an error if the object cannot be recycled
|
|
125
|
+
* @param {object} obj instance to be recycled
|
|
126
|
+
* @param {boolean} [throwOnError=true] throw an exception if the object cannot be recycled
|
|
127
|
+
* @returns {boolean} true if the object was successfully recycled in the object pool
|
|
128
|
+
*/
|
|
129
|
+
push(obj, throwOnError = true) {
|
|
130
|
+
if (!this.poolable(obj)) {
|
|
131
|
+
if (throwOnError === true ) {
|
|
132
|
+
throw new Error("me.pool: object " + obj + " cannot be recycled");
|
|
133
|
+
} else {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
135
136
|
}
|
|
136
|
-
}
|
|
137
137
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
138
|
+
// store back the object instance for later recycling
|
|
139
|
+
this.objectClass[obj.className].pool.push(obj);
|
|
140
|
+
this.instance_counter++;
|
|
141
141
|
|
|
142
|
-
|
|
143
|
-
}
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
144
|
|
|
145
|
-
/**
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
};
|
|
145
|
+
/**
|
|
146
|
+
* Check if an object with the provided name is registered
|
|
147
|
+
* @param {string} name of the registered object class
|
|
148
|
+
* @returns {boolean} true if the classname is registered
|
|
149
|
+
*/
|
|
150
|
+
exists(name) {
|
|
151
|
+
return name in this.objectClass;
|
|
152
|
+
};
|
|
154
153
|
|
|
155
|
-
/**
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
154
|
+
/**
|
|
155
|
+
* Check if an object is poolable
|
|
156
|
+
* (was properly registered with the recycling feature enable)
|
|
157
|
+
* @see register
|
|
158
|
+
* @param {object} obj object to be checked
|
|
159
|
+
* @returns {boolean} true if the object is poolable
|
|
160
|
+
* @example
|
|
161
|
+
* if (!me.pool.poolable(myCherryEntity)) {
|
|
162
|
+
* // object was not properly registered
|
|
163
|
+
* }
|
|
164
|
+
*/
|
|
165
|
+
poolable(obj) {
|
|
166
|
+
var className = obj.className;
|
|
167
|
+
return (typeof className !== "undefined") &&
|
|
168
|
+
(typeof obj.onResetEvent === "function") &&
|
|
169
|
+
(className in this.objectClass) &&
|
|
170
|
+
(this.objectClass[className].pool !== "undefined");
|
|
171
|
+
|
|
172
|
+
}
|
|
173
173
|
|
|
174
|
+
/**
|
|
175
|
+
* returns the amount of object instance currently in the pool
|
|
176
|
+
* @returns {number} amount of object instance
|
|
177
|
+
*/
|
|
178
|
+
getInstanceCount() {
|
|
179
|
+
return this.instance_counter;
|
|
180
|
+
}
|
|
174
181
|
};
|
|
175
182
|
|
|
176
183
|
/**
|
|
177
|
-
*
|
|
178
|
-
* @
|
|
179
|
-
* @
|
|
184
|
+
* a default global object pool instance
|
|
185
|
+
* @public
|
|
186
|
+
* @type {ObjectPool}
|
|
180
187
|
*/
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
188
|
+
var pool = new ObjectPool();
|
|
189
|
+
|
|
190
|
+
export default pool;
|
package/src/text/bitmaptext.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import Color from "./../math/color.js";
|
|
2
2
|
import * as stringUtil from "./../utils/string.js";
|
|
3
|
-
import
|
|
3
|
+
import pool from "./../system/pooling.js";
|
|
4
4
|
import loader from "./../loader/loader.js";
|
|
5
5
|
import Renderable from "./../renderable/renderable.js";
|
|
6
6
|
import TextMetrics from "./textmetrics.js";
|
package/src/text/text.js
CHANGED
|
@@ -2,7 +2,7 @@ import Color from "./../math/color.js";
|
|
|
2
2
|
import WebGLRenderer from "./../video/webgl/webgl_renderer.js";
|
|
3
3
|
import { renderer as globalRenderer, createCanvas } from "./../video/video.js";
|
|
4
4
|
import { trimRight } from "./../utils/string.js";
|
|
5
|
-
import
|
|
5
|
+
import pool from "./../system/pooling.js";
|
|
6
6
|
import Renderable from "./../renderable/renderable.js";
|
|
7
7
|
import { nextPowerOfTwo } from "./../math/math.js";
|
|
8
8
|
import setContextStyle from "./textstyle.js";
|
package/src/utils/utils.js
CHANGED
|
@@ -120,14 +120,14 @@ var utils = {
|
|
|
120
120
|
// never cache if a url is passed as parameter
|
|
121
121
|
var index = url.indexOf("#");
|
|
122
122
|
if (index !== -1) {
|
|
123
|
-
url = url.
|
|
123
|
+
url = url.slice(index, url.length);
|
|
124
124
|
} else {
|
|
125
125
|
return hash;
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
// parse the url
|
|
130
|
-
url.
|
|
130
|
+
url.slice(1).split("&").filter(function (value) {
|
|
131
131
|
return (value !== "");
|
|
132
132
|
}).forEach(function (value) {
|
|
133
133
|
var kv = value.split("=");
|
|
@@ -2,6 +2,7 @@ import Color from "./../../math/color.js";
|
|
|
2
2
|
import Renderer from "./../renderer.js";
|
|
3
3
|
import TextureCache from "./../texture_cache.js";
|
|
4
4
|
import Ellipse from "./../../geometries/ellipse.js";
|
|
5
|
+
import RoundRect from "./../../geometries/roundrect.js";
|
|
5
6
|
import { createCanvas } from "./../video.js";
|
|
6
7
|
|
|
7
8
|
|
|
@@ -65,7 +66,6 @@ class CanvasRenderer extends Renderer {
|
|
|
65
66
|
this.getScreenCanvas().addEventListener("contextrestored", () => {
|
|
66
67
|
this.isContextValid = true;
|
|
67
68
|
event.emit(event.ONCONTEXT_RESTORED, this);
|
|
68
|
-
me.game.repaint();
|
|
69
69
|
}, false );
|
|
70
70
|
}
|
|
71
71
|
|
|
@@ -190,7 +190,7 @@ class CanvasRenderer extends Renderer {
|
|
|
190
190
|
* @param {number} height The rectangle's height.
|
|
191
191
|
*/
|
|
192
192
|
clearRect(x, y, width, height) {
|
|
193
|
-
this.
|
|
193
|
+
this.getContext().clearRect(x, y, width, height);
|
|
194
194
|
}
|
|
195
195
|
|
|
196
196
|
/**
|
|
@@ -209,7 +209,7 @@ class CanvasRenderer extends Renderer {
|
|
|
209
209
|
* var basic = renderer.createPattern(image, "no-repeat");
|
|
210
210
|
*/
|
|
211
211
|
createPattern(image, repeat) {
|
|
212
|
-
return this.
|
|
212
|
+
return this.getContext().createPattern(image, repeat);
|
|
213
213
|
}
|
|
214
214
|
|
|
215
215
|
/**
|
|
@@ -235,10 +235,11 @@ class CanvasRenderer extends Renderer {
|
|
|
235
235
|
* renderer.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
|
|
236
236
|
*/
|
|
237
237
|
drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh) {
|
|
238
|
-
if (this.
|
|
238
|
+
if (this.getGlobalAlpha() < 1 / 255) {
|
|
239
239
|
// Fast path: don't draw fully transparent
|
|
240
240
|
return;
|
|
241
241
|
}
|
|
242
|
+
var context = this.getContext();
|
|
242
243
|
|
|
243
244
|
if (typeof sw === "undefined") {
|
|
244
245
|
sw = dw = image.width;
|
|
@@ -272,7 +273,7 @@ class CanvasRenderer extends Renderer {
|
|
|
272
273
|
// get a tinted version of this image from the texture cache
|
|
273
274
|
source = this.cache.tint(image, this.currentTint.toRGB());
|
|
274
275
|
}
|
|
275
|
-
|
|
276
|
+
context.drawImage(source, sx, sy, sw, sh, dx, dy, dw, dh);
|
|
276
277
|
}
|
|
277
278
|
|
|
278
279
|
/**
|
|
@@ -288,14 +289,15 @@ class CanvasRenderer extends Renderer {
|
|
|
288
289
|
* @see CanvasRenderer#createPattern
|
|
289
290
|
*/
|
|
290
291
|
drawPattern(pattern, x, y, width, height) {
|
|
291
|
-
if (this.
|
|
292
|
+
if (this.getGlobalAlpha() < 1 / 255) {
|
|
292
293
|
// Fast path: don't draw fully transparent
|
|
293
294
|
return;
|
|
294
295
|
}
|
|
295
|
-
var
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
296
|
+
var context = this.getContext();
|
|
297
|
+
var fillStyle = context.fillStyle;
|
|
298
|
+
context.fillStyle = pattern;
|
|
299
|
+
context.fillRect(x, y, width, height);
|
|
300
|
+
context.fillStyle = fillStyle;
|
|
299
301
|
}
|
|
300
302
|
|
|
301
303
|
/**
|
|
@@ -312,12 +314,12 @@ class CanvasRenderer extends Renderer {
|
|
|
312
314
|
* @param {boolean} [fill=false] also fill the shape with the current color if true
|
|
313
315
|
*/
|
|
314
316
|
strokeArc(x, y, radius, start, end, antiClockwise, fill = false) {
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
if (context.globalAlpha < 1 / 255) {
|
|
317
|
+
if (this.getGlobalAlpha() < 1 / 255) {
|
|
318
318
|
// Fast path: don't draw fully transparent
|
|
319
319
|
return;
|
|
320
320
|
}
|
|
321
|
+
var context = this.getContext();
|
|
322
|
+
|
|
321
323
|
context.translate(x, y);
|
|
322
324
|
context.beginPath();
|
|
323
325
|
context.arc(0, 0, radius, start, end, antiClockwise || false);
|
|
@@ -353,12 +355,11 @@ class CanvasRenderer extends Renderer {
|
|
|
353
355
|
* @param {boolean} [fill=false] also fill the shape with the current color if true
|
|
354
356
|
*/
|
|
355
357
|
strokeEllipse(x, y, w, h, fill = false) {
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
if (context.globalAlpha < 1 / 255) {
|
|
358
|
+
if (this.getGlobalAlpha() < 1 / 255) {
|
|
359
359
|
// Fast path: don't draw fully transparent
|
|
360
360
|
return;
|
|
361
361
|
}
|
|
362
|
+
var context = this.getContext();
|
|
362
363
|
|
|
363
364
|
var hw = w,
|
|
364
365
|
hh = h,
|
|
@@ -409,9 +410,7 @@ class CanvasRenderer extends Renderer {
|
|
|
409
410
|
* @param {number} endY the end y coordinate
|
|
410
411
|
*/
|
|
411
412
|
strokeLine(startX, startY, endX, endY) {
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
if (context < 1 / 255) {
|
|
413
|
+
if (this.getGlobalAlpha() < 1 / 255) {
|
|
415
414
|
// Fast path: don't draw fully transparent
|
|
416
415
|
return;
|
|
417
416
|
}
|
|
@@ -445,12 +444,11 @@ class CanvasRenderer extends Renderer {
|
|
|
445
444
|
* @param {boolean} [fill=false] also fill the shape with the current color if true
|
|
446
445
|
*/
|
|
447
446
|
strokePolygon(poly, fill = false) {
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
if (context.globalAlpha < 1 / 255) {
|
|
447
|
+
if (this.getGlobalAlpha() < 1 / 255) {
|
|
451
448
|
// Fast path: don't draw fully transparent
|
|
452
449
|
return;
|
|
453
450
|
}
|
|
451
|
+
var context = this.getContext();
|
|
454
452
|
|
|
455
453
|
this.translate(poly.pos.x, poly.pos.y);
|
|
456
454
|
context.beginPath();
|
|
@@ -489,15 +487,13 @@ class CanvasRenderer extends Renderer {
|
|
|
489
487
|
* @param {boolean} [fill=false] also fill the shape with the current color if true
|
|
490
488
|
*/
|
|
491
489
|
strokeRect(x, y, width, height, fill = false) {
|
|
492
|
-
if (
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
if (this.backBufferContext2D.globalAlpha < 1 / 255) {
|
|
496
|
-
// Fast path: don't draw fully transparent
|
|
497
|
-
return;
|
|
498
|
-
}
|
|
499
|
-
this.backBufferContext2D.strokeRect(x, y, width, height);
|
|
490
|
+
if (this.getGlobalAlpha() < 1 / 255) {
|
|
491
|
+
// Fast path: don't draw fully transparent
|
|
492
|
+
return;
|
|
500
493
|
}
|
|
494
|
+
var context = this.getContext();
|
|
495
|
+
|
|
496
|
+
context[fill === true ? "fillRect" : "strokeRect"](x, y, width, height);
|
|
501
497
|
}
|
|
502
498
|
|
|
503
499
|
/**
|
|
@@ -511,11 +507,46 @@ class CanvasRenderer extends Renderer {
|
|
|
511
507
|
* @param {number} height
|
|
512
508
|
*/
|
|
513
509
|
fillRect(x, y, width, height) {
|
|
514
|
-
|
|
510
|
+
this.strokeRect(x, y, width, height, true);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/**
|
|
514
|
+
* Stroke a rounded rectangle at the specified coordinates
|
|
515
|
+
* @name strokeRoundRect
|
|
516
|
+
* @memberof CanvasRenderer.prototype
|
|
517
|
+
* @function
|
|
518
|
+
* @param {number} x
|
|
519
|
+
* @param {number} y
|
|
520
|
+
* @param {number} width
|
|
521
|
+
* @param {number} height
|
|
522
|
+
* @param {number} radius
|
|
523
|
+
* @param {boolean} [fill=false] also fill the shape with the current color if true
|
|
524
|
+
*/
|
|
525
|
+
strokeRoundRect(x, y, width, height, radius, fill = false) {
|
|
526
|
+
if (this.getGlobalAlpha() < 1 / 255) {
|
|
515
527
|
// Fast path: don't draw fully transparent
|
|
516
528
|
return;
|
|
517
529
|
}
|
|
518
|
-
this.
|
|
530
|
+
var context = this.getContext();
|
|
531
|
+
|
|
532
|
+
context.beginPath();
|
|
533
|
+
context.roundRect(x, y, width, height, radius);
|
|
534
|
+
context[fill === true ? "fill" : "stroke"]();
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
/**
|
|
538
|
+
* Draw a rounded filled rectangle at the specified coordinates
|
|
539
|
+
* @name fillRoundRect
|
|
540
|
+
* @memberof CanvasRenderer.prototype
|
|
541
|
+
* @function
|
|
542
|
+
* @param {number} x
|
|
543
|
+
* @param {number} y
|
|
544
|
+
* @param {number} width
|
|
545
|
+
* @param {number} height
|
|
546
|
+
* @param {number} radius
|
|
547
|
+
*/
|
|
548
|
+
fillRoundRect(x, y, width, height, radius) {
|
|
549
|
+
this.strokeRoundRect(x, y, width, height, radius, true);
|
|
519
550
|
}
|
|
520
551
|
|
|
521
552
|
|
|
@@ -557,7 +588,7 @@ class CanvasRenderer extends Renderer {
|
|
|
557
588
|
*/
|
|
558
589
|
restore() {
|
|
559
590
|
this.backBufferContext2D.restore();
|
|
560
|
-
this.currentColor.glArray[3] = this.
|
|
591
|
+
this.currentColor.glArray[3] = this.getGlobalAlpha();
|
|
561
592
|
this.currentScissor[0] = 0;
|
|
562
593
|
this.currentScissor[1] = 0;
|
|
563
594
|
this.currentScissor[2] = this.backBufferCanvas.width;
|
|
@@ -605,7 +636,7 @@ class CanvasRenderer extends Renderer {
|
|
|
605
636
|
}
|
|
606
637
|
|
|
607
638
|
/**
|
|
608
|
-
* Set the global alpha
|
|
639
|
+
* Set the global alpha
|
|
609
640
|
* @name setGlobalAlpha
|
|
610
641
|
* @memberof CanvasRenderer.prototype
|
|
611
642
|
* @function
|
|
@@ -615,6 +646,17 @@ class CanvasRenderer extends Renderer {
|
|
|
615
646
|
this.backBufferContext2D.globalAlpha = this.currentColor.glArray[3] = alpha;
|
|
616
647
|
}
|
|
617
648
|
|
|
649
|
+
/**
|
|
650
|
+
* Return the global alpha
|
|
651
|
+
* @name getGlobalAlpha
|
|
652
|
+
* @memberof CanvasRenderer.prototype
|
|
653
|
+
* @function
|
|
654
|
+
* @returns {number} global alpha value
|
|
655
|
+
*/
|
|
656
|
+
getGlobalAlpha() {
|
|
657
|
+
return this.backBufferContext2D.globalAlpha;
|
|
658
|
+
}
|
|
659
|
+
|
|
618
660
|
/**
|
|
619
661
|
* Set the line width on the context
|
|
620
662
|
* @name setLineWidth
|
|
@@ -721,14 +763,16 @@ class CanvasRenderer extends Renderer {
|
|
|
721
763
|
* @name setMask
|
|
722
764
|
* @memberof CanvasRenderer.prototype
|
|
723
765
|
* @function
|
|
724
|
-
* @param {Rect|Polygon|Line|Ellipse} [mask] the shape defining the mask to be applied
|
|
766
|
+
* @param {Rect|RoundRect|Polygon|Line|Ellipse} [mask] the shape defining the mask to be applied
|
|
725
767
|
*/
|
|
726
768
|
setMask(mask) {
|
|
727
|
-
var context = this.
|
|
769
|
+
var context = this.getContext();
|
|
728
770
|
var _x = mask.pos.x, _y = mask.pos.y;
|
|
729
771
|
|
|
730
772
|
context.save();
|
|
731
773
|
|
|
774
|
+
context.beginPath();
|
|
775
|
+
|
|
732
776
|
// https://github.com/melonjs/melonJS/issues/648
|
|
733
777
|
if (mask instanceof Ellipse) {
|
|
734
778
|
var hw = mask.radiusV.x,
|
|
@@ -745,14 +789,14 @@ class CanvasRenderer extends Renderer {
|
|
|
745
789
|
ymin = _y - ymagic,
|
|
746
790
|
ymax = _y + ymagic;
|
|
747
791
|
|
|
748
|
-
context.beginPath();
|
|
749
792
|
context.moveTo(_x, ty);
|
|
750
793
|
context.bezierCurveTo(xmax, ty, rx, ymin, rx, _y);
|
|
751
794
|
context.bezierCurveTo(rx, ymax, xmax, by, _x, by);
|
|
752
795
|
context.bezierCurveTo(xmin, by, lx, ymax, lx, _y);
|
|
753
796
|
context.bezierCurveTo(lx, ymin, xmin, ty, _x, ty);
|
|
797
|
+
} else if (mask instanceof RoundRect) {
|
|
798
|
+
context.roundRect(_x, _y, mask.width, mask.height, mask.radius);
|
|
754
799
|
} else {
|
|
755
|
-
context.beginPath();
|
|
756
800
|
context.moveTo(_x + mask.points[0].x, _y + mask.points[0].y);
|
|
757
801
|
var point;
|
|
758
802
|
for (var i = 1; i < mask.points.length; i++) {
|
|
@@ -772,7 +816,7 @@ class CanvasRenderer extends Renderer {
|
|
|
772
816
|
* @function
|
|
773
817
|
*/
|
|
774
818
|
clearMask() {
|
|
775
|
-
this.
|
|
819
|
+
this.getContext().restore();
|
|
776
820
|
}
|
|
777
821
|
|
|
778
822
|
};
|