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. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/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 @@ + 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. + + --> + + + Goneri"> + Le Bouder"> + + mai 19, 2006"> + + 6"> + goneri@rulezlan.org"> + + BLOCKATTACK"> + + + Debian"> + GNU"> + GPL"> +]> + + + +
+ &dhemail; +
+ + &dhfirstname; + &dhsurname; + + + 2006 + &dhusername; + + &dhdate; +
+ + &dhucpackage; + + &dhsection; + + + &dhpackage; + + Rise of the Blocks + + + DESCRIPTION + + This manual page documents briefly the + &dhpackage;. + + + This manual page was written for the &debian; distribution + because the original program does not have a manual page. + . + + + + + OPTIONS + + These programs don't have specific option. + + + + AUTHOR + + 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. + + + On Debian systems, the complete text of the GNU General Public + License can be found in /usr/share/common-licenses/GPL. + + + +
+ + + + 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 +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 + +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=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 -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(Level0) { + 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-startPosition999999) 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 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; k2) + for (int k = i-combo; k-1)&&(board[j][i]%10000000<7))) { + if (board[j][i]%10000000 == previus) { + combo++; + } + else { + if (combo>2) + for (int k = j-combo; k2) + for (int k = j-combo; k2) && (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;i1)) 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;j12) ||(((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)) && (gameStartedAt0)) 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) && (gameStartedAt0;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+1AIlineToClear) + MoveCursor('S'); + else + if (cursorxxplace) + 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 (cursory2) { + 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 (leftleft"; + 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 (cursorxxplace) + 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+1closestTo(AIlineToClear, AIcolorToClear, placeToCenter)) + MoveCursor('W'); + else + if (cursorxclosestTo(AIlineToClear+1, AIcolorToClear, placeToCenter)) + MoveCursor('W'); + else + if (cursorxclosestTo(AIlineToClear+2, AIcolorToClear, placeToCenter)) + MoveCursor('W'); + else + if (cursorx5) 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(LevelstageClearLimit) && (stageClear) && (!bGameOver)) { + stageCleared[Level] = true; + if(stageScores[Level](&tempBool), sizeof(bool)); + } + for (int i=0;i(&tempUInt32), sizeof(Uint32)); + } + for (int i=0;i(&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(&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_MoveSpeedgameStartedAt+nrFellDown*140) && (!bGameOver)) FallDown(); + if ((nowTimegameStartedAt+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)&& (position0) + { + 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 +#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 + +#include +#include +#include "SFont.h" + +static long GetPixel(SDL_Surface *Surface, Sint32 X, Sint32 Y) +{ + Uint8 *bits; + Uint32 Bpp; + + assert(X>=0); + assert(Xw); + + 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 * +* * +* 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 + +#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 +#include +#include +#include + +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> 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;i49)||(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::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 +#include +#include +#include + +#ifndef BOARDHOLDERDEFINED +#define BOARDHOLDERDEFINED +class BoardHolder +{ + + private: + vector 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=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; i0) + 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;idraw(); + } +} + +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;iclick(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 + +//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 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(&tabel[i].score), sizeof(int)); + } + } + else + { + for (int i = 0; i(&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].scoreranking; 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 +#include +#include +#include +#include + +#ifdef _WIN32 +#ifndef CSIDL_PERSONAL +#define CSIDL_PERSONAL 0x0005 +#endif +#define _WIN32_IE 0x0400 +#include "windows.h" +#include +#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=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=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) + 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 +#include +#include + +#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;id_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))&&(nrOfFilesd_name; + if (!isInList(name)) + { + nrOfFiles++; + filenames[nrOfFiles] = name; + } + } + closedir(DirectoryPointer); + + startFileNr=FIRST_FILE; +#endif +} + +string ListFiles::getFileName(int nr) +{ + if (startFileNr+nrFIRST_FILE) + startFileNr = startFileNr-10; + if (startFileNr +#include +#if defined(_WIN32) +#include +#elif defined(__unix__) +#include +#endif +#include +#include + +#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 +#include +#include //Used for srand() +#include +#include +#include "SDL.h" //The SDL libary, used for most things +#include //Used for sound & music +#include //To load PNG images! +#include "ttfont.h" //To use True Type Fonts in SDL +//#include "config.h" +#include + +//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> 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; i800) + { + 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 (!(frameNumbertime; + } + + 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(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;ix+460) && (mousexy+420) && (mouseyx+20) && (mousexy+420) && (mouseyx+10) && (mousexy+10+i*36) && (mouseyx+460) && (mousexy+420) && (mouseyx+20) && (mousexy+420) && (mouseyx+10) && (mousexy+10+i*36) && (mouseyx+460) && (mousexy+420) && (mouseyx+20) && (mousexy+420) && (mouseyx+10) && (mousexy+10+i*36) && (mousey=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(&tempBool),sizeof(bool)); + puzzleCleared[i] = tempBool; + } + puzzleFile.close(); + } + else + { + tempBool = false; + for (int i=0; i(&tempBool),sizeof(bool)); + stageCleared[i]=tempBool; + } + if(!stageFile.eof()) + { + for(int i=0; i(&tempUInt32),sizeof(Uint32)); + stageScores[i]=tempUInt32; + totalScore+=tempUInt32; + } + for(int i=0; i(&tempUInt32),sizeof(Uint32)); + stageTimes[i]=tempUInt32; + totalTime += tempUInt32; + } + } + else + { + for(int i=0; i0) + 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)&&(mousexyplace+10+i*30)&&(mouseyxplace+50+70)&&(mousey>yplace+200)&&(mousexxplace+50+70+300)&&(mousey>yplace+200)&&(mousexxplace+50+i*40)&&(mousexyplace+150)&&(mouseyxplace+50+i*40+300)&&(mousexyplace+150)&&(mouseyxplace+50+i*40)&&(mousexyplace+330)&&(mouseyxplace+50+i*40+300)&&(mousexyplace+330)&&(mousey1024/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(&xsize), sizeof(int)); + optionsFile.read(reinterpret_cast(&ysize), sizeof(int)); + optionsFile.read(reinterpret_cast(&bFullscreen), sizeof(bool)); + optionsFile.read(reinterpret_cast(&keySettings[0].up), sizeof(SDLKey)); + optionsFile.read(reinterpret_cast(&keySettings[0].down), sizeof(SDLKey)); + optionsFile.read(reinterpret_cast(&keySettings[0].left), sizeof(SDLKey)); + optionsFile.read(reinterpret_cast(&keySettings[0].right), sizeof(SDLKey)); + optionsFile.read(reinterpret_cast(&keySettings[0].change), sizeof(SDLKey)); + optionsFile.read(reinterpret_cast(&keySettings[0].push), sizeof(SDLKey)); + optionsFile.read(reinterpret_cast(&keySettings[2].up), sizeof(SDLKey)); + optionsFile.read(reinterpret_cast(&keySettings[2].down), sizeof(SDLKey)); + optionsFile.read(reinterpret_cast(&keySettings[2].left), sizeof(SDLKey)); + optionsFile.read(reinterpret_cast(&keySettings[2].right), sizeof(SDLKey)); + optionsFile.read(reinterpret_cast(&keySettings[2].change), sizeof(SDLKey)); + optionsFile.read(reinterpret_cast(&keySettings[2].push), sizeof(SDLKey)); + optionsFile.read(reinterpret_cast(&MusicEnabled), sizeof(bool)); + optionsFile.read(reinterpret_cast(&SoundEnabled), sizeof(bool)); + optionsFile.read(player1name, 30*sizeof(char)); + optionsFile.read(player2name, 30*sizeof(char)); + //mouseplay? + if (!optionsFile.eof()) + { + optionsFile.read(reinterpret_cast(&mouseplay1), sizeof(bool)); + optionsFile.read(reinterpret_cast(&mouseplay2), sizeof(bool)); + optionsFile.read(reinterpret_cast(&joyplay1),sizeof(bool)); + optionsFile.read(reinterpret_cast(&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)&&(mousex10)&&(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 ((0Save 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 ((360Load 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(&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-120mousex) && (ysize-120mousey)) + { + //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 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)&&(mousextheGame2.score+theGame2.handicap) + theGame.setPlayerWon(); + else + if (theGame.score+theGame.handicap(&xsize),sizeof(int)); + optionsFileOut.write(reinterpret_cast(&ysize),sizeof(int)); + optionsFileOut.write(reinterpret_cast(&bFullscreen),sizeof(bool)); + optionsFileOut.write(reinterpret_cast(&keySettings[0].up), sizeof(SDLKey)); + optionsFileOut.write(reinterpret_cast(&keySettings[0].down), sizeof(SDLKey)); + optionsFileOut.write(reinterpret_cast(&keySettings[0].left), sizeof(SDLKey)); + optionsFileOut.write(reinterpret_cast(&keySettings[0].right), sizeof(SDLKey)); + optionsFileOut.write(reinterpret_cast(&keySettings[0].change), sizeof(SDLKey)); + optionsFileOut.write(reinterpret_cast(&keySettings[0].push), sizeof(SDLKey)); + optionsFileOut.write(reinterpret_cast(&keySettings[2].up), sizeof(SDLKey)); + optionsFileOut.write(reinterpret_cast(&keySettings[2].down), sizeof(SDLKey)); + optionsFileOut.write(reinterpret_cast(&keySettings[2].left), sizeof(SDLKey)); + optionsFileOut.write(reinterpret_cast(&keySettings[2].right), sizeof(SDLKey)); + optionsFileOut.write(reinterpret_cast(&keySettings[2].change), sizeof(SDLKey)); + optionsFileOut.write(reinterpret_cast(&keySettings[2].push), sizeof(SDLKey)); + optionsFileOut.write(reinterpret_cast(&MusicEnabled),sizeof(bool)); + optionsFileOut.write(reinterpret_cast(&SoundEnabled),sizeof(bool)); + optionsFileOut.write(player1name,30*sizeof(char)); + optionsFileOut.write(player2name,30*sizeof(char)); + optionsFileOut.write(reinterpret_cast(&mouseplay1),sizeof(bool)); + optionsFileOut.write(reinterpret_cast(&mouseplay2),sizeof(bool)); + optionsFileOut.write(reinterpret_cast(&joyplay1),sizeof(bool)); + optionsFileOut.write(reinterpret_cast(&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 stageCleared(nrOfStageLevels); //vector that tells if a stage is cleared +vector stageTimes(nrOfStageLevels); //For statistical puposes +vector stageScores(nrOfStageLevels); //--||-- +vector puzzleCleared(maxNrOfPuzzleStages); //vector that tells if puzzle cleared +vector 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(&version),sizeof(Uint32)); //Fileversion + Uint8 nrOfReplays = 1; + saveFile.write(reinterpret_cast(&nrOfReplays),sizeof(Uint8)); //nrOfReplaysIn File + saveFile.write(reinterpret_cast(&nrOfFrames),sizeof(Uint32)); //Nr of frames in file + for (int i=0; i(&bp.time),sizeof(Uint32)); + for (int k=0;k<6;k++) + for (int g=0;g<13;g++) + { + saveFile.write(reinterpret_cast(&bp.brick[k][g]),sizeof(Uint8)); + } + saveFile.write(reinterpret_cast(&bp.pixels),sizeof(Uint8)); + saveFile.write(reinterpret_cast(&bp.cursorX),sizeof(Uint8)); + saveFile.write(reinterpret_cast(&bp.cursorY),sizeof(Uint8)); + saveFile.write(reinterpret_cast(&bp.score),sizeof(Uint32)); + saveFile.write(reinterpret_cast(&bp.speed),sizeof(Uint8)); + saveFile.write(reinterpret_cast(&bp.chain),sizeof(Uint8)); + + } + saveFile.write(reinterpret_cast(&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(&version),sizeof(Uint32)); //Fileversion + Uint8 nrOfReplays = 2; + saveFile.write(reinterpret_cast(&nrOfReplays),sizeof(Uint8)); //nrOfReplaysIn File + saveFile.write(reinterpret_cast(&nrOfFrames),sizeof(Uint32)); //Nr of frames in file + for (int i=0; i(&bp.time),sizeof(Uint32)); + for (int k=0;k<6;k++) + for (int g=0;g<13;g++) + saveFile.write(reinterpret_cast(&bp.brick[k][g]),sizeof(Uint8)); + saveFile.write(reinterpret_cast(&bp.pixels),sizeof(Uint8)); + saveFile.write(reinterpret_cast(&bp.cursorX),sizeof(Uint8)); + saveFile.write(reinterpret_cast(&bp.cursorY),sizeof(Uint8)); + saveFile.write(reinterpret_cast(&bp.score),sizeof(Uint32)); + saveFile.write(reinterpret_cast(&bp.speed),sizeof(Uint8)); + saveFile.write(reinterpret_cast(&bp.chain),sizeof(Uint8)); + } + saveFile.write(reinterpret_cast(&finalPack),sizeof(finalPack)); + ///Player 2 starts here!!!!!!!!!!!!!!!!!!!!!! + saveFile.write(reinterpret_cast(&p2.nrOfFrames),sizeof(Uint32)); //Nr of frames in file + for (int i=0; (i(&bp.time),sizeof(Uint32)); + for (int k=0;k<6;k++) + for (int g=0;g<13;g++) + saveFile.write(reinterpret_cast(&bp.brick[k][g]),sizeof(Uint8)); + saveFile.write(reinterpret_cast(&bp.pixels),sizeof(Uint8)); + saveFile.write(reinterpret_cast(&bp.cursorX),sizeof(Uint8)); + saveFile.write(reinterpret_cast(&bp.cursorY),sizeof(Uint8)); + saveFile.write(reinterpret_cast(&bp.score),sizeof(Uint32)); + saveFile.write(reinterpret_cast(&bp.speed),sizeof(Uint8)); + saveFile.write(reinterpret_cast(&bp.chain),sizeof(Uint8)); + } + saveFile.write(reinterpret_cast(&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(&version),sizeof(Uint32)); + switch (version) + { + case 2: + cout << "Loading a version 2 save game" << endl; + Uint8 nrOfPlayers; + boardPackage bp; + loadFile.read(reinterpret_cast(&nrOfPlayers),sizeof(Uint8)); + loadFile.read(reinterpret_cast(&nrOfFrames),sizeof(Uint32)); + bps.clear(); + for (int i=0; (i(&bp.time),sizeof(Uint32)); //Writing frames + for (int k=0;k<6;k++) + for (int g=0;g<13;g++) + loadFile.read(reinterpret_cast(&bp.brick[k][g]),sizeof(Uint8)); + loadFile.read(reinterpret_cast(&bp.pixels),sizeof(Uint8)); + loadFile.read(reinterpret_cast(&bp.cursorX),sizeof(Uint8)); + loadFile.read(reinterpret_cast(&bp.cursorY),sizeof(Uint8)); + loadFile.read(reinterpret_cast(&bp.score),sizeof(Uint32)); + loadFile.read(reinterpret_cast(&bp.speed),sizeof(Uint8)); + loadFile.read(reinterpret_cast(&bp.chain),sizeof(Uint8)); + bps.push_back(bp); + } + loadFile.read(reinterpret_cast(&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(&version),sizeof(Uint32)); + switch (version) + { + case 2: + Uint8 nrOfPlayers; + boardPackage bp; + loadFile.read(reinterpret_cast(&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(&nrOfFrames),sizeof(Uint32)); + for (int i=0; (i(&bp.time),sizeof(Uint32)); //Writing frames + for (int k=0;k<6;k++) + for (int g=0;g<13;g++) + loadFile.read(reinterpret_cast(&bp.brick[k][g]),sizeof(Uint8)); + loadFile.read(reinterpret_cast(&bp.pixels),sizeof(Uint8)); + loadFile.read(reinterpret_cast(&bp.cursorX),sizeof(Uint8)); + loadFile.read(reinterpret_cast(&bp.cursorY),sizeof(Uint8)); + loadFile.read(reinterpret_cast(&bp.score),sizeof(Uint32)); + loadFile.read(reinterpret_cast(&bp.speed),sizeof(Uint8)); + loadFile.read(reinterpret_cast(&bp.chain),sizeof(Uint8)); + //bps.push_back(bp); + } + loadFile.read(reinterpret_cast(&finalPack),sizeof(finalPack)); + loadFile.read(reinterpret_cast(&nrOfFrames),sizeof(Uint32)); + bps.reserve(nrOfFrames); + for (int i=0; (i(&bp.time),sizeof(Uint32)); //Writing frames + for (int k=0;k<6;k++) + for (int g=0;g<13;g++) + loadFile.read(reinterpret_cast(&bp.brick[k][g]),sizeof(Uint8)); + loadFile.read(reinterpret_cast(&bp.pixels),sizeof(Uint8)); + loadFile.read(reinterpret_cast(&bp.cursorX),sizeof(Uint8)); + loadFile.read(reinterpret_cast(&bp.cursorY),sizeof(Uint8)); + loadFile.read(reinterpret_cast(&bp.score),sizeof(Uint32)); + loadFile.read(reinterpret_cast(&bp.speed),sizeof(Uint8)); + loadFile.read(reinterpret_cast(&bp.chain),sizeof(Uint8)); + bps.push_back(bp); + } + loadFile.read(reinterpret_cast(&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 +#include +#include +#include + +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 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> 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::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::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 +#include + + + + +class Stats +{ +private: + map 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 +#include +#include +#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 +#include "SDL.h" + +using namespace std; + +SDL_mutex *mutDownload,*mutUpload; + +bool uploadReplay_canUpload(); + +void uploadReplay_upload(); + + +class OnlineHighscores +{ + +}; + +#endif /* _UPLOADREPLAY_H */ +