-
Notifications
You must be signed in to change notification settings - Fork 0
/
p5.play.js
4345 lines (3770 loc) · 117 KB
/
p5.play.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
45
46
47
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
p5.play
by Paolo Pedercini/molleindustria, 2015
http://molleindustria.org/
*/
(function(root, factory) {
if (typeof define === 'function' && define.amd)
define('p5.play', ['p5'], function(p5) { (factory(p5)); });
else if (typeof exports === 'object')
factory(require('../p5'));
else
factory(root.p5);
}(this, function(p5) {
/**
* p5.play is a library for p5.js to facilitate the creation of games and gamelike
* projects.
*
* It provides a flexible Sprite class to manage visual objects in 2D space
* and features such as animation support, basic collision detection
* and resolution, mouse and keyboard interactions, and a virtual camera.
*
* p5.play is not a box2D-derived physics engine, it doesn't use events, and it's
* designed to be understood and possibly modified by intermediate programmers.
*
* See the examples folder for more info on how to use this library.
*
* @module p5.play
* @submodule p5.play
* @for p5.play
* @main
*/
// =============================================================================
// initialization
// =============================================================================
// This is the new way to initialize custom p5 properties for any p5 instance.
// The goal is to migrate lazy P5 properties over to this method.
// @see https://github.com/molleindustria/p5.play/issues/46
p5.prototype.registerMethod('init', function p5PlayInit() {
/**
* The sketch camera automatically created at the beginning of a sketch.
* A camera facilitates scrolling and zooming for scenes extending beyond
* the canvas. A camera has a position, a zoom factor, and the mouse
* coordinates relative to the view.
*
* In p5.js terms the camera wraps the whole drawing cycle in a
* transformation matrix but it can be disabled anytime during the draw
* cycle, for example to draw interface elements in an absolute position.
*
* @property camera
* @type {camera}
*/
this.camera = new Camera(this, 0, 0, 1);
this.camera.init = false;
});
// This provides a way for us to lazily define properties that
// are global to p5 instances.
//
// Note that this isn't just an optimization: p5 currently provides no
// way for add-ons to be notified when new p5 instances are created, so
// lazily creating these properties is the *only* mechanism available
// to us. For more information, see:
//
// https://github.com/processing/p5.js/issues/1263
function defineLazyP5Property(name, getter) {
Object.defineProperty(p5.prototype, name, {
configurable: true,
enumerable: true,
get: function() {
var context = (this instanceof p5 && !this._isGlobal) ? this : window;
if (typeof(context._p5PlayProperties) === 'undefined') {
context._p5PlayProperties = {};
}
if (!(name in context._p5PlayProperties)) {
context._p5PlayProperties[name] = getter.call(context);
}
return context._p5PlayProperties[name];
}
});
}
// This returns a factory function, suitable for passing to
// defineLazyP5Property, that returns a subclass of the given
// constructor that is always bound to a particular p5 instance.
function boundConstructorFactory(constructor) {
if (typeof(constructor) !== 'function')
throw new Error('constructor must be a function');
return function createBoundConstructor() {
var pInst = this;
function F() {
var args = Array.prototype.slice.call(arguments);
return constructor.apply(this, [pInst].concat(args));
}
F.prototype = constructor.prototype;
return F;
};
}
// This is a utility that makes it easy to define convenient aliases to
// pre-bound p5 instance methods.
//
// For example:
//
// var pInstBind = createPInstBinder(pInst);
//
// var createVector = pInstBind('createVector');
// var loadImage = pInstBind('loadImage');
//
// The above will create functions createVector and loadImage, which can be
// used similar to p5 global mode--however, they're bound to specific p5
// instances, and can thus be used outside of global mode.
function createPInstBinder(pInst) {
return function pInstBind(methodName) {
var method = pInst[methodName];
if (typeof(method) !== 'function')
throw new Error('"' + methodName + '" is not a p5 method');
return method.bind(pInst);
};
}
// These are utility p5 functions that don't depend on p5 instance state in
// order to work properly, so we'll go ahead and make them easy to
// access without needing to bind them to a p5 instance.
var abs = p5.prototype.abs;
var radians = p5.prototype.radians;
var dist = p5.prototype.dist;
var degrees = p5.prototype.degrees;
var pow = p5.prototype.pow;
var round = p5.prototype.round;
// =============================================================================
// p5 additions
// =============================================================================
/**
* A Group containing all the sprites in the sketch.
*
* @property allSprites
* @type {Group}
*/
defineLazyP5Property('allSprites', function() {
return new p5.prototype.Group();
});
p5.prototype.spriteUpdate = true;
/**
* A Sprite is the main building block of p5.play:
* an element able to store images or animations with a set of
* properties such as position and visibility.
* A Sprite can have a collider that defines the active area to detect
* collisions or overlappings with other sprites and mouse interactions.
*
* Sprites created using createSprite (the preferred way) are added to the
* allSprites group and given a depth value that puts it in front of all
* other sprites.
*
* @method createSprite
* @param {Number} x Initial x coordinate
* @param {Number} y Initial y coordinate
* @param {Number} width Width of the placeholder rectangle and of the
* collider until an image or new collider are set
* @param {Number} height Height of the placeholder rectangle and of the
* collider until an image or new collider are set
* @return {Object} The new sprite instance
*/
p5.prototype.createSprite = function(x, y, width, height) {
var s = new Sprite(this, x, y, width, height);
s.depth = this.allSprites.maxDepth()+1;
this.allSprites.add(s);
return s;
};
/**
* Removes a Sprite from the sketch.
* The removed Sprite won't be drawn or updated anymore.
* Equivalent to Sprite.remove()
*
* @method removeSprite
* @param {Object} sprite Sprite to be removed
*/
p5.prototype.removeSprite = function(sprite) {
sprite.remove();
};
/**
* Updates all the sprites in the sketch (position, animation...)
* it's called automatically at every draw().
* It can be paused by passing a parameter true or false;
* Note: it does not render the sprites.
*
* @method updateSprites
* @param {Boolean} updating false to pause the update, true to resume
*/
p5.prototype.updateSprites = function(upd) {
if(upd === false)
this.spriteUpdate = false;
if(upd === true)
this.spriteUpdate = true;
if(this.spriteUpdate)
for(var i = 0; i<this.allSprites.size(); i++)
{
this.allSprites.get(i).update();
}
};
/**
* Returns all the sprites in the sketch as an array
*
* @method getSprites
* @return {Array} Array of Sprites
*/
p5.prototype.getSprites = function() {
//draw everything
if(arguments.length===0)
{
return this.allSprites.toArray();
}
else
{
var arr = [];
//for every tag
for(var j=0; j<arguments.length; j++)
{
for(var i = 0; i<this.allSprites.size(); i++)
{
if(this.allSprites.get(i).isTagged(arguments[j]))
arr.push(this.allSprites.get(i));
}
}
return arr;
}
};
/**
* Displays a Group of sprites.
* If no parameter is specified, draws all sprites in the
* sketch.
* The drawing order is determined by the Sprite property "depth"
*
* @method drawSprites
* @param {Group} [group] Group of Sprites to be displayed
*/
p5.prototype.drawSprites = function(group) {
// If no group is provided, draw the allSprites group.
group = group || this.allSprites;
if (typeof group.draw !== 'function')
{
throw('Error: with drawSprites you can only draw all sprites or a group');
}
group.draw();
};
/**
* Displays a Sprite.
* To be typically used in the main draw function.
*
* @method drawSprite
* @param {Sprite} sprite Sprite to be displayed
*/
p5.prototype.drawSprite = function(sprite) {
if(sprite)
sprite.display();
};
/**
* Loads an animation.
* To be typically used in the preload() function of the sketch.
*
* @method loadAnimation
* @param {Sprite} sprite Sprite to be displayed
*/
p5.prototype.loadAnimation = function() {
return construct(this.Animation, arguments);
};
/**
* Loads a Sprite Sheet.
* To be typically used in the preload() function of the sketch.
*
* @method loadSpriteSheet
*/
p5.prototype.loadSpriteSheet = function() {
return construct(this.SpriteSheet, arguments);
};
/**
* Displays an animation.
*
* @method animation
* @param {Animation} anim Animation to be displayed
* @param {Number} x X coordinate
* @param {Number} y Y coordinate
*
*/
p5.prototype.animation = function(anim, x, y) {
anim.draw(x, y);
};
//variable to detect instant presses
defineLazyP5Property('_p5play', function() {
return {
keyStates: {},
mouseStates: {}
};
});
var KEY_IS_UP = 0;
var KEY_WENT_DOWN = 1;
var KEY_IS_DOWN = 2;
var KEY_WENT_UP = 3;
/**
* Detects if a key was pressed during the last cycle.
* It can be used to trigger events once, when a key is pressed or released.
* Example: Super Mario jumping.
*
* @method keyWentDown
* @param {Number|String} key Key code or character
* @return {Boolean} True if the key was pressed
*/
p5.prototype.keyWentDown = function(key) {
return this._isKeyInState(key, KEY_WENT_DOWN);
};
/**
* Detects if a key was released during the last cycle.
* It can be used to trigger events once, when a key is pressed or released.
* Example: Spaceship shooting.
*
* @method keyWentUp
* @param {Number|String} key Key code or character
* @return {Boolean} True if the key was released
*/
p5.prototype.keyWentUp = function(key) {
return this._isKeyInState(key, KEY_WENT_UP);
};
/**
* Detects if a key is currently pressed
* Like p5 keyIsDown but accepts strings and codes
*
* @method keyDown
* @param {Number|String} key Key code or character
* @return {Boolean} True if the key is down
*/
p5.prototype.keyDown = function(key) {
return this._isKeyInState(key, KEY_IS_DOWN);
};
/**
* Detects if a key is in the given state during the last cycle.
* Helper method encapsulating common key state logic; it may be preferable
* to call keyDown or other methods directly.
*
* @private
* @method _isKeyInState
* @param {Number|String} key Key code or character
* @param {Number} state Key state to check against
* @return {Boolean} True if the key is in the given state
*/
p5.prototype._isKeyInState = function(key, state) {
var keyCode;
var keyStates = this._p5play.keyStates;
if(typeof key === 'string')
{
keyCode = this._keyCodeFromAlias(key);
}
else
{
keyCode = key;
}
//if undefined start checking it
if(keyStates[keyCode]===undefined)
{
if(this.keyIsDown(keyCode))
keyStates[keyCode] = KEY_IS_DOWN;
else
keyStates[keyCode] = KEY_IS_UP;
}
return (keyStates[keyCode] === state);
};
/**
* Detects if a mouse button is currently down
* Combines mouseIsPressed and mouseButton of p5
*
* @method mouseDown
* @param {Number} [buttonCode] Mouse button constant LEFT, RIGHT or CENTER
* @return {Boolean} True if the button is down
*/
p5.prototype.mouseDown = function(buttonCode) {
return this._isMouseButtonInState(buttonCode, KEY_IS_DOWN);
};
/**
* Detects if a mouse button is currently up
* Combines mouseIsPressed and mouseButton of p5
*
* @method mouseUp
* @param {Number} [buttonCode] Mouse button constant LEFT, RIGHT or CENTER
* @return {Boolean} True if the button is up
*/
p5.prototype.mouseUp = function(buttonCode) {
return this._isMouseButtonInState(buttonCode, KEY_IS_UP);
};
/**
* Detects if a mouse button was released during the last cycle.
* It can be used to trigger events once, to be checked in the draw cycle
*
* @method mouseWentUp
* @param {Number} [buttonCode] Mouse button constant LEFT, RIGHT or CENTER
* @return {Boolean} True if the button was just released
*/
p5.prototype.mouseWentUp = function(buttonCode) {
return this._isMouseButtonInState(buttonCode, KEY_WENT_UP);
};
/**
* Detects if a mouse button was pressed during the last cycle.
* It can be used to trigger events once, to be checked in the draw cycle
*
* @method mouseWentDown
* @param {Number} [buttonCode] Mouse button constant LEFT, RIGHT or CENTER
* @return {Boolean} True if the button was just pressed
*/
p5.prototype.mouseWentDown = function(buttonCode) {
return this._isMouseButtonInState(buttonCode, KEY_WENT_DOWN);
};
/**
* Detects if a mouse button is in the given state during the last cycle.
* Helper method encapsulating common mouse button state logic; it may be
* preferable to call mouseWentUp, etc, directly.
*
* @private
* @method _isMouseButtonInState
* @param {Number} [buttonCode] Mouse button constant LEFT, RIGHT or CENTER
* @param {Number} state
* @return {boolean} True if the button was in the given state
*/
p5.prototype._isMouseButtonInState = function(buttonCode, state) {
var mouseStates = this._p5play.mouseStates;
if(buttonCode === undefined)
buttonCode = this.LEFT;
//undefined = not tracked yet, start tracking
if(mouseStates[buttonCode]===undefined)
{
if(this.mouseIsPressed && this.mouseButton === buttonCode)
mouseStates[buttonCode] = KEY_IS_DOWN;
else
mouseStates[buttonCode] = KEY_IS_UP;
}
return (mouseStates[buttonCode] === state);
};
/**
* An object storing all useful keys for easy access
* Key.tab = 9
*
* @private
* @property KEY
* @type {Object}
*/
p5.prototype.KEY = {
'BACKSPACE': 8,
'TAB': 9,
'ENTER': 13,
'SHIFT': 16,
'CTRL': 17,
'ALT': 18,
'PAUSE': 19,
'CAPS_LOCK': 20,
'ESC': 27,
'SPACE': 32,
' ': 32,
'PAGE_UP': 33,
'PAGE_DOWN': 34,
'END': 35,
'HOME': 36,
'LEFT_ARROW': 37,
'LEFT': 37,
'UP_ARROW': 38,
'UP': 38,
'RIGHT_ARROW': 39,
'RIGHT': 39,
'DOWN_ARROW': 40,
'DOWN': 40,
'INSERT': 45,
'DELETE': 46,
'0': 48,
'1': 49,
'2': 50,
'3': 51,
'4': 52,
'5': 53,
'6': 54,
'7': 55,
'8': 56,
'9': 57,
'A': 65,
'B': 66,
'C': 67,
'D': 68,
'E': 69,
'F': 70,
'G': 71,
'H': 72,
'I': 73,
'J': 74,
'K': 75,
'L': 76,
'M': 77,
'N': 78,
'O': 79,
'P': 80,
'Q': 81,
'R': 82,
'S': 83,
'T': 84,
'U': 85,
'V': 86,
'W': 87,
'X': 88,
'Y': 89,
'Z': 90,
'0NUMPAD': 96,
'1NUMPAD': 97,
'2NUMPAD': 98,
'3NUMPAD': 99,
'4NUMPAD': 100,
'5NUMPAD': 101,
'6NUMPAD': 102,
'7NUMPAD': 103,
'8NUMPAD': 104,
'9NUMPAD': 105,
'MULTIPLY': 106,
'PLUS': 107,
'MINUS': 109,
'DOT': 110,
'SLASH1': 111,
'F1': 112,
'F2': 113,
'F3': 114,
'F4': 115,
'F5': 116,
'F6': 117,
'F7': 118,
'F8': 119,
'F9': 120,
'F10': 121,
'F11': 122,
'F12': 123,
'EQUAL': 187,
'COMMA': 188,
'SLASH': 191,
'BACKSLASH': 220
};
/**
* An object storing deprecated key aliases, which we still support but
* should be mapped to valid aliases and generate warnings.
*
* @private
* @property KEY_DEPRECATIONS
* @type {Object}
*/
p5.prototype.KEY_DEPRECATIONS = {
'MINUT': 'MINUS',
'COMA': 'COMMA'
};
/**
* Given a string key alias (as defined in the KEY property above), look up
* and return the numeric JavaScript key code for that key. If a deprecated
* alias is passed (as defined in the KEY_DEPRECATIONS property) it will be
* mapped to a valid key code, but will also generate a warning about use
* of the deprecated alias.
*
* @private
* @method _keyCodeFromAlias
* @param {!string} alias - a case-insensitive key alias
* @return {number|undefined} a numeric JavaScript key code, or undefined
* if no key code matching the given alias is found.
*/
p5.prototype._keyCodeFromAlias = function(alias) {
alias = alias.toUpperCase();
if (this.KEY_DEPRECATIONS[alias]) {
this._warn('Key literal "' + alias + '" is deprecated and may be removed ' +
'in a future version of p5.play. ' +
'Please use "' + this.KEY_DEPRECATIONS[alias] + '" instead.');
alias = this.KEY_DEPRECATIONS[alias];
}
return this.KEY[alias];
};
//pre draw: detect keyStates
p5.prototype.readPresses = function() {
var keyStates = this._p5play.keyStates;
var mouseStates = this._p5play.mouseStates;
for (var key in keyStates) {
if(this.keyIsDown(key)) //if is down
{
if(keyStates[key] === KEY_IS_UP)//and was up
keyStates[key] = KEY_WENT_DOWN;
else
keyStates[key] = KEY_IS_DOWN; //now is simply down
}
else //if it's up
{
if(keyStates[key] === KEY_IS_DOWN)//and was up
keyStates[key] = KEY_WENT_UP;
else
keyStates[key] = KEY_IS_UP; //now is simply down
}
}
//mouse
for (var btn in mouseStates) {
if(this.mouseIsPressed && this.mouseButton === btn) //if is down
{
if(mouseStates[btn] === KEY_IS_UP)//and was up
mouseStates[btn] = KEY_WENT_DOWN;
else
mouseStates[btn] = KEY_IS_DOWN; //now is simply down
}
else //if it's up
{
if(mouseStates[btn] === KEY_IS_DOWN)//and was up
mouseStates[btn] = KEY_WENT_UP;
else
mouseStates[btn] = KEY_IS_UP; //now is simply down
}
}
};
/**
* Turns the quadTree on or off.
* A quadtree is a data structure used to optimize collision detection.
* It can improve performance when there is a large number of Sprites to be
* checked continuously for overlapping.
*
* p5.play will create and update a quadtree automatically.
*
* @method useQuadTree
* @param {Boolean} use Pass true to enable, false to disable
*/
p5.prototype.useQuadTree = function(use) {
if(this.quadTree !== undefined)
{
if(use === undefined)
return this.quadTree.active;
else if(use)
this.quadTree.active = true;
else
this.quadTree.active = false;
}
else
return false;
};
//the actual quadTree
defineLazyP5Property('quadTree', function() {
return new Quadtree({
x: 0,
y: 0,
width: 0,
height: 0
}, 4);
});
/*
//framerate independent delta, doesn't really work
p5.prototype.deltaTime = 1;
var now = Date.now();
var then = Date.now();
var INTERVAL_60 = 0.0166666; //60 fps
function updateDelta() {
then = now;
now = Date.now();
deltaTime = ((now - then) / 1000)/INTERVAL_60; // seconds since last frame
}
*/
/**
* A Sprite is the main building block of p5.play:
* an element able to store images or animations with a set of
* properties such as position and visibility.
* A Sprite can have a collider that defines the active area to detect
* collisions or overlappings with other sprites and mouse interactions.
*
* To create a Sprite, use
* {{#crossLink "p5.play/createSprite:method"}}{{/crossLink}}.
*
* @class Sprite
*/
// For details on why these docs aren't in a YUIDoc comment block, see:
//
// https://github.com/molleindustria/p5.play/pull/67
//
// @param {Number} x Initial x coordinate
// @param {Number} y Initial y coordinate
// @param {Number} width Width of the placeholder rectangle and of the
// collider until an image or new collider are set
// @param {Number} height Height of the placeholder rectangle and of the
// collider until an image or new collider are set
function Sprite(pInst, _x, _y, _w, _h) {
var pInstBind = createPInstBinder(pInst);
var createVector = pInstBind('createVector');
var color = pInstBind('color');
var random = pInstBind('random');
var print = pInstBind('print');
var push = pInstBind('push');
var pop = pInstBind('pop');
var colorMode = pInstBind('colorMode');
var noStroke = pInstBind('noStroke');
var rectMode = pInstBind('rectMode');
var ellipseMode = pInstBind('ellipseMode');
var imageMode = pInstBind('imageMode');
var translate = pInstBind('translate');
var scale = pInstBind('scale');
var rotate = pInstBind('rotate');
var stroke = pInstBind('stroke');
var strokeWeight = pInstBind('strokeWeight');
var line = pInstBind('line');
var noFill = pInstBind('noFill');
var fill = pInstBind('fill');
var textAlign = pInstBind('textAlign');
var textSize = pInstBind('textSize');
var text = pInstBind('text');
var rect = pInstBind('rect');
var cos = pInstBind('cos');
var sin = pInstBind('sin');
var atan2 = pInstBind('atan2');
var quadTree = pInst.quadTree;
var camera = pInst.camera;
// These are p5 constants that we'd like easy access to.
var RGB = p5.prototype.RGB;
var CENTER = p5.prototype.CENTER;
var LEFT = p5.prototype.LEFT;
var BOTTOM = p5.prototype.BOTTOM;
/**
* The sprite's position of the sprite as a vector (x,y).
* @property position
* @type {p5.Vector}
*/
this.position = createVector(_x, _y);
/**
* The sprite's position at the beginning of the last update as a vector (x,y).
* @property previousPosition
* @type {p5.Vector}
*/
this.previousPosition = createVector(_x, _y);
/*
The sprite's position at the end of the last update as a vector (x,y).
Note: this will differ from position whenever the position is changed
directly by assignment.
*/
this.newPosition = createVector(_x, _y);
//Position displacement on the x coordinate since the last update
this.deltaX = 0;
this.deltaY = 0;
/**
* The sprite's velocity as a vector (x,y)
* Velocity is speed broken down to its vertical and horizontal components.
*
* @property velocity
* @type {p5.Vector}
*/
this.velocity = createVector(0, 0);
/**
* Set a limit to the sprite's scalar speed regardless of the direction.
* The value can only be positive. If set to -1, there's no limit.
*
* @property maxSpeed
* @type {Number}
* @default -1
*/
this.maxSpeed = -1;
/**
* Friction factor, reduces the sprite's velocity.
* The friction should be close to 0 (eg. 0.01)
* 0: no friction
* 1: full friction
*
* @property friction
* @type {Number}
* @default 0
*/
this.friction = 0;
/**
* The sprite's current collider.
* It can either be an Axis Aligned Bounding Box (a non-rotated rectangle)
* or a circular collider.
* If the sprite is checked for collision, bounce, overlapping or mouse events the
* collider is automatically created from the width and height
* of the sprite or from the image dimension in case of animate sprites
*
* You can set a custom collider with Sprite.setCollider
*
* @property collider
* @type {Object}
*/
this.collider = undefined;
//internal use
//"default" - no image or custom collider is specified, use the shape width / height
//"custom" - specified with setCollider
//"image" - no collider is set with setCollider and an image is added
this.colliderType = 'none';
/**
* Object containing information about the most recent collision/overlapping
* To be typically used in combination with Sprite.overlap or Sprite.collide
* functions.
* The properties are touching.left, touching.right, touching.top,
* touching.bottom and are either true or false depending on the side of the
* collider.
*
* @property touching
* @type {Object}
*/
this.touching = {};
this.touching.left = false;
this.touching.right = false;
this.touching.top = false;
this.touching.bottom = false;
/**
* The mass determines the velocity transfer when sprites bounce
* against each other. See Sprite.bounce
* The higher the mass the least the sprite will be affected by collisions.
*
* @property mass
* @type {Number}
* @default 1
*/
this.mass = 1;
/**
* If set to true the sprite won't bounce or be displaced by collisions
* Simulates an infinite mass or an anchored object.
*
* @property immovable
* @type {Boolean}
* @default false
*/
this.immovable = false;
//Coefficient of restitution - velocity lost in the bouncing
//0 perfectly inelastic , 1 elastic, > 1 hyper elastic
/**
* Coefficient of restitution. The velocity lost after bouncing.
* 1: perfectly elastic, no energy is lost
* 0: perfectly inelastic, no bouncing
* less than 1: inelastic, this is the most common in nature
* greater than 1: hyper elastic, energy is increased like in a pinball bumper
*
* @property restitution
* @type {Number}
* @default 1
*/
this.restitution = 1;
/**
* Rotation in degrees of the visual element (image or animation)
* Note: this is not the movement's direction, see getDirection.
*
* @property rotation
* @type {Number}
* @default 0
*/
Object.defineProperty(this, 'rotation', {
enumerable: true,
get: function() {
return this._rotation;
},
set: function(value) {
this._rotation = value;
if (this.rotateToDirection) {
this.setSpeed(this.getSpeed(), value);
}
}
});
/**
* Internal rotation variable (expressed in degrees).
* Note: external callers access this through the rotation property above.
*
* @private
* @property _rotation
* @type {Number}
* @default 0
*/
this._rotation = 0;
/**
* Rotation change in degrees per frame of thevisual element (image or animation)
* Note: this is not the movement's direction, see getDirection.
*
* @property rotationSpeed
* @type {Number}
* @default 0
*/
this.rotationSpeed = 0;
/**
* Automatically lock the rotation property of the visual element
* (image or animation) to the sprite's movement direction and vice versa.
*
* @property rotateToDirection
* @type {Boolean}
* @default false
*/
this.rotateToDirection = false;
/**
* Determines the rendering order within a group: a sprite with
* lower depth will appear below the ones with higher depth.
*
* Note: drawing a group before another with drawSprites will make
* its members appear below the second one, like in normal p5 canvas
* drawing.
*
* @property depth
* @type {Number}
* @default One more than the greatest existing sprite depth, when calling
* createSprite(). When calling new Sprite() directly, depth will
* initialize to 0 (not recommended).
*/
this.depth = 0;
/**
* Determines the sprite's scale.
* Example: 2 will be twice the native size of the visuals,
* 0.5 will be half. Scaling up may make images blurry.
*
* @property scale
* @type {Number}
* @default 1
*/
this.scale = 1;
var dirX = 1;
var dirY = 1;
/**
* The sprite's visibility.