#include #include #include "jscore.h" #define STATE_MENU 0 #define STATE_GAME 1 #define STATE_ENNERYORNEIM 2 Uint8 state = STATE_MENU; SDL_Window* sdlWindow; SDL_Renderer* sdlRenderer; SDL_Texture* sdlTexture; SDL_Event sdlEvent; bool should_exit = false; struct Tetromino { Uint16 figure; Uint8 orig, prev, next; }; Tetromino tetromino[19] { {0x0660, 0, 0, 0}, {0x4444, 1, 2, 2}, {0x0F00, 1, 1, 1}, {0x0C60, 2, 4, 4}, {0x2640, 2, 3, 3}, {0x06C0, 3, 6, 6}, {0x4620, 3, 5, 5}, {0x4460, 4, 8, 10}, {0x2E00, 4, 9, 7}, {0xC440, 4, 10, 8}, {0x0E80, 4, 7, 9}, {0x44C0, 5, 12, 14}, {0x0E20, 5, 13, 11}, {0x6440, 5, 14, 12}, {0x8E00, 5, 11, 13}, {0x4640, 6, 16, 18}, {0x4E00, 6, 17, 15}, {0x4C40, 6, 18, 16}, {0x0E40, 6, 15, 17} }; Uint8 starting[7] { 0, 1, 3, 5, 7, 11, 15 }; Uint8 colors[8][3] { {255, 0, 0}, {0, 255, 0}, {0, 0, 255}, {255, 255, 0}, {0, 255, 255}, {255, 0, 255}, {255, 128, 0}, {255, 255, 255} }; Uint8 board[18][10]; Uint8 bmp[448] {0x42, 0x4D, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x01, 0x00, 0x00, 0x12, 0x0B, 0x00, 0x00, 0x12, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x18, 0xF3, 0x83, 0x83, 0xCF, 0x83, 0x87, 0x00, 0x00, 0xF3, 0x39, 0x39, 0xCF, 0x79, 0xF3, 0x00, 0x00, 0x01, 0xF9, 0x39, 0xCF, 0x61, 0xF9, 0x00, 0x00, 0x33, 0xF9, 0x03, 0xE7, 0x87, 0x81, 0x00, 0x00, 0x93, 0x03, 0x3F, 0xF3, 0x1B, 0x39, 0x00, 0x00, 0xC3, 0x3F, 0x9F, 0x39, 0x3B, 0x39, 0x00, 0x41, 0xE3, 0x03, 0xC3, 0x01, 0x87, 0x83, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xE7, 0x01, 0xC7, 0x81, 0x01, 0x83, 0x00, 0x00, 0xE7, 0x1F, 0x9B, 0xE7, 0x1F, 0x39, 0x00, 0x00, 0xE7, 0x8F, 0x39, 0xE7, 0x87, 0xF9, 0x00, 0x00, 0xC3, 0xC7, 0x39, 0xE7, 0xC3, 0xC3, 0x00, 0x00, 0x99, 0xE3, 0x39, 0xE7, 0xF1, 0xE7, 0x00, 0x00, 0x99, 0xF1, 0xB3, 0xC7, 0x39, 0xF3, 0x00, 0x00, 0x99, 0x01, 0xC7, 0xE7, 0x83, 0x81, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x83, 0xE7, 0x83, 0xEF, 0x39, 0x39, 0x00, 0x00, 0x39, 0xE7, 0x39, 0xC7, 0x11, 0x11, 0x00, 0x00, 0xF9, 0xE7, 0x39, 0x83, 0x01, 0x83, 0x00, 0x00, 0x83, 0xE7, 0x39, 0x11, 0x01, 0xC7, 0x00, 0x00, 0x3F, 0xE7, 0x39, 0x39, 0x29, 0x83, 0x00, 0x00, 0x33, 0xE7, 0x39, 0x39, 0x39, 0x11, 0x00, 0x00, 0x87, 0x81, 0x39, 0x39, 0x39, 0x39, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x39, 0x39, 0x83, 0x3F, 0x85, 0x31, 0x00, 0x00, 0x39, 0x31, 0x39, 0x3F, 0x33, 0x23, 0x00, 0x00, 0x29, 0x21, 0x39, 0x03, 0x21, 0x07, 0x00, 0x00, 0x01, 0x01, 0x39, 0x39, 0x39, 0x31, 0x00, 0x00, 0x01, 0x09, 0x39, 0x39, 0x39, 0x39, 0x00, 0x00, 0x11, 0x19, 0x39, 0x39, 0x39, 0x39, 0x00, 0x00, 0x39, 0x39, 0x83, 0x03, 0x83, 0x03, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xC1, 0x39, 0x81, 0x83, 0x31, 0x01, 0x00, 0x00, 0x99, 0x39, 0xE7, 0x39, 0x23, 0x3F, 0x00, 0x00, 0x39, 0x39, 0xE7, 0xF9, 0x07, 0x3F, 0x00, 0x00, 0x31, 0x01, 0xE7, 0xF9, 0x0F, 0x3F, 0x00, 0x00, 0x3F, 0x39, 0xE7, 0xF9, 0x27, 0x3F, 0x00, 0x00, 0x9F, 0x39, 0xE7, 0xF9, 0x33, 0x3F, 0x00, 0x00, 0xC1, 0x39, 0x81, 0xF9, 0x39, 0x3F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x39, 0x03, 0xC3, 0x07, 0x01, 0x3F, 0x00, 0x00, 0x39, 0x39, 0x99, 0x33, 0x3F, 0x3F, 0x00, 0x00, 0x01, 0x39, 0x3F, 0x39, 0x3F, 0x3F, 0x00, 0x00, 0x39, 0x03, 0x3F, 0x39, 0x03, 0x03, 0x00, 0x00, 0x39, 0x39, 0x3F, 0x39, 0x3F, 0x3F, 0x00, 0x00, 0x93, 0x39, 0x99, 0x33, 0x3F, 0x3F, 0x00, 0x00, 0xC7, 0x03, 0xC3, 0x07, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00}; SDL_Point piece_pos {3, 0}; Uint8 current_piece = 0; Uint8 next_piece = 0; int level = 0, lines = 0, score = 0; Uint8 speed = (20-SDL_min(19, level))*3; bool is_valid_move() { int x = piece_pos.x+3; int y = piece_pos.y+3; Uint16 piece = tetromino[current_piece].figure; for (int i=0; i<16; i++) { if ((piece & 1) && ( (x >= 10) || (x < 0) || (y >= 18) || (board[y][x] != 0) ) ) { return false; } piece = piece >> 1; x--; if (x < piece_pos.x) { x = piece_pos.x+3; y--; } } return true; } void stack_piece() { if (piece_pos.y==0) { state=STATE_ENNERYORNEIM; return; }; int x = piece_pos.x+3, y = piece_pos.y+3; Uint16 piece = tetromino[current_piece].figure; for (int i=0; i<16; i++) { if (piece & 1) { board[y][x] = tetromino[current_piece].orig+1; } piece >>= 1; if (--x < piece_pos.x) { x = piece_pos.x+3; y--; } } piece_pos = {3, 0}; current_piece = next_piece; next_piece = starting[rand()%7]; int count = 0, line = 17; while (line > 0) { bool complete = true; for (int x=0; x<10; x++) { complete = (board[line][x] != 0); if (!complete) break; } if (complete) { count++; for(int y=line; y>0; y--) for(int x=0; x<10; x++) board[y][x] = board[y-1][x]; } else { line--; } } lines += count; const int scoremult[4]={40,100,300,1200}; if (count>0) score += scoremult[count-1] * (level+1); level = lines / 10; } void draw_cube(int x, int y, int color, Uint8 alpha) { SDL_Rect rect { (32/alpha)*x, (32/alpha)*y, (32/alpha), (32/alpha)}; SDL_SetRenderDrawColor(sdlRenderer, colors[color][0]/alpha, colors[color][1]/alpha, colors[color][2]/alpha, 255); SDL_RenderFillRect(sdlRenderer, &rect); SDL_SetRenderDrawColor(sdlRenderer, colors[color][0]/2/alpha, colors[color][1]/2/alpha, colors[color][2]/2/alpha, 255); SDL_RenderDrawRect(sdlRenderer, &rect); } void draw_tetromino(int init_x, int init_y, int piece_to_draw, Uint8 alpha) { int x = init_x+3; int y = init_y+3; Uint16 piece = tetromino[piece_to_draw].figure; for (int i=0; i<16; i++) { if (piece & 1) draw_cube(x, y, tetromino[piece_to_draw].orig, alpha); piece = piece >> 1; x--; if (x < init_x) { x = init_x+3; y--; } } } void print(int x, int y, const char* text, Uint8 color) { int cc = 0; SDL_SetTextureColorMod(sdlTexture, colors[color][0], colors[color][1], colors[color][2]); SDL_Rect src {0, 0, 8, 8}, dst {x, y, 16, 16}; while (text[cc] != 0) { if (text[cc] == 32) { cc++; dst.x+=16;continue; } else if (text[cc] >= 65) { src.x = ((text[cc]-65)%6)*8; src.y = ((text[cc]-65)/6)*8; } else if (text[cc] < 65) { src.x = ((text[cc]-22)%6)*8; src.y = ((text[cc]-22)/6)*8; } SDL_RenderCopy(sdlRenderer, sdlTexture, &src, &dst); cc++; dst.x+=16; } } void print(int x, int y, const int num, int pad, Uint8 color) { char result[8]; SDL_itoa(num, result, 10); while (strlen(result) < pad) { for(int i=strlen(result); i>=0; i--) result[i+1]=result[i]; result[0]='0'; }; print(x, y, result, color); } void doGame() { while(SDL_PollEvent(&sdlEvent)) { if (sdlEvent.type == SDL_QUIT) { should_exit = true; break; } if (sdlEvent.type == SDL_KEYDOWN) switch (sdlEvent.key.keysym.scancode) { case SDL_SCANCODE_RIGHT: { piece_pos.x++; if (!is_valid_move()) piece_pos.x--; break; } case SDL_SCANCODE_LEFT: { piece_pos.x--; if (!is_valid_move()) piece_pos.x++; break; } case SDL_SCANCODE_DOWN: { piece_pos.y++; if (!is_valid_move()) { piece_pos.y--; stack_piece(); } break; } case SDL_SCANCODE_UP: { current_piece = tetromino[current_piece].next; if (!is_valid_move()) current_piece = tetromino[current_piece].prev; break; } } } if (--speed == 0) { speed = (20-SDL_min(19, level))*3; piece_pos.y++; if (!is_valid_move()) { piece_pos.y--; stack_piece(); } } SDL_SetRenderDrawColor(sdlRenderer, 0, 0, 0, 255); SDL_RenderClear(sdlRenderer); print(1, 1, "LEVEL", 2); print(121, 1, "SCORE", 0); print(241, 1, "LINES", 1); print(17, 18, level, 3, 7); print(105, 18, score, 7, 7); print(257, 18, lines, 3, 7); for (int y=0; y<18; y++) for (int x=0; x<10; x++) if (board[y][x] != 0) draw_cube(x, y, board[y][x]-1, 1); draw_tetromino(16, 2, next_piece, 2); draw_tetromino(piece_pos.x, piece_pos.y, current_piece, 1); SDL_RenderPresent(sdlRenderer); } void doMenu() { while(SDL_PollEvent(&sdlEvent)) { if (sdlEvent.type == SDL_QUIT) { should_exit = true; break; } if (sdlEvent.type == SDL_KEYDOWN && sdlEvent.key.repeat==0) { level=score=lines=0; current_piece = starting[rand()%7]; next_piece = starting[rand()%7]; for (int y=0;y<10;++y) for (int x=0;x<18;++x) board[x][y]=0; piece_pos.x=3; piece_pos.y=0; speed = (20-SDL_min(19, level))*3; state=STATE_GAME; } } SDL_SetRenderDrawColor(sdlRenderer, 0, 0, 0, 255); SDL_RenderClear(sdlRenderer); static Uint8 color=0; color++; Uint8 c=color>>4; for (int i=0;i<18;++i) { draw_cube(0,i,c&7,1); draw_cube(9,i,(c++)&7,1); } print(110, 50, "TETRIS", (color>>1)&7); print(90, 100, "TOP SCORES", 1); const int numusers = jscore::getNumUsers(); for (int i=0;i<10;++i) { if (i=SDL_SCANCODE_A && sdlEvent.key.keysym.scancode<=SDL_SCANCODE_0) { if (sdlEvent.key.keysym.scancode<=SDL_SCANCODE_Z) { initials[pos] = sdlEvent.key.keysym.scancode+61; } else if (sdlEvent.key.keysym.scancode0 && (jscore::getNumUsers()<10 || score>jscore::getPoints(jscore::getNumUsers()-1))) { print(40, 150, "CONGRATULATIONS", 1); print(40, 180, "ENTER YOU NAME", 2); print(40, 250, initials, 3); } SDL_RenderPresent(sdlRenderer); } int main(int argc, char* argv[]) { srand(time(NULL)); current_piece = starting[rand()%7]; next_piece = starting[rand()%7]; jscore::initOnlineScore("tetris"); SDL_Init(SDL_INIT_EVERYTHING); sdlWindow = SDL_CreateWindow("TETRIS", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 320, 576, SDL_WINDOW_SHOWN); sdlRenderer = SDL_CreateRenderer(sdlWindow, -1, SDL_RENDERER_PRESENTVSYNC); sdlTexture = SDL_CreateTextureFromSurface(sdlRenderer, SDL_LoadBMP_RW(SDL_RWFromMem(bmp, 448), 1)); while(!should_exit) { switch (state) { case STATE_MENU: doMenu(); break; case STATE_GAME: doGame(); break; case STATE_ENNERYORNEIM: doEnd(); break; }; } SDL_Quit(); return 0; }