]> Dogcows Code - chaz/yoink/commitdiff
big batch of progress
authorCharles McGarvey <chazmcgarvey@brokenzipper.com>
Sat, 25 Jul 2009 07:56:15 +0000 (01:56 -0600)
committerCharles McGarvey <chazmcgarvey@brokenzipper.com>
Sat, 25 Jul 2009 07:56:15 +0000 (01:56 -0600)
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

123 files changed:
COPYING
Makefile.am
configure.ac
data/Makefile.am [new file with mode: 0644]
data/animations/AlienWarrior.json [moved from share/animation/AlienWarrior.json with 100% similarity]
data/animations/BigExplosion.json [moved from share/animation/BigExplosion.json with 100% similarity]
data/animations/Bonuses.json [moved from share/animation/Bonuses.json with 100% similarity]
data/animations/Bullets.json [moved from share/animation/Bullets.json with 100% similarity]
data/animations/Effects.json [moved from share/animation/Effects.json with 100% similarity]
data/animations/Heroine.json [moved from share/animation/Heroine.json with 100% similarity]
data/animations/Jetbot.json [moved from share/animation/Jetbot.json with 100% similarity]
data/animations/RobotTrooper.json [moved from share/animation/RobotTrooper.json with 100% similarity]
data/scenes/Test.json [new file with mode: 0644]
data/scenes/Test.xml [moved from share/scene/Test.xml with 100% similarity]
data/textures/AlienWarrior.png [moved from share/texture/AlienWarrior.png with 100% similarity]
data/textures/BackgroundFar.png [moved from share/texture/BackgroundFar.png with 100% similarity]
data/textures/BackgroundNear.png [moved from share/texture/BackgroundNear.png with 100% similarity]
data/textures/BigExplosion.png [moved from share/texture/BigExplosion.png with 100% similarity]
data/textures/Bonuses.png [moved from share/texture/Bonuses.png with 100% similarity]
data/textures/Building.png [moved from share/texture/Building.png with 100% similarity]
data/textures/Font.png [moved from share/texture/Font.png with 100% similarity]
data/textures/Heroine.png [moved from share/texture/Heroine.png with 100% similarity]
data/textures/Jetbot.png [moved from share/texture/Jetbot.png with 100% similarity]
data/textures/Particles.png [moved from share/texture/Particles.png with 100% similarity]
data/textures/RobotTrooper.png [moved from share/texture/RobotTrooper.png with 100% similarity]
data/textures/Scenery.png [moved from share/texture/Scenery.png with 100% similarity]
data/textures/StatusBars.png [moved from share/texture/StatusBars.png with 100% similarity]
data/textures/TowerBlock1.png [moved from share/texture/TowerBlock1.png with 100% similarity]
data/textures/Trees.png [moved from share/texture/Trees.png with 100% similarity]
data/tilemaps/AlienWarrior.json [moved from share/texture/AlienWarrior.data with 80% similarity]
data/tilemaps/BackgroundFar.json [moved from share/texture/BackgroundNear.data with 59% similarity]
data/tilemaps/BackgroundNear.json [moved from share/texture/BackgroundFar.data with 54% similarity]
data/tilemaps/BigExplosion.json [moved from share/texture/BigExplosion.data with 54% similarity]
data/tilemaps/Bonuses.json [moved from share/texture/Bonuses.data with 54% similarity]
data/tilemaps/Building.json [moved from share/texture/Building.data with 54% similarity]
data/tilemaps/Font.json [moved from share/texture/Font.data with 81% similarity]
data/tilemaps/Heroine.json [moved from share/texture/RobotTrooper.data with 81% similarity]
data/tilemaps/Jetbot.json [moved from share/texture/Jetbot.data with 81% similarity]
data/tilemaps/Particles.json [moved from share/texture/Particles.data with 54% similarity]
data/tilemaps/RobotTrooper.json [moved from share/texture/Heroine.data with 81% similarity]
data/tilemaps/Scenery.json [moved from share/texture/Scenery.data with 59% similarity]
data/tilemaps/StatusBars.json [moved from share/texture/StatusBars.data with 81% similarity]
data/tilemaps/TowerBlock1.json [moved from share/texture/TowerBlock1.data with 54% similarity]
data/tilemaps/Trees.json [moved from share/texture/Trees.data with 54% similarity]
data/yoink.desktop [new file with mode: 0644]
data/yoink.png [new file with mode: 0644]
data/yoinkrc [moved from src/yoinkrc with 65% similarity]
doc/Makefile.am [new file with mode: 0644]
doc/screenshot.jpg [new file with mode: 0644]
doc/yoink.6.in [new file with mode: 0644]
extra/yoink.ebuild [new file with mode: 0644]
m4/boost.m4 [new file with mode: 0644]
m4/sdl.m4 [new file with mode: 0644]
share/character/Heroine.json [deleted file]
share/texture/AlienWarrior.plist [deleted file]
share/texture/BackgroundFar.plist [deleted file]
share/texture/BackgroundNear.plist [deleted file]
share/texture/BigExplosion.plist [deleted file]
share/texture/Bonuses.plist [deleted file]
share/texture/Building.plist [deleted file]
share/texture/Default.plist [deleted file]
share/texture/Font.plist [deleted file]
share/texture/Heroine.plist [deleted file]
share/texture/Jetbot.plist [deleted file]
share/texture/Particles.plist [deleted file]
share/texture/RobotTrooper.plist [deleted file]
share/texture/Scenery.plist [deleted file]
share/texture/StatusBars.plist [deleted file]
share/texture/TowerBlock1.plist [deleted file]
share/texture/Trees.plist [deleted file]
src/Character.cc [new file with mode: 0644]
src/Character.hh
src/Makefile.am
src/TilemapFont.cc [new file with mode: 0644]
src/TilemapFont.hh [new file with mode: 0644]
src/Typesetter.cc [new file with mode: 0644]
src/Typesetter.hh [new file with mode: 0644]
src/YoinkApp.cc
src/YoinkApp.hh
src/aabb.hh [new file with mode: 0644]
src/animation.cc
src/animation.hh
src/camera.hh [new file with mode: 0644]
src/cullable.hh [moved from src/rectangle.cc with 55% similarity]
src/deserializer.cc
src/deserializer.hh
src/dispatcher.cc
src/dispatcher.hh
src/drawable.hh
src/engine.cc
src/engine.hh
src/event.hh
src/interpolator.hh [new file with mode: 0644]
src/math.hh
src/mippleton.hh [new file with mode: 0644]
src/opengl.hh
src/profiler.hh
src/random.cc
src/random.hh
src/rectangle.hh [deleted file]
src/resource.cc
src/resource.hh
src/scene.cc [new file with mode: 0644]
src/scene.hh [new file with mode: 0644]
src/serializable.cc
src/serializable.hh
src/serializer.cc
src/serializer.hh
src/settings.cc
src/settings.hh
src/singleton.hh
src/stringtools.cc
src/stringtools.hh
src/texture.cc
src/texture.hh
src/thread.hh
src/tilemap.cc [new file with mode: 0644]
src/tilemap.hh
src/timer.cc
src/timer.hh
src/video.cc
src/video.hh
yajl/Makefile.am

