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