├── .gitignore ├── Makefile ├── README.txt ├── snake └── snake.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # super simple makefile 2 | # call it using 'make NAME=name_of_code_file_without_extension' 3 | # (assumes a .cpp extension) 4 | NAME = snake 5 | 6 | # 7 | # Add $(MAC_OPT) to the compile line for Mac OSX. 8 | MAC_OPT = "-I/opt/X11/include" 9 | 10 | all: 11 | @echo "Compiling..." 12 | g++ -o $(NAME) $(NAME).cpp -L/usr/X11R6/lib -lX11 -lstdc++ $(MAC_OPT) 13 | 14 | run: all 15 | @echo "Running..." 16 | ./$(NAME) 17 | 18 | clean: 19 | -rm animation clipping doublebuffer drawing drawing.min 20 | -rm eventloop eventloop.min hello.min null null.min openwindow openwindow.min -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | Game Description: 2 | 3 | Press w/a/s/d to control the snake. If the snake eats an apple, it gains 100 scores. It the snake hits wall or itself, and has no extra lives, it dies. 4 | 5 | Press p to pause the game. If the game is paused, press p to resume the game and keep the snake’s direction as before the pause, or press w/a/s/d to resume the game and change the snake’s direction. 6 | 7 | Press r to restart the game at any time (i.e. while playing, paused, and/or dead). 8 | 9 | Default FPS = 60 10 | Default speed = 5 11 | 12 | 13 | Enhancements: 14 | 15 | I have added two power-ups into the game. 16 | 17 | 1. Golden Apple - If the snake eats a golden apple, it gains an extra life. The possibility of generating a golden apple is 10%. 18 | 2. Purple Apple - If the snake eats a purple apple, its speed decreases by 1 (Minimum = 1). If player restarts the game, snake’s speed is reset to default (or the given speed from command line). The possibility of generating a purple apple is 6%. 19 | 20 | For easier test of the special apples, you can keep press r until they show. 21 | 22 | I have also drawn a snake and apples with fillrectangle, which I am not sure if they can be counted as texture graphics. 23 | 24 | 25 | Development Environment: 26 | 27 | macOS Sierra 28 | version 10.12.2 29 | -------------------------------------------------------------------------------- /snake: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/striver79/Snake/10120f19d6e416909bede2c83c11d0ffdc2f4d15/snake -------------------------------------------------------------------------------- /snake.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | CS 349 A1 Skeleton Code - Snake 3 | 4 | - - - - - - - - - - - - - - - - - - - - - - 5 | 6 | Commands to compile and run: 7 | 8 | g++ -o snake snake.cpp -L/usr/X11R6/lib -lX11 -lstdc++ 9 | ./snake 10 | 11 | Note: the -L option and -lstdc++ may not be needed on some machines. 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | /* 25 | * Header files for X functions 26 | */ 27 | #include 28 | #include 29 | 30 | using namespace std; 31 | 32 | /* 33 | * Global game state variables 34 | */ 35 | const int Border = 1; 36 | const int BufferSize = 10; 37 | int FPS = 60; 38 | int speed = 5; 39 | int speed_saver = 5; 40 | const int width = 800; 41 | const int height = 600; 42 | 43 | 44 | /* 45 | * up 0 46 | * down 1 47 | * left 2 48 | * right 3 49 | */ 50 | 51 | 52 | struct snakeLst { 53 | int x; 54 | int y; 55 | snakeLst * next; 56 | snakeLst * previous; 57 | 58 | snakeLst(int x, int y, snakeLst * next, snakeLst * previous) : x(x), y(y), next(next), previous(previous) { 59 | 60 | } 61 | 62 | }; 63 | 64 | int score = 0; 65 | int pause_indicator = 0; 66 | int died = 0; 67 | int dying = 0; 68 | int start_screen = 1; 69 | int just_turned = 0; 70 | int quit_indicator = 0; 71 | int snake_size = 1; 72 | 73 | snakeLst * head = new snakeLst(100, 450, NULL, NULL); 74 | snakeLst * tail = new snakeLst(100, 450, NULL, head); 75 | 76 | 77 | /* 78 | * Information to draw on the window. 79 | */ 80 | struct XInfo { 81 | Display *display; 82 | int screen; 83 | Window window; 84 | Pixmap pixmap; 85 | GC gc[3]; 86 | int width; // size of window 87 | int height; 88 | }; 89 | 90 | 91 | /* 92 | * Function to put out a message on error exits. 93 | */ 94 | void error( string str ) { 95 | cerr << str << endl; 96 | exit(0); 97 | } 98 | 99 | 100 | 101 | /* 102 | * An abstract class representing displayable things. 103 | */ 104 | class Displayable { 105 | public: 106 | virtual void paint(XInfo &xinfo) = 0; 107 | }; 108 | 109 | list dList; // list of Displayables 110 | 111 | class StartScreen : public Displayable { 112 | public: 113 | virtual void paint(XInfo &xinfo) { 114 | 115 | /**************** draw black ***************/ 116 | XColor xcolour_ss_black; 117 | char xcolor_ss_black[] = "#000000"; 118 | Colormap cmap_ss_black = DefaultColormap(xinfo.display, DefaultScreen(xinfo.display)); 119 | XParseColor(xinfo.display, cmap_ss_black, xcolor_ss_black, &xcolour_ss_black); 120 | XAllocColor(xinfo.display, cmap_ss_black, &xcolour_ss_black); 121 | XSetForeground(xinfo.display, xinfo.gc[0], xcolour_ss_black.pixel); 122 | 123 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 280, 180, 100, 20);//1 124 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 260, 200, 20, 40);//2 125 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 240, 240, 20, 60);//3 126 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 260, 300, 20, 20);//4 127 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 280, 240, 20, 40);//5 128 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 360, 240, 20, 40);//6 129 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 380, 200, 20, 20);//7 130 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 400, 220, 20, 40);//8 131 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 420, 260, 20, 40);//9 132 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 280, 320, 120, 20);//10 133 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 400, 300, 20, 80);//11 134 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 240, 340, 40, 20);//12 135 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 220, 360, 20, 20);//13 136 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 200, 380, 20, 60);//14 137 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 220, 440, 20, 20);//15 138 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 240, 460, 180, 20);//16 139 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 320, 340, 20, 20);//17 140 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 300, 360, 20, 20);//18 141 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 260, 380, 20, 20);//19 142 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 280, 400, 100, 20);//20 143 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 380, 380, 20, 20);//21 144 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 420, 340, 20, 20);//22 145 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 440, 360, 20, 20);//23 146 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 460, 380, 20, 20);//24 147 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 480, 400, 20, 60);//25 148 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 460, 460, 20, 20);//26 149 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 440, 400, 20, 60);//27 150 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 420, 440, 20, 20);//28 151 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 420, 200, 20, 20);//29 152 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 440, 180, 20, 20);//30 153 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 460, 200, 20, 20);//31 154 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 480, 180, 20, 20);//32 155 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 460, 160, 20, 20);//33 156 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 480, 80, 20, 60);//34 157 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 500, 140, 20, 20);//35 158 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 520, 160, 140, 20);//36 159 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 660, 140, 20, 20);//37 160 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 680, 80, 20, 60);//38 161 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 660, 60, 20, 20);//39 162 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 520, 40, 140, 20);//40 163 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 500, 60, 20, 20);//41 164 | 165 | XDrawString(xinfo.display, xinfo.pixmap, xinfo.gc[0], 560, 85, "I WANT", 6); 166 | XDrawString(xinfo.display, xinfo.pixmap, xinfo.gc[0], 515, 110, "PRESS w/a/s/d TO GUIDE ME", 25); 167 | XDrawString(xinfo.display, xinfo.pixmap, xinfo.gc[0], 540, 125, "PRESS p TO PAUSE", 16); 168 | XDrawString(xinfo.display, xinfo.pixmap, xinfo.gc[0], 535, 140, "PRESS r TO RESTART", 18); 169 | 170 | XDrawString(xinfo.display, xinfo.pixmap, xinfo.gc[0], 340, 555, "PRESS ANY KEY TO START", 22); 171 | 172 | XDrawString(xinfo.display, xinfo.pixmap, xinfo.gc[0], 673, 520, "WENXUE LI", 9); 173 | XDrawString(xinfo.display, xinfo.pixmap, xinfo.gc[0], 684, 540, "w254li", 6); 174 | XDrawString(xinfo.display, xinfo.pixmap, xinfo.gc[0], 677, 560, "20517629", 8); 175 | 176 | XFreeColormap(xinfo.display, cmap_ss_black); 177 | /**************** draw black ***************/ 178 | 179 | /**************** draw light green ***************/ 180 | XColor xcolour_ss_lgreen; 181 | char xcolor_ss_lgreen[] = "#32CD32"; 182 | Colormap cmap_ss_lgreen = DefaultColormap(xinfo.display, DefaultScreen(xinfo.display)); 183 | XParseColor(xinfo.display, cmap_ss_lgreen, xcolor_ss_lgreen, &xcolour_ss_lgreen); 184 | XAllocColor(xinfo.display, cmap_ss_lgreen, &xcolour_ss_lgreen); 185 | XSetForeground(xinfo.display, xinfo.gc[0], xcolour_ss_lgreen.pixel); 186 | 187 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 280, 200, 100, 40);//1 188 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 260, 240, 20, 40);//2 189 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 380, 220, 20, 60);//3 190 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 300, 240, 60, 60);//4 191 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 280, 280, 100, 20);//5 192 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 280, 340, 40, 20);//6 193 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 240, 360, 60, 20);//7 194 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 220, 380, 40, 20);//8 195 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 240, 400, 40, 40);//9 196 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 280, 420, 100, 20);//10 197 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 380, 400, 20, 40);//11 198 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 400, 380, 20, 60);//12 199 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 340, 340, 40, 20);//13 200 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 320, 360, 60, 20);//14 201 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 460, 400, 20, 60);//15 202 | 203 | XFreeColormap(xinfo.display, cmap_ss_lgreen); 204 | 205 | /**************** draw light green ***************/ 206 | 207 | /**************** draw dark green ***************/ 208 | XColor xcolour_ss_dgreen; 209 | char xcolor_ss_dgreen[] = "#228B22"; 210 | Colormap cmap_ss_dgreen = DefaultColormap(xinfo.display, DefaultScreen(xinfo.display)); 211 | XParseColor(xinfo.display, cmap_ss_dgreen, xcolor_ss_dgreen, &xcolour_ss_dgreen); 212 | XAllocColor(xinfo.display, cmap_ss_dgreen, &xcolour_ss_dgreen); 213 | XSetForeground(xinfo.display, xinfo.gc[0], xcolour_ss_dgreen.pixel); 214 | 215 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 400, 260, 20, 40);//1 216 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 280, 300, 120, 20);//2 217 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 380, 340, 20, 40);//3 218 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 280, 380, 100, 20);//4 219 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 220, 400, 20, 40);//5 220 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 240, 440, 180, 20);//6 221 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 420, 360, 20, 80);//7 222 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 440, 380, 20, 20);//8 223 | 224 | XFreeColormap(xinfo.display, cmap_ss_dgreen); 225 | 226 | /**************** draw dark green ***************/ 227 | 228 | /**************** draw pink ***************/ 229 | XColor xcolour_ss_pink; 230 | char xcolor_ss_pink[] = "#FF69B4"; 231 | Colormap cmap_ss_pink = DefaultColormap(xinfo.display, DefaultScreen(xinfo.display)); 232 | XParseColor(xinfo.display, cmap_ss_pink, xcolor_ss_pink, &xcolour_ss_pink); 233 | XAllocColor(xinfo.display, cmap_ss_pink, &xcolour_ss_pink); 234 | XSetForeground(xinfo.display, xinfo.gc[0], xcolour_ss_pink.pixel); 235 | 236 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 260, 280, 20, 20);//1 237 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 380, 280, 20, 20);//2 238 | 239 | XFreeColormap(xinfo.display, cmap_ss_pink); 240 | 241 | /**************** draw pink ***************/ 242 | 243 | 244 | /**************** draw apple ****************/ 245 | 246 | /***** draw brown *****/ 247 | XColor xbrown; 248 | char brown[] = "#FF0000"; 249 | Colormap cmap_brown = DefaultColormap(xinfo.display, DefaultScreen(xinfo.display)); 250 | XParseColor(xinfo.display, cmap_brown, brown, &xbrown); 251 | XAllocColor(xinfo.display, cmap_brown, &xbrown); 252 | XSetForeground(xinfo.display, xinfo.gc[0], xbrown.pixel); 253 | 254 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 608, 72, 2, 6); 255 | XFreeColormap(xinfo.display, cmap_brown); 256 | 257 | /***** draw brown *****/ 258 | 259 | /***** draw green *****/ 260 | XColor xgreen; 261 | char green[] = "#00FF00"; 262 | Colormap cmap_green = DefaultColormap(xinfo.display, DefaultScreen(xinfo.display)); 263 | XParseColor(xinfo.display, cmap_green, green, &xgreen); 264 | XAllocColor(xinfo.display, cmap_green, &xgreen); 265 | XSetForeground(xinfo.display, xinfo.gc[0], xgreen.pixel); 266 | 267 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 610, 74, 2, 2); 268 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 612, 72, 2, 2); 269 | XFreeColormap(xinfo.display, cmap_green); 270 | 271 | /***** draw green *****/ 272 | 273 | /***** draw white *****/ 274 | XColor xwhite; 275 | char white[] = "#FFFFFF"; 276 | Colormap cmap_white = DefaultColormap(xinfo.display, DefaultScreen(xinfo.display)); 277 | XParseColor(xinfo.display, cmap_white, white, &xwhite); 278 | XAllocColor(xinfo.display, cmap_white, &xwhite); 279 | XSetForeground(xinfo.display, xinfo.gc[0], xwhite.pixel); 280 | 281 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 604, 88, 4, 2); 282 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 604, 80, 2, 2); 283 | XFreeColormap(xinfo.display, cmap_white); 284 | 285 | /***** draw white *****/ 286 | 287 | /***** draw red *****/ 288 | XColor xred; 289 | char red[] = "#FF0000"; 290 | Colormap cmap_red = DefaultColormap(xinfo.display, DefaultScreen(xinfo.display)); 291 | XParseColor(xinfo.display, cmap_red, red, &xred); 292 | XAllocColor(xinfo.display, cmap_red, &xred); 293 | XSetForeground(xinfo.display, xinfo.gc[0], xred.pixel); 294 | 295 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 604, 76, 4, 2);//1 296 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 611, 76, 4, 2);//2 297 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 602, 78, 2, 8);//3 298 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 604, 82, 2, 6);//4 299 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 606, 80, 6, 10);//5 300 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 608, 78, 8, 2);//6 301 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 612, 80, 4, 6);//7 302 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 612, 86, 2, 2);//8 303 | 304 | XDrawString(xinfo.display, xinfo.pixmap, xinfo.gc[0], 680, 500, "MADE BY", 7); 305 | 306 | XFreeColormap(xinfo.display, cmap_red); 307 | 308 | /***** draw red *****/ 309 | 310 | /**************** draw apple ****************/ 311 | 312 | } 313 | }; 314 | 315 | StartScreen startScreen; 316 | 317 | 318 | 319 | /* 320 | * Function to repaint a display list 321 | */ 322 | void repaint( XInfo &xinfo) { 323 | list::const_iterator begin = dList.begin(); 324 | list::const_iterator end = dList.end(); 325 | 326 | 327 | // get height and width of window (might have changed since last repaint) 328 | 329 | XWindowAttributes windowInfo; 330 | XGetWindowAttributes(xinfo.display, xinfo.window, &windowInfo); 331 | unsigned int height = windowInfo.height; 332 | unsigned int width = windowInfo.width; 333 | 334 | // big black rectangle to clear background 335 | 336 | 337 | // draw display list 338 | 339 | XColor xcolour_bg; 340 | char xcolor_bg[] = "#F5F5F5"; 341 | Colormap cmap_bg = DefaultColormap(xinfo.display, DefaultScreen(xinfo.display)); 342 | XParseColor(xinfo.display, cmap_bg, xcolor_bg, &xcolour_bg); 343 | XAllocColor(xinfo.display, cmap_bg, &xcolour_bg); 344 | XSetForeground(xinfo.display, xinfo.gc[0], xcolour_bg.pixel); 345 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 0, 0, 800, 600); 346 | 347 | while( begin != end ) { 348 | Displayable *d = *begin; 349 | d->paint(xinfo); 350 | begin++; 351 | } 352 | XCopyArea(xinfo.display, xinfo.pixmap, xinfo.window, xinfo.gc[0], 0, 0, 800, 600, 0, 0); 353 | XFlush( xinfo.display ); 354 | } 355 | 356 | 357 | 358 | class Obstacles : public Displayable { 359 | public: 360 | virtual void paint(XInfo &xinfo) { 361 | 362 | /**************/ 363 | 364 | XColor xcolour_o; 365 | char xcolor_o[] = "#000000"; 366 | Colormap cmap_o = DefaultColormap(xinfo.display, DefaultScreen(xinfo.display)); 367 | XParseColor(xinfo.display, cmap_o, xcolor_o, &xcolour_o); 368 | XAllocColor(xinfo.display, cmap_o, &xcolour_o); 369 | XSetForeground(xinfo.display, xinfo.gc[0], xcolour_o.pixel); 370 | 371 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 50, 50, 10, 450); 372 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 750, 50, 10, 450); 373 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 50, 500, 710, 10); 374 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], 50, 50, 710, 10); 375 | 376 | XFreeColormap(xinfo.display, cmap_o); 377 | 378 | } 379 | }; 380 | 381 | class Fruit : public Displayable { 382 | public: 383 | virtual void paint(XInfo &xinfo) { 384 | 385 | /**************** draw apple ****************/ 386 | 387 | /***** draw brown *****/ 388 | XColor xbrown; 389 | char brown[] = "#FF0000"; 390 | Colormap cmap_brown = DefaultColormap(xinfo.display, DefaultScreen(xinfo.display)); 391 | XParseColor(xinfo.display, cmap_brown, brown, &xbrown); 392 | XAllocColor(xinfo.display, cmap_brown, &xbrown); 393 | XSetForeground(xinfo.display, xinfo.gc[0], xbrown.pixel); 394 | 395 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], x+5, y+1, 1, 3); 396 | 397 | XFreeColormap(xinfo.display, cmap_brown); 398 | /***** draw brown *****/ 399 | 400 | /***** draw green *****/ 401 | XColor xgreen; 402 | char green[] = "#00FF00"; 403 | Colormap cmap_green = DefaultColormap(xinfo.display, DefaultScreen(xinfo.display)); 404 | XParseColor(xinfo.display, cmap_green, green, &xgreen); 405 | XAllocColor(xinfo.display, cmap_green, &xgreen); 406 | XSetForeground(xinfo.display, xinfo.gc[0], xgreen.pixel); 407 | 408 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], x+7, y+1, 1, 1); 409 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], x+6, y+2, 1, 1); 410 | 411 | XFreeColormap(xinfo.display, cmap_green); 412 | 413 | /***** draw green *****/ 414 | 415 | /***** draw white *****/ 416 | XColor xwhite; 417 | char white[] = "#FFFFFF"; 418 | Colormap cmap_white = DefaultColormap(xinfo.display, DefaultScreen(xinfo.display)); 419 | XParseColor(xinfo.display, cmap_white, white, &xwhite); 420 | XAllocColor(xinfo.display, cmap_white, &xwhite); 421 | XSetForeground(xinfo.display, xinfo.gc[0], xwhite.pixel); 422 | 423 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], x+3, y+4, 2, 1); 424 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], x+3, y+5, 1, 1); 425 | 426 | XFreeColormap(xinfo.display, cmap_white); 427 | /***** draw white *****/ 428 | 429 | if (golden == 1) { 430 | /***** draw yellow *****/ 431 | XColor xyellow; 432 | char yellow[] = "#FFA500"; 433 | Colormap cmap_yellow = DefaultColormap(xinfo.display, DefaultScreen(xinfo.display)); 434 | XParseColor(xinfo.display, cmap_yellow, yellow, &xyellow); 435 | XAllocColor(xinfo.display, cmap_yellow, &xyellow); 436 | XSetForeground(xinfo.display, xinfo.gc[0], xyellow.pixel); 437 | 438 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], x+3, y+3, 2, 1); 439 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], x+6, y+3, 2, 1); 440 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], x+2, y+4, 1, 4); 441 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], x+3, y+6, 1, 3); 442 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], x+4, y+5, 1, 5); 443 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], x+5, y+4, 1, 6); 444 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], x+6, y+4, 1, 6); 445 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], x+7, y+4, 1, 5); 446 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], x+8, y+4, 1, 4); 447 | 448 | XFreeColormap(xinfo.display, cmap_yellow); 449 | /***** draw yellow *****/ 450 | 451 | } else if (slow_down == 1) { 452 | /***** draw purple *****/ 453 | 454 | XColor xpurple; 455 | char purple[] = "#A020F0"; 456 | Colormap cmap_purple = DefaultColormap(xinfo.display, DefaultScreen(xinfo.display)); 457 | XParseColor(xinfo.display, cmap_purple, purple, &xpurple); 458 | XAllocColor(xinfo.display, cmap_purple, &xpurple); 459 | XSetForeground(xinfo.display, xinfo.gc[0], xpurple.pixel); 460 | 461 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], x+3, y+3, 2, 1); 462 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], x+6, y+3, 2, 1); 463 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], x+2, y+4, 1, 4); 464 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], x+3, y+6, 1, 3); 465 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], x+4, y+5, 1, 5); 466 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], x+5, y+4, 1, 6); 467 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], x+6, y+4, 1, 6); 468 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], x+7, y+4, 1, 5); 469 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], x+8, y+4, 1, 4); 470 | 471 | XFreeColormap(xinfo.display, cmap_purple); 472 | 473 | /***** draw purple *****/ 474 | } else { 475 | /***** draw red *****/ 476 | XColor xred; 477 | char red[] = "#FF0000"; 478 | Colormap cmap_red = DefaultColormap(xinfo.display, DefaultScreen(xinfo.display)); 479 | XParseColor(xinfo.display, cmap_red, red, &xred); 480 | XAllocColor(xinfo.display, cmap_red, &xred); 481 | XSetForeground(xinfo.display, xinfo.gc[0], xred.pixel); 482 | 483 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], x+3, y+3, 2, 1); 484 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], x+6, y+3, 2, 1); 485 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], x+2, y+4, 1, 4); 486 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], x+3, y+6, 1, 3); 487 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], x+4, y+5, 1, 5); 488 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], x+5, y+4, 1, 6); 489 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], x+6, y+4, 1, 6); 490 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], x+7, y+4, 1, 5); 491 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], x+8, y+4, 1, 4); 492 | 493 | XFreeColormap(xinfo.display, cmap_red); 494 | /***** draw red *****/ 495 | } 496 | 497 | /**************** draw apple ****************/ 498 | 499 | 500 | /**************** print score *************/ 501 | XColor xcolour_s; 502 | char xcolor_s[] = "#000000"; 503 | Colormap cmap_s = DefaultColormap(xinfo.display, DefaultScreen(xinfo.display)); 504 | XParseColor(xinfo.display, cmap_s, xcolor_s, &xcolour_s); 505 | XAllocColor(xinfo.display, cmap_s, &xcolour_s); 506 | XSetForeground(xinfo.display, xinfo.gc[0], xcolour_s.pixel); 507 | 508 | XDrawString(xinfo.display, xinfo.pixmap, xinfo.gc[0], 20, 550, "SCORE", 5); 509 | 510 | stringstream ss; 511 | ss << score; 512 | ss.str(); // Gets you a C++ std::string 513 | ss.str().c_str(); 514 | 515 | XDrawString(xinfo.display, xinfo.pixmap, xinfo.gc[0], 70, 550, ss.str().c_str(), ss.str().length()); 516 | 517 | XDrawString(xinfo.display, xinfo.pixmap, xinfo.gc[0], 20, 570, "LIFE", 4); 518 | 519 | int life = 1 - died; 520 | stringstream ss2; 521 | ss2 << life; 522 | ss2.str(); // Gets you a C++ std::string 523 | ss2.str().c_str(); 524 | 525 | XDrawString(xinfo.display, xinfo.pixmap, xinfo.gc[0], 70, 570, ss2.str().c_str(), ss2.str().length()); 526 | 527 | XFreeColormap(xinfo.display, cmap_s); 528 | } 529 | 530 | Fruit() { 531 | // generate the x and y value for the fruit 532 | srand(time(NULL)); 533 | int golden_indicator = rand() % 10; 534 | if (golden_indicator == 0) { 535 | golden = 1; 536 | } else { 537 | golden = 0; 538 | int slow_indicator = rand() % 15; 539 | if (slow_indicator == 0) { 540 | slow_down = 1; 541 | } else { 542 | slow_down = 0; 543 | } 544 | } 545 | x = (rand() % 64 + 6) * 10; 546 | y = (rand() % 40 + 6) * 10; 547 | if (x == 100 && y == 450) { 548 | x = 250; 549 | y = 300; 550 | } 551 | } 552 | 553 | int getX() { 554 | return x; 555 | } 556 | 557 | int getY() { 558 | return y; 559 | } 560 | 561 | int getGolden() { 562 | return golden; 563 | } 564 | 565 | int getSlow_down() { 566 | return slow_down; 567 | } 568 | 569 | void refresh(int preX, int preY) { 570 | srand(time(NULL)); 571 | int golden_indicator = rand() % 10; 572 | if (golden_indicator == 0) { 573 | golden = 1; 574 | } else { 575 | golden = 0; 576 | int slow_indicator = rand() % 20; 577 | if (slow_indicator == 0) { 578 | slow_down = 1; 579 | } else { 580 | slow_down = 0; 581 | } 582 | } 583 | 584 | do { 585 | x = (rand() % 64 + 6) * 10; 586 | } while (x == preX); 587 | 588 | do { 589 | y = (rand() % 40 + 6) * 10; 590 | } while (y == preY); 591 | 592 | snakeLst * ptr = head; 593 | 594 | do { 595 | if (x == ptr->x && y == ptr->y) { 596 | refresh(x, y); 597 | } else { 598 | if (ptr->next != NULL) { 599 | ptr = ptr->next; 600 | } else { 601 | break; 602 | } 603 | } 604 | } while (ptr != NULL); 605 | 606 | } 607 | 608 | 609 | private: 610 | int x; 611 | int y; 612 | int golden; 613 | int slow_down; 614 | }; 615 | 616 | 617 | Fruit fruit; 618 | Obstacles obstacles; 619 | 620 | 621 | void deleteLastNode() { 622 | if (head == NULL) { 623 | return; 624 | } 625 | 626 | if (head->next == NULL) { 627 | delete head; 628 | head = NULL; 629 | return; 630 | } 631 | 632 | snakeLst * currNode = head; 633 | while (currNode->next != NULL && currNode->next->next != NULL) { 634 | currNode = currNode->next; 635 | } 636 | tail = currNode; 637 | delete currNode->next; 638 | currNode->next = NULL; 639 | } 640 | 641 | 642 | class Snake : public Displayable { 643 | public: 644 | virtual void paint(XInfo &xinfo) { 645 | 646 | /*******************/ 647 | 648 | XColor xcolour_sn; 649 | char xcolor_sn[] = "#6B8E23"; 650 | Colormap cmap_sn = DefaultColormap(xinfo.display, DefaultScreen(xinfo.display)); 651 | XParseColor(xinfo.display, cmap_sn, xcolor_sn, &xcolour_sn); 652 | XAllocColor(xinfo.display, cmap_sn, &xcolour_sn); 653 | XSetForeground(xinfo.display, xinfo.gc[0], xcolour_sn.pixel); 654 | 655 | snakeLst * ptr = head; 656 | while (true) { 657 | XFillRectangle(xinfo.display, xinfo.pixmap, xinfo.gc[0], ptr->x, ptr->y, blockSize, blockSize); 658 | 659 | if (ptr->next != NULL) { 660 | ptr = ptr->next; 661 | } else { 662 | break; 663 | } 664 | } 665 | 666 | XFreeColormap(xinfo.display, cmap_sn); 667 | 668 | if (dying == 1) { 669 | XColor xcolour_ho; 670 | char xcolor_ho[] = "#000000"; 671 | Colormap cmap_ho = DefaultColormap(xinfo.display, DefaultScreen(xinfo.display)); 672 | XParseColor(xinfo.display, cmap_ho, xcolor_ho, &xcolour_ho); 673 | XAllocColor(xinfo.display, cmap_ho, &xcolour_ho); 674 | XSetForeground(xinfo.display, xinfo.gc[0], xcolour_ho.pixel); 675 | 676 | XDrawString(xinfo.display, xinfo.pixmap, xinfo.gc[0], 365, 200, "HIT OBSTACLE", 12); 677 | 678 | if (died == 1) { 679 | XDrawString(xinfo.display, xinfo.pixmap, xinfo.gc[0], 350, 240, "PRESS r TO RESTART", 18); 680 | 681 | } else { 682 | XDrawString(xinfo.display, xinfo.pixmap, xinfo.gc[0], 350, 240, "PRESS r TO RESTART", 18); 683 | XDrawString(xinfo.display, xinfo.pixmap, xinfo.gc[0], 398, 260, "OR", 2); 684 | XDrawString(xinfo.display, xinfo.pixmap, xinfo.gc[0], 330, 280, "PRESS w/a/s/d TO CONTINUE", 25); 685 | 686 | } 687 | XFreeColormap(xinfo.display, cmap_ho); 688 | } 689 | 690 | if (pause_indicator == 1) { 691 | XColor xcolour_ho; 692 | char xcolor_ho[] = "#000000"; 693 | Colormap cmap_ho = DefaultColormap(xinfo.display, DefaultScreen(xinfo.display)); 694 | XParseColor(xinfo.display, cmap_ho, xcolor_ho, &xcolour_ho); 695 | XAllocColor(xinfo.display, cmap_ho, &xcolour_ho); 696 | XSetForeground(xinfo.display, xinfo.gc[0], xcolour_ho.pixel); 697 | 698 | XDrawString(xinfo.display, xinfo.pixmap, xinfo.gc[0], 390, 200, "PAUSE", 5); 699 | XDrawString(xinfo.display, xinfo.pixmap, xinfo.gc[0], 350, 240, "PRESS r TO RESTART", 18); 700 | XDrawString(xinfo.display, xinfo.pixmap, xinfo.gc[0], 398, 260, "OR", 2); 701 | XDrawString(xinfo.display, xinfo.pixmap, xinfo.gc[0], 330, 280, "PRESS p/w/a/s/d TO CONTINUE", 27); 702 | 703 | XFreeColormap(xinfo.display, cmap_ho); 704 | } 705 | } 706 | 707 | 708 | void move(XInfo &xinfo) { 709 | 710 | int preX = head->x; 711 | int preY = head->y; 712 | 713 | if (direction == 0) { 714 | snakeLst * newHead = new snakeLst(preX, preY - 10, head, NULL); 715 | head = newHead; 716 | 717 | deleteLastNode(); 718 | 719 | } else if (direction == 1) { 720 | snakeLst * newHead = new snakeLst(preX, preY + 10, head, NULL); 721 | head = newHead; 722 | 723 | deleteLastNode(); 724 | 725 | } else if (direction == 2) { 726 | snakeLst * newHead = new snakeLst(preX - 10, preY, head, NULL); 727 | head = newHead; 728 | 729 | deleteLastNode(); 730 | 731 | } else if (direction == 3) { 732 | snakeLst * newHead = new snakeLst(preX + 10, preY, head, NULL); 733 | head = newHead; 734 | 735 | deleteLastNode(); 736 | 737 | } 738 | 739 | int newX = head->x; 740 | int newY = head->y; 741 | 742 | int fX = fruit.getX(); 743 | int fY = fruit.getY(); 744 | 745 | if (((fX - newX > -10 && fX - newX <= 0) || (fX - newX < 10 && fX - newX >= 0)) 746 | && ((fY - newY > -10 && fY - newY <= 0) || (fY - newY < 10 && fY - newY >= 0))) { 747 | didEatFruit(head); 748 | } 749 | 750 | newX = head->x; 751 | newY = head->y; 752 | 753 | if (direction == 0 && newY - 10 < 60) { 754 | didHitObstacle(head, xinfo); 755 | } else if (direction == 1 && newY + 10 > 490) { 756 | didHitObstacle(head, xinfo); 757 | } else if (direction == 2 && newX - 10 < 60) { 758 | didHitObstacle(head, xinfo); 759 | } else if (direction == 3 && newX + 10 > 740) { 760 | didHitObstacle(head, xinfo); 761 | } 762 | 763 | 764 | snakeLst * hh = head; 765 | if (hh->next != NULL) { 766 | hh = hh->next; 767 | } 768 | 769 | while (hh->next != NULL) { 770 | hh = hh->next; 771 | if (direction == 0 && newY - 10 == hh->y && newX == hh->x) { 772 | didHitObstacle(head, xinfo); 773 | break; 774 | } else if (direction == 1 && newY + 10 == hh->y && newX == hh->x) { 775 | didHitObstacle(head, xinfo); 776 | break; 777 | } else if (direction == 2 && newX - 10 == hh->x && newY == hh->y) { 778 | didHitObstacle(head, xinfo); 779 | break; 780 | } else if (direction == 3 && newX + 10 == hh->x && newY == hh->y) { 781 | didHitObstacle(head, xinfo); 782 | break; 783 | } 784 | } 785 | 786 | } 787 | 788 | int getX() { 789 | return x; 790 | } 791 | 792 | int getY() { 793 | return y; 794 | } 795 | 796 | int getDirection() { 797 | return direction; 798 | } 799 | 800 | void setDirection(int d) { 801 | direction = d; 802 | } 803 | 804 | 805 | void didEatFruit(snakeLst * h) { 806 | int x = fruit.getX(); 807 | int y = fruit.getY(); 808 | 809 | snakeLst * newHead = new snakeLst(x, y, h, NULL); 810 | head = newHead; 811 | score += 100; 812 | snake_size += 1; 813 | 814 | if (fruit.getGolden() == 1) { 815 | died -= 1; 816 | } 817 | 818 | if (fruit.getSlow_down() == 1 && speed > 1) { 819 | speed -= 1; 820 | } 821 | 822 | fruit.refresh(x, y); 823 | } 824 | 825 | void didHitObstacle(snakeLst * h, XInfo &xinfo) { 826 | died += 1; 827 | dying = 1; 828 | } 829 | 830 | void turnLeft(snakeLst * h, snakeLst * t, XInfo &xinfo) { 831 | // d = 1 increase x 832 | // d = 0 decrease x 833 | // d = 3 decrease y 834 | // d = 2 increase y 835 | 836 | int preX = h->x; 837 | int preY = h->y; 838 | 839 | if (direction == 0) { 840 | snakeLst * newHead = new snakeLst(preX - 10, preY, head, NULL); 841 | head = newHead; 842 | direction = 2; 843 | } else if (direction == 1) { 844 | snakeLst * newHead = new snakeLst(preX + 10, preY, head, NULL); 845 | head = newHead; 846 | direction = 3; 847 | } else if (direction == 2) { 848 | snakeLst * newHead = new snakeLst(preX, preY + 10, head, NULL); 849 | head = newHead; 850 | direction = 1; 851 | } else if (direction == 3) { 852 | snakeLst * newHead = new snakeLst(preX, preY - 10, head, NULL); 853 | head = newHead; 854 | direction = 0; 855 | } 856 | 857 | deleteLastNode(); 858 | 859 | int newX = head->x; 860 | int newY = head->y; 861 | 862 | int fX = fruit.getX(); 863 | int fY = fruit.getY(); 864 | 865 | if (((fX - newX > -10 && fX - newX <= 0) || (fX - newX < 10 && fX - newX >= 0)) 866 | && ((fY - newY > -10 && fY - newY <= 0) || (fY - newY < 10 && fY - newY >= 0))) { 867 | didEatFruit(head); 868 | } 869 | 870 | newX = head->x; 871 | newY = head->y; 872 | 873 | if (direction == 0 && newY - 10 < 60) { 874 | didHitObstacle(head, xinfo); 875 | } else if (direction == 1 && newY + 10 > 490) { 876 | didHitObstacle(head, xinfo); 877 | } else if (direction == 2 && newX - 10 < 60) { 878 | didHitObstacle(head, xinfo); 879 | } else if (direction == 3 && newX + 10 > 740) { 880 | didHitObstacle(head, xinfo); 881 | } 882 | 883 | 884 | snakeLst * hh = head; 885 | if (hh->next != NULL) { 886 | hh = hh->next; 887 | } 888 | 889 | while (hh->next != NULL) { 890 | hh = hh->next; 891 | if (direction == 0 && newY - 10 == hh->y && newX == hh->x) { 892 | didHitObstacle(head, xinfo); 893 | break; 894 | } else if (direction == 1 && newY + 10 == hh->y && newX == hh->x) { 895 | didHitObstacle(head, xinfo); 896 | break; 897 | } else if (direction == 2 && newX - 10 == hh->x && newY == hh->y) { 898 | didHitObstacle(head, xinfo); 899 | break; 900 | } else if (direction == 3 && newX + 10 == hh->x && newY == hh->y) { 901 | didHitObstacle(head, xinfo); 902 | break; 903 | } 904 | } 905 | 906 | } 907 | 908 | void turnRight(snakeLst * h, snakeLst * t, XInfo &xinfo) { 909 | // d = 1 decrease x 910 | // d = 0 increase x 911 | // d = 3 increase y 912 | // d = 2 decrease y 913 | 914 | int preX = h->x; 915 | int preY = h->y; 916 | 917 | if (direction == 0) { 918 | snakeLst * newHead = new snakeLst(preX + 10, preY, head, NULL); 919 | head = newHead; 920 | direction = 3; 921 | } else if (direction == 1) { 922 | snakeLst * newHead = new snakeLst(preX - 10, preY, head, NULL); 923 | head = newHead; 924 | direction = 2; 925 | } else if (direction == 2) { 926 | snakeLst * newHead = new snakeLst(preX, preY - 10, head, NULL); 927 | head = newHead; 928 | direction = 0; 929 | } else if (direction == 3) { 930 | snakeLst * newHead = new snakeLst(preX, preY + 10, head, NULL); 931 | head = newHead; 932 | direction = 1; 933 | } 934 | 935 | deleteLastNode(); 936 | 937 | int newX = head->x; 938 | int newY = head->y; 939 | 940 | int fX = fruit.getX(); 941 | int fY = fruit.getY(); 942 | 943 | if (((fX - newX > -10 && fX - newX <= 0) || (fX - newX < 10 && fX - newX >= 0)) 944 | && ((fY - newY > -10 && fY - newY <= 0) || (fY - newY < 10 && fY - newY >= 0))) { 945 | didEatFruit(head); 946 | } 947 | 948 | newX = head->x; 949 | newY = head->y; 950 | 951 | if (direction == 0 && newY - 10 < 60) { 952 | didHitObstacle(head, xinfo); 953 | } else if (direction == 1 && newY + 10 > 490) { 954 | didHitObstacle(head, xinfo); 955 | } else if (direction == 2 && newX - 10 < 60) { 956 | didHitObstacle(head, xinfo); 957 | } else if (direction == 3 && newX + 10 > 740) { 958 | didHitObstacle(head, xinfo); 959 | } 960 | 961 | snakeLst * hh = head; 962 | if (hh->next != NULL) { 963 | hh = hh->next; 964 | } 965 | 966 | while (hh->next != NULL) { 967 | hh = hh->next; 968 | if (direction == 0 && newY - 10 == hh->y && newX == hh->x) { 969 | didHitObstacle(head, xinfo); 970 | break; 971 | } else if (direction == 1 && newY + 10 == hh->y && newX == hh->x) { 972 | didHitObstacle(head, xinfo); 973 | break; 974 | } else if (direction == 2 && newX - 10 == hh->x && newY == hh->y) { 975 | didHitObstacle(head, xinfo); 976 | break; 977 | } else if (direction == 3 && newX + 10 == hh->x && newY == hh->y) { 978 | didHitObstacle(head, xinfo); 979 | break; 980 | } 981 | } 982 | } 983 | 984 | Snake(int x, int y): x(x), y(y) { 985 | direction = 3; 986 | blockSize = 10; 987 | } 988 | 989 | private: 990 | int x; 991 | int y; 992 | int blockSize; 993 | int direction; 994 | }; 995 | 996 | 997 | 998 | Snake snake(100, 450); 999 | 1000 | /* 1001 | * Initialize X and create a window 1002 | */ 1003 | void initX(int argc, char *argv[], XInfo &xInfo) { 1004 | if (argc == 3) { 1005 | stringstream ss; 1006 | ss << argv[1]; 1007 | ss >> FPS; 1008 | stringstream ss2; 1009 | ss2 << argv[2]; 1010 | ss2 >> speed; 1011 | speed_saver = speed; 1012 | } 1013 | 1014 | XSizeHints hints; 1015 | unsigned long white, black; 1016 | 1017 | /* 1018 | * Display opening uses the DISPLAY environment variable. 1019 | * It can go wrong if DISPLAY isn't set, or you don't have permission. 1020 | */ 1021 | xInfo.display = XOpenDisplay( "" ); 1022 | if ( !xInfo.display ) { 1023 | error( "Can't open display." ); 1024 | } 1025 | 1026 | /* 1027 | * Find out some things about the display you're using. 1028 | */ 1029 | xInfo.screen = DefaultScreen( xInfo.display ); 1030 | 1031 | white = XWhitePixel( xInfo.display, xInfo.screen ); 1032 | black = XBlackPixel( xInfo.display, xInfo.screen ); 1033 | 1034 | XColor xcolour_bg; 1035 | char xcolor_bg[] = "#F5F5F5"; 1036 | Colormap cmap_bg = DefaultColormap(xInfo.display, DefaultScreen(xInfo.display)); 1037 | XParseColor(xInfo.display, cmap_bg, xcolor_bg, &xcolour_bg); 1038 | XAllocColor(xInfo.display, cmap_bg, &xcolour_bg); 1039 | 1040 | hints.x = 100; 1041 | hints.y = 100; 1042 | hints.width = 800; 1043 | hints.height = 600; 1044 | hints.flags = PPosition | PSize; 1045 | 1046 | xInfo.window = XCreateSimpleWindow( 1047 | xInfo.display, // display where window appears 1048 | DefaultRootWindow( xInfo.display ), // window's parent in window tree 1049 | hints.x, hints.y, // upper left corner location 1050 | hints.width, hints.height, // size of the window 1051 | Border, // width of window's border 1052 | black, // window border colour 1053 | xcolour_bg.pixel ); // window background colour 1054 | 1055 | XSetStandardProperties( 1056 | xInfo.display, // display containing the window 1057 | xInfo.window, // window whose properties are set 1058 | "animation", // window's title 1059 | "Animate", // icon's title 1060 | None, // pixmap for the icon 1061 | argv, argc, // applications command line args 1062 | &hints ); // size hints for the window 1063 | 1064 | /* 1065 | * Create Graphics Contexts 1066 | */ 1067 | int i = 0; 1068 | xInfo.gc[i] = XCreateGC(xInfo.display, xInfo.window, 0, 0); 1069 | XSetForeground(xInfo.display, xInfo.gc[i], BlackPixel(xInfo.display, xInfo.screen)); 1070 | XSetBackground(xInfo.display, xInfo.gc[i], WhitePixel(xInfo.display, xInfo.screen)); 1071 | XSetFillStyle(xInfo.display, xInfo.gc[i], FillSolid); 1072 | XSetLineAttributes(xInfo.display, xInfo.gc[i], 1073 | 1, LineSolid, CapButt, JoinRound); 1074 | 1075 | XSelectInput(xInfo.display, xInfo.window, 1076 | ButtonPressMask | KeyPressMask | 1077 | PointerMotionMask | 1078 | EnterWindowMask | LeaveWindowMask | 1079 | StructureNotifyMask); // for resize events 1080 | 1081 | XSetGraphicsExposures(xInfo.display, xInfo.gc[i],0); 1082 | 1083 | xInfo.pixmap = XCreatePixmap(xInfo.display, xInfo.window, 800, 600, XDefaultDepth(xInfo.display, xInfo.screen)); 1084 | 1085 | /* 1086 | * Put the window on the screen. 1087 | */ 1088 | XMapRaised( xInfo.display, xInfo.window ); 1089 | XFlush(xInfo.display); 1090 | } 1091 | 1092 | 1093 | void handleKeyPress(XInfo &xinfo, XEvent &event) { 1094 | KeySym key; 1095 | char text[BufferSize]; 1096 | 1097 | /* 1098 | * Exit when 'q' is typed. 1099 | * This is a simplified approach that does NOT use localization. 1100 | */ 1101 | int i = XLookupString( 1102 | (XKeyEvent *)&event, // the keyboard event 1103 | text, // buffer when text will be written 1104 | BufferSize, // size of the text buffer 1105 | &key, // workstation-independent key symbol 1106 | NULL ); // pointer to a composeStatus structure (unused) 1107 | if ( i == 1) { 1108 | printf("Got key press -- %c\n", text[0]); 1109 | if (start_screen == 1) { 1110 | 1111 | start_screen = 0; 1112 | dList.pop_front(); 1113 | dList.push_front(&snake); 1114 | dList.push_front(&fruit); 1115 | dList.push_front(&obstacles); 1116 | 1117 | } else if (text[0] == 'q' || text[0] == 'Q') { 1118 | while (snake_size > 0) { 1119 | deleteLastNode(); 1120 | snake_size -= 1; 1121 | } 1122 | quit_indicator = 1; 1123 | 1124 | } else if ((text[0] == 'p' || text[0] == 'P') && pause_indicator == 0) { 1125 | 1126 | pause_indicator = 1; 1127 | 1128 | } else if ((text[0] == 'p' || text[0] == 'P') && pause_indicator == 1) { 1129 | 1130 | pause_indicator = 0; 1131 | 1132 | } else if ((text[0] == 'w' || text[0] == 'W') && died < 1) { 1133 | 1134 | if (pause_indicator == 1) { 1135 | pause_indicator = 0; 1136 | } 1137 | 1138 | if (dying == 1) { 1139 | dying = 0; 1140 | } 1141 | 1142 | int d = snake.getDirection(); 1143 | 1144 | if (d == 2) { 1145 | just_turned = 1; 1146 | snake.turnRight(head, tail, xinfo); 1147 | } else if (d == 3) { 1148 | just_turned = 1; 1149 | snake.turnLeft(head, tail, xinfo); 1150 | } 1151 | } else if ((text[0] == 'a' || text[0] == 'A') && died < 1) { 1152 | 1153 | if (pause_indicator == 1) { 1154 | pause_indicator = 0; 1155 | } 1156 | 1157 | if (dying == 1) { 1158 | dying = 0; 1159 | } 1160 | 1161 | int d = snake.getDirection(); 1162 | 1163 | if (d == 0) { 1164 | just_turned = 1; 1165 | snake.turnLeft(head, tail, xinfo); 1166 | } else if (d == 1) { 1167 | just_turned = 1; 1168 | snake.turnRight(head, tail, xinfo); 1169 | } 1170 | 1171 | } else if ((text[0] == 's' || text[0] == 'S') && died < 1) { 1172 | 1173 | if (pause_indicator == 1) { 1174 | pause_indicator = 0; 1175 | } 1176 | 1177 | if (dying == 1) { 1178 | dying = 0; 1179 | } 1180 | 1181 | int d = snake.getDirection(); 1182 | 1183 | if (d == 2) { 1184 | just_turned = 1; 1185 | snake.turnLeft(head, tail, xinfo); 1186 | } else if (d == 3) { 1187 | just_turned = 1; 1188 | snake.turnRight(head, tail, xinfo); 1189 | } 1190 | 1191 | } else if ((text[0] == 'd' || text[0] == 'D') && died < 1) { 1192 | 1193 | if (pause_indicator == 1) { 1194 | pause_indicator = 0; 1195 | } 1196 | 1197 | if (dying == 1) { 1198 | dying = 0; 1199 | } 1200 | 1201 | int d = snake.getDirection(); 1202 | 1203 | if (d == 0) { 1204 | just_turned = 1; 1205 | snake.turnRight(head, tail, xinfo); 1206 | } else if (d == 1) { 1207 | just_turned = 1; 1208 | snake.turnLeft(head, tail, xinfo); 1209 | } 1210 | 1211 | } else if (text[0] == 'r' || text[0] == 'R') { 1212 | if (pause_indicator == 1) { 1213 | pause_indicator = 0; 1214 | } 1215 | 1216 | if (dying == 1) { 1217 | dying = 0; 1218 | } 1219 | 1220 | died = 0; 1221 | snake.setDirection(3); 1222 | while (snake_size > 0) { 1223 | deleteLastNode(); 1224 | snake_size -= 1; 1225 | } 1226 | head = new snakeLst(100, 450, NULL, NULL); 1227 | tail = new snakeLst(100, 450, NULL, head); 1228 | fruit.refresh(fruit.getX(), fruit.getY()); 1229 | score = 0; 1230 | snake_size = 1; 1231 | speed = speed_saver; 1232 | repaint(xinfo); 1233 | 1234 | } 1235 | } 1236 | } 1237 | 1238 | 1239 | void handleAnimation(XInfo &xinfo, int inside) { 1240 | /* 1241 | * ADD YOUR OWN LOGIC 1242 | * This method handles animation for different objects on the screen and readies the next frame before the screen is re-painted. 1243 | */ 1244 | snake.move(xinfo); 1245 | } 1246 | 1247 | // get microseconds 1248 | unsigned long now() { 1249 | timeval tv; 1250 | gettimeofday(&tv, NULL); 1251 | return tv.tv_sec * 1000000 + tv.tv_usec; 1252 | } 1253 | 1254 | void eventLoop(XInfo &xinfo) { 1255 | if (start_screen == 1) { 1256 | dList.push_front(&startScreen); 1257 | } else { 1258 | // Add stuff to paint to the display list 1259 | dList.push_front(&snake); 1260 | dList.push_front(&fruit); 1261 | dList.push_front(&obstacles); 1262 | } 1263 | 1264 | XEvent event; 1265 | unsigned long lastRepaint = 0; 1266 | int inside = 0; 1267 | 1268 | while( true ) { 1269 | 1270 | if (XPending(xinfo.display) > 0) { 1271 | XNextEvent( xinfo.display, &event ); 1272 | cout << "event.type=" << event.type << "\n"; 1273 | switch( event.type ) { 1274 | case KeyPress: 1275 | handleKeyPress(xinfo, event); 1276 | if (quit_indicator == 1) { 1277 | return; 1278 | } 1279 | break; 1280 | case EnterNotify: 1281 | inside = 1; 1282 | break; 1283 | case LeaveNotify: 1284 | inside = 0; 1285 | break; 1286 | default: 1287 | continue; 1288 | } 1289 | } 1290 | 1291 | usleep(1000000/FPS); 1292 | if (pause_indicator == 0 && dying == 0 && died < 1 && start_screen == 0 && just_turned == 0) { 1293 | int diff = (200000 / speed) - (1000000 / FPS); 1294 | if (diff > 0 && start_screen == 0) usleep(diff); 1295 | handleAnimation(xinfo, inside); 1296 | } 1297 | just_turned = 0; 1298 | repaint(xinfo); 1299 | } 1300 | } 1301 | 1302 | 1303 | 1304 | /* 1305 | * Start executing here. 1306 | * First initialize window. 1307 | * Next loop responding to events. 1308 | * Exit forcing window manager to clean up - cheesy, but easy. 1309 | */ 1310 | 1311 | int main ( int argc, char *argv[] ) { 1312 | XInfo xInfo; 1313 | 1314 | initX(argc, argv, xInfo); 1315 | eventLoop(xInfo); 1316 | XCloseDisplay(xInfo.display); 1317 | } 1318 | --------------------------------------------------------------------------------