From: Charles McGarvey Date: Sat, 25 Jul 2009 07:56:15 +0000 (-0600) Subject: big batch of progress X-Git-Url: https://git.dogcows.com/gitweb?a=commitdiff_plain;h=7d15b919681bb9ec0088b4b27c6abf62d6dfb9b1;p=chaz%2Fyoink big batch of progress more complete build system xml scene file converted to json started man page extracted png icon from the icns new ebuild file in the extra stuff a desktop file included many new classes, notably mippleton, interpolator many code changes to existing classes --- diff --git a/COPYING b/COPYING index 4394081..2d0a39c 100644 --- a/COPYING +++ b/COPYING @@ -570,3 +570,685 @@ necessary. Here is a sample; alter the names: That's all there is to it! +------------------------------------------------------------------------------ + +The file m4/boost.m4 is licensed according to the following terms and +conditions: + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. 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 +them 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 prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. 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. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey 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; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If 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 convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU 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 that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + 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. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +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. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + 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 +state 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 3 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, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program 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, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU 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 Lesser General +Public License instead of this License. But first, please read +. + + + diff --git a/Makefile.am b/Makefile.am index d5f6037..ad16dbe 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1 +1,13 @@ -SUBDIRS = yajl src + +ACLOCAL_AMFLAGS = -I m4 + +SUBDIRS = yajl src data doc + +EXTRA_DIST = yajl + +run: all + $(top_srcdir)/src/yoink + +debug: all + gdb $(top_srcdir)/src/yoink + diff --git a/configure.ac b/configure.ac index 15cba2c..2d839c9 100644 --- a/configure.ac +++ b/configure.ac @@ -1,43 +1,192 @@ -AC_PREREQ(2.60) -AC_INIT([yoink],[0.1],[chaz@dogcows.com]) -AM_INIT_AUTOMAKE + +# +# Yoink +# Process this file with autoconf to produce a configure script. +# + +AC_PREREQ([2.60]) + +AC_INIT([Yoink], [0.1], [chaz@dogcows.com], [yoink]) + +AC_CANONICAL_TARGET + AC_CONFIG_SRCDIR([src/YoinkApp.cc]) +AC_CONFIG_MACRO_DIR([m4]) + +AM_INIT_AUTOMAKE + + +# +# Checks for programs. +# -AC_PROG_CC AC_PROG_CXX -AC_PROG_RANLIB +#AC_PROG_AWK +AC_PROG_CC +AC_PROG_CPP AC_PROG_INSTALL -AM_PROG_CC_C_O +#AC_PROG_LN_S +#AC_PROG_MAKE_SET +AC_PROG_LIBTOOL -AC_HEADER_STDC +# +# Checks for configuration arguments. +# -AC_SEARCH_LIBS([glClear], [GL], [have_opengl=yes]) -if test ! "x${have_opengl}" = xyes +AC_ARG_ENABLE([debug], + [ --enable-debug include debugging symbols and features], + [debug=$enableval + if test x$debug = xyes + then + CFLAGS="-Wall -Werror -g -O0 -DDEBUG" + CXXFLAGS="-Wall -Werror -g -O0 -DDEBUG" + else + CFLAGS="-O2 -DNDEBUG" + CXXFLAGS="-O2 -DNDEBUG" + fi], + [CFLAGS="-O2 -DNDEBUG" + CXXFLAGS="-O2 -DNDEBUG"]) + +AC_ARG_ENABLE([profile], + [ --enable-profile make a binary for use with gprof], + [profile=$enableval + if test x$profile = xyes + then + CFLAGS="$CFLAGS -pg" + CXXFLAGS="$CXXFLAGS -pg" + fi]) + + +if test x$prefix = xNONE then - AC_MSG_ERROR([libGL is required]) + prefix="$ac_default_prefix" fi -AC_SEARCH_LIBS([SDL_Init], [SDL], [have_sdl=yes]) -if test ! "x${have_sdl}" = xyes +if test x$datadir = x'${datarootdir}' then - AC_MSG_ERROR([libSDL is required]) + eval datarootdir="$datarootdir" + eval datadir="$datadir/yoink" fi -AC_SEARCH_LIBS([IMG_Load], [SDL_image], [have_sdlimage=yes]) -if test ! "x${have_sdlimage}" = xyes +AC_DEFINE_UNQUOTED([YOINK_DATADIR], ["$datadir"], + [Define to path of game asset directory.]) + +AC_DEFINE_UNQUOTED([YOINK_CONFIGFILES], + ["\$HOME/.yoinkrc:/etc/yoinkrc:$datadir/yoinkrc"], + [Define to colon-delimited config file paths.]) + + +# +# Checks for libraries. +# + +AM_PATH_SDL([1.2.14], + [CFLAGS="$CFLAGS $SDL_CFLAGS" + CXXFLAGS="$CXXFLAGS $SDL_CFLAGS" + LIBS="$LIBS $SDL_LIBS"]) + +#BOOST_REQUIRE([1.35]) +#CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" +BOOST_SMART_PTR +BOOST_STRING_ALGO +BOOST_BIND +BOOST_FUNCTION + +AC_SEARCH_LIBS([IMG_Load], [SDL_image],, + [AC_MSG_ERROR([libSDL_image is required])]) + +AC_SEARCH_LIBS([glBegin], [GL],, + [AC_MSG_ERROR([libGL is required])]) + +AC_SEARCH_LIBS([clock_gettime], [rt], + [AC_DEFINE([HAVE_LIBRT], 1, + [Define to 1 if you have the 'rt' library.])]) + + +# +# Checks for header files. +# + +AC_HEADER_STDBOOL +AC_HEADER_STDC +AC_CHECK_HEADERS([stddef.h stdint.h stdlib.h string.h unistd.h]) + + +# +# Checks for typedefs, structures, and compiler characteristics. +# + +AC_C_STRINGIZE +AC_C_INLINE + +AC_TYPE_UINT8_T +AC_TYPE_UINT16_T +AC_TYPE_UINT32_T +AC_TYPE_SIZE_T +AC_TYPE_SSIZE_T + + +# +# Checks for library functions. +# + +AC_FUNC_ERROR_AT_LINE +AC_FUNC_STRTOD +AC_CHECK_FUNCS([strchr strcspn strrchr strstr]) + + +# +# Find the data files to install. +# + +DATA_FILES=$(echo $(cd data; \ + find . -name "*.png" -o -name "*.json" -o -name yoinkrc)) +AC_SUBST([DATA_FILES]) + + +# +# Create the build files. +# + +AC_CONFIG_FILES([Makefile + data/Makefile + src/Makefile + doc/Makefile + doc/yoink.6 + yajl/Makefile]) + +AC_CONFIG_HEADERS([src/config.h]) + +AC_OUTPUT + + +# +# Print a friendly little message. +# + +echo "=====================================" +echo " Configuration complete!" +echo "" + +echo " Prefix: $prefix" +echo " Data: $datadir" +echo "" + +if test x$debug = xyes then - AC_MSG_ERROR([libSDL_image is required]) + echo " * Debugging enabled." + echo "" fi -AC_SEARCH_LIBS([clock_gettime], [rt], [have_librt=yes]) -if test "x${have_librt}" = xyes +if test x$profile = xyes then - AC_DEFINE([HAVE_LIBRT], 1, [high-resolution timer enabled]) + echo " * Profiling enabled." + echo "" fi -AC_CONFIG_FILES([Makefile - yajl/Makefile - src/Makefile]) -AC_OUTPUT +echo " To finish the installation, execute:" +echo " make" +echo " make install" +echo "=====================================" diff --git a/data/Makefile.am b/data/Makefile.am new file mode 100644 index 0000000..8387830 --- /dev/null +++ b/data/Makefile.am @@ -0,0 +1,9 @@ + +nobase_dist_data_DATA = @DATA_FILES@ + +appsdir=$(prefix)/share/applications +dist_apps_DATA = yoink.desktop + +pixmapdir=$(prefix)/share/pixmaps +dist_pixmap_DATA = yoink.png + diff --git a/share/animation/AlienWarrior.json b/data/animations/AlienWarrior.json similarity index 100% rename from share/animation/AlienWarrior.json rename to data/animations/AlienWarrior.json diff --git a/share/animation/BigExplosion.json b/data/animations/BigExplosion.json similarity index 100% rename from share/animation/BigExplosion.json rename to data/animations/BigExplosion.json diff --git a/share/animation/Bonuses.json b/data/animations/Bonuses.json similarity index 100% rename from share/animation/Bonuses.json rename to data/animations/Bonuses.json diff --git a/share/animation/Bullets.json b/data/animations/Bullets.json similarity index 100% rename from share/animation/Bullets.json rename to data/animations/Bullets.json diff --git a/share/animation/Effects.json b/data/animations/Effects.json similarity index 100% rename from share/animation/Effects.json rename to data/animations/Effects.json diff --git a/share/animation/Heroine.json b/data/animations/Heroine.json similarity index 100% rename from share/animation/Heroine.json rename to data/animations/Heroine.json diff --git a/share/animation/Jetbot.json b/data/animations/Jetbot.json similarity index 100% rename from share/animation/Jetbot.json rename to data/animations/Jetbot.json diff --git a/share/animation/RobotTrooper.json b/data/animations/RobotTrooper.json similarity index 100% rename from share/animation/RobotTrooper.json rename to data/animations/RobotTrooper.json diff --git a/data/scenes/Test.json b/data/scenes/Test.json new file mode 100644 index 0000000..7b0fd63 --- /dev/null +++ b/data/scenes/Test.json @@ -0,0 +1,1118 @@ +{ + "playfield_bounds": [0, 0, -100, 1280, 500, 100], + "maximum_bounds": [-800, 0, -300, 2400, 1000, 600], + "instructions": + [ + + /* Left end tower block */ + + /* Front */ + + "reset_transform", + "translate", [-5, 0, 5], + "scale", [32], + "texture", "TowerBlock1", + "tilemap", + { + "width": 5, + "tiles": + [ + 2, 2, 2, 2, 2, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 1, 0, 0, 1, 0, + 4, 4, 4, 4, 4 + ] + }, + + /* Right side */ + + "reset_transform", + "rotate", ["y", 90], + "translate", [0, 0, 5], + "scale", [32], + "texture", "TowerBlock1", + "tilemap", + { + "width": 5, + "surface_type": "right", + "tiles": + [ + 2, 2, 2, 2, 2, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, + 4, 5, 5, 5, 4 + ] + }, + + /* Top */ + + "reset_transform", + "rotate", ["x", 90], + "translate", [-5, 15, 0], + "scale", [32], + "texture", "TowerBlock1", + "tilemap", + { + "width": 5, + "surface_type": "top", + "tiles": + [ + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3 + ] + }, + + /* Leftmost background tower block */ + + /* Front */ + + "reset_transform", + "scale", [32], + "texture", "TowerBlock1", + "tilemap", + { + "width": 7, + "detail": 1, + "tiles": + [ + 2, 2, 2, 2, 2, 2, 2, + 0, 1, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 6, 1, 0, + 0, 1, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 1, 0, + 4, 4, 5, 5, 5, 4, 4 + ] + }, + + /* Right side */ + + "reset_transform", + "rotate", ["y", 90], + "translate", [7, 0, 0], + "scale", [32], + "texture", "TowerBlock1", + "tilemap", + { + "width": 6, + "detail": 1, + "tiles": + [ + 2, 2, 2, 2, 2, 2, + 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 4, 4, 4, 4, 4, 4 + ] + }, + + /* Top */ + + "reset_transform", + "rotate", ["x", 90], + "translate", [-2, 8, -6], + "scale", [32], + "texture", "TowerBlock1", + "tilemap", + { + "width": 9, + "detail": 1, + "tiles": + [ + 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3 + ] + }, + + /* Foreground building with pitched roof */ + + /* Left wall */ + + "reset_transform", + "rotate", ["y", -90], + "translate", [10, 0, 1], + "scale", [32], + "texture", "Building", + "tilemap", + { + "width": 4, + "surface_type": "left", + "tiles": + [ + -1, 9, 11, -1, + 9, 10, 12, 11, + 15, 7, 7, 16, + 3, 5, 6, 4, + 3, 6, 5, 4 + ] + }, + + /* Right wall */ + + "reset_transform", + "rotate", ["y", -90], + "translate", [13, 0, 1], + "scale", [32], + "texture", "Building", + "tilemap", + { + "width": 4, + "surface_type": "right", + "tiles": + [ + -1, 9, 11, -1, + 9, 10, 12, 11, + 15, 7, 7, 16, + 3, 5, 6, 4, + 3, 8, 5, 4 + ] + }, + + /* Front wall */ + + "reset_transform", + "translate", [10, 0, 5], + "scale", [32], + "texture", "Building", + "tilemap", + { + "width": 3, + "tiles": + [ + 15, 7, 16, + 3, 5, 4, + 3, 6, 4 + ] + }, + + /* Pitched roof */ + + "reset_transform", + "rotate", ["x", 135], + "scale", [1, 1.5, 1.5], + "translate", [10, 5, 3], + "scale", [32], + "texture", "Building", + "tilemap", + { + "width": 3, + "tiles": + [ + 13, 13, 13, + 13, 13, 13 + ] + }, + + /* Finial */ + + "reset_transform", + "translate", [10, 5, 3], + "scale", [32], + "texture", "Building", + "tilemap", + { + "width": 3, + "tiles": + [ + 18, 18, 18 + ] + }, + + /* Cheaty invisible platform */ + + "reset_transform", + "translate", [10, 4, 3], + "scale", [32], + "texture", "Building", + "tilemap", + { + "width": 3, + "surface_type": "top", + "tiles": + [ + -1, -1, -1 + ] + }, + + /* The ground */ + + /* Courtyard */ + + "reset_transform", + "rotate", ["x", 90], + "translate", [-3, 0, 0], + "scale", [32], + "texture", "Scenery", + "tilemap", + { + "width": 13, + "surface_type": "top", + "tiles": + [ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + -1, -1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, + -1, -1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, + -1, -1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, + -1, -1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, + -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + ] + }, + + /* Front grass */ + + "reset_transform", + "scale", [8, 1, 1], + "translate", [1, -0.5, 5], + "scale", [32], + "texture", "Scenery", + "billboard", + { + "tile": 2, + "u_scale": 8, + "detail": 2 + }, + + /* Back grass */ + + "reset_transform", + "scale", [8, 1, 1], + "translate", [1, -0.5, 1], + "scale", [32], + "texture", "Scenery", + "billboard", + { + "tile": 2, + "u_scale": 8, + "detail": 2 + }, + + /* Left grass */ + + "reset_transform", + "scale", [4, 1, 1], + "rotate", ["y", -90], + "translate", [1, -0.5, 1], + "scale", [32], + "texture", "Scenery", + "billboard", + { + "tile": 2, + "u_scale": 4, + "detail": 2 + }, + + /* Right grass */ + + "reset_transform", + "scale", [4, 1, 1], + "rotate", ["y", -90], + "translate", [9, -0.5, 1], + "scale", [32], + "texture", "Scenery", + "billboard", + { + "tile": 2, + "u_scale": 4, + "detail": 2 + }, + + /* Fence behind house */ + + "reset_transform", + "scale", [11, 1, 1], + "translate", [7, 0, 0], + "scale", [32], + "texture", "Scenery", + "billboard", + { + "tile": 4, + "u_scale": 11, + "detail": 2 + }, + + /* Background building with pitched roof */ + + /* Front wall */ + + "reset_transform", + "translate", [19, 0, 0], + "scale", [32], + "texture", "Building", + "tilemap", + { + "width": 4, + "detail": 1, + "tiles": + [ + -1, 9, 11, -1, + 9, 10, 12, 11, + 15, 7, 7, 16, + 3, 6, 5, 4, + 3, 5, 6, 4, + 3, 8, 5, 4 + ] + }, + + /* Left wall */ + + "reset_transform", + "rotate", ["y", -90], + "translate", [19, 0, -3], + "scale", [32], + "texture", "Building", + "tilemap", + { + "width": 3, + "surface_type": "left", + "detail": 1, + "tiles": + [ + 15, 1, 16, + 3, 7, 4, + 3, 5, 4, + 3, 0, 4 + ] + }, + + /* Right wall */ + + "reset_transform", + "rotate", ["y", -90], + "translate", [23, 0, -3], + "scale", [32], + "texture", "Building", + "tilemap", + { + "width": 3, + "surface_type": "right", + "detail": 1, + "tiles": + [ + 15, 0, 16, + 3, 7, 4, + 3, 6, 4, + 3, 2, 4 + ] + }, + + /* Left pitched roof */ + + "reset_transform", + "rotate", ["x", 135], + "scale", [1, 1.5, 1.5], + "rotate", ["y", -90], + "translate", [21, 6, -3], + "scale", [32], + "texture", "Building", + "tilemap", + { + "width": 3, + "detail": 1, + "tiles": + [ + 13, 13, 13, + 13, 13, 13 + ] + }, + + /* Right pitched roof */ + + "reset_transform", + "rotate", ["x", -135], + "scale", [1, 1.5, 1.5], + "rotate", ["y", -90], + "translate", [21, 6, -3], + "scale", [32], + "texture", "Building", + "tilemap", + { + "width": 3, + "detail": 1, + "tiles": + [ + 13, 13, 13, + 13, 13, 13 + ] + }, + + /* Finial */ + + "reset_transform", + "rotate", ["y", -90], + "translate", [21, 6, -3], + "scale", [32], + "texture", "Building", + "tilemap", + { + "width": 3, + "detail": 1, + "tiles": + [ + 18, 18, 18 + ] + }, + + /* More ground to the right */ + + /* Ground under house */ + + "reset_transform", + "rotate", ["x", 90], + "translate", [10, 0, 0], + "scale", [32], + "texture", "Scenery", + "tilemap", + { + "width": 3, + "surface_type": "top", + "tiles": + [ + 1, 1, 1, + 1, 1, 1, + -1, -1, -1, + -1, -1, -1, + -1, -1, -1, + -1, -1, -1, + 1, 1, 1 + ] + }, + + /* Left part of center courtyard */ + + "reset_transform", + "rotate", ["x", 90], + "translate", [13, 0, 0], + "scale", [32], + "texture", "Scenery", + "tilemap", + { + "width": 8, + "surface_type": "top", + "tiles": + [ + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, 0 + ] + }, + + /* Front grass */ + + "reset_transform", + "scale", [12, 1, 1], + "translate", [14, -0.5, 5], + "scale", [32], + "texture", "Scenery", + "billboard", + { + "tile": 2, + "u_scale": 12, + "detail": 2 + }, + + /* Back grass */ + + "reset_transform", + "scale", [4, 1, 1], + "translate", [14, -0.5, 1], + "scale", [32], + "texture", "Scenery", + "billboard", + { + "tile": 2, + "u_scale": 4, + "detail": 2 + }, + + /* Front grass next to door */ + + "reset_transform", + "scale", [1, 1, 1], + "translate", [13, -0.5, 3], + "scale", [32], + "texture", "Scenery", + "billboard", + { + "tile": 2, + "u_scale": 1, + "detail": 2 + }, + + /* Back grass next to door */ + + "reset_transform", + "scale", [1, 1, 1], + "translate", [13, -0.5, 2], + "scale", [32], + "texture", "Scenery", + "billboard", + { + "tile": 2, + "u_scale": 1, + "detail": 2 + }, + + /* Left grass */ + + "reset_transform", + "rotate", ["y", -90], + "translate", [14, -0.5, 1], + "scale", [32], + "texture", "Scenery", + "tilemap", + { + "width": 4, + "detail": 2, + "tiles": + [ + 2, -1, 2, 2 + ] + }, + + /* Grass left of house */ + + "reset_transform", + "rotate", ["y", -90], + "scale", [1, 1, 1], + "translate", [18, -0.5, 0], + "scale", [32], + "texture", "Scenery", + "billboard", + { + "tile": 2, + "u_scale": 1, + "detail": 2 + }, + + /* Grass right of house */ + + "reset_transform", + "rotate", ["y", -90], + "scale", [1, 1, 1], + "translate", [24, -0.5, 0], + "scale", [32], + "texture", "Scenery", + "billboard", + { + "tile": 2, + "u_scale": 1, + "detail": 2 + }, + + /* Front grass in center */ + + "reset_transform", + "scale", [4, 1, 1], + "translate", [19, -0.5, 4], + "scale", [32], + "texture", "Scenery", + "billboard", + { + "tile": 2, + "u_scale": 4, + "detail": 2 + }, + + /* Back grass in center */ + + "reset_transform", + "scale", [4, 1, 1], + "translate", [19, -0.5, 2], + "scale", [32], + "texture", "Scenery", + "billboard", + { + "tile": 2, + "u_scale": 4, + "detail": 2 + }, + + /* Left grass in center */ + + "reset_transform", + "scale", [2, 1, 1], + "rotate", ["y", -90], + "translate", [19, -0.5, 2], + "scale", [32], + "texture", "Scenery", + "billboard", + { + "tile": 2, + "u_scale": 2, + "detail": 2 + }, + + /* Right grass in center */ + + "reset_transform", + "scale", [2, 1, 1], + "rotate", ["y", -90], + "translate", [23, -0.5, 2], + "scale", [32], + "texture", "Scenery", + "billboard", + { + "tile": 2, + "u_scale": 2, + "detail": 2 + }, + + /* Still more ground */ + + /* Right part of center courtyard */ + + "reset_transform", + "rotate", ["x", 90], + "translate", [21, 0, 0], + "scale", [32], + "texture", "Scenery", + "tilemap", + { + "width": 7, + "surface_type": "top", + "tiles": + [ + 1, 1, 1, 1, 1, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1 + ] + }, + + /* Fence to right of back house */ + + "reset_transform", + "scale", [4, 1, 1], + "translate", [24, 0, 0], + "scale", [32], + "texture", "Scenery", + "billboard", + { + "tile": 4, + "u_scale": 4, + "detail": 2 + }, + + /* Grass in front of fence */ + + "reset_transform", + "scale", [4, 1, 1], + "translate", [24, -0.5, 1], + "scale", [32], + "texture", "Scenery", + "billboard", + { + "tile": 2, + "u_scale": 4, + "detail": 2 + }, + + /* Grass to left of tower block */ + + "reset_transform", + "scale", [2, 1, 1], + "rotate", ["y", -90], + "translate", [26, -0.5, 5], + "scale", [32], + "texture", "Scenery", + "billboard", + { + "tile": 2, + "u_scale": 2, + "detail": 2 + }, + + /* Grass to right of tower block */ + + "reset_transform", + "scale", [2, 1, 1], + "rotate", ["y", -90], + "translate", [35, -0.5, 5], + "scale", [32], + "texture", "Scenery", + "billboard", + { + "tile": 2, + "u_scale": 2, + "detail": 2 + }, + + /* Next bit of grass */ + + "reset_transform", + "scale", [5, 1, 1], + "translate", [35, -0.5, 5], + "scale", [32], + "texture", "Scenery", + "billboard", + { + "tile": 2, + "u_scale": 5, + "detail": 2 + }, + + /* Back grass */ + + "reset_transform", + "scale", [6, 1, 1], + "translate", [34, -0.5, 1], + "scale", [32], + "texture", "Scenery", + "billboard", + { + "tile": 2, + "u_scale": 6, + "detail": 2 + }, + + /* Extra bit of back grass */ + + "reset_transform", + "scale", [1, 1, 1], + "rotate", ["y", -90], + "translate", [34, -0.5, 0], + "scale", [32], + "texture", "Scenery", + "billboard", + { + "tile": 2, + "u_scale": 1, + "detail": 2 + }, + + /* Ground around tower block */ + + "reset_transform", + "rotate", ["x", 90], + "translate", [28, 0, 4], + "scale", [32], + "texture", "Scenery", + "tilemap", + { + "width": 5, + "surface_type": "top", + "tiles": + [ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0 + ] + }, + + /* Rightmost ground */ + + "reset_transform", + "rotate", ["x", 90], + "translate", [33, 0, 0], + "scale", [32], + "texture", "Scenery", + "tilemap", + { + "width": 10, + "surface_type": "top", + "tiles": + [ + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, + 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, + 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, + 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, + 0, 1, 1, 1, 1, 1, 1, -1, -1, -1 + ] + }, + + /* Right foreground tower block */ + + /* Front */ + + "reset_transform", + "translate", [28, 0, 4], + "scale", [32], + "texture", "TowerBlock1", + "tilemap", + { + "width": 5, + "tiles": + [ + 2, 2, 2, 2, 2, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 6, 0, + 4, 4, 4, 4, 4 + ] + }, + + /* Right side */ + + "reset_transform", + "rotate", ["y", 90], + "translate", [33, 0, 4], + "scale", [32], + "texture", "TowerBlock1", + "tilemap", + { + "width": 6, + "surface_type": "right", + "tiles": + [ + 2, 2, 2, 2, 2, 2, + 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 5, 4, 5, 5, 4, 5 + ] + }, + + /* Left side */ + + "reset_transform", + "rotate", ["y", 90], + "translate", [28, 0, 4], + "scale", [32], + "texture", "TowerBlock1", + "tilemap", + { + "width": 6, + "surface_type": "left", + "tiles": + [ + 2, 2, 2, 2, 2, 2, + 0, 1, 6, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, + 5, 4, 5, 5, 4, 5 + ] + }, + + /* Top */ + + "reset_transform", + "rotate", ["x", 90], + "translate", [28, 7, -2], + "scale", [32], + "texture", "TowerBlock1", + "tilemap", + { + "width": 5, + "surface_type": "top", + "tiles": + [ + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3 + ] + }, + + /* Right end tower block */ + + /* Front */ + + "reset_transform", + "translate", [40, 0, 5], + "scale", [32], + "texture", "TowerBlock1", + "tilemap", + { + "width": 5, + "tiles": + [ + 2, 2, 2, 2, 2, + 0, 1, 0, 0, 1, + 0, 1, 0, 0, 1, + 0, 1, 0, 0, 1, + 0, 1, 0, 0, 1, + 6, 1, 0, 0, 1, + 0, 1, 0, 0, 1, + 0, 1, 0, 0, 1, + 0, 1, 0, 0, 1, + 0, 1, 0, 0, 1, + 0, 1, 0, 0, 1, + 6, 1, 0, 0, 1, + 0, 1, 0, 0, 1, + 0, 1, 0, 0, 1, + 4, 4, 4, 4, 4 + ] + }, + + /* Left side */ + + "reset_transform", + "rotate", ["y", 90], + "translate", [40, 0, 5], + "scale", [32], + "texture", "TowerBlock1", + "tilemap", + { + "width": 5, + "surface_type": "left", + "tiles": + [ + 2, 2, 2, 2, 2, + 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 4, 5, 5, 5, 4 + ] + }, + + /* Top */ + + "reset_transform", + "rotate", ["x", 90], + "translate", [40, 15, 0], + "scale", [32], + "texture", "TowerBlock1", + "tilemap", + { + "width": 5, + "surface_type": "top", + "tiles": + [ + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3 + ] + }, + + /* Background */ + + "reset_transform", + "translate", [-0.3, -0.17, -900], + "scale", [3200, 1600, 1], + "texture", "BackgroundFar", + "billboard", + { + "fog": false + }, + "translate", [0, 0, 300], + "texture", "BackgroundNear", + "billboard", + { + "blend": true, + "fog": false + }, + + /* Trees */ + + "texture", "Trees", + + /* Left courtyard */ + + "reset_transform", + "scale", [96], + "translate", [250, -2.5, 16], + "billboard", + { + "tile": 1, + "detail": 1 + }, + + /* Center courtyard */ + + "reset_transform", + "scale", [96], + "translate", [610, -2.5, 85], + "billboard", + { + "tile": 0 + }, + "reset_transform", + "scale", [96], + "translate", [650, -2.5, 115], + "billboard", + { + "tile": 1 + }, + + /* Right courtyard */ + + "reset_transform", + "scale", [96], + "translate", [1080, -2.5, 10], + "billboard", + { + "tile": 1, + "detail": 1 + }, + "reset_transform", + "scale", [96], + "translate", [1120, -2.5, -15], + "billboard", + { + "tile": 0, + "detail": 1 + }, + "reset_transform", + "scale", [96], + "translate", [1220, -2.5, -30], + "billboard", + { + "tile": 1, + "detail": 1 + } + + ] +} diff --git a/share/scene/Test.xml b/data/scenes/Test.xml similarity index 100% rename from share/scene/Test.xml rename to data/scenes/Test.xml diff --git a/share/texture/AlienWarrior.png b/data/textures/AlienWarrior.png similarity index 100% rename from share/texture/AlienWarrior.png rename to data/textures/AlienWarrior.png diff --git a/share/texture/BackgroundFar.png b/data/textures/BackgroundFar.png similarity index 100% rename from share/texture/BackgroundFar.png rename to data/textures/BackgroundFar.png diff --git a/share/texture/BackgroundNear.png b/data/textures/BackgroundNear.png similarity index 100% rename from share/texture/BackgroundNear.png rename to data/textures/BackgroundNear.png diff --git a/share/texture/BigExplosion.png b/data/textures/BigExplosion.png similarity index 100% rename from share/texture/BigExplosion.png rename to data/textures/BigExplosion.png diff --git a/share/texture/Bonuses.png b/data/textures/Bonuses.png similarity index 100% rename from share/texture/Bonuses.png rename to data/textures/Bonuses.png diff --git a/share/texture/Building.png b/data/textures/Building.png similarity index 100% rename from share/texture/Building.png rename to data/textures/Building.png diff --git a/share/texture/Font.png b/data/textures/Font.png similarity index 100% rename from share/texture/Font.png rename to data/textures/Font.png diff --git a/share/texture/Heroine.png b/data/textures/Heroine.png similarity index 100% rename from share/texture/Heroine.png rename to data/textures/Heroine.png diff --git a/share/texture/Jetbot.png b/data/textures/Jetbot.png similarity index 100% rename from share/texture/Jetbot.png rename to data/textures/Jetbot.png diff --git a/share/texture/Particles.png b/data/textures/Particles.png similarity index 100% rename from share/texture/Particles.png rename to data/textures/Particles.png diff --git a/share/texture/RobotTrooper.png b/data/textures/RobotTrooper.png similarity index 100% rename from share/texture/RobotTrooper.png rename to data/textures/RobotTrooper.png diff --git a/share/texture/Scenery.png b/data/textures/Scenery.png similarity index 100% rename from share/texture/Scenery.png rename to data/textures/Scenery.png diff --git a/share/texture/StatusBars.png b/data/textures/StatusBars.png similarity index 100% rename from share/texture/StatusBars.png rename to data/textures/StatusBars.png diff --git a/share/texture/TowerBlock1.png b/data/textures/TowerBlock1.png similarity index 100% rename from share/texture/TowerBlock1.png rename to data/textures/TowerBlock1.png diff --git a/share/texture/Trees.png b/data/textures/Trees.png similarity index 100% rename from share/texture/Trees.png rename to data/textures/Trees.png diff --git a/share/texture/AlienWarrior.data b/data/tilemaps/AlienWarrior.json similarity index 80% rename from share/texture/AlienWarrior.data rename to data/tilemaps/AlienWarrior.json index 564934b..471fed4 100644 --- a/share/texture/AlienWarrior.data +++ b/data/tilemaps/AlienWarrior.json @@ -1,7 +1,6 @@ { "TilesU": 8, "TilesV": 4, - "InvertAlpha": 0, "MinFilter": Nearest, "MagFilter": Nearest } diff --git a/share/texture/BackgroundNear.data b/data/tilemaps/BackgroundFar.json similarity index 59% rename from share/texture/BackgroundNear.data rename to data/tilemaps/BackgroundFar.json index 3272855..8780bea 100644 --- a/share/texture/BackgroundNear.data +++ b/data/tilemaps/BackgroundFar.json @@ -1,9 +1,8 @@ { "TilesU": 1, "TilesV": 1, - "InvertAlpha": 0, "MinFilter": "Linear", "MagFilter": "Linear", - "WrapU": "Wrap", - "WrapV": "Wrap" + "WrapU": "Clamp", + "WrapV": "Clamp" } diff --git a/share/texture/BackgroundFar.data b/data/tilemaps/BackgroundNear.json similarity index 54% rename from share/texture/BackgroundFar.data rename to data/tilemaps/BackgroundNear.json index 11ab592..2ae0637 100644 --- a/share/texture/BackgroundFar.data +++ b/data/tilemaps/BackgroundNear.json @@ -1,9 +1,8 @@ { "TilesU": 1, "TilesV": 1, - "InvertAlpha": 0, "MinFilter": "Linear", "MagFilter": "Linear", - "WrapU": "ClampToEdge", - "WrapV": "ClampToEdge" + "WrapU": "Repeat", + "WrapV": "Repeat" } diff --git a/share/texture/BigExplosion.data b/data/tilemaps/BigExplosion.json similarity index 54% rename from share/texture/BigExplosion.data rename to data/tilemaps/BigExplosion.json index 104ebf0..b57a190 100644 --- a/share/texture/BigExplosion.data +++ b/data/tilemaps/BigExplosion.json @@ -1,9 +1,8 @@ { "TilesU": 8, "TilesV": 1, - "InvertAlpha": 0, "MinFilter": "Linear", "MagFilter": "Linear", - "WrapU": "ClampToEdge", - "WrapV": "ClampToEdge" + "WrapU": "Clamp", + "WrapV": "Clamp" } diff --git a/share/texture/Bonuses.data b/data/tilemaps/Bonuses.json similarity index 54% rename from share/texture/Bonuses.data rename to data/tilemaps/Bonuses.json index a8e3d9d..5c024d5 100644 --- a/share/texture/Bonuses.data +++ b/data/tilemaps/Bonuses.json @@ -1,9 +1,8 @@ { "TilesU": 8, "TilesV": 4, - "InvertAlpha": 0, "MinFilter": "Linear", "MagFilter": "Linear", - "WrapU": "ClampToEdge", - "WrapV": "ClampToEdge" + "WrapU": "Clamp", + "WrapV": "Clamp" } diff --git a/share/texture/Building.data b/data/tilemaps/Building.json similarity index 54% rename from share/texture/Building.data rename to data/tilemaps/Building.json index f041b09..ebc6842 100644 --- a/share/texture/Building.data +++ b/data/tilemaps/Building.json @@ -1,9 +1,8 @@ { "TilesU": 8, "TilesV": 4, - "InvertAlpha": 0, "MinFilter": "Nearest", "MagFilter": "Nearest", - "WrapU": "ClampToEdge", - "WrapV": "ClampToEdge" + "WrapU": "Clamp", + "WrapV": "Clamp" } diff --git a/share/texture/Font.data b/data/tilemaps/Font.json similarity index 81% rename from share/texture/Font.data rename to data/tilemaps/Font.json index 2056f7d..8b1214b 100644 --- a/share/texture/Font.data +++ b/data/tilemaps/Font.json @@ -1,7 +1,6 @@ { "TilesU": 8, "TilesV": 8, - "InvertAlpha": 0, "MinFilter": "Nearest", "MagFilter": "Nearest" } diff --git a/share/texture/RobotTrooper.data b/data/tilemaps/Heroine.json similarity index 81% rename from share/texture/RobotTrooper.data rename to data/tilemaps/Heroine.json index fba6165..3420a10 100644 --- a/share/texture/RobotTrooper.data +++ b/data/tilemaps/Heroine.json @@ -1,7 +1,6 @@ { "TilesU": 8, "TilesV": 4, - "InvertAlpha": 0, "MinFilter": "Nearest", "MagFilter": "Nearest" } diff --git a/share/texture/Jetbot.data b/data/tilemaps/Jetbot.json similarity index 81% rename from share/texture/Jetbot.data rename to data/tilemaps/Jetbot.json index f6d762a..52af3b0 100644 --- a/share/texture/Jetbot.data +++ b/data/tilemaps/Jetbot.json @@ -1,7 +1,6 @@ { "TilesU": 4, "TilesV": 2, - "InvertAlpha": 0, "MinFilter": "Nearest", "MagFilter": "Nearest" } diff --git a/share/texture/Particles.data b/data/tilemaps/Particles.json similarity index 54% rename from share/texture/Particles.data rename to data/tilemaps/Particles.json index a8e3d9d..5c024d5 100644 --- a/share/texture/Particles.data +++ b/data/tilemaps/Particles.json @@ -1,9 +1,8 @@ { "TilesU": 8, "TilesV": 4, - "InvertAlpha": 0, "MinFilter": "Linear", "MagFilter": "Linear", - "WrapU": "ClampToEdge", - "WrapV": "ClampToEdge" + "WrapU": "Clamp", + "WrapV": "Clamp" } diff --git a/share/texture/Heroine.data b/data/tilemaps/RobotTrooper.json similarity index 81% rename from share/texture/Heroine.data rename to data/tilemaps/RobotTrooper.json index fba6165..3420a10 100644 --- a/share/texture/Heroine.data +++ b/data/tilemaps/RobotTrooper.json @@ -1,7 +1,6 @@ { "TilesU": 8, "TilesV": 4, - "InvertAlpha": 0, "MinFilter": "Nearest", "MagFilter": "Nearest" } diff --git a/share/texture/Scenery.data b/data/tilemaps/Scenery.json similarity index 59% rename from share/texture/Scenery.data rename to data/tilemaps/Scenery.json index aee8ed3..83339cf 100644 --- a/share/texture/Scenery.data +++ b/data/tilemaps/Scenery.json @@ -1,9 +1,8 @@ { "TilesU": 4, "TilesV": 4, - "InvertAlpha": 0, "MinFilter": "Linear", "MagFilter": "Linear", - "WrapU": "Wrap", - "WrapV": "Wrap" + "WrapU": "Repeat", + "WrapV": "Repeat" } diff --git a/share/texture/StatusBars.data b/data/tilemaps/StatusBars.json similarity index 81% rename from share/texture/StatusBars.data rename to data/tilemaps/StatusBars.json index 9b94ec7..01b5ed0 100644 --- a/share/texture/StatusBars.data +++ b/data/tilemaps/StatusBars.json @@ -1,7 +1,6 @@ { "TilesU": 4, "TilesV": 1, - "InvertAlpha": 0, "MinFilter": "Nearest", "MagFilter": "Nearest" } diff --git a/share/texture/TowerBlock1.data b/data/tilemaps/TowerBlock1.json similarity index 54% rename from share/texture/TowerBlock1.data rename to data/tilemaps/TowerBlock1.json index 1d5cade..98e7587 100644 --- a/share/texture/TowerBlock1.data +++ b/data/tilemaps/TowerBlock1.json @@ -1,9 +1,8 @@ { "TilesU": 4, "TilesV": 4, - "InvertAlpha": 0, "MinFilter": "Linear", "MagFilter": "Linear", - "WrapU": "ClampToEdge", - "WrapV": "ClampToEdge" + "WrapU": "Clamp", + "WrapV": "Clamp" } diff --git a/share/texture/Trees.data b/data/tilemaps/Trees.json similarity index 54% rename from share/texture/Trees.data rename to data/tilemaps/Trees.json index 665f66a..247ec97 100644 --- a/share/texture/Trees.data +++ b/data/tilemaps/Trees.json @@ -1,9 +1,8 @@ { "TilesU": 2, "TilesV": 1, - "InvertAlpha": 0, "MinFilter": "Linear", "MagFilter": "Linear", - "WrapU": "ClampToEdge", - "WrapV": "ClampToEdge" + "WrapU": "Clamp", + "WrapV": "Clamp" } diff --git a/data/yoink.desktop b/data/yoink.desktop new file mode 100644 index 0000000..2f301e2 --- /dev/null +++ b/data/yoink.desktop @@ -0,0 +1,10 @@ +[Desktop Entry] +Encoding=UTF-8 +Version=1.0 +Name=Yoink +Type=Application +Comment=Alien-stomping Entertainment +Exec=yoink +TryExec=yoink +Icon=yoink +Categories=Game;ActionGame; diff --git a/data/yoink.png b/data/yoink.png new file mode 100644 index 0000000..d40be6b Binary files /dev/null and b/data/yoink.png differ diff --git a/src/yoinkrc b/data/yoinkrc similarity index 65% rename from src/yoinkrc rename to data/yoinkrc index f58c13d..67be5c1 100644 --- a/src/yoinkrc +++ b/data/yoinkrc @@ -4,11 +4,13 @@ "video.resizable": true, "video.mode": [800, 600], "video.colorbuffers": [8, 8, 8, 8], - //"video.multisamplebuffers": 6, - //"video.multisamplesamples": 6, + "video.multisamplebuffers": 6, + "video.multisamplesamples": 6, "video.cursor": true, "video.grab": false, "video.doublebuffer": true, "video.swapcontrol": true, - "engine.maxfps": 40 + "engine.maxfps": 45, + "engine.printfps": true, + "engine.timestep": 0.01 } diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 0000000..c74ebdb --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,3 @@ + +man6_MANS = yoink.6 + diff --git a/doc/screenshot.jpg b/doc/screenshot.jpg new file mode 100644 index 0000000..66e8e26 Binary files /dev/null and b/doc/screenshot.jpg differ diff --git a/doc/yoink.6.in b/doc/yoink.6.in new file mode 100644 index 0000000..a7ad776 --- /dev/null +++ b/doc/yoink.6.in @@ -0,0 +1,236 @@ +.\" +.\" Copyright (c) 2009, Charles McGarvey +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are met: +.\" +.\" * Redistributions of source code must retain the above copyright notice, +.\" this list of conditions and the following disclaimer. +.\" * Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +.\" IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +.\" CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +.\" EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +.\" PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +.\" PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +.\" LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +.\" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +.\" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.hy +.TH YOINK 6 "July 24, 2009" +.SH NAME +Yoink \- An alien-smashing action game. +.SH SYNOPSIS +.B yoink [-h|--help] [-v|--version] [OPTION=VALUE]... +.br +.SH DESCRIPTION +.PP +Leap tall buildings! Crush stupid robots beneath your feet! Wield your +extra-terrestrial powers in the defence of humanity, and send those alien +invaders back from whence they came! Do all these things (apart from the last +one at the moment) in Yoink! You play the part of a flying alien heroine who +must defend her home on Earth from other airborne alien invaders. The game +draws inspiration from classic arcade games like Joust, Bombjack, Rampage, and +Defender--simple, fast-moving action. +.PP +.TP +.B -h, --help +display this help and exit +.TP +.B -v, --version +output version information and exit +.PP +To attack, you must dive on the enemy at high speed. If you're going too +slowly, you'll just drift harmlessly by. Diving from above gives different +results from swooping in and hitting them from the side. If you're too close to +attack, try to build up speed by running away and bouncing off a nearby +building! +.PP +By charging your special alien powers, you can throw fireballs. The orange bar +at the top of the screen represents your power level--at maximum, you can +destroy almost anything. Aiming can be tricky, but with a little practice it's +quite easy to launch them in the right direction. Try doing a little swoop or +circle in the air to line yourself up before releasing your fireball. +.PP +The heroine has limited energy, measured by the blue bar at the top of the +screen. When it runs out, it's game over! She can regain lost energy by +picking up bonuses dropped by enemies. +.PP +To complete the current attack wave, you must destroy all the enemies. Hunt +around, especially in the sky, if you can't find the last few. +.br +.SH OPTIONS +.PP +There are a plethora of options available for tweaking various aspects of the +game. All options can be set either from a configuration file or by passing +them as arguments. Some of the more common options can be set from within the +game. +.PP +A +.B yoink +configuration file ("yoinkrc") consists of key-value pairs organized in a +logical hierarchy. The format of the file is human-readable, so you can get in +there with your favorite text editor if you like to work under the hood. +.B yoink +looks for configuration files and loads them in this order, with the options in +prior configuration files taking precedence over the same options if they exist +in multiple configuration files: +.TP +1. $YOINK_CONFIGFILE +This is an optional environment variable. +.TP +2. $HOME/.yoinkrc +This is a specific user's configuration file. +.TP +3. /etc/yoinkrc +This is a system-wide configuration file. +.TP +4. @datadir@/yoinkrc +This is the base configuration file which should be considered read-only. Look +to this file as an example of the format used for configuration files. +.PP +Options that are passed as arguments take precedence over options loaded from +the configuration file(s). This mechanism is good for running the game with a +temporary setting which you do not intend to retain. Keep in mind that if you +edit and save options in-game, any options you have passed as arguments during +the invocation of the game will be saved to the $HOME/.yoinkrc configuration +file. You may have to go into that file and remove any options you didn't +intend to set. When passing options as arguments, you must use the fully +qualified name of the option if it exists in a subgroup. For example: +.PP +.TP +yoink video.fullscreen=true +Set the option video.fullscreen to true. This will run the game in full-screen +mode. +.TP +yoink video.maxfps=60 +Set the option video.maxfps to 60. This will cap the display rate at 60Hz. +.PP +You can also set options with array values. Arrays can be passed on the +command line by surrounding all the parts with square brackets and separating +each part by a comma. For example: +.TP +yoink video.mode=[1024,768] +Set the option video.mode to an array with numbers 1024 and 768. The video size +will be 1024x768. +.PP +Here is a list of some of the options available: +.TP +.B engine.timestep +The amount of time in seconds between each update of the physics state. A value +of 0.01 or lower is ideal for accurate physics approximations. Values that are +much lower may introduce errors in the game. +.TP +.B input.grab +Takes a boolean (true or false). If true, the cursor pointer will be "stuck" +within the area of the window, and many key combinations which would otherwise +be handled by the window manager will instead be dropped. This is a low-level +option of limited usefulness. +.TP +.B video.colorbuffers +This takes an array of four number values which represent the number of bits to +use for red, green, blue, and the alpha channel. This is a low-level option of +limited usefulness. The default value is almost always preferable. +.TP +.B video.cursor +This option effects the visibility of the cursor while it is "hovering" over the +window. If the value is true, the cursor will be visible. Otherwise, the +cursor will be hidden. +.TP +.B video.doublebuffer +If true, double-buffering will be used to render animations with minimal +distortions. Otherwise, a single buffer will be used. The recommended value is +true. +.TP +.B video.fullscreen +If true, the window will capture the display and render the game in full screen +splendor. A value of false means the game will run in a window. +.TP +.B video.maxfps +The maximum number of frames to be drawn per second. A value of 50 is pretty +good. If your computer is pretty old, can get away with decreasing this value +and still have reasonably smooth animation. You can set this to a very high +number to effectively render as many frames as is possible, but the actual rate +could be limited by vertical display synchronization, depending on the X11 +driver and settings used. You should not set this option higher than the point +where the vertical synchronization effectively limits the draw rate or else the +game may not be able to update the physics on schedule which could actually +significantly lower the quality of the animation. +.TP +.B video.mode +The resolution or size of the window. The value is an array with three number +elements representing the width, height, and bits per pixel that make up the +video mode.. A typical value is [800,600,32] for a size of 800x600 pixels with +millions of colors. +.TP +.B video.multisamplebuffers +The number of multisample buffers used. +.TP +.B video.multisamplesamples +The number of multisample samples used. +.TP +.B video.printfps +If true, the current number of frames being draw per second will be printed to +the console. This is usually off by default, but you can set this to true if +you're interested in the draw rate you're actually getting. +.TP +.B video.resizable +If true, the window will be resizable by the window manager. This option is +meaningless if the game is drawing to the full screen. +.TP +.B video.swapcontrol +If true, drawing will take place at a time which will minimize distortion caused +by the vertical refreshing of displays. The recommended value is true. +.br +.SH ENVIRONMENT +.PP +.B yoink +responds to some variables in the environment: +.TP +HOME +If set to a path of a valid directory (presumably a user's home directory), +.B yoink +will load options from the configuration file at $HOME/.yoinkrc, if it exists. +Saving options within the game will cause this file to be over-written with the +new options. +.TP +USER +.B yoink +uses this variable to guess the user's nickname, for a high score entry or +whatever. +.TP +YOINK_CONFIGFILE +If set to a path of a valid configuration file, +.B yoink +will load the options from that file, and those options will take precedence +over options loaded from other configuration files. Any in-game saving will +cause this file to be over-written by the new options rather than the file at +$HOME/.yoinkrc. +.TP +YOINK_DATADIR +If set to a path of a valid directory, +.B yoink +will look in this directory first when it is loading game assets. Set this +variable if you move the game's assets to another directory or want to load your +own assets. +.br +.SH BUGS +.PP +The pixelated graphics are actually intentional. It adds to the charm of the +game, don't you think? +.PP +Send bug reports and patches to: +.br +Charles McGarvey +.SH AUTHOR +.PP +Neil Carter was the original creator of Yoink, his winning entry in the +uDevGames 2003 Mac game development contest. Charles McGarvey rewrote the game +with SDL and is the current maintainer. diff --git a/extra/yoink.ebuild b/extra/yoink.ebuild new file mode 100644 index 0000000..69fa2f0 --- /dev/null +++ b/extra/yoink.ebuild @@ -0,0 +1,53 @@ +# Copyright 1999-2009 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: $ + +EAPI=2 +inherit autotools eutils games + +DESCRIPTION="Alien-smashing action game" +HOMEPAGE="http://www.dogcows.com/" +SRC_URI="http://www.dogcows.com/yoink/${P}.tar.bz2" + +LICENSE="BSD-2" +SLOT="0" +KEYWORDS="~amd64 ~ppc ~x86" +IUSE="debug" + +RDEPEND="media-libs/libsdl[joystick,video] + media-libs/sdl-image[png]" +DEPEND="${RDEPEND} + dev-util/pkgconfig" + +src_prepare() { + sed -i \ + -e "s/-Werror//g" \ + configure.ac \ + || die "sed failed" + sed -i \ + -e "/apps/d" \ + -e "/pixmap/d" \ + data/Makefile.am \ + || die "sed failed" + sed -i \ + -e "/man/d" \ + doc/Makefile.am \ + || die "sed failed" + eautoreconf +} + +src_configure() { + egamesconf \ + --disable-dependency-tracking \ + --datadir="${GAMES_DATADIR}/${PN}" \ + $(use_enable debug) +} + +src_install() { + emake DESTDIR="${D}" install || die "emake install failed" + dodoc AUTHORS ChangeLog README TODO + doman doc/yoink.6 + doicon data/yoink.png + make_desktop_entry ${PN} Yoink + prepgamesdirs +} diff --git a/m4/boost.m4 b/m4/boost.m4 new file mode 100644 index 0000000..c4ba5ec --- /dev/null +++ b/m4/boost.m4 @@ -0,0 +1,920 @@ +# boost.m4: Locate Boost headers and libraries for autoconf-based projects. +# Copyright (C) 2007, 2008, 2009 Benoit Sigoure +# +# 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 3 of the License, or +# (at your option) any later version. +# +# Additional permission under section 7 of the GNU General Public +# License, version 3 ("GPLv3"): +# +# If you convey this file as part of a work that contains a +# configuration script generated by Autoconf, you may do so under +# terms of your choice. +# +# 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, see . + +# serial 10 +# Original sources can be found at http://repo.or.cz/w/boost.m4.git +# You can fetch the latest version of the script by doing: +# wget 'http://repo.or.cz/w/boost.m4.git?a=blob_plain;f=build-aux/boost.m4;hb=HEAD' -O boost.m4 + +# ------ # +# README # +# ------ # + +# This file provides several macros to use the various Boost libraries. +# The first macro is BOOST_REQUIRE. It will simply check if it's possible to +# find the Boost headers of a given (optional) minimum version and it will +# define BOOST_CPPFLAGS accordingly. It will add an option --with-boost to +# your configure so that users can specify non standard locations. +# If the user's environment contains BOOST_ROOT and --with-boost was not +# specified, --with-boost=$BOOST_ROOT is implicitly used. +# For more README and documentation, go to http://repo.or.cz/w/boost.m4.git +# Note: THESE MACROS ASSUME THAT YOU USE LIBTOOL. If you don't, don't worry, +# simply read the README, it will show you what to do step by step. + +m4_pattern_forbid([^_?BOOST_]) + + +# _BOOST_SED_CPP(SED-PROGRAM, PROGRAM, +# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# -------------------------------------------------------- +# Same as AC_EGREP_CPP, but leave the result in conftest.i. +# PATTERN is *not* overquoted, as in AC_EGREP_CPP. It could be useful +# to turn this into a macro which extracts the value of any macro. +m4_define([_BOOST_SED_CPP], +[AC_LANG_PREPROC_REQUIRE()dnl +AC_REQUIRE([AC_PROG_SED])dnl +AC_LANG_CONFTEST([AC_LANG_SOURCE([[$2]])]) +AS_IF([dnl eval is necessary to expand ac_cpp. +dnl Ultrix and Pyramid sh refuse to redirect output of eval, so use subshell. +(eval "$ac_cpp conftest.$ac_ext") 2>&AS_MESSAGE_LOG_FD | + $SED -n -e "$1" >conftest.i 2>&1], + [$3], + [$4])dnl +rm -f conftest* +])# AC_EGREP_CPP + + + +# BOOST_REQUIRE([VERSION]) +# ------------------------ +# Look for Boost. If version is given, it must either be a literal of the form +# "X.Y.Z" where X, Y and Z are integers (the ".Z" part being optional) or a +# variable "$var". +# Defines the value BOOST_CPPFLAGS. This macro only checks for headers with +# the required version, it does not check for any of the Boost libraries. +# FIXME: Add a 2nd optional argument so that it's not fatal if Boost isn't found +# and add an AC_DEFINE to tell whether HAVE_BOOST. +AC_DEFUN([BOOST_REQUIRE], +[boost_save_IFS=$IFS +boost_version_req="$1" +IFS=. +set x $boost_version_req 0 0 0 +IFS=$boost_save_IFS +shift +boost_version_req=`expr "$[1]" '*' 100000 + "$[2]" '*' 100 + "$[3]"` +AC_ARG_WITH([boost], + [AS_HELP_STRING([--with-boost=DIR], + [prefix of Boost $1 @<:@guess@:>@])])dnl +AC_ARG_VAR([BOOST_ROOT],[Location of Boost installation])dnl +# If BOOST_ROOT is set and the user has not provided a value to +# --with-boost, then treat BOOST_ROOT as if it the user supplied it. +if test x"$BOOST_ROOT" != x; then + if test x"$with_boost" = x; then + AC_MSG_NOTICE([Detected BOOST_ROOT; continuing with --with-boost=$BOOST_ROOT]) + with_boost=$BOOST_ROOT + else + AC_MSG_NOTICE([Detected BOOST_ROOT=$BOOST_ROOT, but overridden by --with-boost=$with_boost]) + fi +fi +AC_SUBST([DISTCHECK_CONFIGURE_FLAGS], + ["$DISTCHECK_CONFIGURE_FLAGS '--with-boost=$with_boost'"]) +boost_save_CPPFLAGS=$CPPFLAGS + AC_CACHE_CHECK([for Boost headers version >= $boost_version_req], + [boost_cv_inc_path], + [boost_cv_inc_path=no +AC_LANG_PUSH([C++])dnl +m4_pattern_allow([^BOOST_VERSION$])dnl + AC_LANG_CONFTEST([AC_LANG_PROGRAM([[#include +#if !defined BOOST_VERSION +# error BOOST_VERSION is not defined +#elif BOOST_VERSION < $boost_version_req +# error Boost headers version < $boost_version_req +#endif +]])]) + # If the user provided a value to --with-boost, use it and only it. + case $with_boost in #( + ''|yes) set x '' /opt/local/include /usr/local/include /opt/include \ + /usr/include C:/Boost/include;; #( + *) set x "$with_boost/include" "$with_boost";; + esac + shift + for boost_dir + do + # Without --layout=system, Boost (or at least some versions) installs + # itself in /include/boost-. This inner loop helps to + # find headers in such directories. + # I didn't indent this loop on purpose (to avoid over-indented code) + for boost_inc in "$boost_dir" "$boost_dir"/boost-* + do + test x"$boost_inc" != x && CPPFLAGS="$CPPFLAGS -I$boost_inc" + AC_COMPILE_IFELSE([], [boost_cv_inc_path=yes], [boost_cv_version=no]) + if test x"$boost_cv_inc_path" = xyes; then + if test x"$boost_inc" != x; then + boost_cv_inc_path=$boost_inc + fi + break 2 + fi + done + done +AC_LANG_POP([C++])dnl + ]) + case $boost_cv_inc_path in #( + no) AC_MSG_ERROR([cannot find Boost headers version >= $boost_version_req]);;#( + yes) BOOST_CPPFLAGS=;;#( + *) AC_SUBST([BOOST_CPPFLAGS], ["-I$boost_cv_inc_path"]);; + esac + AC_CACHE_CHECK([for Boost's header version], + [boost_cv_lib_version], + [m4_pattern_allow([^BOOST_LIB_VERSION$])dnl + _BOOST_SED_CPP([/^boost-lib-version = /{s///;s/\"//g;p;g;}], + [#include +boost-lib-version = BOOST_LIB_VERSION], + [boost_cv_lib_version=`cat conftest.i`])]) + # e.g. "134" for 1_34_1 or "135" for 1_35 + boost_major_version=`echo "$boost_cv_lib_version" | sed 's/_//;s/_.*//'` + case $boost_major_version in #( + '' | *[[!0-9]]*) + AC_MSG_ERROR([Invalid value: boost_major_version=$boost_major_version]) + ;; + esac +CPPFLAGS=$boost_save_CPPFLAGS +])# BOOST_REQUIRE + +# BOOST_STATIC() +# -------------- +# Add the "--enable-static-boost" configure argument. If this argument is given +# on the command line, static versions of the libraries will be looked up. +AC_DEFUN([BOOST_STATIC], + [AC_ARG_ENABLE([static-boost], + [AC_HELP_STRING([--enable-static-boost], + [Prefer the static boost libraries over the shared ones [no]])], + [enable_static_boost=yes], + [enable_static_boost=no])])# BOOST_STATIC + +# BOOST_FIND_HEADER([HEADER-NAME], [ACTION-IF-NOT-FOUND], [ACTION-IF-FOUND]) +# -------------------------------------------------------------------------- +# Wrapper around AC_CHECK_HEADER for Boost headers. Useful to check for +# some parts of the Boost library which are only made of headers and don't +# require linking (such as Boost.Foreach). +# +# Default ACTION-IF-NOT-FOUND: Fail with a fatal error. +# +# Default ACTION-IF-FOUND: define the preprocessor symbol HAVE_ in +# case of success # (where HEADER-NAME is written LIKE_THIS, e.g., +# HAVE_BOOST_FOREACH_HPP). +AC_DEFUN([BOOST_FIND_HEADER], +[AC_REQUIRE([BOOST_REQUIRE])dnl +AC_LANG_PUSH([C++])dnl +boost_save_CPPFLAGS=$CPPFLAGS +CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" +AC_CHECK_HEADER([$1], + [m4_default([$3], [AC_DEFINE(AS_TR_CPP([HAVE_$1]), [1], + [Define to 1 if you have <$1>])])], + [m4_default([$2], [AC_MSG_ERROR([cannot find $1])])]) +CPPFLAGS=$boost_save_CPPFLAGS +AC_LANG_POP([C++])dnl +])# BOOST_FIND_HEADER + + +# BOOST_FIND_LIB([LIB-NAME], [PREFERRED-RT-OPT], [HEADER-NAME], [CXX-TEST], +# [CXX-PROLOGUE]) +# ------------------------------------------------------------------------- +# Look for the Boost library LIB-NAME (e.g., LIB-NAME = `thread', for +# libboost_thread). Check that HEADER-NAME works and check that +# libboost_LIB-NAME can link with the code CXX-TEST. The optional argument +# CXX-PROLOGUE can be used to include some C++ code before the `main' +# function. +# +# Invokes BOOST_FIND_HEADER([HEADER-NAME]) (see above). +# +# Boost libraries typically come compiled with several flavors (with different +# runtime options) so PREFERRED-RT-OPT is the preferred suffix. A suffix is one +# or more of the following letters: sgdpn (in that order). s = static +# runtime, d = debug build, g = debug/diagnostic runtime, p = STLPort build, +# n = (unsure) STLPort build without iostreams from STLPort (it looks like `n' +# must always be used along with `p'). Additionally, PREFERRED-RT-OPT can +# start with `mt-' to indicate that there is a preference for multi-thread +# builds. Some sample values for PREFERRED-RT-OPT: (nothing), mt, d, mt-d, gdp +# ... If you want to make sure you have a specific version of Boost +# (eg, >= 1.33) you *must* invoke BOOST_REQUIRE before this macro. +AC_DEFUN([BOOST_FIND_LIB], +[AC_REQUIRE([_BOOST_FIND_COMPILER_TAG])dnl +AC_REQUIRE([BOOST_REQUIRE])dnl +AC_REQUIRE([BOOST_STATIC])dnl +AC_REQUIRE([_BOOST_GUESS_WHETHER_TO_USE_MT])dnl +AC_LANG_PUSH([C++])dnl +AS_VAR_PUSHDEF([Boost_lib], [boost_cv_lib_$1])dnl +AS_VAR_PUSHDEF([Boost_lib_LDFLAGS], [boost_cv_lib_$1_LDFLAGS])dnl +AS_VAR_PUSHDEF([Boost_lib_LIBS], [boost_cv_lib_$1_LIBS])dnl +BOOST_FIND_HEADER([$3]) +boost_save_CPPFLAGS=$CPPFLAGS +CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" +# Now let's try to find the library. The algorithm is as follows: first look +# for a given library name according to the user's PREFERRED-RT-OPT. For each +# library name, we prefer to use the ones that carry the tag (toolset name). +# Each library is searched through the various standard paths were Boost is +# usually installed. If we can't find the standard variants, we try to +# enforce -mt (for instance on MacOSX, libboost_threads.dylib doesn't exist +# but there's -obviously- libboost_threads-mt.dylib). +AC_CACHE_CHECK([for the Boost $1 library], [Boost_lib], + [Boost_lib=no + case "$2" in #( + mt | mt-) boost_mt=-mt; boost_rtopt=;; #( + mt* | mt-*) boost_mt=-mt; boost_rtopt=`expr "X$2" : 'Xmt-*\(.*\)'`;; #( + *) boost_mt=; boost_rtopt=$2;; + esac + if test $enable_static_boost = yes; then + boost_rtopt="s$boost_rtopt" + fi + # Find the proper debug variant depending on what we've been asked to find. + case $boost_rtopt in #( + *d*) boost_rt_d=$boost_rtopt;; #( + *[[sgpn]]*) # Insert the `d' at the right place (in between `sg' and `pn') + boost_rt_d=`echo "$boost_rtopt" | sed 's/\(s*g*\)\(p*n*\)/\1\2/'`;; #( + *) boost_rt_d='-d';; + esac + # If the PREFERRED-RT-OPT are not empty, prepend a `-'. + test -n "$boost_rtopt" && boost_rtopt="-$boost_rtopt" + $boost_guess_use_mt && boost_mt=-mt + # Look for the abs path the static archive. + # $libext is computed by Libtool but let's make sure it's non empty. + test -z "$libext" && + AC_MSG_ERROR([the libext variable is empty, did you invoke Libtool?]) + boost_save_ac_objext=$ac_objext + # Generate the test file. + AC_LANG_CONFTEST([AC_LANG_PROGRAM([#include <$3> +$5], [$4])]) +dnl Optimization hacks: compiling C++ is slow, especially with Boost. What +dnl we're trying to do here is guess the right combination of link flags +dnl (LIBS / LDFLAGS) to use a given library. This can take several +dnl iterations before it succeeds and is thus *very* slow. So what we do +dnl instead is that we compile the code first (and thus get an object file, +dnl typically conftest.o). Then we try various combinations of link flags +dnl until we succeed to link conftest.o in an executable. The problem is +dnl that the various TRY_LINK / COMPILE_IFELSE macros of Autoconf always +dnl remove all the temporary files including conftest.o. So the trick here +dnl is to temporarily change the value of ac_objext so that conftest.o is +dnl preserved accross tests. This is obviously fragile and I will burn in +dnl hell for not respecting Autoconf's documented interfaces, but in the +dnl mean time, it optimizes the macro by a factor of 5 to 30. +dnl Another small optimization: the first argument of AC_COMPILE_IFELSE left +dnl empty because the test file is generated only once above (before we +dnl start the for loops). + AC_COMPILE_IFELSE([], + [ac_objext=do_not_rm_me_plz], + [AC_MSG_ERROR([Cannot compile a test that uses Boost $1])]) + ac_objext=$boost_save_ac_objext + boost_failed_libs= +# Don't bother to ident the 6 nested for loops, only the 2 innermost ones +# matter. +for boost_tag_ in -$boost_cv_lib_tag ''; do +for boost_ver_ in -$boost_cv_lib_version ''; do +for boost_mt_ in $boost_mt -mt ''; do +for boost_rtopt_ in $boost_rtopt '' -d; do + for boost_lib in \ + boost_$1$boost_tag_$boost_mt_$boost_rtopt_$boost_ver_ \ + boost_$1$boost_tag_$boost_rtopt_$boost_ver_ \ + boost_$1$boost_tag_$boost_mt_$boost_ver_ \ + boost_$1$boost_tag_$boost_ver_ + do + # Avoid testing twice the same lib + case $boost_failed_libs in #( + *@$boost_lib@*) continue;; + esac + # If with_boost is empty, we'll search in /lib first, which is not quite + # right so instead we'll try to a location based on where the headers are. + boost_tmp_lib=$with_boost + test x"$with_boost" = x && boost_tmp_lib=${boost_cv_inc_path%/include} + for boost_ldpath in "$boost_tmp_lib/lib" '' \ + /opt/local/lib /usr/local/lib /opt/lib /usr/lib \ + "$with_boost" C:/Boost/lib /lib /usr/lib64 /lib64 + do + test -e "$boost_ldpath" || continue + boost_save_LDFLAGS=$LDFLAGS + # Are we looking for a static library? + case $boost_ldpath:$boost_rtopt_ in #( + *?*:*s*) # Yes (Non empty boost_ldpath + s in rt opt) + Boost_lib_LIBS="$boost_ldpath/lib$boost_lib.$libext" + test -e "$Boost_lib_LIBS" || continue;; #( + *) # No: use -lboost_foo to find the shared library. + Boost_lib_LIBS="-l$boost_lib";; + esac + boost_save_LIBS=$LIBS + LIBS="$Boost_lib_LIBS $LIBS" + test x"$boost_ldpath" != x && LDFLAGS="$LDFLAGS -L$boost_ldpath" +dnl First argument of AC_LINK_IFELSE left empty because the test file is +dnl generated only once above (before we start the for loops). + _BOOST_AC_LINK_IFELSE([], + [Boost_lib=yes], [Boost_lib=no]) + ac_objext=$boost_save_ac_objext + LDFLAGS=$boost_save_LDFLAGS + LIBS=$boost_save_LIBS + if test x"$Boost_lib" = xyes; then + Boost_lib_LDFLAGS="-L$boost_ldpath -R$boost_ldpath" + break 6 + else + boost_failed_libs="$boost_failed_libs@$boost_lib@" + fi + done + done +done +done +done +done +rm -f conftest.$ac_objext +]) +case $Boost_lib in #( + no) AC_MSG_ERROR([Could not find the flags to link with Boost $1]) + ;; +esac +AC_SUBST(AS_TR_CPP([BOOST_$1_LDFLAGS]), [$Boost_lib_LDFLAGS]) +AC_SUBST(AS_TR_CPP([BOOST_$1_LIBS]), [$Boost_lib_LIBS]) +CPPFLAGS=$boost_save_CPPFLAGS +AS_VAR_POPDEF([Boost_lib])dnl +AS_VAR_POPDEF([Boost_lib_LDFLAGS])dnl +AS_VAR_POPDEF([Boost_lib_LIBS])dnl +AC_LANG_POP([C++])dnl +])# BOOST_FIND_LIB + + +# --------------------------------------- # +# Checks for the various Boost libraries. # +# --------------------------------------- # + +# List of boost libraries: http://www.boost.org/libs/libraries.htm +# The page http://beta.boost.org/doc/libs is useful: it gives the first release +# version of each library (among other things). + + +# BOOST_ASIO() +# ------------ +# Look for Boost.Asio (new in Boost 1.35). +AC_DEFUN([BOOST_ASIO], +[AC_REQUIRE([BOOST_SYSTEM])dnl +BOOST_FIND_HEADER([boost/asio.hpp])]) + + +# BOOST_BIND() +# ------------ +# Look for Boost.Bind +AC_DEFUN([BOOST_BIND], +[BOOST_FIND_HEADER([boost/bind.hpp])]) + + +# BOOST_CONVERSION() +# ------------------ +# Look for Boost.Conversion (cast / lexical_cast) +AC_DEFUN([BOOST_CONVERSION], +[BOOST_FIND_HEADER([boost/cast.hpp]) +BOOST_FIND_HEADER([boost/lexical_cast.hpp]) +])# BOOST_CONVERSION + + +# BOOST_DATE_TIME([PREFERRED-RT-OPT]) +# ----------------------------------- +# Look for Boost.Date_Time. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +AC_DEFUN([BOOST_DATE_TIME], +[BOOST_FIND_LIB([date_time], [$1], + [boost/date_time/posix_time/posix_time.hpp], + [boost::posix_time::ptime t;]) +])# BOOST_DATE_TIME + + +# BOOST_FILESYSTEM([PREFERRED-RT-OPT]) +# ------------------------------------ +# Look for Boost.Filesystem. For the documentation of PREFERRED-RT-OPT, see +# the documentation of BOOST_FIND_LIB above. +# Do not check for boost/filesystem.hpp because this file was introduced in +# 1.34. +AC_DEFUN([BOOST_FILESYSTEM], +[# Do we have to check for Boost.System? This link-time dependency was +# added as of 1.35.0. If we have a version <1.35, we must not attempt to +# find Boost.System as it didn't exist by then. +if test $boost_major_version -ge 135; then +BOOST_SYSTEM([$1]) +fi # end of the Boost.System check. +boost_filesystem_save_LIBS=$LIBS +boost_filesystem_save_LDFLAGS=$LDFLAGS +m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl +LIBS="$LIBS $BOOST_SYSTEM_LIBS" +LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS" +BOOST_FIND_LIB([filesystem], [$1], + [boost/filesystem/path.hpp], [boost::filesystem::path p;]) +LIBS=$boost_filesystem_save_LIBS +LDFLAGS=$boost_filesystem_save_LDFLAGS +])# BOOST_FILESYSTEM + + +# BOOST_FOREACH() +# --------------- +# Look for Boost.Foreach +AC_DEFUN([BOOST_FOREACH], +[BOOST_FIND_HEADER([boost/foreach.hpp])]) + + +# BOOST_FORMAT() +# -------------- +# Look for Boost.Format +# Note: we can't check for boost/format/format_fwd.hpp because the header isn't +# standalone. It can't be compiled because it triggers the following error: +# boost/format/detail/config_macros.hpp:88: error: 'locale' in namespace 'std' +# does not name a type +AC_DEFUN([BOOST_FORMAT], +[BOOST_FIND_HEADER([boost/format.hpp])]) + + +# BOOST_FUNCTION() +# ---------------- +# Look for Boost.Function +AC_DEFUN([BOOST_FUNCTION], +[BOOST_FIND_HEADER([boost/function.hpp])]) + + +# BOOST_GRAPH([PREFERRED-RT-OPT]) +# ------------------------------- +# Look for Boost.Graphs. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +AC_DEFUN([BOOST_GRAPH], +[BOOST_FIND_LIB([graph], [$1], + [boost/graph/adjacency_list.hpp], [boost::adjacency_list<> g;]) +])# BOOST_GRAPH + + +# BOOST_IOSTREAMS([PREFERRED-RT-OPT]) +# ------------------------------- +# Look for Boost.IOStreams. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +AC_DEFUN([BOOST_IOSTREAMS], +[BOOST_FIND_LIB([iostreams], [$1], + [boost/iostreams/device/file_descriptor.hpp], + [boost::iostreams::file_descriptor fd(0); fd.close();]) +])# BOOST_IOSTREAMS + + +# BOOST_HASH() +# ------------ +# Look for Boost.Functional/Hash +AC_DEFUN([BOOST_HASH], +[BOOST_FIND_HEADER([boost/functional/hash.hpp])]) + + +# BOOST_LAMBDA() +# -------------- +# Look for Boost.Lambda +AC_DEFUN([BOOST_LAMBDA], +[BOOST_FIND_HEADER([boost/lambda/lambda.hpp])]) + + +# BOOST_OPTIONAL() +# ---------------- +# Look for Boost.Optional +AC_DEFUN([BOOST_OPTIONAL], +[BOOST_FIND_HEADER([boost/optional.hpp])]) + + +# BOOST_PREPROCESSOR() +# -------------------- +# Look for Boost.Preprocessor +AC_DEFUN([BOOST_PREPROCESSOR], +[BOOST_FIND_HEADER([boost/preprocessor/repeat.hpp])]) + + +# BOOST_PROGRAM_OPTIONS([PREFERRED-RT-OPT]) +# ----------------------------------------- +# Look for Boost.Program_options. For the documentation of PREFERRED-RT-OPT, see +# the documentation of BOOST_FIND_LIB above. +AC_DEFUN([BOOST_PROGRAM_OPTIONS], +[BOOST_FIND_LIB([program_options], [$1], + [boost/program_options.hpp], + [boost::program_options::options_description d("test");]) +])# BOOST_PROGRAM_OPTIONS + + +# BOOST_REF() +# ----------- +# Look for Boost.Ref +AC_DEFUN([BOOST_REF], +[BOOST_FIND_HEADER([boost/ref.hpp])]) + + +# BOOST_REGEX([PREFERRED-RT-OPT]) +# ------------------------------- +# Look for Boost.Regex. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +AC_DEFUN([BOOST_REGEX], +[BOOST_FIND_LIB([regex], [$1], + [boost/regex.hpp], + [boost::regex exp("*"); boost::regex_match("foo", exp);]) +])# BOOST_REGEX + + +# BOOST_SERIALIZATION([PREFERRED-RT-OPT]) +# --------------------------------------- +# Look for Boost.Serialization. For the documentation of PREFERRED-RT-OPT, see +# the documentation of BOOST_FIND_LIB above. +AC_DEFUN([BOOST_SERIALIZATION], +[BOOST_FIND_LIB([serialization], [$1], + [boost/archive/text_oarchive.hpp], + [std::ostream* o = 0; // Cheap way to get an ostream... + boost::archive::text_oarchive t(*o);]) +])# BOOST_SIGNALS + + +# BOOST_SIGNALS([PREFERRED-RT-OPT]) +# --------------------------------- +# Look for Boost.Signals. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +AC_DEFUN([BOOST_SIGNALS], +[BOOST_FIND_LIB([signals], [$1], + [boost/signal.hpp], + [boost::signal s;]) +])# BOOST_SIGNALS + + +# BOOST_SMART_PTR() +# ----------------- +# Look for Boost.SmartPtr +AC_DEFUN([BOOST_SMART_PTR], +[BOOST_FIND_HEADER([boost/scoped_ptr.hpp]) +BOOST_FIND_HEADER([boost/shared_ptr.hpp]) +]) + + +# BOOST_STATICASSERT() +# -------------------- +# Look for Boost.StaticAssert +AC_DEFUN([BOOST_STATICASSERT], +[BOOST_FIND_HEADER([boost/static_assert.hpp])]) + + +# BOOST_STRING_ALGO() +# ------------------- +# Look for Boost.StringAlgo +AC_DEFUN([BOOST_STRING_ALGO], +[BOOST_FIND_HEADER([boost/algorithm/string.hpp]) +]) + + +# BOOST_SYSTEM([PREFERRED-RT-OPT]) +# -------------------------------- +# Look for Boost.System. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. This library was introduced in Boost +# 1.35.0. +AC_DEFUN([BOOST_SYSTEM], +[BOOST_FIND_LIB([system], [$1], + [boost/system/error_code.hpp], + [boost::system::error_code e; e.clear();]) +])# BOOST_SYSTEM + + +# BOOST_TEST([PREFERRED-RT-OPT]) +# ------------------------------ +# Look for Boost.Test. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +AC_DEFUN([BOOST_TEST], +[m4_pattern_allow([^BOOST_CHECK$])dnl +BOOST_FIND_LIB([unit_test_framework], [$1], + [boost/test/unit_test.hpp], [BOOST_CHECK(2 == 2);], + [using boost::unit_test::test_suite; + test_suite* init_unit_test_suite(int argc, char ** argv) + { return NULL; }]) +])# BOOST_TEST + + +# BOOST_THREADS([PREFERRED-RT-OPT]) +# --------------------------------- +# Look for Boost.Thread. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +# FIXME: Provide an alias "BOOST_THREAD". +AC_DEFUN([BOOST_THREADS], +[dnl Having the pthread flag is required at least on GCC3 where +dnl boost/thread.hpp would complain if we try to compile without +dnl -pthread on GNU/Linux. +AC_REQUIRE([_BOOST_PTHREAD_FLAG])dnl +boost_threads_save_LIBS=$LIBS +boost_threads_save_CPPFLAGS=$CPPFLAGS +LIBS="$LIBS $boost_cv_pthread_flag" +# Yes, we *need* to put the -pthread thing in CPPFLAGS because with GCC3, +# boost/thread.hpp will trigger a #error if -pthread isn't used: +# boost/config/requires_threads.hpp:47:5: #error "Compiler threading support +# is not turned on. Please set the correct command line options for +# threading: -pthread (Linux), -pthreads (Solaris) or -mthreads (Mingw32)" +CPPFLAGS="$CPPFLAGS $boost_cv_pthread_flag" +BOOST_FIND_LIB([thread], [$1], + [boost/thread.hpp], [boost::thread t; boost::mutex m;]) +BOOST_THREAD_LIBS="$BOOST_THREAD_LIBS $boost_cv_pthread_flag" +BOOST_CPPFLAGS="$BOOST_CPPFLAGS $boost_cv_pthread_flag" +LIBS=$boost_threads_save_LIBS +CPPFLAGS=$boost_threads_save_CPPFLAGS +])# BOOST_THREADS + + +# BOOST_TOKENIZER() +# ----------------- +# Look for Boost.Tokenizer +AC_DEFUN([BOOST_TOKENIZER], +[BOOST_FIND_HEADER([boost/tokenizer.hpp])]) + + +# BOOST_TRIBOOL() +# --------------- +# Look for Boost.Tribool +AC_DEFUN([BOOST_TRIBOOL], +[BOOST_FIND_HEADER([boost/logic/tribool_fwd.hpp]) +BOOST_FIND_HEADER([boost/logic/tribool.hpp]) +]) + + +# BOOST_TUPLE() +# ------------- +# Look for Boost.Tuple +AC_DEFUN([BOOST_TUPLE], +[BOOST_FIND_HEADER([boost/tuple/tuple.hpp])]) + + +# BOOST_TYPETRAITS() +# -------------------- +# Look for Boost.TypeTraits +AC_DEFUN([BOOST_TYPETRAITS], +[BOOST_FIND_HEADER([boost/type_traits.hpp])]) + + +# BOOST_UTILITY() +# --------------- +# Look for Boost.Utility (noncopyable, result_of, base-from-member idiom, +# etc.) +AC_DEFUN([BOOST_UTILITY], +[BOOST_FIND_HEADER([boost/utility.hpp])]) + + +# BOOST_VARIANT() +# --------------- +# Look for Boost.Variant. +AC_DEFUN([BOOST_VARIANT], +[BOOST_FIND_HEADER([boost/variant/variant_fwd.hpp]) +BOOST_FIND_HEADER([boost/variant.hpp])]) + + +# BOOST_WAVE([PREFERRED-RT-OPT]) +# ------------------------------ +# NOTE: If you intend to use Wave/Spirit with thread support, make sure you +# call BOOST_THREADS first. +# Look for Boost.Wave. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +AC_DEFUN([BOOST_WAVE], +[AC_REQUIRE([BOOST_FILESYSTEM])dnl +AC_REQUIRE([BOOST_DATE_TIME])dnl +boost_wave_save_LIBS=$LIBS +boost_wave_save_LDFLAGS=$LDFLAGS +m4_pattern_allow([^BOOST_((FILE)?SYSTEM|DATE_TIME|THREAD)_(LIBS|LDFLAGS)$])dnl +LIBS="$LIBS $BOOST_SYSTEM_LIBS $BOOST_FILESYSTEM_LIBS $BOOST_DATE_TIME_LIBS\ +$BOOST_THREAD_LIBS" +LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS $BOOST_FILESYSTEM_LDFLAGS\ +$BOOST_DATE_TIME_LDFLAGS $BOOST_THREAD_LDFLAGS" +BOOST_FIND_LIB([wave], [$1], + [boost/wave.hpp], + [boost::wave::token_id id; get_token_name(id);]) +LIBS=$boost_wave_save_LIBS +LDFLAGS=$boost_wave_save_LDFLAGS +])# BOOST_WAVE + + +# BOOST_XPRESSIVE() +# ----------------- +# Look for Boost.Xpressive (new since 1.36.0). +AC_DEFUN([BOOST_XPRESSIVE], +[BOOST_FIND_HEADER([boost/xpressive/xpressive.hpp])]) + + +# ----------------- # +# Internal helpers. # +# ----------------- # + + +# _BOOST_PTHREAD_FLAG() +# --------------------- +# Internal helper for BOOST_THREADS. Based on ACX_PTHREAD: +# http://autoconf-archive.cryp.to/acx_pthread.html +AC_DEFUN([_BOOST_PTHREAD_FLAG], +[AC_REQUIRE([AC_PROG_CXX])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_LANG_PUSH([C++])dnl +AC_CACHE_CHECK([for the flags needed to use pthreads], [boost_cv_pthread_flag], +[ boost_cv_pthread_flag= + # The ordering *is* (sometimes) important. Some notes on the + # individual items follow: + # (none): in case threads are in libc; should be tried before -Kthread and + # other compiler flags to prevent continual compiler warnings + # -lpthreads: AIX (must check this before -lpthread) + # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) + # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) + # -llthread: LinuxThreads port on FreeBSD (also preferred to -pthread) + # -pthread: GNU Linux/GCC (kernel threads), BSD/GCC (userland threads) + # -pthreads: Solaris/GCC + # -mthreads: MinGW32/GCC, Lynx/GCC + # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it + # doesn't hurt to check since this sometimes defines pthreads too; + # also defines -D_REENTRANT) + # ... -mt is also the pthreads flag for HP/aCC + # -lpthread: GNU Linux, etc. + # --thread-safe: KAI C++ + case $host_os in #( + *solaris*) + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (We need to link with -pthreads/-mt/ + # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather + # a function called by this macro, so we could check for that, but + # who knows whether they'll stub that too in a future libc.) So, + # we'll just look for -pthreads and -lpthread first: + boost_pthread_flags="-pthreads -lpthread -mt -pthread";; #( + *) + boost_pthread_flags="-lpthreads -Kthread -kthread -llthread -pthread \ + -pthreads -mthreads -lpthread --thread-safe -mt";; + esac + # Generate the test file. + AC_LANG_CONFTEST([AC_LANG_PROGRAM([#include ], + [pthread_t th; pthread_join(th, 0); + pthread_attr_init(0); pthread_cleanup_push(0, 0); + pthread_create(0,0,0,0); pthread_cleanup_pop(0);])]) + for boost_pthread_flag in '' $boost_pthread_flags; do + boost_pthread_ok=false +dnl Re-use the test file already generated. + boost_pthreads__save_LIBS=$LIBS + LIBS="$LIBS $boost_pthread_flag" + AC_LINK_IFELSE([], + [if grep ".*$boost_pthread_flag" conftest.err; then + echo "This flag seems to have triggered warnings" >&AS_MESSAGE_LOG_FD + else + boost_pthread_ok=:; boost_cv_pthread_flag=$boost_pthread_flag + fi]) + LIBS=$boost_pthreads__save_LIBS + $boost_pthread_ok && break + done +]) +AC_LANG_POP([C++])dnl +])# _BOOST_PTHREAD_FLAG + + +# _BOOST_gcc_test(MAJOR, MINOR) +# ----------------------------- +# Internal helper for _BOOST_FIND_COMPILER_TAG. +m4_define([_BOOST_gcc_test], +["defined __GNUC__ && __GNUC__ == $1 && __GNUC_MINOR__ == $2 && !defined __ICC @ gcc$1$2"])dnl + + +# _BOOST_FIND_COMPILER_TAG() +# -------------------------- +# Internal. When Boost is installed without --layout=system, each library +# filename will hold a suffix that encodes the compiler used during the +# build. The Boost build system seems to call this a `tag'. +AC_DEFUN([_BOOST_FIND_COMPILER_TAG], +[AC_REQUIRE([AC_PROG_CXX])dnl +AC_CACHE_CHECK([for the toolset name used by Boost for $CXX], [boost_cv_lib_tag], +[AC_LANG_PUSH([C++])dnl + boost_cv_lib_tag=unknown + # The following tests are mostly inspired by boost/config/auto_link.hpp + # The list is sorted to most recent/common to oldest compiler (in order + # to increase the likelihood of finding the right compiler with the + # least number of compilation attempt). + # Beware that some tests are sensible to the order (for instance, we must + # look for MinGW before looking for GCC3). + # I used one compilation test per compiler with a #error to recognize + # each compiler so that it works even when cross-compiling (let me know + # if you know a better approach). + # Known missing tags (known from Boost's tools/build/v2/tools/common.jam): + # como, edg, kcc, bck, mp, sw, tru, xlc + # I'm not sure about my test for `il' (be careful: Intel's ICC pre-defines + # the same defines as GCC's). + # TODO: Move the test on GCC 4.4 up once it's released. + for i in \ + _BOOST_gcc_test(4, 3) \ + _BOOST_gcc_test(4, 2) \ + _BOOST_gcc_test(4, 1) \ + _BOOST_gcc_test(4, 0) \ + "defined __GNUC__ && __GNUC__ == 3 && !defined __ICC \ + && (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw" \ + _BOOST_gcc_test(3, 4) \ + _BOOST_gcc_test(3, 3) \ + "defined _MSC_VER && _MSC_VER >= 1400 @ vc80" \ + _BOOST_gcc_test(3, 2) \ + "defined _MSC_VER && _MSC_VER == 1310 @ vc71" \ + _BOOST_gcc_test(3, 1) \ + _BOOST_gcc_test(3, 0) \ + "defined __BORLANDC__ @ bcb" \ + "defined __ICC && (defined __unix || defined __unix__) @ il" \ + "defined __ICL @ iw" \ + "defined _MSC_VER && _MSC_VER == 1300 @ vc7" \ + _BOOST_gcc_test(4, 4) \ + _BOOST_gcc_test(2, 95) \ + "defined __MWERKS__ && __MWERKS__ <= 0x32FF @ cw9" \ + "defined _MSC_VER && _MSC_VER < 1300 && !defined UNDER_CE @ vc6" \ + "defined _MSC_VER && _MSC_VER < 1300 && defined UNDER_CE @ evc4" \ + "defined __MWERKS__ && __MWERKS__ <= 0x31FF @ cw8" + do + boost_tag_test=`expr "X$i" : 'X\([[^@]]*\) @ '` + boost_tag=`expr "X$i" : 'X[[^@]]* @ \(.*\)'` + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#if $boost_tag_test +/* OK */ +#else +# error $boost_tag_test +#endif +]])], [boost_cv_lib_tag=$boost_tag; break], []) + done +AC_LANG_POP([C++])dnl + case $boost_cv_lib_tag in #( + # Some newer (>= 1.35?) versions of Boost seem to only use "gcc" as opposed + # to "gcc41" for instance. + *-gcc | *'-gcc ') :;; #( Don't re-add -gcc: it's already in there. + gcc*) + # We can specify multiple tags in this variable because it's used by + # BOOST_FIND_LIB that does a `for tag in -$boost_cv_lib_tag' ... + boost_cv_lib_tag="$boost_cv_lib_tag -gcc" + ;; #( + unknown) + AC_MSG_WARN([[could not figure out which toolset name to use for $CXX]]) + boost_cv_lib_tag= + ;; + esac +])dnl end of AC_CACHE_CHECK +])# _BOOST_FIND_COMPILER_TAG + + +# _BOOST_GUESS_WHETHER_TO_USE_MT() +# -------------------------------- +# Compile a small test to try to guess whether we should favor MT (Multi +# Thread) flavors of Boost. Sets boost_guess_use_mt accordingly. +AC_DEFUN([_BOOST_GUESS_WHETHER_TO_USE_MT], +[# Check whether we do better use `mt' even though we weren't ask to. +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#if defined _REENTRANT || defined _MT || defined __MT__ +/* use -mt */ +#else +# error MT not needed +#endif +]])], [boost_guess_use_mt=:], [boost_guess_use_mt=false]) +]) + +# _BOOST_AC_LINK_IFELSE(PROGRAM, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) +# ------------------------------------------------------------------- +# Fork of _AC_LINK_IFELSE that preserves conftest.o across calls. Fragile, +# will break when Autoconf changes its internals. Requires that you manually +# rm -f conftest.$ac_objext in between to really different tests, otherwise +# you will try to link a conftest.o left behind by a previous test. +# Used to aggressively optimize BOOST_FIND_LIB (see the big comment in this +# macro) +m4_define([_BOOST_AC_LINK_IFELSE], +[m4_ifvaln([$1], [AC_LANG_CONFTEST([$1])])dnl +rm -f conftest$ac_exeext +boost_ac_ext_save=$ac_ext +boost_use_source=: +# If we already have a .o, re-use it. We change $ac_ext so that $ac_link +# tries to link the existing object file instead of compiling from source. +test -f conftest.$ac_objext && ac_ext=$ac_objext && boost_use_source=false && + _AS_ECHO_LOG([re-using the existing conftest.$ac_objext]) +AS_IF([_AC_DO_STDERR($ac_link) && { + test -z "$ac_[]_AC_LANG_ABBREV[]_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_executable_p conftest$ac_exeext +dnl FIXME: use AS_TEST_X instead when 2.61 is widespread enough. + }], + [$2], + [if $boost_use_source; then + _AC_MSG_LOG_CONFTEST + fi + $3]) +dnl Delete also the IPA/IPO (Inter Procedural Analysis/Optimization) +dnl information created by the PGI compiler (conftest_ipa8_conftest.oo), +dnl as it would interfere with the next link command. +rm -f core conftest.err conftest_ipa8_conftest.oo \ + conftest$ac_exeext m4_ifval([$1], [conftest.$ac_ext])[]dnl +])# _BOOST_AC_LINK_IFELSE + +# Local Variables: +# mode: autoconf +# End: diff --git a/m4/sdl.m4 b/m4/sdl.m4 new file mode 100644 index 0000000..ada3a41 --- /dev/null +++ b/m4/sdl.m4 @@ -0,0 +1,175 @@ +# Configure paths for SDL +# Sam Lantinga 9/21/99 +# stolen from Manish Singh +# stolen back from Frank Belew +# stolen from Manish Singh +# Shamelessly stolen from Owen Taylor + +dnl AM_PATH_SDL([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS +dnl +AC_DEFUN([AM_PATH_SDL], +[dnl +dnl Get the cflags and libraries from the sdl-config script +dnl +AC_ARG_WITH(sdl-prefix,[ --with-sdl-prefix=PFX Prefix where SDL is installed (optional)], + sdl_prefix="$withval", sdl_prefix="") +AC_ARG_WITH(sdl-exec-prefix,[ --with-sdl-exec-prefix=PFX Exec prefix where SDL is installed (optional)], + sdl_exec_prefix="$withval", sdl_exec_prefix="") +AC_ARG_ENABLE(sdltest, [ --disable-sdltest Do not try to compile and run a test SDL program], + , enable_sdltest=yes) + + if test x$sdl_exec_prefix != x ; then + sdl_args="$sdl_args --exec-prefix=$sdl_exec_prefix" + if test x${SDL_CONFIG+set} != xset ; then + SDL_CONFIG=$sdl_exec_prefix/bin/sdl-config + fi + fi + if test x$sdl_prefix != x ; then + sdl_args="$sdl_args --prefix=$sdl_prefix" + if test x${SDL_CONFIG+set} != xset ; then + SDL_CONFIG=$sdl_prefix/bin/sdl-config + fi + fi + + AC_REQUIRE([AC_CANONICAL_TARGET]) + PATH="$prefix/bin:$prefix/usr/bin:$PATH" + AC_PATH_PROG(SDL_CONFIG, sdl-config, no, [$PATH]) + min_sdl_version=ifelse([$1], ,0.11.0,$1) + AC_MSG_CHECKING(for SDL - version >= $min_sdl_version) + no_sdl="" + if test "$SDL_CONFIG" = "no" ; then + no_sdl=yes + else + SDL_CFLAGS=`$SDL_CONFIG $sdlconf_args --cflags` + SDL_LIBS=`$SDL_CONFIG $sdlconf_args --libs` + + sdl_major_version=`$SDL_CONFIG $sdl_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + sdl_minor_version=`$SDL_CONFIG $sdl_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + sdl_micro_version=`$SDL_CONFIG $sdl_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + if test "x$enable_sdltest" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $SDL_CFLAGS" + LIBS="$LIBS $SDL_LIBS" +dnl +dnl Now check if the installed SDL is sufficiently new. (Also sanity +dnl checks the results of sdl-config to some extent +dnl + rm -f conf.sdltest + AC_TRY_RUN([ +#include +#include +#include +#include "SDL.h" + +char* +my_strdup (char *str) +{ + char *new_str; + + if (str) + { + new_str = (char *)malloc ((strlen (str) + 1) * sizeof(char)); + strcpy (new_str, str); + } + else + new_str = NULL; + + return new_str; +} + +int main (int argc, char *argv[]) +{ + int major, minor, micro; + char *tmp_version; + + /* This hangs on some systems (?) + system ("touch conf.sdltest"); + */ + { FILE *fp = fopen("conf.sdltest", "a"); if ( fp ) fclose(fp); } + + /* HP/UX 9 (%@#!) writes to sscanf strings */ + tmp_version = my_strdup("$min_sdl_version"); + if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { + printf("%s, bad version string\n", "$min_sdl_version"); + exit(1); + } + + if (($sdl_major_version > major) || + (($sdl_major_version == major) && ($sdl_minor_version > minor)) || + (($sdl_major_version == major) && ($sdl_minor_version == minor) && ($sdl_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** 'sdl-config --version' returned %d.%d.%d, but the minimum version\n", $sdl_major_version, $sdl_minor_version, $sdl_micro_version); + printf("*** of SDL required is %d.%d.%d. If sdl-config is correct, then it is\n", major, minor, micro); + printf("*** best to upgrade to the required version.\n"); + printf("*** If sdl-config was wrong, set the environment variable SDL_CONFIG\n"); + printf("*** to point to the correct copy of sdl-config, and remove the file\n"); + printf("*** config.cache before re-running configure\n"); + return 1; + } +} + +],, no_sdl=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + if test "x$no_sdl" = x ; then + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + AC_MSG_RESULT(no) + if test "$SDL_CONFIG" = "no" ; then + echo "*** The sdl-config script installed by SDL could not be found" + echo "*** If SDL was installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or set the SDL_CONFIG environment variable to the" + echo "*** full path to sdl-config." + else + if test -f conf.sdltest ; then + : + else + echo "*** Could not run SDL test program, checking why..." + CFLAGS="$CFLAGS $SDL_CFLAGS" + LIBS="$LIBS $SDL_LIBS" + AC_TRY_LINK([ +#include +#include "SDL.h" + +int main(int argc, char *argv[]) +{ return 0; } +#undef main +#define main K_and_R_C_main +], [ return 0; ], + [ echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding SDL or finding the wrong" + echo "*** version of SDL. If it is not finding SDL, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], + [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means SDL was incorrectly installed" + echo "*** or that you have moved SDL since it was installed. In the latter case, you" + echo "*** may want to edit the sdl-config script: $SDL_CONFIG" ]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + SDL_CFLAGS="" + SDL_LIBS="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(SDL_CFLAGS) + AC_SUBST(SDL_LIBS) + rm -f conf.sdltest +]) diff --git a/share/character/Heroine.json b/share/character/Heroine.json deleted file mode 100644 index 0ea723b..0000000 --- a/share/character/Heroine.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "tilemap": "Heroine.png", - "animation": "Heroine.json" -} diff --git a/share/texture/AlienWarrior.plist b/share/texture/AlienWarrior.plist deleted file mode 100644 index d3adf1b..0000000 --- a/share/texture/AlienWarrior.plist +++ /dev/null @@ -1,16 +0,0 @@ - - - - - TilesU - 8 - TilesV - 4 - InvertAlpha - 0 - MinFilter - Nearest - MagFilter - Nearest - - diff --git a/share/texture/BackgroundFar.plist b/share/texture/BackgroundFar.plist deleted file mode 100644 index a02e454..0000000 --- a/share/texture/BackgroundFar.plist +++ /dev/null @@ -1,21 +0,0 @@ - - - - - TilesU - 1 - TilesV - 1 - InvertAlpha - 0 - - WrapU - ClampToEdge - WrapV - ClampToEdge - MinFilter - Linear - MagFilter - Linear - - diff --git a/share/texture/BackgroundNear.plist b/share/texture/BackgroundNear.plist deleted file mode 100644 index 46fe92a..0000000 --- a/share/texture/BackgroundNear.plist +++ /dev/null @@ -1,21 +0,0 @@ - - - - - TilesU - 1 - TilesV - 1 - InvertAlpha - 0 - - WrapU - Wrap - WrapV - Wrap - MinFilter - Linear - MagFilter - Linear - - diff --git a/share/texture/BigExplosion.plist b/share/texture/BigExplosion.plist deleted file mode 100644 index f9c42cb..0000000 --- a/share/texture/BigExplosion.plist +++ /dev/null @@ -1,25 +0,0 @@ - - - - - TilesU - 8 - TilesV - 1 - InvertAlpha - 0 - - MinFilter - Linear - MagFilter - Linear - WrapU - ClampToEdge - WrapV - ClampToEdge - MinFilter - Nearest - MagFilter - Nearest - - diff --git a/share/texture/Bonuses.plist b/share/texture/Bonuses.plist deleted file mode 100644 index 486e2f8..0000000 --- a/share/texture/Bonuses.plist +++ /dev/null @@ -1,25 +0,0 @@ - - - - - TilesU - 8 - TilesV - 4 - InvertAlpha - 0 - - MinFilter - Linear - MagFilter - Linear - WrapU - ClampToEdge - WrapV - ClampToEdge - MinFilter - Nearest - MagFilter - Nearest - - diff --git a/share/texture/Building.plist b/share/texture/Building.plist deleted file mode 100644 index 79084ea..0000000 --- a/share/texture/Building.plist +++ /dev/null @@ -1,21 +0,0 @@ - - - - - TilesU - 8 - TilesV - 4 - InvertAlpha - 0 - - WrapU - ClampToEdge - WrapV - ClampToEdge - MinFilter - Nearest - MagFilter - Nearest - - diff --git a/share/texture/Default.plist b/share/texture/Default.plist deleted file mode 100644 index 18a47ff..0000000 --- a/share/texture/Default.plist +++ /dev/null @@ -1,16 +0,0 @@ - - - - - MinFilter - Linear - MagFilter - Linear - WrapU - Repeat - WrapV - Repeat - InvertAlpha - 0 - - diff --git a/share/texture/Font.plist b/share/texture/Font.plist deleted file mode 100644 index 7688344..0000000 --- a/share/texture/Font.plist +++ /dev/null @@ -1,16 +0,0 @@ - - - - - TilesU - 8 - TilesV - 8 - InvertAlpha - 0 - MinFilter - Nearest - MagFilter - Nearest - - diff --git a/share/texture/Heroine.plist b/share/texture/Heroine.plist deleted file mode 100644 index d3adf1b..0000000 --- a/share/texture/Heroine.plist +++ /dev/null @@ -1,16 +0,0 @@ - - - - - TilesU - 8 - TilesV - 4 - InvertAlpha - 0 - MinFilter - Nearest - MagFilter - Nearest - - diff --git a/share/texture/Jetbot.plist b/share/texture/Jetbot.plist deleted file mode 100644 index 6f7f246..0000000 --- a/share/texture/Jetbot.plist +++ /dev/null @@ -1,16 +0,0 @@ - - - - - TilesU - 4 - TilesV - 2 - InvertAlpha - 0 - MinFilter - Nearest - MagFilter - Nearest - - diff --git a/share/texture/Particles.plist b/share/texture/Particles.plist deleted file mode 100644 index 486e2f8..0000000 --- a/share/texture/Particles.plist +++ /dev/null @@ -1,25 +0,0 @@ - - - - - TilesU - 8 - TilesV - 4 - InvertAlpha - 0 - - MinFilter - Linear - MagFilter - Linear - WrapU - ClampToEdge - WrapV - ClampToEdge - MinFilter - Nearest - MagFilter - Nearest - - diff --git a/share/texture/RobotTrooper.plist b/share/texture/RobotTrooper.plist deleted file mode 100644 index d3adf1b..0000000 --- a/share/texture/RobotTrooper.plist +++ /dev/null @@ -1,16 +0,0 @@ - - - - - TilesU - 8 - TilesV - 4 - InvertAlpha - 0 - MinFilter - Nearest - MagFilter - Nearest - - diff --git a/share/texture/Scenery.plist b/share/texture/Scenery.plist deleted file mode 100644 index 95aedca..0000000 --- a/share/texture/Scenery.plist +++ /dev/null @@ -1,25 +0,0 @@ - - - - - TilesU - 4 - TilesV - 4 - InvertAlpha - 0 - - MinFilter - Linear - MagFilter - Linear - WrapU - Wrap - WrapV - Wrap - MinFilter - Nearest - MagFilter - Nearest - - diff --git a/share/texture/StatusBars.plist b/share/texture/StatusBars.plist deleted file mode 100644 index 148307a..0000000 --- a/share/texture/StatusBars.plist +++ /dev/null @@ -1,16 +0,0 @@ - - - - - TilesU - 4 - TilesV - 1 - InvertAlpha - 0 - MinFilter - Nearest - MagFilter - Nearest - - diff --git a/share/texture/TowerBlock1.plist b/share/texture/TowerBlock1.plist deleted file mode 100644 index f969901..0000000 --- a/share/texture/TowerBlock1.plist +++ /dev/null @@ -1,25 +0,0 @@ - - - - - TilesU - 4 - TilesV - 4 - InvertAlpha - 0 - - MinFilter - Linear - MagFilter - Linear - WrapU - ClampToEdge - WrapV - ClampToEdge - MinFilter - Nearest - MagFilter - Nearest - - diff --git a/share/texture/Trees.plist b/share/texture/Trees.plist deleted file mode 100644 index 3c9b875..0000000 --- a/share/texture/Trees.plist +++ /dev/null @@ -1,25 +0,0 @@ - - - - - TilesU - 2 - TilesV - 1 - InvertAlpha - 0 - - MinFilter - Linear - MagFilter - Linear - WrapU - ClampToEdge - WrapV - ClampToEdge - MinFilter - Nearest - MagFilter - Nearest - - diff --git a/src/Character.cc b/src/Character.cc new file mode 100644 index 0000000..64866c5 --- /dev/null +++ b/src/Character.cc @@ -0,0 +1,57 @@ + +/******************************************************************************* + + Copyright (c) 2009, Charles McGarvey + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "Character.hh" + + +Character::Character(const std::string& name) : + texture(name), + anim(name) {} + +Character::~Character() +{ + //delete texture; + //delete anim; +} + + +void Character::draw(dc::scalar alpha) {} + +dc::tilemap& Character::getTilemap() +{ + return texture; +} + +dc::animation& Character::getAnimation() +{ + return anim; +} + + +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/Character.hh b/src/Character.hh index 2f175ad..c9cf11a 100644 --- a/src/Character.hh +++ b/src/Character.hh @@ -29,13 +29,17 @@ #ifndef _CHARACTER_HH_ #define _CHARACTER_HH_ +#include "resource.hh" +#include "drawable.hh" +#include "animation.hh" +#include "tilemap.hh" + + /** - * @file Character.hh * Parent class of animate objects with "personalities." */ - -class Character : public dc::resource, public dc::drawable +class Character : public dc::drawable { public: struct exception : public std::runtime_error @@ -45,13 +49,20 @@ public: }; Character(const std::string& name); + ~Character(); void draw(dc::scalar alpha); - dc::tilemap* texture; - dc::animation* anim; + dc::tilemap& getTilemap(); + dc::animation& getAnimation(); + +private: + dc::tilemap texture; + dc::animation anim; }; #endif // _CHARACTER_HH_ +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/Makefile.am b/src/Makefile.am index 40dd173..510dc9e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,28 +1,33 @@ -noinst_LIBRARIES = libdc.a +noinst_LTLIBRARIES = libdc.la -libdc_a_SOURCES = \ +libdc_la_SOURCES = \ ConvertUTF.c \ ConvertUTF.h \ + aabb.hh \ + animation.cc \ + animation.hh \ deserializer.cc \ deserializer.hh \ dispatcher.cc \ dispatcher.hh \ + drawable.hh \ engine.cc \ engine.hh \ + event.hh \ fastevents.c \ fastevents.h \ - math.cc \ + interpolator.hh \ math.hh \ - matrix.hh \ + mippleton.hh \ opengl.hh \ - quaternion.hh \ + profiler.hh \ random.cc \ random.hh \ - rectangle.cc \ - rectangle.hh \ resource.cc \ resource.hh \ + scene.cc \ + scene.hh \ serializable.cc \ serializable.hh \ serializer.cc \ @@ -35,27 +40,34 @@ libdc_a_SOURCES = \ texture.cc \ texture.hh \ thread.hh \ + tilemap.cc \ tilemap.hh \ timer.cc \ timer.hh \ - vector.hh \ video.cc \ video.hh \ $(ENDLIST) -libdc_a_CPPFLAGS = -I/usr/include/SDL -I$(top_srcdir)/yajl/src -Wall -#libdc_a_LDFLAGS = -lstdc++ -lSDL_image -lSDL_sound -libdc_a_LIBADD = $(top_srcdir)/yajl/libyajl.a +libdc_la_CPPFLAGS = -I/usr/include/SDL -I$(top_srcdir)/yajl/src +libdc_la_LIBADD = $(top_srcdir)/yajl/libyajl.la bin_PROGRAMS = yoink yoink_SOURCES = \ + Character.cc \ + Character.hh \ + TilemapFont.cc \ + TilemapFont.hh \ + Typesetter.cc \ + Typesetter.hh \ YoinkApp.cc \ YoinkApp.hh \ $(ENDLIST) -yoink_CPPFLAGS = -I/usr/include/SDL -Wall -#yoink_LDFLAGS = -lstdc++ -lSDL_image -lSDL_sound -yoink_LDADD = libdc.a libtinyxml.a ../yajl/libyajl.a +yoink_CPPFLAGS = -I/usr/include/SDL +yoink_LDADD = libdc.la + + +EXTRA_DIST = cml diff --git a/src/TilemapFont.cc b/src/TilemapFont.cc new file mode 100644 index 0000000..60f070c --- /dev/null +++ b/src/TilemapFont.cc @@ -0,0 +1,61 @@ + +/******************************************************************************* + + Copyright (c) 2009, Charles McGarvey + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include "TilemapFont.hh" +#include + + +TilemapFont::TilemapFont() : + dc::tilemap("Font") +{} + + +void TilemapFont::getTileCoords(char symbol, dc::scalar coords[8], + dc::tilemap::orientation what) +{ + unsigned index = 0; + + if (symbol >= ' ' && symbol <= '_') + { + index = symbol - 32; + } + else if (symbol >= 'a' && symbol <= '~') + { + index = symbol - 64; + } + else + { + index = 0; + } + + dc::tilemap::getTileCoords(index, coords, what); +} + + +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/TilemapFont.hh b/src/TilemapFont.hh new file mode 100644 index 0000000..5ec9064 --- /dev/null +++ b/src/TilemapFont.hh @@ -0,0 +1,59 @@ + +/******************************************************************************* + + Copyright (c) 2009, Charles McGarvey + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef _TILEMAPFONT_HH_ +#define _TILEMAPFONT_HH_ + +/** + * @file TilemapFont.hh + * Text on the screen. + */ + +#include "tilemap.hh" + + +class TilemapFont : public dc::tilemap +{ +public: + struct exception : public std::runtime_error + { + explicit exception(const std::string& what_arg) : + std::runtime_error(what_arg) {} + }; + + TilemapFont(); + + void getTileCoords(char symbol, dc::scalar coords[8], + dc::tilemap::orientation what = dc::tilemap::normal); +}; + + +#endif // _TILEMAPFONT_HH_ + +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/Typesetter.cc b/src/Typesetter.cc new file mode 100644 index 0000000..f658c26 --- /dev/null +++ b/src/Typesetter.cc @@ -0,0 +1,51 @@ + +/******************************************************************************* + + Copyright (c) 2009, Charles McGarvey + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include +#include +#include + +#include "Typesetter.hh" + + +void Typesetter::print(const std::string& format, ...) +{ + va_list args; + char buffer[4096]; + int nPrinted; + + va_start(args, format); + buffer[0] = '\0'; + nPrinted = vsnprintf(buffer, sizeof(buffer), format.c_str(), args); + va_end(args); + + nPrinted = std::min(nPrinted, (int)sizeof(buffer) - 1); +} + +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/Typesetter.hh b/src/Typesetter.hh new file mode 100644 index 0000000..d9ccf42 --- /dev/null +++ b/src/Typesetter.hh @@ -0,0 +1,56 @@ + +/******************************************************************************* + + Copyright (c) 2009, Charles McGarvey + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef _TYPESETTER_HH_ +#define _TYPESETTER_HH_ + +#include + +#include "math.hh" + + +class Typesetter +{ +public: + Typesetter(); + + void setLineSpacing(dc::scalar spacing); + + void print(const std::string& format, ...); + +private: + dc::scalar leftBound; + dc::scalar topBound; + dc::scalar lineSpacing; +}; + + +#endif // _TYPESETTER_HH_ + +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/YoinkApp.cc b/src/YoinkApp.cc index 64decfb..4b024b4 100644 --- a/src/YoinkApp.cc +++ b/src/YoinkApp.cc @@ -29,154 +29,298 @@ #include #include +#include // getenv + #include #include "opengl.hh" #include "video.hh" +#include "settings.hh" -#include "vector.hh" +#include "math.hh" #include "YoinkApp.hh" +#include "timer.hh" + +#if HAVE_CONFIG_H +#include "config.h" +#endif + + +static std::string configFiles() +{ + std::string files; + + char* configFile = getenv("YOINK_CONFIGFILE"); + + if (configFile) + { + // if a config file from the environment variable is specified, we want + // to load it first + files += configFile; + files += ":"; + } + + files += YOINK_CONFIGFILES; + + return files; +} + -YoinkApp::YoinkApp(int argc, char* argv[]) - : dc::engine("Yoink "VERSION, argc, argv, "yoinkrc") +YoinkApp::YoinkApp(int argc, char* argv[]) : + dc::engine(PACKAGE_STRING, argc, argv, configFiles()) { - std::cout << "Yoink "VERSION << std::endl + std::cout << PACKAGE_STRING << std::endl << "Compiled " << __TIME__ " " __DATE__ << std::endl - << "Send requests, patches, and bug reports to <" PACKAGE_BUGREPORT - << ">." << std::endl << std::endl; + << "Send requests, patches, and bug reports to <" + PACKAGE_BUGREPORT << ">." << std::endl << std::endl; + + dc::resource::addSearchPath(YOINK_DATADIR); + + dc::dispatcher::instance().addHandler("video.context_recreated", + boost::bind(&YoinkApp::contextRecreated, this, _1), this); + setupGL(); state = 0.0; - glEnable(GL_TEXTURE_2D); + someChar = new Character("RobotTrooper"); + someChar->getAnimation().startSequence("Run"); - heroineTexture = new dc::texture("Heroine.png"); + font = new TilemapFont; - glShadeModel(GL_SMOOTH); - //glEnable(GL_DEPTH_TEST); - - // Enable transparency: - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + dc::vector2 coeffs[4]; + coeffs[0] = dc::vector2(0.0, 0.0); + coeffs[1] = dc::vector2(0.5, 0.0); + coeffs[2] = dc::vector2(0.5, 0.0); + coeffs[3] = dc::vector2(1.0, 0.0); + interp.init(coeffs, 1.0, dc::interpolator::oscillate); - glLoadIdentity(); + dc::scalar coeff[2] = {1.0, 0.0}; + fadeIn.init(coeff, 0.5f); + testScene = new dc::scene("Test"); } YoinkApp::~YoinkApp() { - delete heroineTexture; + delete someChar; + delete font; + + dc::dispatcher::instance().removeHandler(this); + std::cout << "Goodbye..." << std::endl; } -void YoinkApp::update(double t, double dt) +void YoinkApp::setupGL() +{ + glEnable(GL_TEXTURE_2D); + //glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + + glShadeModel(GL_SMOOTH); + + //glEnable(GL_BLEND); + //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GREATER, 0.0); + + glClearColor(0.0, 0.0, 1.0, 1.0); + + glLineWidth(10.0f); +} + +void YoinkApp::contextRecreated(const dc::notification& note) +{ + // Whenever the context and a new one created, it probably won't contain our + // state so we need to set that up again. + setupGL(); +} + + +void YoinkApp::update(dc::scalar t, dc::scalar dt) { - //dt *= 0.1; + //dt *= 0.2; + + fadeIn.update(dt); + + someChar->getAnimation().update(t, dt); + interp.update(dt); prevstate = state; state += dt; } -void drawrect(dc::scalar a, dc::scalar b, dc::scalar c, dc::scalar d) + +void YoinkApp::draw(dc::scalar alpha) { + dc::vector4 meh; + meh.random(0.0, 1.0); + static dc::vector4 c1(meh); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + dc::scalar drawstate = cml::lerp(prevstate, state, alpha); + dc::scalar sinstate = std::sin(drawstate); + dc::scalar cosstate = std::cos(drawstate); + + + // DRAW THE SCENE + testScene->draw(alpha); + + + someChar->getTilemap().bind(); + glColor3f(1.0, 1.0, 1.0); + + unsigned heroFrame = someChar->getAnimation().getFrame(); + + float coords[8]; + someChar->getTilemap().getTileCoords(heroFrame, coords); + glBegin(GL_QUADS); - glTexCoord2f(1.0, 1.0); - glVertex3d(a, d, 0.0); - glTexCoord2f(1.0, 0.0); - glVertex3d(a, b, 0.0); - glTexCoord2f(0.0, 0.0); - glVertex3d(c, b, 0.0); - glTexCoord2f(0.0, 1.0); - glVertex3d(c, d, 0.0); + glTexCoord2f(coords[0], coords[1]); + glVertex3f(-1.0, 0.0, 0.0); + glTexCoord2f(coords[2], coords[3]); + glVertex3f(0.0, 0.0, 0.0); + glTexCoord2f(coords[4], coords[5]); + glVertex3f(0.0, 1.0, 0.0); + glTexCoord2f(coords[6], coords[7]); + glVertex3f(-1.0, 1.0, 0.0); glEnd(); -} -void YoinkApp::draw(double alpha) -{ - static dc::vector3 c1 = dc::vector3::random(0.0, 1.0); - static dc::vector3 c2 = dc::vector3::random(0.0, 1.0); - glClearColor(1.0, 0.0, 0.0, 1.0); - glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + someChar->getTilemap().getTileCoords(heroFrame, coords, + dc::tilemap::reverse); - double drawstate = state * alpha + prevstate * (1.0 - alpha); - double sinstate = std::sin(drawstate); - double cosstate = std::cos(drawstate); + glBegin(GL_QUADS); + glTexCoord2f(coords[0], coords[1]); + glVertex3f(0.0, 0.0, 0.0); + glTexCoord2f(coords[2], coords[3]); + glVertex3f(1.0, 0.0, 0.0); + glTexCoord2f(coords[4], coords[5]); + glVertex3f(1.0, 1.0, 0.0); + glTexCoord2f(coords[6], coords[7]); + glVertex3f(0.0, 1.0, 0.0); + glEnd(); + + glColor4f(1.0,0.0,0.0,0.5); glBindTexture(GL_TEXTURE_2D, 0); + glColor4fv(c1.data()); - glColor3dv(c1.array); - drawrect(-cosstate, -sinstate, sinstate, cosstate); - glColor3dv(c2.array); - drawrect(0.0, 0.0, sinstate, cosstate); + glRectd(-cosstate, -sinstate, sinstate, cosstate); + glRectf(0.0f, 0.0f, sinstate, cosstate); - glColor4f(1.0, 1.0, 1.0, 1.0); + font->bind(); + + font->getTileCoords('c', coords); - heroineTexture->bind(); + glBegin(GL_QUADS); + glTexCoord2f(coords[0], coords[1]); + glVertex3f(-1.0, 0.0, 0.0); + glTexCoord2f(coords[2], coords[3]); + glVertex3f(0.0, 0.0, 0.0); + glTexCoord2f(coords[4], coords[5]); + glVertex3f(0.0, 1.0, 0.0); + glTexCoord2f(coords[6], coords[7]); + glVertex3f(-1.0, 1.0, 0.0); + glEnd(); + + font->getTileCoords('h', coords); glBegin(GL_QUADS); - glTexCoord2f(0.0, 0.0); + glTexCoord2f(coords[0], coords[1]); glVertex3f(0.0, 0.0, 0.0); - glTexCoord2f(1.0/8.0, 0.0); + glTexCoord2f(coords[2], coords[3]); glVertex3f(1.0, 0.0, 0.0); - glTexCoord2f(1.0/8.0, 1.0/4.0); + glTexCoord2f(coords[4], coords[5]); glVertex3f(1.0, 1.0, 0.0); - glTexCoord2f(0.0, 1.0/4.0); + glTexCoord2f(coords[6], coords[7]); glVertex3f(0.0, 1.0, 0.0); glEnd(); + + font->getTileCoords('a', coords); + + glBegin(GL_QUADS); + glTexCoord2f(coords[0], coords[1]); + glVertex3f(-1.0, -1.0, 0.0); + glTexCoord2f(coords[2], coords[3]); + glVertex3f(0.0, -1.0, 0.0); + glTexCoord2f(coords[4], coords[5]); + glVertex3f(0.0, 0.0, 0.0); + glTexCoord2f(coords[6], coords[7]); + glVertex3f(-1.0, 0.0, 0.0); + glEnd(); + + font->getTileCoords('z', coords); + + glBegin(GL_QUADS); + glTexCoord2f(coords[0], coords[1]); + glVertex3f(0.0, -1.0, 0.0); + glTexCoord2f(coords[2], coords[3]); + glVertex3f(1.0, -1.0, 0.0); + glTexCoord2f(coords[4], coords[5]); + glVertex3f(1.0, 0.0, 0.0); + glTexCoord2f(coords[6], coords[7]); + glVertex3f(0.0, 0.0, 0.0); + glEnd(); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_DEPTH_TEST); - glFlush(); + glBindTexture(GL_TEXTURE_2D, 0); + glColor4f(0.0f, 0.0f, 0.0f, 1.0f); + + glBegin(GL_LINES); + glVertex2f(0.0f, 0.0f); + glVertex2fv(interp.getState(alpha).data()); + glEnd(); + + glColor4f(0.0f, 0.0f, 0.0f, fadeIn.getState(alpha)); + glRectf(-1.0f, -1.0f, 1.0f, 1.0f); + + glDisable(GL_BLEND); + glEnable(GL_DEPTH_TEST); } -void YoinkApp::dispatchEvent(const SDL_Event& event) +void YoinkApp::handleEvent(const dc::event& e) { - switch (event.type) + switch (e.type) { case SDL_KEYDOWN: - if (event.key.keysym.sym == SDLK_ESCAPE) + if (e.key.keysym.sym == SDLK_ESCAPE) { stop(); } - else if (event.key.keysym.sym == SDLK_f) + else if (e.key.keysym.sym == SDLK_f) { getVideo().toggleFull(); } + else if (e.key.keysym.sym == SDLK_a) + { + someChar->getAnimation().startSequence("Punch"); + } break; case SDL_QUIT: stop(); break; - } -} - -#include "dispatcher.hh" - -class Foo : public dc::notification -{ -public: - static void func(const dc::notification& meh) - { - std::cout << "func: " << std::endl; - } - - void snap(int zzz, const dc::notification& nice, float lean) - { - std::cout << "snap: " << zzz << "," << lean << std::endl; + case SDL_VIDEORESIZE: + glViewport(0, 0, e.resize.w, e.resize.h); + break; } -}; - -void MyHandler(const dc::notification& cool) -{ - std::cout << "MyHandler with a notification" << std::endl; } + int main(int argc, char* argv[]) { YoinkApp app(argc, argv); return app.run(); } +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/YoinkApp.hh b/src/YoinkApp.hh index 69b53d9..055a64c 100644 --- a/src/YoinkApp.hh +++ b/src/YoinkApp.hh @@ -29,12 +29,24 @@ #ifndef _YOINKAPP_HH_ #define _YOINKAPP_HH_ +/** + * @file YoinkApp.hh + * This is the big enchilada. + */ + #include #include +#include "dispatcher.hh" +#include "math.hh" +#include "interpolator.hh" #include "engine.hh" -#include "texture.hh" +#include "Character.hh" + +#include "TilemapFont.hh" + +#include "scene.hh" class YoinkApp : public dc::engine @@ -44,16 +56,33 @@ public: ~YoinkApp(); private: - void update(double t, double dt); - void draw(double alpha); - void dispatchEvent(const SDL_Event& event); + void update(dc::scalar t, dc::scalar dt); + void draw(dc::scalar alpha); + void handleEvent(const dc::event& e); + + /** + * Set OpenGL to a state we can know and depend on. + */ + void setupGL(); + void contextRecreated(const dc::notification& note); - dc::texture* heroineTexture; + //dc::animation* heroAnimation; + //dc::tilemap* heroineTexture; + Character* someChar; + //dc::binomial_interpolator interp; + dc::cerpv2 interp; + dc::lerps fadeIn; - double state; - double prevstate; + dc::scene* testScene; + + TilemapFont *font; + + dc::scalar state; + dc::scalar prevstate; }; #endif // _YOINKAPP_HH_ +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/aabb.hh b/src/aabb.hh new file mode 100644 index 0000000..e608b21 --- /dev/null +++ b/src/aabb.hh @@ -0,0 +1,65 @@ + +/****************************************************************************** + + Copyright (c) 2009, Charles McGarvey + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +******************************************************************************/ + +#ifndef _AABB_HH_ +#define _AABB_HH_ + +#include "math.hh" + + +namespace dc { + + +/** + * Axis-aligned Bounding Box + */ + +struct aabb +{ + aabb() {} + + aabb(const vector3& minPoint, const vector3& maxPoint) : + min(minPoint), + max(maxPoint) {} + + aabb (scalar minX, scalar minY, scalar minZ, + scalar maxX, scalar maxY, scalar maxZ) : + min(minX, minY, minZ), + max(maxX, maxY, maxZ) {} + + vector3 min; + vector3 max; +}; + + +} // namespace dc + +#endif // _AABB_HH_ + +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/animation.cc b/src/animation.cc index 745f0e4..c03a49d 100644 --- a/src/animation.cc +++ b/src/animation.cc @@ -26,25 +26,329 @@ *******************************************************************************/ +#include +#include + +#include "serializable.hh" +#include "mippleton.hh" #include "animation.hh" namespace dc { -class animation_impl +/** + * The collection of nested animation classes. The animation implementation + * consists of an animation_impl classes which is allocated and initialized with + * the interface object. This class contains the specific fields which are + * required to run a single instance of an animation. The sequence data is + * loaded in a difference class which can be shared amongst multiple animation + * implementation instances. + */ + +struct animation::animation_impl { -public: - class sequence + /** + * Contains "global" animation data for the various animations which get + * loaded. This is a mippleton, so it will be shared amongst any animation + * which wants to use these loaded sequences. + */ + + struct animation_data : public mippleton { + /** + * A frame of an animation sequence. A frame is merely an index which + * presumably represents a "slide" or tile which should be displayed, + * and the duration that is how long the slide will be shown. + */ + + struct frame + { + unsigned index; ///< Frame index. + scalar duration; ///< Frame duration. + + /** + * Construction is initialization. The frame data is loaded from a + * frame map which is probably loaded within an animation file. + */ + + frame(serializable_ptr root) : + index(0), + duration(1.0) + { + std::map rootObj; + + if (root->get(rootObj)) + { + std::map::iterator i; + for (i = rootObj.begin(); i != rootObj.end(); i++) + { + std::string key = (*i).first; + if (key == "index") + { + long value = 0; + (*i).second->get(value); + index = unsigned(value); + } + else if (key == "duration") + { + double value = 0.0; + (*i).second->getNumber(value); + duration = scalar(value); + } + } + } + } + }; + + + /** + * A sequence is just a few attributes and a list of frames in the order + * that they should be played. + */ + + struct sequence + { + std::vector frames; ///< List of frames. + scalar delay; ///< Scale frame durations. + bool loop; ///< Does the sequence repeat? + std::string next; ///< Next sequence name. + + /** + * Construction is initialization. The constructor loads sequence + * data from the sequence map, presumably loaded from an animation + * file. The rest of the loading takes place in the frame's + * constructor which loads each individual frame. + */ + + sequence(serializable_ptr root) : + delay(0.0), + loop(true) + { + std::map rootObj; + + if (root->get(rootObj)) + { + std::map::iterator i; + for (i = rootObj.begin(); i != rootObj.end(); i++) + { + std::string key = (*i).first; + + if (key == "frames") + { + std::vector framesObj; + + if ((*i).second->get(framesObj)) + { + std::vector::iterator j; + + for (j = framesObj.begin(); + j != framesObj.end(); j++) + { + if (*j) + { + frames.push_back(frame(*j)); + } + } + } + } + else if (key == "delay") + { + double value; + (*i).second->getNumber(value); + delay = scalar(value); + } + else if (key == "loop") + { + (*i).second->get(loop); + } + else if (key == "next") + { + (*i).second->get(next); + } + } + } + } + }; + + + /** + * Starts loading a file with animation data. Such a file is formatted + * as a map of named sequences. The sequence constructor loads each + * individual sequence. + */ + + void loadFromFile() + { + std::string filePath = animation::getPathToResource(getName()); + + deserializer in(filePath); + + serializable_ptr root = in.deserialize(); + + if (root) + { + std::map rootObj; + + if (root->get(rootObj)) + { + std::map::iterator i; + + for (i = rootObj.begin(); i != rootObj.end(); i++) + { + sequences.insert(std::pair((*i).first, + sequence((*i).second))); + } + } + } + } + + /** + * Construction is initialization. The animation class data container + * registers itself as a mippleton and then loads the animation data. + */ + + explicit animation_data(const std::string& name) : + mippleton(name) + { + loadFromFile(); + } + + std::map sequences; ///< List of sequences. }; - std::map sequences; + + /** + * Construction is intialization. + */ + + animation_impl(const std::string& name) : + data(animation_data::retain(name), &animation_data::release), + currentSequence(0), + frameCounter(0), + frameIndex(0), + timeAccum(0), + frameDuration(0) {} + + + /** + * Sets up the animation classes to "play" a named sequence. If another + * sequence was active, it will be replaced as the current sequence. Future + * updates will progress the new sequence. + */ + + void startSequence(const std::string& sequenceName) + { + std::map::iterator i; + + i = data->sequences.find(sequenceName); + + if (i != data->sequences.end()) + { + currentSequence = &(*i).second; + frameCounter = 0; + frameIndex = currentSequence->frames[0].index; + timeAccum = 0.0; + frameDuration = currentSequence->delay * + currentSequence->frames[0].duration; + } + } + + /** + * Updates or progresses the animation sequence. If the time interval + * surpasses the duration of the current frame, a new frame becomes the + * current frame. If the last frame of a sequence expires, the active + * sequence will switch automatically to the designated "next" sequence, or + * if none is specified but the sequence is set to loop, the first frame of + * the sequence will become the current frame, and the animation essentially + * starts over again. + */ + + void update(scalar t, scalar dt) + { + if (currentSequence) + { + timeAccum += dt; + + if (timeAccum >= frameDuration) + { + if (++frameCounter >= currentSequence->frames.size()) + { + if (!currentSequence->next.empty()) + { + startSequence(currentSequence->next); + } + else if (currentSequence->loop) + { + frameCounter = 0; + } + else + { + frameCounter--; + currentSequence = 0; + } + } + + frameIndex = currentSequence->frames[frameCounter].index; + timeAccum = frameDuration - timeAccum; + frameDuration = currentSequence->delay * + currentSequence->frames[frameCounter].duration; + } + } + } + + boost::shared_ptr data; ///< Internal data. + + animation_data::sequence* currentSequence; ///< Active sequence. + unsigned frameCounter; ///< Current frame. + unsigned frameIndex; ///< Index of current frame. + scalar timeAccum; ///< Time accumulation. + scalar frameDuration; ///< Scaled frame duration. }; +animation::animation(const std::string& name) : + // pass through + impl(new animation::animation_impl(name)) {} + + +void animation::startSequence(const std::string& sequenceName) +{ + // pass through + impl->startSequence(sequenceName); +} + +void animation::update(scalar t, scalar dt) +{ + // pass through + impl->update(t, dt); +} + + +/** + * Gets the index for the current frame. This is presumably called by some + * drawing code which will draw the correct current frame. + */ + +unsigned animation::getFrame() const +{ + return impl->frameIndex; +} + + +/** + * Specialized search location for animation files. They can be found in the + * "animations" subdirectory of any of the searched directories. + */ + +std::string animation::getPathToResource(const std::string& name) +{ + return resource::getPathToResource("animations/" + name + ".json"); +} } // namespace dc +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/animation.hh b/src/animation.hh index 85307ac..ca56581 100644 --- a/src/animation.hh +++ b/src/animation.hh @@ -34,26 +34,39 @@ * Motion picture!! */ +#include + #include +#include "resource.hh" +#include "math.hh" + namespace dc { -class animation_impl; +/** + * A class to manage frame-based animation. Animation sequences can be loaded + * from file, then named sequences are started. The animation is updated + * periodically (each update cycle), and the correct current frame is + * determined. This class is generic enough that a frame can mean just about + * anything to whatever drawing context is used to render the frame. + */ class animation : public resource { public: animation(const std::string& name); - void setSequence(const std::string& sequence); - bool isSequenceDone(); + void startSequence(const std::string& sequenceName); + + void update(scalar t, scalar dt); + unsigned getFrame() const; - void update(scalar dt); - unsigned getFrame(); + static std::string getPathToResource(const std::string& name); private: + class animation_impl; boost::shared_ptr impl; }; @@ -62,3 +75,5 @@ private: #endif // _ANIMATION_HH_ +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/camera.hh b/src/camera.hh new file mode 100644 index 0000000..dcdc55d --- /dev/null +++ b/src/camera.hh @@ -0,0 +1,48 @@ + +/******************************************************************************* + + Copyright (c) 2009, Charles McGarvey + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef _CAMERA_HH_ +#define _CAMERA_HH_ + + +namespace dc { + + +class camera +{ +public: +private: +}; + + +} // namespace dc + +#endif // _CAMERA_HH_ + +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/rectangle.cc b/src/cullable.hh similarity index 55% rename from src/rectangle.cc rename to src/cullable.hh index 0f9bb9f..e4fe4ca 100644 --- a/src/rectangle.cc +++ b/src/cullable.hh @@ -26,59 +26,29 @@ *******************************************************************************/ -#include +#ifndef _CULLABLE_HH_ +#define _CULLABLE_HH_ -#include "rectangle.hh" +#include "camera.hh" namespace dc { -bool rectangle::containsRect(const rectangle& r) const -{ - point o = r.origin; - point s = r.size; - if (origin.x <= o.x && origin.y <= o.y) - { - scalar a = origin.x + size.x; - scalar b = origin.y + size.y; - scalar c = o.x + s.x; - scalar d = o.y + s.y; - return o.x <= a && o.y <= b && origin.x <= c && - origin.y <= d && c <= a && d <= b; - } - return false; -} +/** + * Interface for anything that can be culled given a camera's frustrum. + */ -bool rectangle::intersectsRect(const rectangle& r) const +class cullable { - // TODO - Perhaps this could be optimized if it proves to be a bottleneck. - rectangle rect = intersectionWith(r); - return rect.isValid(); -} +public: + virtual bool isVisible(const camera& cam) = 0; +}; -rectangle rectangle::unionWith(const rectangle& r) const -{ - point o = r.origin; - point s = r.size; - scalar a = std::min(origin.x, o.x); - scalar b = std::min(origin.y, o.y); - return rectangle(point(a, b), - point(std::max(origin.x + size.x, o.x + s.x) - a, - std::max(origin.y + size.y, o.y + s.y) - b)); -} -rectangle rectangle::intersectionWith(const rectangle& r) const -{ - point o = r.origin; - point s = r.size; - scalar a = std::max(origin.x, o.x); - scalar b = std::max(origin.y, o.y); - return rectangle(point(a, b), - point(std::min(origin.x + size.x, o.x + s.x) - a, - std::min(origin.y + size.y, o.y + s.y) - b)); -} +} // namespace dc +#endif // _CULLABLE_HH_ -} // namespace dc +/** vim: set ts=4 sw=4 tw=80: *************************************************/ diff --git a/src/deserializer.cc b/src/deserializer.cc index 4c3f8f2..8ad3059 100644 --- a/src/deserializer.cc +++ b/src/deserializer.cc @@ -38,7 +38,7 @@ namespace dc { -class deserializer_impl +class deserializer::deserializer_impl { public: deserializer_impl(const std::string& filePath, bool comments = false, @@ -72,9 +72,9 @@ public: void throwError() { unsigned char* errorMsg = yajl_get_error(hand, 0, 0, 0); - deserializer::exception error((char*)errorMsg); + deserializer::exception problem((char*)errorMsg); yajl_free_error(hand, errorMsg); - throw error; + throw problem; } @@ -114,6 +114,7 @@ public: static int parsedBeginMap(void* ctx) { ((deserializer_impl*)ctx)->parsed.push(new wrapped_dictionary); + return 1; } static int parsedMapKey(void* ctx, const unsigned char* value, @@ -205,10 +206,13 @@ private: deserializer::deserializer(const std::string& filePath, bool comments, - bool check) : impl(new deserializer_impl(filePath, comments, check)) {} + bool check) : + // pass through + impl(new deserializer::deserializer_impl(filePath, comments, check)) {} deserializer::deserializer(std::istream& input, bool comments, bool check) : - impl(new deserializer_impl(input, comments, check)) {} + // pass through + impl(new deserializer::deserializer_impl(input, comments, check)) {} serializable_ptr deserializer::deserialize() @@ -235,9 +239,12 @@ serializable* deserializer::pullNext() void deserializer::pop() { + // pass through impl->parsed.pop(); } } // namespace dc +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/deserializer.hh b/src/deserializer.hh index 733ce39..f2b0bcc 100644 --- a/src/deserializer.hh +++ b/src/deserializer.hh @@ -44,23 +44,72 @@ namespace dc { -class serializable; +class serializable; // forward declaration typedef boost::shared_ptr serializable_ptr; -class deserializer_impl; - class deserializer { public: + + /** + * Construction is initialization. A deserializer can be constructed with + * either an input stream or a string representing a filename that will be + * read from. If a stream is provided, it will not be closed after parsing, + * but the parser may read past the end of usable bytes, so you should not + * use a deserializer on a stream that you expect to continue to use after + * the deserialization. + * @param comments If true, C and C++-style comments will be allowed and + * ignored by the parser. + * @param check If true, UTF-8 strings will be checked for validity and an + * exception thrown if such a problem exists. Otherwise strings will not be + * checked. + */ + deserializer(const std::string& filePath, bool comments = false, bool check = false); deserializer(std::istream& input, bool comments = false, bool check = false); + + /** + * Parse the object from of the stream. The stream is considered to be + * dominated by the parser and may read and discard bytes past the end of + * the actual parsed object. Only one object can be deserialized by the + * deserializer. + */ + serializable_ptr deserialize(); + /** + * Used by serializable objects to parse themselves. These methods should + * generally not be used directory for deserialization. This one returns + * the next object in the queue which has been parsed. This method may + * block if more data is pending and an object has not bee constructed yet. + * The caller takes ownership of the object which has been allocated with + * the new operator and must therefore be sure to delete the object as + * appropriated. Null (0) will be returned by this method to signify one of + * three things: 1) the end of an array, 2) the end of a map/dictionary, or + * 3) there is nothing more to be obtained. Container objects will be empty + * and will have to be filled with their contained elements by repeatedly + * calling this method until a null is returned. This method will continue + * to return the same value until pop() is called which will cause this + * method to return the next object as expected. + */ + serializable* pullNext(); + + /** + * If the object returned by pullNext() has been received successfully and + * the caller is ready for the next object, this method should be called to + * take that object off of the queue. + */ + void pop(); + + /** + * This exception is thrown upon deserialization errors. + */ + struct exception : std::runtime_error { explicit exception(const std::string& what_arg) : @@ -68,6 +117,7 @@ public: }; private: + class deserializer_impl; boost::shared_ptr impl; }; @@ -77,3 +127,5 @@ private: #endif // _DESERIALIZER_HH_ +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/dispatcher.cc b/src/dispatcher.cc index 509b69d..d42077a 100644 --- a/src/dispatcher.cc +++ b/src/dispatcher.cc @@ -37,7 +37,7 @@ namespace dc { notification::~notification() {} -class dispatcher_impl +class dispatcher::dispatcher_impl { public: dispatcher_impl() : id(1) {} @@ -62,9 +62,11 @@ public: }; -dispatcher::dispatcher() : impl(new dispatcher_impl) {} +dispatcher::dispatcher() : impl(new dispatcher::dispatcher_impl) {} +// TODO these methods are ugly + dispatcher::handler dispatcher::addHandler(const std::string& message, const function& callback) { @@ -74,8 +76,8 @@ dispatcher::handler dispatcher::addHandler(const std::string& message, dispatcher::handler dispatcher::addHandler(const std::string& message, const function& callback, handler id) { - std::pair - callbackPair(message, dispatcher_impl::callback_t(id, callback)); + std::pair + callbackPair(message, dispatcher::dispatcher_impl::callback_t(id, callback)); std::pair handlerPair(id, message); @@ -88,16 +90,16 @@ dispatcher::handler dispatcher::addHandler(const std::string& message, void dispatcher::removeHandler(handler id) { - std::pair + std::pair handlers(impl->handlers.equal_range(id)); - dispatcher_impl::handler_it_t i; + dispatcher::dispatcher_impl::handler_it_t i; for (i = handlers.first; i != handlers.second; i++) { - dispatcher_impl::callback_it_t it = impl->callbacks.find((*i).second); - dispatcher_impl::callback_it_t last = impl->callbacks.end(); + dispatcher::dispatcher_impl::callback_it_t it = impl->callbacks.find((*i).second); + dispatcher::dispatcher_impl::callback_it_t last = impl->callbacks.end(); - dispatcher_impl::callback_it_t j; + dispatcher::dispatcher_impl::callback_it_t j; for (j = it; j != last; j++) { if (((*j).second).first == id) @@ -119,10 +121,10 @@ void dispatcher::dispatch(const std::string& message) void dispatcher::dispatch(const std::string& message, const notification& param) { - std::pair + std::pair callbacks(impl->callbacks.equal_range(message)); - dispatcher_impl::callback_it_t i; + dispatcher::dispatcher_impl::callback_it_t i; for (i = callbacks.first; i != callbacks.second; i++) { function callback = ((*i).second).second; @@ -133,3 +135,5 @@ void dispatcher::dispatch(const std::string& message, const notification& param) } // namespace dc +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/dispatcher.hh b/src/dispatcher.hh index e45e88e..1a7744a 100644 --- a/src/dispatcher.hh +++ b/src/dispatcher.hh @@ -29,11 +29,6 @@ #ifndef _DISPATCHER_HH_ #define _DISPATCHER_HH_ -/** - * @file dispatcher.hh - * Dispatching of information. - */ - #include #include @@ -45,7 +40,10 @@ namespace dc { -// Subclass this to create more specific notes to dispatch. +/** + * Interface for a notification class. + */ + class notification { public: @@ -53,7 +51,9 @@ public: }; -class dispatcher_impl; +/** + * Dispatcher of notifications to interested parties. + */ class dispatcher : public singleton { @@ -74,6 +74,7 @@ public: void dispatch(const std::string& message, const notification& param); private: + class dispatcher_impl; boost::shared_ptr impl; }; @@ -82,3 +83,5 @@ private: #endif // _DISPATCHER_HH_ +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/drawable.hh b/src/drawable.hh index 835fb61..031cf79 100644 --- a/src/drawable.hh +++ b/src/drawable.hh @@ -29,15 +29,16 @@ #ifndef _DRAWABLE_HH_ #define _DRAWABLE_HH_ -/** - * @file drawable.hh - * Interface for a drawable object. - */ +#include "math.hh" namespace dc { +/** + * Interface for anything that can be drawn. + */ + class drawable { public: @@ -49,3 +50,5 @@ public: #endif // _DRAWABLE_HH_ +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/engine.cc b/src/engine.cc index 3e40361..ec6faa1 100644 --- a/src/engine.cc +++ b/src/engine.cc @@ -46,12 +46,13 @@ namespace dc { -class engine_impl +class engine::engine_impl { public: engine_impl(const std::string& name, int argc, char* argv[], - const std::string& configFile, engine* outer) : config(argc, argv), - interface(outer) + const std::string& configFile, engine* outer) : + config(argc, argv), + interface(outer) { if (SDL_Init(SDL_INIT_EVERYTHING | SDL_INIT_EVENTTHREAD) != 0) { @@ -69,8 +70,9 @@ public: screen = video_ptr(new video(name)); screen->makeActive(); - timestep = 0.01; - config.get("engine.timestep", timestep); + double ts = 0.01; + config.get("engine.timestep", ts); + timestep = scalar(ts); long maxfps = 40; config.get("engine.maxfps", maxfps); @@ -99,10 +101,10 @@ public: scalar nextFPSUpdate = ticksNow + 1.0; scalar totalTime = 0.0; - scalar accumulator = 0.0; + scalar accumulator = timestep; - fps = 0.0; - int frameAccum = 0.0; + fps = 0; + int frameAccum = 0; running = true; do @@ -113,7 +115,7 @@ public: accumulator += newTicks - ticksNow; ticksNow = newTicks; - if (ticksNow >= nextStep) + if (accumulator >= timestep) { interface->update(totalTime, timestep); @@ -121,20 +123,28 @@ public: accumulator -= timestep; nextStep += timestep; - if (ticksNow >= nextStep) nextStep = ticksNow + timestep; + if (ticksNow >= nextStep) + { + // we missed some scheduled steps, so reset the schedule + nextStep = ticksNow + timestep; + accumulator = 0.0; + } } if (ticksNow >= nextDraw) { frameAccum++; - if (ticksNow >= nextFPSUpdate) + if (ticksNow >= nextFPSUpdate) // determine the actual fps { - fps = frameAccum;// + (ticksNow - nextFPSUpdate) / 1.0; + fps = frameAccum; frameAccum = 0; nextFPSUpdate += 1.0; - if (ticksNow >= nextFPSUpdate) nextFPSUpdate = ticksNow + 1.0; + if (ticksNow >= nextFPSUpdate) + { + nextFPSUpdate = ticksNow + 1.0; + } if (printfps) { @@ -146,25 +156,32 @@ public: screen->swap(); nextDraw += drawrate; - if (ticksNow >= nextDraw) nextDraw = ticksNow + drawrate; + if (ticksNow >= nextDraw) + { + // we missed some scheduled draws, so reset the schedule + nextDraw = ticksNow + drawrate; + } } + // be a good citizen and give back what you don't need sleep(std::min(nextStep, nextDraw), true); } while (running); + + return 0; } void dispatchEvents() { - SDL_Event event; + SDL_Event e; - while (FE_PollEvent(&event) == 1) + while (FE_PollEvent(&e) == 1) { - switch (event.type) + switch (e.type) { case SDL_KEYDOWN: - if (event.key.keysym.sym == SDLK_ESCAPE && + if (e.key.keysym.sym == SDLK_ESCAPE && (SDL_GetModState() & KMOD_CTRL) ) { exit(0); @@ -172,11 +189,11 @@ public: break; case SDL_VIDEORESIZE: - screen->resize(event.resize.w, event.resize.h); + screen->resize(e.resize.w, e.resize.h); break; } - interface->dispatchEvent(event); + interface->handleEvent(e); } } @@ -196,16 +213,17 @@ public: engine* interface; }; + engine::engine(const std::string& name, int argc, char* argv[], - const std::string& configFile) - : impl(new engine_impl(name, argc, argv, configFile, this)) {} + const std::string& configFile) : + impl(new engine::engine_impl(name, argc, argv, configFile, this)) {} engine::~engine() {} int engine::run() { - impl->run(); + return impl->run(); } void engine::stop() @@ -248,8 +266,10 @@ long engine::getFPS() void engine::update(scalar t, scalar dt) {} void engine::draw(scalar alpha) {} -void engine::dispatchEvent(const SDL_Event& event) {} +void engine::handleEvent(const SDL_Event& e) {} } // namespace dc +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/engine.hh b/src/engine.hh index bc3bdaf..98141cb 100644 --- a/src/engine.hh +++ b/src/engine.hh @@ -30,16 +30,15 @@ #define _ENGINE_HH_ #include -#include #include "singleton.hh" +#include "event.hh" #include "dispatcher.hh" namespace dc { -class engine_impl; class video; class engine : public singleton @@ -63,9 +62,10 @@ public: // Override these if you want. virtual void update(scalar t, scalar dt); virtual void draw(scalar alpha); - virtual void dispatchEvent(const SDL_Event& event); + virtual void handleEvent(const event& e); private: + class engine_impl; boost::shared_ptr impl; }; @@ -74,3 +74,5 @@ private: #endif // _ENGINE_HH_ +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/event.hh b/src/event.hh index 84a073e..8ca219a 100644 --- a/src/event.hh +++ b/src/event.hh @@ -28,125 +28,25 @@ #ifndef _EVENT_HH_ #define _EVENT_HH_ - -#include "bz/date.h" -#include "bz/object.h" - - -namespace bz { +#include -class event -{ -public: - typedef enum - { - left_click_down = 1<<1, - left_click_up = 1<<2, - right_click_down = 1<<3, - right_click_up = 1<<4, - other_click_down = 1<<5, - other_click_up = 1<<6, - mouse_moved = 1<<7, - mouse_entered = 1<<8, - mouse_exited = 1<<9, - key_down = 1<<10, - key_up = 1<<11, - activated = 1<<12, - iconified = 1<<13, - deactivated = 1<<14, - - file_new = 1<<20, - file_open = 1<<21, - file_revert = 1<<22, - file_save = 1<<23, - file_save_as = 1<<24, - edit_undo = 1<<25, - edit_redo = 1<<26, - edit_copy = 1<<27, - edit_cut = 1<<28, - edit_paste = 1<<29, - edit_select_all = 1<<30, - app_quit = 1<<31, - any = 0xffffffffU - } type; - - // This constructor is for keyboard events: - event( type theType, // What happened? - unsigned char keycode, // The ASCII value. - int modifiers, // Ctrl, Shift, Opt, etc... - bool isRepeat ) : // Is the key held down? - type_(theType), keycode_(keycode), modifiers_(modifiers), - isRepeat_(isRepeat) - { - timestamp_ = date(); - id_ = getIdentifier(); - } - - // This constructor is for mouse events: - event( type theType, // What happened? - vec2d location, // Where? (window coordinates) - vec2d delta, // How far has it moved? - int nClick, // How many consecutive clicks? - float pressure ) : // How hard was it pushed? - type_(theType), location_(location), delta_(delta), nClick_(nClick), - pressure_(pressure) - { - timestamp_ = date(); - id_ = getIdentifier(); - } - // This constructor is for other event types: - event( type theType ) : type_(theType) // What happened? - { - timestamp_ = date(); - id_ = getIdentifier(); - } +namespace dc { - // Accessors for all event types: - type kind() const { return type_; } - const date& timestamp() const { return timestamp_; } - unsigned int identifier() const { return id_; } - void *userInfo() const { return userInfo_; } - void setUserInfo( void* userInfo ) { userInfo_ = userInfo; } - unsigned int tag() const { return tag_; } - void setTag( unsigned int tag ) { tag_ = tag; } +// The event handling in SDL is so big that it would take more time than it's +// worth to add an object-oriented abstraction layer that would completely cover +// what SDL has already layed down. Fortunately, SDL event structures are easy +// to work with, and it is not the purpose of this library to completely hide +// its dependencies and provide full functionality. - // Accessors for keyboard events: - unsigned char keycode() const { return keycode_; } - int modifiers() const { return modifiers_; } - bool isRepeat() const { return isRepeat_; } +typedef SDL_Event event; - // Accessors for mouse events: - const vec2d& location() const { return location_; } - const vec2d& delta() const { return delta_; } - int clicks() const { return nClick_; } - float pressure() const { return pressure_; } -private: - unsigned int getIdentifier() { - static unsigned int identifier = 1; - return identifier++; - } - - type type_; - date timestamp_; - unsigned int id_; - void *userInfo_; - unsigned int tag_; - - unsigned char keycode_; - unsigned char modifiers_; - bool isRepeat_; - - vec2d location_; - vec2d delta_; - int nClick_; - float pressure_; -}; - } // namespace dc #endif // _EVENT_HH_ +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/interpolator.hh b/src/interpolator.hh new file mode 100644 index 0000000..74708d6 --- /dev/null +++ b/src/interpolator.hh @@ -0,0 +1,267 @@ + +/******************************************************************************* + + Copyright (c) 2009, Charles McGarvey + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef _INTERPOLATOR_HH_ +#define _INTERPOLATOR_HH_ + + +namespace dc { + + +class interpolator +{ + void clamp(scalar& value) + { + if (value > 1.0) + { + switch (theMode) + { + case stop: + value = 1.0; + stopped = true; + break; + case repeat: + value -= 1.0; + break; + case oscillate: + value = 2.0 - value; + scale *= -1.0; + break; + } + } + else if (value < 0.0) + { + switch (theMode) + { + case stop: + value = 0.0; + stopped = true; + break; + case repeat: + value += 1.0; + break; + case oscillate: + value = -value; + scale *= -1.0; + break; + } + } + } + +public: + typedef enum + { + stop = 0, + repeat = 1, + oscillate = 2 + } mode; + + void init(scalar seconds = 1.0, mode onFinish = stop) + { + scale = 1.0 / seconds; + alpha = 0.0; + setMode(onFinish); + } + + + void setMode(mode onFinish) + { + theMode = onFinish; + stopped = false; + } + + + void update(scalar dt) + { + if (!stopped) + { + alpha += dt * scale; + clamp(alpha); + calculate(alpha); + } + } + + virtual void calculate(scalar alpha) = 0; + +private: + mode theMode; + scalar alpha; + scalar scale; + bool stopped; +}; + +template +class interpolator_base : public interpolator +{ +public: + void init(scalar seconds = 1.0, mode onFinish = stop) + { + interpolator::init(seconds, onFinish); + + calculate(0.0); // set value + calculate(0.0); // set previous + } + + void calculate(scalar alpha) + { + previous = value; + calculate(value, alpha); + } + + virtual void calculate(T& value, scalar alpha) = 0; + + const T& getValue() + { + return value; + } + + const T getState(scalar alpha) + { + return cml::lerp(previous, value, alpha); + } + +private: + T value; + T previous; +}; + + +template +class binomial_interpolator : public interpolator_base +{ +public: + binomial_interpolator() {} + + explicit binomial_interpolator(const T coeff[D+1], scalar seconds = 1.0, + interpolator::mode onFinish = interpolator::stop) + { + init(coeff, seconds, onFinish); + } + + void init(const T coeff[D+1], scalar seconds = 1.0, + interpolator::mode onFinish = interpolator::stop) + { + scalar fac[D+1]; + + fac[0] = 1.0; + fac[1] = 1.0; + + // build an array of the computed factorials we will need + for (int i = 2; i <= D; i++) + { + fac[i] = i * fac[i - 1]; + } + + // combine the coefficients for fast updating + for (int i = 0; i <= D; i++) + { + // n! / (k! * (n - k)!) + coefficient[i] = coeff[i] * fac[D] / (fac[i] * fac[D - i]); + } + + interpolator_base::init(seconds, onFinish); + } + + + void calculate(T& value, scalar alpha) + { + scalar beta = 1.0 - alpha; + + value = coefficient[0] * std::pow(beta, D); + + for (int i = 1; i <= D; i++) + { + value += coefficient[i] * std::pow(beta, D - i) * std::pow(alpha, i); + } + } + +private: + + T coefficient[D+1]; +}; + + +template +class binomial_interpolator : public interpolator_base +{ +public: + binomial_interpolator() {} + + explicit binomial_interpolator(const T coeff[2], scalar seconds = 1.0, + interpolator::mode onFinish = interpolator::stop) + //interpolator_base(seconds, onFinish) + { + init(coeff, seconds, onFinish); + } + + void init(const T coeff[2], scalar seconds = 1.0, + interpolator::mode onFinish = interpolator::stop) + { + coefficient[0] = coeff[0]; + coefficient[1] = coeff[1]; + + interpolator_base::init(seconds, onFinish); + } + + + void calculate(T& value, scalar alpha) + { + value = cml::lerp(coefficient[0], coefficient[1], alpha); + } + +private: + T coefficient[2]; +}; + + +// Here are some aliases for more common interpolators. Also see the +// interpolation functions in cml for other types of interpolation such as +// slerp and some multi-alpha interpolators. + +typedef binomial_interpolator lerps; // linear +typedef binomial_interpolator lerpv2; +typedef binomial_interpolator lerpv3; +typedef binomial_interpolator lerpv4; + +typedef binomial_interpolator qerps; // quadratic +typedef binomial_interpolator qerpv2; +typedef binomial_interpolator qerpv3; +typedef binomial_interpolator qerpv4; + +typedef binomial_interpolator cerps; // cubic +typedef binomial_interpolator cerpv2; +typedef binomial_interpolator cerpv3; +typedef binomial_interpolator cerpv4; + + +} // namespace dc + +#endif // _INTERPOLATOR_HH_ + +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/math.hh b/src/math.hh index 313ecc1..ab80dcc 100644 --- a/src/math.hh +++ b/src/math.hh @@ -37,29 +37,29 @@ #include #include +#include -namespace dc { +namespace dc { -typedef double scalar; ///< Scalar variable. -typedef cml::vector2d vector2; -typedef cml::vector3d vector3; -typedef cml::vector4d vector4; +// Basic types. -typedef cml::matrix33d_c matrix3; -typedef cml::matrix44d_c matrix4; +typedef float scalar; ///< Scalar type. -typedef cml::quaterniond_p quaternion; +typedef cml::vector2f vector2; +typedef cml::vector3f vector3; +typedef cml::vector4f vector4; -typedef cml::vector4f color; +typedef cml::matrix33f_c matrix3; +typedef cml::matrix44f_c matrix4; +typedef cml::quaternionf_p quaternion; -// Here's a simple way to check the equality of floating-point variables more -// reliably using approximation. +typedef vector4 color; -const scalar default_epsilon = 0.00001; ///< @see equals() +const scalar default_epsilon = 0.00001; /** * Check the equality of scalars with a certain degree of error allowed. @@ -75,3 +75,5 @@ inline bool equals(scalar a, scalar b, scalar epsilon = default_epsilon) #endif // _MATH_HH_ +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/mippleton.hh b/src/mippleton.hh new file mode 100644 index 0000000..16985a3 --- /dev/null +++ b/src/mippleton.hh @@ -0,0 +1,109 @@ + +/******************************************************************************* + + Copyright (c) 2009, Charles McGarvey + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef _MIPPLETON_HH_ +#define _MIPPLETON_HH_ + +/** + * @file mippleton.hh + * Related to singletons, a mippleton is an object which can be obtained + * globally using a unique name. Unlike singletons, there can be multiple + * mippletons per class, each with a different name or identifier. Mippletons + * are create automatically when they are first requested (retained) and deleted + * after the last interested code releases its hold on the object. + */ + +#include +#include + + +namespace dc { + + +template +class mippleton +{ + typedef std::pair ptr_value_t; + typedef std::pair ptr_map_pair_t; + typedef std::map ptr_map_t; + + static ptr_map_t ptrs_; + std::string name_; + +public: + explicit mippleton(const std::string& name) : name_(name) {} + + inline const std::string& getName() const + { + return name_; + } + + inline static T* retain(const std::string& name) + { + typename ptr_map_t::iterator it; + + if ((it = ptrs_.find(name)) != ptrs_.end()) + { + (*it).second.first++; + return (*it).second.second; + } + else + { + T* newObj = new T(name); + ptrs_.insert(ptr_map_pair_t(name, ptr_value_t(1, newObj))); + return newObj; + } + } + + inline static void releaseByName(const std::string& name) + { + typename ptr_map_t::iterator it; + + if ((it = ptrs_.find(name)) != ptrs_.end() && -(*it).second.first == 0) + { + delete (*it).second.second; + ptrs_.erase(it); + } + } + + inline static void release(T* obj) + { + releaseByName(obj->getName()); + } +}; + +template +std::map > mippleton::ptrs_; + + +} // namespace dc + +#endif // _MIPPLETON_HH_ + +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/opengl.hh b/src/opengl.hh index e04fe5c..287918d 100644 --- a/src/opengl.hh +++ b/src/opengl.hh @@ -41,3 +41,5 @@ #endif // _GL_HH_ +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/profiler.hh b/src/profiler.hh index d1a8bb0..7b38e52 100644 --- a/src/profiler.hh +++ b/src/profiler.hh @@ -79,3 +79,5 @@ private: #endif // _PROFILER_HH_ +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/random.cc b/src/random.cc index 22bbd4e..6cd25cf 100644 --- a/src/random.cc +++ b/src/random.cc @@ -113,3 +113,5 @@ double get() }; // namespace rng +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/random.hh b/src/random.hh index 5a34229..ac308c8 100644 --- a/src/random.hh +++ b/src/random.hh @@ -124,3 +124,5 @@ double get(); #endif // _RNG_RANDOM_HH_ +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/rectangle.hh b/src/rectangle.hh deleted file mode 100644 index 1594d62..0000000 --- a/src/rectangle.hh +++ /dev/null @@ -1,124 +0,0 @@ - -/******************************************************************************* - - Copyright (c) 2009, Charles McGarvey - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*******************************************************************************/ - -#ifndef _RECTANGLE_HH_ -#define _RECTANGLE_HH_ - -#include "math.hh" -#include "vector.hh" - - -namespace dc { - -// -// A rectangle is a 2d shape defined by point (origin) and size (width & height) -// vectors. The usual rectangle maths are available. Valid rectangles have -// positive width and height. Invalid rectangles will be returned for invalid -// operations such as trying to get the intersection of two rectangles which -// don't intersect. Using an invalid rectangle is undefined, but it may be used -// after "fixing" it using the fix method which will cause the size to be -// positive and adjust the origin to be the bottom-left point. Check the -// validity of a rectangle using the isValid method especially if the rectangle -// is a result of an operation which could fail. -// - -class rectangle -{ -public: - // Constructors. - rectangle() {} - rectangle(point o, point s) { - origin = o; - size = s; - } - - // Rectangle validity. - bool isValid() const { return size.x >= 0.0 && size.y >= 0.0; } - void fix() - { - if (size.x <= 0.0) - { - size.x = 0.0 - size.x; - origin.x -= size.x; - } - if (size.y <= 0.0) - { - size.y = 0.0 - size.y; - origin.y -= size.y; - } - } - - // Rectangle operations. - scalar area() const { return size.x * size.y; } - scalar perimeter() const { - return size.x + size.x + size.y + size.y; - } - - bool containsPoint(point pt) const - { - return origin.x <= pt.x && origin.y <= pt.y && - pt.x <= origin.x + size.x && pt.y <= origin.y + size.y; - } - - void inset(scalar h, scalar v) - { - origin.x += h; - origin.y += v; - size.x -= h + h; - size.y -= v + v; - } - void offset(scalar h, scalar v) - { - origin.x -= h; - origin.y -= v; - size.x += h + h; - size.y += v + v; - } - - bool containsRect(const rectangle& r) const; - bool intersectsRect(const rectangle& r) const; - rectangle unionWith(const rectangle& r) const; - rectangle intersectionWith(const rectangle& r) const; - - // Checking equality. - bool operator == (const rectangle& r) const { - return origin == r.origin && size == r.size; - } - bool operator != (const rectangle& r) const { - return !(*this == r); - } - - // Data. - point origin, size; -}; - -} // namespace dc - - -#endif // _RECTANGLE_HH_ - diff --git a/src/resource.cc b/src/resource.cc index 758827c..16b5f21 100644 --- a/src/resource.cc +++ b/src/resource.cc @@ -37,26 +37,12 @@ namespace dc { std::vector resource::searchPaths_; -resource::resource(const std::string& name) throw(exception) -{ - filePath_ = getPathToResource(name); - - if (!filePath_.empty()) - { - throw exception("cannot find resource file " + name); - } -} - resource::~resource() {} -const std::string& resource::getPathToFile() -{ - return filePath_; -} - void resource::addSearchPath(const std::string& directory) { + // add a slash if there isn't one already if (directory[directory.length() - 1] != '/') { searchPaths_.push_back(directory + '/'); @@ -73,16 +59,22 @@ std::string resource::getPathToResource(const std::string& name) for (i = searchPaths_.begin(); i != searchPaths_.end(); i++) { - const char* fullPath = ((*i) + name).c_str(); - if (access(fullPath, R_OK) == 0) + std::string fullPath(*i); + fullPath += name; + + // TODO access(2) is not all that portable + if (access(fullPath.c_str(), R_OK) == 0) { - return std::string(fullPath); + return fullPath; } } + // empty string return std::string(); } } // namespace dc +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/resource.hh b/src/resource.hh index eff9e3e..c5020f6 100644 --- a/src/resource.hh +++ b/src/resource.hh @@ -55,16 +55,8 @@ public: std::runtime_error(what_arg) {} }; - resource(const std::string& name) throw(exception); virtual ~resource(); - /** - * Get the path of the file associated with this resource. - * @return Path. - */ - - const std::string& getPathToFile(); - /** * Add a directory to search when looking for resource files. @@ -83,7 +75,6 @@ public: static std::string getPathToResource(const std::string& name); private: - std::string filePath_; static std::vector searchPaths_; }; @@ -92,3 +83,5 @@ private: #endif // _RESOURCE_HH_ +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/scene.cc b/src/scene.cc new file mode 100644 index 0000000..7dd102b --- /dev/null +++ b/src/scene.cc @@ -0,0 +1,138 @@ + +/******************************************************************************* + + Copyright (c) 2009, Charles McGarvey + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include +#include + +#include "mippleton.hh" +#include "deserializer.hh" +#include "serializable.hh" +#include "aabb.hh" + +#include "scene.hh" + + +namespace dc { + + +class scene::scene_impl : public mippleton +{ + static bool loadBox(aabb& theBox, serializable_ptr obj) + { + std::vector numbers; + + if (obj->get(numbers)) + { + if (numbers.size() == 6) + { + double num; + + if (numbers[0]->getNumber(num)) + { + + } + } + } + + return false; + } + +public: + + scene_impl(const std::string& name) : + mippleton(name) + { + loadFromFile(); + } + + + void loadFromFile() + { + std::string filePath = scene::getPathToResource(getName()); + + deserializer in(filePath, true); + + serializable_ptr root = in.deserialize(); + + if (root) + { + std::map rootObj; + + if (root->get(rootObj)) + { + std::map::iterator it; + + if ((it = rootObj.find("playfield_bounds")) != rootObj.end()) + { + loadBox(playfieldBounds, (*it).second); + } + if ((it = rootObj.find("maximum_bounds")) != rootObj.end()) + { + loadBox(maximumBounds, (*it).second); + } + + //for (i = rootObj.begin(); i != rootObj.end(); i++) + //{ + //sequences.insert(std::pair((*i).first, + //sequence((*i).second))); + //} + } + } + } + + aabb playfieldBounds; + aabb maximumBounds; + +}; + + +scene::scene(const std::string& name) : + // pass through + impl(scene::scene_impl::retain(name), &scene::scene_impl::release) {} + + +void scene::draw(scalar alpha) +{ +} + + +/** + * Specialized search location for scene files. They can be found in the + * "scenes" subdirectory of any of the searched directories. + */ + +std::string scene::getPathToResource(const std::string& name) +{ + return resource::getPathToResource("scenes/" + name + ".json"); +} + + +} // namespace dc + +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/scene.hh b/src/scene.hh new file mode 100644 index 0000000..2938db8 --- /dev/null +++ b/src/scene.hh @@ -0,0 +1,62 @@ + +/******************************************************************************* + + Copyright (c) 2009, Charles McGarvey + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef _SCENE_HH_ +#define _SCENE_HH_ + +#include +#include + +#include "resource.hh" +#include "drawable.hh" + + +namespace dc { + + +class scene : public resource, public drawable +{ +public: + scene(const std::string& name); + + void draw(scalar alpha); + + static std::string getPathToResource(const std::string& name); + +private: + class scene_impl; + boost::shared_ptr impl; +}; + + +} // namespace dc + +#endif // _SCENE_HH_ + +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/serializable.cc b/src/serializable.cc index 11e8d26..1da0613 100644 --- a/src/serializable.cc +++ b/src/serializable.cc @@ -72,11 +72,51 @@ bool serializable::get(std::map& value) return false; } + bool serializable::isNull() { return false; } +bool serializable::getNumber(long& value) +{ + if (get(value)) + { + return true; + } + else + { + double dValue; + if (get(dValue)) + { + value = long(dValue); + return true; + } + } + return false; +} + +bool serializable::getNumber(double& value) +{ + if (get(value)) + { + return true; + } + else + { + long lValue; + if (get(lValue)) + { + value = double(lValue); + return true; + } + } + return false; +} + + } // namespace dc +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/serializable.hh b/src/serializable.hh index 5b8b403..967b213 100644 --- a/src/serializable.hh +++ b/src/serializable.hh @@ -34,9 +34,9 @@ #include #include +#include "stringtools.hh" #include "serializer.hh" #include "deserializer.hh" -#include "stringtools.hh" namespace dc { @@ -59,6 +59,15 @@ public: virtual bool get(std::wstring& value); virtual bool get(std::vector& value); virtual bool get(std::map& value); + + /* + * To get a number value which may have been parsed as either an integer or + * double, use these instead. + */ + + bool getNumber(long&); + bool getNumber(double&); + virtual bool isNull(); }; @@ -75,7 +84,6 @@ public: void print() const; bool get(T& value); - public: T variable; }; @@ -240,3 +248,5 @@ inline bool null::isNull() #endif // _SERIALIZABLE_HH_ +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/serializer.cc b/src/serializer.cc index 06563ef..7b7596d 100644 --- a/src/serializer.cc +++ b/src/serializer.cc @@ -37,7 +37,7 @@ namespace dc { -class serializer_impl +class serializer::serializer_impl { public: serializer_impl(const std::string& filePath, const std::string& indent = "") @@ -72,6 +72,8 @@ public: throw serializer::exception("maximum archive depth exceeded"); case yajl_gen_in_error_state: throw serializer::exception("serializer already in error state"); + case yajl_gen_status_ok: + ; // There is no error here. Move along... } } @@ -105,10 +107,12 @@ private: serializer::serializer(const std::string& filePath, const std::string& indent) : - impl(new serializer_impl(filePath, indent)) {} + // pass through + impl(new serializer::serializer_impl(filePath, indent)) {} serializer::serializer(std::ostream& output, const std::string& indent) : - impl(new serializer_impl(output, indent)) {} + // pass through + impl(new serializer::serializer_impl(output, indent)) {} serializer::~serializer() { @@ -119,26 +123,30 @@ serializer::~serializer() void serializer::push(long value) { yajl_gen_status stat = yajl_gen_integer(impl->gen, value); - if (stat != yajl_gen_status_ok) serializer_impl::throwError(stat); + if (stat != yajl_gen_status_ok) + serializer::serializer_impl::throwError(stat); } void serializer::push(double value) { yajl_gen_status stat = yajl_gen_double(impl->gen, value); - if (stat != yajl_gen_status_ok) serializer_impl::throwError(stat); + if (stat != yajl_gen_status_ok) + serializer::serializer_impl::throwError(stat); } void serializer::push(bool value) { yajl_gen_status stat = yajl_gen_bool(impl->gen, value); - if (stat != yajl_gen_status_ok) serializer_impl::throwError(stat); + if (stat != yajl_gen_status_ok) + serializer::serializer_impl::throwError(stat); } void serializer::push(const std::string& value) { yajl_gen_status stat = yajl_gen_string(impl->gen, (const unsigned char*)value.c_str(), value.length()); - if (stat != yajl_gen_status_ok) serializer_impl::throwError(stat); + if (stat != yajl_gen_status_ok) + serializer::serializer_impl::throwError(stat); } void serializer::push(const std::wstring& value) @@ -149,32 +157,37 @@ void serializer::push(const std::wstring& value) void serializer::pushNull() { yajl_gen_status stat = yajl_gen_null(impl->gen); - if (stat != yajl_gen_status_ok) serializer_impl::throwError(stat); + if (stat != yajl_gen_status_ok) + serializer::serializer_impl::throwError(stat); } void serializer::pushMapHead() { yajl_gen_status stat = yajl_gen_map_open(impl->gen); - if (stat != yajl_gen_status_ok) serializer_impl::throwError(stat); + if (stat != yajl_gen_status_ok) + serializer::serializer_impl::throwError(stat); } void serializer::pushMapTail() { yajl_gen_status stat = yajl_gen_map_close(impl->gen); - if (stat != yajl_gen_status_ok) serializer_impl::throwError(stat); + if (stat != yajl_gen_status_ok) + serializer::serializer_impl::throwError(stat); } void serializer::pushArrayHead() { yajl_gen_status stat = yajl_gen_array_open(impl->gen); - if (stat != yajl_gen_status_ok) serializer_impl::throwError(stat); + if (stat != yajl_gen_status_ok) + serializer::serializer_impl::throwError(stat); } void serializer::pushArrayTail() { yajl_gen_status stat = yajl_gen_array_close(impl->gen); - if (stat != yajl_gen_status_ok) serializer_impl::throwError(stat); + if (stat != yajl_gen_status_ok) + serializer::serializer_impl::throwError(stat); } @@ -191,3 +204,5 @@ void serializer::flush() } // namespace dc +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/serializer.hh b/src/serializer.hh index 8e61a62..206a793 100644 --- a/src/serializer.hh +++ b/src/serializer.hh @@ -44,16 +44,28 @@ namespace dc { -class serializer_impl; - class serializer { public: + + /** + * Construction is initialization. Use either an output stream or a string + * representing a path to a fill to which the serialized data will be + * written (replacing any previous file). + * @param indent If non-empty, the string's characters will be used as + * indentation. Otherwise, the serialized data will not be formatted neatly + * but will be tightly packed. + */ + serializer(const std::string& filePath, const std::string& indent = ""); serializer(std::ostream& output, const std::string& indent = ""); ~serializer(); + /** + * Push various types of data onto the stream. + */ + void push(long value); void push(double value); void push(bool value); @@ -61,14 +73,32 @@ public: void push(const std::wstring& value); void pushNull(); + /** + * Push a map onto the stream. Each map head must be matched by a map tail. + */ + void pushMapHead(); void pushMapTail(); + /** + * Push an array onto the stream. Each array head must be matched by an + * array tail. + */ + void pushArrayHead(); void pushArrayTail(); + /** + * Write any pending bytes to the stream. This is called automatically by + * the destructor of this class. + */ + void flush(); + /** + * This exception is thrown for serializer-related exceptional errors. + */ + struct exception : std::runtime_error { explicit exception(const std::string& what_arg) : @@ -76,6 +106,7 @@ public: }; private: + class serializer_impl; boost::shared_ptr impl; }; @@ -84,3 +115,5 @@ private: #endif // _SERIALIZER_HH_ +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/settings.cc b/src/settings.cc index 07ec0e5..74ab384 100644 --- a/src/settings.cc +++ b/src/settings.cc @@ -27,7 +27,10 @@ *******************************************************************************/ #include -#include +#include // getenv +#include // strchr + +#include #include "settings.hh" @@ -64,37 +67,69 @@ void settings::parseArgs(int argc, char* argv[]) } catch (std::exception e) { + // it doesn't deserialize to anything we know, so just store it + // as a string map[key] = serializable_ptr(new wrapped_string(stringValue)); } } } } -void settings::loadFromFile(std::string filePath) + +void settings::loadFromFile(const std::string& filePath, bool precedence) { - deserializer in(filePath, true); + std::vector paths; + boost::split(paths, filePath, boost::is_any_of(":")); - try + loadFromFiles(paths, precedence); +} + +void settings::loadFromFiles(const std::vector& filePaths, + bool precedence) +{ + std::vector::const_iterator it; + + char* home = getenv("HOME"); + + for (it = filePaths.begin(); it != filePaths.end(); it++) { - serializable_ptr obj = in.deserialize(); - std::map dict; - if (obj && obj->get(dict)) + std::string path = *it; + + if (home) { - map.insert(dict.begin(), dict.end()); + boost::replace_first(path, "$HOME", home); } - else + + deserializer in(*it, true); + + std::cout << "Looking for a config file at " << path << std::endl; + try { - std::cerr << "The settings file " << filePath << - " does not contain any valid settings." << std::endl; + serializable_ptr obj = in.deserialize(); + std::map dict; + if (obj && obj->get(dict)) + { + if (!precedence) + { + map.insert(dict.begin(), dict.end()); + } + else + { + dict.insert(map.begin(), map.end()); + map = dict; + } + } + } + catch (deserializer::exception e) + { + std::cerr << "Cannot load settings from " << *it << + " because an exception was thrown: " << e.what() << std::endl; } - } - catch (deserializer::exception e) - { - std::cerr << "Cannot load settings from " << filePath << - " because an exception was thrown: " << e.what() << std::endl; } } } // namepsace dc +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/settings.hh b/src/settings.hh index 5cb0972..9c2f2d8 100644 --- a/src/settings.hh +++ b/src/settings.hh @@ -51,7 +51,10 @@ public: settings(int argc, char* argv[]); void parseArgs(int argc, char* argv[]); - void loadFromFile(std::string filePath); + + void loadFromFile(const std::string& filePath, bool precedence = false); + void loadFromFiles(const std::vector& filePaths, + bool precedence = false); template bool get(const std::string& key, T& value); @@ -82,3 +85,5 @@ bool settings::get(const std::string& key, T& value) #endif // _SETTINGS_HH_ +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/singleton.hh b/src/singleton.hh index 3b2ebf7..ec0d01e 100644 --- a/src/singleton.hh +++ b/src/singleton.hh @@ -32,12 +32,21 @@ #include +namespace dc { + + template class singleton { static T* ptr_; public: + struct exception : public std::runtime_error + { + explicit exception(const std::string& what_arg) : + std::runtime_error(what_arg) {} + }; + singleton() { if (!ptr_) @@ -60,12 +69,12 @@ public: { if (!ptr_) { - throw std::runtime_error("accessing uninstantiated singleton"); + throw exception("accessing uninstantiated singleton"); } return *ptr_; } - static T* instance__ptr() + static T* instance_ptr() { return ptr_; } @@ -74,5 +83,9 @@ public: template T* singleton::ptr_ = 0; +} // namespace dc + #endif // _SINGLETON_HH_ +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/stringtools.cc b/src/stringtools.cc index 8954f9b..91d2a6c 100644 --- a/src/stringtools.cc +++ b/src/stringtools.cc @@ -151,3 +151,5 @@ std::string wideToMulti(const std::wstring& wideStr) } // namespace dc +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/stringtools.hh b/src/stringtools.hh index 9bf4577..bd79eab 100644 --- a/src/stringtools.hh +++ b/src/stringtools.hh @@ -42,3 +42,5 @@ std::string wideToMulti(const std::wstring& wideStr); #endif // _STRINGTOOLS_HH_ +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/texture.cc b/src/texture.cc index 2f8f97a..6d3e912 100644 --- a/src/texture.cc +++ b/src/texture.cc @@ -33,6 +33,8 @@ #include #include +#include "mippleton.hh" + #include "dispatcher.hh" #include "opengl.hh" @@ -42,43 +44,47 @@ namespace dc { -class texture_impl +/** + * The texture implementation just contains all the information about the image + * which is worth having in memory. The image data itself is not worth keeping + * in memory if the texture has been loaded to GL, but the name of the resource + * is retained so that it can be reloaded if necessary. The implementation is a + * mippleton so that multiple texture objects can share the same internal + * objects and avoid having duplicate textures loaded to GL. + */ + +class texture::texture_impl : public mippleton { + + /** + * Delete the texture (if it is loaded) from GL. + */ + void unloadFromGL() { - if (object) + if (object_) { - glDeleteTextures(1, &object); - object = 0; + glDeleteTextures(1, &object_); + object_ = 0; } } + /** + * If the GL context was recreated, we probably need to reload the texture. + * This may involve reading it from disk again, but hopefully the OS was + * smart enough to cache it if the client has plenty of RAM. + */ + void contextRecreated(const notification& note) { unloadFromGL(); uploadToGL(); } -public: - texture_impl(texture* outside, bool keepInMemory) - : interface(outside), keepData(keepInMemory), object(0), imageData(0) - { - dispatcher::instance().addHandler("video.context_recreated", - boost::bind(&texture_impl::contextRecreated, this, _1), - this); - } - - ~texture_impl() - { - dispatcher::instance().removeHandler(this); - - if (imageData) - { - SDL_FreeSurface(imageData); - } - unloadFromGL(); - } - + /** + * This is a helper method used by some of the texture loading code. It + * returns the first power of two which is greater than the input value. + */ static int powerOfTwo(int input) { @@ -91,17 +97,55 @@ public: return value; } +public: + + /** + * Construction is initialization. + */ + + explicit texture_impl(const std::string& name) : + mippleton(name), + width_(0), + height_(0), + mode_(0), + minFilter_(GL_NEAREST), + maxFilter_(GL_NEAREST), + wrapU_(GL_CLAMP), + wrapV_(GL_CLAMP), + object_(0) + { + uploadToGL(); + + // we want to know when the GL context is recreated + dispatcher::instance().addHandler("video.context_recreated", + boost::bind(&texture_impl::contextRecreated, this, _1), this); + } + + ~texture_impl() + { + unloadFromGL(); + + dispatcher::instance().removeHandler(this); + } + + + /** + * Adapted from some public domain code. This stuff is common enough that + * it really should be included in SDL_image... We need this because images + * loaded with SDL_image aren't exactly GL-ready right out of the box. This + * method makes them ready. + */ + static SDL_Surface* prepareImageForGL(SDL_Surface* surface) { - // Adapted from some public domain code. This stuff is common enough - // that it really should be included in SDL_image... We need this - // because images loaded with SDL_image aren't exactly OpenGL-ready - // right out of the box. - int w = powerOfTwo(surface->w); int h = powerOfTwo(surface->h); // 1. OpenGL images must (generally) have dimensions of a power-of-two. + // If this one doesn't, we can at least be more friendly by expanding + // the dimensions so that they are, though there will be some empty + // space within the range of normal texture coordinates. It's better of + // textures are the right size to begin with. SDL_Surface* image = SDL_CreateRGBSurface ( @@ -145,7 +189,8 @@ public: SDL_SetAlpha(surface, savedFlags, savedAlpha); } - // 2. OpenGL textures make more sense when they are "upside down." + // 2. OpenGL textures make more sense within the coordinate system when + // they are "upside down," so let's flip it. Uint8 line[image->pitch]; @@ -168,138 +213,192 @@ public: return image; } + /** + * Use SDL_image to load images from file. A surface with the image data is + * returned. + * @return Image data. + */ - void loadImageData() + SDL_Surface* loadImageData() { SDL_Surface* surface; - surface = IMG_Load(interface->getPathToFile().c_str()); + surface = IMG_Load(texture::getPathToResource(getName()).c_str()); if (!surface) { throw texture::exception("loading failed"); } - imageData = prepareImageForGL(surface); + SDL_Surface* temp = prepareImageForGL(surface); SDL_FreeSurface(surface); - if (!imageData) + if (!temp) { - throw texture::exception(""); + throw texture::exception("image couldn't be prepared for GL"); } - if (imageData->format->BytesPerPixel == 3) + if (temp->format->BytesPerPixel == 3) { - mode = GL_RGB; + mode_ = GL_RGB; } - else if (imageData->format->BytesPerPixel == 4) + else if (temp->format->BytesPerPixel == 4) { - mode = GL_RGBA; + mode_ = GL_RGBA; } else { - SDL_FreeSurface(imageData); + SDL_FreeSurface(temp); throw texture::exception("image is not the required 24 or 32 bpp"); } - width = imageData->w; - height = imageData->h; + width_ = temp->w; + height_ = temp->h; + + return temp; } + /** + * Upload the image to GL so that it will be accessible by a much more + * manageable handle and hopefully reside in video memory. + */ + void uploadToGL() { - if (object) + if (object_) { // Already loaded. return; } - if (!imageData) - { - loadImageData(); - } + SDL_Surface* imageData = loadImageData(); - glGenTextures(1, &object); - - glBindTexture(GL_TEXTURE_2D, object); + glGenTextures(1, &object_); + glBindTexture(GL_TEXTURE_2D, object_); glTexImage2D ( GL_TEXTURE_2D, 0, - mode, + mode_, imageData->w, imageData->h, 0, - mode, + mode_, GL_UNSIGNED_BYTE, imageData->pixels ); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + setProperties(); - if (!keepData) - { - SDL_FreeSurface(imageData); - imageData = 0; - } + SDL_FreeSurface(imageData); } - unsigned width; - unsigned height; - int mode; - GLuint object; + /** + * Sets some texture properties such as the filters and external coordinate + * behavior. + */ + + void setProperties() + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter_); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, maxFilter_); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapU_); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapV_); + } + - bool keepData; - SDL_Surface* imageData; + unsigned width_; ///< Horizontal dimension of the image. + unsigned height_; ///< Vertical dimension. - texture* interface; + GLuint mode_; ///< Depth of the image, GL_RGB or GL_RGBA. + GLuint minFilter_; ///< Filter. + GLuint maxFilter_; ///< Filter. + GLuint wrapU_; ///< Wrapping behavior horizontally. + GLuint wrapV_; ///< Wrapping behavior vertically. + GLuint object_; ///< GL texture handle. }; -texture::texture(const std::string& name, bool keepInMemory) - : resource(name), impl(new texture_impl(this, keepInMemory)) {} +texture::texture(const std::string& name) : + // pass through + impl(texture::texture_impl::retain(name), &texture::texture_impl::release) +{} + +/** + * Bind the GL texture for mapping, etc. + */ void texture::bind() { glBindTexture(GL_TEXTURE_2D, getObject()); } + +/** + * Get the texture object, for the curious. + */ + GLuint texture::getObject() { - if (!impl->object) - { - impl->uploadToGL(); - } - - return impl->object; + // pass through + return impl->object_; } unsigned texture::getWidth() { - if (!impl->object) - { - impl->uploadToGL(); - } - - return impl->width; + // pass through + return impl->width_; } unsigned texture::getHeight() { - if (!impl->object) - { - impl->uploadToGL(); - } + // pass through + return impl->height_; +} + - return impl->height; +void texture::setMinFilter(GLuint filter) +{ + impl->minFilter_ = filter; +} + +void texture::setMaxFilter(GLuint filter) +{ + impl->maxFilter_ = filter; +} + +void texture::setWrapU(GLuint wrap) +{ + impl->wrapU_ = wrap; +} + +void texture::setWrapV(GLuint wrap) +{ + impl->wrapV_ = wrap; +} + + +void texture::applyChanges() +{ + bind(); + impl->setProperties(); +} + + +std::string texture::getPathToResource(const std::string& name) +{ + // TODO since this is a generic library class, more than PNG should be + // supported + return resource::getPathToResource("textures/" + name + ".png"); } } // namespace dc +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/texture.hh b/src/texture.hh index 1be4c5a..f92ad23 100644 --- a/src/texture.hh +++ b/src/texture.hh @@ -38,19 +38,17 @@ #include -#include "resource.hh" #include "opengl.hh" +#include "resource.hh" namespace dc { -class texture_impl; - class texture : public resource { public: - texture(const std::string& name, bool keepInMemory = false); + texture(const std::string& name); void bind(); GLuint getObject(); @@ -58,6 +56,15 @@ public: unsigned getWidth(); unsigned getHeight(); + void setMinFilter(GLuint filter); + void setMaxFilter(GLuint filter); + void setWrapU(GLuint wrap); + void setWrapV(GLuint wrap); + + void applyChanges(); + + static std::string getPathToResource(const std::string& name); + struct exception : std::runtime_error { explicit exception(const std::string& what_arg) : @@ -65,6 +72,7 @@ public: }; private: + class texture_impl; boost::shared_ptr impl; }; @@ -73,3 +81,5 @@ private: #endif // _TEXTURE_HH_ +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/thread.hh b/src/thread.hh index 990f9b0..443decd 100644 --- a/src/thread.hh +++ b/src/thread.hh @@ -213,3 +213,5 @@ private: #endif // _THREAD_HH_ +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/tilemap.cc b/src/tilemap.cc new file mode 100644 index 0000000..0852f98 --- /dev/null +++ b/src/tilemap.cc @@ -0,0 +1,204 @@ + +/******************************************************************************* + + Copyright (c) 2009, Charles McGarvey + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#include + +#include "mippleton.hh" +#include "serializable.hh" +#include "deserializer.hh" + +#include "opengl.hh" + +#include "tilemap.hh" + + +namespace dc { + + +class tilemap::tilemap_impl : public mippleton +{ +public: + tilemap_impl(const std::string& name) : + mippleton(name), + tilesU_(1), + tilesV_(1), + minFilter_(GL_NEAREST), + maxFilter_(GL_NEAREST), + wrapU_(GL_CLAMP), + wrapV_(GL_CLAMP) + { + loadFromFile(); + } + + void loadFromFile() + { + deserializer in(tilemap::getPathToResource(getName())); + + serializable_ptr root = in.deserialize(); + + if (root) + { + std::map rootMap; + + if (root->get(rootMap)) + { + std::map::iterator it; + + if ((it = rootMap.find("TilesU")) != rootMap.end()) + { + long value; + if ((*it).second->get(value)) + { + tilesU_ = unsigned(value); + } + } + if ((it = rootMap.find("TilesV")) != rootMap.end()) + { + long value; + if ((*it).second->get(value)) + { + tilesV_ = unsigned(value); + } + } + if ((it = rootMap.find("MinFilter")) != rootMap.end()) + { + std::string value; + if ((*it).second->get(value)) + { + if (value == "Linear") + { + minFilter_ = GL_LINEAR; + } + } + } + if ((it = rootMap.find("MaxFilter")) != rootMap.end()) + { + std::string value; + if ((*it).second->get(value)) + { + if (value == "Linear") + { + maxFilter_ = GL_LINEAR; + } + } + } + if ((it = rootMap.find("WrapU")) != rootMap.end()) + { + std::string value; + if ((*it).second->get(value)) + { + if (value == "Repeat") + { + wrapU_ = GL_REPEAT; + } + } + } + if ((it = rootMap.find("WrapV")) != rootMap.end()) + { + std::string value; + if ((*it).second->get(value)) + { + if (value == "Repeat") + { + wrapV_ = GL_REPEAT; + } + } + } + } + } + } + + unsigned tilesU_; + unsigned tilesV_; + GLuint minFilter_; + GLuint maxFilter_; + GLuint wrapU_; + GLuint wrapV_; +}; + + +tilemap::tilemap(const std::string& name) : + texture(name), + impl(tilemap::tilemap_impl::retain(name), &tilemap::tilemap_impl::release) +{ + setMinFilter(impl->minFilter_); + setMaxFilter(impl->maxFilter_); + setWrapU(impl->wrapU_); + setWrapV(impl->wrapV_); + applyChanges(); +} + + +void tilemap::getTileCoords(unsigned index, scalar coords[8]) +{ + assert(index < impl->tilesU_ * impl->tilesV_); + + scalar w = 1.0 / scalar(impl->tilesU_); + scalar h = 1.0 / scalar(impl->tilesV_); + + coords[0] = scalar(index % impl->tilesU_) * w; + coords[1] = (scalar(impl->tilesV_ - 1) - scalar(index / impl->tilesU_)) * h; + coords[2] = coords[0] + w; + coords[3] = coords[1]; + coords[4] = coords[2]; + coords[5] = coords[1] + h; + coords[6] = coords[0]; + coords[7] = coords[5]; +} + +void tilemap::getTileCoords(unsigned index, scalar coords[8], orientation what) +{ + getTileCoords(index, coords); + + if (what & flip) + { + coords[1] = coords[5]; + coords[5] = coords[3]; + coords[3] = coords[7]; + coords[7] = coords[5]; + } + if (what & reverse) + { + coords[0] = coords[2]; + coords[2] = coords[6]; + coords[4] = coords[6]; + coords[6] = coords[0]; + } +} + + +std::string tilemap::getPathToResource(const std::string& name) +{ + return resource::getPathToResource("tilemaps/" + name + ".json"); +} + + +} // namespace dc + +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/tilemap.hh b/src/tilemap.hh index 50e5c3d..f2f76ab 100644 --- a/src/tilemap.hh +++ b/src/tilemap.hh @@ -34,34 +34,15 @@ * Small subclass to give some basic tile-mapping functionality to textures. */ -#include - #include -#include "opengl.hh" #include "texture.hh" +#include "math.hh" namespace dc { -namespace tile { - -/** - * Possible orientations for texture coordinates. - */ - -typedef enum -{ - normal = 0, ///< Normal orientation. - flip = 1, ///< Flip over a horizontal axis. - reverse = 2, ///< Flip over a vertical axis. - flip_and_reverse = 3 ///< Flip over both. -} orientation; - -} // namespace tile - - /** * A tilemap is a texture which is meant to be divided into smaller sprites. * This class provides all the functionality of a texture and adds some methods @@ -72,52 +53,34 @@ typedef enum class tilemap : public texture { public: - tilemap(const std::string& filePath, bool keepInMemory = false, - unsigned tilesU = 1, unsigned tilesV = 1) - : texture(filePath, keepInMemory), tilesU_(tilesU), tilesV_(tilesV) {} - - /** - * Set the number of rows and columns of square tiles. - * @param tilesU Columns of tiles. - * @param tilesV Rows of tiles. + * Possible orientations for texture coordinates. */ - void setTileDimensions(unsigned tilesU, unsigned tilesV) + typedef enum { - assert(tilesU != 0 && tilesV != 0); - tilesU_ = tilesU; - tilesV_ = tilesV; - } + normal = 0, ///< Normal orientation. + flip = 1, ///< Flip over a horizontal axis. + reverse = 2, ///< Flip over a vertical axis. + flip_and_reverse = 3 ///< Flip over both. + } orientation; + + tilemap(const std::string& name); /** * Calculate texture coordinates for a tile at a certain index. Tiles are * indexed start with zero as the to-left tile and moving across, then down. * @param index The tile index. - * @param coords An array of floats where the texture coordinates will be + * @param coords An array of scalars where the texture coordinates will be * stored after this call. The first coordinate (u,v) will be in the first * two places and so on until all four coordinates are stored, therefore - * requiring enough room for an array of eight floats. The winding of the + * requiring enough room for an array of eight scalars. The winding of the * coordinates is always counter-clockwise (the GL default). */ - void getTileCoords(unsigned index, float coords[8]) - { - assert(index < tilesU_ * tilesV_); - - float w = 1.0 / float(tilesU_); - float h = 1.0 / float(tilesV_); + void getTileCoords(unsigned index, scalar coords[8]); - coords[0] = float(index % tilesU_) * w; - coords[1] = (float(tilesV_ - 1) - float(index / tilesU_)) * h; - coords[2] = coords[0] + w; - coords[3] = coords[1]; - coords[4] = coords[2]; - coords[5] = coords[1] + h; - coords[6] = coords[0]; - coords[7] = coords[5]; - } /** * This version let's you specify an orientation that will be reflected in @@ -126,29 +89,14 @@ public: * @param what The orientation; can be flip, reverse, or flip_and_reverse. */ - void getTileCoords(unsigned index, float coords[8], tile::orientation what) - { - getTileCoords(index, coords); - - if (what & tile::flip) - { - coords[1] = coords[5]; - coords[5] = coords[3]; - coords[3] = coords[7]; - coords[7] = coords[5]; - } - if (what & tile::reverse) - { - coords[0] = coords[2]; - coords[2] = coords[6]; - coords[4] = coords[6]; - coords[6] = coords[0]; - } - } + void getTileCoords(unsigned index, scalar coords[8], orientation what); + + + static std::string getPathToResource(const std::string& name); private: - unsigned tilesU_; - unsigned tilesV_; + class tilemap_impl; + boost::shared_ptr impl; }; @@ -156,3 +104,5 @@ private: #endif // _TILEMAP_HH_ +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/timer.cc b/src/timer.cc index 2c7a1cb..de601ee 100644 --- a/src/timer.cc +++ b/src/timer.cc @@ -30,8 +30,6 @@ #include #include -#include - #include "timer.hh" @@ -40,44 +38,59 @@ namespace dc { #if HAVE_LIBRT -scalar ticks() +// Since the monotonic clock will provide us with the timer since the computer +// started, the number of seconds since that time could easily become so large +// that it cannot be accurately stored in a float (even with as little two days +// update), therefore we need to start from a more recent reference (when the +// program starts). Of course this isn't much of an issue if scalar is a +// double-precious number. + +static time_t setReference() { struct timespec ts; if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) { - throw std::runtime_error("cannot access monotonic clock"); + return 0; } - return scalar(ts.tv_sec) + scalar(ts.tv_nsec) / 1000000000.0; + return ts.tv_sec; } -void sleep(scalar seconds, bool absolute) +static const time_t reference = setReference(); + + +scalar ticks() { struct timespec ts; - int ret; - if (!absolute) seconds += ticks(); - ts.tv_sec = time_t(seconds); - ts.tv_nsec = time_t((seconds - scalar(ts.tv_sec)) * 1000000000.0); - - do + if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) { - ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts, 0); + throw std::runtime_error("cannot access monotonic clock"); } - while (ret == -1 && errno == EINTR); + + return scalar(ts.tv_sec - reference) + scalar(ts.tv_nsec) / 1000000000.0; } + #else // ! HAVE_LIBRT -// If we don't have librt, we'll have to use different timing methods. + +// If we don't have librt, we'll have to use a different timing method. SDL +// only promises centisecond accuracy, but it may be better than nothing. + +#include scalar ticks() { - unsigned ms = SDL_GetTicks(); + Uint32 ms = SDL_GetTicks(); return scalar(ms / 1000) + scalar(ms % 1000) / 1000.0; } + +#endif // HAVE_LIBRT + + void sleep(scalar seconds, bool absolute) { struct timespec ts; @@ -85,7 +98,7 @@ void sleep(scalar seconds, bool absolute) if (absolute) seconds -= ticks(); ts.tv_sec = time_t(seconds); - ts.tv_nsec = time_t((seconds - scalar(ts.tv_sec)) * 1000000000.0); + ts.tv_nsec = long((seconds - scalar(ts.tv_sec)) * 1000000000.0); do { @@ -94,8 +107,8 @@ void sleep(scalar seconds, bool absolute) while (ret == -1 && errno == EINTR); } -#endif // HAVE_LIBRT - } // namespace dc +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/timer.hh b/src/timer.hh index 3de2a95..8506327 100644 --- a/src/timer.hh +++ b/src/timer.hh @@ -65,3 +65,5 @@ void sleep(scalar seconds, bool absolute = false); #endif // _TIMER_HH_ +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/video.cc b/src/video.cc index 715c407..6960a0b 100644 --- a/src/video.cc +++ b/src/video.cc @@ -30,6 +30,7 @@ #include "serializable.hh" #include "settings.hh" +#include "dispatcher.hh" #include "video.hh" @@ -93,6 +94,7 @@ void video::recreateContext() SDL_FreeSurface(context_); context_ = 0; setVideoMode(attribs_.mode); + dc::dispatcher::instance().dispatch("video.context_recreated"); } void video::setOpenGLAttributes() @@ -345,3 +347,5 @@ video::attributes::attributes() } // namespace dc +/** vim: set ts=4 sw=4 tw=80: *************************************************/ + diff --git a/src/video.hh b/src/video.hh index a16181c..ad89650 100644 --- a/src/video.hh +++ b/src/video.hh @@ -118,3 +118,5 @@ typedef boost::shared_ptr