diff --git a/COPYING b/COPYING
index 439408116235bb116e600ee3af0923a18592b332..2d0a39ccf99ff404c54463fffa19d4558e39e931 100644 (file)
--- 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. <http://fsf.org/>
+ 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.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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 <http://www.gnu.org/licenses/>.
+
+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:
+
+    <program>  Copyright (C) <year>  <name of author>
+    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
+<http://www.gnu.org/licenses/>.
+
+  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
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+
+
+
index d5f603756998443f0fac80d1ac2d646b6d8bb355..ad16dbe049e6fe1ab7b1944f8dcd5f04032bfac1 100644 (file)
@@ -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
+
index 15cba2c2f8ed7116a5165c2a43dea6564c05a2d4..2d839c9b0a36f115a8d8e21c045038694c37c592 100644 (file)
-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 (file)
index 0000000..8387830
--- /dev/null
@@ -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/data/scenes/Test.json b/data/scenes/Test.json
new file mode 100644 (file)
index 0000000..7b0fd63
--- /dev/null
@@ -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
+               }
+
+       ]
+}
similarity index 100%
rename from share/scene/Test.xml
rename to data/scenes/Test.xml
similarity index 80%
rename from share/texture/AlienWarrior.data
rename to data/tilemaps/AlienWarrior.json
index 564934be0256f63fd77ccfa2e71a14bba39b1fbf..471fed43677adf1cb485aa584992f254f6f31b36 100644 (file)
@@ -1,7 +1,6 @@
 {
        "TilesU": 8,
        "TilesV": 4,
-       "InvertAlpha": 0,
        "MinFilter": Nearest,
        "MagFilter": Nearest
 }
similarity index 59%
rename from share/texture/BackgroundNear.data
rename to data/tilemaps/BackgroundFar.json
index 3272855616ecd327d2d4606207ef922b7be43584..8780beaac1289fccb9dd9c2efc1dc12e2485400a 100644 (file)
@@ -1,9 +1,8 @@
 {
        "TilesU": 1,
        "TilesV": 1,
-       "InvertAlpha": 0,
        "MinFilter": "Linear",
        "MagFilter": "Linear",
-       "WrapU": "Wrap",
-       "WrapV": "Wrap"
+       "WrapU": "Clamp",
+       "WrapV": "Clamp"
 }
similarity index 54%
rename from share/texture/BackgroundFar.data
rename to data/tilemaps/BackgroundNear.json
index 11ab59202e400872779c099f247773f77f64a713..2ae063742ae42b8decbfa5e3915372b0771cd68f 100644 (file)
@@ -1,9 +1,8 @@
 {
        "TilesU": 1,
        "TilesV": 1,
-       "InvertAlpha": 0,
        "MinFilter": "Linear",
        "MagFilter": "Linear",
-       "WrapU": "ClampToEdge",
-       "WrapV": "ClampToEdge"
+       "WrapU": "Repeat",
+       "WrapV": "Repeat"
 }
similarity index 54%
rename from share/texture/BigExplosion.data
rename to data/tilemaps/BigExplosion.json
index 104ebf0e25ae024d7c109195faa164b27de02dd1..b57a190ac6414db328508b638be35fc2138cc801 100644 (file)
@@ -1,9 +1,8 @@
 {
        "TilesU": 8,
        "TilesV": 1,
-       "InvertAlpha": 0,
        "MinFilter": "Linear",
        "MagFilter": "Linear",
-       "WrapU": "ClampToEdge",
-       "WrapV": "ClampToEdge"
+       "WrapU": "Clamp",
+       "WrapV": "Clamp"
 }
similarity index 54%
rename from share/texture/Bonuses.data
rename to data/tilemaps/Bonuses.json
index a8e3d9db3f69c25588be0f20124ec8b25a161480..5c024d5ca7557d4c1fc013108400b6028319ab94 100644 (file)
@@ -1,9 +1,8 @@
 {
        "TilesU": 8,
        "TilesV": 4,
-       "InvertAlpha": 0,
        "MinFilter": "Linear",
        "MagFilter": "Linear",
-       "WrapU": "ClampToEdge",
-       "WrapV": "ClampToEdge"
+       "WrapU": "Clamp",
+       "WrapV": "Clamp"
 }
similarity index 54%
rename from share/texture/Building.data
rename to data/tilemaps/Building.json
index f041b09df2b529838aa666fadc3d7611f1f8fc27..ebc6842f4d27de4222c0854dcaa927d8df41afbc 100644 (file)
@@ -1,9 +1,8 @@
 {
        "TilesU": 8,
        "TilesV": 4,
-       "InvertAlpha": 0,
        "MinFilter": "Nearest",
        "MagFilter": "Nearest",
-       "WrapU": "ClampToEdge",
-       "WrapV": "ClampToEdge"
+       "WrapU": "Clamp",
+       "WrapV": "Clamp"
 }
similarity index 81%
rename from share/texture/Font.data
rename to data/tilemaps/Font.json
index 2056f7d282f5594b3fa3e120f7ae5f8a80f5b792..8b1214b83ffd948a6a3b6d4014b03bb76aa76e38 100644 (file)
@@ -1,7 +1,6 @@
 {
        "TilesU": 8,
        "TilesV": 8,
-       "InvertAlpha": 0,
        "MinFilter": "Nearest",
        "MagFilter": "Nearest"
 }
