1 #include <assert.h> 2 #include <SDL.h> 3 #include <SDL_image.h> 4 #include "cube.h" 5 #include "soundDev.h" 6 #include "view.h" 7 #include "controller.h" 8 #include "font.h" 9 #include "help.h" 10 unsigned int NKlein_54321::View::startCoords[ 11 NKlein_54321::Cube::DIMENSIONS + 1 12 ][ 2 ] = { 13 { 0, 0 }, 14 { 15 ( 600 - ( BLOCK - GAP ) ) / 2, 16 ( 600 - ( SQUARE ) ) / 2 17 }, 18 { 19 ( 600 - ( BLOCK - GAP ) ) / 2, 20 ( 600 - ( BLOCK - GAP ) ) / 2 21 }, 22 { 23 ( 600 - ( NKlein_54321::Cube::SIDE_LENGTH * BLOCK - GAP ) ) / 2, 24 ( 600 - ( BLOCK - GAP ) ) / 2 25 }, 26 { 27 ( 600 - ( NKlein_54321::Cube::SIDE_LENGTH * BLOCK - GAP ) ) / 2, 28 ( 600 - ( NKlein_54321::Cube::SIDE_LENGTH * BLOCK - GAP ) ) / 2 29 } 30 }; 31 SDL_Rect NKlein_54321::View::bLocation[ 32 NKlein_54321::View::MAX_BUTTON 33 ] = 34 { 35 { SIDEBAR_X + 2, SIDEBAR_Y + 2, 64, 64 }, 36 { SIDEBAR_X + 68, SIDEBAR_Y + 2, 64, 64 }, 37 { SIDEBAR_X + 134, SIDEBAR_Y + 2, 64, 64 }, 38 { SIDEBAR_X + 2, SIDEBAR_Y + 68, 64, 32 }, 39 { SIDEBAR_X + 68, SIDEBAR_Y + 68, 64, 32 }, 40 { SIDEBAR_X + 134, SIDEBAR_Y + 68, 64, 32 }, 41 { SIDEBAR_X + 68, SIDEBAR_Y + 102, 64, 32 }, 42 { SIDEBAR_X + 36, SIDEBAR_Y + 180, 128, 64 }, 43 { SIDEBAR_X + 36, SIDEBAR_Y + 250, 128, 64 }, 44 { SIDEBAR_X + 2, SIDEBAR_Y + 534, 196, 64 } 45 }; View(SDL_Surface * _screen,SoundDev * _sound,Cube * _cube,unsigned int _dims,unsigned int _skillLevel,bool _wrap)46 NKlein_54321::View::View( 47 SDL_Surface* _screen, 48 SoundDev* _sound, 49 Cube* _cube, 50 unsigned int _dims, 51 unsigned int _skillLevel, 52 bool _wrap 53 ) : screen( _screen ), sound( _sound ), cube( _cube ), 54 dims( _dims ), skillLevel( _skillLevel ), wrap( _wrap ), 55 help( 0 ) 56 { 57 if ( this->screen != 0 ) { 58 SDL_PixelFormat* fmt = this->screen->format; 59 this->bgColor = SDL_MapRGB( fmt, 0, 0, 0 ); 60 } 61 62 this->sidebar = ::IMG_Load( "/usr/local/share/54321/data/panel.png" ); 63 this->overlay = ::IMG_Load( "/usr/local/share/54321/data/overlay.png" ); 64 this->dimButton[ 0 ] = ::IMG_Load( "/usr/local/share/54321/data/dimOff.png" ); 65 this->dimButton[ 1 ] = ::IMG_Load( "/usr/local/share/54321/data/dimOn.png" ); 66 this->setButton[ 0 ] = ::IMG_Load( "/usr/local/share/54321/data/setOff.png" ); 67 this->setButton[ 1 ] = ::IMG_Load( "/usr/local/share/54321/data/setOn.png" ); 68 this->actButton[ 0 ] = ::IMG_Load( "/usr/local/share/54321/data/actOff.png" ); 69 this->actButton[ 1 ] = ::IMG_Load( "/usr/local/share/54321/data/actOn.png" ); 70 this->helpButton[ 0 ] = ::IMG_Load( "/usr/local/share/54321/data/helpOff.png" ); 71 this->helpButton[ 1 ] = ::IMG_Load( "/usr/local/share/54321/data/helpOn.png" ); 72 this->victory = ::IMG_Load( "/usr/local/share/54321/data/victory.png" ); 73 this->losing = ::IMG_Load( "/usr/local/share/54321/data/defeat.png" ); 74 75 this->clickedButton = MAX_BUTTON; 76 this->reset(); 77 } ~View(void)78 NKlein_54321::View::~View( void ) 79 { 80 ::SDL_FreeSurface( this->losing ); 81 ::SDL_FreeSurface( this->victory ); 82 ::SDL_FreeSurface( this->helpButton[ 1 ] ); 83 ::SDL_FreeSurface( this->helpButton[ 0 ] ); 84 ::SDL_FreeSurface( this->actButton[ 1 ] ); 85 ::SDL_FreeSurface( this->actButton[ 0 ] ); 86 ::SDL_FreeSurface( this->setButton[ 1 ] ); 87 ::SDL_FreeSurface( this->setButton[ 0 ] ); 88 ::SDL_FreeSurface( this->dimButton[ 1 ] ); 89 ::SDL_FreeSurface( this->dimButton[ 0 ] ); 90 ::SDL_FreeSurface( this->overlay ); 91 ::SDL_FreeSurface( this->sidebar ); 92 } 93 void reset(void)94 NKlein_54321::View::reset( void ) 95 { 96 for ( unsigned int ii=0; ii < MAX_BUTTON; ++ii ) { 97 this->bPressed[ ii ] = false; 98 } 99 100 this->bPressed[ DIM_2 + dims - 2 ] = true; 101 this->bPressed[ EASY + this->skillLevel ] = true; 102 this->bPressed[ WRAP ] = this->wrap; 103 } 104 bool handleMouseClick(Controller * control,bool isMouseUp,unsigned int xx,unsigned int yy,unsigned int buttonNumber)105 NKlein_54321::View::handleMouseClick( 106 Controller* control, 107 bool isMouseUp, 108 unsigned int xx, 109 unsigned int yy, 110 unsigned int buttonNumber 111 ) 112 { 113 if ( this->help != 0 ) { 114 bool hit = this->help->handleMouseClick( 115 isMouseUp, xx, yy, buttonNumber 116 ); 117 if ( hit ) { 118 return true; 119 } 120 } 121 122 if ( ! isMouseUp ) { 123 for ( unsigned int ii=0; ii < MAX_BUTTON; ++ii ) { 124 if ( this->checkButton( xx, yy, ii ) ) { 125 this->clickedButton = ii; 126 this->originalState = this->bPressed[ this->clickedButton ]; 127 if ( ! this->originalState ) { 128 this->bPressed[ this->clickedButton ] = true; 129 this->drawButton( this->clickedButton ); 130 } 131 return true; 132 } 133 } 134 } else if ( isMouseUp && this->clickedButton < MAX_BUTTON ) { 135 unsigned int ii = this->clickedButton; 136 bool inSide = this->checkButton( xx, yy, ii ); 137 138 this->bPressed[ this->clickedButton ] = this->originalState; 139 this->clickedButton = MAX_BUTTON; 140 141 if ( inSide ) { 142 if ( this->help != 0 ) { 143 this->setHelp( 0 ); 144 this->drawButton( ii ); 145 this->drawButton( HELP ); 146 this->redraw(); 147 } else if ( ii >= DIM_2 && ii <= DIM_4 ) { 148 this->dims = ii + 2 - DIM_2; 149 control->setDimension( this->dims ); 150 } else if ( ii >= EASY && ii <= HARD ) { 151 this->skillLevel = ii - EASY; 152 control->setSkillLevel( this->skillLevel ); 153 } else if ( ii == WRAP ) { 154 this->wrap = ! this->wrap; 155 control->setWrap( this->wrap ); 156 } else if ( ii == NEW ) { 157 control->newGame(); 158 } else if ( ii == BACK ) { 159 SDL_Event change; 160 change.type = SDL_USEREVENT; 161 change.user.code = -1; 162 ::SDL_PushEvent( &change ); 163 } else if ( ii == HELP ) { 164 this->setHelp( new Help( this, this->screen ) ); 165 } else { 166 this->drawButton( ii ); 167 } 168 } else { 169 this->drawButton( ii ); 170 } 171 172 return true; 173 } 174 175 return false; 176 } 177 bool checkButton(unsigned int xx,unsigned int yy,unsigned int ii)178 NKlein_54321::View::checkButton( 179 unsigned int xx, unsigned int yy, 180 unsigned int ii 181 ) 182 { 183 return ( xx >= this->bLocation[ ii ].x 184 && xx < this->bLocation[ ii ].x + this->bLocation[ ii ].w 185 && yy >= this->bLocation[ ii ].y 186 && yy < this->bLocation[ ii ].y + this->bLocation[ ii ].h 187 ); 188 } 189 bool screenToCell(unsigned int xx,unsigned int yy,unsigned int dims,unsigned int * index)190 NKlein_54321::View::screenToCell( 191 unsigned int xx, unsigned int yy, 192 unsigned int dims, 193 unsigned int* index 194 ) 195 { 196 assert( index != 0 ); 197 assert( dims <= 4 && dims > 0 ); 198 199 unsigned int sx = startCoords[ dims ][ 0 ]; 200 unsigned int sy = startCoords[ dims ][ 1 ]; 201 202 if ( xx < sx || sy < sy ) { 203 return false; 204 } 205 206 xx -= sx; 207 yy -= sy; 208 unsigned int coords[ NKlein_54321::Cube::DIMENSIONS ]; 209 210 coords[ 2 ] = xx / BLOCK; 211 coords[ 3 ] = yy / BLOCK; 212 213 coords[ 0 ] = ( xx - coords[ 2 ] * BLOCK ) / SQUARE; 214 coords[ 1 ] = ( yy - coords[ 3 ] * BLOCK ) / SQUARE; 215 for ( unsigned int ii=0; ii < dims; ++ii ) { 216 if ( coords[ ii ] >= NKlein_54321::Cube::SIDE_LENGTH ) { 217 return false; 218 } 219 } 220 for ( unsigned int ii=dims; ii < NKlein_54321::Cube::DIMENSIONS; ++ii ) { 221 if ( coords[ ii ] > 0 ) { 222 return false; 223 } 224 } 225 226 NKlein_54321::Cube::vectorToIndex( coords, index ); 227 return true; 228 } 229 void cellToScreen(unsigned int index,unsigned int dims,unsigned int * xx,unsigned int * yy)230 NKlein_54321::View::cellToScreen( 231 unsigned int index, 232 unsigned int dims, 233 unsigned int* xx, unsigned int* yy 234 ) 235 { 236 assert( xx != 0 ); 237 assert( yy != 0 ); 238 239 unsigned int coords[ NKlein_54321::Cube::DIMENSIONS ]; 240 NKlein_54321::Cube::indexToVector( index, coords ); 241 242 *xx = startCoords[ dims ][ 0 ] 243 + coords[ 0 ] * SQUARE 244 + coords[ 2 ] * BLOCK 245 ; 246 247 *yy = startCoords[ dims ][ 1 ] 248 + coords[ 1 ] * SQUARE 249 + coords[ 3 ] * BLOCK 250 ; 251 } 252 void redraw(void)253 NKlein_54321::View::redraw( void ) 254 { 255 SDL_Rect rect; 256 257 rect.x = 0; 258 rect.y = 0; 259 rect.w = 600; 260 rect.h = 600; 261 ::SDL_FillRect( this->screen, 0, this->bgColor ); 262 if ( this->sidebar != 0 ) { 263 rect.x = SIDEBAR_X; 264 rect.y = SIDEBAR_Y; 265 rect.w = 200; 266 rect.h = 600; 267 ::SDL_BlitSurface( this->sidebar, 0, this->screen, &rect ); 268 } 269 for ( unsigned int ii=0; ii < MAX_BUTTON; ++ii ) { 270 this->drawButton( ii, false ); 271 } 272 if ( this->overlay != 0 ) { 273 rect.x = SIDEBAR_X; 274 rect.y = SIDEBAR_Y; 275 rect.w = 200; 276 rect.h = 600; 277 ::SDL_BlitSurface( this->overlay, 0, this->screen, &rect ); 278 } 279 } 280 void drawButton(unsigned int button,bool update)281 NKlein_54321::View::drawButton( 282 unsigned int button, 283 bool update 284 ) 285 { 286 SDL_Surface** images; 287 288 if ( button >= DIM_2 && button <= DIM_4 ) { 289 images = this->dimButton; 290 } else if ( button >= EASY && button <= WRAP ) { 291 images = this->setButton; 292 } else if ( button >= NEW && button <= BACK ) { 293 images = this->actButton; 294 } else if ( button == HELP ) { 295 images = this->helpButton; 296 } else { 297 assert( 0 == 1 ); 298 } 299 300 if ( this->bPressed[ button ] ) { 301 ++images; 302 } 303 304 ::SDL_BlitSurface( 305 *images, 0, 306 this->screen, &bLocation[ button ] 307 ); 308 309 if ( update ) { 310 SDL_Rect overlayRect; 311 overlayRect.x = bLocation[ button ].x - SIDEBAR_X; 312 overlayRect.y = bLocation[ button ].y - SIDEBAR_Y; 313 overlayRect.w = bLocation[ button ].w; 314 overlayRect.h = bLocation[ button ].h; 315 316 ::SDL_BlitSurface( 317 this->overlay, &overlayRect, 318 this->screen, &bLocation[ button ] 319 ); 320 ::SDL_UpdateRect( this->screen, 321 bLocation[ button ].x, bLocation[ button ].y, 322 bLocation[ button ].w, bLocation[ button ].h 323 ); 324 } 325 } 326 void backgroundMusic(bool stop)327 NKlein_54321::View::backgroundMusic( bool stop ) 328 { 329 } 330 void moveNoise(void)331 NKlein_54321::View::moveNoise( void ) 332 { 333 if ( this->sound != 0 ) { 334 this->sound->ding(); 335 } else { 336 ::SDL_Delay( 250U ); 337 } 338 } 339 void victoryMusic(void)340 NKlein_54321::View::victoryMusic( void ) 341 { 342 ::SDL_Delay( 5000U ); 343 } 344 void losingMusic(void)345 NKlein_54321::View::losingMusic( void ) 346 { 347 ::SDL_Delay( 3000U ); 348 } 349 void showWinning(unsigned int,unsigned int)350 NKlein_54321::View::showWinning( 351 unsigned int /*actualMoves*/, 352 unsigned int /*expectedMoves*/ 353 ) 354 { 355 if ( this->screen != 0 && this->victory != 0 ) { 356 SDL_Rect rect; 357 rect.x = ( 600 - this->victory->w ) / 2; 358 rect.y = ( 600 - this->victory->h ) / 2; 359 ::SDL_BlitSurface( this->victory, 0, this->screen, &rect ); 360 ::SDL_UpdateRect( 361 this->screen, 362 rect.x, rect.y, 363 this->victory->w, this->victory->h 364 ); 365 } 366 this->victoryMusic(); 367 if ( this->screen != 0 && this->victory != 0 ) { 368 this->redraw(); 369 } 370 } 371 void showLosing(void)372 NKlein_54321::View::showLosing( void ) 373 { 374 if ( this->screen != 0 && this->losing != 0 ) { 375 SDL_Rect rect; 376 rect.x = ( 600 - this->losing->w ) / 2; 377 rect.y = ( 600 - this->losing->h ) / 2; 378 ::SDL_BlitSurface( this->losing, 0, this->screen, &rect ); 379 ::SDL_UpdateRect( 380 this->screen, 381 rect.x, rect.y, 382 this->losing->w, this->losing->h 383 ); 384 } 385 this->losingMusic(); 386 if ( this->screen != 0 && this->losing != 0 ) { 387 this->redraw(); 388 } 389 } 390 void setHelp(Help * nn)391 NKlein_54321::View::setHelp( Help* nn ) 392 { 393 delete this->help; 394 this->help = nn; 395 396 if ( this->help == 0 ) { 397 this->bPressed[ HELP ] = false; 398 this->drawButton( HELP ); 399 this->redraw(); 400 } 401 } 402