1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/PTdecode/CImg-1.3.0/examples/jawbreaker.cpp Mon Aug 03 14:09:20 2009 +0100 1.3 @@ -0,0 +1,237 @@ 1.4 +/* 1.5 + # 1.6 + # File : jawbreaker.cpp 1.7 + # ( C++ source file ) 1.8 + # 1.9 + # Description : A funny game featuring small colored balls. 1.10 + # This file is a part of the CImg Library project. 1.11 + # ( http://cimg.sourceforge.net ) 1.12 + # 1.13 + # Copyright : David Tschumperle 1.14 + # ( http://www.greyc.ensicaen.fr/~dtschump/ ) 1.15 + # 1.16 + # License : CeCILL v2.0 1.17 + # ( http://www.cecill.info/licences/Licence_CeCILL_V2-en.html ) 1.18 + # 1.19 + # This software is governed by the CeCILL license under French law and 1.20 + # abiding by the rules of distribution of free software. You can use, 1.21 + # modify and/ or redistribute the software under the terms of the CeCILL 1.22 + # license as circulated by CEA, CNRS and INRIA at the following URL 1.23 + # "http://www.cecill.info". 1.24 + # 1.25 + # As a counterpart to the access to the source code and rights to copy, 1.26 + # modify and redistribute granted by the license, users are provided only 1.27 + # with a limited warranty and the software's author, the holder of the 1.28 + # economic rights, and the successive licensors have only limited 1.29 + # liability. 1.30 + # 1.31 + # In this respect, the user's attention is drawn to the risks associated 1.32 + # with loading, using, modifying and/or developing or reproducing the 1.33 + # software by the user in light of its specific status of free software, 1.34 + # that may mean that it is complicated to manipulate, and that also 1.35 + # therefore means that it is reserved for developers and experienced 1.36 + # professionals having in-depth computer knowledge. Users are therefore 1.37 + # encouraged to load and test the software's suitability as regards their 1.38 + # requirements in conditions enabling the security of their systems and/or 1.39 + # data to be ensured and, more generally, to use and operate it in the 1.40 + # same conditions as regards security. 1.41 + # 1.42 + # The fact that you are presently reading this means that you have had 1.43 + # knowledge of the CeCILL license and that you accept its terms. 1.44 + # 1.45 +*/ 1.46 + 1.47 +#include "CImg.h" 1.48 +using namespace cimg_library; 1.49 + 1.50 +// The lines below are necessary when using a non-standard compiler as visualcpp6. 1.51 +#ifdef cimg_use_visualcpp6 1.52 +#define std 1.53 +#endif 1.54 +#ifdef max 1.55 +#undef max 1.56 +#endif 1.57 + 1.58 +// Start main procedure 1.59 +//---------------------- 1.60 +int main(int argc, char **argv) { 1.61 + 1.62 + // Display help (if option '-h' or '--help' specified) and retrieve program arguments 1.63 + cimg_usage("A small and funny game featuring colored balls.\n (by David Tschumperle)."); 1.64 + const char *score_file = cimg_option("-s",(char*)0,"Specify score file to use (0=default file)."); 1.65 + cimg_help("\n" 1.66 + "** Quick Help *********************************************************\n\n" 1.67 + "Goal : Delete the board by clicking on groups of adjacent colored balls\n" 1.68 + " (a group is made of at least two balls with the same color).\n" 1.69 + " Suppressing large sets gives higher scores.\n\n" 1.70 + "In-game keys : - BACKSPACE or SPACE = Undo last move\n" 1.71 + " - CTRL+F = Toggle fullscreen mode\n" 1.72 + " - ESC = Quit application\n" 1.73 + " - Q = End current game\n\n" 1.74 + "*********************************************************************"); 1.75 + 1.76 + // Load score file if available 1.77 + CImgList<unsigned int> score_history; 1.78 + char filename_history[1024]; 1.79 + std::sprintf(filename_history,"%s%s",score_file?"":cimg::temporary_path(),score_file?score_file:"/jawbreaker.score"); 1.80 + std::FILE *file = std::fopen(filename_history,"r"); 1.81 + if (file) { std::fclose(file); score_history = CImg<unsigned int>::get_load_dlm(filename_history).get_split('y'); } 1.82 + 1.83 + // Create ball graphics 1.84 + const unsigned int W = 12, H = 14, Wi = (W<<5), Hi = (H<<5); 1.85 + unsigned int score = 0, previous_score = 0, shape_score = 0, 1.86 + best_score = score_history?score_history.max():0U; 1.87 + 1.88 + const CImg<> colors(3,7,1,1, 255,255,255, 205,0,230, 0,235,0, 235,255,0, 235,0,0, 0,128,255, 450,350,300); 1.89 + const unsigned char 1.90 + white[] = { 255,255,255 }, orange[] = { 255,128,64 }, yellow[] = { 255,255,64 }, red[] = { 255,64,64 }, six = 6; 1.91 + CImgList<> balls0(7,32,32,1,3,0); 1.92 + cimglist_for(balls0,l) if (l) { 1.93 + balls0[l].draw_circle(16,16,14,colors.ptr(0,l)); 1.94 + cimg_forXYV(balls0[l],x,y,k) if (balls0(l,x,y,k)) (balls0(l,x,y,k)*=(32-x+y)/60.0f)+=20; 1.95 + balls0[l].draw_circle(16,16,14,colors.ptr(0,l),0.5f,~0U). 1.96 + draw_circle(20,10,5,colors,0.2f).draw_circle(22,8,2,colors,0.4f).cut(0,255); 1.97 + } 1.98 + 1.99 + // Create background graphics 1.100 + CImgList<unsigned char> balls(balls0); 1.101 + CImg<unsigned char> 1.102 + mask = balls[1].get_cut(0,1).channel(0).dilate(3), 1.103 + background = CImg<unsigned char>(Wi,Hi,1,3,0). 1.104 + noise(255,1).blur(6,20,0).equalize(100,0,255).blur(2,4,0); 1.105 + background.get_shared_channel(0)/=4; background.get_shared_channel(1)/=8; background.get_shared_channel(2)/=2; 1.106 + 1.107 + // Begin user-interaction loop. 1.108 + CImg<unsigned char> board, previous_board, selected_board, shape, img(background); 1.109 + CImgDisplay disp(img.dimx(),img.dimy(),"Jawbreaker",0); 1.110 + bool redraw = true, gameover = false, title = true; 1.111 + for (float opac = 0.0f; !disp.is_closed; ) { 1.112 + 1.113 + // Init board 1.114 + if (!board) { 1.115 + (++((board.assign(W,H,1,1,5).noise(5,1))%=5)).get_shared_line(0).fill(0); 1.116 + opac = (float)(score = previous_score = shape_score = 0); 1.117 + gameover = false; redraw = title = true; 1.118 + previous_board = board; 1.119 + } 1.120 + 1.121 + // Draw graphical board 1.122 + if (redraw) { 1.123 + (img=background).draw_text(2,2,"Score : %u",yellow,0,0.7f,24,score). 1.124 + draw_text(Wi-90,2,"Best : %u",orange,0,0.9f,16,best_score); 1.125 + if (selected_board) { 1.126 + cimg_forXY(selected_board,x,y) if (selected_board(x,y)) 1.127 + img.draw_image(x<<5,y<<5,balls[selected_board(x,y)],mask); 1.128 + } else cimg_forXY(board,x,y) if (board(x,y)) img.draw_image(x<<5,y<<5,balls[board(x,y)],mask); 1.129 + if (title) { 1.130 + CImg<unsigned char> text1, text2; 1.131 + text1.draw_text(0,0,"- Jawbreaker -",white,0,1,48); 1.132 + text2.draw_text(0,0,"Press button to start",yellow,0,1,24); 1.133 + (img/=2).draw_image((Wi-text1.dimx())/2, 1.134 + (Hi-text1.dimy())/2, 1.135 + text1,text1.get_dilate(7),1,255). 1.136 + draw_image((Wi-text2.dimx())/2, 1.137 + (Hi+text1.dimy()+10)/2, 1.138 + text2,text2.get_dilate(5),0.7f,255); 1.139 + for (float i=1; i<10 && !disp.is_keyESC; i+=0.25) 1.140 + disp.display(img.get_crop((int)(Wi*(0.5f-i*i/200.0f)),(int)(Hi*(0.5f-i*i*i*i/20000.0f)), 1.141 + (int)(Wi*(0.5f+i*i/200.0f)),(int)(Hi*(0.5f+i*i*i*i/20000.0f)))).wait(20); 1.142 + } 1.143 + } 1.144 + if ((opac-=0.02f)>0) disp.display((+img).draw_text(disp.mouse_x-8,disp.mouse_y-54+(int)(30*opac),"+%u", 1.145 + white,0,(float)std::sqrt(opac),32,shape_score)).wait(20); 1.146 + else { if (redraw) { disp.display(img); redraw = false; } else disp.wait(); } 1.147 + 1.148 + // Handle key and window events 1.149 + if (disp.is_resized) disp.resize(disp); 1.150 + if (disp.is_keyBACKSPACE || disp.is_keySPACE) { 1.151 + board = previous_board; score = previous_score; selected_board.assign(); redraw = true; disp.key = 0; 1.152 + } 1.153 + if (disp.is_keyQ) { gameover = true; disp.key = 0; } 1.154 + if (disp.is_keyESC) disp.close(); 1.155 + if (disp.is_keyCTRLLEFT && disp.key==cimg::keyF) disp.toggle_fullscreen().display(img); 1.156 + 1.157 + // Handle ball selection and removal 1.158 + const int x = disp.mouse_x*board.dimx()/disp.dimx(), y = disp.mouse_y*board.dimy()/disp.dimy(); 1.159 + if (disp.button&1 && x>=0 && y>=0) { 1.160 + if (title) { title = false; redraw = true; } else { 1.161 + disp.button=0; 1.162 + if (!board(x,y)) { selected_board.assign(); redraw = true; } 1.163 + else { 1.164 + if (!selected_board || selected_board(x,y)!=6) { 1.165 + (selected_board=board).draw_fill(x,y,0,&six,1,shape); 1.166 + if ((shape_score=(unsigned int)shape.sum())<2) selected_board.assign(); 1.167 + else { (shape_score-=1)*=shape_score; opac = 1.0f; redraw = true; } 1.168 + } else { 1.169 + selected_board.assign(); 1.170 + previous_board = board; 1.171 + previous_score = score; 1.172 + score += shape_score; 1.173 + board&=--shape; 1.174 + redraw = true; 1.175 + 1.176 + // Handle board modification due to ball removal 1.177 + for (int pmax = board.dimx(), p=0; p<pmax; ++p) { 1.178 + for (int q = board.dimy()-1, qs = q; q>=0; --q) { 1.179 + while (!board(p,qs)) --qs; 1.180 + board(p,q) = (qs>=0?board(p,qs--):0); 1.181 + } 1.182 + if (!board(p,board.dimy()-1)) { 1.183 + board.draw_image(p,board.get_crop(p,0,board.dimx()-1,board.dimy()-1).translate(1)); 1.184 + if (p<pmax) { p--; pmax--; } 1.185 + } 1.186 + } 1.187 + 1.188 + // Test possible end of the game 1.189 + gameover = true; 1.190 + cimg_forXY(board,x,y) 1.191 + if (board(x,y) && ((y && board(x,y)==board(x,y-1)) || (x && board(x,y)==board(x-1,y)))) gameover = false; 1.192 + } 1.193 + } 1.194 + } 1.195 + disp.button = 0; 1.196 + } 1.197 + 1.198 + // If game is over... 1.199 + if (gameover && opac<=0) { 1.200 + CImg<unsigned char> text1, text2, text3, text4, text5, text6; 1.201 + text1.draw_text(0,0,"Game Over !",white,0,1,48); 1.202 + const unsigned int remaining_balls = (unsigned int)board.get_cut(0,1).sum(); 1.203 + if (remaining_balls<8) { 1.204 + const unsigned int bonus = (22-2*remaining_balls)*10; 1.205 + score += bonus; 1.206 + text2.draw_text(0,0,"Jawbreaker Bonus : +%u",white,0,1,24,bonus); 1.207 + } 1.208 + score_history.insert(CImg<unsigned int>::vector(score)); 1.209 + text3.draw_text(0,0,"Final score : %u",yellow,0,1,24,score); 1.210 + text4.draw_text(0,0,score>best_score?"** New record ! **":"Best score : %u", 1.211 + orange,0,1,24,score>best_score?score:best_score); 1.212 + text5.draw_text(0,0,"Average score : %u",red,0,1,24, 1.213 + score_history?(unsigned int)score_history.mean():0U); 1.214 + text6.draw_text(0,0,"Games played : %u",red,0,1,24,score_history.size); 1.215 + if (score>best_score) best_score = score; 1.216 + 1.217 + unsigned int yt = (Hi-text1.dimy())/2-20; 1.218 + (img/=2).draw_image((Wi-text1.dimx())/2,yt,text1,text1.get_dilate(7),1,255); yt+=80; 1.219 + if (text2) { img.draw_image((Wi-text2.dimx())/2,yt,text2,text2.get_dilate(5),1,255); yt+=25; } 1.220 + img.draw_image((Wi-text3.dimx())/2,yt,text3,text3.get_dilate(5),1,255). 1.221 + draw_image((Wi-text4.dimx())/2,yt+25,text4,text4.get_dilate(5),1,255). 1.222 + draw_image((Wi-text5.dimx())/2,yt+50,text5,text5.get_dilate(5),1,255). 1.223 + draw_image((Wi-text6.dimx())/2,yt+75,text6,text6.get_dilate(5),1,255).display(disp); 1.224 + for (disp.button = disp.key = 0; !disp.is_closed && !disp.key && !disp.button; disp.wait()) 1.225 + if (disp.is_resized) disp.resize(disp); 1.226 + disp.button = disp.key = 0; 1.227 + board.assign(); 1.228 + for (float i=10; i>0 && !disp.is_keyESC; i-=0.25) 1.229 + disp.display(img.get_crop((int)(Wi*(0.5f-i*i*i*i/20000.0f)),(int)(Hi*(0.5f-i*i/200.0f)), 1.230 + (int)(Wi*(0.5f+i*i*i*i/20000.0f)),(int)(Hi*(0.5f+i*i/200.0f)))).wait(20); 1.231 + } 1.232 + } 1.233 + 1.234 + // Save score history if possible, and exit. 1.235 + if (score_history) { 1.236 + file = std::fopen(filename_history,"w"); 1.237 + if (file) { std::fclose(file); score_history.get_append('y').save_dlm(filename_history); } 1.238 + } 1.239 + return 0; 1.240 +}