git repos / blockattack-game

commit 89c4a3a6

sago007 · 2008-08-29 14:32
89c4a3a64d3d8f2702207048392eb84922f732c9 patch · browse files
parent 9bf30037653e8e01094c0e5fad929feb8aca6515

reorganizing


git-svn-id: https://blockattack.svn.sourceforge.net/svnroot/blockattack/trunk@31 9d7177f8-192b-0410-8f35-a16a89829b06

Changed files

A COPYING
A man/README
A man/SConscript
A man/blockattack.sgml
A source/code/AUTHORS
A source/code/BlockGame.hpp
A source/code/NetworkThing.hpp
A source/code/README
A source/code/ReadKeyboard.cpp
A source/code/ReadKeyboard.h
A source/code/SFont.c
A source/code/SFont.h
A source/code/common.cc
A source/code/common.h
A source/code/editor/BoardHolder.cpp
A source/code/editor/BoardHolder.hpp
A source/code/editor/EditorInterface.cpp
A source/code/editor/EditorInterface.hpp
A source/code/editor/TheBoard.cpp
A source/code/editor/TheBoard.hpp
A source/code/editor/editorMain.cpp
A source/code/editor/editorMain.hpp
A source/code/highscore.cpp
A source/code/highscore.h
A source/code/joypad.cpp
A source/code/joypad.h
A source/code/listFiles.cpp
A source/code/listFiles.h
A source/code/main.cpp
A source/code/mainVars.hpp
A source/code/replay.cpp
A source/code/replay.h
A source/code/stats.cc
A source/code/stats.h
A source/code/ttfont.cc
A source/code/ttfont.h
A source/code/uploadReplay.cc
A source/code/uploadReplay.h
diff --git a/COPYING b/COPYING new file mode 100755 index 0000000..d60c31a --- /dev/null +++ b/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <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 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/man/README b/man/README new file mode 100644 index 0000000..d0403d8 --- /dev/null +++ b/man/README
@@ -0,0 +1,2 @@
+to regenerate the manpage:
+docbook-to-man blockattack.sgml|gzip -9 > blockattack.6.gz
diff --git a/man/SConscript b/man/SConscript new file mode 100644 index 0000000..d03c340 --- /dev/null +++ b/man/SConscript
@@ -0,0 +1,8 @@
+#-------------#
+# Import Vars #
+#-------------#
+Import('*')
+
+env.Install ('$destdir/$mandir/man6/','blockattack.6.gz')
+env.Alias('install', '$destdir/$mandir/man6/')
+
diff --git a/man/blockattack.sgml b/man/blockattack.sgml new file mode 100644 index 0000000..355272d --- /dev/null +++ b/man/blockattack.sgml
@@ -0,0 +1,115 @@
+<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN" [
+
+<!-- Process this file with docbook-to-man to generate an nroff manual
+ page: `docbook-to-man manpage.sgml > manpage.1'. You may view
+ the manual page with: `docbook-to-man manpage.sgml | nroff -man |
+ less'. A typical entry in a Makefile or Makefile.am is:
+
+manpage.1: manpage.sgml
+ docbook-to-man $< > $@
+
+
+ The docbook-to-man binary is found in the docbook-to-man package.
+ Please remember that if you create the nroff version in one of the
+ debian/rules file targets (such as build), you will need to include
+ docbook-to-man in your Build-Depends control field.
+
+ -->
+
+ <!-- Fill in your name for FIRSTNAME and SURNAME. -->
+ <!ENTITY dhfirstname "<firstname>Goneri</firstname>">
+ <!ENTITY dhsurname "<surname>Le Bouder</surname>">
+ <!-- Please adjust the date whenever revising the manpage. -->
+ <!ENTITY dhdate "<date>mai 19, 2006</date>">
+ <!-- SECTION should be 1-8, maybe w/ subsection other parameters are
+ allowed: see man(7), man(1). -->
+ <!ENTITY dhsection "<manvolnum>6</manvolnum>">
+ <!ENTITY dhemail "<email>goneri@rulezlan.org</email>">
+ <!ENTITY dhusername "Goneri Le Bouder">
+ <!ENTITY dhucpackage "<refentrytitle>BLOCKATTACK</refentrytitle>">
+ <!ENTITY dhpackage "blockattack">
+
+ <!ENTITY debian "<productname>Debian</productname>">
+ <!ENTITY gnu "<acronym>GNU</acronym>">
+ <!ENTITY gpl "&gnu; <acronym>GPL</acronym>">
+]>
+
+<refentry>
+ <refentryinfo>
+ <address>
+ &dhemail;
+ </address>
+ <author>
+ &dhfirstname;
+ &dhsurname;
+ </author>
+ <copyright>
+ <year>2006</year>
+ <holder>&dhusername;</holder>
+ </copyright>
+ &dhdate;
+ </refentryinfo>
+ <refmeta>
+ &dhucpackage;
+
+ &dhsection;
+ </refmeta>
+ <refnamediv>
+ <refname>&dhpackage;</refname>
+
+ <refpurpose>Rise of the Blocks</refpurpose>
+ </refnamediv>
+ <refsect1>
+ <title>DESCRIPTION</title>
+
+ <para>This manual page documents briefly the
+ <command>&dhpackage;</command>.
+ </para>
+
+ <para>This manual page was written for the &debian; distribution
+ because the original program does not have a manual page.
+ .</para>
+
+
+ </refsect1>
+ <refsect1>
+ <title>OPTIONS</title>
+
+ <para>These programs don't have specific option.</para>
+
+ </refsect1>
+ <refsect1>
+ <title>AUTHOR</title>
+
+ <para>This manual page was written by &dhusername; &dhemail; for
+ the &debian; system (but may be used by others). Permission is
+ granted to copy, distribute and/or modify this document under
+ the terms of the &gnu; General Public License, Version 2 any
+ later version published by the Free Software Foundation.
+ </para>
+ <para>
+ On Debian systems, the complete text of the GNU General Public
+ License can be found in /usr/share/common-licenses/GPL.
+ </para>
+
+ </refsect1>
+</refentry>
+
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-omittag:t
+sgml-shorttag:t
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:2
+sgml-indent-data:t
+sgml-parent-document:nil
+sgml-default-dtd-file:nil
+sgml-exposed-tags:nil
+sgml-local-catalogs:nil
+sgml-local-ecat-files:nil
+End:
+-->
+
+
diff --git a/source/code/AUTHORS b/source/code/AUTHORS new file mode 100644 index 0000000..ea73053 --- /dev/null +++ b/source/code/AUTHORS
@@ -0,0 +1,12 @@
+Block Attack - Rise of the Blocks by
+Poul Sander <blockattack@poulsander.com>
+http://blockattack.sf.net
+
+Gonéri Le Bouder
+Done some work for making it work with SHAREDIR and all Scons scripts
+
+Contains SFont - SDL Font Library by
+Karl Bartel <karlb@gmx.net>
+
+Jordà Polo
+Two patches
diff --git a/source/code/BlockGame.hpp b/source/code/BlockGame.hpp new file mode 100644 index 0000000..1ad5da4 --- /dev/null +++ b/source/code/BlockGame.hpp
@@ -0,0 +1,2215 @@
+/*
+ * BlockGame.hpp (this was cut from main.cpp for the overview)
+ * Copyright (C) 2005 Poul Sander
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Poul Sander
+ * R�veh�jvej 36, V. 1111
+ * 2800 Kgs. Lyngby
+ * DENMARK
+ * blockattack@poulsander.com
+ */
+
+////////////////////////////////////////////////////////////////////////////////
+//The BloackGame class represents a board, score, time etc. for a single player/
+////////////////////////////////////////////////////////////////////////////////
+class BlockGame {
+private:
+ int prevTowerHeight;
+ bool bGarbageFallLeft;
+
+ bool bDraw;
+ bool bReplaying; //true if we are watching a replay
+ bool bNetworkPlayer; //must recieve packages from the net
+ bool bDisconnected; //The player has disconnected
+ Uint32 nextGarbageNumber;
+ Uint32 pushedPixelAt;
+ Uint32 nrPushedPixel, nrFellDown, nrStops;
+ bool garbageToBeCleared[7][30];
+ Uint32 lastAImove;
+
+ Sint16 AI_LineOffset; //how many lines have changed since command
+ string strHolder;
+ Uint32 hangTicks; //How many times have hang been decreased?
+ //int the two following index 0 may NOT be used (what the fuck did I meen?)
+ Uint8 chainSize[NUMBEROFCHAINS]; //Contains the chains
+ bool chainUsed[NUMBEROFCHAINS]; //True if the chain is used
+
+ Uint32 nextRandomNumber;
+
+ Uint16 rand2() {
+ nextRandomNumber = nextRandomNumber*1103515245 + 12345;
+ return ((Uint16)(nextRandomNumber/65536)) % 32768;
+ }
+
+ int firstUnusedChain() {
+ bool found=false;
+ int i = 0;
+ while (!found) {
+ if (!chainUsed[++i])
+ found=true;
+ if (i>NUMBEROFCHAINS-2)
+ found=true;
+ }
+ return i;
+ }
+
+public:
+ char name[30];
+ Uint32 gameStartedAt;
+ Uint32 gameEndedAfter; //How long did the game last?
+ int linesCleared;
+ SDL_Surface* sBoard;
+ int TowerHeight;
+ BlockGame *garbageTarget;
+ Sint32 board[7][30];
+ int stop;
+ int speedLevel;
+ int pixels;
+ int MovesLeft;
+ bool timetrial, stageClear, vsMode, puzzleMode;
+ int Level; //Only used in stageClear and puzzle (not implemented)
+ int stageClearLimit; //stores number of lines user must clear to win
+ int topx, topy;
+ int combo;
+ int chain;
+ int cursorx; //stores cursor position
+ int cursory; // -||-
+ double speed, baseSpeed; //factor for speed. Lower value = faster gameplay
+ Uint32 score;
+ bool bGameOver;
+ bool hasWonTheGame;
+ int AI_MoveSpeed; //How often will the computer move? milliseconds
+ bool AI_Enabled;
+ Replay theReplay; //Stores the replay
+
+ Uint32 handicap;
+
+ //Constructor
+ BlockGame(int tx, int ty) {
+ tmp = IMG_Load2((char*)"gfx/BackBoard.png");
+ sBoard = SDL_DisplayFormat(tmp);
+ SDL_FreeSurface(tmp);
+ srand((int)time(NULL));
+ nrFellDown = 0;
+ nrPushedPixel = 0;
+ garbageTarget = this;
+ nrStops=0;
+ topx = tx;
+ topy = ty;
+ cursorx = 2;
+ cursory = 3;
+ stop = 0;
+ pixels = 0;
+ score = 0;
+ bGameOver = false;
+ bDraw = false;
+ bReplaying=false; //No replay by default
+ bDisconnected=false;
+ bNetworkPlayer = false;
+ timetrial = false;
+ stageClear = false;
+ vsMode = false;
+ puzzleMode = false;
+ linesCleared = 0;
+ AI_Enabled = false;
+ AI_MoveSpeed=100;
+ hasWonTheGame = false;
+ combo=0; //counts
+ chain=0;
+ hangTicks = 0;
+ baseSpeed = 0.5; //All other speeds are relative to this
+ speed = baseSpeed;
+ speedLevel = 1;
+ gameStartedAt = SDL_GetTicks();
+ gameEndedAfter = 0;
+ pushedPixelAt = gameStartedAt;
+ nextGarbageNumber = 10;
+ handicap=0;
+ for (int i=0;i<7;i++)
+ for (int j=0;j<30;j++) {
+ board[i][j] = -1;
+ }
+ for (int i=0;i<NUMBEROFCHAINS;i++) {
+ chainUsed[i]=false;
+ chainSize[i] = 0;
+ }
+ theReplay = Replay();
+ showGame = true; //The game is now active
+ } //Constructor
+
+ //Deconstructor, never really used... game used to crash when called, cause of the way sBoard was created
+ //It should work now and can be used if we want to assign more players in network games that we need to free later
+ ~BlockGame() {
+ SDL_FreeSurface(sBoard);
+ }
+
+ void setGameSpeed(Uint8 globalSpeedLevel) {
+ switch (globalSpeedLevel) {
+ case 0:
+ baseSpeed=0.5;
+ break;
+ case 1:
+ baseSpeed=0.4;
+ break;
+ case 2:
+ baseSpeed=0.3;
+ break;
+ case 3:
+ baseSpeed=0.25;
+ break;
+ case 4:
+ baseSpeed=0.2;
+ break;
+ default:
+ baseSpeed=0.15;
+ break;
+ };
+ }
+
+ void setHandicap(Uint8 globalHandicap) {
+ handicap=1000*((Uint32)globalHandicap);
+ }
+
+ //Set the move speed of the AI based on the aiLevel parameter
+ void setAIlevel(Uint8 aiLevel) {
+ AI_MoveSpeed=120-(20*(aiLevel-3));
+ };
+
+#ifdef NETWORK
+#define garbageStackSize 10
+ Uint8 garbageStack[garbageStackSize][3]; //A garbage stack with space for 10 garbage blocks. 0=x,1=y,2=type
+ int garbageStackUsed;
+
+ void emptyGarbageStack() {
+ for (int i=0;i<10;i++)
+ for (int j=0;j<3;j++)
+ garbageStack[i][j] = 0;
+ garbageStackUsed = 0;
+ }
+
+ bool pushGarbage(Uint8 width, Uint8 height, Uint8 type) {
+ if (garbageStackUsed>=garbageStackSize)
+ return false;
+ garbageStack[garbageStackUsed][0]=width;
+ garbageStack[garbageStackUsed][1]=height;
+ garbageStack[garbageStackUsed][2]=type;
+ garbageStackUsed++;
+ return true;
+ }
+
+ bool popGarbage(Uint8 *width, Uint8 *height, Uint8 *type) {
+ if (garbageStackUsed<1)
+ return false;
+ garbageStackUsed--;
+ *width=garbageStack[garbageStackUsed][0];
+ *height=garbageStack[garbageStackUsed][1];
+ *type=garbageStack[garbageStackUsed][2];
+ return true;
+ }
+
+#endif
+
+ //Loads BackBoard again if surface format has changed
+ void convertSurface() {
+ SDL_FreeSurface(sBoard);
+ cout << "2.1" << endl;
+ sBoard = SDL_DisplayFormat(backBoard);
+ cout << "2.2" << endl;
+ }
+
+ //Instead of creating new object new game is called, to prevent memory leaks
+ void NewGame(int tx, int ty) {
+ stageButtonStatus = SBdontShow;
+ bReplaying = false;
+ bNetworkPlayer=false;
+ bDisconnected =false;
+ nrFellDown = 0;
+ lastNrOfPlayers = 1; //At least one player :-)
+ nrPushedPixel = 0;
+ nrStops = 0;
+ topx = tx;
+ topy = ty;
+ cursorx = 2;
+ cursory = 3;
+ stop = 0;
+ pixels = 0;
+ score = 0;
+ bGameOver = false;
+ bDraw = false;
+ timetrial = false;
+ stageClear = false;
+ linesCleared = 0;
+ hasWonTheGame = false;
+ vsMode = false;
+ puzzleMode = false;
+ combo=0;
+ chain=0;
+ AI_Enabled = false;
+ baseSpeed= 0.5;
+ speed = baseSpeed;
+ speedLevel = 1;
+ gameStartedAt = SDL_GetTicks()+3000;
+ pushedPixelAt = gameStartedAt;
+ nextGarbageNumber = 10;
+ handicap=0;
+ for (int i=0;i<7;i++)
+ for (int j=0;j<30;j++) {
+ board[i][j] = -1;
+ }
+ for (int i=0;i<NUMBEROFCHAINS;i++) {
+ chainUsed[i]=false;
+ chainSize[i] = 0;
+ }
+ lastAImove = SDL_GetTicks()+3000;
+ showGame = true;
+ theReplay = Replay();
+ } //NewGame
+
+ //Starts a new stage game, takes level as input!
+ void NewStageGame(int level, int tx, int ty) {
+ if (level > -1) {
+ NewGame(tx, ty);
+ stageClear = true;
+ Level = level;
+ stageClearLimit = 30+(Level%6)*10;
+ baseSpeed = 0.5/((double)(Level*0.5)+1.0);
+ speed = baseSpeed;
+ }
+ }
+
+ void NewPuzzleGame(int level, int tx, int ty) {
+ if (level>-1) {
+ NewGame(tx, ty);
+ puzzleMode = true;
+ Level = level;
+ MovesLeft = nrOfMovesAllowed[Level];
+ for (int i=0;i<6;i++)
+ for (int j=0;j<12;j++) {
+ board[i][j+1] = puzzleLevels[Level][i][j];
+ }
+ baseSpeed = 100000;
+ speed = 100000;
+
+ //Now push the blines up
+ for (int i=19;i>0;i--)
+ for (int j=0;j<6;j++) {
+ board[j][i] = board[j][i-1];
+ }
+ for (int j=0;j<6;j++) {
+ board[j][0] = rand() % 6;
+ if (j > 0) {
+ if (board[j][0] == board[j-1][0])
+ board[j][0] = rand() % 6;
+ }
+ if (board[j][0] == board[j][1])
+ board[j][0] = 6;
+ if (board[j][0] == board[j][1])
+ board[j][0] = 6;
+
+ }
+ }
+ }
+
+ //Replay the current level
+ void retryLevel()
+ {
+ if(puzzleMode)
+ NewPuzzleGame(Level,topx,topy);
+ else
+ if(stageClear)
+ NewStageGame(Level,topx,topy);
+ }
+
+ //Play the next level
+ void nextLevel()
+ {
+ if(puzzleMode)
+ {
+ if(Level<nrOfPuzzles-1)
+ NewPuzzleGame(Level+1,topx,topy);
+ }
+ else
+ if(stageClear)
+ {
+ if(Level<50-1)
+ NewStageGame(Level+1,topx,topy);
+ }
+ }
+
+ //Starts new Vs Game (two Player)
+ void NewVsGame(int tx, int ty, BlockGame *target) {
+ NewGame(tx, ty);
+ vsMode = true;
+ putStartBlocks();
+ garbageTarget = target;
+ }
+
+ //Starts new Vs Game (two Player)
+ void NewVsGame(int tx, int ty, BlockGame *target, bool AI) {
+ NewGame(tx, ty);
+ vsMode = true;
+ AI_Enabled = AI;
+ putStartBlocks();
+ garbageTarget = target;
+ }
+
+ //Go in Demonstration mode, no movement
+ void Demonstration(bool toggle) {
+ speed=0;
+ baseSpeed = 0;
+ }
+
+ //We want to play the replay (must have been loaded beforehand)
+ void playReplay(int tx, int ty) {
+ NewGame(tx, ty);
+ gameStartedAt = SDL_GetTicks();
+ bReplaying = true; //We are playing, no calculations
+ bNetworkPlayer = false; //Take input from replay file
+ }
+
+#ifdef NETWORK
+ //network play
+ void playNetwork(int tx, int ty) {
+ NewGame(tx, ty);
+ gameStartedAt = SDL_GetTicks();
+ bReplaying = false; //We are playing, no calculations
+ bNetworkPlayer = true; //Don't Take input from replay file
+ emptyGarbageStack();
+ }
+#endif
+
+ //Prints "winner" and ends game
+ void setPlayerWon() {
+ if (!bGameOver)
+ gameEndedAfter = SDL_GetTicks()-gameStartedAt; //We game ends now!
+ theReplay.setFinalFrame(getPackage(), 1);
+ bGameOver = true;
+ hasWonTheGame = true;
+ showGame = false;
+ if (SoundEnabled)Mix_PlayChannel(1, applause, 0);
+ }
+
+ //void SetGameOver();
+
+ //Sets disconnected:
+ void setDisconnect() {
+ bDisconnected = true;
+ SetGameOver();
+ }
+
+ //Prints "draw" and ends the game
+ void setDraw() {
+ bGameOver = true;
+ theReplay.setFinalFrame(getPackage(), 3);
+ hasWonTheGame = false;
+ bDraw = true;
+ showGame = false;
+ Mix_HaltChannel(1);
+ }
+
+ //Function to get a boardpackage
+ boardPackage getPackage() {
+ boardPackage bp;
+ if(SDL_GetTicks()<gameStartedAt)
+ bp.time = 0;
+ else
+ bp.time = (Uint32)(SDL_GetTicks()-gameStartedAt);
+ for (int i=0;i<6;i++)
+ for (int j=0;j<13;j++) {
+ if (board[i][j]%10<7)
+ bp.brick[i][j]=board[i][j]%10+1;
+ if ((board[i][j]/1000000)%10>0) {
+ int aInt=0; //N=1, S=2, W=4, E=8
+ if (i==0)
+ aInt+=4;
+ else
+ if ((board[i-1][j])!=(board[i][j]))
+ aInt+=4;
+ if (i==5)
+ aInt+=8;
+ else
+ if ((board[i+1][j])!=(board[i][j]))
+ aInt+=8;
+ if (j==0)
+ aInt+=2;
+ else
+ if ((board[i][j-1])!=(board[i][j]))
+ aInt+=2;
+ if ((board[i][j+1])!=(board[i][j]))
+ aInt+=1;
+ switch (aInt) {
+ case 8:
+ bp.brick[i][j]=8;
+ break;
+ case 7:
+ bp.brick[i][j]=10;
+ break;
+ case 11:
+ bp.brick[i][j]=11;
+ break;
+ case 9:
+ bp.brick[i][j]=12;
+ break;
+ case 5:
+ bp.brick[i][j]=13;
+ break;
+ case 6:
+ bp.brick[i][j]=14;
+ break;
+ case 10:
+ bp.brick[i][j]=15;
+ break;
+ case 3: //M
+ bp.brick[i][j]=16;
+ break;
+ case 0:
+ bp.brick[i][j]=17;
+ break;
+ case 1:
+ bp.brick[i][j]=18;
+ break;
+ case 2:
+ bp.brick[i][j]=19;
+ break;
+ case 4:
+ bp.brick[i][j]=20;
+ break;
+ default:
+ bp.brick[i][j]=0;
+ };
+ //cout << "garbage added to replay: " << aInt << endl;
+ }
+ if ((board[i][j]/BLOCKHANG)%10==1) //If "get ready"
+ bp.brick[i][j]+=30;
+ }
+ bp.cursorX = (Uint8)cursorx;
+ bp.cursorY = (Uint8)cursory;
+ bp.score = (Uint32)score;
+ bp.pixels = (Uint8)pixels;
+ bp.chain = (Uint8)chain;
+ bp.speed = (Uint8)speedLevel;
+ Uint8 result = 0;
+ if (bGameOver)
+ result+=1;
+ if (hasWonTheGame)
+ result+=2;
+ if (bDraw)
+ result+=4;
+ bp.result = (Uint8)result;
+ return bp;
+ }
+
+ //Takes a package and sets the board like it
+ void setBoard(boardPackage bp) {
+ //gameStartedAt = SDL_GetTicks()-bp.time;
+ for (int i=0;i<6;i++)
+ for (int j=0;j<13;j++) {
+ //if(bp.brick[i][j]/8==0)
+ board[i][j]=bp.brick[i][j]-1;
+ //else
+ // board[i][j]=-1;
+ }
+ cursorx=bp.cursorX;
+ cursory=bp.cursorY;
+ score=bp.score;
+ pixels=bp.pixels;
+ chain=bp.chain;
+ speedLevel=bp.speed;
+ Uint8 result = bp.result;
+ if (result%2==1) {
+ bGameOver=true;
+ result-=1;
+ }
+ if (result%4==2) {
+ hasWonTheGame = true;
+ result-=2;
+ }
+ if (result==4) {
+ bDraw = true;
+ }
+
+ }
+
+ //Test if LineNr is an empty line, returns false otherwise.
+ bool LineEmpty(int lineNr) {
+ bool empty = true;
+ for (int i = 0; i <7; i++)
+ if (board[i][lineNr] != -1)
+ empty = false;
+ return empty;
+ }
+
+ //Test if the entire board is empty (used for Puzzles)
+ bool BoardEmpty() {
+ bool empty = true;
+ for (int i=0;i<6;i++)
+ for (int j=1;j<13;j++)
+ if (board[i][j] != -1)
+ empty = false;
+ return empty;
+ }
+
+ //Anything that the user can't move? In that case Game Over cannot occur
+ bool hasStaticContent() {
+ for (int i=0;i<6;i++)
+ for (int j=1;j<13;j++)
+ if (board[i][j] >= 10000000) //Higher than this means combos (garbage is static, but the stack is static but nothing to do about it)
+ return true; //They are static
+ return false; //Return false if no static object found
+ }
+
+ /*
+ * Generates some blocks so the user don't see a board without blocks
+ */
+ //void putStartBlocks(Uint32);
+
+ void putStartBlocks() {
+ putStartBlocks(time(0));
+ }
+
+ void putStartBlocks(Uint32 n) {
+ for (int i=0;i<7;i++)
+ for (int j=0;j<30;j++) {
+ board[i][j] = -1;
+ }
+ nextRandomNumber = n;
+ int choice = rand2()%3; //Pick a random layout
+ switch (choice) {
+ case 0:
+ //row 0:
+ board[0][0]=1;
+ board[1][0]=0;
+ board[2][0]=4;
+ board[3][0]=3;
+ board[4][0]=3;
+ board[5][0]=5;
+ //row 1:
+ board[0][1]=1;
+ board[1][1]=4;
+ board[2][1]=2;
+ board[3][1]=0;
+ board[4][1]=4;
+ board[5][1]=5;
+ //row 2:
+ board[0][2]=2;
+ board[1][2]=3;
+ board[2][2]=0;
+ board[3][2]=4;
+ board[4][2]=1;
+ board[5][2]=1;
+ //row 3:
+ board[0][3]=3;
+ board[1][3]=2;
+ board[2][3]=3;
+ board[3][3]=1;
+ board[4][3]=0;
+ board[5][3]=4;
+ //row 4:
+ board[0][4]=2;
+ board[1][4]=3;
+ board[2][4]=3;
+ board[3][4]=1;
+ board[4][4]=4;
+ board[5][4]=0;
+ //row 5:
+ board[0][5]=-1;
+ board[1][5]=5;
+ board[2][5]=5;
+ board[3][5]=-1;
+ board[4][5]=1;
+ board[5][5]=-1;
+ break;
+ case 1:
+ //row 0:
+ board[0][0]=3;
+ board[1][0]=5;
+ board[2][0]=0;
+ board[3][0]=0;
+ board[4][0]=4;
+ board[5][0]=2;
+ //row 1:
+ board[0][1]=3;
+ board[1][1]=5;
+ board[2][1]=-1;
+ board[3][1]=5;
+ board[4][1]=4;
+ board[5][1]=2;
+ //row 2:
+ board[0][2]=2;
+ board[1][2]=-1;
+ board[2][2]=-1;
+ board[3][2]=4;
+ board[4][2]=0;
+ board[5][2]=3;
+ //row 3:
+ board[0][3]=2;
+ board[5][3]=3;
+ break;
+ default:
+ //row 0:
+ board[0][0]=4;
+ board[1][0]=5;
+ board[2][0]=2;
+ board[3][0]=0;
+ board[4][0]=1;
+ board[5][0]=5;
+ //row 1:
+ board[0][1]=4;
+ board[1][1]=5;
+ board[2][1]=2;
+ board[3][1]=1;
+ board[4][1]=0;
+ board[5][1]=2;
+ //row 2:
+ board[0][2]=2;
+ board[1][2]=4;
+ board[2][2]=-1;
+ board[3][2]=0;
+ board[4][2]=1;
+ board[5][2]=5;
+ //row 3:
+ board[0][3]=4;
+ board[1][3]=2;
+ board[2][3]=-1;
+ board[3][3]=1;
+ board[4][3]=0;
+ board[5][3]=2;
+ //row 4:
+ board[0][4]=4;
+ board[1][4]=2;
+ board[2][4]=-1;
+ board[3][4]=0;
+ board[4][4]=1;
+ board[5][4]=-1;
+ break;
+ };
+ }
+
+ //decreases hang for all hanging blocks and wait for waiting blocks
+ void ReduceStuff() {
+ Uint32 howMuchHang = (SDL_GetTicks() - FRAMELENGTH*hangTicks)/FRAMELENGTH;
+ if (howMuchHang>0) {
+ for (int i=0; i<7; i++)
+ for (int j=0; j<30; j++) {
+ if ((board[i][j]/BLOCKHANG)%10==1) {
+ int hangNumber = (board[i][j]/10)%100;
+ if (hangNumber<=howMuchHang) {
+ board[i][j]-=BLOCKHANG;
+ board[i][j]-=hangNumber*10;
+ }
+ else {
+ board[i][j]-=10*howMuchHang;
+ }
+ }
+ if ((board[i][j]/BLOCKWAIT)%10==1) {
+ int hangNumber = (board[i][j]/10)%100;
+ if (hangNumber<=howMuchHang) {
+ //The blocks must be cleared
+ board[i][j]-=hangNumber*10;
+ }
+ else {
+ board[i][j]-=10*howMuchHang;
+ }
+ }
+ }
+ }
+ hangTicks+=howMuchHang;
+ }
+
+ //Creates garbage using a given wide and height
+ bool CreateGarbage(int wide, int height) {
+#ifdef NETWORK
+ if (bNetworkPlayer) {
+ pushGarbage(wide, height, 0);
+ }
+ else
+#endif
+ {
+ if (wide>6) wide = 6;
+ if (height>12) height = 12;
+ int startPosition = 12;
+ while ((!(LineEmpty(startPosition))) || (startPosition == 29))
+ startPosition++;
+ if (startPosition == 29) return false; //failed to place blocks
+ if (29-startPosition<height) return false; //not enough space
+ int start, end;
+ if (bGarbageFallLeft)
+ {
+ start=0;
+ end=start+wide;
+ }
+ else
+ {
+ start=6-wide;
+ end = 6;
+ }
+ for (int i = startPosition; i <startPosition+height; i++)
+ for (int j = start; j < end; j++) {
+ board[j][i] = 1000000+nextGarbageNumber;
+ }
+ nextGarbageNumber++;
+ if (nextGarbageNumber>999999) nextGarbageNumber = 10;
+ bGarbageFallLeft = !(bGarbageFallLeft);
+ return true;
+ }
+ }
+
+ //Creates garbage using a given wide and height
+ bool CreateGreyGarbage() {
+#ifdef NETWORK
+ if (bNetworkPlayer) {
+ pushGarbage(6, 1, 1);
+ }
+ else
+#endif
+ {
+ int startPosition = 12;
+ while ((!(LineEmpty(startPosition))) || (startPosition == 29))
+ startPosition++;
+ if (startPosition == 29) return false; //failed to place blocks
+ if (29-startPosition<1) return false; //not enough space
+ int start, end;
+ {
+ start=0;
+ end=6;
+ }
+ for (int i = startPosition; i <startPosition+1; i++)
+ for (int j = start; j < end; j++) {
+ board[j][i] = 2*1000000+nextGarbageNumber;
+ }
+ nextGarbageNumber++;
+ if (nextGarbageNumber>999999) nextGarbageNumber = 10;
+ return true;
+ }
+ }
+
+
+ //Clears garbage, must take one the lower left corner!
+ int GarbageClearer(int x, int y, int number, bool aLineToClear, int chain) {
+ if ((board[x][y])%1000000 != number) return -1;
+ if (aLineToClear) {
+ board[x][y] = rand() % 6;
+ board[x][y] += 10*HANGTIME+BLOCKHANG+CHAINPLACE*chain;
+ }
+ garbageToBeCleared[x][y] = false;
+ GarbageClearer(x+1, y, number, aLineToClear, chain);
+ GarbageClearer(x, y+1, number, false, chain);
+ return 1;
+ }
+
+ //Marks garbage that must be cleared
+ int GarbageMarker(int x, int y) {
+ if ((x>6)||(x<0)||(y<0)||(y>29)) return -1;
+ if (((board[x][y])/1000000 == 1)&&(garbageToBeCleared[x][y] == false)) {
+ garbageToBeCleared[x][y] = true;
+ //Float fill
+ GarbageMarker(x-1, y);
+ GarbageMarker(x+1, y);
+ GarbageMarker(x, y-1);
+ GarbageMarker(x, y+1);
+ }
+ return 1;
+ }
+
+ int FirstGarbageMarker(int x, int y) {
+ if ((x>6)||(x<0)||(y<0)||(y>29)) return -1;
+ if (((board[x][y])/1000000 == 2)&&(garbageToBeCleared[x][y] == false)) {
+ for (int i=0;i<6;i++)
+ garbageToBeCleared[i][y] = true;
+ }
+ else
+ if (((board[x][y])/1000000 == 1)&&(garbageToBeCleared[x][y] == false)) {
+ garbageToBeCleared[x][y] = true;
+ //Float fill
+ GarbageMarker(x-1, y);
+ GarbageMarker(x+1, y);
+ GarbageMarker(x, y-1);
+ GarbageMarker(x, y+1);
+ }
+ return 1;
+ }
+
+ //Clear Blocks if 3 or more is alligned (naive implemented)
+ void ClearBlocks() {
+
+ bool toBeCleared[7][30]; //true if blok must be removed
+
+ int previus=-1; //the last block checked
+ int combo=0;
+ for (int i=0;i<30;i++)
+ for (int j=0;j<7;j++) {
+ toBeCleared[j][i] = false;
+ garbageToBeCleared[j][i] = false;
+ }
+ for (int i=0;i<7;i++) {
+ bool faaling = false;
+ for (int j=0;j<30;j++) {
+ if ((faaling)&&(board[i][j]>-1)&&(board[i][j]%10000000<7)) {
+ board[i][j]+=BLOCKFALL;
+ }
+ if ((!faaling)&&((board[i][j]/BLOCKFALL)%10==1))
+ board[i][j]-=BLOCKFALL;
+ if (!((board[i][j]>-1)&&(board[i][j]%10000000<7)))
+ faaling=true;
+ if (((board[i][j]/1000000)%10==1)||((board[i][j]/1000000)%10==2)||((board[i][j]/BLOCKHANG)%10==1)||((board[i][j]/BLOCKWAIT)%10==1))
+ faaling = false;
+ }
+ }
+
+
+ for (int j=0;j<7;j++) {
+ previus = -1;
+ combo=0;
+
+ for (int i=1;i<30;i++) {
+ if ((board[j][i]>-1)&&(board[j][i]%10000000<7)) {
+ if (board[j][i]%10000000 == previus) {
+ combo++;
+ }
+ else {
+ if (combo>2)
+ for (int k = i-combo; k<i;k++) {
+ toBeCleared[j][k] = true;
+ }
+ combo=1;
+ previus = board[j][i]%10000000;
+ }
+ } //if board
+ else {
+ if (combo>2)
+ for (int k = i-combo; k<i;k++) {
+ toBeCleared[j][k] = true;
+ }
+ combo = 0;
+ previus = -1;
+ }
+
+ } //for i
+ } //for j
+
+
+ combo = 0;
+ chain = 0;
+ for (int i=0; i<6;i++)
+ for (int j=0; j<30;j++) {
+ //Clears blocks marked for clearing
+ Sint32 temp=board[i][j];
+ if (1==((temp/BLOCKWAIT)%10))
+ if (((temp/10)%100)==0) {
+ if (chainSize[chain]<chainSize[board[i][j]/10000000])
+ chain = board[i][j]/10000000;
+
+ theBallManeger.addBall(topx+40+i*50, topy+600-j*50, true, board[i][j]%10);
+ theBallManeger.addBall(topx+i*50, topy+600-j*50, false, board[i][j]%10);
+ theExplosionManeger.addExplosion(topx-10+i*50, topy+570-j*50);
+ board[i][j]=-2;
+ }
+ }
+ for (int i=0; i<7;i++) {
+ bool setChain=false;
+ for (int j=0; j<30;j++) {
+ if (board[i][j]==-1)
+ setChain=false;
+ if (board[i][j]==-2) {
+ board[i][j]=-1;
+ setChain=true;
+ if (SoundEnabled)Mix_PlayChannel(0, boing, 0);
+ }
+ if (board[i][j]!=-1)
+ if ((setChain)&&((board[i][j]/GARBAGE)%10!=1)&&((board[i][j]/GARBAGE)%10!=2)) {
+ board[i][j]=((board[i][j]%CHAINPLACE)+CHAINPLACE*chain);
+ //somethingsGottaFall = true;
+ }
+
+ }
+ }
+ combo=0;
+ int startvalue;
+ if (pixels == 0)
+ startvalue=1;
+ else
+ startvalue=0;
+ for (int i=startvalue;i<30;i++) {
+ previus=-1;
+ combo=0;
+ for (int j=0;j<7;j++) {
+ if (((board[j][i]>-1)&&(board[j][i]%10000000<7))) {
+ if (board[j][i]%10000000 == previus) {
+ combo++;
+ }
+ else {
+ if (combo>2)
+ for (int k = j-combo; k<j;k++) {
+ toBeCleared[k][i] = true;
+ }
+ combo=1;
+ previus = board[j][i]%10000000;
+ }
+ } //if board
+ else {
+ if (combo>2)
+ for (int k = j-combo; k<j;k++) {
+ toBeCleared[k][i] = true;
+ }
+ combo = 0;
+ previus = -1;
+ }
+
+ } //for j
+ } //for i
+ bool blockIsFalling[6][30]; //See that is falling
+ for (int i=0;i<30;i++)
+ for (int j=0;j<6;j++)
+ blockIsFalling[j][i] = false;
+
+
+
+ combo = 0;
+ chain = 0;
+ int grey = 0;
+ for (int i=0;i<30;i++)
+ for (int j=0;j<6;j++)
+ if (toBeCleared[j][i]) {
+ //see if any garbage is around:
+ FirstGarbageMarker(j-1, i);
+ FirstGarbageMarker(j+1, i);
+ FirstGarbageMarker(j, i-1);
+ FirstGarbageMarker(j, i+1);
+ //that is checked now :-)
+ if (board[j][i]%10000000==6)
+ grey++;
+ if ((vsMode) && (grey>2) && (board[j][i]%10000000==6))
+ garbageTarget->CreateGreyGarbage();
+ if ((board[j][i]>-1)&&(board[j][i]%10000000<7))
+ board[j][i]+=BLOCKWAIT+10*FALLTIME;
+
+ if (chainSize[board[j][i]/10000000]>chainSize[chain])
+ chain=board[j][i]/10000000;
+ combo++;
+ stop+=140*combo;
+ score +=10;
+ if (combo>3)
+ score+=3*combo; //More points if more cleared simontanously
+ }
+ score+=chainSize[chain]*100;
+ if (chain==0) {
+ chain=firstUnusedChain();
+ chainSize[chain]=0;
+ chainUsed[chain]=true;
+ }
+ chainSize[chain]++;
+ for (int i=0;i<30;i++)
+ for (int j=0;j<6;j++) {
+ //if(board[j][i]/10==(BLOCKWAIT+10*FALLTIME)/10)
+ if (toBeCleared[j][i]) {
+ board[j][i]=(board[j][i]%10000000)+chain*10000000;
+ }
+ }
+
+ { //This is here we add text to screen!
+ bool dead = false;
+ for (int i=29;i>=0;i--)
+ for (int j=0;j<6;j++)
+ if (toBeCleared[j][i]) {
+ if (!dead) {
+ dead=true;
+ string tempS = itoa(chainSize[chain]);
+ if (chainSize[chain]>1)
+ theTextManeger.addText(topx-10+j*50, topy+600-i*50, tempS, 1000);
+ }
+ }
+ } //This was there text was added
+
+ if (vsMode)
+ switch (combo) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ break;
+ case 4:
+ garbageTarget->CreateGarbage(3, 1);
+ break;
+ case 5:
+ garbageTarget->CreateGarbage(4, 1);
+ break;
+ case 6:
+ garbageTarget->CreateGarbage(5, 1);
+ break;
+ case 7:
+ garbageTarget->CreateGarbage(6, 1);
+ break;
+ case 8:
+ garbageTarget->CreateGarbage(4, 1);
+ garbageTarget->CreateGarbage(4, 1);
+ break;
+ case 9:
+ garbageTarget->CreateGarbage(5, 1);
+ garbageTarget->CreateGarbage(4, 1);
+ break;
+ case 10:
+ garbageTarget->CreateGarbage(5, 1);
+ garbageTarget->CreateGarbage(5, 1);
+ break;
+ case 11:
+ garbageTarget->CreateGarbage(6, 1);
+ garbageTarget->CreateGarbage(5, 1);
+ break;
+ case 12:
+ garbageTarget->CreateGarbage(6, 1);
+ garbageTarget->CreateGarbage(6, 1);
+ break;
+ case 13:
+ garbageTarget->CreateGarbage(5, 1);
+ garbageTarget->CreateGarbage(5, 1);
+ garbageTarget->CreateGarbage(4, 1);
+ break;
+ default:
+ garbageTarget->CreateGarbage(5, 1);
+ garbageTarget->CreateGarbage(5, 1);
+ garbageTarget->CreateGarbage(4, 1);
+ break;
+ }
+ for (int i=0;i<30;i++)
+ for (int j=0;j<6;j++)
+ if (garbageToBeCleared[j][i]) {
+ GarbageClearer(j, i, board[j][i]%1000000, true, chain); //Clears the blocks and all blocks connected to it.
+ }
+
+ chain=0;
+
+ //Break chains (if a block is stable it is resetted to (chain == 0)):
+ for (int i=0;i<7;i++) {
+ bool faaling = false; //In the beginning we are NOT falling
+ for (int j=0;j<30;j++) {
+ if ((faaling)&&(board[i][j]>-1)&&(board[i][j]<7)) {
+ board[i][j]+=BLOCKFALL;
+ }
+ if ((!faaling)&&((board[i][j]/BLOCKFALL)%10==1))
+ board[i][j]-=BLOCKFALL;
+ if ((!faaling)&&(board[i][j]>0)&&(board[i][j]/10000000!=0)&&((board[i][j]/BLOCKWAIT)%10!=1)&&((board[i][j]/BLOCKHANG)%10!=1)) {
+ if (chainSize[board[i][j]/10000000]>chainSize[chain])
+ chain=board[i][j]/10000000;
+ board[i][j]=board[i][j]%10000000;
+ }
+ if (!((board[i][j]>-1)&&(board[i][j]<7)))
+ faaling=true;
+ if (((board[i][j]/1000000)%10==1)||((board[i][j]/BLOCKHANG)%10==1)||((board[i][j]/BLOCKWAIT)%10==1))
+ faaling = false;
+ }
+ }
+
+ //Create garbage as a result
+ //if((vsMode)&&(chainSize[chain]>1)) garbageTarget->CreateGarbage(6,chainSize[chain]-1);
+
+ //Calculate chain
+ chain=0;
+ for (int i=0; i<6;i++)
+ for (int j=0; j<30;j++) {
+ if (chainSize[board[i][j]/10000000]>chain)
+ chain=chainSize[board[i][j]/10000000];
+ }
+
+ //Make space in table for more things
+ if (chain==0)
+ for (int i=0;i<NUMBEROFCHAINS;i++)
+ if (chainUsed[i]==true) {
+ if ((vsMode)&&(chainSize[i]>1)) garbageTarget->CreateGarbage(6, chainSize[i]-1);
+ if ((SoundEnabled)&&(chainSize[i]>4))Mix_PlayChannel(1, applause, 0);
+ if(chainSize[i]>1 && !puzzleMode)
+ Stats::getInstance()->addOne((string)"chainX"+itoa(chainSize[i]));
+ chainUsed[i]=false;
+ }
+ } //ClearBlocks
+
+ //prints "Game Over" and ends game
+ void SetGameOver() {
+ if (!bGameOver)
+ gameEndedAfter = SDL_GetTicks()-gameStartedAt; //We game ends now!
+ theReplay.setFinalFrame(getPackage(), 0);
+ bGameOver = true;
+ showGame = false;
+ if(stageClear)
+ stageButtonStatus = SBstageClear;
+ }
+
+ //Moves all peaces a spot down if possible
+ int FallBlock(int x, int y, int number) {
+ if (y == 0) return -1;
+ if (x>0)
+ if (board[x-1][y] == number)
+ return -1;
+ int i=x;
+ bool canFall = true;
+ //checks a line of a garbage block and see if something is under it
+ while ((board[i][y] == number)&&(canFall)&&(i<6)) {
+ if (board[i][y-1] != -1) canFall = false;
+ i++;
+ }
+ if (canFall) {
+ //cout << "Now falling" << endl;
+ for (int j = x;j<i;j++) {
+ board[j][y-1] = board[j][y];
+ board[j][y] = -1;
+ }
+ }
+ return 0;
+ } //FallBlock
+
+
+ //Makes all Garbage fall one spot
+ void GarbageFall() {
+ for (int i=0;i<30;i++)
+ for (int j=0;j<7; j++) {
+ if ((((board[j][i]/1000000)%10) == 1)||(((board[j][i]/1000000)%10) == 2))
+ FallBlock(j, i, board[j][i]);
+ }
+ }
+
+ //Makes the blocks fall (it doesn't test time, this must be done before hand)
+ void FallDown() {
+ bool falling =false; //nothing is moving unless proven otherwise
+ for (int i=0;i<29;i++)
+ for (int j=0;j<6;j++) {
+ if ((board[j][i]==-1) && (board[j][i+1]!=-1) && (board[j][i+1]%BLOCKFALL<7)) {
+ board[j][i] = board[j][i+1];
+ board[j][i+1] = -1;
+ falling = true; //something is moving!
+ }
+ if ((board[j][i]/BLOCKWAIT)%10==1)
+ falling=true;
+ }
+ if (!falling) //If nothing is falling
+ {
+ if ((puzzleMode)&&(!bGameOver)&&(MovesLeft==0)&&(!(BoardEmpty()))) {
+ //Puzzle not won
+ SetGameOver();
+ stageButtonStatus = SBpuzzleMode;
+ }
+ }
+ GarbageFall(); //Makes the garbage fall
+ nrFellDown++; //Sets number of this fall, so we know then the next will occur
+ }
+
+ //Moves the cursor, receaves N,S,E or W as a char an moves as desired
+ void MoveCursor(char way) {
+ if (!bGameOver) //If game over nothing happends
+ {
+ if ((way == 'N') && ((cursory<10)||(TowerHeight>12) ||(((pixels==50)||(pixels==0)) && (cursory<11))))
+ cursory++;
+ if ((way == 'S') && (cursory>0))
+ cursory--;
+ if ((way == 'W') && (cursorx>0))
+ cursorx--;
+ if ((way == 'E') && (cursorx<4))
+ cursorx++;
+ }
+ }
+
+ //switches the two blocks at the cursor position, unless game over
+ void SwitchAtCursor() {
+ if ((board[cursorx][cursory+1]<7) && (board[cursorx+1][cursory+1]<7) && (!bGameOver) && ((!puzzleMode)||(MovesLeft>0)) && (gameStartedAt<SDL_GetTicks())) {
+ int temp = board[cursorx][cursory+1];
+ board[cursorx][cursory+1] = board[cursorx+1][cursory+1];
+ board[cursorx+1][cursory+1] = temp;
+ }
+ if ((puzzleMode)&&(gameStartedAt<SDL_GetTicks())&&(MovesLeft>0)) MovesLeft--;
+ }
+
+ //Generates a new line and moves the field one block up (restart puzzle mode)
+ void PushLine() {
+ //If not game over, not high tower and not puzzle mode
+ if ((!bGameOver) && TowerHeight<13 && (!puzzleMode) && (gameStartedAt<SDL_GetTicks())&&(chain==0)) {
+ for (int i=19;i>0;i--)
+ for (int j=0;j<6;j++) {
+ board[j][i] = board[j][i-1];
+ }
+ for (int j=0;j<6;j++) {
+ board[j][0] = rand2() % 4;
+ if (j > 0) {
+ if (board[j][0] == board[j-1][0])
+ board[j][0] = rand2() % 6;
+ }
+ if (board[j][0] == board[j][1])
+ board[j][0] = rand2() % 6;
+ if (board[j][0] == board[j][1])
+ board[j][0] = rand2() % 6;
+ while ((j>0)&&(board[j][0]==board[j-1][0]))
+ board[j][0] = rand2() % 6;
+ }
+ score+=1;
+ MoveCursor('N');
+ if (vsMode) {
+ if (rand2()%6==1)
+ board[rand2()%6][0]=6;
+ }
+ pixels = 0;
+ stop=0;
+ pushedPixelAt = SDL_GetTicks();
+ linesCleared++;
+ AI_LineOffset++;
+ nrPushedPixel=(int)((double)(pushedPixelAt-gameStartedAt)/(1000.0*speed));
+
+ if(!AI_Enabled && !bReplaying)
+ {
+ Stats::getInstance()->addOne("linesPushed");
+ }
+ } //if !bGameOver
+
+ //Restart Puzzle mode
+ if (puzzleMode && !bGameOver) {
+ //Reloads level
+ MovesLeft = nrOfMovesAllowed[Level];
+ for (int i=0;i<6;i++)
+ for (int j=0;j<12;j++) {
+ board[i][j+1] = puzzleLevels[Level][i][j];
+ }
+ score=0;
+ bGameOver=false;
+ showGame = true;
+ }
+
+ if ((TowerHeight>12) && (!puzzleMode)&&(!bGameOver)&&(chain==0)) {
+ if ((theTopScoresEndless.isHighScore(score))&&(!AI_Enabled)) {
+ if (SoundEnabled)Mix_PlayChannel(1, applause, 0);
+ theTopScoresEndless.addScore(name, score);
+ cout << "New high score!" << endl;
+ }
+ SetGameOver();
+ }
+
+
+ }//PushLine
+
+ //Pushes a single pixel, so it appears to scrool
+ void PushPixels() {
+ nrPushedPixel++;
+ if ((pixels < 50) && TowerHeight<13) {
+ pixels++;
+ }
+ else
+ PushLine();
+ if (pixels>50)
+ pixels=0;
+ }
+
+ //See how high the tower is, saved in integer TowerHeight
+ /*void FindTowerHeight()
+ * {
+ * /*
+ * This function needs to be corrected, if an empty line appears towerheight become to low!
+ * /
+ * bool found = false;
+ * bool notNew = false;
+ * TowerHeight = 0;
+ * for(int i=0; i<19;i++)
+ * //while(!found)
+ * {
+ * found = true;
+ * for(int j=0;j<6;j++)
+ * if(board[j][i] != -1)
+ * found = false;
+ * if((!found) && (notNew))
+ * notNew =false;
+ * if((found)&&(!notNew))
+ * {
+ * TowerHeight=i;
+ * notNew = true;
+ * }
+ * }
+ * TowerHeight--;
+ * }*/
+
+ //See how high the tower is, saved in integer TowerHeight
+ void FindTowerHeight() {
+ /*
+ * Old implementation, used until I find the bug in the other.
+ * This function has a bug in stage clear! if an empty line appears.
+ */
+ prevTowerHeight = TowerHeight;
+ bool found = false;
+ TowerHeight = 0;
+ while (!found) {
+ found = true;
+ for (int j=0;j<6;j++)
+ if (board[j][TowerHeight] != -1)
+ found = false;
+ TowerHeight++;
+ }
+ TowerHeight--;
+ }
+
+///////////////////////////////////////////////////////////////////////////
+/////////////////////////// AI starts here! ///////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+ //First the helpet functions:
+ int nrOfType(int line, int type) {
+ // cout << "Start_ nrOfType" << endl;
+ int counter = 0;
+ for (int i=0; i<6; i++)
+ if (board[i][line]==type)counter++;
+ return counter;
+ }
+
+ int AIcolorToClear;
+ int AIlineToClear;
+
+ //See if a combo can be made in this line
+ int horiInLine(int line) {
+ //cout << "Start_ hori in line" << endl;
+ int nrOfType[7] = {0, 0, 0, 0, 0, 0, 0};
+ int iTemp;
+ int max = 0;
+ for (int i=0; i<6; i++) {
+ iTemp = board[i][line];
+ if ((iTemp>-1)&&(iTemp<7))
+ nrOfType[iTemp]++;
+ }
+ for (int j=0; j<7; j++) {
+ if (nrOfType[j]>max) {
+ max = nrOfType[j];
+ AIcolorToClear = j;
+ }
+ }
+ return max;
+ }
+
+ bool horiClearPossible() {
+ //cout << "Start_ horiclear possible" << endl;
+ int i=13;
+ bool solutionFound = false;
+ do{
+ if (horiInLine(i)>2) {
+ AI_LineOffset = 0;
+ AIlineToClear = i;
+ solutionFound = true;
+ }
+ i--;
+ }while ((!solutionFound)&&(i>0));
+ return solutionFound;
+ }
+
+ //the Line Has Unmoveable Objects witch might stall the AI
+ bool lineHasGarbage(int line) {
+ for (int i=0;i<6;i++)
+ if (board[i][line]>1000000)
+ return true;
+ return false;
+ }
+
+ //Types 0..6 in line
+ inline int nrOfRealTypes(int line) {
+ //cout << "Start_ nrOfReal" << endl;
+ int counter = 0;
+ for (int i=0; i<6; i++)
+ if ((board[i][line]>-1)&&(board[i][line]<7))counter++;
+ return counter;
+ }
+
+ //See if there is a tower
+ bool ThereIsATower() {
+ //cout << "Start_ there is a tower" << endl;
+ bool bThereIsATower = false; //Unless proven otherwise!
+ bool topReached = false; //If we have reached the top
+ int lineNumber = 0;
+ bool emptySpacesFound = false;
+ do {
+ if ((emptySpacesFound) && (nrOfRealTypes(lineNumber)>0)&&(nrOfType(lineNumber, -1)>0)) {
+ AIlineToClear = lineNumber;
+ if (lineHasGarbage(lineNumber))
+ return false;
+ else
+ bThereIsATower = true;
+ }
+ else
+ emptySpacesFound=false;
+ if ((!emptySpacesFound)&&(nrOfType(lineNumber, -1)>0))
+ emptySpacesFound = true;
+ if (lineNumber<12)
+ lineNumber++;
+ else
+ topReached = true;
+ }while ((!bThereIsATower)&&(!topReached));
+ //if(bThereIsATower)
+ //cout << "There is actually a tower" << endl;
+ return bThereIsATower;
+ }
+
+ double firstInLine1(int line) {
+ for (int i=0;i<6;i++)
+ if ((board[i][line]>-1)&&(board[i][line]<7))
+ return (double)i;
+ return 3.0;
+ }
+
+ //returns the first coordinate of the block of type
+ double firstInLine(int line, int type) {
+ for (int i=0;i<6;i++)
+ if (board[i][line]==type)
+ return (double)i;
+ return 3.0;
+ }
+
+ //There in the line shall we move
+ int closestTo(int line, int place) {
+ if ((int)firstInLine1(line)>place)
+ return (int)firstInLine1(line)-1;
+ for (int i=place;i>=0;i--) {
+ if ((board[i][line]>-1)&&(board[i][line]<7))
+ return i;
+ }
+ AIstatus=0;
+ return place;
+ }
+
+ //The AI will remove a tower
+ inline void AI_ClearTower() {
+ // cout << "AI: ClearTower, line: " << AIlineToClear << endl;
+ int place = (int)firstInLine(AIlineToClear-1, -1); //Find an empty field to frop a brick into
+ int xplace = closestTo(AIlineToClear, place); //Find the brick to drop in it
+ if (cursory+1<AIlineToClear)
+ MoveCursor('N');
+ else
+ if (cursory+1>AIlineToClear)
+ MoveCursor('S');
+ else
+ if (cursorx<xplace)
+ MoveCursor('E');
+ else
+ if (cursorx>xplace)
+ MoveCursor('W');
+ else
+ SwitchAtCursor();
+ if (!ThereIsATower())
+ AIstatus = 0;
+ }
+
+ //The AI will try to clear block horisontally
+ inline void AI_ClearHori() {
+ // cout << "AI: ClearHori";
+ int lowestLine = AIlineToClear;
+ //AIcolorToClear
+ bool found =true;
+ /*for(int i; (i<12)&&(!found);i++)
+ * {
+ * if(horiInLine(i)>2)
+ * {
+ * int lowestLine = i;
+ * found = true;
+ * }
+ * }*/
+ for (int i=0;i<7;i++) {
+ if (nrOfType(lowestLine, i)>2)
+ AIcolorToClear = i;
+ }
+ if (found) {
+ if (cursory>lowestLine-1)
+ MoveCursor('S');
+ else if (cursory<lowestLine-1)
+ MoveCursor('N');
+ else if (nrOfType(lowestLine, AIcolorToClear)>2) {
+ int left=0, right=0;
+ if (board[0][lowestLine]==AIcolorToClear) left++;
+ if (board[1][lowestLine]==AIcolorToClear) left++;
+ if (board[2][lowestLine]==AIcolorToClear) left++;
+ if (board[3][lowestLine]==AIcolorToClear) right++;
+ if (board[4][lowestLine]==AIcolorToClear) right++;
+ if (board[5][lowestLine]==AIcolorToClear) right++;
+ int xplace = 0;
+ if (left<right) {
+ // cout << ", right>left";
+ int count=0;
+ for (int i=0;(i<4)&&(count<1);i++)
+ if ((board[i][lowestLine]==AIcolorToClear)&&((i==0)||(board[i+1][lowestLine]!=AIcolorToClear))) {
+ count++;
+ xplace = i;
+ }
+ }
+ else {
+ // cout << ", left>=right";
+ int count=0;
+ for (int i=3;(i<=5)&&(count<1);i++)
+ if ((board[i][lowestLine]==AIcolorToClear)&&(board[i-1][lowestLine]!=AIcolorToClear)) {
+ count++;
+ xplace = --i;
+ }
+ }
+ //cout << ", xplace: " << xplace;
+ if (cursorx<xplace)
+ MoveCursor('E');
+ else
+ if (cursorx>xplace)
+ MoveCursor('W');
+ else
+ if (cursorx==xplace)
+ SwitchAtCursor();
+ else
+ AIstatus = 0;
+ }
+ else
+ AIstatus = 0;
+ }
+ else
+ AIstatus = 0;
+ //cout << endl; //for debugging
+ }
+
+ //Test if vertical clear is possible
+ inline bool veriClearPossible() {
+ bool found=false;
+ int colors[7] = {0, 0, 0, 0, 0, 0, 0};
+ for (int i=12;(i>0)&&(!found);i--) {
+ for (int j=0;j<7;j++) {
+ if (nrOfType(i, j)==0)
+ colors[j]=0;
+ else
+ if (++colors[j]>2) {
+ AIcolorToClear = j;
+ AIlineToClear = i;
+ found=true;
+ }
+
+ }
+ }
+ return found;
+ }
+
+
+
+ //There in the line shall we move
+ int closestTo(int line, int type, int place) {
+ if ((int)firstInLine(line, type)>place)
+ return (int)firstInLine(line, type)-1;
+ for (int i=place;i>=0;i--) {
+ if (board[i][line]==type)
+ return i;
+ }
+ AIstatus=0;
+ return place;
+ }
+
+ //The AI will try to clear blocks vertically
+ inline void AI_ClearVertical() {
+ // cout << "AI: ClearVeri";
+ //First we find the place there we will align the bricks
+ int placeToCenter = (int)(firstInLine(AIlineToClear, AIcolorToClear)/3.0+firstInLine(AIlineToClear+1, AIcolorToClear)/3.0+firstInLine(AIlineToClear+2, AIcolorToClear)/3.0);
+ int unlimitedLoop=0;
+ while (((board[placeToCenter][AIlineToClear]>1000000)||(board[placeToCenter][AIlineToClear+1]>1000000)||(board[placeToCenter][AIlineToClear+2]>1000000))&&(unlimitedLoop<10)) {
+ unlimitedLoop++;
+ placeToCenter++;
+ if (placeToCenter>5)
+ placeToCenter=0;
+ }
+ //cout << ", ptc: " << placeToCenter << ", line: " << AIlineToClear << ", cy: " << cursory;
+ if (cursory+1>AIlineToClear+2) {
+ // cout << ", cursory>line+2";
+ MoveCursor('S');
+ }
+ if (cursory+1<AIlineToClear)
+ MoveCursor('N');
+ bool toAlign[3]={true, true, true};
+ if (board[placeToCenter][AIlineToClear+0]==AIcolorToClear)
+ toAlign[0]=false;
+ if (board[placeToCenter][AIlineToClear+1]==AIcolorToClear)
+ toAlign[1]=false;
+ if (board[placeToCenter][AIlineToClear+2]==AIcolorToClear)
+ toAlign[2]=false;
+ //cout << "status: " << toAlign[0] << " " << toAlign[1] << " " << toAlign[2];
+ if (cursory+1==AIlineToClear) {
+ if (toAlign[0]==false)
+ MoveCursor('N');
+ else {
+ if (cursorx>closestTo(AIlineToClear, AIcolorToClear, placeToCenter))
+ MoveCursor('W');
+ else
+ if (cursorx<closestTo(AIlineToClear, AIcolorToClear, placeToCenter))
+ MoveCursor('E');
+ else
+ SwitchAtCursor();
+ }
+ }
+ else
+ if (cursory+1==AIlineToClear+1) {
+ if (toAlign[1]==false) {
+ if (toAlign[2])
+ MoveCursor('N');
+ else
+ MoveCursor('S');
+ }
+ else {
+ if (cursorx>closestTo(AIlineToClear+1, AIcolorToClear, placeToCenter))
+ MoveCursor('W');
+ else
+ if (cursorx<closestTo(AIlineToClear+1, AIcolorToClear, placeToCenter))
+ MoveCursor('E');
+ else
+ SwitchAtCursor();
+ }
+ }
+ else
+ if (cursory+1==AIlineToClear+2) {
+ if (toAlign[2]==false)
+ MoveCursor('S');
+ else {
+ if (cursorx>closestTo(AIlineToClear+2, AIcolorToClear, placeToCenter))
+ MoveCursor('W');
+ else
+ if (cursorx<closestTo(AIlineToClear+2, AIcolorToClear, placeToCenter))
+ MoveCursor('E');
+ else
+ SwitchAtCursor();
+ }
+ }
+
+ if ((!toAlign[0])&&(!toAlign[1])&&(!toAlign[2]))
+ AIstatus = 0;
+ if ((nrOfType(AIlineToClear, AIcolorToClear)==0)||(nrOfType(AIlineToClear+1, AIcolorToClear)==0)||(nrOfType(AIlineToClear+2, AIcolorToClear)==0))
+ AIstatus = 0;
+ //cout << endl;
+ }
+
+
+
+ short AIstatus; //Status flags:
+ //0: nothing, 2: clear tower, 3: clear horisontal, 4: clear vertical
+ //1: make more lines, 5: make 2 lines, 6: make 1 line
+ bool firstLineCreated;
+
+ void AI_Move() {
+ switch (AIstatus) {
+ case 1:
+ if (TowerHeight<8)PushLine();
+ else AIstatus = 0;
+ break;
+ case 2:
+ AI_ClearTower();
+ break;
+ case 3:
+ AI_ClearHori();
+ break;
+ case 4:
+ AI_ClearVertical();
+ break;
+ case 5:
+ if (!firstLineCreated){
+ PushLine();
+ firstLineCreated = true;
+ }
+ else {
+ PushLine();
+ AIstatus = 0;
+ }
+ break;
+ case 6:
+ PushLine();
+ AIstatus = 0;
+ break;
+ default:
+ if (TowerHeight<6) AIstatus = 1;
+ else
+ if (horiClearPossible()) AIstatus = 3;
+ else
+ if (veriClearPossible()) AIstatus = 4;
+ else
+ if (ThereIsATower()) AIstatus = 2;
+ else
+ AIstatus = 5;
+ break;
+ }
+ }
+
+//////////////////////////////////////////////////////////////////////////
+///////////////////////////// AI ends here! //////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+ //Draws all the bricks to the board (including garbage)
+ void PaintBricks() {
+ for (int i=0;((i<13)&&(i<30));i++)
+ for (int j=0;j<6;j++) {
+ if ((board[j][i]%10 != -1) && (board[j][i]%10 < 7) && ((board[j][i]/1000000)%10==0)) {
+ DrawIMG(bricks[board[j][i]%10], sBoard, j*50, 600-i*50-pixels);
+ if ((board[j][i]/BLOCKWAIT)%10==1)
+ DrawIMG(bomb[(SDL_GetTicks()/BOMBTIME)%2], sBoard, j*50, 600-i*50-pixels);
+ if ((board[j][i]/BLOCKHANG)%10==1)
+ DrawIMG(ready[(SDL_GetTicks()/READYTIME)%2], sBoard, j*50, 600-i*50-pixels);
+
+ }
+ if ((board[j][i]/1000000)%10==1) {
+ int left, right, over, under;
+ int number = board[j][i];
+ if (j<1) left = -1;
+ else left = board[j-1][i];
+ if (j>5) right = -1;
+ else right = board[j+1][i];
+ if (i>28) over = -1;
+ else over = board[j][i+1];
+ if (i<1) under = -1;
+ else under = board[j][i-1];
+ if ((left == number)&&(right == number)&&(over == number)&&(under == number))
+ DrawIMG(garbageFill, sBoard, j*50, 600-i*50-pixels);
+ if ((left != number)&&(right == number)&&(over == number)&&(under == number))
+ DrawIMG(garbageL, sBoard, j*50, 600-i*50-pixels);
+ if ((left == number)&&(right != number)&&(over == number)&&(under == number))
+ DrawIMG(garbageR, sBoard, j*50, 600-i*50-pixels);
+ if ((left == number)&&(right == number)&&(over != number)&&(under == number))
+ DrawIMG(garbageT, sBoard, j*50, 600-i*50-pixels);
+ if ((left == number)&&(right == number)&&(over == number)&&(under != number))
+ DrawIMG(garbageB, sBoard, j*50, 600-i*50-pixels);
+ if ((left != number)&&(right == number)&&(over != number)&&(under == number))
+ DrawIMG(garbageTL, sBoard, j*50, 600-i*50-pixels);
+ if ((left != number)&&(right == number)&&(over == number)&&(under != number))
+ DrawIMG(garbageBL, sBoard, j*50, 600-i*50-pixels);
+ if ((left == number)&&(right != number)&&(over != number)&&(under == number))
+ DrawIMG(garbageTR, sBoard, j*50, 600-i*50-pixels);
+ if ((left == number)&&(right != number)&&(over == number)&&(under != number))
+ DrawIMG(garbageBR, sBoard, j*50, 600-i*50-pixels);
+ if ((left == number)&&(right != number)&&(over != number)&&(under != number))
+ DrawIMG(garbageMR, sBoard, j*50, 600-i*50-pixels);
+ if ((left == number)&&(right == number)&&(over != number)&&(under != number))
+ DrawIMG(garbageM, sBoard, j*50, 600-i*50-pixels);
+ if ((left != number)&&(right == number)&&(over != number)&&(under != number))
+ DrawIMG(garbageML, sBoard, j*50, 600-i*50-pixels);
+ }
+ if ((board[j][i]/1000000)%10==2) {
+ if (j==0)
+ DrawIMG(garbageGML, sBoard, j*50, 600-i*50-pixels);
+ else
+ if (j==5)
+ DrawIMG(garbageGMR, sBoard, j*50, 600-i*50-pixels);
+ else
+ DrawIMG(garbageGM, sBoard, j*50, 600-i*50-pixels);
+ }
+ }
+ const int j = 0;
+
+ int garbageSize=0;
+ for (int i=0;i<20;i++) {
+ if ((board[j][i]/1000000)%10==1) {
+ int left, right, over, under;
+ int number = board[j][i];
+ if (j<1) left = -1;
+ else left = board[j-1][i];
+ if (j>5) right = -1;
+ else right = board[j+1][i];
+ if (i>28) over = -1;
+ else over = board[j][i+1];
+ if (i<1) under = -1;
+ else under = board[j][i-1];
+ if (((left != number)&&(right == number)&&(over != number)&&(under == number))&&(garbageSize>0)) {
+ DrawIMG(smiley[board[j][i]%4], sBoard, 100, 600-i*50-pixels+25*garbageSize);
+ }
+ if (!((left != number)&&(right == number)&&(over == number)&&(under == number))) //not in garbage
+ {
+ garbageSize=0;
+ }
+ else {
+ //cout << "In garbage" << endl;
+ garbageSize++;
+ }
+
+ }
+ }
+ for (int i=0;i<6;i++)
+ if (board[i][0]!=-1)
+ DrawIMG(transCover, sBoard, i*50, 600-pixels); //Make the appering blocks transperant
+
+ }
+
+ //Paints the bricks gotten from a replay/net package
+ void SimplePaintBricks() {
+ /*
+ * We will need to mark the blocks that must have a bomb, we will here need to see, what is falling
+ */
+ bool bbomb[6][13]; //has a bomb on it!
+ bool falling[6][13]; //this is falling
+ bool getReady[6][13]; //getReady
+ for (int i=0;i<6;i++)
+ for (int j=0;j<13;j++) {
+ bbomb[i][j]=false; //All false by default
+ falling[i][j]=false;
+ if (board[i][j]>29)
+ getReady[i][j]=true;
+ else
+ getReady[i][j]=false;
+ }
+ //See that is falling
+ for (int i=0;i<6;i++) {
+ bool rowFalling = false;
+ for (int j=0;j<13;j++) {
+ if (rowFalling)
+ falling[i][j]=true;
+ if ((!rowFalling)&&(board[i][j]%30==-1))
+ rowFalling = true;
+ if ((rowFalling)&&(board[i][j]%30>6))
+ rowFalling = false;
+ if (getReady[i][j]) {
+ falling[i][j]=true; //getReady is the same as falling
+ rowFalling = false;
+ }
+ }
+ }
+ //Now looking at rows:
+ for (int i=0;i<6;i++) {
+ int count = 0;
+ int color = -1;
+ for (int j=1;j<13;j++) {
+ if ((board[i][j]%30==color)&&(!falling[i][j]))
+ count++;
+ else
+ if (falling[i][j]) {
+ count = 0;
+ }
+ else {
+ color=board[i][j]%30;
+ count=1;
+ }
+ if ((count>2)&&(color>-1)&&(color)<7) {
+ bbomb[i][j]=true;
+ bbomb[i][j-1]=true;
+ bbomb[i][j-2]=true;
+ }
+ }
+ }
+ //now looking for lines
+ for (int i=1;i<13;i++) {
+ int count = 0;
+ int color = -1;
+ for (int j=0;j<6;j++) {
+ if ((board[j][i]%30==color)&&(!falling[j][i]))
+ count++;
+ else
+ if (falling[j][i]) {
+ count = 0;
+ }
+ else {
+ color=board[j][i]%30;
+ count=1;
+ }
+ if ((count>2)&&(color>-1)&&(color<7)) {
+ bbomb[j][i]=true;
+ bbomb[j-1][i]=true;
+ bbomb[j-2][i]=true;
+ }
+ }
+ }
+ for (int i=0;((i<13)&&(i<30));i++)
+ for (int j=0;j<6;j++) {
+ if ((board[j][i]%10 != -1) && (board[j][i]%30 < 7)) {
+ DrawIMG(bricks[board[j][i]%10], sBoard, j*50, 600-i*50-pixels);
+ if (bbomb[j][i])
+ DrawIMG(bomb[(SDL_GetTicks()/BOMBTIME)%2], sBoard, j*50, 600-i*50-pixels);
+ if (getReady[j][i])
+ DrawIMG(ready[(SDL_GetTicks()/READYTIME)%2], sBoard, j*50, 600-i*50-pixels);
+ }
+ if (board[j][i]%30>6) {
+ if (board[j][i]%30==7)
+ DrawIMG(garbageR, sBoard, j*50, 600-i*50-pixels); //good
+ if (board[j][i]%30==9)
+ DrawIMG(garbageML, sBoard, j*50, 600-i*50-pixels); //good
+ if (board[j][i]%30==10)
+ DrawIMG(garbageMR, sBoard, j*50, 600-i*50-pixels); //good
+ if (board[j][i]%30==11)
+ DrawIMG(garbageTR, sBoard, j*50, 600-i*50-pixels); //good
+ if (board[j][i]%30==12)
+ DrawIMG(garbageTL, sBoard, j*50, 600-i*50-pixels); //good
+ if (board[j][i]%30==13)
+ DrawIMG(garbageBL, sBoard, j*50, 600-i*50-pixels); //good
+ if (board[j][i]%30==14)
+ DrawIMG(garbageBR, sBoard, j*50, 600-i*50-pixels); //good
+ if (board[j][i]%30==15)
+ DrawIMG(garbageM, sBoard, j*50, 600-i*50-pixels); //good
+ if (board[j][i]%30==16)
+ DrawIMG(garbageFill, sBoard, j*50, 600-i*50-pixels); //good
+ if (board[j][i]%30==17)
+ DrawIMG(garbageT, sBoard, j*50, 600-i*50-pixels); //good
+ if (board[j][i]%30==18)
+ DrawIMG(garbageB, sBoard, j*50, 600-i*50-pixels); //good
+ if (board[j][i]%30==19)
+ DrawIMG(garbageL, sBoard, j*50, 600-i*50-pixels); //good
+ //cout << "IS: " << board[j][i] << endl;
+ }
+
+
+ }
+
+ int garbageSize=0;
+ for (int i=0;i<20;i++) {
+ if ((board[0][i]%30==12)&&(garbageSize>0)) {
+ DrawIMG(smiley[0], sBoard, 100, 600-i*50-pixels+25*garbageSize);
+ }
+ if (board[0][i]%30!=19) //not in garbage
+ {
+ garbageSize=0;
+ }
+ else {
+ //cout << "In garbage" << endl;
+ garbageSize++;
+ }
+
+ }
+ }
+
+ //Draws everything
+ void DoPaintJob() {
+ DrawIMG(backBoard, sBoard, 0, 0);
+ if ((!bReplaying)&&(!bNetworkPlayer))
+ PaintBricks();
+ else
+ SimplePaintBricks();
+ if (stageClear) DrawIMG(blackLine, sBoard, 0, 700+50*(stageClearLimit-linesCleared)-pixels-1);
+ if (puzzleMode&&(!bGameOver)) {
+ //We need to write nr. of moves left!
+ strHolder = "Moves left: " + itoa(MovesLeft);
+ SFont_Write(sBoard, fBlueFont, 5, 5, strHolder.c_str());
+ }
+ if(puzzleMode && stageButtonStatus == SBpuzzleMode)
+ {
+ DrawIMG(bRetry,sBoard, cordRetryButton.x, cordRetryButton.y);
+ if(Level<nrOfPuzzles-1)
+ {
+ if(hasWonTheGame)
+ DrawIMG(bNext,sBoard,cordNextButton.x, cordNextButton.y);
+ else
+ DrawIMG(bSkip,sBoard,cordNextButton.x, cordNextButton.y);
+ }
+ else
+ {
+ strHolder = "Last puzzle";
+ SFont_Write(sBoard, fBlueFont, 5, 5, strHolder.c_str());
+ }
+ }
+ if(stageClear && stageButtonStatus == SBstageClear)
+ {
+ DrawIMG(bRetry,sBoard, cordRetryButton.x, cordRetryButton.y);
+ if(Level<50-1)
+ {
+ if(hasWonTheGame)
+ DrawIMG(bNext,sBoard,cordNextButton.x, cordNextButton.y);
+ else
+ DrawIMG(bSkip,sBoard,cordNextButton.x, cordNextButton.y);
+ }
+ else
+ {
+ strHolder = "Last stage";
+ SFont_Write(sBoard, fBlueFont, 5, 5, strHolder.c_str());
+ }
+ }
+
+#if defined(DEBUG)
+ if (AI_Enabled&&(!bGameOver)) {
+ strHolder = "AI_status: " + itoa(AIstatus)+ ", "+ itoa(AIlineToClear);
+ SFont_Write(sBoard, fBlueFont, 5, 5, strHolder.c_str());
+ }
+#endif
+ if (!bGameOver)DrawIMG(cursor[(SDL_GetTicks()/600)%2],sBoard,cursorx*50-4,550-cursory*50-pixels-4);
+ if (SDL_GetTicks()<gameStartedAt)
+ switch (abs((int)SDL_GetTicks()-(int)gameStartedAt)/1000) {
+ case 2:
+ DrawIMG(counter[2], sBoard, 100, 250);
+ break;
+ case 1:
+ DrawIMG(counter[1], sBoard, 100, 250);
+ break;
+ case 0:
+ DrawIMG(counter[0], sBoard, 100, 250);
+ break;
+ default:
+ break;
+ }
+ if ((bGameOver)&&(!editorMode))
+ if (hasWonTheGame)DrawIMG(iWinner, sBoard, 0, 250);
+ else if (bDraw) DrawIMG(iDraw, sBoard, 0, 250);
+ else
+ DrawIMG(iGameOver, sBoard, 0, 250);
+ }
+
+ //Updates evrything, if not called nothing happends
+ void Update() {
+ Uint32 tempUInt32;
+ Uint32 nowTime = SDL_GetTicks(); //We remember the time, so it doesn't change during this call
+ if (bReplaying) {
+ setBoard(theReplay.getFrameSec((Uint32)(nowTime-gameStartedAt)));
+ if (theReplay.isFinnished((Uint32)(nowTime-gameStartedAt)))
+ switch (theReplay.getFinalStatus()) {
+ case 1: //Winner
+ bGameOver = true;
+ hasWonTheGame = true;
+ break;
+ case 2: //Looser
+ case 4: //GameOver
+ bGameOver = true;
+ break;
+ case 3: //draw
+ bGameOver =true;
+ bDraw = true;
+ break;
+ default:
+ bGameOver = true;
+ //Nothing
+ break;
+ };
+ }
+ if ((!bReplaying)&&(!bNetworkPlayer)) {
+ FindTowerHeight();
+ if ((linesCleared-TowerHeight>stageClearLimit) && (stageClear) && (!bGameOver)) {
+ stageCleared[Level] = true;
+ if(stageScores[Level]<score)
+ {
+ gameEndedAfter = nowTime-gameStartedAt;
+ stageScores[Level] = score;
+ stageTimes[Level] = gameEndedAfter;
+ }
+
+ ofstream outfile;
+ outfile.open(stageClearSavePath.c_str(), ios::binary |ios::trunc);
+ if (!outfile) {
+ cout << "Error writing to file: " << stageClearSavePath << endl;
+ }
+ else {
+ for (int i=0;i<nrOfStageLevels;i++) {
+ bool tempBool = stageCleared[i];
+ outfile.write(reinterpret_cast<char*>(&tempBool), sizeof(bool));
+ }
+ for (int i=0;i<nrOfStageLevels;i++) {
+ tempUInt32 = stageScores[i];
+ outfile.write(reinterpret_cast<char*>(&tempUInt32), sizeof(Uint32));
+ }
+ for (int i=0;i<nrOfStageLevels;i++) {
+ tempUInt32 = stageTimes[i];
+ outfile.write(reinterpret_cast<char*>(&tempUInt32), sizeof(Uint32));
+ }
+ outfile.close();
+ }
+ setPlayerWon();
+ stageButtonStatus = SBstageClear;
+ }
+ if ((TowerHeight>12)&&(prevTowerHeight<13)&&(!puzzleMode)) {
+ if (SoundEnabled) Mix_PlayChannel(1, heartBeat, 0);
+ stop+=1000;
+ }
+
+ while (nowTime>nrStops*40+gameStartedAt) //Increase stops, till we reach nowTime
+ {
+ if (stop>0) {
+ stop = stop-20;
+ if (stop<=0) nrPushedPixel=(int)((nowTime-gameStartedAt)/(1000.0*speed));
+ }
+ if (stop<0)
+ stop = 0;
+ nrStops++;
+ }
+ //If we have static content, we don't raise at all!
+ if (hasStaticContent())
+ stop++;
+ if ((puzzleMode)&&(!bGameOver)&&BoardEmpty()) {
+ if (!singlePuzzle) {
+ puzzleCleared[Level] = true;
+ ofstream outfile;
+ stageButtonStatus = SBpuzzleMode;
+ outfile.open(puzzleSavePath.c_str(), ios::binary |ios::trunc);
+ if (!outfile) {
+ cout << "Error writing to file: " << puzzleSavePath << endl;
+ }
+ else {
+ for (int i=0;i<nrOfPuzzles;i++) {
+ bool tempBool = puzzleCleared[i];
+ outfile.write(reinterpret_cast<char*>(&tempBool), sizeof(bool));
+ }
+ outfile.close();
+ }
+ }
+ setPlayerWon();
+ }
+
+ //increse speed:
+ if ((nowTime>gameStartedAt+20000*speedLevel)&&(speedLevel <99)&&(!bGameOver))
+ {
+ speed = (baseSpeed*0.9)/((double)speedLevel*0.5);
+ speedLevel++;
+ nrPushedPixel=(int)((double)(nowTime-gameStartedAt)/(1000.0*speed));
+ }
+
+
+ //To prevent the stack from raising a lot then we stop a chain (doesn't work anymore)
+ if (chain>0)
+ stop+=1;
+ //Raises the stack
+ if ((nowTime>gameStartedAt+nrPushedPixel*1000*speed) && (!bGameOver)&&(!stop))
+ while ((nowTime>gameStartedAt+nrPushedPixel*1000*speed)&&(!(puzzleMode)))
+ PushPixels();
+ if (!bGameOver)ClearBlocks();
+
+ /*************************************************************
+ Ai stuff
+ **************************************************************/
+ if (bGameOver) {
+ AIstatus = 0; //Enusres that AI is resetted
+ }
+ else
+ if (AI_Enabled)
+ if (lastAImove+AI_MoveSpeed<SDL_GetTicks()) {
+ AI_Move();
+ lastAImove=SDL_GetTicks();
+ }
+
+ /*************************************************************
+ Ai stuff ended
+ **************************************************************/
+ if ((nowTime>gameStartedAt+nrFellDown*140) && (!bGameOver)) FallDown();
+ if ((nowTime<gameStartedAt)&&(puzzleMode)) {
+ FallDown();
+ nrFellDown--;
+ }
+ ReduceStuff();
+ if ((timetrial) && (!bGameOver) && (nowTime>gameStartedAt+2*60*1000)) {
+ if (SoundEnabled) Mix_PlayChannel(1, timesUp, 0);
+ SetGameOver();
+ if ((theTopScoresTimeTrial.isHighScore(score))&&(!AI_Enabled)) {
+ theTopScoresTimeTrial.addScore(name, score);
+ //new highscore
+ //Also check if it is better than the best result so far.
+ string checkFilename = getPathToSaveFiles() + "/bestTTresult";
+ ifstream inFile(checkFilename.c_str());
+ Uint32 bestResult = 3000; //Never accept a best result under 3000
+ if(inFile)
+ {
+ inFile >> bestResult;
+ inFile.close();
+ }
+ if(score>bestResult)
+ {
+ string bestFile = getPathToSaveFiles() + "/bestTT";
+ theReplay.saveReplay(bestFile);
+ ofstream outFile(checkFilename.c_str(),ios::trunc);
+ if(outFile)
+ outFile << score;
+ }
+ }
+ }
+ }
+ if ((!bGameOver)&&(!bReplaying)&&(nowTime>gameStartedAt))
+ {
+ //cout << nowTime << " bigger than " << gameStartedAt << endl;
+ theReplay.setFrameSecTo(nowTime-gameStartedAt, getPackage());
+ }
+ DoPaintJob();
+ }
+
+}; //class BlockGame
+////////////////////////////////////////////////////////////////////////////////
+///////////////////////// BlockAttack class end ////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
diff --git a/source/code/NetworkThing.hpp b/source/code/NetworkThing.hpp new file mode 100644 index 0000000..8070fd5 --- /dev/null +++ b/source/code/NetworkThing.hpp
@@ -0,0 +1,390 @@
+/*
+NetworkThing.hpp
+Copyright (C) 2007 Poul Sander
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Poul Sander
+ R�veh�jvej 36, V. 1111
+ 2800 Kgs. Lyngby
+ DENMARK
+ blockattack@poulsander.com
+*/
+
+//The network interface
+class NetworkThing
+{
+private:
+ ENetAddress address;
+ ENetHost * server;
+ ENetHost * client;
+ ENetPeer *peer;
+
+ BlockGame *bgHome, *bgAway; //Pointers to the two games, so we can call the procedures
+ bool weAreAServer, weAreAClient;
+ bool weAreConnected;
+ bool enemyIsReady;
+ bool enemyHasStarted; //If we should have a ready button
+ bool gameHasStarted; //If the player is GameOver it might just be because the game hasn't started yet... not if this is true!
+
+public:
+
+ Uint32 theSeed;
+
+ NetworkThing()
+ {
+ weAreAServer = false;
+ weAreAClient = false;
+ weAreConnected = false;
+ enemyIsReady = false;
+ enemyHasStarted = false;
+ gameHasStarted = false;
+ if (enet_initialize () != 0)
+ {
+ fprintf (stderr, "An error occurred while initializing ENet.\n");
+ }
+ else
+ {
+ cout << "Network is working!" << endl;
+ }
+ //atexit (enet_deinitialize); in deconstructor
+ }
+
+ //This function couses us to remove the connection to the other peer, plus destroying servers
+ void ntDisconnect()
+ {
+ strcpy(bgAway->name,player2name);
+ if (weAreConnected || weAreAClient || weAreAServer)
+ {
+ if (weAreAClient)
+ {
+ enet_peer_disconnect (peer,0);
+ SDL_Delay(20);
+ enet_host_destroy(client);
+ weAreAClient = false;
+ weAreConnected = false;
+ enemyHasStarted = false;
+ }
+ if (weAreAServer)
+ {
+ enet_host_destroy(server);
+ weAreAServer = false;
+ weAreConnected = false;
+ enemyHasStarted = false;
+ }
+ //If the game is running then we disconnect, we are considered the looser!
+ if ((!bgHome->bGameOver)&&(!bgAway->bGameOver))
+ {
+ bgAway->setPlayerWon();
+ bgHome->SetGameOver();
+ }
+ gameHasStarted = false;
+ }
+ };
+
+ //Lets disconnect before we close...
+ ~NetworkThing()
+ {
+ cout << "Network system is going down" << endl;
+ ntDisconnect();
+ enet_deinitialize();
+ cout << "Network system went down" << endl;
+ }
+
+ void theGameHasStarted()
+ {
+ gameHasStarted = true;
+ }
+
+ //The NetworkThing needs to be able to call the models... here the pointers are set
+ void setBGpointers(BlockGame *bg1, BlockGame *bg2)
+ {
+ bgHome = bg1;
+ bgAway = bg2;
+ }
+
+ //Starts a server instance
+ void startServer()
+ {
+ if (!weAreAServer)
+ {
+ ntDisconnect();
+
+ /* Bind the server to the default localhost. */
+ /* A specific host address can be specified by */
+ /* enet_address_set_host (& address, "x.x.x.x"); */
+
+ address.host = ENET_HOST_ANY;
+ /* Bind the server to port SERVERPORT. */
+ address.port = SERVERPORT;
+
+ server = enet_host_create (& address /* the address to bind the server host to */,
+ 1 /* allow up to 1 clients and/or outgoing connections */,
+ 0 /* assume any amount of incoming bandwidth */,
+ 0 /* assume any amount of outgoing bandwidth */);
+ if (server == NULL)
+ {
+ fprintf (stderr,
+ "An error occurred while trying to create an ENet server host.\n");
+
+ }
+ else
+ {
+ weAreAServer = true;
+ enemyIsReady = false;
+ gameHasStarted = false;
+ cout << "Server is listening on port " << SERVERPORT << endl;
+ }
+ }
+ }
+
+ void connectToServer(string server)
+ {
+ ENetAddress address;
+ ENetEvent event;
+
+ enet_address_set_host (& address, server.c_str());
+ address.port = SERVERPORT;
+
+ ntDisconnect();
+ client = enet_host_create (NULL /* create a client host */,
+ 1 /* only allow 1 outgoing connection */,
+ 0 /* Unlimited downstream bandwidth */,
+ 0 /* Unlimted upstream bandwidth */);
+
+ if (client == NULL)
+ {
+ cout << "An error occurred while trying to create an ENet client host." << endl;
+ }
+ else
+ {
+ /* Initiate the connection, allocating the four channels 0 and 1 and 2 and 3. */
+ peer = enet_host_connect (client, & address, 4);
+
+ if (peer == NULL)
+ {
+ cout << "No available peers for initiating an ENet connection." << endl;
+ }
+ else
+ if (enet_host_service (client, & event, 2000) > 0 &&
+ event.type == ENET_EVENT_TYPE_CONNECT)
+ {
+ cout << "We are connected!" << endl;
+ enemyIsReady = false;
+ weAreAClient = true;
+ weAreConnected = true;
+ gameHasStarted = false;
+ }
+ else
+ {
+ cout << "Server didn't answer in time" << endl;
+ }
+ }
+ }
+
+ bool isConnected()
+ {
+ return (weAreConnected||weAreAServer);
+ }
+
+ bool isConnectedToPeer()
+ {
+ return weAreConnected;
+ }
+
+ //This function must be called in the game loop:
+ void updateNetwork()
+ {
+ //Now we must send our own board:
+ if (weAreConnected)
+ {
+ //cout << "Creating package" << endl;
+ boardPackage boardpack = bgHome->getPackage();
+ ENetPacket * packet = enet_packet_create (&boardpack,
+ sizeof(boardPackage),
+ 0);
+ //Now lets send the package
+ if (weAreAServer)
+ enet_host_broadcast (server, 0, packet);
+ else
+ if (weAreAClient)
+ enet_peer_send (peer, 0, packet);
+ //cout << "Package sent" << endl;
+
+ //See if we are game over and in that case notify the other player
+ if ((gameHasStarted)&&(bgHome->bGameOver))
+ {
+ ENetPacket * packet = enet_packet_create("G",2,ENET_PACKET_FLAG_RELIABLE);
+ if (weAreAServer)
+ enet_host_broadcast (server, 1, packet);
+ else
+ if (weAreAClient)
+ enet_peer_send (peer, 1, packet);
+ gameHasStarted=false;
+ }
+
+ //Now lets see if we have something to throw at the opponent.
+ Uint8 x,y,type;
+
+ if (gameHasStarted)
+ while (bgAway->popGarbage(&x,&y,&type))
+ { //if there are garbage to drop
+ if (type==1)
+ {
+ x=255;
+ y=255;
+ }
+ Uint16 g = ((Uint16)x)*256+(Uint16)y; //A 16-bit int containing everything
+ ENetPacket * packet = enet_packet_create(&g,2,ENET_PACKET_FLAG_RELIABLE);
+ if (weAreAServer)
+ enet_host_broadcast (server, 2, packet);
+ else
+ if (weAreAClient)
+ enet_peer_send (peer, 2, packet);
+ cout << "We send a garbage block: " << (int)x << "," << (int)y << "==" << g << endl;
+ }
+ }
+ ENetEvent event;
+
+ /* Wait up to 0 milliseconds for an event. */
+ while (((weAreAClient)&&(enet_host_service (client, & event, 0) > 0))||((weAreAServer)&&(enet_host_service (server, & event, 0) > 0)))
+ {
+ switch (event.type)
+ {
+ case ENET_EVENT_TYPE_CONNECT:
+ printf ("A new client connected from %x:%u.\n",
+ event.peer -> address.host,
+ event.peer -> address.port);
+ weAreConnected = true;
+ /* Store any relevant client information here. */
+ //event.peer -> data = "Client";
+ {
+
+ ENetPacket * namePacket = enet_packet_create(bgHome->name,sizeof(char[30]),ENET_PACKET_FLAG_RELIABLE);
+ //if(weAreAServer)
+ enet_host_broadcast (server, 3, namePacket);
+ ENetPacket * answerPacket = enet_packet_create("version2",sizeof("version2"),ENET_PACKET_FLAG_RELIABLE);
+ enet_host_broadcast (server, 3, answerPacket);
+ theSeed = time(0)/4;
+ bgHome->putStartBlocks(theSeed);
+ ENetPacket * timePacket = enet_packet_create(&theSeed,sizeof(theSeed),ENET_PACKET_FLAG_RELIABLE);
+ enet_host_broadcast (server, 3, timePacket);
+ cout << "We send the seed: " << theSeed << endl;
+ }
+ break;
+
+ case ENET_EVENT_TYPE_RECEIVE:
+ /*printf ("A packet of length %u containing %s was received from %s on channel %u.\n",
+ event.packet -> dataLength,
+ event.packet -> data,
+ event.peer -> data,
+ event.channelID);*/
+ //cout << "Package recieved" << endl;
+ if (event.channelID==0) //Unreliable (only boardPacks)
+ {
+ boardPackage bpack;
+ //cout << "Package size: "<< event.packet->dataLength << " should be: " << sizeof(boardPackage) << endl;
+ memcpy(&bpack,(const char*)event.packet->data,sizeof(boardPackage));
+ bgAway->setBoard(bpack);
+ }
+ if (event.channelID==1) //reliable (used for GameOver notifications only!)
+ {
+ if ((bgHome->bGameOver)&&(!bgHome->hasWonTheGame)&&(gameHasStarted))
+ {
+ bgHome->setDraw();
+ bgAway->setDraw();
+ }
+ else
+ {
+ bgHome->setPlayerWon();
+ bgAway->SetGameOver();
+ }
+ gameHasStarted=false;
+ }
+
+ if (event.channelID==2) //reliable (used for Garbage only!)
+ {
+ Uint16 g;
+ memcpy(&g,event.packet->data,sizeof(Uint16));
+ Uint8 x = (g/256);
+ Uint8 y = (g%256);
+ cout << "Recieved Garbage: " << (int)x << "," << (int)y << endl;
+ if ((x==255)&&(y==255))
+ bgHome->CreateGreyGarbage();
+ else
+ bgHome->CreateGarbage(x,y);
+ }
+
+ if (event.channelID==3) //We have reacieved a name or a version number
+ {
+ if (event.packet->dataLength==sizeof(char[30])) //We have reveived a name
+ {
+ strcpy(bgAway->name,(const char*)event.packet->data);
+ cout << "The enemy name is: " << bgAway->name << " Length: " << sizeof(char[30])<< endl;
+ if (weAreAClient) //We have just recieved the servers name and must send our own
+ {
+ ENetPacket * answerPacket = enet_packet_create(bgHome->name,sizeof(char[30]),ENET_PACKET_FLAG_RELIABLE);
+ enet_peer_send (peer, 3, answerPacket);
+ }
+ }
+ else
+ if (event.packet->dataLength==sizeof("2")) //We have recieved aversion number
+ {
+ if (0!=strcmp((const char*)event.packet->data,"version2"))
+ {
+ cout << "Incompatible version: " << event.packet->data << "!=" << "version2" << endl;
+ ntDisconnect();
+ }
+ if (weAreAClient) //We will send our version number
+ {
+ ENetPacket * answerPacket = enet_packet_create("version2",sizeof("version2"),ENET_PACKET_FLAG_RELIABLE);
+ enet_peer_send (peer, 3, answerPacket);
+ }
+ }
+ else
+ if (event.packet->dataLength==sizeof(Uint32)) //We have recieved a seed
+ {
+ memcpy(&theSeed,event.packet->data,sizeof(Uint32));
+ bgHome->putStartBlocks(theSeed);
+ cout << "We recieved a seed: " << theSeed << endl;
+ }
+ }
+
+ /* Clean up the packet now that we're done using it. */
+ enet_packet_destroy (event.packet);
+
+ break;
+
+ case ENET_EVENT_TYPE_DISCONNECT:
+ printf ("%s disconected.\n", event.peer -> data);
+
+ /* Reset the peer's client information. */
+
+ event.peer -> data = NULL;
+ //weAreConnected = false;
+ if ((!bgHome->bGameOver)&&(!bgAway->bGameOver))
+ {
+ bgHome->setPlayerWon();
+ bgAway->SetGameOver();
+ }
+
+ ntDisconnect(); //When we will disconnect!
+
+ }
+ }
+
+
+ }
+}; //NetworkThing
diff --git a/source/code/README b/source/code/README new file mode 100644 index 0000000..f78cf00 --- /dev/null +++ b/source/code/README
@@ -0,0 +1,26 @@
+Thanks for downloading Block Attack - Rise Of the Blocks 1.3.2 for Linux and other Platforms
+
+Version 1.3.2
+
+scons must be present on the system to compile. (There is a make file but it is mostly for development and unpriviliged compiling, NEVER use "make install"!)
+
+To build:
+scons
+scons install (as root)
+
+The game can be ran by double clicking "starter" in the "Game" directory. (Only if build with the make file)
+
+If it doesn't work (because your distro uses an old stdc++ file, is not Linux or you are running 64 bit you will need to compile)
+
+
+If you get errors you might need certain packages on your system.
+
+Dependencies:
+On Ubunut the required packages are to run are: libsdl1.2debian-all, libsdl-image1.2, libsdl-mixer1.2 and libenet
+To compile: build-essential, libsdl1.2-dev, libsdl-image1.2-dev, libsdl-mixer1.2-dev and libenet-dev
+
+By default the game is now placed in: /usr/local/bin/blockattack
+This means that it can be runned by just typing "blockattack"
+
+http://blockattack.sf.net
+Poul Sander poul@poulsander.com
diff --git a/source/code/ReadKeyboard.cpp b/source/code/ReadKeyboard.cpp new file mode 100644 index 0000000..d3f531a --- /dev/null +++ b/source/code/ReadKeyboard.cpp
@@ -0,0 +1,380 @@
+/*
+ReadKeyboard.cpp
+Copyright (C) 2005 Poul Sander
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Poul Sander
+ R�veh�jvej 36, V. 1111
+ 2800 Kgs. Lyngby
+ DENMARK
+ blockattack@poulsander.com
+*/
+
+#include "ReadKeyboard.h"
+
+ReadKeyboard::ReadKeyboard(void)
+{
+ length = 0;
+ maxLength = 16;
+ position = 0;
+ strcpy(textstring," ");
+}
+
+ReadKeyboard::~ReadKeyboard(void)
+{
+}
+
+Uint8 ReadKeyboard::CharsBeforeCursor()
+{
+ return position;
+}
+
+ReadKeyboard::ReadKeyboard(char *oldName)
+{
+ length = 0;
+ maxLength = 16;
+ position = 0;
+ strcpy(textstring," ");
+ strcpy(textstring,oldName);
+ char charecter = textstring[maxLength+1];
+ int i = maxLength+1;
+ while ((charecter == ' ') && (i>0))
+ {
+ i--;
+ charecter = textstring[i];
+ }
+ if (i>0)length = i+1;
+ else
+ if (charecter == ' ') length = 0;
+ else length = 1;
+ position = length;
+
+}
+
+
+void ReadKeyboard::putchar(char thing)
+{
+ if (length < maxLength)
+ {
+ for (int i = 28; i>position;i--)
+ {
+ textstring[i]=textstring[i-1];
+ }
+ textstring[position] = thing;
+ length++;
+ position++;
+ }
+}
+
+
+void ReadKeyboard::removeChar()
+{
+ for (int i = position;i<28;i++)
+ {
+ textstring[i]=textstring[i+1];
+ }
+ textstring[28]=' ';
+ if (length>0)length--;
+}
+
+bool ReadKeyboard::ReadKey(SDLKey keyPressed)
+{
+ if (keyPressed == SDLK_SPACE)
+ {
+ ReadKeyboard::putchar(' ');
+ return true;
+ }
+ if (keyPressed == SDLK_DELETE)
+ {
+ if ((length>0)&& (position<length))ReadKeyboard::removeChar();
+ return true;
+ }
+ if (keyPressed == SDLK_BACKSPACE)
+ {
+ if (position>0)
+ {
+ position--;
+ ReadKeyboard::removeChar();
+ return true;
+ }
+ return false;
+ }
+ Uint8* keys;
+ keys = SDL_GetKeyState(NULL);
+ if (keyPressed == SDLK_HOME)
+ {
+ position=0;
+ return true;
+ }
+ if (keyPressed == SDLK_END)
+ {
+ position=length;
+ return true;
+ }
+ if ((keyPressed == SDLK_LEFT) && (position>0))
+ {
+ position--;
+ return true;
+ }
+ if ((keyPressed == SDLK_RIGHT) && (position<length))
+ {
+ position++;
+ return true;
+ }
+ char charToPut;
+ switch (keyPressed)
+ {
+ case SDLK_a:
+ charToPut = 'a';
+ break;
+ case SDLK_b:
+ charToPut = 'b';
+ break;
+ case SDLK_c:
+ charToPut = 'c';
+ break;
+ case SDLK_d:
+ charToPut = 'd';
+ break;
+ case SDLK_e:
+ charToPut = 'e';
+ break;
+ case SDLK_f:
+ charToPut = 'f';
+ break;
+ case SDLK_g:
+ charToPut = 'g';
+ break;
+ case SDLK_h:
+ charToPut = 'h';
+ break;
+ case SDLK_i:
+ charToPut = 'i';
+ break;
+ case SDLK_j:
+ charToPut = 'j';
+ break;
+ case SDLK_k:
+ charToPut = 'k';
+ break;
+ case SDLK_l:
+ charToPut = 'l';
+ break;
+ case SDLK_m:
+ charToPut = 'm';
+ break;
+ case SDLK_n:
+ charToPut = 'n';
+ break;
+ case SDLK_o:
+ charToPut = 'o';
+ break;
+ case SDLK_p:
+ charToPut = 'p';
+ break;
+ case SDLK_q:
+ charToPut = 'q';
+ break;
+ case SDLK_r:
+ charToPut = 'r';
+ break;
+ case SDLK_s:
+ charToPut = 's';
+ break;
+ case SDLK_t:
+ charToPut = 't';
+ break;
+ case SDLK_u:
+ charToPut = 'u';
+ break;
+ case SDLK_v:
+ charToPut = 'v';
+ break;
+ case SDLK_w:
+ charToPut = 'w';
+ break;
+ case SDLK_x:
+ charToPut = 'x';
+ break;
+ case SDLK_y:
+ charToPut = 'y';
+ break;
+ case SDLK_z:
+ charToPut = 'z';
+ break;
+ case SDLK_0:
+ charToPut = '0';
+ break;
+ case SDLK_1:
+ charToPut = '1';
+ break;
+ case SDLK_2:
+ charToPut = '2';
+ break;
+ case SDLK_3:
+ charToPut = '3';
+ break;
+ case SDLK_4:
+ charToPut = '4';
+ break;
+ case SDLK_5:
+ charToPut = '5';
+ break;
+ case SDLK_6:
+ charToPut = '6';
+ break;
+ case SDLK_7:
+ charToPut = '7';
+ break;
+ case SDLK_8:
+ charToPut = '8';
+ break;
+ case SDLK_9:
+ charToPut = '9';
+ break;
+ case SDLK_KP0:
+ charToPut = '0';
+ break;
+ case SDLK_KP1:
+ charToPut = '1';
+ break;
+ case SDLK_KP2:
+ charToPut = '2';
+ break;
+ case SDLK_KP3:
+ charToPut = '3';
+ break;
+ case SDLK_KP4:
+ charToPut = '4';
+ break;
+ case SDLK_KP5:
+ charToPut = '5';
+ break;
+ case SDLK_KP6:
+ charToPut = '6';
+ break;
+ case SDLK_KP7:
+ charToPut = '7';
+ break;
+ case SDLK_KP8:
+ charToPut = '8';
+ break;
+ case SDLK_KP9:
+ charToPut = '9';
+ break;
+ case SDLK_KP_PERIOD:
+ case SDLK_PERIOD:
+ charToPut='.';
+ break;
+ default:
+ return false;
+ }
+ if ((keys[SDLK_LSHIFT]) || (keys[SDLK_RSHIFT]))
+ {
+ switch (charToPut)
+ {
+ case 'a':
+ charToPut = 'A';
+ break;
+ case 'b':
+ charToPut = 'B';
+ break;
+ case 'c':
+ charToPut = 'C';
+ break;
+ case 'd':
+ charToPut = 'D';
+ break;
+ case 'e':
+ charToPut = 'E';
+ break;
+ case 'f':
+ charToPut = 'F';
+ break;
+ case 'g':
+ charToPut = 'G';
+ break;
+ case 'h':
+ charToPut = 'H';
+ break;
+ case 'i':
+ charToPut = 'I';
+ break;
+ case 'j':
+ charToPut = 'J';
+ break;
+ case 'k':
+ charToPut = 'K';
+ break;
+ case 'l':
+ charToPut = 'L';
+ break;
+ case 'm':
+ charToPut = 'M';
+ break;
+ case 'n':
+ charToPut = 'N';
+ break;
+ case 'o':
+ charToPut = 'O';
+ break;
+ case 'p':
+ charToPut = 'P';
+ break;
+ case 'q':
+ charToPut = 'Q';
+ break;
+ case 'r':
+ charToPut = 'R';
+ break;
+ case 's':
+ charToPut = 'S';
+ break;
+ case 't':
+ charToPut = 'T';
+ break;
+ case 'u':
+ charToPut = 'U';
+ break;
+ case 'v':
+ charToPut = 'V';
+ break;
+ case 'w':
+ charToPut = 'W';
+ break;
+ case 'x':
+ charToPut = 'X';
+ break;
+ case 'y':
+ charToPut = 'Y';
+ break;
+ case 'z':
+ charToPut = 'Z';
+ break;
+
+ default:
+ charToPut = charToPut;
+ }
+ }
+ ReadKeyboard::putchar(charToPut);
+ return true;
+}
+
+char* ReadKeyboard::GetString()
+{
+ textstring[29]='\0';
+ return &textstring[0];
+}
diff --git a/source/code/ReadKeyboard.h b/source/code/ReadKeyboard.h new file mode 100644 index 0000000..9717e34 --- /dev/null +++ b/source/code/ReadKeyboard.h
@@ -0,0 +1,49 @@
+/*
+ReadKeyBoard.h
+Copyright (C) 2005 Poul Sander
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Poul Sander
+ Rævehøjvej 36, V. 1111
+ 2800 Kgs. Lyngby
+ DENMARK
+ blockattack@poulsander.com
+*/
+
+/*
+Added to project 5/11-2004
+*/
+
+#include <cstring>
+#include "SDL.h"
+
+using namespace std;
+
+class ReadKeyboard
+{
+private:
+ int length, maxLength, position;
+ char textstring[30];
+ void putchar(char);
+ void removeChar();
+public:
+ ReadKeyboard(void);
+ ~ReadKeyboard(void);
+ ReadKeyboard(char*);
+ Uint8 CharsBeforeCursor(); //Where should the cursor be placed?
+ bool ReadKey(SDLKey); //true if key accepted
+ char* GetString(void);
+};
diff --git a/source/code/SFont.c b/source/code/SFont.c new file mode 100644 index 0000000..db4c041 --- /dev/null +++ b/source/code/SFont.c
@@ -0,0 +1,178 @@
+/* SFont: a simple font-library that uses special .pngs as fonts
+ Copyright (C) 2003 Karl Bartel
+
+ License: GPL or LGPL (at your choice)
+ WWW: http://www.linux-games.com/sfont/
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Karl Bartel
+ Cecilienstr. 14
+ 12307 Berlin
+ GERMANY
+ karlb@gmx.net
+*/
+#include <SDL.h>
+
+#include <assert.h>
+#include <stdlib.h>
+#include "SFont.h"
+
+static long GetPixel(SDL_Surface *Surface, Sint32 X, Sint32 Y)
+{
+ Uint8 *bits;
+ Uint32 Bpp;
+
+ assert(X>=0);
+ assert(X<Surface->w);
+
+ Bpp = Surface->format->BytesPerPixel;
+ bits = ((Uint8 *)Surface->pixels)+Y*Surface->pitch+X*Bpp;
+
+ // Get the pixel
+ switch(Bpp) {
+ case 1:
+ return *((Uint8 *)Surface->pixels + Y * Surface->pitch + X);
+ break;
+ case 2:
+ return *((Uint16 *)Surface->pixels + Y * Surface->pitch/2 + X);
+ break;
+ case 3: { // Format/endian independent
+ Uint8 r, g, b;
+ r = *((bits)+Surface->format->Rshift/8);
+ g = *((bits)+Surface->format->Gshift/8);
+ b = *((bits)+Surface->format->Bshift/8);
+ return SDL_MapRGB(Surface->format, r, g, b);
+ }
+ break;
+ case 4:
+ return *((Uint32 *)Surface->pixels + Y * Surface->pitch/4 + X);
+ break;
+ }
+
+ return -1;
+}
+
+SFont_Font* SFont_InitFont(SDL_Surface* Surface)
+{
+ int x = 0, i = 0;
+ Uint32 pixel;
+ SFont_Font* Font;
+ Uint32 pink;
+
+ if (Surface == NULL)
+ return NULL;
+
+ Font = (SFont_Font *) malloc(sizeof(SFont_Font));
+ Font->Surface = Surface;
+
+ SDL_LockSurface(Surface);
+
+ pink = SDL_MapRGB(Surface->format, 255, 0, 255);
+ while (x < Surface->w) {
+ if (GetPixel(Surface, x, 0) == pink) {
+ Font->CharPos[i++]=x;
+ while((x < Surface->w) && (GetPixel(Surface, x, 0)== pink))
+ x++;
+ Font->CharPos[i++]=x;
+ }
+ x++;
+ }
+ Font->MaxPos = x-1;
+
+ pixel = GetPixel(Surface, 0, Surface->h-1);
+ SDL_UnlockSurface(Surface);
+ SDL_SetColorKey(Surface, SDL_SRCCOLORKEY, pixel);
+
+ return Font;
+}
+
+void SFont_FreeFont(SFont_Font* FontInfo)
+{
+ SDL_FreeSurface(FontInfo->Surface);
+ free(FontInfo);
+}
+
+void SFont_Write(SDL_Surface *Surface, const SFont_Font *Font,
+ int x, int y, const char *text)
+{
+ const char* c;
+ int charoffset;
+ SDL_Rect srcrect, dstrect;
+
+ if(text == NULL)
+ return;
+
+ // these values won't change in the loop
+ srcrect.y = 1;
+ dstrect.y = y;
+ srcrect.h = dstrect.h = Font->Surface->h - 1;
+
+ for(c = text; *c != '\0' && x <= Surface->w ; c++) {
+ charoffset = ((int) (*c - 33)) * 2 + 1;
+ // skip spaces and nonprintable characters
+ if (*c == ' ' || charoffset < 0 || charoffset > Font->MaxPos) {
+ x += Font->CharPos[2]-Font->CharPos[1];
+ continue;
+ }
+
+ srcrect.w = dstrect.w =
+ (Font->CharPos[charoffset+2] + Font->CharPos[charoffset+1])/2 -
+ (Font->CharPos[charoffset] + Font->CharPos[charoffset-1])/2;
+ srcrect.x = (Font->CharPos[charoffset]+Font->CharPos[charoffset-1])/2;
+ dstrect.x = x - (int)(Font->CharPos[charoffset]
+ - Font->CharPos[charoffset-1])/2;
+
+ SDL_BlitSurface(Font->Surface, &srcrect, Surface, &dstrect);
+
+ x += Font->CharPos[charoffset+1] - Font->CharPos[charoffset];
+ }
+}
+
+int SFont_TextWidth(const SFont_Font *Font, const char *text)
+{
+ const char* c;
+ int charoffset=0;
+ int width = 0;
+
+ if(text == NULL)
+ return 0;
+
+ for(c = text; *c != '\0'; c++) {
+ charoffset = ((int) *c - 33) * 2 + 1;
+ // skip spaces and nonprintable characters
+ if (*c == ' ' || charoffset < 0 || charoffset > Font->MaxPos) {
+ width += Font->CharPos[2]-Font->CharPos[1];
+ continue;
+ }
+
+ width += Font->CharPos[charoffset+1] - Font->CharPos[charoffset];
+ }
+
+ return width;
+}
+
+int SFont_TextHeight(const SFont_Font* Font)
+{
+ return Font->Surface->h - 1;
+}
+
+void SFont_WriteCenter(SDL_Surface *Surface, const SFont_Font *Font,
+ int y, const char *text)
+{
+ SFont_Write(Surface, Font, Surface->w/2 - SFont_TextWidth(Font, text)/2,
+ y, text);
+}
+
diff --git a/source/code/SFont.h b/source/code/SFont.h new file mode 100644 index 0000000..b856064 --- /dev/null +++ b/source/code/SFont.h
@@ -0,0 +1,83 @@
+/* SFont: a simple font-library that uses special bitmaps as fonts
+ Copyright (C) 2003 Karl Bartel
+
+ License: GPL or LGPL (at your choice)
+ WWW: http://www.linux-games.com/sfont/
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Karl Bartel
+ Cecilienstr. 14
+ 12307 Berlin
+ GERMANY
+ karlb@gmx.net
+*/
+
+/************************************************************************
+* SFONT - SDL Font Library by Karl Bartel <karlb@gmx.net> *
+* *
+* All functions are explained below. For further information, take a *
+* look at the example files, the links at the SFont web site, or *
+* contact me, if you problem isn' addressed anywhere. *
+* *
+************************************************************************/
+#ifndef SFONT_H
+#define SFONT_H
+
+#include <SDL.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Delcare one variable of this type for each font you are using.
+// To load the fonts, load the font image into YourFont->Surface
+// and call InitFont( YourFont );
+ typedef struct {
+ SDL_Surface *Surface;
+ int CharPos[512];
+ int MaxPos;
+ } SFont_Font;
+
+// Initializes the font
+// Font: this contains the suface with the font.
+// The Surface must be loaded before calling this function
+ SFont_Font* SFont_InitFont (SDL_Surface *Font);
+
+// Frees the font
+// Font: The font to free
+// The font must be loaded before using this function.
+ void SFont_FreeFont(SFont_Font* Font);
+
+// Blits a string to a surface
+// Destination: the suface you want to blit to
+// text: a string containing the text you want to blit.
+ void SFont_Write(SDL_Surface *Surface, const SFont_Font *Font, int x, int y,
+ const char *text);
+
+// Returns the width of "text" in pixels
+ int SFont_TextWidth(const SFont_Font* Font, const char *text);
+// Returns the height of "text" in pixels (which is always equal to Font->Surface->h)
+ int SFont_TextHeight(const SFont_Font* Font);
+
+// Blits a string to Surface with centered x position
+ void SFont_WriteCenter(SDL_Surface *Surface, const SFont_Font* Font, int y,
+ const char *text);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SFONT_H */
diff --git a/source/code/common.cc b/source/code/common.cc new file mode 100644 index 0000000..c18f1d8 --- /dev/null +++ b/source/code/common.cc
@@ -0,0 +1,119 @@
+/*
+Block Attack - Rise of the Blocks, SDL game, besed on Nintendo's Tetris Attack
+Copyright (C) 2008 Poul Sander
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Poul Sander
+ R�vehjvej 36, V. 1111
+ 2800 Kgs. Lyngby
+ DENMARK
+ blockattack@poulsander.com
+ http://blockattack.sf.net
+*/
+
+#include "common.h"
+
+#ifdef WIN32
+//Returns path to "my Documents" in windows:
+string getMyDocumentsPath()
+{
+ TCHAR pszPath[MAX_PATH];
+ if (SUCCEEDED(SHGetSpecialFolderPath(NULL, pszPath, CSIDL_PERSONAL, FALSE))) {
+ // pszPath is now the path that you want
+#ifdef DEBUG
+ cout << "MyDocuments Located: " << pszPath << endl;
+#endif
+ string theResult= pszPath;
+ return theResult;
+ }
+ else
+ {
+ cout << "Warning: My Documents not found!" << endl;
+ string theResult ="";
+ return theResult;
+ }
+}
+
+#endif
+
+string getPathToSaveFiles()
+{
+#ifdef __unix__
+ return (string)getenv("HOME")+(string)"/.gamesaves/"+GAMENAME;
+#elif WIN32
+ return getMyDocumentsPath()+(string)"/My Games/"+GAMENAME;
+#else
+ return ".";
+#endif
+}
+
+
+
+commonTime getTotalTime()
+{
+ commonTime ct;
+ string filename = getPathToSaveFiles()+"/totalTime";
+ ifstream inFile(filename.c_str());
+ if(inFile)
+ {
+ inFile >> ct.days;
+ inFile >> ct.hours;
+ inFile >> ct.minutes;
+ inFile >> ct.seconds;
+ inFile.close();
+ }
+ else
+ {
+ ct.days = 0;
+ ct.hours = 0;
+ ct.minutes = 0;
+ ct.seconds = 0;
+ }
+ return ct;
+}
+
+commonTime addTotalTime(commonTime toAdd)
+{
+ commonTime ct = getTotalTime();
+
+ ct.seconds +=toAdd.seconds;
+ ct.minutes +=ct.seconds/60;
+ ct.seconds = ct.seconds%60;
+
+ ct.minutes += toAdd.minutes;
+ ct.hours += ct.minutes/60;
+ ct.minutes = ct.minutes%60;
+
+ ct.hours += toAdd.hours;
+ ct.days += ct.hours/24;
+ ct.minutes += ct.hours%24;
+
+ ct.days += toAdd.days;
+
+ string filename = getPathToSaveFiles()+"/totalTime";
+ ofstream outFile(filename.c_str(),ios::trunc);
+ if(outFile)
+ {
+ outFile << ct.days << endl;
+ outFile << ct.hours << endl;
+ outFile << ct.minutes << endl;
+ outFile << ct.seconds << endl;
+ outFile.close();
+ }
+ else
+ cout << "Error writing total time to: " << filename << endl;
+ return ct;
+}
diff --git a/source/code/common.h b/source/code/common.h new file mode 100644 index 0000000..74bf6fc --- /dev/null +++ b/source/code/common.h
@@ -0,0 +1,53 @@
+/*
+Block Attack - Rise of the Blocks, SDL game, besed on Nintendo's Tetris Attack
+Copyright (C) 2008 Poul Sander
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Poul Sander
+ R�vehjvej 36, V. 1111
+ 2800 Kgs. Lyngby
+ DENMARK
+ blockattack@poulsander.com
+ http://blockattack.sf.net
+*/
+
+#ifndef _COMMON_H
+#define _COMMON_H
+
+#define GAMENAME "blockattack"
+
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <stdlib.h>
+
+using namespace std;
+
+struct commonTime{
+ unsigned int days;
+ unsigned int hours;
+ unsigned int minutes;
+ unsigned int seconds;
+};
+
+string getPathToSaveFiles();
+
+commonTime getTotalTime();
+
+commonTime addTotalTime(commonTime toAdd);
+
+#endif /* _COMMON_H */
+
diff --git a/source/code/editor/BoardHolder.cpp b/source/code/editor/BoardHolder.cpp new file mode 100644 index 0000000..b4cad67 --- /dev/null +++ b/source/code/editor/BoardHolder.cpp
@@ -0,0 +1,154 @@
+/*
+Block Attack - Rise of the Blocks, SDL game, besed on Nintendo's Tetris Attack
+Copyright (C) 2007 Poul Sander
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Poul Sander
+ Raevehjvej 36, V. 1111
+ 2800 Kgs. Lyngby
+ DENMARK
+ blockattack@poulsander.com
+ http://blockattack.sf.net
+*/
+
+#include "BoardHolder.hpp"
+
+BoardHolder::BoardHolder(string filename)
+{
+ fstream inFile(filename.c_str(),ios::in);
+ if(inFile)
+ {
+ int nrOfBoards;
+ inFile >> nrOfBoards;
+ for(int i=0;i<nrOfBoards;i++)
+ {
+ TheBoard ourBoard;
+ int temp;
+ inFile >> temp;
+ ourBoard.setNumberOfMoves(temp);
+ for(int j=0;j<12;j++)
+ {
+ for(int k=0;k<6;k++)
+ {
+ inFile >> temp;
+ ourBoard.setBrick(k,j,temp);
+ }
+ }
+ theBoards[i] = ourBoard;
+ }
+ isNull = false;
+ }
+}
+
+BoardHolder::BoardHolder()
+{
+ isNull = false;
+}
+
+bool BoardHolder::saveBoards(string filename)
+{
+ fstream outFile(filename.c_str(),ios::out);
+ if(outFile)
+ {
+ outFile << getNumberOfBoards() << endl;
+ for(int i=0;i<getNumberOfBoards();i++)
+ {
+ outFile << theBoards[i].getNumberOfMoves() << endl;
+ for(int j=0;j<12;j++)
+ {
+ for(int k=0;k<6;k++)
+ {
+ outFile << theBoards[i].getBrick(k,j);
+ if(k<5)
+ outFile << " ";
+ else
+ outFile << endl;
+ }
+ }
+ }
+ outFile.close();
+ return true;
+ }
+ else
+ return false;
+}
+
+TheBoard BoardHolder::getModel(int nr)
+{
+ if(theBoards.size()<nr)
+ {
+ //Problem!
+
+ }
+ else
+ {
+ return theBoards[nr];
+ }
+}
+
+bool BoardHolder::setModel(int nr, TheBoard model)
+{
+ if((nr>49)||(nr<0))
+ return false;
+ theBoards[nr] = model;
+ return true;
+}
+
+int BoardHolder::getNumberOfBoards()
+{
+ return theBoards.size();
+}
+
+bool BoardHolder::addBoard()
+{
+ if(!(theBoards.size()<49))
+ return false;
+ TheBoard tb;
+ theBoards[theBoards.size()] = tb;
+ return true;
+}
+
+bool BoardHolder::removeBoard(int nr)
+{
+ vector<TheBoard>::iterator itr;
+ itr = theBoards.begin();
+ itr+=nr;
+ theBoards.erase(itr);
+}
+
+bool BoardHolder::moveBoardBack(int nr)
+{
+ if(nr<1) //We can't move back
+ return false;
+ if(nr>getNumberOfBoards())
+ return false;
+ TheBoard temp = theBoards[nr];
+ theBoards[nr] = theBoards[nr-1];
+ theBoards[nr-1] = temp;
+ return true;
+}
+
+bool BoardHolder::moveBoardForward(int nr)
+{
+ if(nr>getNumberOfBoards()-2) //We can't move forward
+ return false;
+ if(nr<0)
+ return false;
+ TheBoard temp = theBoards[nr];
+ theBoards[nr] = theBoards[nr+1];
+ theBoards[nr+1] = temp;
+ return true;
+}
diff --git a/source/code/editor/BoardHolder.hpp b/source/code/editor/BoardHolder.hpp new file mode 100644 index 0000000..18661fe --- /dev/null +++ b/source/code/editor/BoardHolder.hpp
@@ -0,0 +1,54 @@
+/*
+Block Attack - Rise of the Blocks, SDL game, besed on Nintendo's Tetris Attack
+Copyright (C) 2007 Poul Sander
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Poul Sander
+ Rævehjvej 36, V. 1111
+ 2800 Kgs. Lyngby
+ DENMARK
+ blockattack@poulsander.com
+ http://blockattack.sf.net
+*/
+
+#include "TheBoard.hpp"
+#include <vector>
+#include <string.h>
+#include <iostream>
+#include <fstream>
+
+#ifndef BOARDHOLDERDEFINED
+#define BOARDHOLDERDEFINED
+class BoardHolder
+{
+
+ private:
+ vector<TheBoard> theBoards;
+
+ public:
+ bool isNull;
+ BoardHolder();
+ BoardHolder(string filename);
+ bool saveBoards(string filename);
+ TheBoard getModel(int);
+ bool setModel(int nr,TheBoard model);
+ int getNumberOfBoards();
+ bool addBoard();
+ bool removeBoard(int);
+ bool moveBoardBack(int);
+ bool moveBoardForward(int);
+};
+#endif
diff --git a/source/code/editor/EditorInterface.cpp b/source/code/editor/EditorInterface.cpp new file mode 100644 index 0000000..5f94c4c --- /dev/null +++ b/source/code/editor/EditorInterface.cpp
@@ -0,0 +1,234 @@
+/*
+Block Attack - Rise of the Blocks, SDL game, besed on Nintendo's Tetris Attack
+Copyright (C) 2007 Poul Sander
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Poul Sander
+ Raevehjvej 36, V. 1111
+ 2800 Kgs. Lyngby
+ DENMARK
+ blockattack@poulsander.com
+ http://blockattack.sf.net
+*/
+
+/*
+TODO: The way we test for
+
+*/
+
+#include "EditorInterface.hpp"
+
+EditorInterface::EditorInterface()
+{
+ boardActive = -1;
+ saved = true;
+ fileSaved = true;
+ bh.isNull = true;
+}
+
+void EditorInterface::getModel(int nr)
+{
+ tb = bh.getModel(nr);
+ saved = true;
+ boardActive = nr;
+}
+
+bool EditorInterface::exists()
+{
+ if(bh.isNull)
+ return false;
+ else
+ return true;
+}
+
+void EditorInterface::selectColor(int color)
+{
+ colorSelected = color;
+}
+
+int EditorInterface::getSelectedColor()
+{
+ return colorSelected;
+}
+
+void EditorInterface::drawOnModel(int x, int y)
+{
+ if(boardActive!=-1)
+ {
+ if(colorSelected<7) //Ordinary thing
+ tb.setBrick(x,y,colorSelected);
+ if(colorSelected==7)
+ tb.moveUp(x,y);
+ if(colorSelected==8)
+ tb.moveDown(x,y);
+ saved = false;
+ }
+}
+
+void EditorInterface::moveLeft()
+{
+ if(boardActive!=-1)
+ tb.moveLeft();
+ saved = false;
+}
+
+void EditorInterface::moveRight()
+{
+ if(boardActive!=-1)
+ tb.moveRight();
+ saved = false;
+}
+
+void EditorInterface::deleteBoard()
+{
+ if(boardActive!=-1)
+ {
+ bh.removeBoard(boardActive);
+ boardActive = -1;
+ saved = true;
+ fileSaved = false;
+ }
+}
+
+void EditorInterface::moveBoardBack()
+{
+ if(boardActive!=-1)
+ {
+ if(bh.moveBoardBack(boardActive))
+ boardActive--;
+ }
+}
+
+void EditorInterface::moveBoardForward()
+{
+ if(boardActive!=-1)
+ {
+ if(bh.moveBoardForward(boardActive))
+ boardActive++;
+ }
+}
+
+void EditorInterface::saveBoard()
+{
+ if(boardActive!=-1)
+ {
+ bh.setModel(boardActive,tb);
+ saved = true;
+ fileSaved = false;
+ }
+}
+
+bool EditorInterface::saveFile(string filename)
+{
+ if((!bh.isNull)&&(filename!=""))
+ {
+ fileName = filename;
+ bh.saveBoards(filename);
+ fileSaved = true;
+ return true;
+ }
+ return false;
+}
+
+bool EditorInterface::saveFile()
+{
+ if((!bh.isNull)&&(fileName!=""))
+ {
+ bh.saveBoards(fileName);
+ fileSaved = true;
+ return true;
+ }
+ return false;
+}
+
+void EditorInterface::openFile(string filename)
+{
+ fileName = filename;
+ BoardHolder bh2(fileName);
+ bh = bh2;
+ saved = true;
+ fileSaved = true;
+}
+
+void EditorInterface::newFile()
+{
+ fileName = "";
+ bh = BoardHolder();
+ TheBoard tb2;
+ tb.isNull = true; // = null; What here!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ boardActive = -1;
+ saved = true;
+ fileSaved = false;
+}
+
+int EditorInterface::getColor(int x, int y)
+{
+ if(boardActive==-1)
+ return -1;
+ return tb.getBrick(x,y);
+}
+
+int EditorInterface::getActiveBoardNr()
+{
+ return boardActive;
+}
+
+int EditorInterface::getNumberOfMoves()
+{
+ if(!tb.isNull)
+ {
+ return tb.getNumberOfMoves();
+ }
+ return 0;
+}
+
+bool EditorInterface::newBoard()
+{
+ if(!bh.isNull)
+ {
+ fileSaved = false;
+ return bh.addBoard();
+ }
+ else
+ return false;
+}
+
+int EditorInterface::getNumberOfBoards()
+{
+ if(!bh.isNull)
+ return bh.getNumberOfBoards();
+ else
+ return 0;
+}
+
+void EditorInterface::setNumberOfMoves(int moves)
+{
+ if(!tb.isNull)
+ {
+ saved = false;
+ tb.setNumberOfMoves(moves);
+ }
+}
+
+bool EditorInterface::isSaved()
+{
+ return saved;
+}
+
+bool EditorInterface::fileIsSaved()
+{
+ return fileSaved;
+}
diff --git a/source/code/editor/EditorInterface.hpp b/source/code/editor/EditorInterface.hpp new file mode 100644 index 0000000..df747de --- /dev/null +++ b/source/code/editor/EditorInterface.hpp
@@ -0,0 +1,68 @@
+/*
+Block Attack - Rise of the Blocks, SDL game, besed on Nintendo's Tetris Attack
+Copyright (C) 2007 Poul Sander
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Poul Sander
+ Rævehjvej 36, V. 1111
+ 2800 Kgs. Lyngby
+ DENMARK
+ blockattack@poulsander.com
+ http://blockattack.sf.net
+*/
+
+#include "BoardHolder.hpp"
+
+#ifndef EDITORINTERFACEDEFINED
+#define EDITORINTERFACEDEFINED
+class EditorInterface
+{
+ private:
+ int colorSelected; //The color the user have selected
+ int boardActive; //Number of the active board, -1 if not active
+ TheBoard tb; //The active board
+ BoardHolder bh; //The Vector that holds the boards
+ bool saved; //The current board is saved
+ bool fileSaved; //The whole file is saved
+ string fileName; //The filename that is open, "" if no filename is given
+
+ public:
+ EditorInterface();
+ void getModel(int);
+ bool exists();
+ void selectColor(int color);
+ int getSelectedColor();
+ void drawOnModel(int x, int y);
+ void moveLeft();
+ void moveRight();
+ void deleteBoard();
+ void moveBoardBack();
+ void moveBoardForward();
+ void saveBoard();
+ bool saveFile(string);
+ bool saveFile();
+ void openFile(string);
+ void newFile();
+ int getColor(int x, int y);
+ int getActiveBoardNr();
+ int getNumberOfMoves();
+ bool newBoard();
+ int getNumberOfBoards();
+ void setNumberOfMoves(int);
+ bool isSaved();
+ bool fileIsSaved();
+};
+#endif
diff --git a/source/code/editor/TheBoard.cpp b/source/code/editor/TheBoard.cpp new file mode 100644 index 0000000..05a8afd --- /dev/null +++ b/source/code/editor/TheBoard.cpp
@@ -0,0 +1,141 @@
+/*
+Block Attack - Rise of the Blocks, SDL game, besed on Nintendo's Tetris Attack
+Copyright (C) 2007 Poul Sander
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Poul Sander
+ Rævehjvej 36, V. 1111
+ 2800 Kgs. Lyngby
+ DENMARK
+ blockattack@poulsander.com
+ http://blockattack.sf.net
+*/
+
+#include "TheBoard.hpp"
+
+TheBoard::TheBoard()
+{
+ numberOfMoves = 0;
+ for(int i = 0; i < BOARDWIDTH; i++)
+ for(int j = 0; j < BOARDHEIGHT;j++)
+ TheBoard::board[i][j] = -1;
+ isNull = false;
+}
+
+TheBoard::TheBoard(const TheBoard &tb)
+{
+ TheBoard::numberOfMoves = tb.numberOfMoves;
+ for(int i = 0; i < BOARDWIDTH; i++)
+ for(int j = 0; j < BOARDHEIGHT;j++)
+ TheBoard::board[i][j] = tb.board[i][j];
+ isNull = false;
+}
+
+void TheBoard::copyFrom(TheBoard *tb)
+{
+ TheBoard::numberOfMoves = tb->numberOfMoves;
+ for(int i = 0; i < BOARDWIDTH; i++)
+ for(int j = 0; j < BOARDHEIGHT;j++)
+ TheBoard::board[i][j] = tb->board[i][j];
+}
+
+bool TheBoard::setBrick(int x, int y, int color)
+{
+ if((x<0)||(x>=BOARDWIDTH)||(y<0)||(y>=12))
+ return false;
+ board[x][y]=color;
+ return true;
+}
+
+int TheBoard::getBrick(int x, int y)
+{
+ if((x<0)||(x>=BOARDWIDTH)||(y<0)||(y>=BOARDHEIGHT))
+ return -999;
+ return board[x][y];
+}
+
+void TheBoard::setNumberOfMoves(int moves)
+{
+ TheBoard::numberOfMoves = moves;
+}
+
+int TheBoard::getNumberOfMoves()
+{
+ return TheBoard::numberOfMoves;
+}
+
+bool TheBoard::moveUp(int x, int y)
+{
+ if((x<0)||(x>=BOARDWIDTH)||(y<0)||(y>=BOARDHEIGHT))
+ return false;
+ for(int i=1; i<=y; i++)
+ {
+ board[x][i-1]=board[x][i];
+ }
+ board[x][y]=-1;
+ return true;
+} //moveUp
+
+bool TheBoard::moveDown(int x, int y)
+{
+ if((x<0)||(x>=BOARDWIDTH)||(y<0)||(y>=BOARDHEIGHT))
+ return false;
+ for(int i=y-1; i>=0; i--)
+ {
+ board[x][i+1]=board[x][i];
+ }
+ board[x][0]=-1;
+ return true;
+}
+
+void TheBoard::moveRight()
+{
+ for(int i=0; i<BOARDHEIGHT;i++)
+ {
+ for(int j=BOARDWIDTH-2; j>=0; j--)
+ {
+ board[j+1][i]=board[j][i];
+ }
+ board[0][i] = -1;
+ }
+} //moveRight
+
+
+//moves all pieces one to the right
+void TheBoard::moveLeft()
+{
+ for(int i=0; i<BOARDHEIGHT;i++)
+ {
+ for(int j=1; j<=BOARDWIDTH-1; j++)
+ {
+ board[j-1][i]=board[j][i];
+ }
+ board[BOARDWIDTH-1][i] = -1;
+ }
+} //moveRight
+
+bool TheBoard::equals(TheBoard &tb2)
+{
+ if(tb2.getNumberOfMoves()!=getNumberOfMoves())
+ return false;
+ for(int i=0;i<BOARDWIDTH;i++)
+ for(int j=0;j<BOARDHEIGHT;j++)
+ {
+ if(tb2.board[i][j]!=board[i][j])
+ return false;
+ }
+ return true;
+}
diff --git a/source/code/editor/TheBoard.hpp b/source/code/editor/TheBoard.hpp new file mode 100644 index 0000000..bb3ceec --- /dev/null +++ b/source/code/editor/TheBoard.hpp
@@ -0,0 +1,55 @@
+/*
+Block Attack - Rise of the Blocks, SDL game, besed on Nintendo's Tetris Attack
+Copyright (C) 2007 Poul Sander
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Poul Sander
+ Rævehjvej 36, V. 1111
+ 2800 Kgs. Lyngby
+ DENMARK
+ blockattack@poulsander.com
+ http://blockattack.sf.net
+*/
+
+using namespace std;
+
+#define BOARDWIDTH 6
+#define BOARDHEIGHT 12
+
+#ifndef THEBOARDDEFINED
+#define THEBOARDDEFINED
+ class TheBoard
+ {
+ private:
+ int board[BOARDWIDTH][BOARDHEIGHT];
+ int numberOfMoves;
+
+ public:
+ bool isNull;
+ TheBoard();
+ TheBoard(const TheBoard &tb);
+ void copyFrom(TheBoard *tb);
+ bool setBrick(int x, int y, int color);
+ int getBrick(int x, int y);
+ void setNumberOfMoves(int);
+ int getNumberOfMoves();
+ bool moveUp(int x, int y);
+ bool moveDown(int x, int y);
+ void moveRight();
+ void moveLeft();
+ bool equals(TheBoard &tb);
+ };
+#endif
diff --git a/source/code/editor/editorMain.cpp b/source/code/editor/editorMain.cpp new file mode 100644 index 0000000..d7312e4 --- /dev/null +++ b/source/code/editor/editorMain.cpp
@@ -0,0 +1,163 @@
+/*
+editorMain.cpp
+Copyright (C) 2007 Poul Sander
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Poul Sander
+ Rævehøjvej 36, V. 1111
+ 2800 Kgs. Lyngby
+ DENMARK
+ blockattack@poulsander.com
+*/
+
+#include "editorMain.hpp"
+
+EditorInterface ei;
+
+//How to write!
+inline void DrawIMG(SDL_Surface *img, SDL_Surface *target, int x, int y)
+{
+ SDL_Rect dest;
+ dest.x = x;
+ dest.y = y;
+ SDL_BlitSurface(img, NULL, target, &dest);
+}
+
+class createFileButton : public aButton
+{
+
+ public:
+ createFileButton()
+ {
+ aButton::aButton(100,100,bCreateFile);
+ }
+
+ void click(int x,int y)
+ {
+ if(clicked(x,y))
+ {
+ ei.newBoard();
+ }
+ }
+};
+
+class deletePuzzleButton : public aButton
+{
+
+ public:
+ deletePuzzleButton()
+ {
+ aButton::aButton(240,100,bDeletePuzzle);
+ }
+
+ void click(int x,int y)
+ {
+ if(clicked(x,y))
+ {
+ ei.deleteBoard();
+ }
+ }
+};
+
+class loadFileButton : public aButton
+{
+
+ public:
+ loadFileButton()
+ {
+ aButton::aButton(240,100,bLoadFile);
+ }
+
+ void click(int x,int y)
+ {
+ if(clicked(x,y))
+ {
+ //Thing to load file!
+ }
+ }
+};
+
+class moveBackButton : public aButton
+{
+
+ public:
+ moveBackButton()
+ {
+ aButton::aButton(240,100,bMoveBack);
+ }
+
+ void click(int x,int y)
+ {
+ if(clicked(x,y))
+ {
+ ei.moveBoardBack();
+ }
+ }
+};
+
+class moveDownButton : public aButton
+{
+
+ public:
+ moveDownButton()
+ {
+ aButton::aButton(240,100,bMoveDown);
+ }
+
+ void click(int x,int y)
+ {
+ if(clicked(x,y))
+ {
+ if(ei.getNumberOfMoves()>0)
+ ei.setNumberOfMoves(ei.getNumberOfMoves()-1);
+ }
+ }
+};
+
+theEditor::theEditor()
+{
+ //This is the constructor
+ createFileButton cb;
+ buttons.push_back(cb);
+ deletePuzzleButton dpb;
+ buttons.push_back(dpb);
+}
+
+void theEditor::drawButtons()
+{
+ for(int i = 0;i<buttons.size(); i++)
+ {
+ (&(buttons[i]))->draw();
+ }
+}
+
+void aButton::click(int x, int y)
+{
+ cout << "Error: aButtons's click command was executed!" << endl;
+}
+
+void aButton::draw()
+{
+ DrawIMG(label,screen,x,y);
+}
+
+void theEditor::click(int x, int y)
+{
+ for(int i = 0;i<buttons.size(); i++)
+ {
+ (&(buttons[i]))->click(x,y);
+ }
+}
diff --git a/source/code/editor/editorMain.hpp b/source/code/editor/editorMain.hpp new file mode 100644 index 0000000..d015093 --- /dev/null +++ b/source/code/editor/editorMain.hpp
@@ -0,0 +1,101 @@
+/*
+editorMain.hpp
+Copyright (C) 2007 Poul Sander
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Poul Sander
+ Rævehøjvej 36, V. 1111
+ 2800 Kgs. Lyngby
+ DENMARK
+ blockattack@poulsander.com
+*/
+
+#include "SDL.h"
+#include "EditorInterface.hpp"
+#include <vector>
+
+//Do to stability reasons we load everything in the main and just refer to it here:
+extern SDL_Surface *bCreateFile;
+extern SDL_Surface *bDeletePuzzle;
+extern SDL_Surface *bLoadFile;
+extern SDL_Surface *bMoveBack;
+extern SDL_Surface *bMoveDown;
+extern SDL_Surface *bMoveForward;
+extern SDL_Surface *bMoveLeft;
+extern SDL_Surface *bMoveRight;
+extern SDL_Surface *bMoveUp;
+extern SDL_Surface *bNewPuzzle;
+extern SDL_Surface *bSaveFileAs;
+extern SDL_Surface *bSavePuzzle;
+extern SDL_Surface *bSaveToFile;
+extern SDL_Surface *bTestPuzzle;
+
+//The screen we draw on:
+extern SDL_Surface *screen;
+
+extern EditorInterface ei;
+
+class aButton
+{
+ public:
+ int x,y,width,height;
+ SDL_Surface *label;
+
+ aButton()
+ {
+ }
+
+ aButton(int x,int y,SDL_Surface *ss)
+ {
+ this->x = x;
+ this->y = y;
+ this->label = ss;
+ width = this->label->w;
+ height = this->label->h;
+ }
+
+ void draw();
+
+ //Function to check if the button is clicked.
+ bool clicked(int x, int y)
+ {
+ if((x>=this->x)&&(x<=this->x+width)&&(y>=this->y)&&(y<=this->y+height))
+ return true;
+ else
+ return false;
+ }
+
+ void click(int x, int y);
+};
+
+const int numberOfButtons = 14;
+
+//The editor itself...
+class theEditor
+{
+ private:
+ vector<aButton> buttons;
+
+
+ public:
+
+ theEditor();
+
+ void drawButtons();
+
+ void click(int x, int y);
+
+};
diff --git a/source/code/highscore.cpp b/source/code/highscore.cpp new file mode 100644 index 0000000..c151649 --- /dev/null +++ b/source/code/highscore.cpp
@@ -0,0 +1,186 @@
+/*
+highscore.cpp
+Copyright (C) 2005 Poul Sander
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Poul Sander
+ Rævehøjvej 36, V. 1111
+ 2800 Kgs. Lyngby
+ DENMARK
+ blockattack@poulsander.com
+*/
+
+#include "highscore.h"
+
+#ifdef WIN32
+
+//Returns path to "my Documents" in windows:
+string getMyDocumentsPath1()
+{
+ TCHAR pszPath[MAX_PATH];
+ //if (SUCCEEDED(SHGetSpecialFolderPath(NULL, pszPath, CSIDL_PERSONAL, FALSE))) {
+ if (SUCCEEDED(SHGetSpecialFolderPath(NULL, pszPath, CSIDL_PERSONAL, FALSE))) {
+ // pszPath is now the path that you want
+ cout << "MyDocuments Located: " << pszPath << endl;
+ string theResult= pszPath;
+ return theResult;
+ }
+ else
+ {
+ cout << "Warning: My Documents not found!" << endl;
+ string theResult ="";
+ return theResult;
+ }
+}
+
+#endif
+
+Highscore::Highscore(int type)
+{
+#if defined(__unix__)
+ string home = getenv("HOME");
+ string filename1 = home+"/.gamesaves/blockattack/endless.dat";
+ string filename2 = home+"/.gamesaves/blockattack/timetrial.dat";
+#elif defined(_WIN32)
+ string home = getMyDocumentsPath1();
+ string filename1, filename2;
+ if (&home!=NULL)
+ {
+ filename1 = home+"/My Games/blockattack/endless.dat";
+ filename2 = home+"/My Games/blockattack/timetrial.dat";
+ }
+ else
+ {
+ filename1 = "endless.dat";
+ filename2 = "timetrial.dat";
+ }
+#else
+ string filename1 = "endless.dat";
+ string filename2 = "timetrial.dat";
+#endif
+ ourType = type;
+ if (type == 1) filename = (char*)malloc(filename1.length()+1);
+ if (type == 2) filename = (char*)malloc(filename2.length()+1);
+ if (filename == NULL){
+ cout << "Out of memory" << endl;
+ exit(1);
+ }
+ if (type == 1) memcpy(filename,filename1.c_str(),filename1.length()+1);
+ if (type == 2) memcpy(filename,filename2.c_str(),filename2.length()+1);
+ ifstream scorefile(filename, ios::binary);
+ if (scorefile)
+ {
+ for (int i = 0; i<top; i++)
+ {
+ scorefile.read(tabel[i].name,30*sizeof(char));
+ scorefile.read(reinterpret_cast<char*>(&tabel[i].score), sizeof(int));
+ }
+ }
+ else
+ {
+ for (int i = 0; i<top; i++)
+ {
+ strcpy(tabel[i].name,"Poul Sander \0");
+ tabel[i].score = 2000 - i*100;
+ }
+ }
+ scorefile.close();
+ free(filename);
+ writeFile();
+}
+
+void Highscore::writeFile()
+{
+#if defined(__unix__)
+ string home = getenv("HOME");
+ string filename1 = home+"/.gamesaves/blockattack/endless.dat";
+ string filename2 = home+"/.gamesaves/blockattack/timetrial.dat";
+#elif defined(_WIN32)
+ string home = getMyDocumentsPath1();
+ string filename1, filename2;
+ if (&home!=NULL)
+ {
+ filename1 = home+"/My Games/blockattack/endless.dat";
+ filename2 = home+"/My Games/blockattack/timetrial.dat";
+ }
+ else
+ {
+ filename1 = "endless.dat";
+ filename2 = "timetrial.dat";
+ }
+#else
+ string filename1 = "endless.dat";
+ string filename2 = "timetrial.dat";
+#endif
+ if (ourType == 1) filename = (char*)malloc(filename1.length()+1);
+ if (ourType == 2) filename = (char*)malloc(filename2.length()+1);
+ if (filename == NULL){
+ cout << "Out of memory" << endl;
+ exit(1);
+ }
+ if (ourType == 1) memcpy(filename,filename1.c_str(),filename1.length()+1);
+ if (ourType == 2) memcpy(filename,filename2.c_str(),filename2.length()+1);
+
+ ofstream outfile;
+ outfile.open(Highscore::filename, ios::binary |ios::trunc);
+ if (!outfile)
+ {
+ cout << "Error writing to file: " << filename << endl;
+ exit(1);
+ }
+ for (int i = 0;i<top;i++)
+ {
+ outfile.write(tabel[i].name,30*sizeof(char));
+ outfile.write(reinterpret_cast<char*>(&tabel[i].score),sizeof(int));
+ }
+ outfile.close();
+ free(filename);
+}
+
+bool Highscore::isHighScore(int newScore)
+{
+ if (newScore>tabel[top-1].score)
+ return true;
+ else
+ return false;
+}
+
+void Highscore::addScore(char newName[], int newScore)
+{
+ int ranking = top-1;
+ while ((tabel[ranking-1].score<newScore) && (ranking != 0))
+ ranking--;
+ for (int i=top-1; i>ranking; i--)
+ {
+ tabel[i].score = tabel[i-1].score;
+ strcpy(tabel[i].name," \0");
+ strcpy(tabel[i].name,tabel[i-1].name);
+ }
+ tabel[ranking].score = newScore;
+ strcpy(tabel[ranking].name," \0");
+ strcpy(tabel[ranking].name,newName);
+ Highscore::writeFile();
+}
+
+int Highscore::getScoreNumber(int room)
+{
+ return tabel[room].score;
+}
+
+char* Highscore::getScoreName(int room)
+{
+ return &tabel[room].name[0];
+}
diff --git a/source/code/highscore.h b/source/code/highscore.h new file mode 100644 index 0000000..d157fb2 --- /dev/null +++ b/source/code/highscore.h
@@ -0,0 +1,70 @@
+/*
+highscore.h
+Copyright (C) 2005 Poul Sander
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Poul Sander
+ Rævehøjvej 36, V. 1111
+ 2800 Kgs. Lyngby
+ DENMARK
+ blockattack@poulsander.com
+*/
+
+#include <iostream>
+#include <fstream>
+#include <cstring>
+#include <string>
+#include <stdlib.h>
+
+#ifdef _WIN32
+#ifndef CSIDL_PERSONAL
+#define CSIDL_PERSONAL 0x0005
+#endif
+#define _WIN32_IE 0x0400
+#include "windows.h"
+#include <shlobj.h>
+#endif
+
+using namespace std;
+
+const int top = 10;
+
+struct record
+{
+ char name[30];
+ int score;
+};
+
+class Highscore
+{
+private:
+ record tabel[top];
+ char* filename;
+ int ourType; //This is ugly, remove me, plz!
+ void writeFile();
+public:
+
+ Highscore()
+ {
+ }
+
+ Highscore(int type);
+
+ bool isHighScore(int);
+ void addScore(char[],int);
+ int getScoreNumber(int);
+ char* getScoreName(int);
+};
diff --git a/source/code/joypad.cpp b/source/code/joypad.cpp new file mode 100644 index 0000000..457b210 --- /dev/null +++ b/source/code/joypad.cpp
@@ -0,0 +1,176 @@
+/*
+joypad.cpp - Enables joypad support
+Copyright (C) 2005 Poul Sander
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Poul Sander
+ Rævehøjvej 36, V. 1111
+ 2800 Kgs. Lyngby
+ DENMARK
+ blockattack@poulsander.com
+*/
+
+#include "joypad.h"
+
+bool Joypad_init()
+{
+ if (0==SDL_InitSubSystem(SDL_INIT_JOYSTICK))
+ return true;
+ else
+ return false;
+}
+
+Joypad_status Joypad_getStatus(SDL_Joystick *joystick)
+{
+ Joypad_status status;
+ for (int i=0; i<NRofPADS; i++)
+ {
+ //cout << SDL_JoystickNumAxes(joystick) << endl;
+ if (i*2>=SDL_JoystickNumAxes(joystick))
+ {
+ status.padDown[i]=false;
+ status.padUp[i] = false;
+ status.padLeft[i] = false;
+ status.padRight[i] = false;
+ }
+ else
+ {
+ //cout << SDL_JoystickGetAxis(joystick,i*2+1)<< endl;
+ if (SDL_JoystickGetAxis(joystick,i*2)<(-8000))
+ status.padLeft[i]=1;
+ else
+ status.padLeft[i]=0;
+ if (SDL_JoystickGetAxis(joystick,i*2)>(8000))
+ status.padRight[i]=1;
+ else
+ status.padRight[i]=0;
+ if (SDL_JoystickGetAxis(joystick,i*2+1)<(-8000))
+ status.padUp[i]=1;
+ else
+ status.padUp[i]=0;
+ if (SDL_JoystickGetAxis(joystick,i*2+1)>(8000))
+ status.padDown[i]=1;
+ else
+ status.padDown[i]=0;
+ }
+ }//NRofPADS
+ for (int i=0; i<NRofBUTTONS; i++)
+ {
+ if (i>=SDL_JoystickNumButtons(joystick))
+ status.button[i]=false;
+ else
+ if (1==SDL_JoystickGetButton(joystick,i))
+ status.button[i] = true;
+ else
+ status.button[i] = false;
+ }
+ return status;
+}
+
+Joypad::Joypad()
+{
+ up=false;
+ down=false;
+ left=false;
+ right=false;
+ but1=false;
+ but2=false;
+ upREL=true;
+ downREL=true;
+ leftREL=true;
+ rightREL=true;
+ but1REL=true;
+ but2REL=true;
+ int joynum = 0;
+ while ((SDL_JoystickOpened(joynum))&&(joynum<Joypad_number))
+ joynum++;
+ if (joynum>=Joypad_number)
+ working = false;
+ else
+ {
+ joystick=SDL_JoystickOpen(joynum);
+ if (joystick==NULL)
+ working =false;
+ else
+ working=true;
+ }
+}
+
+Joypad::~Joypad()
+{
+ SDL_JoystickClose(joystick);
+}
+
+void Joypad::update()
+{
+ SDL_JoystickUpdate();
+ Joypad_status status = Joypad_getStatus(joystick);
+ if ((upREL)&&((status.padUp[0])||(status.padUp[1])||(status.padUp[2])||(status.padUp[3])))
+ {
+ up=true;
+ upREL=false;
+ }
+ else
+ up=false;
+ if ((downREL)&&((status.padDown[0])||(status.padDown[1])||(status.padDown[2])||(status.padDown[3])))
+ {
+ down=true;
+ downREL=false;
+ }
+ else
+ down=false;
+ if ((leftREL)&&((status.padLeft[0])||(status.padLeft[1])||(status.padLeft[2])||(status.padLeft[3])))
+ {
+ left=true;
+ leftREL=false;
+ }
+ else
+ left=false;
+ if ((rightREL)&&((status.padRight[0])||(status.padRight[1])||(status.padRight[2])||(status.padRight[3])))
+ {
+ right=true;
+ rightREL=false;
+ }
+ else
+ right=false;
+ if ((but1REL)&&((status.button[0])||(status.button[2])||(status.button[4])||(status.button[6])))
+ {
+ but1=true;
+ but1REL=false;
+ }
+ else
+ but1=false;
+ if ((but2REL)&&((status.button[1])||(status.button[3])||(status.button[5])||(status.button[7])))
+ {
+ but2=true;
+ but2REL=false;
+ }
+ else
+ but2=false;
+ //Now testing for up
+ if (!((status.padUp[0])||(status.padUp[1])||(status.padUp[2])||(status.padUp[3])))
+ upREL = true;
+ if (!((status.padDown[0])||(status.padDown[1])||(status.padDown[2])||(status.padDown[3])))
+ downREL = true;
+ if (!((status.padLeft[0])||(status.padLeft[1])||(status.padLeft[2])||(status.padLeft[3])))
+ leftREL = true;
+ if (!((status.padRight[0])||(status.padRight[1])||(status.padRight[2])||(status.padRight[3])))
+ rightREL= true;
+ if (!((status.button[0])||(status.button[2])||(status.button[4])||(status.button[6])))
+ but1REL = true;
+ if (!((status.button[1])||(status.button[3])||(status.button[5])||(status.button[7])))
+ but2REL = true;
+}
diff --git a/source/code/joypad.h b/source/code/joypad.h new file mode 100644 index 0000000..e0bba66 --- /dev/null +++ b/source/code/joypad.h
@@ -0,0 +1,70 @@
+/*
+joypad.h - Enables joypad support
+Copyright (C) 2005 Poul Sander
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Poul Sander
+ Rævehøjvej 36, V. 1111
+ 2800 Kgs. Lyngby
+ DENMARK
+ blockattack@poulsander.com
+*/
+
+//headerfile joypad.h
+
+#include <SDL.h>
+#include <stdlib.h>
+#include <iostream>
+
+#define NRofPADS 4
+#define NRofBUTTONS 12
+
+using namespace std;
+
+struct Joypad_status{
+ bool padLeft[NRofPADS];
+ bool padRight[NRofPADS];
+ bool padUp[NRofPADS];
+ bool padDown[NRofPADS];
+ bool button[NRofBUTTONS];
+};
+
+//Contains the init code
+bool Joypad_init();
+
+//How many joypads are availble?
+#define Joypad_number SDL_NumJoysticks()
+
+//Open a joystick
+#define Joypad_open(X) SDL_JoystickOpen(X)
+
+//Returns the status of the joypad
+Joypad_status Joypad_getStatus(SDL_Joystick);
+
+class Joypad{
+private:
+ SDL_Joystick *joystick;
+ static int Joy_count;
+public:
+ bool up,down,left,right,but1,but2;
+ bool upREL,downREL,leftREL,rightREL,but1REL,but2REL;
+ bool working;
+
+ Joypad();
+ ~Joypad();
+
+ void update();
+};
diff --git a/source/code/listFiles.cpp b/source/code/listFiles.cpp new file mode 100644 index 0000000..1c840c4 --- /dev/null +++ b/source/code/listFiles.cpp
@@ -0,0 +1,177 @@
+/*
+listFiles.cpp
+Copyright (C) 2005 Poul Sander
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Poul Sander
+ R�veh�jvej 36, V. 1111
+ 2800 Kgs. Lyngby
+ DENMARK
+ blockattack@poulsander.com
+*/
+
+/*
+listFiles.cpp
+*/
+
+#include "listFiles.h"
+
+/*ListFiles::ListFiles()
+{
+
+}
+
+ListFiles::~ListFiles()
+{
+
+}*/
+
+
+void ListFiles::setDirectory(string directory)
+{
+ for (int i=0;i<MAX_NR_OF_FILES;i++)
+ filenames[i]="";
+#if defined(_WIN32)
+ DWORD dwError;
+ dictory+="/*";
+ hFind = FindFirstFile(dictory.c_str(), &FindFileData);
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ printf ("Invalid file handle. Error is %u\n", GetLastError());
+ }
+ else
+ {
+ nrOfFiles=0;
+ filenames[nrOfFiles] = FindFileData.cFileName;
+ printf("File: %s\n",FindFileData.cFileName);
+ while ((FindNextFile(hFind, &FindFileData) != 0)&&(nrOfFiles<MAX_NR_OF_FILES-1))
+ {
+ nrOfFiles++;
+ filenames[nrOfFiles] = FindFileData.cFileName;
+ printf("File: %s\n",FindFileData.cFileName);
+ }
+
+ dwError = GetLastError();
+ FindClose(hFind);
+ if (dwError != ERROR_NO_MORE_FILES)
+ {
+ printf ("FindNextFile error. Error is %s\n", dwError);
+ }
+ }
+#elif defined(__unix__)
+ DIR *DirectoryPointer;
+ struct dirent *dp;
+ nrOfFiles=0;
+ //printf("Will look in: %s\n",directory.c_str());
+ DirectoryPointer = opendir(directory.c_str());
+ if(!DirectoryPointer)
+ return;
+ while ((dp=readdir(DirectoryPointer))&&(nrOfFiles<MAX_NR_OF_FILES-1))
+ {
+ nrOfFiles++;
+ filenames[nrOfFiles] = (string)(char*)dp->d_name;
+ }
+ closedir(DirectoryPointer);
+
+
+#endif
+ startFileNr=FIRST_FILE;
+ //Put code here
+}
+
+bool ListFiles::isInList(string name)
+{
+ for (int i=0;(i<=nrOfFiles);i++)
+ {
+ if (0==strcmp(name.c_str(),filenames[i].c_str()))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void ListFiles::setDirectory2(string dic)
+{
+#if defined(__unix__)
+ DIR *DirectoryPointer;
+ struct dirent *dp;
+ //printf("Will look in: %s\n",dic.c_str());
+ DirectoryPointer = opendir(dic.c_str());
+ if(!DirectoryPointer)
+ return;
+ while ((dp=readdir(DirectoryPointer))&&(nrOfFiles<MAX_NR_OF_FILES-1))
+ {
+ string name = (string)(char*)dp->d_name;
+ if (!isInList(name))
+ {
+ nrOfFiles++;
+ filenames[nrOfFiles] = name;
+ }
+ }
+ closedir(DirectoryPointer);
+
+ startFileNr=FIRST_FILE;
+#endif
+}
+
+string ListFiles::getFileName(int nr)
+{
+ if (startFileNr+nr<MAX_NR_OF_FILES)
+ return filenames[startFileNr+nr];
+ else
+ {
+ string emptyString="";
+ return "";
+ }
+}
+
+bool ListFiles::fileExists(int nr)
+{
+ string emptyString="";
+ if (startFileNr+nr<MAX_NR_OF_FILES)
+ {
+ if (filenames[startFileNr+nr]==emptyString)
+ return false;
+ else
+ return true;
+ }
+ else
+ return false;
+}
+
+void ListFiles::back()
+{
+ if (startFileNr>FIRST_FILE)
+ startFileNr = startFileNr-10;
+ if (startFileNr<FIRST_FILE)
+ startFileNr = FIRST_FILE;
+}
+
+void ListFiles::forward()
+{
+ if (startFileNr<nrOfFiles-FIRST_FILE)
+ startFileNr = startFileNr+10;
+}
+
+string ListFiles::getRandom()
+{
+ int numberOfFiles = nrOfFiles-FIRST_FILE+1;
+ if(numberOfFiles<1)
+ return "";
+ int select = rand()%numberOfFiles;
+ return filenames[FIRST_FILE+select];
+}
diff --git a/source/code/listFiles.h b/source/code/listFiles.h new file mode 100644 index 0000000..8859845 --- /dev/null +++ b/source/code/listFiles.h
@@ -0,0 +1,68 @@
+/*
+listFiles.h
+Copyright (C) 2005 Poul Sander
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Poul Sander
+ R�veh�jvej 36, V. 1111
+ 2800 Kgs. Lyngby
+ DENMARK
+ blockattack@poulsander.com
+*/
+
+//listFiles.h - List files in a given directory, 10 files at a time, at most 250 files
+#include <string.h>
+#include <iostream>
+#if defined(_WIN32)
+#include <windows.h>
+#elif defined(__unix__)
+#include <dirent.h>
+#endif
+#include <string>
+#include <vector>
+
+#define MAX_NR_OF_FILES 253
+#if defined (_WIN32)
+#define FIRST_FILE 2
+#else
+#define FIRST_FILE 3
+#endif
+
+using namespace std;
+
+class ListFiles
+{
+private:
+ int startFileNr; //The first fileto belisted
+ string filenames[MAX_NR_OF_FILES];
+ int nrOfFiles;
+#if defined(_WIN32)
+ WIN32_FIND_DATA FindFileData;
+ HANDLE hFind;
+#endif
+ bool isInList(string name); //The name is already in the list
+public:
+ //ListFiles();
+ //~ListFiles();
+ void setDirectory(string dictory); //Find file in BlockAttack folder
+ void setDirectory2(string dictory); //Second directory we also look in
+ //void setDirecctoryInHome(string dictory); //Find files in home folder (it should work...)
+ string getFileName(int); //Returns the filename of a file
+ bool fileExists(int);
+ void forward(); //inclease startFile by 10
+ void back(); //decrease startFile by 10
+ string getRandom(); //Return the name of a random file in the directory, empty if none
+};
diff --git a/source/code/main.cpp b/source/code/main.cpp new file mode 100644 index 0000000..bdb1f86 --- /dev/null +++ b/source/code/main.cpp
@@ -0,0 +1,4580 @@
+/*
+Block Attack - Rise of the Blocks, SDL game, besed on Nintendo's Tetris Attack
+Copyright (C) 2008 Poul Sander
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Poul Sander
+ R�vehjvej 36, V. 1111
+ 2800 Kgs. Lyngby
+ DENMARK
+ blockattack@poulsander.com
+ http://blockattack.sf.net
+*/
+
+#define VERSION_NUMBER "version 1.4.0 BETA"
+
+//If DEBUG is defined: AI info and FPS will be written to screen
+//#define DEBUG
+
+//If NETWORK id defined: enet will be used
+#define NETWORK
+
+//Macros to convert surfaces (for faster drawing)
+#define CONVERT(n) tmp = SDL_DisplayFormat(n); SDL_FreeSurface(n); n = tmp
+#define CONVERTA(n) tmp = SDL_DisplayFormatAlpha(n); SDL_FreeSurface(n); n = tmp
+
+#include <iostream>
+#include <stdlib.h>
+#include <time.h> //Used for srand()
+#include <sstream>
+#include <string>
+#include "SDL.h" //The SDL libary, used for most things
+#include <SDL_mixer.h> //Used for sound & music
+#include <SDL_image.h> //To load PNG images!
+#include "ttfont.h" //To use True Type Fonts in SDL
+//#include "config.h"
+#include <vector>
+
+//if SHAREDIR is not used we look in current directory
+#ifndef SHAREDIR
+#define SHAREDIR "."
+#endif
+
+
+
+//enet things
+#ifdef NETWORK
+#include "enet/enet.h"
+//#include "enet/list.h"
+//#include "enet/protocol.h"
+#endif
+//enet things end
+
+#include "SFont.h" //Used to write on screen
+#include "highscore.h" //Stores highscores
+#include "ReadKeyboard.h" //Reads text from keyboard
+#include "joypad.h" //Used for joypads
+#include "listFiles.h" //Used to show files on screen
+#include "replay.h" //Used for replays
+#include "stats.h" //Saves general stats
+//#include "editor/editorMain.hpp" //The level editor
+#include "uploadReplay.h" //Takes care of everything libcurl related
+
+#include "common.h"
+
+/*******************************************************************************
+* All variables and constant has been moved to mainVars.hpp for the overview. *
+*******************************************************************************/
+#include "mainVars.hpp"
+
+void MakeBackground(int,int);
+
+void closeAllMenus()
+{
+ bNewGameOpen=false; //show sub menues
+ bOptionsOpen=false; //Show OptionsMenu (Configure and Select Puzzle)
+ b1playerOpen=false; //show submenu
+ b2playersOpen=false;
+ bReplayOpen = false;
+#ifdef NETWORK
+ bNetworkOpen = false;
+#endif
+ showOptions = false;
+ showHighscores = false;
+
+}
+
+
+
+//Because we use the SHAREDIR we need:
+SDL_Surface * IMG_Load2(char* path) {
+
+ char * tmp;
+ SDL_Surface * ret=NULL;
+ tmp = (char*)malloc (sizeof(char)*(strlen(path)+strlen(sharedir)+2));
+ strcpy(tmp, sharedir);
+ strcat(tmp, "/");
+ strcat(tmp, path);
+#ifdef DEBUG
+ printf("loading %s\n",tmp);
+#endif
+ if (!(ret = IMG_Load(tmp)))
+ ret = IMG_Load(path);
+
+ free(tmp);
+ return ret;
+}
+
+//Function to replace an image (ie. for a theme). Return true if replacing
+bool reloadIMG(SDL_Surface **surface2replace, string replaceWith)
+{
+ string fullPath = SHAREDIR+(string)"/themes/"+replaceWith;
+ #ifdef DEBUG
+ cout << "Trying to load " << fullPath << endl;
+ #endif
+ SDL_Surface * temp = NULL;
+ temp = IMG_Load(fullPath.c_str());
+ if(temp) //If we loaded a new image
+ {
+ #ifdef DEBUG
+ cout << "Found in game folder: " << fullPath << endl;
+ #endif
+ SDL_FreeSurface(*surface2replace);
+ *surface2replace = temp;
+ return true;
+ }
+ //Stop if under windows:
+ #ifdef __unix__
+ fullPath = (string)getenv("HOME")+(string)"/.gamesaves/blockattack/themes/"+replaceWith;
+ #ifdef DEBUG
+ cout << "Trying to load " << fullPath << endl;
+ #endif
+ temp = IMG_Load(fullPath.c_str());
+ if(temp) //If we loaded a new image
+ {
+ #ifdef DEBUG
+ cout << "Found in home folder: " << fullPath << endl;
+ #endif
+ SDL_FreeSurface(*surface2replace);
+ *surface2replace = temp;
+ return true;
+ }
+ #endif
+ *surface2replace = * surface2replace;
+ return false;
+}
+
+void loadTheme(string themeName)
+{
+ reloadIMG(&backgroundImage,themeName+"/background.png");
+ reloadIMG(&backgroundImage,themeName+"/background.jpg");
+ CONVERT(backgroundImage); //We should always convert even if we don't have to or else: SEGFAULT!
+ reloadIMG(&bNewGame,themeName+"/bNewGame.png");
+ CONVERT(bNewGame);
+ reloadIMG(&b1player,themeName+"/bOnePlayer.png");
+ CONVERT(b1player);
+ reloadIMG(&b2players,themeName+"/bTwoPlayers.png");
+ CONVERT(b2players);
+ reloadIMG(&bVsMode,themeName+"/bVsGame.png");
+ CONVERT(bVsMode);
+ reloadIMG(&bPuzzle,themeName+"/bPuzzle.png");
+ CONVERT(bPuzzle);
+ reloadIMG(&bStageClear,themeName+"/bStageClear.png");
+ CONVERT(bStageClear);
+ reloadIMG(&bTimeTrial,themeName+"/bTimeTrial.png");
+ CONVERT(bTimeTrial);
+ reloadIMG(&bEndless,themeName+"/bEndless.png");
+ CONVERT(bEndless);
+ reloadIMG(&bOptions,themeName+"/bOptions.png");
+ CONVERT(bOptions);
+ reloadIMG(&bConfigure,themeName+"/bConfigure.png");
+ CONVERTA(bConfigure);
+ reloadIMG(&bSelectPuzzle,themeName+"/bSelectPuzzle.png");
+ CONVERTA(bSelectPuzzle);
+ reloadIMG(&bReplay,themeName+"/bReplay.png");
+ CONVERTA(bReplay);
+ reloadIMG(&bReplay,themeName+"/bSave.png");
+ CONVERTA(bSave);
+ reloadIMG(&bLoad,themeName+"/bLoad.png");
+ CONVERTA(bLoad);
+#ifdef NETWORK
+ reloadIMG(&bNetwork,themeName+"/bNetwork.png");
+ CONVERTA(bNetwork);
+ reloadIMG(&bHost,themeName+"/bHost.png");
+ CONVERTA(bHost);
+ reloadIMG(&bConnect,themeName+"/bConnect.png");
+ CONVERTA(bConnect);
+#endif
+ reloadIMG(&bHighScore,themeName+"/bHighScore.png");
+ CONVERT(bHighScore);
+ reloadIMG(&boardBackBack,themeName+"/boardBackBack.png");
+ CONVERTA(boardBackBack);
+ reloadIMG(&backBoard,themeName+"/BackBoard.png");
+ CONVERT(backBoard);
+ reloadIMG(&blackLine,themeName+"/blackLine.png");
+ CONVERT(blackLine);
+ reloadIMG(&changeButtonsBack,themeName+"/changeButtonsBack.png");
+ CONVERTA(changeButtonsBack);
+ reloadIMG(&cursor[0],themeName+"/animations/cursor/1.png");
+ CONVERTA(cursor[0]);
+ reloadIMG(&cursor[1],themeName+"/animations/cursor/2.png");
+ CONVERTA(cursor[1]);
+ reloadIMG(&cursor[0],themeName+"/animations/counter/1.png");
+ CONVERTA(counter[0]);
+ reloadIMG(&cursor[1],themeName+"/animations/counter/2.png");
+ CONVERTA(counter[1]);
+ reloadIMG(&cursor[2],themeName+"/animations/counter/3.png");
+ CONVERTA(counter[2]);
+ reloadIMG(&topscoresBack,themeName+"/topscores.png");
+ CONVERTA(topscoresBack);
+ reloadIMG(&optionsBack,themeName+"/options.png");
+ CONVERTA(optionsBack);
+ reloadIMG(&bExit,themeName+"/bExit.png");
+ CONVERT(bExit);
+ reloadIMG(&bOn,themeName+"/bOn.png");
+ CONVERT(bOn);
+ reloadIMG(&bOff,themeName+"/bOff.png");
+ CONVERT(bOff);
+ reloadIMG(&bChange,themeName+"/bChange.png");
+ CONVERT(bChange);
+ reloadIMG(&b1024,themeName+"/b1024.png");
+ CONVERT(b1024);
+ reloadIMG(&dialogBox,themeName+"/dialogbox.png");
+ CONVERTA(dialogBox);
+// CONVERTA(fileDialogBox);
+ reloadIMG(&iLevelCheck,themeName+"/iLevelCheck.png");
+ CONVERTA(iLevelCheck);
+ reloadIMG(&iLevelCheckBox,themeName+"/iLevelCheckBox.png");
+ CONVERT(iLevelCheckBox);
+ reloadIMG(&iCheckBoxArea,themeName+"/iCheckBoxArea.png");
+ CONVERTA(iCheckBoxArea);
+ for (int i = 0;i<4;i++)
+ {
+ reloadIMG(&explosion[i],themeName+"/animations/explosion/"+(char)('0'+i)+".png");
+ CONVERTA(explosion[i]);
+ }
+ reloadIMG(&bricks[0],themeName+"/blue.png");
+ reloadIMG(&bricks[1],themeName+"/green.png");
+ reloadIMG(&bricks[2],themeName+"/purple.png");
+ reloadIMG(&bricks[3],themeName+"/red.png");
+ reloadIMG(&bricks[4],themeName+"/turkish.png");
+ reloadIMG(&bricks[5],themeName+"/yellow.png");
+ reloadIMG(&bricks[6],themeName+"/gray.png");
+ reloadIMG(&balls[0],themeName+"/balls/ballBlue.png");
+ reloadIMG(&balls[1],themeName+"/balls/ballGreen.png");
+ reloadIMG(&balls[2],themeName+"/balls/ballPurple.png");
+ reloadIMG(&balls[3],themeName+"/balls/ballRed.png");
+ reloadIMG(&balls[4],themeName+"/balls/ballTurkish.png");
+ reloadIMG(&balls[5],themeName+"/balls/ballYellow.png");
+ reloadIMG(&balls[6],themeName+"/balls/ballGray.png");
+ for (int i = 0; i<7; i++)
+ {
+ CONVERTA(bricks[i]);
+ CONVERTA(balls[i]);
+ }
+ reloadIMG(&crossover,themeName+"/crossover.png");
+ CONVERTA(crossover);
+ reloadIMG(&garbageTL,themeName+"/garbage/garbageTL.png");
+ CONVERTA(garbageTL);
+ reloadIMG(&garbageT,themeName+"/garbage/garbageT.png");
+ CONVERTA(garbageT);
+ reloadIMG(&garbageTR,themeName+"/garbage/garbageTR.png");
+ CONVERTA(garbageTR);
+ reloadIMG(&garbageR,themeName+"/garbage/garbageR.png");
+ CONVERTA(garbageR);
+ reloadIMG(&garbageBR,themeName+"/garbage/garbageBR.png");
+ CONVERTA(garbageBR);
+ reloadIMG(&garbageB,themeName+"/garbage/garbageB.png");
+ CONVERTA(garbageB);
+ reloadIMG(&garbageBL,themeName+"/garbage/garbageBL.png");
+ CONVERTA(garbageBL);
+ reloadIMG(&garbageL,themeName+"/garbage/garbageL.png");
+ CONVERTA(garbageL);
+ reloadIMG(&garbageFill,themeName+"/garbage/garbageFill.png");
+ CONVERTA(garbageFill);
+ reloadIMG(&garbageML,themeName+"/garbage/garbageML.png");
+ CONVERTA(garbageML);
+ reloadIMG(&garbageMR,themeName+"/garbage/garbageMR.png");
+ CONVERTA(garbageMR);
+ reloadIMG(&garbageM,themeName+"/garbage/garbageM.png");
+ CONVERTA(garbageM);
+ reloadIMG(&garbageGML,themeName+"/garbage/garbageGML.png");
+ CONVERTA(garbageGML);
+ reloadIMG(&garbageGMR,themeName+"/garbage/garbageGMR.png");
+ CONVERTA(garbageGMR);
+ reloadIMG(&garbageGM,themeName+"/garbage/garbageGM.png");
+ CONVERTA(garbageGM);
+ reloadIMG(&smiley[0],themeName+"/smileys/0.png");
+ CONVERTA(smiley[0]);
+ reloadIMG(&smiley[1],themeName+"/smileys/1.png");
+ CONVERTA(smiley[1]);
+ reloadIMG(&smiley[2],themeName+"/smileys/2.png");
+ CONVERTA(smiley[2]);
+ reloadIMG(&smiley[3],themeName+"/smileys/3.png");
+ CONVERTA(smiley[3]);
+ reloadIMG(&iWinner,themeName+"/iWinner.png");
+ CONVERTA(iWinner);
+ reloadIMG(&iDraw,themeName+"/iDraw.png");
+ CONVERTA(iDraw);
+ reloadIMG(&iLoser,themeName+"/iLoser.png");
+ CONVERTA(iLoser);
+ reloadIMG(&iChainBack,themeName+"/chainFrame.png");
+ CONVERTA(iChainBack);
+ reloadIMG(&iGameOver,themeName+"/iGameOver.png");
+ CONVERTA(iGameOver);
+ reloadIMG(&mouse,themeName+"/mouse.png");
+ CONVERTA(mouse);
+ reloadIMG(&stageBobble,themeName+"/iStageClearLimit.png");
+ CONVERTA(stageBobble);
+ reloadIMG(&bTheme,themeName+"/bTheme.png");
+ CONVERTA(bTheme);
+ reloadIMG(&bSkip,themeName+"/bSkip.png");
+ CONVERTA(bSkip);
+ reloadIMG(&bRetry,themeName+"/bRetry.png");
+ CONVERTA(bRetry);
+ reloadIMG(&bNext,themeName+"/bNext.png");
+ CONVERTA(bNext);
+ /**
+ *Fonts is a special case
+ */
+ //First we free them:
+ /*SFont_FreeFont(fBlueFont);
+ SFont_FreeFont(fSmallFont);
+ //Then we reload the images:
+ reloadIMG(&iBlueFont,themeName+"/24P_Arial_Blue.png");
+ reloadIMG(&iSmallFont,themeName+"/14P_Arial_Angle_Red.png");
+ //Then we convert them:
+ CONVERTA(iBlueFont);
+ CONVERTA(iSmallFont);
+ //Then create the fonts again:
+ fBlueFont = SFont_InitFont(iBlueFont);
+ fSmallFont = SFont_InitFont(iSmallFont);*/
+ //Editor:
+ /*CONVERTA(bCreateFile);
+ CONVERTA(bDeletePuzzle);
+ CONVERTA(bLoadFile);
+ CONVERTA(bMoveBack);
+ CONVERTA(bMoveDown);
+ CONVERTA(bMoveForward);
+ CONVERTA(bMoveLeft);
+ CONVERTA(bMoveRight);
+ CONVERTA(bMoveUp);
+ CONVERTA(bNewPuzzle);
+ CONVERTA(bSaveFileAs);
+ CONVERTA(bSavePuzzle);
+ CONVERTA(bSaveToFile);
+ CONVERTA(bTestPuzzle);*/
+ #ifdef DEBUG
+ cout << "Loading succeded" << endl;
+ #endif
+}
+
+/*TTF_Font * TTF_OpenFont2(char* path, int ptsize) {
+
+ char * tmp;
+ TTF_Font * ret=NULL;
+ tmp = (char*)malloc (sizeof(char)*(strlen(path)+strlen(sharedir)+2));
+ strcpy(tmp, sharedir);
+ strcat(tmp, "/");
+ strcat(tmp, path);
+#ifdef DEBUG
+ printf("loading %s\n",tmp);
+#endif
+ if(!(TTF_WasInit()))
+ TTF_Init();
+ if (!(ret = TTF_OpenFont(tmp, ptsize)))
+ ret = TTF_OpenFont(path, ptsize);
+ if(!ret)
+ cout << "failed to load font: " << TTF_GetError() << endl;
+ free(tmp);
+ return ret;
+}*/
+
+Mix_Music * Mix_LoadMUS2(char* path)
+{
+ char * tmp;
+ Mix_Music * ret=NULL;
+ tmp = (char*)malloc (sizeof(char)*(strlen(path)+strlen(sharedir)+2));
+ strcpy(tmp, sharedir);
+ strcat(tmp, "/");
+ strcat(tmp, path);
+#ifdef DEBUG
+ printf("loading %s\n",tmp);
+#endif
+ if (!(ret = Mix_LoadMUS(tmp)))
+ ret = Mix_LoadMUS(path);
+
+ free(tmp);
+ return ret;
+}
+
+Mix_Chunk * Mix_LoadWAV2(char* path)
+{
+ char * tmp;
+ Mix_Chunk * ret=NULL;
+ tmp = (char*)malloc (sizeof(char)*(strlen(path)+strlen(sharedir)+2));
+ strcpy(tmp, sharedir);
+ strcat(tmp, "/");
+ strcat(tmp, path);
+#ifdef DEBUG
+ printf("loading %s\n",tmp);
+#endif
+ if (!(ret = Mix_LoadWAV(tmp)))
+ ret = Mix_LoadWAV(path);
+
+ free(tmp);
+ return ret;
+}
+
+//Load all image files to memory
+int InitImages()
+{
+ if (!((backgroundImage = IMG_Load2((char*)"gfx/background.png"))
+ && (background = IMG_Load2((char*)"gfx/blackBackGround.png"))
+ && (bNewGame = IMG_Load2((char*)"gfx/bNewGame.png"))
+ && (b1player = IMG_Load2((char*)"gfx/bOnePlayer.png"))
+ && (b2players = IMG_Load2((char*)"gfx/bTwoPlayers.png"))
+ && (bVsMode = IMG_Load2((char*)"gfx/bVsGame.png"))
+ && (bPuzzle = IMG_Load2((char*)"gfx/bPuzzle.png"))
+ && (bStageClear = IMG_Load2((char*)"gfx/bStageClear.png"))
+ && (bTimeTrial = IMG_Load2((char*)"gfx/bTimeTrial.png"))
+ && (bEndless = IMG_Load2((char*)"gfx/bEndless.png"))
+ && (bOptions = IMG_Load2((char*)"gfx/bOptions.png"))
+ && (bConfigure = IMG_Load2((char*)"gfx/bConfigure.png"))
+ && (bSelectPuzzle = IMG_Load2((char*)"gfx/bSelectPuzzle.png"))
+ && (bHighScore = IMG_Load2((char*)"gfx/bHighScore.png"))
+ && (bExit = IMG_Load2((char*)"gfx/bExit.png"))
+ && (bBack = IMG_Load2((char*)"gfx/bBack.png"))
+ && (bForward = IMG_Load2((char*)"gfx/bForward.png"))
+ && (bReplay = IMG_Load2((char*)"gfx/bReplays.png"))
+ && (bSave = IMG_Load2((char*)"gfx/bSave.png"))
+ && (bLoad = IMG_Load2((char*)"gfx/bLoad.png"))
+#ifdef NETWORK
+ && (bNetwork = IMG_Load2((char*)"gfx/bNetwork.png"))
+ && (bHost = IMG_Load2((char*)"gfx/bHost.png"))
+ && (bConnect = IMG_Load2((char*)"gfx/bConnect.png"))
+#endif
+ && (blackLine = IMG_Load2((char*)"gfx/blackLine.png"))
+ && (stageBobble = IMG_Load2((char*)"gfx/iStageClearLimit.png"))
+ && (bricks[0] = IMG_Load2((char*)"gfx/blue.png"))
+ && (bricks[1] = IMG_Load2((char*)"gfx/green.png"))
+ && (bricks[2] = IMG_Load2((char*)"gfx/purple.png"))
+ && (bricks[3] = IMG_Load2((char*)"gfx/red.png"))
+ && (bricks[4] = IMG_Load2((char*)"gfx/turkish.png"))
+ && (bricks[5] = IMG_Load2((char*)"gfx/yellow.png"))
+ && (bricks[6] = IMG_Load2((char*)"gfx/grey.png"))
+ && (crossover = IMG_Load2((char*)"gfx/crossover.png"))
+ && (balls[0] = IMG_Load2((char*)"gfx/balls/ballBlue.png"))
+ && (balls[1] = IMG_Load2((char*)"gfx/balls/ballGreen.png"))
+ && (balls[2] = IMG_Load2((char*)"gfx/balls/ballPurple.png"))
+ && (balls[3] = IMG_Load2((char*)"gfx/balls/ballRed.png"))
+ && (balls[4] = IMG_Load2((char*)"gfx/balls/ballTurkish.png"))
+ && (balls[5] = IMG_Load2((char*)"gfx/balls/ballYellow.png"))
+ && (balls[6] = IMG_Load2((char*)"gfx/balls/ballGray.png"))
+ && (cursor[0] = IMG_Load2((char*)"gfx/animations/cursor/1.png"))
+ && (cursor[1] = IMG_Load2((char*)"gfx/animations/cursor/2.png"))
+ && (bomb[0] = IMG_Load2((char*)"gfx/animations/bomb/bomb_1.png"))
+ && (bomb[1] = IMG_Load2((char*)"gfx/animations/bomb/bomb_2.png"))
+ && (ready[0] = IMG_Load2((char*)"gfx/animations/ready/ready_1.png"))
+ && (ready[1] = IMG_Load2((char*)"gfx/animations/ready/ready_2.png"))
+ && (explosion[0] = IMG_Load2((char*)"gfx/animations/explosion/0.png"))
+ && (explosion[1] = IMG_Load2((char*)"gfx/animations/explosion/1.png"))
+ && (explosion[2] = IMG_Load2((char*)"gfx/animations/explosion/2.png"))
+ && (explosion[3] = IMG_Load2((char*)"gfx/animations/explosion/3.png"))
+ && (counter[0] = IMG_Load2((char*)"gfx/counter/1.png"))
+ && (counter[1] = IMG_Load2((char*)"gfx/counter/2.png"))
+ && (counter[2] = IMG_Load2((char*)"gfx/counter/3.png"))
+ && (backBoard = IMG_Load2((char*)"gfx/BackBoard.png")) //not used, we just test if it exists :)
+ && (iGameOver = IMG_Load2((char*)"gfx/iGameOver.png"))
+ && (iWinner = IMG_Load2((char*)"gfx/iWinner.png"))
+ && (iDraw = IMG_Load2((char*)"gfx/iDraw.png"))
+ && (iLoser = IMG_Load2((char*)"gfx/iLoser.png"))
+ && (iChainBack = IMG_Load2((char*)"gfx/chainFrame.png"))
+ //&& (iBlueFont = IMG_Load2("gfx/24P_Copperplate_Blue.png"))
+ && (iBlueFont = IMG_Load2((char*)"gfx/24P_Arial_Blue.png"))
+ && (iSmallFont = IMG_Load2((char*)"gfx/14P_Arial_Angle_Red.png"))
+ && (topscoresBack = IMG_Load2((char*)"gfx/topscores.png"))
+ && (optionsBack = IMG_Load2((char*)"gfx/options.png"))
+ && (bOn = IMG_Load2((char*)"gfx/bOn.png"))
+ && (bOff = IMG_Load2((char*)"gfx/bOff.png"))
+ && (bChange = IMG_Load2((char*)"gfx/bChange.png"))
+ && (b1024 = IMG_Load2((char*)"gfx/b1024.png"))
+ && (dialogBox = IMG_Load2((char*)"gfx/dialogbox.png"))
+// && (fileDialogBox = IMG_Load2("gfx/fileDialogbox.png"))
+ && (iLevelCheck = IMG_Load2((char*)"gfx/iLevelCheck.png"))
+ && (iLevelCheckBox = IMG_Load2((char*)"gfx/iLevelCheckBox.png"))
+ && (iCheckBoxArea = IMG_Load2((char*)"gfx/iCheckBoxArea.png"))
+ && (boardBackBack = IMG_Load2((char*)"gfx/boardBackBack.png"))
+ && (changeButtonsBack = IMG_Load2((char*)"gfx/changeButtonsBack.png"))
+ && (garbageTL = IMG_Load2((char*)"gfx/garbage/garbageTL.png"))
+ && (garbageT = IMG_Load2((char*)"gfx/garbage/garbageT.png"))
+ && (garbageTR = IMG_Load2((char*)"gfx/garbage/garbageTR.png"))
+ && (garbageR = IMG_Load2((char*)"gfx/garbage/garbageR.png"))
+ && (garbageBR = IMG_Load2((char*)"gfx/garbage/garbageBR.png"))
+ && (garbageB = IMG_Load2((char*)"gfx/garbage/garbageB.png"))
+ && (garbageBL = IMG_Load2((char*)"gfx/garbage/garbageBL.png"))
+ && (garbageL = IMG_Load2((char*)"gfx/garbage/garbageL.png"))
+ && (garbageFill = IMG_Load2((char*)"gfx/garbage/garbageFill.png"))
+ && (garbageML = IMG_Load2((char*)"gfx/garbage/garbageML.png"))
+ && (garbageM = IMG_Load2((char*)"gfx/garbage/garbageM.png"))
+ && (garbageMR = IMG_Load2((char*)"gfx/garbage/garbageMR.png"))
+ && (garbageGM = IMG_Load2((char*)"gfx/garbage/garbageGM.png"))
+ && (garbageGML = IMG_Load2((char*)"gfx/garbage/garbageGML.png"))
+ && (garbageGMR = IMG_Load2((char*)"gfx/garbage/garbageGMR.png"))
+ && (smiley[0] = IMG_Load2((char*)"gfx/smileys/0.png"))
+ && (smiley[1] = IMG_Load2((char*)"gfx/smileys/1.png"))
+ && (smiley[2] = IMG_Load2((char*)"gfx/smileys/2.png"))
+ && (smiley[3] = IMG_Load2((char*)"gfx/smileys/3.png"))
+ //new in 1.3.2
+ && (transCover = IMG_Load2((char*)"gfx/transCover.png"))
+ /*&& (bCreateFile = IMG_Load2((char*)"gfx/editor/bCreateFile.png"))
+ && (bDeletePuzzle = IMG_Load2((char*)"gfx/editor/bDeletePuzzle.png"))
+ && (bLoadFile = IMG_Load2((char*)"gfx/editor/bLoadFile.png"))
+ && (bMoveBack = IMG_Load2((char*)"gfx/editor/bMoveBack.png"))
+ && (bMoveDown = IMG_Load2((char*)"gfx/editor/bMoveDown.png"))
+ && (bMoveForward = IMG_Load2((char*)"gfx/editor/bMoveForward.png"))
+ && (bMoveLeft = IMG_Load2((char*)"gfx/editor/bMoveLeft.png"))
+ && (bMoveRight = IMG_Load2((char*)"gfx/editor/bMoveRight.png"))
+ && (bMoveUp = IMG_Load2((char*)"gfx/editor/bMoveUp.png"))
+ && (bNewPuzzle = IMG_Load2((char*)"gfx/editor/bNewPuzzle.png"))
+ && (bSaveFileAs = IMG_Load2((char*)"gfx/editor/bSaveFileAs.png"))
+ && (bSavePuzzle = IMG_Load2((char*)"gfx/editor/bSavePuzzle.png"))
+ && (bSaveToFile = IMG_Load2((char*)"gfx/editor/bSaveToFile.png"))
+ && (bTestPuzzle = IMG_Load2((char*)"gfx/editor/bTestPuzzle.png"))*/
+ //end new in 1.3.2
+ //new in 1.4.0
+ && (bTheme = IMG_Load2((char*)"gfx/bTheme.png"))
+ && (bSkip = IMG_Load2((char*)"gfx/bSkip.png"))
+ && (bNext = IMG_Load2((char*)"gfx/bNext.png"))
+ && (bRetry = IMG_Load2((char*)"gfx/bRetry.png"))
+ //end new in 1.4.0
+ && (mouse = IMG_Load2((char*)"gfx/mouse.png"))
+ ))
+ //if there was a problem ie. "File not found"
+ {
+ cout << "Error loading image file: " << SDL_GetError() << endl;
+ exit(1);
+ }
+
+
+ //Prepare for fast blittering!
+ CONVERT(background);
+ CONVERT(bNewGame);
+ CONVERT(backgroundImage);
+ CONVERT(b1player);
+ CONVERT(b2players);
+ CONVERT(bVsMode);
+ CONVERT(bPuzzle);
+ CONVERT(bStageClear);
+ CONVERT(bTimeTrial);
+ CONVERT(bEndless);
+ CONVERT(bOptions);
+ CONVERTA(bConfigure);
+ CONVERTA(bSelectPuzzle);
+ CONVERTA(bReplay);
+ CONVERTA(bSave);
+ CONVERTA(bLoad);
+ CONVERTA(bTheme);
+ CONVERTA(bSkip);
+ CONVERTA(bRetry);
+ CONVERTA(bNext);
+#ifdef NETWORK
+ CONVERTA(bNetwork);
+ CONVERTA(bHost);
+ CONVERTA(bConnect);
+#endif
+ CONVERT(bHighScore);
+ CONVERTA(boardBackBack);
+ CONVERT(backBoard);
+ CONVERT(blackLine);
+ CONVERTA(changeButtonsBack);
+ CONVERTA(cursor[0]);
+ CONVERTA(cursor[1]);
+ CONVERTA(counter[0]);
+ CONVERTA(counter[1]);
+ CONVERTA(counter[2]);
+ CONVERTA(topscoresBack);
+ CONVERTA(optionsBack);
+ CONVERT(bExit);
+ CONVERT(bOn);
+ CONVERT(bOff);
+ CONVERT(bChange);
+ CONVERT(b1024);
+ CONVERTA(dialogBox);
+// CONVERTA(fileDialogBox);
+ CONVERTA(iLevelCheck);
+ CONVERT(iLevelCheckBox);
+ CONVERTA(iCheckBoxArea);
+ for (int i = 0;i<4;i++)
+ {
+ CONVERTA(explosion[i]);
+ }
+ for (int i = 0; i<7; i++)
+ {
+ CONVERTA(bricks[i]);
+ CONVERTA(balls[i]);
+ }
+ CONVERTA(crossover);
+ CONVERTA(garbageTL);
+ CONVERTA(garbageT);
+ CONVERTA(garbageTR);
+ CONVERTA(garbageR);
+ CONVERTA(garbageBR);
+ CONVERTA(garbageB);
+ CONVERTA(garbageBL);
+ CONVERTA(garbageL);
+ CONVERTA(garbageFill);
+ CONVERTA(garbageML);
+ CONVERTA(garbageMR);
+ CONVERTA(garbageM);
+ CONVERTA(garbageGML);
+ CONVERTA(garbageGMR);
+ CONVERTA(garbageGM);
+ CONVERTA(smiley[0]);
+ CONVERTA(smiley[1]);
+ CONVERTA(smiley[2]);
+ CONVERTA(smiley[3]);
+ CONVERTA(iWinner);
+ CONVERTA(iDraw);
+ CONVERTA(iLoser);
+ CONVERTA(iChainBack);
+ CONVERTA(iBlueFont);
+ CONVERTA(iSmallFont);
+ CONVERTA(iGameOver);
+ CONVERTA(mouse);
+ CONVERTA(stageBobble);
+ CONVERTA(transCover);
+ //Editor:
+ /*CONVERTA(bCreateFile);
+ CONVERTA(bDeletePuzzle);
+ CONVERTA(bLoadFile);
+ CONVERTA(bMoveBack);
+ CONVERTA(bMoveDown);
+ CONVERTA(bMoveForward);
+ CONVERTA(bMoveLeft);
+ CONVERTA(bMoveRight);
+ CONVERTA(bMoveUp);
+ CONVERTA(bNewPuzzle);
+ CONVERTA(bSaveFileAs);
+ CONVERTA(bSavePuzzle);
+ CONVERTA(bSaveToFile);
+ CONVERTA(bTestPuzzle);*/
+
+ //Here comes the fonts:
+ fBlueFont = SFont_InitFont(iBlueFont);
+ fSmallFont = SFont_InitFont(iSmallFont);
+
+ //And the ttf font:
+// TTF_Font *ttFont1 = TTF_OpenFont2("fonts/FreeSerif.ttf", 24);
+// TTF_SetFontStyle(ttFont1,TTF_STYLE_BOLD);
+// ttfont = TTFont(ttFont1);
+
+//Loads the sound if sound present
+ if (!NoSound)
+ {
+ //And here the music:
+ bgMusic = Mix_LoadMUS2((char*)"music/bgMusic.ogg");
+ //the music... we just hope it exists, else the user won't hear anything
+ //Same goes for the sounds
+ boing = Mix_LoadWAV2((char*)"sound/pop.ogg");
+ timesUp = Mix_LoadWAV2((char*)"sound/whistleblow.ogg");
+ applause = Mix_LoadWAV2((char*)"sound/applause.ogg");
+ photoClick = Mix_LoadWAV2((char*)"sound/cameraclick.ogg");
+ heartBeat = Mix_LoadWAV2((char*)"sound/heartbeat3.ogg");
+ typingChunk = Mix_LoadWAV2((char*)"sound/typing.ogg");
+ counterChunk = Mix_LoadWAV2((char*)"sound/counter.ogg");
+ } //All sound has been loaded or not
+ return 0;
+} //InitImages()
+
+
+//Unload images and fonts and sounds
+void UnloadImages()
+{
+ //Fonts and Sounds needs to be freed
+ SFont_FreeFont(fBlueFont);
+ SFont_FreeFont(fSmallFont);
+ if (!NoSound) //Only unload then it has been loaded!
+ {
+ Mix_FreeMusic(bgMusic);
+ Mix_FreeChunk(boing);
+ Mix_FreeChunk(timesUp);
+ Mix_FreeChunk(applause);
+ Mix_FreeChunk(photoClick);
+ Mix_FreeChunk(heartBeat);
+ Mix_FreeChunk(counterChunk);
+ Mix_FreeChunk(typingChunk);
+ }
+ //Free surfaces:
+ //I think this will crash, at least it happend to me...
+ SDL_FreeSurface(backgroundImage);
+ SDL_FreeSurface(background);
+ SDL_FreeSurface(bNewGame);
+ SDL_FreeSurface(b1player);
+ SDL_FreeSurface(b2players);
+ SDL_FreeSurface(bVsMode);
+ SDL_FreeSurface(bPuzzle);
+ SDL_FreeSurface(bStageClear);
+ SDL_FreeSurface(bTimeTrial);
+ SDL_FreeSurface(bEndless);
+ SDL_FreeSurface(bOptions);
+ SDL_FreeSurface(bConfigure);
+ SDL_FreeSurface(bSelectPuzzle);
+ SDL_FreeSurface(bHighScore);
+ SDL_FreeSurface(bReplay);
+ SDL_FreeSurface(bSave);
+ SDL_FreeSurface(bLoad);
+ #ifdef NETWORK
+ SDL_FreeSurface(bNetwork);
+ SDL_FreeSurface(bHost);
+ SDL_FreeSurface(bConnect);
+ #endif
+ SDL_FreeSurface(bExit);
+ SDL_FreeSurface(blackLine);
+ SDL_FreeSurface(stageBobble);
+ SDL_FreeSurface(bricks[0]);
+ SDL_FreeSurface(bricks[1]);
+ SDL_FreeSurface(bricks[2]);
+ SDL_FreeSurface(bricks[3]);
+ SDL_FreeSurface(bricks[4]);
+ SDL_FreeSurface(bricks[5]);
+ SDL_FreeSurface(bricks[6]);
+ SDL_FreeSurface(crossover);
+ SDL_FreeSurface(balls[0]);
+ SDL_FreeSurface(balls[1]);
+ SDL_FreeSurface(balls[2]);
+ SDL_FreeSurface(balls[3]);
+ SDL_FreeSurface(balls[4]);
+ SDL_FreeSurface(balls[5]);
+ SDL_FreeSurface(balls[6]);
+ SDL_FreeSurface(cursor[0]);
+ SDL_FreeSurface(cursor[1]);
+ SDL_FreeSurface(backBoard); //not used, we just test if it exists :)
+ SDL_FreeSurface(iGameOver);
+ SDL_FreeSurface(iWinner);
+ SDL_FreeSurface(iDraw);
+ SDL_FreeSurface(iLoser);
+ SDL_FreeSurface(iChainBack);
+ //SDL_FreeSurface(iBlueFont); //Segfault
+ //SDL_FreeSurface(iSmallFont); //Segfault
+ SDL_FreeSurface(topscoresBack);
+ SDL_FreeSurface(optionsBack);
+ SDL_FreeSurface(bOn);
+ SDL_FreeSurface(bOff);
+ SDL_FreeSurface(bChange);
+ SDL_FreeSurface(b1024);
+ SDL_FreeSurface(dialogBox);
+ //SDL_FreeSurface(fileDialogBox);
+ SDL_FreeSurface(iLevelCheck);
+ SDL_FreeSurface(iLevelCheckBox);
+ SDL_FreeSurface(iCheckBoxArea);
+ SDL_FreeSurface(boardBackBack);
+ SDL_FreeSurface(changeButtonsBack);
+ SDL_FreeSurface(garbageTL);
+ SDL_FreeSurface(garbageT);
+ SDL_FreeSurface(garbageTR);
+ SDL_FreeSurface(garbageR);
+ SDL_FreeSurface(garbageBR);
+ SDL_FreeSurface(garbageB);
+ SDL_FreeSurface(garbageBL);
+ SDL_FreeSurface(garbageL);
+ SDL_FreeSurface(garbageFill);
+ SDL_FreeSurface(garbageML);
+ SDL_FreeSurface(garbageM);
+ SDL_FreeSurface(garbageMR);
+ SDL_FreeSurface(garbageGML);
+ SDL_FreeSurface(garbageGM);
+ SDL_FreeSurface(garbageGMR);
+ SDL_FreeSurface(smiley[0]);
+ SDL_FreeSurface(smiley[1]);
+ SDL_FreeSurface(smiley[2]);
+ SDL_FreeSurface(smiley[3]);
+ SDL_FreeSurface(transCover);
+ SDL_FreeSurface(mouse);
+
+}
+
+//Function to convert numbers to string
+string itoa(int num)
+{
+ stringstream converter;
+ converter << num;
+ return converter.str();
+}
+
+//Function to convert numbers to string (2 diget)
+string itoa2(int num)
+{
+ stringstream converter;
+ if(num<10)
+ converter << "0";
+ converter << num;
+ return converter.str();
+}
+
+/*Loads all the puzzle levels*/
+int LoadPuzzleStages()
+{
+ //if(puzzleLoaded)
+ // return 1;
+#ifdef __unix__
+ string filename0 = (string)getenv("HOME")+(string)"/.gamesaves/blockattack/puzzles/";
+ filename0 = filename0+puzzleName;
+ if (singlePuzzle)
+ filename0 = singlePuzzleFile;
+#endif //__unix__
+#ifdef SHAREDIR
+ string filename = (string)SHAREDIR+(string)"/res/";
+ filename = filename+puzzleName;
+#else
+ string filename = "res/"+puzzleName;
+#endif
+#ifdef __unix__
+ ifstream inFile(filename0.c_str());
+ if (!inFile)
+ inFile.open(filename.c_str());
+#else
+ ifstream inFile(filename.c_str());
+#endif
+ inFile >> nrOfPuzzles;
+ if (nrOfPuzzles>maxNrOfPuzzleStages)
+ nrOfPuzzles=maxNrOfPuzzleStages;
+ for (int k=0; (k<nrOfPuzzles)&&(!inFile.eof()); k++)
+ {
+ inFile >> nrOfMovesAllowed[k];
+ for (int i=11;i>=0;i--)
+ for (int j=0;j<6;j++)
+ {
+ inFile >> puzzleLevels[k][j][i];
+ }
+ }
+ puzzleLoaded = true;
+ return 0;
+}
+
+/*Draws a image from on a given Surface. Takes source image, destination surface and coordinates*/
+inline void DrawIMG(SDL_Surface *img, SDL_Surface *target, int x, int y)
+{
+ SDL_Rect dest;
+ dest.x = x;
+ dest.y = y;
+ SDL_BlitSurface(img, NULL, target, &dest);
+}
+
+/*Draws a part of an image on a surface of choice*/
+void DrawIMG(SDL_Surface *img, SDL_Surface * target, int x, int y, int w, int h, int x2, int y2)
+{
+ SDL_Rect dest;
+ dest.x = x;
+ dest.y = y;
+ SDL_Rect dest2;
+ dest2.x = x2;
+ dest2.y = y2;
+ dest2.w = w;
+ dest2.h = h;
+ SDL_BlitSurface(img, &dest2, target, &dest);
+}
+
+//The small things that are faaling when you clear something
+class aBall
+{
+private:
+ double x;
+ double y;
+ double velocityY;
+ double velocityX;
+ int color;
+ unsigned long int lastTime;
+public:
+
+ aBall()
+ {}
+
+ //constructor:
+ aBall(int X, int Y, bool right, int coulor)
+ {
+ double tal = 1.0;
+ velocityY = -tal*startVelocityY;
+ lastTime = currentTime;
+ x = (double)X;
+ y = (double)Y;
+ color = coulor;
+ if (right)
+ velocityX = tal*VelocityX;
+ else
+ velocityX = -tal*VelocityX;
+ } //constructor
+
+ //Deconstructor
+ ~aBall()
+ {
+ } //Deconstructor
+
+ void update()
+ {
+ double timePassed = (((double)(currentTime-lastTime))/1000.0); //time passed in seconds
+ x = x+timePassed*velocityX;
+ y = y+timePassed*velocityY;
+ velocityY = velocityY + gravity*timePassed;
+ if (y<1.0)
+ velocityY=10.0;
+ if ((velocityY>minVelocity) && (y>(double)(768-ballSize)) && (y<768.0))
+ {
+ velocityY = -0.70*velocityY;
+ y = 768.0-ballSize;
+ }
+ lastTime = currentTime;
+ }
+
+ int getX()
+ {
+ return (int)x;
+ }
+
+ int getY()
+ {
+ return (int)y;
+ }
+
+ int getColor()
+ {
+ return color;
+ }
+}; //aBall
+
+const int maxNumberOfBalls = 100;
+
+class ballManeger
+{
+public:
+ aBall ballArray[maxNumberOfBalls];
+ bool ballUsed[maxNumberOfBalls];
+ //The old ball information is also saved so balls can be deleted!
+ aBall oldBallArray[maxNumberOfBalls];
+ bool oldBallUsed[maxNumberOfBalls];
+
+ ballManeger()
+ {
+ for (int i=0; i<maxNumberOfBalls; i++)
+ {
+ ballUsed[i] = false;
+ oldBallUsed[i] = false;
+ }
+ }
+
+ int addBall(int x, int y,bool right,int color)
+ {
+ //cout << "Tries to add a ball" << endl;
+ int ballNumber = 0;
+ while ((ballUsed[ballNumber])&&(ballNumber<maxNumberOfBalls))
+ ballNumber++;
+ if (ballNumber==maxNumberOfBalls)
+ return -1;
+ currentTime = SDL_GetTicks();
+ ballArray[ballNumber] = aBall(x,y,right,color);
+ ballUsed[ballNumber] = true;
+ //cout << "Ball added" << endl;
+ return 1;
+ } //addBall
+
+ void update()
+ {
+ currentTime = SDL_GetTicks();
+ for (int i = 0; i<maxNumberOfBalls; i++)
+ {
+
+ if (ballUsed[i])
+ {
+ oldBallUsed[i] = true;
+ oldBallArray[i] = ballArray[i];
+ ballArray[i].update();
+ if (ballArray[i].getY()>800)
+ {
+ ballArray[i].~aBall();
+ ballUsed[i] = false;
+ //cout << "Ball removed" << endl;
+ }
+ }
+ else
+ {
+ oldBallUsed[i] = false;
+ }
+ }
+ } //update
+
+
+}; //theBallManeger
+
+ballManeger theBallManeger;
+
+//a explosions, non moving
+class anExplosion
+{
+private:
+ int x;
+ int y;
+ Uint8 frameNumber;
+#define frameLength 80
+ //How long an image in an animation should be showed
+#define maxFrame 4
+ //How many images there are in the animation
+ unsigned long int placeTime; //Then the explosion occored
+public:
+
+ anExplosion()
+ {}
+
+ //constructor:
+ anExplosion(int X, int Y)
+ {
+ placeTime = currentTime;
+ x = X;
+ y = Y;
+ frameNumber=0;
+ } //constructor
+
+ //Deconstructor
+ ~anExplosion()
+ {
+ } //Deconstructor
+
+ //true if animation has played and object should be removed from the screen
+ bool removeMe()
+ {
+ frameNumber = (currentTime-placeTime)/frameLength;
+ return (!(frameNumber<maxFrame));
+ }
+
+ int getX()
+ {
+ return (int)x;
+ }
+
+ int getY()
+ {
+ return (int)y;
+ }
+
+ int getFrame()
+ {
+ return frameNumber;
+ }
+}; //nExplosion
+
+class explosionManeger
+{
+public:
+ anExplosion explosionArray[maxNumberOfBalls];
+ bool explosionUsed[maxNumberOfBalls];
+ //The old explosion information is also saved so explosions can be deleted!
+ anExplosion oldExplosionArray[maxNumberOfBalls];
+ bool oldExplosionUsed[maxNumberOfBalls];
+
+ explosionManeger()
+ {
+ for (int i=0; i<maxNumberOfBalls; i++)
+ {
+ explosionUsed[i] = false;
+ oldExplosionUsed[i] = false;
+ }
+ }
+
+ int addExplosion(int x, int y)
+ {
+ //cout << "Tries to add an explosion" << endl;
+ int explosionNumber = 0;
+ while ((explosionUsed[explosionNumber])&&(explosionNumber<maxNumberOfBalls))
+ explosionNumber++;
+ if (explosionNumber==maxNumberOfBalls)
+ return -1;
+ currentTime = SDL_GetTicks();
+ explosionArray[explosionNumber] = anExplosion(x,y);
+ explosionUsed[explosionNumber] = true;
+ //cout << "Explosion added" << endl;
+ return 1;
+ } //addBall
+
+ void update()
+ {
+ currentTime = SDL_GetTicks();
+ for (int i = 0; i<maxNumberOfBalls; i++)
+ {
+
+ if (explosionUsed[i])
+ {
+ oldExplosionUsed[i] = true;
+ oldExplosionArray[i] = explosionArray[i];
+ if (explosionArray[i].removeMe())
+ {
+ explosionArray[i].~anExplosion();
+ explosionUsed[i] = false;
+ //cout << "Explosion removed" << endl;
+ }
+ }
+ else
+ {
+ oldExplosionUsed[i] = false;
+ }
+ }
+ } //update
+
+
+}; //explosionManeger
+
+explosionManeger theExplosionManeger;
+
+//text pop-up
+class textMessage
+{
+private:
+ int x;
+ int y;
+ char textt[10];
+ unsigned long int time;
+ unsigned long int placeTime; //Then the text was placed
+public:
+
+ textMessage()
+ {}
+
+ //constructor:
+ textMessage(int X, int Y,const char* Text,unsigned int Time)
+ {
+ //cout << "Running constructor" << endl;
+ placeTime = currentTime;
+ x = X;
+ y = Y;
+ strncpy(textt,Text,10);
+ textt[9]=0;
+ time = Time;
+ //cout << "Constructor runned" << endl;
+ } //constructor
+
+ //true if the text has expired
+ bool removeMe()
+ {
+ return currentTime-placeTime>time;
+ }
+
+ int getX()
+ {
+ //cout << "Gets X" << endl;
+ return x;
+ }
+
+ int getY()
+ {
+ //cout << "Gets Y" << endl;
+ return y;
+ }
+
+ char* getText()
+ {
+ //cout << "Gets text" << endl;
+ return textt;
+ }
+}; //text popup
+
+class textManeger
+{
+public:
+ textMessage textArray[maxNumberOfBalls];
+ bool textUsed[maxNumberOfBalls];
+ //The old text information is also saved so text can be deleted!
+ textMessage oldTextArray[maxNumberOfBalls];
+ bool oldTextUsed[maxNumberOfBalls];
+
+ textManeger()
+ {
+ for (int i=0; i<maxNumberOfBalls; i++)
+ {
+ textUsed[i] = false;
+ oldTextUsed[i] = false;
+ }
+ }
+
+ int addText(int x, int y,string Text,unsigned int Time)
+ {
+ //cout << "Tries to add text" << endl;
+ int textNumber = 0;
+ while ((textNumber<maxNumberOfBalls)&&((textUsed[textNumber])||(oldTextUsed[textNumber])))
+ textNumber++;
+ if (textNumber==maxNumberOfBalls)
+ return -1;
+ //cout << "adding to: " << textNumber << ":" << textUsed[textNumber] << ":" << &textArray[textNumber] << endl;
+ currentTime = SDL_GetTicks();
+ //if(&textArray[textNumber]!=NULL)
+ //*textArray[textNumber]=0;
+ textArray[textNumber] = textMessage(x,y,Text.c_str(),Time);
+ textUsed[textNumber] = true;
+ //cout << "Text added" << endl;
+ return 1;
+ } //addText
+
+ void update()
+ {
+ //cout << "Running update" << endl;
+ currentTime = SDL_GetTicks();
+ for (int i = 0; i<maxNumberOfBalls; i++)
+ {
+
+ if (textUsed[i])
+ {
+ if (!oldTextUsed[i])
+ {
+ oldTextUsed[i] = true;
+ oldTextArray[i] = textMessage(textArray[i]);
+ }
+ if (textArray[i].removeMe())
+ {
+ textArray[i].~textMessage();
+ textUsed[i] = false;
+ }
+ }
+ else
+ if (oldTextUsed[i])
+ {
+ oldTextUsed[i] = false;
+ oldTextArray[i].~textMessage();
+ }
+ }
+ } //update
+
+
+}; //textManeger
+
+textManeger theTextManeger;
+
+//Here comes the Block Game object
+#include "BlockGame.hpp"
+
+//writeScreenShot saves the screen as a bmp file, it uses the time to get a unique filename
+void writeScreenShot()
+{
+ cout << "Saving screenshot" << endl;
+ int rightNow = (int)time(NULL);
+#if defined(__unix__)
+ char buf[514];
+ sprintf( buf, "%s/.gamesaves/blockattack/screenshots/screenshot%i.bmp", getenv("HOME"), rightNow );
+#else
+ char buf[MAX_PATH];
+ sprintf( buf, "%s\\My Games\\blockattack\\screenshots\\screenshot%i.bmp", (getMyDocumentsPath()).c_str(), rightNow );
+#endif
+ SDL_SaveBMP( screen, buf );
+ if (!NoSound)
+ if (SoundEnabled)Mix_PlayChannel(1,photoClick,0);
+}
+
+//Draws the highscores
+inline void DrawHighscores(int x, int y)
+{
+ DrawIMG(topscoresBack,screen,x,y);
+ if (showEndless) SFont_Write(screen,fBlueFont,x+100,y+100,"Endless:");
+ else SFont_Write(screen,fBlueFont,x+100,y+100,"Time Trial:");
+ for (int i =0;i<10;i++)
+ {
+ char playerScore[32];
+ char playerName[32];
+ if (showEndless) sprintf(playerScore, "%i", theTopScoresEndless.getScoreNumber(i));
+ else sprintf(playerScore, "%i", theTopScoresTimeTrial.getScoreNumber(i));
+ if (showEndless) strcpy(playerName,theTopScoresEndless.getScoreName(i));
+ else strcpy(playerName,theTopScoresTimeTrial.getScoreName(i));
+ SFont_Write(screen,fBlueFont,x+420,y+150+i*35,playerScore);
+ SFont_Write(screen,fBlueFont,x+60,y+150+i*35,playerName);
+ }
+}
+
+char keyname[11];
+
+//Function to return the name of a key, to be displayed...
+char* getKeyName(SDLKey key)
+{
+
+ char charToPut = '\0';
+ switch (key)
+ {
+ case SDLK_a:
+ charToPut = 'A';
+ break;
+ case SDLK_b:
+ charToPut = 'B';
+ break;
+ case SDLK_c:
+ charToPut = 'C';
+ break;
+ case SDLK_d:
+ charToPut = 'D';
+ break;
+ case SDLK_e:
+ charToPut = 'E';
+ break;
+ case SDLK_f:
+ charToPut = 'F';
+ break;
+ case SDLK_g:
+ charToPut = 'G';
+ break;
+ case SDLK_h:
+ charToPut = 'H';
+ break;
+ case SDLK_i:
+ charToPut = 'I';
+ break;
+ case SDLK_j:
+ charToPut = 'J';
+ break;
+ case SDLK_k:
+ charToPut = 'K';
+ break;
+ case SDLK_l:
+ charToPut = 'L';
+ break;
+ case SDLK_m:
+ charToPut = 'M';
+ break;
+ case SDLK_n:
+ charToPut = 'N';
+ break;
+ case SDLK_o:
+ charToPut = 'O';
+ break;
+ case SDLK_p:
+ charToPut = 'P';
+ break;
+ case SDLK_q:
+ charToPut = 'Q';
+ break;
+ case SDLK_r:
+ charToPut = 'R';
+ break;
+ case SDLK_s:
+ charToPut = 'S';
+ break;
+ case SDLK_t:
+ charToPut = 'T';
+ break;
+ case SDLK_u:
+ charToPut = 'U';
+ break;
+ case SDLK_v:
+ charToPut = 'V';
+ break;
+ case SDLK_w:
+ charToPut = 'W';
+ break;
+ case SDLK_x:
+ charToPut = 'X';
+ break;
+ case SDLK_y:
+ charToPut = 'Y';
+ break;
+ case SDLK_z:
+ charToPut = 'Z';
+ break;
+ case SDLK_0:
+ charToPut = '0';
+ break;
+ case SDLK_1:
+ charToPut = '1';
+ break;
+ case SDLK_2:
+ charToPut = '2';
+ break;
+ case SDLK_3:
+ charToPut = '3';
+ break;
+ case SDLK_4:
+ charToPut = '4';
+ break;
+ case SDLK_5:
+ charToPut = '5';
+ break;
+ case SDLK_6:
+ charToPut = '6';
+ break;
+ case SDLK_7:
+ charToPut = '7';
+ break;
+ case SDLK_8:
+ charToPut = '8';
+ break;
+ case SDLK_9:
+ charToPut = '9';
+ break;
+ case SDLK_KP0:
+ sprintf(keyname,"NP_0");
+ break;
+ case SDLK_KP1:
+ sprintf(keyname,"NP_1");
+ break;
+ case SDLK_KP2:
+ sprintf(keyname,"NP_2");
+ break;
+ case SDLK_KP3:
+ sprintf(keyname,"NP_3");
+ break;
+ case SDLK_KP4:
+ sprintf(keyname,"NP_4");
+ break;
+ case SDLK_KP5:
+ sprintf(keyname,"NP_5");
+ break;
+ case SDLK_KP6:
+ sprintf(keyname,"NP_6");
+ break;
+ case SDLK_KP7:
+ sprintf(keyname,"NP_7");
+ break;
+ case SDLK_KP8:
+ sprintf(keyname,"NP_8");
+ break;
+ case SDLK_KP9:
+ sprintf(keyname,"NP_9");
+ break;
+ case SDLK_BACKSPACE:
+ sprintf(keyname,"Backspace");
+ break;
+ case SDLK_TAB:
+ sprintf(keyname,"Tab");
+ break;
+ case SDLK_CLEAR:
+ sprintf(keyname,"Clear");
+ break;
+ case SDLK_RETURN:
+ sprintf(keyname,"Return");
+ break;
+ case SDLK_PAUSE:
+ sprintf(keyname,"Pause");
+ break;
+ case SDLK_SPACE:
+ sprintf(keyname,"Space");
+ break;
+ case SDLK_EXCLAIM:
+ charToPut = '!';
+ break;
+ case SDLK_QUOTEDBL:
+ sprintf(keyname,"QuoteDBL");
+ break;
+ case SDLK_HASH:
+ charToPut = '#';
+ break;
+ case SDLK_DOLLAR:
+ sprintf(keyname,"$");
+ break;
+ case SDLK_ASTERISK:
+ sprintf(keyname,"Asterisk");
+ break;
+ case SDLK_PLUS:
+ sprintf(keyname,"Plus");
+ break;
+ case SDLK_COMMA:
+ sprintf(keyname,"Comma");
+ break;
+ case SDLK_MINUS:
+ sprintf(keyname,"Minus");
+ break;
+ case SDLK_PERIOD:
+ sprintf(keyname,"Period");
+ break;
+ case SDLK_SLASH:
+ charToPut ='/';
+ break;
+ case SDLK_COLON:
+ sprintf(keyname,"Colon");
+ break;
+ case SDLK_SEMICOLON:
+ sprintf(keyname,"SemiColon");
+ break;
+ case SDLK_LESS:
+ charToPut = '<';
+ break;
+ case SDLK_EQUALS:
+ sprintf(keyname,"Equals");
+ break;
+ case SDLK_DELETE:
+ sprintf(keyname,"Delete");
+ break;
+ case SDLK_KP_PERIOD:
+ sprintf(keyname,"NPperiod");
+ break;
+ case SDLK_KP_DIVIDE:
+ sprintf(keyname,"NPdivide");
+ break;
+ case SDLK_KP_MULTIPLY:
+ sprintf(keyname,"NPmultiply");
+ break;
+ case SDLK_KP_MINUS:
+ sprintf(keyname,"NPminus");
+ break;
+ case SDLK_KP_PLUS:
+ sprintf(keyname,"NPplus");
+ break;
+ case SDLK_KP_ENTER:
+ sprintf(keyname,"NP_Enter");
+ break;
+ case SDLK_KP_EQUALS:
+ sprintf(keyname,"NP=");
+ break;
+ case SDLK_UP:
+ sprintf(keyname,"UP");
+ break;
+ case SDLK_DOWN:
+ sprintf(keyname,"DOWN");
+ break;
+ case SDLK_RIGHT:
+ sprintf(keyname,"RIGHT");
+ break;
+ case SDLK_LEFT:
+ sprintf(keyname,"LEFT");
+ break;
+ case SDLK_INSERT:
+ sprintf(keyname,"Insert");
+ break;
+ case SDLK_HOME:
+ sprintf(keyname,"Home");
+ break;
+ case SDLK_END:
+ sprintf(keyname,"End");
+ break;
+ case SDLK_PAGEUP:
+ sprintf(keyname,"PageUp");
+ break;
+ case SDLK_PAGEDOWN:
+ sprintf(keyname,"PageDown");
+ break;
+ case SDLK_NUMLOCK:
+ sprintf(keyname,"NumLock");
+ break;
+ case SDLK_CAPSLOCK:
+ sprintf(keyname,"CapsLock");
+ break;
+ case SDLK_SCROLLOCK:
+ sprintf(keyname,"ScrolLock");
+ break;
+ case SDLK_RSHIFT:
+ sprintf(keyname,"Rshift");
+ break;
+ case SDLK_LSHIFT:
+ sprintf(keyname,"Lshift");
+ break;
+ case SDLK_RCTRL:
+ sprintf(keyname,"Rctrl");
+ break;
+ case SDLK_LCTRL:
+ sprintf(keyname,"Lctrl");
+ break;
+ case SDLK_RALT:
+ sprintf(keyname,"Ralt");
+ break;
+ case SDLK_LALT:
+ sprintf(keyname,"Lalt");
+ break;
+ case SDLK_RMETA:
+ sprintf(keyname,"Rmeta");
+ break;
+ case SDLK_LMETA:
+ sprintf(keyname,"Lmeta");
+ break;
+ case SDLK_LSUPER:
+ sprintf(keyname,"Lwin");
+ break;
+ case SDLK_RSUPER:
+ sprintf(keyname,"Rwin");
+ break;
+ case SDLK_MODE:
+ sprintf(keyname,"Mode");
+ break;
+ case SDLK_HELP:
+ sprintf(keyname,"Help");
+ break;
+ default:
+ sprintf(keyname,"Unknown");
+ break;
+ }
+ if (charToPut != '\0')
+ sprintf(keyname,"%c",charToPut);
+ return &keyname[0];
+}
+
+void MakeBackground(int xsize,int ysize,BlockGame &theGame, BlockGame &theGame2);
+
+int OpenControlsBox(int x, int y, int player)
+{
+ int mousex, mousey;
+ Uint8 *keys;
+ bool done =false;
+ char *keyname;
+ MakeBackground(1024,768);
+ while (!done)
+ {
+ SDL_Delay(10);
+ DrawIMG(background, screen, 0, 0);
+ DrawIMG(changeButtonsBack,screen,x,y);
+ if (player == 0)
+ SFont_Write(screen,fBlueFont,x+40,y+2,"Player 1 keys");
+ else
+ SFont_Write(screen,fBlueFont,x+40,y+2,"Player 2 keys");
+ SFont_Write(screen,fBlueFont,x+6,y+50,"Up");
+ keyname = getKeyName(keySettings[player].up);
+ SFont_Write(screen,fBlueFont,x+200,y+50,keyname);
+ SFont_Write(screen,fBlueFont,x+6,y+100,"Down");
+ keyname = getKeyName(keySettings[player].down);
+ SFont_Write(screen,fBlueFont,x+200,y+100,keyname);
+ SFont_Write(screen,fBlueFont,x+6,y+150,"Left");
+ keyname = getKeyName(keySettings[player].left);
+ SFont_Write(screen,fBlueFont,x+200,y+150,keyname);
+ SFont_Write(screen,fBlueFont,x+6,y+200,"Right");
+ keyname = getKeyName(keySettings[player].right);
+ SFont_Write(screen,fBlueFont,x+200,y+200,keyname);
+ SFont_Write(screen,fBlueFont,x+6,y+250,"Push");
+ keyname = getKeyName(keySettings[player].push);
+ SFont_Write(screen,fBlueFont,x+200,y+250,keyname);
+ SFont_Write(screen,fBlueFont,x+6,y+300,"Change");
+ keyname = getKeyName(keySettings[player].change);
+ SFont_Write(screen,fBlueFont,x+200,y+300,keyname);
+ //Ask for mouse play
+ SFont_Write(screen,fBlueFont,x+6,y+350,"Mouse play?");
+ DrawIMG(iLevelCheckBox,screen,x+220,y+350);
+ if (((player==0)&&(mouseplay1))||((player==2)&&(mouseplay2)))
+ DrawIMG(iLevelCheck,screen,x+220,y+350); //iLevelCheck witdh is 42
+ //Ask for joypad play
+ SFont_Write(screen,fBlueFont,x+300,y+350,"Joypad?");
+ DrawIMG(iLevelCheckBox,screen,x+460,y+350);
+ if (((player==0)&&(joyplay1))||((player==2)&&(joyplay2)))
+ DrawIMG(iLevelCheck,screen,x+460,y+350); //iLevelCheck witdh is 42
+ for (int i=1; i<7; i++)
+ DrawIMG(bChange,screen,x+420,y+50*i);
+ SDL_Event event;
+
+ while (SDL_PollEvent(&event))
+ {
+ if ( event.type == SDL_QUIT ) {
+ done = true;
+ }
+
+ if (event.type == SDL_KEYDOWN)
+ {
+ if (event.key.keysym.sym == SDLK_ESCAPE)
+ done = true;
+ }
+ } //PollEvent
+
+ keys = SDL_GetKeyState(NULL);
+
+ SDL_GetMouseState(&mousex,&mousey);
+
+ // If the mouse button is released, make bMouseUp equal true
+ if (!SDL_GetMouseState(NULL, NULL)&SDL_BUTTON(1))
+ {
+ bMouseUp=true;
+ }
+
+ if (SDL_GetMouseState(NULL,NULL)&SDL_BUTTON(1) && bMouseUp)
+ {
+ bMouseUp = false;
+
+ if ((mousex>(420+x)) && (mousex<(540+x)) && (mousey>(50+y)) && (mousey<(90+y)))
+ {
+ //up
+ bool finnish = false;
+ while (!finnish)
+ while ( SDL_PollEvent(&event) )
+ {
+ if (event.type == SDL_KEYDOWN)
+ {
+ if (event.key.keysym.sym != SDLK_ESCAPE)
+ keySettings[player].up = event.key.keysym.sym;
+ finnish = true;
+ }
+ }
+ } //up
+ if ((mousex>(420+x)) && (mousex<(540+x)) && (mousey>(100+y)) && (mousey<(140+y)))
+ {
+ //down
+ bool finnish = false;
+ while (!finnish)
+ while ( SDL_PollEvent(&event) )
+ {
+ if (event.type == SDL_KEYDOWN)
+ {
+ if (event.key.keysym.sym != SDLK_ESCAPE)
+ keySettings[player].down = event.key.keysym.sym;
+ finnish = true;
+ }
+ }
+ } //down
+ if ((mousex>(420+x)) && (mousex<(540+x)) && (mousey>(150+y)) && (mousey<(190+y)))
+ {
+ //left
+ bool finnish = false;
+ while (!finnish)
+ while ( SDL_PollEvent(&event) )
+ {
+ if (event.type == SDL_KEYDOWN)
+ {
+ if (event.key.keysym.sym != SDLK_ESCAPE)
+ keySettings[player].left = event.key.keysym.sym;
+ finnish = true;
+ }
+ }
+ } //left
+ if ((mousex>(420+x)) && (mousex<(540+x)) && (mousey>(200+y)) && (mousey<(240+y)))
+ {
+ //right
+ bool finnish = false;
+ while (!finnish)
+ while ( SDL_PollEvent(&event) )
+ {
+ if (event.type == SDL_KEYDOWN)
+ {
+ if (event.key.keysym.sym != SDLK_ESCAPE)
+ keySettings[player].right = event.key.keysym.sym;
+ finnish = true;
+ }
+ }
+ } //right
+ if ((mousex>(420+x)) && (mousex<(540+x)) && (mousey>(250+y)) && (mousey<(290+y)))
+ {
+ //push
+ bool finnish = false;
+ while (!finnish)
+ while ( SDL_PollEvent(&event) )
+ {
+ if (event.type == SDL_KEYDOWN)
+ {
+ if (event.key.keysym.sym != SDLK_ESCAPE)
+ keySettings[player].push = event.key.keysym.sym;
+ finnish = true;
+ }
+ }
+ } //push
+ if ((mousex>(420+x)) && (mousex<(540+x)) && (mousey>(300+y)) && (mousey<(340+y)))
+ {
+ //change
+ bool finnish = false;
+ while (!finnish)
+ while ( SDL_PollEvent(&event) )
+ {
+ if (event.type == SDL_KEYDOWN)
+ {
+ if (event.key.keysym.sym != SDLK_ESCAPE)
+ keySettings[player].change = event.key.keysym.sym;
+ finnish = true;
+ }
+ }
+ } //change
+ //mouseplay:
+ if ((mousex>(220+x)) && (mousex<(262+x)) && (mousey>(350+y)) && (mousey<(392+y)))
+ {
+ if (player==0)
+ {
+ mouseplay1 = !mouseplay1;
+ }
+ else
+ {
+ mouseplay2 = !mouseplay2;
+ }
+ }
+ //Joyplay:
+ if ((mousex>(460+x)) && (mousex<(502+x)) && (mousey>(350+y)) && (mousey<(392+y)))
+ {
+ if (player==0)
+ {
+ joyplay1 = !joyplay1;
+ }
+ else
+ {
+ joyplay2 = !joyplay2;
+ }
+ }
+ } //get mouse state
+
+ DrawIMG(mouse,screen,mousex,mousey);
+ SDL_Flip(screen);
+ } //while !done
+ DrawIMG(background, screen, 0, 0);
+ return 0;
+}
+
+
+//Dialogbox
+bool OpenDialogbox(int x, int y, char *name)
+{
+ bool done = false; //We are done!
+ bool accept = false; //New name is accepted! (not Cancelled)
+ bool repeating = false; //The key is being held (BACKSPACE)
+ const int repeatDelay = 200; //Repeating
+ unsigned long time = 0;
+ ReadKeyboard rk = ReadKeyboard(name);
+ Uint8* keys;
+ string strHolder;
+ MakeBackground(1024,768);
+ DrawIMG(background,screen,0,0);
+ while (!done)
+ {
+ DrawIMG(dialogBox,screen,x,y);
+ SFont_Write(screen,fBlueFont,x+40,y+72,rk.GetString());
+ strHolder = rk.GetString();
+ //cout << "hej\n" << (int)rk.CharsBeforeCursor() << endl;
+ strHolder.erase((int)rk.CharsBeforeCursor());
+
+ if (((SDL_GetTicks()/600)%2)==1)
+ SFont_Write(screen,fBlueFont,x+40+SFont_TextWidth(fBlueFont,strHolder.c_str()),y+69,"|");
+
+ SDL_Event event;
+
+ while ( SDL_PollEvent(&event) )
+ {
+ if ( event.type == SDL_QUIT ) {
+ done = true;
+ accept = false;
+ }
+
+ if ( event.type == SDL_KEYDOWN )
+ {
+ if ( (event.key.keysym.sym == SDLK_RETURN)||(event.key.keysym.sym == SDLK_KP_ENTER) ) {
+ done = true;
+ accept = true;
+ }
+ else
+ if ( (event.key.keysym.sym == SDLK_ESCAPE) ) {
+ done = true;
+ accept = false;
+ }
+ else if (!(event.key.keysym.sym == SDLK_BACKSPACE)){
+ if ((rk.ReadKey(event.key.keysym.sym))&&(SoundEnabled)&&(!NoSound))Mix_PlayChannel(1,typingChunk,0);
+ }
+ else if ((event.key.keysym.sym == SDLK_BACKSPACE)&&(!repeating)){
+ if ((rk.ReadKey(event.key.keysym.sym))&&(SoundEnabled)&&(!NoSound))Mix_PlayChannel(1,typingChunk,0);
+ repeating = true;
+ time=SDL_GetTicks();
+ }
+ }
+
+ } //while(event)
+
+ if (SDL_GetTicks()>(time+repeatDelay))
+ {
+ time = SDL_GetTicks();
+ keys = SDL_GetKeyState(NULL);
+ if ( (keys[SDLK_BACKSPACE])&&(repeating) )
+ {
+ if ((rk.ReadKey(SDLK_BACKSPACE))&&(SoundEnabled)&&(!NoSound))Mix_PlayChannel(1,typingChunk,0);
+ }
+ else
+ repeating = false;
+ }
+
+ SDL_Flip(screen); //Update screen
+ } //while(!done)
+ strcpy(name,rk.GetString());
+ bScreenLocked = false;
+ showDialog = false;
+ return accept;
+}
+
+
+//Open a puzzle file
+bool OpenFileDialogbox(int x, int y, char *name)
+{
+ bool done = false; //We are done!
+ int mousex, mousey;
+ ListFiles lf = ListFiles();
+#ifdef SHAREDIR
+ string folder = (string)SHAREDIR+(string)"/res";
+ cout << "Looking in " << folder << endl;
+ lf.setDirectory(folder.c_str());
+#else
+ lf.setDirectory("./res");
+#endif
+#ifdef __unix__
+ string homeFolder = (string)getenv("HOME")+(string)"/.gamesaves/blockattack/puzzles";
+ lf.setDirectory2(homeFolder.c_str());
+#endif
+ Uint8* keys;
+ string strHolder;
+ MakeBackground(1024,768);
+ DrawIMG(background,screen,0,0);
+ DrawIMG(bForward,background,x+460,y+420);
+ DrawIMG(bBack,background,x+20,y+420);
+ while (!done)
+ {
+ DrawIMG(background,screen,0,0);
+ const int nrOfFiles = 10;
+ DrawIMG(changeButtonsBack,screen,x,y);
+ for (int i=0;i<nrOfFiles;i++)
+ {
+ SFont_Write(screen,fBlueFont,x+10,y+10+36*i,lf.getFileName(i).c_str());
+ }
+
+ SDL_Event event;
+
+ while ( SDL_PollEvent(&event) )
+ {
+ if ( event.type == SDL_QUIT ) {
+ done = true;
+ }
+
+ if ( event.type == SDL_KEYDOWN )
+ {
+ if ( (event.key.keysym.sym == SDLK_ESCAPE) ) {
+ done = true;
+ }
+
+ if ( (event.key.keysym.sym == SDLK_RIGHT) ) {
+ lf.forward();
+ }
+
+ if ( (event.key.keysym.sym == SDLK_LEFT) ) {
+ lf.back();
+ }
+ }
+
+ } //while(event)
+
+ SDL_GetMouseState(&mousex,&mousey);
+
+ // If the mouse button is released, make bMouseUp equal true
+ if (!SDL_GetMouseState(NULL, NULL)&SDL_BUTTON(1))
+ {
+ bMouseUp=true;
+ }
+
+ if (SDL_GetMouseState(NULL,NULL)&SDL_BUTTON(1) && bMouseUp)
+ {
+ bMouseUp = false;
+
+ //The Forward Button:
+ if ( (mousex>x+460) && (mousex<x+460+120) && (mousey>y+420) && (mousey<y+420+40) )
+ {
+ lf.forward();
+ }
+
+ //The back button:
+ if ( (mousex>x+20) && (mousex<x+20+120) && (mousey>y+420) && (mousey<y+420+40) )
+ {
+ lf.back();
+ }
+
+ for (int i=0;i<10;i++)
+ {
+ if ( (mousex>x+10) && (mousex<x+480) && (mousey>y+10+i*36) && (mousey<y+10+i*36+32) )
+ {
+ if (lf.fileExists(i))
+ {
+ strncpy(name,lf.getFileName(i).c_str(),28); //Problems occurs then larger than 28 (maybe 29)
+ done=true; //The user have, clicked the purpose of this function is now complete
+ }
+ }
+ }
+ }
+
+ DrawIMG(mouse,screen,mousex,mousey);
+ SDL_Flip(screen); //Update screen
+ }
+}
+
+//Slelect a theme
+bool SelectThemeDialogbox(int x, int y, char *name)
+{
+ bool done = false; //We are done!
+ int mousex, mousey;
+ ListFiles lf = ListFiles();
+#ifdef SHAREDIR
+ string folder = (string)SHAREDIR+(string)"/themes";
+ cout << "Looking in " << folder << endl;
+ lf.setDirectory(folder.c_str());
+#else
+ lf.setDirectory("./themes");
+#endif
+#ifdef __unix__
+ string homeFolder = (string)getenv("HOME")+(string)"/.gamesaves/blockattack/themes";
+ lf.setDirectory2(homeFolder.c_str());
+#endif
+ Uint8* keys;
+ string strHolder;
+ MakeBackground(1024,768);
+ DrawIMG(background,screen,0,0);
+ DrawIMG(bForward,background,x+460,y+420);
+ DrawIMG(bBack,background,x+20,y+420);
+ while (!done)
+ {
+ DrawIMG(background,screen,0,0);
+ const int nrOfFiles = 10;
+ DrawIMG(changeButtonsBack,screen,x,y);
+ for (int i=0;i<nrOfFiles;i++)
+ {
+ SFont_Write(screen,fBlueFont,x+10,y+10+36*i,lf.getFileName(i).c_str());
+ }
+
+ SDL_Event event;
+
+ while ( SDL_PollEvent(&event) )
+ {
+ if ( event.type == SDL_QUIT ) {
+ done = true;
+ }
+
+ if ( event.type == SDL_KEYDOWN )
+ {
+ if ( (event.key.keysym.sym == SDLK_ESCAPE) ) {
+ done = true;
+ }
+
+ if ( (event.key.keysym.sym == SDLK_RIGHT) ) {
+ lf.forward();
+ }
+
+ if ( (event.key.keysym.sym == SDLK_LEFT) ) {
+ lf.back();
+ }
+ }
+
+ } //while(event)
+
+ SDL_GetMouseState(&mousex,&mousey);
+
+ // If the mouse button is released, make bMouseUp equal true
+ if (!SDL_GetMouseState(NULL, NULL)&SDL_BUTTON(1))
+ {
+ bMouseUp=true;
+ }
+
+ if (SDL_GetMouseState(NULL,NULL)&SDL_BUTTON(1) && bMouseUp)
+ {
+ bMouseUp = false;
+
+ //The Forward Button:
+ if ( (mousex>x+460) && (mousex<x+460+120) && (mousey>y+420) && (mousey<y+420+40) )
+ {
+ lf.forward();
+ }
+
+ //The back button:
+ if ( (mousex>x+20) && (mousex<x+20+120) && (mousey>y+420) && (mousey<y+420+40) )
+ {
+ lf.back();
+ }
+
+ for (int i=0;i<10;i++)
+ {
+ if ( (mousex>x+10) && (mousex<x+480) && (mousey>y+10+i*36) && (mousey<y+10+i*36+32) )
+ {
+ if (lf.fileExists(i))
+ {
+ strncpy(name,lf.getFileName(i).c_str(),28); //Problems occurs then larger than 28 (maybe 29)
+ loadTheme(lf.getFileName(i));
+ done=true; //The user have, clicked the purpose of this function is now complete
+ }
+ }
+ }
+ }
+
+ DrawIMG(mouse,screen,mousex,mousey);
+ SDL_Flip(screen); //Update screen
+ }
+}
+
+//Open a saved replay
+bool OpenReplayDialogbox(int x, int y, char *name)
+{
+ bool done = false; //We are done!
+ int mousex, mousey;
+ ListFiles lf = ListFiles();
+ cout << "Ready to set directory!" << endl;
+#ifdef __unix__
+ string directory = (string)getenv("HOME")+(string)"/.gamesaves/blockattack/replays";
+#elif WIN32
+ string directory = getMyDocumentsPath()+(string)"/My Games/blockattack/replays";
+#else
+ string directory = "./replays";
+#endif
+ lf.setDirectory(directory);
+ cout << "Directory sat" << endl;
+ Uint8* keys;
+ string strHolder;
+ MakeBackground(1024,768);
+ DrawIMG(background,screen,0,0);
+ DrawIMG(bForward,background,x+460,y+420);
+ DrawIMG(bBack,background,x+20,y+420);
+ while (!done)
+ {
+ DrawIMG(background,screen,0,0);
+ const int nrOfFiles = 10;
+ DrawIMG(changeButtonsBack,screen,x,y);
+ for (int i=0;i<nrOfFiles;i++)
+ {
+ SFont_Write(screen,fBlueFont,x+10,y+10+36*i,lf.getFileName(i).c_str());
+ }
+
+ SDL_Event event;
+
+ while ( SDL_PollEvent(&event) )
+ {
+ if ( event.type == SDL_QUIT ) {
+ done = true;
+ return false;
+ }
+
+ if ( event.type == SDL_KEYDOWN )
+ {
+ if ( (event.key.keysym.sym == SDLK_ESCAPE) ) {
+ done = true;
+ return false;
+ }
+
+ if ( (event.key.keysym.sym == SDLK_RIGHT) ) {
+ lf.forward();
+ }
+
+ if ( (event.key.keysym.sym == SDLK_LEFT) ) {
+ lf.back();
+ }
+ }
+
+ } //while(event)
+
+ SDL_GetMouseState(&mousex,&mousey);
+
+ // If the mouse button is released, make bMouseUp equal true
+ if (!SDL_GetMouseState(NULL, NULL)&SDL_BUTTON(1))
+ {
+ bMouseUp=true;
+ }
+
+ if (SDL_GetMouseState(NULL,NULL)&SDL_BUTTON(1) && bMouseUp)
+ {
+ bMouseUp = false;
+
+ //The Forward Button:
+ if ( (mousex>x+460) && (mousex<x+460+120) && (mousey>y+420) && (mousey<y+420+40) )
+ {
+ lf.forward();
+ }
+
+ //The back button:
+ if ( (mousex>x+20) && (mousex<x+20+120) && (mousey>y+420) && (mousey<y+420+40) )
+ {
+ lf.back();
+ }
+
+ for (int i=0;i<10;i++)
+ {
+ if ( (mousex>x+10) && (mousex<x+480) && (mousey>y+10+i*36) && (mousey<y+10+i*36+32) )
+ {
+ if (lf.fileExists(i))
+ {
+ strncpy(name,lf.getFileName(i).c_str(),28); //Problems occurs then larger than 28 (maybe 29)
+ done=true; //The user have, clicked the purpose of this function is now complete
+ return true;
+ }
+ }
+ }
+ }
+
+ DrawIMG(mouse,screen,mousex,mousey);
+ SDL_Flip(screen); //Update screen
+ }
+}
+
+
+//draws options:
+inline void DrawOptions(int x, int y)
+{
+ if (MusicEnabled) DrawIMG(bOn,optionsBack,400,120);
+ else DrawIMG(bOff,optionsBack,400,120);
+ if (SoundEnabled) DrawIMG(bOn,optionsBack,400,170);
+ else DrawIMG(bOff,optionsBack,400,170);
+ if (bFullscreen) DrawIMG(bOn,optionsBack,400,220);
+ else DrawIMG(bOff,optionsBack,400,220);
+ DrawIMG(bChange,optionsBack,230,435);
+ DrawIMG(bChange,optionsBack,410,435);
+ DrawIMG(bChange,optionsBack,230,500);
+ DrawIMG(bChange,optionsBack,410,500);
+ DrawIMG(optionsBack,screen,x,y);
+} //drawOptions
+
+//Draws the balls and explosions
+void DrawBalls()
+{
+ for (int i = 0; i< maxNumberOfBalls; i++)
+ {
+ if (theBallManeger.ballUsed[i])
+ {
+ DrawIMG(balls[theBallManeger.ballArray[i].getColor()],screen,theBallManeger.ballArray[i].getX(),theBallManeger.ballArray[i].getY());
+ } //if used
+ if (theExplosionManeger.explosionUsed[i])
+ {
+ DrawIMG(explosion[theExplosionManeger.explosionArray[i].getFrame()],screen,theExplosionManeger.explosionArray[i].getX(),theExplosionManeger.explosionArray[i].getY());
+ }
+ if (theTextManeger.textUsed[i])
+ {
+ //cout << "Printing text: " << theTextManeger.textArray[i].getText() << endl;
+ int x = theTextManeger.textArray[i].getX()-SFont_TextWidth(fSmallFont,theTextManeger.textArray[i].getText())/2;
+ int y = theTextManeger.textArray[i].getY()-SFont_TextHeight(fSmallFont)/2;
+ DrawIMG(iChainBack,screen,x,y);
+ SFont_Write(screen,fSmallFont,x+(25-SFont_TextWidth(fSmallFont,theTextManeger.textArray[i].getText()))/2,y+(25-SFont_TextHeight(fSmallFont))/2,theTextManeger.textArray[i].getText());
+ }
+ } //for
+} //DrawBalls
+
+//Removes the old balls
+void UndrawBalls()
+{
+ for (int i = 0; i< maxNumberOfBalls; i++)
+ {
+ if (theBallManeger.oldBallUsed[i])
+ {
+ DrawIMG(background,screen,theBallManeger.oldBallArray[i].getX(),theBallManeger.oldBallArray[i].getY(),ballSize,ballSize,theBallManeger.oldBallArray[i].getX(),theBallManeger.oldBallArray[i].getY());
+ } //if used
+ if (theExplosionManeger.oldExplosionUsed[i])
+ {
+ DrawIMG(background,screen,theExplosionManeger.oldExplosionArray[i].getX(),theExplosionManeger.oldExplosionArray[i].getY(),70,120,theExplosionManeger.oldExplosionArray[i].getX(),theExplosionManeger.oldExplosionArray[i].getY());
+ }
+ if (theTextManeger.oldTextUsed[i])
+ {
+ int x = theTextManeger.oldTextArray[i].getX()-SFont_TextWidth(fSmallFont,theTextManeger.oldTextArray[i].getText())/2;
+ int y = theTextManeger.oldTextArray[i].getY()-SFont_TextHeight(fSmallFont)/2;
+ DrawIMG(background,screen,x,y,25,25,x,y);
+ }
+ } //for
+} //UndrawBalls
+
+//draws everything
+void DrawEverything(int xsize, int ysize,BlockGame &theGame, BlockGame &theGame2)
+{
+ SDL_ShowCursor(SDL_DISABLE);
+ //draw background:
+ if (forceredraw != 1)
+ {
+
+ UndrawBalls();
+ DrawIMG(background,screen,oldMousex,oldMousey,32,32,oldMousex,oldMousey);
+ DrawIMG(background,screen,oldBubleX,oldBubleY,140,50,oldBubleX,oldBubleY);
+
+
+ DrawIMG(background,screen,350,200,120,200,350,200);
+ DrawIMG(background,screen,830,200,120,200,830,200);
+ DrawIMG(background,screen,800,0,140,50,800,0);
+
+ DrawIMG(background,screen,50,60,300,50,50,60);
+ DrawIMG(background,screen,510,60,300,50,510,60);
+ }
+ else
+ DrawIMG(background,screen,0,0);
+ //draw bottons (should be moves and drawn directly to background once)
+ if (!editorMode)
+ if (!networkActive) //We don't show the menu while running server or connected to a server
+ {
+ //Here we draw the menu
+ DrawIMG(bNewGame, screen, 0, 0);
+ DrawIMG(bOptions, screen, 120,0);
+ DrawIMG(bHighScore, screen, 2*120,0);
+ DrawIMG(bReplay,screen,3*120,0);
+ }
+ else
+ { //If network is active
+ DrawIMG(bBack, screen, 0, 0); //Display a disconnect button
+ }
+ if (!editorMode)
+ DrawIMG(bExit, screen, xsize-120,ysize-120);
+ //DrawIMG(boardBackBack,screen,theGame.topx-60,theGame.topy-68);
+ DrawIMG(theGame.sBoard,screen,theGame.topx,theGame.topy);
+ string strHolder;
+ strHolder = itoa(theGame.score+theGame.handicap);
+ SFont_Write(screen,fBlueFont,theGame.topx+310,theGame.topy+100,strHolder.c_str());
+ if (theGame.AI_Enabled)
+ SFont_Write(screen,fBlueFont,theGame.topx+10,theGame.topy-40,"CPU");
+ else
+ if (editorMode)
+ SFont_Write(screen,fBlueFont,theGame.topx+10,theGame.topy-40,"Playing field");
+ else
+ if (!singlePuzzle)
+ SFont_Write(screen,fBlueFont,theGame.topx+10,theGame.topy-40,player1name);
+ if (theGame.timetrial)
+ {
+ int tid = (int)SDL_GetTicks()-theGame.gameStartedAt;
+ int minutes;
+ int seconds;
+ if (tid>=0)
+ {
+ minutes = (2*60*1000-(abs((int)SDL_GetTicks()-(int)theGame.gameStartedAt)))/60/1000;
+ seconds = ((2*60*1000-(abs((int)SDL_GetTicks()-(int)theGame.gameStartedAt)))%(60*1000))/1000;
+ }
+ else
+ {
+ minutes = ((abs((int)SDL_GetTicks()-(int)theGame.gameStartedAt)))/60/1000;
+ seconds = (((abs((int)SDL_GetTicks()-(int)theGame.gameStartedAt)))%(60*1000))/1000;
+ }
+ if (theGame.bGameOver) minutes=0;
+ if (theGame.bGameOver) seconds=0;
+ if (seconds>9)
+ strHolder = itoa(minutes)+":"+itoa(seconds);
+ else strHolder = itoa(minutes)+":0"+itoa(seconds);
+ if ((SoundEnabled)&&(!NoSound)&&(tid>0)&&(seconds<5)&&(minutes == 0)&&(seconds>1)&&(!(Mix_Playing(6)))) Mix_PlayChannel(6,heartBeat,0);
+ SFont_Write(screen,fBlueFont,theGame.topx+310,theGame.topy+150,strHolder.c_str());
+ }
+ else
+ {
+ int minutes = ((abs((int)SDL_GetTicks()-(int)theGame.gameStartedAt)))/60/1000;
+ int seconds = (((abs((int)SDL_GetTicks()-(int)theGame.gameStartedAt)))%(60*1000))/1000;
+ if (theGame.bGameOver) minutes=(theGame.gameEndedAfter/1000/60)%100;
+ if (theGame.bGameOver) seconds=(theGame.gameEndedAfter/1000)%60;
+ if (seconds>9)
+ strHolder = itoa(minutes)+":"+itoa(seconds);
+ else
+ strHolder = itoa(minutes)+":0"+itoa(seconds);
+ SFont_Write(screen,fBlueFont,theGame.topx+310,theGame.topy+150,strHolder.c_str());
+ }
+ strHolder = itoa(theGame.chain);
+ SFont_Write(screen,fBlueFont,theGame.topx+310,theGame.topy+200,strHolder.c_str());
+ //drawspeedLevel:
+ strHolder = itoa(theGame.speedLevel);
+ SFont_Write(screen,fBlueFont,theGame.topx+310,theGame.topy+250,strHolder.c_str());
+ if ((theGame.stageClear) &&(theGame.topy+700+50*(theGame.stageClearLimit-theGame.linesCleared)-theGame.pixels-1<600+theGame.topy))
+ {
+ oldBubleX = theGame.topx+280;
+ oldBubleY = theGame.topy+650+50*(theGame.stageClearLimit-theGame.linesCleared)-theGame.pixels-1;
+ DrawIMG(stageBobble,screen,theGame.topx+280,theGame.topy+650+50*(theGame.stageClearLimit-theGame.linesCleared)-theGame.pixels-1);
+ }
+ //player1 finnish, player2 start
+ //DrawIMG(boardBackBack,screen,theGame2.topx-60,theGame2.topy-68);
+ if (!editorMode)
+ {
+ DrawIMG(theGame2.sBoard,screen,theGame2.topx,theGame2.topy);
+ strHolder = itoa(theGame2.score+theGame2.handicap);
+ SFont_Write(screen,fBlueFont,theGame2.topx+310,theGame2.topy+100,strHolder.c_str());
+ if (theGame2.AI_Enabled)
+ SFont_Write(screen,fBlueFont,theGame2.topx+10,theGame2.topy-40,"CPU");
+ else
+ SFont_Write(screen,fBlueFont,theGame2.topx+10,theGame2.topy-40,theGame2.name);
+ if (theGame2.timetrial)
+ {
+ int tid = (int)SDL_GetTicks()-theGame2.gameStartedAt;
+ int minutes;
+ int seconds;
+ if (tid>=0)
+ {
+ minutes = (2*60*1000-(abs((int)SDL_GetTicks()-(int)theGame2.gameStartedAt)))/60/1000;
+ seconds = ((2*60*1000-(abs((int)SDL_GetTicks()-(int)theGame2.gameStartedAt)))%(60*1000))/1000;
+ }
+ else
+ {
+ minutes = ((abs((int)SDL_GetTicks()-(int)theGame2.gameStartedAt)))/60/1000;
+ seconds = (((abs((int)SDL_GetTicks()-(int)theGame2.gameStartedAt)))%(60*1000))/1000;
+ }
+ if (theGame2.bGameOver) minutes=0;
+ if (theGame2.bGameOver) seconds=0;
+ if (seconds>9)
+ strHolder = itoa(minutes)+":"+itoa(seconds);
+ else
+ strHolder = itoa(minutes)+":0"+itoa(seconds);
+ if ((SoundEnabled)&&(!NoSound)&&(tid>0)&&(seconds<5)&&(minutes == 0)&&(seconds>1)&&(!(Mix_Playing(6)))) Mix_PlayChannel(6,heartBeat,0);
+ SFont_Write(screen,fBlueFont,theGame2.topx+310,theGame2.topy+150,strHolder.c_str());
+ }
+ else
+ {
+ int minutes = (abs((int)SDL_GetTicks()-(int)theGame2.gameStartedAt))/60/1000;
+ int seconds = (abs((int)SDL_GetTicks()-(int)theGame2.gameStartedAt)%(60*1000))/1000;
+ if (theGame2.bGameOver) minutes=(theGame2.gameEndedAfter/1000/60)%100;
+ if (theGame2.bGameOver) seconds=(theGame2.gameEndedAfter/1000)%60;
+ if (seconds>9)
+ strHolder = itoa(minutes)+":"+itoa(seconds);
+ else
+ strHolder = itoa(minutes)+":0"+itoa(seconds);
+ SFont_Write(screen,fBlueFont,theGame2.topx+310,theGame2.topy+150,strHolder.c_str());
+ }
+ strHolder = itoa(theGame2.chain);
+ SFont_Write(screen,fBlueFont,theGame2.topx+310,theGame2.topy+200,strHolder.c_str());
+ strHolder = itoa(theGame2.speedLevel);
+ SFont_Write(screen,fBlueFont,theGame2.topx+310,theGame2.topy+250,strHolder.c_str());
+ }
+ //player2 finnish
+
+ if (bNewGameOpen)
+ {
+ DrawIMG(b1player,screen,0,40);
+ DrawIMG(b2players,screen,0,80);
+#ifdef NETWORK
+ DrawIMG(bNetwork,screen,0,120);
+#endif
+ if (b1playerOpen)
+ {
+ DrawIMG(bEndless,screen,120,40);
+ DrawIMG(bTimeTrial,screen,120,80);
+ DrawIMG(bStageClear,screen,120,120);
+ DrawIMG(bPuzzle,screen,120,160);
+ DrawIMG(bVsMode,screen,120,200);
+ }
+ else
+ if (b2playersOpen)
+ {
+ DrawIMG(bTimeTrial,screen,120,80);
+ DrawIMG(bVsMode,screen,120,120);
+ }
+#ifdef NETWORK
+ else
+ if (bNetworkOpen)
+ {
+ DrawIMG(bHost,screen,120,120);
+ DrawIMG(bConnect,screen,120,160);
+ }
+#endif
+ }
+ if (bOptionsOpen)
+ {
+ DrawIMG(bConfigure,screen,120,40);
+ DrawIMG(bSelectPuzzle,screen,120,80);
+ DrawIMG(bVsMode,screen,120,120);
+ DrawIMG(bTheme,screen,120,160);
+ }
+ if (bReplayOpen)
+ {
+ DrawIMG(bSave,screen,360,40);
+ DrawIMG(bLoad,screen,360,80);
+ }
+ if (showHighscores) DrawHighscores(100,100);
+ if (showOptions) DrawOptions(100,100);
+
+ DrawBalls();
+
+#if defined(DEBUG)
+ Frames++;
+ if (SDL_GetTicks() >= Ticks + 1000)
+ {
+ if (Frames > 999) Frames=999;
+ sprintf(FPS, "%i fps", Frames);
+ Frames = 0;
+ Ticks = SDL_GetTicks();
+ }
+
+ SFont_Write(screen,fBlueFont,800,4,FPS);
+#endif
+
+ //SDL_Flip(screen); Update screen is now called outside DrawEvrything, bacause the mouse needs to be painted
+
+}
+
+//Generates the standard background
+void MakeBackground(int xsize,int ysize)
+{
+ DrawIMG(backgroundImage,background,0,0);
+ standardBackground = true;
+}
+
+//Generates the background with red board backs
+void MakeBackground(int xsize,int ysize,BlockGame &theGame, BlockGame &theGame2)
+{
+ DrawIMG(backgroundImage,background,0,0);
+ DrawIMG(boardBackBack,background,theGame.topx-60,theGame.topy-68);
+ DrawIMG(boardBackBack,background,theGame2.topx-60,theGame2.topy-68);
+ standardBackground = false;
+}
+
+void MakeBackground(int xsize, int ysize, BlockGame &theGame)
+{
+ DrawIMG(backgroundImage,background,0,0);
+ DrawIMG(boardBackBack,background,theGame.topx-60,theGame.topy-68);
+ standardBackground = false;
+}
+
+
+//The function that allows the player to choose PuzzleLevel
+int PuzzleLevelSelect()
+{
+ const int xplace = 200;
+ const int yplace = 300;
+ Uint8 *keys;
+ int levelNr, mousex, mousey;
+ bool levelSelected = false;
+ bool tempBool;
+
+ //Loads the levels, if they havn't been loaded:
+ LoadPuzzleStages();
+
+ //Keeps track of background;
+ int nowTime=SDL_GetTicks();
+
+ ifstream puzzleFile(puzzleSavePath.c_str(),ios::binary);
+ MakeBackground(1024,768);
+ if (puzzleFile)
+ {
+ for (int i=0;(i<nrOfPuzzles)&&(!puzzleFile.eof()); i++)
+ {
+ puzzleFile.read(reinterpret_cast<char*>(&tempBool),sizeof(bool));
+ puzzleCleared[i] = tempBool;
+ }
+ puzzleFile.close();
+ }
+ else
+ {
+ tempBool = false;
+ for (int i=0; i<nrOfPuzzles; i++)
+ puzzleCleared[i] = tempBool;
+ }
+
+ do
+ {
+ nowTime=SDL_GetTicks();
+
+
+ DrawIMG(background, screen, 0, 0);
+ DrawIMG(iCheckBoxArea,screen,xplace,yplace);
+ SFont_Write(screen,fBlueFont,xplace+12,yplace+2,"Select Puzzle");
+ //Now drow the fields you click in (and a V if clicked):
+ for (int i = 0; i < nrOfPuzzles;i++)
+ {
+ DrawIMG(iLevelCheckBox,screen,xplace+10+(i%10)*50, yplace+60+(i/10)*50);
+ if (puzzleCleared[i]==true) DrawIMG(iLevelCheck,screen,xplace+10+(i%10)*50, yplace+60+(i/10)*50);
+ }
+
+ SDL_Event event;
+ while ( SDL_PollEvent(&event) )
+ if ( event.type == SDL_KEYDOWN )
+ {
+ if ( event.key.keysym.sym == SDLK_ESCAPE ) {
+ levelNr = -1;
+ levelSelected = true;
+ }
+ }
+
+ keys = SDL_GetKeyState(NULL);
+
+ SDL_GetMouseState(&mousex,&mousey);
+
+ // If the mouse button is released, make bMouseUp equal true
+ if (!SDL_GetMouseState(NULL, NULL)&SDL_BUTTON(1))
+ {
+ bMouseUp=true;
+ }
+
+ if (SDL_GetMouseState(NULL,NULL)&SDL_BUTTON(1) && bMouseUp)
+ {
+ bMouseUp = false;
+
+ int levelClicked = -1;
+ int i;
+ for (i = 0; (i<nrOfPuzzles/10)||((i<nrOfPuzzles/10+1)&&(nrOfPuzzles%10 != 0)); i++)
+ if ((60+i*50<mousey-yplace)&&(mousey-yplace<i*50+92))
+ levelClicked = i*10;
+ i++;
+ if (levelClicked != -1)
+ for (int j = 0; ((j<nrOfStageLevels%(i*10))&&(j<10)); j++)
+ if ((10+j*50<mousex-xplace)&&(mousex-xplace<j*50+42))
+ {
+ levelClicked +=j;
+ levelSelected = true;
+ levelNr = levelClicked;
+ }
+ }
+
+ DrawIMG(mouse,screen,mousex,mousey);
+ SDL_Flip(screen); //draws it all to the screen
+
+ } while (!levelSelected);
+ DrawIMG(background, screen, 0, 0);
+ return levelNr;
+}
+
+//The function that allows the player to choose Level number
+int StageLevelSelect()
+{
+ const int xplace = 200;
+ const int yplace = 300;
+ Uint8 *keys;
+ int levelNr, mousex, mousey;
+ bool levelSelected = false;
+ bool tempBool;
+ Uint32 tempUInt32;
+ Uint32 totalScore = 0;
+ Uint32 totalTime = 0;
+
+ //Keeps track of background;
+ //int nowTime=SDL_GetTicks();
+
+ MakeBackground(1024,768);
+ ifstream stageFile(stageClearSavePath.c_str(),ios::binary);
+ if (stageFile)
+ {
+ for (int i = 0; i<nrOfStageLevels; i++)
+ {
+ stageFile.read(reinterpret_cast<char*>(&tempBool),sizeof(bool));
+ stageCleared[i]=tempBool;
+ }
+ if(!stageFile.eof())
+ {
+ for(int i=0; i<nrOfStageLevels; i++)
+ {
+ tempUInt32 = 0;
+ if(!stageFile.eof())
+ stageFile.read(reinterpret_cast<char*>(&tempUInt32),sizeof(Uint32));
+ stageScores[i]=tempUInt32;
+ totalScore+=tempUInt32;
+ }
+ for(int i=0; i<nrOfStageLevels; i++)
+ {
+ tempUInt32 = 0;
+ if(!stageFile.eof())
+ stageFile.read(reinterpret_cast<char*>(&tempUInt32),sizeof(Uint32));
+ stageTimes[i]=tempUInt32;
+ totalTime += tempUInt32;
+ }
+ }
+ else
+ {
+ for(int i=0; i<nrOfStageLevels; i++)
+ {
+ stageScores[i]=0;
+ stageTimes[i]=0;
+ }
+ }
+ stageFile.close();
+ }
+ else
+ {
+ for (int i=0; i<nrOfStageLevels; i++)
+ {
+ stageCleared[i]= false;
+ stageScores[i]=0;
+ stageTimes[i]=0;
+ }
+ }
+
+
+ do
+ {
+ //nowTime=SDL_GetTicks();
+ DrawIMG(background, screen, 0, 0);
+ DrawIMG(iCheckBoxArea,screen,xplace,yplace);
+ SFont_Write(screen,fBlueFont,xplace+12,yplace+2,"Stage Clear Level Select");
+ for (int i = 0; i < nrOfStageLevels;i++)
+ {
+ DrawIMG(iLevelCheckBox,screen,xplace+10+(i%10)*50, yplace+60+(i/10)*50);
+ if (stageCleared[i]==true) DrawIMG(iLevelCheck,screen,xplace+10+(i%10)*50, yplace+60+(i/10)*50);
+ }
+
+ SDL_Event event;
+ while ( SDL_PollEvent(&event) )
+ if ( event.type == SDL_KEYDOWN )
+ {
+ if ( event.key.keysym.sym == SDLK_ESCAPE ) {
+ levelNr = -1;
+ levelSelected = true;
+ }
+ }
+
+ keys = SDL_GetKeyState(NULL);
+
+ SDL_GetMouseState(&mousex,&mousey);
+
+ // If the mouse button is released, make bMouseUp equal true
+ if (!SDL_GetMouseState(NULL, NULL)&SDL_BUTTON(1))
+ {
+ bMouseUp=true;
+ }
+
+ if (SDL_GetMouseState(NULL,NULL)&SDL_BUTTON(1) && bMouseUp)
+ {
+ bMouseUp = false;
+
+ int levelClicked = -1;
+ int i;
+ for (i = 0; (i<nrOfStageLevels/10)||((i<nrOfStageLevels/10+1)&&(nrOfStageLevels%10 != 0)); i++)
+ if ((60+i*50<mousey-yplace)&&(mousey-yplace<i*50+92))
+ levelClicked = i*10;
+ i++;
+ if (levelClicked != -1)
+ for (int j = 0; ((j<nrOfStageLevels%(i*10))&&(j<10)); j++)
+ if ((10+j*50<mousex-xplace)&&(mousex-xplace<j*50+42))
+ {
+ levelClicked +=j;
+ levelSelected = true;
+ levelNr = levelClicked;
+ }
+ }
+ //Find what we are over:
+ int overLevel = -1;
+ int i;
+ for (i = 0; (i<nrOfStageLevels/10)||((i<nrOfStageLevels/10+1)&&(nrOfStageLevels%10 != 0)); i++)
+ if ((60+i*50<mousey-yplace)&&(mousey-yplace<i*50+92))
+ overLevel = i*10;
+ i++;
+ if (overLevel != -1)
+ for (int j = 0; ((j<nrOfStageLevels%(i*10))&&(j<10)); j++)
+ if ((10+j*50<mousex-xplace)&&(mousex-xplace<j*50+42))
+ {
+ overLevel +=j;
+ string scoreString = "Best score: 0";
+ string timeString = "Time used: -- : --";
+
+ if(stageScores.at(overLevel)>0)
+ scoreString = "Best score: "+itoa(stageScores[overLevel]);
+ if(stageTimes[overLevel]>0)
+ timeString = "Time used: "+itoa(stageTimes[overLevel]/1000/60)+" : "+itoa2((stageTimes[overLevel]/1000)%60);
+
+ SFont_Write(screen,fBlueFont,200,200,scoreString.c_str());
+ SFont_Write(screen,fBlueFont,200,250,timeString.c_str());
+
+ overLevel;
+ }
+ string totalString = "Total score: " +itoa(totalScore) + " in " + itoa(totalTime/1000/60) + " : " + itoa2((totalTime/1000)%60);
+ SFont_Write(screen,fBlueFont,200,600,totalString.c_str());
+
+ DrawIMG(mouse,screen,mousex,mousey);
+ SDL_Flip(screen); //draws it all to the screen
+
+ } while (!levelSelected);
+ DrawIMG(background, screen, 0, 0);
+ return levelNr;
+}
+
+//Ask user for what AI level he will compete agains, return the number. Number must be 0..AIlevels
+int startSingleVs()
+{
+ //Where to place the windows
+ const int xplace = 200;
+ const int yplace = 100;
+ Uint8 *keys; //To take keyboard input
+ int mousex, mousey; //To allow mouse
+ bool done = false; //When are we done?
+
+ MakeBackground(1024,768);
+ DrawIMG(changeButtonsBack,background,xplace,yplace);
+ SFont_Write(background,fBlueFont,xplace+10,yplace+10,"1 : Very Easy");
+ SFont_Write(background,fBlueFont,xplace+10,yplace+40,"2 : Easy");
+ SFont_Write(background,fBlueFont,xplace+10,yplace+70,"3 : Below Normal");
+ SFont_Write(background,fBlueFont,xplace+10,yplace+100,"4 : Normal");
+ SFont_Write(background,fBlueFont,xplace+10,yplace+130,"5 : Above Normal");
+ SFont_Write(background,fBlueFont,xplace+10,yplace+160,"6 : Hard");
+ SFont_Write(background,fBlueFont,xplace+10,yplace+190,"7 : Hardest");
+ DrawIMG(background, screen, 0, 0);
+ SDL_Flip(screen);
+ do
+ {
+
+ SDL_Delay(10);
+ SDL_Event event;
+ while ( SDL_PollEvent(&event) )
+ if ( event.type == SDL_KEYDOWN )
+ {
+ if ( event.key.keysym.sym == SDLK_ESCAPE ) {
+ done = true;
+ }
+ if ( event.key.keysym.sym == SDLK_RETURN ) {
+ done = true;
+ }
+ if ( event.key.keysym.sym == SDLK_KP_ENTER ) {
+ done = true;
+ }
+ if ( event.key.keysym.sym == SDLK_1 ) {
+ return 0;
+ }
+ if ( event.key.keysym.sym == SDLK_2 ) {
+ return 1;
+ }
+ if ( event.key.keysym.sym == SDLK_3 ) {
+ return 2;
+ }
+ if ( event.key.keysym.sym == SDLK_4 ) {
+ return 3;
+ }
+ if ( event.key.keysym.sym == SDLK_5 ) {
+ return 4;
+ }
+ if ( event.key.keysym.sym == SDLK_6 ) {
+ return 5;
+ }
+ if ( event.key.keysym.sym == SDLK_7 ) {
+ return 6;
+ }
+ if ( event.key.keysym.sym == SDLK_KP1 ) {
+ return 0;
+ }
+ if ( event.key.keysym.sym == SDLK_KP2 ) {
+ return 1;
+ }
+ if ( event.key.keysym.sym == SDLK_KP3 ) {
+ return 2;
+ }
+ if ( event.key.keysym.sym == SDLK_KP4 ) {
+ return 3;
+ }
+ if ( event.key.keysym.sym == SDLK_KP5 ) {
+ return 4;
+ }
+ if ( event.key.keysym.sym == SDLK_KP6 ) {
+ return 5;
+ }
+ if ( event.key.keysym.sym == SDLK_KP7 ) {
+ return 6;
+ }
+
+ }
+
+ // If the mouse button is released, make bMouseUp equal true
+ if (!SDL_GetMouseState(NULL, NULL)&SDL_BUTTON(1))
+ {
+ bMouseUp=true;
+ }
+
+ if (SDL_GetMouseState(NULL,NULL)&SDL_BUTTON(1) && bMouseUp)
+ {
+ bMouseUp = false;
+
+ for (int i=0; i<7;i++)
+ {
+ if ((mousex>xplace+10)&&(mousex<xplace+410)&&(mousey>yplace+10+i*30)&&(mousey<yplace+38+i*30))
+ return i;
+ }
+ }
+
+ SDL_GetMouseState(&mousex,&mousey);
+ DrawIMG(background, screen, 0, 0);
+ DrawIMG(mouse,screen,mousex,mousey);
+ SDL_Flip(screen); //draws it all to the screen
+ }while (!done);
+
+
+ return 3; //Returns normal
+}
+
+//The function that allows the player to choose Level number
+void startVsMenu()
+{
+ const int xplace = 200;
+ const int yplace = 100;
+ Uint8 *keys;
+ int mousex, mousey;
+ bool done = false;
+
+ //Keeps track of background;
+ //int nowTime=SDL_GetTicks();
+
+ MakeBackground(1024,768);
+ SFont_Write(background,fBlueFont,360,650,"Press ESC to accept");
+ DrawIMG(bBack,background,1024/2-120/2,600);
+ do
+ {
+ //nowTime=SDL_GetTicks();
+ DrawIMG(background, screen, 0, 0);
+ DrawIMG(changeButtonsBack,screen,xplace,yplace);
+ SFont_Write(screen,fBlueFont,xplace+50,yplace+20,"Player 1");
+ SFont_Write(screen,fBlueFont,xplace+300+50,yplace+20,"Player 2");
+ SFont_Write(screen,fBlueFont,xplace+50,yplace+70,"Speed:");
+ SFont_Write(screen,fBlueFont,xplace+50+300,yplace+70,"Speed:");
+ for (int i=0; i<5;i++)
+ {
+ char levelS[2]; //level string;
+ levelS[0]='1'+i;
+ levelS[1]=0;
+ SFont_Write(screen,fBlueFont,xplace+50+i*40,yplace+110,levelS);
+ DrawIMG(iLevelCheckBox,screen,xplace+50+i*40,yplace+150);
+ if (player1Speed==i)
+ DrawIMG(iLevelCheck,screen,xplace+50+i*40,yplace+150);
+ }
+ for (int i=0; i<5;i++)
+ {
+ char levelS[2]; //level string;
+ levelS[0]='1'+i;
+ levelS[1]=0;
+ SFont_Write(screen,fBlueFont,xplace+300+50+i*40,yplace+110,levelS);
+ DrawIMG(iLevelCheckBox,screen,xplace+300+50+i*40,yplace+150);
+ if (player2Speed==i)
+ DrawIMG(iLevelCheck,screen,xplace+300+50+i*40,yplace+150);
+ }
+ SFont_Write(screen,fBlueFont,xplace+50,yplace+200,"AI: ");
+ DrawIMG(iLevelCheckBox,screen,xplace+50+70,yplace+200);
+ if (player1AI)
+ DrawIMG(iLevelCheck,screen,xplace+50+70,yplace+200);
+ SFont_Write(screen,fBlueFont,xplace+50,yplace+250,"TT Handicap: ");
+ SFont_Write(screen,fBlueFont,xplace+50+300,yplace+200,"AI: ");
+ DrawIMG(iLevelCheckBox,screen,xplace+50+70+300,yplace+200);
+ if (player2AI)
+ DrawIMG(iLevelCheck,screen,xplace+50+70+300,yplace+200);
+ SFont_Write(screen,fBlueFont,xplace+50+300,yplace+250,"TT Handicap: ");
+ for (int i=0; i<5;i++)
+ {
+ char levelS[2]; //level string;
+ levelS[0]='1'+i;
+ levelS[1]=0;
+ SFont_Write(screen,fBlueFont,xplace+50+i*40,yplace+290,levelS);
+ DrawIMG(iLevelCheckBox,screen,xplace+50+i*40,yplace+330);
+ if (player1handicap==i)
+ DrawIMG(iLevelCheck,screen,xplace+50+i*40,yplace+330);
+ }
+ for (int i=0; i<5;i++)
+ {
+ char levelS[2]; //level string;
+ levelS[0]='1'+i;
+ levelS[1]=0;
+ SFont_Write(screen,fBlueFont,xplace+50+i*40+300,yplace+290,levelS);
+ DrawIMG(iLevelCheckBox,screen,xplace+50+i*40+300,yplace+330);
+ if (player2handicap==i)
+ DrawIMG(iLevelCheck,screen,xplace+50+i*40+300,yplace+330);
+ }
+
+ SDL_Event event;
+ while ( SDL_PollEvent(&event) )
+ if ( event.type == SDL_KEYDOWN )
+ {
+ if ( event.key.keysym.sym == SDLK_ESCAPE ) {
+ done = true;
+ }
+ if ( event.key.keysym.sym == SDLK_RETURN ) {
+ done = true;
+ }
+ if ( event.key.keysym.sym == SDLK_KP_ENTER ) {
+ done = true;
+ }
+ }
+
+ keys = SDL_GetKeyState(NULL);
+
+ SDL_GetMouseState(&mousex,&mousey);
+
+ // If the mouse button is released, make bMouseUp equal true
+ if (!SDL_GetMouseState(NULL, NULL)&SDL_BUTTON(1))
+ {
+ bMouseUp=true;
+ }
+
+ if (SDL_GetMouseState(NULL,NULL)&SDL_BUTTON(1) && bMouseUp)
+ {
+ bMouseUp = false;
+
+ if ((mousex>xplace+50+70)&&(mousey>yplace+200)&&(mousex<xplace+50+70+30)&&(mousey<yplace+200+30))
+ player1AI=!player1AI;
+ if ((mousex>xplace+50+70+300)&&(mousey>yplace+200)&&(mousex<xplace+50+70+30+300)&&(mousey<yplace+200+30))
+ player2AI=!player2AI;
+ for (int i=0; i<5;i++)
+ {
+ if ((mousex>xplace+50+i*40)&&(mousex<xplace+50+i*40+30)&&(mousey>yplace+150)&&(mousey<yplace+150+30))
+ player1Speed=i;
+ }
+ for (int i=0; i<5;i++)
+ {
+ if ((mousex>xplace+50+i*40+300)&&(mousex<xplace+50+i*40+30+300)&&(mousey>yplace+150)&&(mousey<yplace+150+30))
+ player2Speed=i;
+ }
+ for (int i=0; i<5;i++)
+ {
+ if ((mousex>xplace+50+i*40)&&(mousex<xplace+50+i*40+30)&&(mousey>yplace+330)&&(mousey<yplace+330+30))
+ player1handicap=i;
+ }
+ for (int i=0; i<5;i++)
+ {
+ if ((mousex>xplace+50+i*40+300)&&(mousex<xplace+50+i*40+30+300)&&(mousey>yplace+330)&&(mousey<yplace+330+30))
+ player2handicap=i;
+ }
+ if ((mousex>1024/2-120/2)&&(mousex<1024/2+120/2)&&(mousey>600)&&(mousey<640))
+ done = true;
+ }
+
+ DrawIMG(mouse,screen,mousex,mousey);
+ SDL_Flip(screen); //draws it all to the screen
+ SDL_Delay(10);
+
+ } while (!done);
+ DrawIMG(background, screen, 0, 0);
+}
+
+//This function will promt for the user to select another file for puzzle mode
+void changePuzzleLevels()
+{
+ char theFileName[30];
+ strcpy(theFileName,puzzleName.c_str());
+ for (int i=puzzleName.length();i<30;i++)
+ theFileName[i]=' ';
+ theFileName[29]=0;
+ if (OpenFileDialogbox(200,100,theFileName))
+ {
+ for (int i=28;((theFileName[i]==' ')&&(i>0));i--)
+ theFileName[i]=0;
+ puzzleName = theFileName;
+#if defined(__unix__)
+ string home = getenv("HOME");
+ puzzleSavePath = home+"/.gamesaves/blockattack/"+puzzleName+".save";
+#elif defined(_WIN32)
+ string home = getMyDocumentsPath();
+ if (&home!=NULL)
+ {
+ puzzleSavePath = home+"/My Games/blockattack/"+puzzleName+".save";
+ }
+ else
+ {
+ puzzleSavePath = puzzleName+".save";
+ }
+#else
+ puzzleSavePath = puzzleName+".save";
+#endif
+ }
+
+}
+
+#ifdef NETWORK
+#include "NetworkThing.hpp"
+#endif
+
+//#include "editor/editorMain.hpp"
+
+//The main function, quite big... too big
+int main(int argc, char *argv[])
+{
+ //We first create the folder there we will save (only on UNIX systems)
+ //we call the external command "mkdir"... the user might have renamed this, but we hope he hasn't
+#if defined(__unix__)
+ system("mkdir -p ~/.gamesaves/blockattack/screenshots");
+ system("mkdir -p ~/.gamesaves/blockattack/replays");
+ system("mkdir -p ~/.gamesaves/blockattack/puzzles");
+#elif defined(_WIN32)
+ //Now for Windows NT/2k/xp/2k3 etc.
+ string tempA = getMyDocumentsPath()+"\\My Games";
+ CreateDirectory(tempA.c_str(),NULL);//system(tempA.c_str());
+ tempA = getMyDocumentsPath()+"\\My Games\\blockattack";
+ CreateDirectory(tempA.c_str(),NULL);//system(tempA.c_str());
+ tempA = getMyDocumentsPath()+"\\My Games\\blockattack\\replays";
+ CreateDirectory(tempA.c_str(),NULL);//system(tempA.c_str());
+ tempA = getMyDocumentsPath()+"\\My Games\\blockattack\\screenshots";
+ CreateDirectory(tempA.c_str(),NULL);//system(tempA.c_str());
+#endif
+ bool highPriority = false; //if true the game will take most resources, but increase framerate.
+ bFullscreen = false;
+ if (argc > 1)
+ {
+ int argumentNr = 1;
+ forceredraw = 2;
+ while (argc>argumentNr)
+ {
+ char helpString[] = "--help";
+ char priorityString[] = "-priority";
+ char forceRedrawString[] = "-forceredraw";
+ char forcepartdrawString[] = "-forcepartdraw";
+ char singlePuzzleString[] = "-SP";
+ char noSoundAtAll[] = "-nosound";
+ char IntegratedEditor[] = "-editor";
+ if (!(strncmp(argv[argumentNr],helpString,6)))
+ {
+ cout << "Block Attack Help" << endl << "--help Display this message" <<
+ endl << "-priority Starts game in high priority" << endl <<
+ "-forceredraw Redraw the whole screen every frame, prevents garbage" << endl <<
+ "-forcepartdraw Only draw what is changed, sometimes cause garbage" << endl <<
+ "-nosound No sound will be played at all, and sound hardware want be loaded (use this if game crashes because of sound)" << endl <<
+ "-editor Starts the build-in editor (not yet integrated)" << endl;
+#ifdef WIN32
+ system("Pause");
+#endif
+ return 0;
+ }
+ if (!(strncmp(argv[argumentNr],priorityString,9)))
+ {
+ cout << "Priority mode" << endl;
+ highPriority = true;
+ }
+ if (!(strncmp(argv[argumentNr],forceRedrawString,12)))
+ {
+ forceredraw = 1;
+ }
+ if (!(strncmp(argv[argumentNr],forcepartdrawString,14)))
+ {
+ forceredraw = 2;
+ }
+ if (!(strncmp(argv[argumentNr],singlePuzzleString,3)))
+ {
+ singlePuzzle = true; //We will just have one puzzle
+ if (argv[argumentNr+1][1]!=0)
+ singlePuzzleNr = (argv[argumentNr+1][1]-'0')+(argv[argumentNr+1][0]-'0')*10;
+ else
+ singlePuzzleNr = (argv[argumentNr+1][0]-'0');
+ singlePuzzleFile = argv[argumentNr+2];
+ argumentNr+=2;
+ cout << "SinglePuzzleMode, File: " << singlePuzzleFile << " and Level: " << singlePuzzleNr << endl;
+ }
+ if (!(strncmp(argv[argumentNr],noSoundAtAll,8)))
+ {
+ NoSound = true;
+ }
+ if (!(strncmp(argv[argumentNr],IntegratedEditor,7)))
+ {
+ editorMode = true;
+ cout << "Integrated Puzzle Editor Activated" << endl;
+ }
+ argumentNr++;
+ } //while
+ } //if
+
+ SoundEnabled = true;
+ MusicEnabled = true;
+ xsize = 1024; //screen size x
+ int ysize = 768; //screen size y
+ int mousex, mousey; //Mouse coordinates
+ showHighscores = false;
+ showEndless = true;
+ showOptions = false;
+ b1playerOpen = false;
+ b2playersOpen = false;
+ bReplayOpen = false;
+ bScreenLocked = false;
+ bool twoPlayers = false; //true if two players splitscreen
+ bool vsMode = false;
+ theTopScoresEndless = Highscore(1);
+ theTopScoresTimeTrial = Highscore(2);
+ drawBalls = true;
+ puzzleLoaded = false;
+ bool weWhereConnected = false;
+
+ //Things used for repeating keystrokes:
+ bool repeatingP1N = false; //The key is being held
+ bool repeatingP1S = false; //The key is being held
+ bool repeatingP1W = false; //The key is being held
+ bool repeatingP1E = false; //The key is being held
+ bool repeatingP2N = false; //The key is being held
+ bool repeatingP2S = false; //The key is being held
+ bool repeatingP2W = false; //The key is being held
+ bool repeatingP2E = false; //The key is being held
+ const int startRepeat = 200;
+ const int repeatDelay = 100; //Repeating
+ unsigned long timeHeldP1N = 0;
+ unsigned long timeHeldP1S = 0;
+ unsigned long timeHeldP1E = 0;
+ unsigned long timeHeldP1W = 0;
+ unsigned long timeHeldP2N = 0;
+ unsigned long timeHeldP2S = 0;
+ unsigned long timeHeldP2E = 0;
+ unsigned long timeHeldP2W = 0;
+ unsigned long timesRepeatedP1N = 0;
+ unsigned long timesRepeatedP1S = 0;
+ unsigned long timesRepeatedP1E = 0;
+ unsigned long timesRepeatedP1W = 0;
+ unsigned long timesRepeatedP2N = 0;
+ unsigned long timesRepeatedP2S = 0;
+ unsigned long timesRepeatedP2E = 0;
+ unsigned long timesRepeatedP2W = 0;
+
+ theBallManeger = ballManeger();
+ theExplosionManeger = explosionManeger();
+
+//We now set the paths were we are saving, we are using the keyword __unix__ . I hope that all UNIX systems has a home folder
+#if defined(__unix__)
+ string home = getenv("HOME");
+ string optionsPath = home+"/.gamesaves/blockattack/options.dat";
+#elif defined(_WIN32)
+ string home = getMyDocumentsPath();
+ string optionsPath;
+ if (&home!=NULL) //Null if no APPDATA dir exists (win 9x)
+ optionsPath = home+"/My Games/blockattack/options.dat";
+ else
+ optionsPath = "options.dat";
+#else
+ string optionsPath = "options.dat";
+#endif
+
+#if defined(__unix__)
+ stageClearSavePath = home+"/.gamesaves/blockattack/stageClear.SCsave";
+ puzzleSavePath = home+"/.gamesaves/blockattack/puzzle.levels.save";
+#elif defined(_WIN32)
+ if (&home!=NULL)
+ {
+ stageClearSavePath = home+"/My Games/blockattack/stageClear.SCsave";
+ puzzleSavePath = home+"/My Games/blockattack/puzzle.levels.save";
+ }
+ else
+ {
+ stageClearSavePath = "stageClear.SCsave";
+ puzzleSavePath = "puzzle.levels.save";
+ }
+#else
+ stageClearSavePath = "stageClear.SCsave";
+ puzzleSavePath = "puzzle.levels.save";
+#endif
+ puzzleName="puzzle.levels";
+
+ Uint8 *keys;
+
+ //Init SDL
+ if ( SDL_Init(SDL_INIT_VIDEO) < 0 )
+ {
+ cout << "Unable to init SDL: " << SDL_GetError() << endl;
+ exit(1);
+ }
+ atexit(SDL_Quit); //quits SDL when the game stops for some reason (like you hit exit or Esc)
+
+ SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
+
+ Joypad_init(); //Prepare the joysticks
+
+ Joypad joypad1 = Joypad(); //Creates a joypad
+ Joypad joypad2 = Joypad(); //Creates a joypad
+
+ theTextManeger = textManeger();
+
+ //Open Audio
+ if (!NoSound) //If sound has not been disabled, then load the sound system
+ if (Mix_OpenAudio(44100, AUDIO_S16SYS, 2, 2048) < 0)
+ {
+ cout << "Warning: Couldn't set 44100 Hz 16-bit audio - Reason: " << SDL_GetError() << endl
+ << "Sound will be disabled!" << endl;
+ NoSound = true; //Tries to stop all sound from playing/loading
+ }
+
+ SDL_WM_SetCaption("Block Attack - Rise of the Blocks", NULL); //Sets title line
+ //Now sets the icon:
+ SDL_Surface *icon = IMG_Load2((char*)"gfx/icon.png");
+ SDL_WM_SetIcon(icon,NULL);
+ //SDL_FreeSurface(icon);
+
+ //Copyright notice:
+ cout << "Block Attack - Rise of the Blocks (" << VERSION_NUMBER << ")" << endl << "http://blockattack.sf.net" << endl << "Copyright 2004-2007 Poul Sander" << endl <<
+ "A SDL based game (see www.libsdl.org)" << endl <<
+ "The game is availeble under the GPL, see COPYING for details." << endl;
+#if defined(_WIN32)
+ cout << "Windows build" << endl;
+#elif defined(__linux__)
+ cout << "Linux build" << endl;
+#elif defined(__unix__)
+ cout << "Unix build" << endl;
+#else
+ cout << "Alternative build" << endl;
+#endif
+ cout << "-------------------------------------------" << endl;
+
+ keySettings[0].up= SDLK_UP;
+ keySettings[0].down = SDLK_DOWN;
+ keySettings[0].left = SDLK_LEFT;
+ keySettings[0].right = SDLK_RIGHT;
+ keySettings[0].change = SDLK_KP_ENTER;
+ keySettings[0].push = SDLK_KP0;
+
+ keySettings[2].up= SDLK_w;
+ keySettings[2].down = SDLK_s;
+ keySettings[2].left = SDLK_a;
+ keySettings[2].right = SDLK_d;
+ keySettings[2].change = SDLK_LCTRL;
+ keySettings[2].push = SDLK_LSHIFT;
+
+ player1keys=0;
+ player2keys=2;
+
+ strcpy(player1name, "Player 1 \0");
+ strcpy(player2name, "Player 2 \0");
+
+#ifdef NETWORK
+ strcpy(serverAddress, "192.168.0.2 \0");
+#endif
+
+ //Reads options from file:
+ ifstream optionsFile(optionsPath.c_str(), ios::binary);
+ if (optionsFile)
+ {
+ //reads data: xsize,ysize,fullescreen, player1keys, player2keys, MusicEnabled, SoundEnabled,player1name,player2name
+ optionsFile.read(reinterpret_cast<char*>(&xsize), sizeof(int));
+ optionsFile.read(reinterpret_cast<char*>(&ysize), sizeof(int));
+ optionsFile.read(reinterpret_cast<char*>(&bFullscreen), sizeof(bool));
+ optionsFile.read(reinterpret_cast<char*>(&keySettings[0].up), sizeof(SDLKey));
+ optionsFile.read(reinterpret_cast<char*>(&keySettings[0].down), sizeof(SDLKey));
+ optionsFile.read(reinterpret_cast<char*>(&keySettings[0].left), sizeof(SDLKey));
+ optionsFile.read(reinterpret_cast<char*>(&keySettings[0].right), sizeof(SDLKey));
+ optionsFile.read(reinterpret_cast<char*>(&keySettings[0].change), sizeof(SDLKey));
+ optionsFile.read(reinterpret_cast<char*>(&keySettings[0].push), sizeof(SDLKey));
+ optionsFile.read(reinterpret_cast<char*>(&keySettings[2].up), sizeof(SDLKey));
+ optionsFile.read(reinterpret_cast<char*>(&keySettings[2].down), sizeof(SDLKey));
+ optionsFile.read(reinterpret_cast<char*>(&keySettings[2].left), sizeof(SDLKey));
+ optionsFile.read(reinterpret_cast<char*>(&keySettings[2].right), sizeof(SDLKey));
+ optionsFile.read(reinterpret_cast<char*>(&keySettings[2].change), sizeof(SDLKey));
+ optionsFile.read(reinterpret_cast<char*>(&keySettings[2].push), sizeof(SDLKey));
+ optionsFile.read(reinterpret_cast<char*>(&MusicEnabled), sizeof(bool));
+ optionsFile.read(reinterpret_cast<char*>(&SoundEnabled), sizeof(bool));
+ optionsFile.read(player1name, 30*sizeof(char));
+ optionsFile.read(player2name, 30*sizeof(char));
+ //mouseplay?
+ if (!optionsFile.eof())
+ {
+ optionsFile.read(reinterpret_cast<char*>(&mouseplay1), sizeof(bool));
+ optionsFile.read(reinterpret_cast<char*>(&mouseplay2), sizeof(bool));
+ optionsFile.read(reinterpret_cast<char*>(&joyplay1),sizeof(bool));
+ optionsFile.read(reinterpret_cast<char*>(&joyplay2),sizeof(bool));
+ }
+ optionsFile.close();
+ cout << "Data loaded from options file" << endl;
+ }
+ else
+ {
+ cout << "Unable to load options file, using default values" << endl;
+ }
+
+ xsize = 1024;
+ ysize = 768;
+ if (singlePuzzle)
+ {
+ xsize=300;
+ ysize=600;
+ }
+
+
+ //Open video
+ if ((bFullscreen)&&(!singlePuzzle)) screen=SDL_SetVideoMode(xsize,ysize,32,SDL_SWSURFACE|SDL_FULLSCREEN|SDL_ANYFORMAT);
+ else screen=SDL_SetVideoMode(xsize,ysize,32,SDL_SWSURFACE|SDL_ANYFORMAT);
+
+ if ( screen == NULL )
+ {
+ cout << "Unable to set " << xsize << "x" << ysize << " video: " << SDL_GetError() << endl;
+ exit(1);
+ }
+
+ //Loading all images into memory
+ InitImages();
+
+ cout << "Images loaded" << endl;
+
+
+ BlockGame theGame = BlockGame(50,100); //creates game objects
+ BlockGame theGame2 = BlockGame(xsize-500,100);
+ if (singlePuzzle)
+ {
+ theGame.topy=0;
+ theGame.topx=0;
+ theGame2.topy=10000;
+ theGame2.topx=10000;
+ }
+ theGame.DoPaintJob(); //Makes sure what there is something to paint
+ theGame2.DoPaintJob();
+ theGame.SetGameOver(); //sets the game over in the beginning
+ theGame2.SetGameOver();
+
+
+ //Takes names from file instead
+ strcpy(theGame.name, player1name);
+ strcpy(theGame2.name, player2name);
+
+ //Keeps track of background;
+ int nowTime=SDL_GetTicks();
+
+
+#ifdef NETWORK
+ NetworkThing nt = NetworkThing();
+ nt.setBGpointers(&theGame,&theGame2);
+#endif
+
+ if (singlePuzzle)
+ {
+ LoadPuzzleStages();
+ theGame.NewPuzzleGame(singlePuzzleNr,0,0);
+ showGame = true;
+ vsMode = true;
+ }
+ //Draws everything to screen
+ if (!editorMode)
+ MakeBackground(xsize,ysize,theGame,theGame2);
+ else
+ MakeBackground(xsize,ysize,theGame);
+ DrawIMG(background, screen, 0, 0);
+ DrawEverything(xsize,ysize,theGame,theGame2);
+ SDL_Flip(screen);
+ //game loop
+ int done = 0;
+ cout << "Starting game loop" << endl;
+ while (done == 0)
+ {
+ if (!(highPriority)) SDL_Delay(10);
+
+ if ((standardBackground)&&(!editorMode))
+ {
+ MakeBackground(xsize,ysize,theGame,theGame2);
+ DrawIMG(background, screen, 0, 0);
+ }
+
+ if ((standardBackground)&&(editorMode))
+ {
+ DrawIMG(backgroundImage, screen, 0, 0);
+ MakeBackground(xsize,ysize,theGame);
+ DrawIMG(background, screen, 0, 0);
+ }
+
+ //updates the balls and explosions:
+ theBallManeger.update();
+ theExplosionManeger.update();
+ theTextManeger.update();
+
+#ifdef NETWORK
+ if (nt.isConnected())
+ {
+ nt.updateNetwork();
+ networkActive = true;
+ if (!nt.isConnectedToPeer())
+ DrawIMG(background, screen, 0, 0);
+ }
+ else
+ networkActive = false;
+ if (nt.isConnectedToPeer())
+ {
+ networkPlay=true;
+ if (!weWhereConnected) //We have just connected
+ {
+ theGame.NewVsGame(50,100,&theGame2);
+ theGame.putStartBlocks(nt.theSeed);
+ theGame2.playNetwork(xsize-500,100);
+ nt.theGameHasStarted();
+ DrawIMG(background, screen, 0, 0);
+ }
+ weWhereConnected = true;
+ }
+ else
+ {
+ networkPlay=false;
+ weWhereConnected = false;
+ }
+#endif
+
+ if (!bScreenLocked)
+ {
+ SDL_Event event;
+
+ while ( SDL_PollEvent(&event) )
+ {
+ if ( event.type == SDL_QUIT ) {
+ done = 1;
+ }
+
+ if ( event.type == SDL_KEYDOWN )
+ {
+ if ( event.key.keysym.sym == SDLK_ESCAPE )
+ {
+ if (showHighscores)
+ {
+ showHighscores = false;
+ }
+ else
+ if (showOptions)
+ {
+ showOptions = false;
+ }
+ else
+ done=1;
+ DrawIMG(background, screen, 0, 0);
+
+ }
+ if ((!editorMode)&&(!editorModeTest)&&(!theGame.AI_Enabled))
+ {
+ //player1:
+ if ( event.key.keysym.sym == keySettings[player1keys].up ) {
+ theGame.MoveCursor('N');
+ repeatingP1N=true;
+ timeHeldP1N=SDL_GetTicks();
+ timesRepeatedP1N=0;
+ }
+ if ( event.key.keysym.sym == keySettings[player1keys].down ) {
+ theGame.MoveCursor('S');
+ repeatingP1S=true;
+ timeHeldP1S=SDL_GetTicks();
+ timesRepeatedP1S=0;
+ }
+ if ( (event.key.keysym.sym == keySettings[player1keys].left) && (showGame) ) {
+ theGame.MoveCursor('W');
+ repeatingP1W=true;
+ timeHeldP1W=SDL_GetTicks();
+ timesRepeatedP1W=0;
+ }
+ if ( (event.key.keysym.sym == keySettings[player1keys].right) && (showGame) ) {
+ theGame.MoveCursor('E');
+ repeatingP1E=true;
+ timeHeldP1E=SDL_GetTicks();
+ timesRepeatedP1E=0;
+ }
+ if ( event.key.keysym.sym == keySettings[player1keys].push ) {
+ theGame.PushLine();
+ }
+ if ( event.key.keysym.sym == keySettings[player1keys].change ) {
+ theGame.SwitchAtCursor();
+ }
+ }
+ if (!editorMode && !theGame2.AI_Enabled)
+ {
+ //player2:
+ if ( event.key.keysym.sym == keySettings[player2keys].up ) {
+ theGame2.MoveCursor('N');
+ repeatingP2N=true;
+ timeHeldP2N=SDL_GetTicks();
+ timesRepeatedP2N=0;
+ }
+ if ( event.key.keysym.sym == keySettings[player2keys].down ) {
+ theGame2.MoveCursor('S');
+ repeatingP2S=true;
+ timeHeldP2S=SDL_GetTicks();
+ timesRepeatedP2S=0;
+ }
+ if ( (event.key.keysym.sym == keySettings[player2keys].left) && (showGame) ) {
+ theGame2.MoveCursor('W');
+ repeatingP2W=true;
+ timeHeldP2W=SDL_GetTicks();
+ timesRepeatedP2W=0;
+ }
+ if ( (event.key.keysym.sym == keySettings[player2keys].right) && (showGame) ) {
+ theGame2.MoveCursor('E');
+ repeatingP2E=true;
+ timeHeldP2E=SDL_GetTicks();
+ timesRepeatedP2E=0;
+ }
+ if ( event.key.keysym.sym == keySettings[player2keys].push ) {
+ theGame2.PushLine();
+ }
+ if ( event.key.keysym.sym == keySettings[player2keys].change ) {
+ theGame2.SwitchAtCursor();
+ }
+ }
+ //common:
+ if ((!singlePuzzle)&&(!editorMode))
+ {
+ if ( ((event.key.keysym.sym == SDLK_LEFT)||(event.key.keysym.sym == SDLK_RIGHT)) && (showHighscores) ) {
+ showEndless = !showEndless;
+ }
+
+ if ( event.key.keysym.sym == SDLK_F2 ) {
+ if ((!showHighscores)&&(!showOptions)&&(!networkActive)){
+ theGame.NewGame(50,100);
+ theGame.timetrial = false;
+ theGame.putStartBlocks();
+ closeAllMenus();
+ twoPlayers =false;
+ theGame2.SetGameOver();
+ showGame = true;
+ vsMode = false;
+ }}
+ if ( event.key.keysym.sym == SDLK_F3 ) {
+ if ((!showHighscores)&&(!showOptions)&&(!networkActive)){
+ theGame.NewGame(50,100);
+ theGame.timetrial = true;
+ theGame.putStartBlocks();
+ closeAllMenus();
+ twoPlayers =false;
+ theGame2.SetGameOver();
+ showGame = true;
+ vsMode = false;
+ }}
+ if ( event.key.keysym.sym == SDLK_F5 )
+ {
+ if ((!showHighscores)&&(!showOptions)&&(!networkActive))
+ {
+ int myLevel = StageLevelSelect();
+ theGame.NewStageGame(myLevel,50,100);
+ MakeBackground(xsize,ysize,theGame,theGame2);
+ DrawIMG(background, screen, 0, 0);
+ closeAllMenus();
+ twoPlayers =false;
+ theGame2.SetGameOver();
+ showGame = true;
+ vsMode = false;
+ }
+ }
+ if ( event.key.keysym.sym == SDLK_F6 )
+ {
+ if ((!showHighscores)&&(!showOptions)&&(!networkActive))
+ {
+ theGame.NewVsGame(50,100,&theGame2);
+ theGame2.NewVsGame(xsize-500,100,&theGame);
+ closeAllMenus();
+ vsMode = true;
+ theGame.setGameSpeed(player1Speed);
+ theGame2.setGameSpeed(player2Speed);
+ theGame.setHandicap(player1handicap);
+ theGame2.setHandicap(player2handicap);
+ theGame.AI_Enabled = player1AI;
+ theGame2.AI_Enabled = player2AI;
+ theGame.setAIlevel(player1AIlevel);
+ theGame2.setAIlevel(player2AIlevel);
+ int theTime = time(0);
+ theGame.putStartBlocks(theTime);
+ theGame2.putStartBlocks(theTime);
+ twoPlayers = true;
+ }
+ }
+ if ( event.key.keysym.sym == SDLK_F4 )
+ {
+ if ((!showHighscores)&&(!showOptions)&&(!networkActive))
+ {
+ theGame.NewGame(50,100);
+ theGame2.NewGame(xsize-500,100);
+ theGame.timetrial = true;
+ theGame2.timetrial = true;
+ int theTime = time(0);
+ theGame.putStartBlocks(theTime);
+ theGame2.putStartBlocks(theTime);
+ closeAllMenus();
+ twoPlayers = true;
+ theGame.setGameSpeed(player1Speed);
+ theGame2.setGameSpeed(player2Speed);
+ theGame.setHandicap(player1handicap);
+ theGame2.setHandicap(player2handicap);
+ theGame.AI_Enabled = player1AI;
+ theGame2.AI_Enabled = player2AI;
+ theGame.setAIlevel(player1AIlevel);
+ theGame2.setAIlevel(player2AIlevel);
+ }
+ }
+ if ( event.key.keysym.sym == SDLK_F7 )
+ {
+ if ((!showHighscores)&&(!showOptions)&&(!networkActive))
+ {
+ int myLevel = PuzzleLevelSelect();
+ theGame.NewPuzzleGame(myLevel,50,100);
+ MakeBackground(xsize,ysize,theGame,theGame2);
+ DrawIMG(background, screen, 0, 0);
+ closeAllMenus();
+ twoPlayers = false;
+ theGame2.SetGameOver();
+ showGame = true;
+ vsMode = true;
+ }
+ }
+ if ( event.key.keysym.sym == SDLK_F8 )
+ {
+ if ((!showGame)&&(!showOptions)&&(!networkActive))
+ if (!showHighscores)
+ {
+ closeAllMenus();
+ showHighscores = true;
+ MakeBackground(xsize,ysize,theGame,theGame2);
+ DrawIMG(background, screen, 0, 0);
+ closeAllMenus();
+ theGame2.SetGameOver();
+ }
+ else
+ {
+ showEndless = !showEndless;
+ }
+ }
+ if ( event.key.keysym.sym == SDLK_F9 ) {
+ writeScreenShot();
+ }
+ if ( event.key.keysym.sym == SDLK_F11 ) {
+ /*This is the test place, place function to test here*/
+
+ //theGame.CreateGreyGarbage();
+ char mitNavn[30];
+ SelectThemeDialogbox(300,400,mitNavn);
+ } //F11
+ }
+ if ( event.key.keysym.sym == SDLK_F12 ) {
+ done=1;
+ }
+ }
+ } //while event PollEvent - read keys
+
+ /**********************************************************************
+ **************************** Repeating start **************************
+ **********************************************************************/
+
+ keys = SDL_GetKeyState(NULL);
+//Also the joysticks:
+//Repeating not implemented
+
+//Player 1 start
+ if (!(keys[keySettings[player1keys].up]))
+ repeatingP1N=false;
+ while ((repeatingP1N)&&(keys[keySettings[player1keys].up])&&(SDL_GetTicks()>timeHeldP1N+timesRepeatedP1N*repeatDelay+startRepeat))
+ {
+ theGame.MoveCursor('N');
+ timesRepeatedP1N++;
+ }
+
+ if (!(keys[keySettings[player1keys].down]))
+ repeatingP1S=false;
+ while ((repeatingP1S)&&(keys[keySettings[player1keys].down])&&(SDL_GetTicks()>timeHeldP1S+timesRepeatedP1S*repeatDelay+startRepeat))
+ {
+ theGame.MoveCursor('S');
+ timesRepeatedP1S++;
+ }
+
+ if (!(keys[keySettings[player1keys].left]))
+ repeatingP1W=false;
+ while ((repeatingP1W)&&(keys[keySettings[player1keys].left])&&(SDL_GetTicks()>timeHeldP1W+timesRepeatedP1W*repeatDelay+startRepeat))
+ {
+ timesRepeatedP1W++;
+ theGame.MoveCursor('W');
+ }
+
+ if (!(keys[keySettings[player1keys].right]))
+ repeatingP1E=false;
+ while ((repeatingP1E)&&(keys[keySettings[player1keys].right])&&(SDL_GetTicks()>timeHeldP1E+timesRepeatedP1E*repeatDelay+startRepeat))
+ {
+ timesRepeatedP1E++;
+ theGame.MoveCursor('E');
+ }
+
+//Player 1 end
+
+//Player 2 start
+ if (!(keys[keySettings[player2keys].up]))
+ repeatingP2N=false;
+ while ((repeatingP2N)&&(keys[keySettings[player2keys].up])&&(SDL_GetTicks()>timeHeldP2N+timesRepeatedP2N*repeatDelay+startRepeat))
+ {
+ theGame2.MoveCursor('N');
+ timesRepeatedP2N++;
+ }
+
+ if (!(keys[keySettings[player2keys].down]))
+ repeatingP2S=false;
+ while ((repeatingP2S)&&(keys[keySettings[player2keys].down])&&(SDL_GetTicks()>timeHeldP2S+timesRepeatedP2S*repeatDelay+startRepeat))
+ {
+ theGame2.MoveCursor('S');
+ timesRepeatedP2S++;
+ }
+
+ if (!(keys[keySettings[player2keys].left]))
+ repeatingP2W=false;
+ while ((repeatingP2W)&&(keys[keySettings[player2keys].left])&&(SDL_GetTicks()>timeHeldP2W+timesRepeatedP2W*repeatDelay+startRepeat))
+ {
+ theGame2.MoveCursor('W');
+ timesRepeatedP2W++;
+ }
+
+ if (!(keys[keySettings[player2keys].right]))
+ repeatingP2E=false;
+ while ((repeatingP2E)&&(keys[keySettings[player2keys].right])&&(SDL_GetTicks()>timeHeldP2E+timesRepeatedP2E*repeatDelay+startRepeat))
+ {
+ theGame2.MoveCursor('E');
+ timesRepeatedP2E++;
+ }
+
+//Player 2 end
+
+ /**********************************************************************
+ **************************** Repeating end ****************************
+ **********************************************************************/
+
+ /**********************************************************************
+ ***************************** Joypad start ****************************
+ **********************************************************************/
+
+ if (joyplay1||joyplay2)
+ {
+ if (joypad1.working && !theGame.AI_Enabled)
+ if (joyplay1)
+ {
+ joypad1.update();
+ if (joypad1.up)
+ {
+ theGame.MoveCursor('N');
+ repeatingP1N=true;
+ timeHeldP1N=SDL_GetTicks();
+ timesRepeatedP1N=0;
+ }
+ if (joypad1.down)
+ {
+ theGame.MoveCursor('S');
+ repeatingP1S=true;
+ timeHeldP1S=SDL_GetTicks();
+ timesRepeatedP1S=0;
+ }
+ if (joypad1.left)
+ {
+ theGame.MoveCursor('W');
+ repeatingP1W=true;
+ timeHeldP1W=SDL_GetTicks();
+ timesRepeatedP1W=0;
+ }
+ if (joypad1.right)
+ {
+ theGame.MoveCursor('E');
+ repeatingP1E=true;
+ timeHeldP1E=SDL_GetTicks();
+ timesRepeatedP1E=0;
+ }
+ if (joypad1.but1)
+ theGame.SwitchAtCursor();
+ if (joypad1.but2)
+ theGame.PushLine();
+ }
+ else
+ {
+ joypad1.update();
+ if (joypad1.up)
+ {
+ theGame2.MoveCursor('N');
+ repeatingP2N=true;
+ timeHeldP2N=SDL_GetTicks();
+ timesRepeatedP2N=0;
+ }
+ if (joypad1.down)
+ {
+ theGame2.MoveCursor('S');
+ repeatingP2S=true;
+ timeHeldP2S=SDL_GetTicks();
+ timesRepeatedP2S=0;
+ }
+ if (joypad1.left)
+ {
+ theGame2.MoveCursor('W');
+ repeatingP2W=true;
+ timeHeldP2W=SDL_GetTicks();
+ timesRepeatedP2W=0;
+ }
+ if (joypad1.right)
+ {
+ theGame2.MoveCursor('E');
+ repeatingP2E=true;
+ timeHeldP2E=SDL_GetTicks();
+ timesRepeatedP2E=0;
+ }
+ if (joypad1.but1)
+ theGame2.SwitchAtCursor();
+ if (joypad1.but2)
+ theGame2.PushLine();
+ }
+ if (joypad2.working && !theGame2.AI_Enabled)
+ if (!joyplay2)
+ {
+ joypad2.update();
+ if (joypad2.up)
+ {
+ theGame.MoveCursor('N');
+ repeatingP1N=true;
+ timeHeldP1N=SDL_GetTicks();
+ timesRepeatedP1N=0;
+ }
+ if (joypad2.down)
+ {
+ theGame.MoveCursor('S');
+ repeatingP1S=true;
+ timeHeldP1S=SDL_GetTicks();
+ timesRepeatedP1S=0;
+ }
+ if (joypad2.left)
+ {
+ theGame.MoveCursor('W');
+ repeatingP1W=true;
+ timeHeldP1W=SDL_GetTicks();
+ timesRepeatedP1W=0;
+ }
+ if (joypad2.right)
+ {
+ theGame.MoveCursor('E');
+ repeatingP1E=true;
+ timeHeldP1E=SDL_GetTicks();
+ timesRepeatedP1E=0;
+ }
+ if (joypad2.but1)
+ theGame.SwitchAtCursor();
+ if (joypad2.but2)
+ theGame.PushLine();
+ }
+ else
+ {
+ joypad2.update();
+ if (joypad2.up)
+ {
+ theGame2.MoveCursor('N');
+ repeatingP2N=true;
+ timeHeldP2N=SDL_GetTicks();
+ timesRepeatedP2N=0;
+ }
+ if (joypad2.down)
+ {
+ theGame2.MoveCursor('S');
+ repeatingP2S=true;
+ timeHeldP2S=SDL_GetTicks();
+ timesRepeatedP2S=0;
+ }
+ if (joypad2.left)
+ {
+ theGame2.MoveCursor('W');
+ repeatingP2W=true;
+ timeHeldP2W=SDL_GetTicks();
+ timesRepeatedP2W=0;
+ }
+ if (joypad2.right)
+ {
+ theGame2.MoveCursor('E');
+ repeatingP2E=true;
+ timeHeldP2E=SDL_GetTicks();
+ timesRepeatedP2E=0;
+ }
+ if (joypad2.but1)
+ theGame2.SwitchAtCursor();
+ if (joypad2.but2)
+ theGame2.PushLine();
+ }
+ }
+
+ /**********************************************************************
+ ***************************** Joypad end ******************************
+ **********************************************************************/
+
+
+ keys = SDL_GetKeyState(NULL);
+
+ SDL_GetMouseState(&mousex,&mousey);
+
+ /********************************************************************
+ **************** Here comes mouse play ******************************
+ ********************************************************************/
+
+ if ((mouseplay1)&&((!editorMode)&&(!theGame.AI_Enabled)||(editorModeTest))) //player 1
+ if ((mousex > 50)&&(mousey>100)&&(mousex<50+300)&&(mousey<100+600))
+ {
+ int yLine, xLine;
+ yLine = ((100+600)-(mousey-100+theGame.pixels))/50;
+ xLine = (mousex-50+25)/50;
+ yLine-=2;
+ xLine-=1;
+ if ((yLine>10)&&(theGame.TowerHeight<12))
+ yLine=10;
+ if (((theGame.pixels==50)||(theGame.pixels==0)) && (yLine>11))
+ yLine=11;
+ if (yLine<0)
+ yLine=0;
+ if (xLine<0)
+ xLine=0;
+ if (xLine>4)
+ xLine=4;
+ theGame.cursorx=xLine;
+ theGame.cursory=yLine;
+ }
+
+ if ((mouseplay2)&&(!editorMode)&&(!theGame2.AI_Enabled)) //player 2
+ if ((mousex > xsize-500)&&(mousey>100)&&(mousex<xsize-500+300)&&(mousey<100+600))
+ {
+ int yLine, xLine;
+ yLine = ((100+600)-(mousey-100+theGame2.pixels))/50;
+ xLine = (mousex-(xsize-500)+25)/50;
+ yLine-=2;
+ xLine-=1;
+ if ((yLine>10)&&(theGame2.TowerHeight<12))
+ yLine=10;
+ if (((theGame2.pixels==50)||(theGame2.pixels==0)) && (yLine>11))
+ yLine=11;
+ if (yLine<0)
+ yLine=0;
+ if (xLine<0)
+ xLine=0;
+ if (xLine>4)
+ xLine=4;
+ theGame2.cursorx=xLine;
+ theGame2.cursory=yLine;
+ }
+
+ /********************************************************************
+ **************** Here ends mouse play *******************************
+ ********************************************************************/
+
+ // If the mouse button is released, make bMouseUp equal true
+ if (!SDL_GetMouseState(NULL, NULL)&SDL_BUTTON(1))
+ {
+ bMouseUp=true;
+ }
+
+ // If the mouse button 2 is released, make bMouseUp2 equal true
+ if ((SDL_GetMouseState(NULL, NULL)&SDL_BUTTON(3))!=SDL_BUTTON(3))
+ {
+ bMouseUp2=true;
+ }
+
+ if ((!singlePuzzle)&&(!editorMode))
+ {
+ //read mouse events
+ if (SDL_GetMouseState(NULL,NULL)&SDL_BUTTON(1) && bMouseUp)
+ {
+ bMouseUp = false;
+ DrawIMG(background, screen, 0, 0);
+ if ((0<mousex) && (mousex<120) && (0<mousey) && (mousey<40) &&(!networkActive) )
+ {
+ //New game clicked
+ bool state = (!bNewGameOpen);
+ closeAllMenus();
+ bNewGameOpen = state; //theGame.NewGame(50,100);
+ showOptions = false;
+ showHighscores = false;
+ }
+ else
+#ifdef NETWORK
+ if ((0<mousex) && (mousex<120) && (0<mousey) && (mousey<40) &&(networkActive))
+ {
+ //Disconnect clicked!
+ cout << "Disconnect clicked!" << endl;
+ nt.ntDisconnect();
+ }
+ else
+#endif
+ if ((0<mousex) && (mousex<120) && (40<mousey) && (mousey<80) && (bNewGameOpen) &&(!networkActive))
+ {
+ //1player
+ b1playerOpen = (!b1playerOpen);
+ b2playersOpen = false;
+#ifdef NETWORK
+ bNetworkOpen = false;
+#endif
+ }
+ else
+ if ((0<mousex) && (mousex<120) && (80<mousey) && (mousey<120) && (bNewGameOpen) &&(!networkActive))
+ {
+ //2player
+ b2playersOpen = (!b2playersOpen);
+ b1playerOpen = false;
+#ifdef NETWORK
+ bNetworkOpen = false;
+#endif
+ }
+#ifdef NETWORK
+ else
+ if ((0<mousex) && (mousex<120) && (120<mousey) && (mousey<160) && (bNewGameOpen) &&(!networkActive))
+ {
+ //Network
+ b1playerOpen = false;
+ b2playersOpen = false;
+ bNetworkOpen = (!bNetworkOpen);
+ }
+#endif
+ else
+ if ((120<mousex) && (mousex<240) && (40<mousey) && (mousey<80) && (b1playerOpen) &&(!networkActive))
+ {
+ //1 player - endless
+ theGame.NewGame(50,100);
+ theGame.putStartBlocks();
+ bNewGameOpen = false;
+ b1playerOpen = false;
+ twoPlayers =false;
+ theGame2.SetGameOver();
+ showGame = true;
+ }
+ else
+ if ((120<mousex) && (mousex<240) && (80<mousey) && (mousey<120) && (b1playerOpen) &&(!networkActive) )
+ {
+ //1 player - time trial
+ theGame.NewGame(50,100);
+ theGame.timetrial=true;
+ theGame.putStartBlocks();
+ bNewGameOpen = false;
+ b1playerOpen = false;
+ twoPlayers =false;
+ theGame2.SetGameOver();
+ showGame = true;
+ }
+ else
+ if ((120<mousex) && (mousex<240) && (120<mousey) && (mousey<160) && (b1playerOpen)&&(!networkActive) )
+ {
+ //1 player - stage clear
+ bNewGameOpen = false;
+ b1playerOpen = false;
+ int myLevel = StageLevelSelect();
+ theGame.NewStageGame(myLevel,50,100);
+ MakeBackground(xsize,ysize,theGame,theGame2);
+ DrawIMG(background, screen, 0, 0);
+ twoPlayers =false;
+ theGame2.SetGameOver();
+ showGame = true;
+ vsMode = false;
+ }
+ else
+ if ((120<mousex) && (mousex<240) && (160<mousey) && (mousey<200) && (b1playerOpen))
+ {
+ //1 player - puzzle
+ bNewGameOpen = false;
+ b1playerOpen = false;
+ int myLevel = PuzzleLevelSelect();
+ theGame.NewPuzzleGame(myLevel,50,100);
+ MakeBackground(xsize,ysize,theGame,theGame2);
+ DrawIMG(background, screen, 0, 0);
+ twoPlayers =false;
+ theGame2.SetGameOver();
+ showGame = true;
+ vsMode = false;
+ }
+ else
+ if ((120<mousex) && (mousex<240) && (200<mousey) && (mousey<240) && (b1playerOpen))
+ {
+ //1 player - Vs mode
+ bNewGameOpen = false;
+ b1playerOpen = false;
+ int theAIlevel = startSingleVs();
+ theGame.NewVsGame(50,100,&theGame2);
+ theGame2.NewVsGame(xsize-500,100,&theGame);
+ MakeBackground(xsize,ysize,theGame,theGame2);
+ DrawIMG(background, screen, 0, 0);
+ twoPlayers = true; //Single player, but AI plays
+ showGame = true;
+ vsMode = true;
+ theGame2.AI_Enabled=true; //Of course we need an AI
+ theGame2.setAIlevel((Uint8)theAIlevel);
+ int theTime = time(0);
+ theGame.putStartBlocks(theTime);
+ theGame2.putStartBlocks(theTime);
+ }
+ else
+ if ((120<mousex) && (mousex<240) && (80<mousey) && (mousey<120) && (b2playersOpen))
+ {
+ //2 player - time trial
+ theGame.NewGame(50,100);
+ theGame.timetrial=true;
+ bNewGameOpen = false;
+ b2playersOpen = false;
+ theGame.NewGame(50,100);
+ theGame2.NewGame(xsize-500,100);
+ theGame.timetrial = true;
+ theGame2.timetrial = true;
+ int theTime = time(0);
+ theGame.putStartBlocks(theTime);
+ theGame2.putStartBlocks(theTime);
+ theGame.setGameSpeed(player1Speed);
+ theGame2.setGameSpeed(player2Speed);
+ theGame.setHandicap(player1handicap);
+ theGame2.setHandicap(player2handicap);
+ theGame.AI_Enabled = player1AI;
+ theGame2.AI_Enabled = player2AI;
+ theGame.setAIlevel(player1AIlevel);
+ theGame2.setAIlevel(player2AIlevel);
+ twoPlayers = true;
+ }
+ else
+ if ((120<mousex) && (mousex<240) && (120<mousey) && (mousey<160) && (b2playersOpen))
+ {
+ //2 player - VsMode
+ theGame.NewVsGame(50,100,&theGame2);
+ theGame2.NewVsGame(xsize-500,100,&theGame);
+ bNewGameOpen = false;
+ vsMode = true;
+ twoPlayers = true;
+ b2playersOpen = false;
+ theGame.setGameSpeed(player1Speed);
+ theGame2.setGameSpeed(player2Speed);
+ theGame.setHandicap(player1handicap);
+ theGame2.setHandicap(player2handicap);
+ theGame.AI_Enabled = player1AI;
+ theGame2.AI_Enabled = player2AI;
+ theGame.setAIlevel(player1AIlevel);
+ theGame2.setAIlevel(player2AIlevel);
+ int theTime = time(0);
+ theGame.putStartBlocks(theTime);
+ theGame2.putStartBlocks(theTime);
+ }
+#ifdef NETWORK
+ else
+ if ((120<mousex) && (mousex<240) && (120<mousey) && (mousey<160) && (bNetworkOpen))
+ {
+ //Host
+ cout << "Host" << endl;
+ closeAllMenus();
+ theGame.SetGameOver();
+ theGame2.SetGameOver();
+ nt.startServer();
+ }
+ else
+ if ((120<mousex) && (mousex<240) && (160<mousey) && (mousey<200) && (bNetworkOpen))
+ {
+ //Connect
+ cout << "Connect" << endl;
+ closeAllMenus();
+ theGame.SetGameOver();
+ theGame2.SetGameOver();
+ if (OpenDialogbox(200,100,serverAddress))
+ {
+ char buf[30];
+ memcpy(buf,serverAddress,30);
+ nt.connectToServer(strtok(buf," "));
+ }
+ while ( SDL_PollEvent(&event) ); //If the user have pressed ESC or the like
+ }
+#endif
+ else
+ if ((120<mousex) && (mousex<2*120) && (0<mousey) && (mousey<40) &&(!networkActive))
+ {
+ //options button clicked
+ if (bOptionsOpen)
+ {
+ closeAllMenus();
+ }
+ else
+ {
+ closeAllMenus();
+ bOptionsOpen = true;
+ DrawIMG(background, screen, 0, 0);
+ }
+ }
+ else
+ if ((120<mousex) && (mousex<2*120) && (40<mousey) && (mousey<80) && (bOptionsOpen) )
+ {
+ //Configure button clicked
+ closeAllMenus();
+ if (!showOptions) {
+ showOptions = true;
+ showHighscores = false;
+ }
+ else showOptions = false;
+ DrawIMG(background, screen, 0, 0);
+ }
+ else
+ if ((120<mousex) && (mousex<2*120) && (80<mousey) && (mousey<120) && (bOptionsOpen) )
+ {
+ //Configure button clicked
+ closeAllMenus();
+ changePuzzleLevels();
+ }
+ else
+ if ((120<mousex) && (mousex<2*120) && (120<mousey) && (mousey<160) && (bOptionsOpen) )
+ {
+ //vsMode button clicked
+ closeAllMenus();
+ startVsMenu();
+ }
+ else
+ if ((120<mousex) && (mousex<2*120) && (160<mousey) && (mousey<200) && (bOptionsOpen) )
+ {
+ //selectThemClicked
+ closeAllMenus();
+ char temp[30];
+ SelectThemeDialogbox(200,100,temp);
+ }
+ else
+ if ((120*2<mousex) && (mousex<3*120) && (0<mousey) && (mousey<40) &&(!networkActive))
+ {
+ //highscore button clicked
+ bool state = showHighscores;
+ closeAllMenus();
+ if (!state) {
+ showHighscores = true;
+ showOptions = false;
+ }
+ DrawIMG(background, screen, 0, 0);
+ }
+ else
+ if ((360<mousex) && (mousex<4*120) && (0<mousey) && (mousey<40) &&(!networkActive))
+ {
+ //Replay clicked!
+ bool state = (!bReplayOpen);
+ closeAllMenus();
+ bReplayOpen = state; //theGame.NewGame(50,100);
+ showOptions = false;
+ showHighscores = false;
+ }
+ else
+ if ((360<mousex) && (mousex<4*120) && (40<mousey) && (mousey<80) &&(bReplayOpen))
+ {
+ //Replay->Save clicked!
+ //cout << "Replay->Save clicked" << endl;
+ char buf[30];
+ for (int i=0;i<29;i++)buf[i]=' ';
+ buf[30]=0;
+ OpenDialogbox(200,100,buf);
+ for (int i=28;buf[i]==' ';i--)
+ buf[i]=0;
+#ifdef __unix__
+ string saveHere = (string)getenv("HOME")+(string)"/.gamesaves/blockattack/replays/"+(string)buf;
+#elif WIN32
+ string saveHere = home+(string)"/My Games/blockattack/replays/"+(string)buf;
+#else
+ string saveHere = (string)"./replays"+(string)buf;
+#endif
+ if (lastNrOfPlayers<2)
+ theGame.theReplay.saveReplay(saveHere);
+ else
+ theGame.theReplay.saveReplay(saveHere,theGame2.theReplay);
+
+ closeAllMenus();
+ }
+ else
+ if ((360<mousex) && (mousex<4*120) && (80<mousey) && (mousey<120)&&(bReplayOpen))
+ {
+ //Replay->Load clicked!
+ //cout << "Replay->Load clicked" << endl;
+
+ char buf[30];
+ for (int i=0;i<29;i++)buf[i]=' ';
+ buf[30]=0;
+ if (OpenReplayDialogbox(50,100,buf))
+ {
+ //cout << "Good way" << endl;
+ for (int i=28;buf[i]==' ';i--)
+ buf[i]=0;
+#ifdef __unix__
+ string loadThis = (string)getenv("HOME")+(string)"/.gamesaves/blockattack/replays/"+(string)buf;
+#elif WIN32
+ string loadThis = home+(string)"/My Games/blockattack/replays/"+(string)buf;
+#else
+ string loadThis = (string)"./replays/"+(string)buf;
+#endif
+ ifstream replayFileIn;
+ replayFileIn.open(loadThis.c_str(),ios::binary);
+ bool play2 = false;
+ if (replayFileIn)
+ {
+ Uint8 version = 0;
+ replayFileIn.read(reinterpret_cast<char*>(&version),sizeof(Uint8)); replayFileIn.close();
+ Replay r1;
+ r1.loadReplay(loadThis);
+ Replay r2;
+ play2 = r2.loadReplay2(loadThis);
+ theGame.playReplay(50,100); //Fejlen sker her
+ theGame.theReplay = r1;
+ if (play2)
+ {
+ theGame2.playReplay(xsize-500,100);
+ theGame2.theReplay = r2;
+ }
+ else
+ theGame2.SetGameOver();
+ cout << "Replay should have been read" << endl;
+ }
+ }
+ closeAllMenus();
+ }
+ else
+ if ((xsize-120<mousex) && (xsize-20>mousex) && (ysize-120<mousey) && (ysize-20>mousey))
+ {
+ //Exit clicked
+ done=1;
+ }
+ else
+ if ((showOptions) && (mousex>500) && (mousex<560) && (mousey>220) && (mousey<260))
+ {
+ MusicEnabled = !MusicEnabled;
+ if (!MusicEnabled) Mix_FadeOutMusic(500);
+ }
+ if ((showOptions) && (mousex>500) && (mousex<560) && (mousey>270) && (mousey<310))
+ {
+ SoundEnabled = !SoundEnabled;
+ }
+ if ((showOptions) && (mousex>500) && (mousex<560) && (mousey>320) && (mousey<360))
+ {
+ //Fullscreen
+ bFullscreen = !bFullscreen;
+#if defined(WIN32)
+ if (bFullscreen) screen=SDL_SetVideoMode(xsize,ysize,32,SDL_SWSURFACE|SDL_FULLSCREEN|SDL_ANYFORMAT);
+ else screen=SDL_SetVideoMode(xsize,ysize,32,SDL_SWSURFACE|SDL_ANYFORMAT);
+ DrawIMG(background, screen, 0, 0);
+#else
+ SDL_WM_ToggleFullScreen(screen); //Will only work in Linux
+#endif
+ SDL_ShowCursor(SDL_DISABLE);
+ }
+
+ if ((showOptions) && (mousex>330) && (mousex<470) && (mousey>535) && (mousey<585))
+ {
+ //change name
+ bScreenLocked = true;
+ showDialog = true;
+ if (OpenDialogbox(200,100,player1name))
+ strcpy(theGame.name, player1name);
+ else
+ strcpy(player1name,theGame.name);
+ bScreenLocked = false;
+ showDialog = false;
+ MakeBackground(xsize,ysize,theGame,theGame2);
+ DrawIMG(background, screen, 0, 0);
+ }
+ if ((showOptions) && (mousex>330) && (mousex<470) && (mousey>600) && (mousey<640))
+ {
+ //change name
+ bScreenLocked = true;
+ showDialog = true;
+ if (OpenDialogbox(200,100,player2name))
+ strcpy(theGame2.name, player2name);
+ else
+ strcpy(player2name,theGame2.name);
+ bScreenLocked = false;
+ showDialog = false;
+ MakeBackground(xsize,ysize,theGame,theGame2);
+ DrawIMG(background, screen, 0, 0);
+ }
+ if ((showOptions) && (mousex>510) && (mousex<630) && (mousey>535) && (mousey<585))
+ {
+ //changeControls
+ OpenControlsBox(200,100,0);
+ MakeBackground(xsize,ysize,theGame,theGame2);
+ DrawIMG(background, screen, 0, 0);
+ }
+ if ((showOptions) && (mousex>510) && (mousex<630) && (mousey>600) && (mousey<640))
+ {
+ //changeControls
+ OpenControlsBox(200,100,2);
+ MakeBackground(xsize,ysize,theGame,theGame2);
+ DrawIMG(background, screen, 0, 0);
+ }
+ if ((showHighscores)&&(((mousex>150)&&(mousex<173))||((mousex>628)&&(mousex<650)))&&(mousey<652)&&(mousey>630))
+ {
+ //small arrors on Highscore board clicked!
+ showEndless = !showEndless;
+ DrawIMG(background, screen, 0, 0);
+ }
+
+ /********************************************************************
+ **************** Here comes mouse play ******************************
+ ********************************************************************/
+ if ((!showOptions)&&(!showHighscores))
+ {
+ if (mouseplay1 && !theGame.AI_Enabled) //player 1
+ if ((mousex > 50)&&(mousey>100)&&(mousex<50+300)&&(mousey<100+600))
+ {
+ theGame.SwitchAtCursor();
+ }
+ if (mouseplay2 && !theGame2.AI_Enabled) //player 2
+ if ((mousex > xsize-500)&&(mousey>100)&&(mousex<xsize-500+300)&&(mousey<100+600))
+ {
+ theGame2.SwitchAtCursor();
+ }
+ }
+ /********************************************************************
+ **************** Here ends mouse play *******************************
+ ********************************************************************/
+
+ if(stageButtonStatus != SBdontShow && (mousex > theGame.topx+cordNextButton.x)
+ &&(mousex < theGame.topx+cordNextButton.x+cordNextButton.xsize)
+ &&(mousey > theGame.topy+cordNextButton.y)&&(mousey < theGame.topy+cordNextButton.y+cordNextButton.ysize))
+ {
+ //Clicked the next button after a stage clear or puzzle
+ theGame.nextLevel();
+ }
+ if(stageButtonStatus != SBdontShow && (mousex > theGame.topx+cordRetryButton .x)
+ &&(mousex < theGame.topx+cordRetryButton.x+cordRetryButton.xsize)
+ &&(mousey > theGame.topy+cordRetryButton.y)&&(mousey < theGame.topy+cordRetryButton.y+cordRetryButton.ysize))
+ {
+ //Clicked the retry button
+ theGame.retryLevel();
+ }
+
+
+ //cout << "Mouse x: " << mousex << ", mouse y: " << mousey << endl;
+ }
+
+ //Mouse button 2:
+ if ((SDL_GetMouseState(NULL,NULL)&SDL_BUTTON(3))==SDL_BUTTON(3) && bMouseUp2)
+ {
+ bMouseUp2=false; //The button is pressed
+ /********************************************************************
+ **************** Here comes mouse play ******************************
+ ********************************************************************/
+ if ((!showOptions)&&(!showHighscores))
+ {
+ if (mouseplay1 && !theGame.AI_Enabled) //player 1
+ if ((mousex > 50)&&(mousey>100)&&(mousex<50+300)&&(mousey<100+600))
+ {
+ theGame.PushLine();
+ }
+ if (mouseplay2 && !theGame2.AI_Enabled) //player 2
+ if ((mousex > xsize-500)&&(mousey>100)&&(mousex<xsize-500+300)&&(mousey<100+600))
+ {
+ theGame2.PushLine();
+ }
+ }
+ /********************************************************************
+ **************** Here ends mouse play *******************************
+ ********************************************************************/
+ }
+ } //if !singlePuzzle
+ else
+ {
+
+ }
+ } //if !bScreenBocked;
+
+
+ //Sees if music is stopped and if music is enabled
+ if ((!NoSound)&&(!Mix_PlayingMusic())&&(MusicEnabled))
+ {
+ // then starts playing it.
+ Mix_PlayMusic(bgMusic, 0); //music loop
+ }
+
+ //Updates the objects
+ theGame.Update();
+ theGame2.Update();
+
+//see if anyone has won (two players only)
+ if (!networkPlay)
+ if (twoPlayers)
+ {
+ lastNrOfPlayers = 2;
+ if ((theGame.bGameOver) && (theGame2.bGameOver))
+ {
+ if (theGame.score+theGame.handicap>theGame2.score+theGame2.handicap)
+ theGame.setPlayerWon();
+ else
+ if (theGame.score+theGame.handicap<theGame2.score+theGame2.handicap)
+ theGame2.setPlayerWon();
+ else {
+ theGame.setDraw();
+ theGame2.setDraw();
+ }
+ twoPlayers = false;
+ }
+ if ((theGame.bGameOver) && (!theGame2.bGameOver))
+ {
+ theGame2.setPlayerWon();
+ twoPlayers = false;
+ }
+ if ((!theGame.bGameOver) && (theGame2.bGameOver))
+ {
+ theGame.setPlayerWon();
+ twoPlayers = false;
+ }
+ }
+
+ //Once evrything has been checked, update graphics
+ DrawEverything(xsize,ysize,theGame, theGame2);
+ SDL_GetMouseState(&mousex,&mousey);
+ //Remember mouse placement
+ oldMousex = mousex;
+ oldMousey = mousey;
+ //Draw the mouse:
+ DrawIMG(mouse,screen,mousex,mousey);
+ SDL_Flip(screen);
+ } //game loop
+
+
+
+ //Saves options
+ if (!editorMode)
+ {
+ ofstream optionsFileOut;
+ optionsFileOut.open(optionsPath.c_str(),ios::binary|ios::trunc);
+ if (optionsFileOut)
+ {
+ //writes data: xsize,ysize,fullescreen, player1keys, player2keys, MusicEnabled, SoundEnabled,player1name,player2name
+ optionsFileOut.write(reinterpret_cast<char*>(&xsize),sizeof(int));
+ optionsFileOut.write(reinterpret_cast<char*>(&ysize),sizeof(int));
+ optionsFileOut.write(reinterpret_cast<char*>(&bFullscreen),sizeof(bool));
+ optionsFileOut.write(reinterpret_cast<char*>(&keySettings[0].up), sizeof(SDLKey));
+ optionsFileOut.write(reinterpret_cast<char*>(&keySettings[0].down), sizeof(SDLKey));
+ optionsFileOut.write(reinterpret_cast<char*>(&keySettings[0].left), sizeof(SDLKey));
+ optionsFileOut.write(reinterpret_cast<char*>(&keySettings[0].right), sizeof(SDLKey));
+ optionsFileOut.write(reinterpret_cast<char*>(&keySettings[0].change), sizeof(SDLKey));
+ optionsFileOut.write(reinterpret_cast<char*>(&keySettings[0].push), sizeof(SDLKey));
+ optionsFileOut.write(reinterpret_cast<char*>(&keySettings[2].up), sizeof(SDLKey));
+ optionsFileOut.write(reinterpret_cast<char*>(&keySettings[2].down), sizeof(SDLKey));
+ optionsFileOut.write(reinterpret_cast<char*>(&keySettings[2].left), sizeof(SDLKey));
+ optionsFileOut.write(reinterpret_cast<char*>(&keySettings[2].right), sizeof(SDLKey));
+ optionsFileOut.write(reinterpret_cast<char*>(&keySettings[2].change), sizeof(SDLKey));
+ optionsFileOut.write(reinterpret_cast<char*>(&keySettings[2].push), sizeof(SDLKey));
+ optionsFileOut.write(reinterpret_cast<char*>(&MusicEnabled),sizeof(bool));
+ optionsFileOut.write(reinterpret_cast<char*>(&SoundEnabled),sizeof(bool));
+ optionsFileOut.write(player1name,30*sizeof(char));
+ optionsFileOut.write(player2name,30*sizeof(char));
+ optionsFileOut.write(reinterpret_cast<char*>(&mouseplay1),sizeof(bool));
+ optionsFileOut.write(reinterpret_cast<char*>(&mouseplay2),sizeof(bool));
+ optionsFileOut.write(reinterpret_cast<char*>(&joyplay1),sizeof(bool));
+ optionsFileOut.write(reinterpret_cast<char*>(&joyplay2),sizeof(bool));
+ optionsFileOut.close();
+ cout << "options written to file" << endl;
+ }
+ else
+ {
+ cout << "Failed to write options" << endl;
+ }
+ }
+
+ Stats::getInstance()->save();
+
+ //Frees memory from music and fonts
+ //This is done after writing of options since it often crashes the program :(
+ UnloadImages();
+
+
+ //calculate uptime:
+ //int hours, mins, secs,
+ int time;
+ commonTime ct;
+ ct.days = 0;
+ time = SDL_GetTicks();
+ ct.hours = time/(1000*60*60);
+ time = time % (1000*60*60);
+ ct.minutes = time/(1000*60);
+ time = time % (1000*60);
+ ct.seconds = time/1000;
+
+ cout << "Block Attack - Rise of the Blocks ran for: " << ct.hours << " hours " << ct.minutes << " mins and " << ct.seconds << " secs" << endl;
+
+ ct = addTotalTime(ct);
+
+ cout << "Total run time is now: " << ct.days << " days " << ct.hours << " hours " << ct.minutes << " mins and " << ct.seconds << " secs" << endl;
+
+ return 0;
+}
diff --git a/source/code/mainVars.hpp b/source/code/mainVars.hpp new file mode 100644 index 0000000..3e8a938 --- /dev/null +++ b/source/code/mainVars.hpp
@@ -0,0 +1,339 @@
+/*
+mainVars.hpp
+Copyright (C) 2007 Poul Sander
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Poul Sander
+ R�veh�jvej 36, V. 1111
+ 2800 Kgs. Lyngby
+ DENMARK
+ blockattack@poulsander.com
+*/
+
+//main variables and constants
+
+//Some definitions
+//The game is divided in frames. FALLTIME means the blocks will fall one block every FRAMELENGTH*FALLTIME millisecond
+#define FRAMELENGTH 50
+#define HANGTIME 40
+#define FALLTIME 20
+//Don't change the following, they are fundamental and later some functions are hardcoded
+#define BLOCKFALL 10000
+#define BLOCKWAIT 100000
+#define BLOCKHANG 1000
+#define GARBAGE 1000000
+#define CHAINPLACE 10000000
+#define NUMBEROFCHAINS 100
+
+//Animation lengths:
+#define READYTIME 500
+#define BOMBTIME 200
+#define CURSORTIME 200
+
+
+using namespace std; //remove it if you dare...
+#ifdef SHAREDIR
+char sharedir[] = SHAREDIR;
+#endif
+
+//All graphic in the game (as pointers):
+SDL_Surface *background; //Stores background
+SDL_Surface *backgroundImage; //Stores the background image
+int backgroundImageW, backgroundImageH; //size of background image
+SDL_Surface *backBoard; //Stores the background to the board
+SDL_Surface *b1player;
+SDL_Surface *b2players;
+SDL_Surface *bVsMode;
+SDL_Surface *bStageClear;
+SDL_Surface *bPuzzle;
+SDL_Surface *bNewGame; //The New Game botton
+SDL_Surface *bEndless; //Endless button (sub to new)
+SDL_Surface *bTimeTrial; //Time trial button (sub to new)
+SDL_Surface *bOptions; //The Options botton
+//new in 1.1.1
+SDL_Surface *bConfigure; //The configure button
+SDL_Surface *bSelectPuzzle; //The Select Puzzle Button
+SDL_Surface *bBack; //The "Back" button
+SDL_Surface *bForward; //The "forward" button
+//new in 1.1.1 end
+//new in 1.1.2
+SDL_Surface *iChainBack;
+//new in 1.1.2 end (nota that iSmallFont has also been added)
+//new in 1.2.0
+SDL_Surface *bReplay;
+SDL_Surface *bSave;
+SDL_Surface *bLoad;
+#ifdef NETWORK
+SDL_Surface *bNetwork;
+SDL_Surface *bConnect;
+SDL_Surface *bHost;
+#endif
+//new in 1.2.0 end
+SDL_Surface *bHighScore; //The High Score botton
+SDL_Surface *bExit; //The Exit botton
+SDL_Surface *blackLine; //The seperator in stage clear
+SDL_Surface *stageBobble; //The bobble instage clear
+SDL_Surface *screen; //The whole screen;
+SDL_Surface *iGameOver; //The gameOver image
+SDL_Surface *iWinner; //the "winner" image
+SDL_Surface *iDraw; //the "draw" image
+SDL_Surface *iLoser; //the "loser" image
+//Animations:
+SDL_Surface *cursor[2]; //The animated cursor
+SDL_Surface *bomb[2]; //Bomb then the bricks should blow
+SDL_Surface *ready[2]; //Before the blocks fall
+SDL_Surface *explosion[4]; //Then a block explodes
+//Animations end
+SDL_Surface *counter[3]; //Counts down from 3
+SDL_Surface *bricks[7]; //The bricks, saved in an array of pointers
+SDL_Surface *crossover; //Cross the bricks that will be cleared soon
+SDL_Surface *balls[7]; //The balls (the small ones that jump around)
+SDL_Surface *iBlueFont; //Contains the blue font used
+SDL_Surface *iSmallFont; //Small font used for the chain text
+SDL_Surface *topscoresBack; //The backgound to the highscore list
+SDL_Surface *optionsBack;
+SDL_Surface *changeButtonsBack;
+SDL_Surface *dialogBox;
+//SDL_Surface *fileDialogBox; //Manual entering of filename, new in 1.1.1, obsolute in 1.1.2
+SDL_Surface *bOn;
+SDL_Surface *bOff;
+SDL_Surface *bChange;
+SDL_Surface *b1024;
+//SDL_Surface *b1280;
+//SDL_Surface *b1400;
+//SDL_Surface *b1600;
+SDL_Surface *iLevelCheck; //To the level select screen
+SDL_Surface *iLevelCheckBox;
+SDL_Surface *iCheckBoxArea;
+SDL_Surface *boardBackBack;
+SDL_Surface *garbageTL; //the Garbage Blocks
+SDL_Surface *garbageT;
+SDL_Surface *garbageTR;
+SDL_Surface *garbageR;
+SDL_Surface *garbageBR;
+SDL_Surface *garbageB;
+SDL_Surface *garbageBL;
+SDL_Surface *garbageL;
+SDL_Surface *garbageFill;
+SDL_Surface *garbageM;
+SDL_Surface *garbageML;
+SDL_Surface *garbageMR;
+//new in 1.3.0 start
+SDL_Surface *smiley[4];
+SDL_Surface *garbageGM;
+SDL_Surface *garbageGML;
+SDL_Surface *garbageGMR;
+//new in 1.3.0 end
+//new in 1.3.2 start
+SDL_Surface *transCover; //The transperant block, covers the upcomming
+//also new in 1.3.2 for the editor
+/*SDL_Surface *bCreateFile;
+SDL_Surface *bDeletePuzzle;
+SDL_Surface *bLoadFile;
+SDL_Surface *bMoveBack;
+SDL_Surface *bMoveDown;
+SDL_Surface *bMoveForward;
+SDL_Surface *bMoveLeft;
+SDL_Surface *bMoveRight;
+SDL_Surface *bMoveUp;
+SDL_Surface *bNewPuzzle;
+SDL_Surface *bSaveFileAs;
+SDL_Surface *bSavePuzzle;
+SDL_Surface *bSaveToFile;
+SDL_Surface *bTestPuzzle;*/
+//new in 1.3.2 end
+//new in 1.4.0
+SDL_Surface *bTheme;
+SDL_Surface *bSkip;
+SDL_Surface *bRetry;
+SDL_Surface *bNext;
+//end new in 1.4.0
+SDL_Surface *mouse; //The mouse cursor
+
+
+SDL_Surface *tmp; //a temporary surface to use DisplayFormat
+
+
+SFont_Font *fBlueFont; //Stores the blue font (SFont)
+SFont_Font *fSmallFont; //Stores the small font (SFont)
+//TTFont ttfont; //Stores the TTF font (TTFSDL)
+
+Mix_Music *bgMusic; //backgroundMusic
+Mix_Chunk *boing; //boing sound when clearing
+Mix_Chunk *timesUp; //whistle when times up
+Mix_Chunk *applause; //Applause, then the player is good
+Mix_Chunk *photoClick; //clickSound
+Mix_Chunk *heartBeat; //heart beat
+Mix_Chunk *typingChunk; //When writing
+Mix_Chunk *counterChunk; //When counting down
+
+Highscore theTopScoresEndless; //Stores highscores for endless
+Highscore theTopScoresTimeTrial; //Stores highscores for timetrial
+
+bool bMouseUp; //true if the mouse(1) is unpressed
+bool bMouseUp2; //true if the mouse(2) is unpressed
+bool bNewGameOpen; //show sub menues
+bool bOptionsOpen; //Show OptionsMenu (Configure and Select Puzzle)
+bool b1playerOpen; //show submenu
+bool b2playersOpen; //show submenu
+bool bReplayOpen; //Show replay menu
+#ifdef NETWORK
+bool bNetworkOpen; //Show the network menu
+#endif
+bool showHighscores; //true if highscores is displayed
+bool showEndless; //if true show endless highscores else timetrial
+bool showGame; //the game is active don't show highscores/options
+bool showOptions; //true if options is open
+bool bScreenLocked; //Don't take input or allow any mouse interaction! Used for dialogbox and warningbox
+bool showDialog;
+//new in 1.3.1
+bool NoSound; //if true, absolutely no sound will be played, can be set from the commandline
+//prevents crash on systems without a soundcard
+//end new 1.3.1
+bool MusicEnabled; //true if background music is enabled
+bool SoundEnabled; //true if sound effects is enabled
+bool bFullscreen; //true if game is running fullscreen
+bool puzzleLoaded; //true if the puzzle levels have been loaded
+bool drawBalls; //if true balls are drawed to the screen, this might lower framerate too much
+bool standardBackground;
+
+//new in 1.3.2
+bool editorMode = false;
+bool editorModeTest = false;
+//end new 1.3.2
+
+//Things for network play:
+bool networkPlay;
+bool networkActive;
+Uint8 nrOfNetworkPlayers; //Up to 4 players (inkl. self)
+bool playerAlive[4];
+//sockets here
+#define SERVERPORT 41780
+#define CLIENTPORT 41781
+
+#ifdef NETWORK
+char serverAddress[30];
+#endif
+
+//should be automatically disabled if framerate to low (isn't implemented and wont be soon/ever):
+const int ballsFpsEnable = 30; //If framerate higher -> enable balls
+const int ballsFpsDisable = 10; //If framerate lower -> disable balls
+
+//other ball constants:
+const double gravity = 200.8; //acceleration
+const double startVelocityY = 50.0;
+const double VelocityX = 50.0;
+const int ballSize = 16;
+const double minVelocity = 200.0;
+
+//global settings (reset everytime the game starts)
+Uint8 player1Speed=0;
+Uint8 player2Speed=0;
+bool player1AI=false; //Is AI enabled?
+bool player2AI=false; //Is AI enabled for player 2 (opponent in single player)
+Uint8 player1AIlevel=3; //What level is AI? 0 min, 6 max
+Uint8 player2AIlevel=3;
+const Uint8 AIlevels=7; //7 possible levels: 0..6
+Uint8 player1handicap=0;
+Uint8 player2handicap=0;
+
+unsigned long int currentTime; //contains the current time, so we don't call SDL_GetTickets() too often...
+
+int xsize;
+
+//Stores the players names (way to long, but at least no buffer overflows (max length is 16 for display reasons))
+char player1name[30];
+char player2name[30];
+
+//paths
+string stageClearSavePath;
+string puzzleSavePath;
+string puzzleName; //The filename of
+
+const int nrOfStageLevels = 50; //number of stages in stage Clear
+const int maxNrOfPuzzleStages = 50; //Maximum number of puzzle stages
+vector<bool> stageCleared(nrOfStageLevels); //vector that tells if a stage is cleared
+vector<Uint32> stageTimes(nrOfStageLevels); //For statistical puposes
+vector<Uint32> stageScores(nrOfStageLevels); //--||--
+vector<bool> puzzleCleared(maxNrOfPuzzleStages); //vector that tells if puzzle cleared
+vector<int> nrOfMovesAllowed(maxNrOfPuzzleStages); //Moves to clear
+int puzzleLevels[maxNrOfPuzzleStages][6][12]; //Contains board layout;
+int nrOfPuzzles; //How many are there actually?
+
+//Old mouse position:
+int oldMousex, oldMousey;
+//Old Stage Clear Buble
+int oldBubleX, oldBubleY;
+
+//bool doublebuf = false; //if true, screen is double buffered
+char forceredraw; //If 1: always redraw, if 2: rarely redraw
+
+bool singlePuzzle = false; //if true we are just in a little 300x600 window
+int singlePuzzleNr = 0;
+string singlePuzzleFile;
+
+#if defined(DEBUG)
+//frame counter (fps)
+unsigned long int Frames, Ticks;
+char FPS[10];
+#endif
+
+int lastNrOfPlayers; //1 if 1 player and 2 if vs. mode
+
+//keySetup
+int player1keys, player2keys;
+bool mouseplay1=false; //The mouse works on the play field
+bool mouseplay2=false; //Same for player2
+bool joyplay1=false; //Player one uses the joypad
+bool joyplay2=false; //Player two uses the joypad
+
+//Stores the controls
+struct control
+{
+ SDLKey up;
+ SDLKey down;
+ SDLKey left;
+ SDLKey right;
+ SDLKey change;
+ SDLKey push;
+};
+
+control keySettings[3]; //array to hold the controls (default and two custom)
+
+enum stageButton {SBdontShow, SBstageClear, SBpuzzleMode};
+
+stageButton stageButtonStatus = SBdontShow;
+
+struct ButtonCords
+{
+ int x;
+ int y;
+ int xsize;
+ int ysize;
+};
+
+ButtonCords cordNextButton = {
+cordNextButton.x = 150+(150-120)/2,
+cordNextButton.y = 500,
+cordNextButton.xsize = 120,
+cordNextButton.ysize = 40};
+
+ButtonCords cordRetryButton = {
+cordRetryButton.x = (150-120)/2,
+cordRetryButton.y = 500,
+cordRetryButton.xsize = 120,
+cordRetryButton.ysize = 40
+};
diff --git a/source/code/replay.cpp b/source/code/replay.cpp new file mode 100644 index 0000000..9093150 --- /dev/null +++ b/source/code/replay.cpp
@@ -0,0 +1,328 @@
+/*
+replay.cpp
+Copyright (C) 2005 Poul Sander
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Poul Sander
+ R�veh�jvej 36, V. 1111
+ 2800 Kgs. Lyngby
+ DENMARK
+ blockattack@poulsander.com
+*/
+
+/*
+Handles replay
+*/
+
+#include "replay.h"
+
+Replay::Replay()
+{
+ nrOfFrames=0;
+ isLoaded = false;
+}
+
+Replay::Replay(const Replay& r)
+{
+ bps = r.bps;
+ finalPack = r.finalPack;
+ nrOfFrames = r.nrOfFrames;
+ isLoaded = r.isLoaded;
+ theResult = r.theResult;
+}
+
+Uint32 Replay::getNumberOfFrames()
+{
+ return nrOfFrames;
+}
+
+void Replay::setFrameSecTo(Uint32 miliseconds, boardPackage bp)
+{
+ if (isLoaded)
+ return;
+ int framesToSet = (miliseconds*FRAMESPERSEC)/1000;
+ for (int i=nrOfFrames;i<framesToSet;i++)
+ {
+ bps.push_back(bp);
+ }
+ nrOfFrames=framesToSet;
+}
+
+void Replay::setFinalFrame(boardPackage bp,int theStatus)
+{
+ if (isLoaded)
+ return;
+ finalPack = bp;
+ switch (theStatus)
+ {
+ case 1:
+ theResult = winner;
+ break;
+ case 2:
+ theResult = looser;
+ break;
+ case 3:
+ theResult = draw;
+ break;
+ default:
+ theResult = gameOver;
+ };
+
+}
+
+//Returns the frame to the current time, if time too high the final frame is returned
+boardPackage Replay::getFrameSec(Uint32 miliseconds)
+{
+ int frameToGet = (miliseconds*FRAMESPERSEC)/1000;
+ if (!(frameToGet<nrOfFrames))
+ return getFinalFrame();
+ return bps.at(frameToGet);
+}
+
+bool Replay::isFinnished(Uint32 miliseconds)
+{
+ int frameToGet = (miliseconds*FRAMESPERSEC)/1000;
+ if (!(frameToGet<nrOfFrames))
+ return true;
+ return false;
+}
+
+boardPackage Replay::getFinalFrame()
+{
+ return finalPack;
+}
+
+int Replay::getFinalStatus()
+{
+ return theResult;
+}
+
+
+
+bool Replay::saveReplay(string filename)
+{
+ //Saving as fileversion 2
+ cout << "Saving as version 2 save file" << endl;
+ ofstream saveFile;
+ saveFile.open(filename.c_str(),ios::binary|ios::trunc);
+ if (saveFile)
+ {
+ Uint32 version = 2;
+ boardPackage bp;
+ saveFile.write(reinterpret_cast<char*>(&version),sizeof(Uint32)); //Fileversion
+ Uint8 nrOfReplays = 1;
+ saveFile.write(reinterpret_cast<char*>(&nrOfReplays),sizeof(Uint8)); //nrOfReplaysIn File
+ saveFile.write(reinterpret_cast<char*>(&nrOfFrames),sizeof(Uint32)); //Nr of frames in file
+ for (int i=0; i<nrOfFrames && i<bps.size();i++)
+ { //Writing frames
+ bp = bps.at(i);
+ saveFile.write(reinterpret_cast<char*>(&bp.time),sizeof(Uint32));
+ for (int k=0;k<6;k++)
+ for (int g=0;g<13;g++)
+ {
+ saveFile.write(reinterpret_cast<char*>(&bp.brick[k][g]),sizeof(Uint8));
+ }
+ saveFile.write(reinterpret_cast<char*>(&bp.pixels),sizeof(Uint8));
+ saveFile.write(reinterpret_cast<char*>(&bp.cursorX),sizeof(Uint8));
+ saveFile.write(reinterpret_cast<char*>(&bp.cursorY),sizeof(Uint8));
+ saveFile.write(reinterpret_cast<char*>(&bp.score),sizeof(Uint32));
+ saveFile.write(reinterpret_cast<char*>(&bp.speed),sizeof(Uint8));
+ saveFile.write(reinterpret_cast<char*>(&bp.chain),sizeof(Uint8));
+
+ }
+ saveFile.write(reinterpret_cast<char*>(&finalPack),sizeof(finalPack));
+ saveFile.close();
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool Replay::saveReplay(string filename,Replay p2)
+{
+ //Saving as fileversion 2
+ cout << "Saving as version 2 save file (2 players)" << endl;
+ ofstream saveFile;
+ saveFile.open(filename.c_str(),ios::binary|ios::trunc);
+ if (saveFile)
+ {
+ Uint32 version = 2;
+ boardPackage bp;
+ saveFile.write(reinterpret_cast<char*>(&version),sizeof(Uint32)); //Fileversion
+ Uint8 nrOfReplays = 2;
+ saveFile.write(reinterpret_cast<char*>(&nrOfReplays),sizeof(Uint8)); //nrOfReplaysIn File
+ saveFile.write(reinterpret_cast<char*>(&nrOfFrames),sizeof(Uint32)); //Nr of frames in file
+ for (int i=0; i<nrOfFrames && i<bps.size();i++)
+ { //Writing frames
+ bp = bps.at(i);
+ saveFile.write(reinterpret_cast<char*>(&bp.time),sizeof(Uint32));
+ for (int k=0;k<6;k++)
+ for (int g=0;g<13;g++)
+ saveFile.write(reinterpret_cast<char*>(&bp.brick[k][g]),sizeof(Uint8));
+ saveFile.write(reinterpret_cast<char*>(&bp.pixels),sizeof(Uint8));
+ saveFile.write(reinterpret_cast<char*>(&bp.cursorX),sizeof(Uint8));
+ saveFile.write(reinterpret_cast<char*>(&bp.cursorY),sizeof(Uint8));
+ saveFile.write(reinterpret_cast<char*>(&bp.score),sizeof(Uint32));
+ saveFile.write(reinterpret_cast<char*>(&bp.speed),sizeof(Uint8));
+ saveFile.write(reinterpret_cast<char*>(&bp.chain),sizeof(Uint8));
+ }
+ saveFile.write(reinterpret_cast<char*>(&finalPack),sizeof(finalPack));
+ ///Player 2 starts here!!!!!!!!!!!!!!!!!!!!!!
+ saveFile.write(reinterpret_cast<char*>(&p2.nrOfFrames),sizeof(Uint32)); //Nr of frames in file
+ for (int i=0; (i<p2.nrOfFrames)&& i<p2.bps.size();i++)
+ { //Writing frames
+ bp = p2.bps.at(i);
+ saveFile.write(reinterpret_cast<char*>(&bp.time),sizeof(Uint32));
+ for (int k=0;k<6;k++)
+ for (int g=0;g<13;g++)
+ saveFile.write(reinterpret_cast<char*>(&bp.brick[k][g]),sizeof(Uint8));
+ saveFile.write(reinterpret_cast<char*>(&bp.pixels),sizeof(Uint8));
+ saveFile.write(reinterpret_cast<char*>(&bp.cursorX),sizeof(Uint8));
+ saveFile.write(reinterpret_cast<char*>(&bp.cursorY),sizeof(Uint8));
+ saveFile.write(reinterpret_cast<char*>(&bp.score),sizeof(Uint32));
+ saveFile.write(reinterpret_cast<char*>(&bp.speed),sizeof(Uint8));
+ saveFile.write(reinterpret_cast<char*>(&bp.chain),sizeof(Uint8));
+ }
+ saveFile.write(reinterpret_cast<char*>(&p2.finalPack),sizeof(finalPack));
+ saveFile.close();
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool Replay::loadReplay(string filename)
+{
+ isLoaded = true;
+ ifstream loadFile;
+ loadFile.open(filename.c_str(),ios::binary);
+ if (loadFile)
+ {
+ Uint32 version;
+ loadFile.read(reinterpret_cast<char*>(&version),sizeof(Uint32));
+ switch (version)
+ {
+ case 2:
+ cout << "Loading a version 2 save game" << endl;
+ Uint8 nrOfPlayers;
+ boardPackage bp;
+ loadFile.read(reinterpret_cast<char*>(&nrOfPlayers),sizeof(Uint8));
+ loadFile.read(reinterpret_cast<char*>(&nrOfFrames),sizeof(Uint32));
+ bps.clear();
+ for (int i=0; (i<nrOfFrames);i++)
+ {
+ loadFile.read(reinterpret_cast<char*>(&bp.time),sizeof(Uint32)); //Writing frames
+ for (int k=0;k<6;k++)
+ for (int g=0;g<13;g++)
+ loadFile.read(reinterpret_cast<char*>(&bp.brick[k][g]),sizeof(Uint8));
+ loadFile.read(reinterpret_cast<char*>(&bp.pixels),sizeof(Uint8));
+ loadFile.read(reinterpret_cast<char*>(&bp.cursorX),sizeof(Uint8));
+ loadFile.read(reinterpret_cast<char*>(&bp.cursorY),sizeof(Uint8));
+ loadFile.read(reinterpret_cast<char*>(&bp.score),sizeof(Uint32));
+ loadFile.read(reinterpret_cast<char*>(&bp.speed),sizeof(Uint8));
+ loadFile.read(reinterpret_cast<char*>(&bp.chain),sizeof(Uint8));
+ bps.push_back(bp);
+ }
+ loadFile.read(reinterpret_cast<char*>(&finalPack),sizeof(finalPack));
+ break;
+ default:
+ cout << "Unknown version" << endl;
+ return false;
+ };
+ loadFile.close();
+ cout << "Loaded 1 player" << endl;
+ }
+ else
+ {
+ cout << "File not found or couldn't open: " << filename << endl;
+ return false;
+ }
+
+}
+
+bool Replay::loadReplay2(string filename)
+{
+ isLoaded = true;
+ ifstream loadFile;
+ loadFile.open(filename.c_str(),ios::binary);
+ if (loadFile)
+ {
+ Uint32 version;
+ loadFile.read(reinterpret_cast<char*>(&version),sizeof(Uint32));
+ switch (version)
+ {
+ case 2:
+ Uint8 nrOfPlayers;
+ boardPackage bp;
+ loadFile.read(reinterpret_cast<char*>(&nrOfPlayers),sizeof(Uint8));
+ if (nrOfPlayers<2)
+ {
+ loadFile.close();
+ cout << "Only one player in replay" << endl;
+ return false;
+ }
+ cout << "loading player 2" << endl;
+ loadFile.read(reinterpret_cast<char*>(&nrOfFrames),sizeof(Uint32));
+ for (int i=0; (i<nrOfFrames);i++)
+ {
+ loadFile.read(reinterpret_cast<char*>(&bp.time),sizeof(Uint32)); //Writing frames
+ for (int k=0;k<6;k++)
+ for (int g=0;g<13;g++)
+ loadFile.read(reinterpret_cast<char*>(&bp.brick[k][g]),sizeof(Uint8));
+ loadFile.read(reinterpret_cast<char*>(&bp.pixels),sizeof(Uint8));
+ loadFile.read(reinterpret_cast<char*>(&bp.cursorX),sizeof(Uint8));
+ loadFile.read(reinterpret_cast<char*>(&bp.cursorY),sizeof(Uint8));
+ loadFile.read(reinterpret_cast<char*>(&bp.score),sizeof(Uint32));
+ loadFile.read(reinterpret_cast<char*>(&bp.speed),sizeof(Uint8));
+ loadFile.read(reinterpret_cast<char*>(&bp.chain),sizeof(Uint8));
+ //bps.push_back(bp);
+ }
+ loadFile.read(reinterpret_cast<char*>(&finalPack),sizeof(finalPack));
+ loadFile.read(reinterpret_cast<char*>(&nrOfFrames),sizeof(Uint32));
+ bps.reserve(nrOfFrames);
+ for (int i=0; (i<nrOfFrames);i++)
+ {
+ loadFile.read(reinterpret_cast<char*>(&bp.time),sizeof(Uint32)); //Writing frames
+ for (int k=0;k<6;k++)
+ for (int g=0;g<13;g++)
+ loadFile.read(reinterpret_cast<char*>(&bp.brick[k][g]),sizeof(Uint8));
+ loadFile.read(reinterpret_cast<char*>(&bp.pixels),sizeof(Uint8));
+ loadFile.read(reinterpret_cast<char*>(&bp.cursorX),sizeof(Uint8));
+ loadFile.read(reinterpret_cast<char*>(&bp.cursorY),sizeof(Uint8));
+ loadFile.read(reinterpret_cast<char*>(&bp.score),sizeof(Uint32));
+ loadFile.read(reinterpret_cast<char*>(&bp.speed),sizeof(Uint8));
+ loadFile.read(reinterpret_cast<char*>(&bp.chain),sizeof(Uint8));
+ bps.push_back(bp);
+ }
+ loadFile.read(reinterpret_cast<char*>(&finalPack),sizeof(finalPack));
+ break;
+ default:
+ cout << "Unknown version: " << version << endl;
+ return false;
+ };
+ loadFile.close();
+ }
+ else
+ {
+ cout << "File not found or couldn't open: " << filename << endl;
+ return false;
+ }
+
+}
diff --git a/source/code/replay.h b/source/code/replay.h new file mode 100644 index 0000000..fbac67b --- /dev/null +++ b/source/code/replay.h
@@ -0,0 +1,88 @@
+/*
+replay.h
+Copyright (C) 2005 Poul Sander
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Poul Sander
+ R�veh�jvej 36, V. 1111
+ 2800 Kgs. Lyngby
+ DENMARK
+ blockattack@poulsander.com
+*/
+
+//headerfile for replay.h
+/*
+replay is used to save a replay, there is saved 10 moves per second, should be
+able to give a realistic replay
+*/
+
+//constants - 3000 is 5 minutes
+#define FRAMESPERSEC 10
+
+#include "SDL.h"
+#include <stdlib.h>
+#include <iostream>
+#include <fstream>
+#include <vector>
+
+using namespace std;
+
+//board_package, stores a board can be used for network play and replay
+struct boardPackage //92 bytes
+{
+ Uint32 time; //game time
+ Uint8 brick[6][13];
+ Uint8 pixels; //pixels pushed
+ Uint8 cursorX; //Cursor coordinate
+ Uint8 cursorY; // -||-
+ Uint32 score;
+ Uint8 speed;
+ Uint8 chain;
+ Uint8 result; //0=none,1=gameOver,2=winner,4=draw
+};
+
+class Replay{
+private:
+//Our replay is stored in an array of TOTALFRAMES length
+ //boardPackage bps[TOTALFRAMES];
+ vector<boardPackage> bps;
+//The final package is not set to any specific time
+ boardPackage finalPack;
+//We store number of frames, so we know how long to read the array
+ Uint32 nrOfFrames;
+//An enumerator, so we know how it ends! (should be removed then boardPackage is the 92 byte version)
+ enum { gameOver=0, winner, looser, draw } theResult;
+//If we are loaded from a file, then we are read only
+ bool isLoaded;
+
+public:
+ Replay(); //Constructor
+ Replay(const Replay& r); //Copy constructor
+ Uint32 getNumberOfFrames(); //Returns number of frames
+ void setFrameSecTo(Uint32,boardPackage); //Sets frame at a given time to the package
+ void setFinalFrame(boardPackage,int); //Sets the final package
+ boardPackage getFrameSec(Uint32); //Gets a frame to a time
+ boardPackage getFinalFrame(); //Gets the last frame, that must remain
+ int getFinalStatus(); //Return the result: winner, looser, draw or gameOver
+ bool isFinnished(Uint32); //Returns true if we are done
+
+//Ok, I'll ignore this for some time, and just save to file, if however, we ever use a dynamic saving structure, we are fucked
+ bool saveReplay(string); //Saves a replay
+ bool saveReplay(string,Replay p2); //saves a replay, plus another replay given as a parameter
+ bool loadReplay(string); //laods a replay
+ bool loadReplay2(string); //loads the second part of the replay file, if it exists, returns false otherwise
+
+};
diff --git a/source/code/stats.cc b/source/code/stats.cc new file mode 100644 index 0000000..f179843 --- /dev/null +++ b/source/code/stats.cc
@@ -0,0 +1,112 @@
+/*
+Block Attack - Rise of the Blocks, SDL game, besed on Nintendo's Tetris Attack
+Copyright (C) 2008 Poul Sander
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Poul Sander
+ R�vehjvej 36, V. 1111
+ 2800 Kgs. Lyngby
+ DENMARK
+ blockattack@poulsander.com
+ http://blockattack.sf.net
+*/
+
+#include "stats.h"
+#include "common.h"
+
+Stats* Stats::instance = 0;
+
+Stats::Stats()
+{
+ statMap.clear();
+ load();
+}
+
+void Stats::load()
+{
+ string filename = getPathToSaveFiles()+"/statsFile";
+ ifstream inFile(filename.c_str());
+ string key;
+ unsigned int value;
+ if(inFile)
+ {
+ //int antal;
+ //inFile >> antal;
+ //for(int i = 0;i<antal;i++)
+ while(!inFile.eof())
+ {
+ inFile >> key;
+ inFile >> value;
+ statMap[key] = value;
+ }
+ inFile.close();
+ }
+}
+
+Stats* Stats::getInstance()
+{
+ if(Stats::instance==0)
+ {
+ Stats::instance = new Stats();
+
+ }
+ return Stats::instance;
+}
+
+void Stats::save()
+{
+ string filename = getPathToSaveFiles()+"/statsFile";
+ ofstream outFile(filename.c_str(),ios::trunc);
+
+ if(outFile)
+ {
+ //outFile << statMap.size() << endl;
+ map<string,unsigned int>::iterator iter;
+ for(iter = statMap.begin(); iter != statMap.end(); iter++)
+ {
+ outFile << iter->first << " " << iter->second << endl;
+ }
+ }
+}
+
+unsigned int Stats::getNumberOf(string statName)
+{
+ if(exists(statName))
+ {
+ return statMap[statName];
+ }
+ else
+ return 0;
+}
+
+void Stats::addOne(string statName)
+{
+ map<string,unsigned int>::iterator iter = statMap.find(statName);
+ if(iter == statMap.end())
+ {
+ statMap[statName] = 1;
+ }
+ else
+ {
+ iter->second++;
+ }
+}
+
+bool Stats::exists(string statName)
+{
+ //Using that find returns an iterator to the end of the map if not found
+ return statMap.find(statName) != statMap.end();
+}
diff --git a/source/code/stats.h b/source/code/stats.h new file mode 100644 index 0000000..8bf93a9 --- /dev/null +++ b/source/code/stats.h
@@ -0,0 +1,74 @@
+/*
+Block Attack - Rise of the Blocks, SDL game, besed on Nintendo's Tetris Attack
+Copyright (C) 2008 Poul Sander
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Poul Sander
+ R�vehjvej 36, V. 1111
+ 2800 Kgs. Lyngby
+ DENMARK
+ blockattack@poulsander.com
+ http://blockattack.sf.net
+*/
+
+//
+// File: stats.h
+// Author: poul
+//
+// Created on 11. februar 2008, 20:19
+//
+
+#ifndef _STATS_H
+#define _STATS_H
+
+using namespace std;
+
+#include <map>
+#include <string>
+
+
+
+
+class Stats
+{
+private:
+ map<string,unsigned int> statMap;
+
+ static Stats *instance;
+
+ void load();
+protected:
+
+ Stats();
+
+
+public:
+
+ static Stats* getInstance();
+
+ void save();
+
+ unsigned int getNumberOf(string statName);
+
+ void addOne(string statName);
+
+ bool exists(string statName);
+
+
+};
+
+#endif /* _STATS_H */
+
diff --git a/source/code/ttfont.cc b/source/code/ttfont.cc new file mode 100644 index 0000000..482f433 --- /dev/null +++ b/source/code/ttfont.cc
@@ -0,0 +1,115 @@
+/*
+Block Attack - Rise of the Blocks, SDL game, besed on Nintendo's Tetris Attack
+Copyright (C) 2008 Poul Sander
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Poul Sander
+ R�vehjvej 36, V. 1111
+ 2800 Kgs. Lyngby
+ DENMARK
+ blockattack@poulsander.com
+ http://blockattack.sf.net
+*/
+
+#include "ttfont.h"
+
+TTFont::TTFont()
+{
+ font = NULL;
+ actualInstance = false;
+}
+
+int TTFont::count = 0;
+
+TTFont::TTFont(TTF_Font *f)
+{
+ if(!(TTF_WasInit()))
+ {
+ //Init TTF for the first time
+ TTF_Init();
+ }
+
+
+ if(f == NULL)
+ cout << "Font was null!" << endl;
+
+ actualInstance = false; //We have not yet copied to final location
+ font = f;
+
+}
+
+TTFont::~TTFont()
+{
+ if(!actualInstance)
+ return;
+
+ cout << "Closing a font" << endl;
+
+ TTF_CloseFont(font);
+ font = NULL;
+
+ count--;
+ if(count==0)
+ TTF_Quit();
+}
+
+//Copy constructor, you cannot copy an actual instance
+TTFont::TTFont(const TTFont &t)
+{
+ if(t.font == NULL || t.actualInstance)
+ {
+ font = NULL;
+ actualInstance = false;
+ }
+ else
+ {
+ font = t.font;
+ actualInstance = true;
+ count++;
+ }
+}
+
+int TTFont::getTextHeight()
+{
+ return TTF_FontHeight(font);
+}
+
+int TTFont::getTextWidth(string text)
+{
+ int width = 0;
+ if(TTF_SizeText(font,text.c_str(),&width,NULL)!=0)
+ cout << "Failed to get text width!" << endl;
+ return width;
+}
+
+void TTFont::writeText(string text, SDL_Surface *target, int x, int y)
+{
+ SDL_Surface *text_surface;
+ SDL_Color color={255,255,255};
+ if(!(text_surface=TTF_RenderText_Solid(font,text.c_str(), color)))
+ {
+ cout << "Error writing text: " << TTF_GetError() << endl;
+ }
+ else
+ {
+ SDL_Rect dest;
+ dest.x = x;
+ dest.y = y;
+ SDL_BlitSurface(text_surface,NULL,target,&dest);
+ SDL_FreeSurface(text_surface);
+ }
+}
+
diff --git a/source/code/ttfont.h b/source/code/ttfont.h new file mode 100644 index 0000000..3b0fd2f --- /dev/null +++ b/source/code/ttfont.h
@@ -0,0 +1,65 @@
+/*
+Block Attack - Rise of the Blocks, SDL game, besed on Nintendo's Tetris Attack
+Copyright (C) 2008 Poul Sander
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Poul Sander
+ R�vehjvej 36, V. 1111
+ 2800 Kgs. Lyngby
+ DENMARK
+ blockattack@poulsander.com
+ http://blockattack.sf.net
+*/
+
+//
+// File: ttfont.hpp.h
+// Author: poul
+//
+// Created on 25. december 2007, 13:52
+//
+
+#ifndef _TTFONT_H
+#define _TTFONT_H
+
+#include <stdlib.h>
+#include <iostream>
+#include <string>
+#include "SDL.h"
+#include "SDL_ttf.h" //To use True Type Fonts in SDL
+
+using namespace std;
+
+class TTFont
+{
+private:
+ static int count; //The total number of instances
+ TTF_Font *font;
+ bool actualInstance;
+
+public:
+ TTFont();
+ TTFont(TTF_Font *f);
+ TTFont(const TTFont &t);
+ ~TTFont();
+
+ int getTextWidth(string text);
+ int getTextHeight();
+ void writeText(string text, SDL_Surface *target, int x, int y);
+
+};
+
+#endif /* _TTFONT_H */
+
diff --git a/source/code/uploadReplay.cc b/source/code/uploadReplay.cc new file mode 100644 index 0000000..22ae53e --- /dev/null +++ b/source/code/uploadReplay.cc
@@ -0,0 +1,88 @@
+/*
+Block Attack - Rise of the Blocks, SDL game, besed on Nintendo's Tetris Attack
+Copyright (C) 2008 Poul Sander
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Poul Sander
+ R�vehjvej 36, V. 1111
+ 2800 Kgs. Lyngby
+ DENMARK
+ blockattack@poulsander.com
+ http://blockattack.sf.net
+*/
+
+#include "uploadReplay.h"
+#include "common.h"
+
+bool isDownloading;
+bool uploadReplayInitialized;
+bool thresholdUp2Date;
+
+SDL_Thread *threadThresholdFile;
+
+void uploadReplay_init()
+{
+ if(uploadReplayInitialized)
+ return;
+ //mutDownload = SDL_CreateMutex();
+ mutUpload = SDL_CreateMutex();
+ thresholdUp2Date = false;
+}
+
+int downloadThresholdFile(void *ptr)
+{
+ //if(SDL_mutexP(mutDownload)==-1){
+ // isDownloading = false;
+ // return -1; //We don't crash if we can't lock. Just failing to do so
+ //}
+ FILE *outfile;
+ CURL *easyhandle = curl_easy_init();
+ if(!easyhandle){
+ isDownloading=false;
+ //SDL_mutexV(mutDownload);
+ return -1;
+ }
+ string filename = getPathToSaveFiles()+"/scoreThreshold";
+ outfile = fopen(filename.c_str(), "w");
+
+ curl_easy_setopt(easyhandle, CURLOPT_URL, "http://localhost/~poul/blockattackHighscores/result/threshold");
+ curl_easy_setopt(easyhandle, CURLOPT_WRITEDATA, outfile);
+
+ CURLcode res = curl_easy_perform(easyhandle);
+
+ fclose(outfile);
+
+ if(res == 200)
+ thresholdUp2Date = true;
+
+ curl_easy_cleanup(easyhandle);
+ isDownloading=false;
+ //if(SDL_mutexV(mutDownload)==-1){
+ //return 0; //We don't crash if we can't lock. Just failing to do so
+ //}
+ return 0;
+}
+
+bool uploadReplay_canUpload()
+{
+ if(thresholdUp2Date)
+ return true;
+ if(isDownloading)
+ return false;
+ isDownloading=true; //We mark before start the thread
+ threadThresholdFile = SDL_CreateThread(downloadThresholdFile, NULL);
+ return thresholdUp2Date;
+}
diff --git a/source/code/uploadReplay.h b/source/code/uploadReplay.h new file mode 100644 index 0000000..16ede86 --- /dev/null +++ b/source/code/uploadReplay.h
@@ -0,0 +1,31 @@
+//
+// File: uploadReplay.h
+// Author: poul
+//
+// Created on 26. februar 2008, 00:12
+//
+
+#ifndef _UPLOADREPLAY_H
+#define _UPLOADREPLAY_H
+
+#define HIGHSCORESERVER http://localhost/~poul/blockattackHighscores/result/
+
+#include <curl/curl.h>
+#include "SDL.h"
+
+using namespace std;
+
+SDL_mutex *mutDownload,*mutUpload;
+
+bool uploadReplay_canUpload();
+
+void uploadReplay_upload();
+
+
+class OnlineHighscores
+{
+
+};
+
+#endif /* _UPLOADREPLAY_H */
+