similarity index 81%
rename from share/texture/RobotTrooper.data
rename to data/tilemaps/Heroine.json
index fba61655cb5865650ef913a378642c95d7716bdb..3420a10389cc2228a3426a107772c0a67f1175fe 100644 (file)
@@ -1,7 +1,6 @@
 {
        "TilesU": 8,
        "TilesV": 4,
-       "InvertAlpha": 0,
        "MinFilter": "Nearest",
        "MagFilter": "Nearest"
 }
similarity index 81%
rename from share/texture/Jetbot.data
rename to data/tilemaps/Jetbot.json
index f6d762a65582e22df1eff625971add3c8ea781b1..52af3b06bd5c85f73831fbf4f7586cfe74869463 100644 (file)
@@ -1,7 +1,6 @@
 {
        "TilesU": 4,
        "TilesV": 2,
-       "InvertAlpha": 0,
        "MinFilter": "Nearest",
        "MagFilter": "Nearest"
 }
similarity index 54%
rename from share/texture/Particles.data
rename to data/tilemaps/Particles.json
index a8e3d9db3f69c25588be0f20124ec8b25a161480..5c024d5ca7557d4c1fc013108400b6028319ab94 100644 (file)
@@ -1,9 +1,8 @@
 {
        "TilesU": 8,
        "TilesV": 4,
-       "InvertAlpha": 0,
        "MinFilter": "Linear",
        "MagFilter": "Linear",
-       "WrapU": "ClampToEdge",
-       "WrapV": "ClampToEdge"
+       "WrapU": "Clamp",
+       "WrapV": "Clamp"
 }
similarity index 81%
rename from share/texture/Heroine.data
rename to data/tilemaps/RobotTrooper.json
index fba61655cb5865650ef913a378642c95d7716bdb..3420a10389cc2228a3426a107772c0a67f1175fe 100644 (file)
@@ -1,7 +1,6 @@
 {
        "TilesU": 8,
        "TilesV": 4,
-       "InvertAlpha": 0,
        "MinFilter": "Nearest",
        "MagFilter": "Nearest"
 }
similarity index 59%
rename from share/texture/Scenery.data
rename to data/tilemaps/Scenery.json
index aee8ed3a64fb7887b7aa88e972df7e99fb16a748..83339cf551640cdfb222d4baf76500970c6704de 100644 (file)
@@ -1,9 +1,8 @@
 {
        "TilesU": 4,
        "TilesV": 4,
-       "InvertAlpha": 0,
        "MinFilter": "Linear",
        "MagFilter": "Linear",
-       "WrapU": "Wrap",
-       "WrapV": "Wrap"
+       "WrapU": "Repeat",
+       "WrapV": "Repeat"
 }
similarity index 81%
rename from share/texture/StatusBars.data
rename to data/tilemaps/StatusBars.json
index 9b94ec7e7420b37dff592f36ba0fd12ef4368f0b..01b5ed01c298bc04bab2d0dc6839a8f23259063e 100644 (file)
@@ -1,7 +1,6 @@
 {
        "TilesU": 4,
        "TilesV": 1,
-       "InvertAlpha": 0,
        "MinFilter": "Nearest",
        "MagFilter": "Nearest"
 }
similarity index 54%
rename from share/texture/TowerBlock1.data
rename to data/tilemaps/TowerBlock1.json
index 1d5cade5570bc53f60a70784c617b79926cce2e0..98e7587a4a84df5d5d751c769a107edaf4e4666d 100644 (file)
@@ -1,9 +1,8 @@
 {
        "TilesU": 4,
        "TilesV": 4,
-       "InvertAlpha": 0,
        "MinFilter": "Linear",
        "MagFilter": "Linear",
-       "WrapU": "ClampToEdge",
-       "WrapV": "ClampToEdge"
+       "WrapU": "Clamp",
+       "WrapV": "Clamp"
 }
