diff --git a/AndroidManifest.xml b/AndroidManifest.xml new file mode 100644 index 0000000..381146e --- /dev/null +++ b/AndroidManifest.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..d60c31a --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 Library 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. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/README b/README new file mode 100644 index 0000000..9c2c966 --- /dev/null +++ b/README @@ -0,0 +1,9 @@ + +The Android port of the Frozen Bubble game. Developed with SDK v. 1.1_r1. +The code is based on the Java version of Frozen Bubble created by Glenn +Sanson. The original Frozen Bubble was created by Guillaume Cottenceau +(programming), Alexis Younes and Amaury Amblard-Ladurantie (artwork) and +Matthias Le Bidan (soundtrack). + +The Android port, just like the original Frozen Bubble, is covered by +GNU GPL v2. diff --git a/assets/levels.txt b/assets/levels.txt new file mode 100644 index 0000000..7eb0100 --- /dev/null +++ b/assets/levels.txt @@ -0,0 +1,1099 @@ +6 6 4 4 2 2 3 3 + 6 6 4 4 2 2 3 +2 2 3 3 6 6 4 4 + 2 3 3 6 6 4 4 +- - - - - - - - + - - - - - - - +- - - - - - - - + - - - - - - - +- - - - - - - - + - - - - - - - + +- 7 7 7 7 7 7 - + - 1 1 1 1 1 - +- - 2 2 2 2 - - + - - - 2 - - - +- - - 2 2 - - - + - - - 5 - - - +- - - 5 5 - - - + - - - - - - - +- - - - - - - - + - - - - - - - + +- - 7 - - 7 - - + - - 7 1 7 - - +- - - 1 2 - - - + - - 1 2 1 - - +- - - 2 5 - - - + - - 3 5 3 - - +- - - 5 3 - - - + - - - 3 - - - +- - - - - - - - + - - - - - - - + +- - - 0 0 - - - + - - 5 0 1 - - +- - 3 5 1 6 - - + - 4 3 - 6 7 - +- 7 4 - - 7 4 - + 6 7 - - - 4 3 +1 6 - - - - 3 5 + 1 - - - - - 5 +- - - - - - - - + - - - - - - - + +- - 0 0 0 0 - - + - 0 1 1 1 0 - +- 0 1 0 0 1 0 - + - 0 1 1 1 0 - +- - 0 0 0 0 - - + - - 7 - 7 - - +- - 7 7 7 7 - - + - - - - - - - +- - - - - - - - + - - - - - - - + +- 4 4 4 6 6 6 - + 4 - - - - - 6 +- 4 - - - - 6 - + 4 2 3 1 2 3 6 +- 3 1 2 3 1 2 - + - - - - - - - +- - - - - - - - + - - - - - - - +- - - - - - - - + - - - - - - - + +- 4 4 4 6 6 6 - + 4 - - - - - 6 +- 4 - - - - 6 - + 4 2 3 1 2 3 6 +- 3 1 2 3 1 2 - + - 2 3 1 2 3 - +- - - - - - - - + - - - - - - - +- - - - - - - - + - - - - - - - + +- 0 0 - - 2 2 - + - 5 - - - 3 - +- 0 - - - 6 - - + - 3 - - - 0 - +- 4 - - - 5 - - + - 2 - - - 3 - +- 2 - - - 1 - - + - 3 - - - 4 - +- - - - - - - - + - - - - - - - + +3 - - - - - - 3 + 6 3 2 4 6 3 2 +4 - - - - - - 4 + 2 4 6 3 2 4 6 +- - - 6 - - - - + - - - 3 - - - +- - - - - - - - + - - - - - - - +- - - - - - - - + - - - - - - - + +- 2 - 1 - 1 - 2 + 1 2 - 2 1 - 1 +1 - 1 - 2 - 2 - + 2 1 - 1 2 - 2 +- 2 - 2 - 2 - 2 + 1 2 - 2 1 - 1 +1 - 1 - 2 - 1 - + 2 2 - 1 1 - 2 +- 2 - 1 - 1 - 1 + - - - - - - - + +- 7 7 - - 5 5 - + 1 - - - - - 4 +2 1 - - - - 4 3 + 2 - - - - - 3 +1 2 - - - - 3 4 + 1 - - - - - 4 +7 1 - - - - 4 5 + 7 7 - - - 5 5 +- - - - - - - - + - - - - - - - + +7 7 - - - - 5 5 + 1 5 - - - 7 4 +2 1 - - - - 4 3 + 2 - - - - - 3 +1 5 - - - - 7 4 + 1 - - - - - 4 +7 1 - - - - 4 5 + 7 5 - - - 7 5 +- - - - - - - - + - - - - - - - + +- - - 0 0 - - - + - - 5 0 1 - - +- - 3 5 1 6 - - + - 4 3 2 6 2 - +- 7 4 7 2 2 4 - + 6 7 7 3 3 4 3 +1 6 1 1 1 3 3 5 + 1 1 - - - - 5 +- - - - - - - - + - - - - - - - + +- - 0 - - 0 - - + - 3 3 - 3 3 - +- 0 2 0 0 2 0 - + - 3 3 - 3 3 - +- - 0 - - 0 - - + - - - - - - - +- - - - - - - - + - - - - - - - +- - - - - - - - + - - - - - - - + +- - - 1 1 - - - + - - 2 2 2 - - +- - 3 3 3 3 - - + - 4 4 4 4 4 - +- 5 5 5 5 5 5 - + - - - 6 - - - +- - - 7 7 - - - + - - - 0 - - - +- - - - - - - - + - - - - - - - + +- - - 2 5 - - - + - 4 3 - - - - +6 7 - 5 2 - - - + - - - - 3 4 - +- - - 2 5 - 7 6 + - 4 3 - - - - +6 7 - 5 2 - - - + - - - - 3 4 - +- - - - - - 7 6 + - - - - - - - + +- - - 5 5 - - - + - - - 3 - - - +- - - 1 - - - - + - - - 7 - - - +- - - 2 - - - - + - - - 4 - - - +- - - 5 - - - - + - - - 3 - - - +- - - - - - - - + - - - - - - - + +- - - 0 1 - - - + - - 0 2 7 7 - +- - - 0 1 7 - - + - 0 0 0 0 - - +- 0 0 0 1 1 - - + 0 0 0 1 1 1 - +- 0 0 1 1 1 - - + - 0 0 0 7 7 - +- - 7 7 - - - - + - - - - - - - + +- 1 - - - - - - + 1 - - - - - - +- 2 3 4 7 6 5 - + - - - - - - 1 +- - - - - - 1 - + - 2 3 4 7 6 - +- 1 - - - - - - + 1 - - - - - - +- 2 3 4 7 6 5 - + - - - - - - - + +- 6 - - - - - - + 5 - - - - - - +2 3 4 7 6 5 2 3 + - - - - - - 4 +- - - - - - 7 - + - 4 3 2 5 6 - +- 7 - - - - - - + 6 - - - - - - +5 2 3 4 7 6 5 - + - - - - - - - + +3 2 1 0 0 1 2 3 + 3 2 1 0 1 2 3 +4 3 2 1 1 2 3 4 + 4 3 2 1 2 3 4 +5 4 3 2 2 3 4 5 + 5 4 3 2 3 4 5 +6 5 4 3 3 4 5 6 + 6 5 4 3 4 5 6 +7 6 5 4 4 5 6 7 + - - - - - - - + +- - - 5 5 - - - + - - - 3 - - - +- - - 2 4 - - - + - - - 6 - - - +- - - 2 4 - - - + - 2 - 5 - 4 - +1 0 1 0 1 0 1 0 + 3 - 3 - 2 - 6 +- - - - - - - - + - - - - - - - + +- - - - 1 - - - + 7 4 3 5 - - - +6 - - 1 - - - - + - - - 5 3 4 7 +6 - - - 1 - - 6 + 7 4 3 5 - - - +- - - 1 - - - 6 + - - - 5 3 4 7 +- - - - - - - - + - - - - - - - + +- - - - 7 3 6 - + - - 3 7 3 6 3 +- - 5 7 3 6 3 - + - 6 7 3 6 7 - +- 7 7 3 6 1 - - + 3 7 3 6 3 - - +5 6 2 7 1 - - - + - - - - - - - +- - - - - - - - + - - - - - - - + +5 - - - - - - 5 + 5 - 6 6 6 - 5 +- 5 4 - - 4 5 - + - 3 - - - 3 - +- 6 0 - - 0 6 - + - 3 - - - 3 - +- - 4 - - 4 - - + - - 6 6 6 - - +- - - - - - - - + - - - - - - - + +- 7 0 - - 0 7 - + 7 - 0 - 0 - 7 +7 1 - 0 0 - 1 7 + 7 1 2 0 2 1 7 +7 6 3 2 2 3 6 7 + 7 - 3 2 3 - 7 +- 7 7 3 3 7 7 - + - - - 3 - - - +- - - - - - - - + - - - - - - - + +- 3 - 1 - 7 - 6 + 5 - 7 - 7 - 6 +6 - 0 - 5 - 3 - + - 2 - 1 - 5 - +- 4 - 3 - 4 - - + 2 - 3 - 2 - - +- - 4 - 6 - - - + - - - 5 - - - +- - - - - - - - + - - - - - - - + +- - - - 1 - - - + - - - - 3 - - +6 1 3 1 2 1 4 1 + - - - - 6 - - +- - - 4 1 - - - + - - 1 - 3 - - +- - - 2 1 - - - + - - - - 4 - - +- - - 6 1 - - - + - - - 6 - - - + +- - - 5 4 - - - + - - 4 1 0 - - +- - - 2 3 - - - + - 1 4 - 2 2 - +- 3 1 2 5 1 4 - + - 4 2 - 0 4 - +- - - - - - - - + - - - - - - - +- - - - - - - - + - - - - - - - + +- - - - 1 - - - + - - - 1 - - - +- 2 - - 1 - 5 - + 5 - - 1 - - 0 +- 6 - - 1 - 4 - + - 0 - 1 - 5 - +- - 5 5 0 1 - - + - - - - - - - +- - - - - - - - + - - - - - - - + +- - - 6 3 - - - + - - 3 2 6 - - +- - 2 6 3 2 - - + - 6 3 2 6 3 - +- 3 2 6 3 2 6 - + 2 6 3 2 6 3 2 +6 3 2 6 3 2 6 3 + - - - - - - - +- - - - - - - - + - - - - - - - + +6 6 6 6 6 6 6 6 + 4 - - - - - - +- 3 2 5 7 6 4 3 + - 5 - - - - - +- - 7 6 4 3 2 5 + - - 4 - - - - +- - - 3 2 5 7 6 + - - - - - - - +- - - - - - - - + - - - - - - - + +1 - 7 - - 6 - 2 + 6 - 1 - 6 1 3 +- 4 - 7 2 - 7 - + 2 7 - - - 4 - +6 - 3 5 0 2 - 7 + 1 - - - - - 1 +- 1 4 5 7 5 1 - + - - - - - - - +- - - - - - - - + - - - - - - - + +6 6 6 - - 6 6 6 + - - 6 - 6 - - +- - 2 3 3 2 - - + - 3 - 5 - 3 - +- - 5 3 3 5 - - + - - 6 1 6 - - +- 4 2 - - 2 4 - + - - - - - - - +- - - - - - - - + - - - - - - - + +- - - 5 5 - - - + - - 5 - - - - +- 3 4 6 6 - - 5 + 3 3 4 6 5 - 5 +3 2 3 6 6 5 5 - + 3 3 4 6 5 - 5 +- 3 4 6 6 - - 5 + - - 5 - - - - +- - - 5 5 - - - + - - - - - - - + +1 - - - - - - 1 + 1 - 2 2 2 - 1 +- 1 2 3 3 2 1 - + 6 2 3 - 3 2 6 +6 2 3 - - 3 2 6 + 6 2 3 - 3 2 6 +3 3 3 7 7 3 3 3 + 0 5 0 2 0 5 0 +- - - - - - - - + - - - - - - - + +- - 7 7 7 - - - + - 7 2 2 7 - - +- 7 5 5 5 7 - - + 7 7 7 7 7 7 - +- - 6 - 6 - - - + - 6 - - 6 - - +- 6 4 4 - 6 4 4 + - - - - - - - +- - - - - - - - + - - - - - - - + +- 3 3 - 3 3 3 - + 3 7 5 4 6 5 3 +1 3 3 3 - 3 3 1 + 2 1 2 1 2 1 2 +1 3 3 - 3 3 3 1 + 3 5 6 4 5 7 3 +2 3 3 3 - 3 3 2 + 1 1 2 2 2 1 1 +- - - - - - - - + - - - - - - - + +- 6 5 - - - - - + 3 1 3 - - - - +- 5 6 - - - - - + - - 5 3 - - - +- - 6 1 6 - - - + - - 3 5 - - - +- - - - 3 6 - - + - - - 5 6 5 - +- - - - 6 3 - - + - - - - - - - + +6 3 7 4 5 1 6 3 + 5 1 6 3 7 4 5 +6 3 7 4 5 1 6 3 + - - - - - - - +- - - - - - - - + - - - - - - - +- - - - - - - - + - - - - - - - +- - - - - - - - + - - - - - - - + +- - - - - - 4 4 + - - 7 7 7 4 4 +- - - - - - 4 4 + - 1 - - - 7 - +- 1 1 - - 7 - - + 3 3 3 - 7 - - +3 - 2 3 3 3 - 3 + - 2 - 3 - 3 3 +- 2 - - - - - - + - - - - - - - + +- - 4 - - - - - + - 7 4 - - - - +- - 7 4 - - - - + - 4 7 4 - - - +1 1 1 1 1 1 1 - + 1 2 1 2 1 1 - +2 2 2 2 2 2 2 2 + - - - - - - - +- - - - - - - - + - - - - - - - + +0 - - - - - - 6 + 6 1 4 3 7 5 0 +0 - - - - - - 6 + 6 1 4 3 7 5 0 +0 - - - - - - 6 + 6 1 4 3 7 5 0 +- - - - - - - - + - - - - - - - +- - - - - - - - + - - - - - - - + +3 3 4 6 6 4 3 3 + 0 3 4 6 4 3 1 +5 1 3 4 4 3 0 1 + 0 1 3 4 3 1 0 +2 1 6 3 3 0 0 1 + 0 3 4 3 6 1 5 +6 1 2 6 4 0 0 2 + - - - - - - - +- - - - - - - - + - - - - - - - + +6 6 - - - - 4 4 + 4 0 - - - 3 6 +0 6 - - - - 4 2 + 7 - - - - - 7 +4 4 - - - - 5 6 + 6 4 7 7 5 6 4 +- 7 6 4 6 4 7 - + - 0 - 7 - 7 - +- - - - - - - - + - - - - - - - + +- 5 - - - - 4 - + - 5 - - - 4 - +- - 5 6 6 4 - - + - - 2 - 2 - - +0 0 6 - - 6 1 1 + - - 2 - 2 - - +- - 7 6 6 3 - - + - 7 - - - 3 - +- 7 - - - - 3 - + - - - - - - - + +- 6 - - - - 2 - + 1 7 1 1 1 3 1 +- - 4 1 1 4 - - + - 1 3 1 7 1 - +- - - 2 6 - - - + - - 1 5 1 - - +- - - - - - - - + - - - - - - - +- - - - - - - - + - - - - - - - + +7 7 7 7 7 7 7 7 + 7 - - - - - 7 +7 - - 2 0 5 2 2 + 7 - - - 0 3 6 +7 - - - - - 4 0 + 5 5 - - - - - +4 3 6 2 - - - - + 0 2 0 4 - - - +- - - - - - - - + - - - - - - - + +- - 1 - - 1 - - + - 4 - - 5 - - +- 7 - - 1 1 1 - + 6 - - - - 7 - +1 1 1 1 - 4 - - + - - 5 - - - - +- - 0 - - - - - + - 3 - - - - - +- 1 - - - - - - + - - - - - - - + +- 7 7 - - 7 7 - + 6 - 4 - 4 - 6 +5 - - 3 3 - - 5 + 6 - - - - - 6 +- 7 - - - - 7 - + - 4 - - - 4 - +- - 3 - - 3 - - + - - 2 - 2 - - +- - - 5 5 - - - + - - - - - - - + +- 0 0 - - 0 0 - + 7 4 6 6 6 4 3 +5 6 6 6 2 6 6 3 + 7 4 6 6 6 4 3 +- 0 0 - - 0 0 - + - - - - - - - +- - - - - - - - + - - - - - - - +- - - - - - - - + - - - - - - - + +- - - - - 7 7 7 + - - - - 2 7 7 +- 0 7 7 7 - 7 7 + 6 7 7 7 - - - +6 - - - 7 7 7 7 + 6 - - - - - - +4 2 2 2 4 - 3 - + 4 4 4 4 3 3 3 +- - - - - - - - + - - - - - - - + +4 - - 7 - 6 - 7 + 7 6 7 - - 7 4 +- - 7 - - 7 - - + - 0 0 0 0 0 3 +- - 0 2 2 0 6 4 + - - 0 0 0 1 3 +- - - 0 0 - 3 4 + - - - 6 - 5 6 +- - - - - - 1 0 + - - - - - - - + +- 5 - - - - 5 - + 0 - - 0 - - 0 +0 0 0 2 2 0 0 0 + 0 - - 0 - - 0 +- 7 - 3 - - 7 - + - - 3 6 - - - +- - - 6 - - - - + - 3 6 - - - - +- 3 - - - - - - + - - - - - - - + +- - - 6 5 - - - + - - 2 6 3 - - +- - 5 4 7 1 - - + - 6 2 2 3 4 - +- - 3 7 3 6 - - + - - 1 3 2 - - +- - - 4 5 - - - + - - - 4 - - - +- - - - - - - - + - - - - - - - + +7 7 - 2 2 - 6 6 + 6 - - 6 - - 3 +2 - - 1 - - 2 - + 5 - - 3 - - 2 +1 - - 2 - - 1 - + 5 - - 2 - - 2 +6 - - 1 - - 7 - + 5 - - 5 - - 4 +- - - - - - - - + - - - - - - - + +- - - 6 6 - - - + - 0 4 4 4 0 - +- - - 6 6 - - - + - - 2 7 2 - - +- - - 6 6 - - - + - 0 5 5 5 0 - +- - - 3 3 - - - + - - - - - - - +- - - - - - - - + - - - - - - - + +- - 4 1 3 - - - + - 1 - - 1 - - +- - 4 1 3 4 1 - + - 1 3 4 - - 4 +- 3 - - 3 4 1 - + - 1 3 4 1 3 - +- - 4 1 - - - - + - - - - - - - +- - - - - - - - + - - - - - - - + +- 6 4 - 3 2 5 - + 0 - - - - - 1 +- 2 3 5 - 4 6 - + 0 - - - - - 1 +- 4 6 - 2 5 3 - + 0 - - - - - 1 +- 5 2 3 - 4 6 - + - - - - - - - +- - - - - - - - + - - - - - - - + +- - - 6 6 - - - + - - 7 6 4 - - +- 2 1 7 4 1 3 - + 2 1 1 1 1 1 3 +- 2 2 2 3 3 3 - + - - - 5 - - - +- - - 2 3 - - - + - - - 5 - - - +- - 2 2 3 3 - - + - - - - - - - + +4 - 5 - - 3 - 6 + 2 - 3 - 2 - 4 +4 - - 1 0 - - 6 + 6 - 2 3 5 - 4 +4 - - 0 1 - - 6 + 2 - 5 - 3 - 4 +4 - 3 - - 2 - 6 + 6 - - - - - 4 +- - - - - - - - + - - - - - - - + +2 6 0 5 5 1 3 4 + 1 - - 2 - - 0 +4 - - 3 6 - - 2 + - - - 0 - - - +- - - 1 4 - - - + - - - 2 - - - +- - - 6 3 - - - + - - - 5 - - - +- - - 4 1 - - - + - - - - - - - + +- - - - 5 1 1 3 + 0 5 1 0 5 3 3 +5 1 0 5 1 0 5 1 + 0 5 1 0 5 1 6 +- - - - 1 6 5 1 + - - - - 5 1 6 +- - - - 1 0 5 1 + - - - - 5 1 0 +- - - - - - - - + - - - - - - - + +- 0 7 3 - - 2 2 + - 0 7 3 - - 2 +- 0 7 3 - - 2 2 + - 0 7 3 - 3 1 +- 0 7 3 - 6 4 5 + - 0 7 3 - 7 0 +- 0 7 3 - 2 3 4 + - 0 7 3 - 5 6 +- - - - - 7 0 1 + - - - - - - - + +- - - 7 7 7 7 - + 3 4 5 - - - 7 +2 - - - - - - 3 + 7 - - - - - 4 +7 - - - 3 4 5 6 + 7 - - 2 0 1 2 +6 - - - 3 4 5 6 + 0 1 - - - - - +2 3 4 - - - - - + 5 6 0 - - - - + +- 7 - - - - 2 - + 1 1 - - - 3 3 +- 2 - - - - 4 - + 3 3 - - - 5 5 +- 4 - - - - 6 - + 5 5 - - - 1 1 +- 6 - - - - 7 - + - - - - - - - +- - - - - - - - + - - - - - - - + +- 4 - - - - 4 - + 2 - - 1 - - 2 +5 - - 0 0 - - 5 + 5 - - 1 - - 6 +- 4 2 7 7 5 4 - + - - - 6 - - - +- - - 3 3 - - - + - - - 7 - - - +- - - - - - - - + - - - - - - - + +- 1 - - 2 3 4 - + 2 - - 3 0 4 - +4 - - 2 3 1 - - + 3 - 4 3 0 - - +4 - - 2 5 1 - - + 3 - 4 5 0 4 - +- - - - - - - - + - - - - - - - +- - - - - - - - + - - - - - - - + +2 - - 1 1 - - 2 + 2 - 3 3 3 - 2 +- 2 - 4 4 - 2 - + - 7 7 0 7 7 - +- - - 4 4 - - - + - - 5 7 5 - - +6 3 2 6 4 2 3 6 + 5 - - - - - 1 +- - - - - - - - + - - - - - - - + +4 2 3 5 7 1 3 6 + 1 - - 1 - - 1 +3 0 1 3 2 4 3 5 + 4 - - 4 - - 4 +- 5 - - 5 - - 5 + 0 3 2 0 4 5 0 +- 6 - - 6 - - 6 + 7 - - 7 - - 7 +- - - - - - - - + - - - - - - - + +- 5 4 - 1 1 - - + 5 - 4 1 - 1 - +0 - - - - - 0 - + 0 6 4 - - 4 2 +- 4 3 5 2 6 3 6 + - 2 6 - - 5 4 +- - - - - - - - + - - - - - - - +- - - - - - - - + - - - - - - - + +- - - 6 6 - - - + - - 5 5 4 - - +- - 1 6 6 4 - - + - 1 7 2 5 3 - +- 2 7 2 1 5 3 - + 2 1 3 1 4 2 7 +- 3 1 3 4 2 7 - + - 3 5 5 6 6 - +- - - - - - - - + - - - - - - - + +- - 7 3 - - - - + - 1 7 6 - - - +- 3 7 5 1 5 - - + 7 7 0 2 4 0 4 +7 1 4 6 5 6 5 7 + 1 7 7 1 7 7 1 +- - - - - - - - + - - - - - - - +- - - - - - - - + - - - - - - - + +- - 1 - - 1 - - + - 5 6 1 5 6 - +- 1 1 2 2 1 1 - + 4 7 1 0 1 7 4 +- 3 7 5 7 5 3 - + - 1 1 1 1 1 - +- - - - - - - - + - - - - - - - +- - - - - - - - + - - - - - - - + +4 - - - 5 - - 4 + 6 6 7 6 - 4 5 +4 2 7 5 2 2 6 4 + - - 4 1 - 5 2 +- 5 2 7 7 - 7 4 + 4 6 5 4 - 4 2 +- - - 4 - 4 1 - + 0 0 0 5 - - - +- - - - 0 0 0 0 + - - - - - - - + +1 - - - 0 0 - - + 2 - - 0 1 0 - +3 - - 0 2 2 0 - + 4 - 0 1 1 1 0 +5 - - 0 4 4 0 - + 6 - - 4 4 4 - +7 - - - 4 4 - - + - - - 0 1 0 - +- - - 0 1 1 0 - + - - - - - - - + +- - 3 - - 1 7 - + - 7 4 - - 4 3 +1 - - 0 2 0 - - + 5 4 - 3 - - - +4 - 3 6 1 1 6 - + - 1 - - 4 - 1 +- 7 5 - - - 3 - + - - 3 - - - - +- - - - - - - - + - - - - - - - + +1 - - - 1 - - - + 2 - - - 2 - - +- 3 - - 3 3 - - + - 4 - 4 - 4 - +- 5 - - 5 5 - - + 6 - - 7 1 7 - +7 - - - 6 6 - - + - - - - - - - +- - - - - - - - + - - - - - - - + +2 - - 6 - 2 5 1 + 5 - 4 - 4 - 4 +6 - - 3 - - - 3 + 4 2 0 - - - 5 +- - - 6 - 3 6 - + - - 5 - 5 - - +- - - 3 - 4 2 5 + - - - - - - - +- - - - - - - - + - - - - - - - + +6 - - - 4 - - 3 + 0 3 - - 6 - 0 +- - 7 - 1 - 3 - + 7 - 4 7 - 2 - +5 2 3 2 1 6 - 3 + - - 0 4 3 5 4 +- 7 6 - - 0 - - + 4 3 - - - 4 2 +0 - - - - - 6 - + - - - - - - - + +6 1 2 5 1 6 3 0 + - - - - - - 4 +0 5 2 7 1 6 2 - + 3 - - - - - - +6 7 6 4 0 5 2 6 + - - - - - - 1 +6 1 4 0 6 2 3 - + 0 - - - - - - +- 0 4 5 3 7 6 0 + - - - - - - - + +- - - 0 1 - - - + - - 0 7 0 - - +- - 1 2 2 0 - - + - 0 7 0 7 0 - +- 6 - 7 7 - 6 - + 4 1 6 6 6 4 1 +- 5 - 7 7 - 5 - + - - - - - - - +- - - - - - - - + - - - - - - - + +- - - 5 6 - - - + - - 3 3 3 - - +- - 7 5 3 7 - - + - 3 - 6 - 3 - +2 - - 3 7 - - 1 + 2 2 - 3 - 1 1 +- 0 2 5 6 1 0 - + - - - 3 - - - +- - - 3 7 - - - + - - - - - - - + +- 6 - - - - 2 - + - 2 6 0 6 0 - +- 0 - - - - - - + 6 - - - - - - +- 3 3 2 0 6 0 0 + - 6 - - - - 0 +- - - 6 0 2 6 - + - 2 0 - - - - +- - - - - - - - + - - - - - - - + +0 7 - - - - - - + 1 5 - - - - - +7 2 5 - - - - - + 6 3 4 - - - - +5 5 4 4 - - - - + 3 3 5 3 - - - +1 2 2 5 3 - - - + 1 0 0 7 6 - - +3 3 5 5 7 6 - - + - - - - - - - + +- - 2 6 6 2 - - + - 2 1 1 0 2 - +- 2 3 2 2 0 2 - + 2 3 2 5 2 7 2 +2 4 2 5 2 7 2 0 + 2 4 2 6 6 2 0 +- 2 5 2 2 2 7 2 + - 2 5 6 6 7 2 +- - 2 2 2 2 2 - + - - - - - - - + +- - 0 - - 0 - - + 1 0 0 1 0 0 1 +1 7 7 5 5 7 7 1 + 3 2 - 2 - 2 3 +3 7 - 6 6 - 7 3 + 7 - - 6 - - 7 +4 4 5 - - 5 4 4 + - - - - - - - +- - - - - - - - + - - - - - - - + +- 6 3 - - 3 6 - + 6 - 2 - 2 - 6 +2 - 0 1 1 0 - 2 + 5 0 - 7 - 0 5 +- 5 - 6 6 - 5 - + 7 1 4 - 4 1 7 +7 - 4 - - 4 - 7 + 2 0 - - - 0 2 +- 2 - - - - 2 - + - - - - - - - + +6 1 - - - - 4 0 + 2 7 5 5 5 7 3 +6 1 - - - - 4 0 + 2 5 7 7 7 5 3 +6 1 - - - - 4 0 + 2 0 6 6 6 0 3 +6 1 - - - - 4 0 + - - - - - - - +- - - - - - - - + - - - - - - - + +5 - - 1 1 - - 5 + 5 - 4 - 4 - 5 +- 2 4 - - 4 2 - + 7 2 - - - 2 7 +0 - 0 4 4 0 - 0 + 7 2 - - - 2 7 +- 2 3 - - 3 2 - + 5 - 3 - 3 - 5 +5 - - 6 6 - - 5 + - - - - - - - + +2 2 - - - - 5 5 + 5 - - - - - 2 +5 - - - - - - 2 + 1 - 1 5 1 - 3 +5 2 5 3 1 2 5 2 + 2 0 5 - 2 0 5 +- 3 7 - - 3 7 - + - - 2 0 5 - - +- - - - - - - - + - - - - - - - + +0 6 5 2 3 4 1 7 + - - - - 1 - - +- - - 1 1 - - - + - - 1 - - - - +7 1 4 3 2 5 6 0 + - - - - 1 - - +- - - 1 1 - - - + - - 1 - - - - +0 6 5 2 3 4 1 7 + - - - - - - - + +- - 1 - - 1 - - + - 2 4 - 2 4 - +- 2 3 6 5 3 2 - + - 6 5 - 6 5 - +- - - 7 7 - - - + - - - 7 - - - +1 - - 7 7 - - 3 + 2 - - 7 - - 2 +- 3 4 5 6 4 1 - + - - - - - - - + +1 - - 2 2 - - 2 + 1 3 7 3 7 4 2 +- 1 6 - - 6 2 - + 6 - 7 3 7 - 6 +- 4 2 - - 1 3 - + - - 2 6 1 - - +- 4 3 3 4 4 3 - + - - - - - - - +- - - - - - - - + - - - - - - - + +- - - 5 6 - - - + - - - 3 - - - +- - - 1 2 - - - + - - - 4 - - - +- - - 5 7 - - - + - - - 2 - - - +6 5 4 3 2 1 7 5 + - - - - - - - +- - - - - - - - + - - - - - - - + +- 0 - 1 - 2 - - + - 4 - 5 - 6 - +- 7 - 0 - 2 - - + - 6 - 3 - 6 - +- 1 - 1 - 2 - - + - 3 - 5 - 0 - +- 2 - 4 - 6 - - + - 3 - 6 - 7 - +- - - - - - - - + - - - - - - - + +1 1 2 2 3 3 4 4 + 5 5 6 7 6 5 5 +6 4 3 3 2 2 1 6 + 4 6 5 7 6 3 1 +- - - - - - - - + - - - - - - - +- - - - - - - - + - - - - - - - +- - - - - - - - + - - - - - - - + +7 4 - 1 2 - 4 7 + 5 5 - 2 - 4 4 +- 5 - 7 7 - 4 - + 1 0 6 7 6 0 2 +- 2 - 5 3 - 1 - + 1 1 - - - 2 2 +6 1 4 - - 4 2 6 + 5 3 - - - 3 5 +- - - - - - - - + - - - - - - - + +1 5 1 0 0 1 5 1 + 1 2 5 - 5 2 1 +3 6 1 2 2 1 6 3 + 4 3 4 - 4 3 4 +3 4 6 5 5 6 4 3 + 0 2 3 - 3 2 0 +2 3 1 5 5 1 3 2 + - - - - - - - +- - - - - - - - + - - - - - - - + +3 0 2 7 5 7 6 5 + 6 - 1 - 2 - 1 +- 6 4 0 3 4 5 - + - 5 - 1 - 4 - +- 7 3 5 6 5 3 - + 1 - 2 - 4 - 2 +6 4 4 6 6 5 5 1 + - - - - - - - +- - - - - - - - + - - - - - - - diff --git a/build.xml b/build.xml new file mode 100644 index 0000000..05dd141 --- /dev/null +++ b/build.xml @@ -0,0 +1,293 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Creating output directories if needed... + + + + + + + Generating R.java / Manifest.java from the resources... + + + + + + + + + + + + + + + + + Compiling aidl files into Java classes... + + + + + + + + + + + + + + + + + + + + + Converting compiled files and external libraries into ${outdir}/${dex-file}... + + + + + + + + + + + Packaging resources and assets... + + + + + + + + + + + + + + + + + + + Packaging resources... + + + + + + + + + + + + + + + + + + + + + + + + + + Packaging ${out-debug-package}, and signing it with a debug key... + + + + + + + + + + + + + + + + + + Packaging ${out-unsigned-package} for release... + + + + + + + + + + + + + + + It will need to be signed with jarsigner before being published. + + + + + Installing ${out-debug-package} onto default emulator... + + + + + + + + Installing ${out-debug-package} onto default emulator... + + + + + + + + + + Uninstalling ${application-package} from the default emulator... + + + + + + + diff --git a/default.properties b/default.properties new file mode 100644 index 0000000..e3b90ac --- /dev/null +++ b/default.properties @@ -0,0 +1,5 @@ +# This file is automatically generated by activitycreator. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# Instead customize values in a "build.properties" file. + +sdk-folder=/home/pfedor/android/android-sdk-linux_x86-1.1_r1 diff --git a/res/drawable/background.jpg b/res/drawable/background.jpg new file mode 100644 index 0000000..ae18a7d Binary files /dev/null and b/res/drawable/background.jpg differ diff --git a/res/drawable/bubble_1.gif b/res/drawable/bubble_1.gif new file mode 100644 index 0000000..d258264 Binary files /dev/null and b/res/drawable/bubble_1.gif differ diff --git a/res/drawable/bubble_2.gif b/res/drawable/bubble_2.gif new file mode 100644 index 0000000..ccd2bd8 Binary files /dev/null and b/res/drawable/bubble_2.gif differ diff --git a/res/drawable/bubble_3.gif b/res/drawable/bubble_3.gif new file mode 100644 index 0000000..36913d2 Binary files /dev/null and b/res/drawable/bubble_3.gif differ diff --git a/res/drawable/bubble_4.gif b/res/drawable/bubble_4.gif new file mode 100644 index 0000000..c1c98fd Binary files /dev/null and b/res/drawable/bubble_4.gif differ diff --git a/res/drawable/bubble_5.gif b/res/drawable/bubble_5.gif new file mode 100644 index 0000000..4ff0cae Binary files /dev/null and b/res/drawable/bubble_5.gif differ diff --git a/res/drawable/bubble_6.gif b/res/drawable/bubble_6.gif new file mode 100644 index 0000000..5430781 Binary files /dev/null and b/res/drawable/bubble_6.gif differ diff --git a/res/drawable/bubble_7.gif b/res/drawable/bubble_7.gif new file mode 100644 index 0000000..3887368 Binary files /dev/null and b/res/drawable/bubble_7.gif differ diff --git a/res/drawable/bubble_8.gif b/res/drawable/bubble_8.gif new file mode 100644 index 0000000..cb71b26 Binary files /dev/null and b/res/drawable/bubble_8.gif differ diff --git a/res/drawable/bubble_blink.gif b/res/drawable/bubble_blink.gif new file mode 100644 index 0000000..5789eba Binary files /dev/null and b/res/drawable/bubble_blink.gif differ diff --git a/res/drawable/bubble_colourblind_1.gif b/res/drawable/bubble_colourblind_1.gif new file mode 100644 index 0000000..0f393b7 Binary files /dev/null and b/res/drawable/bubble_colourblind_1.gif differ diff --git a/res/drawable/bubble_colourblind_2.gif b/res/drawable/bubble_colourblind_2.gif new file mode 100644 index 0000000..4c6a536 Binary files /dev/null and b/res/drawable/bubble_colourblind_2.gif differ diff --git a/res/drawable/bubble_colourblind_3.gif b/res/drawable/bubble_colourblind_3.gif new file mode 100644 index 0000000..cfd4750 Binary files /dev/null and b/res/drawable/bubble_colourblind_3.gif differ diff --git a/res/drawable/bubble_colourblind_4.gif b/res/drawable/bubble_colourblind_4.gif new file mode 100644 index 0000000..18d9347 Binary files /dev/null and b/res/drawable/bubble_colourblind_4.gif differ diff --git a/res/drawable/bubble_colourblind_5.gif b/res/drawable/bubble_colourblind_5.gif new file mode 100644 index 0000000..2944c45 Binary files /dev/null and b/res/drawable/bubble_colourblind_5.gif differ diff --git a/res/drawable/bubble_colourblind_6.gif b/res/drawable/bubble_colourblind_6.gif new file mode 100644 index 0000000..1ab1a04 Binary files /dev/null and b/res/drawable/bubble_colourblind_6.gif differ diff --git a/res/drawable/bubble_colourblind_7.gif b/res/drawable/bubble_colourblind_7.gif new file mode 100644 index 0000000..d7fa59b Binary files /dev/null and b/res/drawable/bubble_colourblind_7.gif differ diff --git a/res/drawable/bubble_colourblind_8.gif b/res/drawable/bubble_colourblind_8.gif new file mode 100644 index 0000000..3c07d1f Binary files /dev/null and b/res/drawable/bubble_colourblind_8.gif differ diff --git a/res/drawable/bubble_font.gif b/res/drawable/bubble_font.gif new file mode 100644 index 0000000..219447a Binary files /dev/null and b/res/drawable/bubble_font.gif differ diff --git a/res/drawable/close_eyes.gif b/res/drawable/close_eyes.gif new file mode 100644 index 0000000..731fbf1 Binary files /dev/null and b/res/drawable/close_eyes.gif differ diff --git a/res/drawable/compressor.gif b/res/drawable/compressor.gif new file mode 100644 index 0000000..0439126 Binary files /dev/null and b/res/drawable/compressor.gif differ diff --git a/res/drawable/compressor_body.png b/res/drawable/compressor_body.png new file mode 100644 index 0000000..7435095 Binary files /dev/null and b/res/drawable/compressor_body.png differ diff --git a/res/drawable/fixed_1.gif b/res/drawable/fixed_1.gif new file mode 100644 index 0000000..59b0bf1 Binary files /dev/null and b/res/drawable/fixed_1.gif differ diff --git a/res/drawable/fixed_2.gif b/res/drawable/fixed_2.gif new file mode 100644 index 0000000..85ede39 Binary files /dev/null and b/res/drawable/fixed_2.gif differ diff --git a/res/drawable/fixed_3.gif b/res/drawable/fixed_3.gif new file mode 100644 index 0000000..8bdb605 Binary files /dev/null and b/res/drawable/fixed_3.gif differ diff --git a/res/drawable/fixed_4.gif b/res/drawable/fixed_4.gif new file mode 100644 index 0000000..caa4135 Binary files /dev/null and b/res/drawable/fixed_4.gif differ diff --git a/res/drawable/fixed_5.gif b/res/drawable/fixed_5.gif new file mode 100644 index 0000000..0a3e735 Binary files /dev/null and b/res/drawable/fixed_5.gif differ diff --git a/res/drawable/fixed_6.gif b/res/drawable/fixed_6.gif new file mode 100644 index 0000000..c9d8e3b Binary files /dev/null and b/res/drawable/fixed_6.gif differ diff --git a/res/drawable/frozen_1.gif b/res/drawable/frozen_1.gif new file mode 100644 index 0000000..db9004c Binary files /dev/null and b/res/drawable/frozen_1.gif differ diff --git a/res/drawable/frozen_2.gif b/res/drawable/frozen_2.gif new file mode 100644 index 0000000..48e6d31 Binary files /dev/null and b/res/drawable/frozen_2.gif differ diff --git a/res/drawable/frozen_3.gif b/res/drawable/frozen_3.gif new file mode 100644 index 0000000..9008c93 Binary files /dev/null and b/res/drawable/frozen_3.gif differ diff --git a/res/drawable/frozen_4.gif b/res/drawable/frozen_4.gif new file mode 100644 index 0000000..a265c41 Binary files /dev/null and b/res/drawable/frozen_4.gif differ diff --git a/res/drawable/frozen_5.gif b/res/drawable/frozen_5.gif new file mode 100644 index 0000000..3c2d770 Binary files /dev/null and b/res/drawable/frozen_5.gif differ diff --git a/res/drawable/frozen_6.gif b/res/drawable/frozen_6.gif new file mode 100644 index 0000000..464b1f2 Binary files /dev/null and b/res/drawable/frozen_6.gif differ diff --git a/res/drawable/frozen_7.gif b/res/drawable/frozen_7.gif new file mode 100644 index 0000000..1887dd0 Binary files /dev/null and b/res/drawable/frozen_7.gif differ diff --git a/res/drawable/frozen_8.gif b/res/drawable/frozen_8.gif new file mode 100644 index 0000000..c945977 Binary files /dev/null and b/res/drawable/frozen_8.gif differ diff --git a/res/drawable/hurry.gif b/res/drawable/hurry.gif new file mode 100644 index 0000000..93fa1b5 Binary files /dev/null and b/res/drawable/hurry.gif differ diff --git a/res/drawable/launcher.png b/res/drawable/launcher.png new file mode 100644 index 0000000..6bb009f Binary files /dev/null and b/res/drawable/launcher.png differ diff --git a/res/drawable/life.gif b/res/drawable/life.gif new file mode 100644 index 0000000..488cb2f Binary files /dev/null and b/res/drawable/life.gif differ diff --git a/res/drawable/lose_panel.jpg b/res/drawable/lose_panel.jpg new file mode 100644 index 0000000..9f242f5 Binary files /dev/null and b/res/drawable/lose_panel.jpg differ diff --git a/res/drawable/penguins.jpg b/res/drawable/penguins.jpg new file mode 100644 index 0000000..4ac14f7 Binary files /dev/null and b/res/drawable/penguins.jpg differ diff --git a/res/drawable/splash.jpg b/res/drawable/splash.jpg new file mode 100644 index 0000000..d56c7bf Binary files /dev/null and b/res/drawable/splash.jpg differ diff --git a/res/drawable/void_panel.jpg b/res/drawable/void_panel.jpg new file mode 100644 index 0000000..243a2de Binary files /dev/null and b/res/drawable/void_panel.jpg differ diff --git a/res/drawable/win_panel.jpg b/res/drawable/win_panel.jpg new file mode 100644 index 0000000..c282460 Binary files /dev/null and b/res/drawable/win_panel.jpg differ diff --git a/res/layout/main.xml b/res/layout/main.xml new file mode 100644 index 0000000..d1cfbde --- /dev/null +++ b/res/layout/main.xml @@ -0,0 +1,12 @@ + + + + + + diff --git a/res/raw/applause.ogg b/res/raw/applause.ogg new file mode 100644 index 0000000..7924944 Binary files /dev/null and b/res/raw/applause.ogg differ diff --git a/res/raw/destroy_group.ogg b/res/raw/destroy_group.ogg new file mode 100644 index 0000000..2c102d7 Binary files /dev/null and b/res/raw/destroy_group.ogg differ diff --git a/res/raw/hurry.ogg b/res/raw/hurry.ogg new file mode 100644 index 0000000..b30926f Binary files /dev/null and b/res/raw/hurry.ogg differ diff --git a/res/raw/launch.ogg b/res/raw/launch.ogg new file mode 100644 index 0000000..179067f Binary files /dev/null and b/res/raw/launch.ogg differ diff --git a/res/raw/lose.ogg b/res/raw/lose.ogg new file mode 100644 index 0000000..75fb078 Binary files /dev/null and b/res/raw/lose.ogg differ diff --git a/res/raw/newroot_solo.ogg b/res/raw/newroot_solo.ogg new file mode 100644 index 0000000..1cc35c8 Binary files /dev/null and b/res/raw/newroot_solo.ogg differ diff --git a/res/raw/noh.ogg b/res/raw/noh.ogg new file mode 100644 index 0000000..ad16948 Binary files /dev/null and b/res/raw/noh.ogg differ diff --git a/res/raw/rebound.ogg b/res/raw/rebound.ogg new file mode 100644 index 0000000..8789420 Binary files /dev/null and b/res/raw/rebound.ogg differ diff --git a/res/raw/stick.ogg b/res/raw/stick.ogg new file mode 100644 index 0000000..237dfef Binary files /dev/null and b/res/raw/stick.ogg differ diff --git a/res/values/strings.xml b/res/values/strings.xml new file mode 100644 index 0000000..eedbfb3 --- /dev/null +++ b/res/values/strings.xml @@ -0,0 +1,14 @@ + + + FrozenBubble + New Game + Colorblind Mode On + Colorblind Mode Off + Fullscreen On + Fullscreen Off + Sound On + Sound Off + About Frozen Bubble + Don't Rush Me + Rush Me + diff --git a/src/org/jfedor/frozenbubble/BmpWrap.java b/src/org/jfedor/frozenbubble/BmpWrap.java new file mode 100644 index 0000000..53751ff --- /dev/null +++ b/src/org/jfedor/frozenbubble/BmpWrap.java @@ -0,0 +1,68 @@ +/* + * [[ Frozen-Bubble ]] + * + * Copyright (c) 2000-2003 Guillaume Cottenceau. + * Java sourcecode - Copyright (c) 2003 Glenn Sanson. + * + * This code is distributed under the GNU General Public License + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * Artwork: + * Alexis Younes <73lab at free.fr> + * (everything but the bubbles) + * Amaury Amblard-Ladurantie + * (the bubbles) + * + * Soundtrack: + * Matthias Le Bidan + * (the three musics and all the sound effects) + * + * Design & Programming: + * Guillaume Cottenceau + * (design and manage the project, whole Perl sourcecode) + * + * Java version: + * Glenn Sanson + * (whole Java sourcecode, including JIGA classes + * http://glenn.sanson.free.fr/jiga/) + * + * Android port: + * Pawel Aleksander Fedorynski + * + * [[ http://glenn.sanson.free.fr/fb/ ]] + * [[ http://www.frozen-bubble.org/ ]] + */ + +package org.jfedor.frozenbubble; + +import android.graphics.Bitmap; + +// Various classes take arguments of this type during construction. We need +// one level of indirection in case we want to swap the images from under them +// (e.g., to resize them when the surface resolution changes.) We couldn't +// do it if references to Bitmap were kept directly everywhere since you can't +// overwrite an Android Bitmap in place (or at least I haven't found how to +// do it.) +class BmpWrap { + BmpWrap(int id) + { + this.id = id; + } + + public Bitmap bmp; + // Image id used for saving and restoring the image sprites. + public int id; +} diff --git a/src/org/jfedor/frozenbubble/BubbleFont.java b/src/org/jfedor/frozenbubble/BubbleFont.java new file mode 100644 index 0000000..9406bba --- /dev/null +++ b/src/org/jfedor/frozenbubble/BubbleFont.java @@ -0,0 +1,126 @@ +/* + * [[ Frozen-Bubble ]] + * + * Copyright (c) 2000-2003 Guillaume Cottenceau. + * Java sourcecode - Copyright (c) 2003 Glenn Sanson. + * + * This code is distributed under the GNU General Public License + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * Artwork: + * Alexis Younes <73lab at free.fr> + * (everything but the bubbles) + * Amaury Amblard-Ladurantie + * (the bubbles) + * + * Soundtrack: + * Matthias Le Bidan + * (the three musics and all the sound effects) + * + * Design & Programming: + * Guillaume Cottenceau + * (design and manage the project, whole Perl sourcecode) + * + * Java version: + * Glenn Sanson + * (whole Java sourcecode, including JIGA classes + * http://glenn.sanson.free.fr/jiga/) + * + * Android port: + * Pawel Aleksander Fedorynski + * + * [[ http://glenn.sanson.free.fr/fb/ ]] + * [[ http://www.frozen-bubble.org/ ]] + */ + +package org.jfedor.frozenbubble; + +import android.graphics.Canvas; +import android.graphics.Rect; + +public class BubbleFont { + private char[] characters = { + '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', + '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', + '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', + '?', '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', + 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', + 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '|', '{', + '}', '[', ']', ' ', '\\', ' ', ' '}; + + private int[] position = { + 0, 9, 16, 31, 39, 54, 69, 73, 80, 88, 96, 116, 121, 131, + 137, 154, 165, 175, 187, 198, 210, 223, 234, 246, 259, + 271, 276, 282, 293, 313, 324, 336, 351, 360, 370, 381, + 390, 402, 411, 421, 435, 446, 459, 472, 483, 495, 508, + 517, 527, 538, 552, 565, 578, 589, 602, 616, 631, 645, + 663, 684, 700, 716, 732, 748, 764, 780, 796, 812 }; + + public int SEPARATOR_WIDTH = 1; + public int SPACE_CHAR_WIDTH = 6; + + private BmpWrap fontMap; + private Rect clipRect; + + public BubbleFont(BmpWrap fontMap) + { + this.fontMap = fontMap; + clipRect = new Rect(); + } + + public final void print(String s, int x, int y, Canvas canvas, + double scale, int dx, int dy) + { + int len = s.length(); + for (int i = 0; i < len; i++) { + char c = s.charAt(i); + x += paintChar(c, x, y, canvas, scale, dx, dy); + } + } + + public final int paintChar(char c, int x, int y, Canvas canvas, + double scale, int dx, int dy) + { + if (c == ' ') { + return SPACE_CHAR_WIDTH + SEPARATOR_WIDTH; + } + int index = getCharIndex(c); + if (index == -1) { + return 0; + } + int imageWidth = position[index+1]-position[index]; + + clipRect.left = x; + clipRect.right = x + imageWidth; + clipRect.top = y; + clipRect.bottom = y + 22; + Sprite.drawImageClipped(fontMap, x - position[index], y, clipRect, + canvas, scale, dx, dy); + + return imageWidth + SEPARATOR_WIDTH; + } + + private final int getCharIndex(char c) + { + for (int i=0 ; i + * (everything but the bubbles) + * Amaury Amblard-Ladurantie + * (the bubbles) + * + * Soundtrack: + * Matthias Le Bidan + * (the three musics and all the sound effects) + * + * Design & Programming: + * Guillaume Cottenceau + * (design and manage the project, whole Perl sourcecode) + * + * Java version: + * Glenn Sanson + * (whole Java sourcecode, including JIGA classes + * http://glenn.sanson.free.fr/jiga/) + * + * Android port: + * Pawel Aleksander Fedorynski + * + * [[ http://glenn.sanson.free.fr/fb/ ]] + * [[ http://www.frozen-bubble.org/ ]] + */ + +package org.jfedor.frozenbubble; + +import java.util.Random; +import android.os.Bundle; + +public class BubbleManager +{ + int bubblesLeft; + BmpWrap[] bubbles; + int[] countBubbles; + + public BubbleManager(BmpWrap[] bubbles) + { + this.bubbles = bubbles; + this.countBubbles = new int[bubbles.length]; + this.bubblesLeft = 0; + } + + public void saveState(Bundle map) + { + map.putInt("BubbleManager-bubblesLeft", bubblesLeft); + map.putIntArray("BubbleManager-countBubbles", countBubbles); + } + + public void restoreState(Bundle map) + { + bubblesLeft = map.getInt("BubbleManager-bubblesLeft"); + countBubbles = map.getIntArray("BubbleManager-countBubbles"); + } + + public void addBubble(BmpWrap bubble) + { + countBubbles[findBubble(bubble)]++; + bubblesLeft++; + } + + public void removeBubble(BmpWrap bubble) + { + countBubbles[findBubble(bubble)]--; + bubblesLeft--; + } + + public int countBubbles() + { + return bubblesLeft; + } + + public int nextBubbleIndex(Random rand) + { + int select = rand.nextInt() % bubbles.length; + + if (select < 0) + { + select = -select; + } + + int count = -1; + int position = -1; + + while (count != select) + { + position++; + + if (position == bubbles.length) + { + position = 0; + } + + if (countBubbles[position] != 0) + { + count++; + } + } + + return position; + } + + public BmpWrap nextBubble(Random rand) + { + return bubbles[nextBubbleIndex(rand)]; + } + + private int findBubble(BmpWrap bubble) + { + for (int i=0 ; i + * (everything but the bubbles) + * Amaury Amblard-Ladurantie + * (the bubbles) + * + * Soundtrack: + * Matthias Le Bidan + * (the three musics and all the sound effects) + * + * Design & Programming: + * Guillaume Cottenceau + * (design and manage the project, whole Perl sourcecode) + * + * Java version: + * Glenn Sanson + * (whole Java sourcecode, including JIGA classes + * http://glenn.sanson.free.fr/jiga/) + * + * Android port: + * Pawel Aleksander Fedorynski + * + * [[ http://glenn.sanson.free.fr/fb/ ]] + * [[ http://www.frozen-bubble.org/ ]] + */ + +package org.jfedor.frozenbubble; + +import java.util.Vector; +import java.util.Random; +import android.graphics.Canvas; +import android.graphics.Point; +import android.graphics.Rect; +import android.os.Bundle; + +public class BubbleSprite extends Sprite +{ + private static double FALL_SPEED = 1.; + private static double MAX_BUBBLE_SPEED = 8.; + private static double MINIMUM_DISTANCE = 841.; + + private int color; + private BmpWrap bubbleFace; + private BmpWrap bubbleBlindFace; + private BmpWrap frozenFace; + private BmpWrap bubbleBlink; + private BmpWrap[] bubbleFixed; + private FrozenGame frozen; + private BubbleManager bubbleManager; + private double moveX, moveY; + private double realX, realY; + + private boolean fixed; + private boolean blink; + private boolean released; + + private boolean checkJump; + private boolean checkFall; + + private int fixedAnim; + + private SoundManager soundManager; + + public void saveState(Bundle map, Vector savedSprites) { + if (getSavedId() != -1) { + return; + } + super.saveState(map, savedSprites); + map.putInt(String.format("%d-color", getSavedId()), color); + map.putDouble(String.format("%d-moveX", getSavedId()), moveX); + map.putDouble(String.format("%d-moveY", getSavedId()), moveY); + map.putDouble(String.format("%d-realX", getSavedId()), realX); + map.putDouble(String.format("%d-realY", getSavedId()), realY); + map.putBoolean(String.format("%d-fixed", getSavedId()), fixed); + map.putBoolean(String.format("%d-blink", getSavedId()), blink); + map.putBoolean(String.format("%d-released", getSavedId()), released); + map.putBoolean(String.format("%d-checkJump", getSavedId()), checkJump); + map.putBoolean(String.format("%d-checkFall", getSavedId()), checkFall); + map.putInt(String.format("%d-fixedAnim", getSavedId()), fixedAnim); + map.putBoolean(String.format("%d-frozen", getSavedId()), + bubbleFace == frozenFace ? true : false); + } + + public int getTypeId() + { + return Sprite.TYPE_BUBBLE; + } + + public BubbleSprite(Rect area, int color, double moveX, double moveY, + double realX, double realY, boolean fixed, boolean blink, + boolean released, boolean checkJump, boolean checkFall, + int fixedAnim, BmpWrap bubbleFace, + BmpWrap bubbleBlindFace, BmpWrap frozenFace, + BmpWrap[] bubbleFixed, BmpWrap bubbleBlink, + BubbleManager bubbleManager, SoundManager soundManager, + FrozenGame frozen) + { + super(area); + this.color = color; + this.moveX = moveX; + this.moveY = moveY; + this.realX = realX; + this.realY = realY; + this.fixed = fixed; + this.blink = blink; + this.released = released; + this.checkJump = checkJump; + this.checkFall = checkFall; + this.fixedAnim = fixedAnim; + this.bubbleFace = bubbleFace; + this.bubbleBlindFace = bubbleBlindFace; + this.frozenFace = frozenFace; + this.bubbleFixed = bubbleFixed; + this.bubbleBlink = bubbleBlink; + this.bubbleManager = bubbleManager; + this.soundManager = soundManager; + this.frozen = frozen; + } + + public BubbleSprite(Rect area, int direction, int color, BmpWrap bubbleFace, + BmpWrap bubbleBlindFace, BmpWrap frozenFace, + BmpWrap[] bubbleFixed, BmpWrap bubbleBlink, + BubbleManager bubbleManager, SoundManager soundManager, + FrozenGame frozen) + { + super(area); + + this.color = color; + this.bubbleFace = bubbleFace; + this.bubbleBlindFace = bubbleBlindFace; + this.frozenFace = frozenFace; + this.bubbleFixed = bubbleFixed; + this.bubbleBlink = bubbleBlink; + this.bubbleManager = bubbleManager; + this.soundManager = soundManager; + this.frozen = frozen; + + this.moveX = MAX_BUBBLE_SPEED * -Math.cos(direction * Math.PI / 40.); + this.moveY = MAX_BUBBLE_SPEED * -Math.sin(direction * Math.PI / 40.); + this.realX = area.left; + this.realY = area.top; + + fixed = false; + fixedAnim = -1; + } + + public BubbleSprite(Rect area, int color, BmpWrap bubbleFace, + BmpWrap bubbleBlindFace, BmpWrap frozenFace, + BmpWrap bubbleBlink, BubbleManager bubbleManager, + SoundManager soundManager, FrozenGame frozen) + { + super(area); + + this.color = color; + this.bubbleFace = bubbleFace; + this.bubbleBlindFace = bubbleBlindFace; + this.frozenFace = frozenFace; + this.bubbleBlink = bubbleBlink; + this.bubbleManager = bubbleManager; + this.soundManager = soundManager; + this.frozen = frozen; + + this.realX = area.left; + this.realY = area.top; + + fixed = true; + fixedAnim = -1; + bubbleManager.addBubble(bubbleFace); + } + + Point currentPosition() + { + int posY = (int)Math.floor((realY-28.-frozen.getMoveDown())/28.); + int posX = (int)Math.floor((realX-174.)/32. + 0.5*(posY%2)); + + if (posX>7) { + posX = 7; + } + + if (posX<0) { + posX = 0; + } + + if (posY<0) { + posY = 0; + } + + return new Point(posX, posY); + } + + public void removeFromManager() + { + bubbleManager.removeBubble(bubbleFace); + } + + public boolean fixed() + { + return fixed; + } + + public boolean checked() + { + return checkFall; + } + + public boolean released() + { + return released; + } + + public void moveDown() + { + if (fixed) { + realY += 28.; + } + + super.absoluteMove(new Point((int)realX, (int)realY)); + } + + public void move() + { + realX += moveX; + + if (realX>=414.) { + moveX = -moveX; + realX += (414. - realX); + soundManager.playSound(FrozenBubble.SOUND_REBOUND); + } else if (realX<=190.) { + moveX = -moveX; + realX += (190. - realX); + soundManager.playSound(FrozenBubble.SOUND_REBOUND); + } + + realY += moveY; + + Point currentPosition = currentPosition(); + Vector neighbors = getNeighbors(currentPosition); + + if (checkCollision(neighbors) || realY < 44.+frozen.getMoveDown()) { + realX = 190.+currentPosition.x*32-(currentPosition.y%2)*16; + realY = 44.+currentPosition.y*28+frozen.getMoveDown(); + + fixed = true; + + Vector checkJump = new Vector(); + this.checkJump(checkJump, neighbors); + + BubbleSprite[][] grid = frozen.getGrid(); + + if (checkJump.size() >= 3) { + released = true; + + for (int i=0 ; i0) { + current.removeFromManager(); + } + grid[currentPoint.x][currentPoint.y] = null; + } + + for (int i=0 ; i<8 ; i++) { + if (grid[i][0] != null) { + grid[i][0].checkFall(); + } + } + + for (int i=0 ; i<8 ; i++) { + for (int j=0 ; j<12 ; j++) { + if (grid[i][j] != null) { + if (!grid[i][j].checked()) { + frozen.addFallingBubble(grid[i][j]); + grid[i][j].removeFromManager(); + grid[i][j] = null; + } + } + } + } + + soundManager.playSound(FrozenBubble.SOUND_DESTROY); + } else { + bubbleManager.addBubble(bubbleFace); + grid[currentPosition.x][currentPosition.y] = this; + moveX = 0.; + moveY = 0.; + fixedAnim = 0; + soundManager.playSound(FrozenBubble.SOUND_STICK); + } + } + + super.absoluteMove(new Point((int)realX, (int)realY)); + } + + Vector getNeighbors(Point p) + { + BubbleSprite[][] grid = frozen.getGrid(); + + Vector list = new Vector(); + + if ((p.y % 2) == 0) { + if (p.x > 0) { + list.addElement(grid[p.x-1][p.y]); + } + + if (p.x < 7) { + list.addElement(grid[p.x+1][p.y]); + + if (p.y > 0) { + list.addElement(grid[p.x][p.y-1]); + list.addElement(grid[p.x+1][p.y-1]); + } + + if (p.y < 12) { + list.addElement(grid[p.x][p.y+1]); + list.addElement(grid[p.x+1][p.y+1]); + } + } else { + if (p.y > 0) { + list.addElement(grid[p.x][p.y-1]); + } + + if (p.y < 12) { + list.addElement(grid[p.x][p.y+1]); + } + } + } else { + if (p.x < 7) { + list.addElement(grid[p.x+1][p.y]); + } + + if (p.x > 0) { + list.addElement(grid[p.x-1][p.y]); + + if (p.y > 0) { + list.addElement(grid[p.x][p.y-1]); + list.addElement(grid[p.x-1][p.y-1]); + } + + if (p.y < 12) { + list.addElement(grid[p.x][p.y+1]); + list.addElement(grid[p.x-1][p.y+1]); + } + } else { + if (p.y > 0) { + list.addElement(grid[p.x][p.y-1]); + } + + if (p.y < 12) { + list.addElement(grid[p.x][p.y+1]); + } + } + } + + return list; + } + + void checkJump(Vector jump, BmpWrap compare) + { + if (checkJump) { + return; + } + checkJump = true; + + if (this.bubbleFace == compare) { + checkJump(jump, this.getNeighbors(this.currentPosition())); + } + } + + void checkJump(Vector jump, Vector neighbors) + { + jump.addElement(this); + + for (int i=0 ; i= 680.) { + frozen.deleteJumpingBubble(this); + } + } + + public void fall() + { + if (fixed) { + moveY = frozen.getRandom().nextDouble()* 5.; + } + + fixed = false; + + moveY += FALL_SPEED; + realY += moveY; + + super.absoluteMove(new Point((int)realX, (int)realY)); + + if (realY >= 680.) { + frozen.deleteFallingBubble(this); + } + } + + public void blink() + { + blink = true; + } + + public void frozenify() + { + changeSpriteArea(new Rect(getSpritePosition().x-1, getSpritePosition().y-1, + 34, 42)); + bubbleFace = frozenFace; + } + + public final void paint(Canvas c, double scale, int dx, int dy) + { + checkJump = false; + checkFall = false; + + Point p = getSpritePosition(); + + if (blink && bubbleFace != frozenFace) { + blink = false; + drawImage(bubbleBlink, p.x, p.y, c, scale, dx, dy); + } else { + if (FrozenBubble.getMode() == FrozenBubble.GAME_NORMAL || + bubbleFace == frozenFace) { + drawImage(bubbleFace, p.x, p.y, c, scale, dx, dy); + } else { + drawImage(bubbleBlindFace, p.x, p.y, c, scale, dx, dy); + } + } + + if (fixedAnim != -1) { + drawImage(bubbleFixed[fixedAnim], p.x, p.y, c, scale, dx, dy); + fixedAnim++; + if (fixedAnim == 6) { + fixedAnim = -1; + } + } + } +} diff --git a/src/org/jfedor/frozenbubble/Compressor.java b/src/org/jfedor/frozenbubble/Compressor.java new file mode 100644 index 0000000..8110dad --- /dev/null +++ b/src/org/jfedor/frozenbubble/Compressor.java @@ -0,0 +1,98 @@ +/* + * [[ Frozen-Bubble ]] + * + * Copyright (c) 2000-2003 Guillaume Cottenceau. + * Java sourcecode - Copyright (c) 2003 Glenn Sanson. + * + * This code is distributed under the GNU General Public License + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * Artwork: + * Alexis Younes <73lab at free.fr> + * (everything but the bubbles) + * Amaury Amblard-Ladurantie + * (the bubbles) + * + * Soundtrack: + * Matthias Le Bidan + * (the three musics and all the sound effects) + * + * Design & Programming: + * Guillaume Cottenceau + * (design and manage the project, whole Perl sourcecode) + * + * Java version: + * Glenn Sanson + * (whole Java sourcecode, including JIGA classes + * http://glenn.sanson.free.fr/jiga/) + * + * Android port: + * Pawel Aleksander Fedorynski + * + * [[ http://glenn.sanson.free.fr/fb/ ]] + * [[ http://www.frozen-bubble.org/ ]] + */ + +package org.jfedor.frozenbubble; + +import android.graphics.Canvas; +import android.os.Bundle; +import android.util.Log; + +public class Compressor { + private BmpWrap compressorHead; + private BmpWrap compressor; + int steps; + + public Compressor(BmpWrap compressorHead, BmpWrap compressor) + { + this.compressorHead = compressorHead; + this.compressor = compressor; + this.steps = 0; + } + + public void saveState(Bundle map) + { + map.putInt("compressor-steps", steps); + } + + public void restoreState(Bundle map) + { + steps = map.getInt("compressor-steps"); + } + + public void moveDown() { + steps++; + } + + public void paint(Canvas c, double scale, int dx, int dy) + { + for (int i = 0; i < steps; i++) { + c.drawBitmap(compressor.bmp, + (float)(235 * scale + dx), + (float)((28 * i - 4) * scale + dy), + null); + c.drawBitmap(compressor.bmp, + (float)(391 * scale + dx), + (float)((28 * i - 4) * scale + dy), + null); + } + c.drawBitmap(compressorHead.bmp, + (float)(160 * scale + dx), + (float)((-7 + 28 * steps) * scale + dy), + null); + } +}; diff --git a/src/org/jfedor/frozenbubble/FrozenBubble.java b/src/org/jfedor/frozenbubble/FrozenBubble.java new file mode 100644 index 0000000..5f0cc62 --- /dev/null +++ b/src/org/jfedor/frozenbubble/FrozenBubble.java @@ -0,0 +1,299 @@ +/* + * [[ Frozen-Bubble ]] + * + * Copyright (c) 2000-2003 Guillaume Cottenceau. + * Java sourcecode - Copyright (c) 2003 Glenn Sanson. + * + * This code is distributed under the GNU General Public License + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * Artwork: + * Alexis Younes <73lab at free.fr> + * (everything but the bubbles) + * Amaury Amblard-Ladurantie + * (the bubbles) + * + * Soundtrack: + * Matthias Le Bidan + * (the three musics and all the sound effects) + * + * Design & Programming: + * Guillaume Cottenceau + * (design and manage the project, whole Perl sourcecode) + * + * Java version: + * Glenn Sanson + * (whole Java sourcecode, including JIGA classes + * http://glenn.sanson.free.fr/jiga/) + * + * Android port: + * Pawel Aleksander Fedorynski + * + * [[ http://glenn.sanson.free.fr/fb/ ]] + * [[ http://www.frozen-bubble.org/ ]] + */ +// This file is derived from the LunarLander.java file which is part of +// the Lunar Lander game included with Android documentation. The copyright +// notice for the Lunar Lander is reproduced below. +/* + * Copyright (C) 2007 Google Inc. + * + * 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. + */ + +package org.jfedor.frozenbubble; + +import android.app.Activity; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.view.Window; +import android.view.WindowManager; + +import android.util.Log; + +import org.jfedor.frozenbubble.GameView; +import org.jfedor.frozenbubble.GameView.GameThread; + +public class FrozenBubble extends Activity +{ + public final static int SOUND_WON = 0; + public final static int SOUND_LOST = 1; + public final static int SOUND_LAUNCH = 2; + public final static int SOUND_DESTROY = 3; + public final static int SOUND_REBOUND = 4; + public final static int SOUND_STICK = 5; + public final static int SOUND_HURRY = 6; + public final static int SOUND_NEWROOT = 7; + public final static int SOUND_NOH = 8; + public final static int NUM_SOUNDS = 9; + + public final static int GAME_NORMAL = 0; + public final static int GAME_COLORBLIND = 1; + + public final static int MENU_NEW_GAME = 1; + public final static int MENU_COLORBLIND_MODE_ON = 2; + public final static int MENU_COLORBLIND_MODE_OFF = 3; + public final static int MENU_FULLSCREEN_ON = 4; + public final static int MENU_FULLSCREEN_OFF = 5; + public final static int MENU_SOUND_ON = 6; + public final static int MENU_SOUND_OFF = 7; + public final static int MENU_DONT_RUSH_ME = 8; + public final static int MENU_RUSH_ME = 9; + public final static int MENU_ABOUT = 10; + + private static int gameMode = GAME_NORMAL; + private static boolean soundOn = true; + private static boolean dontRushMe = false; + + private boolean fullscreen = true; + + private GameThread mGameThread; + private GameView mGameView; + + @Override + public boolean onCreateOptionsMenu(Menu menu) + { + super.onCreateOptionsMenu(menu); + menu.add(0, MENU_NEW_GAME, 0, R.string.menu_new_game); + menu.add(0, MENU_COLORBLIND_MODE_ON, 0, + R.string.menu_colorblind_mode_on); + menu.add(0, MENU_COLORBLIND_MODE_OFF, 0, + R.string.menu_colorblind_mode_off); + menu.add(0, MENU_FULLSCREEN_ON, 0, R.string.menu_fullscreen_on); + menu.add(0, MENU_FULLSCREEN_OFF, 0, R.string.menu_fullscreen_off); + menu.add(0, MENU_SOUND_ON, 0, R.string.menu_sound_on); + menu.add(0, MENU_SOUND_OFF, 0, R.string.menu_sound_off); + menu.add(0, MENU_DONT_RUSH_ME, 0, R.string.menu_dont_rush_me); + menu.add(0, MENU_RUSH_ME, 0, R.string.menu_rush_me); + menu.add(0, MENU_ABOUT, 0, R.string.menu_about); + return true; + } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) + { + super.onPrepareOptionsMenu(menu); + menu.findItem(MENU_SOUND_ON).setVisible(!getSoundOn()); + menu.findItem(MENU_SOUND_OFF).setVisible(getSoundOn()); + menu.findItem(MENU_COLORBLIND_MODE_ON).setVisible( + getMode() == GAME_NORMAL); + menu.findItem(MENU_COLORBLIND_MODE_OFF).setVisible( + getMode() != GAME_NORMAL); + menu.findItem(MENU_FULLSCREEN_ON).setVisible(!fullscreen); + menu.findItem(MENU_FULLSCREEN_OFF).setVisible(fullscreen); + menu.findItem(MENU_DONT_RUSH_ME).setVisible(!getDontRushMe()); + menu.findItem(MENU_RUSH_ME).setVisible(getDontRushMe()); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) + { + switch (item.getItemId()) { + case MENU_NEW_GAME: + mGameThread.newGame(); + return true; + case MENU_COLORBLIND_MODE_ON: + setMode(GAME_COLORBLIND); + return true; + case MENU_COLORBLIND_MODE_OFF: + setMode(GAME_NORMAL); + return true; + case MENU_FULLSCREEN_ON: + fullscreen = true; + setFullscreen(); + return true; + case MENU_FULLSCREEN_OFF: + fullscreen = false; + setFullscreen(); + return true; + case MENU_SOUND_ON: + setSoundOn(true); + return true; + case MENU_SOUND_OFF: + setSoundOn(false); + return true; + case MENU_ABOUT: + mGameView.getThread().setState(GameView.GameThread.STATE_ABOUT); + return true; + case MENU_DONT_RUSH_ME: + setDontRushMe(true); + return true; + case MENU_RUSH_ME: + setDontRushMe(false); + return true; + } + return false; + } + + private void setFullscreen() + { + if (fullscreen) { + getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); + getWindow().clearFlags( + WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); + } else { + getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); + getWindow().addFlags( + WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); + } + mGameView.requestLayout(); + } + + public synchronized static void setMode(int newMode) + { + gameMode = newMode; + } + + public synchronized static int getMode() + { + return gameMode; + } + + public synchronized static boolean getSoundOn() + { + return soundOn; + } + + public synchronized static void setSoundOn(boolean so) + { + soundOn = so; + } + + public synchronized static boolean getDontRushMe() + { + return dontRushMe; + } + + public synchronized static void setDontRushMe(boolean dont) + { + dontRushMe = dont; + } + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) + { + if (savedInstanceState != null) { + Log.i("frozen-bubble", "FrozenBubble.onCreate(...)"); + } else { + Log.i("frozen-bubble", "FrozenBubble.onCreate(null)"); + } + super.onCreate(savedInstanceState); + requestWindowFeature(Window.FEATURE_NO_TITLE); + setContentView(R.layout.main); + mGameView = (GameView)findViewById(R.id.game); + mGameThread = mGameView.getThread(); + + if (savedInstanceState != null) { + mGameThread.restoreState(savedInstanceState); + } + mGameView.requestFocus(); + setFullscreen(); + } + + /** + * Invoked when the Activity loses user focus. + */ + @Override + protected void onPause() { + Log.i("frozen-bubble", "FrozenBubble.onPause()"); + super.onPause(); + mGameView.getThread().pause(); + } + + @Override + protected void onStop() { + Log.i("frozen-bubble", "FrozenBubble.onStop()"); + super.onStop(); + } + + @Override + protected void onDestroy() { + Log.i("frozen-bubble", "FrozenBubble.onDestroy()"); + super.onDestroy(); + if (mGameView != null) { + mGameView.cleanUp(); + } + mGameView = null; + mGameThread = null; + } + + /** + * Notification that something is about to happen, to give the Activity a + * chance to save state. + * + * @param outState a Bundle into which this Activity should save its state + */ + @Override + protected void onSaveInstanceState(Bundle outState) { + Log.i("frozen-bubble", "FrozenBubble.onSaveInstanceState()"); + // Just have the View's thread save its state into our Bundle. + super.onSaveInstanceState(outState); + mGameThread.saveState(outState); + } +} diff --git a/src/org/jfedor/frozenbubble/FrozenGame.java b/src/org/jfedor/frozenbubble/FrozenGame.java new file mode 100644 index 0000000..8f10b78 --- /dev/null +++ b/src/org/jfedor/frozenbubble/FrozenGame.java @@ -0,0 +1,758 @@ +/* + * [[ Frozen-Bubble ]] + * + * Copyright (c) 2000-2003 Guillaume Cottenceau. + * Java sourcecode - Copyright (c) 2003 Glenn Sanson. + * + * This code is distributed under the GNU General Public License + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * Artwork: + * Alexis Younes <73lab at free.fr> + * (everything but the bubbles) + * Amaury Amblard-Ladurantie + * (the bubbles) + * + * Soundtrack: + * Matthias Le Bidan + * (the three musics and all the sound effects) + * + * Design & Programming: + * Guillaume Cottenceau + * (design and manage the project, whole Perl sourcecode) + * + * Java version: + * Glenn Sanson + * (whole Java sourcecode, including JIGA classes + * http://glenn.sanson.free.fr/jiga/) + * + * Android port: + * Pawel Aleksander Fedorynski + * + * [[ http://glenn.sanson.free.fr/fb/ ]] + * [[ http://www.frozen-bubble.org/ ]] + */ + +package org.jfedor.frozenbubble; + +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.util.Log; +import java.util.Vector; +import java.util.Random; + +public class FrozenGame extends GameScreen { + public final static int HORIZONTAL_MOVE = 0; + public final static int FIRE = 1; + + public final static int KEY_UP = 38; + public final static int KEY_LEFT = 37; + public final static int KEY_RIGHT = 39; + public final static int KEY_SHIFT = 16; + + public static String PARAMETER_PLAYER = "player"; + public static String PARAMETER_OFFLINE = "offline"; + + // Change mode (normal/colorblind) + public final static int KEY_M = 77; + // Toggle sound on/off + public final static int KEY_S = 83; + + boolean modeKeyPressed, soundKeyPressed; + + boolean levelCompleted = false; + + BmpWrap background; + BmpWrap[] bubbles; + BmpWrap[] bubblesBlind; + BmpWrap[] frozenBubbles; + BmpWrap[] targetedBubbles; + Random random; + + LaunchBubbleSprite launchBubble; + double launchBubblePosition; + + PenguinSprite penguin; + Compressor compressor; + + ImageSprite nextBubble; + int currentColor, nextColor; + + BubbleSprite movingBubble; + BubbleManager bubbleManager; + LevelManager levelManager; + // TODO + //HighscoreManager highscoreManager; + + Vector jumping; + Vector falling; + + BubbleSprite[][] bubblePlay; + + int fixedBubbles; + double moveDown; + + BmpWrap gameWon, gameLost; + + int nbBubbles; + + BmpWrap bubbleBlink; + int blinkDelay; + + ImageSprite hurrySprite; + int hurryTime; + + SoundManager soundManager; + + boolean readyToFire; + boolean endOfGame; + boolean frozenify; + int frozenifyX, frozenifyY; + + Drawable launcher; + BmpWrap penguins; + + public FrozenGame(BmpWrap background_arg, + BmpWrap[] bubbles_arg, + BmpWrap[] bubblesBlind_arg, + BmpWrap[] frozenBubbles_arg, + BmpWrap[] targetedBubbles_arg, + BmpWrap bubbleBlink_arg, + BmpWrap gameWon_arg, + BmpWrap gameLost_arg, + BmpWrap hurry_arg, + BmpWrap penguins_arg, + BmpWrap compressorHead_arg, + BmpWrap compressor_arg, + Drawable launcher_arg, + SoundManager soundManager_arg, + LevelManager levelManager_arg) + { + random = new Random(System.currentTimeMillis()); + launcher = launcher_arg; + penguins = penguins_arg; + background = background_arg; + bubbles = bubbles_arg; + bubblesBlind = bubblesBlind_arg; + frozenBubbles = frozenBubbles_arg; + targetedBubbles = targetedBubbles_arg; + bubbleBlink = bubbleBlink_arg; + gameWon = gameWon_arg; + gameLost = gameLost_arg; + soundManager = soundManager_arg; + levelManager = levelManager_arg; + + launchBubblePosition = 20; + + penguin = new PenguinSprite(penguins_arg, random); + this.addSprite(penguin); + compressor = new Compressor(compressorHead_arg, compressor_arg); + + hurrySprite = new ImageSprite(new Rect(203, 265, 203 + 240, 265 + 90), + hurry_arg); + + jumping = new Vector(); + falling = new Vector(); + + bubblePlay = new BubbleSprite[8][13]; + + bubbleManager = new BubbleManager(bubbles); + byte[][] currentLevel = levelManager.getCurrentLevel(); + + if (currentLevel == null) { + Log.i("frozen-bubble", "Level not available."); + return; + } + + for (int j=0 ; j<12 ; j++) { + for (int i=j%2 ; i<8 ; i++) { + if (currentLevel[i][j] != -1) { + BubbleSprite newOne = new BubbleSprite( + new Rect(190+i*32-(j%2)*16, 44+j*28, 32, 32), + currentLevel[i][j], + bubbles[currentLevel[i][j]], bubblesBlind[currentLevel[i][j]], + frozenBubbles[currentLevel[i][j]], bubbleBlink, bubbleManager, + soundManager, this); + bubblePlay[i][j] = newOne; + this.addSprite(newOne); + } + } + } + + currentColor = bubbleManager.nextBubbleIndex(random); + nextColor = bubbleManager.nextBubbleIndex(random); + + if (FrozenBubble.getMode() == FrozenBubble.GAME_NORMAL) { + nextBubble = new ImageSprite(new Rect(302, 440, 302 + 32, 440 + 32), + bubbles[nextColor]); + } else { + nextBubble = new ImageSprite(new Rect(302, 440, 302 + 32, 440 + 32), + bubblesBlind[nextColor]); + } + this.addSprite(nextBubble); + + launchBubble = new LaunchBubbleSprite(currentColor, + (int)launchBubblePosition, + launcher, bubbles, bubblesBlind); + + this.spriteToBack(launchBubble); + + nbBubbles = 0; + } + + public void saveState(Bundle map) { + Vector savedSprites = new Vector(); + saveSprites(map, savedSprites); + for (int i = 0; i < jumping.size(); i++) { + ((Sprite)jumping.elementAt(i)).saveState(map, savedSprites); + map.putInt(String.format("jumping-%d", i), + ((Sprite)jumping.elementAt(i)).getSavedId()); + } + map.putInt("numJumpingSprites", jumping.size()); + for (int i = 0; i < falling.size(); i++) { + ((Sprite)falling.elementAt(i)).saveState(map, savedSprites); + map.putInt(String.format("falling-%d", i), + ((Sprite)falling.elementAt(i)).getSavedId()); + } + map.putInt("numFallingSprites", falling.size()); + for (int i = 0; i < 8; i++) { + for (int j = 0; j < 13; j++) { + if (bubblePlay[i][j] != null) { + bubblePlay[i][j].saveState(map, savedSprites); + map.putInt(String.format("play-%d-%d", i, j), + bubblePlay[i][j].getSavedId()); + } else { + map.putInt(String.format("play-%d-%d", i, j), -1); + } + } + } + launchBubble.saveState(map, savedSprites); + map.putInt("launchBubbleId", launchBubble.getSavedId()); + map.putDouble("launchBubblePosition", launchBubblePosition); + penguin.saveState(map, savedSprites); + compressor.saveState(map); + map.putInt("penguinId", penguin.getSavedId()); + nextBubble.saveState(map, savedSprites); + map.putInt("nextBubbleId", nextBubble.getSavedId()); + map.putInt("currentColor", currentColor); + map.putInt("nextColor", nextColor); + if (movingBubble != null) { + movingBubble.saveState(map, savedSprites); + map.putInt("movingBubbleId", movingBubble.getSavedId()); + } else { + map.putInt("movingBubbleId", -1); + } + bubbleManager.saveState(map); + map.putInt("fixedBubbles", fixedBubbles); + map.putDouble("moveDown", moveDown); + map.putInt("nbBubbles", nbBubbles); + map.putInt("blinkDelay", blinkDelay); + hurrySprite.saveState(map, savedSprites); + map.putInt("hurryId", hurrySprite.getSavedId()); + map.putInt("hurryTime", hurryTime); + map.putBoolean("readyToFire", readyToFire); + map.putBoolean("endOfGame", endOfGame); + map.putBoolean("frozenify", frozenify); + map.putInt("frozenifyX", frozenifyX); + map.putInt("frozenifyY", frozenifyY); + + map.putInt("numSavedSprites", savedSprites.size()); + + for (int i = 0; i < savedSprites.size(); i++) { + ((Sprite)savedSprites.elementAt(i)).clearSavedId(); + } + } + + private Sprite restoreSprite(Bundle map, Vector imageList, int i) + { + int left = map.getInt(String.format("%d-left", i)); + int right = map.getInt(String.format("%d-right", i)); + int top = map.getInt(String.format("%d-top", i)); + int bottom = map.getInt(String.format("%d-bottom", i)); + int type = map.getInt(String.format("%d-type", i)); + if (type == Sprite.TYPE_BUBBLE) { + int color = map.getInt(String.format("%d-color", i)); + double moveX = map.getDouble(String.format("%d-moveX", i)); + double moveY = map.getDouble(String.format("%d-moveY", i)); + double realX = map.getDouble(String.format("%d-realX", i)); + double realY = map.getDouble(String.format("%d-realY", i)); + boolean fixed = map.getBoolean(String.format("%d-fixed", i)); + boolean blink = map.getBoolean(String.format("%d-blink", i)); + boolean released = map.getBoolean(String.format("%d-released", i)); + boolean checkJump = map.getBoolean(String.format("%d-checkJump", i)); + boolean checkFall = map.getBoolean(String.format("%d-checkFall", i)); + int fixedAnim = map.getInt(String.format("%d-fixedAnim", i)); + boolean frozen = map.getBoolean(String.format("%d-frozen", i)); + return new BubbleSprite(new Rect(left, top, right, bottom), + color, moveX, moveY, realX, realY, + fixed, blink, released, checkJump, checkFall, + fixedAnim, + (frozen ? frozenBubbles[color] : bubbles[color]), + bubblesBlind[color], + frozenBubbles[color], + targetedBubbles, bubbleBlink, + bubbleManager, soundManager, this); + } else if (type == Sprite.TYPE_IMAGE) { + int imageId = map.getInt(String.format("%d-imageId", i)); + return new ImageSprite(new Rect(left, top, right, bottom), + (BmpWrap)imageList.elementAt(imageId)); + } else if (type == Sprite.TYPE_LAUNCH_BUBBLE) { + int currentColor = map.getInt(String.format("%d-currentColor", i)); + int currentDirection = map.getInt(String.format("%d-currentDirection", + i)); + return new LaunchBubbleSprite(currentColor, currentDirection, + launcher, bubbles, bubblesBlind); + } else if (type == Sprite.TYPE_PENGUIN) { + int currentPenguin = map.getInt(String.format("%d-currentPenguin", i)); + int count = map.getInt(String.format("%d-count", i)); + int finalState = map.getInt(String.format("%d-finalState", i)); + int nextPosition = map.getInt(String.format("%d-nextPosition", i)); + return new PenguinSprite(penguins, random, currentPenguin, count, + finalState, nextPosition); + } else { + Log.e("frozen-bubble", "Unrecognized sprite type: " + type); + return null; + } + } + + public void restoreState(Bundle map, Vector imageList) + { + Vector savedSprites = new Vector(); + int numSavedSprites = map.getInt("numSavedSprites"); + for (int i = 0; i < numSavedSprites; i++) { + savedSprites.addElement(restoreSprite(map, imageList, i)); + } + + restoreSprites(map, savedSprites); + jumping = new Vector(); + int numJumpingSprites = map.getInt("numJumpingSprites"); + for (int i = 0; i < numJumpingSprites; i++) { + int spriteIdx = map.getInt(String.format("jumping-%d", i)); + jumping.addElement(savedSprites.elementAt(spriteIdx)); + } + falling = new Vector(); + int numFallingSprites = map.getInt("numFallingSprites"); + for (int i = 0; i < numFallingSprites; i++) { + int spriteIdx = map.getInt(String.format("falling-%d", i)); + falling.addElement(savedSprites.elementAt(spriteIdx)); + } + bubblePlay = new BubbleSprite[8][13]; + for (int i = 0; i < 8; i++) { + for (int j = 0; j < 13; j++) { + int spriteIdx = map.getInt(String.format("play-%d-%d", i, j)); + if (spriteIdx != -1) { + bubblePlay[i][j] = (BubbleSprite)savedSprites.elementAt(spriteIdx); + } else { + bubblePlay[i][j] = null; + } + } + } + int launchBubbleId = map.getInt("launchBubbleId"); + launchBubble = (LaunchBubbleSprite)savedSprites.elementAt(launchBubbleId); + launchBubblePosition = map.getDouble("launchBubblePosition"); + int penguinId = map.getInt("penguinId"); + penguin = (PenguinSprite)savedSprites.elementAt(penguinId); + compressor.restoreState(map); + int nextBubbleId = map.getInt("nextBubbleId"); + nextBubble = (ImageSprite)savedSprites.elementAt(nextBubbleId); + currentColor = map.getInt("currentColor"); + nextColor = map.getInt("nextColor"); + int movingBubbleId = map.getInt("movingBubbleId"); + if (movingBubbleId == -1) { + movingBubble = null; + } else { + movingBubble = (BubbleSprite)savedSprites.elementAt(movingBubbleId); + } + bubbleManager.restoreState(map); + fixedBubbles = map.getInt("fixedBubbles"); + moveDown = map.getDouble("moveDown"); + nbBubbles = map.getInt("nbBubbles"); + blinkDelay = map.getInt("blinkDelay"); + int hurryId = map.getInt("hurryId"); + hurrySprite = (ImageSprite)savedSprites.elementAt(hurryId); + hurryTime = map.getInt("hurryTime"); + readyToFire = map.getBoolean("readyToFire"); + endOfGame = map.getBoolean("endOfGame"); + frozenify = map.getBoolean("frozenify"); + frozenifyX = map.getInt("frozenifyX"); + frozenifyY = map.getInt("frozenifyY"); + } + + private void initFrozenify() + { + ImageSprite freezeLaunchBubble = + new ImageSprite(new Rect(301, 389, 34, 42), + frozenBubbles[currentColor]); + ImageSprite freezeNextBubble = + new ImageSprite(new Rect(301, 439, 34, 42), frozenBubbles[nextColor]); + + this.addSprite(freezeLaunchBubble); + this.addSprite(freezeNextBubble); + + frozenifyX = 7; + frozenifyY = 12; + + frozenify = true; + } + + private void frozenify() + { + frozenifyX--; + if (frozenifyX < 0) { + frozenifyX = 7; + frozenifyY--; + + if (frozenifyY<0) { + frozenify = false; + this.addSprite(new ImageSprite(new Rect(152, 190, 337, 116), gameLost)); + soundManager.playSound(FrozenBubble.SOUND_NOH); + + return; + } + } + + while (bubblePlay[frozenifyX][frozenifyY] == null && frozenifyY >=0) { + frozenifyX--; + if (frozenifyX < 0) { + frozenifyX = 7; + frozenifyY--; + + if (frozenifyY<0) { + frozenify = false; + this.addSprite(new ImageSprite(new Rect(152, 190, 337, 116), + gameLost)); + soundManager.playSound(FrozenBubble.SOUND_NOH); + + return; + } + } + } + + this.spriteToBack(bubblePlay[frozenifyX][frozenifyY]); + bubblePlay[frozenifyX][frozenifyY].frozenify(); + + this.spriteToBack(launchBubble); + } + + public BubbleSprite[][] getGrid() + { + return bubblePlay; + } + + public void addFallingBubble(BubbleSprite sprite) + { + spriteToFront(sprite); + falling.addElement(sprite); + } + + public void deleteFallingBubble(BubbleSprite sprite) + { + removeSprite(sprite); + falling.removeElement(sprite); + } + + public void addJumpingBubble(BubbleSprite sprite) + { + spriteToFront(sprite); + jumping.addElement(sprite); + } + + public void deleteJumpingBubble(BubbleSprite sprite) + { + removeSprite(sprite); + jumping.removeElement(sprite); + } + + public Random getRandom() + { + return random; + } + + public double getMoveDown() + { + return moveDown; + } + + private int nextColor() + { + int nextColor = random.nextInt() % 8; + + if (nextColor<0) { + return -nextColor; + } + + return nextColor; + } + + private void sendBubblesDown() + { + soundManager.playSound(FrozenBubble.SOUND_NEWROOT); + + for (int i=0 ; i<8 ; i++) { + for (int j=0 ; j<12 ; j++) { + if (bubblePlay[i][j] != null) { + bubblePlay[i][j].moveDown(); + + if (bubblePlay[i][j].getSpritePosition().y>=380) { + penguin.updateState(PenguinSprite.STATE_GAME_LOST); + endOfGame = true; + initFrozenify(); + + soundManager.playSound(FrozenBubble.SOUND_LOST); + } + } + } + } + + moveDown += 28.; + compressor.moveDown(); + } + + private void blinkLine(int number) + { + int move = number % 2; + int column = (number+1) >> 1; + + for (int i=move ; i<13 ; i++) { + if (bubblePlay[column][i] != null) { + bubblePlay[column][i].blink(); + } + } + } + + public boolean play(boolean key_left, boolean key_right, boolean key_fire, + double trackball_dx, double touch_dx) + { + int[] move = new int[2]; + + if (key_left && !key_right) { + move[HORIZONTAL_MOVE] = KEY_LEFT; + } else if (key_right && !key_left) { + move[HORIZONTAL_MOVE] = KEY_RIGHT; + } else { + move[HORIZONTAL_MOVE] = 0; + } + if (key_fire) { + move[FIRE] = KEY_UP; + } else { + move[FIRE] = 0; + } + + if (move[FIRE] == 0) { + readyToFire = true; + } + + if (FrozenBubble.getDontRushMe()) { + hurryTime = 1; + } + + if (endOfGame) { + if (move[FIRE] == KEY_UP && readyToFire) { + if (levelCompleted) { + levelManager.goToNextLevel(); + } + return true; + } else { + penguin.updateState(PenguinSprite.STATE_VOID); + + if (frozenify) { + frozenify(); + } + } + } else { + if (move[FIRE] == KEY_UP || hurryTime > 480) { + if (movingBubble == null && readyToFire) { + nbBubbles++; + + movingBubble = new BubbleSprite(new Rect(302, 390, 32, 32), + (int)launchBubblePosition, + currentColor, + bubbles[currentColor], + bubblesBlind[currentColor], + frozenBubbles[currentColor], + targetedBubbles, bubbleBlink, + bubbleManager, soundManager, this); + this.addSprite(movingBubble); + + currentColor = nextColor; + nextColor = bubbleManager.nextBubbleIndex(random); + + if (FrozenBubble.getMode() == FrozenBubble.GAME_NORMAL) { + nextBubble.changeImage(bubbles[nextColor]); + } else { + nextBubble.changeImage(bubblesBlind[nextColor]); + } + launchBubble.changeColor(currentColor); + penguin.updateState(PenguinSprite.STATE_FIRE); + + soundManager.playSound(FrozenBubble.SOUND_LAUNCH); + + readyToFire = false; + hurryTime = 0; + removeSprite(hurrySprite); + } else { + penguin.updateState(PenguinSprite.STATE_VOID); + } + } else { + double dx = 0; + if (move[HORIZONTAL_MOVE] == KEY_LEFT) { + dx -= 1; + } + if (move[HORIZONTAL_MOVE] == KEY_RIGHT) { + dx += 1; + } + dx += trackball_dx; + dx += touch_dx; + launchBubblePosition += dx; + if (launchBubblePosition < 1) { + launchBubblePosition = 1; + } + if (launchBubblePosition > 39) { + launchBubblePosition = 39; + } + launchBubble.changeDirection((int)launchBubblePosition); + if (dx < 0) { + penguin.updateState(PenguinSprite.STATE_TURN_LEFT); + } else if (dx > 0) { + penguin.updateState(PenguinSprite.STATE_TURN_RIGHT); + } else { + penguin.updateState(PenguinSprite.STATE_VOID); + } + } + } + + if (movingBubble != null) { + movingBubble.move(); + if (movingBubble.fixed()) { + if (movingBubble.getSpritePosition().y>=380 && + !movingBubble.released()) { + penguin.updateState(PenguinSprite.STATE_GAME_LOST); + endOfGame = true; + initFrozenify(); + + soundManager.playSound(FrozenBubble.SOUND_LOST); + } else if (bubbleManager.countBubbles() == 0) { + penguin.updateState(PenguinSprite.STATE_GAME_WON); + this.addSprite(new ImageSprite(new Rect(152, 190, 337, 116), + gameWon)); + // TODO + //highscoreManager.endLevel(nbBubbles); + levelCompleted = true; + endOfGame = true; + + soundManager.playSound(FrozenBubble.SOUND_WON); + } else { + fixedBubbles++; + blinkDelay = 0; + + if (fixedBubbles == 8) { + fixedBubbles = 0; + sendBubblesDown(); + } + } + movingBubble = null; + } + + if (movingBubble != null) { + movingBubble.move(); + if (movingBubble.fixed()) { + if (movingBubble.getSpritePosition().y>=380 && + !movingBubble.released()) { + penguin.updateState(PenguinSprite.STATE_GAME_LOST); + endOfGame = true; + initFrozenify(); + + soundManager.playSound(FrozenBubble.SOUND_LOST); + } else if (bubbleManager.countBubbles() == 0) { + penguin.updateState(PenguinSprite.STATE_GAME_WON); + this.addSprite(new ImageSprite(new Rect(152, 190, + 152 + 337, 190 + 116), + gameWon)); + // TODO + //highscoreManager.endLevel(nbBubbles); + endOfGame = true; + levelCompleted = true; + soundManager.playSound(FrozenBubble.SOUND_WON); + } else { + fixedBubbles++; + blinkDelay = 0; + + if (fixedBubbles == 8) { + fixedBubbles = 0; + sendBubblesDown(); + } + } + movingBubble = null; + } + } + } + + if (movingBubble == null && !endOfGame) { + hurryTime++; + + if (hurryTime>=240) { + if (hurryTime % 40 == 10) { + addSprite(hurrySprite); + soundManager.playSound(FrozenBubble.SOUND_HURRY); + } else if (hurryTime % 40 == 35) { + removeSprite(hurrySprite); + } + } + } + + if (fixedBubbles == 6) { + if (blinkDelay < 15) { + blinkLine(blinkDelay); + } + + blinkDelay++; + if (blinkDelay == 40) { + blinkDelay = 0; + } + } else if (fixedBubbles == 7) { + if (blinkDelay < 15) { + blinkLine(blinkDelay); + } + + blinkDelay++; + if (blinkDelay == 25) { + blinkDelay = 0; + } + } + + for (int i=0 ; i + * (everything but the bubbles) + * Amaury Amblard-Ladurantie + * (the bubbles) + * + * Soundtrack: + * Matthias Le Bidan + * (the three musics and all the sound effects) + * + * Design & Programming: + * Guillaume Cottenceau + * (design and manage the project, whole Perl sourcecode) + * + * Java version: + * Glenn Sanson + * (whole Java sourcecode, including JIGA classes + * http://glenn.sanson.free.fr/jiga/) + * + * Android port: + * Pawel Aleksander Fedorynski + * + * [[ http://glenn.sanson.free.fr/fb/ ]] + * [[ http://www.frozen-bubble.org/ ]] + */ + +package org.jfedor.frozenbubble; + +import java.util.Vector; +import android.graphics.Canvas; +import android.os.Bundle; + +public abstract class GameScreen +{ + private Vector sprites; + + public final void saveSprites(Bundle map, Vector savedSprites) + { + for (int i = 0; i < sprites.size(); i++) { + ((Sprite)sprites.elementAt(i)).saveState(map, savedSprites); + map.putInt(String.format("game-%d", i), + ((Sprite)sprites.elementAt(i)).getSavedId()); + } + map.putInt("numGameSprites", sprites.size()); + } + + public final void restoreSprites(Bundle map, Vector savedSprites) + { + sprites = new Vector(); + int numSprites = map.getInt("numGameSprites"); + for (int i = 0; i < numSprites; i++) { + int spriteIdx = map.getInt(String.format("game-%d", i)); + sprites.addElement(savedSprites.elementAt(spriteIdx)); + } + } + + public GameScreen() + { + sprites = new Vector(); + } + + public final void addSprite(Sprite sprite) + { + sprites.removeElement(sprite); + sprites.addElement(sprite); + } + + public final void removeSprite(Sprite sprite) + { + sprites.removeElement(sprite); + } + + public final void spriteToBack(Sprite sprite) + { + sprites.removeElement(sprite); + sprites.insertElementAt(sprite,0); + } + + public final void spriteToFront(Sprite sprite) + { + sprites.removeElement(sprite); + sprites.addElement(sprite); + } + + public void paint(Canvas c, double scale, int dx, int dy) { + for (int i = 0; i < sprites.size(); i++) { + ((Sprite)sprites.elementAt(i)).paint(c, scale, dx, dy); + } + } + + public abstract boolean play(boolean key_left, boolean key_right, + boolean key_fire, double trackball_dx, + double touch_dx); +} diff --git a/src/org/jfedor/frozenbubble/GameView.java b/src/org/jfedor/frozenbubble/GameView.java new file mode 100644 index 0000000..78f785d --- /dev/null +++ b/src/org/jfedor/frozenbubble/GameView.java @@ -0,0 +1,920 @@ +/* + * [[ Frozen-Bubble ]] + * + * Copyright (c) 2000-2003 Guillaume Cottenceau. + * Java sourcecode - Copyright (c) 2003 Glenn Sanson. + * + * This code is distributed under the GNU General Public License + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * Artwork: + * Alexis Younes <73lab at free.fr> + * (everything but the bubbles) + * Amaury Amblard-Ladurantie + * (the bubbles) + * + * Soundtrack: + * Matthias Le Bidan + * (the three musics and all the sound effects) + * + * Design & Programming: + * Guillaume Cottenceau + * (design and manage the project, whole Perl sourcecode) + * + * Java version: + * Glenn Sanson + * (whole Java sourcecode, including JIGA classes + * http://glenn.sanson.free.fr/jiga/) + * + * Android port: + * Pawel Aleksander Fedorynski + * + * [[ http://glenn.sanson.free.fr/fb/ ]] + * [[ http://www.frozen-bubble.org/ ]] + */ +// This file is derived from the LunarView.java file which is part of +// the Lunar Lander game included with Android documentation. The copyright +// notice for the Lunar Lander is reproduced below. +/* + * Copyright (C) 2007 Google Inc. + * + * 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. + */ + + +package org.jfedor.frozenbubble; + +import java.io.InputStream; +import java.io.IOException; +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.util.AttributeSet; +import android.view.KeyEvent; +import android.view.SurfaceHolder; +import android.view.SurfaceView; +import android.view.View; +import android.view.MotionEvent; +import java.util.Vector; + +import android.util.Log; + +class GameView extends SurfaceView implements SurfaceHolder.Callback { + class GameThread extends Thread { + private static final int FRAME_DELAY = 40; + + public static final int STATE_RUNNING = 1; + public static final int STATE_PAUSE = 2; + public static final int STATE_ABOUT = 4; + + public static final int GAMEFIELD_WIDTH = 320; + public static final int GAMEFIELD_HEIGHT = 480; + public static final int EXTENDED_GAMEFIELD_WIDTH = 640; + + private static final double TRACKBALL_COEFFICIENT = 5; + private static final double TOUCH_COEFFICIENT = 0.2; + private static final double TOUCH_FIRE_Y_THRESHOLD = 378; + + private int mCanvasHeight = 1; + private int mCanvasWidth = 1; + private long mLastTime; + private int mMode; + private boolean mRun = false; + + private boolean mLeft = false; + private boolean mRight = false; + private boolean mUp = false; + private boolean mFire = false; + private boolean mWasLeft = false; + private boolean mWasRight = false; + private boolean mWasFire = false; + private boolean mWasUp = false; + private double mTrackballDX = 0; + private double mTouchDX = 0; + private double mTouchLastX; + private boolean mTouchFire = false; + + private SurfaceHolder mSurfaceHolder; + private boolean mSurfaceOK = false; + + private double mDisplayScale; + private int mDisplayDX; + private int mDisplayDY; + + private FrozenGame mFrozenGame; + + private boolean mImagesReady = false; + + private Bitmap mBackgroundOrig; + private Bitmap[] mBubblesOrig; + private Bitmap[] mBubblesBlindOrig; + private Bitmap[] mFrozenBubblesOrig; + private Bitmap[] mTargetedBubblesOrig; + private Bitmap mBubbleBlinkOrig; + private Bitmap mGameWonOrig; + private Bitmap mGameLostOrig; + private Bitmap mHurryOrig; + private Bitmap mPenguinsOrig; + private Bitmap mCompressorHeadOrig; + private Bitmap mCompressorOrig; + private Bitmap mLifeOrig; + private Bitmap mFontImageOrig; + private BmpWrap mBackground; + private BmpWrap[] mBubbles; + private BmpWrap[] mBubblesBlind; + private BmpWrap[] mFrozenBubbles; + private BmpWrap[] mTargetedBubbles; + private BmpWrap mBubbleBlink; + private BmpWrap mGameWon; + private BmpWrap mGameLost; + private BmpWrap mHurry; + private BmpWrap mPenguins; + private BmpWrap mCompressorHead; + private BmpWrap mCompressor; + private BmpWrap mLife; + private BmpWrap mFontImage; + // Launcher has to be a drawable, not a bitmap, because we rotate it. + private Drawable mLauncher; + private SoundManager mSoundManager; + private LevelManager mLevelManager; + private BubbleFont mFont; + + Vector mImageList; + + private BmpWrap NewBmpWrap() + { + int new_img_id = mImageList.size(); + BmpWrap new_img = new BmpWrap(new_img_id); + mImageList.addElement(new_img); + return new_img; + } + + public GameThread(SurfaceHolder surfaceHolder) { + Log.i("frozen-bubble", "GameThread()"); + mSurfaceHolder = surfaceHolder; + Resources res = mContext.getResources(); + setState(STATE_PAUSE); + + mBackgroundOrig = + BitmapFactory.decodeResource(res, R.drawable.background); + mBubblesOrig = new Bitmap[8]; + mBubblesOrig[0] = BitmapFactory.decodeResource(res, R.drawable.bubble_1); + mBubblesOrig[1] = BitmapFactory.decodeResource(res, R.drawable.bubble_2); + mBubblesOrig[2] = BitmapFactory.decodeResource(res, R.drawable.bubble_3); + mBubblesOrig[3] = BitmapFactory.decodeResource(res, R.drawable.bubble_4); + mBubblesOrig[4] = BitmapFactory.decodeResource(res, R.drawable.bubble_5); + mBubblesOrig[5] = BitmapFactory.decodeResource(res, R.drawable.bubble_6); + mBubblesOrig[6] = BitmapFactory.decodeResource(res, R.drawable.bubble_7); + mBubblesOrig[7] = BitmapFactory.decodeResource(res, R.drawable.bubble_8); + mBubblesBlindOrig = new Bitmap[8]; + mBubblesBlindOrig[0] = BitmapFactory.decodeResource( + res, R.drawable.bubble_colourblind_1); + mBubblesBlindOrig[1] = BitmapFactory.decodeResource( + res, R.drawable.bubble_colourblind_2); + mBubblesBlindOrig[2] = BitmapFactory.decodeResource( + res, R.drawable.bubble_colourblind_3); + mBubblesBlindOrig[3] = BitmapFactory.decodeResource( + res, R.drawable.bubble_colourblind_4); + mBubblesBlindOrig[4] = BitmapFactory.decodeResource( + res, R.drawable.bubble_colourblind_5); + mBubblesBlindOrig[5] = BitmapFactory.decodeResource( + res, R.drawable.bubble_colourblind_6); + mBubblesBlindOrig[6] = BitmapFactory.decodeResource( + res, R.drawable.bubble_colourblind_7); + mBubblesBlindOrig[7] = BitmapFactory.decodeResource( + res, R.drawable.bubble_colourblind_8); + mFrozenBubblesOrig = new Bitmap[8]; + mFrozenBubblesOrig[0] = BitmapFactory.decodeResource( + res, R.drawable.frozen_1); + mFrozenBubblesOrig[1] = BitmapFactory.decodeResource( + res, R.drawable.frozen_2); + mFrozenBubblesOrig[2] = BitmapFactory.decodeResource( + res, R.drawable.frozen_3); + mFrozenBubblesOrig[3] = BitmapFactory.decodeResource( + res, R.drawable.frozen_4); + mFrozenBubblesOrig[4] = BitmapFactory.decodeResource( + res, R.drawable.frozen_5); + mFrozenBubblesOrig[5] = BitmapFactory.decodeResource( + res, R.drawable.frozen_6); + mFrozenBubblesOrig[6] = BitmapFactory.decodeResource( + res, R.drawable.frozen_7); + mFrozenBubblesOrig[7] = BitmapFactory.decodeResource( + res, R.drawable.frozen_8); + mTargetedBubblesOrig = new Bitmap[6]; + mTargetedBubblesOrig[0] = BitmapFactory.decodeResource( + res, R.drawable.fixed_1); + mTargetedBubblesOrig[1] = BitmapFactory.decodeResource( + res, R.drawable.fixed_2); + mTargetedBubblesOrig[2] = BitmapFactory.decodeResource( + res, R.drawable.fixed_3); + mTargetedBubblesOrig[3] = BitmapFactory.decodeResource( + res, R.drawable.fixed_4); + mTargetedBubblesOrig[4] = BitmapFactory.decodeResource( + res, R.drawable.fixed_5); + mTargetedBubblesOrig[5] = BitmapFactory.decodeResource( + res, R.drawable.fixed_6); + mBubbleBlinkOrig = + BitmapFactory.decodeResource(res, R.drawable.bubble_blink); + mGameWonOrig = BitmapFactory.decodeResource(res, R.drawable.win_panel); + mGameLostOrig = BitmapFactory.decodeResource(res, R.drawable.lose_panel); + mHurryOrig = BitmapFactory.decodeResource(res, R.drawable.hurry); + mPenguinsOrig = BitmapFactory.decodeResource(res, R.drawable.penguins); + mCompressorHeadOrig = + BitmapFactory.decodeResource(res, R.drawable.compressor); + mCompressorOrig = + BitmapFactory.decodeResource(res, R.drawable.compressor_body); + mLifeOrig = BitmapFactory.decodeResource(res, R.drawable.life); + mFontImageOrig = + BitmapFactory.decodeResource(res, R.drawable.bubble_font); + + mImageList = new Vector(); + + mBackground = NewBmpWrap(); + mBubbles = new BmpWrap[8]; + for (int i = 0; i < mBubbles.length; i++) { + mBubbles[i] = NewBmpWrap(); + } + mBubblesBlind = new BmpWrap[8]; + for (int i = 0; i < mBubblesBlind.length; i++) { + mBubblesBlind[i] = NewBmpWrap(); + } + mFrozenBubbles = new BmpWrap[8]; + for (int i = 0; i < mFrozenBubbles.length; i++) { + mFrozenBubbles[i] = NewBmpWrap(); + } + mTargetedBubbles = new BmpWrap[6]; + for (int i = 0; i < mTargetedBubbles.length; i++) { + mTargetedBubbles[i] = NewBmpWrap(); + } + mBubbleBlink = NewBmpWrap(); + mGameWon = NewBmpWrap(); + mGameLost = NewBmpWrap(); + mHurry = NewBmpWrap(); + mPenguins = NewBmpWrap(); + mCompressorHead = NewBmpWrap(); + mCompressor = NewBmpWrap(); + mLife = NewBmpWrap(); + mFontImage = NewBmpWrap(); + + mFont = new BubbleFont(mFontImage); + mLauncher = res.getDrawable(R.drawable.launcher); + + mSoundManager = new SoundManager(mContext); + + try { + InputStream is = mContext.getAssets().open("levels.txt"); + int size = is.available(); + byte[] levels = new byte[size]; + is.read(levels); + is.close(); + mLevelManager = new LevelManager(levels); + } catch (IOException e) { + // Should never happen. + throw new RuntimeException(e); + } + + mFrozenGame = new FrozenGame(mBackground, mBubbles, mBubblesBlind, + mFrozenBubbles, mTargetedBubbles, + mBubbleBlink, mGameWon, mGameLost, + mHurry, mPenguins, mCompressorHead, + mCompressor, mLauncher, + mSoundManager, mLevelManager); + } + + private void scaleFrom(BmpWrap image, Bitmap bmp) + { + if (image.bmp != null && image.bmp != bmp) { + image.bmp.recycle(); + } + + if (mDisplayScale > 0.99999 && mDisplayScale < 1.00001) { + image.bmp = bmp; + return; + } + int dstWidth = (int)(bmp.getWidth() * mDisplayScale); + int dstHeight = (int)(bmp.getHeight() * mDisplayScale); + image.bmp = Bitmap.createScaledBitmap(bmp, dstWidth, dstHeight, true); + } + + private void resizeBitmaps() + { + Log.i("frozen-bubble", "resizeBitmaps()"); + scaleFrom(mBackground, mBackgroundOrig); + for (int i = 0; i < mBubblesOrig.length; i++) { + scaleFrom(mBubbles[i], mBubblesOrig[i]); + } + for (int i = 0; i < mBubblesBlind.length; i++) { + scaleFrom(mBubblesBlind[i], mBubblesBlindOrig[i]); + } + for (int i = 0; i < mFrozenBubbles.length; i++) { + scaleFrom(mFrozenBubbles[i], mFrozenBubblesOrig[i]); + } + for (int i = 0; i < mTargetedBubbles.length; i++) { + scaleFrom(mTargetedBubbles[i], mTargetedBubblesOrig[i]); + } + scaleFrom(mBubbleBlink, mBubbleBlinkOrig); + scaleFrom(mGameWon, mGameWonOrig); + scaleFrom(mGameLost, mGameLostOrig); + scaleFrom(mHurry, mHurryOrig); + scaleFrom(mPenguins, mPenguinsOrig); + scaleFrom(mCompressorHead, mCompressorHeadOrig); + scaleFrom(mCompressor, mCompressorOrig); + scaleFrom(mLife, mLifeOrig); + scaleFrom(mFontImage, mFontImageOrig); + Log.i("frozen-bubble", "resizeBitmaps done."); + mImagesReady = true; + } + + public void pause() + { + synchronized (mSurfaceHolder) { + if (mMode == STATE_RUNNING) { + setState(STATE_PAUSE); + } + } + } + + public void newGame() + { + synchronized (mSurfaceHolder) { + mLevelManager.goToFirstLevel(); + mFrozenGame = new FrozenGame(mBackground, mBubbles, mBubblesBlind, + mFrozenBubbles, mTargetedBubbles, + mBubbleBlink, mGameWon, mGameLost, + mHurry, mPenguins, mCompressorHead, + mCompressor, mLauncher, + mSoundManager, mLevelManager); + } + } + + @Override + public void run() + { + while (mRun) { + long now = System.currentTimeMillis(); + long delay = FRAME_DELAY + mLastTime - now; + if (delay > 0) { + try{ + sleep(delay); + } catch (InterruptedException e) {} + } + mLastTime = now; + Canvas c = null; + try { + if (surfaceOK()) { + c = mSurfaceHolder.lockCanvas(null); + if (c != null) { + synchronized (mSurfaceHolder) { + if (mRun) { + if (mMode == STATE_ABOUT) { + drawAboutScreen(c); + } else { + if (mMode == STATE_RUNNING) { + updateGameState(); + } + doDraw(c); + } + } + } + } + } + } finally { + // do this in a finally so that if an exception is thrown + // during the above, we don't leave the Surface in an + // inconsistent state + if (c != null) { + mSurfaceHolder.unlockCanvasAndPost(c); + } + } + } + } + + /** + * Dump game state to the provided Bundle. Typically called when the + * Activity is being suspended. + * + * @return Bundle with this view's state + */ + public Bundle saveState(Bundle map) { + synchronized (mSurfaceHolder) { + if (map != null) { + mFrozenGame.saveState(map); + mLevelManager.saveState(map); + } + } + return map; + } + + /** + * Restores game state from the indicated Bundle. Typically called when + * the Activity is being restored after having been previously + * destroyed. + * + * @param savedState Bundle containing the game state + */ + public synchronized void restoreState(Bundle map) { + synchronized (mSurfaceHolder) { + setState(STATE_PAUSE); + mFrozenGame.restoreState(map, mImageList); + mLevelManager.restoreState(map); + } + } + + public void setRunning(boolean b) { + mRun = b; + } + + public void setState(int mode) { + synchronized (mSurfaceHolder) { + mMode = mode; + } + } + + public void setSurfaceOK(boolean ok) + { + synchronized (mSurfaceHolder) { + mSurfaceOK = ok; + } + } + + public boolean surfaceOK() + { + synchronized (mSurfaceHolder) { + return mSurfaceOK; + } + } + + public void setSurfaceSize(int width, int height) + { + synchronized (mSurfaceHolder) { + mCanvasWidth = width; + mCanvasHeight = height; + if (width / height >= GAMEFIELD_WIDTH / GAMEFIELD_HEIGHT) { + mDisplayScale = 1.0 * height / GAMEFIELD_HEIGHT; + mDisplayDX = + (int)((width - mDisplayScale * EXTENDED_GAMEFIELD_WIDTH) / 2); + mDisplayDY = 0; + } else { + mDisplayScale = 1.0 * width / GAMEFIELD_WIDTH; + mDisplayDX = (int)(-mDisplayScale * + (EXTENDED_GAMEFIELD_WIDTH - GAMEFIELD_WIDTH) / 2); + mDisplayDY = (int)((height - mDisplayScale * GAMEFIELD_HEIGHT) / 2); + } + resizeBitmaps(); + } + } + + boolean doKeyDown(int keyCode, KeyEvent msg) + { + synchronized (mSurfaceHolder) { + if (mMode != STATE_RUNNING) { + setState(STATE_RUNNING); + } + + if (mMode == STATE_RUNNING) { + Log.i("frozen-bubble", "STATE RUNNING"); + if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) { + mLeft = true; + mWasLeft = true; + return true; + } else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) { + mRight = true; + mWasRight = true; + return true; + } else if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { + mFire = true; + mWasFire = true; + return true; + } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) { + mUp = true; + mWasUp = true; + return true; + } + } + + return false; + } + } + + boolean doKeyUp(int keyCode, KeyEvent msg) + { + synchronized (mSurfaceHolder) { + if (mMode == STATE_RUNNING) { + if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) { + mLeft = false; + return true; + } else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) { + mRight = false; + return true; + } else if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { + mFire = false; + return true; + } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) { + mUp = false; + return true; + } + } + return false; + } + } + + boolean doTrackballEvent(MotionEvent event) + { + synchronized (mSurfaceHolder) { + if (mMode != STATE_RUNNING) { + setState(STATE_RUNNING); + } + + if (mMode == STATE_RUNNING) { + if (event.getAction() == MotionEvent.ACTION_MOVE) { + mTrackballDX += event.getX() * TRACKBALL_COEFFICIENT; + return true; + } + } + return false; + } + } + + private double xFromScr(float x) + { + return (x - mDisplayDX) / mDisplayScale; + } + + private double yFromScr(float y) + { + return (y - mDisplayDY) / mDisplayScale; + } + + boolean doTouchEvent(MotionEvent event) + { + synchronized (mSurfaceHolder) { + if (mMode != STATE_RUNNING) { + setState(STATE_RUNNING); + } + + double x = xFromScr(event.getX()); + double y = yFromScr(event.getY()); + if (event.getAction() == MotionEvent.ACTION_DOWN) { + if (y < TOUCH_FIRE_Y_THRESHOLD) { + mTouchFire = true; + } + mTouchLastX = x; + } else if (event.getAction() == MotionEvent.ACTION_MOVE) { + if (y >= TOUCH_FIRE_Y_THRESHOLD) { + mTouchDX = (x - mTouchLastX) * TOUCH_COEFFICIENT; + } + mTouchLastX = x; + } + return true; + } + } + + private void drawBackground(Canvas c) + { + Sprite.drawImage(mBackground, 0, 0, c, mDisplayScale, + mDisplayDX, mDisplayDY); + } + + private void drawLevelNumber(Canvas canvas) + { + int y = 433; + int x; + int level = mLevelManager.getLevelIndex(); + if (level < 10) { + x = 185; + mFont.paintChar(Character.forDigit(level, 10), x, y, canvas, + mDisplayScale, mDisplayDX, mDisplayDY); + } else if (level < 100) { + x = 178; + x += mFont.paintChar(Character.forDigit(level / 10, 10), x, y, canvas, + mDisplayScale, mDisplayDX, mDisplayDY); + mFont.paintChar(Character.forDigit(level % 10, 10), x, y, canvas, + mDisplayScale, mDisplayDX, mDisplayDY); + } else { + x = 173; + x += mFont.paintChar(Character.forDigit(level / 100, 10), x, y, canvas, + mDisplayScale, mDisplayDX, mDisplayDY); + level -= 100 * (level / 100); + x += mFont.paintChar(Character.forDigit(level / 10, 10), x, y, canvas, + mDisplayScale, mDisplayDX, mDisplayDY); + mFont.paintChar(Character.forDigit(level % 10, 10), x, y, canvas, + mDisplayScale, mDisplayDX, mDisplayDY); + } + } + + private void drawAboutScreen(Canvas canvas) + { + canvas.drawRGB(0, 0, 0); + int x = 168; + int y = 20; + int ysp = 26; + int indent = 10; + mFont.print("original frozen bubble:", x, y, canvas, + mDisplayScale, mDisplayDX, mDisplayDY); + y += ysp; + mFont.print("guillaume cottenceau", x + indent, y, canvas, + mDisplayScale, mDisplayDX, mDisplayDY); + y += ysp; + mFont.print("alexis younes", x + indent, y, canvas, + mDisplayScale, mDisplayDX, mDisplayDY); + y += ysp; + mFont.print("amaury amblard-ladurantie", x + indent, y, canvas, + mDisplayScale, mDisplayDX, mDisplayDY); + y += ysp; + mFont.print("matthias le bidan", x + indent, y, canvas, + mDisplayScale, mDisplayDX, mDisplayDY); + y += ysp; + y += ysp; + mFont.print("java version:", x, y, canvas, + mDisplayScale, mDisplayDX, mDisplayDY); + y += ysp; + mFont.print("glenn sanson", x + indent, y, canvas, + mDisplayScale, mDisplayDX, mDisplayDY); + y += ysp; + y += ysp; + mFont.print("android port:", x, y, canvas, + mDisplayScale, mDisplayDX, mDisplayDY); + y += ysp; + mFont.print("aleksander fedorynski", x + indent, y, canvas, + mDisplayScale, mDisplayDX, mDisplayDY); + y += 2 * ysp; + mFont.print("android port source code", x, y, canvas, + mDisplayScale, mDisplayDX, mDisplayDY); + y += ysp; + mFont.print("is available at:", x, y, canvas, + mDisplayScale, mDisplayDX, mDisplayDY); + y += ysp; + mFont.print("http://code.google.com", x, y, canvas, + mDisplayScale, mDisplayDX, mDisplayDY); + y += ysp; + mFont.print("/p/frozenbubbleandroid", x, y, canvas, + mDisplayScale, mDisplayDX, mDisplayDY); + } + + private void doDraw(Canvas canvas) + { + //Log.i("frozen-bubble", "doDraw()"); + if (!mImagesReady) { + Log.i("frozen-bubble", "!mImagesReady, returning"); + return; + } + if (mDisplayDX > 0 || mDisplayDY > 0) { + Log.i("frozen-bubble", "Drawing black background."); + canvas.drawRGB(0, 0, 0); + } + drawBackground(canvas); + drawLevelNumber(canvas); + mFrozenGame.paint(canvas, mDisplayScale, mDisplayDX, mDisplayDY); + } + + private void updateGameState() { + if (mFrozenGame.play(mLeft || mWasLeft, mRight || mWasRight, + mFire || mUp || mWasFire || mWasUp || mTouchFire, + mTrackballDX, mTouchDX)) { + // Lost or won. Need to start over. The level is already + // incremented if this was a win. + mFrozenGame = new FrozenGame(mBackground, mBubbles, mBubblesBlind, + mFrozenBubbles, mTargetedBubbles, + mBubbleBlink, mGameWon, mGameLost, + mHurry, mPenguins, mCompressorHead, + mCompressor, mLauncher, mSoundManager, + mLevelManager); + } + mWasLeft = false; + mWasRight = false; + mWasFire = false; + mWasUp = false; + mTrackballDX = 0; + mTouchFire = false; + mTouchDX = 0; + } + + public void cleanUp() { + synchronized (mSurfaceHolder) { + // I don't really understand why all this is necessary. + // I used to get a crash (an out-of-memory error) once every six or + // seven times I started the game. I googled the error and someone + // said you have to call recycle() on all the bitmaps and set + // the pointers to null to facilitate garbage collection. So I did + // and the crashes went away. + mImagesReady = false; + boolean imagesScaled = (mBackgroundOrig == mBackground.bmp); + mBackgroundOrig.recycle(); + mBackgroundOrig = null; + for (int i = 0; i < mBubblesOrig.length; i++) { + mBubblesOrig[i].recycle(); + mBubblesOrig[i] = null; + } + mBubblesOrig = null; + for (int i = 0; i < mBubblesBlindOrig.length; i++) { + mBubblesBlindOrig[i].recycle(); + mBubblesBlindOrig[i] = null; + } + mBubblesBlindOrig = null; + for (int i = 0; i < mFrozenBubblesOrig.length; i++) { + mFrozenBubblesOrig[i].recycle(); + mFrozenBubblesOrig[i] = null; + } + mFrozenBubblesOrig = null; + for (int i = 0; i < mTargetedBubblesOrig.length; i++) { + mTargetedBubblesOrig[i].recycle(); + mTargetedBubblesOrig[i] = null; + } + mTargetedBubblesOrig = null; + mBubbleBlinkOrig.recycle(); + mBubbleBlinkOrig = null; + mGameWonOrig.recycle(); + mGameWonOrig = null; + mGameLostOrig.recycle(); + mGameLostOrig = null; + mHurryOrig.recycle(); + mHurryOrig = null; + mPenguinsOrig.recycle(); + mPenguinsOrig = null; + mCompressorHeadOrig.recycle(); + mCompressorHeadOrig = null; + mCompressorOrig.recycle(); + mCompressorOrig = null; + mLifeOrig.recycle(); + mLifeOrig = null; + + if (imagesScaled) { + mBackground.bmp.recycle(); + for (int i = 0; i < mBubbles.length; i++) { + mBubbles[i].bmp.recycle(); + } + for (int i = 0; i < mBubblesBlind.length; i++) { + mBubblesBlind[i].bmp.recycle(); + } + for (int i = 0; i < mFrozenBubbles.length; i++) { + mFrozenBubbles[i].bmp.recycle(); + } + for (int i = 0; i < mTargetedBubbles.length; i++) { + mTargetedBubbles[i].bmp.recycle(); + } + mBubbleBlink.bmp.recycle(); + mGameWon.bmp.recycle(); + mGameLost.bmp.recycle(); + mHurry.bmp.recycle(); + mPenguins.bmp.recycle(); + mCompressorHead.bmp.recycle(); + mCompressor.bmp.recycle(); + mLife.bmp.recycle(); + } + mBackground.bmp = null; + mBackground = null; + for (int i = 0; i < mBubbles.length; i++) { + mBubbles[i].bmp = null; + mBubbles[i] = null; + } + mBubbles = null; + for (int i = 0; i < mBubblesBlind.length; i++) { + mBubblesBlind[i].bmp = null; + mBubblesBlind[i] = null; + } + mBubblesBlind = null; + for (int i = 0; i < mFrozenBubbles.length; i++) { + mFrozenBubbles[i].bmp = null; + mFrozenBubbles[i] = null; + } + mFrozenBubbles = null; + for (int i = 0; i < mTargetedBubbles.length; i++) { + mTargetedBubbles[i].bmp = null; + mTargetedBubbles[i] = null; + } + mTargetedBubbles = null; + mBubbleBlink.bmp = null; + mBubbleBlink = null; + mGameWon.bmp = null; + mGameWon = null; + mGameLost.bmp = null; + mGameLost = null; + mHurry.bmp = null; + mHurry = null; + mPenguins.bmp = null; + mPenguins = null; + mCompressorHead.bmp = null; + mCompressorHead = null; + mCompressor.bmp = null; + mCompressor = null; + mLife.bmp = null; + mLife = null; + + mImageList = null; + mSoundManager.cleanUp(); + mSoundManager = null; + mLevelManager = null; + mFrozenGame = null; + } + } + } + + private Context mContext; + private GameThread thread; + + public GameView(Context context, AttributeSet attrs) { + super(context, attrs); + Log.i("frozen-bubble", "GameView constructor"); + + mContext = context; + SurfaceHolder holder = getHolder(); + holder.addCallback(this); + + thread = new GameThread(holder); + setFocusable(true); + setFocusableInTouchMode(true); + + thread.setRunning(true); + thread.start(); + } + + public GameThread getThread() { + return thread; + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent msg) { + //Log.i("frozen-bubble", "GameView.onKeyDown()"); + return thread.doKeyDown(keyCode, msg); + } + + @Override + public boolean onKeyUp(int keyCode, KeyEvent msg) { + //Log.i("frozen-bubble", "GameView.onKeyUp()"); + return thread.doKeyUp(keyCode, msg); + } + + @Override + public boolean onTrackballEvent(MotionEvent event) { + //Log.i("frozen-bubble", "event.getX(): " + event.getX()); + //Log.i("frozen-bubble", "event.getY(): " + event.getY()); + return thread.doTrackballEvent(event); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + return thread.doTouchEvent(event); + } + + @Override + public void onWindowFocusChanged(boolean hasWindowFocus) { + Log.i("frozen-bubble", "GameView.onWindowFocusChanged()"); + if (!hasWindowFocus) { + thread.pause(); + } + } + + public void surfaceChanged(SurfaceHolder holder, int format, int width, + int height) { + Log.i("frozen-bubble", "GameView.surfaceChanged"); + thread.setSurfaceSize(width, height); + } + + public void surfaceCreated(SurfaceHolder holder) { + Log.i("frozen-bubble", "GameView.surfaceCreated()"); + thread.setSurfaceOK(true); + } + + public void surfaceDestroyed(SurfaceHolder holder) { + Log.i("frozen-bubble", "GameView.surfaceDestroyed()"); + thread.setSurfaceOK(false); + } + + public void cleanUp() { + Log.i("frozen-bubble", "GameView.cleanUp()"); + thread.cleanUp(); + mContext = null; + } +} diff --git a/src/org/jfedor/frozenbubble/ImageSprite.java b/src/org/jfedor/frozenbubble/ImageSprite.java new file mode 100644 index 0000000..371d075 --- /dev/null +++ b/src/org/jfedor/frozenbubble/ImageSprite.java @@ -0,0 +1,91 @@ +/* + * [[ Frozen-Bubble ]] + * + * Copyright (c) 2000-2003 Guillaume Cottenceau. + * Java sourcecode - Copyright (c) 2003 Glenn Sanson. + * + * This code is distributed under the GNU General Public License + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * Artwork: + * Alexis Younes <73lab at free.fr> + * (everything but the bubbles) + * Amaury Amblard-Ladurantie + * (the bubbles) + * + * Soundtrack: + * Matthias Le Bidan + * (the three musics and all the sound effects) + * + * Design & Programming: + * Guillaume Cottenceau + * (design and manage the project, whole Perl sourcecode) + * + * Java version: + * Glenn Sanson + * (whole Java sourcecode, including JIGA classes + * http://glenn.sanson.free.fr/jiga/) + * + * Android port: + * Pawel Aleksander Fedorynski + * + * [[ http://glenn.sanson.free.fr/fb/ ]] + * [[ http://www.frozen-bubble.org/ ]] + */ + +package org.jfedor.frozenbubble; + +import android.graphics.Canvas; +import android.graphics.Point; +import android.graphics.Rect; +import android.os.Bundle; +import java.util.Vector; + +public class ImageSprite extends Sprite +{ + private BmpWrap displayedImage; + + public ImageSprite(Rect area, BmpWrap img) + { + super(area); + + this.displayedImage = img; + } + + public void saveState(Bundle map, Vector savedSprites) { + if (getSavedId() != -1) { + return; + } + super.saveState(map, savedSprites); + map.putInt(String.format("%d-imageId", getSavedId()), displayedImage.id); + } + + public int getTypeId() + { + return Sprite.TYPE_IMAGE; + } + + public void changeImage(BmpWrap img) + { + this.displayedImage = img; + } + + public final void paint(Canvas c, double scale, int dx, int dy) + { + Point p = super.getSpritePosition(); + drawImage(displayedImage, p.x, p.y, c, scale, dx, dy); + } +} diff --git a/src/org/jfedor/frozenbubble/LaunchBubbleSprite.java b/src/org/jfedor/frozenbubble/LaunchBubbleSprite.java new file mode 100644 index 0000000..82db9ce --- /dev/null +++ b/src/org/jfedor/frozenbubble/LaunchBubbleSprite.java @@ -0,0 +1,124 @@ +/* + * [[ Frozen-Bubble ]] + * + * Copyright (c) 2000-2003 Guillaume Cottenceau. + * Java sourcecode - Copyright (c) 2003 Glenn Sanson. + * + * This code is distributed under the GNU General Public License + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * Artwork: + * Alexis Younes <73lab at free.fr> + * (everything but the bubbles) + * Amaury Amblard-Ladurantie + * (the bubbles) + * + * Soundtrack: + * Matthias Le Bidan + * (the three musics and all the sound effects) + * + * Design & Programming: + * Guillaume Cottenceau + * (design and manage the project, whole Perl sourcecode) + * + * Java version: + * Glenn Sanson + * (whole Java sourcecode, including JIGA classes + * http://glenn.sanson.free.fr/jiga/) + * + * Android port: + * Pawel Aleksander Fedorynski + * + * [[ http://glenn.sanson.free.fr/fb/ ]] + * [[ http://www.frozen-bubble.org/ ]] + */ + +package org.jfedor.frozenbubble; + +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import java.util.Vector; + +public class LaunchBubbleSprite extends Sprite +{ + private int currentColor; + private int currentDirection; + private Drawable launcher; + private BmpWrap[] bubbles; + private BmpWrap[] colorblindBubbles; + + public LaunchBubbleSprite(int initialColor, int initialDirection, + Drawable launcher, + BmpWrap[] bubbles, BmpWrap[] colorblindBubbles) + { + super(new Rect(276, 362, 276 + 86, 362 + 76)); + + currentColor = initialColor; + currentDirection = initialDirection; + this.launcher = launcher; + this.bubbles = bubbles; + this.colorblindBubbles = colorblindBubbles; + } + + public void saveState(Bundle map, Vector saved_sprites) { + if (getSavedId() != -1) { + return; + } + super.saveState(map, saved_sprites); + map.putInt(String.format("%d-currentColor", getSavedId()), currentColor); + map.putInt(String.format("%d-currentDirection", getSavedId()), + currentDirection); + } + + public int getTypeId() + { + return Sprite.TYPE_LAUNCH_BUBBLE; + } + + public void changeColor(int newColor) + { + currentColor = newColor; + } + + public void changeDirection(int newDirection) + { + currentDirection = newDirection; + } + + public final void paint(Canvas c, double scale, int dx, int dy) + { + if (FrozenBubble.getMode() == FrozenBubble.GAME_NORMAL) { + drawImage(bubbles[currentColor], 302, 390, c, scale, dx, dy); + } else { + drawImage(colorblindBubbles[currentColor], 302, 390, c, scale, dx, dy); + } + + // Draw the scaled and rotated launcher. + c.save(); + int xCenter = 318; + int yCenter = 406; + c.rotate((float)(0.025 * 180 * (currentDirection - 20)), + (float)(xCenter * scale + dx), (float)(yCenter * scale + dy)); + launcher.setBounds((int)((xCenter - 50) * scale + dx), + (int)((yCenter - 50) * scale + dy), + (int)((xCenter + 50) * scale + dx), + (int)((yCenter + 50) * scale + dy)); + launcher.draw(c); + c.restore(); + } +} diff --git a/src/org/jfedor/frozenbubble/LevelManager.java b/src/org/jfedor/frozenbubble/LevelManager.java new file mode 100644 index 0000000..36dee79 --- /dev/null +++ b/src/org/jfedor/frozenbubble/LevelManager.java @@ -0,0 +1,177 @@ +/* + * [[ Frozen-Bubble ]] + * + * Copyright (c) 2000-2003 Guillaume Cottenceau. + * Java sourcecode - Copyright (c) 2003 Glenn Sanson. + * + * This code is distributed under the GNU General Public License + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * Artwork: + * Alexis Younes <73lab at free.fr> + * (everything but the bubbles) + * Amaury Amblard-Ladurantie + * (the bubbles) + * + * Soundtrack: + * Matthias Le Bidan + * (the three musics and all the sound effects) + * + * Design & Programming: + * Guillaume Cottenceau + * (design and manage the project, whole Perl sourcecode) + * + * Java version: + * Glenn Sanson + * (whole Java sourcecode, including JIGA classes + * http://glenn.sanson.free.fr/jiga/) + * + * Android port: + * Pawel Aleksander Fedorynski + * + * [[ http://glenn.sanson.free.fr/fb/ ]] + * [[ http://www.frozen-bubble.org/ ]] + */ + +package org.jfedor.frozenbubble; + +import android.os.Bundle; +import java.util.Vector; + +public class LevelManager +{ + private int currentLevel; + private Vector levelList; + + public void saveState(Bundle map) + { + map.putInt("LevelManager-currentLevel", currentLevel); + } + + public void restoreState(Bundle map) + { + currentLevel = map.getInt("LevelManager-currentLevel"); + } + + public LevelManager(byte[] levels) + { + String allLevels = new String(levels); + + currentLevel = 0; + levelList = new Vector(); + + int nextLevel = allLevels.indexOf("\n\n"); + if (nextLevel == -1 && allLevels.trim().length() != 0) + { + nextLevel = allLevels.length(); + } + + while (nextLevel != -1) + { + String currentLevel = allLevels.substring(0, nextLevel).trim(); + + levelList.addElement(getLevel(currentLevel)); + + allLevels = allLevels.substring(nextLevel).trim(); + + if (allLevels.length() == 0) + { + nextLevel = -1; + } + else + { + nextLevel = allLevels.indexOf("\n\n"); + + if (nextLevel == -1) + { + nextLevel = allLevels.length(); + } + } + } + } + + private byte[][] getLevel(String data) + { + byte[][] temp = new byte[8][12]; + + for (int j=0 ; j<12 ; j++) + { + for (int i=0 ; i<8 ; i++) + { + temp[i][j] = -1; + } + } + + int tempX = 0; + int tempY = 0; + + for (int i=0 ; i= 48 && data.charAt(i) <= 55) + { + temp[tempX][tempY] = (byte)(data.charAt(i) - 48); + tempX++; + } + else if (data.charAt(i) == 45) + { + temp[tempX][tempY] = -1; + tempX++; + } + + if (tempX == 8) + { + tempY++; + + if (tempY == 12) + { + return temp; + } + + tempX = tempY % 2; + } + } + + return temp; + } + + public byte[][] getCurrentLevel() + { + if (currentLevel < levelList.size()) + { + return (byte[][])levelList.elementAt(currentLevel); + } + + return null; + } + + public void goToNextLevel() + { + currentLevel++; + if (currentLevel >= levelList.size()) { + currentLevel = 0; + } + } + + public void goToFirstLevel() + { + currentLevel = 0; + } + + public int getLevelIndex() + { + return currentLevel+1; + } +} diff --git a/src/org/jfedor/frozenbubble/PenguinSprite.java b/src/org/jfedor/frozenbubble/PenguinSprite.java new file mode 100644 index 0000000..9b598d3 --- /dev/null +++ b/src/org/jfedor/frozenbubble/PenguinSprite.java @@ -0,0 +1,188 @@ +/* + * [[ Frozen-Bubble ]] + * + * Copyright (c) 2000-2003 Guillaume Cottenceau. + * Java sourcecode - Copyright (c) 2003 Glenn Sanson. + * + * This code is distributed under the GNU General Public License + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * Artwork: + * Alexis Younes <73lab at free.fr> + * (everything but the bubbles) + * Amaury Amblard-Ladurantie + * (the bubbles) + * + * Soundtrack: + * Matthias Le Bidan + * (the three musics and all the sound effects) + * + * Design & Programming: + * Guillaume Cottenceau + * (design and manage the project, whole Perl sourcecode) + * + * Java version: + * Glenn Sanson + * (whole Java sourcecode, including JIGA classes + * http://glenn.sanson.free.fr/jiga/) + * + * Android port: + * Pawel Aleksander Fedorynski + * + * [[ http://glenn.sanson.free.fr/fb/ ]] + * [[ http://www.frozen-bubble.org/ ]] + */ + +package org.jfedor.frozenbubble; + +import android.graphics.Canvas; +import android.graphics.Rect; +import android.os.Bundle; +import java.util.Random; +import java.util.Vector; + +public class PenguinSprite extends Sprite +{ + public final static int STATE_TURN_LEFT = 0; + public final static int STATE_TURN_RIGHT = 1; + public final static int STATE_FIRE = 2; + public final static int STATE_VOID = 3; + public final static int STATE_GAME_WON = 4; + public final static int STATE_GAME_LOST = 5; + + public final static int[][] LOST_SEQUENCE = + {{1,0}, {2,8}, {3,9}, {4,10}, {5,11}, {6,12}, {7,13}, {5,14}}; + public final static int[][] WON_SEQUENCE = + {{1,0}, {2,7}, {3,6}, {4,15}, {5,16}, {6,17}, {7,18}, {4,19}}; + + private BmpWrap spritesImage; + + private int currentPenguin; + + private int count; + + private Random rand; + + private int finalState; + private int nextPosition; + + public PenguinSprite(BmpWrap sprites, Random rand) + { + super(new Rect(360, 436, 360 + 57, 435 + 45)); + + this.spritesImage = sprites; + this.rand = rand; + + currentPenguin = 0; + + finalState = STATE_VOID; + nextPosition = 0; + } + + public PenguinSprite(BmpWrap sprites, Random rand, + int currentPenguin, int count, + int finalState, int nextPosition) + { + super(new Rect(360, 436, 360 + 57, 435 + 45)); + + this.spritesImage = sprites; + this.rand = rand; + this.currentPenguin = currentPenguin; + this.count = count; + this.finalState = finalState; + this.nextPosition = nextPosition; + } + + public void saveState(Bundle map, Vector saved_sprites) { + if (getSavedId() != -1) { + return; + } + super.saveState(map, saved_sprites); + map.putInt(String.format("%d-currentPenguin", getSavedId()), + currentPenguin); + map.putInt(String.format("%d-count", getSavedId()), count); + map.putInt(String.format("%d-finalState", getSavedId()), finalState); + map.putInt(String.format("%d-nextPosition", getSavedId()), nextPosition); + } + + public int getTypeId() + { + return Sprite.TYPE_PENGUIN; + } + + public void updateState(int state) + { + if (finalState != STATE_VOID) { + count++; + + if (count % 6 == 0) { + if (finalState == STATE_GAME_LOST) { + currentPenguin = LOST_SEQUENCE[nextPosition][1]; + nextPosition = LOST_SEQUENCE[nextPosition][0]; + } else if (finalState == STATE_GAME_WON) { + currentPenguin = WON_SEQUENCE[nextPosition][1]; + nextPosition = WON_SEQUENCE[nextPosition][0]; + } + } + } else { + count++; + + switch(state) { + case STATE_TURN_LEFT : + count = 0; + currentPenguin = 3; + break; + case STATE_TURN_RIGHT : + count = 0; + currentPenguin = 2; + break; + case STATE_FIRE : + count = 0; + currentPenguin = 1; + break; + case STATE_VOID : + if (currentPenguin<4 || currentPenguin>7) { + currentPenguin = 0; + } + break; + case STATE_GAME_WON : + case STATE_GAME_LOST : + count = 0; + finalState = state; + currentPenguin = 0; + return; + } + + if (count>100) { + currentPenguin = 7; + } else if (count % 15 == 0 && count>25) { + currentPenguin = (rand.nextInt() % 3)+4; + if (currentPenguin < 4) { + currentPenguin = 0; + } + } + } + } + + public void paint(Canvas c, double scale, int dx, int dy) + { + Rect r = this.getSpriteArea(); + drawImageClipped(spritesImage, + 360 - (currentPenguin % 4) * 57, + 435 - (currentPenguin / 4) * 45, + r, c, scale, dx, dy); + } +} diff --git a/src/org/jfedor/frozenbubble/R.java b/src/org/jfedor/frozenbubble/R.java new file mode 100644 index 0000000..d168c81 --- /dev/null +++ b/src/org/jfedor/frozenbubble/R.java @@ -0,0 +1,89 @@ +/* AUTO-GENERATED FILE. DO NOT MODIFY. + * + * This class was automatically generated by the + * aapt tool from the resource data it found. It + * should not be modified by hand. + */ + +package org.jfedor.frozenbubble; + +public final class R { + public static final class attr { + } + public static final class drawable { + public static final int background=0x7f020000; + public static final int bubble_1=0x7f020001; + public static final int bubble_2=0x7f020002; + public static final int bubble_3=0x7f020003; + public static final int bubble_4=0x7f020004; + public static final int bubble_5=0x7f020005; + public static final int bubble_6=0x7f020006; + public static final int bubble_7=0x7f020007; + public static final int bubble_8=0x7f020008; + public static final int bubble_blink=0x7f020009; + public static final int bubble_colourblind_1=0x7f02000a; + public static final int bubble_colourblind_2=0x7f02000b; + public static final int bubble_colourblind_3=0x7f02000c; + public static final int bubble_colourblind_4=0x7f02000d; + public static final int bubble_colourblind_5=0x7f02000e; + public static final int bubble_colourblind_6=0x7f02000f; + public static final int bubble_colourblind_7=0x7f020010; + public static final int bubble_colourblind_8=0x7f020011; + public static final int bubble_font=0x7f020012; + public static final int close_eyes=0x7f020013; + public static final int compressor=0x7f020014; + public static final int compressor_body=0x7f020015; + public static final int fixed_1=0x7f020016; + public static final int fixed_2=0x7f020017; + public static final int fixed_3=0x7f020018; + public static final int fixed_4=0x7f020019; + public static final int fixed_5=0x7f02001a; + public static final int fixed_6=0x7f02001b; + public static final int frozen_1=0x7f02001c; + public static final int frozen_2=0x7f02001d; + public static final int frozen_3=0x7f02001e; + public static final int frozen_4=0x7f02001f; + public static final int frozen_5=0x7f020020; + public static final int frozen_6=0x7f020021; + public static final int frozen_7=0x7f020022; + public static final int frozen_8=0x7f020023; + public static final int hurry=0x7f020024; + public static final int launcher=0x7f020025; + public static final int life=0x7f020026; + public static final int lose_panel=0x7f020027; + public static final int penguins=0x7f020028; + public static final int splash=0x7f020029; + public static final int void_panel=0x7f02002a; + public static final int win_panel=0x7f02002b; + } + public static final class id { + public static final int game=0x7f060000; + } + public static final class layout { + public static final int main=0x7f030000; + } + public static final class raw { + public static final int applause=0x7f040000; + public static final int destroy_group=0x7f040001; + public static final int hurry=0x7f040002; + public static final int launch=0x7f040003; + public static final int lose=0x7f040004; + public static final int newroot_solo=0x7f040005; + public static final int noh=0x7f040006; + public static final int rebound=0x7f040007; + public static final int stick=0x7f040008; + } + public static final class string { + public static final int app_name=0x7f050000; + public static final int menu_about=0x7f050008; + public static final int menu_colorblind_mode_off=0x7f050003; + public static final int menu_colorblind_mode_on=0x7f050002; + public static final int menu_dont_rush_me=0x7f050009; + public static final int menu_fullscreen_off=0x7f050005; + public static final int menu_fullscreen_on=0x7f050004; + public static final int menu_new_game=0x7f050001; + public static final int menu_rush_me=0x7f05000a; + public static final int menu_sound_off=0x7f050007; + public static final int menu_sound_on=0x7f050006; + } +} diff --git a/src/org/jfedor/frozenbubble/SoundManager.java b/src/org/jfedor/frozenbubble/SoundManager.java new file mode 100644 index 0000000..36d743d --- /dev/null +++ b/src/org/jfedor/frozenbubble/SoundManager.java @@ -0,0 +1,97 @@ +/* + * [[ Frozen-Bubble ]] + * + * Copyright (c) 2000-2003 Guillaume Cottenceau. + * Java sourcecode - Copyright (c) 2003 Glenn Sanson. + * + * This code is distributed under the GNU General Public License + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * Artwork: + * Alexis Younes <73lab at free.fr> + * (everything but the bubbles) + * Amaury Amblard-Ladurantie + * (the bubbles) + * + * Soundtrack: + * Matthias Le Bidan + * (the three musics and all the sound effects) + * + * Design & Programming: + * Guillaume Cottenceau + * (design and manage the project, whole Perl sourcecode) + * + * Java version: + * Glenn Sanson + * (whole Java sourcecode, including JIGA classes + * http://glenn.sanson.free.fr/jiga/) + * + * Android port: + * Pawel Aleksander Fedorynski + * + * [[ http://glenn.sanson.free.fr/fb/ ]] + * [[ http://www.frozen-bubble.org/ ]] + */ + +package org.jfedor.frozenbubble; + +import android.content.Context; +import android.media.AudioManager; +import android.media.SoundPool; + +public class SoundManager +{ + private SoundPool soundPool; + private int[] sm; + Context context; + + public SoundManager(Context context) { + this.context = context; + soundPool = new SoundPool(4, AudioManager.STREAM_MUSIC, 0); + sm = new int[FrozenBubble.NUM_SOUNDS]; + sm[FrozenBubble.SOUND_WON] = soundPool.load(context, R.raw.applause, 1); + sm[FrozenBubble.SOUND_LOST] = soundPool.load(context, R.raw.lose, 1); + sm[FrozenBubble.SOUND_LAUNCH] = soundPool.load(context, R.raw.launch, 1); + sm[FrozenBubble.SOUND_DESTROY] = + soundPool.load(context, R.raw.destroy_group, 1); + sm[FrozenBubble.SOUND_REBOUND] = + soundPool.load(context, R.raw.rebound, 1); + sm[FrozenBubble.SOUND_STICK] = soundPool.load(context, R.raw.stick, 1); + sm[FrozenBubble.SOUND_HURRY] = soundPool.load(context, R.raw.hurry, 1); + sm[FrozenBubble.SOUND_NEWROOT] = + soundPool.load(context, R.raw.newroot_solo, 1); + sm[FrozenBubble.SOUND_NOH] = soundPool.load(context, R.raw.noh, 1); + } + + public final void playSound(int sound) { + if (FrozenBubble.getSoundOn()) { + AudioManager mgr = (AudioManager)context.getSystemService( + Context.AUDIO_SERVICE); + float streamVolumeCurrent = + mgr.getStreamVolume(AudioManager.STREAM_MUSIC); + float streamVolumeMax = mgr.getStreamMaxVolume(AudioManager.STREAM_MUSIC); + float volume = streamVolumeCurrent / streamVolumeMax; + soundPool.play(sm[sound], volume, volume, 1, 0, 1f); + } + } + + public final void cleanUp() { + sm = null; + context = null; + soundPool.release(); + soundPool = null; + } +} diff --git a/src/org/jfedor/frozenbubble/Sprite.java b/src/org/jfedor/frozenbubble/Sprite.java new file mode 100644 index 0000000..b189297 --- /dev/null +++ b/src/org/jfedor/frozenbubble/Sprite.java @@ -0,0 +1,155 @@ +/* + * [[ Frozen-Bubble ]] + * + * Copyright (c) 2000-2003 Guillaume Cottenceau. + * Java sourcecode - Copyright (c) 2003 Glenn Sanson. + * + * This code is distributed under the GNU General Public License + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * Artwork: + * Alexis Younes <73lab at free.fr> + * (everything but the bubbles) + * Amaury Amblard-Ladurantie + * (the bubbles) + * + * Soundtrack: + * Matthias Le Bidan + * (the three musics and all the sound effects) + * + * Design & Programming: + * Guillaume Cottenceau + * (design and manage the project, whole Perl sourcecode) + * + * Java version: + * Glenn Sanson + * (whole Java sourcecode, including JIGA classes + * http://glenn.sanson.free.fr/jiga/) + * + * Android port: + * Pawel Aleksander Fedorynski + * + * [[ http://glenn.sanson.free.fr/fb/ ]] + * [[ http://www.frozen-bubble.org/ ]] + */ + +package org.jfedor.frozenbubble; + +import android.graphics.Canvas; +import android.graphics.Point; +import android.graphics.Rect; +import android.graphics.Region; +import android.os.Bundle; +import java.util.Vector; + +public abstract class Sprite +{ + public static int TYPE_BUBBLE = 1; + public static int TYPE_IMAGE = 2; + public static int TYPE_LAUNCH_BUBBLE = 3; + public static int TYPE_PENGUIN = 4; + + private Rect spriteArea; + private int saved_id; + + public Sprite(Rect spriteArea) + { + this.spriteArea = spriteArea; + saved_id = -1; + } + + public void saveState(Bundle map, Vector saved_sprites) + { + if (saved_id != -1) { + return; + } + saved_id = saved_sprites.size(); + saved_sprites.addElement(this); + map.putInt(String.format("%d-left", saved_id), spriteArea.left); + map.putInt(String.format("%d-right", saved_id), spriteArea.right); + map.putInt(String.format("%d-top", saved_id), spriteArea.top); + map.putInt(String.format("%d-bottom", saved_id), spriteArea.bottom); + map.putInt(String.format("%d-type", saved_id), getTypeId()); + } + + public final int getSavedId() + { + return saved_id; + } + + public final void clearSavedId() + { + saved_id = -1; + } + + public abstract int getTypeId(); + + public void changeSpriteArea(Rect newArea) + { + spriteArea = newArea; + } + + public final void relativeMove(Point p) + { + spriteArea = new Rect(spriteArea); + spriteArea.offset(p.x, p.y); + } + + public final void relativeMove(int x, int y) + { + spriteArea = new Rect(spriteArea); + spriteArea.offset(x, y); + } + + public final void absoluteMove(Point p) + { + spriteArea = new Rect(spriteArea); + spriteArea.offsetTo(p.x, p.y); + } + + public final Point getSpritePosition() + { + return new Point(spriteArea.left, spriteArea.top); + } + + public final Rect getSpriteArea() + { + return spriteArea; + } + + public static void drawImage(BmpWrap image, int x, int y, + Canvas c, double scale, int dx, int dy) + { + c.drawBitmap(image.bmp, (float)(x * scale + dx), (float)(y * scale + dy), + null); + } + + public static void drawImageClipped(BmpWrap image, int x, int y, Rect clipr, + Canvas c, double scale, int dx, int dy) + { + c.save(Canvas.CLIP_SAVE_FLAG); + c.clipRect((float)(clipr.left * scale + dx), + (float)(clipr.top * scale + dy), + (float)(clipr.right * scale + dx), + (float)(clipr.bottom * scale + dy), + Region.Op.REPLACE); + c.drawBitmap(image.bmp, (float)(x * scale + dx), (float)(y * scale + dy), + null); + c.restore(); + } + + public abstract void paint(Canvas c, double scale, int dx, int dy); +}