J.P. Armstrong
/
FourInARow_NokiaLCD
Connect Four style game. More information can be found here... http://www.armtronics.com/tag/mbedpg
main.cpp@0:2fa346a91818, 2012-01-29 (annotated)
- Committer:
- jp
- Date:
- Sun Jan 29 19:14:37 2012 +0000
- Revision:
- 0:2fa346a91818
Initial Commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
jp | 0:2fa346a91818 | 1 | // Hello World! for Nokia LCD, sford |
jp | 0:2fa346a91818 | 2 | // - LCD6610 is for newest Sparkfun breakout |
jp | 0:2fa346a91818 | 3 | |
jp | 0:2fa346a91818 | 4 | #include "mbed.h" |
jp | 0:2fa346a91818 | 5 | #include "NokiaLCD.h" |
jp | 0:2fa346a91818 | 6 | #define PIECE_GAP 18 |
jp | 0:2fa346a91818 | 7 | #define PIECE_SIZE 6 |
jp | 0:2fa346a91818 | 8 | #define PI 3.1415 |
jp | 0:2fa346a91818 | 9 | #define RED 0xFF0000 |
jp | 0:2fa346a91818 | 10 | #define GREEN 0x00FF00 |
jp | 0:2fa346a91818 | 11 | |
jp | 0:2fa346a91818 | 12 | InterruptIn button1(p21); |
jp | 0:2fa346a91818 | 13 | InterruptIn button2(p22); |
jp | 0:2fa346a91818 | 14 | InterruptIn button3(p23); |
jp | 0:2fa346a91818 | 15 | |
jp | 0:2fa346a91818 | 16 | DigitalOut ledRed(p24); |
jp | 0:2fa346a91818 | 17 | DigitalOut ledGreen(p25); |
jp | 0:2fa346a91818 | 18 | |
jp | 0:2fa346a91818 | 19 | void refreshMovingPiece(); |
jp | 0:2fa346a91818 | 20 | void displaySplash(); |
jp | 0:2fa346a91818 | 21 | bool scanForWinner(); |
jp | 0:2fa346a91818 | 22 | void lcdAlert(const char*); |
jp | 0:2fa346a91818 | 23 | |
jp | 0:2fa346a91818 | 24 | void drawCircle(int,int,int,int); |
jp | 0:2fa346a91818 | 25 | void fillCircle(int,int,int,int); |
jp | 0:2fa346a91818 | 26 | void drawLine(int,int,int,int,int); |
jp | 0:2fa346a91818 | 27 | |
jp | 0:2fa346a91818 | 28 | NokiaLCD lcd(p5, p7, p8, p9, NokiaLCD::LCD6610); // mosi, sclk, cs, rst, type |
jp | 0:2fa346a91818 | 29 | int board[6][7]; |
jp | 0:2fa346a91818 | 30 | int board_stop_row[7] = {5,5,5,5,5,5,5}; |
jp | 0:2fa346a91818 | 31 | |
jp | 0:2fa346a91818 | 32 | int player_active = RED; |
jp | 0:2fa346a91818 | 33 | int player_position = 3; |
jp | 0:2fa346a91818 | 34 | int next_step = false; |
jp | 0:2fa346a91818 | 35 | |
jp | 0:2fa346a91818 | 36 | |
jp | 0:2fa346a91818 | 37 | void buttonMoveRight() { |
jp | 0:2fa346a91818 | 38 | player_position = (++player_position % 7); |
jp | 0:2fa346a91818 | 39 | refreshMovingPiece(); |
jp | 0:2fa346a91818 | 40 | wait(0.2); |
jp | 0:2fa346a91818 | 41 | } |
jp | 0:2fa346a91818 | 42 | |
jp | 0:2fa346a91818 | 43 | void buttonMoveLeft() { |
jp | 0:2fa346a91818 | 44 | player_position = (--player_position % 7); |
jp | 0:2fa346a91818 | 45 | refreshMovingPiece(); |
jp | 0:2fa346a91818 | 46 | wait(0.2); |
jp | 0:2fa346a91818 | 47 | } |
jp | 0:2fa346a91818 | 48 | |
jp | 0:2fa346a91818 | 49 | void refreshMovingPiece() { |
jp | 0:2fa346a91818 | 50 | |
jp | 0:2fa346a91818 | 51 | for(int i = 0; i < 7; i++) |
jp | 0:2fa346a91818 | 52 | fillCircle(10 + PIECE_GAP * i, 8, PIECE_SIZE, 0x000000); |
jp | 0:2fa346a91818 | 53 | |
jp | 0:2fa346a91818 | 54 | fillCircle(10 + PIECE_GAP * player_position, 8, PIECE_SIZE, player_active); |
jp | 0:2fa346a91818 | 55 | } |
jp | 0:2fa346a91818 | 56 | |
jp | 0:2fa346a91818 | 57 | void buttonSelect() { |
jp | 0:2fa346a91818 | 58 | |
jp | 0:2fa346a91818 | 59 | // PLACE CHIP WHERE IT'S MEANT TO BE |
jp | 0:2fa346a91818 | 60 | |
jp | 0:2fa346a91818 | 61 | if (board_stop_row[player_position] < 0) { |
jp | 0:2fa346a91818 | 62 | lcdAlert("Illegal Move"); |
jp | 0:2fa346a91818 | 63 | return; |
jp | 0:2fa346a91818 | 64 | } |
jp | 0:2fa346a91818 | 65 | |
jp | 0:2fa346a91818 | 66 | board[board_stop_row[player_position]][player_position] = player_active; |
jp | 0:2fa346a91818 | 67 | board_stop_row[player_position]--; |
jp | 0:2fa346a91818 | 68 | |
jp | 0:2fa346a91818 | 69 | // RESET FOR NEXT PLAYER |
jp | 0:2fa346a91818 | 70 | player_active = ( player_active == RED ) ? GREEN : RED; |
jp | 0:2fa346a91818 | 71 | player_position = 3; |
jp | 0:2fa346a91818 | 72 | refreshMovingPiece(); |
jp | 0:2fa346a91818 | 73 | next_step = true; |
jp | 0:2fa346a91818 | 74 | |
jp | 0:2fa346a91818 | 75 | wait(0.2); |
jp | 0:2fa346a91818 | 76 | } |
jp | 0:2fa346a91818 | 77 | |
jp | 0:2fa346a91818 | 78 | int main() { |
jp | 0:2fa346a91818 | 79 | |
jp | 0:2fa346a91818 | 80 | displaySplash(); |
jp | 0:2fa346a91818 | 81 | |
jp | 0:2fa346a91818 | 82 | button3.rise(&buttonMoveLeft); |
jp | 0:2fa346a91818 | 83 | button2.rise(&buttonMoveRight); |
jp | 0:2fa346a91818 | 84 | button1.rise(&buttonSelect); |
jp | 0:2fa346a91818 | 85 | |
jp | 0:2fa346a91818 | 86 | lcd.cls(); |
jp | 0:2fa346a91818 | 87 | lcd.background(0x000000); |
jp | 0:2fa346a91818 | 88 | lcd.fill(2, 16, 126, 110, 0xFFFF00); |
jp | 0:2fa346a91818 | 89 | |
jp | 0:2fa346a91818 | 90 | player_position = 3; |
jp | 0:2fa346a91818 | 91 | refreshMovingPiece(); |
jp | 0:2fa346a91818 | 92 | |
jp | 0:2fa346a91818 | 93 | int cnt = 0; |
jp | 0:2fa346a91818 | 94 | int color = 0x0; |
jp | 0:2fa346a91818 | 95 | |
jp | 0:2fa346a91818 | 96 | do { |
jp | 0:2fa346a91818 | 97 | |
jp | 0:2fa346a91818 | 98 | for(cnt = 0; cnt < 42; cnt++) { |
jp | 0:2fa346a91818 | 99 | color = board[(cnt / 7)][(cnt % 7)]; |
jp | 0:2fa346a91818 | 100 | fillCircle(10 + PIECE_GAP * (cnt % 7), 24 + PIECE_GAP * (cnt / 7), PIECE_SIZE, color); |
jp | 0:2fa346a91818 | 101 | } |
jp | 0:2fa346a91818 | 102 | /* |
jp | 0:2fa346a91818 | 103 | if (scanForWinner()) { |
jp | 0:2fa346a91818 | 104 | for(cnt = 0; cnt < 42; cnt++) { |
jp | 0:2fa346a91818 | 105 | board[(cnt / 7)][(cnt % 7)] = NULL; |
jp | 0:2fa346a91818 | 106 | } |
jp | 0:2fa346a91818 | 107 | } |
jp | 0:2fa346a91818 | 108 | */ |
jp | 0:2fa346a91818 | 109 | while (true) { |
jp | 0:2fa346a91818 | 110 | if (next_step) break; |
jp | 0:2fa346a91818 | 111 | wait(0.25); |
jp | 0:2fa346a91818 | 112 | } |
jp | 0:2fa346a91818 | 113 | |
jp | 0:2fa346a91818 | 114 | next_step = false; |
jp | 0:2fa346a91818 | 115 | |
jp | 0:2fa346a91818 | 116 | } |
jp | 0:2fa346a91818 | 117 | while(true); |
jp | 0:2fa346a91818 | 118 | } |
jp | 0:2fa346a91818 | 119 | |
jp | 0:2fa346a91818 | 120 | |
jp | 0:2fa346a91818 | 121 | bool scanForWinner() { |
jp | 0:2fa346a91818 | 122 | |
jp | 0:2fa346a91818 | 123 | int winner = 0; |
jp | 0:2fa346a91818 | 124 | |
jp | 0:2fa346a91818 | 125 | for (int y = 0; y < 6; y++) { |
jp | 0:2fa346a91818 | 126 | |
jp | 0:2fa346a91818 | 127 | int lead = 0; |
jp | 0:2fa346a91818 | 128 | int count = 0; |
jp | 0:2fa346a91818 | 129 | |
jp | 0:2fa346a91818 | 130 | for (int x = 0; x < 7; x++) { |
jp | 0:2fa346a91818 | 131 | |
jp | 0:2fa346a91818 | 132 | if (board[y][x] == 0) |
jp | 0:2fa346a91818 | 133 | break; |
jp | 0:2fa346a91818 | 134 | |
jp | 0:2fa346a91818 | 135 | if (board[y][x] != lead) { |
jp | 0:2fa346a91818 | 136 | lead = board[y][x]; |
jp | 0:2fa346a91818 | 137 | count = 0; |
jp | 0:2fa346a91818 | 138 | } |
jp | 0:2fa346a91818 | 139 | |
jp | 0:2fa346a91818 | 140 | count++; |
jp | 0:2fa346a91818 | 141 | |
jp | 0:2fa346a91818 | 142 | if (count == 4) { |
jp | 0:2fa346a91818 | 143 | winner = lead; |
jp | 0:2fa346a91818 | 144 | goto someone_won; |
jp | 0:2fa346a91818 | 145 | } |
jp | 0:2fa346a91818 | 146 | } |
jp | 0:2fa346a91818 | 147 | |
jp | 0:2fa346a91818 | 148 | for (int x = 6; x >= 0; x--) { |
jp | 0:2fa346a91818 | 149 | |
jp | 0:2fa346a91818 | 150 | if (board[x][y] == 0) |
jp | 0:2fa346a91818 | 151 | break; |
jp | 0:2fa346a91818 | 152 | |
jp | 0:2fa346a91818 | 153 | if (board[x][y] != lead) { |
jp | 0:2fa346a91818 | 154 | lead = board[x][y]; |
jp | 0:2fa346a91818 | 155 | count = 0; |
jp | 0:2fa346a91818 | 156 | } |
jp | 0:2fa346a91818 | 157 | |
jp | 0:2fa346a91818 | 158 | count++; |
jp | 0:2fa346a91818 | 159 | |
jp | 0:2fa346a91818 | 160 | if (count == 4) |
jp | 0:2fa346a91818 | 161 | goto someone_won; |
jp | 0:2fa346a91818 | 162 | |
jp | 0:2fa346a91818 | 163 | } |
jp | 0:2fa346a91818 | 164 | } |
jp | 0:2fa346a91818 | 165 | |
jp | 0:2fa346a91818 | 166 | return false; |
jp | 0:2fa346a91818 | 167 | |
jp | 0:2fa346a91818 | 168 | someone_won: |
jp | 0:2fa346a91818 | 169 | |
jp | 0:2fa346a91818 | 170 | if (winner == RED) |
jp | 0:2fa346a91818 | 171 | lcdAlert("RED WON!"); |
jp | 0:2fa346a91818 | 172 | else |
jp | 0:2fa346a91818 | 173 | lcdAlert("GREEN WON!"); |
jp | 0:2fa346a91818 | 174 | |
jp | 0:2fa346a91818 | 175 | return true; |
jp | 0:2fa346a91818 | 176 | } |
jp | 0:2fa346a91818 | 177 | void lcdAlert(const char* msg) { |
jp | 0:2fa346a91818 | 178 | |
jp | 0:2fa346a91818 | 179 | lcd.fill(7, 49, 112, 62, 0xFF0000); |
jp | 0:2fa346a91818 | 180 | lcd.fill(8, 50, 110, 60, 0x0); |
jp | 0:2fa346a91818 | 181 | lcd.locate(2,9); |
jp | 0:2fa346a91818 | 182 | lcd.printf(msg); |
jp | 0:2fa346a91818 | 183 | wait(2); |
jp | 0:2fa346a91818 | 184 | |
jp | 0:2fa346a91818 | 185 | lcd.cls(); |
jp | 0:2fa346a91818 | 186 | lcd.background(0x000000); |
jp | 0:2fa346a91818 | 187 | lcd.fill(2, 16, 126, 110, 0xFFFF00); |
jp | 0:2fa346a91818 | 188 | |
jp | 0:2fa346a91818 | 189 | refreshMovingPiece(); |
jp | 0:2fa346a91818 | 190 | next_step = true; |
jp | 0:2fa346a91818 | 191 | |
jp | 0:2fa346a91818 | 192 | } |
jp | 0:2fa346a91818 | 193 | void displaySplash() { |
jp | 0:2fa346a91818 | 194 | lcd.cls(); |
jp | 0:2fa346a91818 | 195 | lcd.background(0x000000); |
jp | 0:2fa346a91818 | 196 | |
jp | 0:2fa346a91818 | 197 | lcd.foreground(0xFF0000); |
jp | 0:2fa346a91818 | 198 | lcd.locate(2, 4); |
jp | 0:2fa346a91818 | 199 | lcd.printf("FOUR"); |
jp | 0:2fa346a91818 | 200 | |
jp | 0:2fa346a91818 | 201 | lcd.foreground(0x00FF00); |
jp | 0:2fa346a91818 | 202 | lcd.locate(6, 5); |
jp | 0:2fa346a91818 | 203 | lcd.printf("IN A"); |
jp | 0:2fa346a91818 | 204 | |
jp | 0:2fa346a91818 | 205 | lcd.foreground(0x0000FF); |
jp | 0:2fa346a91818 | 206 | lcd.locate(10, 6); |
jp | 0:2fa346a91818 | 207 | lcd.printf("ROW!"); |
jp | 0:2fa346a91818 | 208 | |
jp | 0:2fa346a91818 | 209 | lcd.foreground(0xFFFFFF); |
jp | 0:2fa346a91818 | 210 | lcd.locate(2, 10); |
jp | 0:2fa346a91818 | 211 | lcd.printf("JP ARMSTRONG"); |
jp | 0:2fa346a91818 | 212 | lcd.locate(1, 12); |
jp | 0:2fa346a91818 | 213 | lcd.printf("ARMTRONICS.COM"); |
jp | 0:2fa346a91818 | 214 | wait(3); |
jp | 0:2fa346a91818 | 215 | } |
jp | 0:2fa346a91818 | 216 | |
jp | 0:2fa346a91818 | 217 | /**********************************************************************************/ |
jp | 0:2fa346a91818 | 218 | |
jp | 0:2fa346a91818 | 219 | // From: http://free.pages.at/easyfilter/bresenham.html |
jp | 0:2fa346a91818 | 220 | void drawCircle(int xm, int ym, int r, int color) |
jp | 0:2fa346a91818 | 221 | { |
jp | 0:2fa346a91818 | 222 | int x = -r, y = 0, err = 2-2*r; /* II. Quadrant */ |
jp | 0:2fa346a91818 | 223 | do { |
jp | 0:2fa346a91818 | 224 | lcd.pixel(xm-x, ym+y, color); /* I. Quadrant */ |
jp | 0:2fa346a91818 | 225 | lcd.pixel(xm-y, ym-x, color); /* II. Quadrant */ |
jp | 0:2fa346a91818 | 226 | lcd.pixel(xm+x, ym-y, color); /* III. Quadrant */ |
jp | 0:2fa346a91818 | 227 | lcd.pixel(xm+y, ym+x, color); /* IV. Quadrant */ |
jp | 0:2fa346a91818 | 228 | |
jp | 0:2fa346a91818 | 229 | r = err; |
jp | 0:2fa346a91818 | 230 | if (r > x) err += ++x*2+1; /* e_xy+e_x > 0 */ |
jp | 0:2fa346a91818 | 231 | if (r <= y) err += ++y*2+1; /* e_xy+e_y < 0 */ |
jp | 0:2fa346a91818 | 232 | } while (x < 0); |
jp | 0:2fa346a91818 | 233 | |
jp | 0:2fa346a91818 | 234 | } |
jp | 0:2fa346a91818 | 235 | |
jp | 0:2fa346a91818 | 236 | void fillCircle(int xm, int ym, int r, int color) |
jp | 0:2fa346a91818 | 237 | { |
jp | 0:2fa346a91818 | 238 | int x = -r, y = 0, err = 2-2*r; // II. Quadrant |
jp | 0:2fa346a91818 | 239 | do { |
jp | 0:2fa346a91818 | 240 | drawLine(xm-x, ym+y, xm+x, ym-y, color); |
jp | 0:2fa346a91818 | 241 | drawLine(xm-y, ym-x, xm+y, ym+x, color); |
jp | 0:2fa346a91818 | 242 | |
jp | 0:2fa346a91818 | 243 | r = err; |
jp | 0:2fa346a91818 | 244 | if (r > x) err += ++x*2+1; /* e_xy+e_x > 0 */ |
jp | 0:2fa346a91818 | 245 | if (r <= y) err += ++y*2+1; /* e_xy+e_y < 0 */ |
jp | 0:2fa346a91818 | 246 | } while (x < 0); |
jp | 0:2fa346a91818 | 247 | |
jp | 0:2fa346a91818 | 248 | } |
jp | 0:2fa346a91818 | 249 | |
jp | 0:2fa346a91818 | 250 | // From http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#C.2B.2B |
jp | 0:2fa346a91818 | 251 | void drawLine(int x0, int y0, int x1, int y1, int color) { |
jp | 0:2fa346a91818 | 252 | |
jp | 0:2fa346a91818 | 253 | int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1; |
jp | 0:2fa346a91818 | 254 | int dy = abs(y1-y0), sy = y0<y1 ? 1 : -1; |
jp | 0:2fa346a91818 | 255 | int err = (dx>dy ? dx : -dy)/2, e2; |
jp | 0:2fa346a91818 | 256 | |
jp | 0:2fa346a91818 | 257 | for(;;){ |
jp | 0:2fa346a91818 | 258 | lcd.pixel(x0,y0, color); |
jp | 0:2fa346a91818 | 259 | if (x0==x1 && y0==y1) break; |
jp | 0:2fa346a91818 | 260 | e2 = err; |
jp | 0:2fa346a91818 | 261 | if (e2 >-dx) { err -= dy; x0 += sx; } |
jp | 0:2fa346a91818 | 262 | if (e2 < dy) { err += dx; y0 += sy; } |
jp | 0:2fa346a91818 | 263 | } |
jp | 0:2fa346a91818 | 264 | } |
jp | 0:2fa346a91818 | 265 | |
jp | 0:2fa346a91818 | 266 | /* |
jp | 0:2fa346a91818 | 267 | void drawCircle(int x, int y, int ox, int oy, int color) { |
jp | 0:2fa346a91818 | 268 | |
jp | 0:2fa346a91818 | 269 | int lx, rx, ly, ry; |
jp | 0:2fa346a91818 | 270 | |
jp | 0:2fa346a91818 | 271 | for(int i = 0; i < ox; i++) { |
jp | 0:2fa346a91818 | 272 | lcd.pixel(x + ox * cos((i*2*PI)/ox) ,y + oy * sin((i*2*PI)/oy), color); |
jp | 0:2fa346a91818 | 273 | } |
jp | 0:2fa346a91818 | 274 | } |
jp | 0:2fa346a91818 | 275 | */ |