diff --git a/deps/akihabara-core-1.3.1/GPL-LICENSE.txt b/deps/akihabara-core-1.3.1/GPL-LICENSE.txt new file mode 100644 index 0000000..11dddd0 --- /dev/null +++ b/deps/akihabara-core-1.3.1/GPL-LICENSE.txt @@ -0,0 +1,278 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. diff --git a/deps/akihabara-core-1.3.1/MIT-LICENSE.txt b/deps/akihabara-core-1.3.1/MIT-LICENSE.txt new file mode 100644 index 0000000..9e82c0c --- /dev/null +++ b/deps/akihabara-core-1.3.1/MIT-LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2010 Francesco Cottone, http://www.kesiev.com/ + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/deps/akihabara-core-1.3.1/README-AUDIO.markdown b/deps/akihabara-core-1.3.1/README-AUDIO.markdown new file mode 100644 index 0000000..b59adb4 --- /dev/null +++ b/deps/akihabara-core-1.3.1/README-AUDIO.markdown @@ -0,0 +1,7 @@ +Akihabara Audio +=============== + +* Make sure that you're using the latest version of your browser before using audio features. +* Firefox stable has little audio caching problem/slowdowns and sometime freezes - can't figure out if is plugin's fault. Seems fixed on nightly builds. Audio is not marked as experimental. +* For compatibility with Safari, every audio file used for games MUST be more than 1.5 seconds long. Add silence to reach the 1.5secs length. +* Safari is having troubles on downloading audio for unknown reasons. Seems fixed on nightly builds. For now AUDIO IS EXPERIMENTAL. \ No newline at end of file diff --git a/deps/akihabara-core-1.3.1/README.markdown b/deps/akihabara-core-1.3.1/README.markdown new file mode 100644 index 0000000..757ebda --- /dev/null +++ b/deps/akihabara-core-1.3.1/README.markdown @@ -0,0 +1,28 @@ +Akihabara +========= + +Akihabara is a set of libraries, tools and presets to create pixelated indie-style 8/16-bit era games in Javascript that runs in your browser without any Flash plugin, making use of a small small small subset of the HTML5 features, that are actually available on many modern browsers. + +Notes for developers +-------------------- + +* For maximum compatibility make sure that you're using the ["name"] for when setting object properties with reserved names like "goto" and "data" (Discovered during patching for Wii) +* Also do not use the comma after the last element of an array or a property of an object. Still work on many browsers but is broken for Opera Wii. (and probably IE, when will be supported) +* For making sure that your sub-scripts are loaded, try to add an "alert" at the end. Opera for Wii silently fail when there are syntax errors like the one explained before. +* Opera Wii wants that canvas have to be blitted at least once before being used - or fails with a browser crash! The built-in gbox.createCanvas was already fixed. Is a good thing to use that method for spawning canvas. + +Todo +---- + +* Akihabara needs to be documented! (Darren and Darius are wrapping up tutorials and docs! - some scripts for generating docs form sources are needed) +* Better embeddability keeping playability on mobile +* Solve randomly blinking sprites on Wii (?) + +Improvement +----------- + +* Audio compatibility *Work in progress* + +Nice to have +---- +* Networking \ No newline at end of file diff --git a/deps/akihabara-core-1.3.1/akihabara/buttons.png b/deps/akihabara-core-1.3.1/akihabara/buttons.png new file mode 100644 index 0000000..3b056bb Binary files /dev/null and b/deps/akihabara-core-1.3.1/akihabara/buttons.png differ diff --git a/deps/akihabara-core-1.3.1/akihabara/debugfont.png b/deps/akihabara-core-1.3.1/akihabara/debugfont.png new file mode 100644 index 0000000..3564b40 Binary files /dev/null and b/deps/akihabara-core-1.3.1/akihabara/debugfont.png differ diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/code.css b/deps/akihabara-core-1.3.1/akihabara/docs/code.css new file mode 100644 index 0000000..57271dc --- /dev/null +++ b/deps/akihabara-core-1.3.1/akihabara/docs/code.css @@ -0,0 +1,16 @@ +body { + margin: 0; +} +.KEYW { color: #6277AA; font-weight: bold; } +.COMM { color: #008200; } +.NUMB { color: #393;} +.STRN { color: #00d; } +.REGX { color: #339;} +.linenumber { + border-right: 7px solid #8DA6C6; + color: #fff; + font-style: normal; + font-weight: bold; + padding: 0 7px; + background: #6277AA; +} \ No newline at end of file diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/css/default.css b/deps/akihabara-core-1.3.1/akihabara/docs/css/default.css new file mode 100644 index 0000000..b9dde3b --- /dev/null +++ b/deps/akihabara-core-1.3.1/akihabara/docs/css/default.css @@ -0,0 +1,418 @@ +/* + * TABLE OF CONTENTS: + * - Browser reset + * - HTML elements + * - JsDoc styling + */ + + + + + + +/* + * BEGIN BROWSER RESET + */ + +body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,p,pre,form,fieldset,input,textarea,p,blockquote,th,td { + margin:0; + padding:0 +} +html { + height:100%; + overflow:-moz-scrollbars-vertical; + overflow-x:auto +} +table { + border:0; + border-collapse:collapse; + border-spacing:0 +} +fieldset,img { + border:0 +} +address,caption,cite,code,dfn,em,strong,th,var { + font-style:normal; + font-weight:normal +} +em,cite { + font-style:italic +} +strong { + font-weight:bold +} +ol,ul { + list-style:none +} +caption,th { + text-align:left +} +h1,h2,h3,h4,h5,h6 { + font-size:100%; + font-weight:normal; + margin:0; + padding:0 +} +q:before,q:after { + content:'' +} +abbr,acronym { + border:0 +} + +/* + * END BROWSER RESET + */ + + + + + + +/* + * HTML ELEMENTS + */ + +* { + line-height: 1.4em; +} + +html { + font-size: 100%; +} + +body { + font-size: 0.75em !important; + padding: 15px 0; + background: #eee; + background-image: -moz-linear-gradient(left, #dddddd, #f9f9f9); + background-image: -webkit-gradient(linear,left bottom,right bottom,color-stop(0, #dddddd),color-stop(1, #f9f9f9)); + } + +body, +input, +select, +textarea { + color: #000; + font-family: Arial, Geneva, sans-serif; +} + +a:link, +a:hover, +a:active, +a:visited { + color: #19199e; +} +a:hover, +a:focus { + color: #00f; + text-decoration: none; +} + +p { + margin: 0 0 1.5em 0; +} + +/* + * END HTML ELEMENTS + */ + + + +/* + * BEGIN HACK + */ + +div.containerMain:after, +div.safeBox:after { + content:""; + display:block; + height:0; + clear:both; +} + +/* + * END HACK + */ + + + +/* + * BEGIN JSDOC + */ + +div.index *.heading1 { + margin-bottom: 0.5em; + border-bottom: 1px solid #999999; + padding: 0.5em 0 0.1em 0; + font-family: 'Lucida Sans Unicode', 'Lucida Grande', sans-serif; + font-size: 1.3em; + letter-spacing: 1px; +} + +div.index { + float: left; + width: 30%; + min-width: 100px; + max-width: 250px; +} +div.index div.menu { + margin: 0 15px 0 -15px; + -moz-border-radius: 15px; + -webkit-border-radius: 15px; + border-radius: 15px; + padding: 15px 15px 15px 30px; + background-color: #FFFFFF; + background-color: rgba(255, 255, 255, 0.5); + -moz-box-shadow: 0px 0px 10px #c4c4c4; + -webkit-box-shadow: 0px 0px 10px #c4c4c4; + box-shadow: 0px 0px 10px #c4c4c4; +} +*+html div.index div.menu { + background-color: #FFFFFF; +} +* html div.index div.menu { + background-color: #FFFFFF; +} + +div.index div.menu div { + text-align: left; +} + +div.index div.menu a { + text-decoration: none; +} +div.index div.menu a:hover { + text-decoration: underline; +} + +div.index ul.classList a { + font-family: Consolas, "Courier New", Courier, monospace; +} + +div.index div.fineprint { + padding: 15px 30px 15px 15px; + color: #777; + font-size: 0.9em; +} +div.index div.fineprint a { + color: #777; +} + + + +div.content { + float: left; + width: 70%; + min-width: 300px; + max-width: 600px; +} +div.innerContent { + padding: 0 0 0 2.5em; +} + +div.content ul, +div.content ol { + margin-bottom: 3em; +} + +div.content *.classTitle { + margin-bottom: 0.5em; + font-family: 'Lucida Sans Unicode', 'Lucida Grande', sans-serif; + font-size: 2.5em; + letter-spacing: 2px; +} + +div.content *.classTitle span { + font-family: Consolas, "Courier New", Courier, monospace; +} + +div.content p.summary { + font-size: 1.2em; +} + +div.content ul *.classname a, +div.content ul *.filename a { + font-family: Consolas, "Courier New", Courier, monospace; + text-decoration: none; + font-weight: bold; +} +div.content ul *.classname a:hover, +div.content ul *.filename a:hover { + text-decoration: underline; +} + +div.content div.props { + position: relative; + left: -10px; + margin-bottom: 2.5em; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + border-radius: 5px; + padding: 10px 15px 15px 15px; + overflow: hidden; + background: #fff; + background: -moz-linear-gradient(top, rgba(255, 255, 255, 0.7), rgba(255, 255, 255, 0.2)); /* FF3.6 */ + background: -webkit-gradient(linear,left top,left bottom,color-stop(0, rgba(255, 255, 255, 0.7)),color-stop(1, rgba(255, 255, 255, 0.2))); + -moz-box-shadow: 0px 0px 10px #ccc; + -webkit-box-shadow: 0px 0px 5px #bbb; + box-shadow: 0px 0px 5px #bbb; +} + +div.content div.props div.sectionTitle { + padding-bottom: 10px; + font-family: 'Lucida Sans Unicode', 'Lucida Grande', sans-serif; + font-size: 1.4em; + letter-spacing: 1px; +} + +div.content div.hr { + margin: 0 10px 0 0; + height: 4em; +} + + + +table.summaryTable { + position: relative; + left: -10px; + width: 100%; + border-collapse: collapse; + box-sizing: content-box; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + -ms-box-sizing: content-box; + -o-box-sizing: content-box; + -icab-box-sizing: content-box; + -khtml-box-sizing: content-box; +} + +table.summaryTable caption { + padding: 0 10px 10px 10px; + font-family: 'Lucida Sans Unicode', 'Lucida Grande', sans-serif; + font-size: 1.4em; + letter-spacing: 1px; +} + +table.summaryTable td, +table.summaryTable th { + padding: 0px 10px 10px 10px; + vertical-align: top; +} +table.summaryTable tr:last-child td { + padding-bottom: 0; +} + +table.summaryTable th { + font-weight: bold; +} + +table.summaryTable td.attributes { + width: 35%; + font-family: Consolas, "Courier New", Courier, monospace; + color: #666; +} + +table.summaryTable td.nameDescription { + width: 65% +} + +table.summaryTable td.nameDescription div.fixedFont { + font-weight: bold; +} + +table.summaryTable div.description { + color: #333; +} + + + +dl.detailList { + margin-top: 0.5em; +} + +dl.detailList.nomargin + dl.detailList.nomargin { + margin-top: 0; +} + +dl.detailList dt { + display: inline; + margin-right: 5px; + font-weight: bold; +} + +dl.detailList dt:before { + display: block; + content: ""; +} + +dl.detailList dd { + display: inline; +} + +dl.detailList.params dt { + display: block; +} +dl.detailList.params dd { + display: block; + padding-left: 2em; + padding-bottom: 0.4em; +} + + + + +ul.fileList li { + margin-bottom: 1.5em; +} + + + +.fixedFont { + font-family: Consolas, "Courier New", Courier, monospace; +} + +.fixedFont.heading { + margin-bottom: 0.5em; + font-size: 1.25em; + line-height: 1.1em +} + +.fixedFont.heading + .description { + font-size: 1.2em; +} + +.fixedFont.heading .light, +.fixedFont.heading .lighter { + font-weight: bold; +} + +pre.code { + margin: 10px 0 10px 0; + padding: 10px; + border: 1px solid #ccc; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + border-radius: 2px; + overflow: auto; + font-family: Consolas, "Courier New", Courier, monospace; + background: #eee; +} + +.light { + color: #666; +} + +.lighter { + color: #999; +} + +.clear { + clear: both; + width: 100%; + min-height: 0; +} + +/* + * END JSDOC + */ \ No newline at end of file diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/default.css b/deps/akihabara-core-1.3.1/akihabara/docs/default.css new file mode 100644 index 0000000..84c1a4d --- /dev/null +++ b/deps/akihabara-core-1.3.1/akihabara/docs/default.css @@ -0,0 +1,440 @@ +/* --- Basic Layout -------------------------------------------------------- */ +/* For IE for Windows \*/ +* html{ + width: 100%; + height: 100%; + overflow: hidden; +} +* html body{ + width: 100%; + height: 100%; + overflow: auto; +} + +* html .fixed{ + position: absolute; +} +.fixed { + position: fixed; + overflow: auto; +} +/* */ +/* --- Basic Layout -------------------------------------------------------- */ +body { + padding: 0; + margin: 0; + background: #fafafa; + font: 100% Verdana, Arial, Helvetica, sans-serif; +} + +#main { + border-left: 0.625em #356aa0 solid; + margin-left: 16.25em; +} + +#index { + top: 0; + left: 0; + width: 16.25em; + height: 100%; + overflow: auto; + overflow-x: hidden; + border-right: 0.625em solid #356aa0; +} +/* --- General layout ------------------------------------------------------ */ +h1 { + margin: 0.625em 0 0.625em; + font-size: 1.5em; + font-weight: bold; +} + +h1.classTitle { + color: #007b00; + font-size: 1.5em; + line-height:130%; +} + +h2 { + font-size: 1.25em; + color: #6277AA; + margin: 2em 0pt 1em; +} + +h3 { + font-size: 1.1em; + color: #6277AA; +} + +p { + margin: 1em 0; + text-align: justify; +} + +a:link { + color: #001C58; +} + +a:visited { + color: #6277AA; +} + +hr { + border: none 0; + border-top: 0.0625em solid #7f8fb1; + height: 0.0625em; +} + +.invisible { + display: none !important; +} + +.clear { + clear: both; + line-height: 0.0625em; +} + +.description { + font: 0.8125em Verdana, Arial; + line-height: 0.9375em; + padding: 0.25em; + padding-left: 0.25em; +} + +.fineprint { + padding-top: 1.25em; + text-align: right; + font-size: 0.625em; +} + +div.sectionTitle { + background-color: #356aa0; + color: #fff; + font-size: 1.1em; + font-weight: bold; + text-align: left; + padding: 0.125em 0.5em 0.125em 0.5em; + border: 0.0625em #7F8FB1 solid; +} + +/* --- Index toggler ------------------------------------------------------- */ +#index-toggler { + width: 1em; + top: 0.25em; + left: 16.25em; + cursor: pointer; + font-weight: bold; + font-family: Arial; + font-size: 1em; + color: #fff; + z-index: 100; +} +#index-close { + background: url(images/never_translate.png) no-repeat left; + height: 1em; + width: 1em; + float: left; + cursor: pointer; + margin: 0.0625em 0.25em; + display: inline; +} +body.index-collapsed { background-position: 0; } +body.index-collapsed #main { margin-left: 0; } +body.index-collapsed #index { width: 0; } +body.index-collapsed #index-wrapper { display: none; } +body.index-collapsed #index-toggler { left: 0; } + +/* --- Module Filter ------------------------------------------------------- */ +.module-filter { + display: inline; + float: left; + cursor: pointer; + width: 4em; + font-size: 0.8em; + text-align: center; + padding-top: 0.125em; +} +.module-filter, .module-filter a { + text-decoration: none; + color: #007B00 !important; +} +body.filter .sectionItem { display: none; } +body.filter .module-filter, body.filter .module-filter a { color: red !important; } +body.filter.module-core .module-core { display: block; } +body.filter.module-dom .module-dom { display: block; } +body.filter.module-css .module-css { display: block; } +body.filter.module-ajax .module-ajax { display: block; } +body.filter.module-event .module-event { display: block; } + +/* --- Method Toggler ------------------------------------------------------ */ +.method-toggler { + background: url(images/minus.gif) no-repeat left; + cursor: pointer; + float: left; + width: 0.875em; + height: 0.875em; +} +.method-toggler.toggled { + background: url(images/plus.gif) no-repeat left; +} + +/* --- Class Name and File Name Icons -------------------------------------- */ +.itemName .icon, .itemName .icon a { + color: #007B00 !important; +} +.itemName .icon { + font-size: 1em; + font-weight: bold; + padding: 0 0 0.125em 1.5em; +} + +.itemName .icon { + background: url(images/class_obj.png) no-repeat left; +} + +.itemName.namespace .icon { + background-image: url(images/namespace_obj.png) !important; +} + +.itemName.namespace-function .icon { + background-image: url(images/namespace_function_obj.png) !important; +} + +.fileName .icon { + background: url(images/file_obj.png) no-repeat left !important; +} + +/* --- Class Method and Property Icons ------------------------------------- */ +div.classMethod .icon { + padding-left: 1.275em; + background: url(images/method_public_obj.png) no-repeat left; +} + +div.classMethod .private { + background-image: url(images/method_private_obj.png) !important; +} + +div.classProperty .icon { + padding-left: 1.275em; + background: url(images/field_public_obj.png) no-repeat left; +} + +div.classProperty .private { + background-image: url(images/field_private_obj.png) !important; +} + + +/* --- Headers ------------------------------------------------------------- */ +.header { + color: #fff; + font-weight: bold; + font-size: 1.4em; + height: 1.2em; + background: #356aa0; + padding: 0.15em 0.4375em; +} + +#index .header { + padding: 0.5em 0 0 0; + height: 1.625em; + font-size: 1em; + background: #356aa0; +} + +/* --- Main/Index Shared Layouts ------------------------------------------- */ +#content .section { + margin-top: 1.5em; +} + +div.classList { + padding: 0.625em; + font-family: arial, sans-serif; + font-size: 0.75em; +} + +div.sectionItem .signature { + color: #000; + margin-left: 0.250em; + font-weight: normal; +} + +.help, div.sectionItem .signature span { + cursor: help; +} + +/* --- Main layout --------------------------------------------------------- */ +#main .full-description { + font-size: 0.9em; + line-height: 135%; +} + +#main code { + font-size: 1.1em; + font-weight: bold; + color: #666; +} + +html:not([lang*=""]) #main code { + font-size: 1.4em !important; /* Firefox hack */ +} + +#main p p, #main .full-description p, #main span a { + font-size: 1em; +} + +#content { + padding: 0 1.25em 1.25em 1.25em; +} + +#main .sectionItem { + background: #fff; + padding-left: 0.8em; +} + +#main .sectionItem .description { + font-size: 0.8em; + padding-left: 0.4375em; + color: #777; +} + +#main .summary .sectionItems, #main .details .sectionItem { + border: 0.25em #8DA6C6 solid; + padding: 0.625em; +} + +/* --- Summary layout ------------------------------------------------------ */ +#main .summary { + background: #fff; +} + +#main .summary .sectionItems { + border-width: 0.125em 0.125em 0.250em; +} + +#main .summary .sectionItem { + padding: 0 0 0.3em 1.6em; + font-family: Verdana, Arial; + font-size: 0.875em; +} + +#main .summary .sectionItem b { + margin-left: -1.4286em; +} + +#main .summary .module-filter { + margin-left: -5.3571em; +} + +/* --- Details layout ------------------------------------------------------ */ +#main .details .module-filter { + font-size: 70%; +} + +#main .details .sectionItem { + border-width: 0.125em 0.125em 0.250em; + margin-bottom: 0.75em; +} + +#main .details .itemTitle { + color: #001C58; + font-family: Verdana; + font-weight: bold; + font-size: 1em; + display: inline; +} + +#main .details .itemTitle .light { + font-size: 0.9em; +} + +#main .details .full-description { + padding: 0 0.625em; +} + + +.light, .light a:link, .light a:visited { + color: #777; + font-weight: normal; + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; +} + +/* --- Details data -------------------------------------------------------- */ +table.methodItem { + font-size: 0.8em; +} +table.methodItem p { + margin: 0; +} +table.methodItem td { + padding: 0 0.1em 0.1em; + vertical-align: text-top; +} +table.methodItem .methodItemType { + text-align: center; +} +div.heading { + color: #6277AA; + font-size: 0.875em; + font-weight: bold; + margin: 0.625em 0 0; +} + +/* --- Index Layout -------------------------------------------------------- */ +#index-wrapper { + width: 100%; +} + +#index-menu { + background: #8DA6C6; + color: #fff; + text-align: center; + padding: 0.125em 0 0.25em; + font-weight: bold; + font-size: 0.9em; +} + +#index-menu a:link, #index-menu a:visited { + color: #fff; +} + +#index-title { + float: left; +} + +#index-content { + background: #fff; + border: 0 #8DA6C6 solid; + border-width: 0 0 0.25em; + font-size: 1.1em; +} + +#index-content .signature { + font-size: 0.85em; +} + +#index .section { + padding-bottom: 0.625em; +} + +/* --- Class index / File index layout ------------------------------------- */ +* html #content.index-page { + width: 92%; /* IE only hack para evitar bug no layout */ +} + +#content.index-page .sectionItem { + padding: 0.125em; +} + +#content.index-page .sectionItems { + border-top-width: 0.125em; +} + +#content.index-page .summary { + margin: 0; +} + +/* --- Hide private members ------------------------------------------------ */ +/* +div.sectionItem.private { + display: none !important; +} +/**/ diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/files.html b/deps/akihabara-core-1.3.1/akihabara/docs/files.html new file mode 100644 index 0000000..6085b5a --- /dev/null +++ b/deps/akihabara-core-1.3.1/akihabara/docs/files.html @@ -0,0 +1,180 @@ + + + + + + JsDoc Reference - File Index + + + + + + + + +
+
+
+
+
+
 
+
Project Outline
+
+ + +
+ +
+ + + +
+
createMaingame(id, group)
+ +
+
+
 
gbox
addAudio(id, filename, def)
addBundle(call)
addFont(data)
addImage(id, filename)
addObject(data)
addScript(call)
blit(tox, image, data)
blitAll(tox, image, data)
blitClear(image, data)
blitFade(tox, data)
blitRect(tox, data)
blitText(tox, data)
blitTile(tox, data)
blitTilemap(tox, data)
centerCamera(data, viewdata)
collides(o1, o2, t)
createCanvas(id, data)
dataLoad(k, a)
dataSave(k, v, d)
getObject(group, id)
go()
hitAudio(a, data)
log()
pixelcollides(o1, o2, t)
playAudio(a, data)
readBundleData(pack, call)
setCameraX(x, viewdata)
setCameraY(y, viewdata)
setZindex(th, z)
stopAudio(a, permissive)
trashGroup(group)
+ +
+
+
 
help
asciiArtToMap(map, tra)
copyModel(data, model)
createModel(obj, attrs)
decideFrame(cnt, anim)
decideFrameOnce(cnt, anim)
framestotime(frames)
getArrayIndexed(a, value, field)
getTileInMap(x, y, map, ifout, mapid)
isLastFrameOnce(cnt, anim)
isSquished(th, by)
limit(v, min, max)
mergeWithModel(data, model)
multiplier(v, mul)
postpad(str, len, pad)
prepad(str, len, pad)
random(min, range)
seq(st, ed, skip)
setTileInMap(ctx, map, x, y, tile, The)
upAndDown(counter, max)
xPixelToTile(map, x, gap)
xPixelToTileX(map, x, gap)
yPixelToTile(map, y, gap)
yPixelToTileY(map, y, gap)
+ +
+
bounce(th, data)
horizontalKeys(th, keys)
horizontalTileCollision(th, map, tilemap)
initialize(th, data)
jumpKeys(th, key)
spawn(th, data)
verticalTileCollision(th, map, tilemap)
+ +
+
controlKeys(th, keys)
fireBullet(gr, id, data)
generateEnemy(gr, id, data, model)
generateScroller(gr, id, data)
hitByBullet(th, by)
initialize(th, data)
spawn(th, data)
+ +
+
after(th, id, frames)
every(th, id, frames)
randomly(th, id, data)
real(th, id, data)
+ +
+
+
 
tool
makecels(data)
+ +
+
callInColliding(th, data)
collides(fr, to, t)
controlKeys(th, keys)
fireBullet(gr, id, data)
floorCollision(th, data)
getAheadPixel(th, data)
initialize(th, data)
makedoor(gr, id, map, data)
pixelcollides(fr, to, t)
setStaticSpeed(th, speed)
spawn(th, data)
tileCollision(th, map, tilemap, defaulttile, data)
wander(th, map, tilemap, defaulttile, data)
+ + + +
+
+
 
trigo
addAngle(a, add)
getAngle(p1, p2, transl)
getDistance(p1, p2)
translate(p1, a, d)
translateX(x1, a, d)
translateY(y1, a, d)
+ +
+
+
+ + +
+
«
+ +
+ Akihabara Framework +
+ + +
+ +

File Index

+ +
+
+ +
+ gamecycle.js c:\Users\Darius\Desktop\akihabara-1.1\kesiev\akihabara\akihabara\trigo.js + +
+ + +
+
+ +
+ gbox.js c:\Users\Darius\Desktop\akihabara-1.1\kesiev\akihabara\akihabara\trigo.js + +
+ + +
+
+ +
+ help.js c:\Users\Darius\Desktop\akihabara-1.1\kesiev\akihabara\akihabara\trigo.js + +
+ + +
+
+ +
+ iphofretboard.js c:\Users\Darius\Desktop\akihabara-1.1\kesiev\akihabara\akihabara\trigo.js + +
+ + +
+
+ +
+ iphopad.js c:\Users\Darius\Desktop\akihabara-1.1\kesiev\akihabara\akihabara\trigo.js + +
+ + +
+
+ +
+ tool.js c:\Users\Darius\Desktop\akihabara-1.1\kesiev\akihabara\akihabara\trigo.js + +
+ + +
+
+ +
+ toys.js c:\Users\Darius\Desktop\akihabara-1.1\kesiev\akihabara\akihabara\trigo.js + +
+ + +
+
+ +
+ trigo.js c:\Users\Darius\Desktop\akihabara-1.1\kesiev\akihabara\akihabara\trigo.js + +
+ + +
+
+ +
+
+ +
+ +
+ + Documentation generated by JsDoc Toolkit 2.3.2 on Wed Aug 18 2010 16:09:26 GMT-0400 (EDT) +
+
+
+ + + diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/images/bg.png b/deps/akihabara-core-1.3.1/akihabara/docs/images/bg.png new file mode 100644 index 0000000..2a69cea Binary files /dev/null and b/deps/akihabara-core-1.3.1/akihabara/docs/images/bg.png differ diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/images/class_default_obj.png b/deps/akihabara-core-1.3.1/akihabara/docs/images/class_default_obj.png new file mode 100644 index 0000000..8d42ac8 Binary files /dev/null and b/deps/akihabara-core-1.3.1/akihabara/docs/images/class_default_obj.png differ diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/images/class_obj.png b/deps/akihabara-core-1.3.1/akihabara/docs/images/class_obj.png new file mode 100644 index 0000000..b763245 Binary files /dev/null and b/deps/akihabara-core-1.3.1/akihabara/docs/images/class_obj.png differ diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/images/collapsebtn.gif b/deps/akihabara-core-1.3.1/akihabara/docs/images/collapsebtn.gif new file mode 100644 index 0000000..baa80eb Binary files /dev/null and b/deps/akihabara-core-1.3.1/akihabara/docs/images/collapsebtn.gif differ diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/images/expandbtn.gif b/deps/akihabara-core-1.3.1/akihabara/docs/images/expandbtn.gif new file mode 100644 index 0000000..39737e3 Binary files /dev/null and b/deps/akihabara-core-1.3.1/akihabara/docs/images/expandbtn.gif differ diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/images/field_private_obj.png b/deps/akihabara-core-1.3.1/akihabara/docs/images/field_private_obj.png new file mode 100644 index 0000000..e88e002 Binary files /dev/null and b/deps/akihabara-core-1.3.1/akihabara/docs/images/field_private_obj.png differ diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/images/field_public_obj.png b/deps/akihabara-core-1.3.1/akihabara/docs/images/field_public_obj.png new file mode 100644 index 0000000..6c163f5 Binary files /dev/null and b/deps/akihabara-core-1.3.1/akihabara/docs/images/field_public_obj.png differ diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/images/file_obj.png b/deps/akihabara-core-1.3.1/akihabara/docs/images/file_obj.png new file mode 100644 index 0000000..24ed3ea Binary files /dev/null and b/deps/akihabara-core-1.3.1/akihabara/docs/images/file_obj.png differ diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/images/method_private_obj.png b/deps/akihabara-core-1.3.1/akihabara/docs/images/method_private_obj.png new file mode 100644 index 0000000..bf432c0 Binary files /dev/null and b/deps/akihabara-core-1.3.1/akihabara/docs/images/method_private_obj.png differ diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/images/method_public_obj.png b/deps/akihabara-core-1.3.1/akihabara/docs/images/method_public_obj.png new file mode 100644 index 0000000..a032863 Binary files /dev/null and b/deps/akihabara-core-1.3.1/akihabara/docs/images/method_public_obj.png differ diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/images/minus.gif b/deps/akihabara-core-1.3.1/akihabara/docs/images/minus.gif new file mode 100644 index 0000000..90d1d34 Binary files /dev/null and b/deps/akihabara-core-1.3.1/akihabara/docs/images/minus.gif differ diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/images/namespace_function_obj.png b/deps/akihabara-core-1.3.1/akihabara/docs/images/namespace_function_obj.png new file mode 100644 index 0000000..3b3b7ef Binary files /dev/null and b/deps/akihabara-core-1.3.1/akihabara/docs/images/namespace_function_obj.png differ diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/images/namespace_obj.png b/deps/akihabara-core-1.3.1/akihabara/docs/images/namespace_obj.png new file mode 100644 index 0000000..3021c8a Binary files /dev/null and b/deps/akihabara-core-1.3.1/akihabara/docs/images/namespace_obj.png differ diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/images/never_translate.png b/deps/akihabara-core-1.3.1/akihabara/docs/images/never_translate.png new file mode 100644 index 0000000..204f5e7 Binary files /dev/null and b/deps/akihabara-core-1.3.1/akihabara/docs/images/never_translate.png differ diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/images/plus.gif b/deps/akihabara-core-1.3.1/akihabara/docs/images/plus.gif new file mode 100644 index 0000000..014671f Binary files /dev/null and b/deps/akihabara-core-1.3.1/akihabara/docs/images/plus.gif differ diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/index.html b/deps/akihabara-core-1.3.1/akihabara/docs/index.html new file mode 100644 index 0000000..37be46d --- /dev/null +++ b/deps/akihabara-core-1.3.1/akihabara/docs/index.html @@ -0,0 +1,255 @@ + + + + + + JsDoc Reference - Index + + + + + + + + + + + + + +
+
+ +
+
+
+
 
+
Project Outline
+
+ + +
+ +
+ + + +
+
createMaingame(id, group)
+ +
+
+
 
gbox
addAudio(id, filename, def)
addBundle(call)
addFont(data)
addImage(id, filename)
addObject(data)
addScript(call)
blit(tox, image, data)
blitAll(tox, image, data)
blitClear(image, data)
blitFade(tox, data)
blitRect(tox, data)
blitText(tox, data)
blitTile(tox, data)
blitTilemap(tox, data)
centerCamera(data, viewdata)
collides(o1, o2, t)
createCanvas(id, data)
dataLoad(k, a)
dataSave(k, v, d)
getObject(group, id)
go()
hitAudio(a, data)
log()
pixelcollides(o1, o2, t)
playAudio(a, data)
readBundleData(pack, call)
setCameraX(x, viewdata)
setCameraY(y, viewdata)
setZindex(th, z)
stopAudio(a, permissive)
trashGroup(group)
+ +
+
+
 
help
asciiArtToMap(map, tra)
copyModel(data, model)
createModel(obj, attrs)
decideFrame(cnt, anim)
decideFrameOnce(cnt, anim)
framestotime(frames)
getArrayIndexed(a, value, field)
getTileInMap(x, y, map, ifout, mapid)
isLastFrameOnce(cnt, anim)
isSquished(th, by)
limit(v, min, max)
mergeWithModel(data, model)
multiplier(v, mul)
postpad(str, len, pad)
prepad(str, len, pad)
random(min, range)
seq(st, ed, skip)
setTileInMap(ctx, map, x, y, tile, The)
upAndDown(counter, max)
xPixelToTile(map, x, gap)
xPixelToTileX(map, x, gap)
yPixelToTile(map, y, gap)
yPixelToTileY(map, y, gap)
+ +
+
bounce(th, data)
horizontalKeys(th, keys)
horizontalTileCollision(th, map, tilemap)
initialize(th, data)
jumpKeys(th, key)
spawn(th, data)
verticalTileCollision(th, map, tilemap)
+ +
+
controlKeys(th, keys)
fireBullet(gr, id, data)
generateEnemy(gr, id, data, model)
generateScroller(gr, id, data)
hitByBullet(th, by)
initialize(th, data)
spawn(th, data)
+ +
+
after(th, id, frames)
every(th, id, frames)
randomly(th, id, data)
real(th, id, data)
+ +
+
+
 
tool
makecels(data)
+ +
+
callInColliding(th, data)
collides(fr, to, t)
controlKeys(th, keys)
fireBullet(gr, id, data)
floorCollision(th, data)
getAheadPixel(th, data)
initialize(th, data)
makedoor(gr, id, map, data)
pixelcollides(fr, to, t)
setStaticSpeed(th, speed)
spawn(th, data)
tileCollision(th, map, tilemap, defaulttile, data)
wander(th, map, tilemap, defaulttile, data)
+ + + +
+
+
 
trigo
addAngle(a, add)
getAngle(p1, p2, transl)
getDistance(p1, p2)
translate(p1, a, d)
translateX(x1, a, d)
translateY(y1, a, d)
+ +
+
+
+ + +
+
«
+ +
+ Akihabara Framework +
+ + +
+ +

Class Index

+ +
+
+ +
+ + + _global_ +
+

+ Global namespace. +

+
+ +
+ +
+ + gamecycle +
+ Gamecycle contains your basic game loop: intro, menus, crossfading between stages/lifes, gameover and ending. +
+ + +
+ +
+ + gbox +
+ Gamebox module allows multiple grouped objects to move simultaneously, it helps with collisions, rendering and moving objects. It also provides monospaced pixel-font rendering, keyboard handling, audio, double buffering and eventually FSEs. Gamebox can also store and load data from cookies! +
+ + +
+ +
+ + help +
+ Help module provides some Javascript-specific functions, such object copying, randomizing functions, string/array handlers and the akihabaraInit function. +
+ + +
+ +
+ + toys.platformer +
+ platformer The libraries for generating a 2D platformer game. +
+ + +
+ +
+ + toys.shmup +
+ shmup The libraries for a 2D top-down Shmup game. +
+ + +
+ +
+ + toys.timer +
+ timer Timer functionality based methods +
+ + +
+ +
+ + tool +
+ Tool module provides simple developing tools. Currently, this file only has a cel-composer: +it can compose an image stacking a set of frames for animating objects, applying a +number of filters to each frame. +
+ + +
+ +
+ + toys.topview +
+ Top-view RPG specific libraries. +
+ + +
+ +
+ + toys +
+ Toys module provides lots of common routines during the game developing: +from effects for screen titles to HUD handling to platform/SHMUP/RPG oriented routines, +like jumping characters, Z-Indexed objects, bullets, sparks, staff rolls, bonus screens, dialogues etc. +
+ + +
+ +
+ + trigo +
+ Trigo module provides some math stuff for moving objects in a direction or following a round path. +
+ + +
+ +
+
+ +
+
+ + Documentation generated by JsDoc Toolkit 2.3.2 on Wed Aug 18 2010 16:09:26 GMT-0400 (EDT) +
+
+
+ + + diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/jproton.js b/deps/akihabara-core-1.3.1/akihabara/docs/jproton.js new file mode 100644 index 0000000..40dacbc --- /dev/null +++ b/deps/akihabara-core-1.3.1/akihabara/docs/jproton.js @@ -0,0 +1 @@ +(function(){window.jProton=function(selector,context){return new jProton.Set().select(selector,context)};window.$=jProton;jProton.namespace=function(ns){if(!ns){return }var n=ns.split(".");var target=window,o;for(var i=0,ni;ni=n[i];i++){target=(o=target[ni])?o:target[ni]={}}return target};jProton.extend=function(){var target=this,t=target,source,p,o,a0=arguments[0],ai=0,al=arguments.length;if(al>1){ai++;target=t=a0}for(;source=arguments[ai];ai++){for(var prop in source){p=source[prop];if(prop.charAt(0)!="@"){if(p&&p.splice){var tp=t[prop];t[prop]=tp&&tp.splice?tp.concat(p):new Array().concat(p)}else{if(p&&typeof p=="object"){t[prop]=jProton.extend(t[prop]||{},p)}else{t[prop]=p}}}else{if(prop=="@init"){p.call(t)}else{if(prop=="@require"){for(var ext in p){var v=p[ext];o=t.extensions[ext]||null;if(!o){throw'A extensão "'+ext+'" deve estar instalada.'}else{if(o=0){this.removeClass(e,name)}else{this.addClass(e,name)}},css:function(e,name,val){if(e){if(val){e.style[name]=val}else{var type=typeof name;if(type=="object"){for(p in name){e.style[p]=name[p]}}else{return window.getComputedStyle?document.defaultView.getComputedStyle(e,null)[name]||e.style[name]:e.currentStyle?e.currentStyle[name]||e.style[name]:undefined}}}else{return undefined}}});set.extend({"@extension":{css:"0.3.0a"},hasClass:function(name){return this[0]?(" "+this[0].className+" ").indexOf(" "+name+" ")!=-1:undefined},addClass:function(name){for(var i=0,ei;ei=this[i];i++){element.addClass(ei,name)}return this},removeClass:function(name){for(var i=0,ei;ei=this[i];i++){element.removeClass(ei,name)}return this},toggleClass:function(name){for(var i=0,ei;ei=this[i];i++){element.toggleClass(ei,name)}return this},css:function(name,val){if(val){for(var i=0,ei;ei=this[i];i++){element.css(ei,name,val)}return this}else{return element.css(this[0],name)}}});jProton.event=function(){var _events=new Array();var addEventListener=typeof document.addEventListener!="undefined";var attachEvent=typeof document.attachEvent!="undefined";return{version:"jProton.event.0.3.9a",add:function(e,type,fn){_events.push({e:e,type:type,fn:fn});if(addEventListener){e.addEventListener(type,fn,false)}else{if(attachEvent){e["e"+type+fn]=fn;e[type+fn]=function(){e["e"+type+fn](window.event)};e.attachEvent("on"+type,e[type+fn])}}},remove:function(e,type,fn){var l,fs=fn.toString();for(var i=0,li;li=_events[i];i++){if(li.e==e&&li.type==type&&(li.fn==fn||li.fn.toString()==fs)){l=_events.splice(i,1)[0];break}}if(l){fn=l.fn;if(addEventListener){e.removeEventListener(type,fn,false)}else{if(attachEvent){e.detachEvent("on"+type,e[type+fn]);e[type+fn]=null;e["e"+type+fn]=null}}}},removeAll:function(){for(var i=0;li=_events[i];i++){this.remove(li.e,li.type,li.fn)}}}}();set.extend({"@extension":{event:"0.3.0a"},on:function(type,fn){return this.each(function(){jProton.event.add(this,type,fn)})},un:function(type,fn){return this.each(function(){jProton.event.remove(this,type,fn)})}});jProton.ajax=function(options){return this.ajax.request(options)};var ajax=jProton.ajax;jProton.extend(ajax,function(){var _requests=new Array();var _transport=null;var _callback=null;var _states=["Uninitialized","Loading","Loaded","Interactive","Complete"];var _sendRequest=function(){var t=_transport,r=_requests.shift(),data;t.open(r.type,r.url,r.async);t.setRequestHeader("X-Requested-With","XMLHttpRequest");if(data=jProton.serialize(r.data)){t.setRequestHeader("Content-Type",r.contentType)}t.onreadystatechange=function(){_onStateChange(r)};t.send(data)};var _onStateChange=function(options){var fn,o=options,t=_transport;var state=_getState(t);if(fn=o["on"+state]){fn(_getResponse(o),o)}if(state=="Complete"){var success=t.status==200,response=_getResponse(o);if(fn=o.onUpdate){fn(response,o)}if(fn=o["on"+(success?"Success":"Failure")]){fn(response,o)}t.onreadystatechange=jProton.emptyFn;if(_requests.length>0){setTimeout(_sendRequest,10)}}};var _getResponse=function(options){var t=_transport,type=options.dataType;if(t.status!=200){return t.statusText}else{if(type=="text"){return t.responseText}else{if(type=="html"){return t.responseText}else{if(type=="xml"){return t.responseXML}else{if(type=="json"){return eval("("+t.responseText+")")}}}}}};var _getState=function(){return _states[_transport.readyState]};return{"@extension":{ajax:"0.3.0a"},"@init":function(){_transport=null;try{_transport=new XMLHttpRequest()}catch(e){try{_transport=new ActiveXObject("Msxml2.XMLHTTP")}catch(e){try{_transport=new ActiveXObject("Microsoft.XMLHTTP")}catch(e){}}}},request:function(options){var o=options||{};o.type=o.type&&o.type.toLowerCase()||"get";o.async=o.async||true;o.dataType=o.dataType||"text";o.contentType=o.contentType||"application/x-www-form-urlencoded";_requests.push(o);var s=_getState();if(s=="Uninitialized"||s=="Complete"){_sendRequest()}}}}());set.extend({"@require":{dom:"0.3"},"@extension":{ajax:"0.3.0a"},load:function(url,data,callback){var d=data||null,fn=callback||null;if((typeof data=="function")&&(typeof callback=="undefined")){d=null;fn=data}ajax.request({url:url,data:d,onSuccess:fn,elements:this,onUpdate:function(r,o){$(o.elements).html(r)}});return this}});jProton.extend({"@extension":{ajax:"0.2.0a"},serialize:function(data){var r=[""],rl=0;if(data){if(typeof data=="string"){r[rl++]=data}else{if(data.innerHTML&&data.elements){for(var i=0,el,l=(el=data.elements).length;i+~]\s?|\s|$)/,reTag=/^(#)?([\w-\*]+)/,reNth=/(\d*)n\+?(\d*)/,reNth2=/\D/,isIE=!!window.ActiveXObject,key=30803;eval("var batch = 30803;");function _quickId(e,mode,context,val){if(e==context){var d=context.ownerDocument||context;return d.getElementById(val)}e=_getNodes(e,mode,"*");return _byId(e,val)}var _byId=function(e,val){if(e.tagName||e==document){e=[e]}var r=new Array(),rl=-1;for(var i=0,ei;ei=e[i];i++){if(ei&&ei.id==val){r[++rl]=ei;return r}}return r};var _byTag=function(e,val){if(e.tagName||e==document){e=[e]}var r=new Array(),rl=-1;val=val.toLowerCase();for(var i=0,ei;ei=e[i];i++){if(ei.nodeType==1&&ei.tagName.toLowerCase()==val){r[++rl]=ei}}return r};var _byClass=function(e,val){if(!val){return e}var r=new Array(),rl=-1;for(var i=0,ei;ei=e[i];i++){if((" "+ei.className+" ").indexOf(val)!=-1){r[++rl]=ei}}return r};var _byAttr=function(e,attr,op,val){var r=new Array(),rl=-1,f=query.operators[op];for(var i=0,ei,a;ei=e[i];i++){if(attr=="class"||attr=="className"){a=ei.className}else{if(attr=="for"){a=ei.htmlFor}else{if(attr=="href"){a=ei.getAttribute("href",2)}else{a=ei.getAttribute(attr)}}}if((f&&f(a,val))||(!f&&a)){r[++rl]=ei}}return r};var _byPseudo=function(e,name,val){return query.pseudos[name](e,val)};var _getNodes=function(e,mode,name){var r=new Array(),rl=-1;if(!e){return r}name=name||"*";if(typeof e.getElementsByTagName!="undefined"){e=[e]}if(!mode){for(var i=0,ei,n;ei=e[i];i++){n=ei.getElementsByTagName(name);for(var j=0,nj;nj=n[j];j++){r[++rl]=nj}}}else{if(mode=="/"||mode==">"){var utag=name.toUpperCase();for(var i=0,ei,n;ei=e[i];i++){n=ei.children||ei.childNodes;for(var j=0,nj;nj=n[j];j++){if(nj.nodeName==utag||nj.nodeName==name||name=="*"){r[++rl]=nj}}}}else{if(mode=="+"){var utag=name.toUpperCase();for(var i=0,ei;ei=e[i];i++){while((ei=ei.nextSibling)&&ei.nodeType!=1){}if(ei&&(ei.nodeName==utag||ei.nodeName==name||name=="*")){r[++rl]=ei}}}else{if(mode=="~"){for(var i=0,ei;ei=e[i];i++){while((ei=ei.nextSibling)&&(ei.nodeType!=1||(name=="*"||ei.tagName.toLowerCase()!=name))){}if(ei){r[++rl]=ei}}}}}}return r};var _unique=function(e){if(!e){return new Array()}var len=e.length,i,r=e,ei;if(!len||typeof e.nodeType!="undefined"||len==1){return e}if(isIE&&typeof e[0].selectSingleNode!="undefined"){var d=++key;e[0].setAttribute("__unique",d);var r=[e[0]],rl=0;for(var i=1,ei;ei=e[i];i++){if(!ei.getAttribute("__unique")!=d){ei.setAttribute("__unique",d);r[++rl]=ei}}for(var i=0;ei=e[i];i++){ei.removeAttribute("__unique")}return r}var d=++key;e[0].__unique=d;for(i=1,ei;ei=e[i];i++){if(ei.__unique!=d){ei.__unique=d}else{r=new Array(),rl=-1;for(var j=0;j1){return _unique(results)}return results},is:function(e,ss){if(typeof e=="string"){e=document.getElementById(e)}var isArray=!!e.splice,result=query.filter(isArray?e:[e],ss);return isArray?(result.length==e.length):(result.length>0)},filter:function(e,ss,nonMatches){ss=ss.replace(reTrim,"");if(!simpleCache[ss]){simpleCache[ss]=query.compile(ss,"simple")}var result=simpleCache[ss](e);return nonMatches?_diff(result,e):result},rules:[{re:/^\.([\w-]+)/,select:'e = _byClass(e, " {1} ");'},{re:/^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,select:'e = _byPseudo(e, "{1}", "{2}");'},{re:/^\[([\w-]+)(?:(.?=)["']?(.+?)["']?)?\]/,select:'e = _byAttr(e, "{1}", "{2}", "{3}");'},{re:/^#([\w-]+)/,select:'e = _byId(e, "{1}");'}],operators:{"=":function(attr,val){return attr==val},"!=":function(attr,val){return attr!=val},"^=":function(attr,val){return attr&&attr.substr(0,val.length)==val},"$=":function(attr,val){return attr&&attr.substr(attr.length-val.length)==val},"*=":function(attr,val){return attr&&attr.indexOf(val)!==-1},"%=":function(attr,val){return(attr%val)==0},"|=":function(attr,val){return attr&&(attr==val||attr.substr(0,val.length+1)==val+"-")},"~=":function(attr,val){return attr&&(" "+attr+" ").indexOf(" "+val+" ")!=-1}},pseudos:{"first-child":function(e){var r=new Array(),rl=-1,n;for(var i=0,ei;ei=n=e[i];i++){while((n=n.previousSibling)&&n.nodeType!=1){}if(!n){r[++rl]=ei}}return r},"last-child":function(e){var r=new Array(),rl=-1,n;for(var i=0,ei;ei=n=e[i];i++){while((n=n.nextSibling)&&n.nodeType!=1){}if(!n){r[++rl]=ei}}return r},"nth-child":function(e,val){var r=new Array(),rl=-1,m=reNth.exec(val=="even"&&"2n"||val=="odd"&&"2n+1"||!reNth2.test(val)&&"n+"+val||val),f=(m[1]||1)-0,l=m[2]-0;for(var i=0,ei;ei=e[i];i++){var p=ei.parentNode;if(batch!=p._batch){var j=0;for(var n=p.firstChild;n;n=n.nextSibling){if(n.nodeType==1){n.nodeIndex=++j}}p._batch=batch}if(f==1){if(l==0||ei.nodeIndex==l){r[++rl]=ei}}else{if((ei.nodeIndex+l)%f==0){r[++rl]=ei}}}return r},"only-child":function(e){var r=new Array(),rl=-1;for(var i=0,ei;ei=e[i];i++){if(!_prev(ei)&&!_next(ei)){r[++rl]=ei}}return r},empty:function(e){var r=new Array(),rl=-1;for(var i=0,ei;ei=e[i];i++){var n=ei.childNodes,j=-1,nj,empty=true;while(nj=n[++j]){if(nj.nodeType==1||nj.nodeType==3){empty=false;break}}if(empty){r[++rl]=ei}}return r},contains:function(e,val){var r=new Array(),rl=-1;for(var i=0,ei;ei=e[i];i++){if((ei.textContent||ei.innerText||"").indexOf(val)!=-1){r[++rl]=ei}}return r},nodeValue:function(e,val){var r=new Array(),rl=-1;for(var i=0,ei;ei=e[i];i++){if(ei.firstChild&&ei.firstChild.nodeValue==val){r[++rl]=ei}}return r},checked:function(e){var r=new Array(),rl=-1;for(var i=0,ei;ei=e[i];i++){if(ei.checked==true){r[++rl]=ei}}return r},not:function(e,val){return query.filter(e,val,true)},any:function(e,val){var r=new Array(),rl=-1,s,ss=val.split("|");for(var i=0,ei;ei=e[i];i++){for(var j=0;s=ss[j];j++){if(query.is(ei,s)){r[++rl]=ei;break}}}return r},odd:function(e){return this["nth-child"](e,"odd")},even:function(e){return this["nth-child"](e,"even")},nth:function(e,val){return e[val-1]||new Array()},first:function(e){return e[0]||new Array()},last:function(e){return e[e.length-1]||new Array()},has:function(e,val){var r=new Array(),rl=-1,s=query.select;for(var i=0,ei;ei=e[i];i++){if(s(val,ei).length>0){r[++rl]=ei}}return r},next:function(e,val){var r=new Array(),rl=-1,is=query.is;for(var i=0,ei;ei=e[i];i++){var n=_next(ei);if(n&&is(n,val)){r[++rl]=ei}}return r},prev:function(e,val){var r=new Array(),rl=-1,is=query.is;for(var i=0,ei;ei=e[i];i++){var n=_prev(ei);if(n&&is(n,val)){r[++rl]=ei}}return r}}}}();var query=jProton.query})(); \ No newline at end of file diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/sh.css b/deps/akihabara-core-1.3.1/akihabara/docs/sh.css new file mode 100644 index 0000000..e42c6d4 --- /dev/null +++ b/deps/akihabara-core-1.3.1/akihabara/docs/sh.css @@ -0,0 +1,182 @@ +.dp-highlighter +{ + font-family: "Consolas", "Courier New", Courier, mono, serif; + background-color: #E7E5DC; + margin: 1.5em 0 !important; + padding: 1px; /* adds a little border on top when controls are hidden */ +} + +/* clear styles */ +.dp-highlighter ol, +.dp-highlighter ol li, +.dp-highlighter ol li span +{ + line-height: 1.25em; + margin: 0; + padding: 0; + border: none; +} + +.dp-highlighter a, +.dp-highlighter a:hover +{ + background: none; + border: none; + padding: 0; + margin: 0; +} + +.dp-highlighter .bar +{ + padding-left: 45px; +} + +.dp-highlighter.collapsed .bar, +.dp-highlighter.nogutter .bar +{ + padding-left: 0px; +} + +.dp-highlighter ol +{ + list-style: decimal; /* for ie */ + background-color: #fff; + margin: 0px 0px 1px 45px !important; /* 1px bottom margin seems to fix occasional Firefox scrolling */ + padding: 0px; + color: #5C5C5C; +} + +.dp-highlighter.nogutter ol, +.dp-highlighter.nogutter ol li +{ + list-style: none !important; + margin-left: 0px !important; +} + +.dp-highlighter ol li, +.dp-highlighter .columns div +{ + list-style: decimal-leading-zero; /* better look for others, override cascade from OL */ + list-style-position: outside !important; + border-left: 3px solid #6CE26C; + background-color: #fafafa; + color: #5C5C5C; + padding: 0 3px 0 10px !important; + margin: 0 !important; +} + +.dp-highlighter.nogutter ol li, +.dp-highlighter.nogutter .columns div +{ + border: 0; +} + +.dp-highlighter .columns +{ + background-color: #fafafa; + color: gray; + overflow: hidden; + width: 100%; +} + +.dp-highlighter .columns div +{ + padding-bottom: 5px; +} + +.dp-highlighter ol li.alt +{ + background-color: #FFF; + color: inherit; +} + +.dp-highlighter ol li span +{ + color: black; + background-color: inherit; +} + +/* Adjust some properties when collapsed */ + +.dp-highlighter.collapsed ol +{ + margin: 0px; +} + +.dp-highlighter.collapsed ol li +{ + display: none; +} + +/* Additional modifications when in print-view */ + +.dp-highlighter.printing +{ + border: none; +} + +.dp-highlighter.printing .tools +{ + display: none !important; +} + +.dp-highlighter.printing li +{ + display: list-item !important; +} + +/* Styles for the tools */ + +.dp-highlighter .tools +{ + padding: 3px 8px 3px 10px; + font: 9px Verdana, Geneva, Arial, Helvetica, sans-serif; + color: silver; + background-color: #f8f8f8; + padding-bottom: 10px; + border-left: 3px solid #6CE26C; +} + +.dp-highlighter.nogutter .tools +{ + border-left: 0; +} + +.dp-highlighter.collapsed .tools +{ + border-bottom: 0; +} + +.dp-highlighter .tools a +{ + font-size: 9px; + color: #a0a0a0; + background-color: inherit; + text-decoration: none; + margin-right: 10px; +} + +.dp-highlighter .tools a:hover +{ + color: red; + background-color: inherit; + text-decoration: underline; +} + +/* About dialog styles */ + +.dp-about { background-color: #fff; color: #333; margin: 0px; padding: 0px; } +.dp-about table { width: 100%; height: 100%; font-size: 11px; font-family: Tahoma, Verdana, Arial, sans-serif !important; } +.dp-about td { padding: 10px; vertical-align: top; } +.dp-about .copy { border-bottom: 1px solid #ACA899; height: 95%; } +.dp-about .title { color: red; background-color: inherit; font-weight: bold; } +.dp-about .para { margin: 0 0 4px 0; } +.dp-about .footer { background-color: #ECEADB; color: #333; border-top: 1px solid #fff; text-align: right; } +.dp-about .close { font-size: 11px; font-family: Tahoma, Verdana, Arial, sans-serif !important; background-color: #ECEADB; color: #333; width: 60px; height: 22px; } + +/* Language specific styles */ + +.dp-highlighter .comment, .dp-highlighter .comments { color: #008200; background-color: inherit; } +.dp-highlighter .string { color: #00d; background-color: inherit; } +.dp-highlighter .keyword { color: #6277AA; font-weight: bold; background-color: inherit; } +.dp-highlighter .preprocessor { color: gray; background-color: inherit; } diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/sh.js b/deps/akihabara-core-1.3.1/akihabara/docs/sh.js new file mode 100644 index 0000000..e41bb3a --- /dev/null +++ b/deps/akihabara-core-1.3.1/akihabara/docs/sh.js @@ -0,0 +1 @@ +eval(function(p,a,c,k,e,r){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('6 7={8:{16:{},1b:{},1i:{},1e:{},2L:{2G:\'<2y><1W><1S>2k...<1x 18="7-2U"><2S 4g="0"><1E><1C 18="21">

7.2q1T: {V}

36://30.2V.2K/2M

&21;41-3W 3V 3T.<1E><1C 18="3Q"><3N 1J="3E" 18="1p" 1m="3y" 3x="19.1p()"/>\'},1A:e,1T:"1.5.1"}};7.2q=7.8;7.8.16.1K={3m:{1h:"+ 3h 2h",1F:d(A){h A.1t},1j:d(B,A){B.26.2Q(B);A.i.q=A.i.q.l("2a","")}},4m:{1h:"4j 4e",1j:d(B,A){6 D=7.8.1b.1L(A.28).l(/\'+D+"");C.m.1p()}},3D:{1h:"21 3C 1V",1F:d(){h 19.1O!=e||7.8.1A!=e},1j:d(B,A){6 D=7.8.1b.1L(A.28).l(/&1H;/g,"<").l(/&2n;/g,">").l(/&3w;/g,"&");9(19.1O){19.1O.3v("1R",D)}14{9(7.8.1A!=e){6 C=A.2l;9(C==e){C=m.1n("i");A.2l=C;A.i.k(C)}C.y=\'<2r 3r="\'+7.8.1A+\'" 3p="1V=\'+3o(D)+\'" 1v="0" 1w="0" 1J="3n/x-3k-3j">\'}}2v("3g 1a 3d 1D 3b 1V 3a")}},38:{1h:"2N",1j:d(B,A){6 C=m.1n("5c");6 D=e;C.1z.35="58:57;1v:2Z;1w:2Z;51:-2Y;4Z:-2Y;";m.1x.k(C);D=C.2d.m;7.8.1b.2c(D,19.m);D.1M(\'\'+A.i.y+"");D.1p();C.2d.2T();C.2d.2N();2v("4F...");m.1x.2Q(C)}},2k:{1h:"?",1j:d(A){6 B=19.2E("","24","4C,1v=4z,1w=2P,2x=0");6 C=B.m;7.8.1b.2c(C,19.m);C.1M(7.8.2L.2G.l("{V}",7.8.1T));C.1p();B.2T()}}};7.8.16.2O=d(B){6 D=m.1n("29");D.q="4q";j(6 A 1D 7.8.16.1K){6 C=7.8.16.1K[A];9(C.1F!=e&&!C.1F(B)){15}D.y+=\'"+C.1h+""}h D};7.8.16.2R=d(A,B){6 C=B;1u(C!=e&&C.q.1P("7-1r")==-1){C=C.26}9(C!=e){7.8.16.1K[A].1j(B,C.1r)}};7.8.1b.2c=d(A,D){6 B=D.27("25");j(6 C=0;C\')}}};7.8.1b.1L=d(A){h(7.8.2F==12)?A.l(/<1k\\s*\\/?>|&1H;1k\\s*\\/?&2n;/1I,"\\n"):A};7.8.1i={2D:o 17("/\\\\*[\\\\s\\\\S]*?\\\\*/","1l"),2C:o 17("//.*$","1l"),3R:o 17("#.*$","1l"),2A:o 17(\'"(?:\\\\.|(\\\\\\\\\\\\")|[^\\\\""\\\\n])*"\',"g"),2z:o 17("\'(?:\\\\.|(\\\\\\\\\\\\\')|[^\\\\\'\'\\\\n])*\'","g")};7.8.2W=d(C,A,B){3.1m=C;3.v=A;3.f=C.f;3.11=B};7.8.r=d(){3.22=1f;3.2g=12;3.1t=1f;3.2w=12;3.3L=3H;3.2f=12};7.8.r.2u=d(B,A){9(B.vA.v){h 1}14{9(B.fA.f){h 1}}}}h 0};7.8.r.13.z=d(B){6 A=m.1n(B);A.1r=3;h A};7.8.r.13.2t=d(D,C){6 B=0;6 A=e;1u((A=D.1Y(3.1a))!=e){3.u[3.u.f]=o 7.8.2W(A[0],A.v,C)}};7.8.r.13.1q=d(E,C){9(E==e||E.f==0){h}6 D=3.z("1X");E=E.l(/ /g,"&1B;");E=E.l(/");9(C!=e){9((/1k/1I).3A(E)){6 A=E.1s("&1B;<1k>");j(6 B=0;BC.v)&&(A.v/1I,"\\n");6 I=E.1s("\\n");9(3.2g==12){3.1d.k(7.8.16.2O(3))}9(3.2f){6 A=3.z("i");6 C=3.z("i");6 B=10;6 D=1;1u(D<=2P){9(D%B==0){A.y+=D;D+=(D+"").f}14{A.y+="&3t;";D++}}C.q="3s";C.k(A);3.1d.k(C)}j(6 D=0,H=3.1U;D0;J++){9(F(I[J]).f==0){15}6 M=L.1Y(I[J]);9(M!=e&&M.f>0){K=3G.3l(M[0].f,K)}}9(K>0){j(6 J=0;J + + + + + + JsDoc Reference - _global_ + + + + + + + + + +
+
+ +
+
+
+
 
+
Project Outline
+
+ + +
+ +
+ + + +
+
createMaingame(id, group)
+ +
+
+
 
gbox
addAudio(id, filename, def)
addBundle(call)
addFont(data)
addImage(id, filename)
addObject(data)
addScript(call)
blit(tox, image, data)
blitAll(tox, image, data)
blitClear(image, data)
blitFade(tox, data)
blitRect(tox, data)
blitText(tox, data)
blitTile(tox, data)
blitTilemap(tox, data)
centerCamera(data, viewdata)
collides(o1, o2, t)
createCanvas(id, data)
dataLoad(k, a)
dataSave(k, v, d)
getObject(group, id)
go()
hitAudio(a, data)
log()
pixelcollides(o1, o2, t)
playAudio(a, data)
readBundleData(pack, call)
setCameraX(x, viewdata)
setCameraY(y, viewdata)
setZindex(th, z)
stopAudio(a, permissive)
trashGroup(group)
+ +
+
+
 
help
asciiArtToMap(map, tra)
copyModel(data, model)
createModel(obj, attrs)
decideFrame(cnt, anim)
decideFrameOnce(cnt, anim)
framestotime(frames)
getArrayIndexed(a, value, field)
getTileInMap(x, y, map, ifout, mapid)
isLastFrameOnce(cnt, anim)
isSquished(th, by)
limit(v, min, max)
mergeWithModel(data, model)
multiplier(v, mul)
postpad(str, len, pad)
prepad(str, len, pad)
random(min, range)
seq(st, ed, skip)
setTileInMap(ctx, map, x, y, tile, The)
upAndDown(counter, max)
xPixelToTile(map, x, gap)
xPixelToTileX(map, x, gap)
yPixelToTile(map, y, gap)
yPixelToTileY(map, y, gap)
+ +
+
bounce(th, data)
horizontalKeys(th, keys)
horizontalTileCollision(th, map, tilemap)
initialize(th, data)
jumpKeys(th, key)
spawn(th, data)
verticalTileCollision(th, map, tilemap)
+ +
+
controlKeys(th, keys)
fireBullet(gr, id, data)
generateEnemy(gr, id, data, model)
generateScroller(gr, id, data)
hitByBullet(th, by)
initialize(th, data)
spawn(th, data)
+ +
+
after(th, id, frames)
every(th, id, frames)
randomly(th, id, data)
real(th, id, data)
+ +
+
+
 
tool
makecels(data)
+ +
+
callInColliding(th, data)
collides(fr, to, t)
controlKeys(th, keys)
fireBullet(gr, id, data)
floorCollision(th, data)
getAheadPixel(th, data)
initialize(th, data)
makedoor(gr, id, map, data)
pixelcollides(fr, to, t)
setStaticSpeed(th, speed)
spawn(th, data)
tileCollision(th, map, tilemap, defaulttile, data)
wander(th, map, tilemap, defaulttile, data)
+ + + +
+
+
 
trigo
addAngle(a, add)
getAngle(p1, p2, transl)
getDistance(p1, p2)
translate(p1, a, d)
translateX(x1, a, d)
translateY(y1, a, d)
+ +
+
+
+ + +
+
«
+ + + +
+ Akihabara Framework +
+ + + +
+ +

+ Built-In Namespace _global_ +

+ + + +
+

+
+ + + + + + + + + +
+
Field Summary
+
+ +
+ + iphofretboard + Fretboard module provides a touchpad for touch-based device (for now, Android and iDevices). +
+ +
+ + iphopad + Iphopad module provides a touchpad for touch-based device (for now, Android and iDevices). +
+ +
+
+ + + + + + + + + + + + +
+
+ Field Detail +
+
+ +
+ +
+ iphofretboard + +
+ +
+ Fretboard module provides a touchpad for touch-based device (for now, Android and iDevices). + +

Defined in: iphofretboard.js.

+ + +
+ + +

+									
+								
+									
+										
+										
+										
+										
+				
+								
+ +
+ +
+ iphopad + +
+ +
+ Iphopad module provides a touchpad for touch-based device (for now, Android and iDevices). + +

Defined in: iphopad.js.

+ + +
+ + +

+									
+								
+									
+										
+										
+										
+										
+				
+								
+ +
+
+ + + + + +
+ + +
+ + Documentation generated by JsDoc Toolkit 2.3.2 on Wed Aug 18 2010 16:09:22 GMT-0400 (EDT) +
+ +
+
+ + + diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/symbols/gamecycle.html b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/gamecycle.html new file mode 100644 index 0000000..2eed826 --- /dev/null +++ b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/gamecycle.html @@ -0,0 +1,225 @@ + + + + + + + JsDoc Reference - gamecycle + + + + + + + + + +
+
+ +
+
+
+
 
+
Project Outline
+
+ + +
+ +
+ + + +
+
createMaingame(id, group)
+ +
+
+
 
gbox
addAudio(id, filename, def)
addBundle(call)
addFont(data)
addImage(id, filename)
addObject(data)
addScript(call)
blit(tox, image, data)
blitAll(tox, image, data)
blitClear(image, data)
blitFade(tox, data)
blitRect(tox, data)
blitText(tox, data)
blitTile(tox, data)
blitTilemap(tox, data)
centerCamera(data, viewdata)
collides(o1, o2, t)
createCanvas(id, data)
dataLoad(k, a)
dataSave(k, v, d)
getObject(group, id)
go()
hitAudio(a, data)
log()
pixelcollides(o1, o2, t)
playAudio(a, data)
readBundleData(pack, call)
setCameraX(x, viewdata)
setCameraY(y, viewdata)
setZindex(th, z)
stopAudio(a, permissive)
trashGroup(group)
+ +
+
+
 
help
asciiArtToMap(map, tra)
copyModel(data, model)
createModel(obj, attrs)
decideFrame(cnt, anim)
decideFrameOnce(cnt, anim)
framestotime(frames)
getArrayIndexed(a, value, field)
getTileInMap(x, y, map, ifout, mapid)
isLastFrameOnce(cnt, anim)
isSquished(th, by)
limit(v, min, max)
mergeWithModel(data, model)
multiplier(v, mul)
postpad(str, len, pad)
prepad(str, len, pad)
random(min, range)
seq(st, ed, skip)
setTileInMap(ctx, map, x, y, tile, The)
upAndDown(counter, max)
xPixelToTile(map, x, gap)
xPixelToTileX(map, x, gap)
yPixelToTile(map, y, gap)
yPixelToTileY(map, y, gap)
+ +
+
bounce(th, data)
horizontalKeys(th, keys)
horizontalTileCollision(th, map, tilemap)
initialize(th, data)
jumpKeys(th, key)
spawn(th, data)
verticalTileCollision(th, map, tilemap)
+ +
+
controlKeys(th, keys)
fireBullet(gr, id, data)
generateEnemy(gr, id, data, model)
generateScroller(gr, id, data)
hitByBullet(th, by)
initialize(th, data)
spawn(th, data)
+ +
+
after(th, id, frames)
every(th, id, frames)
randomly(th, id, data)
real(th, id, data)
+ +
+
+
 
tool
makecels(data)
+ +
+
callInColliding(th, data)
collides(fr, to, t)
controlKeys(th, keys)
fireBullet(gr, id, data)
floorCollision(th, data)
getAheadPixel(th, data)
initialize(th, data)
makedoor(gr, id, map, data)
pixelcollides(fr, to, t)
setStaticSpeed(th, speed)
spawn(th, data)
tileCollision(th, map, tilemap, defaulttile, data)
wander(th, map, tilemap, defaulttile, data)
+ + + +
+
+
 
trigo
addAngle(a, add)
getAngle(p1, p2, transl)
getDistance(p1, p2)
translate(p1, a, d)
translateX(x1, a, d)
translateY(y1, a, d)
+ +
+
+
+ + +
+
«
+ + + +
+ Akihabara Framework +
+ + + +
+ +

+ Namespace gamecycle +

+ + + +
+

Gamecycle contains your basic game loop: intro, menus, crossfading between stages/lifes, gameover and ending.

+
+ +

Defined in: gamecycle.js.

+ + + + + + + + + + + + + +
+
Method Summary
+
+ +
+ + createMaingame(id, group) + Gamecycle constructor - initializes a new game object +
+ +
+
+ + + + + + + + + + + +
+
+ Method Detail +
+
+ + +
+ +
+ gamecycle.createMaingame(id, group) + +
+
+ Gamecycle constructor - initializes a new game object + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ + + id + + unique id of object +
+ + + group + + name of group to store the object in +
+ + + + + + + + +
+ +
+
+ + +
+ + +
+ + Documentation generated by JsDoc Toolkit 2.3.2 on Wed Aug 18 2010 16:09:22 GMT-0400 (EDT) +
+ +
+
+ + + diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/symbols/gbox.html b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/gbox.html new file mode 100644 index 0000000..8de4566 --- /dev/null +++ b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/gbox.html @@ -0,0 +1,6680 @@ + + + + + + + JsDoc Reference - gbox + + + + + + + + + +
+
+ +
+
+
+
 
+
Project Outline
+
+ + +
+ +
+ + + +
+
createMaingame(id, group)
+ +
+
+
 
gbox
addAudio(id, filename, def)
addBundle(call)
addFont(data)
addImage(id, filename)
addObject(data)
addScript(call)
blit(tox, image, data)
blitAll(tox, image, data)
blitClear(image, data)
blitFade(tox, data)
blitRect(tox, data)
blitText(tox, data)
blitTile(tox, data)
blitTilemap(tox, data)
centerCamera(data, viewdata)
collides(o1, o2, t)
createCanvas(id, data)
dataLoad(k, a)
dataSave(k, v, d)
getObject(group, id)
go()
hitAudio(a, data)
log()
pixelcollides(o1, o2, t)
playAudio(a, data)
readBundleData(pack, call)
setCameraX(x, viewdata)
setCameraY(y, viewdata)
setZindex(th, z)
stopAudio(a, permissive)
trashGroup(group)
+ +
+
+
 
help
asciiArtToMap(map, tra)
copyModel(data, model)
createModel(obj, attrs)
decideFrame(cnt, anim)
decideFrameOnce(cnt, anim)
framestotime(frames)
getArrayIndexed(a, value, field)
getTileInMap(x, y, map, ifout, mapid)
isLastFrameOnce(cnt, anim)
isSquished(th, by)
limit(v, min, max)
mergeWithModel(data, model)
multiplier(v, mul)
postpad(str, len, pad)
prepad(str, len, pad)
random(min, range)
seq(st, ed, skip)
setTileInMap(ctx, map, x, y, tile, The)
upAndDown(counter, max)
xPixelToTile(map, x, gap)
xPixelToTileX(map, x, gap)
yPixelToTile(map, y, gap)
yPixelToTileY(map, y, gap)
+ +
+
bounce(th, data)
horizontalKeys(th, keys)
horizontalTileCollision(th, map, tilemap)
initialize(th, data)
jumpKeys(th, key)
spawn(th, data)
verticalTileCollision(th, map, tilemap)
+ +
+
controlKeys(th, keys)
fireBullet(gr, id, data)
generateEnemy(gr, id, data, model)
generateScroller(gr, id, data)
hitByBullet(th, by)
initialize(th, data)
spawn(th, data)
+ +
+
after(th, id, frames)
every(th, id, frames)
randomly(th, id, data)
real(th, id, data)
+ +
+
+
 
tool
makecels(data)
+ +
+
callInColliding(th, data)
collides(fr, to, t)
controlKeys(th, keys)
fireBullet(gr, id, data)
floorCollision(th, data)
getAheadPixel(th, data)
initialize(th, data)
makedoor(gr, id, map, data)
pixelcollides(fr, to, t)
setStaticSpeed(th, speed)
spawn(th, data)
tileCollision(th, map, tilemap, defaulttile, data)
wander(th, map, tilemap, defaulttile, data)
+ + + +
+
+
 
trigo
addAngle(a, add)
getAngle(p1, p2, transl)
getDistance(p1, p2)
translate(p1, a, d)
translateX(x1, a, d)
translateY(y1, a, d)
+ +
+
+
+ + +
+
«
+ + + +
+ Akihabara Framework +
+ + + +
+ +

+ Namespace gbox +

+ + + +
+

Gamebox module allows multiple grouped objects to move simultaneously, it helps with collisions, rendering and moving objects. It also provides monospaced pixel-font rendering, keyboard handling, audio, double buffering and eventually FSEs. Gamebox can also store and load data from cookies!

+
+ +

Defined in: gbox.js.

+ + + + + + + + + + + + + +
+
Method Summary
+
+ +
+ + addAudio(id, filename, def) + +
+ +
+ + addBundle(call) + +
+ +
+ + addFont(data) + Creates a font. +
+ +
+ + addImage(id, filename) + Adds an image file to the loader, assigning it to an ID. If adding an image to an existing ID, it checks to see if the file you're adding is different than the one currently assigned to the ID. +
+ +
+ + addObject(data) + Creates a new game object. Generally speaking you pass a fully-defined object as the parameter (including a group, id, tileset, and so on). +
+ +
+ + addScript(call) + +
+ +
+ + addTiles(t) + Creates a new Akihabara tileset, adding it to the engine. +
+ +
+ + blit(tox, image, data) + +
+ +
+ + blitAll(tox, image, data) + Draws an image to a canvas context +
+ +
+ + blitClear(image, data) + Clears a rectangular area of a canvas context. +
+ +
+ + blitFade(tox, data) + Draws a filled rectangle over an entire canvas context. +
+ +
+ + blitImageToScreen(image) + Draws an image directly to the screen's current canvas context. Used internally in gbox.go(). +
+ +
+ + blitRect(tox, data) + Draws a filled rectangle to a canvas context. +
+ +
+ + blitText(tox, data) + Draws text to a canvas context +
+ +
+ + blitTile(tox, data) + Draws a tile to a canvas context +
+ +
+ + blitTilemap(tox, data) + Draws a tilemap to a canvas context +
+ +
+ + canLog() + +
+ +
+ + centerCamera(data, viewdata) + Centers the camera. +
+ +
+ + changeAudioVolume(a, vol) + +
+ +
+ + changeChannelVolume(ch, a) + +
+ +
+ + clearCache() + +
+ +
+ + clearGroup(gid) + Destroys all objects in a given group. +
+ +
+ + collides(o1, o2, t) + Calculates a box collision between two collision boxes within a given tolerance. A higher tolerance means less precise collision. +
+ +
+ + createCanvas(id, data) + Creates a new canvas. By default, the width and height is the current gbox. +
+ +
+ + dataClear(k) + Clears a value stored in a key-value pair in a browser cookie. Sets value to "". +
+ +
+ + dataLoad(k, a) + Loads data from a browser cookie. Send it a key and it returns a value (if available). +
+ +
+ + dataSave(k, v, d) + Saves data to a browser cookie as a key-value pair, which can be restored later using gbox.dataLoad. +
+ +
+ + debugGetstats() + Displays basic audio, object, and performance statistics in the status bar. Automatically called each frame if the status bar is enabled. +
+ +
+ + deleteAudio(id) + +
+ +
+ + deleteCanvas(id) + Deletes a given canvas. +
+ +
+ + deleteImage(id) + Deletes an image currently in use. Does not delete the image file, but removes it from Akihabara's image list. +
+ +
+ + getAudioDuration(a) + +
+ + + +
+ + getAudioMute(a) + +
+ +
+ + getAudioPosition(a) + +
+ +
+ + getAudioVolume(a, vol) + +
+ +
+ + getBuffer() + Gets the buffer canvas (automatically created by gbox.initScreen). +
+ +
+ + getBufferContext() + Gets the buffer canvas context. +
+ +
+ + getCamera() + Gets the current camera object. +
+ +
+ + getCanvas(id) + Gets a given canvas. +
+ +
+ + getCanvasContext(id) + Gets the two-dimensional canvas context of a given canvas. The object it returns contains all the drawing functions for the canvas. +
+ + + +
+ + getChannelVolume(ch) + +
+ +
+ + getFlag(f) + Returns a gbox flag at index f. +
+ +
+ + getFont(id) + Returns a font object containing data about the font. +
+ +
+ + getFps() + Get the frames per second rate (default is 25). +
+ +
+ + getGroups() + Get an array containing the names of each group in the game, in order of rendering. +
+ +
+ + getImage(id) + Gets information about a loaded image. +
+ +
+ + getObject(group, id) + Given a group and an id for a particular object instance, this returns the instance requested. NOTE: this does not return a copy of the object you've requested! Any modifications you make to the object returned are directly modifying the object you requested. +
+ +
+ + getScreenH() + Get the screen height. +
+ +
+ + getScreenHH() + Get the screen half-height. +
+ +
+ + getScreenHW() + Get the screen half-width. +
+ +
+ + getScreenW() + Get the screen width. +
+ +
+ + getTiles(t) + Gets an Akihabara tileset, adding it to the engine. +
+ +
+ + go() + This function is called once per frame. This is where the basic rendering and processing of groups occurs. +
+ +
+ + groupIsEmpty(gid) + Returns whether a given group contains no objets. +
+ +
+ + hitAudio(a, data) + +
+ +
+ + imageIsLoaded(id) + Checks to see if an image was successfully loaded. +
+ +
+ + initScreen(w, h) + Initializes the screen to a certain width and height, applies zoom attributes, populates the body of the HTML document including the canvas element, sets an initial camera, creates a '_buffer' canvas, sets keyboard event listeners, and many other initialization functions. +
+ +
+ + keyIsHit(id) + Returns true if a given key in this._keymap is pressed. +
+ +
+ + keyIsHold(id) + Returns true if a given key in this._keymap has been held down for at least one frame. +
+ +
+ + keyIsPressed(id) + Returns true if a given key in this._keymap is being held down. +
+ +
+ + keyIsReleased(id) + Returns true if a given key in this._keymap is released. +
+ +
+ + loadAll(cb) + Loads the initial splash screen and debugging font, then calls gbox._waitforloaded which adds to the game all the previously defined resources. +
+ +
+ + log() + +
+ +
+ + objectIsTrash(o) + Returns whether an object is due to be trashed. Useful in cases you want to check if an object is marked as trash before it is actually deleted. +
+ +
+ + objectIsVisible(obj) + Determines whether an object is visible by seeing if it collides with the camera's viewport. +
+ +
+ + pixelcollides(o1, o2, t) + Calculates a point-box collision between a point and a collision box within a given tolerance. A higher tolerance means less precise collision. +
+ +
+ + playAllGroups() + Enables all groups, toggling any groups that are currently disabled. +
+ +
+ + playAudio(a, data) + +
+ +
+ + playGroup(gid) + If a group is disabled, this will enable the group. +
+ +
+ + playGroups(gid) + +
+ +
+ + purgeGarbage(obj) + Clears the record held in gbox._garbage of what has been deleted. +
+ +
+ + readBundleData(pack, call) + +
+ +
+ + resetChannel(ch) + +
+ +
+ + setAudioChannels(a) + +
+ +
+ + setAudioCompatMode(m) + +
+ +
+ + setAudioCreateMode(m) + +
+ +
+ + setAudioDequeueTime(m) + +
+ +
+ + setAudioMute(a) + +
+ +
+ + setAudioPosition(a, p) + +
+ + + +
+ + setAudioTeam(a) + +
+ +
+ + setAudioUnmute(a) + +
+ +
+ + setAudioVolume(a, vol) + +
+ +
+ + setAutoskip(f) + +
+ +
+ + setCallback(cb) + Deprecated: gbox._cb is now set by passing it directly into gbox.loadAll(). +
+ +
+ + setCameraX(x, viewdata) + Sets the x value of the current camera object. +
+ +
+ + setCameraY(y, viewdata) + Sets the y value of the current camera object. +
+ +
+ + setCanAudio(a) + +
+ +
+ + setCanLog(c) + +
+ +
+ + setChannelVolume(ch, a) + +
+ +
+ + setDoubleBuffering(db) + Sets the gbox._db property. +
+ +
+ + setForcedIdle(f) + Sets the gbox._forcedidle property. +
+ +
+ + setFps(f) + Set the frames per second rate. +
+ +
+ + setFrameskip(f) + +
+ +
+ + setGroups(g) + Defines the names of each group in the game along with their rendering order. +
+ +
+ + setLowerAudioTeam(a) + +
+ +
+ + setRenderOrder(g) + A method of setting the render order of groups independently of gbox.setGroups. +
+ +
+ + setScreenBorder(a) + +
+ +
+ + setShowPlayers(m) + +
+ +
+ + setSplashSettings(a) + +
+ +
+ + setStatBar(txt) + Writes text to the status bar, but only if the status bar is enabled. +
+ +
+ + setStatusBar(f) + Sets the gbox._statbar property. +
+ +
+ + setZindex(th, z) + +
+ +
+ + setZoom(z) + Sets the gbox._zoom parameter, only works before gbox.initScreen is called. +
+ +
+ + soloGroup(gid) + Turns off all groups except for the one specified. +
+ +
+ + stopAudio(a, permissive) + +
+ +
+ + stopChannel(ch) + +
+ +
+ + stopGroup(gid) + If a group is enabled, this will disable the group. +
+ +
+ + stopGroups(gid) + +
+ +
+ + toggleGroup(gid) + Toggles a group between enabled and disabled status. +
+ +
+ + toggleGroups(gid) + +
+ +
+ + trashGroup(group) + Deletes every object in a given group. +
+ +
+ + trashObject(obj) + Deletes an object, keeping a record of its group and id in gbox._garbage. +
+ +
+
+ + + + + + + + + + + +
+
+ Method Detail +
+
+ + +
+ +
+ gbox.addAudio(id, filename, def) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + +
+ + + id + + +
+ + + filename + + +
+ + + def + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.addBundle(call) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + call + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.addFont(data) + +
+
+ Creates a font. + + + + +
gbox.addImage('font', 'font.png');
gbox.addFont({ id: 'small', image: 'font', firstletter: ' ', tileh: 8, tilew: 8, tilerow: 255, gapx: 0, gapy: 0 });
+ +
+ + +
Parameters:
+ + + + + + + + +
+ {Object} + + data + + An object containing:
  • id: the id of the font
  • image: reference to the font image loaded (must contain font character tiles in ASCII order)
  • firstletter: the ASCII character that the font image's first character corresponds to
  • tileh: height in pixels of the character tiles
  • tilew: width in pixels of the character tiles
  • tilerow: width in pixels of each row in the font image
  • gapx: x-coord gap between tile columns, in pixels
  • gapy: y-coord gap between tile rows, in pixels
+
+ + + + + + + + +
+ + +
+ +
+ gbox.addImage(id, filename) + +
+
+ Adds an image file to the loader, assigning it to an ID. If adding an image to an existing ID, it checks to see if the file you're adding is different than the one currently assigned to the ID. If it's different, it overwrites the old image. If it's the same, then no action is taken. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ {String} + + id + + The identifier of the image. +
+ {String} + + filename + + The file name of the image. +
+ + + + + + + + +
+ + +
+ +
+ gbox.addObject(data) + : Object +
+
+ Creates a new game object. Generally speaking you pass a fully-defined object as the parameter (including a group, id, tileset, and so on). A group must be specified, or the program will crash. If no id is specified, then it will automatically provide an id of 'obj-XXXX' where 'XXXX' is an automatically incrementing integer. This is where the initialize, first, and blit functions are defined, as well. + + + + +
data = {
  group: 'player',
  id: 'player_id',
  tileset: 'player_tiles', 
  x: 0,
  y: 0,
  initialize: function() {
+      this.x = 10;
+      this.y = 10;
+      },
};
gbox.addObject(data);
+ +
+ + +
Parameters:
+ + + + + + + + +
+ {Object} + + data + + The object you wish to create. +
+ + + + + +
Returns:
+ + + + + + + +
+ {Object} + + The object you created. +
+ + + + +
+ + +
+ +
+ gbox.addScript(call) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + call + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.addTiles(t) + +
+
+ Creates a new Akihabara tileset, adding it to the engine. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {Object} + + t + + An object containing:
  • id {String}: the new id of the tileset
  • image {String}: reference to the tileset image loaded
  • tileh {Integer}: height in pixels of the tiles
  • tilew {Integer}: width in pixels of the tiles
  • tilerow {Integer}: width in pixels of each row in the font image
  • gapx {Integer}: x-coord gap between tile columns, in pixels
  • gapy {Integer}: y-coord gap between tile rows, in pixels
+
+ + + + + + + + +
+ + +
+ +
+ gbox.blit(tox, image, data) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + +
+ + + tox + + +
+ + + image + + +
+ + + data + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.blitAll(tox, image, data) + +
+
+ Draws an image to a canvas context + + + + +
// draw an image at (100,100)
gbox.blitAll(gbox.getBufferContext(),gbox.getImage("image_id"),{dx:100,dy:100});
+ +
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + +
+ {Object} + + tox + + The canvas context to be drawn on. +
+ {Object} + + image + + The image to draw. Must be a DOM Image element, typicallly accessed via gbox.getImage +
+ {Object} + + data + + An object containing data about the tile to be drawn, including:
  • dx {Integer}: (required) x coordinate to draw the image at
  • dy {Integer}: (required) y coordinate to draw the image at
  • fliph {Integer}: horizontal flip, either 1 or -1
  • flipv {Integer}: vertical flip, either 1 or -1
  • alpha {Float}: alpha value (0 is transparent, 1 is opaque)
+
+ + + + + + + + +
+ + +
+ +
+ gbox.blitClear(image, data) + +
+
+ Clears a rectangular area of a canvas context. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ {Object} + + image + + The canvas context to be drawn on. +
+ {Object} + + data + + An object containing a set of data, including:
  • x {Integer}: (required) the x coordinate of the top-left corner of the rectangle
  • y {Integer}: (required) the y coordinate of the top-left corner of the rectangle
  • w {Integer}: the width of the box; defaults to canvas width
  • h {Integer}: the height the box; defaults to canvas height
+
+ + + + + + + + +
+ + +
+ +
+ gbox.blitFade(tox, data) + +
+
+ Draws a filled rectangle over an entire canvas context. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ {Object} + + tox + + The canvas context to be filled. +
+ {Object} + + data + + An object containing a set of data, including:
  • alpha {Float}: the alpha value of the rectangle; defaults to 1
  • color {Object}: the color of the box, formatted rgb(rValue, gValue, bValue); default black
+
+ + + + + + + + +
+ + +
+ +
+ gbox.blitImageToScreen(image) + +
+
+ Draws an image directly to the screen's current canvas context. Used internally in gbox.go(). Probably shouldn't be used otherwise. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + image + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.blitRect(tox, data) + +
+
+ Draws a filled rectangle to a canvas context. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ {Object} + + tox + + The canvas context to be drawn on. +
+ {Object} + + data + + An object containing a set of data, including:
  • x {Integer}: (required) the x coordinate of the top-left corner of the rectangle
  • y {Integer}: (required) the y coordinate of the top-left corner of the rectangle
  • w {Integer}: (required) the width of the box
  • h {Integer}: (required) the height the box
  • alpha {Float}: the alpha value of the rectangle; defaults to 1
  • color {Object}: the color of the box, formatted rgb(rValue, gValue, bValue); default black
+
+ + + + + + + + +
+ + +
+ +
+ gbox.blitText(tox, data) + +
+
+ Draws text to a canvas context + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ {Object} + + tox + + The canvas context to be drawn on. +
+ {Object} + + data + + An object containing a set of data, including:
  • font {String}: (required) the id of font to draw the text with
  • text {String}: (required) the text to display
  • dx {Integer}: (required) the x coordinate to draw the text at
  • dy {Integer}: (required) the y coordinate to draw the text at
  • dw {Integer}: the width of the text area -- required if you define data.halign
  • dh {Integer}: the height of the text area -- required if you define data.valign
  • valign {Integer}: either gbox.ALIGN_BOTTOM (aligns from the bottom of the text area) or gbox.ALIGN_MIDDLE (vertically centers text in text area)
  • halign {Integer}: either gbox.ALIGN_RIGHT (aligns to the right hand side of text area) or gbox.ALIGN_CENTER (horizontallly centers text in text area)
  • alpha {Float}: alpha value (0 is transparent, 1 is opaque)
+
+ + + + + + + + +
+ + +
+ +
+ gbox.blitTile(tox, data) + +
+
+ Draws a tile to a canvas context + + + + +
// from capman, draws an current object's tile, called from inside its blit function
gbox.blitTile(gbox.getBufferContext(),{tileset:this.tileset,tile:this.frame,dx:this.x,dy:this.y,fliph:this.fliph,flipv:this.flipv,camera:this.camera,alpha:1});
+ +
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ {Object} + + tox + + The canvas context to be drawn on. +
+ {Object} + + data + + An object containing data about the tile to be drawn, including:
  • tileset {String}: the id of the tileset
  • tile {Integer}: the index of the tile within the tileset to be drawn
  • dx {Integer}: x coordinate to draw the tile at
  • dy {Integer}: y coordinate to draw the tile at
  • fliph {Integer}: horizontal flip, either 1 or -1
  • flipv {Integer}: vertical flip, either 1 or -1
  • alpha {Float}: alpha value (0 is transparent, 1 is opaque)
+
+ + + + + + + + +
+ + +
+ +
+ gbox.blitTilemap(tox, data) + +
+
+ Draws a tilemap to a canvas context + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ {Object} + + tox + + The canvas context to be drawn on. +
+ {Object} + + data + + An object containing a set of tilemap data, including:
  • tileset {String}: (required) the id of the tileset the tilemap is based on
  • map {Array}: an array whose x and y coord represent the tilemap coordinates, containing integers that correspond to the index of a given tile (or null for no tile)
+
+ + + + + + + + +
+ + +
+ +
+ gbox.canLog() + +
+
+ + + + + +

+										
+									
+ + + + + + + + + +
+ + +
+ +
+ gbox.centerCamera(data, viewdata) + +
+
+ Centers the camera. + + + + +
// Center the camera on the player object
gbox.centerCamera(gbox.getObject('player', 'player_id'), {w: map.w, h: map.h});
+ +
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ {Object} + + data + + An object containing x and y parameters -- typically the object you wish to center the camera on. +
+ {Object} + + viewdata + + An object containing parameters h and w, which are a bounding box that the camera is not supposed to leave. For example, to use your map as a bounding area for the camera, pass along {w: map.w, h: map.h}. +
+ + + + + + + + +
+ + +
+ +
+ gbox.changeAudioVolume(a, vol) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ + + a + + +
+ + + vol + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.changeChannelVolume(ch, a) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ + + ch + + +
+ + + a + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.clearCache() + +
+
+ + + + + +

+										
+									
+ + + + + + + + + +
+ + +
+ +
+ gbox.clearGroup(gid) + +
+
+ Destroys all objects in a given group. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {String} + + gid + + The id of the group. +
+ + + + + + + + +
+ + +
+ +
+ gbox.collides(o1, o2, t) + +
+
+ Calculates a box collision between two collision boxes within a given tolerance. A higher tolerance means less precise collision. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + +
+ {Object} + + o1 + + A collision box you're testing for collision. Must contain:
  • x {Integer}: (required) the x coordinate of the object's origin; assumes the Akihabara default of top-left being the origin
  • y {Integer}: (required) the y coordinate of the object's origin; assumes the Akihabara default of top-left being the origin
  • w {Integer}: (required) the width of the box
  • h {Integer}: (required) the height the box
+
+ {Object} + + o2 + + A collision box you're testing for collision. Must contain:
  • x {Integer}: (required) the x coordinate of the object's origin; assumes the Akihabara default of top-left being the origin
  • y {Integer}: (required) the y coordinate of the object's origin; assumes the Akihabara default of top-left being the origin
  • w {Integer}: (required) the width of the box
  • h {Integer}: (required) the height the box
+
+ {Integer} + + t + + The tolerance for the collision, in pixels. A value of 0 means pixel-perfect box collision. A value of 2 would mean that the boxes could overlap by up to 2 pixels without being considered a collision. +
+ + + + + +
Returns:
+ + + + + + + +
+ + + True if the two collision boxes are colliding within the given tolerance. +
+ + + + +
+ + +
+ +
+ gbox.createCanvas(id, data) + +
+
+ Creates a new canvas. By default, the width and height is the current gbox._screenw and gbox._screenh, but it can also be set by passing in a data object with the appropriate parameters. + + + + +
gbox.createCanvas('newCanvas', {w: 640, h: 480});
+ +
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ {String} + + id + + The id of the new canvas. +
+ {Object} + + data + + (Optional) The height and width of the new canvas, contained in data.h and data.w parameters. +
+ + + + + + + + +
+ + +
+ +
+ gbox.dataClear(k) + +
+
+ Clears a value stored in a key-value pair in a browser cookie. Sets value to "". Only works if user has cookies enabled. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {String} + + k + + The key which identifies the value you are clearing. +
+ + + + + + + + +
+ + +
+ +
+ gbox.dataLoad(k, a) + : Object +
+
+ Loads data from a browser cookie. Send it a key and it returns a value (if available). Only works if user has cookies enabled. + + + + +
hiscore = gbox.dataLoad("hiscore");
+ +
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ {String} + + k + + The key which identifies the value you are loading. +
+ {String} + + a + + A switch to determine whether a string or a number is returned. By default a string is returned. +
+ + + + + +
Returns:
+ + + + + + + +
+ {Object} + + A string or a number loaded from the cookie. +
+ + + + +
+ + +
+ +
+ gbox.dataSave(k, v, d) + +
+
+ Saves data to a browser cookie as a key-value pair, which can be restored later using gbox.dataLoad. Only works if user has cookies enabled. + + + + +
// (from Capman)
gbox.dataSave("capman-hiscore",maingame.hud.getNumberValue("score","value"));
+ +
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + +
+ {String} + + k + + The key which identifies the value you are storing. +
+ {String} + + v + + The value you wish to store. Needs to be a string! +
+ {String} + + d + + A date offset, to be added to the current date. Defines the cookie's expiration date. By default this is set to 10 years. +
+ + + + + + + + +
+ + +
+ +
+ gbox.debugGetstats() + +
+
+ Displays basic audio, object, and performance statistics in the status bar. Automatically called each frame if the status bar is enabled. + + + + +

+										
+									
+ + + + + + + + + +
+ + +
+ +
+ gbox.deleteAudio(id) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + id + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.deleteCanvas(id) + +
+
+ Deletes a given canvas. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {String} + + id + + The id of the canvas to be deleted. +
+ + + + + + + + +
+ + +
+ +
+ gbox.deleteImage(id) + +
+
+ Deletes an image currently in use. Does not delete the image file, but removes it from Akihabara's image list. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {String} + + id + + The identifier of the image. +
+ + + + + + + + +
+ + +
+ +
+ gbox.getAudioDuration(a) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + a + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.getAudioIsSingleChannel() + +
+
+ + + + + +

+										
+									
+ + + + + + + + + +
+ + +
+ +
+ gbox.getAudioMute(a) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + a + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.getAudioPosition(a) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + a + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.getAudioVolume(a, vol) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ + + a + + +
+ + + vol + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.getBuffer() + : Object +
+
+ Gets the buffer canvas (automatically created by gbox.initScreen). + + + + +

+										
+									
+ + + + + + +
Returns:
+ + + + + + + +
+ {Object} + + A DOM Canvas element, including the width and height of the canvas. +
+ + + + +
+ + +
+ +
+ gbox.getBufferContext() + : Object +
+
+ Gets the buffer canvas context. + + + + +

+										
+									
+ + + + + + +
Returns:
+ + + + + + + +
+ {Object} + + A DOM Canvas context object. +
+ + + + +
+ + +
+ +
+ gbox.getCamera() + : Object +
+
+ Gets the current camera object. + + + + +

+										
+									
+ + + + + + +
Returns:
+ + + + + + + +
+ {Object} + + The camera object. +
+ + + + +
+ + +
+ +
+ gbox.getCanvas(id) + : Object +
+
+ Gets a given canvas. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {Object} + + id + + The identifier of the canvas. +
+ + + + + +
Returns:
+ + + + + + + +
+ {Object} + + A DOM Canvas element, including the width and height of the canvas. +
+ + + + +
+ + +
+ +
+ gbox.getCanvasContext(id) + : Object +
+
+ Gets the two-dimensional canvas context of a given canvas. The object it returns contains all the drawing functions for the canvas. See W3C and Mozilla Developer Center for details. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {Object} + + id + + The identifier of the canvas. +
+ + + + + +
Returns:
+ + + + + + + +
+ {Object} + + A DOM Canvas context object. +
+ + + + +
+ + +
+ +
+ gbox.getChannelDefaultVolume(ch) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + ch + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.getChannelVolume(ch) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + ch + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.getFlag(f) + +
+
+ Returns a gbox flag at index f. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {Object} + + f + + The index of the flag you want returned. +
+ + + + + + + + +
+ + +
+ +
+ gbox.getFont(id) + +
+
+ Returns a font object containing data about the font. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {String} + + id + + The id of the font, as set in gbox.addFont. +
+ + + + + + + + +
+ + +
+ +
+ gbox.getFps() + : Integer +
+
+ Get the frames per second rate (default is 25). + + + + +

+										
+									
+ + + + + + +
Returns:
+ + + + + + + +
+ {Integer} + + Returns the frames per second. +
+ + + + +
+ + +
+ +
+ gbox.getGroups() + : Array +
+
+ Get an array containing the names of each group in the game, in order of rendering. + + + + +
grouplist = gbox.getGroups();
grouplist; // => ["background", "player", "enemy", "game"]
+ +
+ + + + + + +
Returns:
+ + + + + + + +
+ {Array} + + An array of group names. +
+ + + + +
+ + +
+ +
+ gbox.getImage(id) + : Object +
+
+ Gets information about a loaded image. + + + + +
image = gbox.getImage('logo');
image; // => ?
+ +
+ + +
Parameters:
+ + + + + + + + +
+ {String} + + id + + The id of the image. +
+ + + + + +
Returns:
+ + + + + + + +
+ {Object} + + A DOM Image element, including the URL and last modified date of the image, its ID, and whether it was loaded successfully. +
+ + + + +
+ + +
+ +
+ gbox.getObject(group, id) + : Object +
+
+ Given a group and an id for a particular object instance, this returns the instance requested. NOTE: this does not return a copy of the object you've requested! Any modifications you make to the object returned are directly modifying the object you requested. + + + + +
// Find the player and reduce health by half.
playertemp = gbox.getObject('player','player_id');
player.health = player.health/2;
+ +
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ {String} + + group + + The id of the group that contains the object. +
+ {String} + + id + + The id of the instance of the object. +
+ + + + + +
Returns:
+ + + + + + + +
+ {Object} + + The object requested. +
+ + + + +
+ + +
+ +
+ gbox.getScreenH() + : Integer +
+
+ Get the screen height. + + + + +

+										
+									
+ + + + + + +
Returns:
+ + + + + + + +
+ {Integer} + + Screen height in pixels. +
+ + + + +
+ + +
+ +
+ gbox.getScreenHH() + : Integer +
+
+ Get the screen half-height. + + + + +

+										
+									
+ + + + + + +
Returns:
+ + + + + + + +
+ {Integer} + + Screen half-height in pixels. +
+ + + + +
+ + +
+ +
+ gbox.getScreenHW() + : Integer +
+
+ Get the screen half-width. + + + + +

+										
+									
+ + + + + + +
Returns:
+ + + + + + + +
+ {Integer} + + Screen half-width in pixels. +
+ + + + +
+ + +
+ +
+ gbox.getScreenW() + : Integer +
+
+ Get the screen width. + + + + +

+										
+									
+ + + + + + +
Returns:
+ + + + + + + +
+ {Integer} + + Screen width in pixels. +
+ + + + +
+ + +
+ +
+ gbox.getTiles(t) + +
+
+ Gets an Akihabara tileset, adding it to the engine. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {String} + + t + + The ID of a tileset. +
+ + + + + +
Returns:
+ + + + + + + +
+ + + An object containing:
  • id {String}: the new id of the tileset
  • image {String}: reference to the tileset image loaded
  • tileh {Integer}: height in pixels of the tiles
  • tilew {Integer}: width in pixels of the tiles
  • tilerow {Integer}: width in pixels of each row in the font image
  • gapx {Integer}: x-coord gap between tile columns, in pixels
  • gapy {Integer}: y-coord gap between tile rows, in pixels
+
+ + + + +
+ + +
+ +
+ gbox.go() + +
+
+ This function is called once per frame. This is where the basic rendering and processing of groups occurs. + + + + +

+										
+									
+ + + + + + + + + +
+ + +
+ +
+ gbox.groupIsEmpty(gid) + : Boolean +
+
+ Returns whether a given group contains no objets. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {String} + + gid + + The group you're checking. +
+ + + + + +
Returns:
+ + + + + + + +
+ {Boolean} + + True if the group contains no objects. +
+ + + + +
+ + +
+ +
+ gbox.hitAudio(a, data) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ + + a + + +
+ + + data + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.imageIsLoaded(id) + : Boolean +
+
+ Checks to see if an image was successfully loaded. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {String} + + id + + The id of the image. +
+ + + + + +
Returns:
+ + + + + + + +
+ {Boolean} + + True if the image has been loaded. +
+ + + + +
+ + +
+ +
+ gbox.initScreen(w, h) + +
+
+ Initializes the screen to a certain width and height, applies zoom attributes, populates the body of the HTML document including the canvas element, sets an initial camera, creates a '_buffer' canvas, sets keyboard event listeners, and many other initialization functions. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ {Integer} + + w + + The width of the main canvas. +
+ {Integer} + + h + + The height of the main canvas. +
+ + + + + + + + +
+ + +
+ +
+ gbox.keyIsHit(id) + : Boolean +
+
+ Returns true if a given key in this._keymap is pressed. Only returns true on the transition from unpressed to pressed. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {String} + + id + + A key in the keymap. By default, one of: "up" "down" "left" "right" "a" "b" "c" +
+ + + + + +
Returns:
+ + + + + + + +
+ {Boolean} + + True if the given key is transitioning from unpressed to pressed in this frame. +
+ + + + +
+ + +
+ +
+ gbox.keyIsHold(id) + : Boolean +
+
+ Returns true if a given key in this._keymap has been held down for at least one frame. Will not return true if a key is quickly tapped, only once it has been held down for a frame. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {String} + + id + + A key in the keymap. By default, one of: "up" "down" "left" "right" "a" "b" "c" +
+ + + + + +
Returns:
+ + + + + + + +
+ {Boolean} + + True if the given key has been held down for at least one frame. +
+ + + + +
+ + +
+ +
+ gbox.keyIsPressed(id) + : Boolean +
+
+ Returns true if a given key in this._keymap is being held down. Returns true as long as the key is held down. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {String} + + id + + A key in the keymap. By default, one of: "up" "down" "left" "right" "a" "b" "c" +
+ + + + + +
Returns:
+ + + + + + + +
+ {Boolean} + + True if the given key is held down. +
+ + + + +
+ + +
+ +
+ gbox.keyIsReleased(id) + : Boolean +
+
+ Returns true if a given key in this._keymap is released. Only returns true on the transition from pressed to unpressed. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {String} + + id + + A key in the keymap. By default, one of: "up" "down" "left" "right" "a" "b" "c" +
+ + + + + +
Returns:
+ + + + + + + +
+ {Boolean} + + True if the given key is transitioning from pressed to unpressed in this frame. +
+ + + + +
+ + +
+ +
+ gbox.loadAll(cb) + +
+
+ Loads the initial splash screen and debugging font, then calls gbox._waitforloaded which adds to the game all the previously defined resources. Once gbox._waitforloaded is done, it calls the callback function cb. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + cb + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.log() + +
+
+ + + + + +

+										
+									
+ + + + + + + + + +
+ + +
+ +
+ gbox.objectIsTrash(o) + : Boolean +
+
+ Returns whether an object is due to be trashed. Useful in cases you want to check if an object is marked as trash before it is actually deleted. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {Object} + + o + + The object you're checking. +
+ + + + + +
Returns:
+ + + + + + + +
+ {Boolean} + + True if the object is marked as trash. +
+ + + + +
+ + +
+ +
+ gbox.objectIsVisible(obj) + +
+
+ Determines whether an object is visible by seeing if it collides with the camera's viewport. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {Object} + + obj + + The object you're testing to see if it's visible. Must contain:
  • x {Integer}: (required) the x coordinate of the object's origin; assumes the Akihabara default of top-left being the origin
  • y {Integer}: (required) the y coordinate of the object's origin; assumes the Akihabara default of top-left being the origin
  • w {Integer}: (required) the width of the object's collision box
  • h {Integer}: (required) the height the object's box
+
+ + + + + +
Returns:
+ + + + + + + +
+ + + True if the object's collision box is within the camera's viewport. +
+ + + + +
+ + +
+ +
+ gbox.pixelcollides(o1, o2, t) + +
+
+ Calculates a point-box collision between a point and a collision box within a given tolerance. A higher tolerance means less precise collision. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + +
+ {Object} + + o1 + + A point you're testing for collision. Must contain:
  • x {Integer}: (required) the x coordinate of the point
  • y {Integer}: (required) the y coordinate of the point
+
+ {Object} + + o2 + + A collision box you're testing for collision. Must contain:
  • x {Integer}: (required) the x coordinate of the object's origin; assumes the Akihabara default of top-left being the origin
  • y {Integer}: (required) the y coordinate of the object's origin; assumes the Akihabara default of top-left being the origin
  • w {Integer}: (required) the width of the box
  • h {Integer}: (required) the height the box
+
+ {Integer} + + t + + The tolerance for the collision, in pixels. A value of 0 means pixel-perfect collision. A value of 2 would mean that the point could exist within the outermost 2 pixels of the box without being considered a collision. +
+ + + + + +
Returns:
+ + + + + + + +
+ + + True if the point is colliding with the box within the given tolerance. +
+ + + + +
+ + +
+ +
+ gbox.playAllGroups() + +
+
+ Enables all groups, toggling any groups that are currently disabled. + + + + +

+										
+									
+ + + + + + + + + +
+ + +
+ +
+ gbox.playAudio(a, data) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ + + a + + +
+ + + data + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.playGroup(gid) + +
+
+ If a group is disabled, this will enable the group. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {String} + + gid + + The id of the group. +
+ + + + + + + + +
+ + +
+ +
+ gbox.playGroups(gid) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + gid + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.purgeGarbage(obj) + +
+
+ Clears the record held in gbox._garbage of what has been deleted. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {Object} + + obj + + The object you wish to delete. +
+ + + + + + + + +
+ + +
+ +
+ gbox.readBundleData(pack, call) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ + + pack + + +
+ + + call + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.resetChannel(ch) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + ch + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.setAudioChannels(a) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + a + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.setAudioCompatMode(m) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + m + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.setAudioCreateMode(m) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + m + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.setAudioDequeueTime(m) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + m + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.setAudioMute(a) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + a + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.setAudioPosition(a, p) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ + + a + + +
+ + + p + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.setAudioPositionDelay(m) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + m + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.setAudioTeam(a) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + a + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.setAudioUnmute(a) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + a + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.setAudioVolume(a, vol) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ + + a + + +
+ + + vol + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.setAutoskip(f) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + f + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.setCallback(cb) + +
+
+ Deprecated: gbox._cb is now set by passing it directly into gbox.loadAll(). Left in for backwards compatibility. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {String} + + cb + + The name of the function to be called once gbox.loadAll is completed. +
+ + + + + + + + +
+ + +
+ +
+ gbox.setCameraX(x, viewdata) + +
+
+ Sets the x value of the current camera object. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ {Integer} + + x + + The camera object's new x value. +
+ {Object} + + viewdata + + An object containing parameters h and w, which are a bounding box that the camera is not supposed to leave. For example, to use your map as a bounding area for the camera, pass along {w: map.w, h: map.h}. +
+ + + + + + + + +
+ + +
+ +
+ gbox.setCameraY(y, viewdata) + +
+
+ Sets the y value of the current camera object. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ {Integer} + + y + + The camera object's new y value. +
+ {Object} + + viewdata + + An object containing parameters h and w, which are a bounding box that the camera is not supposed to leave. For example, to use your map as a bounding area for the camera, pass along {w: map.w, h: map.h}. +
+ + + + + + + + +
+ + +
+ +
+ gbox.setCanAudio(a) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + a + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.setCanLog(c) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + c + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.setChannelVolume(ch, a) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ + + ch + + +
+ + + a + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.setDoubleBuffering(db) + +
+
+ Sets the gbox._db property. Turns on an off double buffering. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {Boolean} + + db + + The value to write to gbox._db. True enables double buffering, false disables. +
+ + + + + + + + +
+ + +
+ +
+ gbox.setForcedIdle(f) + +
+
+ Sets the gbox._forcedidle property. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {Boolean} + + f + + The value to write to gbox._forcedidle. +
+ + + + + + + + +
+ + +
+ +
+ gbox.setFps(f) + +
+
+ Set the frames per second rate. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {Integer} + + f + + Total frames per second for the game to run at. +
+ + + + + + + + +
+ + +
+ +
+ gbox.setFrameskip(f) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + f + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.setGroups(g) + +
+
+ Defines the names of each group in the game along with their rendering order. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {Array} + + g + + An array of strings of group names, in the order in which the groups should be rendered. So g[0] will contain the first group to render, g[1] the second group to render, etc. +
+ + + + + + + + +
+ + +
+ +
+ gbox.setLowerAudioTeam(a) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + a + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.setRenderOrder(g) + +
+
+ A method of setting the render order of groups independently of gbox.setGroups. Sets gbox._renderorder, which by default is equivalent to gbox._groups. However, gbox._renderorder is what ultimately determines the rendering order of groups. If you need to change your rendering order on the fly, use this function by passing it a reordered array of group names. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {Array} + + g + + An array of strings of group names, in the order in which the groups should be rendered. So g[0] will contain the first group to render, g[1] the second group to render, etc. +
+ + + + + + + + +
+ + +
+ +
+ gbox.setScreenBorder(a) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + a + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.setShowPlayers(m) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + m + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.setSplashSettings(a) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + a + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.setStatBar(txt) + +
+
+ Writes text to the status bar, but only if the status bar is enabled. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {String} + + txt + + The text to write to the status bar. +
+ + + + + + + + +
+ + +
+ +
+ gbox.setStatusBar(f) + +
+
+ Sets the gbox._statbar property. Only useful if called before gbox.initScreen. Debugging funtionality. Much easier to access if you add '?statusbar=1' to your URL. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {Boolean} + + f + + The value to write to gbox._statbar. +
+ + + + + + + + +
+ + +
+ +
+ gbox.setZindex(th, z) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ + + th + + +
+ + + z + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.setZoom(z) + +
+
+ Sets the gbox._zoom parameter, only works before gbox.initScreen is called. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {Integer} + + z + + Zoom factor. +
+ + + + + + + + +
+ + +
+ +
+ gbox.soloGroup(gid) + +
+
+ Turns off all groups except for the one specified. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {String} + + gid + + The id of the group. +
+ + + + + + + + +
+ + +
+ +
+ gbox.stopAudio(a, permissive) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ + + a + + +
+ + + permissive + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.stopChannel(ch) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + ch + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.stopGroup(gid) + +
+
+ If a group is enabled, this will disable the group. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {String} + + gid + + The id of the group. +
+ + + + + + + + +
+ + +
+ +
+ gbox.stopGroups(gid) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + gid + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.toggleGroup(gid) + +
+
+ Toggles a group between enabled and disabled status. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {String} + + gid + + The id of the group. +
+ + + + + + + + +
+ + +
+ +
+ gbox.toggleGroups(gid) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + gid + + +
+ + + + + + + + +
+ + +
+ +
+ gbox.trashGroup(group) + +
+
+ Deletes every object in a given group. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {String} + + group + + The group id. +
+ + + + + + + + +
+ + +
+ +
+ gbox.trashObject(obj) + +
+
+ Deletes an object, keeping a record of its group and id in gbox._garbage. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {Object} + + obj + + The object you wish to delete. +
+ + + + + + + + +
+ +
+
+ + +
+ + +
+ + Documentation generated by JsDoc Toolkit 2.3.2 on Wed Aug 18 2010 16:09:24 GMT-0400 (EDT) +
+ +
+
+ + + diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/symbols/help.html b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/help.html new file mode 100644 index 0000000..0c23c9c --- /dev/null +++ b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/help.html @@ -0,0 +1,2668 @@ + + + + + + + JsDoc Reference - help + + + + + + + + + +
+
+ +
+
+
+
 
+
Project Outline
+
+ + +
+ +
+ + + +
+
createMaingame(id, group)
+ +
+
+
 
gbox
addAudio(id, filename, def)
addBundle(call)
addFont(data)
addImage(id, filename)
addObject(data)
addScript(call)
blit(tox, image, data)
blitAll(tox, image, data)
blitClear(image, data)
blitFade(tox, data)
blitRect(tox, data)
blitText(tox, data)
blitTile(tox, data)
blitTilemap(tox, data)
centerCamera(data, viewdata)
collides(o1, o2, t)
createCanvas(id, data)
dataLoad(k, a)
dataSave(k, v, d)
getObject(group, id)
go()
hitAudio(a, data)
log()
pixelcollides(o1, o2, t)
playAudio(a, data)
readBundleData(pack, call)
setCameraX(x, viewdata)
setCameraY(y, viewdata)
setZindex(th, z)
stopAudio(a, permissive)
trashGroup(group)
+ +
+
+
 
help
asciiArtToMap(map, tra)
copyModel(data, model)
createModel(obj, attrs)
decideFrame(cnt, anim)
decideFrameOnce(cnt, anim)
framestotime(frames)
getArrayIndexed(a, value, field)
getTileInMap(x, y, map, ifout, mapid)
isLastFrameOnce(cnt, anim)
isSquished(th, by)
limit(v, min, max)
mergeWithModel(data, model)
multiplier(v, mul)
postpad(str, len, pad)
prepad(str, len, pad)
random(min, range)
seq(st, ed, skip)
setTileInMap(ctx, map, x, y, tile, The)
upAndDown(counter, max)
xPixelToTile(map, x, gap)
xPixelToTileX(map, x, gap)
yPixelToTile(map, y, gap)
yPixelToTileY(map, y, gap)
+ +
+
bounce(th, data)
horizontalKeys(th, keys)
horizontalTileCollision(th, map, tilemap)
initialize(th, data)
jumpKeys(th, key)
spawn(th, data)
verticalTileCollision(th, map, tilemap)
+ +
+
controlKeys(th, keys)
fireBullet(gr, id, data)
generateEnemy(gr, id, data, model)
generateScroller(gr, id, data)
hitByBullet(th, by)
initialize(th, data)
spawn(th, data)
+ +
+
after(th, id, frames)
every(th, id, frames)
randomly(th, id, data)
real(th, id, data)
+ +
+
+
 
tool
makecels(data)
+ +
+
callInColliding(th, data)
collides(fr, to, t)
controlKeys(th, keys)
fireBullet(gr, id, data)
floorCollision(th, data)
getAheadPixel(th, data)
initialize(th, data)
makedoor(gr, id, map, data)
pixelcollides(fr, to, t)
setStaticSpeed(th, speed)
spawn(th, data)
tileCollision(th, map, tilemap, defaulttile, data)
wander(th, map, tilemap, defaulttile, data)
+ + + +
+
+
 
trigo
addAngle(a, add)
getAngle(p1, p2, transl)
getDistance(p1, p2)
translate(p1, a, d)
translateX(x1, a, d)
translateY(y1, a, d)
+ +
+
+
+ + +
+
«
+ + + +
+ Akihabara Framework +
+ + + +
+ +

+ Namespace help +

+ + + +
+

Help module provides some Javascript-specific functions, such object copying, randomizing functions, string/array handlers and the akihabaraInit function.

+
+ +

Defined in: help.js.

+ + + + + + + + + + + + + +
+
Method Summary
+
+ +
+ + akihabaraInit(data) + This provides a number of configurations: fps, display zoom, dynamic frameskip, force touch parameters, etc. Many of these settings can be set manually by passing an object with the parameters defined, or via URL parameters. +
+ +
+ + asciiArtToMap(map, tra) + Takes an ascii-art-style array of characters and converts it to an Akihabara-compatible map format. +
+ +
+ + cloneObject(model) + Creates a duplicate of an existing set of parameters. +
+ +
+ + copyModel(data, model) + Merges two sets of parameters together overwriting any existing parameters. This merges model->data, and if data and model share parameters, data's are overwritten by model's. +
+ +
+ + createModel(obj, attrs) + Creates a subset of an existing set of parameters. +
+ +
+ + decideFrame(cnt, anim) + Determines which frame of a given animation to display. Will loop an animation. +
+ +
+ + decideFrameOnce(cnt, anim) + Determines which frame of a given animation to display. Will remain on the last frame when the animation has played once. +
+ +
+ + finalizeTilemap(map) + Calculates and sets the width and height (map.h, map.w) and half-width and half-height (map.hh, map.hw) of a map object. +
+ +
+ + framestotime(frames) + Converts a quantity of frames into a timestamp formatted "mm:ss:cs" (minutes, seconds, centiseconds). Calculated using the current frames per second. +
+ +
+ + getArrayCapped(a, id) + Returns the Nth element in an array. If the array is shorter than N, it returns the last element of the array. +
+ +
+ + getArrayIndexed(a, value, field) + +
+ +
+ + getDeviceConfig() + Automatically configures a bunch of settings depending on the web browser and device that is viewing the game. Mostly sets the maximum number of audio channels and touch settings. +
+ +
+ + getTileInMap(x, y, map, ifout, mapid) + Given x,y coordinates and map information, this returns the tile at a given point. +
+ +
+ + geturlparameter(name) + Reads the value of a query parameter from the URL of the web page. +
+ +
+ + goToZero(v) + Subtracts or adds 1 to a value, always converging to zero. For example, passing -3 yields -2, 5 yields 4, etc. +
+ +
+ + isDefined(A) + Tests whether an object contains a given parameter. +
+ +
+ + isLastFrameOnce(cnt, anim) + Returns whether the animation was fully played at least once with decideFrame or fully with decideFrameOnce. +
+ +
+ + 0 means you're falling onto something else.">isSquished(th, by) + Tests to see if an object is being "jumped on" by another object. Only works for platformers, since it assumes accy>0 means you're falling onto something else. +
+ +
+ + limit(v, min, max) + Limits a number to a certain range. If the number is below the minimum, the minimum is returned. +
+ +
+ + mergeWithModel(data, model) + Merges two sets of parameters together without overwriting existing parameters. This merges from model to data, and if data and model share parameters, data's values remain intact. +
+ +
+ + multiplier(v, mul) + Multiplies two numbers together, returning the result, unless the first parameter is less than 2, in which case it returns 1. +
+ +
+ + objToStr(Any) + Writes the contents of an object to a string. Useful for debugging. +
+ +
+ + postpad(str, len, pad) + Postpends a string with repeated instances of another string until it the result is greater than or equal to a desired length. +
+ +
+ + prepad(str, len, pad) + Prepends a string with repeated instances of another string until it the result is greater than or equal to a desired length. +
+ +
+ + random(min, range) + Generates uniformly distributed random integers between min and min+range, non-inclusive. So help.random(0,2) will only return 0 and 1, etc. +
+ +
+ + seq(st, ed, skip) + Generates numbers from st to ed, along with a skip value. +
+ +
+ + setTileInMap(ctx, map, x, y, tile, The) + Sets a tile in the map and draws it. Does not return anything. +
+ +
+ + upAndDown(counter, max) + Given an incrementing value each step, this will return a value increasing from 0 until max/2, at which point it will decrement to 0, then go back up to max/2, in an endless cycle. +
+ +
+ + xPixelToTile(map, x, gap) + Converts an x-coordinate of a pixel to the x-coordinate of the tile column it's in. This effectively "snaps" an x coordinate to a tile edge. +
+ +
+ + xPixelToTileX(map, x, gap) + Converts an x-coordinate of a pixel to its corresponding tile x-coordinate. +
+ +
+ + yPixelToTile(map, y, gap) + Converts a y-coordinate of a pixel to the y-coordinate of the tile row it's in. This effectively "snaps" a y coordinate to a tile edge. +
+ +
+ + yPixelToTileY(map, y, gap) + Converts a y-coordinate of a pixel to its corresponding tile y-coordinate. +
+ +
+
+ + + + + + + + + + + +
+
+ Method Detail +
+
+ + +
+ +
+ help.akihabaraInit(data) + +
+
+ This provides a number of configurations: fps, display zoom, dynamic frameskip, force touch parameters, etc. Many of these settings can be set manually by passing an object with the parameters defined, or via URL parameters. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {Object} + + data + + An optional object containing parameters you wish to set. Works for data.zoom, data.splash, data.width, data.height, data.title, data.fps, and data.padmode. +
+ + + + + + + + +
+ + +
+ +
+ help.asciiArtToMap(map, tra) + +
+
+ Takes an ascii-art-style array of characters and converts it to an Akihabara-compatible map format. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ {Array} + + map + + An array of characters representing a map. +
+ {Array} + + tra + + A translation array. This is an array of arrays, formatted like [ [null, char1], [0, char2], [1, char3] ]. There must at least be a null entry, followed by one numerical entry for each tile type you want to render, corresponding to the unique characters in the map array. The null entry maps a character to empty space. +
+ + + + + +
Returns:
+ + + + + + + +
+ + + A map array formatted such that it can be attached to a map object. +
+ + + + +
+ + +
+ +
+ help.cloneObject(model) + +
+
+ Creates a duplicate of an existing set of parameters. + + + + +
data = {a: 1, b: 2, c: "three"};
newdata = help.cloneObject(data);
newdata; // => {a: 1, b: 2, c: "three"}
+ +
+ + +
Parameters:
+ + + + + + + + +
+ {Object} + + model + + An object containing a set of parameters. +
+ + + + + +
Returns:
+ + + + + + + +
+ + + A new object, equivalent to 'model'. +
+ + + + +
+ + +
+ +
+ help.copyModel(data, model) + +
+
+ Merges two sets of parameters together overwriting any existing parameters. This merges model->data, and if data and model share parameters, data's are overwritten by model's. + + + + +
dst = {a: 1, b: 2, c: "three"};
src = {c: "three", d: "four"};
merged = help.mergeWithModel(dst,src);
merged; // => {a: 1, b: 2, c: "three", d: "four"}
+ +
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ {Object} + + data + + An object containing a set of parameters, the destination of the merge. +
+ {Object} + + model + + An object containing a set of parameters, the source of the merge. +
+ + + + + +
Returns:
+ + + + + + + +
+ + + A merged model where the values of 'model' take precedence over those of 'data'. The 'data' object is returned and will be an exact copy of 'model', plus any parameters that 'data' had before the merge that 'model' did not. +
+ + + + +
+ + +
+ +
+ help.createModel(obj, attrs) + +
+
+ Creates a subset of an existing set of parameters. + + + + +
data = {a: 1, b: 2, c: "three"};
newdata = help.createModel(data, ["a", "c"]);
newdata; // => {a: 1, c: "three"}
+ +
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ {Object} + + obj + + An object containing a set of parameters, the source of the data. +
+ {Array} + + attrs + + An array of strings, containing the names of parameters you wish to copy. +
+ + + + + +
Returns:
+ + + + + + + +
+ + + A new set of parameters based on the subset specified. +
+ + + + +
+ + +
+ +
+ help.decideFrame(cnt, anim) + +
+
+ Determines which frame of a given animation to display. Will loop an animation. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ {Integer} + + cnt + + A global frame counter. +
+ {Object} + + anim + + An object with parameters speed (the animation speed) and frames (the array representing the animation sequence). +
+ + + + + +
Returns:
+ + + + + + + +
+ + + The particular animation frame to display during this step. +
+ + + + +
+ + +
+ +
+ help.decideFrameOnce(cnt, anim) + +
+
+ Determines which frame of a given animation to display. Will remain on the last frame when the animation has played once. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ {Integer} + + cnt + + A global frame counter. +
+ {Object} + + anim + + An object with parameters speed (the animation speed) and frames (the array representing the animation sequence). +
+ + + + + +
Returns:
+ + + + + + + +
+ + + The particular animation frame to display during this step. +
+ + + + +
+ + +
+ +
+ help.finalizeTilemap(map) + +
+
+ Calculates and sets the width and height (map.h, map.w) and half-width and half-height (map.hh, map.hw) of a map object. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {Object} + + map + + A map object, containing a map array and a tileset array. +
+ + + + + +
Returns:
+ + + + + + + +
+ + + A map object with map.w, map.h, map.hh, and map.hw set correctly. +
+ + + + +
+ + +
+ +
+ help.framestotime(frames) + +
+
+ Converts a quantity of frames into a timestamp formatted "mm:ss:cs" (minutes, seconds, centiseconds). Calculated using the current frames per second. + + + + +
// Assuming 25 frames per second, Akihabara's default.
timestamp = help.framestotime(25);
timestamp; // => '00:01:00';
timestamp = help.framestotime(25 * 60);
timestamp; // => '01:00:00';
+ +
+ + +
Parameters:
+ + + + + + + + +
+ {Integer} + + frames + + A quantity of frames. +
+ + + + + +
Returns:
+ + + + + + + +
+ + + A string containing a timestamp formatted "mm:ss:cs", representing the length of time it would take to render that many frames. +
+ + + + +
+ + +
+ +
+ help.getArrayCapped(a, id) + +
+
+ Returns the Nth element in an array. If the array is shorter than N, it returns the last element of the array. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ {Array} + + a + + An array. +
+ {Integer} + + id + + An index to the array. +
+ + + + + +
Returns:
+ + + + + + + +
+ + + If id > a.length, it returns a[a.length-1]. Otherwise returns a[id]. +
+ + + + +
+ + +
+ +
+ help.getArrayIndexed(a, value, field) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + +
+ + + a + + +
+ + + value + + +
+ + + field + + +
+ + + + + + + + +
+ + +
+ +
+ help.getDeviceConfig() + +
+
+ Automatically configures a bunch of settings depending on the web browser and device that is viewing the game. Mostly sets the maximum number of audio channels and touch settings. + + + + +

+										
+									
+ + + + + + + + + +
+ + +
+ +
+ help.getTileInMap(x, y, map, ifout, mapid) + +
+
+ Given x,y coordinates and map information, this returns the tile at a given point. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ {Integer} + + x + + An x-coordinate. +
+ {Integer} + + y + + A y-coordinate. +
+ {Object} + + map + + The map object. +
+ {Object} + + ifout + + An object or value to be returned if the x,y coordinate pair is outside the map. +
+ {String} + + mapid + + The id for the map array within the map object. Default is 'map'. +
+ + + + + +
Returns:
+ + + + + + + +
+ + + An integer representing the value of the tile in the map array at that x,y coordinate. If there is no tile, null is returned. +
+ + + + +
+ + +
+ +
+ help.geturlparameter(name) + +
+
+ Reads the value of a query parameter from the URL of the web page. + + + + +
// If the URL is http://example.com/game.html?lives=3
player.lives = help.geturlparameter("lives");
player.lives; // => 3
+ +
+ + +
Parameters:
+ + + + + + + + +
+ {String} + + name + + The name of the URL parameter. +
+ + + + + +
Returns:
+ + + + + + + +
+ + + The value of the URL parameter, as a string. +
+ + + + +
+ + +
+ +
+ help.goToZero(v) + +
+
+ Subtracts or adds 1 to a value, always converging to zero. For example, passing -3 yields -2, 5 yields 4, etc. Works best with integers. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {Integer} + + v + + A value. +
+ + + + + +
Returns:
+ + + + + + + +
+ + + A value that is one closer to 0 on the number line than v. +
+ + + + +
+ + +
+ +
+ help.isDefined(A) + +
+
+ Tests whether an object contains a given parameter. + + + + +
foo = {a: 1, b: 2};
help.isDefined(foo.a); // => true
help.isDefined(foo.c); // => false
+ +
+ + +
Parameters:
+ + + + + + + + +
+ {Object} + + A + + reference to a parameter of an object. +
+ + + + + +
Returns:
+ + + + + + + +
+ + + True if the object contains that parameter, false if it does not. +
+ + + + +
+ + +
+ +
+ help.isLastFrameOnce(cnt, anim) + +
+
+ Returns whether the animation was fully played at least once with decideFrame or fully with decideFrameOnce. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ {Integer} + + cnt + + A global frame counter. +
+ {Object} + + anim + + An object with parameters speed (the animation speed) and frames (the array representing the animation sequence). +
+ + + + + +
Returns:
+ + + + + + + +
+ + + A boolean, true if the animation has been played at least once. +
+ + + + +
+ + +
+ +
+ help.isSquished(th, by) + +
+
+ Tests to see if an object is being "jumped on" by another object. Only works for platformers, since it assumes accy>0 means you're falling onto something else. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ {Object} + + th + + The object that is (possibly) being jumped on. +
+ {Object} + + by + + The object doing the jumping-on. +
+ + + + + +
Returns:
+ + + + + + + +
+ + + True if the two objects are overlapping enough and by.accy>0. +
+ + + + +
+ + +
+ +
+ help.limit(v, min, max) + +
+
+ Limits a number to a certain range. If the number is below the minimum, the minimum is returned. If the number is above the maximum, the maximum is returned. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + +
+ {Float} + + v + + A value. +
+ {Float} + + min + + The minimum limit. +
+ {Float} + + max + + The maximum limit. +
+ + + + + +
Returns:
+ + + + + + + +
+ + + A value equal to v if minmax. +
+ + + + +
+ + +
+ +
+ help.mergeWithModel(data, model) + +
+
+ Merges two sets of parameters together without overwriting existing parameters. This merges from model to data, and if data and model share parameters, data's values remain intact. + + + + +
dst = {a: 1, b: 2, c: "three"};
src = {c: "three", d: "four"};
merged = help.mergeWithModel(dst,src);
merged; // => {a: 1, b: 2, c: 3, d: "four"};
+ +
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ {Object} + + data + + An object containing a set of parameters, the destination of the merge. +
+ {Object} + + model + + An object containing a set of parameters, the source of the merge. +
+ + + + + +
Returns:
+ + + + + + + +
+ + + A merged model where the values of 'data' remain untouched: only new parameters and values from 'model' make it in. +
+ + + + +
+ + +
+ +
+ help.multiplier(v, mul) + +
+
+ Multiplies two numbers together, returning the result, unless the first parameter is less than 2, in which case it returns 1. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ {Float} + + v + + First value. +
+ {Float} + + mul + + Second value. +
+ + + + + +
Returns:
+ + + + + + + +
+ + + An integer, v*mul, unless v<2 in which case it returns 1. +
+ + + + +
+ + +
+ +
+ help.objToStr(Any) + +
+
+ Writes the contents of an object to a string. Useful for debugging. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {Object} + + Any + + object. +
+ + + + + +
Returns:
+ + + + + + + +
+ + + A string containing all the contents of an object. If the object contains functions, the string will contain the code for those functions. +
+ + + + +
+ + +
+ +
+ help.postpad(str, len, pad) + +
+
+ Postpends a string with repeated instances of another string until it the result is greater than or equal to a desired length. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + +
+ {String} + + str + + The string you wish to modify. +
+ {Integer} + + len + + The desired length of your resultant string. +
+ {String} + + pad + + The string you wish to postpend to str. +
+ + + + + +
Returns:
+ + + + + + + +
+ + + A string whose length is no greater than len+pad.length, with pad postpending str repeatedly. +
+ + + + +
+ + +
+ +
+ help.prepad(str, len, pad) + +
+
+ Prepends a string with repeated instances of another string until it the result is greater than or equal to a desired length. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + +
+ {String} + + str + + The string you wish to modify. +
+ {Integer} + + len + + The desired length of your resultant string. +
+ {String} + + pad + + The string you wish to prepend to str. +
+ + + + + +
Returns:
+ + + + + + + +
+ + + A string whose length is no greater than len+pad.length, with pad prepending str repeatedly. +
+ + + + +
+ + +
+ +
+ help.random(min, range) + +
+
+ Generates uniformly distributed random integers between min and min+range, non-inclusive. So help.random(0,2) will only return 0 and 1, etc. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ {Integer} + + min + + The minimum random value to be returned by the function. +
+ {Integer} + + range + + The number of different values returned by the function. +
+ + + + + +
Returns:
+ + + + + + + +
+ + + An integer between min (includive) and min+range (noninclusive). +
+ + + + +
+ + +
+ +
+ help.seq(st, ed, skip) + +
+
+ Generates numbers from st to ed, along with a skip value. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + +
+ {Integer} + + st + + Starting number. +
+ {Integer} + + ed + + Ending number. +
+ {Integer} + + skip + + Number to increment by. +
+ + + + + +
Returns:
+ + + + + + + +
+ + + An array containing the set of numbers from st to ed, incrementing by skip. +
+ + + + +
+ + +
+ +
+ help.setTileInMap(ctx, map, x, y, tile, The) + +
+
+ Sets a tile in the map and draws it. Does not return anything. + + + + +
// Remove the second tile to the right and down from the upper left corner of the tile map. Assumes our map canvas is called 'map_canvas'.
help.setTileInMap(gbox.getCanvasContext("map_canvas"),map,1,1,null,"map");
+ +
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ {Object} + + ctx + + The canvas context for the map. Accessed via gbox.getCanvasContext("canvasname") +
+ {Object} + + map + + The game map object. +
+ {Integer} + + x + + The index of the tile column within the map array -- so a 1 would mean the second column of tiles. +
+ {Integer} + + y + + The index of the tile row within the map array -- so a 1 would mean the second row of tiles. +
+ {Integer} + + tile + + The integer representing the new tile you wish to draw. This is its index within the tileset; a null value will erase whatever tile is present. +
+ {String} + + The + + ID of the map. Defaults to 'map'. +
+ + + + + + + + +
+ + +
+ +
+ help.upAndDown(counter, max) + +
+
+ Given an incrementing value each step, this will return a value increasing from 0 until max/2, at which point it will decrement to 0, then go back up to max/2, in an endless cycle. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ {Integer} + + counter + + A counter. +
+ {Integer} + + max + + This determines the period of the function -- assuming counter is incrementing by one, a complete back-and-forth will take 'max' steps. +
+ + + + + +
Returns:
+ + + + + + + +
+ + + An integer. +
+ + + + +
+ + +
+ +
+ help.xPixelToTile(map, x, gap) + +
+
+ Converts an x-coordinate of a pixel to the x-coordinate of the tile column it's in. This effectively "snaps" an x coordinate to a tile edge. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + +
+ {Object} + + map + + A map object, containing a map array and a tileset array. +
+ {Integer} + + x + + An x-coordinate. +
+ {Integer} + + gap + + Number of pixels gap in tilemap. Default is 0. +
+ + + + + +
Returns:
+ + + + + + + +
+ + + The x-coordinate in pixels of the tile column. +
+ + + + +
+ + +
+ +
+ help.xPixelToTileX(map, x, gap) + +
+
+ Converts an x-coordinate of a pixel to its corresponding tile x-coordinate. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + +
+ {Object} + + map + + A map object, containing a map array and a tileset array. +
+ {Integer} + + x + + An x-coordinate. +
+ {Integer} + + gap + + (Not used.) +
+ + + + + +
Returns:
+ + + + + + + +
+ + + A map object with map.w, map.h, map.hh, and map.hw set correctly. +
+ + + + +
+ + +
+ +
+ help.yPixelToTile(map, y, gap) + +
+
+ Converts a y-coordinate of a pixel to the y-coordinate of the tile row it's in. This effectively "snaps" a y coordinate to a tile edge. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + +
+ {Object} + + map + + A map object, containing a map array and a tileset array. +
+ {Integer} + + y + + A y-coordinate. +
+ {Integer} + + gap + + Number of pixels gap in tilemap. Default is 0. +
+ + + + + +
Returns:
+ + + + + + + +
+ + + The y-coordinate in pixels of the tile row. +
+ + + + +
+ + +
+ +
+ help.yPixelToTileY(map, y, gap) + +
+
+ Converts a y-coordinate of a pixel to its corresponding tile y-coordinate. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + +
+ {Object} + + map + + A map object, containing a map array and a tileset array. +
+ {Integer} + + y + + A y-coordinate. +
+ {Integer} + + gap + + (Not used.) +
+ + + + + +
Returns:
+ + + + + + + +
+ + + A map object with map.w, map.h, map.hh, and map.hw set correctly. +
+ + + + +
+ +
+
+ + +
+ + +
+ + Documentation generated by JsDoc Toolkit 2.3.2 on Wed Aug 18 2010 16:09:24 GMT-0400 (EDT) +
+ +
+
+ + + diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/symbols/iphopad.html b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/iphopad.html new file mode 100644 index 0000000..9fac52d --- /dev/null +++ b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/iphopad.html @@ -0,0 +1,205 @@ + + + + + + + JsDoc Reference - iphopad + + + + + + + + + +
+
+ +
+
+
+
 
+
Project Outline
+
+ + +
+ +
+ + + +
+
createMaingame(id, group)
+ +
+
+
 
gbox
addAudio(id, filename, def)
addBundle(call)
addFont(data)
addImage(id, filename)
addObject(data)
addScript(call)
blit(tox, image, data)
blitAll(tox, image, data)
blitClear(image, data)
blitFade(tox, data)
blitRect(tox, data)
blitText(tox, data)
blitTile(tox, data)
blitTilemap(tox, data)
centerCamera(data, viewdata)
collides(o1, o2, t)
createCanvas(id, data)
dataLoad(k, a)
dataSave(k, v, d)
getObject(group, id)
go()
hitAudio(a, data)
log()
pixelcollides(o1, o2, t)
playAudio(a, data)
readBundleData(pack, call)
setCameraX(x, viewdata)
setCameraY(y, viewdata)
setZindex(th, z)
stopAudio(a, permissive)
trashGroup(group)
+ +
+
+
 
help
asciiArtToMap(map, tra)
copyModel(data, model)
createModel(obj, attrs)
decideFrame(cnt, anim)
decideFrameOnce(cnt, anim)
framestotime(frames)
getArrayIndexed(a, value, field)
getTileInMap(x, y, map, ifout, mapid)
isLastFrameOnce(cnt, anim)
isSquished(th, by)
limit(v, min, max)
mergeWithModel(data, model)
multiplier(v, mul)
postpad(str, len, pad)
prepad(str, len, pad)
random(min, range)
seq(st, ed, skip)
setTileInMap(ctx, map, x, y, tile, The)
upAndDown(counter, max)
xPixelToTile(map, x, gap)
xPixelToTileX(map, x, gap)
yPixelToTile(map, y, gap)
yPixelToTileY(map, y, gap)
+ +
+
+
 
iphopad
+ +
+
+
 
tool
makecels(data)
+ +
+
callInColliding(th, data)
collides(fr, to, t)
controlKeys(th, keys)
fireBullet(gr, id, data)
floorCollision(th, data)
getAheadPixel(th, data)
initialize(th, data)
makedoor(gr, id, map, data)
pixelcollides(fr, to, t)
setStaticSpeed(th, speed)
spawn(th, data)
tileCollision(th, map, tilemap, defaulttile, data)
wander(th, map, tilemap, defaulttile, data)
+ +
+
+
 
toys
getToyStatus(th, id)
getToyValue(th, id, v, def)
resetToy(th, id)
+ +
+
+
 
trigo
addAngle(a, add)
getAngle(p1, p2, transl)
getDistance(p1, p2)
translate(p1, a, d)
translateX(x1, a, d)
translateY(y1, a, d)
+ +
+
+
+ + +
+
«
+ + + +
+ Akihabara Framework +
+ + + +
+ +

+ Namespace iphopad +

+ + + +
+

Iphopad module provides a touchpad for touch-based device (for now, Android and iDevices).

+
+ +

Defined in: iphopad.js.

+ + + + + + + + + + + + + +
+
Method Summary
+
+ +
+ + initialize(data) + Initializes the game controls for use with an I-product or Android device. +
+ +
+
+ + + + + + + + + + + +
+
+ Method Detail +
+
+ + +
+ +
+ iphopad.initialize(data) + +
+
+ Initializes the game controls for use with an I-product or Android device. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {Object} + + data + + Passes in information about the screen and its traits such as size. +
+ + + + + + + + +
+ +
+
+ + +
+ + +
+ + Documentation generated by JsDoc Toolkit 2.3.2 on Wed Aug 18 2010 12:50:14 GMT-0400 (EDT) +
+ +
+
+ + + diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/symbols/src/c__Users_Darius_Desktop_akihabara-1.1_kesiev_akihabara_akihabara_gamecycle.js.html b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/src/c__Users_Darius_Desktop_akihabara-1.1_kesiev_akihabara_akihabara_gamecycle.js.html new file mode 100644 index 0000000..0108623 --- /dev/null +++ b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/src/c__Users_Darius_Desktop_akihabara-1.1_kesiev_akihabara_akihabara_gamecycle.js.html @@ -0,0 +1,439 @@ +
  1 // ---
+  2 // Copyright (c) 2010 Francesco Cottone, http://www.kesiev.com/
+  3 // ---
+  4 
+  5 /**
+  6  * @namespace
+  7  * Gamecycle contains your basic game loop: intro, menus, 
+  8  * crossfading between stages/lifes, gameover and ending. 
+  9  */
+ 10 var gamecycle={
+ 11 
+ 12 	/**
+ 13 	 * Gamecycle constructor - initializes a new game object
+ 14 	 * 
+ 15 	 * @param	id		unique id of object
+ 16 	 * @param	group		name of group to store the object in
+ 17 	 */
+ 18 	createMaingame:function(id,group) {
+ 19 	return gbox.addObject({
+ 20 		id:id,
+ 21 		group:group,
+ 22 		counter:0,
+ 23 		difficulty:0,
+ 24 		
+ 25 		// state transition
+ 26 		state:50,  
+ 27 		stateFirstIteration:true, 
+ 28 		
+ 29 		hud:{},
+ 30 		
+ 31 		/**
+ 32 		 * This method is called whenever you load a new map. It's meant to be
+ 33 		 * overridden when you create your game.
+ 34 		 */
+ 35 		changeLevel:function() { },
+ 36 		
+ 37 		/**
+ 38 		 * This method is called every time a player is "reborn". This method is 
+ 39 		 * meant to be overridden since you have to do garbage collection. 
+ 40 		 */
+ 41 		newLife:function() { },
+ 42 
+ 43 		// game disclaimer animation (if needed)
+ 44 		gameDisclaimerAnimation:function(reset) {
+ 45 			return true;
+ 46 		 },
+ 47 		
+ 48 		// game intro animation
+ 49 		gameIntroAnimation:function(reset) {
+ 50 			if (reset) {
+ 51 				gbox.stopChannel("bgmusic");
+ 52 				toys.resetToy(this,"default-blinker");
+ 53 			} else {
+ 54 				gbox.blitFade(gbox.getBufferContext(),{alpha:1});
+ 55 				return toys.text.blink(this,"default-blinker",gbox.getBufferContext(),{font:"small",text:"LETS BEGIN!",valign:gbox.ALIGN_MIDDLE,halign:gbox.ALIGN_CENTER,dx:0,dy:0,dw:gbox.getScreenW(),dh:gbox.getScreenH(),blinkspeed:5,times:6});
+ 56 			}
+ 57 		 },
+ 58 		 
+ 59 		// level intro animation
+ 60 		levelIntroAnimation:function(reset) {
+ 61 			if (reset) {
+ 62 				gbox.stopChannel("bgmusic");
+ 63 				toys.resetToy(this,"default-blinker");
+ 64 			} else {
+ 65 				gbox.blitFade(gbox.getBufferContext(),{alpha:1});
+ 66 				return toys.text.blink(this,"default-blinker",gbox.getBufferContext(),{font:"small",text:"GET READY!",valign:gbox.ALIGN_MIDDLE,halign:gbox.ALIGN_CENTER,dx:0,dy:0,dw:gbox.getScreenW(),dh:gbox.getScreenH(),blinkspeed:5,times:6});
+ 67 			}
+ 68 		 },
+ 69 	  
+ 70 		 // Life intro animation
+ 71 		 newlifeIntroAnimation:function(reset) {
+ 72 			 if (reset) {
+ 73 				gbox.stopChannel("bgmusic");
+ 74 				toys.resetToy(this,"default-blinker");
+ 75 			} else {
+ 76 				gbox.blitFade(gbox.getBufferContext(),{alpha:1});
+ 77 				return toys.text.fixed(this,"default-blinker",gbox.getBufferContext(),{font:"small",text:"GET READY!",valign:gbox.ALIGN_MIDDLE,halign:gbox.ALIGN_CENTER,dx:0,dy:0,dw:gbox.getScreenW(),dh:gbox.getScreenH(),time:30});
+ 78 			}
+ 79 		},
+ 80 		
+ 81 		// gameover animation
+ 82 		gameoverIntroAnimation:function(reset) {
+ 83 			 if (reset) {
+ 84 				gbox.stopChannel("bgmusic");
+ 85 				toys.resetToy(this,"default-blinker");
+ 86 			} else {
+ 87 				gbox.blitFade(gbox.getBufferContext(),{alpha:1});
+ 88 				return toys.text.fixed(this,"default-blinker",gbox.getBufferContext(),{font:"small",text:"GAME OVER",valign:gbox.ALIGN_MIDDLE,halign:gbox.ALIGN_CENTER,dx:0,dy:0,dw:gbox.getScreenW(),dh:gbox.getScreenH(),time:50});
+ 89 			}
+ 90 		},
+ 91 		
+ 92 		// game title animation
+ 93 		gameTitleIntroAnimation:function(reset) {
+ 94 			if (reset)
+ 95 				gbox.stopChannel("bgmusic");
+ 96 			else {
+ 97 				gbox.blitFade(gbox.getBufferContext(),{alpha:1});
+ 98 				gbox.blitText(gbox.getBufferContext(),{font:"small",text:"GAME TITLE",valign:gbox.ALIGN_MIDDLE,halign:gbox.ALIGN_CENTER,dx:0,dy:0,dw:gbox.getScreenW(),dh:gbox.getScreenH()-100});
+ 99 			}
+100 		},
+101 		
+102 		// End level animation
+103 		endlevelIntroAnimation:function(reset) {
+104 			 if (reset) {
+105 				 toys.resetToy(this,"default-blinker");
+106 			} else {
+107 				return toys.text.blink(this,"default-blinker",gbox.getBufferContext(),{font:"small",text:"WELL DONE!",valign:gbox.ALIGN_MIDDLE,halign:gbox.ALIGN_CENTER,dx:0,dy:0,dw:gbox.getScreenW(),dh:gbox.getScreenH(),blinkspeed:5,times:10});
+108 			}
+109 		},
+110 		
+111 		// Game ending
+112 		gameEndingIntroAnimation:function(reset) {
+113 			if (reset) {
+114 				toys.resetToy(this,"default-blinker");
+115 			} else {
+116 				gbox.blitFade(gbox.getBufferContext(),{alpha:1});
+117 				return toys.text.blink(this,"default-blinker",gbox.getBufferContext(),{font:"small",text:"CONGRATULATIONS!",valign:gbox.ALIGN_MIDDLE,halign:gbox.ALIGN_CENTER,dx:0,dy:0,dw:gbox.getScreenW(),dh:gbox.getScreenH(),blinkspeed:5,times:10});
+118 			}		  	
+119 		},
+120 		
+121 		// PRESS START
+122 		pressStartIntroAnimation:function(reset) {
+123 			if (reset) {
+124 				toys.resetToy(this,"default-blinker");
+125 			} else {
+126 				toys.text.blink(this,"default-blinker",gbox.getBufferContext(),{font:"small",text:"PRESS A TO START",valign:gbox.ALIGN_MIDDLE,halign:gbox.ALIGN_CENTER,dx:0,dy:Math.floor(gbox.getScreenH()/3),dw:gbox.getScreenW(),dh:Math.floor(gbox.getScreenH()/3)*2,blinkspeed:10});
+127 				return gbox.keyIsHit("a");
+128 			}
+129 		},
+130 		
+131 		/**
+132 		 * This method is called when the player dies.
+133 		 */
+134 		gameIsOver:function() { return true; },
+135 		
+136 		/** 
+137 		 * Actions done during the game (i.e. stage is clear or other ending conditions)
+138 		 */
+139 		gameEvents:function() {
+140 		
+141 		},
+142 		
+143 		gameMenu:function(reset) {
+144 			if (reset) {
+145 				toys.resetToy(this,"difficulty");
+146 			} else {
+147 				gbox.blitFade(gbox.getBufferContext(),{alpha:0.5});
+148 				if (toys.ui.menu(this,"difficulty",{audiooption:"default-menu-option",audioconfirm:"default-menu-confirm",font:"small",keys:{up:"up",down:"down",ok:"a",cancel:"b"},selector:">",items:["EASY","NORMAL","HARD"],x:10,y:10})) {
+149 					if (toys.getToyValue(this,"difficulty","ok") == -1) return -1;
+150 					else {
+151 						this.difficulty=toys.getToyValue(this,"difficulty","selected");
+152 						return true;
+153 					}
+154 				}
+155 				return false;
+156 			}
+157 		},
+158 	  
+159 		// CHECK
+160 		
+161 		gameIsHold:function() { // Use this clause to check collision and kill player: if true the level is changing
+162 			return (this.state==400)||(this.state==401);
+163 		},
+164 		
+165 		isCompleted:function() {
+166 			return (this.state==800);
+167 		},
+168 		
+169 		// GAME CYCLE
+170 		
+171 		getNextLevel:function() {
+172 			return this._nextlevel;
+173 		},
+174 		
+175 		gotoLevel:function(level) {
+176 			this._nextlevel=level;
+177 			this.setState(400);
+178 		},
+179 		
+180 		playerDied:function(data) {
+181 			this._loselife=data;
+182 			this.setState(500);
+183 		},
+184 		
+185 		gameIsCompleted:function() {
+186 			this.setState(800);
+187 		},
+188 		
+189 		// private methods
+190 		
+191 		/**
+192 		 * Changes the current game state
+193 		 * 
+194 		 * @param	st	state number
+195 		 */
+196 		setState:function(st) {
+197 			this.state=st;
+198 			this.stateFirstIteration=true;
+199 		},
+200 	
+201 		/*
+202 		 * Removes all objects in each group except the game 
+203 		 * cycle group. Used for garbage collection when resetting the game.
+204 		 */	
+205 		_resetGroups:function() {
+206 			var g=gbox.getGroups();
+207 			for (var i=0;i<g.length;i++)
+208 				if (g[i]!=this.group) gbox.clearGroup(g[i]);
+209 			gbox.soloGroup(this.group);
+210 		},
+211 
+212 		stateIsReady:function() { this.stateFirstIteration=false; },
+213 
+214 		blit:function() {
+215 			switch (this.state) {
+216 
+217 				// Disclaimer
+218 				case 50: {
+219 					if (this.stateFirstIteration) {
+220 						this._resetGroups();
+221 						this.gameDisclaimerAnimation(true);
+222 						this.stateIsReady();
+223 					}
+224 					if (this.gameDisclaimerAnimation(false)) 
+225 						this.setState(100);
+226 					break;
+227 				}
+228 				// main menu
+229 				case 100: 
+230 				case 101:
+231 				case 102: { // Press Start / Menu
+232 					if (this.stateFirstIteration && (this.state == 100)) {
+233 						this._resetGroups();
+234 						this.gameTitleIntroAnimation(true);
+235 					}
+236 					this.gameTitleIntroAnimation(false);
+237 					switch (this.state) {
+238 						case 100: { // Press to start
+239 							if (this.stateFirstIteration) {
+240 								gbox.resetChannel("bgmusic");
+241 								this.pressStartIntroAnimation(true);
+242 								this.stateIsReady();
+243 							}
+244 							if (this.pressStartIntroAnimation(false)) this.setState(101);
+245 							break;
+246 						}
+247 						case 101: { // Game menu
+248 							if (this.stateFirstIteration) {
+249 								gbox.setChannelVolume("bgmusic",0.5);
+250 								this.gameMenu(true);
+251 								this.stateIsReady();
+252 							}
+253 							
+254 							var menu=this.gameMenu(false);
+255 							if (menu)
+256 								if (menu == -1) this.setState(100); else this.setState(102);
+257 							break;
+258 						}
+259 						case 102: { // Fader
+260 							if (this.stateFirstIteration) {
+261 								this._resetGroups();
+262 								toys.resetToy(this,"fadeout");
+263 								this.stateIsReady();
+264 							}
+265 							if (toys.fullscreen.fadeout(this,"fadeout",gbox.getBufferContext(),{fadespeed:0.05,audiochannelfade:"bgmusic"}))
+266 								this.setState(200);
+267 							break;
+268 						}
+269 						break;
+270 					}
+271 					break;
+272 				}
+273 				case 200:// Game intro animation
+274 				
+275 				case 300:// Start game
+276 				case 301:// Game is going
+277 				
+278 				case 400:// Fade out to change level
+279 				case 401:// Level animation (levelIntroAnimation)
+280 				case 402:// Fade in to next level
+281 				
+282 				case 500:// Wait after dead
+283 				case 501:// Dead fadeout
+284 				
+285 				case 600:// Next life intro
+286 				case 601:// New life fadein
+287 				
+288 				case 700:// Gameover animation
+289 
+290 				case 800:// Fade out game ending
+291 				case 801:// Game ending
+292 
+293 				{ // Game playing
+294 					if (this.stateFirstIteration) {
+295 						switch (this.state) {
+296 							case 200: { // Game intro
+297 								toys.resetToy(this,"fadein");
+298 								this.level=null;
+299 								this._nextlevel=null;
+300 								this.hud=toys.ui.hud("maingamehud");
+301 								
+302 								this.initializeGame();
+303 								this.gameIntroAnimation(true);
+304 								
+305 								break;
+306 							}
+307 							case 300: {
+308 								// Game start
+309 								this.level=this._nextlevel;
+310 								gbox.playAllGroups();
+311 								this.changeLevel(this._nextlevel);
+312 							}
+313 							case 800:
+314 							case 400:{
+315 								this.endlevelIntroAnimation(true);
+316 								toys.resetToy(this,"fadeout");
+317 								break;
+318 							}
+319 							case 501: {
+320 								toys.resetToy(this,"fadeout");
+321 								break;
+322 							}
+323 							case 401: {
+324 								gbox.soloGroup(this.group);
+325 								this.levelIntroAnimation(true);
+326 								break;
+327 							}
+328 							case 402: {
+329 								toys.resetToy(this,"fadein");
+330 								this.level=this._nextlevel;
+331 								gbox.playAllGroups();
+332 								this.changeLevel(this._nextlevel);
+333 								break;
+334 							}
+335 							case 600: {
+336 								gbox.soloGroup(this.group);
+337 								this.newlifeIntroAnimation(true);
+338 								break;
+339 							}
+340 							case 500: {
+341 								this._loselife.counter=0;
+342 								break;
+343 							}
+344 							case 601: {
+345 								toys.resetToy(this,"fadein");
+346 								this.newLife();
+347 								gbox.playAllGroups();
+348 								break;
+349 							}
+350 							case 700: {
+351 								gbox.resetChannel("bgmusic");
+352 								gbox.soloGroup(this.group);
+353 								this.gameoverIntroAnimation(true);
+354 								break;
+355 							}
+356 							case 801: {
+357 								gbox.resetChannel("bgmusic");
+358 								gbox.soloGroup(this.group);
+359 								this.gameEndingIntroAnimation(true);
+360 								break;
+361 							}
+362 						}
+363 						this.stateIsReady();
+364 					}
+365 					
+366 					switch (this.state) {
+367 						case 200: { // Game intro
+368 							if (this.gameIntroAnimation(false)) this.setState(300);
+369 							break;
+370 						}
+371 						case 601: // Fade in with new life
+372 						case 402: // Fade in after level change
+373 						case 300: { // Fade in at the beginning of the game
+374 							if (toys.fullscreen.fadein(this,"fadein",gbox.getBufferContext(),{fadespeed:0.05,audiochannelfade:"bgmusic"})) this.setState(301);
+375 							break;
+376 						}
+377 						case 301: { // Ingame stuff
+378 							this.gameEvents();
+379 							break;
+380 						}
+381 						case 400: { // Fade out before changing the level
+382 							if (this.endlevelIntroAnimation(false))
+383 								if (toys.fullscreen.fadeout(this,"fadeout",gbox.getBufferContext(),{fadespeed:0.05,audiochannelfade:"bgmusic"})) this.setState(401);
+384 							break;
+385 						}
+386 						case 800: { // Fade out before game ending
+387 							if (this.endlevelIntroAnimation(false))
+388 								if (toys.fullscreen.fadeout(this,"fadeout",gbox.getBufferContext(),{fadespeed:0.05,audiochannelfade:"bgmusic"})) this.setState(801);
+389 							break;
+390 						}
+391 						case 501: { // Fade out after dead
+392 							if (toys.fullscreen.fadeout(this,"fadeout",gbox.getBufferContext(),{fadespeed:0.05,audiochannelfade:"bgmusic"})) 
+393 								if (this.gameIsOver())
+394 									this.setState(700); // GAME OVER
+395 								else
+396 									this.setState(600);
+397 							break;
+398 						}
+399 						case 401:{ // Level intro animation
+400 							if (this.levelIntroAnimation(false)) this.setState(402);
+401 							break;
+402 						}
+403 						case 500: { // Wait after dead
+404 							this._loselife.counter++;
+405 							if (this._loselife.counter==this._loselife.wait) this.setState(501);
+406 							break;
+407 						}
+408 						case 600:{ // New life intro
+409 							if (this.newlifeIntroAnimation(false)) this.setState(601);
+410 							break;
+411 						}
+412 						case 700:{ // gameover
+413 							if (this.gameoverIntroAnimation(false)) this.setState(100); // Restart game
+414 							break;
+415 						}
+416 						case 801:{ // Game ending
+417 							if (this.gameEndingIntroAnimation(false)) {
+418 								this._loselife={ending:true};
+419 								this.setState(700); // Game over
+420 							}
+421 							break;
+422 						}
+423 					}
+424 					this.hud.blit();
+425 					break;
+426 				}
+427 			}
+428 		}
+429 	});
+430 	}
+431 }
+432 
\ No newline at end of file diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/symbols/src/c__Users_Darius_Desktop_akihabara-1.1_kesiev_akihabara_akihabara_gbox.js.html b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/src/c__Users_Darius_Desktop_akihabara-1.1_kesiev_akihabara_akihabara_gbox.js.html new file mode 100644 index 0000000..07d8319 --- /dev/null +++ b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/src/c__Users_Darius_Desktop_akihabara-1.1_kesiev_akihabara_akihabara_gbox.js.html @@ -0,0 +1,1856 @@ +
  1 // ---
+  2 // Copyright (c) 2010 Francesco Cottone, http://www.kesiev.com/
+  3 // ---
+  4 
+  5 var dynalist={
+  6 	create:function() {
+  7 		return {
+  8 			first:null,
+  9 			last:null,
+ 10 			data:[],
+ 11 			dl:0,
+ 12 			gar:[],
+ 13 			disconnect:function(obd) {
+ 14 				if (this.data[obd].__first!=null)  this.data[this.data[obd].__first].__next=this.data[obd].__next; else this.first=this.data[obd].__next;
+ 15 				if (this.data[obd].__next!=null)  this.data[this.data[obd].__next].__first=this.data[obd].__first; else this.last=this.data[obd].__first;
+ 16 			},
+ 17 			addObject:function(obj,prio) {
+ 18 				var nid=this.gar.pop();
+ 19 				if (nid==null) {
+ 20 					nid=this.dl;
+ 21 					this.dl++;
+ 22 				}
+ 23 				if (this.first==null) { // First element
+ 24 					obj.__next=null;
+ 25 					obj.__first=null;
+ 26 					this.first=nid;
+ 27 					this.last=nid;
+ 28 				} else { // Chain next
+ 29 					var i=this.first;
+ 30 					while (i!=null)
+ 31 						if (this.data[i].__prio>prio) break; else i=this.data[i].__next;
+ 32 					if (i==null) { // if last, chain in queue
+ 33 						obj.__next=null;
+ 34 						obj.__first=this.last;								
+ 35 						this.data[this.last].__next=nid;
+ 36 						this.last=nid;								
+ 37 					} else { // else reconnect objects
+ 38 						obj.__first=this.data[i].__first;
+ 39 						obj.__next=i;
+ 40 						this.data[i].__first=nid;
+ 41 						if (obj.__first!=null) this.data[obj.__first].__next=nid; else this.first=nid;
+ 42 					}
+ 43 					
+ 44 				}
+ 45 				obj.__prio=prio;
+ 46 				obj.__id=nid;
+ 47 				this.data[nid]=obj;
+ 48 				return nid;
+ 49 			},
+ 50 			setPrio:function(obd,prio) {
+ 51 				if (this.data[obd].__prio==prio) return;
+ 52 				if (this.first!=this.last)
+ 53 				if (this.data[obd].__prio<prio) {
+ 54 					if (this.data[obd].__id!=this.last) {
+ 55 						var i=this.data[obd].__next;
+ 56 						while (i!=null)
+ 57 							if (this.data[i].__prio>=prio) break; else i=this.data[i].__next;
+ 58 						if ((i==null)||(this.data[i].__first!=this.data[obd].__id)) {
+ 59 							// disconnect
+ 60 							this.disconnect(obd);
+ 61 							// Reconnect
+ 62 							if (i==null) {
+ 63 								this.data[this.last].__next=this.data[obd].__id;
+ 64 								this.data[obd].__first=this.last;
+ 65 								this.data[obd].__next=null;
+ 66 								this.last=this.data[obd].__id;
+ 67 							} else {
+ 68 								this.data[obd].__first=this.data[i].__first;
+ 69 								this.data[obd].__next=i;
+ 70 								this.data[i].__first=this.data[obd].__id;
+ 71 								if (this.data[obd].__first!=null) this.data[this.data[obd].__first].__next=this.data[obd].__id; else this.first=this.data[obd].__id;
+ 72 							}
+ 73 						}
+ 74 					}
+ 75 				} else {
+ 76 					if (this.data[obd].__id!=this.first) {
+ 77 						var i=this.data[obd].__first;
+ 78 						while (i!=null)
+ 79 							if (this.data[i].__prio<=prio) break; else i=this.data[i].__first;
+ 80 						if ((i==null)||(this.data[i].__next!=this.data[obd].__id)) {
+ 81 							// disconnect
+ 82 							this.disconnect(obd);
+ 83 							if (i==null) {
+ 84 								this.data[this.first].__first=this.data[obd].__id;
+ 85 								this.data[obd].__first=null;
+ 86 								this.data[obd].__next=this.first;
+ 87 								this.first=this.data[obd].__id;
+ 88 							} else {
+ 89 								this.data[obd].__first=i;
+ 90 								this.data[obd].__next=this.data[i].__next;
+ 91 								this.data[i].__next=this.data[obd].__id;
+ 92 								if (this.data[obd].__next!=null) this.data[this.data[obd].__next].__first=this.data[obd].__id; else this.last=this.data[obd].__id;
+ 93 							}
+ 94 						}
+ 95 					}
+ 96 				}
+ 97 				this.data[obd].__prio=prio;
+ 98 			},
+ 99 			remove:function(obd) {
+100 				this.disconnect(obd);
+101 				this.gar.push(this.data[obd].__id);
+102 				delete this.data[this.data[obd].__id];
+103 			}
+104 		}
+105 	}
+106 }
+107 
+108 // A special circular queue with some features useful for the resource loader
+109 var cyclelist={
+110 	create:function(size) {
+111 		return {
+112 			_head:0,
+113 			_tail:0,
+114 			_data:[],
+115 			_size:(size?size:10),
+116 			_total:0,
+117 			_done:0,
+118 			_current:null,
+119 			getTotal:function(){return this._total}, // Number of elements to be "poped"
+120 			getDone:function(){return this._done}, // Number of popped elements since the last empty
+121 			getSize:function(){return this._size}, // The maximum number of elements in the queue
+122 			isProcessing:function(){return this._current!=null}, // The last pop was not a null (i.e. the queue returned a valid object)
+123 			isEnded:function(){return (this._head==this._tail)}, // There are other elements in the queue
+124 			isBusy:function(){return this.isProcessing()||!this.isEnded()}, // There are elements in the queue/the last one pop returned an object that is being processed
+125 			getCurrent:function(){return this._current}, // Return the last popped element
+126 			push:function(d) {
+127 				this._data[this._head]=d;
+128 				this._head=(this._head+1)%this._size;
+129 				this._total++;
+130 			},
+131 			pop:function() {
+132 				if (this.isEnded()) {
+133 					this._total=0;
+134 					this._done=0;
+135 					this._current=null;
+136 				} else {
+137 					this._current=this._data[this._tail];
+138 					this._tail=(this._tail+1)%this._size;
+139 					this._done++;
+140 				}
+141 				return this._current;
+142 			},
+143 			dump:function() {
+144 				var r="";
+145 				for (var i=0;i<this._size;i++) {
+146 					r+=i+") "+this._data[i]+" | "+(i==this._head?"HEAD ":"")+(i==this._tail?"TAIL ":"")+"\n";
+147 				}
+148 				r+="\n\n"+this._done+"/"+this._total;
+149 				return r;
+150 			}
+151 		}
+152 	}
+153 }
+154 
+155 // A simple circular cache handler
+156 var cachelist={
+157 	create:function(size) {
+158 		return {
+159 			_cache:{},
+160 			_queue:[],
+161 			_head:0,
+162 			_size:(size?size:10),
+163 			add:function(k,v) {
+164 				if (!this._cache[k]) {
+165 					if (this._queue[this._head])
+166 						delete this._cache[this._queue[this._head]];
+167 					this._queue[this._head]=k;
+168 					this._cache[k]={pos:this._head,value:v};
+169 					this._head=(this._head+1)%this._size;
+170 				} else this._cache[k].value=v;
+171 			},
+172 			read:function(k) {
+173 				return (this._cache[k]?this._cache[k].value:null);
+174 			},
+175 			clear:function() {
+176 				this._cache={};
+177 				this._queue=[];
+178 				this._head=0;
+179 			}
+180 		}
+181 	}
+182 }
+183 
+184 /**
+185  * @namespace
+186  * Gamebox module allows multiple grouped objects to move simultaneously, it helps with collisions, 
+187  * rendering and moving objects. It also provides monospaced pixel-font rendering, keyboard handling,  
+188  * audio, double buffering and eventually FSEs. Gamebox can also store and load data from cookies! 
+189  */
+190 var gbox={
+191 	// CONSTANTS
+192 	ALIGN_CENTER:0,
+193 	ALIGN_MIDDLE:0,
+194 	ALIGN_RIGHT:1,
+195 	ALIGN_BOTTOM:1,
+196 	COLOR_BLACK:'rgb(0,0,0)',
+197 	COLOR_WHITE:'rgb(255,255,255)',
+198 	ZINDEX_LAYER:-1,
+199 	
+200 	// VARS
+201 	_autoid:0,
+202 	_cb:null, // callback for loadAll()
+203 	_keyboard:[],
+204 	_keymap:{
+205 		up:38,
+206 		down:40,
+207 		right:39,
+208 		left:37,
+209 		a:90,
+210 		b:88,
+211 		c:67
+212 	},
+213 	_flags:{
+214 		experimental:false,
+215 		noaudio:false
+216 	},
+217 	_fonts:{},
+218 	_tiles:{},
+219 	_images:{},
+220 	_camera:{},
+221 	_screen:0,
+222 	_screenposition:0,
+223 	_keyboardpicker:0,
+224 	_screenh:0,
+225 	_screenw:0,
+226 	_screenhh:0,
+227 	_screenhw:0,
+228 	_zoom:1,
+229 	_canvas:{},
+230 	_objects:{},
+231 	_groups:[],
+232 	_renderorder:[],
+233 	_groupplay:{},
+234 	_actionqueue:["first","then","blit","after"], // initialize is executed once
+235 	_mspf:0,
+236 	_fps:0,
+237 	_gametimer:0,
+238 	_frameskip:0,
+239 	_autoskip:{min:0,max:5,lowidle:0,hiidle:5}, // minimum frameskip, maximum frameskip, minimum idle time allowed for increasing frameskip, maximum idle time allowed for decreasing frameskip
+240 	_fskid:0,
+241 	_statbar:0,
+242 	_border:0,
+243 	_garbage:[],
+244 	_zindexch:[],
+245 	_framestart:0,
+246 	_zindex:dynalist.create(),
+247 	_db:false,
+248 	_systemcookie:"__gboxsettings",
+249 	_sessioncache:"",
+250 	_breakcacheurl:function(a) {return a+(a.indexOf("?")==-1?"?":"&")+"_brc="+gbox._sessioncache; },
+251 	_forcedidle:0,
+252 	_gamewaiting:0,
+253 	_canlog:false,
+254 	_splash:{
+255 		gaugeLittleColor:"rgb(255,240,0)",
+256 		gaugeLittleBackColor:"rgb(255,255,255)",
+257 		gaugeBorderColor:"rgb(0,0,0)",
+258 		gaugeBackColor:"rgb(100,100,100)",
+259 		gaugeColor:"rgb(255,240,0)",
+260 		gaugeHeight:10,
+261 		background:null,
+262 		minimalTime:0,
+263 		footnotes:null,
+264 		footnotesSpacing:1
+265 	},
+266 	_minimalexpired:0, // 0: not triggered, 1: triggered, 2: done
+267 	setCanLog:function(c) { this._canlog=c&&window.console; },
+268 	canLog:function() { return this._canlog},
+269 	log:function() {}, // Overridden if console is really available
+270 	_safedrawimage:function(tox,img,sx,sy,sw,sh,dx,dy,dw,dh) {
+271 		if (!img||!tox) return;
+272 		if (sx<0) { dx-=(dw/sw)*sx;sw+=sx; sx=0; }
+273 		if (sy<0) { dy-=(dh/sh)*sy;sh+=sy; sy=0; }
+274 		if (sx+sw>img.width) { dw=(dw/sw)*(img.width-sx);sw=img.width-sx;}
+275 		if (sy+sh>img.height) { dh=(dh/sh)*(img.height-sy);sh=img.height-sy;}
+276 		try { if ((sh>0)&&(sw>0)&&(sx<img.width)&&(sy<img.height)) tox.drawImage(img, sx,sy,sw,sh,dx,dy,dw,dh); } catch(e){}
+277 	},
+278 	_keydown:function(e){
+279 		var key=(e.fake||window.event?e.keyCode:e.which);
+280 		if (!gbox._keyboard[key]) gbox._keyboard[key]=1;
+281 	},
+282 	_keyup:function(e){
+283 		var key=(e.fake||window.event?e.keyCode:e.which);
+284 		gbox._keyboard[key]=-1;
+285 	},
+286 	_resetkeys:function() {
+287 		for (var key in gbox._keymap)
+288 			gbox._keyup({fake:1,keyCode:gbox._keymap[key]});
+289 	},
+290 	_showkeyboardpicker:function(){
+291 		gbox._keyboardpicker.value="Click/Tap here to enable the keyboard";
+292 		gbox._keyboardpicker.style.left=(gbox._screenposition.x+5)+"px";
+293 		gbox._keyboardpicker.style.top=(gbox._screenposition.y+5)+"px";
+294 		gbox._keyboardpicker.style.width=(gbox._screenposition.w-10)+"px";
+295 		gbox._keyboardpicker.style.height="30px";
+296 		this._keyboardpicker.style.border="1px dashed white";
+297 		this._keyboardpicker.readOnly=null;
+298 	},
+299 	_hidekeyboardpicker:function(){
+300 		this._keyboardpicker.style.zIndex=100;
+301 		this._keyboardpicker.readOnly="yes";
+302 		this._keyboardpicker.style.position="absolute";
+303 		this._keyboardpicker.style.textAlign="center";
+304 		this._keyboardpicker.style.backgroundColor="#000000";
+305 		this._keyboardpicker.style.color="#fefefe";
+306 		this._keyboardpicker.style.cursor="pointer";			
+307 		this._keyboardpicker.value="";
+308 		this._keyboardpicker.style.left="0px";
+309 		this._keyboardpicker.style.top="0px";
+310 		this._keyboardpicker.style.height="0px";
+311 		this._keyboardpicker.style.width="0px";
+312 		this._keyboardpicker.style.border="0px";
+313 		this._keyboardpicker.style.padding="0px";
+314 		this._keyboardpicker.style.margin="0px";
+315 	},
+316 	_domgetabsposition:function(oElement) {
+317 		var sizes={x:0,y:0,h:0,w:0};
+318 		sizes.h=oElement.offsetHeight;
+319 		sizes.w=oElement.offsetWidth;
+320 		while( oElement != null) {
+321 			sizes.y += oElement.offsetTop;
+322 			sizes.x += oElement.offsetLeft;
+323 			oElement = oElement.offsetParent;
+324 		}
+325 		return sizes;
+326 	},
+327   
+328   /**
+329   * Sets the gbox._forcedidle property.
+330   * @param {Boolean} f The value to write to gbox._forcedidle.
+331   */	  
+332 	setForcedIdle:function(f) { this._forcedidle=f},
+333   
+334   /**
+335   * Returns a gbox flag at index f.
+336   * @param {Object} f The index of the flag you want returned.
+337   */	  
+338 	getFlag:function(f) { return this._flags[f] },
+339   
+340   /**
+341   * Sets the gbox._statbar property. Only useful if called before gbox.initScreen. Debugging funtionality.
+342   * Much easier to access if you add '?statusbar=1' to your URL.
+343   * @param {Boolean} f The value to write to gbox._statbar.
+344   */	
+345   setStatusBar:function(a) { this._statbar=a },
+346 	setScreenBorder:function(a) { this._border=a},
+347   
+348   /**
+349   * Initializes the screen to a certain width and height, applies zoom attributes, populates the 
+350   * body of the HTML document including the canvas element, sets an initial camera, creates a '_buffer'
+351   * canvas, sets keyboard event listeners, and many other initialization functions.
+352   * @param {Integer} w The width of the main canvas.
+353   * @param {Integer} h The height of the main canvas.
+354   */	
+355 	initScreen:function(w,h) {
+356 		document.body.style.textAlign="center";
+357 		var container=document.createElement("div");
+358 		container.style.width="100%";
+359 		container.style.height="100%";
+360 		container.style.display="table";
+361 		this._box=document.createElement("div");
+362 		this._box.style.display="table-cell";
+363 		this._box.style.width="100%";
+364 		this._box.style.textAlign="center";
+365 		this._box.style.verticalAlign="middle";
+366 		
+367 		this._screen=document.createElement("canvas");
+368 		if (this._border) this._screen.style.border="1px solid black";
+369 		this._screen.setAttribute('height',h);
+370 		this._screen.setAttribute('width',w);
+371 		this._screen.style.width=(w*this._zoom)+"px";
+372 		this._screen.style.height=(h*this._zoom)+"px";
+373 		this._screenh=h;
+374 		this._screenw=w;
+375 		this._screenhh=Math.floor(h/2);
+376 		this._screenhw=Math.floor(w/2);
+377 		this._camera.x=0;
+378 		this._camera.y=0;
+379 		this._camera.h=h;
+380 		this._camera.w=w;
+381 		this._box.appendChild(this._screen);
+382 		container.appendChild(this._box);
+383 		document.body.appendChild(container);
+384 
+385 		this.createCanvas("_buffer");
+386 		window.addEventListener('keydown', this._keydown,false);
+387 		window.addEventListener('keyup', this._keyup,false);
+388 		if (this._statbar) {
+389 			this._statbar=document.createElement("div");
+390 			if (this._border) this._statbar.style.border="1px solid black";
+391 			this._statbar.style.margin="auto";
+392 			this._statbar.style.backgroundColor="#ffffff";
+393 			this._statbar.style.fontSize="10px";
+394 			this._statbar.style.fontFamily="sans-serif";
+395 			this._statbar.style.width=(w*this._zoom)+"px";
+396 			this._box.appendChild(this._statbar);
+397 		}
+398 		// Keyboard support on devices that needs focus (like iPad) - actually is not working for a bug on WebKit's "focus" command.
+399 		this._keyboardpicker=document.createElement("input");
+400 		this._keyboardpicker.onclick=function(evt) { gbox._hidekeyboardpicker();evt.preventDefault();evt.stopPropagation();};
+401 		this._hidekeyboardpicker(this._keyboardpicker);
+402 		
+403 		gbox._box.appendChild(this._keyboardpicker);
+404 		gbox._screen.ontouchstart=function(evt) { gbox._screenposition=gbox._domgetabsposition(gbox._screen);if (evt.touches[0].pageY-gbox._screenposition.y<30) gbox._showkeyboardpicker();else gbox._hidekeyboardpicker();evt.preventDefault();evt.stopPropagation();};
+405 		gbox._screen.ontouchend=function(evt) {evt.preventDefault();evt.stopPropagation();};
+406 		gbox._screen.ontouchmove=function(evt) { evt.preventDefault();evt.stopPropagation();};
+407 		gbox._screen.onmousedown=function(evt) {gbox._screenposition=gbox._domgetabsposition(gbox._screen);if (evt.pageY-gbox._screenposition.y<30)  gbox._showkeyboardpicker(); else gbox._hidekeyboardpicker();evt.preventDefault();evt.stopPropagation();};
+408 		
+409 		var d=new Date();
+410 		gbox._sessioncache=d.getDate()+"-"+d.getMonth()+"-"+d.getFullYear()+"-"+d.getHours()+"-"+d.getMinutes()+"-"+d.getSeconds();
+411 		
+412 		gbox._loadsettings(); // Load default configuration
+413 		gbox.setCanAudio(true); // Tries to enable audio by default
+414 	},
+415 
+416   /**
+417   * Sets the gbox._db property. Turns on an off double buffering.
+418   * @param {Boolean} db The value to write to gbox._db. True enables double buffering, false disables.
+419   */	  
+420 	setDoubleBuffering:function(db){this._db=db},
+421   
+422   /**
+423   * Writes text to the status bar, but only if the status bar is enabled.
+424   * @param {String} txt The text to write to the status bar.
+425   */	  
+426 	setStatBar:function(txt){ if (gbox._statbar) this._statbar.innerHTML=(txt?txt:" ")},
+427 
+428   /**
+429   * Set the frames per second rate.
+430   * @param {Integer} f Total frames per second for the game to run at.
+431   */	  
+432 	setFps:function(f){
+433 		this._fps=f;
+434 		this._mspf=Math.floor(1000/f)
+435 	},
+436   
+437   /**
+438   * Get the frames per second rate (default is 25).
+439   * @returns {Integer} Returns the frames per second.
+440   */
+441 	getFps:function() { return this._fps },
+442 	setAutoskip:function(f){this._autoskip=f},
+443 	setFrameskip:function(f){this._frameskip=f},
+444   
+445   /**
+446   * Get the screen height.
+447   * @returns {Integer} Screen height in pixels.
+448   */
+449 	getScreenH:function(){return this._screenh},
+450 
+451   /**
+452   * Get the screen width.
+453   * @returns {Integer} Screen width in pixels.
+454   */
+455 	getScreenW:function(){return this._screenw},
+456   
+457   /**
+458   * Get the screen half-height.
+459   * @returns {Integer} Screen half-height in pixels.
+460   */
+461 	getScreenHH:function(){return this._screenhh},
+462 
+463   /**
+464   * Get the screen half-width.
+465   * @returns {Integer} Screen half-width in pixels.
+466   */
+467 	getScreenHW:function(){return this._screenhw},
+468   
+469   /**
+470   * Sets the gbox._zoom parameter, only works before gbox.initScreen is called.
+471   * @param {Integer} z Zoom factor.
+472   */
+473 	setZoom:function(z) { this._zoom=z},
+474 
+475   /**
+476   * Deprecated: gbox._cb is now set by passing it directly into gbox.loadAll(). Left in for backwards compatibility.
+477   * @param {String} cb The name of the function to be called once gbox.loadAll is completed.
+478   */
+479 	setCallback:function(cb) { this._cb=cb; },
+480 
+481 	_playobject:function(g,obj,a) {
+482 		if (gbox._objects[g][obj].initialize) {
+483 			gbox._objects[g][obj].initialize(obj);
+484 			delete gbox._objects[g][obj].initialize;
+485 		}
+486 		if (gbox._objects[g][obj][a]) gbox._objects[g][obj][a](obj,a);
+487 	},
+488 
+489 	_nextframe:function(){
+490 		gbox._framestart=gbox._mspf-(new Date().getTime()-gbox._framestart);
+491 		if (gbox._autoskip)
+492 			if ((gbox._framestart<gbox._autoskip.lowidle)&&(gbox._frameskip<gbox._autoskip.max)) gbox.setFrameskip(gbox._frameskip+1); else
+493 			if ((gbox._framestart>gbox._autoskip.hiidle)&&(gbox._frameskip>gbox._autoskip.min)) gbox.setFrameskip(gbox._frameskip-1);
+494 		if (gbox._statbar) gbox.debugGetstats();
+495 		this._gametimer=setTimeout(gbox.go,(gbox._framestart<=0?1:gbox._framestart));		
+496 	},
+497 
+498   /**
+499   * This function is called once per frame. This is where the basic rendering and processing of groups occurs.
+500   */
+501 	go:function() {
+502 		if (gbox._loaderqueue.isBusy()) {
+503 			if (gbox._gamewaiting==1) {
+504 				gbox.blitFade(gbox._screen.getContext("2d"),{alpha:0.5});
+505 				gbox.blitText(gbox._screen.getContext("2d"),{font:"_dbf",dx:2,dy:2,text:"LOADING..."});
+506 				gbox._gamewaiting=true;
+507 			}
+508 			if (gbox._gamewaiting<=1) {
+509 				var bw=Math.floor(((gbox.getScreenW()-4)*gbox._loaderqueue.getDone())/gbox._loaderqueue.getSize());
+510 				gbox._screen.getContext("2d").globalAlpha=1;
+511 				gbox._screen.getContext("2d").fillStyle = gbox._splash.gaugeLittleBackColor;
+512 				gbox._screen.getContext("2d").fillRect(0,4+gbox.getFont("_dbf").tileh,gbox.getScreenW(),1);
+513 				gbox._screen.getContext("2d").fillStyle = gbox._splash.gaugeLittleColor;
+514 				gbox._screen.getContext("2d").fillRect(0,4+gbox.getFont("_dbf").tileh,(bw>0?bw:0),1);
+515 				gbox._screen.getContext("2d").restore();
+516 				gbox.setStatBar("Loading... ("+gbox._loaderqueue.getDone()+"/"+gbox._loaderqueue.getTotal()+")");
+517 			}
+518 			if (gbox._gamewaiting) gbox._gamewaiting--;
+519 			setTimeout(gbox.go,1000);
+520 		} else {
+521 			gbox._gamewaiting=3;
+522 			gbox._framestart=new Date().getTime();
+523 			var gr="";
+524 			for (var g=0;g<gbox._renderorder.length;g++)
+525 				if (gbox._groupplay[gbox._renderorder[g]])
+526 					if (gbox._renderorder[g]==gbox.ZINDEX_LAYER) {
+527 						var id;
+528 						for (var i=0;i<gbox._actionqueue.length;i++) {
+529 							id=gbox._zindex.first;
+530 							while (id!=null) {
+531 								if (gbox._groupplay[gbox._zindex.data[id].g])
+532 									gbox._playobject(gbox._zindex.data[id].g,gbox._zindex.data[id].o,gbox._actionqueue[i]);
+533 								id=gbox._zindex.data[id].__next;
+534 							}
+535 						}
+536 					} else
+537 						for (var i=0;i<gbox._actionqueue.length;i++)
+538 							for (var obj in gbox._objects[gbox._renderorder[g]])
+539 								gbox._playobject(gbox._renderorder[g],obj,gbox._actionqueue[i]);
+540 			if (gbox._fskid>=gbox._frameskip) {
+541 				if (gbox._db) gbox.blitImageToScreen(gbox.getBuffer());
+542 				gbox._fskid=0;
+543 			} else gbox._fskid++;
+544 			
+545 			gbox.purgeGarbage();
+546 	
+547 			if (gbox._zindexch.length) {
+548 				
+549 				for (var i=0;i<gbox._zindexch.length;i++) {
+550 					if (gbox._objects[gbox._zindexch[i].o.g][gbox._zindexch[i].o.o])
+551 						if (gbox._objects[gbox._zindexch[i].o.g][gbox._zindexch[i].o.o].__zt==null)
+552 							gbox._objects[gbox._zindexch[i].o.g][gbox._zindexch[i].o.o].__zt=gbox._zindex.addObject(gbox._zindexch[i].o,gbox._zindexch[i].z);
+553 						else
+554 							gbox._zindex.setPrio(gbox._objects[gbox._zindexch[i].o.g][gbox._zindexch[i].o.o].__zt,gbox._zindexch[i].z);
+555 				}
+556 				gbox._zindexch=[];
+557 			}
+558 			
+559 			
+560 			// Handle holding
+561 			for (var key in gbox._keymap)
+562 				if (gbox._keyboard[gbox._keymap[key]]==-1) gbox._keyboard[gbox._keymap[key]]=0; else
+563 				if (gbox._keyboard[gbox._keymap[key]]&&(gbox._keyboard[gbox._keymap[key]]<100))	gbox._keyboard[gbox._keymap[key]]++;
+564 			if (gbox._forcedidle)
+565 				this._gametimer=setTimeout(gbox._nextframe,gbox._forcedidle); // Wait for the browser
+566 			else
+567 				gbox._nextframe();
+568 		}
+569 	},
+570   
+571   /**
+572   * Displays basic audio, object, and performance statistics in the status bar. Automatically called each frame if the status bar is enabled.
+573   */
+574 	debugGetstats:function() {
+575 		var statline="Idle: "+gbox._framestart+"/"+gbox._mspf+(gbox._frameskip>0?" ("+gbox._frameskip+"skip)":"")+" | ";
+576 		var cnt=0;
+577 		for (var g=0;g<gbox._groups.length;g++)
+578 			if (gbox._groupplay[gbox._groups[g]]) {
+579 				cnt=0;
+580 				for (var obj in gbox._objects[gbox._groups[g]]) cnt++;
+581 				if (cnt) statline+=gbox._groups[g]+"["+cnt+"] ";
+582 			}
+583 		var cnt=0;
+584 		var ply=0;
+585 		for (var g in gbox._audio.aud) 
+586 			for (var x=0;x<gbox._audio.aud[g].length;x++) {
+587 				cnt++;
+588 				if (!gbox._audio.aud[g][x].paused&&!gbox._audio.aud[g][x].ended) ply++;
+589 			}
+590 		statline+="| audio: "+ply+"/"+cnt+":"+this._audioteam;
+591 			/*
+592 			statline+="<br><br>";
+593 		var id=gbox._zindex.first;
+594 			while (id!=null) {
+595 				if (gbox._groupplay[gbox._zindex.data[id].g]) statline+=gbox._zindex.data[id].g+" | "+gbox._zindex.data[id].o+" ("+gbox._zindex.data[id].__prio+")<br>";
+596 				id=gbox._zindex.data[id].__next;
+597 			}
+598 			*/
+599 		gbox.setStatBar(statline);
+600 	},
+601   
+602 	setZindex:function(th,z) {
+603 		if ((th.__zt==null)||(th.zindex!=z)) {
+604 			th.zindex=z;
+605 			this._zindexch.push({o:{g:th.group,o:th.id},z:z});
+606 		}
+607 	},
+608 
+609   /**
+610   * Returns true if a given key in this._keymap is pressed. Only returns true on the transition from unpressed to pressed.
+611   * @param {String} id A key in the keymap. By default, one of: "up" "down" "left" "right" "a" "b" "c"
+612   * @returns {Boolean} True if the given key is transitioning from unpressed to pressed in this frame.
+613   */
+614 	keyIsHit:function(id) { return this._keyboard[this._keymap[id]]==1},
+615   
+616   /**
+617   * Returns true if a given key in this._keymap is being held down. Returns true as long as the key is held down.
+618   * @param {String} id A key in the keymap. By default, one of: "up" "down" "left" "right" "a" "b" "c"
+619   * @returns {Boolean} True if the given key is held down.
+620   */  
+621 	keyIsPressed:function(id) { return this._keyboard[this._keymap[id]]>0},
+622 
+623   /**
+624   * Returns true if a given key in this._keymap has been held down for at least one frame. Will not return true if a key
+625   * is quickly tapped, only once it has been held down for a frame.
+626   * @param {String} id A key in the keymap. By default, one of: "up" "down" "left" "right" "a" "b" "c"
+627   * @returns {Boolean} True if the given key has been held down for at least one frame.
+628   */  
+629 	keyIsHold:function(id) { return this._keyboard[this._keymap[id]]>1},
+630   
+631   /**
+632   * Returns true if a given key in this._keymap is released. Only returns true on the transition from pressed to unpressed.
+633   * @param {String} id A key in the keymap. By default, one of: "up" "down" "left" "right" "a" "b" "c"
+634   * @returns {Boolean} True if the given key is transitioning from pressed to unpressed in this frame.
+635   */
+636 	keyIsReleased:function(id) { return this._keyboard[this._keymap[id]]==-1},
+637   
+638 	_savesettings:function() {
+639 		var saved="";
+640 		for (var k in this._keymap) saved+="keymap-"+k+":"+this._keymap[k]+"~";
+641 		for (var f in this._flags) saved+="flag-"+f+":"+(this._flags[f]?1:0)+"~";
+642 		this.dataSave("sys",saved);
+643 	},
+644 	_loadsettings:function() {
+645 		var cfg=this.dataLoad("sys");
+646 		if (cfg!==null) {
+647 			cfg=cfg.split("~");
+648 			var kv;
+649 			var mk;
+650 			for (var i=0;i<cfg.length;i++) {
+651 				kv=cfg[i].split(":");
+652 				mk=kv[0].split("-");
+653 				switch (mk[0]) {
+654 					case "keymap": { this._keymap[mk[1]]=kv[1]*1; break }
+655 					case "flag": { this._flags[mk[1]]=kv[1]*1; break }
+656 				}
+657 			}
+658 		}
+659 	},
+660 
+661   /**
+662   * Saves data to a browser cookie as a key-value pair, which can be restored later using gbox.dataLoad. Only 
+663   * works if user has cookies enabled.
+664   * @param {String} k The key which identifies the value you are storing.
+665   * @param {String} v The value you wish to store. Needs to be a string!
+666   * @param {String} d A date offset, to be added to the current date. Defines the cookie's expiration date. By default this is set to 10 years.
+667   * @example
+668   * // (from Capman)
+669   * gbox.dataSave("capman-hiscore",maingame.hud.getNumberValue("score","value"));
+670   */
+671 	dataSave:function(k,v,d) { 
+672 		var date = new Date();
+673 		date.setTime(date.getTime()+((d?d:365*10)*24*60*60*1000));
+674 		document.cookie =this._systemcookie+"~"+k+"="+v+"; expires="+date.toGMTString()+"; path=/";
+675 	},
+676   
+677   /**
+678   * Loads data from a browser cookie. Send it a key and it returns a value (if available). Only works if user has cookies enabled.
+679   * @param {String} k The key which identifies the value you are loading.
+680   * @param {String} a A switch to determine whether a string or a number is returned. By default a string is returned.
+681   * @returns {Object} A string or a number loaded from the cookie.
+682   * @example
+683   * hiscore = gbox.dataLoad("hiscore");
+684   */
+685 	dataLoad:function(k,a) {
+686 		var nameeq=this._systemcookie+"~"+k+"=";
+687 		var ca = document.cookie.split(";");
+688 		var rt;
+689 		for (var i=0;i<ca.length;i++) {
+690 			var c=ca[i];
+691 			while (c.charAt(0)==' ') c=c.substring(1,c.length);
+692 			if (c.indexOf(nameeq)==0) {
+693 				rt=c.substring(nameeq.length,c.length);
+694 				if (a&&a.number) return rt*1; else return rt;
+695 				if (a&&a.number) return rt*1; else return rt;
+696 			}
+697 		}
+698 		return null;
+699 	},
+700 
+701   /**
+702   * Clears a value stored in a  key-value pair in a browser cookie. Sets value to "". Only works if user has cookies enabled.
+703   * @param {String} k The key which identifies the value you are clearing.
+704   */
+705 	dataClear:function(k) { this.dataSave(k,"",-1) },
+706   
+707   /**
+708   * Gets the current camera object.
+709   * @returns {Object} The camera object.
+710   */
+711 	getCamera:function() { return this._camera; },
+712   
+713   /**
+714   * Sets the y value of the current camera object.
+715   * @param {Integer} y The camera object's new y value.
+716   * @param {Object} viewdata An object containing parameters h and w, which are a bounding box that the camera is
+717   * not supposed to leave. For example, to use your map as a bounding area for the camera, pass along {w: map.w, h: map.h}.
+718   */
+719 	setCameraY:function(y,viewdata) {
+720 		this._camera.y=y;
+721 		if (this._camera.y+this._camera.h>viewdata.h) this._camera.y=viewdata.h-this._screenh;
+722 		if (this._camera.y<0) this._camera.y=0;
+723 	},
+724 
+725   /**
+726   * Sets the x value of the current camera object.
+727   * @param {Integer} x The camera object's new x value.
+728   * @param {Object} viewdata An object containing parameters h and w, which are a bounding box that the camera is
+729   * not supposed to leave. For example, to use your map as a bounding area for the camera, pass along {w: map.w, h: map.h}.
+730   */  
+731 	setCameraX:function(x,viewdata) {
+732 		this._camera.x=x;
+733 		if (this._camera.x+this._camera.w>viewdata.w) this._camera.x=viewdata.w-this._screenw;
+734 		if (this._camera.x<0) this._camera.x=0;
+735 	},
+736   
+737   /**
+738   * Centers the camera.
+739   * @param {Object} data An object containing x and y parameters -- typically the object you wish to center the camera on.
+740   * @param {Object} viewdata An object containing parameters h and w, which are a bounding box that the camera is
+741   * not supposed to leave. For example, to use your map as a bounding area for the camera, pass along {w: map.w, h: map.h}.
+742   * @example
+743   * // Center the camera on the player object
+744   * gbox.centerCamera(gbox.getObject('player', 'player_id'), {w: map.w, h: map.h});
+745   */
+746 	centerCamera:function(data,viewdata) {
+747 		this.setCameraX(data.x-this._screenhw,viewdata);
+748 		this.setCameraY(data.y-this._screenhh,viewdata);
+749 	},
+750 
+751   /**
+752   * Get an array containing the names of each group in the game, in order of rendering.
+753   * @returns {Array} An array of group names.
+754   * @example
+755   * grouplist = gbox.getGroups();
+756   * grouplist; // => ["background", "player", "enemy", "game"]	
+757   */
+758   getGroups:function() { return this._groups; },
+759   
+760   /**
+761   * Defines the names of each group in the game along with their rendering order.
+762   * @param {Array} g An array of strings of group names, in the order in which the groups should be rendered. So
+763   * g[0] will contain the first group to render, g[1] the second group to render, etc.
+764   */
+765 	setGroups:function(g){
+766 		this._groups=g;
+767 		this._groupplay[gbox.ZINDEX_LAYER]=true;
+768 		for (var i=0;i<g.length;i++)
+769 			if (!this._objects[g[i]]) {
+770 				this._objects[g[i]]={};
+771 				this._groupplay[g[i]]=true;
+772 				this._renderorder[i]=g[i];
+773 			}
+774 	},
+775   
+776   /**
+777   * A method of setting the render order of groups independently of gbox.setGroups. Sets gbox._renderorder, 
+778   * which by default is equivalent to gbox._groups. However, gbox._renderorder is what ultimately determines
+779   * the rendering order of groups. If you need to change your rendering order on the fly, use this function 
+780   * by passing it a reordered array of group names.
+781   * @param {Array} g An array of strings of group names, in the order in which the groups should be rendered. So
+782   * g[0] will contain the first group to render, g[1] the second group to render, etc.
+783   */
+784 	setRenderOrder:function(g) { this._renderorder=g; },
+785   
+786   /**
+787   * If a group is disabled, this will enable the group.
+788   * @param {String} gid The id of the group.
+789   */
+790 	playGroup:function(gid){this._groupplay[gid]=true;},
+791 
+792   /**
+793   * If a group is enabled, this will disable the group.
+794   * @param {String} gid The id of the group.
+795   */
+796 	stopGroup:function(gid){this._groupplay[gid]=false;},
+797   
+798   /**
+799   * Toggles a group between enabled and disabled status.
+800   * @param {String} gid The id of the group.
+801   */
+802 	toggleGroup:function(gid){this._groupplay[gid]=!this._groupplay[gid];},
+803   
+804   /**
+805   * Turns off all groups except for the one specified. 
+806   * @param {String} gid The id of the group.
+807   */
+808 	soloGroup:function(gid) {
+809 		for (var i=0;i<this._groups.length;i++)
+810 			if (this._groups[i]==gid) this.playGroup(this._groups[i]); else this.stopGroup(this._groups[i]);
+811 	},
+812   
+813   /**
+814   * Enables all groups, toggling any groups that are currently disabled.
+815   */
+816 	playAllGroups:function() { for (var i=0;i<this._groups.length;i++) this.playGroup(this._groups[i]); },
+817 
+818   /**
+819   * Destroys all objects in a given group.
+820   * @param {String} gid The id of the group.
+821   */
+822 	clearGroup:function(group) {
+823 		for (var obj in this._objects[group]) {
+824 			if (this._objects[group][obj].__zt!=null) this._zindex.remove(this._objects[group][obj].__zt);
+825 			delete this._objects[group][obj];
+826 		}
+827 	},
+828 	playGroups:function(gid){for (var i=0;i<gid.length;i++)this.playGroup(gid[i])},
+829 	stopGroups:function(gid){for (var i=0;i<gid.length;i++)this.stopGroup(gid[i])},
+830 	toggleGroups:function(gid){for (var i=0;i<gid.length;i++)this.toggleGroup(gid[i])},
+831   
+832   /**
+833   * Given a group and an id for a particular object instance, this returns the instance requested.
+834   * <b>NOTE:</b> this does not return a copy of the object you've requested! Any modifications you make
+835   * to the object returned are directly modifying the object you requested.
+836   * @param {String} group The id of the group that contains the object.
+837   * @param {String} id The id of the instance of the object.
+838   * @returns {Object} The object requested.
+839   * @example
+840   * // Find the player and reduce health by half.
+841   * playertemp = gbox.getObject('player','player_id');
+842   * player.health = player.health/2;
+843   */ 
+844 	getObject:function(group,id) {return this._objects[group][id]},
+845 
+846   /**
+847   * Creates a font.
+848   * @param {Object} data An object containing: <ul><li>id: the id of the font</li>
+849   * <li>image: reference to the font image loaded (must contain font character tiles in ASCII order)</li>
+850   * <li>firstletter: the ASCII character that the font image's first character corresponds to</li>
+851   * <li>tileh: height in pixels of the character tiles</li>
+852   * <li>tilew: width in pixels of the character tiles</li>
+853   * <li>tilerow: width in pixels of each row in the font image</li>
+854   * <li>gapx: x-coord gap between tile columns, in pixels</li>
+855   * <li>gapy: y-coord gap between tile rows, in pixels</li></ul>
+856   * @example
+857   * gbox.addImage('font', 'font.png');
+858   * gbox.addFont({ id: 'small', image: 'font', firstletter: ' ', tileh: 8, tilew: 8, tilerow: 255, gapx: 0, gapy: 0 });
+859   */ 
+860 	addFont:function(data) {
+861 		data.tilehh=Math.floor(data.tileh/2);
+862 		data.tilehw=Math.floor(data.tilew/2);
+863 		this._fonts[data.id]=data;
+864 		this._fonts[data.id].firstascii=data.firstletter.charCodeAt(0);
+865 	},
+866   
+867   /**
+868   * Returns a font object containing data about the font.
+869   * @param {String} id The id of the font, as set in gbox.addFont.
+870   */   
+871 	getFont:function(id) {
+872 		return this._fonts[id];
+873 	},
+874 
+875   /**
+876   * Deletes an object, keeping a record of its group and id in gbox._garbage.
+877   * @param {Object} obj The object you wish to delete.
+878   */  
+879 	trashObject:function(obj) {
+880 		if (!this._garbage[obj.group]) this._garbage[obj.group]={};
+881 		this._garbage[obj.group][obj.id]=1;
+882 		obj.__trashing=true;
+883 	},
+884   
+885   /**
+886   * Clears the record held in gbox._garbage of what has been deleted.
+887   * @param {Object} obj The object you wish to delete.
+888   */    
+889 	purgeGarbage:function() {
+890 		for (var group in this._garbage)
+891 			for (var id in this._garbage[group]) {
+892 				if (this._objects[group][id].__zt!=null)
+893 					this._zindex.remove(this._objects[group][id].__zt)
+894 				delete this._objects[group][id];
+895 			}
+896 		gbox._garbage={};
+897 	},
+898   
+899   /**
+900   * Deletes every object in a given group.
+901   * @param {String} group The group id.
+902   */    
+903 	trashGroup:function(group) {
+904 		if (!this._garbage[group]) this._garbage[group]={};
+905 		for (var obj in this._objects[group])
+906 			this._garbage[group][obj]=1;
+907 	},
+908   
+909   /**
+910   * Returns whether an object is due to be trashed. Useful in cases you want to check if
+911   * an object is marked as trash before it is actually deleted.
+912   * @param {Object} o The object you're checking.
+913   * @returns {Boolean} True if the object is marked as trash.
+914   */      
+915 	objectIsTrash:function(o) { return o.__trashing },
+916   
+917   /**
+918   * Creates a new game object. Generally speaking you pass a fully-defined object as the parameter (including a group, id, tileset, and so on).
+919   * A group must be specified, or the program will crash. If no id is specified, then it will automatically provide 
+920   * an id of 'obj-XXXX' where 'XXXX' is an automatically incrementing integer. This is where the <i>initialize</i>, <i>first</i>, and <i>blit</i>
+921   * functions are defined, as well.
+922   * @param {Object} data The object you wish to create.
+923   * @returns {Object} The object you created.
+924   * @example
+925   * data = {
+926   *   group: 'player',
+927   *   id: 'player_id',
+928   *   tileset: 'player_tiles', 
+929   *   x: 0,
+930   *   y: 0,
+931   *   initialize: function() {
+932       this.x = 10;
+933       this.y = 10;
+934       },
+935   * };
+936   * gbox.addObject(data);
+937   */    
+938 	addObject:function(data) {
+939 		// Extras
+940 		if (!data.id) {
+941 			data.id="obj-"+this._autoid;
+942 			this._autoid=(this._autoid+1)%1000;
+943 		}
+944 		if (data.tileset) {
+945 			if (data.h==null) data.h=this._tiles[data.tileset].tileh;
+946 			if (data.w==null) data.w=this._tiles[data.tileset].tilew;
+947 			if (data.hw==null) data.hw=this._tiles[data.tileset].tilehw;
+948 			if (data.hh==null) data.hh=this._tiles[data.tileset].tilehh;
+949 		}
+950 		this._objects[data.group][data.id]=data;
+951 		if (data.zindex!=null)
+952 			this.setZindex(this._objects[data.group][data.id],data.zindex);
+953 		return this._objects[data.group][data.id];
+954 	},
+955   
+956    /**
+957   * Returns whether a given group contains no objets.
+958   * @param {String} gid The group you're checking.
+959   * @returns {Boolean} True if the group contains no objects.
+960   */    
+961 	groupIsEmpty:function(gid) { for (var i in this._objects[gid]) return false; return true; },
+962   
+963   /**
+964   * Creates a new canvas. By default, the width and height is the current gbox._screenw and gbox._screenh,
+965   * but it can also be set by passing in a data object with the appropriate parameters.
+966   * @param {String} id The id of the new canvas.
+967   * @param {Object} data (Optional) The height and width of the new canvas, contained in data.h and data.w parameters.
+968   * @example
+969   * gbox.createCanvas('newCanvas', {w: 640, h: 480});
+970   */    
+971 	createCanvas:function(id,data) {
+972 		this.deleteCanvas(id);
+973 		this._canvas[id]=document.createElement("canvas");
+974 		this._canvas[id].setAttribute('height',(data&&data.h?data.h:this._screenh));
+975 		this._canvas[id].setAttribute('width',(data&&data.w?data.w:this._screenw));
+976 	},
+977   
+978   /**
+979   * Deletes a given canvas.
+980   * @param {String} id The id of the canvas to be deleted.
+981   */  
+982 	deleteCanvas:function(id) {
+983 		if (this._canvas[id]) delete this._canvas[id];	
+984 	},
+985   
+986   /**
+987   * Checks to see if an image was successfully loaded.
+988   * @param {String} id The id of the image.
+989   * @returns {Boolean} True if the image has been loaded.
+990   */    
+991 	imageIsLoaded:function(id){ return this._images[id]&&(this._images[id].getAttribute("wasloaded"))&&this._images[id].width },
+992   
+993   /**
+994   * Gets information about a loaded image.
+995   * @param {String} id The id of the image.
+996   * @returns {Object} A DOM Image element, including the URL and last modified date of the image, its ID, and whether it was loaded successfully.
+997   * @example
+998   * image = gbox.getImage('logo');
+999   * image; // => <img src=?"logo.png?_brc=5-7-2010-15-48-42" src_org=?"logo.png" id=?"logo" wasloaded=?"true">?
+1000   */
+1001 	getImage:function(id){return this._images[id]},
+1002   
+1003   /**
+1004   * Gets the buffer canvas (automatically created by gbox.initScreen).
+1005   * @returns {Object} A DOM Canvas element, including the width and height of the canvas.
+1006   */
+1007 	getBuffer:function(){return this.getCanvas("_buffer")},
+1008 
+1009   /**
+1010   * Gets the buffer canvas context.
+1011   * @returns {Object} A DOM Canvas context object.
+1012   */
+1013 	getBufferContext:function(){ return (gbox._fskid>=gbox._frameskip?(this._db?this.getCanvasContext("_buffer"):this._screen.getContext("2d")):null) },
+1014   
+1015   /**
+1016   * Gets a given canvas.
+1017   * @param {Object} id The identifier of the canvas.
+1018   * @returns {Object} A DOM Canvas element, including the width and height of the canvas.
+1019   */
+1020 	getCanvas:function(id){return this._canvas[id]},
+1021   
+1022   /**
+1023   * Gets the two-dimensional canvas context of a given canvas. The object it returns contains all the drawing functions for the canvas.
+1024   * See <a href = "http://dev.w3.org/html5/spec/Overview.html#the-canvas-element">W3C</a> and
+1025   * <a href = "https://developer.mozilla.org/en/canvas_tutorial/basic_usage">Mozilla Developer Center</a> for details.
+1026   * @param {Object} id The identifier of the canvas.
+1027   * @returns {Object} A DOM Canvas context object.
+1028   */
+1029 	getCanvasContext:function(id){return this.getCanvas(id).getContext("2d");},
+1030   
+1031   /**
+1032   * Adds an image file to the loader, assigning it to an ID. If adding an image to an existing ID, it checks to see if the file you're
+1033   * adding is different than the one currently assigned to the ID. If it's different, it overwrites the old image. If it's the same, then
+1034   * no action is taken.
+1035   * @param {String} id The identifier of the image.
+1036   * @param {String} filename The file name of the image.
+1037   */
+1038 	addImage:function(id,filename) {
+1039 		if (this._images[id])
+1040 			if (this._images[id].getAttribute("src_org")==filename)
+1041 				return;
+1042 			else
+1043 				delete this._images[id];
+1044 		this._addtoloader({type:"image",id:id,filename:filename});
+1045 	},
+1046   
+1047   /**
+1048   * Deletes an image currently in use. Does not delete the image file, but removes it from Akihabara's image list.
+1049   * @param {String} id The identifier of the image.
+1050   */
+1051 	deleteImage:function(id) {
+1052 		delete this._images[id];
+1053 	},
+1054   
+1055   /**
+1056   * Creates a new Akihabara tileset, adding it to the engine.
+1057   * @param {Object} t An object containing: <ul><li>id {String}: the new id of the tileset</li>
+1058   * <li>image {String}: reference to the tileset image loaded</li>
+1059   * <li>tileh {Integer}: height in pixels of the tiles</li>
+1060   * <li>tilew {Integer}: width in pixels of the tiles</li>
+1061   * <li>tilerow {Integer}: width in pixels of each row in the font image</li>
+1062   * <li>gapx {Integer}: x-coord gap between tile columns, in pixels</li>
+1063   * <li>gapy {Integer}: y-coord gap between tile rows, in pixels</li></ul>
+1064   */
+1065 	addTiles:function(t) { 
+1066 		t.tilehh=Math.floor(t.tileh/2);
+1067 		t.tilehw=Math.floor(t.tilew/2);
+1068 		this._tiles[t.id]=t;
+1069 	},
+1070 
+1071   /**
+1072   * Gets an Akihabara tileset, adding it to the engine.
+1073   * @param {String} t The ID of a tileset.
+1074   * @returns An object containing: <ul><li>id {String}: the new id of the tileset</li>
+1075   * <li>image {String}: reference to the tileset image loaded</li>
+1076   * <li>tileh {Integer}: height in pixels of the tiles</li>
+1077   * <li>tilew {Integer}: width in pixels of the tiles</li>
+1078   * <li>tilerow {Integer}: width in pixels of each row in the font image</li>
+1079   * <li>gapx {Integer}: x-coord gap between tile columns, in pixels</li>
+1080   * <li>gapy {Integer}: y-coord gap between tile rows, in pixels</li></ul>
+1081   */
+1082 	getTiles:function(t) { return this._tiles[t] },
+1083   
+1084   /**
+1085   * Loads the initial splash screen and debugging font, then calls gbox._waitforloaded which adds to the game all the previously
+1086   * defined resources. Once gbox._waitforloaded is done, it calls the callback function cb.
+1087   * @params {String} cb The name of the function to be called when all assets are done loading.
+1088   */
+1089 	loadAll:function(cb) {
+1090 		// Setup logger
+1091 		if (this._canlog) this.log=console.log;
+1092 		// Set the callback function, which is called after the resources are loaded.
+1093 		if (!this._cb) this._cb = cb;
+1094 		// Default stuff
+1095 		this.addImage("_dbf","akihabara/debugfont.png");
+1096 		if (this._splash.background) this.addImage("_splash",this._splash.background);
+1097 		gbox.addFont({id:"_dbf",image:"_dbf",firstletter:" ",tileh:5,tilew:4,tilerow:16,gapx:0,gapy:0});
+1098 		if (!gbox._splash.minimalTime)
+1099 			gbox._minimalexpired=2;
+1100 		this._waitforloaded();
+1101 	},
+1102   
+1103 	_implicitsargs:function(data) {
+1104 		if (data.camera) {
+1105 			data.dx-=this._camera.x;
+1106 			data.dy-=this._camera.y;	
+1107 		}
+1108 		if (data.sourcecamera) {
+1109 			data.x=this._camera.x*(data.parallaxx?data.parallaxx:1);
+1110 			data.y=this._camera.y*(data.parallaxy?data.parallaxy:1);	
+1111 		}
+1112 	},
+1113   
+1114   /**
+1115   * Draws a tile to a canvas context
+1116   * @param {Object} tox The canvas context to be drawn on.
+1117   * @param {Object} data An object containing data about the tile to be drawn, including:
+1118   * <ul><li>tileset {String}: the id of the tileset</li>
+1119   * <li>tile {Integer}: the index of the tile within the tileset to be drawn</li>
+1120   * <li>dx {Integer}: x coordinate to draw the tile at</li>
+1121   * <li>dy {Integer}: y coordinate to draw the tile at</li>
+1122   * <li>fliph {Integer}: horizontal flip, either 1 or -1</li>
+1123   * <li>flipv {Integer}: vertical flip, either 1 or -1</li>
+1124   * <li>alpha {Float}: alpha value (0 is transparent, 1 is opaque)</li></ul>
+1125   * @example
+1126   * // from capman, draws an current object's tile, called from inside its blit function
+1127   * gbox.blitTile(gbox.getBufferContext(),{tileset:this.tileset,tile:this.frame,dx:this.x,dy:this.y,fliph:this.fliph,flipv:this.flipv,camera:this.camera,alpha:1});
+1128   */
+1129 	blitTile:function(tox,data) {
+1130 		if (tox==null) return;
+1131 		var ts=this._tiles[data.tileset];
+1132 		var img=this.getImage(ts.image);
+1133 		this._implicitsargs(data);
+1134 		tox.save();
+1135 		tox.globalAlpha=(data.alpha?data.alpha:1);
+1136 		tox.translate((data.fliph?ts.tilew:0), (data.flipv?ts.tileh:0)); tox.scale((data.fliph?-1:1), (data.flipv?-1:1));
+1137 		this._safedrawimage(tox,img, ts.gapx+(ts.tilew*(data.tile%ts.tilerow)),ts.gapy+(ts.tileh*Math.floor(data.tile/ts.tilerow)),(data.w==null?ts.tilew:data.w),(data.h==null?ts.tileh:data.h),data.dx*(data.fliph?-1:1),data.dy*(data.flipv?-1:1),(data.w?data.w:ts.tilew),(data.h?data.h:ts.tileh));
+1138 		tox.restore();
+1139 	},
+1140 
+1141   /**
+1142   * Draws an image to a canvas context
+1143   * @param {Object} tox The canvas context to be drawn on.
+1144   * @param {Object} image The image to draw. Must be a DOM Image element, typicallly accessed via gbox.getImage
+1145   * @param {Object} data An object containing data about the tile to be drawn, including:
+1146   * <ul><li>dx {Integer}: (required) x coordinate to draw the image at</li>
+1147   * <li>dy {Integer}: (required) y coordinate to draw the image at</li>
+1148   * <li>fliph {Integer}: horizontal flip, either 1 or -1</li>
+1149   * <li>flipv {Integer}: vertical flip, either 1 or -1</li>
+1150   * <li>alpha {Float}: alpha value (0 is transparent, 1 is opaque)</li></ul>
+1151   * @example
+1152   * // draw an image at (100,100)
+1153   * gbox.blitAll(gbox.getBufferContext(),gbox.getImage("image_id"),{dx:100,dy:100});
+1154   */
+1155 	blitAll:function(tox,image,data) {
+1156 		if (tox==null) return;
+1157 		this._implicitsargs(data);
+1158 		tox.save();
+1159 		tox.globalAlpha=(data.alpha?data.alpha:1);
+1160 		tox.translate((data.fliph?image.width:0), (data.flipv?image.height:0)); tox.scale((data.fliph?-1:1), (data.flipv?-1:1));
+1161 		this._safedrawimage(tox,image, 0,0, image.width,image.height,data.dx*(data.fliph?-1:1),data.dy*(data.flipv?-1:1),image.width,image.height);
+1162 		tox.restore();
+1163 	},
+1164   
+1165 	blit:function(tox,image,data) {
+1166 		if (tox==null) return;
+1167 		this._implicitsargs(data);
+1168 		tox.save();
+1169 		tox.globalAlpha=(data.alpha?data.alpha:1);
+1170 		tox.translate((data.fliph?data.dw:0), (data.flipv?data.dh:0)); tox.scale((data.fliph?-1:1), (data.flipv?-1:1));
+1171 		this._safedrawimage(tox,image,(data.x?data.x:0), (data.y?data.y:0),(data.w?data.w:data.dw),(data.h?data.h:data.dh),data.dx*(data.fliph?-1:1),data.dy*(data.flipv?-1:1),data.dw,data.dh);
+1172 		tox.restore();
+1173 	},
+1174   
+1175   
+1176   /**
+1177   * Draws a tilemap to a canvas context
+1178   * @param {Object} tox The canvas context to be drawn on.
+1179   * @param {Object} data An object containing a set of tilemap data, including:
+1180   * <ul><li>tileset {String}: (required) the id of the tileset the tilemap is based on</li>
+1181   * <li>map {Array}: an array whose x and y coord represent the tilemap coordinates, containing integers that correspond to the index of a given tile (or null for no tile)</li></ul>
+1182   */
+1183 	blitTilemap:function(tox,data) {
+1184 		if (tox==null) return;
+1185 		var ts=this._tiles[data.tileset];
+1186 		for (var y=0;y<data.map.length;y++)
+1187 			for (var x=0;x<data.map[y].length;x++)
+1188 				if (data.map[y][x]!=null) this.blitTile(tox,{tileset:data.tileset,tile:data.map[y][x],dx:x*ts.tilew,dy:y*ts.tilew});
+1189 	},
+1190   
+1191   
+1192   /**
+1193   * Draws text to a canvas context
+1194   * @param {Object} tox The canvas context to be drawn on.
+1195   * @param {Object} data An object containing a set of data, including:
+1196   * <ul><li>font {String}: (required) the id of font to draw the text with</li>
+1197   * <li>text {String}: (required) the text to display</li>
+1198   * <li>dx {Integer}: (required) the x coordinate to draw the text at</li>
+1199   * <li>dy {Integer}: (required) the y coordinate to draw the text at</li>
+1200   * <li>dw {Integer}: the width of the text area -- required if you define data.halign</li>
+1201   * <li>dh {Integer}: the height of the text area -- required if you define data.valign</li>
+1202   * <li>valign {Integer}: either gbox.ALIGN_BOTTOM (aligns from the bottom of the text area) or gbox.ALIGN_MIDDLE (vertically centers text in text area)</li>
+1203   * <li>halign {Integer}: either gbox.ALIGN_RIGHT (aligns to the right hand side of text area) or gbox.ALIGN_CENTER (horizontallly centers text in text area)</li>
+1204   * <li>alpha {Float}: alpha value (0 is transparent, 1 is opaque)</li></ul>
+1205   */
+1206 	blitText:function(tox,data) {
+1207 		if (tox==null) return;
+1208 		data.text+=""; // Convert to string.
+1209 		var fn=this._fonts[data.font];
+1210 		var tile=0;
+1211 		this._implicitsargs(data);
+1212 		var dx=data.dx;
+1213 		var dy=data.dy;			
+1214 		if (data.valign==gbox.ALIGN_BOTTOM) dy = dy+data.dh-fn.tileh;
+1215 		else if (data.valign==gbox.ALIGN_MIDDLE) dy = dy+Math.floor(data.dh/2)-fn.tileh;
+1216 		if (data.halign==gbox.ALIGN_RIGHT) dx = dx+data.dw-(data.text.length*fn.tilew);
+1217 		else if (data.halign==gbox.ALIGN_CENTER) dx = dx+Math.floor((data.dw-(data.text.length*fn.tilew))/2);
+1218 		tox.save();
+1219 		tox.globalAlpha=(data.alpha?data.alpha:1);
+1220 		for (var y=0;y<data.text.length;y++) {
+1221 			tile=data.text.charCodeAt(y)-fn.firstascii;
+1222 			if (tile>=0) {
+1223 				if (data.clear) tox.clearRect(dx+(y*fn.tilew),dy,(data.w?data.w:fn.tilew),(data.h?data.h:fn.tileh));
+1224 				this._safedrawimage(tox,this.getImage(fn.image), fn.gapx+(fn.tilew*(tile%fn.tilerow)),
+1225 				fn.gapy+(fn.tileh*Math.floor(tile/fn.tilerow)),fn.tilew,fn.tileh,dx+(y*fn.tilew),dy,(data.w?data.w:fn.tilew),(data.h?data.h:fn.tileh));
+1226 			}
+1227 		}
+1228 		tox.restore();
+1229 	},
+1230   
+1231   /**
+1232   * Clears a rectangular area of a canvas context.
+1233   * @param {Object} image The canvas context to be drawn on.
+1234   * @param {Object} data An object containing a set of data, including:
+1235   * <ul><li>x {Integer}: (required) the x coordinate of the top-left corner of the rectangle</li>
+1236   * <li>y {Integer}: (required) the y coordinate of the top-left corner of the rectangle</li>
+1237   * <li>w {Integer}: the width of the box; defaults to canvas width</li>
+1238   * <li>h {Integer}: the height the box; defaults to canvas height</li></ul>
+1239   */
+1240 	blitClear:function(image,data) {
+1241 		if (image==null) return;
+1242 		if (data==null) data={x:0,y:0};
+1243 		this._implicitsargs(data);
+1244 		image.clearRect(data.x,data.y,(data.w==null?image.canvas.width:data.w),(data.h==null?image.canvas.height:data.h));
+1245 	},
+1246   
+1247   /**
+1248   * Draws an image directly to the screen's current canvas context. Used internally in gbox.go(). Probably shouldn't be used otherwise.
+1249   */
+1250 	blitImageToScreen:function(image) {
+1251 		this._screen.getContext("2d").drawImage(image,0,0);
+1252 	},
+1253   
+1254    /**
+1255   * Draws a filled rectangle over an entire canvas context.
+1256   * @param {Object} tox The canvas context to be filled.
+1257   * @param {Object} data An object containing a set of data, including:
+1258   * <ul><li>alpha {Float}: the alpha value of the rectangle; defaults to 1</li>
+1259   * <li>color {Object}: the color of the box, formatted rgb(rValue, gValue, bValue); default black</li></ul>
+1260   */
+1261 	blitFade:function(tox,data) { 
+1262 		if (tox) this.blitRect(tox,{x:0,y:0,w:tox.canvas.width,h:tox.canvas.height,alpha:data.alpha,color:data.color});
+1263 	},
+1264   
+1265   /**
+1266   * Draws a filled rectangle to a canvas context.
+1267   * @param {Object} tox The canvas context to be drawn on.
+1268   * @param {Object} data An object containing a set of data, including:
+1269   * <ul><li>x {Integer}: (required) the x coordinate of the top-left corner of the rectangle</li>
+1270   * <li>y {Integer}: (required) the y coordinate of the top-left corner of the rectangle</li>
+1271   * <li>w {Integer}: (required) the width of the box</li>
+1272   * <li>h {Integer}: (required) the height the box</li>
+1273   * <li>alpha {Float}: the alpha value of the rectangle; defaults to 1</li>
+1274   * <li>color {Object}: the color of the box, formatted rgb(rValue, gValue, bValue); default black</li></ul>
+1275   */
+1276 	blitRect:function(tox,data) {
+1277 		if (tox==null) return;
+1278 		tox.save();
+1279 		tox.globalAlpha=(data.alpha?data.alpha:1);
+1280 		tox.fillStyle = (data.color?data.color:gbox.COLOR_BLACK);
+1281 		tox.fillRect(data.x,data.y,data.w,data.h);
+1282 		tox.restore();
+1283 	},
+1284   
+1285   /**
+1286   * Calculates a box collision between two collision boxes within a given tolerance. A higher tolerance means less precise collision.
+1287   * @param {Object} o1 A collision box you're testing for collision. Must contain:
+1288   * <ul><li>x {Integer}: (required) the x coordinate of the object's origin; assumes the Akihabara default of top-left being the origin</li>
+1289   * <li>y {Integer}: (required) the y coordinate of the object's origin; assumes the Akihabara default of top-left being the origin</li>
+1290   * <li>w {Integer}: (required) the width of the box</li>
+1291   * <li>h {Integer}: (required) the height the box</li></ul>
+1292   * @param {Object} o2 A collision box you're testing for collision. Must contain:
+1293   * <ul><li>x {Integer}: (required) the x coordinate of the object's origin; assumes the Akihabara default of top-left being the origin</li>
+1294   * <li>y {Integer}: (required) the y coordinate of the object's origin; assumes the Akihabara default of top-left being the origin</li>
+1295   * <li>w {Integer}: (required) the width of the box</li>
+1296   * <li>h {Integer}: (required) the height the box</li></ul>
+1297   * @param {Integer} t The tolerance for the collision, in pixels. A value of 0 means pixel-perfect box collision. A value of 2 would mean that the
+1298   * boxes could overlap by up to 2 pixels without being considered a collision.
+1299   * @returns True if the two collision boxes are colliding within the given tolerance.
+1300   */  
+1301 	collides:function(o1,o2,t) {
+1302 		if (!t) t=0;
+1303 		return !((o1.y+o1.h-1-t<o2.y+t) || (o1.y+t> o2.y+o2.h-1-t) || (o1.x+o1.w-1-t<o2.x+t) || (o1.x+t>o2.x+o2.w-1-t));
+1304 	},
+1305   
+1306   /**
+1307   * Calculates a point-box collision between a point and a collision box within a given tolerance. A higher tolerance means less precise collision.
+1308   * @param {Object} o1 A point you're testing for collision. Must contain:
+1309   * <ul><li>x {Integer}: (required) the x coordinate of the point</li>
+1310   * <li>y {Integer}: (required) the y coordinate of the point</li></ul>
+1311   * @param {Object} o2 A collision box you're testing for collision. Must contain:
+1312   * <ul><li>x {Integer}: (required) the x coordinate of the object's origin; assumes the Akihabara default of top-left being the origin</li>
+1313   * <li>y {Integer}: (required) the y coordinate of the object's origin; assumes the Akihabara default of top-left being the origin</li>
+1314   * <li>w {Integer}: (required) the width of the box</li>
+1315   * <li>h {Integer}: (required) the height the box</li></ul>
+1316   * @param {Integer} t The tolerance for the collision, in pixels. A value of 0 means pixel-perfect collision. A value of 2 would mean that the
+1317   * point could exist within the outermost 2 pixels of the box without being considered a collision.
+1318   * @returns True if the point is colliding with the box within the given tolerance.
+1319   */  
+1320 	pixelcollides:function(o1,o2,t) {
+1321 		if (!t) t=0;
+1322 		return !((o1.y<o2.y+t) || (o1.y> o2.y+o2.h-1-t) || (o1.x<o2.x+t) || (o1.x>o2.x+o2.w-1-t));
+1323 	},
+1324   
+1325   /**
+1326   * Determines whether an object is visible by seeing if it collides with the camera's viewport.
+1327   * @param {Object} obj The object you're testing to see if it's visible. Must contain:
+1328   * <ul><li>x {Integer}: (required) the x coordinate of the object's origin; assumes the Akihabara default of top-left being the origin</li>
+1329   * <li>y {Integer}: (required) the y coordinate of the object's origin; assumes the Akihabara default of top-left being the origin</li>
+1330   * <li>w {Integer}: (required) the width of the object's collision box</li>
+1331   * <li>h {Integer}: (required) the height the object's box</li></ul>
+1332   * @returns True if the object's collision box is within the camera's viewport.
+1333   */  
+1334 	objectIsVisible:function(obj) { return this.collides(obj,this._camera,0); },
+1335 	
+1336 	// --- 
+1337 	// --- 
+1338 	// ---  AUDIO ENGINE
+1339 	// --- 
+1340 	// --- 
+1341 	
+1342 	_audiochannels:{},
+1343 	_audiomastervolume:1.0,
+1344 	_canaudio:false,
+1345 	_audiodequeuetime:0,
+1346 	_audioprefetch:0.5,
+1347 	_audiocompatmode:0, // 0: pause/play, 1: google chrome compatibility, 2: ipad compatibility (single channel)
+1348 	_createmode:0, // 0: clone, 1: rehinstance
+1349 	_fakecheckprogressspeed:100, // Frequency of fake audio monitoring
+1350 	_fakestoptime:1, // Fake audio stop for compatibility mode
+1351 	_audioteam:2,
+1352 	_loweraudioteam:1,
+1353 	_audio:{lding:null,qtimer:false,aud:{},ast:{}},
+1354 	_audioactions:[],
+1355 	_showplayers:false,
+1356 	_singlechannelname:"bgmusic",
+1357 	_positiondelay:0,
+1358 	_playerforcer:0,
+1359 	_audiomutevolume:0.0001, // Zero is still not accepted by everyone :(
+1360 	_rawstopaudio:function(su) {
+1361 		if (gbox._audiocompatmode==1) {
+1362 			if (su.duration-su.currentTime>gbox._fakestoptime)
+1363 				su.currentTime=su.duration-gbox._fakestoptime;
+1364 			su.muted=true;
+1365 		} else
+1366 			su.pause();
+1367 
+1368 	},
+1369 	_rawplayaudio:function(su) {
+1370 		if (gbox._audiocompatmode==1) {
+1371 			try { su.currentTime=0; } catch (e) {}
+1372 			su.muted=false;
+1373 			su.play();
+1374 		} else if (gbox._audiocompatmode==2) {
+1375 			su.load();
+1376 			gbox._playerforcer=setInterval(function(e){try{su.play();clearInterval(gbox._playerforcer)}catch(e){}},1000);
+1377 		} else {
+1378 			try { su.currentTime=0; } catch (e) {}
+1379 			su.play();
+1380 		}
+1381 	},
+1382 	_finalizeaudio:function(ob,who,donext){
+1383 	
+1384 		var cur=(who?who:this);
+1385 		cur.removeEventListener('ended', gbox._finalizeaudio,false);
+1386 		cur.removeEventListener('timeupdate', gbox._checkprogress,false);
+1387 		
+1388 		cur.addEventListener('ended', gbox._playbackended,false);
+1389 		if (donext) gbox._loaderloaded();
+1390 	},
+1391 	_audiodoload:function() {
+1392 		if (gbox._audiocompatmode==1) gbox._audio.lding.muted=true;
+1393 		else if (gbox._audiocompatmode==2)
+1394 			gbox._finalizeaudio(null,gbox._audio.lding,true);
+1395 		else {
+1396 			gbox._audio.lding.load();
+1397 			gbox._audio.lding.play();
+1398 		}
+1399 	},
+1400 	_timedfinalize:function() {
+1401 		gbox._rawstopaudio(gbox._audio.lding);
+1402 		gbox._finalizeaudio(null,gbox._audio.lding,true);	
+1403 	},
+1404 	_checkprogress:function() {
+1405 		if (gbox._audio.lding.currentTime>gbox._audioprefetch) gbox._timedfinalize();
+1406 	},
+1407 	_fakecheckprogress:function() {
+1408 		if (gbox._audio.lding.currentTime>gbox._audioprefetch) gbox._timedfinalize(); else setTimeout(gbox._fakecheckprogress,gbox._fakecheckprogressspeed);	
+1409 	},
+1410 	_audiofiletomime:function(f) {
+1411 		var fsp=f.split(".");
+1412 		switch (fsp.pop().toLowerCase()) {
+1413 			case "ogg": { return "audio/ogg"; break }
+1414 			case "mp3": { return "audio/mpeg"; break }
+1415 			default: {
+1416 				return "audio/mpeg";
+1417 			}
+1418 		}
+1419 	},
+1420 	_pushaudio:function(){try {this.currentTime=1.0} catch(e){} },
+1421 	_createnextaudio:function(cau) {
+1422 		if (cau.def) {
+1423 			gbox.deleteAudio(cau.id);
+1424 			this._audio.aud[cau.id]=[];
+1425 			this._audio.ast[cau.id]={cy:-1,volume:1,channel:null,play:false,mute:false,filename:cau.filename[0]};
+1426 			if (cau.def) for (var a in cau.def) this._audio.ast[cau.id][a]=cau.def[a];
+1427 		}
+1428 		if ((gbox._createmode==0)&&(cau.team>0)) {
+1429 			var ael =this._audio.aud[cau.id][0].cloneNode(true);
+1430 			gbox._finalizeaudio(null,ael,false);
+1431 		} else {
+1432 			var ael=document.createElement('audio');
+1433 			ael.volume=gbox._audiomutevolume;
+1434 		}
+1435 		if (!gbox._showplayers) {
+1436 			ael.style.display="none";
+1437 			ael.style.visibility="hidden";
+1438 			ael.style.width="1px";
+1439 			ael.style.height="1px";
+1440 			ael.style.position="absolute";
+1441 			ael.style.left="0px";
+1442 			ael.style.top="-1000px";
+1443 		}
+1444 		ael.setAttribute('controls',gbox._showplayers);
+1445 		ael.setAttribute('aki_id',cau.id);
+1446 		ael.setAttribute('aki_cnt',cau.team);
+1447 		ael.addEventListener('loadedmetadata', gbox._pushaudio,false); // Push locked audio in safari
+1448 		if (((gbox._createmode==0)&&(cau.team==0))||(gbox._createmode==1)) {
+1449 			if (ael.canPlayType) {
+1450 				var cmime;
+1451 				for (var i=0;i<cau.filename.length;i++) {
+1452 					cmime=gbox._audiofiletomime(cau.filename[i]);
+1453 					if (("no" != ael.canPlayType(cmime)) && ("" != ael.canPlayType(cmime))) {
+1454 						ael.src=gbox._breakcacheurl(cau.filename[i]);
+1455 						break;
+1456 					}
+1457 				}
+1458 			} else {
+1459 				for (var i=0;i<cau.filename.length;i++) {
+1460 					var src=document.createElement('source');
+1461 					src.setAttribute('src', gbox._breakcacheurl(cau.filename[i]));
+1462 					ael.appendChild(src);
+1463 				}
+1464 			}
+1465 			ael.addEventListener('ended',this._finalizeaudio,false);
+1466 			if (gbox._audiocompatmode==1)
+1467 				setTimeout(gbox._fakecheckprogress,gbox._fakecheckprogressspeed);
+1468 			else
+1469 				ael.addEventListener('timeupdate',this._checkprogress,false);
+1470 			ael.setAttribute('buffering',"auto");
+1471 			ael.volume=0;
+1472 			this._audio.aud[cau.id].push(ael);
+1473 			document.body.appendChild(ael);
+1474 			gbox._audio.lding=ael;
+1475 			setTimeout(gbox._audiodoload,1);
+1476 		} else {
+1477 			this._audio.aud[cau.id].push(ael);
+1478 			document.body.appendChild(ael);
+1479 			gbox._loaderloaded();
+1480 		}
+1481 	},
+1482 	_playbackended:function(e) {
+1483 		if (gbox._audio.ast[this.getAttribute('aki_id')].cy==this.getAttribute('aki_cnt')) {
+1484 			if (gbox._audio.ast[this.getAttribute('aki_id')].play&&gbox._audio.ast[this.getAttribute('aki_id')].loop)
+1485 				if (gbox._audiocompatmode==2)
+1486 					gbox._rawplayaudio(this);
+1487 				else
+1488 					this.currentTime=0;
+1489 			else
+1490 				gbox._audio.ast[this.getAttribute('aki_id')].play=false; 
+1491 		} else if (gbox._audiocompatmode==1) {
+1492 			this.pause();
+1493 			this.muted=false;
+1494 		}
+1495 	},
+1496 	_updateaudio:function(a) {
+1497 		if (this._audio.ast[a].play) {
+1498 			this._audio.aud[a][this._audio.ast[a].cy].volume=(this._audio.ast[a].mute?this._audiomutevolume: 
+1499 				this._audiomastervolume*
+1500 				(this._audio.ast[a].volume!=null?this._audio.ast[a].volume:1)*
+1501 				((this._audio.ast[a].channel!=null)&&(this._audiochannels[this._audio.ast[a].channel]!=null)&&(this._audiochannels[this._audio.ast[a].channel].volume!=null)?this._audiochannels[this._audio.ast[a].channel].volume:1)
+1502 			)
+1503 		}
+1504 	},
+1505 	_minimaltimeexpired:function() { gbox._minimalexpired=2; },
+1506 	_splashscreeniscompleted:function() { return (gbox._splash.background?gbox.imageIsLoaded("_splash"):true) && (gbox._splash.minilogo?gbox.imageIsLoaded("logo"):true) && (gbox._splash.footnotes?gbox.imageIsLoaded("_dbf"):true) },
+1507 	_addqueue:function(a) {
+1508 		if (!gbox._audiodequeuetime)
+1509 			gbox._dequeueaudio(null,a);
+1510 		else {
+1511 			gbox._audioactions.push(a);
+1512 			if (!gbox._audio.qtimer) {
+1513 				gbox._audio.qtimer=true;
+1514 				setTimeout(gbox._dequeueaudio,gbox._audiodequeuetime);
+1515 			}
+1516 		}
+1517 	},
+1518 	_dequeueaudio:function(k,rt) {
+1519 			var ac=(rt?rt:gbox._audioactions.pop());
+1520 			switch (ac.t) {
+1521 				case 0: {
+1522 					gbox._updateaudio(ac.a.getAttribute("aki_id"));
+1523 					gbox._rawplayaudio(ac.a);
+1524 					break
+1525 				}
+1526 				case 1: {
+1527 					gbox._rawstopaudio(ac.a);
+1528 					break;
+1529 				}
+1530 				case 2: {
+1531 					gbox._updateaudio(ac.a.getAttribute("aki_id"));
+1532 					break;
+1533 				}
+1534 			}
+1535 			if (!rt&&gbox._audioactions.length) {
+1536 				gbox._audio.qtimer=true;
+1537 				setTimeout(gbox._dequeueaudio,gbox._audiodequeuetime);
+1538 			} else gbox._audio.qtimer=false;
+1539 	
+1540 	},
+1541 	getAudioIsSingleChannel:function() { return this._audiocompatmode==2; },
+1542 	setAudioPositionDelay:function(m) { gbox._positiondelay=m },
+1543 	setAudioDequeueTime:function(m) { gbox._audiodequeuetime=m },
+1544 	setShowPlayers:function(m) { gbox._showplayers=m},
+1545 	setAudioCompatMode:function(m) { gbox._audiocompatmode=m },
+1546 	setAudioCreateMode:function(m) { gbox._createmode=m },
+1547 	addAudio:function(id,filename,def) {
+1548 		if (gbox._canaudio) {
+1549 			if (gbox._audio.aud[id])
+1550 				if (gbox._audio.ast[id].filename==filename[0])
+1551 					return;
+1552 				else
+1553 					gbox.deleteAudio(id);
+1554 			if ((gbox._audiocompatmode!=2)||(def.channel==gbox._singlechannelname)) {
+1555 				var grsize=(def.channel==gbox._singlechannelname?gbox._loweraudioteam:(def.background?gbox._loweraudioteam:gbox._audioteam));
+1556 				for (var i=0;i<grsize;i++)
+1557 					gbox._addtoloader({type:"audio",data:{id:id,filename:filename,def:(i==0?def:null),team:i}});
+1558 			}
+1559 		}
+1560 	},
+1561 	deleteAudio:function(id) {
+1562 		if (gbox._audio.aud[id]) {
+1563 			for (var i=0;i<gbox._audio.aud[id].length;i++) {
+1564 				try {document.body.removeChild(gbox._audio.aud[id][i]);}catch(e){}
+1565 				delete gbox._audio.aud[id][i];
+1566 			}
+1567 			delete gbox._audio.aud[id];
+1568 			if (gbox._audio.ast[id]) delete gbox._audio.ast[id];
+1569 		}
+1570 	},
+1571 	playAudio:function(a,data) {
+1572 		if (this._canaudio&&this._audio.ast[a])
+1573 			if (!this._audio.ast[a].play) this.hitAudio(a,data);
+1574 	},
+1575 	hitAudio:function(a,data) {
+1576 		if (this._canaudio&&this._audio.ast[a]) {
+1577 			var ael;
+1578 			if (this._audio.ast[a].cy!=-1)
+1579 				this.stopAudio(a,true);
+1580 			this._audio.ast[a].cy=(this._audio.ast[a].cy+1)%this._audio.aud[a].length;
+1581 			ael=this._audio.aud[a][this._audio.ast[a].cy];
+1582 			if (data) 
+1583 				for (var n in data) this._audio.ast[a][n]=data[n];
+1584 			this._audio.ast[a].play=true;
+1585 			this._addqueue({t:0,a:ael});
+1586 		}
+1587 	},
+1588 	stopAudio:function(a,permissive) {
+1589 		if (this._canaudio) {
+1590 			var ael;
+1591 			if (this._canaudio&&this._audio.ast[a]&&this._audio.ast[a].play) {
+1592 				this._audio.ast[a].play=false;
+1593 				ael=this._audio.aud[a][this._audio.ast[a].cy];
+1594 				if (ael.duration-1.5>0)
+1595 					this._addqueue({t:1,a:ael});
+1596 			}
+1597 		}
+1598 	},
+1599 	setSplashSettings:function(a) { for (var n in a) this._splash[n]=a[n]; },
+1600 	resetChannel:function(ch) {
+1601 		if (this._canaudio&&this._audiochannels[ch])
+1602 			if (ch=="master")
+1603 				for (var ch in this._audiochannels)
+1604 					this.setChannelVolume(ch,this._audiochannels[ch]._def.volume);
+1605 			else if (this._audiochannels[ch])
+1606 				this.setChannelVolume(ch,this._audiochannels[ch]._def.volume);
+1607 	},
+1608 	getChannelDefaultVolume:function(ch) {
+1609 		if (this._canaudio&&this._audiochannels[ch]) return this._audiochannels[ch]._def.volume; else return null;
+1610 	},
+1611 	setChannelVolume:function(ch,a) {
+1612 		if (this._canaudio&&this._audiochannels[ch]) {
+1613 			if (ch=="master") this._audiomastervolume=a; else this._audiochannels[ch].volume=a
+1614 			for (var j in gbox._audio.aud)
+1615 				if (this._audio.ast[j].cy>-1) this._updateaudio(j);
+1616 		}
+1617 	},
+1618 	getChannelVolume:function(ch) { if (ch=="master") return this._audiomastervolume; else if (this._audiochannels[ch]) return this._audiochannels[ch].volume; else return 0 },
+1619 	changeChannelVolume:function(ch,a) {
+1620 		if (this._canaudio&&this._audiochannels[ch]) {
+1621 			var vol=this.getChannelVolume(ch)+a;
+1622 			if (vol>1) vol=1; else if (vol<0) vol=0;
+1623 			this.setChannelVolume(ch,vol);
+1624 		}
+1625 	},
+1626 	stopChannel:function(ch) {
+1627 		if (this._canaudio)
+1628 			for (var j in gbox._audio.aud)
+1629 				if (this._audio.ast[j].cy>-1&&gbox._audio.ast[j].play&&((ch=="master")||(this._audio.ast[j].channel==ch)))
+1630 					this.stopAudio(j);
+1631 	},
+1632 	
+1633 	setAudioUnmute:function(a) { if (this._canaudio&&this._audio.ast[a]) { this._audio.ast[a].mute=false; this._updateaudio(a); } },
+1634 	setAudioMute:function(a) { if (this._canaudio&&this._audio.ast[a]) { this._audio.ast[a].mute=true; this._updateaudio(a); } },
+1635 	getAudioMute:function(a) { if (this._canaudio&&this._audio.ast[a]) return this._audio.ast[a].mute; else return null},
+1636 	
+1637 	setAudioVolume:function(a,vol) { if (this._canaudio&&this._audio.ast[a]) { this._audio.ast[a].volume=vol; this._updateaudio(a); } },
+1638 	getAudioVolume:function(a,vol) { if (this._canaudio&&this._audio.ast[a]) return this._audio.ast[a].volume; else return null},
+1639 	
+1640 	setAudioPosition:function(a,p) {  if (this._canaudio&&this._audio.ast[a]&&this._audio.aud[a][this._audio.ast[a].cy]) this._audio.aud[a][this._audio.ast[a].cy].currentTime=p;},
+1641 	getAudioPosition:function(a) {if (this._canaudio&&this._audio.ast[a]&&this._audio.aud[a][this._audio.ast[a].cy]) if (this._audio.aud[a][this._audio.ast[a].cy].currentTime>this._positiondelay) return this._audio.aud[a][this._audio.ast[a].cy].currentTime-this._positiondelay; else return 0; else return 0},
+1642 
+1643 	getAudioDuration:function(a) {if (this._canaudio&&this._audio.ast[a]&&this._audio.aud[a][this._audio.ast[a].cy]) return this._audio.aud[a][this._audio.ast[a].cy].duration; else return 0},
+1644 
+1645 	changeAudioVolume:function(a,vol) { if (this._canaudio&&this._audio.ast[a]) { if (this._audio.ast[a].volume+vol>1) this._audio.ast[a].volume=1; else  if (this._audio.ast[a].volume+vol<0) this._audio.ast[a].volume=0; else this._audio.ast[a].volume+=vol; this._updateaudio(a); } },
+1646 	setCanAudio:function(a) { this._canaudio=!this._flags.noaudio&&a;},
+1647 	setAudioChannels:function(a){
+1648 		this._audiochannels=a;
+1649 		for (var ch in a) {
+1650 			this._audiochannels[ch]._def={};
+1651 			for (var attr in this._audiochannels[ch])
+1652 				if (attr!="_def") this._audiochannels[ch]._def[attr]=this._audiochannels[ch][attr];
+1653 		}
+1654 	},
+1655 	setAudioTeam:function(a){ this._audioteam=a; },
+1656 	setLowerAudioTeam:function(a){ this._loweraudioteam=a; },
+1657 	
+1658 	// ---
+1659 	// ---
+1660 	// ---  DYNAMIC SCRIPT INCLUSION
+1661 	// ---
+1662 	// ---
+1663 	
+1664 	addScript:function(call) {
+1665 		gbox._addtoloader({type:"script",call:call});
+1666 	},
+1667 	
+1668 	// ---
+1669 	// ---
+1670 	// ---  BUNDLES
+1671 	// ---
+1672 	// ---
+1673 	
+1674 	addBundle:function(call){
+1675 		gbox._addtoloader({type:"bundle",call:call});
+1676 	},
+1677 	
+1678 	readBundleData:function(pack,call) {
+1679 		// Local resources first
+1680 		if (pack.setObject) for (var i=0;i<pack.setObject.length;i++) eval("("+pack.setObject[i].object+")")[pack.setObject[i].property]=pack.setObject[i].value;
+1681 		if (pack.addFont) for (var i=0;i<pack.addFont.length;i++) gbox.addFont(pack.addFont[i]);
+1682 		if (pack.addTiles) for (var i=0;i<pack.addTiles.length;i++) gbox.addTiles(pack.addTiles[i]);
+1683 		// Remote resources for last
+1684 		if (pack.addImage) for (var i=0;i<pack.addImage.length;i++) gbox.addImage(pack.addImage[i][0],pack.addImage[i][1]);
+1685 		if (pack.addAudio) for (var i=0;i<pack.addAudio.length;i++) gbox.addAudio(pack.addAudio[i][0],pack.addAudio[i][1],pack.addAudio[i][2]);
+1686 		if (pack.addBundle) for (var i=0;i<pack.addBundle.length;i++) gbox.addBundle(pack.addBundle[i]);
+1687 		if (pack.addScript) for (var i=0;i<pack.addScript.length;i++) gbox.addScript(pack.addScript[i]);
+1688 		// Trigger the onLoad events in resource and loader
+1689 		if (pack.onLoad) gbox._addtoloader({type:"exec-onl",func:pack.onLoad,call:call,pack:pack});				
+1690 		if (call.onLoad) gbox._addtoloader({type:"exec-onl",func:call.onLoad,call:call,pack:pack});	
+1691 	},
+1692 	
+1693 	// --- 
+1694 	// --- 
+1695 	// ---  DATA LOADER
+1696 	// --- 
+1697 	// --- 
+1698 
+1699 	_xmlhttp:null,
+1700 	_loaderqueue:cyclelist.create(200),
+1701 	_loadercache:cachelist.create(30),
+1702 	
+1703 	// Callback for loaded image
+1704 	_loaderimageloaded:function() {
+1705 		this.setAttribute('wasloaded',true);
+1706 		this.hheight=Math.floor(this.height/2);
+1707 		this.hwidth=Math.floor(this.width/2);
+1708 		gbox._loaderloaded();	
+1709 	},
+1710 	// Callback for loaded bundle
+1711 	_loaderhmlhttploading:function(){
+1712 		if(this.readyState == 4 && (this.status == 0||this.status == 200)) {
+1713 			if (this.responseText) {
+1714 				if (!gbox._loaderqueue.getCurrent().call.skipCacheSave)
+1715 					gbox._loadercache.add(gbox._loaderqueue.getCurrent().call.file,this.responseText);
+1716 				var pack=eval("("+this.responseText+")");
+1717 				gbox.readBundleData(pack,gbox._loaderqueue.getCurrent().call);
+1718 				// Keep loading the other resources.
+1719 				gbox._loaderloaded();
+1720 			}	
+1721 		}
+1722 	},
+1723 	
+1724 	// Loader code
+1725 	_addtoloader:function(d) { // type:xx, data:yy
+1726 		gbox._loaderqueue.push(d);
+1727 		if (!gbox._loaderqueue.isProcessing())
+1728 			gbox._loadnext();
+1729 	},
+1730 	_loaderloaded:function() {
+1731 		setTimeout(gbox._loadnext,10);
+1732 	},
+1733 	_loaderscript:function() {
+1734 		if (gbox._loaderqueue.getCurrent().call.onLoad) gbox._addtoloader({type:"exec-onl",func:gbox._loaderqueue.getCurrent().call.onLoad,call:gbox._loaderqueue.getCurrent().call});
+1735 		gbox._loadnext();
+1736 	},
+1737 	_loadnext:function() {
+1738 		var current=gbox._loaderqueue.pop();
+1739 		if (gbox._loaderqueue.isProcessing()) {
+1740 			switch (gbox._loaderqueue.getCurrent().type) {
+1741 				case "image":{
+1742 					gbox._images[current.id]=new Image();
+1743 					gbox._images[current.id].addEventListener('load', gbox._loaderimageloaded,false);
+1744 					gbox._images[current.id].src=gbox._breakcacheurl(current.filename);
+1745 					gbox._images[current.id].setAttribute('src_org',current.filename);
+1746 					gbox._images[current.id].setAttribute('id',current.id);
+1747 					gbox._images[current.id].setAttribute('wasloaded',false);
+1748 					break;
+1749 				}
+1750 				case "bundle":{
+1751 					var done=false;
+1752 					if (!current.call.skipCacheLoad) {
+1753 						var data=gbox._loadercache.read(current.call.file);
+1754 						if (data) {
+1755 							var pack=eval("("+data+")");
+1756 							gbox.readBundleData(pack,current.call);
+1757 							// Keep loading the other resources.
+1758 							gbox._loaderloaded();
+1759 							done=true;
+1760 						}
+1761 					}
+1762 					if (!done) {
+1763 						gbox._xmlhttp=new XMLHttpRequest();
+1764 						gbox._xmlhttp.open((current.call.data?"POST":"GET"), gbox._breakcacheurl(current.call.file),true);
+1765 						gbox._xmlhttp.onreadystatechange = gbox._loaderhmlhttploading;
+1766 						if (current.call.data) {
+1767 							gbox._xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
+1768 							gbox._xmlhttp.send(current.call.data);
+1769 						} else gbox._xmlhttp.send();
+1770 					}
+1771 					break;
+1772 				}
+1773 				case "audio":{
+1774 					gbox._createnextaudio(current.data);
+1775 					break;
+1776 				}
+1777 				case "exec-onl":{
+1778 					current.func(current.call,current.pack);
+1779 					gbox._loaderloaded();
+1780 					break;
+1781 				}
+1782 				case "script":{
+1783 					var script= document.createElement('script');
+1784 					script.type="text/javascript";
+1785 					script.onload=gbox._loaderscript;
+1786 					script.src=current.call.file;
+1787 					document.getElementsByTagName('body')[0].appendChild(script);
+1788 					break;
+1789 				}
+1790 			}
+1791 		}
+1792 	
+1793 	},
+1794 	_waitforloaded:function() {
+1795 		var aul;
+1796 		if (gbox._loaderqueue.isBusy()||(gbox._minimalexpired!=2)) {
+1797 			var tox=gbox._screen.getContext("2d");
+1798 			tox.save();
+1799 			gbox.blitFade(tox,{alpha:1});
+1800 			if (!gbox._minimalexpired&&gbox._splashscreeniscompleted()) {
+1801 				gbox._minimalexpired=1;
+1802 				setTimeout(gbox._minimaltimeexpired,gbox._splash.minimalTime);
+1803 			}
+1804 			if (gbox._splash.loading) gbox._splash.loading(tox,gbox._loaderqueue.getDone(),gbox._loaderqueue.getTotal());
+1805 			if (gbox._splash.background&&gbox.imageIsLoaded("_splash"))
+1806 				gbox.blit(tox,gbox.getImage("_splash"),{w:gbox.getImage("_splash").width,h:gbox.getImage("_splash").height,dx:0,dy:0,dw:gbox.getScreenW(),dh:gbox.getScreenH()});
+1807 			if (gbox._splash.minilogo&&gbox.imageIsLoaded("logo")) {
+1808 				var dw=gbox.getScreenW()/4;
+1809 				var dh=(gbox.getImage("logo").height*dw)/gbox.getImage("logo").width
+1810 				gbox.blit(tox,gbox.getImage(gbox._splash.minilogo),{w:gbox.getImage("logo").width,h:gbox.getImage("logo").height,dx:gbox.getScreenW()-dw-5,dy:gbox.getScreenH()-dh-5,dw:dw,dh:dh});
+1811 			}
+1812 			if (gbox._splash.footnotes&&gbox.imageIsLoaded("_dbf")) {
+1813 				if (!gbox.getCanvas("_footnotes")) {
+1814 					var fd=gbox.getFont("_dbf");
+1815 					gbox.createCanvas("_footnotes",{w:gbox.getScreenW()-5,h:(gbox._splash.footnotes.length)*(fd.tileh+gbox._splash.footnotesSpacing)});
+1816 					for (var i=0;i<gbox._splash.footnotes.length;i++)
+1817 						gbox.blitText(gbox.getCanvasContext("_footnotes"),{
+1818 										font:"_dbf",
+1819 										dx:0,
+1820 										dy:i*(fd.tileh+gbox._splash.footnotesSpacing),
+1821 										text:gbox._splash.footnotes[i]
+1822 									});
+1823 				}
+1824 				gbox.blitAll(tox,gbox.getCanvas("_footnotes"),{dx:5,dy:gbox.getScreenH()-gbox.getCanvas("_footnotes").height-5});
+1825 			}
+1826 			if (gbox._loaderqueue.isBusy()) {
+1827 				var bw=Math.floor(((gbox.getScreenW()-4)*gbox._loaderqueue.getDone())/gbox._loaderqueue.getTotal());
+1828 				tox.globalAlpha=1;
+1829 				tox.fillStyle = gbox._splash.gaugeBorderColor;
+1830 				tox.fillRect(0,Math.floor((gbox.getScreenH()-gbox._splash.gaugeHeight)/2),gbox.getScreenW(),gbox._splash.gaugeHeight);
+1831 				tox.fillStyle = gbox._splash.gaugeBackColor;
+1832 				tox.fillRect(1,Math.floor(((gbox.getScreenH()-gbox._splash.gaugeHeight)/2)+1),gbox.getScreenW()-4,gbox._splash.gaugeHeight-2);
+1833 				tox.fillStyle = gbox._splash.gaugeColor;
+1834 				tox.fillRect(1,Math.floor(((gbox.getScreenH()-gbox._splash.gaugeHeight)/2)+1),(bw>0?bw:0),gbox._splash.gaugeHeight-2);
+1835 			}
+1836 			tox.restore();		
+1837 			gbox.setStatBar("Loading... ("+gbox._loaderqueue.getDone()+"/"+gbox._loaderqueue.getTotal()+")");
+1838 			setTimeout(gbox._waitforloaded,50);
+1839 		} else {
+1840 			gbox.deleteImage("_splash");
+1841 			gbox.setStatBar();
+1842 			gbox._cb();
+1843 		}
+1844 	},
+1845 	clearCache:function() { this._loadercache.clear(); }
+1846 
+1847 };
+1848 
+1849 
\ No newline at end of file diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/symbols/src/c__Users_Darius_Desktop_akihabara-1.1_kesiev_akihabara_akihabara_help.js.html b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/src/c__Users_Darius_Desktop_akihabara-1.1_kesiev_akihabara_akihabara_help.js.html new file mode 100644 index 0000000..e20cd09 --- /dev/null +++ b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/src/c__Users_Darius_Desktop_akihabara-1.1_kesiev_akihabara_akihabara_help.js.html @@ -0,0 +1,547 @@ +
  1 // ---
+  2 // Copyright (c) 2010 Francesco Cottone, http://www.kesiev.com/
+  3 // ---
+  4 
+  5 /**
+  6  * @namespace Help module provides some Javascript-specific functions, such object copying, randomizing functions, 
+  7  * string/array handlers and the akihabaraInit function.
+  8  */
+  9 var help={
+ 10 
+ 11  /**
+ 12  * Generates numbers from st to ed, along with a skip value.
+ 13  * @param {Integer} st Starting number.
+ 14  * @param {Integer} ed Ending number.
+ 15  * @param {Integer} skip Number to increment by.
+ 16  * @returns An array containing the set of numbers from st to ed, incrementing by skip.
+ 17  */
+ 18 	seq:function(st,ed,skip) {
+ 19 		var ret=[];
+ 20 		for (var i=st;i<ed;i+=(skip==null?1:skip)) ret.push(i);
+ 21 		return ret;
+ 22 	},
+ 23 
+ 24  /**
+ 25  * Multiplies two numbers together, returning the result, unless the first parameter is less than 2, in which case it returns 1.
+ 26  * @param {Float} v First value.
+ 27  * @param {Float} mul Second value.
+ 28  * @returns An integer, v*mul, unless v<2 in which case it returns 1.
+ 29  */
+ 30 	// Handle a multiplier like counter. that means, 0=1 / 1=1 / 2=2*mul etc...
+ 31 	multiplier:function(v,mul) {
+ 32 		return (!v||(v<2)?1:v*(!mul?1:mul));
+ 33 	},
+ 34 	
+ 35  /**
+ 36  * Prepends a string with repeated instances of another string until it the result is greater than or equal to a desired length.
+ 37  * @param {String} str The string you wish to modify.
+ 38  * @param {Integer} len The desired length of your resultant string.
+ 39  * @param {String} pad The string you wish to prepend to str.
+ 40  * @returns A string whose length is no greater than len+pad.length, with pad prepending str repeatedly.
+ 41  */
+ 42 	prepad:function(str,len,pad) {
+ 43 		str+="";
+ 44 		while (str.length<len) str=pad+str;
+ 45 		return str;
+ 46 	},
+ 47 	
+ 48  /**
+ 49  * Postpends a string with repeated instances of another string until it the result is greater than or equal to a desired length.
+ 50  * @param {String} str The string you wish to modify.
+ 51  * @param {Integer} len The desired length of your resultant string.
+ 52  * @param {String} pad The string you wish to postpend to str.
+ 53  * @returns A string whose length is no greater than len+pad.length, with pad postpending str repeatedly.
+ 54  */
+ 55 	postpad:function(str,len,pad) {
+ 56 		str+="";
+ 57 		while (str.length<len) str+=pad;
+ 58 		return str;
+ 59 	},
+ 60 
+ 61  /**
+ 62  * Tests to see if an object is being "jumped on" by another object. Only works for platformers, since it assumes accy>0 means you're falling onto something else.
+ 63  * @param {Object} th The object that is (possibly) being jumped on.
+ 64  * @param {Object} by The object doing the jumping-on.
+ 65  * @returns True if the two objects are overlapping enough and by.accy>0.
+ 66  */
+ 67 	isSquished:function(th,by) {
+ 68 		return ((by.accy>0)&&gbox.collides(th,by)&&(Math.abs(th.y-(by.y+by.h))<(th.h/2)))
+ 69 	},
+ 70  
+ 71  /**
+ 72  * Generates uniformly distributed random integers between min and min+range, non-inclusive. So help.random(0,2) will only return 0 and 1, etc.
+ 73  * @param {Integer} min The minimum random value to be returned by the function.
+ 74  * @param {Integer} range The number of different values returned by the function.
+ 75  * @returns An integer between min (includive) and min+range (noninclusive).
+ 76  */
+ 77 	random:function(min,range) {
+ 78 		return min+Math.floor(Math.random()*range);
+ 79 	},
+ 80  
+ 81  
+ 82   /**
+ 83  * Determines which frame of a given animation to display. Will loop an animation.
+ 84  * @param {Integer} cnt A global frame counter.
+ 85  * @param {Object} anim An object with parameters speed (the animation speed) and frames (the array representing the animation sequence).
+ 86  * @returns The particular animation frame to display during this step.
+ 87  */
+ 88 	decideFrame:function(cnt,anim) {
+ 89 		return anim.frames[Math.floor(cnt/anim.speed)%anim.frames.length];
+ 90 	},
+ 91   
+ 92  /**
+ 93  * Determines which frame of a given animation to display. Will remain on the last frame when the animation has played once.
+ 94  * @param {Integer} cnt A global frame counter.
+ 95  * @param {Object} anim An object with parameters speed (the animation speed) and frames (the array representing the animation sequence).
+ 96  * @returns The particular animation frame to display during this step.
+ 97  */
+ 98 	decideFrameOnce:function(cnt,anim) {
+ 99 		return anim.frames[(cnt>=anim.frames.length*anim.speed?anim.frames.length-1:Math.floor(cnt/anim.speed))];
+100 	},
+101   
+102  /**
+103  * Returns whether the animation was fully played at least once with decideFrame or fully with decideFrameOnce.
+104  * @param {Integer} cnt A global frame counter.
+105  * @param {Object} anim An object with parameters speed (the animation speed) and frames (the array representing the animation sequence).
+106  * @returns A boolean, true if the animation has been played at least once.
+107  */
+108  	isLastFrameOnce:function(cnt,anim) {
+109 		return (cnt>=anim.frames.length*anim.speed);
+110 	},
+111 
+112  /**
+113  * Given an incrementing value each step, this will return a value increasing from 0 until max/2, at which point it will decrement to 0, then go back up to max/2, in an endless cycle.
+114  * @param {Integer} counter A counter.
+115  * @param {Integer} max This determines the period of the function -- assuming counter is incrementing by one, a complete back-and-forth will take 'max' steps.
+116  * @returns An integer.
+117  */
+118 	upAndDown:function(counter,max) {
+119 		if ((counter%max)>(max/2)) return max-(counter%max); else return (counter%max);
+120 	},
+121   
+122  /**
+123  * Given x,y coordinates and map information, this returns the tile at a given point.
+124  * @param {Integer} x An x-coordinate.
+125  * @param {Integer} y A y-coordinate.
+126  * @param {Object} map The map object.
+127  * @param {Object} ifout An object or value to be returned if the x,y coordinate pair is outside the map.
+128  * @param {String} mapid The id for the map array within the map object. Default is 'map'.
+129  * @returns An integer representing the value of the tile in the map array at that x,y coordinate. If there is no tile, null is returned.
+130  */
+131  	getTileInMap:function(x,y,map,ifout,mapid) {
+132 		if (!mapid) mapid="map";
+133 		var ts=gbox._tiles[map.tileset];
+134 		var tx=Math.floor(x/ts.tilew);
+135 		var ty=Math.floor(y/ts.tileh);
+136 		if ((ty<0)||(ty>=map[mapid].length)) return ifout; else
+137 		if ((tx<0)||(tx>=map[mapid][ty].length)) return ifout; else
+138 		return map[mapid][ty][tx];
+139 	},
+140 
+141  /**
+142  * Takes an ascii-art-style array of characters and converts it to an Akihabara-compatible map format.
+143  * @param {Array} map An array of characters representing a map.
+144  * @param {Array} tra A translation array. This is an array of arrays, formatted like [ [null, char1], [0, char2], [1, char3] ]. There must at least be a null entry, followed by one numerical entry for each tile type you want to render, corresponding to the unique characters in the map array. The null entry maps a character to empty space.
+145  * @returns A map array formatted such that it can be attached to a map object.
+146  */
+147 	asciiArtToMap:function(map,tra) {
+148 		var sz=tra[0][1].length;
+149 		var ret=[];
+150 		var xpos;
+151 		var pie;
+152 		for (var y=0;y<map.length;y++) {
+153 			var row=[];
+154 			xpos=0;
+155 			while (xpos<map[y].length) {
+156 				pie=map[y].substr(xpos,sz);
+157 				for (var t=0;t<tra.length;t++)
+158 					if (pie==tra[t][1]) {
+159 						if (t==0) row.push(null); else row.push(tra[t][0]);
+160 						break;
+161 					}
+162 				xpos+=sz;
+163 			}
+164 			ret.push(row);
+165 		}
+166 		return ret;
+167 	},
+168 	
+169   /**
+170   * Calculates and sets the width and height (map.h, map.w) and half-width and half-height (map.hh, map.hw) of a map object.
+171   * @param {Object} map A map object, containing a map array and a tileset array.
+172   * @returns A map object with map.w, map.h, map.hh, and map.hw set correctly.
+173   */	
+174 	// Finalize a map definition, setting height and width in pixels etc.
+175 	// Args: (map)
+176 	// Outs: finalized map
+177 	finalizeTilemap:function(map) {
+178 		var ts=gbox._tiles[map.tileset];
+179 		map.h=map.map.length*ts.tileh;
+180 		map.w=map.map[0].length*ts.tilew;
+181 		map.hw=Math.floor(map.w/2);
+182 		map.hh=Math.floor(map.h/2);
+183 		return map;
+184 	},
+185  
+186   /**
+187   * Converts an x-coordinate of a pixel to its corresponding tile x-coordinate.
+188   * @param {Object} map A map object, containing a map array and a tileset array.
+189   * @param {Integer} x An x-coordinate.
+190   * @param {Integer} gap (Not used.)
+191   * @returns A map object with map.w, map.h, map.hh, and map.hw set correctly.
+192   */	
+193 	xPixelToTileX:function(map,x,gap) {
+194 		var ts=gbox._tiles[map.tileset];
+195 		return Math.floor(x/ts.tilew);
+196 	},
+197   
+198   /**
+199   * Converts a y-coordinate of a pixel to its corresponding tile y-coordinate.
+200   * @param {Object} map A map object, containing a map array and a tileset array.
+201   * @param {Integer} y A y-coordinate.
+202   * @param {Integer} gap (Not used.)
+203   * @returns A map object with map.w, map.h, map.hh, and map.hw set correctly.
+204   */	
+205 	yPixelToTileY:function(map,y,gap) {
+206 		var ts=gbox._tiles[map.tileset];
+207 		return Math.floor(y/ts.tileh);
+208 	},
+209   
+210   /**
+211   * Converts an x-coordinate of a pixel to the x-coordinate of the tile column it's in. This effectively "snaps" an x coordinate to a tile edge.
+212   * @param {Object} map A map object, containing a map array and a tileset array.
+213   * @param {Integer} x An x-coordinate.
+214   * @param {Integer} gap Number of pixels gap in tilemap. Default is 0.
+215   * @returns The x-coordinate in pixels of the tile column.
+216   */	
+217 	xPixelToTile:function(map,x,gap) {
+218 		var ts=gbox._tiles[map.tileset];
+219 		return (Math.floor(x/ts.tilew)+(gap?gap:0))*ts.tilew;
+220 	},
+221 
+222   /**
+223   * Converts a y-coordinate of a pixel to the y-coordinate of the tile row it's in. This effectively "snaps" a y coordinate to a tile edge.
+224   * @param {Object} map A map object, containing a map array and a tileset array.
+225   * @param {Integer} y A y-coordinate.
+226   * @param {Integer} gap Number of pixels gap in tilemap. Default is 0.
+227   * @returns The y-coordinate in pixels of the tile row.
+228   */	
+229 	yPixelToTile:function(map,y,gap) {
+230 		var ts=gbox._tiles[map.tileset];
+231 		return (Math.floor(y/ts.tileh)+(gap?gap:0))*ts.tileh;
+232 	},
+233   
+234   /**
+235   * Limits a number to a certain range. If the number is below the minimum, the minimum is returned. If the number is above the maximum, the maximum is returned.
+236   * @param {Float} v A value.
+237   * @param {Float} min The minimum limit.
+238   * @param {Float} max The maximum limit.
+239   * @returns A value equal to v if min<v<max. Returns min if v<min, max if v>max.
+240   */	
+241 	limit:function(v,min,max) {
+242 		if (v<min) return min; else if (v>max) return max; else return v;
+243 	},
+244  
+245   /**
+246   * Subtracts or adds 1 to a value, always converging to zero. For example, passing -3 yields -2, 5 yields 4, etc. Works best with integers.
+247   * @param {Integer} v A value.
+248   * @returns A value that is one closer to 0 on the number line than v.
+249   */	
+250 	goToZero:function(v) { return (v?v-(v/Math.abs(v)):0); },
+251 	
+252   /**
+253   * Merges two sets of parameters together without overwriting existing parameters. This merges from model to data, and if data and model share parameters, data's values remain intact.
+254   * @param {Object} data An object containing a set of parameters, the destination of the merge.
+255   * @param {Object} model An object containing a set of parameters, the source of the merge.
+256   * @returns A merged model where the values of 'data' remain untouched: only new parameters and values from 'model' make it in.
+257   * @example
+258   * dst = {a: 1, b: 2, c: "three"};
+259   * src = {c: "three", d: "four"};
+260   * merged = help.mergeWithModel(dst,src);
+261   * merged; // => {a: 1, b: 2, c: 3, d: "four"};
+262   */	
+263 	mergeWithModel:function(data,model) {
+264 		if (data==null) data={};
+265 		if (model!=null)
+266 			for (var i in model)
+267 				if (data[i]==null) data[i]=model[i];
+268 		return data;
+269 	},
+270 	
+271   /**
+272   * Merges two sets of parameters together overwriting any existing parameters. This merges model->data, and if data and model share parameters, data's are overwritten by model's.
+273   * @param {Object} data An object containing a set of parameters, the destination of the merge.
+274   * @param {Object} model An object containing a set of parameters, the source of the merge.
+275   * @returns A merged model where the values of 'model' take precedence over those of 'data'. The 'data' object is returned and will be an exact copy of 'model', plus any parameters that 'data' had before the merge that 'model' did not.
+276   * @example
+277   * dst = {a: 1, b: 2, c: "three"};
+278   * src = {c: "three", d: "four"};
+279   * merged = help.mergeWithModel(dst,src);
+280   * merged; // => {a: 1, b: 2, c: "three", d: "four"}
+281   */	
+282 	copyModel:function(data,model) {
+283 		if (data==null) data={};
+284 		if (model!=null)
+285 			for (var i in model) data[i]=model[i];
+286 		return data;
+287 	},
+288 
+289   /**
+290   * Creates a subset of an existing set of parameters.
+291   * @param {Object} obj An object containing a set of parameters, the source of the data.
+292   * @param {Array} attrs An array of strings, containing the names of parameters you wish to copy.
+293   * @returns A new set of parameters based on the subset specified.
+294   * @example
+295   * data = {a: 1, b: 2, c: "three"};
+296   * newdata = help.createModel(data, ["a", "c"]);
+297   * newdata; // => {a: 1, c: "three"}
+298   */	
+299 	createModel:function(obj,attrs) {
+300 		var ret={};
+301 		for (var i=0;i<attrs.length;i++) ret[attrs[i]]=obj[attrs[i]];
+302 		return ret;
+303 	},
+304 	
+305   /**
+306   * Creates a duplicate of an existing set of parameters.
+307   * @param {Object} model An object containing a set of parameters.
+308   * @returns A new object, equivalent to 'model'.
+309   * @example
+310   * data = {a: 1, b: 2, c: "three"};
+311   * newdata = help.cloneObject(data);
+312   * newdata; // => {a: 1, b: 2, c: "three"}
+313   */	
+314 	cloneObject:function(model) {
+315 		if (!model) return model;
+316 		var data={};
+317 		for (var i in model) data[i]=model[i];
+318 		return data;
+319 	},
+320 	
+321   /**
+322   * Sets a tile in the map and draws it. Does not return anything.
+323   * @param {Object} ctx The canvas context for the map. Accessed via gbox.getCanvasContext("canvasname")
+324   * @param {Object} map The game map object.
+325   * @param {Integer} x The index of the tile column within the map array -- so a 1 would mean the second column of tiles. 
+326   * @param {Integer} y The index of the tile row within the map array -- so a 1 would mean the second row of tiles. 
+327   * @param {Integer} tile The integer representing the new tile you wish to draw. This is its index within the tileset; a null value will erase whatever tile is present.
+328   * @param {String} The ID of the map. Defaults to 'map'.
+329   * @example
+330   * // Remove the second tile to the right and down from the upper left corner of the tile map. Assumes our map canvas is called 'map_canvas'.
+331   * help.setTileInMap(gbox.getCanvasContext("map_canvas"),map,1,1,null,"map");
+332   */	  
+333 	setTileInMap:function(ctx,tilemap,x,y,tile,map) {
+334 		var ts=gbox.getTiles(tilemap.tileset);
+335 		tilemap[(map==null?"map":map)][y][x]=tile;
+336 		if (tile==null)
+337 			gbox.blitClear(ctx,{x:x*ts.tilew,y:y*ts.tilew,h:ts.tileh,w:ts.tilew});
+338 		else
+339 			gbox.blitTile(ctx,{tileset:tilemap.tileset,tile:tile,dx:x*ts.tilew,dy:y*ts.tilew});
+340 	},
+341 	
+342 
+343   /**
+344   * Returns the Nth element in an array. If the array is shorter than N, it returns the last element of the array.
+345   * @param {Array} a An array.
+346   * @param {Integer} id An index to the array.
+347   * @returns If id > a.length, it returns a[a.length-1]. Otherwise returns a[id].
+348   */	
+349 	getArrayCapped:function(a,id) {
+350 		if (id>=a.length) return a[a.length-1]; else return a[id];
+351 	},
+352 	
+353 	// Get an item of an array of object, using a field as index. is returned the first entry if the field is not valued.
+354 	getArrayIndexed:function(a,value,field) {
+355 		if (a[0][field]==null) return a[0];
+356 		var i=0;
+357 		while ((value>a[i][field])&&(i!=a.length-1)) i++;
+358 		return a[i];
+359 	},
+360 	
+361 			
+362   /**
+363   * Converts a quantity of frames into a timestamp formatted "mm:ss:cs" (minutes, seconds, centiseconds). Calculated using the current frames per second.
+364   * @param {Integer} frames A quantity of frames.
+365   * @returns A string containing a timestamp formatted "mm:ss:cs", representing the length of time it would take to render that many frames.
+366   * @example
+367   * // Assuming 25 frames per second, Akihabara's default.
+368   * timestamp = help.framestotime(25);
+369   * timestamp; // => '00:01:00';
+370   * timestamp = help.framestotime(25 * 60);
+371   * timestamp; // => '01:00:00';  
+372   */	
+373 	framestotime:function(frames) {
+374 		var csec=Math.ceil(frames/gbox.getFps()*100);
+375 		return this.prepad((Math.floor(csec/6000)%60),2,"0")+":"+this.prepad((Math.floor(csec/100)%60),2,"0")+":"+this.prepad(csec%100,2,"0");
+376 		
+377 	},
+378 	
+379   /**
+380   * Reads the value of a query parameter from the URL of the web page. 
+381   * @param {String} name The name of the URL parameter.
+382   * @returns The value of the URL parameter, as a string.
+383   * @example
+384   * // If the URL is http://example.com/game.html?lives=3
+385   * player.lives = help.geturlparameter("lives");
+386   * player.lives; // => 3
+387   */	
+388 	geturlparameter:function( name ) {
+389 	  name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
+390 	  var regexS = "[\\?&]"+name+"=([^&#]*)";
+391 	  var regex = new RegExp( regexS );
+392 	  var results = regex.exec( window.location.href );
+393 	  if( results == null )
+394 		return "";
+395 	  else
+396 		return results[1];
+397 	},
+398 	
+399   /**
+400   * Writes the contents of an object to a string. Useful for debugging.
+401   * @param {Object} Any object.
+402   * @returns A string containing all the contents of an object. If the object contains functions, the string will contain the code for those functions.
+403   */	
+404 	objToStr:function(o) {
+405 		var ret="";
+406 		for (var n in o) ret+=n+":["+o[n]+"] ";
+407 		return ret;
+408 	},
+409 	
+410   /**
+411   * Tests whether an object contains a given parameter.
+412   * @param {Object} A reference to a parameter of an object.
+413   * @returns True if the object contains that parameter, false if it does not.
+414   * @example
+415   * foo = {a: 1, b: 2};
+416   * help.isDefined(foo.a); // => true
+417   * help.isDefined(foo.c); // => false
+418   */	
+419 	isDefined:function(v) {
+420 		return ((typeof(v) !== 'undefined') || (v===null));
+421 	},
+422 	
+423   /**
+424   * Automatically configures a bunch of settings depending on the web browser and device that is viewing the game. Mostly sets the maximum number of audio channels and touch settings.
+425   */	
+426 	getDeviceConfig:function() {
+427 
+428 		var cap;
+429 		if (navigator.userAgent.match(/iPhone/i)||navigator.userAgent.match(/iPod/i) || navigator.userAgent.match(/Android/i))
+430 			cap={touch:true,width:320};			
+431 		else if (navigator.userAgent.match(/iPad/i))
+432 			cap={touch:true,width:768,forcedidle:10}; // Forced idle time is needed for correct framerate calculation.
+433 		else
+434 			cap={zoom:2};
+435 		
+436 		cap.canaudio=!!(document.createElement('audio').canPlayType);
+437 
+438 		if (cap.canaudio) {
+439 			if (navigator.userAgent.match(/iPad/i)||navigator.userAgent.match(/iPhone/i)||navigator.userAgent.match(/iPod/i)) {
+440 				cap.audiocompatmode=2; // Single audio per time, so compatibility mode is needed. Plays only the "bgmusic" channel.
+441 				cap.audioteam=1; // Only a member is required in the audioteam.
+442 				cap.audioisexperimental=true; // Audio is experimental, since limited.
+443 			} else if (navigator.userAgent.match(/Chrome/i)) {
+444 				cap.audioteam=3; // Quite low performance on playback responsiveness.
+445 			} else if (navigator.userAgent.match(/Firefox/i)) {
+446 				cap.audioteam=1; // Testing smaller audioteam
+447 				cap.audiopositiondelay=0.3; // Ogg playback is slower 0.3 between MP3 playback. Don't know why :)
+448 				cap.audiocreatemode=1; // Firefox is stalling while downloading lot of things
+449 			} else if (navigator.userAgent.match(/Minefield/i)) {
+450 				cap.audioteam=1; // Testing smaller audioteam
+451 				cap.audiocreatemode=1; // Firefox is stalling while downloading lot of things
+452 				// Minefield has fixed the 0.3 delay!
+453 			} else if (navigator.userAgent.match(/Safari/i)) {
+454 				cap.audioteam=1; // Testing smaller audioteam						
+455 			} else if (navigator.userAgent.match(/Opera/i)) {
+456 				cap.audioteam=1; // Testing smaller audioteam			
+457 				cap.audiocreatemode=1; // Do not like audio object cloning very much
+458 			} else
+459 				cap.audioisexperimental=true; // Audio is just experimental on all other devices.
+460 				
+461 		}
+462 
+463 		return cap;
+464 	},
+465 
+466   /**
+467   * This provides a number of configurations: fps, display zoom, dynamic frameskip, force touch parameters, etc. Many of these settings can
+468   * be set manually by passing an object with the parameters defined, or via URL parameters.
+469   * @param {Object} data An optional object containing parameters you wish to set. Works for data.zoom, data.splash, data.width, data.height, data.title, data.fps, and data.padmode.
+470   */	
+471 	akihabaraInit:function(data) {
+472 		if ((typeof data).toLowerCase() == "string") data={title:data};
+473 		var device=this.getDeviceConfig();
+474 		var footnotes=["MADE WITH AKIHABARA (C)2010 - GPL2/MIT","Project: www.kesiev.com/akihabara","Sources: github.com/kesiev/akihabara"];
+475 		document.title=(data.title?data.title:"Akihabara");
+476 		if (data.splash) {
+477 			if (data.splash.footnotes) 
+478 				for (var i=0;i<footnotes.length;i++) data.splash.footnotes.push(footnotes[i]);
+479 			gbox.setSplashSettings(data.splash);
+480 		}
+481 		var screenwidth=(data.width?data.width:(data.portrait?240:320));
+482 		var screenheight=(data.height?data.height:(data.portrait?320:240));
+483 		if (!data.splash||(data.splash.minilogo==null)) gbox.setSplashSettings({minilogo:"logo"});
+484 		if (!data.splash||(data.splash.background==null)) gbox.setSplashSettings({background:"akihabara/splash.png"});
+485 		if (!data.splash||(data.splash.minimalTime==null)) gbox.setSplashSettings({minimalTime:3000});
+486 		if (!data.splash||(data.splash.footnotes==null)) gbox.setSplashSettings({footnotes:footnotes});
+487 		document.body.style.backgroundColor="#000000";
+488 		gbox.setScreenBorder(false);
+489 		if (help.geturlparameter("statusbar")) gbox.setStatusBar(1);
+490 		if (help.geturlparameter("db")) gbox.setDoubleBuffering(true);
+491 		if (help.geturlparameter("noautoskip")) gbox.setAutoskip(null);
+492 		if (help.geturlparameter("zoom")) gbox.setZoom(help.geturlparameter("zoom")); else
+493 	     	if (help.isDefined(data.zoom)) gbox.setZoom(data.zoom); else
+494 			if (help.isDefined(device.zoom)) gbox.setZoom(device.zoom); else
+495 			if (help.isDefined(device.width)) gbox.setZoom(device.width/screenwidth);
+496 		if (help.geturlparameter("fps")) gbox.setFps(help.geturlparameter("fps")*1);
+497 			else gbox.setFps((data.fps?data.fps:25));
+498 		if (help.geturlparameter("fskip")) gbox.setFrameskip(help.geturlparameter("fskip"));
+499 		if (help.geturlparameter("forcedidle")) gbox.setForcedIdle(help.geturlparameter("forcedidle")*1);
+500 			else if (help.isDefined(device.forcedidle)) gbox.setForcedIdle(device.forcedidle);
+501 		if (help.geturlparameter("canlog")) gbox.setCanLog(true);
+502 
+503 		gbox.initScreen(screenwidth,screenheight);
+504 
+505 		if (help.geturlparameter("showplayers")) gbox.setShowPlayers(help.geturlparameter("showplayers")=="yes");
+506 		if (help.geturlparameter("canaudio")) gbox.setCanAudio(help.geturlparameter("canaudio")=="yes"); else
+507 			gbox.setCanAudio(device.canaudio&&(!device.audioisexperimental||gbox.getFlag("experimental")));
+508 		if (help.geturlparameter("audiocompatmode")) gbox.setAudioCompatMode(help.geturlparameter("audiocompatmode")*1); else
+509 			if (help.isDefined(device.audiocompatmode)) gbox.setAudioCompatMode(device.audiocompatmode);
+510 		if (help.geturlparameter("audioteam")) gbox.setAudioTeam(help.geturlparameter("audioteam")*1); else
+511 			if (help.isDefined(device.audioteam)) gbox.setAudioTeam(device.audioteam);
+512 		if (help.geturlparameter("loweraudioteam")) gbox.setLowerAudioTeam(help.geturlparameter("loweraudioteam")*1); else
+513 			if (help.isDefined(device.loweraudioteam)) gbox.setLowerAudioTeam(device.loweraudioteam);			
+514 		if (help.geturlparameter("audiocreatemode")) gbox.setAudioCreateMode(help.geturlparameter("audiocreatemode")*1); else
+515 			if (help.isDefined(device.audiocreatemode)) gbox.setAudioCreateMode(device.audiocreatemode);
+516 		if (help.geturlparameter("audiodequeuetime")) gbox.setAudioDequeueTime(help.geturlparameter("audiodequeuetime")*1); else
+517 			if (help.isDefined(device.audiodequeuetime)) gbox.setAudioDequeueTime(device.audiodequeuetime);
+518 		if (help.geturlparameter("audiopositiondelay")) gbox.setAudioPositionDelay(help.geturlparameter("audiopositiondelay")*1); else
+519 			if (help.isDefined(device.audiopositiondelay)) gbox.setAudioPositionDelay(device.audiopositiondelay);
+520 			
+521 			
+522 			
+523 		if (help.geturlparameter("touch")=="no");
+524 			else if ((help.geturlparameter("touch")=="yes")||device.touch)
+525 				switch (data.padmode) {
+526 					case "fretboard": {
+527 						iphofretboard.initialize({h:100,bg:"akihabara/fretboard.png"});		
+528 						break;
+529 					}
+530 					case "none": {
+531 						break;
+532 					}
+533 					default: {
+534 						iphopad.initialize({h:100,dpad:"akihabara/dpad.png",buttons:"akihabara/buttons.png",bg:"akihabara/padbg.png"});		
+535 						break;
+536 					}
+537 				}
+538 	}
+539 }
+540 
\ No newline at end of file diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/symbols/src/c__Users_Darius_Desktop_akihabara-1.1_kesiev_akihabara_akihabara_iphofretboard.js.html b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/src/c__Users_Darius_Desktop_akihabara-1.1_kesiev_akihabara_akihabara_iphofretboard.js.html new file mode 100644 index 0000000..74561f9 --- /dev/null +++ b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/src/c__Users_Darius_Desktop_akihabara-1.1_kesiev_akihabara_akihabara_iphofretboard.js.html @@ -0,0 +1,65 @@ +
  1 // ---
+  2 // Copyright (c) 2010 Francesco Cottone, http://www.kesiev.com/
+  3 // ---
+  4 
+  5 /**
+  6  * Fretboard module provides a touchpad for touch-based device (for now, Android and iDevices).
+  7  */
+  8 var iphofretboard={
+  9 	_swap:false,
+ 10 	_frets:["a","b","c","left","right"],
+ 11 	_move:["up","down"],
+ 12 	_buttons:{up:false,down:false,left:false,right:false,a:false,b:false,c:false},
+ 13 	_fretw:0,
+ 14 	_moveh:0,
+ 15 	_gapx:0,
+ 16 	_gapy:0,
+ 17 	_listen:function(e) {
+ 18 		var nc={up:false,down:false,left:false,right:false,a:false,b:false,c:false};
+ 19 		var fret;
+ 20 		for (var i=0;i<e.touches.length;i++) {
+ 21 			fret=Math.floor((e.touches[i].pageX-iphofretboard._gapx)/iphofretboard._fretw);
+ 22 			if (fret<iphofretboard._frets.length)			
+ 23 				nc[iphofretboard._frets[fret]]=true;
+ 24 			else
+ 25 				nc[iphofretboard._move[Math.floor((e.touches[i].pageY-iphofretboard._gapy)/iphofretboard._moveh)]]=true;
+ 26 		}
+ 27 		this._swap=!this._swap;
+ 28 		for (var i in nc) {
+ 29 			if (nc[i]!=iphofretboard._buttons[i])
+ 30 				if (nc[i]) gbox._keydown({fake:true,keyCode:gbox._keymap[i]});
+ 31 				else gbox._keyup({fake:true,keyCode:gbox._keymap[i]});
+ 32 		}
+ 33 		
+ 34 		iphofretboard._buttons=nc;
+ 35 	},
+ 36 	initialize:function(data) {
+ 37 		var oElement=document.createElement("img");
+ 38 		oElement.src=data.bg;		
+ 39 		oElement.style.margin="auto";
+ 40 		oElement.style.padding="0px";
+ 41 		oElement.style.height=data.h+"px";
+ 42 		oElement.style.width="100%";
+ 43 		
+ 44 		gbox._box.appendChild(oElement);
+ 45 
+ 46 		oElement.ontouchstart=function(evt) { evt.preventDefault();evt.stopPropagation(); iphofretboard._listen(evt) };
+ 47 		oElement.ontouchend=function(evt) { evt.preventDefault();evt.stopPropagation();iphofretboard._listen(evt) };
+ 48 		oElement.ontouchmove=function(evt) { evt.preventDefault();evt.stopPropagation();iphofretboard._listen(evt) };
+ 49 
+ 50 		var sizes=gbox._domgetabsposition(oElement);
+ 51 		this._gapx=sizes.x;
+ 52 		this._gapy=sizes.y;
+ 53 		this._fretw=sizes.w/(this._frets.length+1);
+ 54 		this._moveh=sizes.h/(this._move.length);
+ 55 	}
+ 56 	
+ 57 }
+ 58 
\ No newline at end of file diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/symbols/src/c__Users_Darius_Desktop_akihabara-1.1_kesiev_akihabara_akihabara_iphopad.js.html b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/src/c__Users_Darius_Desktop_akihabara-1.1_kesiev_akihabara_akihabara_iphopad.js.html new file mode 100644 index 0000000..afaf85a --- /dev/null +++ b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/src/c__Users_Darius_Desktop_akihabara-1.1_kesiev_akihabara_akihabara_iphopad.js.html @@ -0,0 +1,128 @@ +
  1 // ---
+  2 // Copyright (c) 2010 Francesco Cottone, http://www.kesiev.com/
+  3 // ---
+  4 
+  5 /**
+  6  * Iphopad module provides a touchpad for touch-based device (for now, Android and iDevices).
+  7  */
+  8 var iphopad={
+  9 	_buttonsize:50,
+ 10 	_buttonsize2:100,
+ 11 	_buttonsize3:150,
+ 12 	_gapx:0,
+ 13 	_gapy:0,
+ 14 	_width:0,
+ 15 	_height:0,
+ 16 	_center:{},
+ 17 	_cross:{up:false,down:false,left:false,right:false},
+ 18 	_buttons:{a:false,b:false,c:false},
+ 19 	_transl:(Math.PI*0.125),
+ 20 	_brad:(Math.PI*0.25),
+ 21 	_positions:[
+ 22 		{up:false,down:false,left:false,right:true},
+ 23 		{up:false,down:true,left:false,right:true},
+ 24 		{up:false,down:true,left:false,right:false},
+ 25 		{up:false,down:true,left:true,right:false},
+ 26 		{up:false,down:false,left:true,right:false},
+ 27 		{up:true,down:false,left:true,right:false},
+ 28 		{up:true,down:false,left:false,right:false},
+ 29 		{up:true,down:false,left:false,right:true}
+ 30 	],
+ 31 	_swap:false,
+ 32 	_listen:function(e) {
+ 33 		var nc={up:false,down:false,left:false,right:false};
+ 34 		var nb={a:false,b:false,c:false};
+ 35 		for (var i=0;i<e.touches.length;i++) {
+ 36 			rp={x:e.touches[i].pageX-iphopad._gapx,y:e.touches[i].pageY-iphopad._gapy};
+ 37 			if (rp.x<iphopad._height)
+ 38 				nc=iphopad._positions[Math.floor(trigo.getAngle(iphopad._center,rp,iphopad._transl)/iphopad._brad)];
+ 39 			else if (rp.x>iphopad._width-iphopad._buttonsize)
+ 40 					nb.a=true;
+ 41 				else if (rp.x>iphopad._width-iphopad._buttonsize2)
+ 42 					nb.b=true;
+ 43 				else if (rp.x>iphopad._width-iphopad._buttonsize3)
+ 44 					nb.c=true;
+ 45 			
+ 46 		}
+ 47 		this._swap=!this._swap;
+ 48 		for (var i in this._cross) {
+ 49 			if (nc[i]!=iphopad._cross[i])
+ 50 				if (nc[i]) gbox._keydown({fake:true,keyCode:gbox._keymap[i]});
+ 51 				else gbox._keyup({fake:true,keyCode:gbox._keymap[i]});
+ 52 		}
+ 53 		for (var i in this._buttons) {
+ 54 			if (nb[i]!=iphopad._buttons[i])
+ 55 				if (nb[i]) gbox._keydown({fake:true,keyCode:gbox._keymap[i]});
+ 56 				else gbox._keyup({fake:true,keyCode:gbox._keymap[i]});
+ 57 		}
+ 58 		
+ 59 		iphopad._cross=nc;
+ 60 		iphopad._buttons=nb;
+ 61 	},
+ 62 	_fakelisten:function(e) {
+ 63 		iphopad._listen({
+ 64 			touches:[
+ 65 				{
+ 66 					pageX:e.clientX,
+ 67 					pageY:e.clientY
+ 68 				}
+ 69 			]
+ 70 		});
+ 71 	},
+ 72 	
+ 73 	/**
+ 74 	* Initializes the game controls for use with an I-product or Android device.
+ 75 	* @param {Object} data passes in information about the screen and its traits such as size. 
+ 76 	*/
+ 77 	initialize:function(data) {
+ 78 		var oElement=document.createElement("div");
+ 79 		oElement.style.margin="auto";
+ 80 		oElement.style.padding="0px";
+ 81 		oElement.style.height=data.h+"px";
+ 82 		oElement.style.width="100%";
+ 83 		oElement.style.backgroundImage="url("+data.bg+")";
+ 84 		oElement.style.backgroundRepeat="repeat-x";
+ 85 		
+ 86 		var tpad=document.createElement("div");
+ 87 		tpad.style.cssFloat="left";
+ 88 		tpad.style.padding="0px";
+ 89 		tpad.style.margin="0px";
+ 90 		tpad.style.height=data.h+"px";
+ 91 		tpad.style.width=data.h+"px";
+ 92 		tpad.style.backgroundImage="url("+data.dpad+")";
+ 93 		tpad.style.backgroundRepeat="no-repeat";
+ 94 
+ 95 		var bpad=document.createElement("div");
+ 96 		bpad.style.cssFloat="right";
+ 97 		bpad.style.padding="0px";
+ 98 		bpad.style.margin="0px";
+ 99 		bpad.style.height=data.h+"px";
+100 		bpad.style.width=iphopad._buttonsize3+"px";
+101 		bpad.style.backgroundImage="url("+data.buttons+")";
+102 		bpad.style.backgroundRepeat="no-repeat";
+103 		
+104 		oElement.appendChild(tpad);
+105 		oElement.appendChild(bpad);
+106 		gbox._box.appendChild(oElement);
+107 
+108 		oElement.ontouchstart=function(evt) { evt.preventDefault();evt.stopPropagation(); iphopad._listen(evt) };
+109 		oElement.ontouchend=function(evt) { evt.preventDefault();evt.stopPropagation();iphopad._listen(evt) };
+110 		oElement.ontouchmove=function(evt) { evt.preventDefault();evt.stopPropagation();iphopad._listen(evt) };
+111 		//oElement.onmousemove=function(evt) { iphopad._fakelisten(evt) };
+112 		var sizes=gbox._domgetabsposition(oElement);
+113 		this._gapx=sizes.x;
+114 		this._gapy=sizes.y;
+115 		this._width=sizes.w;
+116 		this._height=sizes.h;
+117 		this._center={x:Math.floor(this._height/2),y:Math.floor(this._height/2)};			
+118 	}
+119 	
+120 }
+121 
\ No newline at end of file diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/symbols/src/c__Users_Darius_Desktop_akihabara-1.1_kesiev_akihabara_akihabara_tool.js.html b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/src/c__Users_Darius_Desktop_akihabara-1.1_kesiev_akihabara_akihabara_tool.js.html new file mode 100644 index 0000000..82c57bc --- /dev/null +++ b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/src/c__Users_Darius_Desktop_akihabara-1.1_kesiev_akihabara_akihabara_tool.js.html @@ -0,0 +1,139 @@ +
  1 // ---
+  2 // Copyright (c) 2010 Francesco Cottone, http://www.kesiev.com/
+  3 // ---
+  4 
+  5 /**
+  6  * @namespace Tool module provides simple developing tools. Currently, this file only has a cel-composer: 
+  7  * it can compose an image stacking a set of frames for animating objects, applying a 
+  8  * number of filters to each frame.
+  9  */
+ 10 var tool={
+ 11 	_images:[],
+ 12 	_loadedflag:[],
+ 13 	_data:{},
+ 14 	_count:0,
+ 15 	_countloaded:0,
+ 16 	
+ 17 	/**
+ 18 	* This function documents that an image in an animation sequence is loaded and checks if the other images are loaded or not
+ 19 	* @param {Object} id This is the object which is used as an id for keeping track of things related to this object in this function
+ 20 	*/
+ 21 	_loaded:function(id) {
+ 22 		this._loadedflag[id]=true;
+ 23 		tool._countloaded++;
+ 24 		document.title=tool._countloaded+"/"+tool._count;
+ 25 		for (var i=0;i<this._images.length;i++)
+ 26 			if (!this._loadedflag[i]) document.title+=this._images[i].src+", ";
+ 27 	},
+ 28 	
+ 29 	/**
+ 30 	* This checks that everything being kept track of with _count is loaded and depending on the result calls 
+ 31 	*/
+ 32 	_loadall:function() {
+ 33 		if (tool._count!=tool._countloaded)
+ 34 			setTimeout(tool._loadall,1000);
+ 35 		else
+ 36 			tool._allloaded();
+ 37 	},
+ 38 	
+ 39 	/**
+ 40 	* This makes the image cells for an animation and adds the load event listeners that the other stuff work to them. Calls loadall at the end.
+ 41 	* @param {Object} data This is the created animation data being passed in to be used by the function.
+ 42 	*/
+ 43 	makecels:function(data) {
+ 44 		this._data=data;
+ 45 		var id=0;
+ 46 		for (var r=0;r<data.rows.length;r++) {
+ 47 			for (var i=0;i<data.rows[r].length;i++) {
+ 48 				this._images[id]=new Image();
+ 49 				this._images[id].addEventListener('load', function(){tool._loaded(this.id)},false);
+ 50 				this._images[id].setAttribute("id",id);
+ 51 				this._images[id].src=data.rows[r][i].img;
+ 52 				this._count++;
+ 53 				id++;
+ 54 			}
+ 55 		}
+ 56 		this._loadall();
+ 57 	},
+ 58 	
+ 59 	/**
+ 60 	* @function
+ 61     * Creates and initializes the Canvas element. Is called from makecels. This function requires that this._data have been instantiated prior to function call.
+ 62 	*/
+ 63 	_allloaded:function() {
+ 64 		var data=this._data;
+ 65 		var wid=0;
+ 66 		var hei=0;
+ 67 		var curwid=0;
+ 68 		var id=0;
+ 69 		for (var r=0;r<data.rows.length;r++) {
+ 70 			hei+=this._images[id].height*1;
+ 71 			curwid=0;
+ 72 			for (var i=0;i<data.rows[r].length;i++) { curwid+=this._images[id].width*1; id++}
+ 73 			if (wid<curwid) wid=curwid;
+ 74 		}
+ 75 		
+ 76 		var cels=document.createElement("canvas");
+ 77 		cels.style.border="1px solid red";
+ 78 		cels.setAttribute('height',hei);
+ 79 		cels.setAttribute('width',wid);
+ 80 		document.body.appendChild(cels);
+ 81 		var ctx=cels.getContext("2d");
+ 82 	
+ 83 		var curx=0;
+ 84 		var cury=0;
+ 85 		id=0;
+ 86 		for (var r=0;r<data.rows.length;r++) {
+ 87 			curx=0;
+ 88 			for (var i=0;i<data.rows[r].length;i++) {
+ 89 				ctx.drawImage(this._images[id],curx,cury);
+ 90 				if (data.rows[r][i].filter) {
+ 91 					if (data.rows[r][i].filter) {
+ 92 						var imgd = ctx.getImageData(curx, cury, this._images[id].width, this._images[id].height);
+ 93 						var pix = imgd.data;
+ 94 
+ 95 						// Loop over each pixel and invert the color.
+ 96 						for (var z = 0, n = pix.length; z < n; z += 4) {
+ 97 							if (data.rows[r][i].filter.replace) {
+ 98 								for (var w=0;w<data.rows[r][i].filter.replace.length;w++) {
+ 99 									
+100 									repl=data.rows[r][i].filter.replace[w].from;
+101 									to=data.rows[r][i].filter.replace[w].to;
+102 									if ((pix[z]==repl.r)&&(pix[z+1]==repl.g)&&(pix[z+2]==repl.b)&&(pix[z+3]==repl.a)) {
+103 										pix[z  ] = to.r;
+104 										pix[z+1] = to.g;
+105 										pix[z+2] =to.b;
+106 										pix[z+3] =to.a;
+107 									}
+108 								}
+109 							}
+110 							if (data.rows[r][i].filter.color&&(pix[z+3]!=0)) {
+111 								pix[z  ] = data.rows[r][i].filter.color.r;
+112 								pix[z+1] = data.rows[r][i].filter.color.g;
+113 								pix[z+2] =data.rows[r][i].filter.color.b;
+114 								pix[z+3] =data.rows[r][i].filter.color.a;
+115 							}
+116 							
+117 							// i+3 is alpha (the fourth element)
+118 						}
+119 						ctx.putImageData(imgd, curx, cury);
+120 					
+121 					}
+122 				}
+123 				curx+=this._images[id].width*1;
+124 				id++;
+125 			}
+126 			cury+=this._images[id-1].height*1;
+127 		}
+128 		
+129 	}
+130 
+131 }
+132 
\ No newline at end of file diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/symbols/src/c__Users_Darius_Desktop_akihabara-1.1_kesiev_akihabara_akihabara_toys.js.html b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/src/c__Users_Darius_Desktop_akihabara-1.1_kesiev_akihabara_akihabara_toys.js.html new file mode 100644 index 0000000..bdb3f39 --- /dev/null +++ b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/src/c__Users_Darius_Desktop_akihabara-1.1_kesiev_akihabara_akihabara_toys.js.html @@ -0,0 +1,2449 @@ +
  1 // ---
+  2 // Copyright (c) 2010 Francesco Cottone, http://www.kesiev.com/
+  3 // ---
+  4 
+  5 /**
+  6  * @namespace
+  7  * Toys module provides lots of common routines during the game developing: 
+  8  * from effects for screen titles to HUD handling to platform/SHMUP/RPG oriented routines, 
+  9  * like jumping characters, Z-Indexed objects, bullets, sparks, staff rolls, bonus screens, dialogues etc.
+ 10  */
+ 11 var toys={
+ 12 
+ 13 	// CONSTANTS
+ 14 	NOOP:function(){},
+ 15 	PUSH_NONE:0,
+ 16 	PUSH_LEFT:1,
+ 17 	PUSH_RIGHT:2,
+ 18 	PUSH_UP:3,
+ 19 	PUSH_DOWN:4,
+ 20 	
+ 21 	FACES:["up","right","down","left"],
+ 22 	FACES_ANGLE:[trigo.ANGLE_UP,trigo.ANGLE_RIGHT,trigo.ANGLE_DOWN,trigo.ANGLE_LEFT],
+ 23 	FACE_UP:0,
+ 24 	FACE_RIGHT:1,
+ 25 	FACE_DOWN:2,
+ 26 	FACE_LEFT:3,
+ 27 	
+ 28 	/** 
+ 29 	* @namespace
+ 30   * Top-view RPG specific libraries.
+ 31 	*/
+ 32 	topview:{
+ 33 	
+ 34 		/**
+ 35 		* Checks if an object checks that both objects are on the same Z plane and if so it calls gbox.collides.
+ 36 		* @param {Object} fr The object which collision is being checked for. 
+ 37 		* <ul>
+ 38 		* <li>x{Integer}: (required)Objects x position</li>
+ 39 		* <li>y{Integer}: (required)Objects y position</li>
+ 40 		* <li>z{Integer}: (required)Objects z position</li>
+ 41 		* <li>colx{Integer}: (required)The dimension of the collision box along the x axis</li>
+ 42 		* <li>coly{Integer}: (required)The dimension of the collision box along the y axis</li>
+ 43 		* <li>colh{Integer}: (required)Collision box height</li>
+ 44 		* <li>colw{Integer}: (required)Collision box width</li>
+ 45 		* </ul>
+ 46 		* @param {Object} to The object that collision is being checked against.
+ 47 		* <ul>
+ 48 		* <li>x{Integer}: (required)Objects x position</li>
+ 49 		* <li>y{Integer}: (required)Objects y position</li>
+ 50 		* <li>z{Integer}: (required)Objects z position</li>
+ 51 		* <li>colx{Integer}: (required)Collision x</li>
+ 52 		* <li>coly{Integer}: (required)Collision y</li>
+ 53 		* <li>colh{Integer}: (required)Collision box height</li>
+ 54 		* <li>colw{Integer}: (required)Collision box width</li>
+ 55 		* </ul>
+ 56 		* @param {int} t This is the tollerance (or margin for error) on the collide function.
+ 57 		*/
+ 58 		collides:function(fr,to,t) { // Special collision. Counts also the Z
+ 59 			if (Math.abs(fr.z,to.z)<5) return gbox.collides({x:fr.x+fr.colx,y:fr.y+fr.coly,h:fr.colh,w:fr.colw},{x:to.x+to.colx,y:to.y+to.coly,h:to.colh,w:to.colw},t); else return false;
+ 60 		},
+ 61 		
+ 62 		/**
+ 63 		* Checks for pixel collisions with an offset to the X and Y of the colidable using colx and coly.
+ 64 		* @param {Object} fr The object which collision is being tested for.
+ 65 		* @param {Object} to The object (or point) which collision is being tested against.
+ 66 		* @param {int} t The tollerance of the collision algorithm.
+ 67 		*/
+ 68 		pixelcollides:function(fr,to,t) { // Special collision. Counts also the Z
+ 69 			return gbox.pixelcollides(fr,{x:to.x+to.colx,y:to.y+to.coly,h:to.colh,w:to.colw},t);
+ 70 		},
+ 71 		
+ 72 		/**
+ 73 		* Initializes the game with the variables needed for topview and whatever else you feed in through data.
+ 74 		* @param {Object} th Passes in the object being initialized.
+ 75 		* @param {Object} data This is used to pass in everything that's being initiliized. If a value is not in Data then a default value is used instead. This can pass in values which do not have a default.
+ 76 		* <ul>
+ 77 		* <li>x{Integer}: x position of the object. (defaults to 0)</li>
+ 78 		* <li>y{Integer}: y position of the object. (defaults to 0)</li>
+ 79 		* <li>z{Integer}: z index of the object. (defaults to 0)</li>
+ 80 		* <li>accx{Integer}: The starting x velociyt of the object. (defaults to 0)</li>
+ 81 		* <li>accy{Integer}: The starting y velocity of the object. (defaults to 0)</li>
+ 82 		* <li>accz{Integer}: The starting z velocity of the object. (defaults to 0)</li>
+ 83 		* <li>frames{Object}: This is stores the animation frames for the objects in a map style structure. An empty map means the default image will display with no animation frames. (defaults to an empty map)</li>
+ 84 		* <li>shadow: (defaults to null)</li> //incomplete
+ 85 		* <li>maxacc{Integer}: (defaults to )4</li>
+ 86 		* <li>controlmaxacc{Integer}: (defaults to 4)</li>
+ 87 		* <li>responsive: (defaults to 0)</li>
+ 88 		* <li>weapon: (defaults to 0)</li>
+ 89 		* <li>camera{Boolean}: (defaults to true)</li>
+ 90 		* <li>flipv{Boolean}: Notes if the object is flipped vertically(defaults to false)</li>
+ 91 		* <li>fliph{Boolean}: Notes if the object is flipped horrizontally(defaults to false)</li>
+ 92 		* <li>facing{Integer}: Stores the facing of the object. This is set with pre-defined Integer values from within Toys.(defaults to toys.FACE_DOWN)</li>
+ 93 		* <ul>
+ 94 		* <li>FACE_UP:0,</li>
+ 95 		* <li>FACE_RIGHT:1,</li>
+ 96 		* <li>FACE_DOWN:2,</li>
+ 97 		* <li>FACE_LEFT:3,</li>
+ 98 		* </ul>
+ 99 		* <li>flipside{Boolean}: (defaults to true)</li>
+100 		* <li>haspushing{Boolean}: (defaults to false)</li>
+101 		* <li>frame: (default to 0)</li>
+102 		* <li>colh{Integer}: (defaults to gbox.getTiles(th.tileset).tilehh)</li>
+103 		* <li>colw{Integer}: (defaults to gbox.getTiles(th.tileset).tilew)</li>
+104 		* <li>colx{Integer}: (defaults to 0)</li>
+105 		* <li>staticspeed{Integer}: (defaults to 0)</li>
+106 		* <li>nodiagonals{Boolean}: (defaults to false)</li>
+107 		* <li>noreset: (defaults to false)</li>
+108 		* </ul>
+109 		*/
+110 		initialize:function(th,data) {
+111 			help.mergeWithModel(
+112 				th,
+113 				help.mergeWithModel(
+114 					data,
+115 					{
+116 						x:0, y:0,
+117 						z:0,
+118 						accx:0, accy:0, accz:0,
+119 						frames:{},
+120 						shadow:null,
+121 						maxacc:4, controlmaxacc:4,
+122 						responsive:0, // Responsiveness
+123 						weapon:0, // Weapon
+124 						camera:true,
+125 						flipv:false, fliph:false,
+126 						facing:toys.FACE_DOWN,
+127 						flipside:true,
+128 						haspushing:false,
+129 						frame:0,
+130 						colh:gbox.getTiles(th.tileset).tilehh,
+131 						colw:gbox.getTiles(th.tileset).tilew,
+132 						colx:0,
+133 						staticspeed:0,
+134 						nodiagonals:false,
+135 						noreset:false
+136 					}
+137 				)
+138 			);
+139 			if (th.coly==null) th.coly=gbox.getTiles(th.tileset).tileh-th.colh;
+140 			th.colhh=Math.floor(th.colh/2);
+141 			th.colhw=Math.floor(th.colw/2);
+142 			
+143 			toys.topview.spawn(th);
+144 		},
+145 		
+146 		/**
+147 		* Spawns a new object in the topview namespace. This also merges parameters in data into paramaters in th using help.copyModel.
+148     * This initializes some basic basic variables for the object and sets the Z index.
+149 		* @param {Object} th References 'this' which is the object that called the method (generally).
+150 		* <ul>
+151 		* <li>y {Integer}: (required) The object's y position.</li>
+152 		* <li>h {Integer}: (required) The object's height.</li>
+153 		* </ul>
+154 		* @param {Object} data This holds variables to be merged into th's stored info.
+155 		*/
+156 		spawn:function(th,data) {
+157 			th.xpushing=toys.PUSH_NONE; // user is moving side
+158 			th.vpushing=toys.PUSH_NONE; // user is moving side
+159 			th.zpushing=toys.PUSH_NONE; // user is moving side
+160 			th.counter=0; // self counter
+161 			th.hittimer=0;
+162 			th.killed=false;				
+163 			help.copyModel(th,data);
+164 			gbox.setZindex(th,th.y+th.h); // these object follows the z-index and uses ZINDEX_LAYER
+165 		},
+166 		
+167 		/**
+168 		* This sets and runs the control keys for the game. 
+169 		* @param {Object} th This is the object that is being controlled by the keys (assumed to be the player)
+170 		* <ul>
+171 		* <li>accx: the object's currect acceleration in the x direction</li>
+172 		* <li>accy: the object's currect acceleration in the y direction</li>
+173 		* <li>responsive: minimum movement speed</li>
+174 		* <li>staticspeed: turns off acceleration</li>
+175 		* <li>nodiagonals: boolean determining if the object can move along both axis at once.</li>
+176 		* <li>xpushing: a boolean that notes whether the object is pushing against something in the x direction.</li>
+177 		* <li>ypushing: a boolean that notes whether the object is pushing against something in the y direction.</li>
+178 		* <li>controlmaxacc: max acceleration for the object along an axis</li>
+179 		* <li>noreset: checks for the object being allowed to reset its pushing status (?)</li>
+180 		* </ul>
+181 		* @param {Object} keys These are the control keys being passed in for left, right, up, and down.
+182 		* //incomplete
+183 		*/
+184 		controlKeys:function(th,keys) {
+185 			var cancelx=false;
+186 			var cancely=false;
+187 			var idlex=false;
+188 			var idley=false;
+189 			
+190 			if (gbox.keyIsPressed(keys.left)||keys.pressleft) {
+191 				th.xpushing=toys.PUSH_LEFT;
+192 				th.facing=toys.FACE_LEFT;
+193 				if (th.accx>th.responsive) th.accx=th.responsive;
+194 				if (th.staticspeed) th.accx=-th.staticspeed; else th.accx=help.limit(th.accx-1,-th.controlmaxacc,th.controlmaxacc);
+195 				if (th.nodiagonals) { cancely=true; idley=true }
+196 			} else if (gbox.keyIsPressed(keys.right)||keys.pressright) {
+197 				th.xpushing=toys.PUSH_RIGHT;
+198 				th.facing=toys.FACE_RIGHT;
+199 				if (th.accx<-th.responsive) th.accx=-th.responsive;
+200 				if (th.staticspeed) th.accx=th.staticspeed; else th.accx=help.limit(th.accx+1,-th.controlmaxacc,th.controlmaxacc);
+201 				if (th.nodiagonals) { cancely=true; idley=true }
+202 			} else idlex=true;
+203 			
+204 			if (!cancely&&(gbox.keyIsPressed(keys.up)||keys.pressup)) {
+205 				th.ypushing=toys.PUSH_UP;
+206 				th.facing=toys.FACE_UP;
+207 				if (th.accy>th.responsive) th.accy=th.responsive;
+208 				if (th.staticspeed) th.accy=-th.staticspeed; else th.accy=help.limit(th.accy-1,-th.controlmaxacc,th.controlmaxacc);
+209 				if (th.nodiagonals) { cancelx=true; idlex=true; }
+210 			} else if (!cancely&&(gbox.keyIsPressed(keys.down)||keys.pressdown)) {
+211 				th.ypushing=toys.PUSH_DOWN;
+212 				th.facing=toys.FACE_DOWN;
+213 				if (th.accy<-th.responsive) th.accy=-th.responsive;
+214 				if (th.staticspeed) th.accy=th.staticspeed; else th.accy=help.limit(th.accy+1,-th.controlmaxacc,th.controlmaxacc);
+215 				if (th.nodiagonals) { cancelx=true; idlex=true; }
+216 			} else idley=true;
+217 			
+218 			
+219 			
+220 			 if (idlex) {
+221 				if (cancelx) th.accx=0;
+222 				if (cancelx||!th.noreset) th.xpushing=toys.PUSH_NONE;
+223 			}
+224 			if (idley) {
+225 				if (cancely) th.accy=0;				
+226 				if (cancely||!th.noreset) th.ypushing=toys.PUSH_NONE;
+227 			}
+228 		},
+229 		
+230 		/**
+231 		* Gets the next X position the object is going to move to.
+232 		* @param {Object} th The object being checked.
+233 		* <ul>
+234 		* <li>x: the current x position of the object</li>
+235 		* <li>accx: the object's currect acceleration in the x direction</li>
+236 		* <li>maxacc: the max accleration the object can have (if accx is greater than this then this value is used instead)</li>
+237 		* </ul>
+238 		*/
+239 		getNextX:function(th) { return th.x+help.limit(th.accx,-th.maxacc,th.maxacc); },
+240 		
+241 		/**
+242 		* Gets the next Y position the object is going to move to.
+243 		* @param {Object} th The object being checked.
+244 		* <ul>
+245 		* <li>y: the current y position of the object</li>
+246 		* <li>accy: the object's currect acceleration in the y direction</li>
+247 		* <li>maxacc: the max accleration the object can have (if accy is greater than this then this value is used instead)</li>
+248 		* </ul>
+249 		*/
+250 		getNextY:function(th) { return th.y+help.limit(th.accy,-th.maxacc,th.maxacc); },
+251 		
+252 		/**
+253 		* Gets the next Z position the object is going to move to.
+254 		* @param {Object} th The object being checked.
+255 		* <ul>
+256 		* <li>z: the current z position of the object</li>
+257 		* <li>accz: the object's currect acceleration in the z direction</li>
+258 		* <li>maxacc: the max accleration the object can have (if accz is greater than this then this value is used instead)</li>
+259 		* </ul>
+260 		*/
+261 		getNextZ:function(th) { return th.z+help.limit(th.accz,-th.maxacc,th.maxacc); },
+262 		
+263 		/**
+264 		* Sets the objects current location to its next location using the getNextX and getNextY methods.
+265 		* @param {Object} th The object being modified.
+266 		* <ul>
+267 		* <li>x: the current x position of the object</li>
+268 		* <li>y: the current y position of the object</li>
+269 		* <li>accx: the object's currect acceleration in the x direction</li>
+270 		* <li>accy: the object's currect acceleration in the y direction</li>
+271 		* <li>maxacc: the max accleration the object can have (if either acceleration is greater than this then this value is used instead for that acceleration)</li>
+272 		* </ul>
+273 		*/
+274 		applyForces:function(th) {
+275 			th.x=toys.topview.getNextX(th);
+276 			th.y=toys.topview.getNextY(th);
+277 		},
+278 		
+279 		/**
+280 		* This applies acceleration in the Z direction (not nessesarily gravity but whatever the next accerlation on the Z axis is)
+281 		* @param {Object} th The object being modified.
+282 		* <ul>
+283 		* <li>z: the current z position of the object</li>
+284 		* <li>accz: the object's currect acceleration in the z direction</li>
+285 		* <li>maxacc: the max accleration the object can have (if accz is greater than this then this value is used instead)</li>
+286 		* </ul>
+287 		*/
+288 		applyGravity:function(th) {
+289 			th.z=toys.topview.getNextZ(th);
+290 		},
+291 		
+292 		/**
+293 		* Degrades all accelerations on an object by one toward zero.
+294 		* @param {Object} th The object being modified.
+295 		* <ul>
+296 		* <li>xpushing: a boolean that notes whether the object is pushing against something in the x direction.</li>
+297 		* <li>ypushing: a boolean that notes whether the object is pushing against something in the y direction.</li>
+298 		* <li>accx: the object's currect acceleration in the x direction</li>
+299 		* <li>accy: the object's currect acceleration in the y direction</li>
+300 		* </ul>
+301 		*/
+302 		handleAccellerations:function(th) {
+303 			if (!th.xpushing) th.accx=help.goToZero(th.accx);
+304 			if (!th.ypushing) th.accy=help.goToZero(th.accy);
+305 			
+306 		},
+307 		
+308 		/**
+309 		* Increases the Z acceleration on the object by one.
+310 		* @param {Object} th The object being modified.
+311 		* <ul>
+312 		* <li>accz: the acceleration on the Z axis</li>
+313 		* </ul>
+314 		*/
+315 		handleGravity:function(th) {
+316 			th.accz++;
+317 		},
+318 		
+319 		/**
+320 		* This sets which frame the object is going to display based on an agregate word that describes predefined states.
+321 		* @param {Object} th The object whose frame is being set.
+322 		* <ul>
+323 		* <li>xpushing: a boolean that notes whether the object is pushing against something in the x direction.</li>
+324 		* <li>ypushing: a boolean that notes whether the object is pushing against something in the y direction.</li>
+325 		* <li>haspushing: a boolean that notes if the object changes when pushing against something.</li>
+326 		* <li>toucheddown: a boolean that notes if the object is touching something below it on the screen.</li>
+327 		* <li>touchedup: a boolean that notes if the object is touching something above it on the screen.<</li>
+328 		* <li>touchedright: a boolean that notes if the object is touching something right of it on the screen.<</li>
+329 		* <li>touchedleft: a boolean that notes if the object is touching something left of it on the screen.<</li>
+330 		* <li>flipside: </li>
+331 		* <li>fliph: </li>
+332 		* <li>facing: </li>
+333 		* <li>frames: </li>
+334 		* <li>frame: </li>
+335 		* <li>counter: </li>
+336 		* </ul>
+337 		* // incomplete
+338 		*/
+339 		setFrame:function(th) {
+340 			var pref="stand";
+341 			if (th.xpushing||th.ypushing) 
+342 				if (th.haspushing&&(th.toucheddown||th.touchedup||th.touchedleft||th.touchedright)) pref="pushing"; else pref="moving";
+343 			if (th.flipside)
+344 				th.fliph=(th.facing==toys.FACE_RIGHT);
+345 			th.frame=help.decideFrame(th.counter,th.frames[pref+toys.FACES[th.facing]]);
+346 		},
+347 		
+348 		/**
+349 		* Checks if the specified object is colliding with tiles in the map in an area defined by the object's colw and colh variables as well as the tolerance and approximation variables that are passed in through data. Only tiles in the map marked as solid are checked against. The alogrithm checks the 
+350 		* @param {Object} th The object that is being checked against the tilemap.
+351 		* @param {Object} map This is the asci map that the tile map is generated from.
+352 		* @param {Object} tilemap This is the array of tile objects that it itterated over checking for collisions.
+353 		* @param {Object} defaulttile The default tile to be returned if nothing can be found. Null can be used here.
+354 		* @param {Object} data Passes is extra dat to the function. Can be set as null.
+355 		* <ul>
+356 		* <li>tolerance{Integer}: This is subtracted from the collision space to get the maximum collision area for the object. This defaults to 6.</li>
+357 		* <li>approximation{Integer}: This is the amount that the checked values are incremented by until they reach the maximum value allowed. This defaults to 10.</li>
+358 		* </ul>
+359 		*/
+360 		tileCollision:function(th,map,tilemap,defaulttile,data) {
+361 			
+362 			th.touchedup=false;
+363 			th.toucheddown=false;
+364 			th.touchedleft=false;
+365 			th.touchedright=false;
+366 			
+367 			var tolerance=(data&&(data.tolerance!=null)?data.tolerance:6);
+368 			var approximation=(data&&(data.approximation!=null)?data.approximation:10);
+369 			var t=tolerance-approximation;
+370 			do {
+371 				t+=approximation;
+372 				if (t>th.colw-tolerance-1) t=th.colw-tolerance-1;
+373 				var bottom=help.getTileInMap(th.x+th.colx+t,th.y+th.coly+th.colh-1,map,defaulttile,tilemap);
+374 				var top=help.getTileInMap(th.x+th.colx+t,th.y+th.coly,map,defaulttile,tilemap);
+375 				if (map.tileIsSolid(th,top)) th.touchedup=true;
+376 				if (map.tileIsSolid(th,bottom)) th.toucheddown=true;	
+377 			} while (t!=th.colw-tolerance-1);
+378 			
+379 			t=tolerance-approximation;
+380 			do {
+381 				t+=approximation;
+382 				if (t>th.colh-tolerance-1) t=th.colh-tolerance-1;
+383 				var left=help.getTileInMap(th.x+th.colx,th.y+th.coly+t,map,defaulttile,tilemap);
+384 				var right=help.getTileInMap(th.x+th.colx+th.colw-1,th.y+th.coly+t,map,defaulttile,tilemap);
+385 				if (map.tileIsSolid(th,left)) th.touchedleft=true;
+386 				if (map.tileIsSolid(th,right)) th.touchedright=true;
+387 			} while (t!=th.colh-tolerance-1);
+388 			
+389 			if (th.touchedup) {
+390 				th.accy=0;
+391 				th.y=help.yPixelToTile(map,th.y+th.coly,1)-th.coly;				
+392 			}
+393 			if (th.toucheddown) {
+394 				th.accy=0;
+395 				th.y=help.yPixelToTile(map,th.y+th.coly+th.colh-1)-th.coly-th.colh;				
+396 			}
+397 			if (th.touchedleft) {
+398 				th.accx=0;
+399 				th.x=help.xPixelToTile(map,th.x+th.colx,1)-th.colx;				
+400 			}
+401 			if (th.touchedright) {
+402 				th.accx=0;
+403 				th.x=help.xPixelToTile(map,th.x+th.colx+th.colw-1)-th.colx-th.colw;				
+404 			}
+405 			
+406 		},
+407 		
+408 		/**
+409 		* @param {Object} th The object being checked for collisions.
+410 		* <ul>
+411 		* <li></li>
+412 		* <li></li>
+413 		* <li></li>
+414 		* <li></li>
+415 		* </ul>
+416 		* @param {Object} data This is used to pass in other data and arguments.
+417 		* <ul>
+418 		* <li>group {String}: (required) This is the group of objects being checked against.</li>
+419 		* <li></li>
+420 		* <li></li>
+421 		* <li></li>
+422 		* <li></li>
+423 		* </ul> //incomplete
+424 		*/
+425 		spritewallCollision:function(th,data) {
+426 			var wl;
+427 			for (var i in gbox._objects[data.group])
+428 				if ((!gbox._objects[data.group][i].initialize)&&toys.topview.collides(th,gbox._objects[data.group][i])) {
+429 					wl=gbox._objects[data.group][i];
+430 					if (toys.topview.pixelcollides({x:th.x+th.colx,y:th.y+th.coly+th.colhh},wl)) {
+431 						th.touchedleft=true;
+432 						th.accx=0;
+433 						th.x=wl.x+wl.colx+wl.colw-th.colx;
+434 					} else if (toys.topview.pixelcollides({x:th.x+th.colx+th.colw,y:th.y+th.coly+th.colhh},wl)) {
+435 						th.touchedright=true;
+436 						th.accx=0;
+437 						th.x=wl.x+wl.colx-th.colw-th.colx;
+438 					}
+439 					if (toys.topview.pixelcollides({x:th.x+th.colx+th.colhw,y:th.y+th.coly+th.colh},wl)) {
+440 						th.toucheddown=true;
+441 						th.accy=0;
+442 						th.y=wl.y+wl.coly-th.colh-th.coly;
+443 					} else if (toys.topview.pixelcollides({x:th.x+th.colx+th.colhw,y:th.y+th.coly},wl)) {
+444 						th.touchedup=true;
+445 						th.accy=0;
+446 						th.y=wl.y+wl.coly+wl.colh-th.coly;
+447 					}
+448 				}
+449 						
+450 		},
+451 		
+452 		/**
+453 		* This checks if the object's z index is 0 which means it has hit the floor. If this has occured it also plays an impact or bounce noise if one is passed in. Note: The area above the floor is in the negative z index space so a value of 1 for z will return that the object has collided with the floor and z will then be set to zero.
+454 		* @param {Object} th The object being checked for collision.
+455 		* <ul>
+456 		* <li>touchedfloor{boolean}: This value is not passed in but is created or set in the function. This contains the function's return value.</li>
+457 		* <li></li>
+458 		* <li></li>
+459 		* <li></li>
+460 		* </ul>
+461 		* @param {Object} data This is used to pass in extra parameters.
+462 		* <ul>
+463 		* <li></li>
+464 		* </ul>
+465 		*/
+466 		floorCollision:function(th,data) {
+467 			th.touchedfloor=false;
+468 			if (th.z>0) {
+469 				th.accz=(data==null?0:-Math.floor(th.accz/data.bounce));
+470 				if (data&&data.audiobounce&&th.accz) gbox.hitAudio(data.audiobounce);
+471 				th.z=0;
+472 				th.touchedfloor=true;
+473 			}			
+474 		},
+475 		
+476 		/**
+477 		* 
+478 		*/
+479 		adjustZindex:function(th) {
+480 			gbox.setZindex(th,th.y+th.h);
+481 		},
+482 		
+483 		/**
+484 		* 
+485 		*/
+486 		// Helper: returns the ahead pixel (i.e. destination use action)
+487 		getAheadPixel:function(th,data) {
+488 			switch (th.facing) {
+489 				case toys.FACE_RIGHT:{
+490 					return {x:th.x+th.colx+th.colw+data.distance,y:th.y+th.coly+th.colhh};
+491 					break;
+492 				}
+493 				case toys.FACE_LEFT:{
+494 					return {x:th.x+th.colx-data.distance,y:th.y+th.coly+th.colhh};
+495 					break;
+496 				}
+497 				case toys.FACE_UP:{
+498 					return {x:th.x+th.colx+th.colhw,y:th.y+th.coly-data.distance};
+499 					break;
+500 				}
+501 				case toys.FACE_DOWN:{
+502 					return {x:th.x+th.colx+th.colhw,y:th.y+th.coly+th.colh+data.distance};
+503 					break;
+504 				}
+505 			}
+506 		},
+507 		
+508 		/**
+509 		* 
+510 		*/
+511 		// Helper: trigger a method in colliding objects (i.e. "use action")
+512 		callInColliding:function(th,data) {
+513 			for (var i in gbox._objects[data.group])
+514 				if ((!gbox._objects[data.group][i].initialize)&&toys.topview.pixelcollides(data,gbox._objects[data.group][i]))
+515 					if (gbox._objects[data.group][i][data.call]) {
+516 						gbox._objects[data.group][i][data.call](th);
+517 						return i;
+518 					}
+519 			return false;
+520 		},
+521 		
+522 		/**
+523 		* 
+524 		*/
+525 		// Enemy methods
+526 		wander:function(th,map,tilemap,defaulttile,data) {
+527 			if ((!th.wandercounter)||(th.toucheddown||th.touchedup||th.touchedleft||th.touchedright)) {
+528 				th.wandercounter=help.random(data.minstep,data.steprange);
+529 				th.wanderdirection=help.random(0,4);
+530 			} else th.wandercounter--;
+531 			switch (th.wanderdirection) {
+532 				case toys.FACE_LEFT: {
+533 					th.xpushing=toys.PUSH_LEFT;
+534 					th.ypushing=toys.PUSH_NONE;
+535 					th.facing=toys.FACE_LEFT;
+536 					th.accx=-data.speed;
+537 					th.accy=0;
+538 					break;
+539 				}
+540 				case toys.FACE_RIGHT: {
+541 					th.xpushing=toys.PUSH_RIGHT;
+542 					th.ypushing=toys.PUSH_NONE;
+543 					th.facing=toys.FACE_RIGHT;
+544 					th.accx=data.speed;
+545 					th.accy=0;
+546 					break;
+547 				}
+548 				case toys.FACE_UP: {
+549 					th.ypushing=toys.PUSH_UP;
+550 					th.xpushing=toys.PUSH_NONE;
+551 					th.facing=toys.FACE_UP;
+552 					th.accy=-data.speed;
+553 					th.accx=0;
+554 					break;
+555 				}
+556 				case toys.FACE_DOWN: {
+557 					th.ypushing=toys.PUSH_DOWN;
+558 					th.xpushing=toys.PUSH_NONE;
+559 					th.facing=toys.FACE_DOWN;
+560 					th.accy=data.speed;
+561 					th.accx=0;
+562 					break;
+563 				}					
+564 			}
+565 		},
+566 		
+567 		/**
+568 		* 
+569 		*/
+570 		// generators (firebullet specific for topdown - more complex than SHMUP one)
+571 		fireBullet:function(gr,id,data) {
+572 
+573 			var ts=gbox.getTiles(data.tileset);
+574 			
+575 						
+576 			var obj=gbox.addObject(
+577 				help.mergeWithModel(
+578 					data,{
+579 						_bullet:true,
+580 						zindex:0,
+581 						fliph:false, flipv:false,
+582 						id:id,
+583 						group:gr,
+584 						cnt:0,
+585 						tileset:"",
+586 						frames:{},
+587 						acc:0,
+588 						angle:0,
+589 						camera:data.from.camera,
+590 						accx:(data.accx==null?Math.floor(trigo.translateX(0,data.angle,data.acc)):0),
+591 						accy:(data.accy==null?Math.floor(trigo.translateY(0,data.angle,data.acc)):0),
+592 						accz:0,
+593 						x:(data.sidex==toys.FACE_LEFT?data.from.x-ts.tilehw:(data.sidex==toys.FACE_RIGHT?data.from.x+data.from.w-ts.tilehw:data.from.x+data.from.hw-ts.tilehw))+(data.gapx?data.gapx:0),
+594 						y:(data.sidey==toys.FACE_UP?data.from.y-ts.tilehh:(data.sidey==toys.FACE_DOWN?data.from.y+data.from.h-ts.tilehh:data.from.y+data.from.hh-ts.tilehh))+(data.gapy?data.gapy:0),
+595 						z:(data.from.z==null?0:data.from.z),
+596 						collidegroup:"",
+597 						spark:toys.NOOP,
+598 						power:1,
+599 						lifetime:null,
+600 						tilemap:null,
+601 						defaulttile:0,
+602 						applyzgravity:false,
+603 						map:null,
+604 						defaulttile:0,
+605 						mapindex:"",
+606 						spritewalls:null,
+607 						colx:(data.fullhit?0:null),
+608 						coly:(data.fullhit?0:null),
+609 						colh:(data.fullhit?ts.tileh:null),
+610 						colw:(data.fullhit?ts.tilew:null),
+611 						duration:null,
+612 						onWallHit:function() {
+613 							this.spark(this);
+614 							gbox.trashObject(this);
+615 						},
+616 						bulletIsAlive:function() {
+617 							return gbox.objectIsVisible(this);
+618 						}
+619 					}
+620 				)
+621 			);
+622 			
+623 			obj.initialize=function() {
+624 				toys.topview.initialize(this);
+625 			};
+626 			
+627 			obj[(data.logicon==null?"first":data.logicon)]=function() {
+628 				this.cnt=(this.cnt+1)%10;
+629 				
+630 				if (this.applyzgravity) toys.topview.handleGravity(this); // z-gravity					
+631 				toys.topview.applyForces(this); // Apply forces
+632 				if (this.applyzgravity) toys.topview.applyGravity(this); // z-gravity
+633 				if (this.map!=null) toys.topview.tileCollision(this,this.map,this.mapindex,this.defaulttile); // tile collisions
+634 				if (this.spritewalls!=null) toys.topview.spritewallCollision(this,{group:this.spritewalls}); // walls collisions
+635 				if (this.applyzgravity) toys.topview.floorCollision(this); // Collision with the floor (for z-gravity)
+636 				toys.topview.adjustZindex(this);
+637 				if (this.duration!=null) {
+638 					this.duration--;
+639 					if (this.duration==0) gbox.trashObject(this);
+640 				}
+641 				if (!this.bulletIsAlive()) gbox.trashObject(this);
+642 				else if (this.toucheddown||this.touchedup||this.touchedleft||this.touchedright) this.onWallHit();
+643 				else if (this.collidegroup!=null)
+644 					for (var i in gbox._objects[this.collidegroup])
+645 						if ((!gbox._objects[this.collidegroup][i].initialize)&&toys.topview.collides(this,gbox._objects[this.collidegroup][i],gbox._objects[this.collidegroup][i].tolerance)) {
+646 							if (gbox._objects[this.collidegroup][i]["hitByBullet"]!=null)
+647 								if (!gbox._objects[this.collidegroup][i].hitByBullet(this)) {
+648 									this.spark(this);
+649 									gbox.trashObject(this);
+650 								}
+651 						}
+652 			}
+653 			
+654 			obj[(data.bliton==null?"blit":data.bliton)]=function() {
+655 				if (!gbox.objectIsTrash(this))
+656 					gbox.blitTile(gbox.getBufferContext(),{tileset:this.tileset,tile:help.decideFrame(this.cnt,this.frames),dx:this.x,dy:this.y+this.z,camera:this.camera,fliph:this.fliph,flipv:this.flipv});
+657 			}
+658 			
+659 			gbox.setZindex(obj,obj.y+obj.h);
+660 			
+661 			return obj;
+662 		
+663 		},
+664 		
+665 		/**
+666 		* 
+667 		*/
+668 		makedoor:function(gr,id,map,data) {
+669 
+670 			var mts=gbox.getTiles(map.tileset);
+671 			var ts=gbox.getTiles(data.tileset);
+672 						
+673 			var obj=gbox.addObject(
+674 				help.mergeWithModel(
+675 					data,{
+676 						zindex:0,
+677 						fliph:false, flipv:false,
+678 						id:id,
+679 						group:gr,
+680 						cnt:0,
+681 						tileset:"",
+682 						frames:{},
+683 						camera:true,
+684 						x:data.tilex*mts.tilew,
+685 						y:data.tiley*mts.tileh,
+686 						z:0,
+687 						tilemap:null,
+688 						defaulttile:0,
+689 						map:map,
+690 						colx:(data.fullhit?0:null),
+691 						coly:(data.fullhit?0:null),
+692 						colh:(data.fullhit?ts.tileh:null),
+693 						colw:(data.fullhit?ts.tilew:null),
+694 						opening:false,
+695 						doorheight:ts.tileh,
+696 						opencounter:0,
+697 						opening:false,
+698 						closing:false,
+699 						audiobefore:null,
+700 						audioafter:null,
+701 						doOpen:function() {
+702 							this.opening=true;
+703 						},
+704 						whenClosed:toys.NOOP,
+705 						whenOpened:toys.NOOP,
+706 						whileMoving:toys.NOOP,
+707 						hitByBullet:function(by) {
+708 						
+709 						}
+710 					}
+711 				)
+712 			);
+713 			
+714 			// Closing animation
+715 			if (obj.closing) obj.opencounter=obj.doorheight;
+716 			
+717 			obj.initialize=function() {
+718 				this.ismoving=false;
+719 				toys.topview.initialize(this);
+720 			};
+721 			
+722 			obj[(data.logicon==null?"first":data.logicon)]=function() {
+723 				if (this.closing) {
+724 					if (!this.ismoving) {
+725 						if (this.audiobefore) gbox.hitAudio(this.audiobefore);
+726 						this.ismoving=true;
+727 					}
+728 					this.whileMoving();
+729 					this.opencounter--;
+730 					if (this.opencounter<0) {
+731 						if (this.audioafter) gbox.hitAudio(this.audioafter);
+732 						this.ismoving=false;
+733 						this.opencounter=0;
+734 						this.closing=false;
+735 						this.whenClosed();
+736 					}
+737 				}
+738 				if (this.opening) {
+739 					if (!this.ismoving) {
+740 						if (this.audiobefore) gbox.hitAudio(this.audiobefore);
+741 						this.ismoving=true;
+742 					}
+743 					this.whileMoving();
+744 					this.opencounter++;
+745 					if (this.opencounter>=this.doorheight) {
+746 						if (this.audioafter) gbox.hitAudio(this.audioafter);
+747 						this.ismoving=false;
+748 						if (!this.whenOpened()) gbox.trashObject(this);
+749 					}
+750 				}
+751 			}
+752 			
+753 			obj[(data.bliton==null?"blit":data.bliton)]=function() {
+754 				if (!gbox.objectIsTrash(this))
+755 					gbox.blitTile(gbox.getBufferContext(),{tileset:this.tileset,tile:help.decideFrame(this.cnt,this.frames),dx:this.x,dy:this.y+this.z+this.opencounter,h:this.h-this.opencounter,camera:this.camera,fliph:this.fliph,flipv:this.flipv});
+756 			}
+757 			
+758 			gbox.setZindex(obj,obj.y+obj.h);
+759 			
+760 			return obj;
+761 		},
+762 		// Set the object speed making sure that the X and Y coords are multiple of the speed. Useful on maze-based games.
+763 		setStaticSpeed:function(th,speed) {
+764 			th.staticspeed=speed;
+765 			th.x=Math.round(th.x/speed)*speed;
+766 			th.y=Math.round(th.y/speed)*speed;
+767 		}
+768 	},
+769 	
+770 	
+771 	/**
+772 	* @namespace shmup The libraries for a 2D top-down Shmup game.
+773 	*/
+774 	// Shoot'em up specifics
+775 	shmup:{
+776 		
+777 		/**
+778 		* 
+779 		*/
+780 		initialize:function(th,data) {
+781 			help.mergeWithModel(
+782 				th,
+783 				help.mergeWithModel(
+784 					data,
+785 					{
+786 						x:0, y:0,
+787 						accx:0, accy:0,
+788 						frames:{},
+789 						maxacc:5, controlmaxacc:5,
+790 						responsive:0, // Responsiveness
+791 						bounds:{x:0,y:0,w:gbox.getScreenW(),h:gbox.getScreenH()}, // Bounds box (ship cannot exit from there)
+792 						weapon:0, // Weapon
+793 						hittime:5,
+794 						camera:false,
+795 						flipv:false, fliph:false,
+796 						health:1,
+797 						tolerance:4
+798 					}
+799 				)
+800 			);
+801 			toys.shmup.spawn(th);
+802 		},
+803 		
+804 		/**
+805 		* 
+806 		*/
+807 		spawn:function(th,data) {
+808 			th.xpushing=toys.PUSH_NONE; // user is moving side
+809 			th.vpushing=toys.PUSH_NONE; // user is moving side
+810 			th.counter=0; // self counter
+811 			th.hittimer=0;
+812 			th.killed=false;
+813 			help.copyModel(th,data);
+814 		},
+815 		
+816 		/**
+817 		* 
+818 		*/
+819 		getNextX:function(th) { return th.x+help.limit(th.accx,-th.maxacc,th.maxacc); },
+820 		
+821 		/**
+822 		* 
+823 		*/
+824 		getNextY:function(th) { return th.y+help.limit(th.accy,-th.maxacc,th.maxacc); },
+825 		
+826 		/**
+827 		* 
+828 		*/
+829 		controlKeys:function(th,keys) {
+830 			
+831 			if (gbox.keyIsPressed(keys.left)) {
+832 				th.xpushing=toys.PUSH_LEFT;
+833 				if (th.accx>th.responsive) th.accx=th.responsive;
+834 				th.accx=help.limit(th.accx-1,-th.controlmaxacc,th.controlmaxacc);
+835 			} else if (gbox.keyIsPressed(keys.right)) {
+836 				th.xpushing=toys.PUSH_RIGHT;
+837 				if (th.accx<-th.responsive) th.accx=-th.responsive;
+838 				th.accx=help.limit(th.accx+1,-th.controlmaxacc,th.controlmaxacc);
+839 			} else th.xpushing=toys.PUSH_NONE;
+840 			if (gbox.keyIsPressed(keys.up)) {
+841 				th.ypushing=toys.PUSH_UP;
+842 				if (th.accy>th.responsive) th.accy=th.responsive;
+843 				th.accy=help.limit(th.accy-1,-th.controlmaxacc,th.controlmaxacc);
+844 			} else if (gbox.keyIsPressed(keys.down)) {
+845 				th.ypushing=toys.PUSH_DOWN;
+846 				if (th.accy<-th.responsive) th.accy=-th.responsive;
+847 				th.accy=help.limit(th.accy+1,-th.controlmaxacc,th.controlmaxacc);
+848 			} else th.ypushing=toys.PUSH_NONE;
+849 		},
+850 		
+851 		/**
+852 		* 
+853 		*/
+854 		applyForces:function(th) {
+855 			th.x=toys.shmup.getNextX(th);
+856 			th.y=toys.shmup.getNextY(th);
+857 		},
+858 		
+859 		/**
+860 		* 
+861 		*/
+862 		handleAccellerations:function(th) {
+863 			if (!th.xpushing) th.accx=help.goToZero(th.accx);
+864 			if (!th.ypushing) th.accy=help.goToZero(th.accy);
+865 		},
+866 		
+867 		/**
+868 		* 
+869 		*/
+870 		keepInBounds:function(th) {
+871 			if (th.x<th.bounds.x) {
+872 				th.x=th.bounds.x;
+873 				th.accx=0;
+874 			} else if (th.x+th.w>th.bounds.x+th.bounds.w) {
+875 				th.x=th.bounds.x+th.bounds.w-th.w;
+876 				th.accx=0;				
+877 			}
+878 			if (th.y<th.bounds.y) {
+879 				th.y=th.bounds.y;
+880 				th.accy=0;
+881 			} else if (th.y+th.h>th.bounds.y+th.bounds.h) {
+882 				th.y=th.bounds.y+th.bounds.h-th.h;
+883 				th.accy=0;				
+884 			}
+885 		},
+886 		
+887 		/**
+888 		* 
+889 		*/
+890 		setFrame:function(th) {
+891 			if (th.hittimer) th.hittimer--;
+892 			th.frame=help.decideFrame(th.counter,(th.hittimer?th.frames.hit:th.frames.still));
+893 		},
+894 		
+895 		/**
+896 		* 
+897 		*/
+898 		fireBullet:function(gr,id,data) {
+899 		
+900 			var ts=gbox.getTiles(data.tileset);
+901 			
+902 			var obj=gbox.addObject(
+903 				help.mergeWithModel(
+904 					data,{
+905 						_bullet:true,
+906 						fliph:false, flipv:false,
+907 						id:id,
+908 						group:gr,
+909 						cnt:0,
+910 						tileset:"",
+911 						frames:{},
+912 						acc:0,
+913 						angle:0,
+914 						camera:false,
+915 						accx:(data.accx==null?Math.floor(trigo.translateX(0,data.angle,data.acc)):0),
+916 						accy:(data.accy==null?Math.floor(trigo.translateY(0,data.angle,data.acc)):0),
+917 						x:data.from.x+data.from.hw-ts.tilehw+(data.gapx?data.gapx:0),
+918 						y:(data.upper?data.from.y-ts.tilehh+(data.gapy?data.gapy:0):data.from.y+data.from.h-ts.tilehh-(data.gapy?data.gapy:0)),
+919 						collidegroup:"",
+920 						spark:toys.NOOP,
+921 						power:1
+922 					}
+923 				)
+924 			);
+925 			
+926 			obj[(data.logicon==null?"first":data.logicon)]=function() {
+927 				this.x+=this.accx;
+928 				this.y+=this.accy;
+929 				this.cnt=(this.cnt+1)%10;
+930 				if (!gbox.objectIsVisible(this)) gbox.trashObject(this);
+931 				else if (this.collidegroup!=null)
+932 					for (var i in gbox._objects[this.collidegroup])
+933 						if ((!gbox._objects[this.collidegroup][i].initialize)&&gbox.collides(this,gbox._objects[this.collidegroup][i],gbox._objects[this.collidegroup][i].tolerance)) {
+934 							if (gbox._objects[this.collidegroup][i]["hitByBullet"]!=null)
+935 								if (!gbox._objects[this.collidegroup][i].hitByBullet(this)) {
+936 									this.spark(this);
+937 									gbox.trashObject(this);
+938 								}
+939 						}
+940 			}
+941 			
+942 			obj[(data.bliton==null?"blit":data.bliton)]=function() {
+943 				gbox.blitTile(gbox.getBufferContext(),{tileset:this.tileset,tile:help.decideFrame(this.cnt,this.frames),dx:this.x,dy:this.y,camera:this.camera,fliph:this.side,flipv:this.flipv});
+944 			}
+945 			
+946 			return obj;
+947 		
+948 		},
+949 		
+950 		/**
+951 		* 
+952 		*/
+953 		hitByBullet:function(th,by) {
+954 			if (by.power) {
+955 				th.health-=by.power;
+956 				if (th.health<=0) th.kill(by); else  th.hittimer=th.hittime;
+957 			}
+958 		},
+959 		
+960 		/**
+961 		* 
+962 		*/
+963 		generateEnemy:function(gr,id,data,model) {
+964 			help.mergeWithModel(data,model);
+965 			var obj=gbox.addObject(
+966 				help.mergeWithModel(
+967 					data,{
+968 						id:id,
+969 						group:gr,
+970 						cnt:0,
+971 						tileset:"",
+972 						frames:{},
+973 						acc:0,
+974 						angle:0,
+975 						camera:false,
+976 						fliph:false,
+977 						flipv:false,
+978 						accx:(data.accx==null?Math.floor(trigo.translateX(0,data.angle,data.acc)):0),
+979 						accy:(data.accy==null?Math.floor(trigo.translateY(0,data.angle,data.acc)):0),
+980 						x:data.x,
+981 						y:data.y,
+982 						// -- spec
+983 						animationset:"still",
+984 						defaultanimationset:"still",
+985 						hitanimationset:"still",
+986 						hittime:5,
+987 						script:toys.NOOP,
+988 						handler:toys.NOOP,
+989 						scriptline:(data.scriptline==null?-1:data.scriptline-1),
+990 						newline:true,
+991 						waitframes:0,
+992 						doframes:0,
+993 						mode:0,
+994 						line:{},
+995 						dohandler:null,
+996 						ended:false,
+997 						health:1,
+998 						hittimer:0,
+999 						kill:toys.NOOP,
+1000 						tolerance:0,
+1001 						initialize:null,
+1002 						invulnerable:false,
+1003 						hitAnimation:function(time) {
+1004 							this.hittimer=(time==null?this.hittime:time);
+1005 							this.animationset=this.hitanimationset;
+1006 						},
+1007 						goTo:function(nl) { // Jump to a line
+1008 							this.waitframes=0;
+1009 							this.doframes=0;
+1010 							this.line={};
+1011 							this.scriptline=nl-1;
+1012 						},
+1013 						hitByBullet:function(by) {
+1014 							if (!this.invulnerable&&by.power) {
+1015 								this.health-=by.power;
+1016 								if (this.health<=0) this.kill(this,by); else this.hitAnimation();
+1017 							}
+1018 						},
+1019 					}
+1020 				)
+1021 			);
+1022 			
+1023 			
+1024 			obj[(data.logicon==null?"first":data.logicon)]=function() {
+1025 				if (this.initialize!=null)  {
+1026 					this.initialize(this);
+1027 					this.initialize=null;
+1028 				}
+1029 				if (!this.ended) {
+1030 					if (!this.waitframes&&!this.doframes&&((this.line.waitfor==null)||this.line.waitfor(this))) {
+1031 						this.scriptline++;
+1032 						this.everycnt=-1;
+1033 						if (this.script[this.scriptline]==null)
+1034 							this.ended=true;
+1035 						else {
+1036 							if (this.script[this.scriptline].goto!=null) this.scriptline=this.script[this.scriptline].goto;
+1037 							this.line=this.script[this.scriptline];
+1038 							if (this.line.afterframes!=null)
+1039 								this.waitframes=this.line.afterframes;
+1040 							if (this.line.forframes!=null)
+1041 								this.doframes=this.line.forframes;
+1042 							else
+1043 								this.doframes=1;
+1044 							if (this.line.cleardo)
+1045 								this.dohandler=null;
+1046 							else if (this.line.doit!=null) {
+1047 								this.dohandler={
+1048 									actiontimes:0,
+1049 									timer:(this.line.doit.every=="keep"?this.dohandler.every:this.line.doit.every),
+1050 									every:(this.line.doit.every=="keep"?this.dohandler.every:this.line.doit.every),
+1051 									once:(this.line.doit.once=="keep"?this.dohandler.once:this.line.doit.once),
+1052 									action:(this.line.doit.action=="keep"?this.dohandler.action:this.line.doit.action),
+1053 									render:(this.line.doit.render=="keep"?this.dohandler.render:this.line.doit.render)
+1054 								}
+1055 							}
+1056 								
+1057 						}
+1058 					}
+1059 					if (!this.waitframes&&this.doframes&&!this.ended) {
+1060 						this.doframes--;
+1061 						if (this.line.setinvulnerable!=null) this.invulnerable=this.line.setinvulnerable;
+1062 						if (this.line.setx!=null) this.x=this.line.setx;
+1063 						if (this.line.sety!=null) this.y=this.line.sety;
+1064 						if (this.line.addx!=null) this.x+=this.line.addx;
+1065 						if (this.line.addy!=null) this.y+=this.line.addy;
+1066 						if (this.line.setaccx!=null) this.accx=this.line.setaccx;
+1067 						if (this.line.setaccy!=null) this.accy=this.line.setaccy;
+1068 						if (this.line.setacc!=null) {
+1069 							this.acc=this.line.setacc;
+1070 							this.accx=Math.floor(trigo.translateX(0,this.angle,this.acc));
+1071 							this.accy=Math.floor(trigo.translateY(0,this.angle,this.acc));
+1072 						}
+1073 						if (this.line.addaccx!=null) this.accx+=this.line.addaccx;
+1074 						if (this.line.addaccy!=null) this.accy+=this.line.addaccy;
+1075 						if (this.line.addacc!=null) {
+1076 							this.acc+=this.line.addacc;
+1077 							this.accx=Math.floor(trigo.translateX(0,this.angle,this.acc));
+1078 							this.accy=Math.floor(trigo.translateY(0,this.angle,this.acc));
+1079 						}
+1080 						
+1081 						if (this.line.setangle!=null) {
+1082 							this.angle=this.line.setangle;
+1083 							this.accx=Math.floor(trigo.translateX(0,this.angle,this.acc));
+1084 							this.accy=Math.floor(trigo.translateY(0,this.angle,this.acc));
+1085 						}
+1086 						if (this.line.addangle!=null) {
+1087 							this.angle+=this.line.addangle;
+1088 							this.accx=Math.floor(trigo.translateX(0,this.angle,this.acc));
+1089 							this.accy=Math.floor(trigo.translateY(0,this.angle,this.acc));
+1090 						}
+1091 						if (this.line.everyframe) this.waitframes=this.line.everyframe;
+1092 							
+1093 					}
+1094 					if (this.waitframes>0) this.waitframes--;
+1095 				}
+1096 				if (this.dohandler&&(this.dohandler.action!=null)) {
+1097 					if (this.dohandler.timer==this.dohandler.every) {
+1098 						this.dohandler.action(this,this.dohandler.actiontimes);
+1099 						this.dohandler.timer=0;
+1100 						this.dohandler.actiontimes++;
+1101 					} else if (!this.dohandler.once) this.dohandler.timer++;
+1102 				}
+1103 				if (this.handler!=null) this.handler(this);
+1104 				
+1105 				if (this.hittimer) {
+1106 					this.hittimer--;
+1107 					if (!this.hittimer) this.animationset=this.defaultanimationset;
+1108 				}
+1109 				
+1110 				this.x+=this.accx;
+1111 				this.y+=this.accy;
+1112 				this.cnt=(this.cnt+1)%10;
+1113 				
+1114 			}
+1115 
+1116 			obj[(data.bliton==null?"blit":data.bliton)]=function() {
+1117 				gbox.blitTile(gbox.getBufferContext(),{tileset:this.tileset,tile:help.decideFrame(this.cnt,this.frames[this.animationset]),dx:this.x,dy:this.y,camera:this.camera,fliph:this.side,flipv:this.flipv});
+1118 				if (this.dohandler&&(this.dohandler.render!=null)) this.dohandler.render(this);
+1119 			}
+1120 			
+1121 			return obj;
+1122 
+1123 		},
+1124 		
+1125 		/**
+1126 		* 
+1127 		*/
+1128 		generateScroller:function(gr,id,data) {
+1129 			var obj=gbox.addObject(
+1130 				help.mergeWithModel(
+1131 					help.cloneObject(data),{
+1132 						id:id, group:gr,
+1133 						y:0, x:0,
+1134 						stage:{},
+1135 						speed:0,
+1136 						stop:null, // Remember to set the last stop ever! or the last loop!
+1137 						block:-1,
+1138 						bly:0,
+1139 						lblock:-1,
+1140 						lbly:0,
+1141 						lget:0,
+1142 						tbly:0,
+1143 						trb:0,
+1144 						maxwidth:0,
+1145 						loopstart:null, loopend:null, looprounds:0,
+1146 						panspeed:1, panstimer:0, destspeed:0,
+1147 						
+1148 						setLoop:function(st,en) {
+1149 							this.loopstart=st;
+1150 							this.loopend=en;
+1151 							this.lget=1;
+1152 							this.looprounds=1;
+1153 						},
+1154 						
+1155 						quitLoop:function() {
+1156 							this.setLoop(null,null);
+1157 							this.looprounds=0;
+1158 						},
+1159 					
+1160 						setSpeed:function(s) {
+1161 							this.speed=s;
+1162 							this.destspeed=s;
+1163 						},
+1164 						
+1165 						panToSpeed:function(s,pans) {
+1166 							this.destspeed=s;
+1167 							this.panspeed=pans;
+1168 						},
+1169 						
+1170 						quitStop:function() {
+1171 							this.stop=null;
+1172 						},
+1173 						
+1174 						setStop:function(s) {
+1175 							this.stop=s;
+1176 						},
+1177 						
+1178 						setX:function(x) {
+1179 							if (x<0) this.x=0; else
+1180 							if (x+gbox.getScreenW()>this.maxwidth) this.x=this.maxwidth-gbox.getScreenW();
+1181 							else this.x=x;
+1182 						}
+1183 						
+1184 					}
+1185 				)
+1186 			);
+1187 			
+1188 			obj[(data.logicon==null?"first":data.logicon)]=function() {
+1189 				if ((this.stop==null)||(this.y<this.stop)) {
+1190 					if (this.speed!=this.destspeed) {
+1191 						if (this.panstimer) {
+1192 							this.panstimer--;
+1193 						} else {
+1194 							if (this.speed<this.destspeed) this.speed++; else
+1195 							if (this.speed>this.destspeed) this.speed--;
+1196 							this.panstimer=this.panspeed;
+1197 						}
+1198 					}
+1199 					this.y+=this.speed;
+1200 					if ((this.stop!=null)&&(this.y>=this.stop)) this.y=this.stop;
+1201 					if ((this.loopend!=null)&&(this.y>this.loopend)) {
+1202 						this.y=this.loopstart+(this.y-this.loopend);
+1203 						this.looprounds++;
+1204 						if (this.lget==1) {
+1205 							this.block=0;
+1206 							this.bly=0;
+1207 							this.lget=2;
+1208 						} else {
+1209 							this.block=this.lblock;
+1210 							this.bly=this.lbly;
+1211 						}
+1212 						
+1213 					}
+1214 				}
+1215 						
+1216 				// Cerca il blocco da mostrare
+1217 				this.trb=this.block;
+1218 				this.tbly=this.bly;
+1219 				do {
+1220 					this.trb++;
+1221 					this.tbly+=gbox.getImage(this.stage[this.trb].image).height;	
+1222 				} while (this.tbly<this.y);
+1223 				
+1224 				this.block=this.trb-1;
+1225 				this.bly=this.tbly-gbox.getImage(this.stage[this.trb].image).height;
+1226 				
+1227 						
+1228 				if (this.lget==2) {
+1229 					this.lblock=this.block;
+1230 					this.lbly=this.bly;
+1231 					this.lget=3;
+1232 				}
+1233 				
+1234 			}
+1235 				
+1236 			obj[(data.bliton==null?"blit":data.bliton)]=function() {
+1237 				var dy=this.tbly-this.y;
+1238 				var done=false;
+1239 				do {
+1240 					if (dy>gbox.getScreenH()) done=true;
+1241 					gbox.blitAll(gbox.getBufferContext(),gbox.getImage(this.stage[this.trb].image),{dx:-this.x,dy:gbox.getScreenH()-dy});
+1242 					this.trb++;
+1243 					dy+=gbox.getImage(this.stage[this.trb].image).height;
+1244 				} while (!done);
+1245 			}
+1246 			
+1247 			return obj;
+1248 		}
+1249 	},
+1250 		
+1251 	/**
+1252 	* @namespace platformer The libraries for generating a 2D platformer game.
+1253 	*/
+1254 	platformer:{
+1255 		
+1256 		/**
+1257 		* 
+1258 		*/
+1259 		initialize:function(th,data) {
+1260 			help.mergeWithModel(
+1261 				th,
+1262 				help.mergeWithModel(
+1263 					data,
+1264 					{
+1265 						maxaccx:5, maxaccy:10,
+1266 						jumpsize:6, jumpaccy:6,
+1267 						accx:0, accy:0,
+1268 						x:0, y:0,
+1269 						frames:{},
+1270 						camera:true,
+1271 						flipv:false,
+1272 						side:false
+1273 					}
+1274 				)
+1275 			);
+1276 			toys.platformer.spawn(th);
+1277 		},
+1278 		
+1279 		/**
+1280 		* 
+1281 		*/
+1282 		spawn:function(th,data) {
+1283 			th.curjsize=0; // current jump size
+1284 			th.counter=0; // self counter
+1285 			th.touchedfloor=false; // touched floor
+1286 			th.touchedceil=false;
+1287 			th.touchedleftwall=false;
+1288 			th.touchedrightwall=false;
+1289 			th.pushing=toys.PUSH_NONE; // user is moving side
+1290 			th.killed=false;
+1291 			help.copyModel(th,data);
+1292 		},
+1293 		
+1294 		/**
+1295 		* 
+1296 		*/
+1297 		getNextX:function(th) { return th.x+th.accx; },
+1298 		
+1299 		/**
+1300 		* 
+1301 		*/
+1302 		getNextY:function(th) { return th.y+help.limit(th.accy,-th.maxaccy,th.maxaccy); },
+1303 		
+1304 		/**
+1305 		* 
+1306 		*/
+1307 		applyGravity:function(th) {
+1308 			th.x=toys.platformer.getNextX(th);
+1309 			th.y=toys.platformer.getNextY(th);
+1310 		},	
+1311 		
+1312 		/**
+1313 		* 
+1314 		*/
+1315 		horizontalKeys:function(th,keys) {
+1316 			if (gbox.keyIsPressed(keys.left)) {
+1317 				th.pushing=toys.PUSH_LEFT;
+1318 				th.accx=help.limit(th.accx-1,-th.maxaccx,th.maxaccx);
+1319 			} else if (gbox.keyIsPressed(keys.right)) {
+1320 				th.pushing=toys.PUSH_RIGHT;
+1321 				th.accx=help.limit(th.accx+1,-th.maxaccx,th.maxaccx);
+1322 			} else th.pushing=toys.PUSH_NONE;
+1323 		},
+1324 		
+1325 		/**
+1326 		* 
+1327 		*/
+1328 		verticalTileCollision:function(th,map,tilemap) {
+1329 			var bottom=help.getTileInMap(th.x+(th.w/2),th.y+th.h,map,0,tilemap);
+1330 			var top=help.getTileInMap(th.x+(th.w/2),th.y,map,0,tilemap);
+1331 			th.touchedfloor=false;
+1332 			th.touchedceil=false;
+1333 	
+1334 			if (map.tileIsSolidCeil(th,top)) {
+1335 				th.accy=0;
+1336 				th.y=help.yPixelToTile(map,th.y,1);
+1337 				th.touchedceil=true;
+1338 			}
+1339 			if (map.tileIsSolidFloor(th,bottom)) {
+1340 				th.accy=0;
+1341 				th.y=help.yPixelToTile(map,th.y+th.h)-th.h;
+1342 				th.touchedfloor=true;
+1343 			}
+1344 		},
+1345 		
+1346 		/**
+1347 		* 
+1348 		*/
+1349 		horizontalTileCollision:function(th,map,tilemap) {
+1350 			var left=0;
+1351 			var right=0;
+1352 			var t=0;
+1353 			
+1354 			th.touchedleftwall=false;
+1355 			th.touchedrightwall=false;
+1356 			
+1357 			while (t<th.h) {
+1358 				left=help.getTileInMap(th.x,th.y+t,map,0,tilemap);
+1359 				right=help.getTileInMap(th.x+th.w-1,th.y+t,map,0,tilemap);
+1360 					
+1361 				if ((th.accx<0)&&map.tileIsSolidFloor(th,left)) {
+1362 					th.accx=0;
+1363 					th.x=help.xPixelToTile(map,th.x-1,1);
+1364 					th.touchedleftwall=true;
+1365 				} 
+1366 				if ((th.accx>0)&&map.tileIsSolidFloor(th,right)) {
+1367 					th.accx=0;
+1368 					th.x=help.xPixelToTile(map,th.x+th.w)-th.w;
+1369 					th.touchedrightwall=true;
+1370 				}
+1371 				t+=gbox.getTiles(map.tileset).tileh;
+1372 			}
+1373 		},
+1374 		
+1375 		/**
+1376 		* Checks if the passed object is touching the floor and can therefore jump at present.
+1377 		* @param th This is the object being checked for jump ability at the time of calling.
+1378 		*/
+1379 		canJump:function(th) {
+1380 			return th.touchedfloor;
+1381 		},
+1382 		
+1383 		/**
+1384 		* 
+1385 		*/
+1386 		jumpKeys:function(th,key) {
+1387 			if ((toys.platformer.canJump(th)||(key.doublejump&&(th.accy>=0)))&&gbox.keyIsHit(key.jump)&&(th.curjsize==0)) {
+1388 				if (key.audiojump) gbox.hitAudio(key.audiojump);
+1389 				th.accy=-th.jumpaccy;
+1390 				th.curjsize=th.jumpsize;
+1391 				return true;
+1392 			} else if (th.curjsize&&gbox.keyIsHold(key.jump)) { // Jump modulation
+1393 				th.accy--;
+1394 				th.curjsize--;
+1395 			} else
+1396 				th.curjsize=0;
+1397 			return false;
+1398 		},
+1399 		
+1400 		/**
+1401 		* 
+1402 		*/	
+1403 		bounce:function(th,data) {
+1404 			th.curjsize=0;
+1405 			th.accy=-data.jumpsize;
+1406 		},
+1407 		
+1408 		/**
+1409 		* 
+1410 		*/
+1411 		handleAccellerations:function(th) {
+1412 			// Gravity
+1413 			if (!th.touchedfloor) th.accy++;
+1414 			// Attrito
+1415 			if (th.pushing==toys.PUSH_NONE) if (th.accx) th.accx=help.goToZero(th.accx);
+1416 		},
+1417 		
+1418 		/**
+1419 		* 
+1420 		*/
+1421 		setSide:function(th) {
+1422 			if (th.accx) th.side=th.accx>0;
+1423 		},
+1424 		
+1425 		/**
+1426 		* 
+1427 		*/
+1428 		setFrame:function(th) {
+1429 			if (th.touchedfloor)
+1430 				if (th.pushing!=toys.PUSH_NONE)
+1431 					th.frame=help.decideFrame(th.counter,th.frames.walking);
+1432 				else
+1433 					th.frame=help.decideFrame(th.counter,th.frames.still);
+1434 			else if (th.accy>0)
+1435 				th.frame=help.decideFrame(th.counter,th.frames.falling);
+1436 			else
+1437 				th.frame=help.decideFrame(th.counter,th.frames.jumping);
+1438 		},
+1439 		
+1440 		/**
+1441 		* 
+1442 		*/
+1443 		auto:{
+1444 			// Moves on a platform. It tries to do not fall down, if specified.
+1445 			// Args: (object,{moveWhileFalling:<moves while not touching the floor>,speed:<movement speed>})
+1446 			// Outs: the frame
+1447 			goomba:function(th,data) {
+1448 				if (data.moveWhileFalling||th.touchedfloor) {
+1449 					if (th.side) {
+1450 						th.pushing=toys.PUSH_LEFT;
+1451 						th.accx=-data.speed;
+1452 					} else {
+1453 						th.pushing=toys.PUSH_RIGHT;
+1454 						th.accx=data.speed;
+1455 					}
+1456 				} else th.pushing=toys.PUSH_NONE;
+1457 			},
+1458 			dontFall:function(th,map,tilemap) {
+1459 				if (th.accx&&th.touchedfloor) {
+1460 					var til;
+1461 					if (th.accx>0) til=help.getTileInMap(toys.platformer.getNextX(th)+th.w-1+th.accx,th.y+th.h,map,0,tilemap);				
+1462 					else til=help.getTileInMap(toys.platformer.getNextX(th),th.y+th.h,map,0,tilemap);
+1463 					if (!map.tileIsSolidFloor(th,til)) {
+1464 						th.side=!th.side;
+1465 						th.accx=0;
+1466 					}
+1467 				}
+1468 			},
+1469 			horizontalBounce:function(th) {
+1470 				if (th.touchedleftwall||th.touchedrightwall) th.side=!th.side;
+1471 			},
+1472 		}
+1473 	},
+1474 	
+1475 	// State-based toys
+1476 	// CONSTANTS
+1477 	TOY_BUSY:0,
+1478 	TOY_DONE:1,
+1479 	TOY_IDLE:2,
+1480 	
+1481 	// PRIVATE
+1482 
+1483 	// Generical toys method
+1484 		
+1485 	/**
+1486 	* 
+1487 	*/
+1488 	resetToy:function(th,id) { if (th.toys) delete th.toys[id] },
+1489 	
+1490 	/**
+1491 	* 
+1492 	*/
+1493 	getToyValue:function(th,id,v,def) { return ((th.toys==null)||(th.toys[id]==null)?def:th.toys[id][v]) },
+1494 	
+1495 	/**
+1496 	* 
+1497 	*/
+1498 	getToyStatus:function(th,id) { return ((th.toys==null)||(th.toys[id]==null)?toys.TOY_BUSY:th.toys[id].__status) },
+1499 	
+1500 	/**
+1501 	* 
+1502 	*/
+1503 	_toydone:function(th,id) {
+1504 		if (th.toys[id].__status<toys.TOY_IDLE) th.toys[id].__status++;
+1505 		return th.toys[id].__status;
+1506 	},
+1507 	
+1508 	/**
+1509 	* 
+1510 	*/
+1511 	_toybusy:function(th,id) {
+1512 		th.toys[id].__status=toys.TOY_BUSY;
+1513 		return th.toys[id].__status;
+1514 	},
+1515 	
+1516 	/**
+1517 	* 
+1518 	*/
+1519 	_toyfrombool:function(th,id,b) { return (b?toys._toydone(th,id):toys._toybusy(th,id)) },
+1520 	
+1521 	/**
+1522 	* 
+1523 	*/
+1524 	_maketoy:function(th,id){
+1525 		if (!th.toys) th.toys={};
+1526 		if (!th.toys[id]) {
+1527 			th.toys[id]={__status:toys.TOY_BUSY};
+1528 			return true;
+1529 		} else return false;
+1530 	},
+1531 	
+1532 	/**
+1533 	* @namespace timer Timer functionality based methods
+1534 	*/
+1535 	// Pure timers
+1536 	timer:{
+1537 		
+1538 		/**
+1539 		* 
+1540 		*/
+1541 		randomly:function(th,id,data) {
+1542 			if (toys._maketoy(th,id)) {
+1543 				th.toys[id].time=help.random(data.base,data.range);
+1544 			}
+1545 			if (th.toys[id].time) {
+1546 				th.toys[id].time--;
+1547 				return toys._toybusy(th,id);
+1548 			} else {
+1549 				th.toys[id].time=help.random(data.base,data.range);
+1550 				return toys._toydone(th,id);
+1551 			}	
+1552 		},
+1553 		
+1554 		/**
+1555 		* 
+1556 		*/
+1557 		real:function(th,id,data) {
+1558 			if (toys._maketoy(th,id)) {
+1559 				th.toys[id].subtimer=gbox.getFps();
+1560 				th.toys[id].done=false;
+1561 				if (data.countdown)
+1562 					th.toys[id].time=data.countdown;
+1563 				else
+1564 					th.toys[id].time=0;
+1565 			}
+1566 			th.toys[id].subtimer--;
+1567 			if (!th.toys[id].subtimer) {
+1568 				th.toys[id].subtimer=gbox.getFps();
+1569 				if (data.countdown) {
+1570 					if (th.toys[id].time) {
+1571 						th.toys[id].time--; 
+1572 						if (data.audiocritical&&(th.toys[id].time<=data.critical))
+1573 							gbox.hitAudio(data.audiocritical);
+1574 					} else th.toys[id].done=true;
+1575 				} else
+1576 					th.toys[id].time++;
+1577 			}
+1578 			return toys._toyfrombool(th,id,th.toys[id].done);
+1579 
+1580 		},
+1581 		
+1582 		/**
+1583 		* 
+1584 		*/
+1585 		every:function(th,id,frames){
+1586 			if (toys._maketoy(th,id)) th.toys[id].timer=0;
+1587 			th.toys[id].timer++;
+1588 			if (th.toys[id].timer==frames) {
+1589 				th.toys[id].timer=0;
+1590 				return toys._toydone(th,id);
+1591 			} else return toys._toybusy(th,id)
+1592 		},
+1593 		
+1594 		/**
+1595 		* 
+1596 		*/
+1597 		after:function(th,id,frames) {
+1598 			if (toys._maketoy(th,id)) th.toys[id].timer=0;
+1599 			if (th.toys[id].timer==frames) return toys._toydone(th,id); else {
+1600 				th.toys[id].timer++;
+1601 				return toys._toybusy(th,id);
+1602 			}
+1603 		}
+1604 	},
+1605 	
+1606 	/**
+1607 	* 
+1608 	*/
+1609 	// Logical helpers
+1610 	logic: {
+1611 		
+1612 		/**
+1613 		* 
+1614 		*/
+1615 		once:function(th,id,cond){
+1616 			if (toys._maketoy(th,id)) th.toys[id].done=false;
+1617 			if (th.toys[id].done) return false; else if (cond) th.toys[id].done=true;
+1618 			return cond;
+1619 		}
+1620 	},
+1621 	
+1622 	/**
+1623 	* 
+1624 	*/
+1625 	// UI
+1626 	ui:{
+1627 		
+1628 		/**
+1629 		* 
+1630 		*/
+1631 		menu:function(th,id,opt) {
+1632 			if (toys._maketoy(th,id)||opt.resetmenu) {
+1633 				var fd=gbox.getFont(opt.font);
+1634 				th.toys[id].selected=(opt.selected?opt.selected:0);
+1635 				th.toys[id].ok=0;
+1636 				var w=0;
+1637 				for (var i=0;i<opt.items.length;i++)
+1638 					if (opt.items[i].length>w) w=opt.items[i].length;
+1639 				gbox.createCanvas("menu-"+id,{w:w*fd.tilew,h:opt.items.length*fd.tileh});
+1640 				for (var i=0;i<opt.items.length;i++)
+1641 					gbox.blitText(gbox.getCanvasContext("menu-"+id),{font:opt.font,text:opt.items[i],dx:0,dy:fd.tileh*i});
+1642 				th.toys[id].fh=fd.tileh;
+1643 				th.toys[id].fw=fd.tilew;
+1644 			}
+1645 			if (!th.toys[id].ok) {
+1646 				if (gbox.keyIsHit(opt.keys.up)&&(th.toys[id].selected>0)) {
+1647 					if (opt.audiooption) gbox.hitAudio(opt.audiooption);
+1648 					th.toys[id].selected--;
+1649 				} else
+1650 				if (gbox.keyIsHit(opt.keys.down)&&(th.toys[id].selected<opt.items.length-1)) {
+1651 					if (opt.audiooption) gbox.hitAudio(opt.audiooption);
+1652 					th.toys[id].selected++;
+1653 				} else
+1654 				if (gbox.keyIsHit(opt.keys.ok)) {
+1655 					if (opt.audioconfirm) gbox.hitAudio(opt.audioconfirm);
+1656 					th.toys[id].ok=1;
+1657 				} else
+1658 				if (gbox.keyIsHit(opt.keys.cancel)) th.toys[id].ok=-1;
+1659 			}
+1660 			gbox.blitAll(gbox.getBufferContext(),gbox.getCanvas("menu-"+id),{dx:opt.x+th.toys[id].fw,dy:opt.y,camera:opt.camera});
+1661 			if (!(th.toys[id].ok%2)) gbox.blitText(gbox.getBufferContext(),{font:opt.font,text:opt.selector,dx:opt.x,dy:opt.y+th.toys[id].selected*th.toys[id].fh,camera:opt.camera});
+1662 			if (th.toys[id].ok) {
+1663 				if (th.toys[id].ok>0)
+1664 					if (th.toys[id].ok<10) {
+1665 						th.toys[id].ok++;
+1666 						toys._toybusy(th,id);
+1667 					} else return toys._toydone(th,id); // selected > 0
+1668 				else return toys._toydone(th,id); // selected == -1
+1669 			} else return toys._toybusy(th,id);
+1670 		},
+1671 		
+1672 		/**
+1673 		* 
+1674 		*/
+1675 		// Returns a full customizable object for optimized huds
+1676 		hud:function(id) {
+1677 			gbox.createCanvas(id);
+1678 			return {
+1679 				w:{},
+1680 				surfaceid:id,
+1681 				
+1682 				/**
+1683 				* 
+1684 				*/
+1685 				updateWidget:function(i){
+1686 					if (!this.w[i].__hidden) {
+1687 						if (this.w[i].widget=="label") {
+1688 							if (this.w[i].prepad!=null) this.w[i].text=help.prepad(this.w[i].value,this.w[i].prepad,this.w[i].padwith); else
+1689 							if (this.w[i].postpad!=null) this.w[i].text=help.postpad(this.w[i].value,this.w[i].postpad,this.w[i].padwith); else
+1690 							this.w[i].text=this.w[i].value+"";
+1691 							gbox.blitText(gbox.getCanvasContext(this.surfaceid),this.w[i]);
+1692 						}
+1693 						if (this.w[i].widget=="symbols") {
+1694 							var ts=gbox.getTiles(this.w[i].tileset);
+1695 							gbox.blitClear(gbox.getCanvasContext(this.surfaceid),{x:this.w[i].dx,y:this.w[i].dy,w:((this.w[i].maxshown-1)*this.w[i].gapx)+ts.tilew,h:((this.w[i].maxshown-1)*this.w[i].gapy)+ts.tileh});
+1696 							var cnt=this.w[i].value;
+1697 							for (var x=0;x<this.w[i].maxshown;x++) {
+1698 								if (cnt>0) {
+1699 									gbox.blitTile(gbox.getCanvasContext(this.surfaceid),{tileset:this.w[i].tileset,tile:this.w[i].tiles[(cnt>this.w[i].tiles.length?this.w[i].tiles.length-1:cnt-1)],dx:this.w[i].dx+(x*this.w[i].gapx),dy:this.w[i].dy+(x*this.w[i].gapy),fliph:this.w[i].fliph,flipv:this.w[i].flipv});
+1700 								} else
+1701 									if (this.w[i].emptytile!=null)
+1702 										gbox.blitTile(gbox.getCanvasContext(this.surfaceid),{tileset:this.w[i].tileset,tile:this.w[i].emptytile,dx:this.w[i].dx+(x*this.w[i].gapx),dy:this.w[i].dy+(x*this.w[i].gapy),fliph:this.w[i].fliph,flipv:this.w[i].flipv});	
+1703 								cnt-=this.w[i].tiles.length;
+1704 							}
+1705 
+1706 						}
+1707 						if (this.w[i].widget=="stack") {
+1708 							var ts=gbox.getTiles(this.w[i].tileset);
+1709 							var bw=((this.w[i].maxshown-1)*this.w[i].gapx)+ts.tilew;
+1710 							gbox.blitClear(gbox.getCanvasContext(this.surfaceid),{x:this.w[i].dx-(this.w[i].rightalign?bw:0),y:this.w[i].dy,w:bw,h:((this.w[i].maxshown-1)*this.w[i].gapy)+ts.tileh});
+1711 							for (var x=0;x<this.w[i].maxshown;x++)
+1712 								if (x<this.w[i].value.length)
+1713 									gbox.blitTile(gbox.getCanvasContext(this.surfaceid),{tileset:this.w[i].tileset,tile:this.w[i].value[x],dx:(this.w[i].rightalign?this.w[i].dx-ts.tileh-(this.w[i].gapx*x):this.w[i].dx+(x*this.w[i].gapx)),dy:this.w[i].dy+(x*this.w[i].gapy),fliph:this.w[i].fliph,flipv:this.w[i].flipv});
+1714 						}
+1715 						if (this.w[i].widget=="radio") {
+1716 							var ts=gbox.getTiles(this.w[i].tileset);
+1717 							gbox.blitClear(gbox.getCanvasContext(this.surfaceid),{x:this.w[i].dx,y:this.w[i].dy,w:ts.tilew,h:ts.tileh});
+1718 							gbox.blitTile(gbox.getCanvasContext(this.surfaceid),{tileset:this.w[i].tileset,tile:this.w[i].frames[this.w[i].value],dx:this.w[i].dx,dy:this.w[i].dy,fliph:this.w[i].fliph,flipv:this.w[i].flipv});
+1719 
+1720 						}
+1721 						if (this.w[i].widget=="blit") {
+1722 							var ts=gbox.getTiles(this.w[i].tileset);
+1723 							gbox.blitClear(gbox.getCanvasContext(this.surfaceid),{x:this.w[i].dx,y:this.w[i].dy,w:ts.tilew,h:ts.tileh});
+1724 							gbox.blitTile(gbox.getCanvasContext(this.surfaceid),{tileset:this.w[i].tileset,tile:this.w[i].value,dx:this.w[i].dx,dy:this.w[i].dy,fliph:this.w[i].fliph,flipv:this.w[i].flipv});
+1725 
+1726 						}
+1727 						if (this.w[i].widget=="bool") {
+1728 							var ts=gbox.getTiles(this.w[i].tileset);
+1729 							gbox.blitClear(gbox.getCanvasContext(this.surfaceid),{x:this.w[i].dx,y:this.w[i].dy,w:ts.tilew,h:ts.tileh});
+1730 							if (this.w[i].value)
+1731 								gbox.blitTile(gbox.getCanvasContext(this.surfaceid),{tileset:this.w[i].tileset,tile:this.w[i].frame,dx:this.w[i].dx,dy:this.w[i].dy,fliph:this.w[i].fliph,flipv:this.w[i].flipv});
+1732 						}
+1733 						if (this.w[i].widget=="gauge") {
+1734 							var ts=gbox.getTiles(this.w[i].tileset);
+1735 							gbox.blitTile(gbox.getCanvasContext(this.surfaceid),{tileset:this.w[i].tileset,tile:0,dx:this.w[i].dx,dy:this.w[i].dy});						
+1736 							gbox.blitTile(gbox.getCanvasContext(this.surfaceid),{tileset:this.w[i].tileset,tile:1,dx:this.w[i].dx,dy:this.w[i].dy,w:(this.w[i].value*ts.tilew)/this.w[i].maxvalue});
+1737 						}
+1738 					}
+1739 				},
+1740 				
+1741 				/**
+1742 				* 
+1743 				*/
+1744 				hideWidgets:function(l) {
+1745 					for (var i=0;i<l.length;i++) this.w[l[i]].__hidden=true;
+1746 					this.redraw();
+1747 				},
+1748 				
+1749 				/**
+1750 				* 
+1751 				*/
+1752 				showWidgets:function(l) {
+1753 					for (var i=0;i<l.length;i++) this.w[l[i]].__hidden=false;
+1754 					this.redraw();
+1755 				},
+1756 				
+1757 				/**
+1758 				* 
+1759 				*/
+1760 				getValue:function(w,k) {
+1761 					return this.w[w][k];
+1762 				},
+1763 				
+1764 				/**
+1765 				* 
+1766 				*/
+1767 				getNumberValue:function(w,k) {
+1768 					return this.w[w][k]*1;
+1769 				},
+1770 
+1771 				/**
+1772 				* 
+1773 				*/
+1774 				setValue:function(w,k,v) {
+1775 					if (this.w[w][k]!=v) {
+1776 						if (k=="value") {
+1777 							if ((this.w[w].maxvalue!=null)&&(v>this.w[w].maxvalue)) v=this.w[w].maxvalue;
+1778 							if ((this.w[w].minvalue!=null)&&(v<this.w[w].minvalue)) v=this.w[w].minvalue;	
+1779 							if (this.w[w].widget=="radio") v=(v%this.w[w].frames.length);
+1780 						}
+1781 						this.w[w][k]=v;							
+1782 						this.updateWidget(w);
+1783 					}
+1784 				},
+1785 				
+1786 				/**
+1787 				* 
+1788 				*/
+1789 				pushValue:function(w,k,v) {
+1790 					this.w[w][k].push(v);
+1791 					this.updateWidget(w);
+1792 				},
+1793 				
+1794 				/**
+1795 				* 
+1796 				*/
+1797 				addValue:function(w,k,v) {
+1798 					if (v) this.setValue(w,k,this.w[w][k]+v);
+1799 				},
+1800 				
+1801 				/**
+1802 				* 
+1803 				*/
+1804 				setWidget:function(id,w) {
+1805 					this.w[id]=w;
+1806 					this.updateWidget(id);
+1807 				},
+1808 				
+1809 				/**
+1810 				* 
+1811 				*/
+1812 				redraw:function() {
+1813 					gbox.blitClear(gbox.getCanvasContext(this.surfaceid));
+1814 					for (var i in this.w) this.updateWidget(i);
+1815 				},
+1816 				
+1817 				/**
+1818 				* 
+1819 				*/
+1820 				blit:function() {
+1821 					gbox.blitAll(gbox.getBufferContext(),gbox.getCanvas(this.surfaceid),{dx:0,dy:0});
+1822 				}
+1823 			
+1824 			}
+1825 		}
+1826 	},
+1827 	
+1828 	/**
+1829 	* 
+1830 	*/
+1831 	fullscreen:{
+1832 	
+1833 		/**
+1834 		* 
+1835 		*/
+1836 		fadeout:function(th,id,tox,data) {
+1837 			if (toys._maketoy(th,id)||data.resetfade) {
+1838 				th.toys[id].fade=0;
+1839 				if (data.audiofade) th.toys[id].stv=gbox.getAudioVolume(data.audiofade);
+1840 				if (data.audiochannelfade) th.toys[id].chv=gbox.getChannelVolume(data.audiochannelfade);
+1841 			}
+1842 			th.toys[id].fade+=data.fadespeed;
+1843 			if (th.toys[id].fade>1) th.toys[id].fade=1;
+1844 			data.alpha=th.toys[id].fade;
+1845 			gbox.blitFade(tox,data);
+1846 			if (data.audiofade) gbox.setAudioVolume(data.audiofade,th.toys[id].stv*(1-data.alpha));
+1847 			if (data.audiochannelfade) 
+1848 				if (data.alpha==1)
+1849 					gbox.stopChannel(data.audiochannelfade);
+1850 				else
+1851 					gbox.setChannelVolume(data.audiochannelfade,th.toys[id].chv*(1-data.alpha));
+1852 			return toys._toyfrombool(th,id,th.toys[id].fade==1)
+1853 		},
+1854 		
+1855 		/**
+1856 		* 
+1857 		*/
+1858 		fadein:function(th,id,tox,data) {
+1859 			if (toys._maketoy(th,id)||data.resetfade) {
+1860 				th.toys[id].fade=1;
+1861 				if (data.audiofade) th.toys[id].stv=gbox.getAudioVolume(data.audiofade);
+1862 				if (data.audiochannelfade) th.toys[id].chv=gbox.getChannelDefaultVolume(data.audiochannelfade);
+1863 			}
+1864 			th.toys[id].fade-=data.fadespeed;
+1865 			if (th.toys[id].fade<0) th.toys[id].fade=0;
+1866 			if (th.toys[id].fade) {
+1867 				data.alpha=th.toys[id].fade;
+1868 				if (data.audiofade) gbox.setAudioVolume(data.audiofade,th.toys[id].stv*(1-data.alpha));
+1869 				if (data.audiochannelfade) gbox.setChannelVolume(data.audiochannelfade,th.toys[id].chv*(1-data.alpha));
+1870 				gbox.blitFade(tox,data);
+1871 			}
+1872 			return toys._toyfrombool(th,id,th.toys[id].fade==0);
+1873 		}
+1874 	},
+1875 	
+1876 	/**
+1877 	* 
+1878 	*/
+1879 	text:{
+1880 		
+1881 		/**
+1882 		* 
+1883 		*/
+1884 		blink:function(th,id,tox,data) {
+1885 			if (toys._maketoy(th,id)) {
+1886 				th.toys[id].texttimer=0;
+1887 				th.toys[id].visible=false;
+1888 				th.toys[id].times=0;
+1889 			}
+1890 			if (th.toys[id].texttimer>=data.blinkspeed) {
+1891 				th.toys[id].texttimer=0;
+1892 				th.toys[id].visible=!th.toys[id].visible;		
+1893 				if (data.times) th.toys[id].times++;
+1894 			} else th.toys[id].texttimer++;
+1895 			if (th.toys[id].visible)
+1896 				gbox.blitText(tox,data);
+1897 			return toys._toyfrombool(th,id,(data.times?data.times<th.toys[id].times:false));
+1898 		},
+1899 		
+1900 		/**
+1901 		* 
+1902 		*/
+1903 		fixed:function(th,id,tox,data) {
+1904 			if (toys._maketoy(th,id))
+1905 				th.toys[id].texttimer=0;
+1906 			else
+1907 				th.toys[id].texttimer++;
+1908 			gbox.blitText(tox,data);
+1909 			return toys._toyfrombool(th,id,data.time<th.toys[id].texttimer);
+1910 		}
+1911 	},
+1912 	
+1913 	/**
+1914 	* 
+1915 	*/
+1916 	logos:{
+1917 		
+1918 		/**
+1919 		* 
+1920 		*/
+1921 		linear:function(th,id,data) {
+1922 			if (toys._maketoy(th,id)) {
+1923 				th.toys[id].x=data.sx;
+1924 				th.toys[id].y=data.sy;
+1925 				th.toys[id].every=data.every;
+1926 				th.toys[id].played=false;
+1927 			}
+1928 			if (!th.toys[id].every) {
+1929 				if ((data.x!=th.toys[id].x)||(data.y!=th.toys[id].y))
+1930 					if ((Math.abs(data.x-th.toys[id].x)<=data.speed)&&(Math.abs(data.y-th.toys[id].y)<=data.speed)) {
+1931 						th.toys[id].x=data.x;
+1932 						th.toys[id].y=data.y;
+1933 					} else
+1934 						trigo.translate(th.toys[id],trigo.getAngle(th.toys[id],data),data.speed);
+1935 				else
+1936 					if (!th.toys[id].played) {
+1937 						if (data.audioreach) gbox.hitAudio(data.audioreach);
+1938 						th.toys[id].played=true;
+1939 					}
+1940 				th.toys[id].every=data.every;
+1941 			} else th.toys[id].every--;
+1942 			if (data.text)
+1943 				gbox.blitText(gbox.getBufferContext(),{
+1944 					font:data.font,
+1945 					dx:th.toys[id].x,dy:th.toys[id].y,
+1946 					text:data.text
+1947 				});
+1948 			else if (data.tileset)
+1949 				gbox.blitTile(gbox.getBufferContext(),{tileset:data.tileset,tile:data.tile,dx:th.toys[id].x,dy:th.toys[id].y,camera:data.camera,fliph:data.fliph,flipv:data.flipv,alpha:data.alpha});			
+1950 			else
+1951 				gbox.blitAll(gbox.getBufferContext(),gbox.getImage(data.image),{dx:th.toys[id].x,dy:th.toys[id].y,alpha:data.alpha});
+1952 			return toys._toyfrombool(th,id,(data.x==th.toys[id].x)&&(data.y==th.toys[id].y));
+1953 		},
+1954 		
+1955 		/**
+1956 		* 
+1957 		*/
+1958 		crossed:function(th,id,data) {
+1959 			if (toys._maketoy(th,id)) {
+1960 				th.toys[id].gapx=data.gapx;
+1961 				th.toys[id].lw=gbox.getImage(data.image).height;
+1962 				th.toys[id].done=false;
+1963 			}
+1964 			if (th.toys[id].gapx) {
+1965 				th.toys[id].gapx-=data.speed;
+1966 				if (th.toys[id].gapx<0) th.toys[id].gapx=0;
+1967 				gbox.blitAll(gbox.getBufferContext(),gbox.getImage(data.image),{dx:data.x-th.toys[id].gapx,dy:data.y,alpha:data.alpha});
+1968 				gbox.blitAll(gbox.getBufferContext(),gbox.getImage(data.image),{dx:data.x+th.toys[id].gapx,dy:data.y,alpha:data.alpha});
+1969 				return toys._toybusy(th,id);
+1970 			} else {
+1971 				if (!th.toys[id].done) {
+1972 					th.toys[id].done=true;
+1973 					if (data.audioreach) gbox.hitAudio(data.audioreach);					
+1974 				}
+1975 				gbox.blitAll(gbox.getBufferContext(),gbox.getImage(data.image),{dx:data.x,dy:data.y});
+1976 				return toys._toydone(th,id);
+1977 			}
+1978 		},
+1979 		
+1980 		/**
+1981 		* 
+1982 		*/
+1983 		zoomout:function(th,id,data) {
+1984 			if (toys._maketoy(th,id)) {
+1985 				th.toys[id].zoom=data.zoom;
+1986 				th.toys[id].done=false;
+1987 				th.toys[id].img=gbox.getImage(data.image);
+1988 			}
+1989 			if (th.toys[id].zoom!=1) {
+1990 				th.toys[id].zoom-=data.speed;
+1991 				if (th.toys[id].zoom<=1) {
+1992 					th.toys[id].zoom=1;
+1993 					if (data.audioreach) gbox.hitAudio(data.audioreach);
+1994 				}
+1995 				gbox.blit(gbox.getBufferContext(),gbox.getImage(data.image),{h:th.toys[id].img.height,w:th.toys[id].img.width,dx:data.x-Math.floor(th.toys[id].img.width*(th.toys[id].zoom-1)/2),dy:data.y-Math.floor(th.toys[id].img.height*(th.toys[id].zoom-1)/2),dh:Math.floor(th.toys[id].img.height*th.toys[id].zoom),dw:Math.floor(th.toys[id].img.width*th.toys[id].zoom),alpha:1/th.toys[id].zoom});
+1996 				return toys._toybusy(th,id);
+1997 			} else {
+1998 				gbox.blitAll(gbox.getBufferContext(),gbox.getImage(data.image),{dx:data.x,dy:data.y});
+1999 				return toys._toydone(th,id);
+2000 			}
+2001 		},
+2002 		
+2003 		/**
+2004 		* 
+2005 		*/
+2006 		rising:function(th,id,data) {
+2007 			if (toys._maketoy(th,id)) {
+2008 				th.toys[id].cnt=0;
+2009 				th.toys[id].lh=gbox.getImage(data.image).height;
+2010 				th.toys[id].lw=gbox.getImage(data.image).width;
+2011 				th.toys[id].done=false;
+2012 			}
+2013 			if (th.toys[id].cnt<th.toys[id].lh) {
+2014 				th.toys[id].cnt+=data.speed;
+2015 				if (th.toys[id].cnt>th.toys[id].lh) th.toys[id].gapx=th.toys[id].lh;
+2016 				gbox.blit(gbox.getBufferContext(),gbox.getImage(data.image),{dh:th.toys[id].cnt,dw:th.toys[id].lw,dx:data.x,dy:data.y+th.toys[id].lh-th.toys[id].cnt,alpha:data.alpha});
+2017 				if (data.reflex) gbox.blit(gbox.getBufferContext(),gbox.getImage(data.image),{dh:th.toys[id].cnt,dw:th.toys[id].lw,dx:data.x,dy:data.y+th.toys[id].lh,alpha:data.reflex,flipv:true});
+2018 				if (th.toys[id].cnt>=th.toys[id].lh)
+2019 					if (data.audioreach) gbox.hitAudio(data.audioreach);					
+2020 				return toys._toybusy(th,id);
+2021 			} else {
+2022 				gbox.blitAll(gbox.getBufferContext(),gbox.getImage(data.image),{dx:data.x,dy:data.y});
+2023 				if (data.reflex) gbox.blitAll(gbox.getBufferContext(),gbox.getImage(data.image),{dx:data.x,dy:data.y+th.toys[id].lh,alpha:data.reflex,flipv:true});
+2024 				
+2025 				return toys._toydone(th,id);
+2026 			}
+2027 		},
+2028 		
+2029 		/**
+2030 		* 
+2031 		*/
+2032 		bounce:function(th,id,data) {
+2033 			if (toys._maketoy(th,id)) {
+2034 				th.toys[id].accy=data.accy;
+2035 				th.toys[id].y=data.y;
+2036 				th.toys[id].h=gbox.getImage(data.image).height;
+2037 				th.toys[id].done=false;
+2038 			}
+2039 			if (!th.toys[id].done) {
+2040 				if (th.toys[id].y+th.toys[id].h>=data.floory) {
+2041 					if (data.audiobounce) gbox.hitAudio(data.audiobounce);
+2042 					th.toys[id].y=data.floory-th.toys[id].h;
+2043 					th.toys[id].accy=-Math.ceil(th.toys[id].accy/(data.heavy?data.heavy:2));
+2044 					th.toys[id].done=(th.toys[id].accy==0);
+2045 				} else th.toys[id].accy--;
+2046 				th.toys[id].y-=th.toys[id].accy;
+2047 			}
+2048 			gbox.blitAll(gbox.getBufferContext(),gbox.getImage(data.image),{dx:data.x,dy:th.toys[id].y});
+2049 					
+2050 			return toys._toyfrombool(th,id,th.toys[id].done);
+2051 		}
+2052 	},
+2053 	
+2054 	/**
+2055 	* 
+2056 	*/
+2057 	dialogue: {
+2058 		
+2059 		/**
+2060 		* 
+2061 		*/
+2062 		render:function(th,id,data){
+2063 			if (toys._maketoy(th,id)) {
+2064 				th.toys[id].newscene=true;
+2065 				th.toys[id].sceneid=-1;
+2066 				th.toys[id].ended=false;
+2067 				th.toys[id].timer=0;
+2068 				th.toys[id].counter=0;
+2069 				th.toys[id].anim=0;
+2070 				gbox.createCanvas("dialogue-"+id);
+2071 			}
+2072 			if (!data.hideonend||(data.hideonend&&!th.toys[id].ended)) {
+2073 				if (th.toys[id].newscene&&!th.toys[id].ended) {
+2074 					th.toys[id].anim=0;
+2075 					th.toys[id].timer=0;
+2076 					th.toys[id].newscene=false;
+2077 					th.toys[id].sceneid++;
+2078 					th.toys[id].ended=(th.toys[id].sceneid==data.scenes.length);
+2079 					if (!th.toys[id].ended) {
+2080 						th.toys[id].letter=0;
+2081 						th.toys[id].wait=false;
+2082 						th.toys[id].scene=data.scenes[th.toys[id].sceneid];
+2083 						th.toys[id].fd=gbox.getFont((th.toys[id].scene.font?th.toys[id].scene.font:data.font));
+2084 						th.toys[id].sceneH=(th.toys[id].scene.dh?th.toys[id].scene.dh:gbox.getScreenH());
+2085 						th.toys[id].sceneW=(th.toys[id].scene.dw?th.toys[id].scene.dw:gbox.getScreenW());
+2086 						th.toys[id].sceneX=(th.toys[id].scene.dx?th.toys[id].scene.dx:0);
+2087 						th.toys[id].sceneY=(th.toys[id].scene.dy?th.toys[id].scene.dy:0);
+2088 						gbox.blitClear(gbox.getCanvasContext("dialogue-"+id));
+2089 						if (th.toys[id].scene.slide) {							
+2090 							gbox.blitAll(gbox.getCanvasContext("dialogue-"+id),gbox.getImage(th.toys[id].scene.slide.image),{dx:th.toys[id].scene.slide.x,dy:th.toys[id].scene.slide.y});
+2091 						}
+2092 						if (th.toys[id].scene.scroller) {
+2093 							gbox.createCanvas("scroller-"+id,{w:th.toys[id].sceneW,h:(th.toys[id].scene.scroller.length)*(th.toys[id].fd.tileh+th.toys[id].scene.spacing)});
+2094 							for (var i=0;i<th.toys[id].scene.scroller.length;i++)
+2095 								gbox.blitText(gbox.getCanvasContext("scroller-"+id),{
+2096 										font:th.toys[id].fd.id,
+2097 										dx:0,
+2098 										dy:i*(th.toys[id].fd.tileh+th.toys[id].scene.spacing),
+2099 										dw:th.toys[id].sceneW,
+2100 										halign:gbox.ALIGN_CENTER,
+2101 										text:th.toys[id].scene.scroller[i]
+2102 									});
+2103 						}
+2104 						if (th.toys[id].scene.bonus) {
+2105 							gbox.createCanvas("bonus-"+id,{w:th.toys[id].sceneW,h:(th.toys[id].scene.bonus.length)*(th.toys[id].fd.tileh+th.toys[id].scene.spacing)});
+2106 						}
+2107 						if (th.toys[id].scene.audiomusic) gbox.hitAudio(th.toys[id].scene.audiomusic);
+2108 					}
+2109 				}
+2110 				if (!th.toys[id].ended) {
+2111 					if (th.toys[id].wait) {
+2112 						if (gbox.keyIsHit(data.esckey)) th.toys[id].ended=true; else
+2113 						if (gbox.keyIsHit(data.skipkey)) th.toys[id].newscene=true;
+2114 					} else {
+2115 									
+2116 						// SKIP KEYS
+2117 						
+2118 						if (gbox.keyIsHit(data.esckey)) th.toys[id].ended=true; else
+2119 						if (gbox.keyIsHold(data.skipkey)) th.toys[id].counter=th.toys[id].scene.speed;
+2120 						else th.toys[id].counter++;
+2121 						
+2122 						// MOVING
+2123 						
+2124 						if (th.toys[id].scene.talk) { // DIALOGUES
+2125 						
+2126 						
+2127 							if (th.toys[id].counter==th.toys[id].scene.speed) {
+2128 								th.toys[id].letter++;
+2129 								th.toys[id].counter=0;
+2130 								if (th.toys[id].scene.audio&&!(th.toys[id].letter%3)) gbox.hitAudio(th.toys[id].scene.audio);
+2131 								var tmp=th.toys[id].letter;
+2132 								var row=0;
+2133 								while (tmp>th.toys[id].scene.talk[row].length) {
+2134 									tmp-=th.toys[id].scene.talk[row].length;
+2135 									row++;
+2136 									if (row==th.toys[id].scene.talk.length)  {
+2137 										row=-1;
+2138 										break;
+2139 									}
+2140 								}
+2141 								if (row>=0) {
+2142 									gbox.blitText(gbox.getCanvasContext("dialogue-"+id),{
+2143 										font:data.font,
+2144 										dx:data.who[th.toys[id].scene.who].x,
+2145 										dy:(data.who[th.toys[id].scene.who].y)+(row*th.toys[id].fd.tileh),
+2146 										text:th.toys[id].scene.talk[row].substr(0,tmp)
+2147 									});
+2148 								} else
+2149 									th.toys[id].wait=true;
+2150 							}
+2151 						
+2152 						} else if (th.toys[id].scene.scroller) { // SCROLLER (i.e. credits)
+2153 						
+2154 							if (th.toys[id].counter==th.toys[id].scene.speed) {
+2155 								th.toys[id].letter++;
+2156 								th.toys[id].counter=0;
+2157 								if (th.toys[id].letter==(gbox.getCanvas("scroller-"+id).height+th.toys[id].scene.push))
+2158 									th.toys[id].wait=true;
+2159 							}
+2160 							
+2161 						} else if (th.toys[id].scene.bonus) { // BONUS (classic bonus award screen)
+2162 							for (var row=0;row<=th.toys[id].letter;row++) {
+2163 								if (th.toys[id].scene.bonus[row].text)
+2164 									gbox.blitText(gbox.getCanvasContext("bonus-"+id),{
+2165 										font:data.font,
+2166 										dx:0,
+2167 										dy:(row*(th.toys[id].fd.tileh+th.toys[id].scene.spacing)),
+2168 										text:th.toys[id].scene.bonus[row].text
+2169 									});
+2170 								else if (th.toys[id].scene.bonus[row].mul) {
+2171 									// Mask is %VAL%e%MUL%=%TOT%
+2172 									th.toys[id].scene.bonus[row].tmptext=th.toys[id].scene.bonus[row].mask.replace(/%VAL%/,th.toys[id].timer).replace(/%MUL%/,th.toys[id].scene.bonus[row].mul).replace(/%TOT%/,(th.toys[id].timer*th.toys[id].scene.bonus[row].mul));
+2173 									gbox.blitText(gbox.getCanvasContext("bonus-"+id),{
+2174 										clear:true,
+2175 										font:data.font,
+2176 										dx:0,
+2177 										dy:(row*(th.toys[id].fd.tileh+th.toys[id].scene.spacing)),
+2178 										text:th.toys[id].scene.bonus[row].tmptext
+2179 									});
+2180 								}
+2181 							}
+2182 							
+2183 							if (!th.toys[id].wait) {
+2184 								var next=false;
+2185 								if (th.toys[id].scene.bonus[th.toys[id].letter].mul&&!th.toys[id].scene.bonus[th.toys[id].letter].text) {
+2186 									if (th.toys[id].counter>=th.toys[id].scene.bonus[th.toys[id].letter].speed) {
+2187 										th.toys[id].counter=0;
+2188 										th.toys[id].timer++;
+2189 										if (th.toys[id].timer>th.toys[id].scene.bonus[th.toys[id].letter].mulvalue) {
+2190 											th.toys[id].scene.bonus[th.toys[id].letter].text=th.toys[id].scene.bonus[th.toys[id].letter].tmptext;
+2191 											next=true;
+2192 										} else {
+2193 											if (th.toys[id].scene.bonus[th.toys[id].letter].callback)
+2194 												th.toys[id].scene.bonus[th.toys[id].letter].callback(th.toys[id].scene.bonus[th.toys[id].letter],th.toys[id].scene.bonus[th.toys[id].letter].arg);
+2195 										}
+2196 									}
+2197 									
+2198 								} else if (th.toys[id].counter>=th.toys[id].scene.speed) next=true;
+2199 								if (next) {
+2200 									if (th.toys[id].letter==th.toys[id].scene.bonus.length-1)
+2201 										th.toys[id].wait=true;
+2202 									else {
+2203 										th.toys[id].letter++;
+2204 										if (th.toys[id].scene.bonus[th.toys[id].letter].mul) {
+2205 											th.toys[id].scene.bonus[th.toys[id].letter].text=null;
+2206 											th.toys[id].scene.bonus[th.toys[id].letter].tmptext=null;
+2207 											th.toys[id].timer=0;
+2208 										}
+2209 										th.toys[id].counter=0;
+2210 									}
+2211 								}
+2212 							}
+2213 						}
+2214 							
+2215 					}
+2216 				
+2217 				}
+2218 				
+2219 				// RENDERING
+2220 				
+2221 				
+2222 				if (th.toys[id].scene.talk) { // DIALOGUES
+2223 					if (data.who[th.toys[id].scene.who].box)
+2224 							gbox.blitRect(gbox.getBufferContext(),data.who[th.toys[id].scene.who].box);
+2225 					if (data.who[th.toys[id].scene.who].tileset) {
+2226 						th.toys[id].anim=(th.toys[id].anim+1)%20;
+2227 						gbox.blitTile(gbox.getBufferContext(),{tileset:data.who[th.toys[id].scene.who].tileset,tile:help.decideFrame(th.toys[id].anim,data.who[th.toys[id].scene.who].frames),dx:data.who[th.toys[id].scene.who].portraitx,dy:data.who[th.toys[id].scene.who].portraity,camera:false,fliph:data.who[th.toys[id].scene.who].fliph,flipv:data.who[th.toys[id].scene.who].flipv});
+2228 					}
+2229 					gbox.blitAll(gbox.getBufferContext(),gbox.getCanvas("dialogue-"+id),{dx:0,dy:0});
+2230 				} else if (th.toys[id].scene.scroller) // SCROLLER (i.e. credits)
+2231 					gbox.blit(gbox.getBufferContext(),gbox.getCanvas("scroller-"+id),{dx:th.toys[id].sceneX,dy:th.toys[id].sceneY+(th.toys[id].letter<th.toys[id].sceneH?th.toys[id].sceneH-th.toys[id].letter:0),dw:th.toys[id].sceneW,y:(th.toys[id].letter<th.toys[id].sceneH?0:th.toys[id].letter-th.toys[id].sceneH),dh:(th.toys[id].letter<th.toys[id].sceneH?th.toys[id].letter:th.toys[id].sceneH)});
+2232 				else if (th.toys[id].scene.bonus) // BONUS (i.e. credits)
+2233 					gbox.blitAll(gbox.getBufferContext(),gbox.getCanvas("bonus-"+id),{dx:th.toys[id].sceneX,dy:th.toys[id].sceneY});
+2234 			}		
+2235 			return toys._toyfrombool(th,id,th.toys[id].ended);
+2236 		}
+2237 	},
+2238 	
+2239 	// GENERATORS
+2240 	
+2241 		
+2242 	/**
+2243 	* 
+2244 	*/
+2245 	generate: {
+2246 		
+2247 		/**
+2248 		* 
+2249 		*/
+2250 		sparks:{
+2251 			simple:function(th,group,id,data) {
+2252 				var ts=gbox.getTiles(data.tileset);
+2253 				if (data.frames==null) {
+2254 					data.frames={ speed:(data.animspeed==null?1:data.animspeed), frames:[]};
+2255 					for (var i=0;i<ts.tilerow;i++) data.frames.frames[i]=i;
+2256 				}
+2257 
+2258 				var obj=gbox.addObject(
+2259 					help.mergeWithModel(
+2260 						data,{
+2261 							id:id,
+2262 							group:group,
+2263 							x:th.x+th.hw-ts.tilehw+(data.gapx==null?0:data.gapx),
+2264 							y:(data.valign=="top"?th.y:th.y+th.hh-ts.tilehh+(data.gapy==null?0:data.gapy)),
+2265 							tileset:data.tileset,
+2266 							alpha:null,
+2267 							accx:0, accy:0,
+2268 							frame:0,
+2269 							timer:(data.delay?-data.delay:-1),
+2270 							frames:data.frames,
+2271 							toptimer:((data.frames.frames.length)*data.frames.speed)-1,
+2272 							camera:th.camera,
+2273 							gravity:false,
+2274 							trashoffscreen:true,
+2275 							fliph:(data.fliph==null?th.fliph:data.fliph), flipv:(data.flipv==null?th.flipv:data.flipv),
+2276 							blinkspeed:0
+2277 						}
+2278 					)
+2279 				);
+2280 
+2281 				obj[(data.logicon==null?"first":data.logicon)]=function() {
+2282 					this.timer++;
+2283 					if (this.timer>=0) {
+2284 						this.x+=this.accx;
+2285 						this.y+=this.accy;
+2286 						if (this.gravity) this.accy++;
+2287 						if ((this.timer==this.toptimer)||(this.trashoffscreen&&(!gbox.objectIsVisible(this)))) gbox.trashObject(this);
+2288 					}
+2289 				}
+2290 				
+2291 				obj[(data.bliton==null?"blit":data.bliton)]=function() {
+2292 					if ((this.timer>=0)&&(!this.blinkspeed||(Math.floor(this.timer/this.blinkspeed)%2)))
+2293 						gbox.blitTile(gbox.getBufferContext(),{tileset:this.tileset,tile:help.decideFrame(this.timer,this.frames),dx:this.x,dy:this.y,camera:this.camera,fliph:this.fliph,flipv:this.flipv,alpha:this.alpha});					
+2294 				}
+2295 				
+2296 				return obj;
+2297 			},
+2298 		
+2299 			/**
+2300 			* 
+2301 			*/
+2302 			popupText:function(th,group,id,data) {
+2303 				data.text+="";
+2304 				var fd=gbox.getFont(data.font);
+2305 				
+2306 				var obj=gbox.addObject(
+2307 					help.mergeWithModel(
+2308 						data,{
+2309 							id:id,
+2310 							group:group,
+2311 							x:Math.floor(th.x+th.hw-(fd.tilehw*data.text.length)),
+2312 							y:th.y-fd.tilehh,
+2313 							vaccy:-data.jump,
+2314 							font:"small",
+2315 							keep:0,
+2316 							text:data.text,
+2317 							cnt:0,
+2318 							camera:th.camera
+2319 						}
+2320 					)
+2321 				);
+2322 				
+2323 				obj[(data.logicon==null?"first":data.logicon)]=function() {
+2324 					if (gbox.objectIsVisible(this)) {
+2325 						if (this.vaccy)
+2326 							this.vaccy++;
+2327 						else
+2328 							this.cnt++;
+2329 						this.y+=this.vaccy;
+2330 						if (this.cnt>=this.keep) gbox.trashObject(this);
+2331 					} else gbox.trashObject(this);
+2332 				}
+2333 				
+2334 				obj[(data.bliton==null?"blit":data.bliton)]=function() {
+2335 					gbox.blitText(gbox.getBufferContext(),{font:this.font,text:this.text,dx:this.x,dy:this.y,camera:this.camera});
+2336 				}
+2337 				
+2338 				return obj;
+2339 			},
+2340 		
+2341 			/**
+2342 			* 
+2343 			*/
+2344 			bounceDie:function(th,group,id,data){
+2345 				var obj=gbox.addObject(
+2346 					help.mergeWithModel(
+2347 						data,{
+2348 							id:id,
+2349 							group:group,
+2350 							tileset:th.tileset,
+2351 							frame:th.frame,
+2352 							side:th.side,
+2353 							frames:th.frames.die,
+2354 							x:th.x,
+2355 							y:th.y,
+2356 							vaccy:-data.jump,
+2357 							accx:0,
+2358 							flipv:data.flipv,
+2359 							cnt:0,
+2360 							blinkspeed:0,
+2361 							camera:th.camera
+2362 						}
+2363 					)
+2364 				);
+2365 				
+2366 				obj[(data.logicon==null?"first":data.logicon)]=function() {
+2367 					if (gbox.objectIsVisible(this)) {
+2368 						this.vaccy++;
+2369 						this.y+=this.vaccy;
+2370 						this.x+=this.accx;
+2371 						this.cnt++;
+2372 					} else gbox.trashObject(this);	
+2373 				}
+2374 				
+2375 				obj[(data.bliton==null?"blit":data.bliton)]=function() {
+2376 					if (!this.blinkspeed||(Math.floor(this.cnt/this.blinkspeed)%2))
+2377 						gbox.blitTile(gbox.getBufferContext(),{tileset:this.tileset,tile:help.decideFrame(this.cnt,this.frames),dx:this.x,dy:this.y,camera:this.camera,fliph:this.side,flipv:this.flipv});					
+2378 				}
+2379 				
+2380 				return obj;
+2381 			}
+2382 		},
+2383 		
+2384 		/**
+2385 		* 
+2386 		*/
+2387 		audio:{
+2388 		
+2389 			/**
+2390 			* 
+2391 			*/
+2392 			fadeOut:function(th,group,id,data){
+2393 				var obj=gbox.addObject(
+2394 					help.mergeWithModel(
+2395 						data,{
+2396 							id:id,
+2397 							group:group,
+2398 							fadespeed:-0.02*(data.fadein?-1:1),
+2399 							stoponmute:true,
+2400 							audio:null,
+2401 							channel:null,
+2402 							destination:null
+2403 						}
+2404 					)
+2405 				);
+2406 
+2407 				obj[(data.logicon==null?"first":data.logicon)]=function() {
+2408 					if (this.destination==null)
+2409 						if (this.audio)
+2410 							if (this.fadespeed>0) this.destination=1; else this.destination=0;
+2411 						else
+2412 							if (this.fadespeed>0) this.destination=gbox.getChannelDefaultVolume(this.channel); else this.destination=0;
+2413 					if (this.fadespeed>0) gbox.playAudio(this.audio);
+2414 				}
+2415 				
+2416 				obj[(data.bliton==null?"blit":data.bliton)]=function() {
+2417 					if (this.audio) gbox.changeAudioVolume(this.audio,this.fadespeed);
+2418 					if (this.channel) gbox.changeChannelVolume(this.channel,this.fadespeed);
+2419 					if (
+2420 						(this.audio&&(
+2421 							((this.fadespeed<0)&&(gbox.getAudioVolume(this.audio)<=this.destination))||
+2422 							((this.fadespeed>0)&&(gbox.getAudioVolume(this.audio)>=this.destination))
+2423 					   ))||
+2424 						(this.channel&&(
+2425 							((this.fadespeed<0)&&(gbox.getChannelVolume(this.channel)<=this.destination))||
+2426 							((this.fadespeed>0)&&(gbox.getChannelVolume(this.channel)>=this.destination))
+2427 					   ))
+2428 					) {
+2429 						if (this.channel&&this.stoponmute&&(this.fadespeed<0)) gbox.stopChannel(this.channel);
+2430 						if (this.audio&&this.stoponmute&&(this.fadespeed<0)) gbox.stopAudio(this.audio);
+2431 						gbox.trashObject(this);
+2432 					}
+2433 				}
+2434 			}
+2435 		
+2436 		}
+2437 		
+2438 	}
+2439 	
+2440 
+2441 }
+2442 
\ No newline at end of file diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/symbols/src/c__Users_Darius_Desktop_akihabara-1.1_kesiev_akihabara_akihabara_trigo.js.html b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/src/c__Users_Darius_Desktop_akihabara-1.1_kesiev_akihabara_akihabara_trigo.js.html new file mode 100644 index 0000000..fdeb4ac --- /dev/null +++ b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/src/c__Users_Darius_Desktop_akihabara-1.1_kesiev_akihabara_akihabara_trigo.js.html @@ -0,0 +1,84 @@ +
  1 // ---
+  2 // Copyright (c) 2010 Francesco Cottone, http://www.kesiev.com/
+  3 // ---
+  4 
+  5 /**
+  6  * @namespace Trigo module provides some math stuff for moving objects in a 
+  7  * direction or following a round path.
+  8  */
+  9 var trigo={
+ 10 	ANGLE_RIGHT:0,
+ 11 	ANGLE_DOWN:Math.PI*0.5,
+ 12 	ANGLE_LEFT:Math.PI,
+ 13 	ANGLE_UP:Math.PI*1.5555555,
+ 14  
+ 15  /**
+ 16  * Adds two angles together (radians).
+ 17  * @param {Float} a Base angle.
+ 18  * @param {Float} add The angle you're adding to the base angle.
+ 19  * @returns The resultant angle, always between 0 and 2*pi.
+ 20  */
+ 21 	addAngle:function(a,add) {
+ 22 		a=(a+add)%(Math.PI*2);
+ 23 		if (a<0) return (Math.PI*2)+a; else return a;
+ 24 	},
+ 25   /**
+ 26   * Gets the distance between two points.
+ 27   * @param {Object} p1 This is an object containing x and y params for the first point.
+ 28   * @param {Object} p2 This is an object containing x and y params for the second point.
+ 29   * @returns The distance between p1 and p2.
+ 30   */
+ 31 	getDistance:function(p1,p2) {
+ 32 		return Math.sqrt(Math.pow(p2.x-p1.x,2)+Math.pow(p2.y-p1.y,2))
+ 33 	},
+ 34   
+ 35   /**
+ 36   * Calculates the angle between two points.
+ 37   * @param {Object} p1 This is an object containing x and y params for the first point.
+ 38   * @param {Object} p2 This is an object containing x and y params for the second point.
+ 39   * @param {Float} transl (Optional) Adds an angle (in radians) to the result. Defaults to 0.
+ 40   * @returns The angle between points p1 and p2, plus transl.
+ 41   */
+ 42 	getAngle:function(p1,p2,transl) {
+ 43 		return this.addAngle(Math.atan2(p2.y-p1.y,p2.x-p1.x),(transl?transl:0));
+ 44 	},
+ 45   
+ 46   /**
+ 47   * Translates a point by a vector defined by angle and distance. This does not return a value but rather modifies the x and y values of p1.
+ 48   * @param {Object} p1 This is an object containing x and y params for the point.
+ 49   * @param {Float} a The angle of translation (rad).
+ 50   * @param {Float} d The distance of translation.
+ 51   */  
+ 52 	translate:function(p1,a,d) {
+ 53 		p1.x=p1.x+Math.cos(a)*d;
+ 54 		p1.y=p1.y+Math.sin(a)*d;
+ 55 	},
+ 56   
+ 57   /**
+ 58   * Translates an x component of a coordinate by a vector defined by angle and distance. This returns its component translation.
+ 59   * @param {Float} x1 This is an x coordinate.
+ 60   * @param {Float} a The angle of translation (rad).
+ 61   * @param {Float} d The distance of translation.
+ 62   */    
+ 63 	translateX:function(x1,a,d) {
+ 64 		return x1+Math.cos(a)*d
+ 65 	},
+ 66 
+ 67   /**
+ 68   * Translates a y component of a coordinate by a vector defined by angle and distance. This returns its component translation.
+ 69   * @param {Float} y1 This is a y coordinate.
+ 70   * @param {Float} a The angle of translation (rad).
+ 71   * @param {Float} d The distance of translation.
+ 72   */    
+ 73 	translateY:function(y1,a,d) {
+ 74 		return y1+Math.sin(a)*d;
+ 75 	}
+ 76 }
+ 77 
\ No newline at end of file diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/symbols/tool.html b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/tool.html new file mode 100644 index 0000000..9074480 --- /dev/null +++ b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/tool.html @@ -0,0 +1,215 @@ + + + + + + + JsDoc Reference - tool + + + + + + + + + +
+
+ +
+
+
+
 
+
Project Outline
+
+ + +
+ +
+ + + +
+
createMaingame(id, group)
+ +
+
+
 
gbox
addAudio(id, filename, def)
addBundle(call)
addFont(data)
addImage(id, filename)
addObject(data)
addScript(call)
blit(tox, image, data)
blitAll(tox, image, data)
blitClear(image, data)
blitFade(tox, data)
blitRect(tox, data)
blitText(tox, data)
blitTile(tox, data)
blitTilemap(tox, data)
centerCamera(data, viewdata)
collides(o1, o2, t)
createCanvas(id, data)
dataLoad(k, a)
dataSave(k, v, d)
getObject(group, id)
go()
hitAudio(a, data)
log()
pixelcollides(o1, o2, t)
playAudio(a, data)
readBundleData(pack, call)
setCameraX(x, viewdata)
setCameraY(y, viewdata)
setZindex(th, z)
stopAudio(a, permissive)
trashGroup(group)
+ +
+
+
 
help
asciiArtToMap(map, tra)
copyModel(data, model)
createModel(obj, attrs)
decideFrame(cnt, anim)
decideFrameOnce(cnt, anim)
framestotime(frames)
getArrayIndexed(a, value, field)
getTileInMap(x, y, map, ifout, mapid)
isLastFrameOnce(cnt, anim)
isSquished(th, by)
limit(v, min, max)
mergeWithModel(data, model)
multiplier(v, mul)
postpad(str, len, pad)
prepad(str, len, pad)
random(min, range)
seq(st, ed, skip)
setTileInMap(ctx, map, x, y, tile, The)
upAndDown(counter, max)
xPixelToTile(map, x, gap)
xPixelToTileX(map, x, gap)
yPixelToTile(map, y, gap)
yPixelToTileY(map, y, gap)
+ +
+
bounce(th, data)
horizontalKeys(th, keys)
horizontalTileCollision(th, map, tilemap)
initialize(th, data)
jumpKeys(th, key)
spawn(th, data)
verticalTileCollision(th, map, tilemap)
+ +
+
controlKeys(th, keys)
fireBullet(gr, id, data)
generateEnemy(gr, id, data, model)
generateScroller(gr, id, data)
hitByBullet(th, by)
initialize(th, data)
spawn(th, data)
+ +
+
after(th, id, frames)
every(th, id, frames)
randomly(th, id, data)
real(th, id, data)
+ +
+
+
 
tool
makecels(data)
+ +
+
callInColliding(th, data)
collides(fr, to, t)
controlKeys(th, keys)
fireBullet(gr, id, data)
floorCollision(th, data)
getAheadPixel(th, data)
initialize(th, data)
makedoor(gr, id, map, data)
pixelcollides(fr, to, t)
setStaticSpeed(th, speed)
spawn(th, data)
tileCollision(th, map, tilemap, defaulttile, data)
wander(th, map, tilemap, defaulttile, data)
+ + + +
+
+
 
trigo
addAngle(a, add)
getAngle(p1, p2, transl)
getDistance(p1, p2)
translate(p1, a, d)
translateX(x1, a, d)
translateY(y1, a, d)
+ +
+
+
+ + +
+
«
+ + + +
+ Akihabara Framework +
+ + + +
+ +

+ Namespace tool +

+ + + +
+

Tool module provides simple developing tools. Currently, this file only has a cel-composer: +it can compose an image stacking a set of frames for animating objects, applying a +number of filters to each frame.

+
+ +

Defined in: tool.js.

+ + + + + + + + + + + + + +
+
Method Summary
+
+ +
+ + makecels(data) + This makes the image cells for an animation and adds the load event listeners that the other stuff work to them. Calls loadall at the end. +
+ +
+
+ + + + + + + + + + + +
+
+ Method Detail +
+
+ + +
+ +
+ tool.makecels(data) + +
+
+ This makes the image cells for an animation and adds the load event listeners that the other stuff work to them. Calls loadall at the end. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {Object} + + data + + This is the created animation data being passed in to be used by the function. +
+ + + + + + + + +
+ +
+
+ + +
+ + +
+ + Documentation generated by JsDoc Toolkit 2.3.2 on Wed Aug 18 2010 16:09:24 GMT-0400 (EDT) +
+ +
+
+ + + diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/symbols/toys.html b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/toys.html new file mode 100644 index 0000000..8f9e26d --- /dev/null +++ b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/toys.html @@ -0,0 +1,796 @@ + + + + + + + JsDoc Reference - toys + + + + + + + + + +
+
+ +
+
+
+
 
+
Project Outline
+
+ + +
+ +
+ + + +
+
createMaingame(id, group)
+ +
+
+
 
gbox
addAudio(id, filename, def)
addBundle(call)
addFont(data)
addImage(id, filename)
addObject(data)
addScript(call)
blit(tox, image, data)
blitAll(tox, image, data)
blitClear(image, data)
blitFade(tox, data)
blitRect(tox, data)
blitText(tox, data)
blitTile(tox, data)
blitTilemap(tox, data)
centerCamera(data, viewdata)
collides(o1, o2, t)
createCanvas(id, data)
dataLoad(k, a)
dataSave(k, v, d)
getObject(group, id)
go()
hitAudio(a, data)
log()
pixelcollides(o1, o2, t)
playAudio(a, data)
readBundleData(pack, call)
setCameraX(x, viewdata)
setCameraY(y, viewdata)
setZindex(th, z)
stopAudio(a, permissive)
trashGroup(group)
+ +
+
+
 
help
asciiArtToMap(map, tra)
copyModel(data, model)
createModel(obj, attrs)
decideFrame(cnt, anim)
decideFrameOnce(cnt, anim)
framestotime(frames)
getArrayIndexed(a, value, field)
getTileInMap(x, y, map, ifout, mapid)
isLastFrameOnce(cnt, anim)
isSquished(th, by)
limit(v, min, max)
mergeWithModel(data, model)
multiplier(v, mul)
postpad(str, len, pad)
prepad(str, len, pad)
random(min, range)
seq(st, ed, skip)
setTileInMap(ctx, map, x, y, tile, The)
upAndDown(counter, max)
xPixelToTile(map, x, gap)
xPixelToTileX(map, x, gap)
yPixelToTile(map, y, gap)
yPixelToTileY(map, y, gap)
+ +
+
bounce(th, data)
horizontalKeys(th, keys)
horizontalTileCollision(th, map, tilemap)
initialize(th, data)
jumpKeys(th, key)
spawn(th, data)
verticalTileCollision(th, map, tilemap)
+ +
+
controlKeys(th, keys)
fireBullet(gr, id, data)
generateEnemy(gr, id, data, model)
generateScroller(gr, id, data)
hitByBullet(th, by)
initialize(th, data)
spawn(th, data)
+ +
+
after(th, id, frames)
every(th, id, frames)
randomly(th, id, data)
real(th, id, data)
+ +
+
+
 
tool
makecels(data)
+ +
+
callInColliding(th, data)
collides(fr, to, t)
controlKeys(th, keys)
fireBullet(gr, id, data)
floorCollision(th, data)
getAheadPixel(th, data)
initialize(th, data)
makedoor(gr, id, map, data)
pixelcollides(fr, to, t)
setStaticSpeed(th, speed)
spawn(th, data)
tileCollision(th, map, tilemap, defaulttile, data)
wander(th, map, tilemap, defaulttile, data)
+ + + +
+
+
 
trigo
addAngle(a, add)
getAngle(p1, p2, transl)
getDistance(p1, p2)
translate(p1, a, d)
translateX(x1, a, d)
translateY(y1, a, d)
+ +
+
+
+ + +
+
«
+ + + +
+ Akihabara Framework +
+ + + +
+ +

+ Namespace toys +

+ + + +
+

Toys module provides lots of common routines during the game developing: +from effects for screen titles to HUD handling to platform/SHMUP/RPG oriented routines, +like jumping characters, Z-Indexed objects, bullets, sparks, staff rolls, bonus screens, dialogues etc.

+
+ +

Defined in: toys.js.

+ + + + + + + + + +
+
Field Summary
+
+ +
+ + topview + +
+ +
+ + shmup + +
+ +
+ + platformer + +
+ +
+ + timer + +
+ +
+ + logic + +
+ +
+ + ui + +
+ +
+ + fullscreen + +
+ +
+ + text + +
+ +
+ + logos + +
+ +
+ + dialogue + +
+ +
+ + generate + +
+ +
+
+ + + + + + + + +
+
Method Summary
+
+ +
+ + getToyStatus(th, id) + +
+ +
+ + getToyValue(th, id, v, def) + +
+ +
+ + NOOP() + +
+ +
+ + resetToy(th, id) + +
+ +
+
+ + + + + + + + +
+
+ Field Detail +
+
+ +
+ +
+ toys.topview + +
+ +
+ + + +
+ + +

+									
+								
+									
+										
+										
+										
+										
+				
+								
+ +
+ +
+ toys.shmup + +
+ +
+ + + +
+ + +

+									
+								
+									
+										
+										
+										
+										
+				
+								
+ +
+ +
+ toys.platformer + +
+ +
+ + + +
+ + +

+									
+								
+									
+										
+										
+										
+										
+				
+								
+ +
+ +
+ toys.timer + +
+ +
+ + + +
+ + +

+									
+								
+									
+										
+										
+										
+										
+				
+								
+ +
+ +
+ toys.logic + +
+ +
+ + + +
+ + +

+									
+								
+									
+										
+										
+										
+										
+				
+								
+ +
+ +
+ toys.ui + +
+ +
+ + + +
+ + +

+									
+								
+									
+										
+										
+										
+										
+				
+								
+ +
+ +
+ toys.fullscreen + +
+ +
+ + + +
+ + +

+									
+								
+									
+										
+										
+										
+										
+				
+								
+ +
+ +
+ toys.text + +
+ +
+ + + +
+ + +

+									
+								
+									
+										
+										
+										
+										
+				
+								
+ +
+ +
+ toys.logos + +
+ +
+ + + +
+ + +

+									
+								
+									
+										
+										
+										
+										
+				
+								
+ +
+ +
+ toys.dialogue + +
+ +
+ + + +
+ + +

+									
+								
+									
+										
+										
+										
+										
+				
+								
+ +
+ +
+ toys.generate + +
+ +
+ + + +
+ + +

+									
+								
+									
+										
+										
+										
+										
+				
+								
+ +
+
+ + + + +
+
+ Method Detail +
+
+ + +
+ +
+ toys.getToyStatus(th, id) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ + + th + + +
+ + + id + + +
+ + + + + + + + +
+ + +
+ +
+ toys.getToyValue(th, id, v, def) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + th + + +
+ + + id + + +
+ + + v + + +
+ + + def + + +
+ + + + + + + + +
+ + +
+ +
+ toys.NOOP() + +
+
+ + + + + +

+										
+									
+ + + + + + + + + +
+ + +
+ +
+ toys.resetToy(th, id) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ + + th + + +
+ + + id + + +
+ + + + + + + + +
+ +
+
+ + +
+ + +
+ + Documentation generated by JsDoc Toolkit 2.3.2 on Wed Aug 18 2010 16:09:25 GMT-0400 (EDT) +
+ +
+
+ + + diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/symbols/toys.platformer.html b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/toys.platformer.html new file mode 100644 index 0000000..1b527b6 --- /dev/null +++ b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/toys.platformer.html @@ -0,0 +1,1049 @@ + + + + + + + JsDoc Reference - toys.platformer + + + + + + + + + +
+
+ +
+
+
+
 
+
Project Outline
+
+ + +
+ +
+ + + +
+
createMaingame(id, group)
+ +
+
+
 
gbox
addAudio(id, filename, def)
addBundle(call)
addFont(data)
addImage(id, filename)
addObject(data)
addScript(call)
blit(tox, image, data)
blitAll(tox, image, data)
blitClear(image, data)
blitFade(tox, data)
blitRect(tox, data)
blitText(tox, data)
blitTile(tox, data)
blitTilemap(tox, data)
centerCamera(data, viewdata)
collides(o1, o2, t)
createCanvas(id, data)
dataLoad(k, a)
dataSave(k, v, d)
getObject(group, id)
go()
hitAudio(a, data)
log()
pixelcollides(o1, o2, t)
playAudio(a, data)
readBundleData(pack, call)
setCameraX(x, viewdata)
setCameraY(y, viewdata)
setZindex(th, z)
stopAudio(a, permissive)
trashGroup(group)
+ +
+
+
 
help
asciiArtToMap(map, tra)
copyModel(data, model)
createModel(obj, attrs)
decideFrame(cnt, anim)
decideFrameOnce(cnt, anim)
framestotime(frames)
getArrayIndexed(a, value, field)
getTileInMap(x, y, map, ifout, mapid)
isLastFrameOnce(cnt, anim)
isSquished(th, by)
limit(v, min, max)
mergeWithModel(data, model)
multiplier(v, mul)
postpad(str, len, pad)
prepad(str, len, pad)
random(min, range)
seq(st, ed, skip)
setTileInMap(ctx, map, x, y, tile, The)
upAndDown(counter, max)
xPixelToTile(map, x, gap)
xPixelToTileX(map, x, gap)
yPixelToTile(map, y, gap)
yPixelToTileY(map, y, gap)
+ +
+
bounce(th, data)
horizontalKeys(th, keys)
horizontalTileCollision(th, map, tilemap)
initialize(th, data)
jumpKeys(th, key)
spawn(th, data)
verticalTileCollision(th, map, tilemap)
+ +
+
controlKeys(th, keys)
fireBullet(gr, id, data)
generateEnemy(gr, id, data, model)
generateScroller(gr, id, data)
hitByBullet(th, by)
initialize(th, data)
spawn(th, data)
+ +
+
after(th, id, frames)
every(th, id, frames)
randomly(th, id, data)
real(th, id, data)
+ +
+
+
 
tool
makecels(data)
+ +
+
callInColliding(th, data)
collides(fr, to, t)
controlKeys(th, keys)
fireBullet(gr, id, data)
floorCollision(th, data)
getAheadPixel(th, data)
initialize(th, data)
makedoor(gr, id, map, data)
pixelcollides(fr, to, t)
setStaticSpeed(th, speed)
spawn(th, data)
tileCollision(th, map, tilemap, defaulttile, data)
wander(th, map, tilemap, defaulttile, data)
+ + + +
+
+
 
trigo
addAngle(a, add)
getAngle(p1, p2, transl)
getDistance(p1, p2)
translate(p1, a, d)
translateX(x1, a, d)
translateY(y1, a, d)
+ +
+
+
+ + +
+
«
+ + + +
+ Akihabara Framework +
+ + + +
+ +

+ Namespace toys.platformer +

+ + + +
+

platformer The libraries for generating a 2D platformer game.

+
+ +

Defined in: toys.js.

+ + + + + + + + + +
+
Field Summary
+
+ +
+ + auto + +
+ +
+
+ + + + + + + + +
+
Method Summary
+
+ +
+ + applyGravity(th) + +
+ +
+ + bounce(th, data) + +
+ +
+ + canJump(th) + Checks if the passed object is touching the floor and can therefore jump at present. +
+ +
+ + getNextX(th) + +
+ +
+ + getNextY(th) + +
+ +
+ + handleAccellerations(th) + +
+ +
+ + horizontalKeys(th, keys) + +
+ +
+ + horizontalTileCollision(th, map, tilemap) + +
+ +
+ + initialize(th, data) + +
+ +
+ + jumpKeys(th, key) + +
+ +
+ + setFrame(th) + +
+ +
+ + setSide(th) + +
+ +
+ + spawn(th, data) + +
+ +
+ + verticalTileCollision(th, map, tilemap) + +
+ +
+
+ + + + + + + + +
+
+ Field Detail +
+
+ +
+ +
+ toys.platformer.auto + +
+ +
+ + + +
+ + +

+									
+								
+									
+										
+										
+										
+										
+				
+								
+ +
+
+ + + + +
+
+ Method Detail +
+
+ + +
+ +
+ toys.platformer.applyGravity(th) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + th + + +
+ + + + + + + + +
+ + +
+ +
+ toys.platformer.bounce(th, data) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ + + th + + +
+ + + data + + +
+ + + + + + + + +
+ + +
+ +
+ toys.platformer.canJump(th) + +
+
+ Checks if the passed object is touching the floor and can therefore jump at present. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + th + + This is the object being checked for jump ability at the time of calling. +
+ + + + + + + + +
+ + +
+ +
+ toys.platformer.getNextX(th) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + th + + +
+ + + + + + + + +
+ + +
+ +
+ toys.platformer.getNextY(th) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + th + + +
+ + + + + + + + +
+ + +
+ +
+ toys.platformer.handleAccellerations(th) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + th + + +
+ + + + + + + + +
+ + +
+ +
+ toys.platformer.horizontalKeys(th, keys) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ + + th + + +
+ + + keys + + +
+ + + + + + + + +
+ + +
+ +
+ toys.platformer.horizontalTileCollision(th, map, tilemap) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + +
+ + + th + + +
+ + + map + + +
+ + + tilemap + + +
+ + + + + + + + +
+ + +
+ +
+ toys.platformer.initialize(th, data) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ + + th + + +
+ + + data + + +
+ + + + + + + + +
+ + +
+ +
+ toys.platformer.jumpKeys(th, key) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ + + th + + +
+ + + key + + +
+ + + + + + + + +
+ + +
+ +
+ toys.platformer.setFrame(th) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + th + + +
+ + + + + + + + +
+ + +
+ +
+ toys.platformer.setSide(th) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + th + + +
+ + + + + + + + +
+ + +
+ +
+ toys.platformer.spawn(th, data) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ + + th + + +
+ + + data + + +
+ + + + + + + + +
+ + +
+ +
+ toys.platformer.verticalTileCollision(th, map, tilemap) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + +
+ + + th + + +
+ + + map + + +
+ + + tilemap + + +
+ + + + + + + + +
+ +
+
+ + +
+ + +
+ + Documentation generated by JsDoc Toolkit 2.3.2 on Wed Aug 18 2010 16:09:24 GMT-0400 (EDT) +
+ +
+
+ + + diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/symbols/toys.shmup.html b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/toys.shmup.html new file mode 100644 index 0000000..449af5e --- /dev/null +++ b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/toys.shmup.html @@ -0,0 +1,969 @@ + + + + + + + JsDoc Reference - toys.shmup + + + + + + + + + +
+
+ +
+
+
+
 
+
Project Outline
+
+ + +
+ +
+ + + +
+
createMaingame(id, group)
+ +
+
+
 
gbox
addAudio(id, filename, def)
addBundle(call)
addFont(data)
addImage(id, filename)
addObject(data)
addScript(call)
blit(tox, image, data)
blitAll(tox, image, data)
blitClear(image, data)
blitFade(tox, data)
blitRect(tox, data)
blitText(tox, data)
blitTile(tox, data)
blitTilemap(tox, data)
centerCamera(data, viewdata)
collides(o1, o2, t)
createCanvas(id, data)
dataLoad(k, a)
dataSave(k, v, d)
getObject(group, id)
go()
hitAudio(a, data)
log()
pixelcollides(o1, o2, t)
playAudio(a, data)
readBundleData(pack, call)
setCameraX(x, viewdata)
setCameraY(y, viewdata)
setZindex(th, z)
stopAudio(a, permissive)
trashGroup(group)
+ +
+
+
 
help
asciiArtToMap(map, tra)
copyModel(data, model)
createModel(obj, attrs)
decideFrame(cnt, anim)
decideFrameOnce(cnt, anim)
framestotime(frames)
getArrayIndexed(a, value, field)
getTileInMap(x, y, map, ifout, mapid)
isLastFrameOnce(cnt, anim)
isSquished(th, by)
limit(v, min, max)
mergeWithModel(data, model)
multiplier(v, mul)
postpad(str, len, pad)
prepad(str, len, pad)
random(min, range)
seq(st, ed, skip)
setTileInMap(ctx, map, x, y, tile, The)
upAndDown(counter, max)
xPixelToTile(map, x, gap)
xPixelToTileX(map, x, gap)
yPixelToTile(map, y, gap)
yPixelToTileY(map, y, gap)
+ +
+
bounce(th, data)
horizontalKeys(th, keys)
horizontalTileCollision(th, map, tilemap)
initialize(th, data)
jumpKeys(th, key)
spawn(th, data)
verticalTileCollision(th, map, tilemap)
+ +
+
controlKeys(th, keys)
fireBullet(gr, id, data)
generateEnemy(gr, id, data, model)
generateScroller(gr, id, data)
hitByBullet(th, by)
initialize(th, data)
spawn(th, data)
+ +
+
after(th, id, frames)
every(th, id, frames)
randomly(th, id, data)
real(th, id, data)
+ +
+
+
 
tool
makecels(data)
+ +
+
callInColliding(th, data)
collides(fr, to, t)
controlKeys(th, keys)
fireBullet(gr, id, data)
floorCollision(th, data)
getAheadPixel(th, data)
initialize(th, data)
makedoor(gr, id, map, data)
pixelcollides(fr, to, t)
setStaticSpeed(th, speed)
spawn(th, data)
tileCollision(th, map, tilemap, defaulttile, data)
wander(th, map, tilemap, defaulttile, data)
+ + + +
+
+
 
trigo
addAngle(a, add)
getAngle(p1, p2, transl)
getDistance(p1, p2)
translate(p1, a, d)
translateX(x1, a, d)
translateY(y1, a, d)
+ +
+
+
+ + +
+
«
+ + + +
+ Akihabara Framework +
+ + + +
+ +

+ Namespace toys.shmup +

+ + + +
+

shmup The libraries for a 2D top-down Shmup game.

+
+ +

Defined in: toys.js.

+ + + + + + + + + + + + + +
+
Method Summary
+
+ +
+ + applyForces(th) + +
+ +
+ + controlKeys(th, keys) + +
+ +
+ + fireBullet(gr, id, data) + +
+ +
+ + generateEnemy(gr, id, data, model) + +
+ +
+ + generateScroller(gr, id, data) + +
+ +
+ + getNextX(th) + +
+ +
+ + getNextY(th) + +
+ +
+ + handleAccellerations(th) + +
+ +
+ + hitByBullet(th, by) + +
+ +
+ + initialize(th, data) + +
+ +
+ + keepInBounds(th) + +
+ +
+ + setFrame(th) + +
+ +
+ + spawn(th, data) + +
+ +
+
+ + + + + + + + + + + +
+
+ Method Detail +
+
+ + +
+ +
+ toys.shmup.applyForces(th) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + th + + +
+ + + + + + + + +
+ + +
+ +
+ toys.shmup.controlKeys(th, keys) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ + + th + + +
+ + + keys + + +
+ + + + + + + + +
+ + +
+ +
+ toys.shmup.fireBullet(gr, id, data) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + +
+ + + gr + + +
+ + + id + + +
+ + + data + + +
+ + + + + + + + +
+ + +
+ +
+ toys.shmup.generateEnemy(gr, id, data, model) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + gr + + +
+ + + id + + +
+ + + data + + +
+ + + model + + +
+ + + + + + + + +
+ + +
+ +
+ toys.shmup.generateScroller(gr, id, data) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + +
+ + + gr + + +
+ + + id + + +
+ + + data + + +
+ + + + + + + + +
+ + +
+ +
+ toys.shmup.getNextX(th) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + th + + +
+ + + + + + + + +
+ + +
+ +
+ toys.shmup.getNextY(th) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + th + + +
+ + + + + + + + +
+ + +
+ +
+ toys.shmup.handleAccellerations(th) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + th + + +
+ + + + + + + + +
+ + +
+ +
+ toys.shmup.hitByBullet(th, by) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ + + th + + +
+ + + by + + +
+ + + + + + + + +
+ + +
+ +
+ toys.shmup.initialize(th, data) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ + + th + + +
+ + + data + + +
+ + + + + + + + +
+ + +
+ +
+ toys.shmup.keepInBounds(th) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + th + + +
+ + + + + + + + +
+ + +
+ +
+ toys.shmup.setFrame(th) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + th + + +
+ + + + + + + + +
+ + +
+ +
+ toys.shmup.spawn(th, data) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ + + th + + +
+ + + data + + +
+ + + + + + + + +
+ +
+
+ + +
+ + +
+ + Documentation generated by JsDoc Toolkit 2.3.2 on Wed Aug 18 2010 16:09:24 GMT-0400 (EDT) +
+ +
+
+ + + diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/symbols/toys.timer.html b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/toys.timer.html new file mode 100644 index 0000000..92edd6f --- /dev/null +++ b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/toys.timer.html @@ -0,0 +1,465 @@ + + + + + + + JsDoc Reference - toys.timer + + + + + + + + + +
+
+ +
+
+
+
 
+
Project Outline
+
+ + +
+ +
+ + + +
+
createMaingame(id, group)
+ +
+
+
 
gbox
addAudio(id, filename, def)
addBundle(call)
addFont(data)
addImage(id, filename)
addObject(data)
addScript(call)
blit(tox, image, data)
blitAll(tox, image, data)
blitClear(image, data)
blitFade(tox, data)
blitRect(tox, data)
blitText(tox, data)
blitTile(tox, data)
blitTilemap(tox, data)
centerCamera(data, viewdata)
collides(o1, o2, t)
createCanvas(id, data)
dataLoad(k, a)
dataSave(k, v, d)
getObject(group, id)
go()
hitAudio(a, data)
log()
pixelcollides(o1, o2, t)
playAudio(a, data)
readBundleData(pack, call)
setCameraX(x, viewdata)
setCameraY(y, viewdata)
setZindex(th, z)
stopAudio(a, permissive)
trashGroup(group)
+ +
+
+
 
help
asciiArtToMap(map, tra)
copyModel(data, model)
createModel(obj, attrs)
decideFrame(cnt, anim)
decideFrameOnce(cnt, anim)
framestotime(frames)
getArrayIndexed(a, value, field)
getTileInMap(x, y, map, ifout, mapid)
isLastFrameOnce(cnt, anim)
isSquished(th, by)
limit(v, min, max)
mergeWithModel(data, model)
multiplier(v, mul)
postpad(str, len, pad)
prepad(str, len, pad)
random(min, range)
seq(st, ed, skip)
setTileInMap(ctx, map, x, y, tile, The)
upAndDown(counter, max)
xPixelToTile(map, x, gap)
xPixelToTileX(map, x, gap)
yPixelToTile(map, y, gap)
yPixelToTileY(map, y, gap)
+ +
+
bounce(th, data)
horizontalKeys(th, keys)
horizontalTileCollision(th, map, tilemap)
initialize(th, data)
jumpKeys(th, key)
spawn(th, data)
verticalTileCollision(th, map, tilemap)
+ +
+
controlKeys(th, keys)
fireBullet(gr, id, data)
generateEnemy(gr, id, data, model)
generateScroller(gr, id, data)
hitByBullet(th, by)
initialize(th, data)
spawn(th, data)
+ +
+
after(th, id, frames)
every(th, id, frames)
randomly(th, id, data)
real(th, id, data)
+ +
+
+
 
tool
makecels(data)
+ +
+
callInColliding(th, data)
collides(fr, to, t)
controlKeys(th, keys)
fireBullet(gr, id, data)
floorCollision(th, data)
getAheadPixel(th, data)
initialize(th, data)
makedoor(gr, id, map, data)
pixelcollides(fr, to, t)
setStaticSpeed(th, speed)
spawn(th, data)
tileCollision(th, map, tilemap, defaulttile, data)
wander(th, map, tilemap, defaulttile, data)
+ + + +
+
+
 
trigo
addAngle(a, add)
getAngle(p1, p2, transl)
getDistance(p1, p2)
translate(p1, a, d)
translateX(x1, a, d)
translateY(y1, a, d)
+ +
+
+
+ + +
+
«
+ + + +
+ Akihabara Framework +
+ + + +
+ +

+ Namespace toys.timer +

+ + + +
+

timer Timer functionality based methods

+
+ +

Defined in: toys.js.

+ + + + + + + + + + + + + +
+
Method Summary
+
+ +
+ + after(th, id, frames) + +
+ +
+ + every(th, id, frames) + +
+ +
+ + randomly(th, id, data) + +
+ +
+ + real(th, id, data) + +
+ +
+
+ + + + + + + + + + + +
+
+ Method Detail +
+
+ + +
+ +
+ toys.timer.after(th, id, frames) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + +
+ + + th + + +
+ + + id + + +
+ + + frames + + +
+ + + + + + + + +
+ + +
+ +
+ toys.timer.every(th, id, frames) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + +
+ + + th + + +
+ + + id + + +
+ + + frames + + +
+ + + + + + + + +
+ + +
+ +
+ toys.timer.randomly(th, id, data) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + +
+ + + th + + +
+ + + id + + +
+ + + data + + +
+ + + + + + + + +
+ + +
+ +
+ toys.timer.real(th, id, data) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + +
+ + + th + + +
+ + + id + + +
+ + + data + + +
+ + + + + + + + +
+ +
+
+ + +
+ + +
+ + Documentation generated by JsDoc Toolkit 2.3.2 on Wed Aug 18 2010 16:09:24 GMT-0400 (EDT) +
+ +
+
+ + + diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/symbols/toys.topview.html b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/toys.topview.html new file mode 100644 index 0000000..cb85f93 --- /dev/null +++ b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/toys.topview.html @@ -0,0 +1,1803 @@ + + + + + + + JsDoc Reference - toys.topview + + + + + + + + + +
+
+ +
+
+
+
 
+
Project Outline
+
+ + +
+ +
+ + + +
+
createMaingame(id, group)
+ +
+
+
 
gbox
addAudio(id, filename, def)
addBundle(call)
addFont(data)
addImage(id, filename)
addObject(data)
addScript(call)
blit(tox, image, data)
blitAll(tox, image, data)
blitClear(image, data)
blitFade(tox, data)
blitRect(tox, data)
blitText(tox, data)
blitTile(tox, data)
blitTilemap(tox, data)
centerCamera(data, viewdata)
collides(o1, o2, t)
createCanvas(id, data)
dataLoad(k, a)
dataSave(k, v, d)
getObject(group, id)
go()
hitAudio(a, data)
log()
pixelcollides(o1, o2, t)
playAudio(a, data)
readBundleData(pack, call)
setCameraX(x, viewdata)
setCameraY(y, viewdata)
setZindex(th, z)
stopAudio(a, permissive)
trashGroup(group)
+ +
+
+
 
help
asciiArtToMap(map, tra)
copyModel(data, model)
createModel(obj, attrs)
decideFrame(cnt, anim)
decideFrameOnce(cnt, anim)
framestotime(frames)
getArrayIndexed(a, value, field)
getTileInMap(x, y, map, ifout, mapid)
isLastFrameOnce(cnt, anim)
isSquished(th, by)
limit(v, min, max)
mergeWithModel(data, model)
multiplier(v, mul)
postpad(str, len, pad)
prepad(str, len, pad)
random(min, range)
seq(st, ed, skip)
setTileInMap(ctx, map, x, y, tile, The)
upAndDown(counter, max)
xPixelToTile(map, x, gap)
xPixelToTileX(map, x, gap)
yPixelToTile(map, y, gap)
yPixelToTileY(map, y, gap)
+ +
+
bounce(th, data)
horizontalKeys(th, keys)
horizontalTileCollision(th, map, tilemap)
initialize(th, data)
jumpKeys(th, key)
spawn(th, data)
verticalTileCollision(th, map, tilemap)
+ +
+
controlKeys(th, keys)
fireBullet(gr, id, data)
generateEnemy(gr, id, data, model)
generateScroller(gr, id, data)
hitByBullet(th, by)
initialize(th, data)
spawn(th, data)
+ +
+
after(th, id, frames)
every(th, id, frames)
randomly(th, id, data)
real(th, id, data)
+ +
+
+
 
tool
makecels(data)
+ +
+
callInColliding(th, data)
collides(fr, to, t)
controlKeys(th, keys)
fireBullet(gr, id, data)
floorCollision(th, data)
getAheadPixel(th, data)
initialize(th, data)
makedoor(gr, id, map, data)
pixelcollides(fr, to, t)
setStaticSpeed(th, speed)
spawn(th, data)
tileCollision(th, map, tilemap, defaulttile, data)
wander(th, map, tilemap, defaulttile, data)
+ + + +
+
+
 
trigo
addAngle(a, add)
getAngle(p1, p2, transl)
getDistance(p1, p2)
translate(p1, a, d)
translateX(x1, a, d)
translateY(y1, a, d)
+ +
+
+
+ + +
+
«
+ + + +
+ Akihabara Framework +
+ + + +
+ +

+ Namespace toys.topview +

+ + + +
+

Top-view RPG specific libraries.

+
+ +

Defined in: toys.js.

+ + + + + + + + + + + + + +
+
Method Summary
+
+ +
+ + adjustZindex(th) + +
+ +
+ + applyForces(th) + Sets the objects current location to its next location using the getNextX and getNextY methods. +
+ +
+ + applyGravity(th) + This applies acceleration in the Z direction (not nessesarily gravity but whatever the next accerlation on the Z axis is) +
+ +
+ + callInColliding(th, data) + +
+ +
+ + collides(fr, to, t) + Checks if an object checks that both objects are on the same Z plane and if so it calls gbox.collides. +
+ +
+ + controlKeys(th, keys) + This sets and runs the control keys for the game. +
+ +
+ + fireBullet(gr, id, data) + +
+ +
+ + floorCollision(th, data) + This checks if the object's z index is 0 which means it has hit the floor. If this has occured it also plays an impact or bounce noise if one is passed in. +
+ +
+ + getAheadPixel(th, data) + +
+ +
+ + getNextX(th) + Gets the next X position the object is going to move to. +
+ +
+ + getNextY(th) + Gets the next Y position the object is going to move to. +
+ +
+ + getNextZ(th) + Gets the next Z position the object is going to move to. +
+ +
+ + handleAccellerations(th) + Degrades all accelerations on an object by one toward zero. +
+ +
+ + handleGravity(th) + Increases the Z acceleration on the object by one. +
+ +
+ + initialize(th, data) + Initializes the game with the variables needed for topview and whatever else you feed in through data. +
+ +
+ + makedoor(gr, id, map, data) + +
+ +
+ + pixelcollides(fr, to, t) + Checks for pixel collisions with an offset to the X and Y of the colidable using colx and coly. +
+ +
+ + setFrame(th) + This sets which frame the object is going to display based on an agregate word that describes predefined states. +
+ +
+ + setStaticSpeed(th, speed) + +
+ +
+ + spawn(th, data) + Spawns a new object in the topview namespace. This also merges parameters in data into paramaters in th using help.copyModel. +
+ +
+ + spritewallCollision(th, data) + +
+ +
+ + tileCollision(th, map, tilemap, defaulttile, data) + Checks if the specified object is colliding with tiles in the map in an area defined by the object's colw and colh variables as well as the tolerance and approximation variables that are passed in through data. Only tiles in the map marked as solid are checked against. +
+ +
+ + wander(th, map, tilemap, defaulttile, data) + +
+ +
+
+ + + + + + + + + + + +
+
+ Method Detail +
+
+ + +
+ +
+ toys.topview.adjustZindex(th) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ + + th + + +
+ + + + + + + + +
+ + +
+ +
+ toys.topview.applyForces(th) + +
+
+ Sets the objects current location to its next location using the getNextX and getNextY methods. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {Object} + + th + + The object being modified. +
    +
  • x: the current x position of the object
  • +
  • y: the current y position of the object
  • +
  • accx: the object's currect acceleration in the x direction
  • +
  • accy: the object's currect acceleration in the y direction
  • +
  • maxacc: the max accleration the object can have (if either acceleration is greater than this then this value is used instead for that acceleration)
  • +
+
+ + + + + + + + +
+ + +
+ +
+ toys.topview.applyGravity(th) + +
+
+ This applies acceleration in the Z direction (not nessesarily gravity but whatever the next accerlation on the Z axis is) + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {Object} + + th + + The object being modified. +
    +
  • z: the current z position of the object
  • +
  • accz: the object's currect acceleration in the z direction
  • +
  • maxacc: the max accleration the object can have (if accz is greater than this then this value is used instead)
  • +
+
+ + + + + + + + +
+ + +
+ +
+ toys.topview.callInColliding(th, data) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ + + th + + +
+ + + data + + +
+ + + + + + + + +
+ + +
+ +
+ toys.topview.collides(fr, to, t) + +
+
+ Checks if an object checks that both objects are on the same Z plane and if so it calls gbox.collides. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + +
+ {Object} + + fr + + The object which collision is being checked for. +
    +
  • x{Integer}: (required)Objects x position
  • +
  • y{Integer}: (required)Objects y position
  • +
  • z{Integer}: (required)Objects z position
  • +
  • colx{Integer}: (required)The dimension of the collision box along the x axis
  • +
  • coly{Integer}: (required)The dimension of the collision box along the y axis
  • +
  • colh{Integer}: (required)Collision box height
  • +
  • colw{Integer}: (required)Collision box width
  • +
+
+ {Object} + + to + + The object that collision is being checked against. +
    +
  • x{Integer}: (required)Objects x position
  • +
  • y{Integer}: (required)Objects y position
  • +
  • z{Integer}: (required)Objects z position
  • +
  • colx{Integer}: (required)Collision x
  • +
  • coly{Integer}: (required)Collision y
  • +
  • colh{Integer}: (required)Collision box height
  • +
  • colw{Integer}: (required)Collision box width
  • +
+
+ {int} + + t + + This is the tollerance (or margin for error) on the collide function. +
+ + + + + + + + +
+ + +
+ +
+ toys.topview.controlKeys(th, keys) + +
+
+ This sets and runs the control keys for the game. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ {Object} + + th + + This is the object that is being controlled by the keys (assumed to be the player) +
    +
  • accx: the object's currect acceleration in the x direction
  • +
  • accy: the object's currect acceleration in the y direction
  • +
  • responsive: minimum movement speed
  • +
  • staticspeed: turns off acceleration
  • +
  • nodiagonals: boolean determining if the object can move along both axis at once.
  • +
  • xpushing: a boolean that notes whether the object is pushing against something in the x direction.
  • +
  • ypushing: a boolean that notes whether the object is pushing against something in the y direction.
  • +
  • controlmaxacc: max acceleration for the object along an axis
  • +
  • noreset: checks for the object being allowed to reset its pushing status (?)
  • +
+
+ {Object} + + keys + + These are the control keys being passed in for left, right, up, and down. +//incomplete +
+ + + + + + + + +
+ + +
+ +
+ toys.topview.fireBullet(gr, id, data) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + +
+ + + gr + + +
+ + + id + + +
+ + + data + + +
+ + + + + + + + +
+ + +
+ +
+ toys.topview.floorCollision(th, data) + +
+
+ This checks if the object's z index is 0 which means it has hit the floor. If this has occured it also plays an impact or bounce noise if one is passed in. Note: The area above the floor is in the negative z index space so a value of 1 for z will return that the object has collided with the floor and z will then be set to zero. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ {Object} + + th + + The object being checked for collision. +
    +
  • touchedfloor{boolean}: This value is not passed in but is created or set in the function. This contains the function's return value.
  • +
  • +
  • +
  • +
+
+ {Object} + + data + + This is used to pass in extra parameters. +
    +
  • +
+
+ + + + + + + + +
+ + +
+ +
+ toys.topview.getAheadPixel(th, data) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ + + th + + +
+ + + data + + +
+ + + + + + + + +
+ + +
+ +
+ toys.topview.getNextX(th) + +
+
+ Gets the next X position the object is going to move to. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {Object} + + th + + The object being checked. +
    +
  • x: the current x position of the object
  • +
  • accx: the object's currect acceleration in the x direction
  • +
  • maxacc: the max accleration the object can have (if accx is greater than this then this value is used instead)
  • +
+
+ + + + + + + + +
+ + +
+ +
+ toys.topview.getNextY(th) + +
+
+ Gets the next Y position the object is going to move to. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {Object} + + th + + The object being checked. +
    +
  • y: the current y position of the object
  • +
  • accy: the object's currect acceleration in the y direction
  • +
  • maxacc: the max accleration the object can have (if accy is greater than this then this value is used instead)
  • +
+
+ + + + + + + + +
+ + +
+ +
+ toys.topview.getNextZ(th) + +
+
+ Gets the next Z position the object is going to move to. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {Object} + + th + + The object being checked. +
    +
  • z: the current z position of the object
  • +
  • accz: the object's currect acceleration in the z direction
  • +
  • maxacc: the max accleration the object can have (if accz is greater than this then this value is used instead)
  • +
+
+ + + + + + + + +
+ + +
+ +
+ toys.topview.handleAccellerations(th) + +
+
+ Degrades all accelerations on an object by one toward zero. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {Object} + + th + + The object being modified. +
    +
  • xpushing: a boolean that notes whether the object is pushing against something in the x direction.
  • +
  • ypushing: a boolean that notes whether the object is pushing against something in the y direction.
  • +
  • accx: the object's currect acceleration in the x direction
  • +
  • accy: the object's currect acceleration in the y direction
  • +
+
+ + + + + + + + +
+ + +
+ +
+ toys.topview.handleGravity(th) + +
+
+ Increases the Z acceleration on the object by one. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {Object} + + th + + The object being modified. +
    +
  • accz: the acceleration on the Z axis
  • +
+
+ + + + + + + + +
+ + +
+ +
+ toys.topview.initialize(th, data) + +
+
+ Initializes the game with the variables needed for topview and whatever else you feed in through data. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ {Object} + + th + + Passes in the object being initialized. +
+ {Object} + + data + + This is used to pass in everything that's being initiliized. If a value is not in Data then a default value is used instead. This can pass in values which do not have a default. +
    +
  • x{Integer}: x position of the object. (defaults to 0)
  • +
  • y{Integer}: y position of the object. (defaults to 0)
  • +
  • z{Integer}: z index of the object. (defaults to 0)
  • +
  • accx{Integer}: The starting x velociyt of the object. (defaults to 0)
  • +
  • accy{Integer}: The starting y velocity of the object. (defaults to 0)
  • +
  • accz{Integer}: The starting z velocity of the object. (defaults to 0)
  • +
  • frames{Object}: This is stores the animation frames for the objects in a map style structure. An empty map means the default image will display with no animation frames. (defaults to an empty map)
  • +
  • shadow: (defaults to null)
  • //incomplete +
  • maxacc{Integer}: (defaults to )4
  • +
  • controlmaxacc{Integer}: (defaults to 4)
  • +
  • responsive: (defaults to 0)
  • +
  • weapon: (defaults to 0)
  • +
  • camera{Boolean}: (defaults to true)
  • +
  • flipv{Boolean}: Notes if the object is flipped vertically(defaults to false)
  • +
  • fliph{Boolean}: Notes if the object is flipped horrizontally(defaults to false)
  • +
  • facing{Integer}: Stores the facing of the object. This is set with pre-defined Integer values from within Toys.(defaults to toys.FACE_DOWN)
  • +
      +
    • FACE_UP:0,
    • +
    • FACE_RIGHT:1,
    • +
    • FACE_DOWN:2,
    • +
    • FACE_LEFT:3,
    • +
    +
  • flipside{Boolean}: (defaults to true)
  • +
  • haspushing{Boolean}: (defaults to false)
  • +
  • frame: (default to 0)
  • +
  • colh{Integer}: (defaults to gbox.getTiles(th.tileset).tilehh)
  • +
  • colw{Integer}: (defaults to gbox.getTiles(th.tileset).tilew)
  • +
  • colx{Integer}: (defaults to 0)
  • +
  • staticspeed{Integer}: (defaults to 0)
  • +
  • nodiagonals{Boolean}: (defaults to false)
  • +
  • noreset: (defaults to false)
  • +
+
+ + + + + + + + +
+ + +
+ +
+ toys.topview.makedoor(gr, id, map, data) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + gr + + +
+ + + id + + +
+ + + map + + +
+ + + data + + +
+ + + + + + + + +
+ + +
+ +
+ toys.topview.pixelcollides(fr, to, t) + +
+
+ Checks for pixel collisions with an offset to the X and Y of the colidable using colx and coly. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + +
+ {Object} + + fr + + The object which collision is being tested for. +
+ {Object} + + to + + The object (or point) which collision is being tested against. +
+ {int} + + t + + The tollerance of the collision algorithm. +
+ + + + + + + + +
+ + +
+ +
+ toys.topview.setFrame(th) + +
+
+ This sets which frame the object is going to display based on an agregate word that describes predefined states. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + +
+ {Object} + + th + + The object whose frame is being set. +
    +
  • xpushing: a boolean that notes whether the object is pushing against something in the x direction.
  • +
  • ypushing: a boolean that notes whether the object is pushing against something in the y direction.
  • +
  • haspushing: a boolean that notes if the object changes when pushing against something.
  • +
  • toucheddown: a boolean that notes if the object is touching something below it on the screen.
  • +
  • touchedup: a boolean that notes if the object is touching something above it on the screen.<
  • +
  • touchedright: a boolean that notes if the object is touching something right of it on the screen.<
  • +
  • touchedleft: a boolean that notes if the object is touching something left of it on the screen.<
  • +
  • flipside:
  • +
  • fliph:
  • +
  • facing:
  • +
  • frames:
  • +
  • frame:
  • +
  • counter:
  • +
+// incomplete +
+ + + + + + + + +
+ + +
+ +
+ toys.topview.setStaticSpeed(th, speed) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ + + th + + +
+ + + speed + + +
+ + + + + + + + +
+ + +
+ +
+ toys.topview.spawn(th, data) + +
+
+ Spawns a new object in the topview namespace. This also merges parameters in data into paramaters in th using help.copyModel. +This initializes some basic basic variables for the object and sets the Z index. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ {Object} + + th + + References 'this' which is the object that called the method (generally). +
    +
  • y {Integer}: (required) The object's y position.
  • +
  • h {Integer}: (required) The object's height.
  • +
+
+ {Object} + + data + + This holds variables to be merged into th's stored info. +
+ + + + + + + + +
+ + +
+ +
+ toys.topview.spritewallCollision(th, data) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ {Object} + + th + + The object being checked for collisions. +
    +
  • +
  • +
  • +
  • +
+
+ {Object} + + data + + This is used to pass in other data and arguments. +
    +
  • group {String}: (required) This is the group of objects being checked against.
  • +
  • +
  • +
  • +
  • +
//incomplete +
+ + + + + + + + +
+ + +
+ +
+ toys.topview.tileCollision(th, map, tilemap, defaulttile, data) + +
+
+ Checks if the specified object is colliding with tiles in the map in an area defined by the object's colw and colh variables as well as the tolerance and approximation variables that are passed in through data. Only tiles in the map marked as solid are checked against. The alogrithm checks the + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ {Object} + + th + + The object that is being checked against the tilemap. +
+ {Object} + + map + + This is the asci map that the tile map is generated from. +
+ {Object} + + tilemap + + This is the array of tile objects that it itterated over checking for collisions. +
+ {Object} + + defaulttile + + The default tile to be returned if nothing can be found. Null can be used here. +
+ {Object} + + data + + Passes is extra dat to the function. Can be set as null. +
    +
  • tolerance{Integer}: This is subtracted from the collision space to get the maximum collision area for the object. This defaults to 6.
  • +
  • approximation{Integer}: This is the amount that the checked values are incremented by until they reach the maximum value allowed. This defaults to 10.
  • +
+
+ + + + + + + + +
+ + +
+ +
+ toys.topview.wander(th, map, tilemap, defaulttile, data) + +
+
+ + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + th + + +
+ + + map + + +
+ + + tilemap + + +
+ + + defaulttile + + +
+ + + data + + +
+ + + + + + + + +
+ +
+
+ + +
+ + +
+ + Documentation generated by JsDoc Toolkit 2.3.2 on Wed Aug 18 2010 16:09:25 GMT-0400 (EDT) +
+ +
+
+ + + diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/symbols/trigo.html b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/trigo.html new file mode 100644 index 0000000..c5cdf6a --- /dev/null +++ b/deps/akihabara-core-1.3.1/akihabara/docs/symbols/trigo.html @@ -0,0 +1,635 @@ + + + + + + + JsDoc Reference - trigo + + + + + + + + + +
+
+ +
+
+
+
 
+
Project Outline
+
+ + +
+ +
+ + + +
+
createMaingame(id, group)
+ +
+
+
 
gbox
addAudio(id, filename, def)
addBundle(call)
addFont(data)
addImage(id, filename)
addObject(data)
addScript(call)
blit(tox, image, data)
blitAll(tox, image, data)
blitClear(image, data)
blitFade(tox, data)
blitRect(tox, data)
blitText(tox, data)
blitTile(tox, data)
blitTilemap(tox, data)
centerCamera(data, viewdata)
collides(o1, o2, t)
createCanvas(id, data)
dataLoad(k, a)
dataSave(k, v, d)
getObject(group, id)
go()
hitAudio(a, data)
log()
pixelcollides(o1, o2, t)
playAudio(a, data)
readBundleData(pack, call)
setCameraX(x, viewdata)
setCameraY(y, viewdata)
setZindex(th, z)
stopAudio(a, permissive)
trashGroup(group)
+ +
+
+
 
help
asciiArtToMap(map, tra)
copyModel(data, model)
createModel(obj, attrs)
decideFrame(cnt, anim)
decideFrameOnce(cnt, anim)
framestotime(frames)
getArrayIndexed(a, value, field)
getTileInMap(x, y, map, ifout, mapid)
isLastFrameOnce(cnt, anim)
isSquished(th, by)
limit(v, min, max)
mergeWithModel(data, model)
multiplier(v, mul)
postpad(str, len, pad)
prepad(str, len, pad)
random(min, range)
seq(st, ed, skip)
setTileInMap(ctx, map, x, y, tile, The)
upAndDown(counter, max)
xPixelToTile(map, x, gap)
xPixelToTileX(map, x, gap)
yPixelToTile(map, y, gap)
yPixelToTileY(map, y, gap)
+ +
+
bounce(th, data)
horizontalKeys(th, keys)
horizontalTileCollision(th, map, tilemap)
initialize(th, data)
jumpKeys(th, key)
spawn(th, data)
verticalTileCollision(th, map, tilemap)
+ +
+
controlKeys(th, keys)
fireBullet(gr, id, data)
generateEnemy(gr, id, data, model)
generateScroller(gr, id, data)
hitByBullet(th, by)
initialize(th, data)
spawn(th, data)
+ +
+
after(th, id, frames)
every(th, id, frames)
randomly(th, id, data)
real(th, id, data)
+ +
+
+
 
tool
makecels(data)
+ +
+
callInColliding(th, data)
collides(fr, to, t)
controlKeys(th, keys)
fireBullet(gr, id, data)
floorCollision(th, data)
getAheadPixel(th, data)
initialize(th, data)
makedoor(gr, id, map, data)
pixelcollides(fr, to, t)
setStaticSpeed(th, speed)
spawn(th, data)
tileCollision(th, map, tilemap, defaulttile, data)
wander(th, map, tilemap, defaulttile, data)
+ + + +
+
+
 
trigo
addAngle(a, add)
getAngle(p1, p2, transl)
getDistance(p1, p2)
translate(p1, a, d)
translateX(x1, a, d)
translateY(y1, a, d)
+ +
+
+
+ + +
+
«
+ + + +
+ Akihabara Framework +
+ + + +
+ +

+ Namespace trigo +

+ + + +
+

Trigo module provides some math stuff for moving objects in a direction or following a round path.

+
+ +

Defined in: trigo.js.

+ + + + + + + + + + + + + +
+
Method Summary
+
+ +
+ + addAngle(a, add) + Adds two angles together (radians). +
+ +
+ + getAngle(p1, p2, transl) + Calculates the angle between two points. +
+ +
+ + getDistance(p1, p2) + Gets the distance between two points. +
+ +
+ + translate(p1, a, d) + Translates a point by a vector defined by angle and distance. This does not return a value but rather modifies the x and y values of p1. +
+ +
+ + translateX(x1, a, d) + Translates an x component of a coordinate by a vector defined by angle and distance. This returns its component translation. +
+ +
+ + translateY(y1, a, d) + Translates a y component of a coordinate by a vector defined by angle and distance. This returns its component translation. +
+ +
+
+ + + + + + + + + + + +
+
+ Method Detail +
+
+ + +
+ +
+ trigo.addAngle(a, add) + +
+
+ Adds two angles together (radians). + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ {Float} + + a + + Base angle. +
+ {Float} + + add + + The angle you're adding to the base angle. +
+ + + + + +
Returns:
+ + + + + + + +
+ + + The resultant angle, always between 0 and 2*pi. +
+ + + + +
+ + +
+ +
+ trigo.getAngle(p1, p2, transl) + +
+
+ Calculates the angle between two points. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + +
+ {Object} + + p1 + + This is an object containing x and y params for the first point. +
+ {Object} + + p2 + + This is an object containing x and y params for the second point. +
+ {Float} + + transl + + (Optional) Adds an angle (in radians) to the result. Defaults to 0. +
+ + + + + +
Returns:
+ + + + + + + +
+ + + The angle between points p1 and p2, plus transl. +
+ + + + +
+ + +
+ +
+ trigo.getDistance(p1, p2) + +
+
+ Gets the distance between two points. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + +
+ {Object} + + p1 + + This is an object containing x and y params for the first point. +
+ {Object} + + p2 + + This is an object containing x and y params for the second point. +
+ + + + + +
Returns:
+ + + + + + + +
+ + + The distance between p1 and p2. +
+ + + + +
+ + +
+ +
+ trigo.translate(p1, a, d) + +
+
+ Translates a point by a vector defined by angle and distance. This does not return a value but rather modifies the x and y values of p1. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + +
+ {Object} + + p1 + + This is an object containing x and y params for the point. +
+ {Float} + + a + + The angle of translation (rad). +
+ {Float} + + d + + The distance of translation. +
+ + + + + + + + +
+ + +
+ +
+ trigo.translateX(x1, a, d) + +
+
+ Translates an x component of a coordinate by a vector defined by angle and distance. This returns its component translation. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + +
+ {Float} + + x1 + + This is an x coordinate. +
+ {Float} + + a + + The angle of translation (rad). +
+ {Float} + + d + + The distance of translation. +
+ + + + + + + + +
+ + +
+ +
+ trigo.translateY(y1, a, d) + +
+
+ Translates a y component of a coordinate by a vector defined by angle and distance. This returns its component translation. + + + + +

+										
+									
+ + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + +
+ {Float} + + y1 + + This is a y coordinate. +
+ {Float} + + a + + The angle of translation (rad). +
+ {Float} + + d + + The distance of translation. +
+ + + + + + + + +
+ +
+
+ + +
+ + +
+ + Documentation generated by JsDoc Toolkit 2.3.2 on Wed Aug 18 2010 16:09:25 GMT-0400 (EDT) +
+ +
+
+ + + diff --git a/deps/akihabara-core-1.3.1/akihabara/docs/ui.js b/deps/akihabara-core-1.3.1/akihabara/docs/ui.js new file mode 100644 index 0000000..f013c2a --- /dev/null +++ b/deps/akihabara-core-1.3.1/akihabara/docs/ui.js @@ -0,0 +1,113 @@ +ui = { + toggleIndex: function() { + $('body').toggleClass('index-collapsed'); + var indexToggler = $('#index-toggler'); + if (encodeURIComponent(indexToggler.html()) == '%C2%AB') + indexToggler.html('»'); + else + indexToggler.html('«'); + }, + + toggleMethods: function() { + $.element.toggleClass(this, 'toggled'); + $('.sectionItems', this.parentNode.parentNode).toggleClass('invisible'); + }, + + toggleModule: function(module) { + if (module) { + var name = 'filter module-'+module; + + if ($('body').toggleClass(name).hasClass(name)) { + createCookie("jProtonDocModule", module); + } else { + eraseCookie("jProtonDocModule"); + } + } + ui.hideEmptySections(); + ui.updateFragmentLocation(); + }, + + hideEmptySections: function() { + var sections = $('.section'); + sections.each(function(i){ + + var count = 0; + var sectionItems = $(this).find('.sectionItems'); + + sectionItems.find('.sectionItem').each(function(){ + if ($.element.css(this, 'display') != 'none') + count++; + }); + + if (sectionItems.e.length > 0 && count == 0) + $.element.addClass(this, 'invisible'); + else + $.element.removeClass(this, 'invisible'); + }); + }, + + updateFragmentLocation: function() { + if (window.location.hash) + window.location.hash = window.location.hash; + }, + + updateModuleState: function() { + var module = readCookie("jProtonDocModule"); + if (module) { + $('body').addClass('filter module-'+module); + ui.hideEmptySections(); + } + ui.updateFragmentLocation(); + } +} + +window.onload = function() { + // Controle para alternar a exibição do outline + $('#index-toggler').attr('title', 'Alterna a exibição do outline'); + $('#index-toggler, #index-close').on('click', ui.toggleIndex); + + // Controle para alternar a exibição de métodos + $('.method-toggler').on('click', ui.toggleMethods); + + // Controle para filtro de módulos + $('.module-filter').attr('title', 'Liga/Desliga filtro do módulo'); + $.each(['core', 'css', 'dom', 'event', 'ajax'], function(i,e){ + $('.module-' + e + ' .module-filter').on('click', function(){ + ui.toggleModule(e); + }); + }); + + ui.updateModuleState(); + + if (typeof dp != 'undefined') + dp.SyntaxHighlighter.HighlightAll('code'); +} + +window.onunload = function() { + $.event.removeAll(); +} + +function createCookie(name,value,days) { + if (days) { + var date = new Date(); + date.setTime(date.getTime()+(days*24*60*60*1000)); + var expires = "; expires="+date.toGMTString(); + } + else var expires = ""; + document.cookie = name+"="+value+expires+"; path=/"; +} + +function readCookie(name) { + var nameEQ = name + "="; + var ca = document.cookie.split(';'); + for(var i=0;i < ca.length;i++) { + var c = ca[i]; + while (c.charAt(0)==' ') c = c.substring(1,c.length); + if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length); + } + return null; +} + +function eraseCookie(name) { + createCookie(name,"",-1); +} diff --git a/deps/akihabara-core-1.3.1/akihabara/dpad.png b/deps/akihabara-core-1.3.1/akihabara/dpad.png new file mode 100644 index 0000000..ff536b5 Binary files /dev/null and b/deps/akihabara-core-1.3.1/akihabara/dpad.png differ diff --git a/deps/akihabara-core-1.3.1/akihabara/fretboard.png b/deps/akihabara-core-1.3.1/akihabara/fretboard.png new file mode 100644 index 0000000..52cd354 Binary files /dev/null and b/deps/akihabara-core-1.3.1/akihabara/fretboard.png differ diff --git a/deps/akihabara-core-1.3.1/akihabara/gamecycle.js b/deps/akihabara-core-1.3.1/akihabara/gamecycle.js new file mode 100644 index 0000000..bc678a8 --- /dev/null +++ b/deps/akihabara-core-1.3.1/akihabara/gamecycle.js @@ -0,0 +1,429 @@ +// --- +// Copyright (c) 2010 Francesco Cottone, http://www.kesiev.com/ +// --- + +/** + * @namespace + * Gamecycle contains your basic game loop: intro, menus, + * crossfading between stages/lifes, gameover and ending. + */ +var gamecycle={ + + /** + * Gamecycle constructor - initializes a new game object + * + * @param id unique id of object + * @param group name of group to store the object in + */ + createMaingame:function(id,group) { + return gbox.addObject({ + id:id, + group:group, + counter:0, + difficulty:0, + + // state transition + state:50, + stateFirstIteration:true, + + hud:{}, + + /** + * This method is called whenever you load a new map. It's meant to be + * overridden when you create your game. + */ + changeLevel:function() { }, + + /** + * This method is called every time a player is "reborn". This method is + * meant to be overridden since you have to do garbage collection. + */ + newLife:function() { }, + + // game disclaimer animation (if needed) + gameDisclaimerAnimation:function(reset) { + return true; + }, + + // game intro animation + gameIntroAnimation:function(reset) { + if (reset) { + gbox.stopChannel("bgmusic"); + toys.resetToy(this,"default-blinker"); + } else { + gbox.blitFade(gbox.getBufferContext(),{alpha:1}); + return toys.text.blink(this,"default-blinker",gbox.getBufferContext(),{font:"small",text:"LETS BEGIN!",valign:gbox.ALIGN_MIDDLE,halign:gbox.ALIGN_CENTER,dx:0,dy:0,dw:gbox.getScreenW(),dh:gbox.getScreenH(),blinkspeed:5,times:6}); + } + }, + + // level intro animation + levelIntroAnimation:function(reset) { + if (reset) { + gbox.stopChannel("bgmusic"); + toys.resetToy(this,"default-blinker"); + } else { + gbox.blitFade(gbox.getBufferContext(),{alpha:1}); + return toys.text.blink(this,"default-blinker",gbox.getBufferContext(),{font:"small",text:"GET READY!",valign:gbox.ALIGN_MIDDLE,halign:gbox.ALIGN_CENTER,dx:0,dy:0,dw:gbox.getScreenW(),dh:gbox.getScreenH(),blinkspeed:5,times:6}); + } + }, + + // Life intro animation + newlifeIntroAnimation:function(reset) { + if (reset) { + gbox.stopChannel("bgmusic"); + toys.resetToy(this,"default-blinker"); + } else { + gbox.blitFade(gbox.getBufferContext(),{alpha:1}); + return toys.text.fixed(this,"default-blinker",gbox.getBufferContext(),{font:"small",text:"GET READY!",valign:gbox.ALIGN_MIDDLE,halign:gbox.ALIGN_CENTER,dx:0,dy:0,dw:gbox.getScreenW(),dh:gbox.getScreenH(),time:30}); + } + }, + + // gameover animation + gameoverIntroAnimation:function(reset) { + if (reset) { + gbox.stopChannel("bgmusic"); + toys.resetToy(this,"default-blinker"); + } else { + gbox.blitFade(gbox.getBufferContext(),{alpha:1}); + return toys.text.fixed(this,"default-blinker",gbox.getBufferContext(),{font:"small",text:"GAME OVER",valign:gbox.ALIGN_MIDDLE,halign:gbox.ALIGN_CENTER,dx:0,dy:0,dw:gbox.getScreenW(),dh:gbox.getScreenH(),time:50}); + } + }, + + // game title animation + gameTitleIntroAnimation:function(reset) { + if (reset) + gbox.stopChannel("bgmusic"); + else { + gbox.blitFade(gbox.getBufferContext(),{alpha:1}); + gbox.blitText(gbox.getBufferContext(),{font:"small",text:"GAME TITLE",valign:gbox.ALIGN_MIDDLE,halign:gbox.ALIGN_CENTER,dx:0,dy:0,dw:gbox.getScreenW(),dh:gbox.getScreenH()-100}); + } + }, + + // End level animation + endlevelIntroAnimation:function(reset) { + if (reset) { + toys.resetToy(this,"default-blinker"); + } else { + return toys.text.blink(this,"default-blinker",gbox.getBufferContext(),{font:"small",text:"WELL DONE!",valign:gbox.ALIGN_MIDDLE,halign:gbox.ALIGN_CENTER,dx:0,dy:0,dw:gbox.getScreenW(),dh:gbox.getScreenH(),blinkspeed:5,times:10}); + } + }, + + // Game ending + gameEndingIntroAnimation:function(reset) { + if (reset) { + toys.resetToy(this,"default-blinker"); + } else { + gbox.blitFade(gbox.getBufferContext(),{alpha:1}); + return toys.text.blink(this,"default-blinker",gbox.getBufferContext(),{font:"small",text:"CONGRATULATIONS!",valign:gbox.ALIGN_MIDDLE,halign:gbox.ALIGN_CENTER,dx:0,dy:0,dw:gbox.getScreenW(),dh:gbox.getScreenH(),blinkspeed:5,times:10}); + } + }, + + // PRESS START + pressStartIntroAnimation:function(reset) { + if (reset) { + toys.resetToy(this,"default-blinker"); + } else { + toys.text.blink(this,"default-blinker",gbox.getBufferContext(),{font:"small",text:"PRESS A TO START",valign:gbox.ALIGN_MIDDLE,halign:gbox.ALIGN_CENTER,dx:0,dy:Math.floor(gbox.getScreenH()/3),dw:gbox.getScreenW(),dh:Math.floor(gbox.getScreenH()/3)*2,blinkspeed:10}); + return gbox.keyIsHit("a"); + } + }, + + /** + * This method is called when the player dies. + */ + gameIsOver:function() { return true; }, + + /** + * Actions done during the game (i.e. stage is clear or other ending conditions) + */ + gameEvents:function() { + + }, + + gameMenu:function(reset) { + if (reset) { + toys.resetToy(this,"difficulty"); + } else { + gbox.blitFade(gbox.getBufferContext(),{alpha:0.5}); + if (toys.ui.menu(this,"difficulty",{audiooption:"default-menu-option",audioconfirm:"default-menu-confirm",font:"small",keys:{up:"up",down:"down",ok:"a",cancel:"b"},selector:">",items:["EASY","NORMAL","HARD"],x:10,y:10})) { + if (toys.getToyValue(this,"difficulty","ok") == -1) return -1; + else { + this.difficulty=toys.getToyValue(this,"difficulty","selected"); + return true; + } + } + return false; + } + }, + + // CHECK + + gameIsHold:function() { // Use this clause to check collision and kill player: if true the level is changing + return (this.state==400)||(this.state==401); + }, + + isCompleted:function() { + return (this.state==800); + }, + + // GAME CYCLE + + getNextLevel:function() { + return this._nextlevel; + }, + + gotoLevel:function(level) { + this._nextlevel=level; + this.setState(400); + }, + + playerDied:function(data) { + this._loselife=data; + this.setState(500); + }, + + gameIsCompleted:function() { + this.setState(800); + }, + + // private methods + + /** + * Changes the current game state + * + * @param st state number + */ + setState:function(st) { + this.state=st; + this.stateFirstIteration=true; + }, + + /* + * Removes all objects in each group except the game + * cycle group. Used for garbage collection when resetting the game. + */ + _resetGroups:function() { + var g=gbox.getGroups(); + for (var i=0;iprio) break; else i=this.data[i].__next; + if (i==null) { // if last, chain in queue + obj.__next=null; + obj.__first=this.last; + this.data[this.last].__next=nid; + this.last=nid; + } else { // else reconnect objects + obj.__first=this.data[i].__first; + obj.__next=i; + this.data[i].__first=nid; + if (obj.__first!=null) this.data[obj.__first].__next=nid; else this.first=nid; + } + + } + obj.__prio=prio; + obj.__id=nid; + this.data[nid]=obj; + return nid; + }, + setPrio:function(obd,prio) { + if (this.data[obd].__prio==prio) return; + if (this.first!=this.last) + if (this.data[obd].__prio=prio) break; else i=this.data[i].__next; + if ((i==null)||(this.data[i].__first!=this.data[obd].__id)) { + // disconnect + this.disconnect(obd); + // Reconnect + if (i==null) { + this.data[this.last].__next=this.data[obd].__id; + this.data[obd].__first=this.last; + this.data[obd].__next=null; + this.last=this.data[obd].__id; + } else { + this.data[obd].__first=this.data[i].__first; + this.data[obd].__next=i; + this.data[i].__first=this.data[obd].__id; + if (this.data[obd].__first!=null) this.data[this.data[obd].__first].__next=this.data[obd].__id; else this.first=this.data[obd].__id; + } + } + } + } else { + if (this.data[obd].__id!=this.first) { + var i=this.data[obd].__first; + while (i!=null) + if (this.data[i].__prio<=prio) break; else i=this.data[i].__first; + if ((i==null)||(this.data[i].__next!=this.data[obd].__id)) { + // disconnect + this.disconnect(obd); + if (i==null) { + this.data[this.first].__first=this.data[obd].__id; + this.data[obd].__first=null; + this.data[obd].__next=this.first; + this.first=this.data[obd].__id; + } else { + this.data[obd].__first=i; + this.data[obd].__next=this.data[i].__next; + this.data[i].__next=this.data[obd].__id; + if (this.data[obd].__next!=null) this.data[this.data[obd].__next].__first=this.data[obd].__id; else this.last=this.data[obd].__id; + } + } + } + } + this.data[obd].__prio=prio; + }, + remove:function(obd) { + this.disconnect(obd); + this.gar.push(this.data[obd].__id); + delete this.data[this.data[obd].__id]; + } + } + } +} + +// A special circular queue with some features useful for the resource loader +var cyclelist={ + create:function(size) { + return { + _head:0, + _tail:0, + _data:[], + _size:(size?size:10), + _total:0, + _done:0, + _current:null, + getTotal:function(){return this._total}, // Number of elements to be "poped" + getDone:function(){return this._done}, // Number of popped elements since the last empty + getSize:function(){return this._size}, // The maximum number of elements in the queue + isProcessing:function(){return this._current!=null}, // The last pop was not a null (i.e. the queue returned a valid object) + isEnded:function(){return (this._head==this._tail)}, // There are other elements in the queue + isBusy:function(){return this.isProcessing()||!this.isEnded()}, // There are elements in the queue/the last one pop returned an object that is being processed + getCurrent:function(){return this._current}, // Return the last popped element + push:function(d) { + this._data[this._head]=d; + this._head=(this._head+1)%this._size; + this._total++; + }, + pop:function() { + if (this.isEnded()) { + this._total=0; + this._done=0; + this._current=null; + } else { + this._current=this._data[this._tail]; + this._tail=(this._tail+1)%this._size; + this._done++; + } + return this._current; + }, + dump:function() { + var r=""; + for (var i=0;iimg.width) { dw=(dw/sw)*(img.width-sx);sw=img.width-sx;} + if (sy+sh>img.height) { dh=(dh/sh)*(img.height-sy);sh=img.height-sy;} + try { if ((sh>0)&&(sw>0)&&(sxgbox._autoskip.hiidle)&&(gbox._frameskip>gbox._autoskip.min)) gbox.setFrameskip(gbox._frameskip-1); + if (gbox._statbar) gbox.debugGetstats(); + this._gametimer=setTimeout(gbox.go,(gbox._framestart<=0?1:gbox._framestart)); + }, + /** + * Apply FSEs to the screen. Is called each frame. + */ + _applyfse:function(){ + switch (gbox._flags.fse) { + case "scanlines": { + gbox.getBufferContext().drawImage(gbox.getCanvas("-gbox-fse"),0,0); + break; + } + case "lcd":{ + if (gbox._localflags.fselcdget&&gbox.getBuffer()) + gbox.getCanvasContext("-gbox-fse-new").drawImage(gbox.getBuffer(),0,0); + gbox.getBufferContext().save(); + gbox.getBufferContext().globalAlpha=0.5; + gbox.getBufferContext().drawImage(gbox.getCanvas("-gbox-fse-old"),0,0); + gbox.getBufferContext().restore(); + if (gbox._localflags.fselcdget) + gbox.swapCanvas("-gbox-fse-new","-gbox-fse-old"); + gbox._localflags.fselcdget=!gbox._localflags.fselcdget; + break; + } + } + }, + /** + * Register the code that have to be executed once the page is loaded. Usually contains game initialization, resources loading etc. + */ + onLoad:function(code) { + this.addEventListener(window,'load',code); + }, + /** + * This function is called once per frame. This is where the basic rendering and processing of groups occurs. + */ + go:function() { + if (gbox._loaderqueue.isBusy()) { + if (gbox._gamewaiting==1) { + gbox.blitFade(gbox._screen.getContext("2d"),{alpha:0.5}); + gbox.blitText(gbox._screen.getContext("2d"),{font:"_dbf",dx:2,dy:2,text:"LOADING..."}); + gbox._gamewaiting=true; + } + if (gbox._gamewaiting<=1) { + var bw=Math.floor(((gbox.getScreenW()-4)*gbox._loaderqueue.getDone())/gbox._loaderqueue.getSize()); + gbox._screen.getContext("2d").globalAlpha=1; + gbox._screen.getContext("2d").fillStyle = gbox._splash.gaugeLittleBackColor; + gbox._screen.getContext("2d").fillRect(0,4+gbox.getFont("_dbf").tileh,gbox.getScreenW(),1); + gbox._screen.getContext("2d").fillStyle = gbox._splash.gaugeLittleColor; + gbox._screen.getContext("2d").fillRect(0,4+gbox.getFont("_dbf").tileh,(bw>0?bw:0),1); + gbox._screen.getContext("2d").restore(); + gbox.setStatBar("Loading... ("+gbox._loaderqueue.getDone()+"/"+gbox._loaderqueue.getTotal()+")"); + } + if (gbox._gamewaiting) gbox._gamewaiting--; + setTimeout(gbox.go,1000); + } else { + gbox._gamewaiting=3; + gbox._framestart=new Date().getTime(); + var gr=""; + for (var g=0;g=gbox._frameskip) { + if (gbox._localflags.fse) gbox._applyfse(); + if (gbox._db) gbox.blitImageToScreen(gbox.getBuffer()); + gbox._fskid=0; + } else gbox._fskid++; + + gbox.purgeGarbage(); + + if (gbox._zindexch.length) { + + for (var i=0;i0?" ("+gbox._frameskip+"skip)":"")+" | "; + var cnt=0; + for (var g=0;g"; + id=gbox._zindex.data[id].__next; + } + */ + gbox.setStatBar(statline); + }, + + setZindex:function(th,z) { + if ((th.__zt==null)||(th.zindex!=z)) { + th.zindex=z; + this._zindexch.push({o:{g:th.group,o:th.id},z:z}); + } + }, + + /** + * Returns true if a given key in this._keymap is pressed. Only returns true on the transition from unpressed to pressed. + * @param {String} id A key in the keymap. By default, one of: "up" "down" "left" "right" "a" "b" "c" + * @returns {Boolean} True if the given key is transitioning from unpressed to pressed in this frame. + */ + keyIsHit:function(id) { return this._keyboard[this._keymap[id]]==1}, + + /** + * Returns true if a given key in this._keymap is being held down. Returns true as long as the key is held down. + * @param {String} id A key in the keymap. By default, one of: "up" "down" "left" "right" "a" "b" "c" + * @returns {Boolean} True if the given key is held down. + */ + keyIsPressed:function(id) { return this._keyboard[this._keymap[id]]>0}, + + /** + * Returns true if a given key in this._keymap has been held down for at least one frame. Will not return true if a key + * is quickly tapped, only once it has been held down for a frame. + * @param {String} id A key in the keymap. By default, one of: "up" "down" "left" "right" "a" "b" "c" + * @returns {Boolean} True if the given key has been held down for at least one frame. + */ + keyIsHold:function(id) { return this._keyboard[this._keymap[id]]>1}, + + /** + * Returns true if a given key in this._keymap is released. Only returns true on the transition from pressed to unpressed. + * @param {String} id A key in the keymap. By default, one of: "up" "down" "left" "right" "a" "b" "c" + * @returns {Boolean} True if the given key is transitioning from pressed to unpressed in this frame. + */ + keyIsReleased:function(id) { return this._keyboard[this._keymap[id]]==-1}, + + _savesettings:function() { + var saved=""; + for (var k in this._keymap) saved+="keymap-"+k+":"+this._keymap[k]+"~"; + for (var f in this._flags) { + switch (this._flagstype[f]) { + case "check": { saved+="flag-"+f+":"+(this._flags[f]?1:0)+"~"; break; } + case "list": { saved+="flag-"+f+":"+this._flags[f]+"~"; break; } + } + } + this.dataSave("sys",saved); + }, + _loadsettings:function() { + var cfg=this.dataLoad("sys"); + if (cfg!==null) { + cfg=cfg.split("~"); + var kv; + var mk; + for (var i=0;iviewdata.h) this._camera.y=viewdata.h-this._screenh; + if (this._camera.y<0) this._camera.y=0; + }, + + /** + * Sets the x value of the current camera object. + * @param {Integer} x The camera object's new x value. + * @param {Object} viewdata An object containing parameters h and w, which are a bounding box that the camera is + * not supposed to leave. For example, to use your map as a bounding area for the camera, pass along {w: map.w, h: map.h}. + */ + setCameraX:function(x,viewdata) { + this._camera.x=x; + if (this._camera.x+this._camera.w>viewdata.w) this._camera.x=viewdata.w-this._screenw; + if (this._camera.x<0) this._camera.x=0; + }, + + /** + * Centers the camera. + * @param {Object} data An object containing x and y parameters -- typically the object you wish to center the camera on. + * @param {Object} viewdata An object containing parameters h and w, which are a bounding box that the camera is + * not supposed to leave. For example, to use your map as a bounding area for the camera, pass along {w: map.w, h: map.h}. + * @example + * // Center the camera on the player object + * gbox.centerCamera(gbox.getObject('player', 'player_id'), {w: map.w, h: map.h}); + */ + centerCamera:function(data,viewdata) { + this.setCameraX(data.x-this._screenhw,viewdata); + this.setCameraY(data.y-this._screenhh,viewdata); + }, + + /** + * Get an array containing the names of each group in the game, in order of rendering. + * @returns {Array} An array of group names. + * @example + * grouplist = gbox.getGroups(); + * grouplist; // => ["background", "player", "enemy", "game"] + */ + getGroups:function() { return this._groups; }, + + /** + * Defines the names of each group in the game along with their rendering order. + * @param {Array} g An array of strings of group names, in the order in which the groups should be rendered. So + * g[0] will contain the first group to render, g[1] the second group to render, etc. + */ + setGroups:function(g){ + this._groups=g; + this._groupplay[gbox.ZINDEX_LAYER]=true; + for (var i=0;iNOTE: this does not return a copy of the object you've requested! Any modifications you make + * to the object returned are directly modifying the object you requested. + * @param {String} group The id of the group that contains the object. + * @param {String} id The id of the instance of the object. + * @returns {Object} The object requested. + * @example + * // Find the player and reduce health by half. + * playertemp = gbox.getObject('player','player_id'); + * player.health = player.health/2; + */ + getObject:function(group,id) {return this._objects[group][id]}, + + /** + * Creates a font. + * @param {Object} data An object containing:
  • id: the id of the font
  • + *
  • image: reference to the font image loaded (must contain font character tiles in ASCII order)
  • + *
  • firstletter: the ASCII character that the font image's first character corresponds to
  • + *
  • tileh: height in pixels of the character tiles
  • + *
  • tilew: width in pixels of the character tiles
  • + *
  • tilerow: width in pixels of each row in the font image
  • + *
  • gapx: x-coord gap between tile columns, in pixels
  • + *
  • gapy: y-coord gap between tile rows, in pixels
+ * @example + * gbox.addImage('font', 'font.png'); + * gbox.addFont({ id: 'small', image: 'font', firstletter: ' ', tileh: 8, tilew: 8, tilerow: 255, gapx: 0, gapy: 0 }); + */ + addFont:function(data) { + data.tilehh=Math.floor(data.tileh/2); + data.tilehw=Math.floor(data.tilew/2); + this._fonts[data.id]=data; + this._fonts[data.id].firstascii=data.firstletter.charCodeAt(0); + }, + + /** + * Returns a font object containing data about the font. + * @param {String} id The id of the font, as set in gbox.addFont. + */ + getFont:function(id) { + return this._fonts[id]; + }, + + /** + * Deletes an object, keeping a record of its group and id in gbox._garbage. + * @param {Object} obj The object you wish to delete. + */ + trashObject:function(obj) { + if (!this._garbage[obj.group]) this._garbage[obj.group]={}; + this._garbage[obj.group][obj.id]=1; + obj.__trashing=true; + }, + + /** + * Clears the record held in gbox._garbage of what has been deleted. The "onpurge" method is called on the object before being deleted (for canvas deallocation etc.) + */ + purgeGarbage:function() { + for (var group in this._garbage) + for (var id in this._garbage[group]) { + if (this._objects[group][id]["onpurge"]) this._objects[group][id].onpurge(); + if (this._objects[group][id].__zt!=null) + this._zindex.remove(this._objects[group][id].__zt) + delete this._objects[group][id]; + } + gbox._garbage={}; + }, + + /** + * Deletes every object in a given group. + * @param {String} group The group id. + */ + trashGroup:function(group) { + if (!this._garbage[group]) this._garbage[group]={}; + for (var obj in this._objects[group]) + this._garbage[group][obj]=1; + }, + + /** + * Returns whether an object is due to be trashed. Useful in cases you want to check if + * an object is marked as trash before it is actually deleted. + * @param {Object} o The object you're checking. + * @returns {Boolean} True if the object is marked as trash. + */ + objectIsTrash:function(o) { return o.__trashing }, + + /** + * Creates a new game object. Generally speaking you pass a fully-defined object as the parameter (including a group, id, tileset, and so on). + * A group must be specified, or the program will crash. If no id is specified, then it will automatically provide + * an id of 'obj-XXXX' where 'XXXX' is an automatically incrementing integer. This is where the initialize, first, and blit + * functions are defined, as well. + * @param {Object} data The object you wish to create. + * @returns {Object} The object you created. + * @example + * data = { + * group: 'player', + * id: 'player_id', + * tileset: 'player_tiles', + * x: 0, + * y: 0, + * initialize: function() { + this.x = 10; + this.y = 10; + }, + * }; + * gbox.addObject(data); + */ + addObject:function(data) { + // Extras + if (!data.id) { + data.id="obj-"+this._autoid; + this._autoid=(this._autoid+1)%1000; + } + if (data.tileset) { + if (data.h==null) data.h=this._tiles[data.tileset].tileh; + if (data.w==null) data.w=this._tiles[data.tileset].tilew; + if (data.hw==null) data.hw=this._tiles[data.tileset].tilehw; + if (data.hh==null) data.hh=this._tiles[data.tileset].tilehh; + } + this._objects[data.group][data.id]=data; + if (data.zindex!=null) + this.setZindex(this._objects[data.group][data.id],data.zindex); + return this._objects[data.group][data.id]; + }, + + /** + * Returns whether a given group contains no objets. + * @param {String} gid The group you're checking. + * @returns {Boolean} True if the group contains no objects. + */ + groupIsEmpty:function(gid) { for (var i in this._objects[gid]) return false; return true; }, + + /** + * Creates a new canvas. By default, the width and height is the current gbox._screenw and gbox._screenh, + * but it can also be set by passing in a data object with the appropriate parameters. + * @param {String} id The id of the new canvas. + * @param {Object} data (Optional) The height and width of the new canvas, contained in data.h and data.w parameters. + * @example + * gbox.createCanvas('newCanvas', {w: 640, h: 480}); + */ + createCanvas:function(id,data) { + this.deleteCanvas(id); + var w=(data&&data.w?data.w:this._screenw); + var h=(data&&data.h?data.h:this._screenh); + this._canvas[id]=document.createElement("canvas"); + this._canvas[id].setAttribute('height',h); + this._canvas[id].setAttribute('width',w); + this._canvas[id].getContext("2d").save(); + this._canvas[id].getContext("2d").globalAlpha=0; + this._canvas[id].getContext("2d").fillStyle = gbox.COLOR_BLACK; + this._canvas[id].getContext("2d").fillRect(0,0,w,h); + this._canvas[id].getContext("2d").restore(); + }, + /** + * Swap two canvas using their ID. + * @param {String} id The id of the first canvas. + * @param {String} id The id of the second canvas. + * @example + * gbox.swapCanvas('canvas1','canvas2'); + */ + swapCanvas:function(a,b) { + var swp=this._canvas[a]; + this._canvas[a]=this._canvas[b]; + this._canvas[b]=swp; + }, + /** + * Deletes a given canvas. + * @param {String} id The id of the canvas to be deleted. + */ + deleteCanvas:function(id) { + if (this._canvas[id]) delete this._canvas[id]; + }, + + /** + * Checks to see if an image was successfully loaded. + * @param {String} id The id of the image. + * @returns {Boolean} True if the image has been loaded. + */ + imageIsLoaded:function(id){ return this._images[id]&&(this._images[id].getAttribute("wasloaded"))&&this._images[id].width }, + + /** + * Gets information about a loaded image. + * @param {String} id The id of the image. + * @returns {Object} A DOM Image element, including the URL and last modified date of the image, its ID, and whether it was loaded successfully. + * @example + * image = gbox.getImage('logo'); + * image; // => ? + */ + getImage:function(id){return this._images[id]}, + + /** + * Gets the buffer canvas (automatically created by gbox.initScreen). + * @returns {Object} A DOM Canvas element, including the width and height of the canvas. + */ + getBuffer:function(){return (gbox._fskid>=gbox._frameskip?(this._db?this.getCanvas("_buffer"):this._screen):null)}, + + /** + * Gets the buffer canvas context. + * @returns {Object} A DOM Canvas context object. + */ + getBufferContext:function(){ return (gbox._fskid>=gbox._frameskip?(this._db?this.getCanvasContext("_buffer"):this._screen.getContext("2d")):null) }, + + /** + * Gets a given canvas. + * @param {Object} id The identifier of the canvas. + * @returns {Object} A DOM Canvas element, including the width and height of the canvas. + */ + getCanvas:function(id){return this._canvas[id]}, + + /** + * Gets the two-dimensional canvas context of a given canvas. The object it returns contains all the drawing functions for the canvas. + * See W3C and + * Mozilla Developer Center for details. + * @param {Object} id The identifier of the canvas. + * @returns {Object} A DOM Canvas context object. + */ + getCanvasContext:function(id){return this.getCanvas(id).getContext("2d");}, + + /** + * Adds an image file to the loader, assigning it to an ID. If adding an image to an existing ID, it checks to see if the file you're + * adding is different than the one currently assigned to the ID. If it's different, it overwrites the old image. If it's the same, then + * no action is taken. + * @param {String} id The identifier of the image. + * @param {String} filename The file name of the image. + */ + addImage:function(id,filename) { + if (this._images[id]) + if (this._images[id].getAttribute("src_org")==filename) + return; + else + delete this._images[id]; + this._addtoloader({type:"image",id:id,filename:filename}); + }, + + /** + * Deletes an image currently in use. Does not delete the image file, but removes it from Akihabara's image list. + * @param {String} id The identifier of the image. + */ + deleteImage:function(id) { + delete this._images[id]; + }, + + /** + * Creates a new Akihabara tileset, adding it to the engine. + * @param {Object} t An object containing:
  • id {String}: the new id of the tileset
  • + *
  • image {String}: reference to the tileset image loaded
  • + *
  • tileh {Integer}: height in pixels of the tiles
  • + *
  • tilew {Integer}: width in pixels of the tiles
  • + *
  • tilerow {Integer}: width in pixels of each row in the font image
  • + *
  • gapx {Integer}: x-coord gap between tile columns, in pixels
  • + *
  • gapy {Integer}: y-coord gap between tile rows, in pixels
+ */ + addTiles:function(t) { + t.tilehh=Math.floor(t.tileh/2); + t.tilehw=Math.floor(t.tilew/2); + this._tiles[t.id]=t; + }, + + /** + * Gets an Akihabara tileset, adding it to the engine. + * @param {String} t The ID of a tileset. + * @returns An object containing:
  • id {String}: the new id of the tileset
  • + *
  • image {String}: reference to the tileset image loaded
  • + *
  • tileh {Integer}: height in pixels of the tiles
  • + *
  • tilew {Integer}: width in pixels of the tiles
  • + *
  • tilerow {Integer}: width in pixels of each row in the font image
  • + *
  • gapx {Integer}: x-coord gap between tile columns, in pixels
  • + *
  • gapy {Integer}: y-coord gap between tile rows, in pixels
+ */ + getTiles:function(t) { return this._tiles[t] }, + + /** + * Loads the initial splash screen and debugging font, then calls gbox._waitforloaded which adds to the game all the previously + * defined resources. Once gbox._waitforloaded is done, it calls the callback function cb. + * @params {String} cb The name of the function to be called when all assets are done loading. + */ + loadAll:function(cb) { + // Setup logger + if (this._canlog) this.log=console.log; + // Set the callback function, which is called after the resources are loaded. + if (!this._cb) this._cb = cb; + // Default stuff + this.addImage("_dbf","akihabara/debugfont.png"); + if (this._splash.background) this.addImage("_splash",this._splash.background); + gbox.addFont({id:"_dbf",image:"_dbf",firstletter:" ",tileh:5,tilew:4,tilerow:16,gapx:0,gapy:0}); + if (!gbox._splash.minimalTime) + gbox._minimalexpired=2; + this._waitforloaded(); + }, + + _implicitsargs:function(data) { + if (data.camera) { + data.dx-=this._camera.x; + data.dy-=this._camera.y; + } + if (data.sourcecamera) { + data.x=this._camera.x*(data.parallaxx?data.parallaxx:1); + data.y=this._camera.y*(data.parallaxy?data.parallaxy:1); + } + }, + + /** + * Draws a tile to a canvas context + * @param {Object} tox The canvas context to be drawn on. + * @param {Object} data An object containing data about the tile to be drawn, including: + *
  • tileset {String}: the id of the tileset
  • + *
  • tile {Integer}: the index of the tile within the tileset to be drawn
  • + *
  • dx {Integer}: x coordinate to draw the tile at
  • + *
  • dy {Integer}: y coordinate to draw the tile at
  • + *
  • fliph {Integer}: horizontal flip, either 1 or -1
  • + *
  • flipv {Integer}: vertical flip, either 1 or -1
  • + *
  • alpha {Float}: alpha value (0 is transparent, 1 is opaque)
+ * @example + * // from capman, draws an current object's tile, called from inside its blit function + * gbox.blitTile(gbox.getBufferContext(),{tileset:this.tileset,tile:this.frame,dx:this.x,dy:this.y,fliph:this.fliph,flipv:this.flipv,camera:this.camera,alpha:1}); + */ + blitTile:function(tox,data) { + if (tox==null) return; + var ts=this._tiles[data.tileset]; + var img=this.getImage(ts.image); + this._implicitsargs(data); + tox.save(); + tox.globalAlpha=(data.alpha?data.alpha:1); + tox.translate((data.fliph?ts.tilew:0), (data.flipv?ts.tileh:0)); tox.scale((data.fliph?-1:1), (data.flipv?-1:1)); + this._safedrawimage(tox,img, ts.gapx+(ts.tilew*(data.tile%ts.tilerow)),ts.gapy+(ts.tileh*Math.floor(data.tile/ts.tilerow)),(data.w==null?ts.tilew:data.w),(data.h==null?ts.tileh:data.h),data.dx*(data.fliph?-1:1),data.dy*(data.flipv?-1:1),(data.w?data.w:ts.tilew),(data.h?data.h:ts.tileh)); + tox.restore(); + }, + + /** + * Draws an image to a canvas context + * @param {Object} tox The canvas context to be drawn on. + * @param {Object} image The image to draw. Must be a DOM Image element, typicallly accessed via gbox.getImage + * @param {Object} data An object containing data about the tile to be drawn, including: + *
  • dx {Integer}: (required) x coordinate to draw the image at
  • + *
  • dy {Integer}: (required) y coordinate to draw the image at
  • + *
  • fliph {Integer}: horizontal flip, either 1 or -1
  • + *
  • flipv {Integer}: vertical flip, either 1 or -1
  • + *
  • alpha {Float}: alpha value (0 is transparent, 1 is opaque)
+ * @example + * // draw an image at (100,100) + * gbox.blitAll(gbox.getBufferContext(),gbox.getImage("image_id"),{dx:100,dy:100}); + */ + blitAll:function(tox,image,data) { + if (tox==null) return; + this._implicitsargs(data); + tox.save(); + tox.globalAlpha=(data.alpha?data.alpha:1); + tox.translate((data.fliph?image.width:0), (data.flipv?image.height:0)); tox.scale((data.fliph?-1:1), (data.flipv?-1:1)); + this._safedrawimage(tox,image, 0,0, image.width,image.height,data.dx*(data.fliph?-1:1),data.dy*(data.flipv?-1:1),image.width,image.height); + tox.restore(); + }, + + blit:function(tox,image,data) { + if (tox==null) return; + this._implicitsargs(data); + tox.save(); + tox.globalAlpha=(data.alpha?data.alpha:1); + tox.translate((data.fliph?data.dw:0), (data.flipv?data.dh:0)); tox.scale((data.fliph?-1:1), (data.flipv?-1:1)); + this._safedrawimage(tox,image,(data.x?data.x:0), (data.y?data.y:0),(data.w?data.w:data.dw),(data.h?data.h:data.dh),data.dx*(data.fliph?-1:1),data.dy*(data.flipv?-1:1),data.dw,data.dh); + tox.restore(); + }, + + + /** + * Draws a tilemap to a canvas context + * @param {Object} tox The canvas context to be drawn on. + * @param {Object} data An object containing a set of tilemap data, including: + *
  • tileset {String}: (required) the id of the tileset the tilemap is based on
  • + *
  • map {Array}: an array whose x and y coord represent the tilemap coordinates, containing integers that correspond to the index of a given tile (or null for no tile)
+ */ + blitTilemap:function(tox,data) { + if (tox==null) return; + var ts=this._tiles[data.tileset]; + for (var y=0;y
  • font {String}: (required) the id of font to draw the text with
  • + *
  • text {String}: (required) the text to display
  • + *
  • dx {Integer}: (required) the x coordinate to draw the text at
  • + *
  • dy {Integer}: (required) the y coordinate to draw the text at
  • + *
  • dw {Integer}: the width of the text area -- required if you define data.halign
  • + *
  • dh {Integer}: the height of the text area -- required if you define data.valign
  • + *
  • valign {Integer}: either gbox.ALIGN_BOTTOM (aligns from the bottom of the text area) or gbox.ALIGN_MIDDLE (vertically centers text in text area)
  • + *
  • halign {Integer}: either gbox.ALIGN_RIGHT (aligns to the right hand side of text area) or gbox.ALIGN_CENTER (horizontallly centers text in text area)
  • + *
  • alpha {Float}: alpha value (0 is transparent, 1 is opaque)
  • + */ + blitText:function(tox,data) { + if (tox==null) return; + data.text+=""; // Convert to string. + var fn=this._fonts[data.font]; + var tile=0; + this._implicitsargs(data); + var dx=data.dx; + var dy=data.dy; + if (data.valign==gbox.ALIGN_BOTTOM) dy = dy+data.dh-fn.tileh; + else if (data.valign==gbox.ALIGN_MIDDLE) dy = dy+Math.floor(data.dh/2)-fn.tileh; + if (data.halign==gbox.ALIGN_RIGHT) dx = dx+data.dw-(data.text.length*fn.tilew); + else if (data.halign==gbox.ALIGN_CENTER) dx = dx+Math.floor((data.dw-(data.text.length*fn.tilew))/2); + tox.save(); + tox.globalAlpha=(data.alpha?data.alpha:1); + for (var y=0;y=0) { + if (data.clear) tox.clearRect(dx+(y*fn.tilew),dy,(data.w?data.w:fn.tilew),(data.h?data.h:fn.tileh)); + this._safedrawimage(tox,this.getImage(fn.image), fn.gapx+(fn.tilew*(tile%fn.tilerow)), + fn.gapy+(fn.tileh*Math.floor(tile/fn.tilerow)),fn.tilew,fn.tileh,dx+(y*fn.tilew),dy,(data.w?data.w:fn.tilew),(data.h?data.h:fn.tileh)); + } + } + tox.restore(); + }, + + /** + * Clears a rectangular area of a canvas context. + * @param {Object} image The canvas context to be drawn on. + * @param {Object} data An object containing a set of data, including: + *
    • x {Integer}: (required) the x coordinate of the top-left corner of the rectangle
    • + *
    • y {Integer}: (required) the y coordinate of the top-left corner of the rectangle
    • + *
    • w {Integer}: the width of the box; defaults to canvas width
    • + *
    • h {Integer}: the height the box; defaults to canvas height
    + */ + blitClear:function(image,data) { + if (image==null) return; + if (data==null) data={x:0,y:0}; + this._implicitsargs(data); + image.clearRect(data.x,data.y,(data.w==null?image.canvas.width:data.w),(data.h==null?image.canvas.height:data.h)); + }, + + /** + * Draws an image directly to the screen's current canvas context. Used internally in gbox.go(). Probably shouldn't be used otherwise. + */ + blitImageToScreen:function(image) { + this._screen.getContext("2d").drawImage(image,0,0); + }, + + /** + * Draws a filled rectangle over an entire canvas context. + * @param {Object} tox The canvas context to be filled. + * @param {Object} data An object containing a set of data, including: + *
    • alpha {Float}: the alpha value of the rectangle; defaults to 1
    • + *
    • color {Object}: the color of the box, formatted rgb(rValue, gValue, bValue); default black
    + */ + blitFade:function(tox,data) { + if (tox) this.blitRect(tox,{x:0,y:0,w:tox.canvas.width,h:tox.canvas.height,alpha:data.alpha,color:data.color}); + }, + + /** + * Draws a filled rectangle to a canvas context. + * @param {Object} tox The canvas context to be drawn on. + * @param {Object} data An object containing a set of data, including: + *
    • x {Integer}: (required) the x coordinate of the top-left corner of the rectangle
    • + *
    • y {Integer}: (required) the y coordinate of the top-left corner of the rectangle
    • + *
    • w {Integer}: (required) the width of the box
    • + *
    • h {Integer}: (required) the height the box
    • + *
    • alpha {Float}: the alpha value of the rectangle; defaults to 1
    • + *
    • color {Object}: the color of the box, formatted rgb(rValue, gValue, bValue); default black
    + */ + blitRect:function(tox,data) { + if (tox==null) return; + tox.save(); + tox.globalAlpha=(data.alpha?data.alpha:1); + tox.fillStyle = (data.color?data.color:gbox.COLOR_BLACK); + tox.fillRect(data.x,data.y,data.w,data.h); + tox.restore(); + }, + + /** + * Calculates a box collision between two collision boxes within a given tolerance. A higher tolerance means less precise collision. + * @param {Object} o1 A collision box you're testing for collision. Must contain: + *
    • x {Integer}: (required) the x coordinate of the object's origin; assumes the Akihabara default of top-left being the origin
    • + *
    • y {Integer}: (required) the y coordinate of the object's origin; assumes the Akihabara default of top-left being the origin
    • + *
    • w {Integer}: (required) the width of the box
    • + *
    • h {Integer}: (required) the height the box
    + * @param {Object} o2 A collision box you're testing for collision. Must contain: + *
    • x {Integer}: (required) the x coordinate of the object's origin; assumes the Akihabara default of top-left being the origin
    • + *
    • y {Integer}: (required) the y coordinate of the object's origin; assumes the Akihabara default of top-left being the origin
    • + *
    • w {Integer}: (required) the width of the box
    • + *
    • h {Integer}: (required) the height the box
    + * @param {Integer} t The tolerance for the collision, in pixels. A value of 0 means pixel-perfect box collision. A value of 2 would mean that the + * boxes could overlap by up to 2 pixels without being considered a collision. + * @returns True if the two collision boxes are colliding within the given tolerance. + */ + collides:function(o1,o2,t) { + if (!t) t=0; + return !((o1.y+o1.h-1-t o2.y+o2.h-1-t) || (o1.x+o1.w-1-to2.x+o2.w-1-t)); + }, + + /** + * Calculates a point-box collision between a point and a collision box within a given tolerance. A higher tolerance means less precise collision. + * @param {Object} o1 A point you're testing for collision. Must contain: + *
    • x {Integer}: (required) the x coordinate of the point
    • + *
    • y {Integer}: (required) the y coordinate of the point
    + * @param {Object} o2 A collision box you're testing for collision. Must contain: + *
    • x {Integer}: (required) the x coordinate of the object's origin; assumes the Akihabara default of top-left being the origin
    • + *
    • y {Integer}: (required) the y coordinate of the object's origin; assumes the Akihabara default of top-left being the origin
    • + *
    • w {Integer}: (required) the width of the box
    • + *
    • h {Integer}: (required) the height the box
    + * @param {Integer} t The tolerance for the collision, in pixels. A value of 0 means pixel-perfect collision. A value of 2 would mean that the + * point could exist within the outermost 2 pixels of the box without being considered a collision. + * @returns True if the point is colliding with the box within the given tolerance. + */ + pixelcollides:function(o1,o2,t) { + if (!t) t=0; + return !((o1.y o2.y+o2.h-1-t) || (o1.xo2.x+o2.w-1-t)); + }, + + /** + * Determines whether an object is visible by seeing if it collides with the camera's viewport. + * @param {Object} obj The object you're testing to see if it's visible. Must contain: + *
    • x {Integer}: (required) the x coordinate of the object's origin; assumes the Akihabara default of top-left being the origin
    • + *
    • y {Integer}: (required) the y coordinate of the object's origin; assumes the Akihabara default of top-left being the origin
    • + *
    • w {Integer}: (required) the width of the object's collision box
    • + *
    • h {Integer}: (required) the height the object's box
    + * @returns True if the object's collision box is within the camera's viewport. + */ + objectIsVisible:function(obj) { return this.collides(obj,this._camera,0); }, + + // --- + // --- + // --- AUDIO ENGINE + // --- + // --- + + _audiochannels:{}, + _audiomastervolume:1.0, + _canaudio:false, + _audiodequeuetime:0, + _audioprefetch:0.5, + _audiocompatmode:0, // 0: pause/play, 1: google chrome compatibility, 2: ipad compatibility (single channel) + _createmode:0, // 0: clone, 1: rehinstance + _fakecheckprogressspeed:100, // Frequency of fake audio monitoring + _fakestoptime:1, // Fake audio stop for compatibility mode + _audioteam:2, + _loweraudioteam:1, + _audio:{lding:null,qtimer:false,aud:{},ast:{}}, + _audioactions:[], + _showplayers:false, + _singlechannelname:"bgmusic", + _positiondelay:0, + _playerforcer:0, + _forcedmimeaudio:null, + _singlechannelaudio:false, + _audiomutevolume:0.0001, // Zero is still not accepted by everyone :( + _rawstopaudio:function(su) { + if (gbox._audiocompatmode==1) { + if (su.duration-su.currentTime>gbox._fakestoptime) + su.currentTime=su.duration-gbox._fakestoptime; + su.muted=true; + } else + su.pause(); + + }, + _rawplayaudio:function(su) { + if (gbox._audiocompatmode==1) { + try { su.currentTime=0; } catch (e) {} + su.muted=false; + su.play(); + } else if (gbox._audiocompatmode==2) { + su.load(); + gbox._playerforcer=setInterval(function(e){try{su.play();clearInterval(gbox._playerforcer)}catch(e){}},1000); + } else { + try { su.currentTime=0; } catch (e) {} + su.play(); + } + }, + _finalizeaudio:function(ob,who,donext){ + + var cur=(who?who:this); + gbox.removeEventListener(cur,'ended', gbox._finalizeaudio); + gbox.removeEventListener(cur,'timeupdate', gbox._checkprogress); + + gbox.addEventListener(cur,'ended', gbox._playbackended); + if (donext) gbox._loaderloaded(); + }, + _audiodoload:function() { + if (gbox._audiocompatmode==1) gbox._audio.lding.muted=true; + else if (gbox._audiocompatmode==2) + gbox._finalizeaudio(null,gbox._audio.lding,true); + else { + gbox._audio.lding.load(); + gbox._audio.lding.play(); + } + }, + _timedfinalize:function() { + gbox._rawstopaudio(gbox._audio.lding); + gbox._finalizeaudio(null,gbox._audio.lding,true); + }, + _checkprogress:function() { + if (gbox._audio.lding.currentTime>gbox._audioprefetch) gbox._timedfinalize(); + }, + _fakecheckprogress:function() { + if (gbox._audio.lding.currentTime>gbox._audioprefetch) gbox._timedfinalize(); else setTimeout(gbox._fakecheckprogress,gbox._fakecheckprogressspeed); + }, + _audiofiletomime:function(f) { + var fsp=f.split("."); + switch (fsp.pop().toLowerCase()) { + case "ogg": { return "audio/ogg"; break } + case "mp3": { return "audio/mpeg"; break } + default: { + return "audio/mpeg"; + } + } + }, + _pushaudio:function(){try {this.currentTime=1.0} catch(e){} }, + _createnextaudio:function(cau) { + if (cau.def) { + gbox.deleteAudio(cau.id); + this._audio.aud[cau.id]=[]; + this._audio.ast[cau.id]={cy:-1,volume:1,channel:null,play:false,mute:false,filename:cau.filename[0]}; + if (cau.def) for (var a in cau.def) this._audio.ast[cau.id][a]=cau.def[a]; + } + if ((gbox._createmode==0)&&(cau.team>0)) { + var ael =this._audio.aud[cau.id][0].cloneNode(true); + gbox._finalizeaudio(null,ael,false); + } else { + var ael=document.createElement('audio'); + ael.volume=gbox._audiomutevolume; + } + if (!gbox._showplayers) { + ael.style.display="none"; + ael.style.visibility="hidden"; + ael.style.width="1px"; + ael.style.height="1px"; + ael.style.position="absolute"; + ael.style.left="0px"; + ael.style.top="-1000px"; + } + ael.setAttribute('controls',gbox._showplayers); + ael.setAttribute('aki_id',cau.id); + ael.setAttribute('aki_cnt',cau.team); + gbox.addEventListener(ael,'loadedmetadata', gbox._pushaudio); // Push locked audio in safari + if (((gbox._createmode==0)&&(cau.team==0))||(gbox._createmode==1)) { + if (gbox._forcedmimeaudio) { + for (var i=0;i0) + this._addqueue({t:1,a:ael}); + } + } + }, + setSplashSettings:function(a) { for (var n in a) this._splash[n]=a[n]; }, + resetChannel:function(ch) { + if (this._canaudio&&this._audiochannels[ch]) + if (ch=="master") + for (var ch in this._audiochannels) + this.setChannelVolume(ch,this._audiochannels[ch]._def.volume); + else if (this._audiochannels[ch]) + this.setChannelVolume(ch,this._audiochannels[ch]._def.volume); + }, + getChannelDefaultVolume:function(ch) { + if (this._canaudio&&this._audiochannels[ch]) return this._audiochannels[ch]._def.volume; else return null; + }, + setChannelVolume:function(ch,a) { + if (this._canaudio&&this._audiochannels[ch]) { + if (ch=="master") this._audiomastervolume=a; else this._audiochannels[ch].volume=a + for (var j in gbox._audio.aud) + if (this._audio.ast[j].cy>-1) this._updateaudio(j); + } + }, + getChannelVolume:function(ch) { if (ch=="master") return this._audiomastervolume; else if (this._audiochannels[ch]) return this._audiochannels[ch].volume; else return 0 }, + changeChannelVolume:function(ch,a) { + if (this._canaudio&&this._audiochannels[ch]) { + var vol=this.getChannelVolume(ch)+a; + if (vol>1) vol=1; else if (vol<0) vol=0; + this.setChannelVolume(ch,vol); + } + }, + stopChannel:function(ch) { + if (this._canaudio) + for (var j in gbox._audio.aud) + if (this._audio.ast[j].cy>-1&&gbox._audio.ast[j].play&&((ch=="master")||(this._audio.ast[j].channel==ch))) + this.stopAudio(j); + }, + + setAudioUnmute:function(a) { if (this._canaudio&&this._audio.ast[a]) { this._audio.ast[a].mute=false; this._updateaudio(a); } }, + setAudioMute:function(a) { if (this._canaudio&&this._audio.ast[a]) { this._audio.ast[a].mute=true; this._updateaudio(a); } }, + getAudioMute:function(a) { if (this._canaudio&&this._audio.ast[a]) return this._audio.ast[a].mute; else return null}, + + setAudioVolume:function(a,vol) { if (this._canaudio&&this._audio.ast[a]) { this._audio.ast[a].volume=vol; this._updateaudio(a); } }, + getAudioVolume:function(a,vol) { if (this._canaudio&&this._audio.ast[a]) return this._audio.ast[a].volume; else return null}, + + setAudioPosition:function(a,p) { if (this._canaudio&&this._audio.ast[a]&&this._audio.aud[a][this._audio.ast[a].cy]) this._audio.aud[a][this._audio.ast[a].cy].currentTime=p;}, + getAudioPosition:function(a) {if (this._canaudio&&this._audio.ast[a]&&this._audio.aud[a][this._audio.ast[a].cy]) if (this._audio.aud[a][this._audio.ast[a].cy].currentTime>this._positiondelay) return this._audio.aud[a][this._audio.ast[a].cy].currentTime-this._positiondelay; else return 0; else return 0}, + + getAudioDuration:function(a) {if (this._canaudio&&this._audio.ast[a]&&this._audio.aud[a][this._audio.ast[a].cy]) return this._audio.aud[a][this._audio.ast[a].cy].duration; else return 0}, + + changeAudioVolume:function(a,vol) { if (this._canaudio&&this._audio.ast[a]) { if (this._audio.ast[a].volume+vol>1) this._audio.ast[a].volume=1; else if (this._audio.ast[a].volume+vol<0) this._audio.ast[a].volume=0; else this._audio.ast[a].volume+=vol; this._updateaudio(a); } }, + setCanAudio:function(a) { this._canaudio=!this._flags.noaudio&&a;}, + setForcedMimeAudio:function(a){ this._forcedmimeaudio=a;}, + setAudioChannels:function(a){ + this._audiochannels=a; + for (var ch in a) { + this._audiochannels[ch]._def={}; + for (var attr in this._audiochannels[ch]) + if (attr!="_def") this._audiochannels[ch]._def[attr]=this._audiochannels[ch][attr]; + } + }, + setAudioTeam:function(a){ this._audioteam=a; }, + setLowerAudioTeam:function(a){ this._loweraudioteam=a; }, + + // --- + // --- + // --- DYNAMIC SCRIPT INCLUSION + // --- + // --- + + addScript:function(call) { + gbox._addtoloader({type:"script",call:call}); + }, + + // --- + // --- + // --- BUNDLES + // --- + // --- + + addBundle:function(call){ + gbox._addtoloader({type:"bundle",call:call}); + }, + + readBundleData:function(pack,call) { + // Local resources first + if (pack.setObject) for (var i=0;igbox.getScreenH()) l=gbox.getScreenH()-p; + tox.fillStyle = gbox.PALETTES.c64.colors[gbox.PALETTES.c64.order[Math.floor(Math.random()*gbox.PALETTES.c64.order.length)]]; + tox.fillRect(0,p,gbox.getScreenW(),l); + p+=l; + } + tox.fillStyle = gbox.PALETTES.c64.colors.lightblue; + tox.fillRect(Math.floor(gbox.getScreenW()/10),Math.floor(gbox.getScreenH()/10),gbox.getScreenW()-Math.floor(gbox.getScreenW()/5),gbox.getScreenH()-Math.floor(gbox.getScreenH()/5)); + if (gbox._splash.minilogo&&gbox.imageIsLoaded("logo")) { + var dw=gbox.getScreenW()/4; + var dh=(gbox.getImage("logo").height*dw)/gbox.getImage("logo").width; + gbox.blit(tox,gbox.getImage(gbox._splash.minilogo),{w:gbox.getImage("logo").width,h:gbox.getImage("logo").height,dx:(gbox.getScreenW()-dw)/2,dy:(gbox.getScreenH()-dh)/2,dw:dw,dh:dh}); + } + break; + } + default:{ + if (gbox._splash.background&&gbox.imageIsLoaded("_splash")) + gbox.blit(tox,gbox.getImage("_splash"),{w:gbox.getImage("_splash").width,h:gbox.getImage("_splash").height,dx:0,dy:0,dw:gbox.getScreenW(),dh:gbox.getScreenH()}); + if (gbox._splash.minilogo&&gbox.imageIsLoaded("logo")) { + var dw=gbox.getScreenW()/4; + var dh=(gbox.getImage("logo").height*dw)/gbox.getImage("logo").width; + gbox.blit(tox,gbox.getImage(gbox._splash.minilogo),{w:gbox.getImage("logo").width,h:gbox.getImage("logo").height,dx:gbox.getScreenW()-dw-5,dy:gbox.getScreenH()-dh-5,dw:dw,dh:dh}); + } + if (gbox._splash.footnotes&&gbox.imageIsLoaded("_dbf")) { + if (!gbox.getCanvas("_footnotes")) { + var fd=gbox.getFont("_dbf"); + gbox.createCanvas("_footnotes",{w:gbox.getScreenW()-5,h:(gbox._splash.footnotes.length)*(fd.tileh+gbox._splash.footnotesSpacing)}); + for (var i=0;i0?bw:0),gbox._splash.gaugeHeight-2); + } + } + } + tox.restore(); + gbox.setStatBar("Loading... ("+gbox._loaderqueue.getDone()+"/"+gbox._loaderqueue.getTotal()+")"); + setTimeout(gbox._waitforloaded,50); + } else { + gbox.deleteImage("_splash"); + gbox.setStatBar(); + gbox._cb(); + } + }, + clearCache:function() { this._loadercache.clear(); }, + + // --- + // --- + // --- BROWSER QUIRKS + // --- + // --- + + checkCanvasSupport:function() { + return !!document.createElement('canvas').getContext; + }, + addEventListener:function(to,event,code) { + if (to.addEventListener) to.addEventListener(event,code,false); + else to.attachEvent('on'+event,code); + }, + removeEventListener:function(to,event,code) { + if (to.removeEventListener) to.removeEventListener(event,code,false); + else to.detachEvent('on'+event,code); + }, + XMLHttpFactories:[ + function () {return new XMLHttpRequest()}, + function () {return new ActiveXObject("Msxml2.XMLHTTP")}, + function () {return new ActiveXObject("Msxml3.XMLHTTP")}, + function () {return new ActiveXObject("Microsoft.XMLHTTP")} + ], + createXmlHttpRequest:function() { + var xmlhttp=false; + /* running locally on IE5.5, IE6, IE7 */ ; /*@cc_on + if(location.protocol=="file:"){ + if(!xmlhttp)try{ xmlhttp=new ActiveXObject("MSXML2.XMLHTTP"); }catch(e){xmlhttp=false;} + if(!xmlhttp)try{ xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); }catch(e){xmlhttp=false;} + } ; @cc_off @*/ + /* IE7, Firefox, Safari, Opera... */ + if(!xmlhttp)try{ xmlhttp=new XMLHttpRequest(); }catch(e){xmlhttp=false;} + /* IE6 */ + if(typeof ActiveXObject != "undefined"){ + if(!xmlhttp)try{ xmlhttp=new ActiveXObject("MSXML2.XMLHTTP"); }catch(e){xmlhttp=false;} + if(!xmlhttp)try{ xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); }catch(e){xmlhttp=false;} + } + /* IceBrowser */ + if(!xmlhttp)try{ xmlhttp=createRequest(); }catch(e){xmlhttp=false;} + return xmlhttp; + } + +}; + diff --git a/deps/akihabara-core-1.3.1/akihabara/help.js b/deps/akihabara-core-1.3.1/akihabara/help.js new file mode 100644 index 0000000..2c4c5fa --- /dev/null +++ b/deps/akihabara-core-1.3.1/akihabara/help.js @@ -0,0 +1,608 @@ +// --- +// Copyright (c) 2010 Francesco Cottone, http://www.kesiev.com/ +// --- + +/** + * @namespace Help module provides some Javascript-specific functions, such object copying, randomizing functions, + * string/array handlers and the akihabaraInit function. + */ +var help={ + + /** + * Searches an object in an array filtering for one of their properties. + * @param {Array} a The array. + * @param {String} field The searched field. + * @param {String} value The searched value. + * @returns The found object, otherwise null. + */ + searchObject:function(a,field,value) { + if (!a) return null; else + for (var i=0;i0 means you're falling onto something else. + * @param {Object} th The object that is (possibly) being jumped on. + * @param {Object} by The object doing the jumping-on. + * @returns True if the two objects are overlapping enough and by.accy>0. + */ + isSquished:function(th,by) { + return ((by.accy>0)&&gbox.collides(th,by)&&(Math.abs(th.y-(by.y+by.h))<(th.h/2))) + }, + + /** + * Generates uniformly distributed random integers between min and min+range, non-inclusive. So help.random(0,2) will only return 0 and 1, etc. + * @param {Integer} min The minimum random value to be returned by the function. + * @param {Integer} range The number of different values returned by the function. + * @returns An integer between min (includive) and min+range (noninclusive). + */ + random:function(min,range) { + return min+Math.floor(Math.random()*range); + }, + + + /** + * Determines which frame of a given animation to display. Will loop an animation. + * @param {Integer} cnt A global frame counter. + * @param {Object} anim An object with parameters speed (the animation speed) and frames (the array representing the animation sequence). + * @returns The particular animation frame to display during this step. + */ + decideFrame:function(cnt,anim) { + return anim.frames[Math.floor(cnt/anim.speed)%anim.frames.length]; + }, + + /** + * Determines which frame of a given animation to display. Will remain on the last frame when the animation has played once. + * @param {Integer} cnt A global frame counter. + * @param {Object} anim An object with parameters speed (the animation speed) and frames (the array representing the animation sequence). + * @returns The particular animation frame to display during this step. + */ + decideFrameOnce:function(cnt,anim) { + return anim.frames[(cnt>=anim.frames.length*anim.speed?anim.frames.length-1:Math.floor(cnt/anim.speed))]; + }, + + /** + * Returns whether the animation was fully played at least once with decideFrame or fully with decideFrameOnce. + * @param {Integer} cnt A global frame counter. + * @param {Object} anim An object with parameters speed (the animation speed) and frames (the array representing the animation sequence). + * @returns A boolean, true if the animation has been played at least once. + */ + isLastFrameOnce:function(cnt,anim) { + return (cnt>=anim.frames.length*anim.speed); + }, + + /** + * Given an incrementing value each step, this will return a value increasing from 0 until max/2, at which point it will decrement to 0, then go back up to max/2, in an endless cycle. + * @param {Integer} counter A counter. + * @param {Integer} max This determines the period of the function -- assuming counter is incrementing by one, a complete back-and-forth will take 'max' steps. + * @returns An integer. + */ + upAndDown:function(counter,max) { + if ((counter%max)>(max/2)) return max-(counter%max); else return (counter%max); + }, + + /** + * Given x,y coordinates and map information, this returns the tile at a given point. + * @param {Integer} x An x-coordinate. + * @param {Integer} y A y-coordinate. + * @param {Object} map The map object. + * @param {Object} ifout An object or value to be returned if the x,y coordinate pair is outside the map. + * @param {String} mapid The id for the map array within the map object. Default is 'map'. + * @returns An integer representing the value of the tile in the map array at that x,y coordinate. If there is no tile, null is returned. + */ + getTileInMap:function(x,y,map,ifout,mapid) { + if (!mapid) mapid="map"; + var ts=gbox._tiles[map.tileset]; + var tx=Math.floor(x/ts.tilew); + var ty=Math.floor(y/ts.tileh); + if ((ty<0)||(ty>=map[mapid].length)) return ifout; else + if ((tx<0)||(tx>=map[mapid][ty].length)) return ifout; else + return map[mapid][ty][tx]; + }, + + /** + * Takes an ascii-art-style array of characters and converts it to an Akihabara-compatible map format. + * @param {Array} map An array of characters representing a map. + * @param {Array} tra A translation array. This is an array of arrays, formatted like [ [null, char1], [0, char2], [1, char3] ]. There must at least be a null entry, followed by one numerical entry for each tile type you want to render, corresponding to the unique characters in the map array. The null entry maps a character to empty space. + * @returns A map array formatted such that it can be attached to a map object. + */ + asciiArtToMap:function(map,tra) { + var sz=tra[0][1].length; + var ret=[]; + var xpos; + var pie; + for (var y=0;ymax. + */ + limit:function(v,min,max) { + if (vmax) return max; else return v; + }, + + /** + * Subtracts or adds 1 to a value, always converging to zero. For example, passing -3 yields -2, 5 yields 4, etc. Works best with integers. + * @param {Integer} v A value. + * @returns A value that is one closer to 0 on the number line than v. + */ + goToZero:function(v) { return (v?v-(v/Math.abs(v)):0); }, + + /** + * Merges two sets of parameters together without overwriting existing parameters. This merges from model to data, and if data and model share parameters, data's values remain intact. + * @param {Object} data An object containing a set of parameters, the destination of the merge. + * @param {Object} model An object containing a set of parameters, the source of the merge. + * @returns A merged model where the values of 'data' remain untouched: only new parameters and values from 'model' make it in. + * @example + * dst = {a: 1, b: 2, c: "three"}; + * src = {c: "three", d: "four"}; + * merged = help.mergeWithModel(dst,src); + * merged; // => {a: 1, b: 2, c: 3, d: "four"}; + */ + mergeWithModel:function(data,model) { + if (data==null) data={}; + if (model!=null) + for (var i in model) + if (data[i]==null) data[i]=model[i]; + return data; + }, + + /** + * Merges two sets of parameters together overwriting any existing parameters. This merges model->data, and if data and model share parameters, data's are overwritten by model's. + * @param {Object} data An object containing a set of parameters, the destination of the merge. + * @param {Object} model An object containing a set of parameters, the source of the merge. + * @returns A merged model where the values of 'model' take precedence over those of 'data'. The 'data' object is returned and will be an exact copy of 'model', plus any parameters that 'data' had before the merge that 'model' did not. + * @example + * dst = {a: 1, b: 2, c: "three"}; + * src = {c: "three", d: "four"}; + * merged = help.mergeWithModel(dst,src); + * merged; // => {a: 1, b: 2, c: "three", d: "four"} + */ + copyModel:function(data,model) { + if (data==null) data={}; + if (model!=null) + for (var i in model) data[i]=model[i]; + return data; + }, + + /** + * Creates a subset of an existing set of parameters. + * @param {Object} obj An object containing a set of parameters, the source of the data. + * @param {Array} attrs An array of strings, containing the names of parameters you wish to copy. + * @returns A new set of parameters based on the subset specified. + * @example + * data = {a: 1, b: 2, c: "three"}; + * newdata = help.createModel(data, ["a", "c"]); + * newdata; // => {a: 1, c: "three"} + */ + createModel:function(obj,attrs) { + var ret={}; + for (var i=0;i {a: 1, b: 2, c: "three"} + */ + cloneObject:function(model) { + if (!model) return model; + var data={}; + for (var i in model) data[i]=model[i]; + return data; + }, + + /** + * Sets a tile in the map and draws it. Does not return anything. + * @param {Object} ctx The canvas context for the map. Accessed via gbox.getCanvasContext("canvasname") + * @param {Object} map The game map object. + * @param {Integer} x The index of the tile column within the map array -- so a 1 would mean the second column of tiles. + * @param {Integer} y The index of the tile row within the map array -- so a 1 would mean the second row of tiles. + * @param {Integer} tile The integer representing the new tile you wish to draw. This is its index within the tileset; a null value will erase whatever tile is present. + * @param {String} The ID of the map. Defaults to 'map'. + * @example + * // Remove the second tile to the right and down from the upper left corner of the tile map. Assumes our map canvas is called 'map_canvas'. + * help.setTileInMap(gbox.getCanvasContext("map_canvas"),map,1,1,null,"map"); + */ + setTileInMap:function(ctx,tilemap,x,y,tile,map) { + var ts=gbox.getTiles(tilemap.tileset); + tilemap[(map==null?"map":map)][y][x]=tile; + if (tile==null) + gbox.blitClear(ctx,{x:x*ts.tilew,y:y*ts.tilew,h:ts.tileh,w:ts.tilew}); + else + gbox.blitTile(ctx,{tileset:tilemap.tileset,tile:tile,dx:x*ts.tilew,dy:y*ts.tilew}); + }, + + /** + * Sets a tile in the map and draws it using pixels as coords. Does not return anything. + * @param {Object} ctx The canvas context for the map. Accessed via gbox.getCanvasContext("canvasname") + * @param {Object} map The game map object. + * @param {Integer} x The index of the pixel column within the map array -- so a 1 would mean the second column of tiles. + * @param {Integer} y The index of the pixel row within the map array -- so a 1 would mean the second row of tiles. + * @param {Integer} tile The integer representing the new tile you wish to draw. This is its index within the tileset; a null value will erase whatever tile is present. + * @param {String} The ID of the map. Defaults to 'map'. + */ + setTileInMapAtPixel:function(ctx,tilemap,x,y,tile,map) { + var ts=gbox.getTiles(tilemap.tileset); + x=Math.floor(x/ts.tilew); + y=Math.floor(y/ts.tileh); + help.setTileInMap(ctx,tilemap,x,y,tile,map); + }, + + + /** + * Returns the Nth element in an array. If the array is shorter than N, it returns the last element of the array. + * @param {Array} a An array. + * @param {Integer} id An index to the array. + * @returns If id > a.length, it returns a[a.length-1]. Otherwise returns a[id]. + */ + getArrayCapped:function(a,id) { + if (id>=a.length) return a[a.length-1]; else return a[id]; + }, + + /** + * Returns the element of a sorted array that have the highest value of one of the properties. + * @param {Array} a An array. + * @param {Integer} value The target value. + * @param {String} field The property used to filter the array. + * @returns The object with the highest target value, otherwise the first element of the array. + */ + getArrayIndexed:function(a,value,field) { + if (a[0][field]==null) return a[0]; + var i=0; + while ((value>a[i][field])&&(i!=a.length-1)) i++; + return a[i]; + }, + + + /** + * Converts a quantity of frames into a timestamp formatted "mm:ss:cs" (minutes, seconds, centiseconds). Calculated using the current frames per second. + * @param {Integer} frames A quantity of frames. + * @returns A string containing a timestamp formatted "mm:ss:cs", representing the length of time it would take to render that many frames. + * @example + * // Assuming 25 frames per second, Akihabara's default. + * timestamp = help.framestotime(25); + * timestamp; // => '00:01:00'; + * timestamp = help.framestotime(25 * 60); + * timestamp; // => '01:00:00'; + */ + framestotime:function(frames) { + var csec=Math.ceil(frames/gbox.getFps()*100); + return this.prepad((Math.floor(csec/6000)%60),2,"0")+":"+this.prepad((Math.floor(csec/100)%60),2,"0")+":"+this.prepad(csec%100,2,"0"); + + }, + + /** + * Reads the value of a query parameter from the URL of the web page. + * @param {String} name The name of the URL parameter. + * @returns The value of the URL parameter, as a string. + * @example + * // If the URL is http://example.com/game.html?lives=3 + * player.lives = help.geturlparameter("lives"); + * player.lives; // => 3 + */ + geturlparameter:function( name ) { + name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]"); + var regexS = "[\\?&]"+name+"=([^&#]*)"; + var regex = new RegExp( regexS ); + var results = regex.exec( window.location.href ); + if( results == null ) + return ""; + else + return results[1]; + }, + + /** + * Writes the contents of an object to a string. Useful for debugging. + * @param {Object} Any object. + * @returns A string containing all the contents of an object. If the object contains functions, the string will contain the code for those functions. + */ + objToStr:function(o) { + var ret=""; + for (var n in o) ret+=n+":["+o[n]+"] "; + return ret; + }, + + /** + * Tests whether an object contains a given parameter. + * @param {Object} A reference to a parameter of an object. + * @returns True if the object contains that parameter, false if it does not. + * @example + * foo = {a: 1, b: 2}; + * help.isDefined(foo.a); // => true + * help.isDefined(foo.c); // => false + */ + isDefined:function(v) { + return ((typeof(v) !== 'undefined') || (v===null)); + }, + + /** + * Automatically configures a bunch of settings depending on the web browser and device that is viewing the game. Mostly sets the maximum number of audio channels and touch settings. + */ + getDeviceConfig:function() { + var cap; + if (navigator.userAgent.match(/nintendo wii/i)) + cap={iswii:true,height:window.innerHeight,doublebuffering:true} // Simulated double buffering has been resumed. Canvas on Opera for Wii has a strange sprite blinking effect - usually browsers render frames once ended and this is an exception. + else if (navigator.userAgent.match(/iPhone/i)||navigator.userAgent.match(/iPod/i) || navigator.userAgent.match(/Android/i)) + cap={touch:true,width:320}; + else if (navigator.userAgent.match(/iPad/i)) + cap={touch:true,width:768,forcedidle:10}; // Forced idle time is needed for correct framerate calculation. + else + cap={zoom:2}; + + cap.canaudio=!!(document.createElement('audio').canPlayType); + if (cap.canaudio) { + if (navigator.userAgent.match(/iPad/i)||navigator.userAgent.match(/iPhone/i)||navigator.userAgent.match(/iPod/i)) { + cap.audiocompatmode=2; // Audio loading mode. + cap.audioteam=1; // Only a member is required in the audioteam. + cap.audioisexperimental=true; // Audio is experimental, since limited. + cap.audioissinglechannel=true; // Single channeled. Plays only the "bgmusic" channel. + } else if (navigator.userAgent.match(/Chrome/i)) { + cap.audioteam=3; // Quite low performance on playback responsiveness. + } else if (navigator.userAgent.match(/Firefox/i)) { + cap.audioteam=1; // Testing smaller audioteam + cap.audiopositiondelay=0.3; // Ogg playback is slower 0.3 between MP3 playback. Don't know why :) + cap.audiocreatemode=1; // Firefox is stalling while downloading lot of things + } else if (navigator.userAgent.match(/Minefield/i)) { + cap.audioteam=1; // Testing smaller audioteam + cap.audiocreatemode=1; // Firefox is stalling while downloading lot of things + // Minefield has fixed the 0.3 delay! + } else if (navigator.userAgent.match(/khtml/i)&&navigator.userAgent.match(/konqueror/i)) { + // Note that audio is not supported in applewebkit mode :( + cap.audioteam=1; + cap.audioissinglechannel=true; // Single channeled. Plays only the "bgmusic" channel. + cap.audiocompatmode=2; // Sorry. iPad single channel mode. Audio events are not triggered properly and audio properties are missing so many audio feautres are not available. :( + cap.forcedmimeaudio="audio/ogg"; // Usually OGG audio playback is supported by default in KDE env. + cap.audioisexperimental=true; // Audio is experimental, since limited. + } else if (navigator.userAgent.match(/Safari/i)) { + cap.audioteam=1; // Testing smaller audioteam + } else if (navigator.userAgent.match(/Opera/i)) { + cap.audioteam=1; // Testing smaller audioteam + cap.audiocreatemode=1; // Do not like audio object cloning very much + } else if (navigator.userAgent.match(/MSIE 9.0/i)||navigator.userAgent.match(/MSIE 7.0/i)) { + cap.audioteam=2; + cap.audiocompatmode=1; // Audio loading mode. + cap.audioisexperimental=navigator.userAgent.match(/MSIE 7.0/i); // Audio is experimental, on IE7 (for compat mode) + } else + cap.audioisexperimental=true; // Audio is just experimental on all other devices. + } + return cap; + }, + + /** + * This provides a number of configurations: fps, display zoom, dynamic frameskip, force touch parameters, etc. Many of these settings can + * be set manually by passing an object with the parameters defined, or via URL parameters. + * @param {Object} data An optional object containing parameters you wish to set. Works for data.zoom, data.splash, data.width, data.height, data.title, data.fps, and data.padmode. + */ + akihabaraInit:function(data) { + if ((typeof data).toLowerCase() == "string") data={title:data}; + var device=this.getDeviceConfig(); + var footnotes=["MADE WITH AKIHABARA (C)2010 - GPL2/MIT","Project: www.kesiev.com/akihabara","Sources: github.com/kesiev/akihabara"]; + document.title=(data.title?data.title:"Akihabara"); + if (data.splash) { + if (data.splash.footnotes) + for (var i=0;iiphopad._width-iphopad._buttonsize) + nb.a=true; + else if (rp.x>iphopad._width-iphopad._buttonsize2) + nb.b=true; + else if (rp.x>iphopad._width-iphopad._buttonsize3) + nb.c=true; + + } + this._swap=!this._swap; + for (var i in this._cross) { + if (nc[i]!=iphopad._cross[i]) + if (nc[i]) gbox._keydown({fake:true,keyCode:gbox._keymap[i]}); + else gbox._keyup({fake:true,keyCode:gbox._keymap[i]}); + } + for (var i in this._buttons) { + if (nb[i]!=iphopad._buttons[i]) + if (nb[i]) gbox._keydown({fake:true,keyCode:gbox._keymap[i]}); + else gbox._keyup({fake:true,keyCode:gbox._keymap[i]}); + } + + iphopad._cross=nc; + iphopad._buttons=nb; + }, + _fakelisten:function(e) { + iphopad._listen({ + touches:[ + { + pageX:e.clientX, + pageY:e.clientY + } + ] + }); + }, + + /** + * Initializes the game controls for use with an I-product or Android device. + * @param {Object} data passes in information about the screen and its traits such as size. + */ + initialize:function(data) { + var oElement=document.createElement("div"); + oElement.style.margin="auto"; + oElement.style.padding="0px"; + oElement.style.height=data.h+"px"; + oElement.style.width="100%"; + oElement.style.backgroundImage="url("+data.bg+")"; + oElement.style.backgroundRepeat="repeat-x"; + + var tpad=document.createElement("div"); + tpad.style.cssFloat="left"; + tpad.style.padding="0px"; + tpad.style.margin="0px"; + tpad.style.height=data.h+"px"; + tpad.style.width=data.h+"px"; + tpad.style.backgroundImage="url("+data.dpad+")"; + tpad.style.backgroundRepeat="no-repeat"; + + var bpad=document.createElement("div"); + bpad.style.cssFloat="right"; + bpad.style.padding="0px"; + bpad.style.margin="0px"; + bpad.style.height=data.h+"px"; + bpad.style.width=iphopad._buttonsize3+"px"; + bpad.style.backgroundImage="url("+data.buttons+")"; + bpad.style.backgroundRepeat="no-repeat"; + + oElement.appendChild(tpad); + oElement.appendChild(bpad); + gbox._box.appendChild(oElement); + + oElement.ontouchstart=function(evt) { evt.preventDefault();evt.stopPropagation(); iphopad._listen(evt) }; + oElement.ontouchend=function(evt) { evt.preventDefault();evt.stopPropagation();iphopad._listen(evt) }; + oElement.ontouchmove=function(evt) { evt.preventDefault();evt.stopPropagation();iphopad._listen(evt) }; + //oElement.onmousemove=function(evt) { iphopad._fakelisten(evt) }; + var sizes=gbox._domgetabsposition(oElement); + this._gapx=sizes.x; + this._gapy=sizes.y; + this._width=sizes.w; + this._height=sizes.h; + this._center={x:Math.floor(this._height/2),y:Math.floor(this._height/2)}; + } + +} diff --git a/deps/akihabara-core-1.3.1/akihabara/padbg.png b/deps/akihabara-core-1.3.1/akihabara/padbg.png new file mode 100644 index 0000000..09b9db0 Binary files /dev/null and b/deps/akihabara-core-1.3.1/akihabara/padbg.png differ diff --git a/deps/akihabara-core-1.3.1/akihabara/splash.png b/deps/akihabara-core-1.3.1/akihabara/splash.png new file mode 100644 index 0000000..5d031ce Binary files /dev/null and b/deps/akihabara-core-1.3.1/akihabara/splash.png differ diff --git a/deps/akihabara-core-1.3.1/akihabara/tool.js b/deps/akihabara-core-1.3.1/akihabara/tool.js new file mode 100644 index 0000000..9f41b2e --- /dev/null +++ b/deps/akihabara-core-1.3.1/akihabara/tool.js @@ -0,0 +1,131 @@ +// --- +// Copyright (c) 2010 Francesco Cottone, http://www.kesiev.com/ +// --- + +/** + * @namespace Tool module provides simple developing tools. Currently, this file only has a cel-composer: + * it can compose an image stacking a set of frames for animating objects, applying a + * number of filters to each frame. + */ +var tool={ + _images:[], + _loadedflag:[], + _data:{}, + _count:0, + _countloaded:0, + + /** + * This function documents that an image in an animation sequence is loaded and checks if the other images are loaded or not + * @param {Object} id This is the object which is used as an id for keeping track of things related to this object in this function + */ + _loaded:function(id) { + this._loadedflag[id]=true; + tool._countloaded++; + document.title=tool._countloaded+"/"+tool._count; + for (var i=0;i + *
  • x{Integer}: (required)Objects x position
  • + *
  • y{Integer}: (required)Objects y position
  • + *
  • z{Integer}: (required)Objects z position
  • + *
  • colx{Integer}: (required)The dimension of the collision box along the x axis
  • + *
  • coly{Integer}: (required)The dimension of the collision box along the y axis
  • + *
  • colh{Integer}: (required)Collision box height
  • + *
  • colw{Integer}: (required)Collision box width
  • + * + * @param {Object} to The object that collision is being checked against. + *
      + *
    • x{Integer}: (required)Objects x position
    • + *
    • y{Integer}: (required)Objects y position
    • + *
    • z{Integer}: (required)Objects z position
    • + *
    • colx{Integer}: (required)Collision x
    • + *
    • coly{Integer}: (required)Collision y
    • + *
    • colh{Integer}: (required)Collision box height
    • + *
    • colw{Integer}: (required)Collision box width
    • + *
    + * @param {int} t This is the tollerance (or margin for error) on the collide function. + */ + collides:function(fr,to,t) { // Special collision. Counts also the Z + if (Math.abs(fr.z,to.z)<5) return gbox.collides({x:fr.x+fr.colx,y:fr.y+fr.coly,h:fr.colh,w:fr.colw},{x:to.x+to.colx,y:to.y+to.coly,h:to.colh,w:to.colw},t); else return false; + }, + + /** + * Checks for pixel collisions with an offset to the X and Y of the colidable using colx and coly. + * @param {Object} fr The object which collision is being tested for. + * @param {Object} to The object (or point) which collision is being tested against. + * @param {int} t The tollerance of the collision algorithm. + */ + pixelcollides:function(fr,to,t) { // Special collision. Counts also the Z + return gbox.pixelcollides(fr,{x:to.x+to.colx,y:to.y+to.coly,h:to.colh,w:to.colw},t); + }, + + /** + * Initializes the game with the variables needed for topview and whatever else you feed in through data. + * @param {Object} th Passes in the object being initialized. + * @param {Object} data This is used to pass in everything that's being initiliized. If a value is not in Data then a default value is used instead. This can pass in values which do not have a default. + *
      + *
    • x{Integer}: x position of the object. (defaults to 0)
    • + *
    • y{Integer}: y position of the object. (defaults to 0)
    • + *
    • z{Integer}: z index of the object. (defaults to 0)
    • + *
    • accx{Integer}: The starting x velociyt of the object. (defaults to 0)
    • + *
    • accy{Integer}: The starting y velocity of the object. (defaults to 0)
    • + *
    • accz{Integer}: The starting z velocity of the object. (defaults to 0)
    • + *
    • frames{Object}: This is stores the animation frames for the objects in a map style structure. An empty map means the default image will display with no animation frames. (defaults to an empty map)
    • + *
    • shadow: (defaults to null)
    • //incomplete + *
    • maxacc{Integer}: (defaults to )4
    • + *
    • controlmaxacc{Integer}: (defaults to 4)
    • + *
    • responsive: (defaults to 0)
    • + *
    • weapon: (defaults to 0)
    • + *
    • camera{Boolean}: (defaults to true)
    • + *
    • flipv{Boolean}: Notes if the object is flipped vertically(defaults to false)
    • + *
    • fliph{Boolean}: Notes if the object is flipped horrizontally(defaults to false)
    • + *
    • facing{Integer}: Stores the facing of the object. This is set with pre-defined Integer values from within Toys.(defaults to toys.FACE_DOWN)
    • + *
        + *
      • FACE_UP:0,
      • + *
      • FACE_RIGHT:1,
      • + *
      • FACE_DOWN:2,
      • + *
      • FACE_LEFT:3,
      • + *
      + *
    • flipside{Boolean}: (defaults to true)
    • + *
    • haspushing{Boolean}: (defaults to false)
    • + *
    • frame: (default to 0)
    • + *
    • colh{Integer}: (defaults to gbox.getTiles(th.tileset).tilehh)
    • + *
    • colw{Integer}: (defaults to gbox.getTiles(th.tileset).tilew)
    • + *
    • colx{Integer}: (defaults to 0)
    • + *
    • staticspeed{Integer}: (defaults to 0)
    • + *
    • nodiagonals{Boolean}: (defaults to false)
    • + *
    • noreset: (defaults to false)
    • + *
    + */ + initialize:function(th,data) { + help.mergeWithModel( + th, + help.mergeWithModel( + data, + { + x:0, y:0, + z:0, + accx:0, accy:0, accz:0, + frames:{}, + shadow:null, + maxacc:4, controlmaxacc:4, + responsive:0, // Responsiveness + weapon:0, // Weapon + camera:true, + flipv:false, fliph:false, + facing:toys.FACE_DOWN, + flipside:true, + haspushing:false, + frame:0, + colh:gbox.getTiles(th.tileset).tilehh, + colw:gbox.getTiles(th.tileset).tilew, + colx:0, + staticspeed:0, + nodiagonals:false, + noreset:false + } + ) + ); + if (th.coly==null) th.coly=gbox.getTiles(th.tileset).tileh-th.colh; + th.colhh=Math.floor(th.colh/2); + th.colhw=Math.floor(th.colw/2); + + toys.topview.spawn(th); + }, + + /** + * Spawns a new object in the topview namespace. This also merges parameters in data into paramaters in th using help.copyModel. + * This initializes some basic basic variables for the object and sets the Z index. + * @param {Object} th References 'this' which is the object that called the method (generally). + *
      + *
    • y {Integer}: (required) The object's y position.
    • + *
    • h {Integer}: (required) The object's height.
    • + *
    + * @param {Object} data This holds variables to be merged into th's stored info. + */ + spawn:function(th,data) { + th.xpushing=toys.PUSH_NONE; // user is moving side + th.vpushing=toys.PUSH_NONE; // user is moving side + th.zpushing=toys.PUSH_NONE; // user is moving side + th.counter=0; // self counter + th.hittimer=0; + th.killed=false; + help.copyModel(th,data); + gbox.setZindex(th,th.y+th.h); // these object follows the z-index and uses ZINDEX_LAYER + }, + + /** + * This sets and runs the control keys for the game. + * @param {Object} th This is the object that is being controlled by the keys (assumed to be the player) + *
      + *
    • accx: the object's currect acceleration in the x direction
    • + *
    • accy: the object's currect acceleration in the y direction
    • + *
    • responsive: minimum movement speed
    • + *
    • staticspeed: turns off acceleration
    • + *
    • nodiagonals: boolean determining if the object can move along both axis at once.
    • + *
    • xpushing: a boolean that notes whether the object is pushing against something in the x direction.
    • + *
    • ypushing: a boolean that notes whether the object is pushing against something in the y direction.
    • + *
    • controlmaxacc: max acceleration for the object along an axis
    • + *
    • noreset: checks for the object being allowed to reset its pushing status (?)
    • + *
    + * @param {Object} keys These are the control keys being passed in for left, right, up, and down. + * //incomplete + */ + controlKeys:function(th,keys) { + var cancelx=false; + var cancely=false; + var idlex=false; + var idley=false; + + if (gbox.keyIsPressed(keys.left)||keys.pressleft) { + th.xpushing=toys.PUSH_LEFT; + th.facing=toys.FACE_LEFT; + if (th.accx>th.responsive) th.accx=th.responsive; + if (th.staticspeed) th.accx=-th.staticspeed; else th.accx=help.limit(th.accx-1,-th.controlmaxacc,th.controlmaxacc); + if (th.nodiagonals) { cancely=true; idley=true } + } else if (gbox.keyIsPressed(keys.right)||keys.pressright) { + th.xpushing=toys.PUSH_RIGHT; + th.facing=toys.FACE_RIGHT; + if (th.accx<-th.responsive) th.accx=-th.responsive; + if (th.staticspeed) th.accx=th.staticspeed; else th.accx=help.limit(th.accx+1,-th.controlmaxacc,th.controlmaxacc); + if (th.nodiagonals) { cancely=true; idley=true } + } else idlex=true; + + if (!cancely&&(gbox.keyIsPressed(keys.up)||keys.pressup)) { + th.ypushing=toys.PUSH_UP; + th.facing=toys.FACE_UP; + if (th.accy>th.responsive) th.accy=th.responsive; + if (th.staticspeed) th.accy=-th.staticspeed; else th.accy=help.limit(th.accy-1,-th.controlmaxacc,th.controlmaxacc); + if (th.nodiagonals) { cancelx=true; idlex=true; } + } else if (!cancely&&(gbox.keyIsPressed(keys.down)||keys.pressdown)) { + th.ypushing=toys.PUSH_DOWN; + th.facing=toys.FACE_DOWN; + if (th.accy<-th.responsive) th.accy=-th.responsive; + if (th.staticspeed) th.accy=th.staticspeed; else th.accy=help.limit(th.accy+1,-th.controlmaxacc,th.controlmaxacc); + if (th.nodiagonals) { cancelx=true; idlex=true; } + } else idley=true; + + + + if (idlex) { + if (cancelx) th.accx=0; + if (cancelx||!th.noreset) th.xpushing=toys.PUSH_NONE; + } + if (idley) { + if (cancely) th.accy=0; + if (cancely||!th.noreset) th.ypushing=toys.PUSH_NONE; + } + }, + + /** + * Gets the next X position the object is going to move to. + * @param {Object} th The object being checked. + *
      + *
    • x: the current x position of the object
    • + *
    • accx: the object's currect acceleration in the x direction
    • + *
    • maxacc: the max accleration the object can have (if accx is greater than this then this value is used instead)
    • + *
    + */ + getNextX:function(th) { return th.x+help.limit(th.accx,-th.maxacc,th.maxacc); }, + + /** + * Gets the next Y position the object is going to move to. + * @param {Object} th The object being checked. + *
      + *
    • y: the current y position of the object
    • + *
    • accy: the object's currect acceleration in the y direction
    • + *
    • maxacc: the max accleration the object can have (if accy is greater than this then this value is used instead)
    • + *
    + */ + getNextY:function(th) { return th.y+help.limit(th.accy,-th.maxacc,th.maxacc); }, + + /** + * Gets the next Z position the object is going to move to. + * @param {Object} th The object being checked. + *
      + *
    • z: the current z position of the object
    • + *
    • accz: the object's currect acceleration in the z direction
    • + *
    • maxacc: the max accleration the object can have (if accz is greater than this then this value is used instead)
    • + *
    + */ + getNextZ:function(th) { return th.z+help.limit(th.accz,-th.maxacc,th.maxacc); }, + + /** + * Sets the objects current location to its next location using the getNextX and getNextY methods. + * @param {Object} th The object being modified. + *
      + *
    • x: the current x position of the object
    • + *
    • y: the current y position of the object
    • + *
    • accx: the object's currect acceleration in the x direction
    • + *
    • accy: the object's currect acceleration in the y direction
    • + *
    • maxacc: the max accleration the object can have (if either acceleration is greater than this then this value is used instead for that acceleration)
    • + *
    + */ + applyForces:function(th) { + th.x=toys.topview.getNextX(th); + th.y=toys.topview.getNextY(th); + }, + + /** + * This applies acceleration in the Z direction (not nessesarily gravity but whatever the next accerlation on the Z axis is) + * @param {Object} th The object being modified. + *
      + *
    • z: the current z position of the object
    • + *
    • accz: the object's currect acceleration in the z direction
    • + *
    • maxacc: the max accleration the object can have (if accz is greater than this then this value is used instead)
    • + *
    + */ + applyGravity:function(th) { + th.z=toys.topview.getNextZ(th); + }, + + /** + * Degrades all accelerations on an object by one toward zero. + * @param {Object} th The object being modified. + *
      + *
    • xpushing: a boolean that notes whether the object is pushing against something in the x direction.
    • + *
    • ypushing: a boolean that notes whether the object is pushing against something in the y direction.
    • + *
    • accx: the object's currect acceleration in the x direction
    • + *
    • accy: the object's currect acceleration in the y direction
    • + *
    + */ + handleAccellerations:function(th) { + if (!th.xpushing) th.accx=help.goToZero(th.accx); + if (!th.ypushing) th.accy=help.goToZero(th.accy); + + }, + + /** + * Increases the Z acceleration on the object by one. + * @param {Object} th The object being modified. + *
      + *
    • accz: the acceleration on the Z axis
    • + *
    + */ + handleGravity:function(th) { + th.accz++; + }, + + /** + * This sets which frame the object is going to display based on an agregate word that describes predefined states. + * @param {Object} th The object whose frame is being set. + *
      + *
    • xpushing: a boolean that notes whether the object is pushing against something in the x direction.
    • + *
    • ypushing: a boolean that notes whether the object is pushing against something in the y direction.
    • + *
    • haspushing: a boolean that notes if the object changes when pushing against something.
    • + *
    • toucheddown: a boolean that notes if the object is touching something below it on the screen.
    • + *
    • touchedup: a boolean that notes if the object is touching something above it on the screen.<
    • + *
    • touchedright: a boolean that notes if the object is touching something right of it on the screen.<
    • + *
    • touchedleft: a boolean that notes if the object is touching something left of it on the screen.<
    • + *
    • flipside:
    • + *
    • fliph:
    • + *
    • facing:
    • + *
    • frames:
    • + *
    • frame:
    • + *
    • counter:
    • + *
    + * // incomplete + */ + setFrame:function(th) { + var pref="stand"; + if (th.xpushing||th.ypushing) + if (th.haspushing&&(th.toucheddown||th.touchedup||th.touchedleft||th.touchedright)) pref="pushing"; else pref="moving"; + if (th.flipside) + th.fliph=(th.facing==toys.FACE_RIGHT); + th.frame=help.decideFrame(th.counter,th.frames[pref+toys.FACES[th.facing]]); + }, + + /** + * Checks if the specified object is colliding with tiles in the map in an area defined by the object's colw and colh variables as well as the tolerance and approximation variables that are passed in through data. Only tiles in the map marked as solid are checked against. The alogrithm checks the + * @param {Object} th The object that is being checked against the tilemap. + * @param {Object} map This is the asci map that the tile map is generated from. + * @param {Object} tilemap This is the array of tile objects that it itterated over checking for collisions. + * @param {Object} defaulttile The default tile to be returned if nothing can be found. Null can be used here. + * @param {Object} data Passes is extra dat to the function. Can be set as null. + *
      + *
    • tolerance{Integer}: This is subtracted from the collision space to get the maximum collision area for the object. This defaults to 6.
    • + *
    • approximation{Integer}: This is the amount that the checked values are incremented by until they reach the maximum value allowed. This defaults to 10.
    • + *
    + */ + tileCollision:function(th,map,tilemap,defaulttile,data) { + + th.touchedup=false; + th.toucheddown=false; + th.touchedleft=false; + th.touchedright=false; + + var tolerance=(data&&(data.tolerance!=null)?data.tolerance:6); + var approximation=(data&&(data.approximation!=null)?data.approximation:10); + var t=tolerance-approximation; + do { + t+=approximation; + if (t>th.colw-tolerance-1) t=th.colw-tolerance-1; + var bottom=help.getTileInMap(th.x+th.colx+t,th.y+th.coly+th.colh-1,map,defaulttile,tilemap); + var top=help.getTileInMap(th.x+th.colx+t,th.y+th.coly,map,defaulttile,tilemap); + if (map.tileIsSolid(th,top)) th.touchedup=true; + if (map.tileIsSolid(th,bottom)) th.toucheddown=true; + } while (t!=th.colw-tolerance-1); + + t=tolerance-approximation; + do { + t+=approximation; + if (t>th.colh-tolerance-1) t=th.colh-tolerance-1; + var left=help.getTileInMap(th.x+th.colx,th.y+th.coly+t,map,defaulttile,tilemap); + var right=help.getTileInMap(th.x+th.colx+th.colw-1,th.y+th.coly+t,map,defaulttile,tilemap); + if (map.tileIsSolid(th,left)) th.touchedleft=true; + if (map.tileIsSolid(th,right)) th.touchedright=true; + } while (t!=th.colh-tolerance-1); + + if (th.touchedup) { + th.accy=0; + th.y=help.yPixelToTile(map,th.y+th.coly,1)-th.coly; + } + if (th.toucheddown) { + th.accy=0; + th.y=help.yPixelToTile(map,th.y+th.coly+th.colh-1)-th.coly-th.colh; + } + if (th.touchedleft) { + th.accx=0; + th.x=help.xPixelToTile(map,th.x+th.colx,1)-th.colx; + } + if (th.touchedright) { + th.accx=0; + th.x=help.xPixelToTile(map,th.x+th.colx+th.colw-1)-th.colx-th.colw; + } + + }, + + /** + * @param {Object} th The object being checked for collisions. + *
      + *
    • + *
    • + *
    • + *
    • + *
    + * @param {Object} data This is used to pass in other data and arguments. + *
      + *
    • group {String}: (required) This is the group of objects being checked against.
    • + *
    • + *
    • + *
    • + *
    • + *
    //incomplete + */ + spritewallCollision:function(th,data) { + var wl; + for (var i in gbox._objects[data.group]) + if ((!gbox._objects[data.group][i].initialize)&&toys.topview.collides(th,gbox._objects[data.group][i])) { + wl=gbox._objects[data.group][i]; + if (toys.topview.pixelcollides({x:th.x+th.colx,y:th.y+th.coly+th.colhh},wl)) { + th.touchedleft=true; + th.accx=0; + th.x=wl.x+wl.colx+wl.colw-th.colx; + } else if (toys.topview.pixelcollides({x:th.x+th.colx+th.colw,y:th.y+th.coly+th.colhh},wl)) { + th.touchedright=true; + th.accx=0; + th.x=wl.x+wl.colx-th.colw-th.colx; + } + if (toys.topview.pixelcollides({x:th.x+th.colx+th.colhw,y:th.y+th.coly+th.colh},wl)) { + th.toucheddown=true; + th.accy=0; + th.y=wl.y+wl.coly-th.colh-th.coly; + } else if (toys.topview.pixelcollides({x:th.x+th.colx+th.colhw,y:th.y+th.coly},wl)) { + th.touchedup=true; + th.accy=0; + th.y=wl.y+wl.coly+wl.colh-th.coly; + } + } + + }, + + /** + * This checks if the object's z index is 0 which means it has hit the floor. If this has occured it also plays an impact or bounce noise if one is passed in. Note: The area above the floor is in the negative z index space so a value of 1 for z will return that the object has collided with the floor and z will then be set to zero. + * @param {Object} th The object being checked for collision. + *
      + *
    • touchedfloor{boolean}: This value is not passed in but is created or set in the function. This contains the function's return value.
    • + *
    • + *
    • + *
    • + *
    + * @param {Object} data This is used to pass in extra parameters. + *
      + *
    • + *
    + */ + floorCollision:function(th,data) { + th.touchedfloor=false; + if (th.z>0) { + th.accz=(data==null?0:-Math.floor(th.accz/data.bounce)); + if (data&&data.audiobounce&&th.accz) gbox.hitAudio(data.audiobounce); + th.z=0; + th.touchedfloor=true; + } + }, + + /** + * + */ + adjustZindex:function(th) { + gbox.setZindex(th,th.y+th.h); + }, + + /** + * + */ + // Helper: returns the ahead pixel (i.e. destination use action) + getAheadPixel:function(th,data) { + switch (th.facing) { + case toys.FACE_RIGHT:{ + return {x:th.x+th.colx+th.colw+data.distance,y:th.y+th.coly+th.colhh}; + break; + } + case toys.FACE_LEFT:{ + return {x:th.x+th.colx-data.distance,y:th.y+th.coly+th.colhh}; + break; + } + case toys.FACE_UP:{ + return {x:th.x+th.colx+th.colhw,y:th.y+th.coly-data.distance}; + break; + } + case toys.FACE_DOWN:{ + return {x:th.x+th.colx+th.colhw,y:th.y+th.coly+th.colh+data.distance}; + break; + } + } + }, + + /** + * + */ + // Helper: trigger a method in colliding objects (i.e. "use action") + callInColliding:function(th,data) { + for (var i in gbox._objects[data.group]) + if ((!gbox._objects[data.group][i].initialize)&&toys.topview.pixelcollides(data,gbox._objects[data.group][i])) + if (gbox._objects[data.group][i][data.call]) { + gbox._objects[data.group][i][data.call](th); + return i; + } + return false; + }, + + /** + * + */ + // Enemy methods + wander:function(th,map,tilemap,defaulttile,data) { + if ((!th.wandercounter)||(th.toucheddown||th.touchedup||th.touchedleft||th.touchedright)) { + th.wandercounter=help.random(data.minstep,data.steprange); + th.wanderdirection=help.random(0,4); + } else th.wandercounter--; + switch (th.wanderdirection) { + case toys.FACE_LEFT: { + th.xpushing=toys.PUSH_LEFT; + th.ypushing=toys.PUSH_NONE; + th.facing=toys.FACE_LEFT; + th.accx=-data.speed; + th.accy=0; + break; + } + case toys.FACE_RIGHT: { + th.xpushing=toys.PUSH_RIGHT; + th.ypushing=toys.PUSH_NONE; + th.facing=toys.FACE_RIGHT; + th.accx=data.speed; + th.accy=0; + break; + } + case toys.FACE_UP: { + th.ypushing=toys.PUSH_UP; + th.xpushing=toys.PUSH_NONE; + th.facing=toys.FACE_UP; + th.accy=-data.speed; + th.accx=0; + break; + } + case toys.FACE_DOWN: { + th.ypushing=toys.PUSH_DOWN; + th.xpushing=toys.PUSH_NONE; + th.facing=toys.FACE_DOWN; + th.accy=data.speed; + th.accx=0; + break; + } + } + }, + + /** + * + */ + // generators (firebullet specific for topdown - more complex than SHMUP one) + fireBullet:function(gr,id,data) { + + var ts=gbox.getTiles(data.tileset); + + + var obj=gbox.addObject( + help.mergeWithModel( + data,{ + _bullet:true, + zindex:0, + fliph:false, flipv:false, + id:id, + group:gr, + cnt:0, + tileset:"", + frames:{}, + acc:0, + angle:0, + camera:data.from.camera, + accx:(data.accx==null?Math.floor(trigo.translateX(0,data.angle,data.acc)):0), + accy:(data.accy==null?Math.floor(trigo.translateY(0,data.angle,data.acc)):0), + accz:0, + x:(data.sidex==toys.FACE_LEFT?data.from.x-ts.tilehw:(data.sidex==toys.FACE_RIGHT?data.from.x+data.from.w-ts.tilehw:data.from.x+data.from.hw-ts.tilehw))+(data.gapx?data.gapx:0), + y:(data.sidey==toys.FACE_UP?data.from.y-ts.tilehh:(data.sidey==toys.FACE_DOWN?data.from.y+data.from.h-ts.tilehh:data.from.y+data.from.hh-ts.tilehh))+(data.gapy?data.gapy:0), + z:(data.from.z==null?0:data.from.z), + collidegroup:"", + spark:toys.NOOP, + power:1, + lifetime:null, + tilemap:null, + defaulttile:0, + applyzgravity:false, + map:null, + defaulttile:0, + mapindex:"", + spritewalls:null, + colx:(data.fullhit?0:null), + coly:(data.fullhit?0:null), + colh:(data.fullhit?ts.tileh:null), + colw:(data.fullhit?ts.tilew:null), + duration:null, + onWallHit:function() { + this.spark(this); + gbox.trashObject(this); + }, + bulletIsAlive:function() { + return gbox.objectIsVisible(this); + } + } + ) + ); + + obj.initialize=function() { + toys.topview.initialize(this); + }; + + obj[(data.logicon==null?"first":data.logicon)]=function() { + this.cnt=(this.cnt+1)%10; + + if (this.applyzgravity) toys.topview.handleGravity(this); // z-gravity + toys.topview.applyForces(this); // Apply forces + if (this.applyzgravity) toys.topview.applyGravity(this); // z-gravity + if (this.map!=null) toys.topview.tileCollision(this,this.map,this.mapindex,this.defaulttile); // tile collisions + if (this.spritewalls!=null) toys.topview.spritewallCollision(this,{group:this.spritewalls}); // walls collisions + if (this.applyzgravity) toys.topview.floorCollision(this); // Collision with the floor (for z-gravity) + toys.topview.adjustZindex(this); + if (this.duration!=null) { + this.duration--; + if (this.duration==0) gbox.trashObject(this); + } + if (!this.bulletIsAlive()) gbox.trashObject(this); + else if (this.toucheddown||this.touchedup||this.touchedleft||this.touchedright) this.onWallHit(); + else if (this.collidegroup!=null) + for (var i in gbox._objects[this.collidegroup]) + if ((!gbox._objects[this.collidegroup][i].initialize)&&toys.topview.collides(this,gbox._objects[this.collidegroup][i],gbox._objects[this.collidegroup][i].tolerance)) { + if (gbox._objects[this.collidegroup][i]["hitByBullet"]!=null) + if (!gbox._objects[this.collidegroup][i].hitByBullet(this)) { + this.spark(this); + gbox.trashObject(this); + } + } + } + + obj[(data.bliton==null?"blit":data.bliton)]=function() { + if (!gbox.objectIsTrash(this)) + gbox.blitTile(gbox.getBufferContext(),{tileset:this.tileset,tile:help.decideFrame(this.cnt,this.frames),dx:this.x,dy:this.y+this.z,camera:this.camera,fliph:this.fliph,flipv:this.flipv}); + } + + gbox.setZindex(obj,obj.y+obj.h); + + return obj; + + }, + + /** + * + */ + makedoor:function(gr,id,map,data) { + + var mts=gbox.getTiles(map.tileset); + var ts=gbox.getTiles(data.tileset); + + var obj=gbox.addObject( + help.mergeWithModel( + data,{ + zindex:0, + fliph:false, flipv:false, + id:id, + group:gr, + cnt:0, + tileset:"", + frames:{}, + camera:true, + x:data.tilex*mts.tilew, + y:data.tiley*mts.tileh, + z:0, + tilemap:null, + defaulttile:0, + map:map, + colx:(data.fullhit?0:null), + coly:(data.fullhit?0:null), + colh:(data.fullhit?ts.tileh:null), + colw:(data.fullhit?ts.tilew:null), + opening:false, + doorheight:ts.tileh, + opencounter:0, + opening:false, + closing:false, + audiobefore:null, + audioafter:null, + doOpen:function() { + this.opening=true; + }, + whenClosed:toys.NOOP, + whenOpened:toys.NOOP, + whileMoving:toys.NOOP, + hitByBullet:function(by) { + + } + } + ) + ); + + // Closing animation + if (obj.closing) obj.opencounter=obj.doorheight; + + obj.initialize=function() { + this.ismoving=false; + toys.topview.initialize(this); + }; + + obj[(data.logicon==null?"first":data.logicon)]=function() { + if (this.closing) { + if (!this.ismoving) { + if (this.audiobefore) gbox.hitAudio(this.audiobefore); + this.ismoving=true; + } + this.whileMoving(); + this.opencounter--; + if (this.opencounter<0) { + if (this.audioafter) gbox.hitAudio(this.audioafter); + this.ismoving=false; + this.opencounter=0; + this.closing=false; + this.whenClosed(); + } + } + if (this.opening) { + if (!this.ismoving) { + if (this.audiobefore) gbox.hitAudio(this.audiobefore); + this.ismoving=true; + } + this.whileMoving(); + this.opencounter++; + if (this.opencounter>=this.doorheight) { + if (this.audioafter) gbox.hitAudio(this.audioafter); + this.ismoving=false; + if (!this.whenOpened()) gbox.trashObject(this); + } + } + } + + obj[(data.bliton==null?"blit":data.bliton)]=function() { + if (!gbox.objectIsTrash(this)) + gbox.blitTile(gbox.getBufferContext(),{tileset:this.tileset,tile:help.decideFrame(this.cnt,this.frames),dx:this.x,dy:this.y+this.z+this.opencounter,h:this.h-this.opencounter,camera:this.camera,fliph:this.fliph,flipv:this.flipv}); + } + + gbox.setZindex(obj,obj.y+obj.h); + + return obj; + }, + // Set the object speed making sure that the X and Y coords are multiple of the speed. Useful on maze-based games. + setStaticSpeed:function(th,speed) { + th.staticspeed=speed; + th.x=Math.round(th.x/speed)*speed; + th.y=Math.round(th.y/speed)*speed; + } + }, + + + /** + * @namespace shmup The libraries for a 2D top-down Shmup game. + */ + // Shoot'em up specifics + shmup:{ + + /** + * + */ + initialize:function(th,data) { + help.mergeWithModel( + th, + help.mergeWithModel( + data, + { + x:0, y:0, + accx:0, accy:0, + frames:{}, + maxacc:5, controlmaxacc:5, + responsive:0, // Responsiveness + bounds:{x:0,y:0,w:gbox.getScreenW(),h:gbox.getScreenH()}, // Bounds box (ship cannot exit from there) + weapon:0, // Weapon + hittime:5, + camera:false, + flipv:false, fliph:false, + health:1, + tolerance:4 + } + ) + ); + toys.shmup.spawn(th); + }, + + /** + * + */ + spawn:function(th,data) { + th.xpushing=toys.PUSH_NONE; // user is moving side + th.vpushing=toys.PUSH_NONE; // user is moving side + th.counter=0; // self counter + th.hittimer=0; + th.killed=false; + help.copyModel(th,data); + }, + + /** + * + */ + getNextX:function(th) { return th.x+help.limit(th.accx,-th.maxacc,th.maxacc); }, + + /** + * + */ + getNextY:function(th) { return th.y+help.limit(th.accy,-th.maxacc,th.maxacc); }, + + /** + * + */ + controlKeys:function(th,keys) { + + if (gbox.keyIsPressed(keys.left)) { + th.xpushing=toys.PUSH_LEFT; + if (th.accx>th.responsive) th.accx=th.responsive; + th.accx=help.limit(th.accx-1,-th.controlmaxacc,th.controlmaxacc); + } else if (gbox.keyIsPressed(keys.right)) { + th.xpushing=toys.PUSH_RIGHT; + if (th.accx<-th.responsive) th.accx=-th.responsive; + th.accx=help.limit(th.accx+1,-th.controlmaxacc,th.controlmaxacc); + } else th.xpushing=toys.PUSH_NONE; + if (gbox.keyIsPressed(keys.up)) { + th.ypushing=toys.PUSH_UP; + if (th.accy>th.responsive) th.accy=th.responsive; + th.accy=help.limit(th.accy-1,-th.controlmaxacc,th.controlmaxacc); + } else if (gbox.keyIsPressed(keys.down)) { + th.ypushing=toys.PUSH_DOWN; + if (th.accy<-th.responsive) th.accy=-th.responsive; + th.accy=help.limit(th.accy+1,-th.controlmaxacc,th.controlmaxacc); + } else th.ypushing=toys.PUSH_NONE; + }, + + /** + * + */ + applyForces:function(th) { + th.x=toys.shmup.getNextX(th); + th.y=toys.shmup.getNextY(th); + }, + + /** + * + */ + handleAccellerations:function(th) { + if (!th.xpushing) th.accx=help.goToZero(th.accx); + if (!th.ypushing) th.accy=help.goToZero(th.accy); + }, + + /** + * + */ + keepInBounds:function(th) { + if (th.xth.bounds.x+th.bounds.w) { + th.x=th.bounds.x+th.bounds.w-th.w; + th.accx=0; + } + if (th.yth.bounds.y+th.bounds.h) { + th.y=th.bounds.y+th.bounds.h-th.h; + th.accy=0; + } + }, + + /** + * + */ + setFrame:function(th) { + if (th.hittimer) th.hittimer--; + th.frame=help.decideFrame(th.counter,(th.hittimer?th.frames.hit:th.frames.still)); + }, + + /** + * + */ + fireBullet:function(gr,id,data) { + + var ts=gbox.getTiles(data.tileset); + + var obj=gbox.addObject( + help.mergeWithModel( + data,{ + _bullet:true, + fliph:false, flipv:false, + id:id, + group:gr, + cnt:0, + tileset:"", + frames:{}, + acc:0, + angle:0, + camera:false, + accx:(data.accx==null?Math.floor(trigo.translateX(0,data.angle,data.acc)):0), + accy:(data.accy==null?Math.floor(trigo.translateY(0,data.angle,data.acc)):0), + x:data.from.x+data.from.hw-ts.tilehw+(data.gapx?data.gapx:0), + y:(data.upper?data.from.y-ts.tilehh+(data.gapy?data.gapy:0):data.from.y+data.from.h-ts.tilehh-(data.gapy?data.gapy:0)), + collidegroup:"", + spark:toys.NOOP, + power:1 + } + ) + ); + + obj[(data.logicon==null?"first":data.logicon)]=function() { + this.x+=this.accx; + this.y+=this.accy; + this.cnt=(this.cnt+1)%10; + if (!gbox.objectIsVisible(this)) gbox.trashObject(this); + else if (this.collidegroup!=null) + for (var i in gbox._objects[this.collidegroup]) + if ((!gbox._objects[this.collidegroup][i].initialize)&&gbox.collides(this,gbox._objects[this.collidegroup][i],gbox._objects[this.collidegroup][i].tolerance)) { + if (gbox._objects[this.collidegroup][i]["hitByBullet"]!=null) + if (!gbox._objects[this.collidegroup][i].hitByBullet(this)) { + this.spark(this); + gbox.trashObject(this); + } + } + } + + obj[(data.bliton==null?"blit":data.bliton)]=function() { + gbox.blitTile(gbox.getBufferContext(),{tileset:this.tileset,tile:help.decideFrame(this.cnt,this.frames),dx:this.x,dy:this.y,camera:this.camera,fliph:this.side,flipv:this.flipv}); + } + + return obj; + + }, + + /** + * + */ + hitByBullet:function(th,by) { + if (by.power) { + th.health-=by.power; + if (th.health<=0) th.kill(by); else th.hittimer=th.hittime; + } + }, + + /** + * + */ + generateEnemy:function(gr,id,data,model) { + help.mergeWithModel(data,model); + var obj=gbox.addObject( + help.mergeWithModel( + data,{ + id:id, + group:gr, + cnt:0, + tileset:"", + frames:{}, + acc:0, + angle:0, + camera:false, + fliph:false, + flipv:false, + accx:(data.accx==null?Math.floor(trigo.translateX(0,data.angle,data.acc)):0), + accy:(data.accy==null?Math.floor(trigo.translateY(0,data.angle,data.acc)):0), + x:data.x, + y:data.y, + // -- spec + animationset:"still", + defaultanimationset:"still", + hitanimationset:"still", + hittime:5, + script:toys.NOOP, + handler:toys.NOOP, + scriptline:(data.scriptline==null?-1:data.scriptline-1), + newline:true, + waitframes:0, + doframes:0, + mode:0, + line:{}, + dohandler:null, + ended:false, + health:1, + hittimer:0, + kill:toys.NOOP, + tolerance:0, + initialize:null, + invulnerable:false, + hitAnimation:function(time) { + this.hittimer=(time==null?this.hittime:time); + this.animationset=this.hitanimationset; + }, + goTo:function(nl) { // Jump to a line + this.waitframes=0; + this.doframes=0; + this.line={}; + this.scriptline=nl-1; + }, + hitByBullet:function(by) { + if (!this.invulnerable&&by.power) { + this.health-=by.power; + if (this.health<=0) this.kill(this,by); else this.hitAnimation(); + } + } + } + ) + ); + + + obj[(data.logicon==null?"first":data.logicon)]=function() { + if (this.initialize!=null) { + this.initialize(this); + this.initialize=null; + } + if (!this.ended) { + if (!this.waitframes&&!this.doframes&&((this.line.waitfor==null)||this.line.waitfor(this))) { + this.scriptline++; + this.everycnt=-1; + if (this.script[this.scriptline]==null) + this.ended=true; + else { + if (this.script[this.scriptline]["goto"]!=null) this.scriptline=this.script[this.scriptline]["goto"]; + this.line=this.script[this.scriptline]; + if (this.line.afterframes!=null) + this.waitframes=this.line.afterframes; + if (this.line.forframes!=null) + this.doframes=this.line.forframes; + else + this.doframes=1; + if (this.line.cleardo) + this.dohandler=null; + else if (this.line.doit!=null) { + this.dohandler={ + actiontimes:0, + timer:(this.line.doit.every=="keep"?this.dohandler.every:this.line.doit.every), + every:(this.line.doit.every=="keep"?this.dohandler.every:this.line.doit.every), + once:(this.line.doit.once=="keep"?this.dohandler.once:this.line.doit.once), + action:(this.line.doit.action=="keep"?this.dohandler.action:this.line.doit.action), + render:(this.line.doit.render=="keep"?this.dohandler.render:this.line.doit.render) + } + } + + } + } + if (!this.waitframes&&this.doframes&&!this.ended) { + this.doframes--; + if (this.line.setinvulnerable!=null) this.invulnerable=this.line.setinvulnerable; + if (this.line.setx!=null) this.x=this.line.setx; + if (this.line.sety!=null) this.y=this.line.sety; + if (this.line.addx!=null) this.x+=this.line.addx; + if (this.line.addy!=null) this.y+=this.line.addy; + if (this.line.setaccx!=null) this.accx=this.line.setaccx; + if (this.line.setaccy!=null) this.accy=this.line.setaccy; + if (this.line.setacc!=null) { + this.acc=this.line.setacc; + this.accx=Math.floor(trigo.translateX(0,this.angle,this.acc)); + this.accy=Math.floor(trigo.translateY(0,this.angle,this.acc)); + } + if (this.line.addaccx!=null) this.accx+=this.line.addaccx; + if (this.line.addaccy!=null) this.accy+=this.line.addaccy; + if (this.line.addacc!=null) { + this.acc+=this.line.addacc; + this.accx=Math.floor(trigo.translateX(0,this.angle,this.acc)); + this.accy=Math.floor(trigo.translateY(0,this.angle,this.acc)); + } + + if (this.line.setangle!=null) { + this.angle=this.line.setangle; + this.accx=Math.floor(trigo.translateX(0,this.angle,this.acc)); + this.accy=Math.floor(trigo.translateY(0,this.angle,this.acc)); + } + if (this.line.addangle!=null) { + this.angle+=this.line.addangle; + this.accx=Math.floor(trigo.translateX(0,this.angle,this.acc)); + this.accy=Math.floor(trigo.translateY(0,this.angle,this.acc)); + } + if (this.line.everyframe) this.waitframes=this.line.everyframe; + + } + if (this.waitframes>0) this.waitframes--; + } + if (this.dohandler&&(this.dohandler.action!=null)) { + if (this.dohandler.timer==this.dohandler.every) { + this.dohandler.action(this,this.dohandler.actiontimes); + this.dohandler.timer=0; + this.dohandler.actiontimes++; + } else if (!this.dohandler.once) this.dohandler.timer++; + } + if (this.handler!=null) this.handler(this); + + if (this.hittimer) { + this.hittimer--; + if (!this.hittimer) this.animationset=this.defaultanimationset; + } + + this.x+=this.accx; + this.y+=this.accy; + this.cnt=(this.cnt+1)%10; + + } + + obj[(data.bliton==null?"blit":data.bliton)]=function() { + gbox.blitTile(gbox.getBufferContext(),{tileset:this.tileset,tile:help.decideFrame(this.cnt,this.frames[this.animationset]),dx:this.x,dy:this.y,camera:this.camera,fliph:this.side,flipv:this.flipv}); + if (this.dohandler&&(this.dohandler.render!=null)) this.dohandler.render(this); + } + + return obj; + + }, + + /** + * + */ + generateScroller:function(gr,id,data) { + var obj=gbox.addObject( + help.mergeWithModel( + help.cloneObject(data),{ + id:id, group:gr, + y:0, x:0, + stage:{}, + speed:0, + stop:null, // Remember to set the last stop ever! or the last loop! + block:-1, + bly:0, + lblock:-1, + lbly:0, + lget:0, + tbly:0, + trb:0, + maxwidth:0, + loopstart:null, loopend:null, looprounds:0, + panspeed:1, panstimer:0, destspeed:0, + + setLoop:function(st,en) { + this.loopstart=st; + this.loopend=en; + this.lget=1; + this.looprounds=1; + }, + + quitLoop:function() { + this.setLoop(null,null); + this.looprounds=0; + }, + + setSpeed:function(s) { + this.speed=s; + this.destspeed=s; + }, + + panToSpeed:function(s,pans) { + this.destspeed=s; + this.panspeed=pans; + }, + + quitStop:function() { + this.stop=null; + }, + + setStop:function(s) { + this.stop=s; + }, + + setX:function(x) { + if (x<0) this.x=0; else + if (x+gbox.getScreenW()>this.maxwidth) this.x=this.maxwidth-gbox.getScreenW(); + else this.x=x; + } + + } + ) + ); + + obj[(data.logicon==null?"first":data.logicon)]=function() { + if ((this.stop==null)||(this.ythis.destspeed) this.speed--; + this.panstimer=this.panspeed; + } + } + this.y+=this.speed; + if ((this.stop!=null)&&(this.y>=this.stop)) this.y=this.stop; + if ((this.loopend!=null)&&(this.y>this.loopend)) { + this.y=this.loopstart+(this.y-this.loopend); + this.looprounds++; + if (this.lget==1) { + this.block=0; + this.bly=0; + this.lget=2; + } else { + this.block=this.lblock; + this.bly=this.lbly; + } + + } + } + + // Cerca il blocco da mostrare + this.trb=this.block; + this.tbly=this.bly; + do { + this.trb++; + this.tbly+=gbox.getImage(this.stage[this.trb].image).height; + } while (this.tblygbox.getScreenH()) done=true; + gbox.blitAll(gbox.getBufferContext(),gbox.getImage(this.stage[this.trb].image),{dx:-this.x,dy:gbox.getScreenH()-dy}); + this.trb++; + dy+=gbox.getImage(this.stage[this.trb].image).height; + } while (!done); + } + + return obj; + } + }, + + /** + * @namespace platformer The libraries for generating a 2D platformer game. + */ + platformer:{ + + /** + * + */ + initialize:function(th,data) { + help.mergeWithModel( + th, + help.mergeWithModel( + data, + { + maxaccx:5, maxaccy:10, + jumpsize:6, jumpaccy:6, + accx:0, accy:0, + x:0, y:0, + frames:{}, + camera:true, + flipv:false, + side:false + } + ) + ); + toys.platformer.spawn(th); + }, + + /** + * + */ + spawn:function(th,data) { + th.curjsize=0; // current jump size + th.counter=0; // self counter + th.touchedfloor=false; // touched floor + th.touchedceil=false; + th.touchedleftwall=false; + th.touchedrightwall=false; + th.pushing=toys.PUSH_NONE; // user is moving side + th.killed=false; + help.copyModel(th,data); + }, + + /** + * + */ + getNextX:function(th) { return th.x+th.accx; }, + + /** + * + */ + getNextY:function(th) { return th.y+help.limit(th.accy,-th.maxaccy,th.maxaccy); }, + + /** + * + */ + applyGravity:function(th) { + th.x=toys.platformer.getNextX(th); + th.y=toys.platformer.getNextY(th); + }, + + /** + * + */ + horizontalKeys:function(th,keys) { + if (gbox.keyIsPressed(keys.left)) { + th.pushing=toys.PUSH_LEFT; + th.accx=help.limit(th.accx-1,-th.maxaccx,th.maxaccx); + } else if (gbox.keyIsPressed(keys.right)) { + th.pushing=toys.PUSH_RIGHT; + th.accx=help.limit(th.accx+1,-th.maxaccx,th.maxaccx); + } else th.pushing=toys.PUSH_NONE; + }, + + /** + * + */ + verticalTileCollision:function(th,map,tilemap) { + var bottom=help.getTileInMap(th.x+(th.w/2),th.y+th.h,map,0,tilemap); + var top=help.getTileInMap(th.x+(th.w/2),th.y,map,0,tilemap); + th.touchedfloor=false; + th.touchedceil=false; + + if (map.tileIsSolidCeil(th,top)) { + th.accy=0; + th.y=help.yPixelToTile(map,th.y,1); + th.touchedceil=true; + } + if (map.tileIsSolidFloor(th,bottom)) { + th.accy=0; + th.y=help.yPixelToTile(map,th.y+th.h)-th.h; + th.touchedfloor=true; + } + }, + + /** + * + */ + horizontalTileCollision:function(th,map,tilemap,precision) { + var left=0; + var right=0; + var t=0; + + th.touchedleftwall=false; + th.touchedrightwall=false; + + while (t0)&&map.tileIsSolidFloor(th,right)) { + th.accx=0; + th.x=help.xPixelToTile(map,th.x+th.w)-th.w; + th.touchedrightwall=true; + } + t+=gbox.getTiles(map.tileset).tileh/(precision?precision:1); + } + }, + + /** + * Checks if the passed object is touching the floor and can therefore jump at present. + * @param th This is the object being checked for jump ability at the time of calling. + */ + canJump:function(th) { + return th.touchedfloor; + }, + + /** + * + */ + jumpKeys:function(th,key) { + if ((toys.platformer.canJump(th)||(key.doublejump&&(th.accy>=0)))&&gbox.keyIsHit(key.jump)&&(th.curjsize==0)) { + if (key.audiojump) gbox.hitAudio(key.audiojump); + th.accy=-th.jumpaccy; + th.curjsize=th.jumpsize; + return true; + } else if (th.curjsize&&gbox.keyIsHold(key.jump)) { // Jump modulation + th.accy--; + th.curjsize--; + } else + th.curjsize=0; + return false; + }, + + /** + * + */ + bounce:function(th,data) { + th.curjsize=0; + th.accy=-data.jumpsize; + }, + + /** + * + */ + handleAccellerations:function(th) { + // Gravity + if (!th.touchedfloor) th.accy++; + // Attrito + if (th.pushing==toys.PUSH_NONE) if (th.accx) th.accx=help.goToZero(th.accx); + }, + + /** + * + */ + setSide:function(th) { + if (th.accx) th.side=th.accx>0; + }, + + /** + * + */ + setFrame:function(th) { + if (th.touchedfloor) + if (th.pushing!=toys.PUSH_NONE) + th.frame=help.decideFrame(th.counter,th.frames.walking); + else + th.frame=help.decideFrame(th.counter,th.frames.still); + else if (th.accy>0) + th.frame=help.decideFrame(th.counter,th.frames.falling); + else + th.frame=help.decideFrame(th.counter,th.frames.jumping); + }, + + /** + * + */ + auto:{ + // Moves on a platform. It tries to do not fall down, if specified. + // Args: (object,{moveWhileFalling:,speed:}) + // Outs: the frame + goomba:function(th,data) { + if (data.moveWhileFalling||th.touchedfloor) { + if (th.side) { + th.pushing=toys.PUSH_LEFT; + th.accx=-data.speed; + } else { + th.pushing=toys.PUSH_RIGHT; + th.accx=data.speed; + } + } else th.pushing=toys.PUSH_NONE; + }, + dontFall:function(th,map,tilemap) { + if (th.accx&&th.touchedfloor) { + var til; + if (th.accx>0) til=help.getTileInMap(toys.platformer.getNextX(th)+th.w-1+th.accx,th.y+th.h,map,0,tilemap); + else til=help.getTileInMap(toys.platformer.getNextX(th),th.y+th.h,map,0,tilemap); + if (!map.tileIsSolidFloor(th,til)) { + th.side=!th.side; + th.accx=0; + } + } + }, + horizontalBounce:function(th) { + if (th.touchedleftwall||th.touchedrightwall) th.side=!th.side; + } + } + }, + + // State-based toys + // CONSTANTS + TOY_BUSY:0, + TOY_DONE:1, + TOY_IDLE:2, + + // PRIVATE + + // Generical toys method + + /** + * + */ + resetToy:function(th,id) { if (th.toys) delete th.toys[id] }, + + /** + * + */ + getToyValue:function(th,id,v,def) { return ((th.toys==null)||(th.toys[id]==null)?def:th.toys[id][v]) }, + + /** + * + */ + getToyStatus:function(th,id) { return ((th.toys==null)||(th.toys[id]==null)?toys.TOY_BUSY:th.toys[id].__status) }, + + /** + * + */ + _toydone:function(th,id) { + if (th.toys[id].__statusw) w=opt.items[i].length; + gbox.createCanvas("menu-"+id,{w:w*fd.tilew,h:opt.items.length*fd.tileh}); + for (var i=0;i0)) { + if (opt.audiooption) gbox.hitAudio(opt.audiooption); + th.toys[id].selected--; + } else + if (gbox.keyIsHit(opt.keys.down)&&(th.toys[id].selected0) + if (th.toys[id].ok<10) { + th.toys[id].ok++; + toys._toybusy(th,id); + } else return toys._toydone(th,id); // selected > 0 + else return toys._toydone(th,id); // selected == -1 + } else return toys._toybusy(th,id); + }, + + /** + * + */ + // Returns a full customizable object for optimized huds + hud:function(id) { + gbox.createCanvas(id); + return { + w:{}, + surfaceid:id, + + /** + * + */ + updateWidget:function(i){ + if (!this.w[i].__hidden) { + if (this.w[i].widget=="label") { + if (this.w[i].prepad!=null) this.w[i].text=help.prepad(this.w[i].value,this.w[i].prepad,this.w[i].padwith); else + if (this.w[i].postpad!=null) this.w[i].text=help.postpad(this.w[i].value,this.w[i].postpad,this.w[i].padwith); else + this.w[i].text=this.w[i].value+""; + gbox.blitText(gbox.getCanvasContext(this.surfaceid),this.w[i]); + } + if (this.w[i].widget=="symbols") { + var ts=gbox.getTiles(this.w[i].tileset); + gbox.blitClear(gbox.getCanvasContext(this.surfaceid),{x:this.w[i].dx,y:this.w[i].dy,w:((this.w[i].maxshown-1)*this.w[i].gapx)+ts.tilew,h:((this.w[i].maxshown-1)*this.w[i].gapy)+ts.tileh}); + var cnt=this.w[i].value; + for (var x=0;x0) { + gbox.blitTile(gbox.getCanvasContext(this.surfaceid),{tileset:this.w[i].tileset,tile:this.w[i].tiles[(cnt>this.w[i].tiles.length?this.w[i].tiles.length-1:cnt-1)],dx:this.w[i].dx+(x*this.w[i].gapx),dy:this.w[i].dy+(x*this.w[i].gapy),fliph:this.w[i].fliph,flipv:this.w[i].flipv}); + } else + if (this.w[i].emptytile!=null) + gbox.blitTile(gbox.getCanvasContext(this.surfaceid),{tileset:this.w[i].tileset,tile:this.w[i].emptytile,dx:this.w[i].dx+(x*this.w[i].gapx),dy:this.w[i].dy+(x*this.w[i].gapy),fliph:this.w[i].fliph,flipv:this.w[i].flipv}); + cnt-=this.w[i].tiles.length; + } + + } + if (this.w[i].widget=="stack") { + var ts=gbox.getTiles(this.w[i].tileset); + var bw=((this.w[i].maxshown-1)*this.w[i].gapx)+ts.tilew; + gbox.blitClear(gbox.getCanvasContext(this.surfaceid),{x:this.w[i].dx-(this.w[i].rightalign?bw:0),y:this.w[i].dy,w:bw,h:((this.w[i].maxshown-1)*this.w[i].gapy)+ts.tileh}); + for (var x=0;xthis.w[w].maxvalue)) v=this.w[w].maxvalue; + if ((this.w[w].minvalue!=null)&&(v1) th.toys[id].fade=1; + data.alpha=th.toys[id].fade; + gbox.blitFade(tox,data); + if (data.audiofade) gbox.setAudioVolume(data.audiofade,th.toys[id].stv*(1-data.alpha)); + if (data.audiochannelfade) + if (data.alpha==1) + gbox.stopChannel(data.audiochannelfade); + else + gbox.setChannelVolume(data.audiochannelfade,th.toys[id].chv*(1-data.alpha)); + return toys._toyfrombool(th,id,th.toys[id].fade==1) + }, + + /** + * + */ + fadein:function(th,id,tox,data) { + if (toys._maketoy(th,id)||data.resetfade) { + th.toys[id].fade=1; + if (data.audiofade) th.toys[id].stv=gbox.getAudioVolume(data.audiofade); + if (data.audiochannelfade) th.toys[id].chv=gbox.getChannelDefaultVolume(data.audiochannelfade); + } + th.toys[id].fade-=data.fadespeed; + if (th.toys[id].fade<0) th.toys[id].fade=0; + if (th.toys[id].fade) { + data.alpha=th.toys[id].fade; + if (data.audiofade) gbox.setAudioVolume(data.audiofade,th.toys[id].stv*(1-data.alpha)); + if (data.audiochannelfade) gbox.setChannelVolume(data.audiochannelfade,th.toys[id].chv*(1-data.alpha)); + gbox.blitFade(tox,data); + } + return toys._toyfrombool(th,id,th.toys[id].fade==0); + } + }, + + /** + * + */ + text:{ + + /** + * + */ + blink:function(th,id,tox,data) { + if (toys._maketoy(th,id)) { + th.toys[id].texttimer=0; + th.toys[id].visible=false; + th.toys[id].times=0; + } + if (th.toys[id].texttimer>=data.blinkspeed) { + th.toys[id].texttimer=0; + th.toys[id].visible=!th.toys[id].visible; + if (data.times) th.toys[id].times++; + } else th.toys[id].texttimer++; + if (th.toys[id].visible) + gbox.blitText(tox,data); + return toys._toyfrombool(th,id,(data.times?data.timesth.toys[id].lh) th.toys[id].gapx=th.toys[id].lh; + gbox.blit(gbox.getBufferContext(),gbox.getImage(data.image),{dh:th.toys[id].cnt,dw:th.toys[id].lw,dx:data.x,dy:data.y+th.toys[id].lh-th.toys[id].cnt,alpha:data.alpha}); + if (data.reflex) gbox.blit(gbox.getBufferContext(),gbox.getImage(data.image),{dh:th.toys[id].cnt,dw:th.toys[id].lw,dx:data.x,dy:data.y+th.toys[id].lh,alpha:data.reflex,flipv:true}); + if (th.toys[id].cnt>=th.toys[id].lh) + if (data.audioreach) gbox.hitAudio(data.audioreach); + return toys._toybusy(th,id); + } else { + gbox.blitAll(gbox.getBufferContext(),gbox.getImage(data.image),{dx:data.x,dy:data.y}); + if (data.reflex) gbox.blitAll(gbox.getBufferContext(),gbox.getImage(data.image),{dx:data.x,dy:data.y+th.toys[id].lh,alpha:data.reflex,flipv:true}); + + return toys._toydone(th,id); + } + }, + + /** + * + */ + bounce:function(th,id,data) { + if (toys._maketoy(th,id)) { + th.toys[id].accy=data.accy; + th.toys[id].y=data.y; + th.toys[id].h=gbox.getImage(data.image).height; + th.toys[id].done=false; + } + if (!th.toys[id].done) { + if (th.toys[id].y+th.toys[id].h>=data.floory) { + if (data.audiobounce) gbox.hitAudio(data.audiobounce); + th.toys[id].y=data.floory-th.toys[id].h; + th.toys[id].accy=-Math.ceil(th.toys[id].accy/(data.heavy?data.heavy:2)); + th.toys[id].done=(th.toys[id].accy==0); + } else th.toys[id].accy--; + th.toys[id].y-=th.toys[id].accy; + } + gbox.blitAll(gbox.getBufferContext(),gbox.getImage(data.image),{dx:data.x,dy:th.toys[id].y}); + + return toys._toyfrombool(th,id,th.toys[id].done); + } + }, + + /** + * + */ + dialogue: { + + /** + * + */ + render:function(th,id,data){ + if (toys._maketoy(th,id)) { + th.toys[id].newscene=true; + th.toys[id].sceneid=-1; + th.toys[id].ended=false; + th.toys[id].timer=0; + th.toys[id].counter=0; + th.toys[id].anim=0; + gbox.createCanvas("dialogue-"+id); + } + if (!data.hideonend||(data.hideonend&&!th.toys[id].ended)) { + if (th.toys[id].newscene&&!th.toys[id].ended) { + th.toys[id].anim=0; + th.toys[id].timer=0; + th.toys[id].newscene=false; + th.toys[id].sceneid++; + th.toys[id].ended=(th.toys[id].sceneid==data.scenes.length); + if (!th.toys[id].ended) { + th.toys[id].letter=0; + th.toys[id].wait=false; + th.toys[id].scene=data.scenes[th.toys[id].sceneid]; + th.toys[id].fd=gbox.getFont((th.toys[id].scene.font?th.toys[id].scene.font:data.font)); + th.toys[id].sceneH=(th.toys[id].scene.dh?th.toys[id].scene.dh:gbox.getScreenH()); + th.toys[id].sceneW=(th.toys[id].scene.dw?th.toys[id].scene.dw:gbox.getScreenW()); + th.toys[id].sceneX=(th.toys[id].scene.dx?th.toys[id].scene.dx:0); + th.toys[id].sceneY=(th.toys[id].scene.dy?th.toys[id].scene.dy:0); + gbox.blitClear(gbox.getCanvasContext("dialogue-"+id)); + if (th.toys[id].scene.slide) { + gbox.blitAll(gbox.getCanvasContext("dialogue-"+id),gbox.getImage(th.toys[id].scene.slide.image),{dx:th.toys[id].scene.slide.x,dy:th.toys[id].scene.slide.y}); + } + if (th.toys[id].scene.scroller) { + gbox.createCanvas("scroller-"+id,{w:th.toys[id].sceneW,h:(th.toys[id].scene.scroller.length)*(th.toys[id].fd.tileh+th.toys[id].scene.spacing)}); + for (var i=0;ith.toys[id].scene.talk[row].length) { + tmp-=th.toys[id].scene.talk[row].length; + row++; + if (row==th.toys[id].scene.talk.length) { + row=-1; + break; + } + } + if (row>=0) { + gbox.blitText(gbox.getCanvasContext("dialogue-"+id),{ + font:data.font, + dx:data.who[th.toys[id].scene.who].x, + dy:(data.who[th.toys[id].scene.who].y)+(row*th.toys[id].fd.tileh), + text:th.toys[id].scene.talk[row].substr(0,tmp) + }); + } else + th.toys[id].wait=true; + } + + } else if (th.toys[id].scene.scroller) { // SCROLLER (i.e. credits) + + if (th.toys[id].counter==th.toys[id].scene.speed) { + th.toys[id].letter++; + th.toys[id].counter=0; + if (th.toys[id].letter==(gbox.getCanvas("scroller-"+id).height+th.toys[id].scene.push)) + th.toys[id].wait=true; + } + + } else if (th.toys[id].scene.bonus) { // BONUS (classic bonus award screen) + for (var row=0;row<=th.toys[id].letter;row++) { + if (th.toys[id].scene.bonus[row].text) + gbox.blitText(gbox.getCanvasContext("bonus-"+id),{ + font:data.font, + dx:0, + dy:(row*(th.toys[id].fd.tileh+th.toys[id].scene.spacing)), + text:th.toys[id].scene.bonus[row].text + }); + else if (th.toys[id].scene.bonus[row].mul) { + // Mask is %VAL%e%MUL%=%TOT% + th.toys[id].scene.bonus[row].tmptext=th.toys[id].scene.bonus[row].mask.replace(/%VAL%/,th.toys[id].timer).replace(/%MUL%/,th.toys[id].scene.bonus[row].mul).replace(/%TOT%/,(th.toys[id].timer*th.toys[id].scene.bonus[row].mul)); + gbox.blitText(gbox.getCanvasContext("bonus-"+id),{ + clear:true, + font:data.font, + dx:0, + dy:(row*(th.toys[id].fd.tileh+th.toys[id].scene.spacing)), + text:th.toys[id].scene.bonus[row].tmptext + }); + } + } + + if (!th.toys[id].wait) { + var next=false; + if (th.toys[id].scene.bonus[th.toys[id].letter].mul&&!th.toys[id].scene.bonus[th.toys[id].letter].text) { + if (th.toys[id].counter>=th.toys[id].scene.bonus[th.toys[id].letter].speed) { + th.toys[id].counter=0; + th.toys[id].timer++; + if (th.toys[id].timer>th.toys[id].scene.bonus[th.toys[id].letter].mulvalue) { + th.toys[id].scene.bonus[th.toys[id].letter].text=th.toys[id].scene.bonus[th.toys[id].letter].tmptext; + next=true; + } else { + if (th.toys[id].scene.bonus[th.toys[id].letter].callback) + th.toys[id].scene.bonus[th.toys[id].letter].callback(th.toys[id].scene.bonus[th.toys[id].letter],th.toys[id].scene.bonus[th.toys[id].letter].arg); + } + } + + } else if (th.toys[id].counter>=th.toys[id].scene.speed) next=true; + if (next) { + if (th.toys[id].letter==th.toys[id].scene.bonus.length-1) + th.toys[id].wait=true; + else { + th.toys[id].letter++; + if (th.toys[id].scene.bonus[th.toys[id].letter].mul) { + th.toys[id].scene.bonus[th.toys[id].letter].text=null; + th.toys[id].scene.bonus[th.toys[id].letter].tmptext=null; + th.toys[id].timer=0; + } + th.toys[id].counter=0; + } + } + } + } + + } + + } + + // RENDERING + + + if (th.toys[id].scene.talk) { // DIALOGUES + if (data.who[th.toys[id].scene.who].box) + gbox.blitRect(gbox.getBufferContext(),data.who[th.toys[id].scene.who].box); + if (data.who[th.toys[id].scene.who].tileset) { + th.toys[id].anim=(th.toys[id].anim+1)%20; + gbox.blitTile(gbox.getBufferContext(),{tileset:data.who[th.toys[id].scene.who].tileset,tile:help.decideFrame(th.toys[id].anim,data.who[th.toys[id].scene.who].frames),dx:data.who[th.toys[id].scene.who].portraitx,dy:data.who[th.toys[id].scene.who].portraity,camera:false,fliph:data.who[th.toys[id].scene.who].fliph,flipv:data.who[th.toys[id].scene.who].flipv}); + } + gbox.blitAll(gbox.getBufferContext(),gbox.getCanvas("dialogue-"+id),{dx:0,dy:0}); + } else if (th.toys[id].scene.scroller) // SCROLLER (i.e. credits) + gbox.blit(gbox.getBufferContext(),gbox.getCanvas("scroller-"+id),{dx:th.toys[id].sceneX,dy:th.toys[id].sceneY+(th.toys[id].letter=0) { + this.x+=this.accx; + this.y+=this.accy; + if (this.gravity) this.accy++; + if ((this.timer==this.toptimer)||(this.trashoffscreen&&(!gbox.objectIsVisible(this)))) gbox.trashObject(this); + } + } + + obj[(data.bliton==null?"blit":data.bliton)]=function() { + if ((this.timer>=0)&&(!this.blinkspeed||(Math.floor(this.timer/this.blinkspeed)%2))) + gbox.blitTile(gbox.getBufferContext(),{tileset:this.tileset,tile:help.decideFrame(this.timer,this.frames),dx:this.x,dy:this.y,camera:this.camera,fliph:this.fliph,flipv:this.flipv,alpha:this.alpha}); + } + + return obj; + }, + + /** + * + */ + popupText:function(th,group,id,data) { + data.text+=""; + var fd=gbox.getFont(data.font); + + var obj=gbox.addObject( + help.mergeWithModel( + data,{ + id:id, + group:group, + x:Math.floor(th.x+th.hw-(fd.tilehw*data.text.length)), + y:th.y-fd.tilehh, + vaccy:-data.jump, + font:"small", + keep:0, + text:data.text+"", + cnt:0, + camera:th.camera + } + ) + ); + + obj.initialize=function() { + var fd=gbox.getFont(this.font); + gbox.createCanvas("poptext-"+this.id,{w:this.text.length*fd.tilew,h:fd.tileh}); + gbox.blitText(gbox.getCanvasContext("poptext-"+this.id),{font:this.font,text:this.text,dx:0,dy:0}); + } + + obj.onpurge=function() { + gbox.deleteCanvas("poptext-"+this.id); + } + + obj[(data.logicon==null?"first":data.logicon)]=function() { + if (gbox.objectIsVisible(this)) { + if (this.vaccy) + this.vaccy++; + else + this.cnt++; + this.y+=this.vaccy; + if (this.cnt>=this.keep) gbox.trashObject(this); + } else gbox.trashObject(this); + } + + obj[(data.bliton==null?"blit":data.bliton)]=function() { + gbox.blitAll(gbox.getBufferContext(),gbox.getCanvas("poptext-"+this.id),{dx:this.x,dy:this.y,camera:this.camera}); + } + + return obj; + }, + + /** + * + */ + bounceDie:function(th,group,id,data){ + var obj=gbox.addObject( + help.mergeWithModel( + data,{ + id:id, + group:group, + tileset:th.tileset, + frame:th.frame, + side:th.side, + frames:th.frames.die, + x:th.x, + y:th.y, + vaccy:-data.jump, + accx:0, + flipv:data.flipv, + cnt:0, + blinkspeed:0, + camera:th.camera + } + ) + ); + + obj[(data.logicon==null?"first":data.logicon)]=function() { + if (gbox.objectIsVisible(this)) { + this.vaccy++; + this.y+=this.vaccy; + this.x+=this.accx; + this.cnt++; + } else gbox.trashObject(this); + } + + obj[(data.bliton==null?"blit":data.bliton)]=function() { + if (!this.blinkspeed||(Math.floor(this.cnt/this.blinkspeed)%2)) + gbox.blitTile(gbox.getBufferContext(),{tileset:this.tileset,tile:help.decideFrame(this.cnt,this.frames),dx:this.x,dy:this.y,camera:this.camera,fliph:this.side,flipv:this.flipv}); + } + + return obj; + } + }, + + /** + * + */ + audio:{ + + /** + * + */ + fadeOut:function(th,group,id,data){ + var obj=gbox.addObject( + help.mergeWithModel( + data,{ + id:id, + group:group, + fadespeed:-0.02*(data.fadein?-1:1), + stoponmute:true, + audio:null, + channel:null, + destination:null + } + ) + ); + + obj[(data.logicon==null?"first":data.logicon)]=function() { + if (this.destination==null) + if (this.audio) + if (this.fadespeed>0) this.destination=1; else this.destination=0; + else + if (this.fadespeed>0) this.destination=gbox.getChannelDefaultVolume(this.channel); else this.destination=0; + if (this.fadespeed>0) gbox.playAudio(this.audio); + } + + obj[(data.bliton==null?"blit":data.bliton)]=function() { + if (this.audio) gbox.changeAudioVolume(this.audio,this.fadespeed); + if (this.channel) gbox.changeChannelVolume(this.channel,this.fadespeed); + if ( + (this.audio&&( + ((this.fadespeed<0)&&(gbox.getAudioVolume(this.audio)<=this.destination))|| + ((this.fadespeed>0)&&(gbox.getAudioVolume(this.audio)>=this.destination)) + ))|| + (this.channel&&( + ((this.fadespeed<0)&&(gbox.getChannelVolume(this.channel)<=this.destination))|| + ((this.fadespeed>0)&&(gbox.getChannelVolume(this.channel)>=this.destination)) + )) + ) { + if (this.channel&&this.stoponmute&&(this.fadespeed<0)) gbox.stopChannel(this.channel); + if (this.audio&&this.stoponmute&&(this.fadespeed<0)) gbox.stopAudio(this.audio); + gbox.trashObject(this); + } + } + } + + } + + } + + +} \ No newline at end of file diff --git a/deps/akihabara-core-1.3.1/akihabara/trigo.js b/deps/akihabara-core-1.3.1/akihabara/trigo.js new file mode 100644 index 0000000..de75b23 --- /dev/null +++ b/deps/akihabara-core-1.3.1/akihabara/trigo.js @@ -0,0 +1,76 @@ +// --- +// Copyright (c) 2010 Francesco Cottone, http://www.kesiev.com/ +// --- + +/** + * @namespace Trigo module provides some math stuff for moving objects in a + * direction or following a round path. + */ +var trigo={ + ANGLE_RIGHT:0, + ANGLE_DOWN:Math.PI*0.5, + ANGLE_LEFT:Math.PI, + ANGLE_UP:Math.PI*1.5555555, + + /** + * Adds two angles together (radians). + * @param {Float} a Base angle. + * @param {Float} add The angle you're adding to the base angle. + * @returns The resultant angle, always between 0 and 2*pi. + */ + addAngle:function(a,add) { + a=(a+add)%(Math.PI*2); + if (a<0) return (Math.PI*2)+a; else return a; + }, + /** + * Gets the distance between two points. + * @param {Object} p1 This is an object containing x and y params for the first point. + * @param {Object} p2 This is an object containing x and y params for the second point. + * @returns The distance between p1 and p2. + */ + getDistance:function(p1,p2) { + return Math.sqrt(Math.pow(p2.x-p1.x,2)+Math.pow(p2.y-p1.y,2)) + }, + + /** + * Calculates the angle between two points. + * @param {Object} p1 This is an object containing x and y params for the first point. + * @param {Object} p2 This is an object containing x and y params for the second point. + * @param {Float} transl (Optional) Adds an angle (in radians) to the result. Defaults to 0. + * @returns The angle between points p1 and p2, plus transl. + */ + getAngle:function(p1,p2,transl) { + return this.addAngle(Math.atan2(p2.y-p1.y,p2.x-p1.x),(transl?transl:0)); + }, + + /** + * Translates a point by a vector defined by angle and distance. This does not return a value but rather modifies the x and y values of p1. + * @param {Object} p1 This is an object containing x and y params for the point. + * @param {Float} a The angle of translation (rad). + * @param {Float} d The distance of translation. + */ + translate:function(p1,a,d) { + p1.x=p1.x+Math.cos(a)*d; + p1.y=p1.y+Math.sin(a)*d; + }, + + /** + * Translates an x component of a coordinate by a vector defined by angle and distance. This returns its component translation. + * @param {Float} x1 This is an x coordinate. + * @param {Float} a The angle of translation (rad). + * @param {Float} d The distance of translation. + */ + translateX:function(x1,a,d) { + return x1+Math.cos(a)*d + }, + + /** + * Translates a y component of a coordinate by a vector defined by angle and distance. This returns its component translation. + * @param {Float} y1 This is a y coordinate. + * @param {Float} a The angle of translation (rad). + * @param {Float} d The distance of translation. + */ + translateY:function(y1,a,d) { + return y1+Math.sin(a)*d; + } +} diff --git a/deps/akihabara-core-1.3.1/extra-halloffame.html b/deps/akihabara-core-1.3.1/extra-halloffame.html new file mode 100644 index 0000000..8d455fd --- /dev/null +++ b/deps/akihabara-core-1.3.1/extra-halloffame.html @@ -0,0 +1,281 @@ + + + + + + + + + + + + + + + + diff --git a/deps/akihabara-core-1.3.1/extras/AkibaHero/akibahero-mapper.html b/deps/akihabara-core-1.3.1/extras/AkibaHero/akibahero-mapper.html new file mode 100644 index 0000000..d35d389 --- /dev/null +++ b/deps/akihabara-core-1.3.1/extras/AkibaHero/akibahero-mapper.html @@ -0,0 +1,937 @@ + + +
    Marker tool (use with Safari/Opera - press play here and then any key)
    + +
    Mapper tool

    + + + + \ No newline at end of file diff --git a/deps/akihabara-core-1.3.1/game-capman.html b/deps/akihabara-core-1.3.1/game-capman.html new file mode 100644 index 0000000..f47528e --- /dev/null +++ b/deps/akihabara-core-1.3.1/game-capman.html @@ -0,0 +1,720 @@ + + + + + + + + + + + + + + + + diff --git a/deps/akihabara-core-1.3.1/resources/audio/capman-ingame.mp3 b/deps/akihabara-core-1.3.1/resources/audio/capman-ingame.mp3 new file mode 100644 index 0000000..0b1d858 Binary files /dev/null and b/deps/akihabara-core-1.3.1/resources/audio/capman-ingame.mp3 differ diff --git a/deps/akihabara-core-1.3.1/resources/audio/capman-ingame.ogg b/deps/akihabara-core-1.3.1/resources/audio/capman-ingame.ogg new file mode 100644 index 0000000..2c35939 Binary files /dev/null and b/deps/akihabara-core-1.3.1/resources/audio/capman-ingame.ogg differ diff --git a/deps/akihabara-core-1.3.1/resources/audio/coin.mp3 b/deps/akihabara-core-1.3.1/resources/audio/coin.mp3 new file mode 100644 index 0000000..eda4dfd Binary files /dev/null and b/deps/akihabara-core-1.3.1/resources/audio/coin.mp3 differ diff --git a/deps/akihabara-core-1.3.1/resources/audio/coin.ogg b/deps/akihabara-core-1.3.1/resources/audio/coin.ogg new file mode 100644 index 0000000..5cfb9c0 Binary files /dev/null and b/deps/akihabara-core-1.3.1/resources/audio/coin.ogg differ diff --git a/deps/akihabara-core-1.3.1/resources/audio/die.mp3 b/deps/akihabara-core-1.3.1/resources/audio/die.mp3 new file mode 100644 index 0000000..9d8d0e5 Binary files /dev/null and b/deps/akihabara-core-1.3.1/resources/audio/die.mp3 differ diff --git a/deps/akihabara-core-1.3.1/resources/audio/die.ogg b/deps/akihabara-core-1.3.1/resources/audio/die.ogg new file mode 100644 index 0000000..da474bd Binary files /dev/null and b/deps/akihabara-core-1.3.1/resources/audio/die.ogg differ diff --git a/deps/akihabara-core-1.3.1/resources/audio/eat.mp3 b/deps/akihabara-core-1.3.1/resources/audio/eat.mp3 new file mode 100644 index 0000000..da3703d Binary files /dev/null and b/deps/akihabara-core-1.3.1/resources/audio/eat.mp3 differ diff --git a/deps/akihabara-core-1.3.1/resources/audio/eat.ogg b/deps/akihabara-core-1.3.1/resources/audio/eat.ogg new file mode 100644 index 0000000..62c25bf Binary files /dev/null and b/deps/akihabara-core-1.3.1/resources/audio/eat.ogg differ diff --git a/deps/akihabara-core-1.3.1/resources/audio/halloffame-theme.mp3 b/deps/akihabara-core-1.3.1/resources/audio/halloffame-theme.mp3 new file mode 100644 index 0000000..c35c26b Binary files /dev/null and b/deps/akihabara-core-1.3.1/resources/audio/halloffame-theme.mp3 differ diff --git a/deps/akihabara-core-1.3.1/resources/audio/halloffame-theme.ogg b/deps/akihabara-core-1.3.1/resources/audio/halloffame-theme.ogg new file mode 100644 index 0000000..70acf8d Binary files /dev/null and b/deps/akihabara-core-1.3.1/resources/audio/halloffame-theme.ogg differ diff --git a/deps/akihabara-core-1.3.1/resources/audio/laser.mp3 b/deps/akihabara-core-1.3.1/resources/audio/laser.mp3 new file mode 100644 index 0000000..6bd69a4 Binary files /dev/null and b/deps/akihabara-core-1.3.1/resources/audio/laser.mp3 differ diff --git a/deps/akihabara-core-1.3.1/resources/audio/laser.ogg b/deps/akihabara-core-1.3.1/resources/audio/laser.ogg new file mode 100644 index 0000000..2a54b13 Binary files /dev/null and b/deps/akihabara-core-1.3.1/resources/audio/laser.ogg differ diff --git a/deps/akihabara-core-1.3.1/resources/audio/powerup3.mp3 b/deps/akihabara-core-1.3.1/resources/audio/powerup3.mp3 new file mode 100644 index 0000000..18b8d23 Binary files /dev/null and b/deps/akihabara-core-1.3.1/resources/audio/powerup3.mp3 differ diff --git a/deps/akihabara-core-1.3.1/resources/audio/powerup3.ogg b/deps/akihabara-core-1.3.1/resources/audio/powerup3.ogg new file mode 100644 index 0000000..9d2a471 Binary files /dev/null and b/deps/akihabara-core-1.3.1/resources/audio/powerup3.ogg differ diff --git a/deps/akihabara-core-1.3.1/resources/audio/select.mp3 b/deps/akihabara-core-1.3.1/resources/audio/select.mp3 new file mode 100644 index 0000000..fd5ceec Binary files /dev/null and b/deps/akihabara-core-1.3.1/resources/audio/select.mp3 differ diff --git a/deps/akihabara-core-1.3.1/resources/audio/select.ogg b/deps/akihabara-core-1.3.1/resources/audio/select.ogg new file mode 100644 index 0000000..0829a93 Binary files /dev/null and b/deps/akihabara-core-1.3.1/resources/audio/select.ogg differ diff --git a/deps/akihabara-core-1.3.1/resources/audio/start.mp3 b/deps/akihabara-core-1.3.1/resources/audio/start.mp3 new file mode 100644 index 0000000..01de403 Binary files /dev/null and b/deps/akihabara-core-1.3.1/resources/audio/start.mp3 differ diff --git a/deps/akihabara-core-1.3.1/resources/audio/start.ogg b/deps/akihabara-core-1.3.1/resources/audio/start.ogg new file mode 100644 index 0000000..a6bccd4 Binary files /dev/null and b/deps/akihabara-core-1.3.1/resources/audio/start.ogg differ diff --git a/deps/akihabara-core-1.3.1/resources/capman/cels.png b/deps/akihabara-core-1.3.1/resources/capman/cels.png new file mode 100644 index 0000000..cd76f6d Binary files /dev/null and b/deps/akihabara-core-1.3.1/resources/capman/cels.png differ diff --git a/deps/akihabara-core-1.3.1/resources/capman/font.png b/deps/akihabara-core-1.3.1/resources/capman/font.png new file mode 100644 index 0000000..89d9c09 Binary files /dev/null and b/deps/akihabara-core-1.3.1/resources/capman/font.png differ diff --git a/deps/akihabara-core-1.3.1/resources/capman/logo.png b/deps/akihabara-core-1.3.1/resources/capman/logo.png new file mode 100644 index 0000000..17885d9 Binary files /dev/null and b/deps/akihabara-core-1.3.1/resources/capman/logo.png differ diff --git a/deps/akihabara-core-1.3.1/resources/halloffame/font.png b/deps/akihabara-core-1.3.1/resources/halloffame/font.png new file mode 100644 index 0000000..301219a Binary files /dev/null and b/deps/akihabara-core-1.3.1/resources/halloffame/font.png differ diff --git a/deps/akihabara-core-1.3.1/resources/halloffame/kesiev.png b/deps/akihabara-core-1.3.1/resources/halloffame/kesiev.png new file mode 100644 index 0000000..bbcc12d Binary files /dev/null and b/deps/akihabara-core-1.3.1/resources/halloffame/kesiev.png differ diff --git a/deps/akihabara-core-1.3.1/resources/halloffame/logo.png b/deps/akihabara-core-1.3.1/resources/halloffame/logo.png new file mode 100644 index 0000000..d80063f Binary files /dev/null and b/deps/akihabara-core-1.3.1/resources/halloffame/logo.png differ diff --git a/deps/akihabara-core-1.3.1/tool-settings.html b/deps/akihabara-core-1.3.1/tool-settings.html new file mode 100644 index 0000000..24a924e --- /dev/null +++ b/deps/akihabara-core-1.3.1/tool-settings.html @@ -0,0 +1,204 @@ + + + + + + Akihabara setup + + +

    Akihabara setup

    +
    +

    Gamebox buttons setup

    +

    These settings will be used by any Gamebox game hosted by this domain. Click a box and press a key to customize.

    +
      +
    • Up
    • +
    • Down
    • +
    • Left
    • +
    • Right
    • +
    • A Button
    • +
    • B Button
    • +
    • C Button
    • +
    + +
    +
    +

    Gamebox audio setup

    +

    These settings will be used by any Gamebox game hosted by this domain. Audio is still in beta and is available on some browsers by default.

    +
      +
    • Disable audio
    • +
    +
    +
    +

    Gamebox screen setup

    +

    These settings will be used by any Gamebox game hosted by this domain.

    +
      +
    • Loading screen
    • +
    • Full screen effects
    • +
    +
    +
    +

    Gamebox experimental

    +

    This checkbox enables misc experimental features that are really unstable. Use at yout own risk!

    +
      +
    • Enable experimental features
    • +
    +

    Experimental features are: iPad with 3.6 firmware, iPhone with 4.x betas (single channel mode), IE9 Beta in IE7 Compat mode, latest builds of Konqueror (single channle mode) and all other audio-enabled devices (untested)

    +
    +
    + + +
    + + + diff --git a/index.ejs b/index.ejs new file mode 100644 index 0000000..27465b0 --- /dev/null +++ b/index.ejs @@ -0,0 +1,38 @@ + + + + + WebSocket Whiteboard Example + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/package.json b/package.json index c13df3a..ae32cd7 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,10 @@ "node": "~0.6.10" }, "dependencies": { - "ws" : "0.4.7", - "mongodb" : "0.9.9-4" + "websocket" : "1.0.4", + "mongodb" : "0.9.9-4", + "express" : "2.5.8", + "ejs" : "0.6.1" }, "devDependencies": {}, "optionalDependencies": {} diff --git a/public/akihabara/buttons.png b/public/akihabara/buttons.png new file mode 100644 index 0000000..3b056bb Binary files /dev/null and b/public/akihabara/buttons.png differ diff --git a/public/akihabara/debugfont.png b/public/akihabara/debugfont.png new file mode 100644 index 0000000..3564b40 Binary files /dev/null and b/public/akihabara/debugfont.png differ diff --git a/public/akihabara/dpad.png b/public/akihabara/dpad.png new file mode 100644 index 0000000..ff536b5 Binary files /dev/null and b/public/akihabara/dpad.png differ diff --git a/public/akihabara/fretboard.png b/public/akihabara/fretboard.png new file mode 100644 index 0000000..52cd354 Binary files /dev/null and b/public/akihabara/fretboard.png differ diff --git a/public/akihabara/gamecycle.js b/public/akihabara/gamecycle.js new file mode 100644 index 0000000..bc678a8 --- /dev/null +++ b/public/akihabara/gamecycle.js @@ -0,0 +1,429 @@ +// --- +// Copyright (c) 2010 Francesco Cottone, http://www.kesiev.com/ +// --- + +/** + * @namespace + * Gamecycle contains your basic game loop: intro, menus, + * crossfading between stages/lifes, gameover and ending. + */ +var gamecycle={ + + /** + * Gamecycle constructor - initializes a new game object + * + * @param id unique id of object + * @param group name of group to store the object in + */ + createMaingame:function(id,group) { + return gbox.addObject({ + id:id, + group:group, + counter:0, + difficulty:0, + + // state transition + state:50, + stateFirstIteration:true, + + hud:{}, + + /** + * This method is called whenever you load a new map. It's meant to be + * overridden when you create your game. + */ + changeLevel:function() { }, + + /** + * This method is called every time a player is "reborn". This method is + * meant to be overridden since you have to do garbage collection. + */ + newLife:function() { }, + + // game disclaimer animation (if needed) + gameDisclaimerAnimation:function(reset) { + return true; + }, + + // game intro animation + gameIntroAnimation:function(reset) { + if (reset) { + gbox.stopChannel("bgmusic"); + toys.resetToy(this,"default-blinker"); + } else { + gbox.blitFade(gbox.getBufferContext(),{alpha:1}); + return toys.text.blink(this,"default-blinker",gbox.getBufferContext(),{font:"small",text:"LETS BEGIN!",valign:gbox.ALIGN_MIDDLE,halign:gbox.ALIGN_CENTER,dx:0,dy:0,dw:gbox.getScreenW(),dh:gbox.getScreenH(),blinkspeed:5,times:6}); + } + }, + + // level intro animation + levelIntroAnimation:function(reset) { + if (reset) { + gbox.stopChannel("bgmusic"); + toys.resetToy(this,"default-blinker"); + } else { + gbox.blitFade(gbox.getBufferContext(),{alpha:1}); + return toys.text.blink(this,"default-blinker",gbox.getBufferContext(),{font:"small",text:"GET READY!",valign:gbox.ALIGN_MIDDLE,halign:gbox.ALIGN_CENTER,dx:0,dy:0,dw:gbox.getScreenW(),dh:gbox.getScreenH(),blinkspeed:5,times:6}); + } + }, + + // Life intro animation + newlifeIntroAnimation:function(reset) { + if (reset) { + gbox.stopChannel("bgmusic"); + toys.resetToy(this,"default-blinker"); + } else { + gbox.blitFade(gbox.getBufferContext(),{alpha:1}); + return toys.text.fixed(this,"default-blinker",gbox.getBufferContext(),{font:"small",text:"GET READY!",valign:gbox.ALIGN_MIDDLE,halign:gbox.ALIGN_CENTER,dx:0,dy:0,dw:gbox.getScreenW(),dh:gbox.getScreenH(),time:30}); + } + }, + + // gameover animation + gameoverIntroAnimation:function(reset) { + if (reset) { + gbox.stopChannel("bgmusic"); + toys.resetToy(this,"default-blinker"); + } else { + gbox.blitFade(gbox.getBufferContext(),{alpha:1}); + return toys.text.fixed(this,"default-blinker",gbox.getBufferContext(),{font:"small",text:"GAME OVER",valign:gbox.ALIGN_MIDDLE,halign:gbox.ALIGN_CENTER,dx:0,dy:0,dw:gbox.getScreenW(),dh:gbox.getScreenH(),time:50}); + } + }, + + // game title animation + gameTitleIntroAnimation:function(reset) { + if (reset) + gbox.stopChannel("bgmusic"); + else { + gbox.blitFade(gbox.getBufferContext(),{alpha:1}); + gbox.blitText(gbox.getBufferContext(),{font:"small",text:"GAME TITLE",valign:gbox.ALIGN_MIDDLE,halign:gbox.ALIGN_CENTER,dx:0,dy:0,dw:gbox.getScreenW(),dh:gbox.getScreenH()-100}); + } + }, + + // End level animation + endlevelIntroAnimation:function(reset) { + if (reset) { + toys.resetToy(this,"default-blinker"); + } else { + return toys.text.blink(this,"default-blinker",gbox.getBufferContext(),{font:"small",text:"WELL DONE!",valign:gbox.ALIGN_MIDDLE,halign:gbox.ALIGN_CENTER,dx:0,dy:0,dw:gbox.getScreenW(),dh:gbox.getScreenH(),blinkspeed:5,times:10}); + } + }, + + // Game ending + gameEndingIntroAnimation:function(reset) { + if (reset) { + toys.resetToy(this,"default-blinker"); + } else { + gbox.blitFade(gbox.getBufferContext(),{alpha:1}); + return toys.text.blink(this,"default-blinker",gbox.getBufferContext(),{font:"small",text:"CONGRATULATIONS!",valign:gbox.ALIGN_MIDDLE,halign:gbox.ALIGN_CENTER,dx:0,dy:0,dw:gbox.getScreenW(),dh:gbox.getScreenH(),blinkspeed:5,times:10}); + } + }, + + // PRESS START + pressStartIntroAnimation:function(reset) { + if (reset) { + toys.resetToy(this,"default-blinker"); + } else { + toys.text.blink(this,"default-blinker",gbox.getBufferContext(),{font:"small",text:"PRESS A TO START",valign:gbox.ALIGN_MIDDLE,halign:gbox.ALIGN_CENTER,dx:0,dy:Math.floor(gbox.getScreenH()/3),dw:gbox.getScreenW(),dh:Math.floor(gbox.getScreenH()/3)*2,blinkspeed:10}); + return gbox.keyIsHit("a"); + } + }, + + /** + * This method is called when the player dies. + */ + gameIsOver:function() { return true; }, + + /** + * Actions done during the game (i.e. stage is clear or other ending conditions) + */ + gameEvents:function() { + + }, + + gameMenu:function(reset) { + if (reset) { + toys.resetToy(this,"difficulty"); + } else { + gbox.blitFade(gbox.getBufferContext(),{alpha:0.5}); + if (toys.ui.menu(this,"difficulty",{audiooption:"default-menu-option",audioconfirm:"default-menu-confirm",font:"small",keys:{up:"up",down:"down",ok:"a",cancel:"b"},selector:">",items:["EASY","NORMAL","HARD"],x:10,y:10})) { + if (toys.getToyValue(this,"difficulty","ok") == -1) return -1; + else { + this.difficulty=toys.getToyValue(this,"difficulty","selected"); + return true; + } + } + return false; + } + }, + + // CHECK + + gameIsHold:function() { // Use this clause to check collision and kill player: if true the level is changing + return (this.state==400)||(this.state==401); + }, + + isCompleted:function() { + return (this.state==800); + }, + + // GAME CYCLE + + getNextLevel:function() { + return this._nextlevel; + }, + + gotoLevel:function(level) { + this._nextlevel=level; + this.setState(400); + }, + + playerDied:function(data) { + this._loselife=data; + this.setState(500); + }, + + gameIsCompleted:function() { + this.setState(800); + }, + + // private methods + + /** + * Changes the current game state + * + * @param st state number + */ + setState:function(st) { + this.state=st; + this.stateFirstIteration=true; + }, + + /* + * Removes all objects in each group except the game + * cycle group. Used for garbage collection when resetting the game. + */ + _resetGroups:function() { + var g=gbox.getGroups(); + for (var i=0;iprio) break; else i=this.data[i].__next; + if (i==null) { // if last, chain in queue + obj.__next=null; + obj.__first=this.last; + this.data[this.last].__next=nid; + this.last=nid; + } else { // else reconnect objects + obj.__first=this.data[i].__first; + obj.__next=i; + this.data[i].__first=nid; + if (obj.__first!=null) this.data[obj.__first].__next=nid; else this.first=nid; + } + + } + obj.__prio=prio; + obj.__id=nid; + this.data[nid]=obj; + return nid; + }, + setPrio:function(obd,prio) { + if (this.data[obd].__prio==prio) return; + if (this.first!=this.last) + if (this.data[obd].__prio=prio) break; else i=this.data[i].__next; + if ((i==null)||(this.data[i].__first!=this.data[obd].__id)) { + // disconnect + this.disconnect(obd); + // Reconnect + if (i==null) { + this.data[this.last].__next=this.data[obd].__id; + this.data[obd].__first=this.last; + this.data[obd].__next=null; + this.last=this.data[obd].__id; + } else { + this.data[obd].__first=this.data[i].__first; + this.data[obd].__next=i; + this.data[i].__first=this.data[obd].__id; + if (this.data[obd].__first!=null) this.data[this.data[obd].__first].__next=this.data[obd].__id; else this.first=this.data[obd].__id; + } + } + } + } else { + if (this.data[obd].__id!=this.first) { + var i=this.data[obd].__first; + while (i!=null) + if (this.data[i].__prio<=prio) break; else i=this.data[i].__first; + if ((i==null)||(this.data[i].__next!=this.data[obd].__id)) { + // disconnect + this.disconnect(obd); + if (i==null) { + this.data[this.first].__first=this.data[obd].__id; + this.data[obd].__first=null; + this.data[obd].__next=this.first; + this.first=this.data[obd].__id; + } else { + this.data[obd].__first=i; + this.data[obd].__next=this.data[i].__next; + this.data[i].__next=this.data[obd].__id; + if (this.data[obd].__next!=null) this.data[this.data[obd].__next].__first=this.data[obd].__id; else this.last=this.data[obd].__id; + } + } + } + } + this.data[obd].__prio=prio; + }, + remove:function(obd) { + this.disconnect(obd); + this.gar.push(this.data[obd].__id); + delete this.data[this.data[obd].__id]; + } + } + } +} + +// A special circular queue with some features useful for the resource loader +var cyclelist={ + create:function(size) { + return { + _head:0, + _tail:0, + _data:[], + _size:(size?size:10), + _total:0, + _done:0, + _current:null, + getTotal:function(){return this._total}, // Number of elements to be "poped" + getDone:function(){return this._done}, // Number of popped elements since the last empty + getSize:function(){return this._size}, // The maximum number of elements in the queue + isProcessing:function(){return this._current!=null}, // The last pop was not a null (i.e. the queue returned a valid object) + isEnded:function(){return (this._head==this._tail)}, // There are other elements in the queue + isBusy:function(){return this.isProcessing()||!this.isEnded()}, // There are elements in the queue/the last one pop returned an object that is being processed + getCurrent:function(){return this._current}, // Return the last popped element + push:function(d) { + this._data[this._head]=d; + this._head=(this._head+1)%this._size; + this._total++; + }, + pop:function() { + if (this.isEnded()) { + this._total=0; + this._done=0; + this._current=null; + } else { + this._current=this._data[this._tail]; + this._tail=(this._tail+1)%this._size; + this._done++; + } + return this._current; + }, + dump:function() { + var r=""; + for (var i=0;iimg.width) { dw=(dw/sw)*(img.width-sx);sw=img.width-sx;} + if (sy+sh>img.height) { dh=(dh/sh)*(img.height-sy);sh=img.height-sy;} + try { if ((sh>0)&&(sw>0)&&(sxgbox._autoskip.hiidle)&&(gbox._frameskip>gbox._autoskip.min)) gbox.setFrameskip(gbox._frameskip-1); + if (gbox._statbar) gbox.debugGetstats(); + this._gametimer=setTimeout(gbox.go,(gbox._framestart<=0?1:gbox._framestart)); + }, + /** + * Apply FSEs to the screen. Is called each frame. + */ + _applyfse:function(){ + switch (gbox._flags.fse) { + case "scanlines": { + gbox.getBufferContext().drawImage(gbox.getCanvas("-gbox-fse"),0,0); + break; + } + case "lcd":{ + if (gbox._localflags.fselcdget&&gbox.getBuffer()) + gbox.getCanvasContext("-gbox-fse-new").drawImage(gbox.getBuffer(),0,0); + gbox.getBufferContext().save(); + gbox.getBufferContext().globalAlpha=0.5; + gbox.getBufferContext().drawImage(gbox.getCanvas("-gbox-fse-old"),0,0); + gbox.getBufferContext().restore(); + if (gbox._localflags.fselcdget) + gbox.swapCanvas("-gbox-fse-new","-gbox-fse-old"); + gbox._localflags.fselcdget=!gbox._localflags.fselcdget; + break; + } + } + }, + /** + * Register the code that have to be executed once the page is loaded. Usually contains game initialization, resources loading etc. + */ + onLoad:function(code) { + this.addEventListener(window,'load',code); + }, + /** + * This function is called once per frame. This is where the basic rendering and processing of groups occurs. + */ + go:function() { + if (gbox._loaderqueue.isBusy()) { + if (gbox._gamewaiting==1) { + gbox.blitFade(gbox._screen.getContext("2d"),{alpha:0.5}); + gbox.blitText(gbox._screen.getContext("2d"),{font:"_dbf",dx:2,dy:2,text:"LOADING..."}); + gbox._gamewaiting=true; + } + if (gbox._gamewaiting<=1) { + var bw=Math.floor(((gbox.getScreenW()-4)*gbox._loaderqueue.getDone())/gbox._loaderqueue.getSize()); + gbox._screen.getContext("2d").globalAlpha=1; + gbox._screen.getContext("2d").fillStyle = gbox._splash.gaugeLittleBackColor; + gbox._screen.getContext("2d").fillRect(0,4+gbox.getFont("_dbf").tileh,gbox.getScreenW(),1); + gbox._screen.getContext("2d").fillStyle = gbox._splash.gaugeLittleColor; + gbox._screen.getContext("2d").fillRect(0,4+gbox.getFont("_dbf").tileh,(bw>0?bw:0),1); + gbox._screen.getContext("2d").restore(); + gbox.setStatBar("Loading... ("+gbox._loaderqueue.getDone()+"/"+gbox._loaderqueue.getTotal()+")"); + } + if (gbox._gamewaiting) gbox._gamewaiting--; + setTimeout(gbox.go,1000); + } else { + gbox._gamewaiting=3; + gbox._framestart=new Date().getTime(); + var gr=""; + for (var g=0;g=gbox._frameskip) { + if (gbox._localflags.fse) gbox._applyfse(); + if (gbox._db) gbox.blitImageToScreen(gbox.getBuffer()); + gbox._fskid=0; + } else gbox._fskid++; + + gbox.purgeGarbage(); + + if (gbox._zindexch.length) { + + for (var i=0;i0?" ("+gbox._frameskip+"skip)":"")+" | "; + var cnt=0; + for (var g=0;g"; + id=gbox._zindex.data[id].__next; + } + */ + gbox.setStatBar(statline); + }, + + setZindex:function(th,z) { + if ((th.__zt==null)||(th.zindex!=z)) { + th.zindex=z; + this._zindexch.push({o:{g:th.group,o:th.id},z:z}); + } + }, + + /** + * Returns true if a given key in this._keymap is pressed. Only returns true on the transition from unpressed to pressed. + * @param {String} id A key in the keymap. By default, one of: "up" "down" "left" "right" "a" "b" "c" + * @returns {Boolean} True if the given key is transitioning from unpressed to pressed in this frame. + */ + keyIsHit:function(id) { return this._keyboard[this._keymap[id]]==1}, + + /** + * Returns true if a given key in this._keymap is being held down. Returns true as long as the key is held down. + * @param {String} id A key in the keymap. By default, one of: "up" "down" "left" "right" "a" "b" "c" + * @returns {Boolean} True if the given key is held down. + */ + keyIsPressed:function(id) { return this._keyboard[this._keymap[id]]>0}, + + /** + * Returns true if a given key in this._keymap has been held down for at least one frame. Will not return true if a key + * is quickly tapped, only once it has been held down for a frame. + * @param {String} id A key in the keymap. By default, one of: "up" "down" "left" "right" "a" "b" "c" + * @returns {Boolean} True if the given key has been held down for at least one frame. + */ + keyIsHold:function(id) { return this._keyboard[this._keymap[id]]>1}, + + /** + * Returns true if a given key in this._keymap is released. Only returns true on the transition from pressed to unpressed. + * @param {String} id A key in the keymap. By default, one of: "up" "down" "left" "right" "a" "b" "c" + * @returns {Boolean} True if the given key is transitioning from pressed to unpressed in this frame. + */ + keyIsReleased:function(id) { return this._keyboard[this._keymap[id]]==-1}, + + _savesettings:function() { + var saved=""; + for (var k in this._keymap) saved+="keymap-"+k+":"+this._keymap[k]+"~"; + for (var f in this._flags) { + switch (this._flagstype[f]) { + case "check": { saved+="flag-"+f+":"+(this._flags[f]?1:0)+"~"; break; } + case "list": { saved+="flag-"+f+":"+this._flags[f]+"~"; break; } + } + } + this.dataSave("sys",saved); + }, + _loadsettings:function() { + var cfg=this.dataLoad("sys"); + if (cfg!==null) { + cfg=cfg.split("~"); + var kv; + var mk; + for (var i=0;iviewdata.h) this._camera.y=viewdata.h-this._screenh; + if (this._camera.y<0) this._camera.y=0; + }, + + /** + * Sets the x value of the current camera object. + * @param {Integer} x The camera object's new x value. + * @param {Object} viewdata An object containing parameters h and w, which are a bounding box that the camera is + * not supposed to leave. For example, to use your map as a bounding area for the camera, pass along {w: map.w, h: map.h}. + */ + setCameraX:function(x,viewdata) { + this._camera.x=x; + if (this._camera.x+this._camera.w>viewdata.w) this._camera.x=viewdata.w-this._screenw; + if (this._camera.x<0) this._camera.x=0; + }, + + /** + * Centers the camera. + * @param {Object} data An object containing x and y parameters -- typically the object you wish to center the camera on. + * @param {Object} viewdata An object containing parameters h and w, which are a bounding box that the camera is + * not supposed to leave. For example, to use your map as a bounding area for the camera, pass along {w: map.w, h: map.h}. + * @example + * // Center the camera on the player object + * gbox.centerCamera(gbox.getObject('player', 'player_id'), {w: map.w, h: map.h}); + */ + centerCamera:function(data,viewdata) { + this.setCameraX(data.x-this._screenhw,viewdata); + this.setCameraY(data.y-this._screenhh,viewdata); + }, + + /** + * Get an array containing the names of each group in the game, in order of rendering. + * @returns {Array} An array of group names. + * @example + * grouplist = gbox.getGroups(); + * grouplist; // => ["background", "player", "enemy", "game"] + */ + getGroups:function() { return this._groups; }, + + /** + * Defines the names of each group in the game along with their rendering order. + * @param {Array} g An array of strings of group names, in the order in which the groups should be rendered. So + * g[0] will contain the first group to render, g[1] the second group to render, etc. + */ + setGroups:function(g){ + this._groups=g; + this._groupplay[gbox.ZINDEX_LAYER]=true; + for (var i=0;iNOTE: this does not return a copy of the object you've requested! Any modifications you make + * to the object returned are directly modifying the object you requested. + * @param {String} group The id of the group that contains the object. + * @param {String} id The id of the instance of the object. + * @returns {Object} The object requested. + * @example + * // Find the player and reduce health by half. + * playertemp = gbox.getObject('player','player_id'); + * player.health = player.health/2; + */ + getObject:function(group,id) {return this._objects[group][id]}, + + /** + * Creates a font. + * @param {Object} data An object containing:
    • id: the id of the font
    • + *
    • image: reference to the font image loaded (must contain font character tiles in ASCII order)
    • + *
    • firstletter: the ASCII character that the font image's first character corresponds to
    • + *
    • tileh: height in pixels of the character tiles
    • + *
    • tilew: width in pixels of the character tiles
    • + *
    • tilerow: width in pixels of each row in the font image
    • + *
    • gapx: x-coord gap between tile columns, in pixels
    • + *
    • gapy: y-coord gap between tile rows, in pixels
    + * @example + * gbox.addImage('font', 'font.png'); + * gbox.addFont({ id: 'small', image: 'font', firstletter: ' ', tileh: 8, tilew: 8, tilerow: 255, gapx: 0, gapy: 0 }); + */ + addFont:function(data) { + data.tilehh=Math.floor(data.tileh/2); + data.tilehw=Math.floor(data.tilew/2); + this._fonts[data.id]=data; + this._fonts[data.id].firstascii=data.firstletter.charCodeAt(0); + }, + + /** + * Returns a font object containing data about the font. + * @param {String} id The id of the font, as set in gbox.addFont. + */ + getFont:function(id) { + return this._fonts[id]; + }, + + /** + * Deletes an object, keeping a record of its group and id in gbox._garbage. + * @param {Object} obj The object you wish to delete. + */ + trashObject:function(obj) { + if (!this._garbage[obj.group]) this._garbage[obj.group]={}; + this._garbage[obj.group][obj.id]=1; + obj.__trashing=true; + }, + + /** + * Clears the record held in gbox._garbage of what has been deleted. The "onpurge" method is called on the object before being deleted (for canvas deallocation etc.) + */ + purgeGarbage:function() { + for (var group in this._garbage) + for (var id in this._garbage[group]) { + if (this._objects[group][id]["onpurge"]) this._objects[group][id].onpurge(); + if (this._objects[group][id].__zt!=null) + this._zindex.remove(this._objects[group][id].__zt) + delete this._objects[group][id]; + } + gbox._garbage={}; + }, + + /** + * Deletes every object in a given group. + * @param {String} group The group id. + */ + trashGroup:function(group) { + if (!this._garbage[group]) this._garbage[group]={}; + for (var obj in this._objects[group]) + this._garbage[group][obj]=1; + }, + + /** + * Returns whether an object is due to be trashed. Useful in cases you want to check if + * an object is marked as trash before it is actually deleted. + * @param {Object} o The object you're checking. + * @returns {Boolean} True if the object is marked as trash. + */ + objectIsTrash:function(o) { return o.__trashing }, + + /** + * Creates a new game object. Generally speaking you pass a fully-defined object as the parameter (including a group, id, tileset, and so on). + * A group must be specified, or the program will crash. If no id is specified, then it will automatically provide + * an id of 'obj-XXXX' where 'XXXX' is an automatically incrementing integer. This is where the initialize, first, and blit + * functions are defined, as well. + * @param {Object} data The object you wish to create. + * @returns {Object} The object you created. + * @example + * data = { + * group: 'player', + * id: 'player_id', + * tileset: 'player_tiles', + * x: 0, + * y: 0, + * initialize: function() { + this.x = 10; + this.y = 10; + }, + * }; + * gbox.addObject(data); + */ + addObject:function(data) { + // Extras + if (!data.id) { + data.id="obj-"+this._autoid; + this._autoid=(this._autoid+1)%1000; + } + if (data.tileset) { + if (data.h==null) data.h=this._tiles[data.tileset].tileh; + if (data.w==null) data.w=this._tiles[data.tileset].tilew; + if (data.hw==null) data.hw=this._tiles[data.tileset].tilehw; + if (data.hh==null) data.hh=this._tiles[data.tileset].tilehh; + } + this._objects[data.group][data.id]=data; + if (data.zindex!=null) + this.setZindex(this._objects[data.group][data.id],data.zindex); + return this._objects[data.group][data.id]; + }, + + /** + * Returns whether a given group contains no objets. + * @param {String} gid The group you're checking. + * @returns {Boolean} True if the group contains no objects. + */ + groupIsEmpty:function(gid) { for (var i in this._objects[gid]) return false; return true; }, + + /** + * Creates a new canvas. By default, the width and height is the current gbox._screenw and gbox._screenh, + * but it can also be set by passing in a data object with the appropriate parameters. + * @param {String} id The id of the new canvas. + * @param {Object} data (Optional) The height and width of the new canvas, contained in data.h and data.w parameters. + * @example + * gbox.createCanvas('newCanvas', {w: 640, h: 480}); + */ + createCanvas:function(id,data) { + this.deleteCanvas(id); + var w=(data&&data.w?data.w:this._screenw); + var h=(data&&data.h?data.h:this._screenh); + this._canvas[id]=document.createElement("canvas"); + this._canvas[id].setAttribute('height',h); + this._canvas[id].setAttribute('width',w); + this._canvas[id].getContext("2d").save(); + this._canvas[id].getContext("2d").globalAlpha=0; + this._canvas[id].getContext("2d").fillStyle = gbox.COLOR_BLACK; + this._canvas[id].getContext("2d").fillRect(0,0,w,h); + this._canvas[id].getContext("2d").restore(); + }, + /** + * Swap two canvas using their ID. + * @param {String} id The id of the first canvas. + * @param {String} id The id of the second canvas. + * @example + * gbox.swapCanvas('canvas1','canvas2'); + */ + swapCanvas:function(a,b) { + var swp=this._canvas[a]; + this._canvas[a]=this._canvas[b]; + this._canvas[b]=swp; + }, + /** + * Deletes a given canvas. + * @param {String} id The id of the canvas to be deleted. + */ + deleteCanvas:function(id) { + if (this._canvas[id]) delete this._canvas[id]; + }, + + /** + * Checks to see if an image was successfully loaded. + * @param {String} id The id of the image. + * @returns {Boolean} True if the image has been loaded. + */ + imageIsLoaded:function(id){ return this._images[id]&&(this._images[id].getAttribute("wasloaded"))&&this._images[id].width }, + + /** + * Gets information about a loaded image. + * @param {String} id The id of the image. + * @returns {Object} A DOM Image element, including the URL and last modified date of the image, its ID, and whether it was loaded successfully. + * @example + * image = gbox.getImage('logo'); + * image; // => ? + */ + getImage:function(id){return this._images[id]}, + + /** + * Gets the buffer canvas (automatically created by gbox.initScreen). + * @returns {Object} A DOM Canvas element, including the width and height of the canvas. + */ + getBuffer:function(){return (gbox._fskid>=gbox._frameskip?(this._db?this.getCanvas("_buffer"):this._screen):null)}, + + /** + * Gets the buffer canvas context. + * @returns {Object} A DOM Canvas context object. + */ + getBufferContext:function(){ return (gbox._fskid>=gbox._frameskip?(this._db?this.getCanvasContext("_buffer"):this._screen.getContext("2d")):null) }, + + /** + * Gets a given canvas. + * @param {Object} id The identifier of the canvas. + * @returns {Object} A DOM Canvas element, including the width and height of the canvas. + */ + getCanvas:function(id){return this._canvas[id]}, + + /** + * Gets the two-dimensional canvas context of a given canvas. The object it returns contains all the drawing functions for the canvas. + * See W3C and + * Mozilla Developer Center for details. + * @param {Object} id The identifier of the canvas. + * @returns {Object} A DOM Canvas context object. + */ + getCanvasContext:function(id){return this.getCanvas(id).getContext("2d");}, + + /** + * Adds an image file to the loader, assigning it to an ID. If adding an image to an existing ID, it checks to see if the file you're + * adding is different than the one currently assigned to the ID. If it's different, it overwrites the old image. If it's the same, then + * no action is taken. + * @param {String} id The identifier of the image. + * @param {String} filename The file name of the image. + */ + addImage:function(id,filename) { + if (this._images[id]) + if (this._images[id].getAttribute("src_org")==filename) + return; + else + delete this._images[id]; + this._addtoloader({type:"image",id:id,filename:filename}); + }, + + /** + * Deletes an image currently in use. Does not delete the image file, but removes it from Akihabara's image list. + * @param {String} id The identifier of the image. + */ + deleteImage:function(id) { + delete this._images[id]; + }, + + /** + * Creates a new Akihabara tileset, adding it to the engine. + * @param {Object} t An object containing:
    • id {String}: the new id of the tileset
    • + *
    • image {String}: reference to the tileset image loaded
    • + *
    • tileh {Integer}: height in pixels of the tiles
    • + *
    • tilew {Integer}: width in pixels of the tiles
    • + *
    • tilerow {Integer}: width in pixels of each row in the font image
    • + *
    • gapx {Integer}: x-coord gap between tile columns, in pixels
    • + *
    • gapy {Integer}: y-coord gap between tile rows, in pixels
    + */ + addTiles:function(t) { + t.tilehh=Math.floor(t.tileh/2); + t.tilehw=Math.floor(t.tilew/2); + this._tiles[t.id]=t; + }, + + /** + * Gets an Akihabara tileset, adding it to the engine. + * @param {String} t The ID of a tileset. + * @returns An object containing:
    • id {String}: the new id of the tileset
    • + *
    • image {String}: reference to the tileset image loaded
    • + *
    • tileh {Integer}: height in pixels of the tiles
    • + *
    • tilew {Integer}: width in pixels of the tiles
    • + *
    • tilerow {Integer}: width in pixels of each row in the font image
    • + *
    • gapx {Integer}: x-coord gap between tile columns, in pixels
    • + *
    • gapy {Integer}: y-coord gap between tile rows, in pixels
    + */ + getTiles:function(t) { return this._tiles[t] }, + + /** + * Loads the initial splash screen and debugging font, then calls gbox._waitforloaded which adds to the game all the previously + * defined resources. Once gbox._waitforloaded is done, it calls the callback function cb. + * @params {String} cb The name of the function to be called when all assets are done loading. + */ + loadAll:function(cb) { + // Setup logger + if (this._canlog) this.log=console.log; + // Set the callback function, which is called after the resources are loaded. + if (!this._cb) this._cb = cb; + // Default stuff + this.addImage("_dbf","akihabara/debugfont.png"); + if (this._splash.background) this.addImage("_splash",this._splash.background); + gbox.addFont({id:"_dbf",image:"_dbf",firstletter:" ",tileh:5,tilew:4,tilerow:16,gapx:0,gapy:0}); + if (!gbox._splash.minimalTime) + gbox._minimalexpired=2; + this._waitforloaded(); + }, + + _implicitsargs:function(data) { + if (data.camera) { + data.dx-=this._camera.x; + data.dy-=this._camera.y; + } + if (data.sourcecamera) { + data.x=this._camera.x*(data.parallaxx?data.parallaxx:1); + data.y=this._camera.y*(data.parallaxy?data.parallaxy:1); + } + }, + + /** + * Draws a tile to a canvas context + * @param {Object} tox The canvas context to be drawn on. + * @param {Object} data An object containing data about the tile to be drawn, including: + *
    • tileset {String}: the id of the tileset
    • + *
    • tile {Integer}: the index of the tile within the tileset to be drawn
    • + *
    • dx {Integer}: x coordinate to draw the tile at
    • + *
    • dy {Integer}: y coordinate to draw the tile at
    • + *
    • fliph {Integer}: horizontal flip, either 1 or -1
    • + *
    • flipv {Integer}: vertical flip, either 1 or -1
    • + *
    • alpha {Float}: alpha value (0 is transparent, 1 is opaque)
    + * @example + * // from capman, draws an current object's tile, called from inside its blit function + * gbox.blitTile(gbox.getBufferContext(),{tileset:this.tileset,tile:this.frame,dx:this.x,dy:this.y,fliph:this.fliph,flipv:this.flipv,camera:this.camera,alpha:1}); + */ + blitTile:function(tox,data) { + if (tox==null) return; + var ts=this._tiles[data.tileset]; + var img=this.getImage(ts.image); + this._implicitsargs(data); + tox.save(); + tox.globalAlpha=(data.alpha?data.alpha:1); + tox.translate((data.fliph?ts.tilew:0), (data.flipv?ts.tileh:0)); tox.scale((data.fliph?-1:1), (data.flipv?-1:1)); + this._safedrawimage(tox,img, ts.gapx+(ts.tilew*(data.tile%ts.tilerow)),ts.gapy+(ts.tileh*Math.floor(data.tile/ts.tilerow)),(data.w==null?ts.tilew:data.w),(data.h==null?ts.tileh:data.h),data.dx*(data.fliph?-1:1),data.dy*(data.flipv?-1:1),(data.w?data.w:ts.tilew),(data.h?data.h:ts.tileh)); + tox.restore(); + }, + + /** + * Draws an image to a canvas context + * @param {Object} tox The canvas context to be drawn on. + * @param {Object} image The image to draw. Must be a DOM Image element, typicallly accessed via gbox.getImage + * @param {Object} data An object containing data about the tile to be drawn, including: + *
    • dx {Integer}: (required) x coordinate to draw the image at
    • + *
    • dy {Integer}: (required) y coordinate to draw the image at
    • + *
    • fliph {Integer}: horizontal flip, either 1 or -1
    • + *
    • flipv {Integer}: vertical flip, either 1 or -1
    • + *
    • alpha {Float}: alpha value (0 is transparent, 1 is opaque)
    + * @example + * // draw an image at (100,100) + * gbox.blitAll(gbox.getBufferContext(),gbox.getImage("image_id"),{dx:100,dy:100}); + */ + blitAll:function(tox,image,data) { + if (tox==null) return; + this._implicitsargs(data); + tox.save(); + tox.globalAlpha=(data.alpha?data.alpha:1); + tox.translate((data.fliph?image.width:0), (data.flipv?image.height:0)); tox.scale((data.fliph?-1:1), (data.flipv?-1:1)); + this._safedrawimage(tox,image, 0,0, image.width,image.height,data.dx*(data.fliph?-1:1),data.dy*(data.flipv?-1:1),image.width,image.height); + tox.restore(); + }, + + blit:function(tox,image,data) { + if (tox==null) return; + this._implicitsargs(data); + tox.save(); + tox.globalAlpha=(data.alpha?data.alpha:1); + tox.translate((data.fliph?data.dw:0), (data.flipv?data.dh:0)); tox.scale((data.fliph?-1:1), (data.flipv?-1:1)); + this._safedrawimage(tox,image,(data.x?data.x:0), (data.y?data.y:0),(data.w?data.w:data.dw),(data.h?data.h:data.dh),data.dx*(data.fliph?-1:1),data.dy*(data.flipv?-1:1),data.dw,data.dh); + tox.restore(); + }, + + + /** + * Draws a tilemap to a canvas context + * @param {Object} tox The canvas context to be drawn on. + * @param {Object} data An object containing a set of tilemap data, including: + *
    • tileset {String}: (required) the id of the tileset the tilemap is based on
    • + *
    • map {Array}: an array whose x and y coord represent the tilemap coordinates, containing integers that correspond to the index of a given tile (or null for no tile)
    + */ + blitTilemap:function(tox,data) { + if (tox==null) return; + var ts=this._tiles[data.tileset]; + for (var y=0;y
  • font {String}: (required) the id of font to draw the text with
  • + *
  • text {String}: (required) the text to display
  • + *
  • dx {Integer}: (required) the x coordinate to draw the text at
  • + *
  • dy {Integer}: (required) the y coordinate to draw the text at
  • + *
  • dw {Integer}: the width of the text area -- required if you define data.halign
  • + *
  • dh {Integer}: the height of the text area -- required if you define data.valign
  • + *
  • valign {Integer}: either gbox.ALIGN_BOTTOM (aligns from the bottom of the text area) or gbox.ALIGN_MIDDLE (vertically centers text in text area)
  • + *
  • halign {Integer}: either gbox.ALIGN_RIGHT (aligns to the right hand side of text area) or gbox.ALIGN_CENTER (horizontallly centers text in text area)
  • + *
  • alpha {Float}: alpha value (0 is transparent, 1 is opaque)
  • + */ + blitText:function(tox,data) { + if (tox==null) return; + data.text+=""; // Convert to string. + var fn=this._fonts[data.font]; + var tile=0; + this._implicitsargs(data); + var dx=data.dx; + var dy=data.dy; + if (data.valign==gbox.ALIGN_BOTTOM) dy = dy+data.dh-fn.tileh; + else if (data.valign==gbox.ALIGN_MIDDLE) dy = dy+Math.floor(data.dh/2)-fn.tileh; + if (data.halign==gbox.ALIGN_RIGHT) dx = dx+data.dw-(data.text.length*fn.tilew); + else if (data.halign==gbox.ALIGN_CENTER) dx = dx+Math.floor((data.dw-(data.text.length*fn.tilew))/2); + tox.save(); + tox.globalAlpha=(data.alpha?data.alpha:1); + for (var y=0;y=0) { + if (data.clear) tox.clearRect(dx+(y*fn.tilew),dy,(data.w?data.w:fn.tilew),(data.h?data.h:fn.tileh)); + this._safedrawimage(tox,this.getImage(fn.image), fn.gapx+(fn.tilew*(tile%fn.tilerow)), + fn.gapy+(fn.tileh*Math.floor(tile/fn.tilerow)),fn.tilew,fn.tileh,dx+(y*fn.tilew),dy,(data.w?data.w:fn.tilew),(data.h?data.h:fn.tileh)); + } + } + tox.restore(); + }, + + /** + * Clears a rectangular area of a canvas context. + * @param {Object} image The canvas context to be drawn on. + * @param {Object} data An object containing a set of data, including: + *
    • x {Integer}: (required) the x coordinate of the top-left corner of the rectangle
    • + *
    • y {Integer}: (required) the y coordinate of the top-left corner of the rectangle
    • + *
    • w {Integer}: the width of the box; defaults to canvas width
    • + *
    • h {Integer}: the height the box; defaults to canvas height
    + */ + blitClear:function(image,data) { + if (image==null) return; + if (data==null) data={x:0,y:0}; + this._implicitsargs(data); + image.clearRect(data.x,data.y,(data.w==null?image.canvas.width:data.w),(data.h==null?image.canvas.height:data.h)); + }, + + /** + * Draws an image directly to the screen's current canvas context. Used internally in gbox.go(). Probably shouldn't be used otherwise. + */ + blitImageToScreen:function(image) { + this._screen.getContext("2d").drawImage(image,0,0); + }, + + /** + * Draws a filled rectangle over an entire canvas context. + * @param {Object} tox The canvas context to be filled. + * @param {Object} data An object containing a set of data, including: + *
    • alpha {Float}: the alpha value of the rectangle; defaults to 1
    • + *
    • color {Object}: the color of the box, formatted rgb(rValue, gValue, bValue); default black
    + */ + blitFade:function(tox,data) { + if (tox) this.blitRect(tox,{x:0,y:0,w:tox.canvas.width,h:tox.canvas.height,alpha:data.alpha,color:data.color}); + }, + + /** + * Draws a filled rectangle to a canvas context. + * @param {Object} tox The canvas context to be drawn on. + * @param {Object} data An object containing a set of data, including: + *
    • x {Integer}: (required) the x coordinate of the top-left corner of the rectangle
    • + *
    • y {Integer}: (required) the y coordinate of the top-left corner of the rectangle
    • + *
    • w {Integer}: (required) the width of the box
    • + *
    • h {Integer}: (required) the height the box
    • + *
    • alpha {Float}: the alpha value of the rectangle; defaults to 1
    • + *
    • color {Object}: the color of the box, formatted rgb(rValue, gValue, bValue); default black
    + */ + blitRect:function(tox,data) { + if (tox==null) return; + tox.save(); + tox.globalAlpha=(data.alpha?data.alpha:1); + tox.fillStyle = (data.color?data.color:gbox.COLOR_BLACK); + tox.fillRect(data.x,data.y,data.w,data.h); + tox.restore(); + }, + + /** + * Calculates a box collision between two collision boxes within a given tolerance. A higher tolerance means less precise collision. + * @param {Object} o1 A collision box you're testing for collision. Must contain: + *
    • x {Integer}: (required) the x coordinate of the object's origin; assumes the Akihabara default of top-left being the origin
    • + *
    • y {Integer}: (required) the y coordinate of the object's origin; assumes the Akihabara default of top-left being the origin
    • + *
    • w {Integer}: (required) the width of the box
    • + *
    • h {Integer}: (required) the height the box
    + * @param {Object} o2 A collision box you're testing for collision. Must contain: + *
    • x {Integer}: (required) the x coordinate of the object's origin; assumes the Akihabara default of top-left being the origin
    • + *
    • y {Integer}: (required) the y coordinate of the object's origin; assumes the Akihabara default of top-left being the origin
    • + *
    • w {Integer}: (required) the width of the box
    • + *
    • h {Integer}: (required) the height the box
    + * @param {Integer} t The tolerance for the collision, in pixels. A value of 0 means pixel-perfect box collision. A value of 2 would mean that the + * boxes could overlap by up to 2 pixels without being considered a collision. + * @returns True if the two collision boxes are colliding within the given tolerance. + */ + collides:function(o1,o2,t) { + if (!t) t=0; + return !((o1.y+o1.h-1-t o2.y+o2.h-1-t) || (o1.x+o1.w-1-to2.x+o2.w-1-t)); + }, + + /** + * Calculates a point-box collision between a point and a collision box within a given tolerance. A higher tolerance means less precise collision. + * @param {Object} o1 A point you're testing for collision. Must contain: + *
    • x {Integer}: (required) the x coordinate of the point
    • + *
    • y {Integer}: (required) the y coordinate of the point
    + * @param {Object} o2 A collision box you're testing for collision. Must contain: + *
    • x {Integer}: (required) the x coordinate of the object's origin; assumes the Akihabara default of top-left being the origin
    • + *
    • y {Integer}: (required) the y coordinate of the object's origin; assumes the Akihabara default of top-left being the origin
    • + *
    • w {Integer}: (required) the width of the box
    • + *
    • h {Integer}: (required) the height the box
    + * @param {Integer} t The tolerance for the collision, in pixels. A value of 0 means pixel-perfect collision. A value of 2 would mean that the + * point could exist within the outermost 2 pixels of the box without being considered a collision. + * @returns True if the point is colliding with the box within the given tolerance. + */ + pixelcollides:function(o1,o2,t) { + if (!t) t=0; + return !((o1.y o2.y+o2.h-1-t) || (o1.xo2.x+o2.w-1-t)); + }, + + /** + * Determines whether an object is visible by seeing if it collides with the camera's viewport. + * @param {Object} obj The object you're testing to see if it's visible. Must contain: + *
    • x {Integer}: (required) the x coordinate of the object's origin; assumes the Akihabara default of top-left being the origin
    • + *
    • y {Integer}: (required) the y coordinate of the object's origin; assumes the Akihabara default of top-left being the origin
    • + *
    • w {Integer}: (required) the width of the object's collision box
    • + *
    • h {Integer}: (required) the height the object's box
    + * @returns True if the object's collision box is within the camera's viewport. + */ + objectIsVisible:function(obj) { return this.collides(obj,this._camera,0); }, + + // --- + // --- + // --- AUDIO ENGINE + // --- + // --- + + _audiochannels:{}, + _audiomastervolume:1.0, + _canaudio:false, + _audiodequeuetime:0, + _audioprefetch:0.5, + _audiocompatmode:0, // 0: pause/play, 1: google chrome compatibility, 2: ipad compatibility (single channel) + _createmode:0, // 0: clone, 1: rehinstance + _fakecheckprogressspeed:100, // Frequency of fake audio monitoring + _fakestoptime:1, // Fake audio stop for compatibility mode + _audioteam:2, + _loweraudioteam:1, + _audio:{lding:null,qtimer:false,aud:{},ast:{}}, + _audioactions:[], + _showplayers:false, + _singlechannelname:"bgmusic", + _positiondelay:0, + _playerforcer:0, + _forcedmimeaudio:null, + _singlechannelaudio:false, + _audiomutevolume:0.0001, // Zero is still not accepted by everyone :( + _rawstopaudio:function(su) { + if (gbox._audiocompatmode==1) { + if (su.duration-su.currentTime>gbox._fakestoptime) + su.currentTime=su.duration-gbox._fakestoptime; + su.muted=true; + } else + su.pause(); + + }, + _rawplayaudio:function(su) { + if (gbox._audiocompatmode==1) { + try { su.currentTime=0; } catch (e) {} + su.muted=false; + su.play(); + } else if (gbox._audiocompatmode==2) { + su.load(); + gbox._playerforcer=setInterval(function(e){try{su.play();clearInterval(gbox._playerforcer)}catch(e){}},1000); + } else { + try { su.currentTime=0; } catch (e) {} + su.play(); + } + }, + _finalizeaudio:function(ob,who,donext){ + + var cur=(who?who:this); + gbox.removeEventListener(cur,'ended', gbox._finalizeaudio); + gbox.removeEventListener(cur,'timeupdate', gbox._checkprogress); + + gbox.addEventListener(cur,'ended', gbox._playbackended); + if (donext) gbox._loaderloaded(); + }, + _audiodoload:function() { + if (gbox._audiocompatmode==1) gbox._audio.lding.muted=true; + else if (gbox._audiocompatmode==2) + gbox._finalizeaudio(null,gbox._audio.lding,true); + else { + gbox._audio.lding.load(); + gbox._audio.lding.play(); + } + }, + _timedfinalize:function() { + gbox._rawstopaudio(gbox._audio.lding); + gbox._finalizeaudio(null,gbox._audio.lding,true); + }, + _checkprogress:function() { + if (gbox._audio.lding.currentTime>gbox._audioprefetch) gbox._timedfinalize(); + }, + _fakecheckprogress:function() { + if (gbox._audio.lding.currentTime>gbox._audioprefetch) gbox._timedfinalize(); else setTimeout(gbox._fakecheckprogress,gbox._fakecheckprogressspeed); + }, + _audiofiletomime:function(f) { + var fsp=f.split("."); + switch (fsp.pop().toLowerCase()) { + case "ogg": { return "audio/ogg"; break } + case "mp3": { return "audio/mpeg"; break } + default: { + return "audio/mpeg"; + } + } + }, + _pushaudio:function(){try {this.currentTime=1.0} catch(e){} }, + _createnextaudio:function(cau) { + if (cau.def) { + gbox.deleteAudio(cau.id); + this._audio.aud[cau.id]=[]; + this._audio.ast[cau.id]={cy:-1,volume:1,channel:null,play:false,mute:false,filename:cau.filename[0]}; + if (cau.def) for (var a in cau.def) this._audio.ast[cau.id][a]=cau.def[a]; + } + if ((gbox._createmode==0)&&(cau.team>0)) { + var ael =this._audio.aud[cau.id][0].cloneNode(true); + gbox._finalizeaudio(null,ael,false); + } else { + var ael=document.createElement('audio'); + ael.volume=gbox._audiomutevolume; + } + if (!gbox._showplayers) { + ael.style.display="none"; + ael.style.visibility="hidden"; + ael.style.width="1px"; + ael.style.height="1px"; + ael.style.position="absolute"; + ael.style.left="0px"; + ael.style.top="-1000px"; + } + ael.setAttribute('controls',gbox._showplayers); + ael.setAttribute('aki_id',cau.id); + ael.setAttribute('aki_cnt',cau.team); + gbox.addEventListener(ael,'loadedmetadata', gbox._pushaudio); // Push locked audio in safari + if (((gbox._createmode==0)&&(cau.team==0))||(gbox._createmode==1)) { + if (gbox._forcedmimeaudio) { + for (var i=0;i0) + this._addqueue({t:1,a:ael}); + } + } + }, + setSplashSettings:function(a) { for (var n in a) this._splash[n]=a[n]; }, + resetChannel:function(ch) { + if (this._canaudio&&this._audiochannels[ch]) + if (ch=="master") + for (var ch in this._audiochannels) + this.setChannelVolume(ch,this._audiochannels[ch]._def.volume); + else if (this._audiochannels[ch]) + this.setChannelVolume(ch,this._audiochannels[ch]._def.volume); + }, + getChannelDefaultVolume:function(ch) { + if (this._canaudio&&this._audiochannels[ch]) return this._audiochannels[ch]._def.volume; else return null; + }, + setChannelVolume:function(ch,a) { + if (this._canaudio&&this._audiochannels[ch]) { + if (ch=="master") this._audiomastervolume=a; else this._audiochannels[ch].volume=a + for (var j in gbox._audio.aud) + if (this._audio.ast[j].cy>-1) this._updateaudio(j); + } + }, + getChannelVolume:function(ch) { if (ch=="master") return this._audiomastervolume; else if (this._audiochannels[ch]) return this._audiochannels[ch].volume; else return 0 }, + changeChannelVolume:function(ch,a) { + if (this._canaudio&&this._audiochannels[ch]) { + var vol=this.getChannelVolume(ch)+a; + if (vol>1) vol=1; else if (vol<0) vol=0; + this.setChannelVolume(ch,vol); + } + }, + stopChannel:function(ch) { + if (this._canaudio) + for (var j in gbox._audio.aud) + if (this._audio.ast[j].cy>-1&&gbox._audio.ast[j].play&&((ch=="master")||(this._audio.ast[j].channel==ch))) + this.stopAudio(j); + }, + + setAudioUnmute:function(a) { if (this._canaudio&&this._audio.ast[a]) { this._audio.ast[a].mute=false; this._updateaudio(a); } }, + setAudioMute:function(a) { if (this._canaudio&&this._audio.ast[a]) { this._audio.ast[a].mute=true; this._updateaudio(a); } }, + getAudioMute:function(a) { if (this._canaudio&&this._audio.ast[a]) return this._audio.ast[a].mute; else return null}, + + setAudioVolume:function(a,vol) { if (this._canaudio&&this._audio.ast[a]) { this._audio.ast[a].volume=vol; this._updateaudio(a); } }, + getAudioVolume:function(a,vol) { if (this._canaudio&&this._audio.ast[a]) return this._audio.ast[a].volume; else return null}, + + setAudioPosition:function(a,p) { if (this._canaudio&&this._audio.ast[a]&&this._audio.aud[a][this._audio.ast[a].cy]) this._audio.aud[a][this._audio.ast[a].cy].currentTime=p;}, + getAudioPosition:function(a) {if (this._canaudio&&this._audio.ast[a]&&this._audio.aud[a][this._audio.ast[a].cy]) if (this._audio.aud[a][this._audio.ast[a].cy].currentTime>this._positiondelay) return this._audio.aud[a][this._audio.ast[a].cy].currentTime-this._positiondelay; else return 0; else return 0}, + + getAudioDuration:function(a) {if (this._canaudio&&this._audio.ast[a]&&this._audio.aud[a][this._audio.ast[a].cy]) return this._audio.aud[a][this._audio.ast[a].cy].duration; else return 0}, + + changeAudioVolume:function(a,vol) { if (this._canaudio&&this._audio.ast[a]) { if (this._audio.ast[a].volume+vol>1) this._audio.ast[a].volume=1; else if (this._audio.ast[a].volume+vol<0) this._audio.ast[a].volume=0; else this._audio.ast[a].volume+=vol; this._updateaudio(a); } }, + setCanAudio:function(a) { this._canaudio=!this._flags.noaudio&&a;}, + setForcedMimeAudio:function(a){ this._forcedmimeaudio=a;}, + setAudioChannels:function(a){ + this._audiochannels=a; + for (var ch in a) { + this._audiochannels[ch]._def={}; + for (var attr in this._audiochannels[ch]) + if (attr!="_def") this._audiochannels[ch]._def[attr]=this._audiochannels[ch][attr]; + } + }, + setAudioTeam:function(a){ this._audioteam=a; }, + setLowerAudioTeam:function(a){ this._loweraudioteam=a; }, + + // --- + // --- + // --- DYNAMIC SCRIPT INCLUSION + // --- + // --- + + addScript:function(call) { + gbox._addtoloader({type:"script",call:call}); + }, + + // --- + // --- + // --- BUNDLES + // --- + // --- + + addBundle:function(call){ + gbox._addtoloader({type:"bundle",call:call}); + }, + + readBundleData:function(pack,call) { + // Local resources first + if (pack.setObject) for (var i=0;igbox.getScreenH()) l=gbox.getScreenH()-p; + tox.fillStyle = gbox.PALETTES.c64.colors[gbox.PALETTES.c64.order[Math.floor(Math.random()*gbox.PALETTES.c64.order.length)]]; + tox.fillRect(0,p,gbox.getScreenW(),l); + p+=l; + } + tox.fillStyle = gbox.PALETTES.c64.colors.lightblue; + tox.fillRect(Math.floor(gbox.getScreenW()/10),Math.floor(gbox.getScreenH()/10),gbox.getScreenW()-Math.floor(gbox.getScreenW()/5),gbox.getScreenH()-Math.floor(gbox.getScreenH()/5)); + if (gbox._splash.minilogo&&gbox.imageIsLoaded("logo")) { + var dw=gbox.getScreenW()/4; + var dh=(gbox.getImage("logo").height*dw)/gbox.getImage("logo").width; + gbox.blit(tox,gbox.getImage(gbox._splash.minilogo),{w:gbox.getImage("logo").width,h:gbox.getImage("logo").height,dx:(gbox.getScreenW()-dw)/2,dy:(gbox.getScreenH()-dh)/2,dw:dw,dh:dh}); + } + break; + } + default:{ + if (gbox._splash.background&&gbox.imageIsLoaded("_splash")) + gbox.blit(tox,gbox.getImage("_splash"),{w:gbox.getImage("_splash").width,h:gbox.getImage("_splash").height,dx:0,dy:0,dw:gbox.getScreenW(),dh:gbox.getScreenH()}); + if (gbox._splash.minilogo&&gbox.imageIsLoaded("logo")) { + var dw=gbox.getScreenW()/4; + var dh=(gbox.getImage("logo").height*dw)/gbox.getImage("logo").width; + gbox.blit(tox,gbox.getImage(gbox._splash.minilogo),{w:gbox.getImage("logo").width,h:gbox.getImage("logo").height,dx:gbox.getScreenW()-dw-5,dy:gbox.getScreenH()-dh-5,dw:dw,dh:dh}); + } + if (gbox._splash.footnotes&&gbox.imageIsLoaded("_dbf")) { + if (!gbox.getCanvas("_footnotes")) { + var fd=gbox.getFont("_dbf"); + gbox.createCanvas("_footnotes",{w:gbox.getScreenW()-5,h:(gbox._splash.footnotes.length)*(fd.tileh+gbox._splash.footnotesSpacing)}); + for (var i=0;i0?bw:0),gbox._splash.gaugeHeight-2); + } + } + } + tox.restore(); + gbox.setStatBar("Loading... ("+gbox._loaderqueue.getDone()+"/"+gbox._loaderqueue.getTotal()+")"); + setTimeout(gbox._waitforloaded,50); + } else { + gbox.deleteImage("_splash"); + gbox.setStatBar(); + gbox._cb(); + } + }, + clearCache:function() { this._loadercache.clear(); }, + + // --- + // --- + // --- BROWSER QUIRKS + // --- + // --- + + checkCanvasSupport:function() { + return !!document.createElement('canvas').getContext; + }, + addEventListener:function(to,event,code) { + if (to.addEventListener) to.addEventListener(event,code,false); + else to.attachEvent('on'+event,code); + }, + removeEventListener:function(to,event,code) { + if (to.removeEventListener) to.removeEventListener(event,code,false); + else to.detachEvent('on'+event,code); + }, + XMLHttpFactories:[ + function () {return new XMLHttpRequest()}, + function () {return new ActiveXObject("Msxml2.XMLHTTP")}, + function () {return new ActiveXObject("Msxml3.XMLHTTP")}, + function () {return new ActiveXObject("Microsoft.XMLHTTP")} + ], + createXmlHttpRequest:function() { + var xmlhttp=false; + /* running locally on IE5.5, IE6, IE7 */ ; /*@cc_on + if(location.protocol=="file:"){ + if(!xmlhttp)try{ xmlhttp=new ActiveXObject("MSXML2.XMLHTTP"); }catch(e){xmlhttp=false;} + if(!xmlhttp)try{ xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); }catch(e){xmlhttp=false;} + } ; @cc_off @*/ + /* IE7, Firefox, Safari, Opera... */ + if(!xmlhttp)try{ xmlhttp=new XMLHttpRequest(); }catch(e){xmlhttp=false;} + /* IE6 */ + if(typeof ActiveXObject != "undefined"){ + if(!xmlhttp)try{ xmlhttp=new ActiveXObject("MSXML2.XMLHTTP"); }catch(e){xmlhttp=false;} + if(!xmlhttp)try{ xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); }catch(e){xmlhttp=false;} + } + /* IceBrowser */ + if(!xmlhttp)try{ xmlhttp=createRequest(); }catch(e){xmlhttp=false;} + return xmlhttp; + } + +}; + diff --git a/public/akihabara/help.js b/public/akihabara/help.js new file mode 100644 index 0000000..2c4c5fa --- /dev/null +++ b/public/akihabara/help.js @@ -0,0 +1,608 @@ +// --- +// Copyright (c) 2010 Francesco Cottone, http://www.kesiev.com/ +// --- + +/** + * @namespace Help module provides some Javascript-specific functions, such object copying, randomizing functions, + * string/array handlers and the akihabaraInit function. + */ +var help={ + + /** + * Searches an object in an array filtering for one of their properties. + * @param {Array} a The array. + * @param {String} field The searched field. + * @param {String} value The searched value. + * @returns The found object, otherwise null. + */ + searchObject:function(a,field,value) { + if (!a) return null; else + for (var i=0;i0 means you're falling onto something else. + * @param {Object} th The object that is (possibly) being jumped on. + * @param {Object} by The object doing the jumping-on. + * @returns True if the two objects are overlapping enough and by.accy>0. + */ + isSquished:function(th,by) { + return ((by.accy>0)&&gbox.collides(th,by)&&(Math.abs(th.y-(by.y+by.h))<(th.h/2))) + }, + + /** + * Generates uniformly distributed random integers between min and min+range, non-inclusive. So help.random(0,2) will only return 0 and 1, etc. + * @param {Integer} min The minimum random value to be returned by the function. + * @param {Integer} range The number of different values returned by the function. + * @returns An integer between min (includive) and min+range (noninclusive). + */ + random:function(min,range) { + return min+Math.floor(Math.random()*range); + }, + + + /** + * Determines which frame of a given animation to display. Will loop an animation. + * @param {Integer} cnt A global frame counter. + * @param {Object} anim An object with parameters speed (the animation speed) and frames (the array representing the animation sequence). + * @returns The particular animation frame to display during this step. + */ + decideFrame:function(cnt,anim) { + return anim.frames[Math.floor(cnt/anim.speed)%anim.frames.length]; + }, + + /** + * Determines which frame of a given animation to display. Will remain on the last frame when the animation has played once. + * @param {Integer} cnt A global frame counter. + * @param {Object} anim An object with parameters speed (the animation speed) and frames (the array representing the animation sequence). + * @returns The particular animation frame to display during this step. + */ + decideFrameOnce:function(cnt,anim) { + return anim.frames[(cnt>=anim.frames.length*anim.speed?anim.frames.length-1:Math.floor(cnt/anim.speed))]; + }, + + /** + * Returns whether the animation was fully played at least once with decideFrame or fully with decideFrameOnce. + * @param {Integer} cnt A global frame counter. + * @param {Object} anim An object with parameters speed (the animation speed) and frames (the array representing the animation sequence). + * @returns A boolean, true if the animation has been played at least once. + */ + isLastFrameOnce:function(cnt,anim) { + return (cnt>=anim.frames.length*anim.speed); + }, + + /** + * Given an incrementing value each step, this will return a value increasing from 0 until max/2, at which point it will decrement to 0, then go back up to max/2, in an endless cycle. + * @param {Integer} counter A counter. + * @param {Integer} max This determines the period of the function -- assuming counter is incrementing by one, a complete back-and-forth will take 'max' steps. + * @returns An integer. + */ + upAndDown:function(counter,max) { + if ((counter%max)>(max/2)) return max-(counter%max); else return (counter%max); + }, + + /** + * Given x,y coordinates and map information, this returns the tile at a given point. + * @param {Integer} x An x-coordinate. + * @param {Integer} y A y-coordinate. + * @param {Object} map The map object. + * @param {Object} ifout An object or value to be returned if the x,y coordinate pair is outside the map. + * @param {String} mapid The id for the map array within the map object. Default is 'map'. + * @returns An integer representing the value of the tile in the map array at that x,y coordinate. If there is no tile, null is returned. + */ + getTileInMap:function(x,y,map,ifout,mapid) { + if (!mapid) mapid="map"; + var ts=gbox._tiles[map.tileset]; + var tx=Math.floor(x/ts.tilew); + var ty=Math.floor(y/ts.tileh); + if ((ty<0)||(ty>=map[mapid].length)) return ifout; else + if ((tx<0)||(tx>=map[mapid][ty].length)) return ifout; else + return map[mapid][ty][tx]; + }, + + /** + * Takes an ascii-art-style array of characters and converts it to an Akihabara-compatible map format. + * @param {Array} map An array of characters representing a map. + * @param {Array} tra A translation array. This is an array of arrays, formatted like [ [null, char1], [0, char2], [1, char3] ]. There must at least be a null entry, followed by one numerical entry for each tile type you want to render, corresponding to the unique characters in the map array. The null entry maps a character to empty space. + * @returns A map array formatted such that it can be attached to a map object. + */ + asciiArtToMap:function(map,tra) { + var sz=tra[0][1].length; + var ret=[]; + var xpos; + var pie; + for (var y=0;ymax. + */ + limit:function(v,min,max) { + if (vmax) return max; else return v; + }, + + /** + * Subtracts or adds 1 to a value, always converging to zero. For example, passing -3 yields -2, 5 yields 4, etc. Works best with integers. + * @param {Integer} v A value. + * @returns A value that is one closer to 0 on the number line than v. + */ + goToZero:function(v) { return (v?v-(v/Math.abs(v)):0); }, + + /** + * Merges two sets of parameters together without overwriting existing parameters. This merges from model to data, and if data and model share parameters, data's values remain intact. + * @param {Object} data An object containing a set of parameters, the destination of the merge. + * @param {Object} model An object containing a set of parameters, the source of the merge. + * @returns A merged model where the values of 'data' remain untouched: only new parameters and values from 'model' make it in. + * @example + * dst = {a: 1, b: 2, c: "three"}; + * src = {c: "three", d: "four"}; + * merged = help.mergeWithModel(dst,src); + * merged; // => {a: 1, b: 2, c: 3, d: "four"}; + */ + mergeWithModel:function(data,model) { + if (data==null) data={}; + if (model!=null) + for (var i in model) + if (data[i]==null) data[i]=model[i]; + return data; + }, + + /** + * Merges two sets of parameters together overwriting any existing parameters. This merges model->data, and if data and model share parameters, data's are overwritten by model's. + * @param {Object} data An object containing a set of parameters, the destination of the merge. + * @param {Object} model An object containing a set of parameters, the source of the merge. + * @returns A merged model where the values of 'model' take precedence over those of 'data'. The 'data' object is returned and will be an exact copy of 'model', plus any parameters that 'data' had before the merge that 'model' did not. + * @example + * dst = {a: 1, b: 2, c: "three"}; + * src = {c: "three", d: "four"}; + * merged = help.mergeWithModel(dst,src); + * merged; // => {a: 1, b: 2, c: "three", d: "four"} + */ + copyModel:function(data,model) { + if (data==null) data={}; + if (model!=null) + for (var i in model) data[i]=model[i]; + return data; + }, + + /** + * Creates a subset of an existing set of parameters. + * @param {Object} obj An object containing a set of parameters, the source of the data. + * @param {Array} attrs An array of strings, containing the names of parameters you wish to copy. + * @returns A new set of parameters based on the subset specified. + * @example + * data = {a: 1, b: 2, c: "three"}; + * newdata = help.createModel(data, ["a", "c"]); + * newdata; // => {a: 1, c: "three"} + */ + createModel:function(obj,attrs) { + var ret={}; + for (var i=0;i {a: 1, b: 2, c: "three"} + */ + cloneObject:function(model) { + if (!model) return model; + var data={}; + for (var i in model) data[i]=model[i]; + return data; + }, + + /** + * Sets a tile in the map and draws it. Does not return anything. + * @param {Object} ctx The canvas context for the map. Accessed via gbox.getCanvasContext("canvasname") + * @param {Object} map The game map object. + * @param {Integer} x The index of the tile column within the map array -- so a 1 would mean the second column of tiles. + * @param {Integer} y The index of the tile row within the map array -- so a 1 would mean the second row of tiles. + * @param {Integer} tile The integer representing the new tile you wish to draw. This is its index within the tileset; a null value will erase whatever tile is present. + * @param {String} The ID of the map. Defaults to 'map'. + * @example + * // Remove the second tile to the right and down from the upper left corner of the tile map. Assumes our map canvas is called 'map_canvas'. + * help.setTileInMap(gbox.getCanvasContext("map_canvas"),map,1,1,null,"map"); + */ + setTileInMap:function(ctx,tilemap,x,y,tile,map) { + var ts=gbox.getTiles(tilemap.tileset); + tilemap[(map==null?"map":map)][y][x]=tile; + if (tile==null) + gbox.blitClear(ctx,{x:x*ts.tilew,y:y*ts.tilew,h:ts.tileh,w:ts.tilew}); + else + gbox.blitTile(ctx,{tileset:tilemap.tileset,tile:tile,dx:x*ts.tilew,dy:y*ts.tilew}); + }, + + /** + * Sets a tile in the map and draws it using pixels as coords. Does not return anything. + * @param {Object} ctx The canvas context for the map. Accessed via gbox.getCanvasContext("canvasname") + * @param {Object} map The game map object. + * @param {Integer} x The index of the pixel column within the map array -- so a 1 would mean the second column of tiles. + * @param {Integer} y The index of the pixel row within the map array -- so a 1 would mean the second row of tiles. + * @param {Integer} tile The integer representing the new tile you wish to draw. This is its index within the tileset; a null value will erase whatever tile is present. + * @param {String} The ID of the map. Defaults to 'map'. + */ + setTileInMapAtPixel:function(ctx,tilemap,x,y,tile,map) { + var ts=gbox.getTiles(tilemap.tileset); + x=Math.floor(x/ts.tilew); + y=Math.floor(y/ts.tileh); + help.setTileInMap(ctx,tilemap,x,y,tile,map); + }, + + + /** + * Returns the Nth element in an array. If the array is shorter than N, it returns the last element of the array. + * @param {Array} a An array. + * @param {Integer} id An index to the array. + * @returns If id > a.length, it returns a[a.length-1]. Otherwise returns a[id]. + */ + getArrayCapped:function(a,id) { + if (id>=a.length) return a[a.length-1]; else return a[id]; + }, + + /** + * Returns the element of a sorted array that have the highest value of one of the properties. + * @param {Array} a An array. + * @param {Integer} value The target value. + * @param {String} field The property used to filter the array. + * @returns The object with the highest target value, otherwise the first element of the array. + */ + getArrayIndexed:function(a,value,field) { + if (a[0][field]==null) return a[0]; + var i=0; + while ((value>a[i][field])&&(i!=a.length-1)) i++; + return a[i]; + }, + + + /** + * Converts a quantity of frames into a timestamp formatted "mm:ss:cs" (minutes, seconds, centiseconds). Calculated using the current frames per second. + * @param {Integer} frames A quantity of frames. + * @returns A string containing a timestamp formatted "mm:ss:cs", representing the length of time it would take to render that many frames. + * @example + * // Assuming 25 frames per second, Akihabara's default. + * timestamp = help.framestotime(25); + * timestamp; // => '00:01:00'; + * timestamp = help.framestotime(25 * 60); + * timestamp; // => '01:00:00'; + */ + framestotime:function(frames) { + var csec=Math.ceil(frames/gbox.getFps()*100); + return this.prepad((Math.floor(csec/6000)%60),2,"0")+":"+this.prepad((Math.floor(csec/100)%60),2,"0")+":"+this.prepad(csec%100,2,"0"); + + }, + + /** + * Reads the value of a query parameter from the URL of the web page. + * @param {String} name The name of the URL parameter. + * @returns The value of the URL parameter, as a string. + * @example + * // If the URL is http://example.com/game.html?lives=3 + * player.lives = help.geturlparameter("lives"); + * player.lives; // => 3 + */ + geturlparameter:function( name ) { + name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]"); + var regexS = "[\\?&]"+name+"=([^&#]*)"; + var regex = new RegExp( regexS ); + var results = regex.exec( window.location.href ); + if( results == null ) + return ""; + else + return results[1]; + }, + + /** + * Writes the contents of an object to a string. Useful for debugging. + * @param {Object} Any object. + * @returns A string containing all the contents of an object. If the object contains functions, the string will contain the code for those functions. + */ + objToStr:function(o) { + var ret=""; + for (var n in o) ret+=n+":["+o[n]+"] "; + return ret; + }, + + /** + * Tests whether an object contains a given parameter. + * @param {Object} A reference to a parameter of an object. + * @returns True if the object contains that parameter, false if it does not. + * @example + * foo = {a: 1, b: 2}; + * help.isDefined(foo.a); // => true + * help.isDefined(foo.c); // => false + */ + isDefined:function(v) { + return ((typeof(v) !== 'undefined') || (v===null)); + }, + + /** + * Automatically configures a bunch of settings depending on the web browser and device that is viewing the game. Mostly sets the maximum number of audio channels and touch settings. + */ + getDeviceConfig:function() { + var cap; + if (navigator.userAgent.match(/nintendo wii/i)) + cap={iswii:true,height:window.innerHeight,doublebuffering:true} // Simulated double buffering has been resumed. Canvas on Opera for Wii has a strange sprite blinking effect - usually browsers render frames once ended and this is an exception. + else if (navigator.userAgent.match(/iPhone/i)||navigator.userAgent.match(/iPod/i) || navigator.userAgent.match(/Android/i)) + cap={touch:true,width:320}; + else if (navigator.userAgent.match(/iPad/i)) + cap={touch:true,width:768,forcedidle:10}; // Forced idle time is needed for correct framerate calculation. + else + cap={zoom:2}; + + cap.canaudio=!!(document.createElement('audio').canPlayType); + if (cap.canaudio) { + if (navigator.userAgent.match(/iPad/i)||navigator.userAgent.match(/iPhone/i)||navigator.userAgent.match(/iPod/i)) { + cap.audiocompatmode=2; // Audio loading mode. + cap.audioteam=1; // Only a member is required in the audioteam. + cap.audioisexperimental=true; // Audio is experimental, since limited. + cap.audioissinglechannel=true; // Single channeled. Plays only the "bgmusic" channel. + } else if (navigator.userAgent.match(/Chrome/i)) { + cap.audioteam=3; // Quite low performance on playback responsiveness. + } else if (navigator.userAgent.match(/Firefox/i)) { + cap.audioteam=1; // Testing smaller audioteam + cap.audiopositiondelay=0.3; // Ogg playback is slower 0.3 between MP3 playback. Don't know why :) + cap.audiocreatemode=1; // Firefox is stalling while downloading lot of things + } else if (navigator.userAgent.match(/Minefield/i)) { + cap.audioteam=1; // Testing smaller audioteam + cap.audiocreatemode=1; // Firefox is stalling while downloading lot of things + // Minefield has fixed the 0.3 delay! + } else if (navigator.userAgent.match(/khtml/i)&&navigator.userAgent.match(/konqueror/i)) { + // Note that audio is not supported in applewebkit mode :( + cap.audioteam=1; + cap.audioissinglechannel=true; // Single channeled. Plays only the "bgmusic" channel. + cap.audiocompatmode=2; // Sorry. iPad single channel mode. Audio events are not triggered properly and audio properties are missing so many audio feautres are not available. :( + cap.forcedmimeaudio="audio/ogg"; // Usually OGG audio playback is supported by default in KDE env. + cap.audioisexperimental=true; // Audio is experimental, since limited. + } else if (navigator.userAgent.match(/Safari/i)) { + cap.audioteam=1; // Testing smaller audioteam + } else if (navigator.userAgent.match(/Opera/i)) { + cap.audioteam=1; // Testing smaller audioteam + cap.audiocreatemode=1; // Do not like audio object cloning very much + } else if (navigator.userAgent.match(/MSIE 9.0/i)||navigator.userAgent.match(/MSIE 7.0/i)) { + cap.audioteam=2; + cap.audiocompatmode=1; // Audio loading mode. + cap.audioisexperimental=navigator.userAgent.match(/MSIE 7.0/i); // Audio is experimental, on IE7 (for compat mode) + } else + cap.audioisexperimental=true; // Audio is just experimental on all other devices. + } + return cap; + }, + + /** + * This provides a number of configurations: fps, display zoom, dynamic frameskip, force touch parameters, etc. Many of these settings can + * be set manually by passing an object with the parameters defined, or via URL parameters. + * @param {Object} data An optional object containing parameters you wish to set. Works for data.zoom, data.splash, data.width, data.height, data.title, data.fps, and data.padmode. + */ + akihabaraInit:function(data) { + if ((typeof data).toLowerCase() == "string") data={title:data}; + var device=this.getDeviceConfig(); + var footnotes=["MADE WITH AKIHABARA (C)2010 - GPL2/MIT","Project: www.kesiev.com/akihabara","Sources: github.com/kesiev/akihabara"]; + document.title=(data.title?data.title:"Akihabara"); + if (data.splash) { + if (data.splash.footnotes) + for (var i=0;iiphopad._width-iphopad._buttonsize) + nb.a=true; + else if (rp.x>iphopad._width-iphopad._buttonsize2) + nb.b=true; + else if (rp.x>iphopad._width-iphopad._buttonsize3) + nb.c=true; + + } + this._swap=!this._swap; + for (var i in this._cross) { + if (nc[i]!=iphopad._cross[i]) + if (nc[i]) gbox._keydown({fake:true,keyCode:gbox._keymap[i]}); + else gbox._keyup({fake:true,keyCode:gbox._keymap[i]}); + } + for (var i in this._buttons) { + if (nb[i]!=iphopad._buttons[i]) + if (nb[i]) gbox._keydown({fake:true,keyCode:gbox._keymap[i]}); + else gbox._keyup({fake:true,keyCode:gbox._keymap[i]}); + } + + iphopad._cross=nc; + iphopad._buttons=nb; + }, + _fakelisten:function(e) { + iphopad._listen({ + touches:[ + { + pageX:e.clientX, + pageY:e.clientY + } + ] + }); + }, + + /** + * Initializes the game controls for use with an I-product or Android device. + * @param {Object} data passes in information about the screen and its traits such as size. + */ + initialize:function(data) { + var oElement=document.createElement("div"); + oElement.style.margin="auto"; + oElement.style.padding="0px"; + oElement.style.height=data.h+"px"; + oElement.style.width="100%"; + oElement.style.backgroundImage="url("+data.bg+")"; + oElement.style.backgroundRepeat="repeat-x"; + + var tpad=document.createElement("div"); + tpad.style.cssFloat="left"; + tpad.style.padding="0px"; + tpad.style.margin="0px"; + tpad.style.height=data.h+"px"; + tpad.style.width=data.h+"px"; + tpad.style.backgroundImage="url("+data.dpad+")"; + tpad.style.backgroundRepeat="no-repeat"; + + var bpad=document.createElement("div"); + bpad.style.cssFloat="right"; + bpad.style.padding="0px"; + bpad.style.margin="0px"; + bpad.style.height=data.h+"px"; + bpad.style.width=iphopad._buttonsize3+"px"; + bpad.style.backgroundImage="url("+data.buttons+")"; + bpad.style.backgroundRepeat="no-repeat"; + + oElement.appendChild(tpad); + oElement.appendChild(bpad); + gbox._box.appendChild(oElement); + + oElement.ontouchstart=function(evt) { evt.preventDefault();evt.stopPropagation(); iphopad._listen(evt) }; + oElement.ontouchend=function(evt) { evt.preventDefault();evt.stopPropagation();iphopad._listen(evt) }; + oElement.ontouchmove=function(evt) { evt.preventDefault();evt.stopPropagation();iphopad._listen(evt) }; + //oElement.onmousemove=function(evt) { iphopad._fakelisten(evt) }; + var sizes=gbox._domgetabsposition(oElement); + this._gapx=sizes.x; + this._gapy=sizes.y; + this._width=sizes.w; + this._height=sizes.h; + this._center={x:Math.floor(this._height/2),y:Math.floor(this._height/2)}; + } + +} diff --git a/public/akihabara/padbg.png b/public/akihabara/padbg.png new file mode 100644 index 0000000..09b9db0 Binary files /dev/null and b/public/akihabara/padbg.png differ diff --git a/public/akihabara/splash.png b/public/akihabara/splash.png new file mode 100644 index 0000000..5d031ce Binary files /dev/null and b/public/akihabara/splash.png differ diff --git a/public/akihabara/tool.js b/public/akihabara/tool.js new file mode 100644 index 0000000..9f41b2e --- /dev/null +++ b/public/akihabara/tool.js @@ -0,0 +1,131 @@ +// --- +// Copyright (c) 2010 Francesco Cottone, http://www.kesiev.com/ +// --- + +/** + * @namespace Tool module provides simple developing tools. Currently, this file only has a cel-composer: + * it can compose an image stacking a set of frames for animating objects, applying a + * number of filters to each frame. + */ +var tool={ + _images:[], + _loadedflag:[], + _data:{}, + _count:0, + _countloaded:0, + + /** + * This function documents that an image in an animation sequence is loaded and checks if the other images are loaded or not + * @param {Object} id This is the object which is used as an id for keeping track of things related to this object in this function + */ + _loaded:function(id) { + this._loadedflag[id]=true; + tool._countloaded++; + document.title=tool._countloaded+"/"+tool._count; + for (var i=0;i + *
  • x{Integer}: (required)Objects x position
  • + *
  • y{Integer}: (required)Objects y position
  • + *
  • z{Integer}: (required)Objects z position
  • + *
  • colx{Integer}: (required)The dimension of the collision box along the x axis
  • + *
  • coly{Integer}: (required)The dimension of the collision box along the y axis
  • + *
  • colh{Integer}: (required)Collision box height
  • + *
  • colw{Integer}: (required)Collision box width
  • + * + * @param {Object} to The object that collision is being checked against. + *
      + *
    • x{Integer}: (required)Objects x position
    • + *
    • y{Integer}: (required)Objects y position
    • + *
    • z{Integer}: (required)Objects z position
    • + *
    • colx{Integer}: (required)Collision x
    • + *
    • coly{Integer}: (required)Collision y
    • + *
    • colh{Integer}: (required)Collision box height
    • + *
    • colw{Integer}: (required)Collision box width
    • + *
    + * @param {int} t This is the tollerance (or margin for error) on the collide function. + */ + collides:function(fr,to,t) { // Special collision. Counts also the Z + if (Math.abs(fr.z,to.z)<5) return gbox.collides({x:fr.x+fr.colx,y:fr.y+fr.coly,h:fr.colh,w:fr.colw},{x:to.x+to.colx,y:to.y+to.coly,h:to.colh,w:to.colw},t); else return false; + }, + + /** + * Checks for pixel collisions with an offset to the X and Y of the colidable using colx and coly. + * @param {Object} fr The object which collision is being tested for. + * @param {Object} to The object (or point) which collision is being tested against. + * @param {int} t The tollerance of the collision algorithm. + */ + pixelcollides:function(fr,to,t) { // Special collision. Counts also the Z + return gbox.pixelcollides(fr,{x:to.x+to.colx,y:to.y+to.coly,h:to.colh,w:to.colw},t); + }, + + /** + * Initializes the game with the variables needed for topview and whatever else you feed in through data. + * @param {Object} th Passes in the object being initialized. + * @param {Object} data This is used to pass in everything that's being initiliized. If a value is not in Data then a default value is used instead. This can pass in values which do not have a default. + *
      + *
    • x{Integer}: x position of the object. (defaults to 0)
    • + *
    • y{Integer}: y position of the object. (defaults to 0)
    • + *
    • z{Integer}: z index of the object. (defaults to 0)
    • + *
    • accx{Integer}: The starting x velociyt of the object. (defaults to 0)
    • + *
    • accy{Integer}: The starting y velocity of the object. (defaults to 0)
    • + *
    • accz{Integer}: The starting z velocity of the object. (defaults to 0)
    • + *
    • frames{Object}: This is stores the animation frames for the objects in a map style structure. An empty map means the default image will display with no animation frames. (defaults to an empty map)
    • + *
    • shadow: (defaults to null)
    • //incomplete + *
    • maxacc{Integer}: (defaults to )4
    • + *
    • controlmaxacc{Integer}: (defaults to 4)
    • + *
    • responsive: (defaults to 0)
    • + *
    • weapon: (defaults to 0)
    • + *
    • camera{Boolean}: (defaults to true)
    • + *
    • flipv{Boolean}: Notes if the object is flipped vertically(defaults to false)
    • + *
    • fliph{Boolean}: Notes if the object is flipped horrizontally(defaults to false)
    • + *
    • facing{Integer}: Stores the facing of the object. This is set with pre-defined Integer values from within Toys.(defaults to toys.FACE_DOWN)
    • + *
        + *
      • FACE_UP:0,
      • + *
      • FACE_RIGHT:1,
      • + *
      • FACE_DOWN:2,
      • + *
      • FACE_LEFT:3,
      • + *
      + *
    • flipside{Boolean}: (defaults to true)
    • + *
    • haspushing{Boolean}: (defaults to false)
    • + *
    • frame: (default to 0)
    • + *
    • colh{Integer}: (defaults to gbox.getTiles(th.tileset).tilehh)
    • + *
    • colw{Integer}: (defaults to gbox.getTiles(th.tileset).tilew)
    • + *
    • colx{Integer}: (defaults to 0)
    • + *
    • staticspeed{Integer}: (defaults to 0)
    • + *
    • nodiagonals{Boolean}: (defaults to false)
    • + *
    • noreset: (defaults to false)
    • + *
    + */ + initialize:function(th,data) { + help.mergeWithModel( + th, + help.mergeWithModel( + data, + { + x:0, y:0, + z:0, + accx:0, accy:0, accz:0, + frames:{}, + shadow:null, + maxacc:4, controlmaxacc:4, + responsive:0, // Responsiveness + weapon:0, // Weapon + camera:true, + flipv:false, fliph:false, + facing:toys.FACE_DOWN, + flipside:true, + haspushing:false, + frame:0, + colh:gbox.getTiles(th.tileset).tilehh, + colw:gbox.getTiles(th.tileset).tilew, + colx:0, + staticspeed:0, + nodiagonals:false, + noreset:false + } + ) + ); + if (th.coly==null) th.coly=gbox.getTiles(th.tileset).tileh-th.colh; + th.colhh=Math.floor(th.colh/2); + th.colhw=Math.floor(th.colw/2); + + toys.topview.spawn(th); + }, + + /** + * Spawns a new object in the topview namespace. This also merges parameters in data into paramaters in th using help.copyModel. + * This initializes some basic basic variables for the object and sets the Z index. + * @param {Object} th References 'this' which is the object that called the method (generally). + *
      + *
    • y {Integer}: (required) The object's y position.
    • + *
    • h {Integer}: (required) The object's height.
    • + *
    + * @param {Object} data This holds variables to be merged into th's stored info. + */ + spawn:function(th,data) { + th.xpushing=toys.PUSH_NONE; // user is moving side + th.vpushing=toys.PUSH_NONE; // user is moving side + th.zpushing=toys.PUSH_NONE; // user is moving side + th.counter=0; // self counter + th.hittimer=0; + th.killed=false; + help.copyModel(th,data); + gbox.setZindex(th,th.y+th.h); // these object follows the z-index and uses ZINDEX_LAYER + }, + + /** + * This sets and runs the control keys for the game. + * @param {Object} th This is the object that is being controlled by the keys (assumed to be the player) + *
      + *
    • accx: the object's currect acceleration in the x direction
    • + *
    • accy: the object's currect acceleration in the y direction
    • + *
    • responsive: minimum movement speed
    • + *
    • staticspeed: turns off acceleration
    • + *
    • nodiagonals: boolean determining if the object can move along both axis at once.
    • + *
    • xpushing: a boolean that notes whether the object is pushing against something in the x direction.
    • + *
    • ypushing: a boolean that notes whether the object is pushing against something in the y direction.
    • + *
    • controlmaxacc: max acceleration for the object along an axis
    • + *
    • noreset: checks for the object being allowed to reset its pushing status (?)
    • + *
    + * @param {Object} keys These are the control keys being passed in for left, right, up, and down. + * //incomplete + */ + controlKeys:function(th,keys) { + var cancelx=false; + var cancely=false; + var idlex=false; + var idley=false; + + if (gbox.keyIsPressed(keys.left)||keys.pressleft) { + th.xpushing=toys.PUSH_LEFT; + th.facing=toys.FACE_LEFT; + if (th.accx>th.responsive) th.accx=th.responsive; + if (th.staticspeed) th.accx=-th.staticspeed; else th.accx=help.limit(th.accx-1,-th.controlmaxacc,th.controlmaxacc); + if (th.nodiagonals) { cancely=true; idley=true } + } else if (gbox.keyIsPressed(keys.right)||keys.pressright) { + th.xpushing=toys.PUSH_RIGHT; + th.facing=toys.FACE_RIGHT; + if (th.accx<-th.responsive) th.accx=-th.responsive; + if (th.staticspeed) th.accx=th.staticspeed; else th.accx=help.limit(th.accx+1,-th.controlmaxacc,th.controlmaxacc); + if (th.nodiagonals) { cancely=true; idley=true } + } else idlex=true; + + if (!cancely&&(gbox.keyIsPressed(keys.up)||keys.pressup)) { + th.ypushing=toys.PUSH_UP; + th.facing=toys.FACE_UP; + if (th.accy>th.responsive) th.accy=th.responsive; + if (th.staticspeed) th.accy=-th.staticspeed; else th.accy=help.limit(th.accy-1,-th.controlmaxacc,th.controlmaxacc); + if (th.nodiagonals) { cancelx=true; idlex=true; } + } else if (!cancely&&(gbox.keyIsPressed(keys.down)||keys.pressdown)) { + th.ypushing=toys.PUSH_DOWN; + th.facing=toys.FACE_DOWN; + if (th.accy<-th.responsive) th.accy=-th.responsive; + if (th.staticspeed) th.accy=th.staticspeed; else th.accy=help.limit(th.accy+1,-th.controlmaxacc,th.controlmaxacc); + if (th.nodiagonals) { cancelx=true; idlex=true; } + } else idley=true; + + + + if (idlex) { + if (cancelx) th.accx=0; + if (cancelx||!th.noreset) th.xpushing=toys.PUSH_NONE; + } + if (idley) { + if (cancely) th.accy=0; + if (cancely||!th.noreset) th.ypushing=toys.PUSH_NONE; + } + }, + + /** + * Gets the next X position the object is going to move to. + * @param {Object} th The object being checked. + *
      + *
    • x: the current x position of the object
    • + *
    • accx: the object's currect acceleration in the x direction
    • + *
    • maxacc: the max accleration the object can have (if accx is greater than this then this value is used instead)
    • + *
    + */ + getNextX:function(th) { return th.x+help.limit(th.accx,-th.maxacc,th.maxacc); }, + + /** + * Gets the next Y position the object is going to move to. + * @param {Object} th The object being checked. + *
      + *
    • y: the current y position of the object
    • + *
    • accy: the object's currect acceleration in the y direction
    • + *
    • maxacc: the max accleration the object can have (if accy is greater than this then this value is used instead)
    • + *
    + */ + getNextY:function(th) { return th.y+help.limit(th.accy,-th.maxacc,th.maxacc); }, + + /** + * Gets the next Z position the object is going to move to. + * @param {Object} th The object being checked. + *
      + *
    • z: the current z position of the object
    • + *
    • accz: the object's currect acceleration in the z direction
    • + *
    • maxacc: the max accleration the object can have (if accz is greater than this then this value is used instead)
    • + *
    + */ + getNextZ:function(th) { return th.z+help.limit(th.accz,-th.maxacc,th.maxacc); }, + + /** + * Sets the objects current location to its next location using the getNextX and getNextY methods. + * @param {Object} th The object being modified. + *
      + *
    • x: the current x position of the object
    • + *
    • y: the current y position of the object
    • + *
    • accx: the object's currect acceleration in the x direction
    • + *
    • accy: the object's currect acceleration in the y direction
    • + *
    • maxacc: the max accleration the object can have (if either acceleration is greater than this then this value is used instead for that acceleration)
    • + *
    + */ + applyForces:function(th) { + th.x=toys.topview.getNextX(th); + th.y=toys.topview.getNextY(th); + }, + + /** + * This applies acceleration in the Z direction (not nessesarily gravity but whatever the next accerlation on the Z axis is) + * @param {Object} th The object being modified. + *
      + *
    • z: the current z position of the object
    • + *
    • accz: the object's currect acceleration in the z direction
    • + *
    • maxacc: the max accleration the object can have (if accz is greater than this then this value is used instead)
    • + *
    + */ + applyGravity:function(th) { + th.z=toys.topview.getNextZ(th); + }, + + /** + * Degrades all accelerations on an object by one toward zero. + * @param {Object} th The object being modified. + *
      + *
    • xpushing: a boolean that notes whether the object is pushing against something in the x direction.
    • + *
    • ypushing: a boolean that notes whether the object is pushing against something in the y direction.
    • + *
    • accx: the object's currect acceleration in the x direction
    • + *
    • accy: the object's currect acceleration in the y direction
    • + *
    + */ + handleAccellerations:function(th) { + if (!th.xpushing) th.accx=help.goToZero(th.accx); + if (!th.ypushing) th.accy=help.goToZero(th.accy); + + }, + + /** + * Increases the Z acceleration on the object by one. + * @param {Object} th The object being modified. + *
      + *
    • accz: the acceleration on the Z axis
    • + *
    + */ + handleGravity:function(th) { + th.accz++; + }, + + /** + * This sets which frame the object is going to display based on an agregate word that describes predefined states. + * @param {Object} th The object whose frame is being set. + *
      + *
    • xpushing: a boolean that notes whether the object is pushing against something in the x direction.
    • + *
    • ypushing: a boolean that notes whether the object is pushing against something in the y direction.
    • + *
    • haspushing: a boolean that notes if the object changes when pushing against something.
    • + *
    • toucheddown: a boolean that notes if the object is touching something below it on the screen.
    • + *
    • touchedup: a boolean that notes if the object is touching something above it on the screen.<
    • + *
    • touchedright: a boolean that notes if the object is touching something right of it on the screen.<
    • + *
    • touchedleft: a boolean that notes if the object is touching something left of it on the screen.<
    • + *
    • flipside:
    • + *
    • fliph:
    • + *
    • facing:
    • + *
    • frames:
    • + *
    • frame:
    • + *
    • counter:
    • + *
    + * // incomplete + */ + setFrame:function(th) { + var pref="stand"; + if (th.xpushing||th.ypushing) + if (th.haspushing&&(th.toucheddown||th.touchedup||th.touchedleft||th.touchedright)) pref="pushing"; else pref="moving"; + if (th.flipside) + th.fliph=(th.facing==toys.FACE_RIGHT); + th.frame=help.decideFrame(th.counter,th.frames[pref+toys.FACES[th.facing]]); + }, + + /** + * Checks if the specified object is colliding with tiles in the map in an area defined by the object's colw and colh variables as well as the tolerance and approximation variables that are passed in through data. Only tiles in the map marked as solid are checked against. The alogrithm checks the + * @param {Object} th The object that is being checked against the tilemap. + * @param {Object} map This is the asci map that the tile map is generated from. + * @param {Object} tilemap This is the array of tile objects that it itterated over checking for collisions. + * @param {Object} defaulttile The default tile to be returned if nothing can be found. Null can be used here. + * @param {Object} data Passes is extra dat to the function. Can be set as null. + *
      + *
    • tolerance{Integer}: This is subtracted from the collision space to get the maximum collision area for the object. This defaults to 6.
    • + *
    • approximation{Integer}: This is the amount that the checked values are incremented by until they reach the maximum value allowed. This defaults to 10.
    • + *
    + */ + tileCollision:function(th,map,tilemap,defaulttile,data) { + + th.touchedup=false; + th.toucheddown=false; + th.touchedleft=false; + th.touchedright=false; + + var tolerance=(data&&(data.tolerance!=null)?data.tolerance:6); + var approximation=(data&&(data.approximation!=null)?data.approximation:10); + var t=tolerance-approximation; + do { + t+=approximation; + if (t>th.colw-tolerance-1) t=th.colw-tolerance-1; + var bottom=help.getTileInMap(th.x+th.colx+t,th.y+th.coly+th.colh-1,map,defaulttile,tilemap); + var top=help.getTileInMap(th.x+th.colx+t,th.y+th.coly,map,defaulttile,tilemap); + if (map.tileIsSolid(th,top)) th.touchedup=true; + if (map.tileIsSolid(th,bottom)) th.toucheddown=true; + } while (t!=th.colw-tolerance-1); + + t=tolerance-approximation; + do { + t+=approximation; + if (t>th.colh-tolerance-1) t=th.colh-tolerance-1; + var left=help.getTileInMap(th.x+th.colx,th.y+th.coly+t,map,defaulttile,tilemap); + var right=help.getTileInMap(th.x+th.colx+th.colw-1,th.y+th.coly+t,map,defaulttile,tilemap); + if (map.tileIsSolid(th,left)) th.touchedleft=true; + if (map.tileIsSolid(th,right)) th.touchedright=true; + } while (t!=th.colh-tolerance-1); + + if (th.touchedup) { + th.accy=0; + th.y=help.yPixelToTile(map,th.y+th.coly,1)-th.coly; + } + if (th.toucheddown) { + th.accy=0; + th.y=help.yPixelToTile(map,th.y+th.coly+th.colh-1)-th.coly-th.colh; + } + if (th.touchedleft) { + th.accx=0; + th.x=help.xPixelToTile(map,th.x+th.colx,1)-th.colx; + } + if (th.touchedright) { + th.accx=0; + th.x=help.xPixelToTile(map,th.x+th.colx+th.colw-1)-th.colx-th.colw; + } + + }, + + /** + * @param {Object} th The object being checked for collisions. + *
      + *
    • + *
    • + *
    • + *
    • + *
    + * @param {Object} data This is used to pass in other data and arguments. + *
      + *
    • group {String}: (required) This is the group of objects being checked against.
    • + *
    • + *
    • + *
    • + *
    • + *
    //incomplete + */ + spritewallCollision:function(th,data) { + var wl; + for (var i in gbox._objects[data.group]) + if ((!gbox._objects[data.group][i].initialize)&&toys.topview.collides(th,gbox._objects[data.group][i])) { + wl=gbox._objects[data.group][i]; + if (toys.topview.pixelcollides({x:th.x+th.colx,y:th.y+th.coly+th.colhh},wl)) { + th.touchedleft=true; + th.accx=0; + th.x=wl.x+wl.colx+wl.colw-th.colx; + } else if (toys.topview.pixelcollides({x:th.x+th.colx+th.colw,y:th.y+th.coly+th.colhh},wl)) { + th.touchedright=true; + th.accx=0; + th.x=wl.x+wl.colx-th.colw-th.colx; + } + if (toys.topview.pixelcollides({x:th.x+th.colx+th.colhw,y:th.y+th.coly+th.colh},wl)) { + th.toucheddown=true; + th.accy=0; + th.y=wl.y+wl.coly-th.colh-th.coly; + } else if (toys.topview.pixelcollides({x:th.x+th.colx+th.colhw,y:th.y+th.coly},wl)) { + th.touchedup=true; + th.accy=0; + th.y=wl.y+wl.coly+wl.colh-th.coly; + } + } + + }, + + /** + * This checks if the object's z index is 0 which means it has hit the floor. If this has occured it also plays an impact or bounce noise if one is passed in. Note: The area above the floor is in the negative z index space so a value of 1 for z will return that the object has collided with the floor and z will then be set to zero. + * @param {Object} th The object being checked for collision. + *
      + *
    • touchedfloor{boolean}: This value is not passed in but is created or set in the function. This contains the function's return value.
    • + *
    • + *
    • + *
    • + *
    + * @param {Object} data This is used to pass in extra parameters. + *
      + *
    • + *
    + */ + floorCollision:function(th,data) { + th.touchedfloor=false; + if (th.z>0) { + th.accz=(data==null?0:-Math.floor(th.accz/data.bounce)); + if (data&&data.audiobounce&&th.accz) gbox.hitAudio(data.audiobounce); + th.z=0; + th.touchedfloor=true; + } + }, + + /** + * + */ + adjustZindex:function(th) { + gbox.setZindex(th,th.y+th.h); + }, + + /** + * + */ + // Helper: returns the ahead pixel (i.e. destination use action) + getAheadPixel:function(th,data) { + switch (th.facing) { + case toys.FACE_RIGHT:{ + return {x:th.x+th.colx+th.colw+data.distance,y:th.y+th.coly+th.colhh}; + break; + } + case toys.FACE_LEFT:{ + return {x:th.x+th.colx-data.distance,y:th.y+th.coly+th.colhh}; + break; + } + case toys.FACE_UP:{ + return {x:th.x+th.colx+th.colhw,y:th.y+th.coly-data.distance}; + break; + } + case toys.FACE_DOWN:{ + return {x:th.x+th.colx+th.colhw,y:th.y+th.coly+th.colh+data.distance}; + break; + } + } + }, + + /** + * + */ + // Helper: trigger a method in colliding objects (i.e. "use action") + callInColliding:function(th,data) { + for (var i in gbox._objects[data.group]) + if ((!gbox._objects[data.group][i].initialize)&&toys.topview.pixelcollides(data,gbox._objects[data.group][i])) + if (gbox._objects[data.group][i][data.call]) { + gbox._objects[data.group][i][data.call](th); + return i; + } + return false; + }, + + /** + * + */ + // Enemy methods + wander:function(th,map,tilemap,defaulttile,data) { + if ((!th.wandercounter)||(th.toucheddown||th.touchedup||th.touchedleft||th.touchedright)) { + th.wandercounter=help.random(data.minstep,data.steprange); + th.wanderdirection=help.random(0,4); + } else th.wandercounter--; + switch (th.wanderdirection) { + case toys.FACE_LEFT: { + th.xpushing=toys.PUSH_LEFT; + th.ypushing=toys.PUSH_NONE; + th.facing=toys.FACE_LEFT; + th.accx=-data.speed; + th.accy=0; + break; + } + case toys.FACE_RIGHT: { + th.xpushing=toys.PUSH_RIGHT; + th.ypushing=toys.PUSH_NONE; + th.facing=toys.FACE_RIGHT; + th.accx=data.speed; + th.accy=0; + break; + } + case toys.FACE_UP: { + th.ypushing=toys.PUSH_UP; + th.xpushing=toys.PUSH_NONE; + th.facing=toys.FACE_UP; + th.accy=-data.speed; + th.accx=0; + break; + } + case toys.FACE_DOWN: { + th.ypushing=toys.PUSH_DOWN; + th.xpushing=toys.PUSH_NONE; + th.facing=toys.FACE_DOWN; + th.accy=data.speed; + th.accx=0; + break; + } + } + }, + + /** + * + */ + // generators (firebullet specific for topdown - more complex than SHMUP one) + fireBullet:function(gr,id,data) { + + var ts=gbox.getTiles(data.tileset); + + + var obj=gbox.addObject( + help.mergeWithModel( + data,{ + _bullet:true, + zindex:0, + fliph:false, flipv:false, + id:id, + group:gr, + cnt:0, + tileset:"", + frames:{}, + acc:0, + angle:0, + camera:data.from.camera, + accx:(data.accx==null?Math.floor(trigo.translateX(0,data.angle,data.acc)):0), + accy:(data.accy==null?Math.floor(trigo.translateY(0,data.angle,data.acc)):0), + accz:0, + x:(data.sidex==toys.FACE_LEFT?data.from.x-ts.tilehw:(data.sidex==toys.FACE_RIGHT?data.from.x+data.from.w-ts.tilehw:data.from.x+data.from.hw-ts.tilehw))+(data.gapx?data.gapx:0), + y:(data.sidey==toys.FACE_UP?data.from.y-ts.tilehh:(data.sidey==toys.FACE_DOWN?data.from.y+data.from.h-ts.tilehh:data.from.y+data.from.hh-ts.tilehh))+(data.gapy?data.gapy:0), + z:(data.from.z==null?0:data.from.z), + collidegroup:"", + spark:toys.NOOP, + power:1, + lifetime:null, + tilemap:null, + defaulttile:0, + applyzgravity:false, + map:null, + defaulttile:0, + mapindex:"", + spritewalls:null, + colx:(data.fullhit?0:null), + coly:(data.fullhit?0:null), + colh:(data.fullhit?ts.tileh:null), + colw:(data.fullhit?ts.tilew:null), + duration:null, + onWallHit:function() { + this.spark(this); + gbox.trashObject(this); + }, + bulletIsAlive:function() { + return gbox.objectIsVisible(this); + } + } + ) + ); + + obj.initialize=function() { + toys.topview.initialize(this); + }; + + obj[(data.logicon==null?"first":data.logicon)]=function() { + this.cnt=(this.cnt+1)%10; + + if (this.applyzgravity) toys.topview.handleGravity(this); // z-gravity + toys.topview.applyForces(this); // Apply forces + if (this.applyzgravity) toys.topview.applyGravity(this); // z-gravity + if (this.map!=null) toys.topview.tileCollision(this,this.map,this.mapindex,this.defaulttile); // tile collisions + if (this.spritewalls!=null) toys.topview.spritewallCollision(this,{group:this.spritewalls}); // walls collisions + if (this.applyzgravity) toys.topview.floorCollision(this); // Collision with the floor (for z-gravity) + toys.topview.adjustZindex(this); + if (this.duration!=null) { + this.duration--; + if (this.duration==0) gbox.trashObject(this); + } + if (!this.bulletIsAlive()) gbox.trashObject(this); + else if (this.toucheddown||this.touchedup||this.touchedleft||this.touchedright) this.onWallHit(); + else if (this.collidegroup!=null) + for (var i in gbox._objects[this.collidegroup]) + if ((!gbox._objects[this.collidegroup][i].initialize)&&toys.topview.collides(this,gbox._objects[this.collidegroup][i],gbox._objects[this.collidegroup][i].tolerance)) { + if (gbox._objects[this.collidegroup][i]["hitByBullet"]!=null) + if (!gbox._objects[this.collidegroup][i].hitByBullet(this)) { + this.spark(this); + gbox.trashObject(this); + } + } + } + + obj[(data.bliton==null?"blit":data.bliton)]=function() { + if (!gbox.objectIsTrash(this)) + gbox.blitTile(gbox.getBufferContext(),{tileset:this.tileset,tile:help.decideFrame(this.cnt,this.frames),dx:this.x,dy:this.y+this.z,camera:this.camera,fliph:this.fliph,flipv:this.flipv}); + } + + gbox.setZindex(obj,obj.y+obj.h); + + return obj; + + }, + + /** + * + */ + makedoor:function(gr,id,map,data) { + + var mts=gbox.getTiles(map.tileset); + var ts=gbox.getTiles(data.tileset); + + var obj=gbox.addObject( + help.mergeWithModel( + data,{ + zindex:0, + fliph:false, flipv:false, + id:id, + group:gr, + cnt:0, + tileset:"", + frames:{}, + camera:true, + x:data.tilex*mts.tilew, + y:data.tiley*mts.tileh, + z:0, + tilemap:null, + defaulttile:0, + map:map, + colx:(data.fullhit?0:null), + coly:(data.fullhit?0:null), + colh:(data.fullhit?ts.tileh:null), + colw:(data.fullhit?ts.tilew:null), + opening:false, + doorheight:ts.tileh, + opencounter:0, + opening:false, + closing:false, + audiobefore:null, + audioafter:null, + doOpen:function() { + this.opening=true; + }, + whenClosed:toys.NOOP, + whenOpened:toys.NOOP, + whileMoving:toys.NOOP, + hitByBullet:function(by) { + + } + } + ) + ); + + // Closing animation + if (obj.closing) obj.opencounter=obj.doorheight; + + obj.initialize=function() { + this.ismoving=false; + toys.topview.initialize(this); + }; + + obj[(data.logicon==null?"first":data.logicon)]=function() { + if (this.closing) { + if (!this.ismoving) { + if (this.audiobefore) gbox.hitAudio(this.audiobefore); + this.ismoving=true; + } + this.whileMoving(); + this.opencounter--; + if (this.opencounter<0) { + if (this.audioafter) gbox.hitAudio(this.audioafter); + this.ismoving=false; + this.opencounter=0; + this.closing=false; + this.whenClosed(); + } + } + if (this.opening) { + if (!this.ismoving) { + if (this.audiobefore) gbox.hitAudio(this.audiobefore); + this.ismoving=true; + } + this.whileMoving(); + this.opencounter++; + if (this.opencounter>=this.doorheight) { + if (this.audioafter) gbox.hitAudio(this.audioafter); + this.ismoving=false; + if (!this.whenOpened()) gbox.trashObject(this); + } + } + } + + obj[(data.bliton==null?"blit":data.bliton)]=function() { + if (!gbox.objectIsTrash(this)) + gbox.blitTile(gbox.getBufferContext(),{tileset:this.tileset,tile:help.decideFrame(this.cnt,this.frames),dx:this.x,dy:this.y+this.z+this.opencounter,h:this.h-this.opencounter,camera:this.camera,fliph:this.fliph,flipv:this.flipv}); + } + + gbox.setZindex(obj,obj.y+obj.h); + + return obj; + }, + // Set the object speed making sure that the X and Y coords are multiple of the speed. Useful on maze-based games. + setStaticSpeed:function(th,speed) { + th.staticspeed=speed; + th.x=Math.round(th.x/speed)*speed; + th.y=Math.round(th.y/speed)*speed; + } + }, + + + /** + * @namespace shmup The libraries for a 2D top-down Shmup game. + */ + // Shoot'em up specifics + shmup:{ + + /** + * + */ + initialize:function(th,data) { + help.mergeWithModel( + th, + help.mergeWithModel( + data, + { + x:0, y:0, + accx:0, accy:0, + frames:{}, + maxacc:5, controlmaxacc:5, + responsive:0, // Responsiveness + bounds:{x:0,y:0,w:gbox.getScreenW(),h:gbox.getScreenH()}, // Bounds box (ship cannot exit from there) + weapon:0, // Weapon + hittime:5, + camera:false, + flipv:false, fliph:false, + health:1, + tolerance:4 + } + ) + ); + toys.shmup.spawn(th); + }, + + /** + * + */ + spawn:function(th,data) { + th.xpushing=toys.PUSH_NONE; // user is moving side + th.vpushing=toys.PUSH_NONE; // user is moving side + th.counter=0; // self counter + th.hittimer=0; + th.killed=false; + help.copyModel(th,data); + }, + + /** + * + */ + getNextX:function(th) { return th.x+help.limit(th.accx,-th.maxacc,th.maxacc); }, + + /** + * + */ + getNextY:function(th) { return th.y+help.limit(th.accy,-th.maxacc,th.maxacc); }, + + /** + * + */ + controlKeys:function(th,keys) { + + if (gbox.keyIsPressed(keys.left)) { + th.xpushing=toys.PUSH_LEFT; + if (th.accx>th.responsive) th.accx=th.responsive; + th.accx=help.limit(th.accx-1,-th.controlmaxacc,th.controlmaxacc); + } else if (gbox.keyIsPressed(keys.right)) { + th.xpushing=toys.PUSH_RIGHT; + if (th.accx<-th.responsive) th.accx=-th.responsive; + th.accx=help.limit(th.accx+1,-th.controlmaxacc,th.controlmaxacc); + } else th.xpushing=toys.PUSH_NONE; + if (gbox.keyIsPressed(keys.up)) { + th.ypushing=toys.PUSH_UP; + if (th.accy>th.responsive) th.accy=th.responsive; + th.accy=help.limit(th.accy-1,-th.controlmaxacc,th.controlmaxacc); + } else if (gbox.keyIsPressed(keys.down)) { + th.ypushing=toys.PUSH_DOWN; + if (th.accy<-th.responsive) th.accy=-th.responsive; + th.accy=help.limit(th.accy+1,-th.controlmaxacc,th.controlmaxacc); + } else th.ypushing=toys.PUSH_NONE; + }, + + /** + * + */ + applyForces:function(th) { + th.x=toys.shmup.getNextX(th); + th.y=toys.shmup.getNextY(th); + }, + + /** + * + */ + handleAccellerations:function(th) { + if (!th.xpushing) th.accx=help.goToZero(th.accx); + if (!th.ypushing) th.accy=help.goToZero(th.accy); + }, + + /** + * + */ + keepInBounds:function(th) { + if (th.xth.bounds.x+th.bounds.w) { + th.x=th.bounds.x+th.bounds.w-th.w; + th.accx=0; + } + if (th.yth.bounds.y+th.bounds.h) { + th.y=th.bounds.y+th.bounds.h-th.h; + th.accy=0; + } + }, + + /** + * + */ + setFrame:function(th) { + if (th.hittimer) th.hittimer--; + th.frame=help.decideFrame(th.counter,(th.hittimer?th.frames.hit:th.frames.still)); + }, + + /** + * + */ + fireBullet:function(gr,id,data) { + + var ts=gbox.getTiles(data.tileset); + + var obj=gbox.addObject( + help.mergeWithModel( + data,{ + _bullet:true, + fliph:false, flipv:false, + id:id, + group:gr, + cnt:0, + tileset:"", + frames:{}, + acc:0, + angle:0, + camera:false, + accx:(data.accx==null?Math.floor(trigo.translateX(0,data.angle,data.acc)):0), + accy:(data.accy==null?Math.floor(trigo.translateY(0,data.angle,data.acc)):0), + x:data.from.x+data.from.hw-ts.tilehw+(data.gapx?data.gapx:0), + y:(data.upper?data.from.y-ts.tilehh+(data.gapy?data.gapy:0):data.from.y+data.from.h-ts.tilehh-(data.gapy?data.gapy:0)), + collidegroup:"", + spark:toys.NOOP, + power:1 + } + ) + ); + + obj[(data.logicon==null?"first":data.logicon)]=function() { + this.x+=this.accx; + this.y+=this.accy; + this.cnt=(this.cnt+1)%10; + if (!gbox.objectIsVisible(this)) gbox.trashObject(this); + else if (this.collidegroup!=null) + for (var i in gbox._objects[this.collidegroup]) + if ((!gbox._objects[this.collidegroup][i].initialize)&&gbox.collides(this,gbox._objects[this.collidegroup][i],gbox._objects[this.collidegroup][i].tolerance)) { + if (gbox._objects[this.collidegroup][i]["hitByBullet"]!=null) + if (!gbox._objects[this.collidegroup][i].hitByBullet(this)) { + this.spark(this); + gbox.trashObject(this); + } + } + } + + obj[(data.bliton==null?"blit":data.bliton)]=function() { + gbox.blitTile(gbox.getBufferContext(),{tileset:this.tileset,tile:help.decideFrame(this.cnt,this.frames),dx:this.x,dy:this.y,camera:this.camera,fliph:this.side,flipv:this.flipv}); + } + + return obj; + + }, + + /** + * + */ + hitByBullet:function(th,by) { + if (by.power) { + th.health-=by.power; + if (th.health<=0) th.kill(by); else th.hittimer=th.hittime; + } + }, + + /** + * + */ + generateEnemy:function(gr,id,data,model) { + help.mergeWithModel(data,model); + var obj=gbox.addObject( + help.mergeWithModel( + data,{ + id:id, + group:gr, + cnt:0, + tileset:"", + frames:{}, + acc:0, + angle:0, + camera:false, + fliph:false, + flipv:false, + accx:(data.accx==null?Math.floor(trigo.translateX(0,data.angle,data.acc)):0), + accy:(data.accy==null?Math.floor(trigo.translateY(0,data.angle,data.acc)):0), + x:data.x, + y:data.y, + // -- spec + animationset:"still", + defaultanimationset:"still", + hitanimationset:"still", + hittime:5, + script:toys.NOOP, + handler:toys.NOOP, + scriptline:(data.scriptline==null?-1:data.scriptline-1), + newline:true, + waitframes:0, + doframes:0, + mode:0, + line:{}, + dohandler:null, + ended:false, + health:1, + hittimer:0, + kill:toys.NOOP, + tolerance:0, + initialize:null, + invulnerable:false, + hitAnimation:function(time) { + this.hittimer=(time==null?this.hittime:time); + this.animationset=this.hitanimationset; + }, + goTo:function(nl) { // Jump to a line + this.waitframes=0; + this.doframes=0; + this.line={}; + this.scriptline=nl-1; + }, + hitByBullet:function(by) { + if (!this.invulnerable&&by.power) { + this.health-=by.power; + if (this.health<=0) this.kill(this,by); else this.hitAnimation(); + } + } + } + ) + ); + + + obj[(data.logicon==null?"first":data.logicon)]=function() { + if (this.initialize!=null) { + this.initialize(this); + this.initialize=null; + } + if (!this.ended) { + if (!this.waitframes&&!this.doframes&&((this.line.waitfor==null)||this.line.waitfor(this))) { + this.scriptline++; + this.everycnt=-1; + if (this.script[this.scriptline]==null) + this.ended=true; + else { + if (this.script[this.scriptline]["goto"]!=null) this.scriptline=this.script[this.scriptline]["goto"]; + this.line=this.script[this.scriptline]; + if (this.line.afterframes!=null) + this.waitframes=this.line.afterframes; + if (this.line.forframes!=null) + this.doframes=this.line.forframes; + else + this.doframes=1; + if (this.line.cleardo) + this.dohandler=null; + else if (this.line.doit!=null) { + this.dohandler={ + actiontimes:0, + timer:(this.line.doit.every=="keep"?this.dohandler.every:this.line.doit.every), + every:(this.line.doit.every=="keep"?this.dohandler.every:this.line.doit.every), + once:(this.line.doit.once=="keep"?this.dohandler.once:this.line.doit.once), + action:(this.line.doit.action=="keep"?this.dohandler.action:this.line.doit.action), + render:(this.line.doit.render=="keep"?this.dohandler.render:this.line.doit.render) + } + } + + } + } + if (!this.waitframes&&this.doframes&&!this.ended) { + this.doframes--; + if (this.line.setinvulnerable!=null) this.invulnerable=this.line.setinvulnerable; + if (this.line.setx!=null) this.x=this.line.setx; + if (this.line.sety!=null) this.y=this.line.sety; + if (this.line.addx!=null) this.x+=this.line.addx; + if (this.line.addy!=null) this.y+=this.line.addy; + if (this.line.setaccx!=null) this.accx=this.line.setaccx; + if (this.line.setaccy!=null) this.accy=this.line.setaccy; + if (this.line.setacc!=null) { + this.acc=this.line.setacc; + this.accx=Math.floor(trigo.translateX(0,this.angle,this.acc)); + this.accy=Math.floor(trigo.translateY(0,this.angle,this.acc)); + } + if (this.line.addaccx!=null) this.accx+=this.line.addaccx; + if (this.line.addaccy!=null) this.accy+=this.line.addaccy; + if (this.line.addacc!=null) { + this.acc+=this.line.addacc; + this.accx=Math.floor(trigo.translateX(0,this.angle,this.acc)); + this.accy=Math.floor(trigo.translateY(0,this.angle,this.acc)); + } + + if (this.line.setangle!=null) { + this.angle=this.line.setangle; + this.accx=Math.floor(trigo.translateX(0,this.angle,this.acc)); + this.accy=Math.floor(trigo.translateY(0,this.angle,this.acc)); + } + if (this.line.addangle!=null) { + this.angle+=this.line.addangle; + this.accx=Math.floor(trigo.translateX(0,this.angle,this.acc)); + this.accy=Math.floor(trigo.translateY(0,this.angle,this.acc)); + } + if (this.line.everyframe) this.waitframes=this.line.everyframe; + + } + if (this.waitframes>0) this.waitframes--; + } + if (this.dohandler&&(this.dohandler.action!=null)) { + if (this.dohandler.timer==this.dohandler.every) { + this.dohandler.action(this,this.dohandler.actiontimes); + this.dohandler.timer=0; + this.dohandler.actiontimes++; + } else if (!this.dohandler.once) this.dohandler.timer++; + } + if (this.handler!=null) this.handler(this); + + if (this.hittimer) { + this.hittimer--; + if (!this.hittimer) this.animationset=this.defaultanimationset; + } + + this.x+=this.accx; + this.y+=this.accy; + this.cnt=(this.cnt+1)%10; + + } + + obj[(data.bliton==null?"blit":data.bliton)]=function() { + gbox.blitTile(gbox.getBufferContext(),{tileset:this.tileset,tile:help.decideFrame(this.cnt,this.frames[this.animationset]),dx:this.x,dy:this.y,camera:this.camera,fliph:this.side,flipv:this.flipv}); + if (this.dohandler&&(this.dohandler.render!=null)) this.dohandler.render(this); + } + + return obj; + + }, + + /** + * + */ + generateScroller:function(gr,id,data) { + var obj=gbox.addObject( + help.mergeWithModel( + help.cloneObject(data),{ + id:id, group:gr, + y:0, x:0, + stage:{}, + speed:0, + stop:null, // Remember to set the last stop ever! or the last loop! + block:-1, + bly:0, + lblock:-1, + lbly:0, + lget:0, + tbly:0, + trb:0, + maxwidth:0, + loopstart:null, loopend:null, looprounds:0, + panspeed:1, panstimer:0, destspeed:0, + + setLoop:function(st,en) { + this.loopstart=st; + this.loopend=en; + this.lget=1; + this.looprounds=1; + }, + + quitLoop:function() { + this.setLoop(null,null); + this.looprounds=0; + }, + + setSpeed:function(s) { + this.speed=s; + this.destspeed=s; + }, + + panToSpeed:function(s,pans) { + this.destspeed=s; + this.panspeed=pans; + }, + + quitStop:function() { + this.stop=null; + }, + + setStop:function(s) { + this.stop=s; + }, + + setX:function(x) { + if (x<0) this.x=0; else + if (x+gbox.getScreenW()>this.maxwidth) this.x=this.maxwidth-gbox.getScreenW(); + else this.x=x; + } + + } + ) + ); + + obj[(data.logicon==null?"first":data.logicon)]=function() { + if ((this.stop==null)||(this.ythis.destspeed) this.speed--; + this.panstimer=this.panspeed; + } + } + this.y+=this.speed; + if ((this.stop!=null)&&(this.y>=this.stop)) this.y=this.stop; + if ((this.loopend!=null)&&(this.y>this.loopend)) { + this.y=this.loopstart+(this.y-this.loopend); + this.looprounds++; + if (this.lget==1) { + this.block=0; + this.bly=0; + this.lget=2; + } else { + this.block=this.lblock; + this.bly=this.lbly; + } + + } + } + + // Cerca il blocco da mostrare + this.trb=this.block; + this.tbly=this.bly; + do { + this.trb++; + this.tbly+=gbox.getImage(this.stage[this.trb].image).height; + } while (this.tblygbox.getScreenH()) done=true; + gbox.blitAll(gbox.getBufferContext(),gbox.getImage(this.stage[this.trb].image),{dx:-this.x,dy:gbox.getScreenH()-dy}); + this.trb++; + dy+=gbox.getImage(this.stage[this.trb].image).height; + } while (!done); + } + + return obj; + } + }, + + /** + * @namespace platformer The libraries for generating a 2D platformer game. + */ + platformer:{ + + /** + * + */ + initialize:function(th,data) { + help.mergeWithModel( + th, + help.mergeWithModel( + data, + { + maxaccx:5, maxaccy:10, + jumpsize:6, jumpaccy:6, + accx:0, accy:0, + x:0, y:0, + frames:{}, + camera:true, + flipv:false, + side:false + } + ) + ); + toys.platformer.spawn(th); + }, + + /** + * + */ + spawn:function(th,data) { + th.curjsize=0; // current jump size + th.counter=0; // self counter + th.touchedfloor=false; // touched floor + th.touchedceil=false; + th.touchedleftwall=false; + th.touchedrightwall=false; + th.pushing=toys.PUSH_NONE; // user is moving side + th.killed=false; + help.copyModel(th,data); + }, + + /** + * + */ + getNextX:function(th) { return th.x+th.accx; }, + + /** + * + */ + getNextY:function(th) { return th.y+help.limit(th.accy,-th.maxaccy,th.maxaccy); }, + + /** + * + */ + applyGravity:function(th) { + th.x=toys.platformer.getNextX(th); + th.y=toys.platformer.getNextY(th); + }, + + /** + * + */ + horizontalKeys:function(th,keys) { + if (gbox.keyIsPressed(keys.left)) { + th.pushing=toys.PUSH_LEFT; + th.accx=help.limit(th.accx-1,-th.maxaccx,th.maxaccx); + } else if (gbox.keyIsPressed(keys.right)) { + th.pushing=toys.PUSH_RIGHT; + th.accx=help.limit(th.accx+1,-th.maxaccx,th.maxaccx); + } else th.pushing=toys.PUSH_NONE; + }, + + /** + * + */ + verticalTileCollision:function(th,map,tilemap) { + var bottom=help.getTileInMap(th.x+(th.w/2),th.y+th.h,map,0,tilemap); + var top=help.getTileInMap(th.x+(th.w/2),th.y,map,0,tilemap); + th.touchedfloor=false; + th.touchedceil=false; + + if (map.tileIsSolidCeil(th,top)) { + th.accy=0; + th.y=help.yPixelToTile(map,th.y,1); + th.touchedceil=true; + } + if (map.tileIsSolidFloor(th,bottom)) { + th.accy=0; + th.y=help.yPixelToTile(map,th.y+th.h)-th.h; + th.touchedfloor=true; + } + }, + + /** + * + */ + horizontalTileCollision:function(th,map,tilemap,precision) { + var left=0; + var right=0; + var t=0; + + th.touchedleftwall=false; + th.touchedrightwall=false; + + while (t0)&&map.tileIsSolidFloor(th,right)) { + th.accx=0; + th.x=help.xPixelToTile(map,th.x+th.w)-th.w; + th.touchedrightwall=true; + } + t+=gbox.getTiles(map.tileset).tileh/(precision?precision:1); + } + }, + + /** + * Checks if the passed object is touching the floor and can therefore jump at present. + * @param th This is the object being checked for jump ability at the time of calling. + */ + canJump:function(th) { + return th.touchedfloor; + }, + + /** + * + */ + jumpKeys:function(th,key) { + if ((toys.platformer.canJump(th)||(key.doublejump&&(th.accy>=0)))&&gbox.keyIsHit(key.jump)&&(th.curjsize==0)) { + if (key.audiojump) gbox.hitAudio(key.audiojump); + th.accy=-th.jumpaccy; + th.curjsize=th.jumpsize; + return true; + } else if (th.curjsize&&gbox.keyIsHold(key.jump)) { // Jump modulation + th.accy--; + th.curjsize--; + } else + th.curjsize=0; + return false; + }, + + /** + * + */ + bounce:function(th,data) { + th.curjsize=0; + th.accy=-data.jumpsize; + }, + + /** + * + */ + handleAccellerations:function(th) { + // Gravity + if (!th.touchedfloor) th.accy++; + // Attrito + if (th.pushing==toys.PUSH_NONE) if (th.accx) th.accx=help.goToZero(th.accx); + }, + + /** + * + */ + setSide:function(th) { + if (th.accx) th.side=th.accx>0; + }, + + /** + * + */ + setFrame:function(th) { + if (th.touchedfloor) + if (th.pushing!=toys.PUSH_NONE) + th.frame=help.decideFrame(th.counter,th.frames.walking); + else + th.frame=help.decideFrame(th.counter,th.frames.still); + else if (th.accy>0) + th.frame=help.decideFrame(th.counter,th.frames.falling); + else + th.frame=help.decideFrame(th.counter,th.frames.jumping); + }, + + /** + * + */ + auto:{ + // Moves on a platform. It tries to do not fall down, if specified. + // Args: (object,{moveWhileFalling:,speed:}) + // Outs: the frame + goomba:function(th,data) { + if (data.moveWhileFalling||th.touchedfloor) { + if (th.side) { + th.pushing=toys.PUSH_LEFT; + th.accx=-data.speed; + } else { + th.pushing=toys.PUSH_RIGHT; + th.accx=data.speed; + } + } else th.pushing=toys.PUSH_NONE; + }, + dontFall:function(th,map,tilemap) { + if (th.accx&&th.touchedfloor) { + var til; + if (th.accx>0) til=help.getTileInMap(toys.platformer.getNextX(th)+th.w-1+th.accx,th.y+th.h,map,0,tilemap); + else til=help.getTileInMap(toys.platformer.getNextX(th),th.y+th.h,map,0,tilemap); + if (!map.tileIsSolidFloor(th,til)) { + th.side=!th.side; + th.accx=0; + } + } + }, + horizontalBounce:function(th) { + if (th.touchedleftwall||th.touchedrightwall) th.side=!th.side; + } + } + }, + + // State-based toys + // CONSTANTS + TOY_BUSY:0, + TOY_DONE:1, + TOY_IDLE:2, + + // PRIVATE + + // Generical toys method + + /** + * + */ + resetToy:function(th,id) { if (th.toys) delete th.toys[id] }, + + /** + * + */ + getToyValue:function(th,id,v,def) { return ((th.toys==null)||(th.toys[id]==null)?def:th.toys[id][v]) }, + + /** + * + */ + getToyStatus:function(th,id) { return ((th.toys==null)||(th.toys[id]==null)?toys.TOY_BUSY:th.toys[id].__status) }, + + /** + * + */ + _toydone:function(th,id) { + if (th.toys[id].__statusw) w=opt.items[i].length; + gbox.createCanvas("menu-"+id,{w:w*fd.tilew,h:opt.items.length*fd.tileh}); + for (var i=0;i0)) { + if (opt.audiooption) gbox.hitAudio(opt.audiooption); + th.toys[id].selected--; + } else + if (gbox.keyIsHit(opt.keys.down)&&(th.toys[id].selected0) + if (th.toys[id].ok<10) { + th.toys[id].ok++; + toys._toybusy(th,id); + } else return toys._toydone(th,id); // selected > 0 + else return toys._toydone(th,id); // selected == -1 + } else return toys._toybusy(th,id); + }, + + /** + * + */ + // Returns a full customizable object for optimized huds + hud:function(id) { + gbox.createCanvas(id); + return { + w:{}, + surfaceid:id, + + /** + * + */ + updateWidget:function(i){ + if (!this.w[i].__hidden) { + if (this.w[i].widget=="label") { + if (this.w[i].prepad!=null) this.w[i].text=help.prepad(this.w[i].value,this.w[i].prepad,this.w[i].padwith); else + if (this.w[i].postpad!=null) this.w[i].text=help.postpad(this.w[i].value,this.w[i].postpad,this.w[i].padwith); else + this.w[i].text=this.w[i].value+""; + gbox.blitText(gbox.getCanvasContext(this.surfaceid),this.w[i]); + } + if (this.w[i].widget=="symbols") { + var ts=gbox.getTiles(this.w[i].tileset); + gbox.blitClear(gbox.getCanvasContext(this.surfaceid),{x:this.w[i].dx,y:this.w[i].dy,w:((this.w[i].maxshown-1)*this.w[i].gapx)+ts.tilew,h:((this.w[i].maxshown-1)*this.w[i].gapy)+ts.tileh}); + var cnt=this.w[i].value; + for (var x=0;x0) { + gbox.blitTile(gbox.getCanvasContext(this.surfaceid),{tileset:this.w[i].tileset,tile:this.w[i].tiles[(cnt>this.w[i].tiles.length?this.w[i].tiles.length-1:cnt-1)],dx:this.w[i].dx+(x*this.w[i].gapx),dy:this.w[i].dy+(x*this.w[i].gapy),fliph:this.w[i].fliph,flipv:this.w[i].flipv}); + } else + if (this.w[i].emptytile!=null) + gbox.blitTile(gbox.getCanvasContext(this.surfaceid),{tileset:this.w[i].tileset,tile:this.w[i].emptytile,dx:this.w[i].dx+(x*this.w[i].gapx),dy:this.w[i].dy+(x*this.w[i].gapy),fliph:this.w[i].fliph,flipv:this.w[i].flipv}); + cnt-=this.w[i].tiles.length; + } + + } + if (this.w[i].widget=="stack") { + var ts=gbox.getTiles(this.w[i].tileset); + var bw=((this.w[i].maxshown-1)*this.w[i].gapx)+ts.tilew; + gbox.blitClear(gbox.getCanvasContext(this.surfaceid),{x:this.w[i].dx-(this.w[i].rightalign?bw:0),y:this.w[i].dy,w:bw,h:((this.w[i].maxshown-1)*this.w[i].gapy)+ts.tileh}); + for (var x=0;xthis.w[w].maxvalue)) v=this.w[w].maxvalue; + if ((this.w[w].minvalue!=null)&&(v1) th.toys[id].fade=1; + data.alpha=th.toys[id].fade; + gbox.blitFade(tox,data); + if (data.audiofade) gbox.setAudioVolume(data.audiofade,th.toys[id].stv*(1-data.alpha)); + if (data.audiochannelfade) + if (data.alpha==1) + gbox.stopChannel(data.audiochannelfade); + else + gbox.setChannelVolume(data.audiochannelfade,th.toys[id].chv*(1-data.alpha)); + return toys._toyfrombool(th,id,th.toys[id].fade==1) + }, + + /** + * + */ + fadein:function(th,id,tox,data) { + if (toys._maketoy(th,id)||data.resetfade) { + th.toys[id].fade=1; + if (data.audiofade) th.toys[id].stv=gbox.getAudioVolume(data.audiofade); + if (data.audiochannelfade) th.toys[id].chv=gbox.getChannelDefaultVolume(data.audiochannelfade); + } + th.toys[id].fade-=data.fadespeed; + if (th.toys[id].fade<0) th.toys[id].fade=0; + if (th.toys[id].fade) { + data.alpha=th.toys[id].fade; + if (data.audiofade) gbox.setAudioVolume(data.audiofade,th.toys[id].stv*(1-data.alpha)); + if (data.audiochannelfade) gbox.setChannelVolume(data.audiochannelfade,th.toys[id].chv*(1-data.alpha)); + gbox.blitFade(tox,data); + } + return toys._toyfrombool(th,id,th.toys[id].fade==0); + } + }, + + /** + * + */ + text:{ + + /** + * + */ + blink:function(th,id,tox,data) { + if (toys._maketoy(th,id)) { + th.toys[id].texttimer=0; + th.toys[id].visible=false; + th.toys[id].times=0; + } + if (th.toys[id].texttimer>=data.blinkspeed) { + th.toys[id].texttimer=0; + th.toys[id].visible=!th.toys[id].visible; + if (data.times) th.toys[id].times++; + } else th.toys[id].texttimer++; + if (th.toys[id].visible) + gbox.blitText(tox,data); + return toys._toyfrombool(th,id,(data.times?data.timesth.toys[id].lh) th.toys[id].gapx=th.toys[id].lh; + gbox.blit(gbox.getBufferContext(),gbox.getImage(data.image),{dh:th.toys[id].cnt,dw:th.toys[id].lw,dx:data.x,dy:data.y+th.toys[id].lh-th.toys[id].cnt,alpha:data.alpha}); + if (data.reflex) gbox.blit(gbox.getBufferContext(),gbox.getImage(data.image),{dh:th.toys[id].cnt,dw:th.toys[id].lw,dx:data.x,dy:data.y+th.toys[id].lh,alpha:data.reflex,flipv:true}); + if (th.toys[id].cnt>=th.toys[id].lh) + if (data.audioreach) gbox.hitAudio(data.audioreach); + return toys._toybusy(th,id); + } else { + gbox.blitAll(gbox.getBufferContext(),gbox.getImage(data.image),{dx:data.x,dy:data.y}); + if (data.reflex) gbox.blitAll(gbox.getBufferContext(),gbox.getImage(data.image),{dx:data.x,dy:data.y+th.toys[id].lh,alpha:data.reflex,flipv:true}); + + return toys._toydone(th,id); + } + }, + + /** + * + */ + bounce:function(th,id,data) { + if (toys._maketoy(th,id)) { + th.toys[id].accy=data.accy; + th.toys[id].y=data.y; + th.toys[id].h=gbox.getImage(data.image).height; + th.toys[id].done=false; + } + if (!th.toys[id].done) { + if (th.toys[id].y+th.toys[id].h>=data.floory) { + if (data.audiobounce) gbox.hitAudio(data.audiobounce); + th.toys[id].y=data.floory-th.toys[id].h; + th.toys[id].accy=-Math.ceil(th.toys[id].accy/(data.heavy?data.heavy:2)); + th.toys[id].done=(th.toys[id].accy==0); + } else th.toys[id].accy--; + th.toys[id].y-=th.toys[id].accy; + } + gbox.blitAll(gbox.getBufferContext(),gbox.getImage(data.image),{dx:data.x,dy:th.toys[id].y}); + + return toys._toyfrombool(th,id,th.toys[id].done); + } + }, + + /** + * + */ + dialogue: { + + /** + * + */ + render:function(th,id,data){ + if (toys._maketoy(th,id)) { + th.toys[id].newscene=true; + th.toys[id].sceneid=-1; + th.toys[id].ended=false; + th.toys[id].timer=0; + th.toys[id].counter=0; + th.toys[id].anim=0; + gbox.createCanvas("dialogue-"+id); + } + if (!data.hideonend||(data.hideonend&&!th.toys[id].ended)) { + if (th.toys[id].newscene&&!th.toys[id].ended) { + th.toys[id].anim=0; + th.toys[id].timer=0; + th.toys[id].newscene=false; + th.toys[id].sceneid++; + th.toys[id].ended=(th.toys[id].sceneid==data.scenes.length); + if (!th.toys[id].ended) { + th.toys[id].letter=0; + th.toys[id].wait=false; + th.toys[id].scene=data.scenes[th.toys[id].sceneid]; + th.toys[id].fd=gbox.getFont((th.toys[id].scene.font?th.toys[id].scene.font:data.font)); + th.toys[id].sceneH=(th.toys[id].scene.dh?th.toys[id].scene.dh:gbox.getScreenH()); + th.toys[id].sceneW=(th.toys[id].scene.dw?th.toys[id].scene.dw:gbox.getScreenW()); + th.toys[id].sceneX=(th.toys[id].scene.dx?th.toys[id].scene.dx:0); + th.toys[id].sceneY=(th.toys[id].scene.dy?th.toys[id].scene.dy:0); + gbox.blitClear(gbox.getCanvasContext("dialogue-"+id)); + if (th.toys[id].scene.slide) { + gbox.blitAll(gbox.getCanvasContext("dialogue-"+id),gbox.getImage(th.toys[id].scene.slide.image),{dx:th.toys[id].scene.slide.x,dy:th.toys[id].scene.slide.y}); + } + if (th.toys[id].scene.scroller) { + gbox.createCanvas("scroller-"+id,{w:th.toys[id].sceneW,h:(th.toys[id].scene.scroller.length)*(th.toys[id].fd.tileh+th.toys[id].scene.spacing)}); + for (var i=0;ith.toys[id].scene.talk[row].length) { + tmp-=th.toys[id].scene.talk[row].length; + row++; + if (row==th.toys[id].scene.talk.length) { + row=-1; + break; + } + } + if (row>=0) { + gbox.blitText(gbox.getCanvasContext("dialogue-"+id),{ + font:data.font, + dx:data.who[th.toys[id].scene.who].x, + dy:(data.who[th.toys[id].scene.who].y)+(row*th.toys[id].fd.tileh), + text:th.toys[id].scene.talk[row].substr(0,tmp) + }); + } else + th.toys[id].wait=true; + } + + } else if (th.toys[id].scene.scroller) { // SCROLLER (i.e. credits) + + if (th.toys[id].counter==th.toys[id].scene.speed) { + th.toys[id].letter++; + th.toys[id].counter=0; + if (th.toys[id].letter==(gbox.getCanvas("scroller-"+id).height+th.toys[id].scene.push)) + th.toys[id].wait=true; + } + + } else if (th.toys[id].scene.bonus) { // BONUS (classic bonus award screen) + for (var row=0;row<=th.toys[id].letter;row++) { + if (th.toys[id].scene.bonus[row].text) + gbox.blitText(gbox.getCanvasContext("bonus-"+id),{ + font:data.font, + dx:0, + dy:(row*(th.toys[id].fd.tileh+th.toys[id].scene.spacing)), + text:th.toys[id].scene.bonus[row].text + }); + else if (th.toys[id].scene.bonus[row].mul) { + // Mask is %VAL%e%MUL%=%TOT% + th.toys[id].scene.bonus[row].tmptext=th.toys[id].scene.bonus[row].mask.replace(/%VAL%/,th.toys[id].timer).replace(/%MUL%/,th.toys[id].scene.bonus[row].mul).replace(/%TOT%/,(th.toys[id].timer*th.toys[id].scene.bonus[row].mul)); + gbox.blitText(gbox.getCanvasContext("bonus-"+id),{ + clear:true, + font:data.font, + dx:0, + dy:(row*(th.toys[id].fd.tileh+th.toys[id].scene.spacing)), + text:th.toys[id].scene.bonus[row].tmptext + }); + } + } + + if (!th.toys[id].wait) { + var next=false; + if (th.toys[id].scene.bonus[th.toys[id].letter].mul&&!th.toys[id].scene.bonus[th.toys[id].letter].text) { + if (th.toys[id].counter>=th.toys[id].scene.bonus[th.toys[id].letter].speed) { + th.toys[id].counter=0; + th.toys[id].timer++; + if (th.toys[id].timer>th.toys[id].scene.bonus[th.toys[id].letter].mulvalue) { + th.toys[id].scene.bonus[th.toys[id].letter].text=th.toys[id].scene.bonus[th.toys[id].letter].tmptext; + next=true; + } else { + if (th.toys[id].scene.bonus[th.toys[id].letter].callback) + th.toys[id].scene.bonus[th.toys[id].letter].callback(th.toys[id].scene.bonus[th.toys[id].letter],th.toys[id].scene.bonus[th.toys[id].letter].arg); + } + } + + } else if (th.toys[id].counter>=th.toys[id].scene.speed) next=true; + if (next) { + if (th.toys[id].letter==th.toys[id].scene.bonus.length-1) + th.toys[id].wait=true; + else { + th.toys[id].letter++; + if (th.toys[id].scene.bonus[th.toys[id].letter].mul) { + th.toys[id].scene.bonus[th.toys[id].letter].text=null; + th.toys[id].scene.bonus[th.toys[id].letter].tmptext=null; + th.toys[id].timer=0; + } + th.toys[id].counter=0; + } + } + } + } + + } + + } + + // RENDERING + + + if (th.toys[id].scene.talk) { // DIALOGUES + if (data.who[th.toys[id].scene.who].box) + gbox.blitRect(gbox.getBufferContext(),data.who[th.toys[id].scene.who].box); + if (data.who[th.toys[id].scene.who].tileset) { + th.toys[id].anim=(th.toys[id].anim+1)%20; + gbox.blitTile(gbox.getBufferContext(),{tileset:data.who[th.toys[id].scene.who].tileset,tile:help.decideFrame(th.toys[id].anim,data.who[th.toys[id].scene.who].frames),dx:data.who[th.toys[id].scene.who].portraitx,dy:data.who[th.toys[id].scene.who].portraity,camera:false,fliph:data.who[th.toys[id].scene.who].fliph,flipv:data.who[th.toys[id].scene.who].flipv}); + } + gbox.blitAll(gbox.getBufferContext(),gbox.getCanvas("dialogue-"+id),{dx:0,dy:0}); + } else if (th.toys[id].scene.scroller) // SCROLLER (i.e. credits) + gbox.blit(gbox.getBufferContext(),gbox.getCanvas("scroller-"+id),{dx:th.toys[id].sceneX,dy:th.toys[id].sceneY+(th.toys[id].letter=0) { + this.x+=this.accx; + this.y+=this.accy; + if (this.gravity) this.accy++; + if ((this.timer==this.toptimer)||(this.trashoffscreen&&(!gbox.objectIsVisible(this)))) gbox.trashObject(this); + } + } + + obj[(data.bliton==null?"blit":data.bliton)]=function() { + if ((this.timer>=0)&&(!this.blinkspeed||(Math.floor(this.timer/this.blinkspeed)%2))) + gbox.blitTile(gbox.getBufferContext(),{tileset:this.tileset,tile:help.decideFrame(this.timer,this.frames),dx:this.x,dy:this.y,camera:this.camera,fliph:this.fliph,flipv:this.flipv,alpha:this.alpha}); + } + + return obj; + }, + + /** + * + */ + popupText:function(th,group,id,data) { + data.text+=""; + var fd=gbox.getFont(data.font); + + var obj=gbox.addObject( + help.mergeWithModel( + data,{ + id:id, + group:group, + x:Math.floor(th.x+th.hw-(fd.tilehw*data.text.length)), + y:th.y-fd.tilehh, + vaccy:-data.jump, + font:"small", + keep:0, + text:data.text+"", + cnt:0, + camera:th.camera + } + ) + ); + + obj.initialize=function() { + var fd=gbox.getFont(this.font); + gbox.createCanvas("poptext-"+this.id,{w:this.text.length*fd.tilew,h:fd.tileh}); + gbox.blitText(gbox.getCanvasContext("poptext-"+this.id),{font:this.font,text:this.text,dx:0,dy:0}); + } + + obj.onpurge=function() { + gbox.deleteCanvas("poptext-"+this.id); + } + + obj[(data.logicon==null?"first":data.logicon)]=function() { + if (gbox.objectIsVisible(this)) { + if (this.vaccy) + this.vaccy++; + else + this.cnt++; + this.y+=this.vaccy; + if (this.cnt>=this.keep) gbox.trashObject(this); + } else gbox.trashObject(this); + } + + obj[(data.bliton==null?"blit":data.bliton)]=function() { + gbox.blitAll(gbox.getBufferContext(),gbox.getCanvas("poptext-"+this.id),{dx:this.x,dy:this.y,camera:this.camera}); + } + + return obj; + }, + + /** + * + */ + bounceDie:function(th,group,id,data){ + var obj=gbox.addObject( + help.mergeWithModel( + data,{ + id:id, + group:group, + tileset:th.tileset, + frame:th.frame, + side:th.side, + frames:th.frames.die, + x:th.x, + y:th.y, + vaccy:-data.jump, + accx:0, + flipv:data.flipv, + cnt:0, + blinkspeed:0, + camera:th.camera + } + ) + ); + + obj[(data.logicon==null?"first":data.logicon)]=function() { + if (gbox.objectIsVisible(this)) { + this.vaccy++; + this.y+=this.vaccy; + this.x+=this.accx; + this.cnt++; + } else gbox.trashObject(this); + } + + obj[(data.bliton==null?"blit":data.bliton)]=function() { + if (!this.blinkspeed||(Math.floor(this.cnt/this.blinkspeed)%2)) + gbox.blitTile(gbox.getBufferContext(),{tileset:this.tileset,tile:help.decideFrame(this.cnt,this.frames),dx:this.x,dy:this.y,camera:this.camera,fliph:this.side,flipv:this.flipv}); + } + + return obj; + } + }, + + /** + * + */ + audio:{ + + /** + * + */ + fadeOut:function(th,group,id,data){ + var obj=gbox.addObject( + help.mergeWithModel( + data,{ + id:id, + group:group, + fadespeed:-0.02*(data.fadein?-1:1), + stoponmute:true, + audio:null, + channel:null, + destination:null + } + ) + ); + + obj[(data.logicon==null?"first":data.logicon)]=function() { + if (this.destination==null) + if (this.audio) + if (this.fadespeed>0) this.destination=1; else this.destination=0; + else + if (this.fadespeed>0) this.destination=gbox.getChannelDefaultVolume(this.channel); else this.destination=0; + if (this.fadespeed>0) gbox.playAudio(this.audio); + } + + obj[(data.bliton==null?"blit":data.bliton)]=function() { + if (this.audio) gbox.changeAudioVolume(this.audio,this.fadespeed); + if (this.channel) gbox.changeChannelVolume(this.channel,this.fadespeed); + if ( + (this.audio&&( + ((this.fadespeed<0)&&(gbox.getAudioVolume(this.audio)<=this.destination))|| + ((this.fadespeed>0)&&(gbox.getAudioVolume(this.audio)>=this.destination)) + ))|| + (this.channel&&( + ((this.fadespeed<0)&&(gbox.getChannelVolume(this.channel)<=this.destination))|| + ((this.fadespeed>0)&&(gbox.getChannelVolume(this.channel)>=this.destination)) + )) + ) { + if (this.channel&&this.stoponmute&&(this.fadespeed<0)) gbox.stopChannel(this.channel); + if (this.audio&&this.stoponmute&&(this.fadespeed<0)) gbox.stopAudio(this.audio); + gbox.trashObject(this); + } + } + } + + } + + } + + +} \ No newline at end of file diff --git a/public/akihabara/trigo.js b/public/akihabara/trigo.js new file mode 100644 index 0000000..de75b23 --- /dev/null +++ b/public/akihabara/trigo.js @@ -0,0 +1,76 @@ +// --- +// Copyright (c) 2010 Francesco Cottone, http://www.kesiev.com/ +// --- + +/** + * @namespace Trigo module provides some math stuff for moving objects in a + * direction or following a round path. + */ +var trigo={ + ANGLE_RIGHT:0, + ANGLE_DOWN:Math.PI*0.5, + ANGLE_LEFT:Math.PI, + ANGLE_UP:Math.PI*1.5555555, + + /** + * Adds two angles together (radians). + * @param {Float} a Base angle. + * @param {Float} add The angle you're adding to the base angle. + * @returns The resultant angle, always between 0 and 2*pi. + */ + addAngle:function(a,add) { + a=(a+add)%(Math.PI*2); + if (a<0) return (Math.PI*2)+a; else return a; + }, + /** + * Gets the distance between two points. + * @param {Object} p1 This is an object containing x and y params for the first point. + * @param {Object} p2 This is an object containing x and y params for the second point. + * @returns The distance between p1 and p2. + */ + getDistance:function(p1,p2) { + return Math.sqrt(Math.pow(p2.x-p1.x,2)+Math.pow(p2.y-p1.y,2)) + }, + + /** + * Calculates the angle between two points. + * @param {Object} p1 This is an object containing x and y params for the first point. + * @param {Object} p2 This is an object containing x and y params for the second point. + * @param {Float} transl (Optional) Adds an angle (in radians) to the result. Defaults to 0. + * @returns The angle between points p1 and p2, plus transl. + */ + getAngle:function(p1,p2,transl) { + return this.addAngle(Math.atan2(p2.y-p1.y,p2.x-p1.x),(transl?transl:0)); + }, + + /** + * Translates a point by a vector defined by angle and distance. This does not return a value but rather modifies the x and y values of p1. + * @param {Object} p1 This is an object containing x and y params for the point. + * @param {Float} a The angle of translation (rad). + * @param {Float} d The distance of translation. + */ + translate:function(p1,a,d) { + p1.x=p1.x+Math.cos(a)*d; + p1.y=p1.y+Math.sin(a)*d; + }, + + /** + * Translates an x component of a coordinate by a vector defined by angle and distance. This returns its component translation. + * @param {Float} x1 This is an x coordinate. + * @param {Float} a The angle of translation (rad). + * @param {Float} d The distance of translation. + */ + translateX:function(x1,a,d) { + return x1+Math.cos(a)*d + }, + + /** + * Translates a y component of a coordinate by a vector defined by angle and distance. This returns its component translation. + * @param {Float} y1 This is a y coordinate. + * @param {Float} a The angle of translation (rad). + * @param {Float} d The distance of translation. + */ + translateY:function(y1,a,d) { + return y1+Math.sin(a)*d; + } +} diff --git a/public/binary.js b/public/binary.js new file mode 100644 index 0000000..ed3ba69 --- /dev/null +++ b/public/binary.js @@ -0,0 +1,188 @@ +/** + * Module dependencies. + */ +var Buffer = require('buffer').Buffer; // TODO just use global Buffer +var bson = require('./bson'); + +/** + * A class representation of the BSON Binary type. + * + * Sub types + * - **BSON.BSON_BINARY_SUBTYPE_DEFAULT**, default BSON type. + * - **BSON.BSON_BINARY_SUBTYPE_FUNCTION**, BSON function type. + * - **BSON.BSON_BINARY_SUBTYPE_BYTE_ARRAY**, BSON byte array type. + * - **BSON.BSON_BINARY_SUBTYPE_UUID**, BSON uuid type. + * - **BSON.BSON_BINARY_SUBTYPE_MD5**, BSON md5 type. + * - **BSON.BSON_BINARY_SUBTYPE_USER_DEFINED**, BSON user defined type. + * + * @class Represents the Binary BSON type. + * @param {Buffer} buffer a buffer object containing the binary data. + * @param {Number} [subType] the option binary type. + * @return {Grid} + */ +function Binary(buffer, subType) { + this._bsontype = 'Binary'; + + if(buffer instanceof Number) { + this.sub_type = buffer; + this.position = 0; + } else { + this.sub_type = subType == null ? bson.BSON.BSON_BINARY_SUBTYPE_DEFAULT : subType; + this.position = 0; + } + + if(buffer != null && !(buffer instanceof Number)) { + this.buffer = typeof buffer == 'string' ? new Buffer(buffer) : buffer; + this.position = buffer.length; + } else { + this.buffer = new Buffer(Binary.BUFFER_SIZE); + this.position = 0; + } +}; + +/** + * Updates this binary with byte_value. + * + * @param {Character} byte_value a single byte we wish to write. + * @api public + */ +Binary.prototype.put = function put (byte_value) { + if(this.buffer.length > this.position) { + this.buffer[this.position++] = byte_value.charCodeAt(0); + } else { + // Create additional overflow buffer + var buffer = new Buffer(Binary.BUFFER_SIZE + this.buffer.length); + // Combine the two buffers together + this.buffer.copy(buffer, 0, 0, this.buffer.length); + this.buffer = buffer; + this.buffer[this.position++] = byte_value.charCodeAt(0); + } +}; + +/** + * Writes. + * + * @param {Buffer|String} string a string or buffer to be written to the Binary BSON object. + * @param {Number} offset specify the binary of where to write the content. + * @api public + */ +Binary.prototype.write = function write(string, offset) { + offset = offset ? offset : this.position; + + // If the buffer is to small let's extend the buffer + if (this.buffer.length < offset + string.length) { + var buffer = new Buffer(this.buffer.length + string.length); + this.buffer.copy(buffer, 0, 0, this.buffer.length); + // Assign the new buffer + this.buffer = buffer; + } + + if(Buffer.isBuffer(string)) { + string.copy(this.buffer, offset, 0, string.length); + } else { + this.buffer.write(string, 'binary', offset); + } + + this.position = offset + string.length; +}; + +/** + * Reads **length** bytes starting at **position**. + * + * @param {Number} position read from the given position in the Binary. + * @param {Number} length the number of bytes to read. + * @return {Buffer} + * @api public + */ +Binary.prototype.read = function read(position, length) { + length = length && length > 0 + ? length + : this.position; + + // Return the buffer + return this.buffer.slice(position, position + length); +}; + +/** + * Returns the value of this binary as a string. + * + * @return {String} + * @api public + */ +Binary.prototype.value = function value(asRaw) { + asRaw = asRaw == null ? false : asRaw; + return asRaw ? this.buffer.slice(0, this.position) : this.buffer.toString('binary', 0, this.position); +}; + +/** + * Length. + * + * @return {Number} the length of the binary. + * @api public + */ +Binary.prototype.length = function length() { + return this.position; +}; + +/** + * @ignore + * @api private + */ +Binary.prototype.toJSON = function() { + return this.buffer != null ? this.buffer.toString('base64') : ''; +} + +/** + * @ignore + * @api private + */ +Binary.prototype.toString = function(format) { + return this.buffer != null ? this.buffer.slice(0, this.position).toString(format) : ''; +} + +Binary.BUFFER_SIZE = 256; + +/** + * Default BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_DEFAULT = 0; +/** + * Function BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_FUNCTION = 1; +/** + * Byte Array BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_BYTE_ARRAY = 2; +/** + * UUID BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_UUID = 3; +/** + * MD5 BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_MD5 = 4; +/** + * User BSON type + * + * @classconstant SUBTYPE_DEFAULT + **/ +Binary.SUBTYPE_USER_DEFINED = 128; + +/** + * Expose. + */ +if(typeof window === 'undefined') { + exports.Binary = Binary; +} + diff --git a/public/binary_parser.js b/public/binary_parser.js new file mode 100644 index 0000000..f752fee --- /dev/null +++ b/public/binary_parser.js @@ -0,0 +1,386 @@ +/** + * Binary Parser. + * Jonas Raoni Soares Silva + * http://jsfromhell.com/classes/binary-parser [v1.0] + */ +var chr = String.fromCharCode; + +var maxBits = []; +for (var i = 0; i < 64; i++) { + maxBits[i] = Math.pow(2, i); +} + +function BinaryParser (bigEndian, allowExceptions) { + this.bigEndian = bigEndian; + this.allowExceptions = allowExceptions; +}; + +BinaryParser.warn = function warn (msg) { + if (this.allowExceptions) { + throw new Error(msg); + } + + return 1; +}; + +BinaryParser.decodeFloat = function decodeFloat (data, precisionBits, exponentBits) { + var b = new this.Buffer(this.bigEndian, data); + + b.checkBuffer(precisionBits + exponentBits + 1); + + var bias = maxBits[exponentBits - 1] - 1 + , signal = b.readBits(precisionBits + exponentBits, 1) + , exponent = b.readBits(precisionBits, exponentBits) + , significand = 0 + , divisor = 2 + , curByte = b.buffer.length + (-precisionBits >> 3) - 1; + + do { + for (var byteValue = b.buffer[ ++curByte ], startBit = precisionBits % 8 || 8, mask = 1 << startBit; mask >>= 1; ( byteValue & mask ) && ( significand += 1 / divisor ), divisor *= 2 ); + } while (precisionBits -= startBit); + + return exponent == ( bias << 1 ) + 1 ? significand ? NaN : signal ? -Infinity : +Infinity : ( 1 + signal * -2 ) * ( exponent || significand ? !exponent ? Math.pow( 2, -bias + 1 ) * significand : Math.pow( 2, exponent - bias ) * ( 1 + significand ) : 0 ); +}; + +BinaryParser.decodeInt = function decodeInt (data, bits, signed, forceBigEndian) { + var b = new this.Buffer(this.bigEndian || forceBigEndian, data) + , x = b.readBits(0, bits) + , max = maxBits[bits]; //max = Math.pow( 2, bits ); + + return signed && x >= max / 2 + ? x - max + : x; +}; + +BinaryParser.encodeFloat = function encodeFloat (data, precisionBits, exponentBits) { + var bias = maxBits[exponentBits - 1] - 1 + , minExp = -bias + 1 + , maxExp = bias + , minUnnormExp = minExp - precisionBits + , n = parseFloat(data) + , status = isNaN(n) || n == -Infinity || n == +Infinity ? n : 0 + , exp = 0 + , len = 2 * bias + 1 + precisionBits + 3 + , bin = new Array(len) + , signal = (n = status !== 0 ? 0 : n) < 0 + , intPart = Math.floor(n = Math.abs(n)) + , floatPart = n - intPart + , lastBit + , rounded + , result + , i + , j; + + for (i = len; i; bin[--i] = 0); + + for (i = bias + 2; intPart && i; bin[--i] = intPart % 2, intPart = Math.floor(intPart / 2)); + + for (i = bias + 1; floatPart > 0 && i; (bin[++i] = ((floatPart *= 2) >= 1) - 0 ) && --floatPart); + + for (i = -1; ++i < len && !bin[i];); + + if (bin[(lastBit = precisionBits - 1 + (i = (exp = bias + 1 - i) >= minExp && exp <= maxExp ? i + 1 : bias + 1 - (exp = minExp - 1))) + 1]) { + if (!(rounded = bin[lastBit])) { + for (j = lastBit + 2; !rounded && j < len; rounded = bin[j++]); + } + + for (j = lastBit + 1; rounded && --j >= 0; (bin[j] = !bin[j] - 0) && (rounded = 0)); + } + + for (i = i - 2 < 0 ? -1 : i - 3; ++i < len && !bin[i];); + + if ((exp = bias + 1 - i) >= minExp && exp <= maxExp) { + ++i; + } else if (exp < minExp) { + exp != bias + 1 - len && exp < minUnnormExp && this.warn("encodeFloat::float underflow"); + i = bias + 1 - (exp = minExp - 1); + } + + if (intPart || status !== 0) { + this.warn(intPart ? "encodeFloat::float overflow" : "encodeFloat::" + status); + exp = maxExp + 1; + i = bias + 2; + + if (status == -Infinity) { + signal = 1; + } else if (isNaN(status)) { + bin[i] = 1; + } + } + + for (n = Math.abs(exp + bias), j = exponentBits + 1, result = ""; --j; result = (n % 2) + result, n = n >>= 1); + + for (n = 0, j = 0, i = (result = (signal ? "1" : "0") + result + bin.slice(i, i + precisionBits).join("")).length, r = []; i; j = (j + 1) % 8) { + n += (1 << j) * result.charAt(--i); + if (j == 7) { + r[r.length] = String.fromCharCode(n); + n = 0; + } + } + + r[r.length] = n + ? String.fromCharCode(n) + : ""; + + return (this.bigEndian ? r.reverse() : r).join(""); +}; + +BinaryParser.encodeInt = function encodeInt (data, bits, signed, forceBigEndian) { + var max = maxBits[bits]; + + if (data >= max || data < -(max / 2)) { + this.warn("encodeInt::overflow"); + data = 0; + } + + if (data < 0) { + data += max; + } + + for (var r = []; data; r[r.length] = String.fromCharCode(data % 256), data = Math.floor(data / 256)); + + for (bits = -(-bits >> 3) - r.length; bits--; r[r.length] = "\0"); + + return ((this.bigEndian || forceBigEndian) ? r.reverse() : r).join(""); +}; + +BinaryParser.toSmall = function( data ){ return this.decodeInt( data, 8, true ); }; +BinaryParser.fromSmall = function( data ){ return this.encodeInt( data, 8, true ); }; +BinaryParser.toByte = function( data ){ return this.decodeInt( data, 8, false ); }; +BinaryParser.fromByte = function( data ){ return this.encodeInt( data, 8, false ); }; +BinaryParser.toShort = function( data ){ return this.decodeInt( data, 16, true ); }; +BinaryParser.fromShort = function( data ){ return this.encodeInt( data, 16, true ); }; +BinaryParser.toWord = function( data ){ return this.decodeInt( data, 16, false ); }; +BinaryParser.fromWord = function( data ){ return this.encodeInt( data, 16, false ); }; +BinaryParser.toInt = function( data ){ return this.decodeInt( data, 32, true ); }; +BinaryParser.fromInt = function( data ){ return this.encodeInt( data, 32, true ); }; +BinaryParser.toLong = function( data ){ return this.decodeInt( data, 64, true ); }; +BinaryParser.fromLong = function( data ){ return this.encodeInt( data, 64, true ); }; +BinaryParser.toDWord = function( data ){ return this.decodeInt( data, 32, false ); }; +BinaryParser.fromDWord = function( data ){ return this.encodeInt( data, 32, false ); }; +BinaryParser.toQWord = function( data ){ return this.decodeInt( data, 64, true ); }; +BinaryParser.fromQWord = function( data ){ return this.encodeInt( data, 64, true ); }; +BinaryParser.toFloat = function( data ){ return this.decodeFloat( data, 23, 8 ); }; +BinaryParser.fromFloat = function( data ){ return this.encodeFloat( data, 23, 8 ); }; +BinaryParser.toDouble = function( data ){ return this.decodeFloat( data, 52, 11 ); }; +BinaryParser.fromDouble = function( data ){ return this.encodeFloat( data, 52, 11 ); }; + +// Factor out the encode so it can be shared by add_header and push_int32 +BinaryParser.encode_int32 = function encode_int32 (number, asArray) { + var a, b, c, d, unsigned; + unsigned = (number < 0) ? (number + 0x100000000) : number; + a = Math.floor(unsigned / 0xffffff); + unsigned &= 0xffffff; + b = Math.floor(unsigned / 0xffff); + unsigned &= 0xffff; + c = Math.floor(unsigned / 0xff); + unsigned &= 0xff; + d = Math.floor(unsigned); + return asArray ? [chr(a), chr(b), chr(c), chr(d)] : chr(a) + chr(b) + chr(c) + chr(d); +}; + +BinaryParser.encode_int64 = function encode_int64 (number) { + var a, b, c, d, e, f, g, h, unsigned; + unsigned = (number < 0) ? (number + 0x10000000000000000) : number; + a = Math.floor(unsigned / 0xffffffffffffff); + unsigned &= 0xffffffffffffff; + b = Math.floor(unsigned / 0xffffffffffff); + unsigned &= 0xffffffffffff; + c = Math.floor(unsigned / 0xffffffffff); + unsigned &= 0xffffffffff; + d = Math.floor(unsigned / 0xffffffff); + unsigned &= 0xffffffff; + e = Math.floor(unsigned / 0xffffff); + unsigned &= 0xffffff; + f = Math.floor(unsigned / 0xffff); + unsigned &= 0xffff; + g = Math.floor(unsigned / 0xff); + unsigned &= 0xff; + h = Math.floor(unsigned); + return chr(a) + chr(b) + chr(c) + chr(d) + chr(e) + chr(f) + chr(g) + chr(h); +}; + +/** + * UTF8 methods + */ + +// Take a raw binary string and return a utf8 string +BinaryParser.decode_utf8 = function decode_utf8 (binaryStr) { + var len = binaryStr.length + , decoded = '' + , i = 0 + , c = 0 + , c1 = 0 + , c2 = 0 + , c3; + + while (i < len) { + c = binaryStr.charCodeAt(i); + if (c < 128) { + decoded += String.fromCharCode(c); + i++; + } else if ((c > 191) && (c < 224)) { + c2 = binaryStr.charCodeAt(i+1); + decoded += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); + i += 2; + } else { + c2 = binaryStr.charCodeAt(i+1); + c3 = binaryStr.charCodeAt(i+2); + decoded += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); + i += 3; + } + } + + return decoded; +}; + +// Encode a cstring +BinaryParser.encode_cstring = function encode_cstring (s) { + return unescape(encodeURIComponent(s)) + BinaryParser.fromByte(0); +}; + +// Take a utf8 string and return a binary string +BinaryParser.encode_utf8 = function encode_utf8 (s) { + var a = "" + , c; + + for (var n = 0, len = s.length; n < len; n++) { + c = s.charCodeAt(n); + + if (c < 128) { + a += String.fromCharCode(c); + } else if ((c > 127) && (c < 2048)) { + a += String.fromCharCode((c>>6) | 192) ; + a += String.fromCharCode((c&63) | 128); + } else { + a += String.fromCharCode((c>>12) | 224); + a += String.fromCharCode(((c>>6) & 63) | 128); + a += String.fromCharCode((c&63) | 128); + } + } + + return a; +}; + +BinaryParser.hprint = function hprint (s) { + var number; + + for (var i = 0, len = s.length; i < len; i++) { + if (s.charCodeAt(i) < 32) { + number = s.charCodeAt(i) <= 15 + ? "0" + s.charCodeAt(i).toString(16) + : s.charCodeAt(i).toString(16); + process.stdout.write(number + " ") + } else { + number = s.charCodeAt(i) <= 15 + ? "0" + s.charCodeAt(i).toString(16) + : s.charCodeAt(i).toString(16); + process.stdout.write(number + " ") + } + } + + process.stdout.write("\n\n"); +}; + +BinaryParser.ilprint = function hprint (s) { + var number; + + for (var i = 0, len = s.length; i < len; i++) { + if (s.charCodeAt(i) < 32) { + number = s.charCodeAt(i) <= 15 + ? "0" + s.charCodeAt(i).toString(10) + : s.charCodeAt(i).toString(10); + + require('util').debug(number+' : '); + } else { + number = s.charCodeAt(i) <= 15 + ? "0" + s.charCodeAt(i).toString(10) + : s.charCodeAt(i).toString(10); + require('util').debug(number+' : '+ s.charAt(i)); + } + } +}; + +BinaryParser.hlprint = function hprint (s) { + var number; + + for (var i = 0, len = s.length; i < len; i++) { + if (s.charCodeAt(i) < 32) { + number = s.charCodeAt(i) <= 15 + ? "0" + s.charCodeAt(i).toString(16) + : s.charCodeAt(i).toString(16); + require('util').debug(number+' : '); + } else { + number = s.charCodeAt(i) <= 15 + ? "0" + s.charCodeAt(i).toString(16) + : s.charCodeAt(i).toString(16); + require('util').debug(number+' : '+ s.charAt(i)); + } + } +}; + +/** + * BinaryParser buffer constructor. + */ + +function BinaryParserBuffer (bigEndian, buffer) { + this.bigEndian = bigEndian || 0; + this.buffer = []; + this.setBuffer(buffer); +}; + +BinaryParserBuffer.prototype.setBuffer = function setBuffer (data) { + var l, i, b; + + if (data) { + i = l = data.length; + b = this.buffer = new Array(l); + for (; i; b[l - i] = data.charCodeAt(--i)); + this.bigEndian && b.reverse(); + } +}; + +BinaryParserBuffer.prototype.hasNeededBits = function hasNeededBits (neededBits) { + return this.buffer.length >= -(-neededBits >> 3); +}; + +BinaryParserBuffer.prototype.checkBuffer = function checkBuffer (neededBits) { + if (!this.hasNeededBits(neededBits)) { + throw new Error("checkBuffer::missing bytes"); + } +}; + +BinaryParserBuffer.prototype.readBits = function readBits (start, length) { + //shl fix: Henri Torgemane ~1996 (compressed by Jonas Raoni) + + function shl (a, b) { + for (; b--; a = ((a %= 0x7fffffff + 1) & 0x40000000) == 0x40000000 ? a * 2 : (a - 0x40000000) * 2 + 0x7fffffff + 1); + return a; + } + + if (start < 0 || length <= 0) { + return 0; + } + + this.checkBuffer(start + length); + + var offsetLeft + , offsetRight = start % 8 + , curByte = this.buffer.length - ( start >> 3 ) - 1 + , lastByte = this.buffer.length + ( -( start + length ) >> 3 ) + , diff = curByte - lastByte + , sum = ((this.buffer[ curByte ] >> offsetRight) & ((1 << (diff ? 8 - offsetRight : length)) - 1)) + (diff && (offsetLeft = (start + length) % 8) ? (this.buffer[lastByte++] & ((1 << offsetLeft) - 1)) << (diff-- << 3) - offsetRight : 0); + + for(; diff; sum += shl(this.buffer[lastByte++], (diff-- << 3) - offsetRight)); + + return sum; +}; + +/** + * Expose. + */ +BinaryParser.Buffer = BinaryParserBuffer; + +if(typeof window === 'undefined') { + exports.BinaryParser = BinaryParser; +} diff --git a/public/bson.js b/public/bson.js new file mode 100644 index 0000000..694809d --- /dev/null +++ b/public/bson.js @@ -0,0 +1,1360 @@ +if(typeof window === 'undefined') { + var Long = require('./long').Long + , Double = require('./double').Double + , Timestamp = require('./timestamp').Timestamp + , ObjectID = require('./objectid').ObjectID + , Symbol = require('./symbol').Symbol + , Code = require('./code').Code + , MinKey = require('./min_key').MinKey + , MaxKey = require('./max_key').MaxKey + , DBRef = require('./db_ref').DBRef + , Binary = require('./binary').Binary + , ieee754 = require('./float_parser'); +} else { + // Let's create our own Buffer class + Buffer = Array; + // Add missing methods + Buffer.byteLength = function(string, encoding) { + return string.length; + } + + Buffer.prototype.write = function(data, index, encoding) { + index = index == null || isNaN(index) ? 0 : index; + + for(var i = 0; i < data.length; i++) { + this[index + i] = data[i].charCodeAt(0); + } + + // return the number of bytes written + return data.length; + } + + Buffer.prototype.asArrayBuffer = function() { + return new Uint8Array(this).buffer; + } +} + +/** + * Create a new BSON instance + * + * @class Represents the BSON Parser + * @return {BSON} instance of BSON Parser. + */ +function BSON () {}; + +/** + * @ignore + * @api private + */ +// BSON MAX VALUES +BSON.BSON_INT32_MAX = 0x7FFFFFFF; +BSON.BSON_INT32_MIN = -0x80000000; + +BSON.BSON_INT64_MAX = Math.pow(2, 63) - 1; +BSON.BSON_INT64_MIN = -Math.pow(2, 63); + +// JS MAX PRECISE VALUES +BSON.JS_INT_MAX = 0x20000000000000; // Any integer up to 2^53 can be precisely represented by a double. +BSON.JS_INT_MIN = -0x20000000000000; // Any integer down to -2^53 can be precisely represented by a double. + +// Internal long versions +var JS_INT_MAX_LONG = Long.fromNumber(0x20000000000000); // Any integer up to 2^53 can be precisely represented by a double. +var JS_INT_MIN_LONG = Long.fromNumber(-0x20000000000000); // Any integer down to -2^53 can be precisely represented by a double. + +/** + * Number BSON Type + * + * @classconstant BSON_DATA_NUMBER + **/ +BSON.BSON_DATA_NUMBER = 1; +/** + * String BSON Type + * + * @classconstant BSON_DATA_STRING + **/ +BSON.BSON_DATA_STRING = 2; +/** + * Object BSON Type + * + * @classconstant BSON_DATA_OBJECT + **/ +BSON.BSON_DATA_OBJECT = 3; +/** + * Array BSON Type + * + * @classconstant BSON_DATA_ARRAY + **/ +BSON.BSON_DATA_ARRAY = 4; +/** + * Binary BSON Type + * + * @classconstant BSON_DATA_BINARY + **/ +BSON.BSON_DATA_BINARY = 5; +/** + * ObjectID BSON Type + * + * @classconstant BSON_DATA_OID + **/ +BSON.BSON_DATA_OID = 7; +/** + * Boolean BSON Type + * + * @classconstant BSON_DATA_BOOLEAN + **/ +BSON.BSON_DATA_BOOLEAN = 8; +/** + * Date BSON Type + * + * @classconstant BSON_DATA_DATE + **/ +BSON.BSON_DATA_DATE = 9; +/** + * null BSON Type + * + * @classconstant BSON_DATA_NULL + **/ +BSON.BSON_DATA_NULL = 10; +/** + * RegExp BSON Type + * + * @classconstant BSON_DATA_REGEXP + **/ +BSON.BSON_DATA_REGEXP = 11; +/** + * Code BSON Type + * + * @classconstant BSON_DATA_CODE + **/ +BSON.BSON_DATA_CODE = 13; +/** + * Symbol BSON Type + * + * @classconstant BSON_DATA_SYMBOL + **/ +BSON.BSON_DATA_SYMBOL = 14; +/** + * Code with Scope BSON Type + * + * @classconstant BSON_DATA_CODE_W_SCOPE + **/ +BSON.BSON_DATA_CODE_W_SCOPE = 15; +/** + * 32 bit Integer BSON Type + * + * @classconstant BSON_DATA_INT + **/ +BSON.BSON_DATA_INT = 16; +/** + * Timestamp BSON Type + * + * @classconstant BSON_DATA_TIMESTAMP + **/ +BSON.BSON_DATA_TIMESTAMP = 17; +/** + * Long BSON Type + * + * @classconstant BSON_DATA_LONG + **/ +BSON.BSON_DATA_LONG = 18; +/** + * MinKey BSON Type + * + * @classconstant BSON_DATA_MIN_KEY + **/ +BSON.BSON_DATA_MIN_KEY = 0xff; +/** + * MaxKey BSON Type + * + * @classconstant BSON_DATA_MAX_KEY + **/ +BSON.BSON_DATA_MAX_KEY = 0x7f; + +/** + * Binary Default Type + * + * @classconstant BSON_BINARY_SUBTYPE_DEFAULT + **/ +BSON.BSON_BINARY_SUBTYPE_DEFAULT = 0; +/** + * Binary Function Type + * + * @classconstant BSON_BINARY_SUBTYPE_FUNCTION + **/ +BSON.BSON_BINARY_SUBTYPE_FUNCTION = 1; +/** + * Binary Byte Array Type + * + * @classconstant BSON_BINARY_SUBTYPE_BYTE_ARRAY + **/ +BSON.BSON_BINARY_SUBTYPE_BYTE_ARRAY = 2; +/** + * Binary UUID Type + * + * @classconstant BSON_BINARY_SUBTYPE_UUID + **/ +BSON.BSON_BINARY_SUBTYPE_UUID = 3; +/** + * Binary MD5 Type + * + * @classconstant BSON_BINARY_SUBTYPE_MD5 + **/ +BSON.BSON_BINARY_SUBTYPE_MD5 = 4; +/** + * Binary User Defined Type + * + * @classconstant BSON_BINARY_SUBTYPE_USER_DEFINED + **/ +BSON.BSON_BINARY_SUBTYPE_USER_DEFINED = 128; + +/** + * Calculate the bson size for a passed in Javascript object. + * + * @param {Object} object the Javascript object to calculate the BSON byte size for. + * @param {Boolean} [serializeFunctions] serialize all functions in the object **(default:false)**. + * @return {Number} returns the number of bytes the BSON object will take up. + * @api public + */ +BSON.calculateObjectSize = function calculateObjectSize(object, serializeFunctions) { + var totalLength = (4 + 1); + + if(Array.isArray(object)) { + for(var i = 0; i < object.length; i++) { + totalLength += calculateElement(i.toString(), object[i], serializeFunctions) + } + } else { + for(var key in object) { + totalLength += calculateElement(key, object[key], serializeFunctions) + } + } + + return totalLength; +} + +/** + * @ignore + * @api private + */ +function calculateElement(name, value, serializeFunctions) { + switch(typeof value) { + case 'string': + return 1 + Buffer.byteLength(name, 'utf8') + 1 + 4 + Buffer.byteLength(value, 'utf8') + 1; + case 'number': + if(Math.floor(value) === value && value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) { + if(value >= BSON.BSON_INT32_MIN && value <= BSON.BSON_INT32_MAX) { // 32 bit + return (name != null ? (Buffer.byteLength(name) + 1) : 0) + (4 + 1); + } else { + return (name != null ? (Buffer.byteLength(name) + 1) : 0) + (8 + 1); + } + } else { // 64 bit + return (name != null ? (Buffer.byteLength(name) + 1) : 0) + (8 + 1); + } + case 'undefined': + return (name != null ? (Buffer.byteLength(name) + 1) : 0) + (1); + case 'boolean': + return (name != null ? (Buffer.byteLength(name) + 1) : 0) + (1 + 1); + case 'object': + if(value == null || value instanceof MinKey || value instanceof MaxKey || value['_bsontype'] == 'MinKey' || value['_bsontype'] == 'MaxKey') { + return (name != null ? (Buffer.byteLength(name) + 1) : 0) + (1); + } else if(value instanceof ObjectID || value['_bsontype'] == 'ObjectID') { + return (name != null ? (Buffer.byteLength(name) + 1) : 0) + (12 + 1); + } else if(value instanceof Date) { + return (name != null ? (Buffer.byteLength(name) + 1) : 0) + (8 + 1); + } else if(Buffer.isBuffer(value)) { + return (name != null ? (Buffer.byteLength(name) + 1) : 0) + (1 + 4 + 1) + value.length; + } else if(value instanceof Long || value instanceof Double || value instanceof Timestamp + || value['_bsontype'] == 'Long' || value['_bsontype'] == 'Double' || value['_bsontype'] == 'Timestamp') { + return (name != null ? (Buffer.byteLength(name) + 1) : 0) + (8 + 1); + } else if(value instanceof Code || value['_bsontype'] == 'Code') { + // Calculate size depending on the availability of a scope + if(value.scope != null && Object.keys(value.scope).length > 0) { + return (name != null ? (Buffer.byteLength(name) + 1) : 0) + 1 + 4 + 4 + Buffer.byteLength(value.code.toString(), 'utf8') + 1 + BSON.calculateObjectSize(value.scope); + } else { + return (name != null ? (Buffer.byteLength(name) + 1) : 0) + 1 + 4 + Buffer.byteLength(value.code.toString(), 'utf8') + 1; + } + } else if(value instanceof Binary || value['_bsontype'] == 'Binary') { + return (name != null ? (Buffer.byteLength(name) + 1) : 0) + (value.position + 1 + 4 + 1); + } else if(value instanceof Symbol || value['_bsontype'] == 'Symbol') { + return (name != null ? (Buffer.byteLength(name) + 1) : 0) + (Buffer.byteLength(value.value, 'utf8') + 4 + 1 + 1); + } else if(value instanceof DBRef || value['_bsontype'] == 'DBRef') { + // Set up correct object for serialization + var ordered_values = { + '$ref': value.namespace + , '$id' : value.oid + }; + + // Add db reference if it exists + if(null != value.db) { + ordered_values['$db'] = value.db; + } + + return (name != null ? (Buffer.byteLength(name) + 1) : 0) + 1 + BSON.calculateObjectSize(ordered_values, serializeFunctions); + } else if(value instanceof RegExp || toString.call(value) === '[object RegExp]') { + return (name != null ? (Buffer.byteLength(name) + 1) : 0) + 1 + Buffer.byteLength(value.source, 'utf8') + 1 + + (value.global ? 1 : 0) + (value.ignoreCase ? 1 : 0) + (value.multiline ? 1 : 0) + 1 + } else { + return (name != null ? (Buffer.byteLength(name) + 1) : 0) + BSON.calculateObjectSize(value, serializeFunctions) + 1; + } + case 'function': + // WTF for 0.4.X where typeof /someregexp/ === 'function' + if(value instanceof RegExp || toString.call(value) === '[object RegExp]') { + return (name != null ? (Buffer.byteLength(name) + 1) : 0) + 1 + Buffer.byteLength(value.source, 'utf8') + 1 + + (value.global ? 1 : 0) + (value.ignoreCase ? 1 : 0) + (value.multiline ? 1 : 0) + 1 + } else { + if(serializeFunctions && value.scope != null && Object.keys(value.scope).length > 0) { + return (name != null ? (Buffer.byteLength(name) + 1) : 0) + 1 + 4 + 4 + Buffer.byteLength(value.toString(), 'utf8') + 1 + BSON.calculateObjectSize(value.scope); + } else if(serializeFunctions) { + return (name != null ? (Buffer.byteLength(name) + 1) : 0) + 1 + 4 + Buffer.byteLength(value.toString(), 'utf8') + 1; + } + } + } + + return 0; +} + +/** + * Serialize a Javascript object using a predefined Buffer and index into the buffer, useful when pre-allocating the space for serialization. + * + * @param {Object} object the Javascript object to serialize. + * @param {Boolean} checkKeys the serializer will check if keys are valid. + * @param {Buffer} buffer the Buffer you pre-allocated to store the serialized BSON object. + * @param {Number} index the index in the buffer where we wish to start serializing into. + * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**. + * @return {Number} returns the new write index in the Buffer. + * @api public + */ +BSON.serializeWithBufferAndIndex = function serializeWithBufferAndIndex(object, checkKeys, buffer, index, serializeFunctions) { + // Default setting false + serializeFunctions = serializeFunctions == null ? false : serializeFunctions; + // Write end information (length of the object) + var size = buffer.length; + // Write the size of the object + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + return serializeObject(object, checkKeys, buffer, index, serializeFunctions) - 1; +} + +/** + * @ignore + * @api private + */ +var serializeObject = function(object, checkKeys, buffer, index, serializeFunctions) { + // Process the object + if(Array.isArray(object)) { + for(var i = 0; i < object.length; i++) { + index = packElement(i.toString(), object[i], checkKeys, buffer, index, serializeFunctions); + } + } else { + for(var key in object) { + // Check the key and throw error if it's illegal + if(checkKeys == true && (key != '$db' && key != '$ref' && key != '$id')) { + BSON.checkKey(key); + } + + // Pack the element + index = packElement(key, object[key], checkKeys, buffer, index, serializeFunctions); + } + } + + // Write zero + buffer[index++] = 0; + return index; +} + +/** + * @ignore + * @api private + */ +var packElement = function(name, value, checkKeys, buffer, index, serializeFunctions) { + // console.log("packElement: " + name + " :: " + value) + var startIndex = index; + + switch(typeof value) { + case 'string': + // Encode String type + buffer[index++] = BSON.BSON_DATA_STRING; + // Encode the name + index = index + buffer.write(name, index, 'utf8') + 1; + buffer[index - 1] = 0; + + // Calculate size + var size = Buffer.byteLength(value) + 1; + // Write the size of the string to buffer + buffer[index + 3] = (size >> 24) & 0xff; + buffer[index + 2] = (size >> 16) & 0xff; + buffer[index + 1] = (size >> 8) & 0xff; + buffer[index] = size & 0xff; + // Ajust the index + index = index + 4; + // Write the string + buffer.write(value, index, 'utf8'); + // Update index + index = index + size - 1; + // Write zero + buffer[index++] = 0; + // Return index + return index; + case 'number': + // We have an integer value + if(Math.floor(value) === value && value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) { + // If the value fits in 32 bits encode as int, if it fits in a double + // encode it as a double, otherwise long + if(value >= BSON.BSON_INT32_MIN && value <= BSON.BSON_INT32_MAX) { + // Set int type 32 bits or less + buffer[index++] = BSON.BSON_DATA_INT; + // Encode the name + index = index + buffer.write(name, index, 'utf8') + 1; + buffer[index - 1] = 0; + // Write the int value + buffer[index++] = value & 0xff; + buffer[index++] = (value >> 8) & 0xff; + buffer[index++] = (value >> 16) & 0xff; + buffer[index++] = (value >> 24) & 0xff; + } else if(value >= BSON.JS_INT_MIN && value <= BSON.JS_INT_MAX) { + // Encode as double + buffer[index++] = BSON.BSON_DATA_NUMBER; + // Encode the name + index = index + buffer.write(name, index, 'utf8') + 1; + buffer[index - 1] = 0; + // Write float + ieee754.writeIEEE754(buffer, value, index, 'little', 52, 8); + // Ajust index + index = index + 8; + } else { + // Set long type + buffer[index++] = BSON.BSON_DATA_LONG; + // Encode the name + index = index + buffer.write(name, index, 'utf8') + 1; + buffer[index - 1] = 0; + var longVal = Long.fromNumber(value); + var lowBits = longVal.getLowBits(); + var highBits = longVal.getHighBits(); + // Encode low bits + buffer[index++] = lowBits & 0xff; + buffer[index++] = (lowBits >> 8) & 0xff; + buffer[index++] = (lowBits >> 16) & 0xff; + buffer[index++] = (lowBits >> 24) & 0xff; + // Encode high bits + buffer[index++] = highBits & 0xff; + buffer[index++] = (highBits >> 8) & 0xff; + buffer[index++] = (highBits >> 16) & 0xff; + buffer[index++] = (highBits >> 24) & 0xff; + } + } else { + // Encode as double + buffer[index++] = BSON.BSON_DATA_NUMBER; + // Encode the name + index = index + buffer.write(name, index, 'utf8') + 1; + buffer[index - 1] = 0; + // Write float + ieee754.writeIEEE754(buffer, value, index, 'little', 52, 8); + // Ajust index + index = index + 8; + } + + return index; + case 'undefined': + // Set long type + buffer[index++] = BSON.BSON_DATA_NULL; + // Encode the name + index = index + buffer.write(name, index, 'utf8') + 1; + buffer[index - 1] = 0; + return index; + case 'boolean': + // Write the type + buffer[index++] = BSON.BSON_DATA_BOOLEAN; + // Encode the name + index = index + buffer.write(name, index, 'utf8') + 1; + buffer[index - 1] = 0; + // Encode the boolean value + buffer[index++] = value ? 1 : 0; + return index; + case 'object': + if(value === null || value instanceof MinKey || value instanceof MaxKey + || value['_bsontype'] == 'MinKey' || value['_bsontype'] == 'MaxKey') { + // Write the type of either min or max key + if(value === null) { + buffer[index++] = BSON.BSON_DATA_NULL; + } else if(value instanceof MinKey) { + buffer[index++] = BSON.BSON_DATA_MIN_KEY; + } else { + buffer[index++] = BSON.BSON_DATA_MAX_KEY; + } + + // Encode the name + index = index + buffer.write(name, index, 'utf8') + 1; + buffer[index - 1] = 0; + return index; + } else if(value instanceof ObjectID || value['_bsontype'] == 'ObjectID') { + // Write the type + buffer[index++] = BSON.BSON_DATA_OID; + // Encode the name + index = index + buffer.write(name, index, 'utf8') + 1; + buffer[index - 1] = 0; + // Write objectid + buffer.write(value.id, index, 'binary'); + // Ajust index + index = index + 12; + return index; + } else if(value instanceof Date) { + // Write the type + buffer[index++] = BSON.BSON_DATA_DATE; + // Encode the name + index = index + buffer.write(name, index, 'utf8') + 1; + buffer[index - 1] = 0; + + // Write the date + var dateInMilis = Long.fromNumber(value.getTime()); + var lowBits = dateInMilis.getLowBits(); + var highBits = dateInMilis.getHighBits(); + // Encode low bits + buffer[index++] = lowBits & 0xff; + buffer[index++] = (lowBits >> 8) & 0xff; + buffer[index++] = (lowBits >> 16) & 0xff; + buffer[index++] = (lowBits >> 24) & 0xff; + // Encode high bits + buffer[index++] = highBits & 0xff; + buffer[index++] = (highBits >> 8) & 0xff; + buffer[index++] = (highBits >> 16) & 0xff; + buffer[index++] = (highBits >> 24) & 0xff; + return index; + } else if(Buffer.isBuffer(value)) { + // Write the type + buffer[index++] = BSON.BSON_DATA_BINARY; + // Encode the name + index = index + buffer.write(name, index, 'utf8') + 1; + buffer[index - 1] = 0; + // Get size of the buffer (current write point) + var size = value.length; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write the default subtype + buffer[index++] = BSON.BSON_BINARY_SUBTYPE_DEFAULT; + // Copy the content form the binary field to the buffer + value.copy(buffer, index, 0, size); + // Adjust the index + index = index + size; + return index; + } else if(value instanceof Long || value instanceof Timestamp || value['_bsontype'] == 'Long' || value['_bsontype'] == 'Timestamp') { + // Write the type + buffer[index++] = value instanceof Long ? BSON.BSON_DATA_LONG : BSON.BSON_DATA_TIMESTAMP; + // Encode the name + index = index + buffer.write(name, index, 'utf8') + 1; + buffer[index - 1] = 0; + // Write the date + var lowBits = value.getLowBits(); + var highBits = value.getHighBits(); + // Encode low bits + buffer[index++] = lowBits & 0xff; + buffer[index++] = (lowBits >> 8) & 0xff; + buffer[index++] = (lowBits >> 16) & 0xff; + buffer[index++] = (lowBits >> 24) & 0xff; + // Encode high bits + buffer[index++] = highBits & 0xff; + buffer[index++] = (highBits >> 8) & 0xff; + buffer[index++] = (highBits >> 16) & 0xff; + buffer[index++] = (highBits >> 24) & 0xff; + return index; + } else if(value instanceof Double || value['_bsontype'] == 'Double') { + // Encode as double + buffer[index++] = BSON.BSON_DATA_NUMBER; + // Encode the name + index = index + buffer.write(name, index, 'utf8') + 1; + buffer[index - 1] = 0; + // Write float + ieee754.writeIEEE754(buffer, value, index, 'little', 52, 8); + // Ajust index + index = index + 8; + return index; + } else if(value instanceof Code || value['_bsontype'] == 'Code') { + if(value.scope != null && Object.keys(value.scope).length > 0) { + // Write the type + buffer[index++] = BSON.BSON_DATA_CODE_W_SCOPE; + // Encode the name + index = index + buffer.write(name, index, 'utf8') + 1; + buffer[index - 1] = 0; + // Calculate the scope size + var scopeSize = BSON.calculateObjectSize(value.scope); + // Function string + var functionString = value.code.toString(); + // Function Size + var codeSize = Buffer.byteLength(functionString) + 1; + + // Calculate full size of the object + var totalSize = 4 + codeSize + scopeSize + 4; + + // Write the total size of the object + buffer[index++] = totalSize & 0xff; + buffer[index++] = (totalSize >> 8) & 0xff; + buffer[index++] = (totalSize >> 16) & 0xff; + buffer[index++] = (totalSize >> 24) & 0xff; + + // Write the size of the string to buffer + buffer[index++] = codeSize & 0xff; + buffer[index++] = (codeSize >> 8) & 0xff; + buffer[index++] = (codeSize >> 16) & 0xff; + buffer[index++] = (codeSize >> 24) & 0xff; + + // Write the string + buffer.write(functionString, index, 'utf8'); + // Update index + index = index + codeSize - 1; + // Write zero + buffer[index++] = 0; + // Serialize the scope object + var scopeObjectBuffer = new Buffer(scopeSize); + // Execute the serialization into a seperate buffer + serializeObject(value.scope, checkKeys, scopeObjectBuffer, 0, serializeFunctions); + + // Adjusted scope Size (removing the header) + var scopeDocSize = scopeSize; + // Write scope object size + buffer[index++] = scopeDocSize & 0xff; + buffer[index++] = (scopeDocSize >> 8) & 0xff; + buffer[index++] = (scopeDocSize >> 16) & 0xff; + buffer[index++] = (scopeDocSize >> 24) & 0xff; + + // Write the scopeObject into the buffer + scopeObjectBuffer.copy(buffer, index, 0, scopeSize); + + // Adjust index, removing the empty size of the doc (5 bytes 0000000005) + index = index + scopeDocSize - 5; + // Write trailing zero + buffer[index++] = 0; + return index + } else { + buffer[index++] = BSON.BSON_DATA_CODE; + // Encode the name + index = index + buffer.write(name, index, 'utf8') + 1; + buffer[index - 1] = 0; + // Function string + var functionString = value.code.toString(); + // Function Size + var size = Buffer.byteLength(functionString) + 1; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write the string + buffer.write(functionString, index, 'utf8'); + // Update index + index = index + size - 1; + // Write zero + buffer[index++] = 0; + return index; + } + } else if(value instanceof Binary || value['_bsontype'] == 'Binary') { + // Write the type + buffer[index++] = BSON.BSON_DATA_BINARY; + // Encode the name + index = index + buffer.write(name, index, 'utf8') + 1; + buffer[index - 1] = 0; + // Extract the buffer + var data = value.value(true); + // Calculate size + var size = value.position; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write the subtype to the buffer + buffer[index++] = value.sub_type; + // Write the data to the object + data.copy(buffer, index, 0, value.position); + // Ajust index + index = index + value.position; + return index; + } else if(value instanceof Symbol || value['_bsontype'] == 'Symbol') { + // Write the type + buffer[index++] = BSON.BSON_DATA_SYMBOL; + // Encode the name + index = index + buffer.write(name, index, 'utf8') + 1; + buffer[index - 1] = 0; + // Calculate size + size = Buffer.byteLength(value.value) + 1; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write the string + buffer.write(value.value, index, 'utf8'); + // Update index + index = index + size - 1; + // Write zero + buffer[index++] = 0x00; + return index; + } else if(value instanceof DBRef || value['_bsontype'] == 'DBRef') { + // Write the type + buffer[index++] = BSON.BSON_DATA_OBJECT; + // Encode the name + index = index + buffer.write(name, index, 'utf8') + 1; + buffer[index - 1] = 0; + // Set up correct object for serialization + var ordered_values = { + '$ref': value.namespace + , '$id' : value.oid + }; + + // Add db reference if it exists + if(null != value.db) { + ordered_values['$db'] = value.db; + } + + // Message size + var size = BSON.calculateObjectSize(ordered_values); + // Serialize the object + var endIndex = BSON.serializeWithBufferAndIndex(ordered_values, checkKeys, buffer, index, serializeFunctions); + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write zero for object + buffer[endIndex++] = 0x00; + // Return the end index + return endIndex; + } else if(value instanceof RegExp || toString.call(value) === '[object RegExp]') { + // Write the type + buffer[index++] = BSON.BSON_DATA_REGEXP; + // Encode the name + index = index + buffer.write(name, index, 'utf8') + 1; + buffer[index - 1] = 0; + + // Write the regular expression string + buffer.write(value.source, index, 'utf8'); + // Adjust the index + index = index + Buffer.byteLength(value.source); + // Write zero + buffer[index++] = 0x00; + // Write the parameters + if(value.global) buffer[index++] = 0x73; // s + if(value.ignoreCase) buffer[index++] = 0x69; // i + if(value.multiline) buffer[index++] = 0x6d; // m + // Add ending zero + buffer[index++] = 0x00; + return index; + } else { + // Write the type + buffer[index++] = Array.isArray(value) ? BSON.BSON_DATA_ARRAY : BSON.BSON_DATA_OBJECT; + // Encode the name + index = index + buffer.write(name, index, 'utf8') + 1; + buffer[index - 1] = 0; + // Serialize the object + var endIndex = serializeObject(value, checkKeys, buffer, index + 4, serializeFunctions); + // Write size + var size = endIndex - index; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + return endIndex; + } + case 'function': + // WTF for 0.4.X where typeof /someregexp/ === 'function' + if(value instanceof RegExp || toString.call(value) === '[object RegExp]') { + // Write the type + buffer[index++] = BSON.BSON_DATA_REGEXP; + // Encode the name + index = index + buffer.write(name, index, 'utf8') + 1; + buffer[index - 1] = 0; + + // Write the regular expression string + buffer.write(value.source, index, 'utf8'); + // Adjust the index + index = index + Buffer.byteLength(value.source); + // Write zero + buffer[index++] = 0x00; + // Write the parameters + if(value.global) buffer[index++] = 0x73; // s + if(value.ignoreCase) buffer[index++] = 0x69; // i + if(value.multiline) buffer[index++] = 0x6d; // m + // Add ending zero + buffer[index++] = 0x00; + return index; + } else { + if(serializeFunctions && value.scope != null && Object.keys(value.scope).length > 0) { + // Write the type + buffer[index++] = BSON.BSON_DATA_CODE_W_SCOPE; + // Encode the name + index = index + buffer.write(name, index, 'utf8') + 1; + buffer[index - 1] = 0; + // Calculate the scope size + var scopeSize = BSON.calculateObjectSize(value.scope); + // Function string + var functionString = value.toString(); + // Function Size + var codeSize = Buffer.byteLength(functionString) + 1; + + // Calculate full size of the object + var totalSize = 4 + codeSize + scopeSize; + + // Write the total size of the object + buffer[index++] = totalSize & 0xff; + buffer[index++] = (totalSize >> 8) & 0xff; + buffer[index++] = (totalSize >> 16) & 0xff; + buffer[index++] = (totalSize >> 24) & 0xff; + + // Write the size of the string to buffer + buffer[index++] = codeSize & 0xff; + buffer[index++] = (codeSize >> 8) & 0xff; + buffer[index++] = (codeSize >> 16) & 0xff; + buffer[index++] = (codeSize >> 24) & 0xff; + + // Write the string + buffer.write(functionString, index, 'utf8'); + // Update index + index = index + codeSize - 1; + // Write zero + buffer[index++] = 0; + // Serialize the scope object + var scopeObjectBuffer = new Buffer(scopeSize); + // Execute the serialization into a seperate buffer + serializeObject(value.scope, checkKeys, scopeObjectBuffer, 0, serializeFunctions); + + // Adjusted scope Size (removing the header) + var scopeDocSize = scopeSize - 4; + // Write scope object size + buffer[index++] = scopeDocSize & 0xff; + buffer[index++] = (scopeDocSize >> 8) & 0xff; + buffer[index++] = (scopeDocSize >> 16) & 0xff; + buffer[index++] = (scopeDocSize >> 24) & 0xff; + + // Write the scopeObject into the buffer + scopeObjectBuffer.copy(buffer, index, 0, scopeSize); + + // Adjust index, removing the empty size of the doc (5 bytes 0000000005) + index = index + scopeDocSize - 5; + // Write trailing zero + buffer[index++] = 0; + return index + } else if(serializeFunctions) { + buffer[index++] = BSON.BSON_DATA_CODE; + // Encode the name + index = index + buffer.write(name, index, 'utf8') + 1; + buffer[index - 1] = 0; + // Function string + var functionString = value.toString(); + // Function Size + var size = Buffer.byteLength(functionString) + 1; + // Write the size of the string to buffer + buffer[index++] = size & 0xff; + buffer[index++] = (size >> 8) & 0xff; + buffer[index++] = (size >> 16) & 0xff; + buffer[index++] = (size >> 24) & 0xff; + // Write the string + buffer.write(functionString, index, 'utf8'); + // Update index + index = index + size - 1; + // Write zero + buffer[index++] = 0; + return index; + } + } + } + + // If no value to serialize + return index; +} + +/** + * Serialize a Javascript object. + * + * @param {Object} object the Javascript object to serialize. + * @param {Boolean} checkKeys the serializer will check if keys are valid. + * @param {Boolean} asBuffer return the serialized object as a Buffer object **(ignore)**. + * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**. + * @return {Buffer} returns the Buffer object containing the serialized object. + * @api public + */ +BSON.serialize = function(object, checkKeys, asBuffer, serializeFunctions) { + var buffer = new Buffer(BSON.calculateObjectSize(object, serializeFunctions)); + BSON.serializeWithBufferAndIndex(object, checkKeys, buffer, 0, serializeFunctions); + return buffer; +} + +/** + * Contains the function cache if we have that enable to allow for avoiding the eval step on each deserialization, comparison is by md5 + * + * @ignore + * @api private + */ +var functionCache = BSON.functionCache = {}; + +/** + * Crc state variables shared by function + * + * @ignore + * @api private + */ +var table = [0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D]; + +/** + * CRC32 hash method, Fast and enough versitility for our usage + * + * @ignore + * @api private + */ +var crc32 = function(string, start, end) { + var crc = 0 + var x = 0; + var y = 0; + crc = crc ^ (-1); + + for(var i = start, iTop = end; i < iTop;i++) { + y = (crc ^ string[i]) & 0xFF; + x = table[y]; + crc = (crc >>> 8) ^ x; + } + + return crc ^ (-1); +} + +/** + * Deserialize stream data as BSON documents. + * + * Options + * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized. + * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse. + * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function. + * + * @param {Buffer} data the buffer containing the serialized set of BSON documents. + * @param {Number} startIndex the start index in the data Buffer where the deserialization is to start. + * @param {Number} numberOfDocuments number of documents to deserialize. + * @param {Array} documents an array where to store the deserialized documents. + * @param {Number} docStartIndex the index in the documents array from where to start inserting documents. + * @param {Object} [options] additional options used for the deserialization. + * @return {Number} returns the next index in the buffer after deserialization **x** numbers of documents. + * @api public + */ +BSON.deserializeStream = function(data, startIndex, numberOfDocuments, documents, docStartIndex, options) { + // if(numberOfDocuments !== documents.length) throw new Error("Number of expected results back is less than the number of documents"); + options = options != null ? options : {}; + var index = startIndex; + // Loop over all documents + for(var i = 0; i < numberOfDocuments; i++) { + // Find size of the document + var size = data[index] | data[index + 1] << 8 | data[index + 2] << 16 | data[index + 3] << 24; + // Update options with index + options['index'] = index; + // Parse the document at this point + documents[docStartIndex + i] = BSON.deserialize(data, options); + // Adjust index by the document size + index = index + size; + } + + // Return object containing end index of parsing and list of documents + return index; +} + +/** + * Ensure eval is isolated. + * + * @ignore + * @api private + */ +var isolateEvalWithHash = function(functionCache, hash, functionString, object) { + // Contains the value we are going to set + var value = null; + + // Check for cache hit, eval if missing and return cached function + if(functionCache[hash] == null) { + eval("value = " + functionString); + functionCache[hash] = value; + } + // Set the object + return functionCache[hash].bind(object); +} + +/** + * Ensure eval is isolated. + * + * @ignore + * @api private + */ +var isolateEval = function(functionString) { + // Contains the value we are going to set + var value = null; + // Eval the function + eval("value = " + functionString); + return value; +} + +/** + * Deserialize data as BSON. + * + * Options + * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized. + * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse. + * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function. + * + * @param {Buffer} buffer the buffer containing the serialized set of BSON documents. + * @param {Object} [options] additional options used for the deserialization. + * @param {Boolean} [isArray] ignore used for recursive parsing. + * @return {Object} returns the deserialized Javascript Object. + * @api public + */ +BSON.deserialize = function(buffer, options, isArray) { + // Options + options = options == null ? {} : options; + var evalFunctions = options['evalFunctions'] == null ? false : options['evalFunctions']; + var cacheFunctions = options['cacheFunctions'] == null ? false : options['cacheFunctions']; + var cacheFunctionsCrc32 = options['cacheFunctionsCrc32'] == null ? false : options['cacheFunctionsCrc32']; + + // Validate that we have at least 4 bytes of buffer + if(buffer.length < 5) throw new Error("corrupt bson message < 5 bytes long"); + + // Set up index + var index = typeof options['index'] == 'number' ? options['index'] : 0; + // Reads in a C style string + var readCStyleString = function() { + // Get the start search index + var i = index; + // Locate the end of the c string + while(buffer[i] !== 0x00) { i++ } + // Grab utf8 encoded string + var string = buffer.toString('utf8', index, i); + // Update index position + index = i + 1; + // Return string + return string; + } + + // Create holding object + var object = isArray ? [] : {}; + + // Read the document size + var size = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + + // Ensure buffer is valid size + if(size < 0 || size > buffer.length) throw new Error("corrupt bson message"); + + // While we have more left data left keep parsing + while(true) { + // Read the type + var elementType = buffer[index++]; + // If we get a zero it's the last byte, exit + if(elementType == 0) break; + // Read the name of the field + var name = readCStyleString(); + // Switch on the type + switch(elementType) { + case BSON.BSON_DATA_OID: + // Decode the oid + object[name] = new ObjectID(buffer.toString('binary', index, index + 12)); + // Update index + index = index + 12; + break; + case BSON.BSON_DATA_STRING: + // Read the content of the field + var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Add string to object + object[name] = buffer.toString('utf8', index, index + stringSize - 1); + // Update parse index position + index = index + stringSize; + break; + case BSON.BSON_DATA_INT: + // Decode the 32bit value + object[name] = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + break; + case BSON.BSON_DATA_NUMBER: + // Decode the double value + object[name] = ieee754.readIEEE754(buffer, index, 'little', 52, 8); + // Update the index + index = index + 8; + break; + case BSON.BSON_DATA_DATE: + // Unpack the low and high bits + var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Set date object + object[name] = new Date(new Long(lowBits, highBits).toNumber()); + break; + case BSON.BSON_DATA_BOOLEAN: + // Parse the boolean value + object[name] = buffer[index++] == 1; + break; + case BSON.BSON_DATA_NULL: + // Parse the boolean value + object[name] = null; + break; + case BSON.BSON_DATA_BINARY: + // Decode the size of the binary blob + var binarySize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Decode the subtype + var subType = buffer[index++]; + // Decode as raw Buffer object if options specifies it + object[name] = new Binary(buffer.slice(index, index + binarySize), subType); + // Update the index + index = index + binarySize; + break; + case BSON.BSON_DATA_ARRAY: + options['index'] = index; + // Decode the size of the array document + var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24; + // Set the array to the object + object[name] = BSON.deserialize(buffer, options, true); + // Adjust the index + index = index + objectSize; + break; + case BSON.BSON_DATA_OBJECT: + options['index'] = index; + // Decode the size of the object document + var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24; + // Set the array to the object + object[name] = BSON.deserialize(buffer, options, false); + // Adjust the index + index = index + objectSize; + break; + case BSON.BSON_DATA_REGEXP: + // Create the regexp + var source = readCStyleString(); + var regExpOptions = readCStyleString(); + // For each option add the corresponding one for javascript + var optionsArray = new Array(regExpOptions.length); + + // Parse options + for(var i = 0; i < regExpOptions.length; i++) { + switch(regExpOptions[i]) { + case 'm': + optionsArray[i] = 'm'; + break; + case 's': + optionsArray[i] = 'g'; + break; + case 'i': + optionsArray[i] = 'i'; + break; + } + } + + object[name] = new RegExp(source, optionsArray.join('')); + break; + case BSON.BSON_DATA_LONG: + // Unpack the low and high bits + var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Create long object + var long = new Long(lowBits, highBits); + // Set the object + object[name] = long.lessThanOrEqual(JS_INT_MAX_LONG) && long.greaterThanOrEqual(JS_INT_MIN_LONG) ? long.toNumber() : long; + break; + case BSON.BSON_DATA_SYMBOL: + // Read the content of the field + var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Add string to object + object[name] = new Symbol(buffer.toString('utf8', index, index + stringSize - 1)); + // Update parse index position + index = index + stringSize; + break; + case BSON.BSON_DATA_TIMESTAMP: + // Unpack the low and high bits + var lowBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + var highBits = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Set the object + object[name] = new Timestamp(lowBits, highBits); + break; + case BSON.BSON_DATA_MIN_KEY: + // Parse the object + object[name] = new MinKey(); + break; + case BSON.BSON_DATA_MAX_KEY: + // Parse the object + object[name] = new MaxKey(); + break; + case BSON.BSON_DATA_CODE: + // Read the content of the field + var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Function string + var functionString = buffer.toString('utf8', index, index + stringSize - 1); + + // If we are evaluating the functions + if(evalFunctions) { + // Contains the value we are going to set + var value = null; + // If we have cache enabled let's look for the md5 of the function in the cache + if(cacheFunctions) { + var hash = cacheFunctionsCrc32 ? crc32(functionString) : functionString; + // Got to do this to avoid V8 deoptimizing the call due to finding eval + object[name] = isolateEvalWithHash(functionCache, hash, functionString, object); + } else { + // Set directly + object[name] = isolateEval(functionString); + } + } else { + object[name] = new Code(functionString, {}); + } + + // Update parse index position + index = index + stringSize; + break; + case BSON.BSON_DATA_CODE_W_SCOPE: + // Read the content of the field + var totalSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + var stringSize = buffer[index++] | buffer[index++] << 8 | buffer[index++] << 16 | buffer[index++] << 24; + // Javascript function + var functionString = buffer.toString('utf8', index, index + stringSize - 1); + // Update parse index position + index = index + stringSize; + // Parse the element + options['index'] = index; + // Decode the size of the object document + var objectSize = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24; + // Decode the scope object + var scopeObject = BSON.deserialize(buffer, options, false); + // Adjust the index + index = index + objectSize; + + // If we are evaluating the functions + if(evalFunctions) { + // Contains the value we are going to set + var value = null; + // If we have cache enabled let's look for the md5 of the function in the cache + if(cacheFunctions) { + var hash = cacheFunctionsCrc32 ? crc32(functionString) : functionString; + // Got to do this to avoid V8 deoptimizing the call due to finding eval + object[name] = isolateEvalWithHash(functionCache, hash, functionString, object); + } else { + // Set directly + object[name] = isolateEval(functionString); + } + + // Set the scope on the object + object[name].scope = scopeObject; + } else { + object[name] = new Code(functionString, scopeObject); + } + + // Add string to object + break; + } + } + + // Check if we have a db ref object + if(object['$id'] != null) object = new DBRef(object['$ref'], object['$id'], object['$db']); + + // Return the final objects + return object; +} + +/** + * Check if key name is valid. + * + * @ignore + * @api private + */ +BSON.checkKey = function checkKey (key) { + if (!key.length) return; + // Check if we have a legal key for the object + if('$' == key[0]) { + throw Error("key " + key + " must not start with '$'"); + } else if (!!~key.indexOf('.')) { + throw Error("key " + key + " must not contain '.'"); + } +}; + +/** + * Deserialize data as BSON. + * + * Options + * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized. + * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse. + * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function. + * + * @param {Buffer} buffer the buffer containing the serialized set of BSON documents. + * @param {Object} [options] additional options used for the deserialization. + * @param {Boolean} [isArray] ignore used for recursive parsing. + * @return {Object} returns the deserialized Javascript Object. + * @api public + */ +BSON.prototype.deserialize = function(data, options) { + return BSON.deserialize(data, options); +} + +/** + * Deserialize stream data as BSON documents. + * + * Options + * - **evalFunctions** {Boolean, default:false}, evaluate functions in the BSON document scoped to the object deserialized. + * - **cacheFunctions** {Boolean, default:false}, cache evaluated functions for reuse. + * - **cacheFunctionsCrc32** {Boolean, default:false}, use a crc32 code for caching, otherwise use the string of the function. + * + * @param {Buffer} data the buffer containing the serialized set of BSON documents. + * @param {Number} startIndex the start index in the data Buffer where the deserialization is to start. + * @param {Number} numberOfDocuments number of documents to deserialize. + * @param {Array} documents an array where to store the deserialized documents. + * @param {Number} docStartIndex the index in the documents array from where to start inserting documents. + * @param {Object} [options] additional options used for the deserialization. + * @return {Number} returns the next index in the buffer after deserialization **x** numbers of documents. + * @api public + */ +BSON.prototype.deserializeStream = function(data, startIndex, numberOfDocuments, documents, docStartIndex, options) { + return BSON.deserializeStream(data, startIndex, numberOfDocuments, documents, docStartIndex, options); +} + +/** + * Serialize a Javascript object. + * + * @param {Object} object the Javascript object to serialize. + * @param {Boolean} checkKeys the serializer will check if keys are valid. + * @param {Boolean} asBuffer return the serialized object as a Buffer object **(ignore)**. + * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**. + * @return {Buffer} returns the Buffer object containing the serialized object. + * @api public + */ +BSON.prototype.serialize = function(object, checkKeys, asBuffer, serializeFunctions) { + return BSON.serialize(object, checkKeys, asBuffer, serializeFunctions); +} + +/** + * Calculate the bson size for a passed in Javascript object. + * + * @param {Object} object the Javascript object to calculate the BSON byte size for. + * @param {Boolean} [serializeFunctions] serialize all functions in the object **(default:false)**. + * @return {Number} returns the number of bytes the BSON object will take up. + * @api public + */ +BSON.prototype.calculateObjectSize = function(object, serializeFunctions) { + return BSON.calculateObjectSize(object, serializeFunctions); +} + +/** + * Serialize a Javascript object using a predefined Buffer and index into the buffer, useful when pre-allocating the space for serialization. + * + * @param {Object} object the Javascript object to serialize. + * @param {Boolean} checkKeys the serializer will check if keys are valid. + * @param {Buffer} buffer the Buffer you pre-allocated to store the serialized BSON object. + * @param {Number} index the index in the buffer where we wish to start serializing into. + * @param {Boolean} serializeFunctions serialize the javascript functions **(default:false)**. + * @return {Number} returns the new write index in the Buffer. + * @api public + */ +BSON.prototype.serializeWithBufferAndIndex = function(object, checkKeys, buffer, startIndex, serializeFunctions) { + return BSON.serializeWithBufferAndIndex(object, checkKeys, buffer, startIndex, serializeFunctions); +} + +/** + * @ignore + * @api private + */ +if(typeof window === 'undefined') { + exports.Code = Code; + exports.Symbol = Symbol; + exports.BSON = BSON; + exports.DBRef = DBRef; + exports.Binary = Binary; + exports.ObjectID = ObjectID; + exports.Long = Long; + exports.Timestamp = Timestamp; + exports.Double = Double; + exports.MinKey = MinKey; + exports.MaxKey = MaxKey; +} diff --git a/public/code.js b/public/code.js new file mode 100644 index 0000000..cc951c1 --- /dev/null +++ b/public/code.js @@ -0,0 +1,25 @@ +/** + * A class representation of the BSON Code type. + * + * @class Represents the BSON Code type. + * @param {String|Function} code a string or function. + * @param {Object} [scope] an optional scope for the function. + * @return {Code} + */ +function Code(code, scope) { + this._bsontype = 'Code'; + this.code = code; + this.scope = scope == null ? {} : scope; +}; + +/** + * @ignore + * @api private + */ +Code.prototype.toJSON = function() { + return {scope:this.scope, code:this.code}; +} + +if(typeof window === 'undefined') { + exports.Code = Code; +} \ No newline at end of file diff --git a/public/communication.js b/public/communication.js new file mode 100644 index 0000000..d1d10a4 --- /dev/null +++ b/public/communication.js @@ -0,0 +1,66 @@ +// Handles all our communication +var GameCommunication = function() { + // Set up the object handling all the communication + // with the backend server + // this.messageHandler = { + // initCommands: this.initCommands.bind(this) + // }; +} + +// Handle the setup of the connection +GameCommunication.prototype.connect = function(callback) { + var url = "ws://" + document.URL.substr(7).split('/')[0]; + // Create a websocket either using the Mozilla web socket or the + // standard one + var wsCtor = window['MozWebSocket'] ? MozWebSocket : WebSocket; + this.socket = new wsCtor(url, 'game'); + this.socket.binaryType = 'blob'; + + // Bind the handlers + this.socket.onopen = callback; + this.socket.onerror = callback; + this.socket.onmessage = this.handleWebsocketMessage.bind(this); + this.socket.onclose = this.handleWebsocketClose.bind(this); + + // Contains all the incoming messages + // We only access messages during the rendering phase of the game + this.messages = []; +} + +// Dispatch a command +GameCommunication.prototype.dispatchCommand = function(command) { + console.log("=============== command :: " + (command instanceof ArrayBuffer)) + + if(command instanceof ArrayBuffer) { + console.log("---------------------------------------- ArrayBuffer") + + this.socket.send(command); + } else if(typeof command == 'object') { + console.log("---------------------------------------- Object") + + this.socket.send(JSON.stringify(command)); + } +} + +// Open the connection +GameCommunication.prototype.handleWebsocketOpen = function() { + console.log("==================================== socket opened") +} + +// Handle the web socket messages +GameCommunication.prototype.handleWebsocketMessage = function(message) { + // Let's add the message to the incoming message array + // this.messages.push(message); + console.log("==================================== received message") + console.dir(message) +} + +// Close the connection +GameCommunication.prototype.handleWebsocketClose = function() { + console.log("==================================== socket closed") +} + + + + + diff --git a/public/db_ref.js b/public/db_ref.js new file mode 100644 index 0000000..7961ba0 --- /dev/null +++ b/public/db_ref.js @@ -0,0 +1,31 @@ +/** + * A class representation of the BSON DBRef type. + * + * @class Represents the BSON DBRef type. + * @param {String} namespace the collection name. + * @param {ObjectID} oid the reference ObjectID. + * @param {String} [db] optional db name, if omitted the reference is local to the current db. + * @return {DBRef} + */ +function DBRef(namespace, oid, db) { + this._bsontype = 'DBRef'; + this.namespace = namespace; + this.oid = oid; + this.db = db; +}; + +/** + * @ignore + * @api private + */ +DBRef.prototype.toJSON = function() { + return { + '$ref':this.namespace, + '$id':this.oid, + '$db':this.db == null ? '' : this.db + }; +} + +if(typeof window === 'undefined') { + exports.DBRef = DBRef; +} \ No newline at end of file diff --git a/public/double.js b/public/double.js new file mode 100644 index 0000000..173ac0c --- /dev/null +++ b/public/double.js @@ -0,0 +1,33 @@ +/** + * A class representation of the BSON Double type. + * + * @class Represents the BSON Double type. + * @param {Number} value the number we want to represent as a double. + * @return {Double} + */ +function Double(value) { + this._bsontype = 'Double'; + this.value = value; +} + +/** + * Access the number value. + * + * @return {Number} returns the wrapped double number. + * @api public + */ +Double.prototype.valueOf = function() { + return this.value; +}; + +/** + * @ignore + * @api private + */ +Double.prototype.toJSON = function() { + return this.value; +} + +if(typeof window === 'undefined') { + exports.Double = Double; +} \ No newline at end of file diff --git a/public/float_parser.js b/public/float_parser.js new file mode 100644 index 0000000..7c12fe5 --- /dev/null +++ b/public/float_parser.js @@ -0,0 +1,123 @@ +// Copyright (c) 2008, Fair Oaks Labs, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of Fair Oaks Labs, Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// +// Modifications to writeIEEE754 to support negative zeroes made by Brian White + +var readIEEE754 = function(buffer, offset, endian, mLen, nBytes) { + var e, m, + bBE = (endian === 'big'), + eLen = nBytes * 8 - mLen - 1, + eMax = (1 << eLen) - 1, + eBias = eMax >> 1, + nBits = -7, + i = bBE ? 0 : (nBytes - 1), + d = bBE ? 1 : -1, + s = buffer[offset + i]; + + i += d; + + e = s & ((1 << (-nBits)) - 1); + s >>= (-nBits); + nBits += eLen; + for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8); + + m = e & ((1 << (-nBits)) - 1); + e >>= (-nBits); + nBits += mLen; + for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8); + + if (e === 0) { + e = 1 - eBias; + } else if (e === eMax) { + return m ? NaN : ((s ? -1 : 1) * Infinity); + } else { + m = m + Math.pow(2, mLen); + e = e - eBias; + } + return (s ? -1 : 1) * m * Math.pow(2, e - mLen); +}; + +var writeIEEE754 = function(buffer, value, offset, endian, mLen, nBytes) { + var e, m, c, + bBE = (endian === 'big'), + eLen = nBytes * 8 - mLen - 1, + eMax = (1 << eLen) - 1, + eBias = eMax >> 1, + rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0), + i = bBE ? (nBytes-1) : 0, + d = bBE ? -1 : 1, + s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0; + + value = Math.abs(value); + + if (isNaN(value) || value === Infinity) { + m = isNaN(value) ? 1 : 0; + e = eMax; + } else { + e = Math.floor(Math.log(value) / Math.LN2); + if (value * (c = Math.pow(2, -e)) < 1) { + e--; + c *= 2; + } + if (e+eBias >= 1) { + value += rt / c; + } else { + value += rt * Math.pow(2, 1 - eBias); + } + if (value * c >= 2) { + e++; + c /= 2; + } + + if (e + eBias >= eMax) { + m = 0; + e = eMax; + } else if (e + eBias >= 1) { + m = (value * c - 1) * Math.pow(2, mLen); + e = e + eBias; + } else { + m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen); + e = 0; + } + } + + for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8); + + e = (e << mLen) | m; + eLen += mLen; + for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8); + + buffer[offset + i - d] |= s * 128; +}; + +if(typeof window === 'undefined') { + exports.readIEEE754 = readIEEE754; + exports.writeIEEE754 = writeIEEE754; +} diff --git a/public/game.js b/public/game.js new file mode 100644 index 0000000..d012ebf --- /dev/null +++ b/public/game.js @@ -0,0 +1,370 @@ +// Game state variables +var maingame = null; +var maze = null; +var client = null; + +// Load the game box +gbox.onLoad(function () { + // Prepare the connection + client = new GameCommunication('game'); + // Start the client + client.connect(function() { + var message = BSON.serialize({hello:"world"}, true, true, false); + console.log("------------------------------------------------------- :: " + message.length) + console.log(message) + + // Dispatch a message + client.dispatchCommand(message.asArrayBuffer()); + + help.akihabaraInit({ + title: "Bombaman", + splash: {footnotes: ["Music 'Only Heroes Win at Skee Ball' by Greenleo","Contact him: greenleo.bandcamp.com"] } + }); + + // Load the logo, do at the start so it will be there first for the title screen + gbox.addImage("logo","resources/capman/logo.png"); + // Load the sprite sheet + gbox.addImage("cels","resources/capman/cels.png"); + // Load the font set + gbox.addImage("font","resources/capman/font.png"); + + // Font are mapped over an image, setting the first letter, the letter size, the length of all rows of letters and a horizontal/vertical gap. + gbox.addFont({id: "small", image: "font", firstletter: " ", tileh: 8, tilew: 8, tilerow: 255, gapx: 0, gapy: 0}); + + // Cut up all the sprites + gbox.addTiles({id:"capman",image:"cels",tileh:12,tilew:12,tilerow:10,gapx:0,gapy:0}); + gbox.addTiles({id:"ghost1",image:"cels",tileh:12,tilew:12,tilerow:3,gapx:0,gapy:12}); + gbox.addTiles({id:"ghost2",image:"cels",tileh:12,tilew:12,tilerow:3,gapx:36,gapy:12}); + gbox.addTiles({id:"ghost3",image:"cels",tileh:12,tilew:12,tilerow:3,gapx:36*2,gapy:12}); + gbox.addTiles({id:"ghost4",image:"cels",tileh:12,tilew:12,tilerow:3,gapx:36*3,gapy:12}); + gbox.addTiles({id:"ghostscared",image:"cels",tileh:12,tilew:12,tilerow:3,gapx:36*4,gapy:12}); + gbox.addTiles({id:"ghosteaten",image:"cels",tileh:12,tilew:12,tilerow:3,gapx:36*5,gapy:12}); + gbox.addTiles({id:"bonus",image:"cels",tileh:12,tilew:12,tilerow:8,gapx:0,gapy:24}); + gbox.addTiles({id:"maze",image:"cels",tileh:4,tilew:4,tilerow:10,gapx:0,gapy:36}); + + // Now let's load some audio samples... + var audioserver = "resources/audio/"; + gbox.addAudio("eat", [audioserver+"eat.mp3",audioserver+"eat.ogg"],{channel:"sfx"}); + gbox.addAudio("eatghost", [audioserver+"laser.mp3",audioserver+"laser.ogg"],{channel:"sfx"}); + gbox.addAudio("powerpill", [audioserver+"powerup3.mp3",audioserver+"powerup3.ogg"],{channel:"sfx"}); + gbox.addAudio("die", [audioserver+"die.mp3",audioserver+"die.ogg"],{channel:"sfx"}); + gbox.addAudio("bonus", [audioserver+"coin.mp3",audioserver+"coin.ogg"],{channel:"sfx"}); + gbox.addAudio("default-menu-option", [audioserver+"select.mp3",audioserver+"select.ogg"],{channel:"sfx"}); + gbox.addAudio("default-menu-confirm", [audioserver+"start.mp3",audioserver+"start.ogg"],{channel:"sfx"}); + gbox.addAudio("ingame", [audioserver+"capman-ingame.mp3",audioserver+"capman-ingame.ogg"],{channel:"bgmusic",loop:true}); + + // The loadAll function loads all the resources and triggers the main game loop + gbox.loadAll(go); + + // Start the game + gbox.go(); + }); +}, false); + +// Start game function +var go = function() { + // console.log("--------------------------------------------------------- go"); + // Set up the groups involved in the game, this is the different parts of the + // game that requires attention during the game loop, the order defines the drawing order of the groups + // background object will be draw first + // gbox.setGroups(["background","player","ghosts","bonus","sparks","gamecycle"]); + gbox.setGroups(["background", "player", "gamecycle"]); + + // Set up the main loop object + maingame = gamecycle.createMaingame("gamecycle","gamecycle"); + + // Set method called each time we change the level + maingame.changeLevel = function(level) { + console.log("--------------------------------------------------------- changeLevel"); + + // Create a maze object based on the tilemap, mapping function + // and the function that determines if a tile is solid or not + maze = help.finalizeTilemap({ + tileset: "maze", + map: help.asciiArtToMap(tilemap, tilemapTranslation), + tileIsSolid: isTileSolid + }); + + // Create a canvas using the calculated size of the maze + gbox.createCanvas("mazecanvas", {w:maze.w,h:maze.h}); + // Render the tilemap to the canvas + gbox.blitTilemap(gbox.getCanvasContext("mazecanvas"), maze); + + // // Set up the pill count + // this.pillscount = 0; + // for (var y=0;y7) this.pillscount++; // If the row/column contains a "pill" tile (8 for plain pill, 9 for powerpill), let's + + this.newLife(); + } + + maingame.newLife = function() { + gbox.purgeGarbage(); // the gbox module have a garbage collector that runs sometime. Let's call this manually, for optimization (and better reinitialization) + toys.topview.spawn(gbox.getObject("player","capman"),{x:maze.hw-6,y:maze.hh+50,accx:0,accy:0,xpushing:false,ypushing:false}); // Our "capman" object into the "player" group spawns in the middle of the maze every time it spawns. + // maingame.addGhost({id:1,x:maze.hw-12,y:maze.hh-20}); // Ghost are added here + // maingame.addGhost({id:2,x:maze.hw-24,y:maze.hh-17}); + // maingame.addGhost({id:3,x:maze.hw+4,y:maze.hh-20}); + // maingame.addGhost({id:4,x:maze.hw+14,y:maze.hh-17}); + + // if (this.bonustimer) this.bonustimer=300; + // gbox.playAudio("ingame"); + + } + + // This method is triggered once pr game + maingame.initializeGame = function() { + // console.log("--------------------------------------------------------- initializeGame"); + // Set up the HUD used to signal all the different values visable to the user + maingame.hud.setWidget("label", {widget:"label", font:"small", value:"1UP", dx:240, dy:10, clear:true}); + maingame.hud.setWidget("score",{widget:"label",font:"small",value:0,dx:240,dy:25,clear:true}); + maingame.hud.setWidget("label",{widget:"label",font:"small",value:"HI",dx:240,dy:40,clear:true}); + maingame.hud.setWidget("hiscore",{widget:"label",font:"small",value:0,dx:240,dy:55,clear:true}); + maingame.hud.setWidget("lives",{widget:"symbols",minvalue:0,value:3-maingame.difficulty,maxshown:3,tileset:"capman",tiles:[5],dx:240,dy:70,gapx:16,gapy:0}); + maingame.hud.setWidget("bonus",{widget:"stack",rightalign:true,tileset:"bonus",dx:gbox.getScreenW()-5,dy:gbox.getScreenH()-34,gapx:12,gapy:0,maxshown:8,value:[]}); + maingame.hud.setWidget("stage",{widget:"label",font:"small",value:"",dx:0,dw:gbox.getScreenW()-5,dy:gbox.getScreenH()-13,halign:gbox.ALIGN_RIGHT,clear:true}); + maingame.hud.setValue("hiscore","value",gbox.dataLoad("capman-hiscore")); + + // Let's add the object that will draw the maze + gbox.addObject(drawMaze); + // Let's add the player + gbox.addObject(player); + } + + maingame.gameMenu = function(reset) { + return true; + } + + maingame.gameEvents = function() { + // console.log("--------------------------------------------------------- gameEvents"); + } + + // Show the intro screen + maingame.gameTitleIntroAnimation = function(reset) { + // console.log("--------------------------------------------------------- gameTitleIntroAnimation"); + + if(reset) { + toys.resetToy(this,"rising"); + } else { + // Clear the screen + gbox.blitFade(gbox.getBufferContext(),{alpha:1}); + // Show the logos + toys.logos.linear(this,"rising",{image:"logo",x:gbox.getScreenHW()-gbox.getImage("logo").hwidth,y:20,sx:gbox.getScreenHW()-gbox.getImage("logo").hwidth,sy:gbox.getScreenH(),speed:1,audioreach:"eatghost"}); + } + }; +} + +// +// Draws the player +// +var player = { + id:"capman", + group:"player", + tileset:"capman", + killed:false, + scorecombo:1, + + initialize: function() { + // Sets up the objects, properties on our 2D map + toys.topview.initialize(this,{ + colh:gbox.getTiles(this.tileset).tileh, + colw:gbox.getTiles(this.tileset).tilew, + staticspeed:2, + nodiagonals:true, + noreset:true, + frames:{ + still:{ speed:2, frames:[0] }, + hit:{speed:1,frames:[0,1,0,1]}, + standup:{ speed:1, frames:[0] }, + standdown:{ speed:1, frames:[0] }, + standleft:{ speed:1, frames:[0] }, + standright:{ speed:1, frames:[0] }, + movingup:{speed:3,frames:[0,2,1,2] }, + movingdown:{speed:3,frames:[0,4,3,4] }, + movingleft:{speed:3,frames:[0,6,5,6] }, + movingright:{speed:3,frames:[0,6,5,6] } + } + }); + }, + + first: function() { + // Ensure we are showing the current correct frame out of 10 possible + this.counter = (this.counter+1) % 10; + + // If capman is still alive and the game is not "hold" (level changing fadein/fadeouts etc.) and the "bullet timer" is not stopping the game. + if(!this.killed && !maingame.gameIsHold() && !maingame.bullettimer) { + + // First of all, let's move. + // A little trick: capman cannot change direction, if hits a wall, so we backup capman's status here. Will restored if capman hits the wall. + var olddata = help.createModel(this,["x","y","accx","accy","xpushing","ypushing","facing"]); + // Set up the control keys for the player + toys.topview.controlKeys(this,{left:"left",right:"right",up:"up",down:"down"}); + // Apply forces to the model + toys.topview.applyForces(this); + + // Handle collisions with the map, accuracy and tolerance controls how precise the collision detection is + toys.topview.tileCollision(this, maze, "map", null, {tolerance:0,approximation:1}); + + // If we have a collision + if(this.touchedup||this.toucheddown||this.touchedleft||this.touchedright) { + help.copyModel(this,olddata); + toys.topview.applyForces(this); + toys.topview.tileCollision(this, maze, "map", null, {tolerance:0,approximation:1}); + } + + // The side warp. If capman reach one of the left or right side of the maze, is spawn on the other side,in the same direction + if ((this.x<0)&&(this.facing==toys.FACE_LEFT)) { + this.x = maze.w - this.w; + } else if ((this.x>(maze.w-this.w)) && (this.facing == toys.FACE_RIGHT)) { + this.x = 0; + } + + // setFrame sets the right frame checking the facing and the defined animations in "initialize" + toys.topview.setFrame(this); + + // // Grab the current tile in the map object + // var inmouth = help.getTileInMap(this.x+this.hw,this.y+this.hh, maze, 0); // I'll explain this the next line. + // + // // Handle pills + // if (inmouth>7) { // If capman is eating a pill (8 for normal pill, 9 for power pill) + // if (inmouth == 9) { // If is a powerpill + // gbox.hitAudio("powerpill"); // Play the powerpill sound. hitAudio plays an audio from start and is useful for sound effects. playAudio does nothing if the audio was already playing, so is useful for music playback. + // this.scorecombo=1; // Reset the combo counter. + // gbox.getObject("ghosts","ghost1").makeeatable(); // Make the ghosts vulnerable. + // gbox.getObject("ghosts","ghost2").makeeatable(); + // gbox.getObject("ghosts","ghost3").makeeatable(); + // gbox.getObject("ghosts","ghost4").makeeatable(); + // } else + // gbox.hitAudio("eat"); // If is a classic pill, play the classic "gabogabo" sound! + // var mouthx=help.xPixelToTileX(maze,this.x+this.hw); // Let's get the pill coordinate in the maze... + // var mouthy=help.yPixelToTileY(maze,this.y+this.hh); + // help.setTileInMap(gbox.getCanvasContext("mazecanvas"),maze,mouthx,mouthy,null); // ... and set a null tile over that. + // maingame.hud.addValue("score","value",10); // Player earns 10 points. "hud" items also stores their values and can be used to store the real score. + // maingame.pillscount--; // Let's decrease the number of pills into the maze. + // } + } + }, + + blit:function() { + if (!this.killed) { + gbox.blitTile(gbox.getBufferContext(), {tileset:this.tileset, tile:this.frame, dx:this.x, dy:this.y, fliph:this.fliph, flipv:this.flipv, camera:this.camera, alpha:1}); + } + }, + + // And now, a custom method. This one will kill the player and will be called by ghosts, when colliding with capman. + kill:function() { + // if (!this.killed) { // If we're alive... + // this.killed=true; // First of all, capman is killed. As you've seen, that makes capman invisible and on hold. + // gbox.hitAudio("die"); // Play the die sound + // maingame.hud.addValue("lives","value",-1); // Then decrease the lives count. + // maingame.playerDied({wait:50}); // Telling the main game cycle that the player died. The arguments sets a short delay after the last fadeout, for making visible the dead animation + // toys.generate.sparks.simple(this,"sparks",null,{tileset:this.tileset,frames:{speed:4,frames:[6,5,7,8,9,9,9,9]}}); + // // And here comes a common trick: the player is still where was killed and a "spark" (i.e. unuseful animation) starts in the same place. + // // This method allows many nice tricks, since avoid destruction/recreation of the player object, allow a respawn the player in the place it was killed very easily (switching + // // the killed attribute. The "spark.simple" method spawns a spark in the same position of the object in the first argument. + // } + } +} + + +// +// Draws the maze for the game +// +var drawMaze = { + id:"bg", + group:"background", + + // This action is executed the first time the object is called, so... + initialize:function() { + // We place the camera a bit down, since the full maze doesn't fit the screen. + gbox.setCameraY(2, {w: maze.w, h: maze.h}); + }, + + blit:function() { + // Clear the entire screen + gbox.blitFade(gbox.getBufferContext(),{alpha: 1}); + gbox.blit(gbox.getBufferContext(), gbox.getCanvas("mazecanvas"), + {dx: 0,dy: 0,dw: gbox.getCanvas("mazecanvas").width, dh:gbox.getCanvas("mazecanvas").height, sourcecamera:true}); + } +} + + +// ---------------------------------------------------------------------------- +// +// Map functions +// +// ---------------------------------------------------------------------------- +var isTileSolid = function(obj, t) { + return (t!==null)&& + ((t<6)|| + ((t==6)&&(obj.status!="goout")&&(obj.status!="goin"))); +} + +// The tilemap used for the game +var tilemap = [ + "||T----------------------------------------------------TxxT----------------------------------------------------T||", + "|||| ||xx|| ||||", + "|||| . . . . . . . . . . . . ||xx|| . . . . . . . . . . . . ||||", + "|||| ||xx|| ||||", + "|||| . T------------T . T----------------T . ||xx|| . T----------------T . T------------T . ||||", + "|||| ||xxxxxxxxxx|| ||xxxxxxxxxxxxxx|| ||xx|| ||xxxxxxxxxxxxxx|| ||xxxxxxxxxx|| ||||", + "|||| o ||xxxxxxxxxx|| . ||xxxxxxxxxxxxxx|| . ||xx|| . ||xxxxxxxxxxxxxx|| . ||xxxxxxxxxx|| o ||||", + "|||| ||xxxxxxxxxx|| ||xxxxxxxxxxxxxx|| ||xx|| ||xxxxxxxxxxxxxx|| ||xxxxxxxxxx|| ||||", + "|||| . L------------J . L----------------J . L----J . L----------------J . L------------J . ||||", + "|||| ||||", + "|||| . . . . . . . . . . . . . . . . . . . . . . . . . . ||||", + "|||| ||||", + "|||| . T------------T . T----T . T----------------------------T . T----T . T------------T . ||||", + "|||| ||xxxxxxxxxx|| ||xx|| ||xxxxxxxxxxxxxxxxxxxxxxxxxx|| ||xx|| ||xxxxxxxxxx|| ||||", + "|||| . L------------J . ||xx|| . L------------TxxT------------J . ||xx|| . L------------J . ||||", + "|||| ||xx|| ||xx|| ||xx|| ||||", + "|||| . . . . . . ||xx|| . . . . ||xx|| . . . . ||xx|| . . . . . . ||||", + "|||| ||xx|| ||xx|| ||xx|| ||||", + "||L--------------------T . ||xxL------------T ||xx|| T------------Jxx|| . T--------------------J||", + "L--------------------T|| ||xxxxxxxxxxxxxx|| ||xx|| ||xxxxxxxxxxxxxx|| ||T--------------------J", + " |||| . ||xxT------------J L----J L------------Txx|| . |||| ", + " |||| ||xx|| ||xx|| |||| ", + " |||| . ||xx|| ||xx|| . |||| ", + " |||| ||xx|| ||xx|| |||| ", + " |||| . ||xx|| T---------~~~~~~~~~~---------T ||xx|| . |||| ", + "---------------------J|| ||xx|| || || ||xx|| ||L---------------------", + "-----------------------J . L----J || || L----J . L-----------------------", + " || || ", + " . || || . ", + " || || ", + "-----------------------T . T----T || || T----T . T-----------------------", + "---------------------T|| ||xx|| || || ||xx|| ||T---------------------", + " |||| . ||xx|| L----------------------------J ||xx|| . |||| ", + " |||| ||xx|| ||xx|| |||| ", + " |||| . ||xx|| ||xx|| . |||| ", + " |||| ||xx|| ||xx|| |||| ", + " |||| . ||xx|| T----------------------------T ||xx|| . |||| ", + "T--------------------J|| ||xx|| ||xxxxxxxxxxxxxxxxxxxxxxxxxx|| ||xx|| ||L--------------------T", + "||T--------------------J . L----J L------------TxxT------------J L----J . L--------------------T||", + "|||| ||xx|| ||||", + "|||| . . . . . . . . . . . . ||xx|| . . . . . . . . . . . . ||||", + "|||| ||xx|| ||||", + "|||| . T------------T . T----------------T . ||xx|| . T----------------T . T------------T . ||||", + "|||| ||xxxxxxxxxx|| ||xxxxxxxxxxxxxx|| ||xx|| ||xxxxxxxxxxxxxx|| ||xxxxxxxxxx|| ||||", + "|||| . L--------Txx|| . L----------------J . L----J . L----------------J . ||xxT--------J . ||||", + "|||| ||xx|| ||xx|| ||||", + "|||| o . . ||xx|| . . ||xx|| . . o ||||", + "|||| ||xx|| ||xx|| ||||", + "||L--------T . ||xx|| . T----T . T----------------------------T . T----T . ||xx|| . T--------J||", + "||xxxxxxxx|| ||xx|| ||xx|| ||xxxxxxxxxxxxxxxxxxxxxxxxxx|| ||xx|| ||xx|| ||xxxxxxxx||", + "||T--------J . L----J . ||xx|| . L------------TxxT------------J . ||xx|| . L----J . L--------T||", + "|||| ||xx|| ||xx|| ||xx|| ||||", + "|||| . . . . . . ||xx|| . . . . ||xx|| . . . . ||xx|| . . . . . . ||||", + "|||| ||xx|| ||xx|| ||xx|| ||||", + "|||| . T--------------------JxxL------------T . ||xx|| . T------------JxxL--------------------T . ||||", + "|||| ||xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|| ||xx|| ||xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|| ||||", + "|||| . L------------------------------------J . ||xx|| . L------------------------------------J . ||||", + "|||| ||xx|| ||||", + "|||| . . . . . . . . . . . . ||xx|| . . . . . . . . . . . . ||||", + "|||| ||xx|| ||||", + "||L----------------------------------------------------JxxL----------------------------------------------------J||", +] + +// The tilemap translation array +var tilemapTranslation = [[null," "],[0,"||"],[1,"--"],[2,"L-"],[3,"-J"],[4,"T-"],[5,"-T"],[6,"~~"],[7,"xx"],[8," ."],[9," o"]]; + diff --git a/public/long.js b/public/long.js new file mode 100644 index 0000000..3a472ac --- /dev/null +++ b/public/long.js @@ -0,0 +1,854 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Copyright 2009 Google Inc. All Rights Reserved + +/** + * Defines a Long class for representing a 64-bit two's-complement + * integer value, which faithfully simulates the behavior of a Java "Long". This + * implementation is derived from LongLib in GWT. + * + * Constructs a 64-bit two's-complement integer, given its low and high 32-bit + * values as *signed* integers. See the from* functions below for more + * convenient ways of constructing Longs. + * + * The internal representation of a Long is the two given signed, 32-bit values. + * We use 32-bit pieces because these are the size of integers on which + * Javascript performs bit-operations. For operations like addition and + * multiplication, we split each number into 16-bit pieces, which can easily be + * multiplied within Javascript's floating-point representation without overflow + * or change in sign. + * + * In the algorithms below, we frequently reduce the negative case to the + * positive case by negating the input(s) and then post-processing the result. + * Note that we must ALWAYS check specially whether those values are MIN_VALUE + * (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as + * a positive number, it overflows back into a negative). Not handling this + * case would often result in infinite recursion. + * + * @class Represents the BSON Long type. + * @param {Number} low the low (signed) 32 bits of the Long. + * @param {Number} high the high (signed) 32 bits of the Long. + */ +function Long(low, high) { + this._bsontype = 'Long'; + /** + * @type {number} + * @api private + */ + this.low_ = low | 0; // force into 32 signed bits. + + /** + * @type {number} + * @api private + */ + this.high_ = high | 0; // force into 32 signed bits. +}; + +/** + * Return the int value. + * + * @return {Number} the value, assuming it is a 32-bit integer. + * @api public + */ +Long.prototype.toInt = function() { + return this.low_; +}; + +/** + * Return the Number value. + * + * @return {Number} the closest floating-point representation to this value. + * @api public + */ +Long.prototype.toNumber = function() { + return this.high_ * Long.TWO_PWR_32_DBL_ + + this.getLowBitsUnsigned(); +}; + +/** + * Return the JSON value. + * + * @return {String} the JSON representation. + * @api public + */ +Long.prototype.toJSON = function() { + return this.toString(); +} + +/** + * Return the String value. + * + * @param {Number} [opt_radix] the radix in which the text should be written. + * @return {String} the textual representation of this value. + * @api public + */ +Long.prototype.toString = function(opt_radix) { + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (this.isZero()) { + return '0'; + } + + if (this.isNegative()) { + if (this.equals(Long.MIN_VALUE)) { + // We need to change the Long value before it can be negated, so we remove + // the bottom-most digit in this base and then recurse to do the rest. + var radixLong = Long.fromNumber(radix); + var div = this.div(radixLong); + var rem = div.multiply(radixLong).subtract(this); + return div.toString(radix) + rem.toInt().toString(radix); + } else { + return '-' + this.negate().toString(radix); + } + } + + // Do several (6) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = Long.fromNumber(Math.pow(radix, 6)); + + var rem = this; + var result = ''; + while (true) { + var remDiv = rem.div(radixToPower); + var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt(); + var digits = intval.toString(radix); + + rem = remDiv; + if (rem.isZero()) { + return digits + result; + } else { + while (digits.length < 6) { + digits = '0' + digits; + } + result = '' + digits + result; + } + } +}; + +/** + * Return the high 32-bits value. + * + * @return {Number} the high 32-bits as a signed value. + * @api public + */ +Long.prototype.getHighBits = function() { + return this.high_; +}; + +/** + * Return the low 32-bits value. + * + * @return {Number} the low 32-bits as a signed value. + * @api public + */ +Long.prototype.getLowBits = function() { + return this.low_; +}; + +/** + * Return the low unsigned 32-bits value. + * + * @return {Number} the low 32-bits as an unsigned value. + * @api public + */ +Long.prototype.getLowBitsUnsigned = function() { + return (this.low_ >= 0) ? + this.low_ : Long.TWO_PWR_32_DBL_ + this.low_; +}; + +/** + * Returns the number of bits needed to represent the absolute value of this Long. + * + * @return {Number} Returns the number of bits needed to represent the absolute value of this Long. + * @api public + */ +Long.prototype.getNumBitsAbs = function() { + if (this.isNegative()) { + if (this.equals(Long.MIN_VALUE)) { + return 64; + } else { + return this.negate().getNumBitsAbs(); + } + } else { + var val = this.high_ != 0 ? this.high_ : this.low_; + for (var bit = 31; bit > 0; bit--) { + if ((val & (1 << bit)) != 0) { + break; + } + } + return this.high_ != 0 ? bit + 33 : bit + 1; + } +}; + +/** + * Return whether this value is zero. + * + * @return {Boolean} whether this value is zero. + * @api public + */ +Long.prototype.isZero = function() { + return this.high_ == 0 && this.low_ == 0; +}; + +/** + * Return whether this value is negative. + * + * @return {Boolean} whether this value is negative. + * @api public + */ +Long.prototype.isNegative = function() { + return this.high_ < 0; +}; + +/** + * Return whether this value is odd. + * + * @return {Boolean} whether this value is odd. + * @api public + */ +Long.prototype.isOdd = function() { + return (this.low_ & 1) == 1; +}; + +/** + * Return whether this Long equals the other + * + * @param {Long} other Long to compare against. + * @return {Boolean} whether this Long equals the other + * @api public + */ +Long.prototype.equals = function(other) { + return (this.high_ == other.high_) && (this.low_ == other.low_); +}; + +/** + * Return whether this Long does not equal the other. + * + * @param {Long} other Long to compare against. + * @return {Boolean} whether this Long does not equal the other. + * @api public + */ +Long.prototype.notEquals = function(other) { + return (this.high_ != other.high_) || (this.low_ != other.low_); +}; + +/** + * Return whether this Long is less than the other. + * + * @param {Long} other Long to compare against. + * @return {Boolean} whether this Long is less than the other. + * @api public + */ +Long.prototype.lessThan = function(other) { + return this.compare(other) < 0; +}; + +/** + * Return whether this Long is less than or equal to the other. + * + * @param {Long} other Long to compare against. + * @return {Boolean} whether this Long is less than or equal to the other. + * @api public + */ +Long.prototype.lessThanOrEqual = function(other) { + return this.compare(other) <= 0; +}; + +/** + * Return whether this Long is greater than the other. + * + * @param {Long} other Long to compare against. + * @return {Boolean} whether this Long is greater than the other. + * @api public + */ +Long.prototype.greaterThan = function(other) { + return this.compare(other) > 0; +}; + +/** + * Return whether this Long is greater than or equal to the other. + * + * @param {Long} other Long to compare against. + * @return {Boolean} whether this Long is greater than or equal to the other. + * @api public + */ +Long.prototype.greaterThanOrEqual = function(other) { + return this.compare(other) >= 0; +}; + +/** + * Compares this Long with the given one. + * + * @param {Long} other Long to compare against. + * @return {Boolean} 0 if they are the same, 1 if the this is greater, and -1 if the given one is greater. + * @api public + */ +Long.prototype.compare = function(other) { + if (this.equals(other)) { + return 0; + } + + var thisNeg = this.isNegative(); + var otherNeg = other.isNegative(); + if (thisNeg && !otherNeg) { + return -1; + } + if (!thisNeg && otherNeg) { + return 1; + } + + // at this point, the signs are the same, so subtraction will not overflow + if (this.subtract(other).isNegative()) { + return -1; + } else { + return 1; + } +}; + +/** + * The negation of this value. + * + * @return {Long} the negation of this value. + * @api public + */ +Long.prototype.negate = function() { + if (this.equals(Long.MIN_VALUE)) { + return Long.MIN_VALUE; + } else { + return this.not().add(Long.ONE); + } +}; + +/** + * Returns the sum of this and the given Long. + * + * @param {Long} other Long to add to this one. + * @return {Long} the sum of this and the given Long. + * @api public + */ +Long.prototype.add = function(other) { + // Divide each number into 4 chunks of 16 bits, and then sum the chunks. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 + b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 + b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 + b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 + b48; + c48 &= 0xFFFF; + return Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); +}; + +/** + * Returns the difference of this and the given Long. + * + * @param {Long} other Long to subtract from this. + * @return {Long} the difference of this and the given Long. + * @api public + */ +Long.prototype.subtract = function(other) { + return this.add(other.negate()); +}; + +/** + * Returns the product of this and the given Long. + * + * @param {Long} other Long to multiply with this. + * @return {Long} the product of this and the other. + * @api public + */ +Long.prototype.multiply = function(other) { + if (this.isZero()) { + return Long.ZERO; + } else if (other.isZero()) { + return Long.ZERO; + } + + if (this.equals(Long.MIN_VALUE)) { + return other.isOdd() ? Long.MIN_VALUE : Long.ZERO; + } else if (other.equals(Long.MIN_VALUE)) { + return this.isOdd() ? Long.MIN_VALUE : Long.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().multiply(other.negate()); + } else { + return this.negate().multiply(other).negate(); + } + } else if (other.isNegative()) { + return this.multiply(other.negate()).negate(); + } + + // If both Longs are small, use float multiplication + if (this.lessThan(Long.TWO_PWR_24_) && + other.lessThan(Long.TWO_PWR_24_)) { + return Long.fromNumber(this.toNumber() * other.toNumber()); + } + + // Divide each Long into 4 chunks of 16 bits, and then add up 4x4 products. + // We can skip products that would overflow. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 * b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 * b00; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c16 += a00 * b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 * b00; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a16 * b16; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a00 * b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48; + c48 &= 0xFFFF; + return Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32); +}; + +/** + * Returns this Long divided by the given one. + * + * @param {Long} other Long by which to divide. + * @return {Long} this Long divided by the given one. + * @api public + */ +Long.prototype.div = function(other) { + if (other.isZero()) { + throw Error('division by zero'); + } else if (this.isZero()) { + return Long.ZERO; + } + + if (this.equals(Long.MIN_VALUE)) { + if (other.equals(Long.ONE) || + other.equals(Long.NEG_ONE)) { + return Long.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE + } else if (other.equals(Long.MIN_VALUE)) { + return Long.ONE; + } else { + // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|. + var halfThis = this.shiftRight(1); + var approx = halfThis.div(other).shiftLeft(1); + if (approx.equals(Long.ZERO)) { + return other.isNegative() ? Long.ONE : Long.NEG_ONE; + } else { + var rem = this.subtract(other.multiply(approx)); + var result = approx.add(rem.div(other)); + return result; + } + } + } else if (other.equals(Long.MIN_VALUE)) { + return Long.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().div(other.negate()); + } else { + return this.negate().div(other).negate(); + } + } else if (other.isNegative()) { + return this.div(other.negate()).negate(); + } + + // Repeat the following until the remainder is less than other: find a + // floating-point that approximates remainder / other *from below*, add this + // into the result, and subtract it from the remainder. It is critical that + // the approximate value is less than or equal to the real value so that the + // remainder never becomes negative. + var res = Long.ZERO; + var rem = this; + while (rem.greaterThanOrEqual(other)) { + // Approximate the result of division. This may be a little greater or + // smaller than the actual value. + var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber())); + + // We will tweak the approximate result by changing it in the 48-th digit or + // the smallest non-fractional digit, whichever is larger. + var log2 = Math.ceil(Math.log(approx) / Math.LN2); + var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48); + + // Decrease the approximation until it is smaller than the remainder. Note + // that if it is too large, the product overflows and is negative. + var approxRes = Long.fromNumber(approx); + var approxRem = approxRes.multiply(other); + while (approxRem.isNegative() || approxRem.greaterThan(rem)) { + approx -= delta; + approxRes = Long.fromNumber(approx); + approxRem = approxRes.multiply(other); + } + + // We know the answer can't be zero... and actually, zero would cause + // infinite recursion since we would make no progress. + if (approxRes.isZero()) { + approxRes = Long.ONE; + } + + res = res.add(approxRes); + rem = rem.subtract(approxRem); + } + return res; +}; + +/** + * Returns this Long modulo the given one. + * + * @param {Long} other Long by which to mod. + * @return {Long} this Long modulo the given one. + * @api public + */ +Long.prototype.modulo = function(other) { + return this.subtract(this.div(other).multiply(other)); +}; + +/** + * The bitwise-NOT of this value. + * + * @return {Long} the bitwise-NOT of this value. + * @api public + */ +Long.prototype.not = function() { + return Long.fromBits(~this.low_, ~this.high_); +}; + +/** + * Returns the bitwise-AND of this Long and the given one. + * + * @param {Long} other the Long with which to AND. + * @return {Long} the bitwise-AND of this and the other. + * @api public + */ +Long.prototype.and = function(other) { + return Long.fromBits(this.low_ & other.low_, this.high_ & other.high_); +}; + +/** + * Returns the bitwise-OR of this Long and the given one. + * + * @param {Long} other the Long with which to OR. + * @return {Long} the bitwise-OR of this and the other. + * @api public + */ +Long.prototype.or = function(other) { + return Long.fromBits(this.low_ | other.low_, this.high_ | other.high_); +}; + +/** + * Returns the bitwise-XOR of this Long and the given one. + * + * @param {Long} other the Long with which to XOR. + * @return {Long} the bitwise-XOR of this and the other. + * @api public + */ +Long.prototype.xor = function(other) { + return Long.fromBits(this.low_ ^ other.low_, this.high_ ^ other.high_); +}; + +/** + * Returns this Long with bits shifted to the left by the given amount. + * + * @param {Number} numBits the number of bits by which to shift. + * @return {Long} this shifted to the left by the given amount. + * @api public + */ +Long.prototype.shiftLeft = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var low = this.low_; + if (numBits < 32) { + var high = this.high_; + return Long.fromBits( + low << numBits, + (high << numBits) | (low >>> (32 - numBits))); + } else { + return Long.fromBits(0, low << (numBits - 32)); + } + } +}; + +/** + * Returns this Long with bits shifted to the right by the given amount. + * + * @param {Number} numBits the number of bits by which to shift. + * @return {Long} this shifted to the right by the given amount. + * @api public + */ +Long.prototype.shiftRight = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return Long.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >> numBits); + } else { + return Long.fromBits( + high >> (numBits - 32), + high >= 0 ? 0 : -1); + } + } +}; + +/** + * Returns this Long with bits shifted to the right by the given amount, with the new top bits matching the current sign bit. + * + * @param {Number} numBits the number of bits by which to shift. + * @return {Long} this shifted to the right by the given amount, with zeros placed into the new leading bits. + * @api public + */ +Long.prototype.shiftRightUnsigned = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return Long.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >>> numBits); + } else if (numBits == 32) { + return Long.fromBits(high, 0); + } else { + return Long.fromBits(high >>> (numBits - 32), 0); + } + } +}; + +/** + * Returns a Long representing the given (32-bit) integer value. + * + * @param {Number} value the 32-bit integer in question. + * @return {Long} the corresponding Long value. + * @api public + */ +Long.fromInt = function(value) { + if (-128 <= value && value < 128) { + var cachedObj = Long.INT_CACHE_[value]; + if (cachedObj) { + return cachedObj; + } + } + + var obj = new Long(value | 0, value < 0 ? -1 : 0); + if (-128 <= value && value < 128) { + Long.INT_CACHE_[value] = obj; + } + return obj; +}; + +/** + * Returns a Long representing the given value, provided that it is a finite number. Otherwise, zero is returned. + * + * @param {Number} value the number in question. + * @return {Long} the corresponding Long value. + * @api public + */ +Long.fromNumber = function(value) { + if (isNaN(value) || !isFinite(value)) { + return Long.ZERO; + } else if (value <= -Long.TWO_PWR_63_DBL_) { + return Long.MIN_VALUE; + } else if (value + 1 >= Long.TWO_PWR_63_DBL_) { + return Long.MAX_VALUE; + } else if (value < 0) { + return Long.fromNumber(-value).negate(); + } else { + return new Long( + (value % Long.TWO_PWR_32_DBL_) | 0, + (value / Long.TWO_PWR_32_DBL_) | 0); + } +}; + +/** + * Returns a Long representing the 64-bit integer that comes by concatenating the given high and low bits. Each is assumed to use 32 bits. + * + * @param {Number} lowBits the low 32-bits. + * @param {Number} highBits the high 32-bits. + * @return {Long} the corresponding Long value. + * @api public + */ +Long.fromBits = function(lowBits, highBits) { + return new Long(lowBits, highBits); +}; + +/** + * Returns a Long representation of the given string, written using the given radix. + * + * @param {String} str the textual representation of the Long. + * @param {Number} opt_radix the radix in which the text is written. + * @return {Long} the corresponding Long value. + * @api public + */ +Long.fromString = function(str, opt_radix) { + if (str.length == 0) { + throw Error('number format error: empty string'); + } + + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (str.charAt(0) == '-') { + return Long.fromString(str.substring(1), radix).negate(); + } else if (str.indexOf('-') >= 0) { + throw Error('number format error: interior "-" character: ' + str); + } + + // Do several (8) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = Long.fromNumber(Math.pow(radix, 8)); + + var result = Long.ZERO; + for (var i = 0; i < str.length; i += 8) { + var size = Math.min(8, str.length - i); + var value = parseInt(str.substring(i, i + size), radix); + if (size < 8) { + var power = Long.fromNumber(Math.pow(radix, size)); + result = result.multiply(power).add(Long.fromNumber(value)); + } else { + result = result.multiply(radixToPower); + result = result.add(Long.fromNumber(value)); + } + } + return result; +}; + +// NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the +// from* methods on which they depend. + + +/** + * A cache of the Long representations of small integer values. + * @type {Object} + * @api private + */ +Long.INT_CACHE_ = {}; + +// NOTE: the compiler should inline these constant values below and then remove +// these variables, so there should be no runtime penalty for these. + +/** + * Number used repeated below in calculations. This must appear before the + * first call to any from* function below. + * @type {number} + * @api private + */ +Long.TWO_PWR_16_DBL_ = 1 << 16; + +/** + * @type {number} + * @api private + */ +Long.TWO_PWR_24_DBL_ = 1 << 24; + +/** + * @type {number} + * @api private + */ +Long.TWO_PWR_32_DBL_ = Long.TWO_PWR_16_DBL_ * Long.TWO_PWR_16_DBL_; + +/** + * @type {number} + * @api private + */ +Long.TWO_PWR_31_DBL_ = Long.TWO_PWR_32_DBL_ / 2; + +/** + * @type {number} + * @api private + */ +Long.TWO_PWR_48_DBL_ = Long.TWO_PWR_32_DBL_ * Long.TWO_PWR_16_DBL_; + +/** + * @type {number} + * @api private + */ +Long.TWO_PWR_64_DBL_ = Long.TWO_PWR_32_DBL_ * Long.TWO_PWR_32_DBL_; + +/** + * @type {number} + * @api private + */ +Long.TWO_PWR_63_DBL_ = Long.TWO_PWR_64_DBL_ / 2; + +/** @type {Long} */ +Long.ZERO = Long.fromInt(0); + +/** @type {Long} */ +Long.ONE = Long.fromInt(1); + +/** @type {Long} */ +Long.NEG_ONE = Long.fromInt(-1); + +/** @type {Long} */ +Long.MAX_VALUE = + Long.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0); + +/** @type {Long} */ +Long.MIN_VALUE = Long.fromBits(0, 0x80000000 | 0); + +/** + * @type {Long} + * @api private + */ +Long.TWO_PWR_24_ = Long.fromInt(1 << 24); + +/** + * Expose. + */ +if(typeof window === 'undefined') { + exports.Long = Long; +} \ No newline at end of file diff --git a/public/max_key.js b/public/max_key.js new file mode 100644 index 0000000..98c6ee0 --- /dev/null +++ b/public/max_key.js @@ -0,0 +1,13 @@ +/** + * A class representation of the BSON MaxKey type. + * + * @class Represents the BSON MaxKey type. + * @return {MaxKey} + */ +function MaxKey() { + this._bsontype = 'MaxKey'; +} + +if(typeof window === 'undefined') { + exports.MaxKey = MaxKey; +} \ No newline at end of file diff --git a/public/min_key.js b/public/min_key.js new file mode 100644 index 0000000..3d4e7ae --- /dev/null +++ b/public/min_key.js @@ -0,0 +1,13 @@ +/** + * A class representation of the BSON MinKey type. + * + * @class Represents the BSON MinKey type. + * @return {MinKey} + */ +function MinKey() { + this._bsontype = 'MinKey'; +} + +if(typeof window === 'undefined') { + exports.MinKey = MinKey; +} \ No newline at end of file diff --git a/public/objectid.js b/public/objectid.js new file mode 100644 index 0000000..f6a5b20 --- /dev/null +++ b/public/objectid.js @@ -0,0 +1,249 @@ +/** + * Module dependencies. + */ +if(typeof window === 'undefined') { + var BinaryParser = require('./binary_parser').BinaryParser; +} + +/** + * Machine id. + * + * Create a random 3-byte value (i.e. unique for this + * process). Other drivers use a md5 of the machine id here, but + * that would mean an asyc call to gethostname, so we don't bother. + */ +var MACHINE_ID = parseInt(Math.random() * 0xFFFFFF, 10); + +// Regular expression that checks for hex value +var checkForHexRegExp = new RegExp("^[0-9a-fA-F]{24}$"); + +/** +* Create a new ObjectID instance +* +* @class Represents the BSON ObjectID type +* @param {String|Number} id Can be a 24 byte hex string, 12 byte binary string or a Number. +* @return {Object} instance of ObjectID. +*/ +function ObjectID(id) { + this._bsontype = 'ObjectID'; + + var self = this; + // Throw an error if it's not a valid setup + if(id != null && 'number' != typeof id && (id.length != 12 && id.length != 24)) throw new Error("Argument passed in must be a single String of 12 bytes or a string of 24 hex characters in hex format"); + // Generate id based on the input + if(id == null || typeof id == 'number') { + this.id = this.generate(id); + } else if(id != null && id.length === 12) { + this.id = id; + } else if(checkForHexRegExp.test(id)) { + return ObjectID.createFromHexString(id); + } else { + this.id = id; + } + + /** + * Returns the generation time in seconds that this ID was generated. + * + * @field generationTime + * @type {Number} + * @getter + * @setter + * @property return number of seconds in the timestamp part of the 12 byte id. + */ + Object.defineProperty(this, "generationTime", { + enumerable: true + , get: function () { + return Math.floor(BinaryParser.decodeInt(this.id.substring(0,4), 32, true, true)); + } + , set: function (value) { + var value = BinaryParser.encodeInt(value, 32, true, true); + this.id = value + this.id.substr(4); + } + }); +}; + +/** +* Update the ObjectID index used in generating new ObjectID's on the driver +* +* @return {Number} returns next index value. +* @api private +*/ +ObjectID.prototype.get_inc = function() { + return ObjectID.index = (ObjectID.index + 1) % 0xFFFFFF; +}; + +/** +* Update the ObjectID index used in generating new ObjectID's on the driver +* +* @return {Number} returns next index value. +* @api private +*/ +ObjectID.prototype.getInc = function() { + return this.get_inc(); +}; + +/** +* Generate a 12 byte id string used in ObjectID's +* +* @param {Number} [time] optional parameter allowing to pass in a second based timestamp. +* @return {String} return the 12 byte id binary string. +* @api private +*/ +ObjectID.prototype.generate = function(time) { + if ('number' == typeof time) { + var time4Bytes = BinaryParser.encodeInt(time, 32, true, true); + /* for time-based ObjectID the bytes following the time will be zeroed */ + var machine3Bytes = BinaryParser.encodeInt(MACHINE_ID, 24, false); + var pid2Bytes = BinaryParser.fromShort(process.pid); + var index3Bytes = BinaryParser.encodeInt(this.get_inc(), 24, false, true); + } else { + var unixTime = parseInt(Date.now()/1000,10); + var time4Bytes = BinaryParser.encodeInt(unixTime, 32, true, true); + var machine3Bytes = BinaryParser.encodeInt(MACHINE_ID, 24, false); + var pid2Bytes = BinaryParser.fromShort(process.pid); + var index3Bytes = BinaryParser.encodeInt(this.get_inc(), 24, false, true); + } + + return time4Bytes + machine3Bytes + pid2Bytes + index3Bytes; +}; + +/** +* Return the ObjectID id as a 24 byte hex string representation +* +* @return {String} return the 24 byte hex string representation. +* @api public +*/ +ObjectID.prototype.toHexString = function() { + if(this.__id) return this.__id; + + var hexString = '' + , number + , value; + + for (var index = 0, len = this.id.length; index < len; index++) { + value = BinaryParser.toByte(this.id[index]); + number = value <= 15 + ? '0' + value.toString(16) + : value.toString(16); + hexString = hexString + number; + } + + return this.__id = hexString; +}; + +/** +* Converts the id into a 24 byte hex string for printing +* +* @return {String} return the 24 byte hex string representation. +* @api private +*/ +ObjectID.prototype.toString = function() { + return this.toHexString(); +}; + +/** +* Converts to a string representation of this Id. +* +* @return {String} return the 24 byte hex string representation. +* @api private +*/ +ObjectID.prototype.inspect = ObjectID.prototype.toString; + +/** +* Converts to its JSON representation. +* +* @return {String} return the 24 byte hex string representation. +* @api private +*/ +ObjectID.prototype.toJSON = function() { + return this.toHexString(); +}; + +/** +* Compares the equality of this ObjectID with `otherID`. +* +* @param {Object} otherID ObjectID instance to compare against. +* @return {Bool} the result of comparing two ObjectID's +* @api public +*/ +ObjectID.prototype.equals = function equals (otherID) { + var id = (otherID instanceof ObjectID || otherID.toHexString) + ? otherID.id + : ObjectID.createFromHexString(otherID).id; + + return this.id === id; +} + +/** +* Returns the generation time in seconds that this ID was generated. +* +* @return {Number} return number of seconds in the timestamp part of the 12 byte id. +* @api public +*/ +ObjectID.prototype.getTimestamp = function() { + var timestamp = new Date(); + timestamp.setTime(Math.floor(BinaryParser.decodeInt(this.id.substring(0,4), 32, true, true)) * 1000); + return timestamp; +} + +/** +* @ignore +* @api private +*/ +ObjectID.index = 0; + +ObjectID.createPk = function createPk () { + return new ObjectID(); +}; + +/** +* Creates an ObjectID from a second based number, with the rest of the ObjectID zeroed out. Used for comparisons or sorting the ObjectID. +* +* @param {Number} time an integer number representing a number of seconds. +* @return {ObjectID} return the created ObjectID +* @api public +*/ +ObjectID.createFromTime = function createFromHexString(time) { + var time4Bytes = BinaryParser.encodeInt(time, 32, true, true); + var objectID = new ObjectID(); + objectID.id = BinaryParser.encodeInt(time, 32, true, true) + BinaryParser.encodeInt(0, 64, true, true) + return objectID; +}; + +/** +* Creates an ObjectID from a hex string representation of an ObjectID. +* +* @param {String} hexString create a ObjectID from a passed in 24 byte hexstring. +* @return {ObjectID} return the created ObjectID +* @api public +*/ +ObjectID.createFromHexString = function createFromHexString (hexString) { + // Throw an error if it's not a valid setup + if(hexString != null && hexString.length != 24) throw new Error("Argument passed in must be a single String of 12 bytes or a string of 24 hex characters in hex format"); + + var len = hexString.length; + + if(len > 12*2) { + throw new Error('Id cannot be longer than 12 bytes'); + } + + var result = '' + , string + , number; + + for (var index = 0; index < len; index += 2) { + string = hexString.substr(index, 2); + number = parseInt(string, 16); + result += BinaryParser.fromByte(number); + } + + return new ObjectID(result); +}; + +/** + * Expose. + */ +if(typeof window === 'undefined') { + exports.ObjectID = ObjectID; +} + diff --git a/public/resources/audio/capman-ingame.mp3 b/public/resources/audio/capman-ingame.mp3 new file mode 100644 index 0000000..0b1d858 Binary files /dev/null and b/public/resources/audio/capman-ingame.mp3 differ diff --git a/public/resources/audio/capman-ingame.ogg b/public/resources/audio/capman-ingame.ogg new file mode 100644 index 0000000..2c35939 Binary files /dev/null and b/public/resources/audio/capman-ingame.ogg differ diff --git a/public/resources/audio/coin.mp3 b/public/resources/audio/coin.mp3 new file mode 100644 index 0000000..eda4dfd Binary files /dev/null and b/public/resources/audio/coin.mp3 differ diff --git a/public/resources/audio/coin.ogg b/public/resources/audio/coin.ogg new file mode 100644 index 0000000..5cfb9c0 Binary files /dev/null and b/public/resources/audio/coin.ogg differ diff --git a/public/resources/audio/die.mp3 b/public/resources/audio/die.mp3 new file mode 100644 index 0000000..9d8d0e5 Binary files /dev/null and b/public/resources/audio/die.mp3 differ diff --git a/public/resources/audio/die.ogg b/public/resources/audio/die.ogg new file mode 100644 index 0000000..da474bd Binary files /dev/null and b/public/resources/audio/die.ogg differ diff --git a/public/resources/audio/eat.mp3 b/public/resources/audio/eat.mp3 new file mode 100644 index 0000000..da3703d Binary files /dev/null and b/public/resources/audio/eat.mp3 differ diff --git a/public/resources/audio/eat.ogg b/public/resources/audio/eat.ogg new file mode 100644 index 0000000..62c25bf Binary files /dev/null and b/public/resources/audio/eat.ogg differ diff --git a/public/resources/audio/halloffame-theme.mp3 b/public/resources/audio/halloffame-theme.mp3 new file mode 100644 index 0000000..c35c26b Binary files /dev/null and b/public/resources/audio/halloffame-theme.mp3 differ diff --git a/public/resources/audio/halloffame-theme.ogg b/public/resources/audio/halloffame-theme.ogg new file mode 100644 index 0000000..70acf8d Binary files /dev/null and b/public/resources/audio/halloffame-theme.ogg differ diff --git a/public/resources/audio/laser.mp3 b/public/resources/audio/laser.mp3 new file mode 100644 index 0000000..6bd69a4 Binary files /dev/null and b/public/resources/audio/laser.mp3 differ diff --git a/public/resources/audio/laser.ogg b/public/resources/audio/laser.ogg new file mode 100644 index 0000000..2a54b13 Binary files /dev/null and b/public/resources/audio/laser.ogg differ diff --git a/public/resources/audio/powerup3.mp3 b/public/resources/audio/powerup3.mp3 new file mode 100644 index 0000000..18b8d23 Binary files /dev/null and b/public/resources/audio/powerup3.mp3 differ diff --git a/public/resources/audio/powerup3.ogg b/public/resources/audio/powerup3.ogg new file mode 100644 index 0000000..9d2a471 Binary files /dev/null and b/public/resources/audio/powerup3.ogg differ diff --git a/public/resources/audio/select.mp3 b/public/resources/audio/select.mp3 new file mode 100644 index 0000000..fd5ceec Binary files /dev/null and b/public/resources/audio/select.mp3 differ diff --git a/public/resources/audio/select.ogg b/public/resources/audio/select.ogg new file mode 100644 index 0000000..0829a93 Binary files /dev/null and b/public/resources/audio/select.ogg differ diff --git a/public/resources/audio/start.mp3 b/public/resources/audio/start.mp3 new file mode 100644 index 0000000..01de403 Binary files /dev/null and b/public/resources/audio/start.mp3 differ diff --git a/public/resources/audio/start.ogg b/public/resources/audio/start.ogg new file mode 100644 index 0000000..a6bccd4 Binary files /dev/null and b/public/resources/audio/start.ogg differ diff --git a/public/resources/capman/cels.png b/public/resources/capman/cels.png new file mode 100644 index 0000000..cd76f6d Binary files /dev/null and b/public/resources/capman/cels.png differ diff --git a/public/resources/capman/font.png b/public/resources/capman/font.png new file mode 100644 index 0000000..89d9c09 Binary files /dev/null and b/public/resources/capman/font.png differ diff --git a/public/resources/capman/logo.png b/public/resources/capman/logo.png new file mode 100644 index 0000000..17885d9 Binary files /dev/null and b/public/resources/capman/logo.png differ diff --git a/public/resources/halloffame/font.png b/public/resources/halloffame/font.png new file mode 100644 index 0000000..301219a Binary files /dev/null and b/public/resources/halloffame/font.png differ diff --git a/public/resources/halloffame/kesiev.png b/public/resources/halloffame/kesiev.png new file mode 100644 index 0000000..bbcc12d Binary files /dev/null and b/public/resources/halloffame/kesiev.png differ diff --git a/public/resources/halloffame/logo.png b/public/resources/halloffame/logo.png new file mode 100644 index 0000000..d80063f Binary files /dev/null and b/public/resources/halloffame/logo.png differ diff --git a/public/symbol.js b/public/symbol.js new file mode 100644 index 0000000..22d57d9 --- /dev/null +++ b/public/symbol.js @@ -0,0 +1,49 @@ +/** + * A class representation of the BSON Symbol type. + * + * @class Represents the BSON Symbol type. + * @param {String} value the string representing the symbol. + * @return {Symbol} + */ +function Symbol(value) { + this._bsontype = 'Symbol'; + this.value = value; +} + +/** + * Access the wrapped string value. + * + * @return {String} returns the wrapped string. + * @api public + */ +Symbol.prototype.valueOf = function() { + return this.value; +}; + +/** + * @ignore + * @api private + */ +Symbol.prototype.toString = function() { + return this.value; +} + +/** + * @ignore + * @api private + */ +Symbol.prototype.inspect = function() { + return this.value; +} + +/** + * @ignore + * @api private + */ +Symbol.prototype.toJSON = function() { + return this.value; +} + +if(typeof window === 'undefined') { + exports.Symbol = Symbol; +} \ No newline at end of file diff --git a/public/timestamp.js b/public/timestamp.js new file mode 100644 index 0000000..f417892 --- /dev/null +++ b/public/timestamp.js @@ -0,0 +1,854 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Copyright 2009 Google Inc. All Rights Reserved + +/** + * Defines a Timestamp class for representing a 64-bit two's-complement + * integer value, which faithfully simulates the behavior of a Java "Timestamp". This + * implementation is derived from TimestampLib in GWT. + * + * Constructs a 64-bit two's-complement integer, given its low and high 32-bit + * values as *signed* integers. See the from* functions below for more + * convenient ways of constructing Timestamps. + * + * The internal representation of a Timestamp is the two given signed, 32-bit values. + * We use 32-bit pieces because these are the size of integers on which + * Javascript performs bit-operations. For operations like addition and + * multiplication, we split each number into 16-bit pieces, which can easily be + * multiplied within Javascript's floating-point representation without overflow + * or change in sign. + * + * In the algorithms below, we frequently reduce the negative case to the + * positive case by negating the input(s) and then post-processing the result. + * Note that we must ALWAYS check specially whether those values are MIN_VALUE + * (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as + * a positive number, it overflows back into a negative). Not handling this + * case would often result in infinite recursion. + * + * @class Represents the BSON Timestamp type. + * @param {Number} low the low (signed) 32 bits of the Timestamp. + * @param {Number} high the high (signed) 32 bits of the Timestamp. + */ +function Timestamp(low, high) { + this._bsontype = 'Timestamp'; + /** + * @type {number} + * @api private + */ + this.low_ = low | 0; // force into 32 signed bits. + + /** + * @type {number} + * @api private + */ + this.high_ = high | 0; // force into 32 signed bits. +}; + +/** + * Return the int value. + * + * @return {Number} the value, assuming it is a 32-bit integer. + * @api public + */ +Timestamp.prototype.toInt = function() { + return this.low_; +}; + +/** + * Return the Number value. + * + * @return {Number} the closest floating-point representation to this value. + * @api public + */ +Timestamp.prototype.toNumber = function() { + return this.high_ * Timestamp.TWO_PWR_32_DBL_ + + this.getLowBitsUnsigned(); +}; + +/** + * Return the JSON value. + * + * @return {String} the JSON representation. + * @api public + */ +Timestamp.prototype.toJSON = function() { + return this.toString(); +} + +/** + * Return the String value. + * + * @param {Number} [opt_radix] the radix in which the text should be written. + * @return {String} the textual representation of this value. + * @api public + */ +Timestamp.prototype.toString = function(opt_radix) { + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (this.isZero()) { + return '0'; + } + + if (this.isNegative()) { + if (this.equals(Timestamp.MIN_VALUE)) { + // We need to change the Timestamp value before it can be negated, so we remove + // the bottom-most digit in this base and then recurse to do the rest. + var radixTimestamp = Timestamp.fromNumber(radix); + var div = this.div(radixTimestamp); + var rem = div.multiply(radixTimestamp).subtract(this); + return div.toString(radix) + rem.toInt().toString(radix); + } else { + return '-' + this.negate().toString(radix); + } + } + + // Do several (6) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = Timestamp.fromNumber(Math.pow(radix, 6)); + + var rem = this; + var result = ''; + while (true) { + var remDiv = rem.div(radixToPower); + var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt(); + var digits = intval.toString(radix); + + rem = remDiv; + if (rem.isZero()) { + return digits + result; + } else { + while (digits.length < 6) { + digits = '0' + digits; + } + result = '' + digits + result; + } + } +}; + +/** + * Return the high 32-bits value. + * + * @return {Number} the high 32-bits as a signed value. + * @api public + */ +Timestamp.prototype.getHighBits = function() { + return this.high_; +}; + +/** + * Return the low 32-bits value. + * + * @return {Number} the low 32-bits as a signed value. + * @api public + */ +Timestamp.prototype.getLowBits = function() { + return this.low_; +}; + +/** + * Return the low unsigned 32-bits value. + * + * @return {Number} the low 32-bits as an unsigned value. + * @api public + */ +Timestamp.prototype.getLowBitsUnsigned = function() { + return (this.low_ >= 0) ? + this.low_ : Timestamp.TWO_PWR_32_DBL_ + this.low_; +}; + +/** + * Returns the number of bits needed to represent the absolute value of this Timestamp. + * + * @return {Number} Returns the number of bits needed to represent the absolute value of this Timestamp. + * @api public + */ +Timestamp.prototype.getNumBitsAbs = function() { + if (this.isNegative()) { + if (this.equals(Timestamp.MIN_VALUE)) { + return 64; + } else { + return this.negate().getNumBitsAbs(); + } + } else { + var val = this.high_ != 0 ? this.high_ : this.low_; + for (var bit = 31; bit > 0; bit--) { + if ((val & (1 << bit)) != 0) { + break; + } + } + return this.high_ != 0 ? bit + 33 : bit + 1; + } +}; + +/** + * Return whether this value is zero. + * + * @return {Boolean} whether this value is zero. + * @api public + */ +Timestamp.prototype.isZero = function() { + return this.high_ == 0 && this.low_ == 0; +}; + +/** + * Return whether this value is negative. + * + * @return {Boolean} whether this value is negative. + * @api public + */ +Timestamp.prototype.isNegative = function() { + return this.high_ < 0; +}; + +/** + * Return whether this value is odd. + * + * @return {Boolean} whether this value is odd. + * @api public + */ +Timestamp.prototype.isOdd = function() { + return (this.low_ & 1) == 1; +}; + +/** + * Return whether this Timestamp equals the other + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} whether this Timestamp equals the other + * @api public + */ +Timestamp.prototype.equals = function(other) { + return (this.high_ == other.high_) && (this.low_ == other.low_); +}; + +/** + * Return whether this Timestamp does not equal the other. + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} whether this Timestamp does not equal the other. + * @api public + */ +Timestamp.prototype.notEquals = function(other) { + return (this.high_ != other.high_) || (this.low_ != other.low_); +}; + +/** + * Return whether this Timestamp is less than the other. + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} whether this Timestamp is less than the other. + * @api public + */ +Timestamp.prototype.lessThan = function(other) { + return this.compare(other) < 0; +}; + +/** + * Return whether this Timestamp is less than or equal to the other. + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} whether this Timestamp is less than or equal to the other. + * @api public + */ +Timestamp.prototype.lessThanOrEqual = function(other) { + return this.compare(other) <= 0; +}; + +/** + * Return whether this Timestamp is greater than the other. + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} whether this Timestamp is greater than the other. + * @api public + */ +Timestamp.prototype.greaterThan = function(other) { + return this.compare(other) > 0; +}; + +/** + * Return whether this Timestamp is greater than or equal to the other. + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} whether this Timestamp is greater than or equal to the other. + * @api public + */ +Timestamp.prototype.greaterThanOrEqual = function(other) { + return this.compare(other) >= 0; +}; + +/** + * Compares this Timestamp with the given one. + * + * @param {Timestamp} other Timestamp to compare against. + * @return {Boolean} 0 if they are the same, 1 if the this is greater, and -1 if the given one is greater. + * @api public + */ +Timestamp.prototype.compare = function(other) { + if (this.equals(other)) { + return 0; + } + + var thisNeg = this.isNegative(); + var otherNeg = other.isNegative(); + if (thisNeg && !otherNeg) { + return -1; + } + if (!thisNeg && otherNeg) { + return 1; + } + + // at this point, the signs are the same, so subtraction will not overflow + if (this.subtract(other).isNegative()) { + return -1; + } else { + return 1; + } +}; + +/** + * The negation of this value. + * + * @return {Timestamp} the negation of this value. + * @api public + */ +Timestamp.prototype.negate = function() { + if (this.equals(Timestamp.MIN_VALUE)) { + return Timestamp.MIN_VALUE; + } else { + return this.not().add(Timestamp.ONE); + } +}; + +/** + * Returns the sum of this and the given Timestamp. + * + * @param {Timestamp} other Timestamp to add to this one. + * @return {Timestamp} the sum of this and the given Timestamp. + * @api public + */ +Timestamp.prototype.add = function(other) { + // Divide each number into 4 chunks of 16 bits, and then sum the chunks. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 + b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 + b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 + b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 + b48; + c48 &= 0xFFFF; + return Timestamp.fromBits((c16 << 16) | c00, (c48 << 16) | c32); +}; + +/** + * Returns the difference of this and the given Timestamp. + * + * @param {Timestamp} other Timestamp to subtract from this. + * @return {Timestamp} the difference of this and the given Timestamp. + * @api public + */ +Timestamp.prototype.subtract = function(other) { + return this.add(other.negate()); +}; + +/** + * Returns the product of this and the given Timestamp. + * + * @param {Timestamp} other Timestamp to multiply with this. + * @return {Timestamp} the product of this and the other. + * @api public + */ +Timestamp.prototype.multiply = function(other) { + if (this.isZero()) { + return Timestamp.ZERO; + } else if (other.isZero()) { + return Timestamp.ZERO; + } + + if (this.equals(Timestamp.MIN_VALUE)) { + return other.isOdd() ? Timestamp.MIN_VALUE : Timestamp.ZERO; + } else if (other.equals(Timestamp.MIN_VALUE)) { + return this.isOdd() ? Timestamp.MIN_VALUE : Timestamp.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().multiply(other.negate()); + } else { + return this.negate().multiply(other).negate(); + } + } else if (other.isNegative()) { + return this.multiply(other.negate()).negate(); + } + + // If both Timestamps are small, use float multiplication + if (this.lessThan(Timestamp.TWO_PWR_24_) && + other.lessThan(Timestamp.TWO_PWR_24_)) { + return Timestamp.fromNumber(this.toNumber() * other.toNumber()); + } + + // Divide each Timestamp into 4 chunks of 16 bits, and then add up 4x4 products. + // We can skip products that would overflow. + + var a48 = this.high_ >>> 16; + var a32 = this.high_ & 0xFFFF; + var a16 = this.low_ >>> 16; + var a00 = this.low_ & 0xFFFF; + + var b48 = other.high_ >>> 16; + var b32 = other.high_ & 0xFFFF; + var b16 = other.low_ >>> 16; + var b00 = other.low_ & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 * b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 * b00; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c16 += a00 * b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 * b00; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a16 * b16; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a00 * b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48; + c48 &= 0xFFFF; + return Timestamp.fromBits((c16 << 16) | c00, (c48 << 16) | c32); +}; + +/** + * Returns this Timestamp divided by the given one. + * + * @param {Timestamp} other Timestamp by which to divide. + * @return {Timestamp} this Timestamp divided by the given one. + * @api public + */ +Timestamp.prototype.div = function(other) { + if (other.isZero()) { + throw Error('division by zero'); + } else if (this.isZero()) { + return Timestamp.ZERO; + } + + if (this.equals(Timestamp.MIN_VALUE)) { + if (other.equals(Timestamp.ONE) || + other.equals(Timestamp.NEG_ONE)) { + return Timestamp.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE + } else if (other.equals(Timestamp.MIN_VALUE)) { + return Timestamp.ONE; + } else { + // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|. + var halfThis = this.shiftRight(1); + var approx = halfThis.div(other).shiftLeft(1); + if (approx.equals(Timestamp.ZERO)) { + return other.isNegative() ? Timestamp.ONE : Timestamp.NEG_ONE; + } else { + var rem = this.subtract(other.multiply(approx)); + var result = approx.add(rem.div(other)); + return result; + } + } + } else if (other.equals(Timestamp.MIN_VALUE)) { + return Timestamp.ZERO; + } + + if (this.isNegative()) { + if (other.isNegative()) { + return this.negate().div(other.negate()); + } else { + return this.negate().div(other).negate(); + } + } else if (other.isNegative()) { + return this.div(other.negate()).negate(); + } + + // Repeat the following until the remainder is less than other: find a + // floating-point that approximates remainder / other *from below*, add this + // into the result, and subtract it from the remainder. It is critical that + // the approximate value is less than or equal to the real value so that the + // remainder never becomes negative. + var res = Timestamp.ZERO; + var rem = this; + while (rem.greaterThanOrEqual(other)) { + // Approximate the result of division. This may be a little greater or + // smaller than the actual value. + var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber())); + + // We will tweak the approximate result by changing it in the 48-th digit or + // the smallest non-fractional digit, whichever is larger. + var log2 = Math.ceil(Math.log(approx) / Math.LN2); + var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48); + + // Decrease the approximation until it is smaller than the remainder. Note + // that if it is too large, the product overflows and is negative. + var approxRes = Timestamp.fromNumber(approx); + var approxRem = approxRes.multiply(other); + while (approxRem.isNegative() || approxRem.greaterThan(rem)) { + approx -= delta; + approxRes = Timestamp.fromNumber(approx); + approxRem = approxRes.multiply(other); + } + + // We know the answer can't be zero... and actually, zero would cause + // infinite recursion since we would make no progress. + if (approxRes.isZero()) { + approxRes = Timestamp.ONE; + } + + res = res.add(approxRes); + rem = rem.subtract(approxRem); + } + return res; +}; + +/** + * Returns this Timestamp modulo the given one. + * + * @param {Timestamp} other Timestamp by which to mod. + * @return {Timestamp} this Timestamp modulo the given one. + * @api public + */ +Timestamp.prototype.modulo = function(other) { + return this.subtract(this.div(other).multiply(other)); +}; + +/** + * The bitwise-NOT of this value. + * + * @return {Timestamp} the bitwise-NOT of this value. + * @api public + */ +Timestamp.prototype.not = function() { + return Timestamp.fromBits(~this.low_, ~this.high_); +}; + +/** + * Returns the bitwise-AND of this Timestamp and the given one. + * + * @param {Timestamp} other the Timestamp with which to AND. + * @return {Timestamp} the bitwise-AND of this and the other. + * @api public + */ +Timestamp.prototype.and = function(other) { + return Timestamp.fromBits(this.low_ & other.low_, this.high_ & other.high_); +}; + +/** + * Returns the bitwise-OR of this Timestamp and the given one. + * + * @param {Timestamp} other the Timestamp with which to OR. + * @return {Timestamp} the bitwise-OR of this and the other. + * @api public + */ +Timestamp.prototype.or = function(other) { + return Timestamp.fromBits(this.low_ | other.low_, this.high_ | other.high_); +}; + +/** + * Returns the bitwise-XOR of this Timestamp and the given one. + * + * @param {Timestamp} other the Timestamp with which to XOR. + * @return {Timestamp} the bitwise-XOR of this and the other. + * @api public + */ +Timestamp.prototype.xor = function(other) { + return Timestamp.fromBits(this.low_ ^ other.low_, this.high_ ^ other.high_); +}; + +/** + * Returns this Timestamp with bits shifted to the left by the given amount. + * + * @param {Number} numBits the number of bits by which to shift. + * @return {Timestamp} this shifted to the left by the given amount. + * @api public + */ +Timestamp.prototype.shiftLeft = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var low = this.low_; + if (numBits < 32) { + var high = this.high_; + return Timestamp.fromBits( + low << numBits, + (high << numBits) | (low >>> (32 - numBits))); + } else { + return Timestamp.fromBits(0, low << (numBits - 32)); + } + } +}; + +/** + * Returns this Timestamp with bits shifted to the right by the given amount. + * + * @param {Number} numBits the number of bits by which to shift. + * @return {Timestamp} this shifted to the right by the given amount. + * @api public + */ +Timestamp.prototype.shiftRight = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return Timestamp.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >> numBits); + } else { + return Timestamp.fromBits( + high >> (numBits - 32), + high >= 0 ? 0 : -1); + } + } +}; + +/** + * Returns this Timestamp with bits shifted to the right by the given amount, with the new top bits matching the current sign bit. + * + * @param {Number} numBits the number of bits by which to shift. + * @return {Timestamp} this shifted to the right by the given amount, with zeros placed into the new leading bits. + * @api public + */ +Timestamp.prototype.shiftRightUnsigned = function(numBits) { + numBits &= 63; + if (numBits == 0) { + return this; + } else { + var high = this.high_; + if (numBits < 32) { + var low = this.low_; + return Timestamp.fromBits( + (low >>> numBits) | (high << (32 - numBits)), + high >>> numBits); + } else if (numBits == 32) { + return Timestamp.fromBits(high, 0); + } else { + return Timestamp.fromBits(high >>> (numBits - 32), 0); + } + } +}; + +/** + * Returns a Timestamp representing the given (32-bit) integer value. + * + * @param {Number} value the 32-bit integer in question. + * @return {Timestamp} the corresponding Timestamp value. + * @api public + */ +Timestamp.fromInt = function(value) { + if (-128 <= value && value < 128) { + var cachedObj = Timestamp.INT_CACHE_[value]; + if (cachedObj) { + return cachedObj; + } + } + + var obj = new Timestamp(value | 0, value < 0 ? -1 : 0); + if (-128 <= value && value < 128) { + Timestamp.INT_CACHE_[value] = obj; + } + return obj; +}; + +/** + * Returns a Timestamp representing the given value, provided that it is a finite number. Otherwise, zero is returned. + * + * @param {Number} value the number in question. + * @return {Timestamp} the corresponding Timestamp value. + * @api public + */ +Timestamp.fromNumber = function(value) { + if (isNaN(value) || !isFinite(value)) { + return Timestamp.ZERO; + } else if (value <= -Timestamp.TWO_PWR_63_DBL_) { + return Timestamp.MIN_VALUE; + } else if (value + 1 >= Timestamp.TWO_PWR_63_DBL_) { + return Timestamp.MAX_VALUE; + } else if (value < 0) { + return Timestamp.fromNumber(-value).negate(); + } else { + return new Timestamp( + (value % Timestamp.TWO_PWR_32_DBL_) | 0, + (value / Timestamp.TWO_PWR_32_DBL_) | 0); + } +}; + +/** + * Returns a Timestamp representing the 64-bit integer that comes by concatenating the given high and low bits. Each is assumed to use 32 bits. + * + * @param {Number} lowBits the low 32-bits. + * @param {Number} highBits the high 32-bits. + * @return {Timestamp} the corresponding Timestamp value. + * @api public + */ +Timestamp.fromBits = function(lowBits, highBits) { + return new Timestamp(lowBits, highBits); +}; + +/** + * Returns a Timestamp representation of the given string, written using the given radix. + * + * @param {String} str the textual representation of the Timestamp. + * @param {Number} opt_radix the radix in which the text is written. + * @return {Timestamp} the corresponding Timestamp value. + * @api public + */ +Timestamp.fromString = function(str, opt_radix) { + if (str.length == 0) { + throw Error('number format error: empty string'); + } + + var radix = opt_radix || 10; + if (radix < 2 || 36 < radix) { + throw Error('radix out of range: ' + radix); + } + + if (str.charAt(0) == '-') { + return Timestamp.fromString(str.substring(1), radix).negate(); + } else if (str.indexOf('-') >= 0) { + throw Error('number format error: interior "-" character: ' + str); + } + + // Do several (8) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = Timestamp.fromNumber(Math.pow(radix, 8)); + + var result = Timestamp.ZERO; + for (var i = 0; i < str.length; i += 8) { + var size = Math.min(8, str.length - i); + var value = parseInt(str.substring(i, i + size), radix); + if (size < 8) { + var power = Timestamp.fromNumber(Math.pow(radix, size)); + result = result.multiply(power).add(Timestamp.fromNumber(value)); + } else { + result = result.multiply(radixToPower); + result = result.add(Timestamp.fromNumber(value)); + } + } + return result; +}; + +// NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the +// from* methods on which they depend. + + +/** + * A cache of the Timestamp representations of small integer values. + * @type {Object} + * @api private + */ +Timestamp.INT_CACHE_ = {}; + +// NOTE: the compiler should inline these constant values below and then remove +// these variables, so there should be no runtime penalty for these. + +/** + * Number used repeated below in calculations. This must appear before the + * first call to any from* function below. + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_16_DBL_ = 1 << 16; + +/** + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_24_DBL_ = 1 << 24; + +/** + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_32_DBL_ = Timestamp.TWO_PWR_16_DBL_ * Timestamp.TWO_PWR_16_DBL_; + +/** + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_31_DBL_ = Timestamp.TWO_PWR_32_DBL_ / 2; + +/** + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_48_DBL_ = Timestamp.TWO_PWR_32_DBL_ * Timestamp.TWO_PWR_16_DBL_; + +/** + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_64_DBL_ = Timestamp.TWO_PWR_32_DBL_ * Timestamp.TWO_PWR_32_DBL_; + +/** + * @type {number} + * @api private + */ +Timestamp.TWO_PWR_63_DBL_ = Timestamp.TWO_PWR_64_DBL_ / 2; + +/** @type {Timestamp} */ +Timestamp.ZERO = Timestamp.fromInt(0); + +/** @type {Timestamp} */ +Timestamp.ONE = Timestamp.fromInt(1); + +/** @type {Timestamp} */ +Timestamp.NEG_ONE = Timestamp.fromInt(-1); + +/** @type {Timestamp} */ +Timestamp.MAX_VALUE = + Timestamp.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0); + +/** @type {Timestamp} */ +Timestamp.MIN_VALUE = Timestamp.fromBits(0, 0x80000000 | 0); + +/** + * @type {Timestamp} + * @api private + */ +Timestamp.TWO_PWR_24_ = Timestamp.fromInt(1 << 24); + +/** + * Expose. + */ +if(typeof window === 'undefined') { + exports.Timestamp = Timestamp; +} \ No newline at end of file diff --git a/server.js b/server.js new file mode 100644 index 0000000..6f5b939 --- /dev/null +++ b/server.js @@ -0,0 +1,78 @@ +var WebSocketServer = require('websocket').server; +// Setup of ports etc +var port = 3000; +// Create an express server instance +var express = require('express'); +var app = express.createServer(); +var mongo = require('mongodb'); + +// BSON decoder +var BSON = mongo.BSONPure.BSON; + +// console.dir(BSON) + +// Set up the configuration for the express server +app.configure(function() { + app.use(express.static(__dirname + "/public")); + app.set('views', __dirname); + app.set('view engine', 'ejs'); +}); + +// Provide the bootstrap file +app.get('/', function(req, res) { + res.render('index', { layout: false }); +}); + +// Start on port 8000 +app.listen(port, function(err) { + console.log("= server listening on :: " + port); +}); + +// Keeps all the live connections +var connections = []; + +// Websocket server +var wsServer = new WebSocketServer({ + httpServer: app, + // Firefox 7 alpha has a bug that drops the + // connection on large fragmented messages + fragmentOutgoingMessages: false +}); + +wsServer.on('request', function(request) { + // Accept the connection + var connection = request.accept('game', request.origin); + // Save the connection + connections.push(connection); + + console.log(connection.remoteAddress + " connected - Protocol Version " + connection.websocketVersion); + + // Handle closed connections + connection.on('close', function() { + console.log(connection.remoteAddress + " disconnected"); + var index = connections.indexOf(connection); + // remove the connection from the pool + if(index !== -1) { + connections.splice(index, 1); + } + }); + + // Handle incoming messages + connection.on('message', function(message) { + console.log("-------------------------------------------------- received message") + console.dir(message) + + var buffer = new Buffer(message.binaryData); + var object = BSON.deserialize(buffer); + + console.log("-------------------------------------------------- object") + console.dir(object) + + // rebroadcast command to all clients + connections.forEach(function(destination) { + destination.sendUTF(message.binaryData); + }); + }); +}); + +