similarity index 54%
rename from share/texture/Trees.data
rename to data/tilemaps/Trees.json
index 665f66a2e88ae720164ba795757ae070f570f127..247ec97500055d3edead3c1b00fa920bf5a55354 100644 (file)
@@ -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 (file)
index 0000000..2f301e2
--- /dev/null
@@ -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 (file)
index 0000000..d40be6b
Binary files /dev/null and b/data/yoink.png differ
similarity index 65%
rename from src/yoinkrc
rename to data/yoinkrc
index f58c13d46f0f06df1cc93ed44c9d280f21ae3c81..67be5c112b5d0dfa6dadd3bc927922f9e961f313 100644 (file)
@@ -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 (file)
index 0000000..c74ebdb
--- /dev/null
@@ -0,0 +1,3 @@
+
+man6_MANS = yoink.6
+
diff --git a/doc/screenshot.jpg b/doc/screenshot.jpg
new file mode 100644 (file)
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 (file)
index 0000000..a7ad776
--- /dev/null
@@ -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 <onefriedrice@brokenzipper.com>
+.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 (file)
index 0000000..69fa2f0
--- /dev/null
@@ -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 (file)
index 0000000..c4ba5ec
--- /dev/null
@@ -0,0 +1,920 @@
+# boost.m4: Locate Boost headers and libraries for autoconf-based projects.
+# Copyright (C) 2007, 2008, 2009  Benoit Sigoure <tsuna@lrde.epita.fr>
+#
+# 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 <http://www.gnu.org/licenses/>.
+
+# 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 <boost/version.hpp>
+#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 <prefix>/include/boost-<version>.  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/version.hpp>
+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_<HEADER-NAME> 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<void ()> 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.h>],
+    [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 (file)
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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#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, &micro) != 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 <stdio.h>
+#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 (file)
index 0ea723b..0000000
+++ /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 (file)
index d3adf1b..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
-       <key>TilesU</key>
-       <string>8</string>
-       <key>TilesV</key>
-       <string>4</string>
-       <key>InvertAlpha</key>
-       <string>0</string>
-       <key>MinFilter</key>
-       <string>Nearest</string>
-       <key>MagFilter</key>
-       <string>Nearest</string>
-</dict>
-</plist>
diff --git a/share/texture/BackgroundFar.plist b/share/texture/BackgroundFar.plist
deleted file mode 100644 (file)
index a02e454..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
-       <key>TilesU</key>
-       <string>1</string>
-       <key>TilesV</key>
-       <string>1</string>
-       <key>InvertAlpha</key>
-       <string>0</string>
-
-       <key>WrapU</key>
-       <string>ClampToEdge</string>
-       <key>WrapV</key>
-       <string>ClampToEdge</string>
-       <key>MinFilter</key>
-       <string>Linear</string>
-       <key>MagFilter</key>
-       <string>Linear</string>
-</dict>
-</plist>
diff --git a/share/texture/BackgroundNear.plist b/share/texture/BackgroundNear.plist
deleted file mode 100644 (file)
index 46fe92a..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
-       <key>TilesU</key>
-       <string>1</string>
-       <key>TilesV</key>
-       <string>1</string>
-       <key>InvertAlpha</key>
-       <string>0</string>
-
-       <key>WrapU</key>
-       <string>Wrap</string>
-       <key>WrapV</key>
-       <string>Wrap</string>
-       <key>MinFilter</key>
-       <string>Linear</string>
-       <key>MagFilter</key>
-       <string>Linear</string>
-</dict>
-</plist>
diff --git a/share/texture/BigExplosion.plist b/share/texture/BigExplosion.plist
deleted file mode 100644 (file)
index f9c42cb..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
-       <key>TilesU</key>
-       <string>8</string>
-       <key>TilesV</key>
-       <string>1</string>
-       <key>InvertAlpha</key>
-       <string>0</string>
-
-       <key>MinFilter</key>
-       <string>Linear</string>
-       <key>MagFilter</key>
-       <string>Linear</string>
-       <key>WrapU</key>
-       <string>ClampToEdge</string>
-       <key>WrapV</key>
-       <string>ClampToEdge</string>
-       <key>MinFilter</key>
-       <string>Nearest</string>
-       <key>MagFilter</key>
-       <string>Nearest</string>
-</dict>
-</plist>
diff --git a/share/texture/Bonuses.plist b/share/texture/Bonuses.plist
deleted file mode 100644 (file)
index 486e2f8..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
-       <key>TilesU</key>
-       <string>8</string>
-       <key>TilesV</key>
-       <string>4</string>
-       <key>InvertAlpha</key>
-       <string>0</string>
-
-       <key>MinFilter</key>
-       <string>Linear</string>
-       <key>MagFilter</key>
-       <string>Linear</string>
-       <key>WrapU</key>
-       <string>ClampToEdge</string>
-       <key>WrapV</key>
-       <string>ClampToEdge</string>
-       <key>MinFilter</key>
-       <string>Nearest</string>
-       <key>MagFilter</key>
-       <string>Nearest</string>
-</dict>
-</plist>
diff --git a/share/texture/Building.plist b/share/texture/Building.plist
deleted file mode 100644 (file)
index 79084ea..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
-       <key>TilesU</key>
-       <string>8</string>
-       <key>TilesV</key>
-       <string>4</string>
-       <key>InvertAlpha</key>
-       <string>0</string>
-
-       <key>WrapU</key>
-       <string>ClampToEdge</string>
-       <key>WrapV</key>
-       <string>ClampToEdge</string>
-       <key>MinFilter</key>
-       <string>Nearest</string>
-       <key>MagFilter</key>
-       <string>Nearest</string>
-</dict>
-</plist>
diff --git a/share/texture/Default.plist b/share/texture/Default.plist
deleted file mode 100644 (file)
index 18a47ff..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
-       <key>MinFilter</key>
-       <string>Linear</string>
-       <key>MagFilter</key>
-       <string>Linear</string>
-       <key>WrapU</key>
-       <string>Repeat</string>
-       <key>WrapV</key>
-       <string>Repeat</string>
-       <key>InvertAlpha</key>
-       <string>0</string>
-</dict>
-</plist>
diff --git a/share/texture/Font.plist b/share/texture/Font.plist
deleted file mode 100644 (file)
index 7688344..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
-       <key>TilesU</key>
-       <string>8</string>
-       <key>TilesV</key>
-       <string>8</string>
-       <key>InvertAlpha</key>
-       <string>0</string>
-       <key>MinFilter</key>
-       <string>Nearest</string>
-       <key>MagFilter</key>
-       <string>Nearest</string>
-</dict>
-</plist>
diff --git a/share/texture/Heroine.plist b/share/texture/Heroine.plist
deleted file mode 100644 (file)
index d3adf1b..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
-       <key>TilesU</key>
-       <string>8</string>
-       <key>TilesV</key>
-       <string>4</string>
-       <key>InvertAlpha</key>
-       <string>0</string>
-       <key>MinFilter</key>
-       <string>Nearest</string>
-       <key>MagFilter</key>
-       <string>Nearest</string>
-</dict>
-</plist>
diff --git a/share/texture/Jetbot.plist b/share/texture/Jetbot.plist
deleted file mode 100644 (file)
index 6f7f246..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
-       <key>TilesU</key>
-       <string>4</string>
-       <key>TilesV</key>
-       <string>2</string>
-       <key>InvertAlpha</key>
-       <string>0</string>
-       <key>MinFilter</key>
-       <string>Nearest</string>
-       <key>MagFilter</key>
-       <string>Nearest</string>
-</dict>
-</plist>
diff --git a/share/texture/Particles.plist b/share/texture/Particles.plist
deleted file mode 100644 (file)
index 486e2f8..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
-       <key>TilesU</key>
-       <string>8</string>
-       <key>TilesV</key>
-       <string>4</string>
-       <key>InvertAlpha</key>
-       <string>0</string>
-
-       <key>MinFilter</key>
-       <string>Linear</string>
-       <key>MagFilter</key>
-       <string>Linear</string>
-       <key>WrapU</key>
-       <string>ClampToEdge</string>
-       <key>WrapV</key>
-       <string>ClampToEdge</string>
-       <key>MinFilter</key>
-       <string>Nearest</string>
-       <key>MagFilter</key>
-       <string>Nearest</string>
-</dict>
-</plist>
diff --git a/share/texture/RobotTrooper.plist b/share/texture/RobotTrooper.plist
deleted file mode 100644 (file)
index d3adf1b..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
-       <key>TilesU</key>
-       <string>8</string>
-       <key>TilesV</key>
-       <string>4</string>
-       <key>InvertAlpha</key>
-       <string>0</string>
-       <key>MinFilter</key>
-       <string>Nearest</string>
-       <key>MagFilter</key>
-       <string>Nearest</string>
-</dict>
-</plist>
diff --git a/share/texture/Scenery.plist b/share/texture/Scenery.plist
deleted file mode 100644 (file)
index 95aedca..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
-       <key>TilesU</key>
-       <string>4</string>
-       <key>TilesV</key>
-       <string>4</string>
-       <key>InvertAlpha</key>
-       <string>0</string>
-
-       <key>MinFilter</key>
-       <string>Linear</string>
-       <key>MagFilter</key>
-       <string>Linear</string>
-       <key>WrapU</key>
-       <string>Wrap</string>
-       <key>WrapV</key>
-       <string>Wrap</string>
-       <key>MinFilter</key>
-       <string>Nearest</string>
-       <key>MagFilter</key>
-       <string>Nearest</string>
-</dict>
-</plist>
diff --git a/share/texture/StatusBars.plist b/share/texture/StatusBars.plist
deleted file mode 100644 (file)
index 148307a..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
-       <key>TilesU</key>
-       <string>4</string>
-       <key>TilesV</key>
-       <string>1</string>
-       <key>InvertAlpha</key>
-       <string>0</string>
-       <key>MinFilter</key>
-       <string>Nearest</string>
-       <key>MagFilter</key>
-       <string>Nearest</string>
-</dict>
-</plist>
diff --git a/share/texture/TowerBlock1.plist b/share/texture/TowerBlock1.plist
deleted file mode 100644 (file)
index f969901..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
-       <key>TilesU</key>
-       <string>4</string>
-       <key>TilesV</key>
-       <string>4</string>
-       <key>InvertAlpha</key>
-       <string>0</string>
-
-       <key>MinFilter</key>
-       <string>Linear</string>
-       <key>MagFilter</key>
-       <string>Linear</string>
-       <key>WrapU</key>
-       <string>ClampToEdge</string>
-       <key>WrapV</key>
-       <string>ClampToEdge</string>
-       <key>MinFilter</key>
-       <string>Nearest</string>
-       <key>MagFilter</key>
-       <string>Nearest</string>
-</dict>
-</plist>
diff --git a/share/texture/Trees.plist b/share/texture/Trees.plist
deleted file mode 100644 (file)
index 3c9b875..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
-<plist version="0.9">
-<dict>
-       <key>TilesU</key>
-       <string>2</string>
-       <key>TilesV</key>
-       <string>1</string>
-       <key>InvertAlpha</key>
-       <string>0</string>
-
-       <key>MinFilter</key>
-       <string>Linear</string>
-       <key>MagFilter</key>
-       <string>Linear</string>
-       <key>WrapU</key>
-       <string>ClampToEdge</string>
-       <key>WrapV</key>
-       <string>ClampToEdge</string>
-       <key>MinFilter</key>
-       <string>Nearest</string>
-       <key>MagFilter</key>
-       <string>Nearest</string>
-</dict>
-</plist>
diff --git a/src/Character.cc b/src/Character.cc
new file mode 100644 (file)
index 0000000..64866c5
--- /dev/null
@@ -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: *************************************************/
+
index 2f175ad65d3b7c90aeafaa03a7f6f6de3ba9c5b6..c9cf11a0542635798f2eeba1b18ea92e6058a680 100644 (file)
 #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: *************************************************/
+
index 40dd17331c4d9851e0c0840d301241e99122d133..510dc9efdc278e2a32dee404ce07fd1fc91f22d8 100644 (file)
@@ -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 (file)
index 0000000..60f070c
--- /dev/null
@@ -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 <iostream>
+
+
+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 (file)
index 0000000..5ec9064
--- /dev/null
@@ -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 (file)
index 0000000..f658c26
--- /dev/null
@@ -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 <algorithm>
+#include <cstdio>
+#include <cstdarg>
+
+#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 (file)
index 0000000..d9ccf42
--- /dev/null
@@ -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 <string>
+
+#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: *************************************************/
+
index 64decfb73a88f9e6b0b405f1c94fa3c7c9babc2e..4b024b47ec74f1e617d87b96689e7a645fbdd4c6 100644 (file)
 #include <iostream>
 #include <string>
 
+#include <cstdlib>             // getenv
+
 #include <boost/bind.hpp>
 
 #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: *************************************************/
+
index 69b53d92e6eb93f98809c5d05127660114b036ac..055a64c25ea97415d6a2f47bb844ae3188b46164 100644 (file)
 #ifndef _YOINKAPP_HH_
 #define _YOINKAPP_HH_
 
+/**
+ * @file YoinkApp.hh
+ * This is the big enchilada.
+ */
+
 #include <iostream>
 #include <string>
 
+#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<dc::vector2,2> 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 (file)
index 0000000..e608b21
--- /dev/null
@@ -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: *************************************************/
+
index 745f0e4493eddcb486c5334f6b841d42da9575fe..c03a49d7195a08e4f3d0252f1581eb18f3b00855 100644 (file)
 
 *******************************************************************************/
 
+#include <map>
+#include <vector>
+
+#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<animation_data>
        {
+               /**
+                * 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<std::string,serializable_ptr> rootObj;
+
+                               if (root->get(rootObj))
+                               {
+                                       std::map<std::string,serializable_ptr>::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<frame>      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<std::string,serializable_ptr> rootObj;
+
+                               if (root->get(rootObj))
+                               {
+                                       std::map<std::string,serializable_ptr>::iterator i;
+                                       for (i = rootObj.begin(); i != rootObj.end(); i++)
+                                       {
+                                               std::string key = (*i).first;
+
+                                               if (key == "frames")
+                                               {
+                                                       std::vector<serializable_ptr> framesObj;
+
+                                                       if ((*i).second->get(framesObj))
+                                                       {
+                                                               std::vector<serializable_ptr>::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<std::string,serializable_ptr> rootObj;
+
+                               if (root->get(rootObj))
+                               {
+                                       std::map<std::string,serializable_ptr>::iterator i;
+
+                                       for (i = rootObj.begin(); i != rootObj.end(); i++)
+                                       {
+                                               sequences.insert(std::pair<std::string,sequence>((*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<animation_data>(name)
+               {
+                       loadFromFile();
+               }
+
+               std::map<std::string,sequence> sequences;               ///< List of sequences.
        };
 
-       std::map<std::string,sequence> 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<std::string,animation_data::sequence>::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<animation_data> 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: *************************************************/
+
index 85307ac921d56f4409caf2d898e90f8c0c793f18..ca565818d569b07442a88ebb28623880b080948d 100644 (file)
  * Motion picture!!
  */
 
+#include <string>
+
 #include <boost/shared_ptr.hpp>
 
+#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<animation_impl> 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 (file)
index 0000000..dcdc55d
--- /dev/null
@@ -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: *************************************************/
+
similarity index 55%
rename from src/rectangle.cc
rename to src/cullable.hh
index 0f9bb9f4a74c60977ae9141267886c665e160593..e4fe4ca7f292ee408c37f350c76a6acee31e8b9c 100644 (file)
 
 *******************************************************************************/
 
-#include <algorithm>
+#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: *************************************************/
 
index 4c3f8f2caab6a69cc049dc5e79affd8341c04cf6..8ad30591a54cb7087f788acb92c0a845b0842439 100644 (file)
@@ -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: *************************************************/
+
index 733ce3912f33652d20697bff046d357ba0e2581d..f2b0bccc06d1ade59f920f120cbf42d3a262148c 100644 (file)
 namespace dc {
 
 
-class serializable;
+class serializable;            // forward declaration
 typedef boost::shared_ptr<serializable> 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<deserializer_impl> impl;
 };
 
@@ -77,3 +127,5 @@ private:
 
 #endif // _DESERIALIZER_HH_
 
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
index 509b69d151bd039e5bf85d8f1d717e172c6321e7..d42077a2ec8b20a300051ae6f69e87b43ee4d775 100644 (file)
@@ -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<std::string,dispatcher_impl::callback_t>
-               callbackPair(message, dispatcher_impl::callback_t(id, callback));
+       std::pair<std::string,dispatcher::dispatcher_impl::callback_t>
+               callbackPair(message, dispatcher::dispatcher_impl::callback_t(id, callback));
 
        std::pair<handler,std::string> handlerPair(id, message);
 
@@ -88,16 +90,16 @@ dispatcher::handler dispatcher::addHandler(const std::string& message,
 
 void dispatcher::removeHandler(handler id)
 {
-       std::pair<dispatcher_impl::handler_it_t,dispatcher_impl::handler_it_t>
+       std::pair<dispatcher::dispatcher_impl::handler_it_t,dispatcher::dispatcher_impl::handler_it_t>
                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<dispatcher_impl::callback_it_t,dispatcher_impl::callback_it_t>
+       std::pair<dispatcher::dispatcher_impl::callback_it_t,dispatcher::dispatcher_impl::callback_it_t>
                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: *************************************************/
+
index e45e88ed926d20e1c438823b2fb16a3690e84503..1a7744ae1f8aa689a6506946ee9c0a6738445060 100644 (file)
 #ifndef _DISPATCHER_HH_
 #define _DISPATCHER_HH_
 
-/**
- * @file dispatcher.hh
- * Dispatching of information.
- */
-
 #include <string>
 
 #include <boost/shared_ptr.hpp>
 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<dispatcher>
 {
@@ -74,6 +74,7 @@ public:
        void dispatch(const std::string& message, const notification& param);
 
 private:
+       class dispatcher_impl;
        boost::shared_ptr<dispatcher_impl> impl;
 };
 
@@ -82,3 +83,5 @@ private:
 
 #endif // _DISPATCHER_HH_
 
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
index 835fb61dd723c80ad766158342c89bf52f3fbef5..031cf79aab69eec38c20f0e12b0c9b257a7230b7 100644 (file)
 #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: *************************************************/
+
index 3e40361a3213f73c220d2ced348931c9dfd4e8cb..ec6faa15e9d0505c027c659aa2867ae62eb263ba 100644 (file)
 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: *************************************************/
+
index bc3bdaf11aef6d08fc1275659dc440f273a10862..98141cb384e079a4180a98d173f6dd4753e6d58b 100644 (file)
 #define _ENGINE_HH_
 
 #include <boost/shared_ptr.hpp>
-#include <SDL/SDL.h>
 
 #include "singleton.hh"
+#include "event.hh"
 #include "dispatcher.hh"
 
 
 namespace dc {
 
 
-class engine_impl;
 class video;
 
 class engine : public singleton<engine>
@@ -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<engine_impl> impl;
 };
 
@@ -74,3 +74,5 @@ private:
 
 #endif // _ENGINE_HH_
 
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
index 84a073e34b8d0fb717be08815bbe25b6ea3bc2c2..8ca219a925917109e6c09bd50135e373a7c142cd 100644 (file)
 
 #ifndef _EVENT_HH_
 #define _EVENT_HH_
-
-#include "bz/date.h"
-#include "bz/object.h"
-
-
-namespace bz {
        
+#include <SDL/SDL.h>
 
-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 (file)
index 0000000..74708d6
--- /dev/null
@@ -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 T>
+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 T, int D>
+class binomial_interpolator : public interpolator_base<T>
+{
+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<T>::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 T>
+class binomial_interpolator<T,1> : public interpolator_base<T>
+{
+public:
+       binomial_interpolator() {}
+
+       explicit binomial_interpolator(const T coeff[2], scalar seconds = 1.0,
+                       interpolator::mode onFinish = interpolator::stop)
+               //interpolator_base<T>(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<T>::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<scalar, 1>       lerps;  // linear
+typedef binomial_interpolator<vector2,1>       lerpv2;
+typedef binomial_interpolator<vector3,1>       lerpv3;
+typedef binomial_interpolator<vector4,1>       lerpv4;
+
+typedef binomial_interpolator<scalar ,2>       qerps;  // quadratic
+typedef binomial_interpolator<vector2,2>       qerpv2;
+typedef binomial_interpolator<vector3,2>       qerpv3;
+typedef binomial_interpolator<vector4,2>       qerpv4;
+
+typedef binomial_interpolator<scalar ,3>       cerps;  // cubic
+typedef binomial_interpolator<vector2,3>       cerpv2;
+typedef binomial_interpolator<vector3,3>       cerpv3;
+typedef binomial_interpolator<vector4,3>       cerpv4;
+
+
+} // namespace dc
+
+#endif // _INTERPOLATOR_HH_
+
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
index 313ecc1c09fa8b036821cc4871d31f6b06b8957a..ab80dcc35af94cf3677ffa9d4e83224eb3824045 100644 (file)
 #include <cmath>
 #include <cml/cml.h>
 
+#include <iostream>
 
-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 (file)
index 0000000..16985a3
--- /dev/null
@@ -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 <map>
+#include <string>
+
+
+namespace dc {
+
+
+template <class T>
+class mippleton
+{
+       typedef std::pair<unsigned,T*>                          ptr_value_t;
+       typedef std::pair<std::string,ptr_value_t>      ptr_map_pair_t;
+       typedef std::map<std::string,ptr_value_t>       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 <class T>
+std::map<std::string,std::pair<unsigned,T*> > mippleton<T>::ptrs_;
+
+
+} // namespace dc
+
+#endif // _MIPPLETON_HH_
+
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
index e04fe5ccac96a42658d62d7cd826a9a5696dc7f7..287918dfdf8be3ba2600819bffb8e934584528e6 100644 (file)
@@ -41,3 +41,5 @@
 
 #endif // _GL_HH_
 
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
index d1a8bb0048b82c35c02c99f7996424b8baa30d6c..7b38e52ea880fbeb2f241d459733b632d23283df 100644 (file)
@@ -79,3 +79,5 @@ private:
 
 #endif // _PROFILER_HH_
 
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
index 22bbd4e615e2171047650c33b70c9c937065b378..6cd25cf7af042943746d2455302ac16e367340a4 100644 (file)
@@ -113,3 +113,5 @@ double get()
 
 }; // namespace rng
 
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
index 5a342295776200c63c2979855478ad3cb0c2dc1d..ac308c8baa99532e17e9690f4d2866145b4ad2e9 100644 (file)
@@ -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 (file)
index 1594d62..0000000
+++ /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_
-
index 758827cada59d731bea82a6387c7657fabf33cdc..16b5f213489ae39ed9448901e5f06d0b2a901160 100644 (file)
@@ -37,26 +37,12 @@ namespace dc {
 std::vector<std::string> 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: *************************************************/
+
index eff9e3e4d4e49a88ba18706c662592cf5e0e4753..c5020f65c26bafed4bec8f2c070729c52f4a9f8c 100644 (file)
@@ -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<std::string> 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 (file)
index 0000000..7dd102b
--- /dev/null
@@ -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 <map>
+#include <vector>
+
+#include "mippleton.hh"
+#include "deserializer.hh"
+#include "serializable.hh"
+#include "aabb.hh"
+
+#include "scene.hh"
+
+
+namespace dc {
+
+
+class scene::scene_impl : public mippleton<scene_impl>
+{
+       static bool loadBox(aabb& theBox, serializable_ptr obj)
+       {
+               std::vector<serializable_ptr> 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<scene_impl>(name)
+       {
+               loadFromFile();
+       }
+
+
+       void loadFromFile()
+       {
+               std::string filePath = scene::getPathToResource(getName());
+
+               deserializer in(filePath, true);
+
+               serializable_ptr root = in.deserialize();
+
+               if (root)
+               {
+                       std::map<std::string,serializable_ptr> rootObj;
+
+                       if (root->get(rootObj))
+                       {
+                               std::map<std::string,serializable_ptr>::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<std::string,sequence>((*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 (file)
index 0000000..2938db8
--- /dev/null
@@ -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 <string>
+#include <boost/shared_ptr.hpp>
+
+#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<scene_impl> impl;
+};
+
+
+} // namespace dc
+
+#endif // _SCENE_HH_
+
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
index 11e8d265c6c1608f9fe0b4a71ffb4d2c8733aecc..1da0613266a0bb0abb93587d9581ff392f9d32dc 100644 (file)
@@ -72,11 +72,51 @@ bool serializable::get(std::map<std::string,serializable_ptr>& 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: *************************************************/
+
index 5b8b403dabc8e0020d55918d6a28257994b96bf6..967b2133376ffc2a43b20fe94ac5edc237114f34 100644 (file)
@@ -34,9 +34,9 @@
 #include <map>
 #include <vector>
 
+#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<serializable_ptr>& value);
        virtual bool get(std::map<std::string,serializable_ptr>& 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: *************************************************/
+
index 06563ef1ed69995847cd0f9751ae8713f43f8fee..7b7596d7b3eb99c8054df4a62250fac5eb66746f 100644 (file)
@@ -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: *************************************************/
+
index 8e61a622bc12e97feb4e68e95ab74e5881f6c2e5..206a7930fab9903b5ad6e9acd4eb848ddfff9182 100644 (file)
 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<serializer_impl> impl;
 };
 
@@ -84,3 +115,5 @@ private:
 
 #endif // _SERIALIZER_HH_
 
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
index 07ec0e50c1cebbc0d10f40e55f5e22e31b73376c..74ab384dd0bb1cd6e2a9a334bfc9ca5cb6bf1efd 100644 (file)
 *******************************************************************************/
 
 #include <sstream>
-#include <cstring>
+#include <cstdlib>             // getenv
+#include <cstring>             // strchr
+
+#include <boost/algorithm/string.hpp>
 
 #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<std::string> paths;
+       boost::split(paths, filePath, boost::is_any_of(":"));
 
-       try
+       loadFromFiles(paths, precedence);
+}
+
+void settings::loadFromFiles(const std::vector<std::string>& filePaths,
+               bool precedence)
+{
+       std::vector<std::string>::const_iterator it;
+
+       char* home = getenv("HOME");
+
+       for (it = filePaths.begin(); it != filePaths.end(); it++)
        {
-               serializable_ptr obj = in.deserialize();
-               std::map<std::string,serializable_ptr> 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<std::string,serializable_ptr> 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: *************************************************/
+
index 5cb09722bd43530aa48668eaa2f091b58fc35804..9c2f2d83eb21dcc00744f77cfde2d7d990121526 100644 (file)
@@ -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<std::string>& filePaths,
+                       bool precedence = false);
 
        template <typename T>
        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: *************************************************/
+
index 3b2ebf73239719f419f374e22527c24492f3b9e0..ec0d01e9997fbce426c4f41a460e00540f81c66f 100644 (file)
 #include <stdexcept>
 
 
+namespace dc {
+
+
 template <typename T>
 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 <typename T> T* singleton<T>::ptr_ = 0;
 
 
+} // namespace dc
+
 #endif // _SINGLETON_HH_
 
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
index 8954f9b0e44ebf55be628bffe45e174984116520..91d2a6cb805f90454e5506459bb06d9d987b16e6 100644 (file)
@@ -151,3 +151,5 @@ std::string wideToMulti(const std::wstring& wideStr)
 
 } // namespace dc
 
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
index 9bf457753aa582be36cb77f54a421895a587dbbf..bd79eab37c359daed98066ba1b627ce88d9fa748 100644 (file)
@@ -42,3 +42,5 @@ std::string wideToMulti(const std::wstring& wideStr);
 
 #endif // _STRINGTOOLS_HH_
 
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
index 2f8f97a1c366f3befe9f8838f721ed3c608c5e9f..6d3e912925b8f1376018b9cc612fde8db1d4677a 100644 (file)
@@ -33,6 +33,8 @@
 #include <SDL/SDL.h>
 #include <SDL/SDL_image.h>
 
+#include "mippleton.hh"
+
 #include "dispatcher.hh"
 #include "opengl.hh"
 
 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<texture_impl>
 {
+
+       /**
+        * 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<texture_impl>(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: *************************************************/
+
index 1be4c5a004287fe51fc7e0832870e638055d13fe..f92ad23faf06db7c16c59c2d22d107ec6ad920e7 100644 (file)
 
 #include <boost/shared_ptr.hpp>
 
-#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<texture_impl> impl;
 };
 
@@ -73,3 +81,5 @@ private:
 
 #endif // _TEXTURE_HH_
 
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
index 990f9b018a5ecf92d496ff196dbffbbe7101b78e..443decd31849dce265f89b6d826c7e2cdc4309db 100644 (file)
@@ -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 (file)
index 0000000..0852f98
--- /dev/null
@@ -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 <cassert>
+
+#include "mippleton.hh"
+#include "serializable.hh"
+#include "deserializer.hh"
+
+#include "opengl.hh"
+
+#include "tilemap.hh"
+
+
+namespace dc {
+
+
+class tilemap::tilemap_impl : public mippleton<tilemap_impl>
+{
+public:
+       tilemap_impl(const std::string& name) :
+               mippleton<tilemap_impl>(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<std::string,serializable_ptr> rootMap;
+
+                       if (root->get(rootMap))
+                       {
+                               std::map<std::string,serializable_ptr>::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: *************************************************/
+
index 50e5c3dd72d7620358713cafe8748c457ac29581..f2f76ab5fc8849f9b89e02b98ed69a48ef0b8acc 100644 (file)
  * Small subclass to give some basic tile-mapping functionality to textures.
  */
 
-#include <cassert>
-
 #include <boost/shared_ptr.hpp>
 
-#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<tilemap_impl> impl;
 };
 
 
@@ -156,3 +104,5 @@ private:
 
 #endif // _TILEMAP_HH_
 
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
index 2c7a1cbc39e05f3957422cc7de6f7d0f71db6b64..de601ee5db999fa8e54ce456ac7a840216565bbb 100644 (file)
@@ -30,8 +30,6 @@
 #include <ctime>
 #include <cerrno>
 
-#include <SDL/SDL.h>
-
 #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 <SDL/SDL.h>
 
 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: *************************************************/
+
index 3de2a952887af489de4ad20c9409b339ff6c2ea3..8506327d09c763cc8079513615e5b33b76a1deb7 100644 (file)
@@ -65,3 +65,5 @@ void sleep(scalar seconds, bool absolute = false);
 
 #endif // _TIMER_HH_
 
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
index 715c407cd7e3803968b5e113523b3a364ea4334b..6960a0bafac8827abfabaa51cd5fe30fc1e7cbcf 100644 (file)
@@ -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: *************************************************/
+
index a16181cefc17baaadfb46812a0329c6d31e67650..ad896506161635f8ac60ec8a6dfe387773256d0c 100644 (file)
@@ -118,3 +118,5 @@ typedef boost::shared_ptr<video> video_ptr;
 
 #endif // _VIDEO_HH_
 
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
index 8b359e1310403f93ee984835f7c4348346c6f3ac..e2e7c520c5fc8234d8064182f4d3ebcbc60184a2 100644 (file)
@@ -1,25 +1,25 @@
 
 # To make yajl works as a convenience library, the directory src/api must be
-# renamed to src/yajl, and any sources or headers which refer to headers in in
-# that directory will need to be modified to look in the new directory.
+# renamed to src/yajl, and any sources or headers which refer to headers in that
+# directory will need to be modified to look in the new directory.
 
-noinst_LIBRARIES = libyajl.a
+noinst_LTLIBRARIES = libyajl.la
 
-libyajl_a_SOURCES = \
-                                       src/yajl.c \
-                                       src/yajl_alloc.c \
-                                       src/yajl_alloc.h \
-                                       src/yajl_buf.c \
-                                       src/yajl_buf.h \
-                                       src/yajl_bytestack.h \
-                                       src/yajl_encode.c \
-                                       src/yajl_encode.h \
-                                       src/yajl_gen.c \
-                                       src/yajl_lex.c \
-                                       src/yajl_lex.h \
-                                       src/yajl_parser.c \
-                                       src/yajl_parser.h \
-                                       $(ENDLIST)
+libyajl_la_SOURCES = \
+                                        src/yajl.c \
+                                        src/yajl_alloc.c \
+                                        src/yajl_alloc.h \
+                                        src/yajl_buf.c \
+                                        src/yajl_buf.h \
+                                        src/yajl_bytestack.h \
+                                        src/yajl_encode.c \
+                                        src/yajl_encode.h \
+                                        src/yajl_gen.c \
+                                        src/yajl_lex.c \
+                                        src/yajl_lex.h \
+                                        src/yajl_parser.c \
+                                        src/yajl_parser.h \
+                                        $(ENDLIST)
 
 noinst_HEADERS = \
                                 src/yajl/yajl_common.h \
@@ -27,5 +27,5 @@ noinst_HEADERS = \
                                 src/yajl/yajl_parse.h \
                                 $(ENDLIST)
 
-libyajl_a_CPPFLAGS = -Isrc
+libyajl_la_CPPFLAGS = -Isrc
 
This page took 0.24706 seconds and 4 git commands to generate.