├── LICENSE.md ├── README.md └── exsprite.js /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) [year] 2017 Try.Catch.Run 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | EXPERIMENTAL. NOT IN ACTIVE DEVELOPMENT 3 | 4 | exSprite JavaScript Library v1.0.1 5 | 6 | exSprite is Javascript Library for manipulating graphics on HTML5 Canvas. 7 | 8 | features: 9 | 10 | 1. Supports Graphical Objects 11 | 2. Supports parent containers and child objects 12 | 3. Detects Mouse Events 13 | 4. Detects Collision of objects 14 | 15 | 16 | pending / in ptogress: 17 | 1. Dragging of objects 18 | 2. Plugin architecture 19 | 20 | 21 | 22 | . 23 | -------------------------------------------------------------------------------- /exsprite.js: -------------------------------------------------------------------------------- 1 | /** 2 | * exSprite JavaScript Library v1.0.1 3 | * http://www.exsprite.com 4 | * Copyright 2011, Vipin V 5 | * Licensed under the MIT or GPL Version 2 licenses. 6 | * Date: November 1 2011 7 | * 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining a copy 10 | * of this software to deal in the Software without 11 | * restriction, including without limitation the rights 12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | * copies of the Software, and to permit persons to whom the Software is 14 | * furnished to do so, subject to the following conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be included in 17 | * all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | */ 27 | /** 28 | * Class: Ex 29 | * Global singleton class 30 | * 31 | * 32 | */ 33 | ex = (function () { 34 | 35 | 36 | var _defs = { 37 | 38 | ExView: function () { 39 | 40 | 41 | 42 | var _xthis = null; 43 | 44 | 45 | /* 46 | Variable: _container (private) 47 | Container element of the canvas in the HTML DOM 48 | */ 49 | var _container = null; 50 | 51 | /* 52 | Variable: _canvas (private) 53 | Canvas Element 54 | */ 55 | var _canvas = null; 56 | 57 | /* 58 | Variable: _graphics2D (private) 59 | 2D Graphics context of the canavs 60 | */ 61 | var _graphics2D = null; 62 | 63 | /* 64 | Variable: _baseSprite (private) 65 | Instance of Root Container which is added at the root position 66 | */ 67 | var _baseSprite = null; 68 | 69 | /* 70 | Variable: _rendering (private) 71 | Rendering interval ID 72 | */ 73 | var _rendering = null; 74 | 75 | /* 76 | Variable: _start (private) 77 | Time at which rendering started 78 | */ 79 | var _start = 0; 80 | 81 | /* 82 | Variable: _count (private) 83 | Variable to count frames 84 | */ 85 | var _count = 0; 86 | 87 | /* 88 | Variable: _frame (private) 89 | Number of current frame 90 | */ 91 | var _frame = 0; 92 | 93 | /* 94 | Variable: _fps (private) 95 | Number of frames per second 96 | */ 97 | var _fps = 0; 98 | 99 | /* 100 | Variable: _dragHandler (private) 101 | Number of frames per second 102 | */ 103 | var _dragHandler; 104 | 105 | 106 | /************************************************** METHODS **********************************************/ 107 | 108 | 109 | /* 110 | * Function: init 111 | * Initiate exSprite Environement 112 | * 113 | **/ 114 | this.init = function (container, width, height, fps) { 115 | 116 | 117 | 118 | _container = document.getElementById(container); 119 | 120 | if (_container) { 121 | 122 | _canvas = document.createElement('canvas'); 123 | 124 | if (_canvas && _canvas.getContext) { 125 | 126 | _graphics2D = _canvas.getContext("2d"); 127 | 128 | _canvas.width = width; 129 | _canvas.height = height; 130 | 131 | _baseSprite = ex.createSprite(); 132 | _baseSprite.name("BaseSprite"); 133 | 134 | 135 | var _fns = { 136 | 137 | onMouseClick: function (event) { 138 | 139 | var mouseClickPoint = ex.geometry.getCanvasPoint(_canvas, event.pageX, event.pageY); 140 | var mouseClickEvent = ex.mouseEvent(ex.MOUSE_CLICK, mouseClickPoint); 141 | _baseSprite.dispatchEvent(mouseClickEvent); 142 | 143 | }, 144 | 145 | onMouseOver: function (event) { 146 | 147 | var mouseOverPoint = ex.geometry.getCanvasPoint(_canvas, event.pageX, event.pageY); 148 | var mouseOverEvent = ex.mouseEvent(ex.MOUSE_OVER, mouseOverPoint); 149 | _baseSprite.dispatchEvent(mouseOverEvent); 150 | 151 | }, 152 | 153 | onMouseOut: function (event) { 154 | 155 | var mouseOutPoint = ex.geometry.getCanvasPoint(_canvas, event.pageX, event.pageY); 156 | var mouseOutEvent = ex.mouseEvent(ex.MOUSE_OUT, mouseOutPoint); 157 | _baseSprite.dispatchEvent(mouseOutEvent); 158 | 159 | }, 160 | 161 | onMouseMove: function (event) { 162 | 163 | var mouseMovePoint = ex.geometry.getCanvasPoint(_canvas, event.pageX, event.pageY); 164 | var mouseMoveEvent = ex.mouseEvent(ex.MOUSE_MOVE, mouseMovePoint); 165 | _baseSprite.dispatchEvent(mouseMoveEvent); 166 | 167 | _xthis.handleDrag(event); 168 | 169 | }, 170 | 171 | onMouseDown: function (event) { 172 | 173 | var mouseDownPoint = ex.geometry.getCanvasPoint(_canvas, event.pageX, event.pageY); 174 | var mouseDownEvent = ex.mouseEvent(ex.MOUSE_DOWN, mouseDownPoint); 175 | _baseSprite.dispatchEvent(mouseDownEvent); 176 | 177 | }, 178 | 179 | onMouseUp: function (event) { 180 | 181 | var mouseUpPoint = ex.geometry.getCanvasPoint(_canvas, event.pageX, event.pageY); 182 | var mouseUpEvent = ex.mouseEvent(ex.MOUSE_UP, mouseUpPoint); 183 | _baseSprite.dispatchEvent(mouseUpEvent); 184 | 185 | } 186 | 187 | 188 | } 189 | 190 | 191 | _canvas.onclick = _fns.onMouseClick; 192 | _canvas.onmouseover = _fns.onMouseOver; 193 | _canvas.onmouseout = _fns.onMouseOut; 194 | _canvas.onmousemove = _fns.onMouseMove; 195 | _canvas.onmousedown = _fns.onMouseDown; 196 | _canvas.onmouseup = _fns.onMouseUp; 197 | 198 | 199 | _container.appendChild(_canvas); 200 | 201 | _xthis = this; 202 | 203 | return true; 204 | 205 | } 206 | 207 | } 208 | 209 | 210 | 211 | 212 | return false; 213 | 214 | } 215 | 216 | 217 | /** Function: addToBase 218 | * Adds sprite to the base container 219 | * 220 | **/ 221 | this.addChild = function (exSprite) { 222 | 223 | if (_baseSprite) { 224 | _baseSprite.addChild(exSprite); 225 | } 226 | 227 | } 228 | 229 | 230 | /** Function: startRendering 231 | * Start rendering if animation is involved 232 | * 233 | **/ 234 | this.startRendering = function () { 235 | 236 | if (ex) { 237 | 238 | _start = new Date().getTime(); 239 | 240 | var xthis = this; 241 | _rendering = setInterval(function () { 242 | xthis.render(); 243 | }, 1000 / 15); 244 | 245 | 246 | } 247 | 248 | 249 | } 250 | 251 | 252 | /** Function: render 253 | * Function that renders view 254 | * 255 | **/ 256 | this.render = function () { 257 | 258 | _frame++; 259 | 260 | var now = new Date().getTime(); 261 | var diff = now - _start; 262 | _fps = ((_frame / diff) * 1000).toFixed(2); 263 | 264 | _graphics2D.setTransform(1, 0, 0, 1, 0, 0); 265 | _graphics2D.clearRect(0, 0, _canvas.width, _canvas.height); 266 | 267 | 268 | _baseSprite.updateTransform(_graphics2D); 269 | _baseSprite.updateBounds(); 270 | _baseSprite.updateDisplay(_graphics2D, _frame, _fps); 271 | 272 | 273 | } 274 | 275 | 276 | 277 | /** Function: stopRendering 278 | * Stop rendering if animation is involved 279 | * 280 | **/ 281 | this.stopRendering = function () { 282 | 283 | if (_rendering) { 284 | clearInterval(_rendering); 285 | } 286 | 287 | } 288 | 289 | 290 | this.handleDrag = function (event) {} 291 | 292 | }, 293 | 294 | ExSprite: function () { 295 | 296 | /************************************************** PROPERTIES **********************************************/ 297 | 298 | 299 | 300 | /* 301 | Variable: _xthis (private) 302 | instance 303 | */ 304 | var _xthis = null; 305 | 306 | 307 | /* 308 | Variable: _name (private) 309 | Name of the instance 310 | */ 311 | var _name = ""; 312 | 313 | 314 | /* 315 | Variable: _data (private) 316 | This is used to store any data associated with the object 317 | */ 318 | var _data = ""; 319 | 320 | /* 321 | Variable: _frame (private) 322 | Current frame number 323 | */ 324 | var _frame = 0; 325 | 326 | /* 327 | Variable: _fps (private) 328 | Number of frames per second 329 | */ 330 | var _fps = 0; 331 | 332 | /* 333 | Variable: _x (private) 334 | Cartesian coordinate x 335 | */ 336 | var _x = 0; 337 | 338 | /* 339 | Variable: _y (private) 340 | Cartesian coordinate y 341 | */ 342 | var _y = 0; 343 | 344 | /* 345 | Variable: _width (private) 346 | Width of the object 347 | */ 348 | var _width = 0; 349 | 350 | /* 351 | Variable: _height (private) 352 | Height of the object 353 | */ 354 | var _height = 0; 355 | 356 | /* 357 | Variable: _angleUnit (private) 358 | Unit in which angle is measured. values: "radian", "degree" default:"radian" 359 | */ 360 | var _angleUnit = "radian"; 361 | 362 | /* 363 | Variable: _rotation (private) 364 | Rotation of the object on XY plane 365 | */ 366 | var _rotation = 0; 367 | 368 | /* 369 | Variable: _scaleX (private) 370 | Horizontal scaling of the object 371 | */ 372 | var _scaleX = 1; 373 | 374 | /* 375 | Variable: _scaleY (private) 376 | Vertical scaling of the object 377 | */ 378 | var _scaleY = 1; 379 | 380 | 381 | 382 | /* 383 | Variable: _transform (private) 384 | Transforamtion in expressed as matrices. _transform.augMatrix2D: concatenated transforamtion matrix, _transform.matrix2D: local transforamtion matrix 385 | */ 386 | var _transform = { 387 | augMatrix2D: { 388 | a: 1, 389 | b: 0, 390 | u: 0, 391 | c: 0, 392 | d: 1, 393 | v: 0, 394 | dx: 0, 395 | dy: 0, 396 | w: 1 397 | }, 398 | matrix2D: { 399 | a: 1, 400 | b: 0, 401 | u: 0, 402 | c: 0, 403 | d: 1, 404 | v: 0, 405 | dx: 0, 406 | dy: 0, 407 | w: 1 408 | } 409 | }; 410 | 411 | 412 | /* 413 | Variable: _points (private) 414 | Collecion points inside the object to determine the bounds. 415 | */ 416 | var _points = {}; 417 | 418 | /* 419 | Variable: _showInnerBounds (private) 420 | Flag that decides the visibility of inner bounds 421 | */ 422 | var _showInnerBounds = false; 423 | 424 | /* 425 | Variable: _innerBounds (private) 426 | Inner bounds of the object expressed as rectangle 427 | */ 428 | var _innerBounds = { 429 | x: 0, 430 | y: 0, 431 | w: 0, 432 | h: 0 433 | }; 434 | 435 | /* 436 | Variable: _showOuterBounds (private) 437 | Flag that decides the visibility of outer bounds. With respect to parent object 438 | */ 439 | var _showOuterBounds = false; 440 | 441 | /* 442 | Variable: _outerBounds (private) 443 | Outer bounds of the object expressed as rectangle. With respect to parent object 444 | */ 445 | var _outerBounds = { 446 | x: 0, 447 | y: 0, 448 | w: 0, 449 | h: 0 450 | }; 451 | 452 | 453 | /* 454 | Variable: _showGlobalBounds (private) 455 | Flag that decides the visibility of global bounds. With respect to the coordinate system of the canvas. 456 | */ 457 | var _showGlobalBounds = false; 458 | 459 | /* 460 | Variable: _globalBounds (private) 461 | Global bounds of the object expressed as rectangle. With respect to the coordinate system of the canvas. 462 | */ 463 | var _globalBounds = { 464 | x: 0, 465 | y: 0, 466 | w: 0, 467 | h: 0 468 | }; 469 | 470 | 471 | /* 472 | Variable: _hitArea (private) 473 | Area which will be used for hit test. Expressed as rectangle object. 474 | */ 475 | var _hitArea = { 476 | x: 0, 477 | y: 0, 478 | w: 0, 479 | h: 0 480 | } 481 | 482 | /* 483 | Variable: _parentSprite (private) 484 | Parent object to which this object is added. 485 | */ 486 | var _parentSprite; 487 | 488 | /* 489 | Variable: _childIndex (private) 490 | Index of this object in the children array of its parent object 491 | */ 492 | var _childIndex = 0; 493 | 494 | /* 495 | Variable: _children (private) 496 | List of the children of this object 497 | */ 498 | var _children = []; 499 | 500 | 501 | /* 502 | Variable: _eventHandlers (private) 503 | List of event handling functions 504 | */ 505 | var _eventHandlers = {}; 506 | 507 | 508 | /* 509 | Variable: _defaultEventHandlers (private) 510 | List of event handling functions 511 | */ 512 | var _defaultEventHandlers = {}; 513 | 514 | 515 | /* 516 | Variable: _mouseEnabled (private) 517 | Flag that decides whether this object responds to Mouse Interactions 518 | */ 519 | var _mouseEnabled = true; 520 | 521 | /* 522 | Variable: _mouseOver (private) 523 | Flag that shows mouse pointer is on this object 524 | */ 525 | var _mouseOver = false; 526 | 527 | 528 | /************************************************** GETTER & SETTER FUNCTIONS **********************************************/ 529 | 530 | 531 | /** 532 | * Function: name 533 | * Setter and Getter of _name 534 | * 535 | */ 536 | this.name = function (value) { 537 | if (typeof (value) != 'undefined') { 538 | _name = value; 539 | } else { 540 | return _name; 541 | } 542 | } 543 | 544 | /** 545 | * Function: frame 546 | * Setter and Getter of _frame 547 | * 548 | */ 549 | this.frame = function (value) { 550 | if (typeof (value) != 'undefined') { 551 | _frame = value; 552 | } else { 553 | return _frame; 554 | } 555 | } 556 | 557 | 558 | /** 559 | * Function: fps 560 | * Setter and Getter of _fps 561 | * 562 | */ 563 | this.fps = function (value) { 564 | if (typeof (value) != 'undefined') { 565 | _fps = value; 566 | } else { 567 | return _fps; 568 | } 569 | } 570 | 571 | 572 | /** 573 | * Function: data 574 | * Setter and Getter of _data 575 | * 576 | */ 577 | this.data = function (value) { 578 | if (typeof (value) != 'undefined') { 579 | _data = value; 580 | } else { 581 | return _data; 582 | } 583 | } 584 | 585 | 586 | /** 587 | * Function: x 588 | * Setter and Getter of _x 589 | * 590 | */ 591 | this.x = function (value) { 592 | if (typeof (value) != 'undefined') { 593 | _x = value; 594 | } else { 595 | return _x; 596 | } 597 | } 598 | 599 | 600 | /** 601 | * Function: y 602 | * Setter and Getter of _y 603 | * 604 | */ 605 | this.y = function (value) { 606 | if (typeof (value) != 'undefined') { 607 | _y = value; 608 | } else { 609 | return _y; 610 | } 611 | } 612 | 613 | /** 614 | * Function: width 615 | * Setter and Getter of _width 616 | * 617 | */ 618 | this.width = function (value) { 619 | if (typeof (value) != 'undefined') { 620 | _width = value; 621 | } else { 622 | return _width; 623 | } 624 | } 625 | 626 | 627 | /** 628 | * Function: height 629 | * Setter and Getter of _height 630 | * 631 | */ 632 | this.height = function (value) { 633 | if (typeof (value) != 'undefined') { 634 | _height = value; 635 | } else { 636 | return _height; 637 | } 638 | } 639 | 640 | /** 641 | * Function: angleUnit 642 | * Setter and Getter of _angleUnit 643 | * 644 | */ 645 | this.angleUnit = function (value) { 646 | if (typeof (value) != 'undefined') { 647 | _angleUnit = value; 648 | } else { 649 | return _angleUnit; 650 | } 651 | } 652 | 653 | /** 654 | * Function: rotation 655 | * Setter and Getter of _rotation 656 | * 657 | */ 658 | this.rotation = function (value) { 659 | if (typeof (value) != 'undefined') { 660 | _rotation = value; 661 | } else { 662 | return _rotation; 663 | } 664 | } 665 | 666 | 667 | /** 668 | * Function: scaleX 669 | * Setter and Getter of _scaleX 670 | * 671 | */ 672 | this.scaleX = function (value) { 673 | if (typeof (value) != 'undefined') { 674 | _scaleX = value; 675 | } else { 676 | return _scaleX; 677 | } 678 | } 679 | 680 | 681 | /** 682 | * Function: scaleY 683 | * Setter and Getter of _scaleY 684 | * 685 | */ 686 | this.scaleY = function (value) { 687 | if (typeof (value) != 'undefined') { 688 | _scaleY = value; 689 | } else { 690 | return _scaleY; 691 | } 692 | } 693 | 694 | 695 | /** 696 | * Function: transform 697 | * Setter and Getter of _height 698 | * 699 | */ 700 | this.transform = function (value) { 701 | if (typeof (value) != 'undefined') { 702 | _transform = value; 703 | } else { 704 | return _transform; 705 | } 706 | } 707 | 708 | 709 | 710 | 711 | /* Function: showInnerBounds 712 | * Getter of showInnerBounds 713 | * 714 | */ 715 | this.showInnerBounds = function (value) { 716 | if (typeof (value) != 'undefined') { 717 | _showInnerBounds = value; 718 | } else { 719 | return _showInnerBounds; 720 | } 721 | } 722 | 723 | /* Function: innerBounds 724 | * Getter of _innerBounds 725 | * 726 | */ 727 | this.innerBounds = function () { 728 | return _innerBounds; 729 | } 730 | 731 | 732 | 733 | /* Function: showOuterBounds 734 | * Getter of showOuterBounds 735 | * 736 | */ 737 | this.showOuterBounds = function (value) { 738 | if (typeof (value) != 'undefined') { 739 | _showOuterBounds = value; 740 | } else { 741 | return _showOuterBounds; 742 | } 743 | } 744 | 745 | /* Function: innerBounds 746 | * Getter of _innerBounds 747 | * 748 | */ 749 | this.outerBounds = function () { 750 | return _outerBounds; 751 | } 752 | 753 | /* Function: showGlobalBounds 754 | * Getter of showGlobalBounds 755 | * 756 | */ 757 | this.showGlobalBounds = function (value) { 758 | if (typeof (value) != 'undefined') { 759 | _showGlobalBounds = value; 760 | } else { 761 | return _showGlobalBounds; 762 | } 763 | } 764 | 765 | /* Function: globalBounds 766 | * Getter of _globalBounds 767 | * 768 | */ 769 | this.globalBounds = function () { 770 | return _globalBounds; 771 | } 772 | 773 | 774 | /** 775 | * Function: hitArea 776 | * Setter and Getter of _hitArea 777 | * 778 | */ 779 | this.hitArea = function (value) { 780 | if (typeof (value) != 'undefined' && typeof (value.x) != 'undefined' && typeof (value.y) != 'undefined' && typeof (value.w) != 'undefined' && typeof (value.h) != 'undefined') { 781 | _hitArea = value; 782 | } else { 783 | return _hitArea; 784 | } 785 | } 786 | 787 | 788 | 789 | /** 790 | * Function: parentSprite 791 | * Getter of _parentSprite 792 | * 793 | */ 794 | this.parentSprite = function (value) { 795 | if (typeof (value) != 'undefined') { 796 | _parentSprite = value; 797 | } else { 798 | return _parentSprite; 799 | } 800 | } 801 | 802 | 803 | /** 804 | * Function: childIndex 805 | * Getter of _childIndex 806 | * 807 | */ 808 | this.childIndex = function () { 809 | return _childIndex; 810 | } 811 | 812 | 813 | /** 814 | * Function: mouseEnabled 815 | * Setter and Getter of _mouseEnabled 816 | * 817 | */ 818 | this.mouseEnabled = function (value) { 819 | if (typeof (value) != 'undefined') { 820 | _mouseEnabled = value; 821 | } else { 822 | return _mouseEnabled; 823 | } 824 | } 825 | 826 | 827 | /** 828 | * Function: mouseOver 829 | * Setter and Getter of _mouseOver 830 | * 831 | */ 832 | this.mouseOver = function (value) { 833 | if (typeof (value) != 'undefined') { 834 | _mouseOver = value; 835 | } else { 836 | return _mouseOver; 837 | } 838 | } 839 | 840 | 841 | 842 | 843 | /************************************************** METHODS **********************************************/ 844 | 845 | 846 | 847 | /** 848 | * Function: pushChild 849 | * Push item to the array of child elements 850 | * 851 | */ 852 | this.addChild = function (exSprite) { 853 | _children.push(exSprite); 854 | exSprite.parentSprite(this); 855 | } 856 | 857 | /** 858 | * Function: getChildren 859 | * Returns the array of child elements 860 | * 861 | */ 862 | this.getChildren = function () { 863 | return _children; 864 | } 865 | 866 | /** 867 | * Function: numChildren 868 | * Returns the number of child elements 869 | * 870 | */ 871 | this.numChildren = function () { 872 | return _children.length; 873 | } 874 | 875 | /** 876 | * Function: addElements 877 | * Override this function in Subclasses to addChildren and call froem where the instance is created 878 | * 879 | */ 880 | this.addElements = function () { 881 | 882 | 883 | } 884 | 885 | /** 886 | * Function: updateTransform 887 | * Update the transformation matrix of this object and its child objects 888 | * 889 | */ 890 | this.updateTransform = function (graphics2D) { 891 | 892 | this.modifyTransform(); 893 | this.calculateTransform(graphics2D); 894 | 895 | for (var i = 0; i < this.numChildren(); i++) { 896 | 897 | var child = _children[i]; 898 | 899 | if (child && child.updateTransform) { 900 | 901 | child.updateTransform(); 902 | 903 | } 904 | 905 | } 906 | 907 | } 908 | 909 | /** 910 | * Function: modifyTransform 911 | * This function modifies the orientation of the object . This function has to be overrided and used in subclasses 912 | * 913 | */ 914 | this.modifyTransform = function () { 915 | 916 | 917 | } 918 | 919 | /** 920 | * Function: applyParentTransform 921 | * This function applies the transformation of parent object to draw something in parent object 922 | * 923 | */ 924 | this.applyParentTransform = function (graphics2D) { 925 | 926 | var parentTransform = _parentSprite.transform(); 927 | var m2D = parentTransform.augMatrix2D; 928 | graphics2D.setTransform(m2D.a, m2D.b, m2D.c, m2D.d, m2D.dx, m2D.dy); 929 | 930 | } 931 | 932 | /** 933 | * Function: applyLocalTransform 934 | * This function applies the transformation of this object to draw something 935 | * 936 | */ 937 | this.applyLocalTransform = function (graphics2D) { 938 | 939 | var m2D = _transform.augMatrix2D; 940 | graphics2D.setTransform(m2D.a, m2D.b, m2D.c, m2D.d, m2D.dx, m2D.dy); 941 | 942 | } 943 | 944 | /** 945 | * Function: calculateTransform 946 | * This function creates the resultant transformation matrix 947 | * 948 | */ 949 | this.calculateTransform = function (graphics2D) { 950 | 951 | 952 | var rot = _rotation; 953 | if (_angleUnit == "degree") { 954 | rot = rot * (Math.PI / 180); 955 | } 956 | 957 | 958 | var sMatrix = { 959 | a: _scaleX, 960 | b: 0, 961 | u: 0, 962 | c: 0, 963 | d: _scaleY, 964 | v: 0, 965 | dx: 0, 966 | dy: 0, 967 | w: 1 968 | }; 969 | var rMatrix = { 970 | a: Math.cos(rot), 971 | b: Math.sin(rot), 972 | u: 0, 973 | c: -Math.sin(rot), 974 | d: Math.cos(rot), 975 | v: 0, 976 | dx: 0, 977 | dy: 0, 978 | w: 1 979 | }; 980 | var tMatrix = { 981 | a: 1, 982 | b: 0, 983 | u: 0, 984 | c: 0, 985 | d: 1, 986 | v: 0, 987 | dx: _x, 988 | dy: _y, 989 | w: 1 990 | }; 991 | 992 | _transform.matrix2D = ex.matrix.multiply2DMatrices(ex.matrix.multiply2DMatrices(tMatrix, rMatrix), sMatrix); 993 | 994 | 995 | if (_parentSprite) { 996 | 997 | 998 | var parentTransform = _parentSprite.transform(); 999 | 1000 | _transform.augMatrix2D = ex.matrix.multiply2DMatrices(parentTransform.augMatrix2D, _transform.matrix2D); 1001 | 1002 | 1003 | } else { 1004 | 1005 | ex.matrix.copyMatrix(_transform.augMatrix2D, _transform.matrix2D); 1006 | 1007 | } 1008 | 1009 | 1010 | 1011 | 1012 | } 1013 | 1014 | /** 1015 | * Function: determineBounds 1016 | * Adds points to points list to determine the bounds of this object 1017 | * 1018 | */ 1019 | this.determineBounds = function (key, points) { 1020 | 1021 | _points[key] = points; 1022 | 1023 | } 1024 | 1025 | /** 1026 | * Function: updateBounds 1027 | * update the bounds of this object after transformation is modified. 1028 | * 1029 | */ 1030 | this.updateBounds = function () { 1031 | 1032 | 1033 | for (var i = 0; i < this.numChildren(); i++) { 1034 | 1035 | var child = _children[i]; 1036 | 1037 | if (child && child.updateBounds) { 1038 | 1039 | child.updateBounds(); 1040 | 1041 | var childBounds = child.outerBounds(); 1042 | 1043 | 1044 | var points = []; 1045 | ex.geometry.rectToPoints(childBounds, points); 1046 | 1047 | 1048 | this.determineBounds("child_" + i.toString(), points); 1049 | 1050 | } 1051 | 1052 | } 1053 | 1054 | 1055 | var innerBounds = { 1056 | x1: undefined, 1057 | x2: undefined, 1058 | y1: undefined, 1059 | y2: undefined 1060 | }; 1061 | 1062 | for (var key in _points) { 1063 | 1064 | var innerPoints = _points[key]; 1065 | 1066 | if (typeof (innerPoints) != "undefined" && innerPoints.length) { 1067 | 1068 | ex.geometry.pointsToRect(innerPoints, innerBounds); 1069 | 1070 | 1071 | } 1072 | 1073 | } 1074 | 1075 | if (typeof (innerBounds.x) == "number") { 1076 | _innerBounds.x = innerBounds.x; 1077 | } 1078 | 1079 | if (typeof (innerBounds.y) == "number") { 1080 | _innerBounds.y = innerBounds.y; 1081 | } 1082 | 1083 | if (typeof (innerBounds.w) == "number") { 1084 | _innerBounds.w = innerBounds.w; 1085 | } 1086 | 1087 | if (typeof (innerBounds.h) == "number") { 1088 | _innerBounds.h = innerBounds.h; 1089 | } 1090 | 1091 | 1092 | if (_parentSprite) { 1093 | 1094 | var pltGlobal = this.localToGlobal(_innerBounds.x, _innerBounds.y); 1095 | var plbGlobal = this.localToGlobal(_innerBounds.x, _innerBounds.y + _innerBounds.h); 1096 | var prtGlobal = this.localToGlobal(_innerBounds.x + _innerBounds.w, _innerBounds.y); 1097 | var prbGlobal = this.localToGlobal(_innerBounds.x + _innerBounds.w, _innerBounds.y + _innerBounds.h); 1098 | 1099 | var globalPoints = [pltGlobal, plbGlobal, prtGlobal, prbGlobal]; 1100 | var globalBounds = { 1101 | x1: undefined, 1102 | x2: undefined, 1103 | y1: undefined, 1104 | y2: undefined 1105 | }; 1106 | ex.geometry.pointsToRect(globalPoints, globalBounds); 1107 | 1108 | 1109 | if (typeof (globalBounds.x) == "number") { 1110 | _globalBounds.x = globalBounds.x; 1111 | } 1112 | if (typeof (globalBounds.y) == "number") { 1113 | _globalBounds.y = globalBounds.y; 1114 | } 1115 | if (typeof (globalBounds.w) == "number") { 1116 | _globalBounds.w = globalBounds.w; 1117 | } 1118 | if (typeof (globalBounds.h) == "number") { 1119 | _globalBounds.h = globalBounds.h; 1120 | } 1121 | 1122 | 1123 | var pltParent = _parentSprite.globalToLocal(pltGlobal); 1124 | var plbParent = _parentSprite.globalToLocal(plbGlobal); 1125 | var prtParent = _parentSprite.globalToLocal(prtGlobal); 1126 | var prbParent = _parentSprite.globalToLocal(prbGlobal); 1127 | 1128 | var outerPoints = [pltParent, plbParent, prtParent, prbParent]; 1129 | var outerBounds = { 1130 | x1: undefined, 1131 | x2: undefined, 1132 | y1: undefined, 1133 | y2: undefined 1134 | }; 1135 | ex.geometry.pointsToRect(outerPoints, outerBounds); 1136 | 1137 | 1138 | if (typeof (outerBounds.x) == "number") { 1139 | _outerBounds.x = outerBounds.x; 1140 | } 1141 | if (typeof (outerBounds.y) == "number") { 1142 | _outerBounds.y = outerBounds.y; 1143 | } 1144 | if (typeof (outerBounds.w) == "number") { 1145 | _outerBounds.w = outerBounds.w; 1146 | } 1147 | if (typeof (outerBounds.h) == "number") { 1148 | _outerBounds.h = outerBounds.h; 1149 | } 1150 | 1151 | } 1152 | 1153 | 1154 | 1155 | } 1156 | 1157 | 1158 | 1159 | /** 1160 | * Function: updateDisplay 1161 | * Updates the display graphics. Recurses into child objects 1162 | * 1163 | * 1164 | */ 1165 | this.updateDisplay = function (graphics2D, frame, fps) { 1166 | 1167 | _frame = frame; 1168 | _fps = fps; 1169 | 1170 | 1171 | this.drawGlobalBounds(graphics2D); 1172 | 1173 | 1174 | if (_parentSprite) { 1175 | this.applyParentTransform(graphics2D); 1176 | this.drawInParent(graphics2D); 1177 | this.drawOuterBounds(graphics2D); 1178 | } 1179 | 1180 | 1181 | 1182 | this.applyLocalTransform(graphics2D); 1183 | this.draw(graphics2D); 1184 | this.drawInnerBounds(graphics2D); 1185 | 1186 | /*for( var i = 0; i < this.numChildren(); i++){ 1187 | 1188 | var child = _children[i]; 1189 | 1190 | if(child && child.drawInParent){ 1191 | child.drawInParent(graphics2D); 1192 | child. 1193 | } 1194 | 1195 | }*/ 1196 | 1197 | for (var i = 0; i < this.numChildren(); i++) { 1198 | 1199 | var child = _children[i]; 1200 | 1201 | if (child && child.updateDisplay) { 1202 | 1203 | for (var j = i + 1; j < this.numChildren(); j++) { 1204 | 1205 | var child1 = _children[j]; 1206 | var hit = child.hitTestObject(child1); 1207 | if (hit) { 1208 | 1209 | var hitEvent1 = ex.hitEvent(ex.HIT, child1, 0, 0); 1210 | var hitEvent2 = ex.hitEvent(ex.HIT, child, 0, 0); 1211 | 1212 | child.dispatchEvent(hitEvent1); 1213 | child1.dispatchEvent(hitEvent2); 1214 | 1215 | } 1216 | 1217 | } 1218 | 1219 | child.updateDisplay(graphics2D, frame, fps); 1220 | } 1221 | 1222 | } 1223 | 1224 | } 1225 | 1226 | /** 1227 | * Function: drawInnerBounds 1228 | * Draw the inner bounds of the object if the flag is true 1229 | * 1230 | * 1231 | */ 1232 | this.drawInnerBounds = function (graphics2D) { 1233 | 1234 | if (typeof (_showInnerBounds) === "string") { 1235 | 1236 | var bounds = this.innerBounds(); 1237 | graphics2D.strokeStyle = _showInnerBounds; //"rgba(255, 255, 0, 0.7)"; 1238 | graphics2D.strokeRect(bounds.x, bounds.y, bounds.w, bounds.h); 1239 | 1240 | } 1241 | 1242 | } 1243 | 1244 | /** 1245 | * Function: drawOuterBounds 1246 | * Draw the outer bounds of the object if the flag is true 1247 | * 1248 | * 1249 | */ 1250 | this.drawOuterBounds = function (graphics2D) { 1251 | 1252 | if (typeof (_showOuterBounds) === "string") { 1253 | 1254 | var bounds = this.outerBounds(); 1255 | graphics2D.strokeStyle = _showOuterBounds; //"rgba(255, 255, 0, 0.7)"; 1256 | graphics2D.strokeRect(bounds.x, bounds.y, bounds.w, bounds.h); 1257 | 1258 | } 1259 | 1260 | } 1261 | 1262 | 1263 | /** 1264 | * Function: drawGlobalBounds 1265 | * Draw the global bounds of the object if the flag is true 1266 | * 1267 | * 1268 | */ 1269 | this.drawGlobalBounds = function (graphics2D) { 1270 | 1271 | if (typeof (_showGlobalBounds) === "string") { 1272 | 1273 | graphics2D.setTransform(1, 0, 0, 1, 0, 0); 1274 | 1275 | var bounds = this.globalBounds(); 1276 | graphics2D.strokeStyle = _showGlobalBounds; //"rgba(255, 255, 0, 0.7)"; 1277 | graphics2D.strokeRect(bounds.x, bounds.y, bounds.w, bounds.h); 1278 | 1279 | } 1280 | 1281 | } 1282 | 1283 | 1284 | /** 1285 | * Function: drawInParent 1286 | * Draws the pixels according to parent transformation. This function has to be overrided in subclasses to draw something in parent object 1287 | * 1288 | */ 1289 | this.drawInParent = function (graphics2D) { 1290 | 1291 | 1292 | 1293 | } 1294 | 1295 | /** 1296 | * Function: draw 1297 | * Draws the pixel according to the sprite content. This function has to be overrided in subclasses to draw something. 1298 | * 1299 | */ 1300 | this.draw = function (graphics2D) { 1301 | 1302 | 1303 | } 1304 | 1305 | 1306 | /** 1307 | * Function: localToGlobal 1308 | * Returns the global point equivalent to the given local point. 1309 | * 1310 | */ 1311 | this.localToGlobal = function (x, y) { 1312 | 1313 | 1314 | if (typeof (x) == "object") { 1315 | 1316 | y = x.y; 1317 | x = x.x; 1318 | 1319 | } 1320 | 1321 | if (typeof (x) == "number" && typeof (y) == "number") { 1322 | 1323 | var augmatrix2D = this.transform().augMatrix2D; 1324 | 1325 | 1326 | var point = { 1327 | a: 1, 1328 | b: 0, 1329 | u: 0, 1330 | c: 0, 1331 | d: 1, 1332 | v: 0, 1333 | dx: x, 1334 | dy: y, 1335 | w: 1 1336 | }; 1337 | 1338 | var result = ex.matrix.multiply2DMatrices(augmatrix2D, point); 1339 | 1340 | return { 1341 | x: result.dx, 1342 | y: result.dy 1343 | }; 1344 | 1345 | } 1346 | 1347 | } 1348 | 1349 | /** 1350 | * Function: globalToLocal 1351 | * Returns the local point equivalent to the given global point. 1352 | * 1353 | */ 1354 | this.globalToLocal = function (x, y) { 1355 | 1356 | if (typeof (x) == "object") { 1357 | 1358 | y = x.y; 1359 | x = x.x; 1360 | 1361 | } 1362 | 1363 | if (typeof (x) == "number" && typeof (y) == "number") { 1364 | 1365 | var augmatrix2D = this.transform().augMatrix2D; 1366 | 1367 | var point = { 1368 | a: 1, 1369 | b: 0, 1370 | u: 0, 1371 | c: 0, 1372 | d: 1, 1373 | v: 0, 1374 | dx: x, 1375 | dy: y, 1376 | w: 1 1377 | }; 1378 | 1379 | var result = ex.matrix.multiply2DMatrices(ex.matrix.getInverse2D(augmatrix2D), point); 1380 | 1381 | return { 1382 | x: result.dx, 1383 | y: result.dy 1384 | }; 1385 | 1386 | } 1387 | 1388 | } 1389 | 1390 | 1391 | /** 1392 | * Function: hitTest 1393 | * Checks whether the point is inside this object. 1394 | * 1395 | */ 1396 | 1397 | this.hitTest = function (x, y) { 1398 | 1399 | var p; 1400 | if (typeof (x) == "object" && typeof (x.x) == "number" && typeof (x.y) == "number") { 1401 | p = x; 1402 | } else if (typeof (x) == "number" && typeof (y) == "number") { 1403 | p = { 1404 | x: x, 1405 | y: y 1406 | }; 1407 | } 1408 | 1409 | var hit = false; 1410 | var bounds = this.outerBounds(); 1411 | if (typeof (p) == "object") { 1412 | hit = ex.geometry.isPointInside(p, bounds); 1413 | } 1414 | 1415 | return hit; 1416 | 1417 | } 1418 | 1419 | /** 1420 | * Function: hitTestObject 1421 | * Checks whether the given object collides with this one. 1422 | * 1423 | */ 1424 | this.hitTestObject = function (object) { 1425 | 1426 | var bounds1 = this.outerBounds(); 1427 | var bounds2 = object.outerBounds(); 1428 | 1429 | if (bounds1 && bounds2) { 1430 | 1431 | var intersection = ex.geometry.intersects(bounds1, bounds2); 1432 | 1433 | if (typeof (intersection) == "object") { 1434 | return true; 1435 | } 1436 | 1437 | } 1438 | 1439 | return false; 1440 | 1441 | } 1442 | 1443 | 1444 | this.startDrag = function () { 1445 | 1446 | 1447 | 1448 | } 1449 | 1450 | 1451 | this.stopDrag = function () { 1452 | 1453 | 1454 | 1455 | } 1456 | 1457 | 1458 | 1459 | this.dispatchEvent = function (event) { 1460 | 1461 | event.setTarget(this); 1462 | 1463 | this.callEventListener(event); 1464 | 1465 | var available = this.callDefaultEventListener(event); 1466 | 1467 | if (!available) { 1468 | for (var i = 0; i < this.numChildren(); i++) { 1469 | var child = _children[i]; 1470 | if (child && child.dispatchEvent) { 1471 | child.dispatchEvent(event); 1472 | } 1473 | } 1474 | } 1475 | 1476 | 1477 | 1478 | } 1479 | 1480 | 1481 | this.bindDefault = function (eventType, handler) { 1482 | 1483 | if (typeof (eventType) == "string" && typeof (handler) == "function") { 1484 | 1485 | _defaultEventHandlers[eventType] = handler; 1486 | 1487 | } 1488 | 1489 | } 1490 | 1491 | this.bind = function (eventType, handler) { 1492 | 1493 | if (typeof (eventType) == "string" && typeof (handler) == "function") { 1494 | 1495 | if (typeof (_eventHandlers[eventType]) != "object") { 1496 | _eventHandlers[eventType] = []; 1497 | } 1498 | 1499 | var handlers = _eventHandlers[eventType]; 1500 | 1501 | var exists = false; 1502 | if (typeof (handlers) != "undefined" && handlers.length) { 1503 | 1504 | for (var i = 0; i < handlers.length; i++) { 1505 | if (handlers[i] == handler) { 1506 | exists = true; 1507 | break; 1508 | } 1509 | } 1510 | } 1511 | if (!exists) { 1512 | handlers.push(handler); 1513 | } 1514 | } 1515 | 1516 | } 1517 | 1518 | 1519 | this.callDefaultEventListener = function (event) { 1520 | 1521 | var eventType = event.type(); 1522 | 1523 | if (typeof (eventType) == "string") { 1524 | 1525 | if (typeof (_defaultEventHandlers[eventType]) == "undefined") { 1526 | return false; 1527 | } 1528 | 1529 | var handler = _defaultEventHandlers[eventType]; 1530 | 1531 | if (typeof (handler) == "function") { 1532 | handler(event); 1533 | return true; 1534 | } 1535 | return false; 1536 | } 1537 | 1538 | } 1539 | 1540 | this.callEventListener = function (event) { 1541 | 1542 | var eventType = event.type(); 1543 | 1544 | if (typeof (eventType) == "string") { 1545 | 1546 | if (typeof (_eventHandlers[eventType]) != "object") { 1547 | return; 1548 | } 1549 | 1550 | var handlers = _eventHandlers[eventType]; 1551 | 1552 | if (typeof (handlers) != "undefined" && handlers.length) { 1553 | 1554 | for (var i = 0; i < handlers.length; i++) { 1555 | var handler = handlers[i]; 1556 | handler(event); 1557 | } 1558 | } 1559 | 1560 | } 1561 | 1562 | } 1563 | 1564 | 1565 | this.unbind = function (eventType, handler) { 1566 | 1567 | if (typeof (eventType) == "string" && typeof (handler) == "function") { 1568 | 1569 | if (typeof (_eventHandlers[eventType]) != "object") { 1570 | return; 1571 | } 1572 | 1573 | var handlers = _eventHandlers[eventType]; 1574 | 1575 | if (typeof (handlers) != "undefined" && handlers.length) { 1576 | 1577 | for (var i = 0; i < handlers.length; i++) { 1578 | if (handlers[i] == handler) { 1579 | handlers.splice(i, 1); 1580 | break; 1581 | } 1582 | } 1583 | } 1584 | 1585 | } 1586 | 1587 | } 1588 | 1589 | 1590 | this.mouseclick = function (event) { 1591 | 1592 | if (typeof (event.mouseX()) == "number" && typeof (event.mouseY()) == "number") { 1593 | 1594 | var gX = event.mouseX(); 1595 | var gY = event.mouseY(); 1596 | 1597 | var point = _xthis.globalToLocal(gX, gY); 1598 | 1599 | for (var i = 0; i < _xthis.numChildren(); i++) { 1600 | var child = _children[i]; 1601 | 1602 | var clicked = false; 1603 | 1604 | if (child && child.hitTest) { 1605 | clicked = child.hitTest(point); 1606 | } 1607 | 1608 | if (clicked === true && child.dispatchEvent) { 1609 | child.dispatchEvent(event); 1610 | } 1611 | 1612 | } 1613 | 1614 | } 1615 | 1616 | } 1617 | 1618 | 1619 | this.mouseover = function (event) { 1620 | 1621 | _mouseOver = true; 1622 | 1623 | if (typeof (event.mouseX()) == "number" && typeof (event.mouseY()) == "number") { 1624 | 1625 | var gX = event.mouseX(); 1626 | var gY = event.mouseY(); 1627 | 1628 | var point = _xthis.globalToLocal(gX, gY); 1629 | 1630 | for (var i = 0; i < _xthis.numChildren(); i++) { 1631 | var child = _children[i]; 1632 | 1633 | var over = false; 1634 | 1635 | if (child && child.hitTest) { 1636 | over = child.hitTest(point); 1637 | } 1638 | 1639 | if (over === true && !child.mouseOver() && child.dispatchEvent) { 1640 | child.dispatchEvent(event); 1641 | } 1642 | 1643 | } 1644 | 1645 | } 1646 | } 1647 | 1648 | this.mouseout = function (event) { 1649 | 1650 | _mouseOver = false; 1651 | 1652 | if (typeof (event.mouseX()) == "number" && typeof (event.mouseY()) == "number") { 1653 | 1654 | var gX = event.mouseX(); 1655 | var gY = event.mouseY(); 1656 | 1657 | var point = _xthis.globalToLocal(gX, gY); 1658 | 1659 | for (var i = 0; i < _xthis.numChildren(); i++) { 1660 | var child = _children[i]; 1661 | 1662 | var over = false; 1663 | 1664 | if (child && child.hitTest) { 1665 | over = child.hitTest(point); 1666 | } 1667 | 1668 | if (over != true && child.mouseOver() === true && child.dispatchEvent) { 1669 | child.dispatchEvent(event); 1670 | } 1671 | 1672 | } 1673 | 1674 | } 1675 | } 1676 | 1677 | this.mousemove = function (event) { 1678 | 1679 | 1680 | 1681 | if (typeof (event.mouseX()) == "number" && typeof (event.mouseY()) == "number") { 1682 | 1683 | var gX = event.mouseX(); 1684 | var gY = event.mouseY(); 1685 | 1686 | var point = _xthis.globalToLocal(gX, gY); 1687 | 1688 | for (var i = 0; i < _xthis.numChildren(); i++) { 1689 | var child = _children[i]; 1690 | 1691 | var over = false; 1692 | 1693 | if (child && child.hitTest) { 1694 | over = child.hitTest(point); 1695 | } 1696 | 1697 | 1698 | 1699 | if (over === true && child.mouseOver() != true && child.dispatchEvent) { 1700 | var mouseOverEvent = ex.mouseEvent(ex.MOUSE_OVER, { 1701 | x: event.mouseX(), 1702 | y: event.mouseY() 1703 | }); 1704 | child.dispatchEvent(mouseOverEvent); 1705 | } 1706 | 1707 | if (over != true && child.mouseOver() === true && child.dispatchEvent) { 1708 | var mouseOutEvent = ex.mouseEvent(ex.MOUSE_OUT, { 1709 | x: event.mouseX(), 1710 | y: event.mouseY() 1711 | }); 1712 | child.dispatchEvent(mouseOutEvent); 1713 | } 1714 | 1715 | 1716 | if (over === true && child.dispatchEvent) { 1717 | child.dispatchEvent(event); 1718 | } 1719 | 1720 | 1721 | } 1722 | 1723 | } 1724 | } 1725 | 1726 | 1727 | this.mousedown = function (event) { 1728 | 1729 | 1730 | 1731 | if (typeof (event.mouseX()) == "number" && typeof (event.mouseY()) == "number") { 1732 | 1733 | var gX = event.mouseX(); 1734 | var gY = event.mouseY(); 1735 | 1736 | var point = _xthis.globalToLocal(gX, gY); 1737 | 1738 | for (var i = 0; i < _xthis.numChildren(); i++) { 1739 | var child = _children[i]; 1740 | 1741 | var over = false; 1742 | 1743 | if (child && child.hitTest) { 1744 | over = child.hitTest(point); 1745 | } 1746 | 1747 | if (over === true && child.dispatchEvent) { 1748 | child.dispatchEvent(event); 1749 | } 1750 | 1751 | } 1752 | 1753 | } 1754 | } 1755 | 1756 | this.mouseup = function (event) { 1757 | 1758 | 1759 | 1760 | if (typeof (event.mouseX()) == "number" && typeof (event.mouseY()) == "number") { 1761 | 1762 | var gX = event.mouseX(); 1763 | var gY = event.mouseY(); 1764 | 1765 | var point = _xthis.globalToLocal(gX, gY); 1766 | 1767 | for (var i = 0; i < _xthis.numChildren(); i++) { 1768 | var child = _children[i]; 1769 | 1770 | var over = false; 1771 | 1772 | if (child && child.hitTest) { 1773 | over = child.hitTest(point); 1774 | } 1775 | 1776 | if (over === true && child.dispatchEvent) { 1777 | child.dispatchEvent(event); 1778 | } 1779 | 1780 | } 1781 | 1782 | } 1783 | } 1784 | 1785 | 1786 | this.bindDefault(ex.MOUSE_CLICK, this.mouseclick); 1787 | this.bindDefault(ex.MOUSE_OVER, this.mouseover); 1788 | this.bindDefault(ex.MOUSE_OUT, this.mousemove); 1789 | this.bindDefault(ex.MOUSE_DOWN, this.mousedown); 1790 | this.bindDefault(ex.MOUSE_UP, this.mouseup); 1791 | 1792 | _xthis = this; 1793 | 1794 | }, 1795 | 1796 | Event: function (type) { 1797 | 1798 | var _type = type; 1799 | var _target; 1800 | var _currentTarget; 1801 | 1802 | this.setTarget = function (t) { 1803 | _target = t; 1804 | } 1805 | 1806 | 1807 | this.setCurrentTarget = function () { 1808 | _currentTarget = ct; 1809 | } 1810 | 1811 | 1812 | this.type = function () { 1813 | return _type; 1814 | } 1815 | 1816 | this.getTarget = function () { 1817 | return _target; 1818 | } 1819 | 1820 | 1821 | this.getCurrentTarget = function () { 1822 | return _currentTarget; 1823 | } 1824 | 1825 | 1826 | 1827 | 1828 | } 1829 | 1830 | 1831 | } 1832 | 1833 | 1834 | var _exViews = []; 1835 | 1836 | var _ex = { 1837 | 1838 | 1839 | 1840 | /* 1841 | Constant: MOUSE_CLICK 1842 | Event type Mouse Click 1843 | */ 1844 | MOUSE_CLICK: "mouseClick", 1845 | 1846 | /* 1847 | Constant: MOUSE_MOVE 1848 | Event type Mouse Move 1849 | */ 1850 | MOUSE_MOVE: "mouseMove", 1851 | 1852 | /* 1853 | Constant: MOUSE_OVER 1854 | Event type Mouse Over 1855 | */ 1856 | MOUSE_OVER: "mouseOver", 1857 | 1858 | /* 1859 | Constant: MOUSE_OUT 1860 | Event type Mouse Out 1861 | */ 1862 | MOUSE_OUT: "mouseOut", 1863 | 1864 | /* 1865 | Constant: MOUSE_DOWN 1866 | Event type Mouse Down 1867 | */ 1868 | MOUSE_DOWN: "mouseDown", 1869 | 1870 | /* 1871 | Constant: MOUSE_UP 1872 | Event type Mouse Up 1873 | */ 1874 | MOUSE_UP: "mouseUp", 1875 | 1876 | 1877 | /* 1878 | Constant: HIT 1879 | Event type HIT*/ 1880 | HIT: "hit", 1881 | 1882 | 1883 | log: function () { 1884 | if (console && console.log) { 1885 | console.log(arguments); 1886 | } 1887 | }, 1888 | 1889 | matrix: { 1890 | 1891 | 1892 | 1893 | /* 1894 | Function: copyMatrix 1895 | Function that copies the elements of one matrix to another 1896 | 1897 | Parameters: 1898 | 1899 | m1 (object) - Target Matrix. 1900 | m2 (object) - Source Matrix. 1901 | 1902 | Returns: 1903 | 1904 | (void). 1905 | 1906 | See Also: 1907 | */ 1908 | copyMatrix: function (m1, m2) { 1909 | for (var x in m2) { 1910 | m1[x] = m2[x]; 1911 | } 1912 | }, 1913 | 1914 | 1915 | 1916 | /* 1917 | Function: multiply2DMatrix 1918 | Function that multiplies two 2D transformation matrices and returns the product matrix. 1919 | 1920 | Parameters: 1921 | 1922 | m1 (object) - First 2D transformation matrix. 1923 | m2 (object) - Second 2D transformation matrix. 1924 | 1925 | Returns: 1926 | 1927 | m1.m2 (object) - product of the two 2D transformation matrices. 1928 | 1929 | See Also: 1930 | */ 1931 | multiply2DMatrices: function (m1, m2) { 1932 | var r = {}; 1933 | r.a = m1.a * m2.a + m1.c * m2.b + m1.dx * m2.u; 1934 | r.c = m1.a * m2.c + m1.c * m2.d + m1.dx * m2.v; 1935 | r.dx = m1.a * m2.dx + m1.c * m2.dy + m1.dx * m2.w; 1936 | r.b = m1.b * m2.a + m1.d * m2.b + m1.dy * m2.u; 1937 | r.d = m1.b * m2.c + m1.d * m2.d + m1.dy * m2.v; 1938 | r.dy = m1.b * m2.dx + m1.d * m2.dy + m1.dy * m2.w; 1939 | r.u = m1.u * m2.a + m1.v * m2.b + m1.w * m2.u; 1940 | r.v = m1.u * m2.c + m1.v * m2.d + m1.w * m2.v; 1941 | r.w = m1.u * m2.dx + m1.v * m2.dy + m1.w * m2.w; 1942 | return r; 1943 | }, 1944 | 1945 | /* 1946 | Function: getDeterminant2D 1947 | Function that finds out the determinant value of a 2D transformation matrix. 1948 | 1949 | Parameters: 1950 | 1951 | m (object) - Transformation matrix. 1952 | 1953 | Returns: 1954 | 1955 | (number) - determinant value 1956 | 1957 | See Also: 1958 | */ 1959 | getDeterminant2D: function (m) { 1960 | var d = 0; 1961 | d += m.a * m.d * m.w; 1962 | d += m.c * m.dy * m.u; 1963 | d += m.dx * m.b * m.v; 1964 | d -= m.u * m.d * m.dx; 1965 | d -= m.v * m.dy * m.a; 1966 | d -= m.w * m.b * m.c; 1967 | return d; 1968 | }, 1969 | 1970 | 1971 | /* 1972 | Function: getTranspose2D 1973 | Function that returns the transpose of a 2D transformation matrix. 1974 | 1975 | Parameters: 1976 | 1977 | m (object) - Transformation matrix. 1978 | 1979 | Returns: 1980 | 1981 | (object) - Transpose of the matrix 1982 | 1983 | See Also: 1984 | */ 1985 | getTranspose2D: function (m) { 1986 | var t = {}; 1987 | t.a = m.a; 1988 | t.b = m.c; 1989 | t.u = m.dx; 1990 | t.c = m.b; 1991 | t.d = m.d; 1992 | t.v = m.dy; 1993 | t.dx = m.u; 1994 | t.dy = m.v; 1995 | t.w = m.w; 1996 | return t; 1997 | }, 1998 | 1999 | 2000 | /* 2001 | Function: getAdjoint2D 2002 | Function that returns the adjoint of a 2D transformation matrix. 2003 | 2004 | Parameters: 2005 | 2006 | m (object) - Transformation matrix. 2007 | 2008 | Returns: 2009 | 2010 | (object) - Adjoint of the matrix 2011 | 2012 | See Also: 2013 | */ 2014 | getAdjoint2D: function (m) { 2015 | var c = {}; 2016 | c.a = m.d * m.w - m.v * m.dy; 2017 | c.c = (-1) * (m.b * m.w - m.u * m.dy); 2018 | c.dx = m.b * m.v - m.u * m.d; 2019 | c.b = (-1) * (m.c * m.w - m.v * m.dx); 2020 | c.d = m.a * m.w - m.u * m.dx; 2021 | c.dy = (-1) * (m.a * m.v - m.u * m.c); 2022 | c.u = m.c * m.dy - m.d * m.dx; 2023 | c.v = (-1) * (m.a * m.dy - m.b * m.dx); 2024 | c.w = m.a * m.d - m.b * m.c; 2025 | return this.getTranspose2D(c); 2026 | }, 2027 | 2028 | 2029 | /* 2030 | Function: getInverse2D 2031 | Function that returns the inverse of a 2D transformation matrix. 2032 | 2033 | Parameters: 2034 | 2035 | m (object) - Transformation matrix. 2036 | 2037 | Returns: 2038 | 2039 | (object) - Inverse of the matrix 2040 | 2041 | See Also: 2042 | */ 2043 | getInverse2D: function (m) { 2044 | var d = this.getDeterminant2D(m); 2045 | var i = {}; 2046 | if (typeof (d) == "number" && d != 0) { 2047 | var f = 1 / d; 2048 | var a = this.getAdjoint2D(m); 2049 | for (var x in a) { 2050 | i[x] = a[x] * f; 2051 | } 2052 | } 2053 | return i; 2054 | } 2055 | 2056 | }, 2057 | 2058 | geometry: { 2059 | 2060 | 2061 | 2062 | /* 2063 | Function: rectToPoints 2064 | Function that returns or sets the four vertices of a rectangle object 2065 | 2066 | Parameters: 2067 | 2068 | rect (object) - Rectangle object ex: {x:0, y:0, w:100, h:100} 2069 | points (array) - This array is filled with the four vertices objects 2070 | 2071 | Returns: 2072 | 2073 | (array) - Array of four vertices of the rectangle object 2074 | 2075 | See Also: 2076 | */ 2077 | rectToPoints: function (rect, points) { 2078 | 2079 | var ps = [{ 2080 | x: rect.x, 2081 | y: rect.y 2082 | }, { 2083 | x: rect.x + rect.w, 2084 | y: rect.y 2085 | }, { 2086 | x: rect.x, 2087 | y: rect.y + rect.h 2088 | }, { 2089 | x: rect.x + rect.w, 2090 | y: rect.y + rect.h 2091 | } 2092 | 2093 | ]; 2094 | 2095 | 2096 | if (points) { 2097 | points[0] = ps[0]; 2098 | points[1] = ps[1]; 2099 | points[2] = ps[2]; 2100 | points[3] = ps[3]; 2101 | } 2102 | 2103 | return ps; 2104 | 2105 | }, 2106 | 2107 | 2108 | 2109 | /* 2110 | Function: pointsToRect 2111 | Function that sets the bounding rectangle of set of points 2112 | 2113 | Parameters: 2114 | 2115 | points (array) - Array of point objects ex: [{x:0, y:10}, {x:-9, y:-8}] 2116 | rect (object) - x, y , w, h properties of this object is set 2117 | 2118 | Returns: 2119 | 2120 | (void) 2121 | 2122 | See Also: 2123 | */ 2124 | pointsToRect: function (points, rect) { 2125 | 2126 | 2127 | for (var i = 0; i < points.length; i++) { 2128 | 2129 | var p = points[i]; 2130 | 2131 | if (rect.x1 == undefined) { 2132 | rect.x1 = p.x; 2133 | } 2134 | 2135 | if (rect.x2 == undefined) { 2136 | rect.x2 = p.x; 2137 | } 2138 | 2139 | rect.x1 = Math.min(p.x, rect.x1); 2140 | rect.x2 = Math.max(p.x, rect.x2); 2141 | 2142 | if (rect.y1 == undefined) { 2143 | rect.y1 = p.y; 2144 | } 2145 | 2146 | if (rect.y2 == undefined) { 2147 | rect.y2 = p.y; 2148 | } 2149 | 2150 | rect.y1 = Math.min(p.y, rect.y1); 2151 | rect.y2 = Math.max(p.y, rect.y2); 2152 | 2153 | 2154 | rect.x = rect.x1; 2155 | rect.y = rect.y1; 2156 | rect.w = rect.x2 - rect.x1; 2157 | rect.h = rect.y2 - rect.y1; 2158 | 2159 | } 2160 | 2161 | }, 2162 | 2163 | /* 2164 | Function: intersects 2165 | Checks whether the given rectangles intersect 2166 | 2167 | Parameters: 2168 | 2169 | rect1 (object) - x, y , w, h 2170 | rect2 (object) - x, y , w, h 2171 | 2172 | Returns: 2173 | 2174 | (false/object) the intersection rectangle object if they intersect else 2175 | 2176 | See Also: 2177 | */ 2178 | intersects: function (rect1, rect2) { 2179 | 2180 | 2181 | if ( 2182 | typeof (rect1) == "object" && typeof (rect1.x) == "number" && typeof (rect1.y) == "number" && typeof (rect1.w) == "number" && typeof (rect1.h) == "number" && typeof (rect1) == "object" && typeof (rect2.x) == "number" && typeof (rect2.y) == "number" && typeof (rect2.w) == "number" && typeof (rect2.h) == "number") { 2183 | 2184 | var intersection = {}; 2185 | 2186 | intersection.x = Math.max(rect1.x, rect2.x); 2187 | intersection.y = Math.max(rect1.y, rect2.y); 2188 | 2189 | intersection.w = Math.min((rect1.x + rect1.w), (rect2.x + rect2.w)) - intersection.x; 2190 | intersection.h = Math.min((rect1.y + rect1.h), (rect2.y + rect2.h)) - intersection.y; 2191 | 2192 | if (typeof (intersection.x) == "number" && typeof (intersection.y) == "number" && typeof (intersection.w) == "number" && typeof (intersection.h) == "number" && intersection.w > 0 && intersection.h > 0) { 2193 | return intersection; 2194 | } 2195 | 2196 | return false; 2197 | } 2198 | 2199 | return false; 2200 | 2201 | }, 2202 | 2203 | /* 2204 | Function: isPointInside 2205 | Checks whether the given point is inside the given rectangle 2206 | 2207 | Parameters: 2208 | 2209 | point (object) - a point object ex: {x:0, y:10}, {x:-9, y:-8} 2210 | rect (object) - x, y , w, h 2211 | 2212 | Returns: 2213 | 2214 | (boolean) true if the point is inside and false if point is outside 2215 | 2216 | See Also: 2217 | */ 2218 | isPointInside: function (point, rect) { 2219 | 2220 | 2221 | if (typeof (point.x) == "number" && typeof (point.y) == "number" && typeof (rect.x) == "number" && typeof (rect.y) == "number" && typeof (rect.w) == "number" && typeof (rect.h) == "number") { 2222 | 2223 | if (rect.x <= point.x && (rect.x + rect.w) >= point.x && rect.y <= point.y && (rect.y + rect.h) >= point.y) { 2224 | 2225 | return true; 2226 | 2227 | } 2228 | 2229 | 2230 | } 2231 | 2232 | 2233 | return false; 2234 | 2235 | }, 2236 | 2237 | 2238 | 2239 | 2240 | /* 2241 | Function: getVector 2242 | Returns a vector object {x,y,value} 2243 | 2244 | Parameters: 2245 | 2246 | vx (number) - horizontal component 2247 | vy (number) - vertical component 2248 | 2249 | Returns: 2250 | 2251 | (object) 2252 | 2253 | See Also: 2254 | */ 2255 | getVector: function (vx, vy) { 2256 | 2257 | 2258 | /* Class: Vector 2259 | Returns a Vector class 2260 | 2261 | */ 2262 | return { 2263 | 2264 | x: typeof (vx) != 'undefined' ? vx : 0, 2265 | y: typeof (vy) != 'undefined' ? vy : 0, 2266 | /* 2267 | Function: value 2268 | Returns the magnitude of this vector 2269 | 2270 | Parameters: 2271 | 2272 | Returns: 2273 | (number) 2274 | 2275 | See Also: 2276 | */ 2277 | value: function () { 2278 | return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2)); 2279 | } 2280 | 2281 | } 2282 | 2283 | 2284 | }, 2285 | 2286 | 2287 | getCanvasPoint: function (canvas, mx, my) { 2288 | 2289 | var element = canvas; 2290 | var tx = 0, 2291 | ty = 0, 2292 | cx = 0, 2293 | cy = 0; 2294 | 2295 | while (element) { 2296 | tx += element.offsetLeft; 2297 | ty += element.offsetTop; 2298 | element = element.offsetParent; 2299 | } 2300 | 2301 | cx = mx - tx; 2302 | cy = my - ty; 2303 | 2304 | return { 2305 | x: cx, 2306 | y: cy 2307 | } 2308 | 2309 | 2310 | } 2311 | 2312 | }, 2313 | 2314 | 2315 | define: function (c, Def) { 2316 | _defs[c] = Def; 2317 | }, 2318 | 2319 | extend: function (b, c, Def) { 2320 | if (_defs[b]) { 2321 | Def.prototype = new _defs[b](); 2322 | _defs[c] = Def; 2323 | 2324 | } 2325 | }, 2326 | 2327 | inherit: function (c, ref) { 2328 | if (_defs[c]) { 2329 | ref.sup = _defs[c]; 2330 | } 2331 | }, 2332 | 2333 | set: function (props) { 2334 | for (var prop in props) { 2335 | this[prop] = props[prop]; 2336 | } 2337 | }, 2338 | 2339 | createView: function () { 2340 | 2341 | if (_defs["ExView"]) { 2342 | var exView = new _defs["ExView"](); 2343 | _exViews.push(exView); 2344 | return exView; 2345 | } 2346 | 2347 | }, 2348 | 2349 | createSprite: function (s, params) { 2350 | 2351 | s = (s) ? s : "ExSprite"; 2352 | 2353 | if (_defs[s]) { 2354 | var exSprite = new _defs[s](params); 2355 | return exSprite; 2356 | } 2357 | 2358 | }, 2359 | 2360 | mouseEvent: function (type, mx, my) { 2361 | 2362 | if (_defs["MouseEvent"]) { 2363 | var mouseEvent = new _defs["MouseEvent"](type, mx, my); 2364 | return mouseEvent; 2365 | } 2366 | 2367 | }, 2368 | 2369 | hitEvent: function (type, mx, my) { 2370 | 2371 | if (_defs["HitEvent"]) { 2372 | var hitEvent = new _defs["HitEvent"](type, mx, my); 2373 | return hitEvent; 2374 | } 2375 | 2376 | } 2377 | 2378 | 2379 | 2380 | }; 2381 | 2382 | 2383 | 2384 | _ex.extend("Event", "MouseEvent", function (type, mousepoint) { 2385 | 2386 | ex.inherit("Event", this); 2387 | this.sup.call(this, type); 2388 | 2389 | var _mouseX = mousepoint.x; 2390 | var _mouseY = mousepoint.y; 2391 | 2392 | this.mouseX = function (item) { 2393 | return _mouseX; 2394 | } 2395 | 2396 | 2397 | this.mouseY = function (item) { 2398 | return _mouseY; 2399 | } 2400 | 2401 | 2402 | }); 2403 | 2404 | _ex.extend("Event", "HitEvent", function (type, object, mouseX, mouseY) { 2405 | 2406 | ex.inherit("Event", this); 2407 | this.sup.call(this, type); 2408 | 2409 | var _object = object; 2410 | var _mouseX = mouseX; 2411 | var _mouseY = mouseY; 2412 | 2413 | 2414 | this.hitObject = function () { 2415 | return _object; 2416 | } 2417 | 2418 | 2419 | this.mouseX = function (item) { 2420 | return _mouseX; 2421 | } 2422 | 2423 | 2424 | this.mouseX = function (item) { 2425 | return _mouseY; 2426 | } 2427 | 2428 | 2429 | 2430 | }); 2431 | 2432 | 2433 | return _ex; 2434 | 2435 | 2436 | 2437 | })(); --------------------------------------------------------------------------------