Guest User

Picoris

a guest
Jan 27th, 2021
1,826
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <string.h>
  2. #include <math.h>
  3. #include <vector>
  4. #include <cstdlib>
  5.  
  6. #include "pico_display.hpp"
  7. #include "pico/multicore.h"
  8.  
  9. using namespace pimoroni;
  10.  
  11. #define u8 uint8_t
  12. #define u16 uint16_t
  13. #define u32 uint32_t
  14. #define i8 int8_t
  15. #define i16 int16_t
  16. #define i32 int32_t
  17.  
  18. const u8 TETROMINOES[7][4][16] = {
  19.     { // LONG PIECE
  20.         {
  21.             0, 0, 0, 0,
  22.             1, 1, 1, 1,
  23.             0, 0, 0, 0,
  24.             0, 0, 0, 0
  25.         },
  26.         {
  27.             0, 0, 1, 0,
  28.             0, 0, 1, 0,
  29.             0, 0, 1, 0,
  30.             0, 0, 1, 0
  31.         },
  32.         {
  33.             0, 0, 0, 0,
  34.             0, 0, 0, 0,
  35.             1, 1, 1, 1,
  36.             0, 0, 0, 0
  37.         },
  38.         {
  39.             0, 1, 0, 0,
  40.             0, 1, 0, 0,
  41.             0, 1, 0, 0,
  42.             0, 1, 0, 0
  43.         }
  44.     },
  45.     { // BACKWARD L
  46.         {
  47.             1, 0, 0, 0,
  48.             1, 1, 1, 0,
  49.             0, 0, 0, 0,
  50.             0, 0, 0, 0
  51.         },
  52.         {
  53.             0, 1, 1, 0,
  54.             0, 1, 0, 0,
  55.             0, 1, 0, 0,
  56.             0, 0, 0, 0
  57.         },
  58.         {
  59.             0, 0, 0, 0,
  60.             1, 1, 1, 0,
  61.             0, 0, 1, 0,
  62.             0, 0, 0, 0
  63.         },
  64.         {
  65.             0, 1, 0, 0,
  66.             0, 1, 0, 0,
  67.             1, 1, 0, 0,
  68.             0, 0, 0, 0
  69.         }
  70.     },
  71.     { // L
  72.         {
  73.             0, 0, 1, 0,
  74.             1, 1, 1, 0,
  75.             0, 0, 0, 0,
  76.             0, 0, 0, 0
  77.         },
  78.         {
  79.             0, 1, 0, 0,
  80.             0, 1, 0, 0,
  81.             0, 1, 1, 0,
  82.             0, 0, 0, 0
  83.         },
  84.         {
  85.             0, 0, 0, 0,
  86.             1, 1, 1, 0,
  87.             1, 0, 0, 0,
  88.             0, 0, 0, 0
  89.         },
  90.         {
  91.             1, 1, 0, 0,
  92.             0, 1, 0, 0,
  93.             0, 1, 0, 0,
  94.             0, 0, 0, 0
  95.         }
  96.     },
  97.     { // SQUARE
  98.         {
  99.             0, 1, 1, 0,
  100.             0, 1, 1, 0,
  101.             0, 0, 0, 0,
  102.             0, 0, 0, 0
  103.         },
  104.         {
  105.             0, 1, 1, 0,
  106.             0, 1, 1, 0,
  107.             0, 0, 0, 0,
  108.             0, 0, 0, 0
  109.         },
  110.         {
  111.             0, 1, 1, 0,
  112.             0, 1, 1, 0,
  113.             0, 0, 0, 0,
  114.             0, 0, 0, 0
  115.         },
  116.         {
  117.             0, 1, 1, 0,
  118.             0, 1, 1, 0,
  119.             0, 0, 0, 0,
  120.             0, 0, 0, 0
  121.         }
  122.     },
  123.     { // S
  124.         {
  125.             0, 1, 1, 0,
  126.             1, 1, 0, 0,
  127.             0, 0, 0, 0,
  128.             0, 0, 0, 0
  129.         },
  130.         {
  131.             0, 1, 0, 0,
  132.             0, 1, 1, 0,
  133.             0, 0, 1, 0,
  134.             0, 0, 0, 0
  135.         },
  136.         {
  137.             0, 0, 0, 0,
  138.             0, 1, 1, 0,
  139.             1, 1, 0, 0,
  140.             0, 0, 0, 0
  141.         },
  142.         {
  143.             1, 0, 0, 0,
  144.             1, 1, 0, 0,
  145.             0, 1, 0, 0,
  146.             0, 0, 0, 0
  147.         }
  148.     },
  149.     { // T
  150.         {
  151.             0, 1, 0, 0,
  152.             1, 1, 1, 0,
  153.             0, 0, 0, 0,
  154.             0, 0, 0, 0
  155.         },
  156.         {
  157.             0, 1, 0, 0,
  158.             0, 1, 1, 0,
  159.             0, 1, 0, 0,
  160.             0, 0, 0, 0
  161.         },
  162.         {
  163.             0, 0, 0, 0,
  164.             1, 1, 1, 0,
  165.             0, 1, 0, 0,
  166.             0, 0, 0, 0
  167.         },
  168.         {
  169.             0, 1, 0, 0,
  170.             1, 1, 0, 0,
  171.             0, 1, 0, 0,
  172.             0, 0, 0, 0
  173.         }
  174.     },
  175.     { // BACKWARD S
  176.         {
  177.             1, 1, 0, 0,
  178.             0, 1, 1, 0,
  179.             0, 0, 0, 0,
  180.             0, 0, 0, 0
  181.         },
  182.         {
  183.             0, 0, 1, 0,
  184.             0, 1, 1, 0,
  185.             0, 1, 0, 0,
  186.             0, 0, 0, 0
  187.         },
  188.         {
  189.             0, 0, 0, 0,
  190.             1, 1, 0, 0,
  191.             0, 1, 1, 0,
  192.             0, 0, 0, 0
  193.         },
  194.         {
  195.             0, 1, 0, 0,
  196.             1, 1, 0, 0,
  197.             1, 0, 0, 0,
  198.             0, 0, 0, 0
  199.         }
  200.     }
  201. };
  202.  
  203. const u16 SCREEN_WIDTH = PicoDisplay::WIDTH / 2;
  204. const u16 SCREEN_HEIGHT = PicoDisplay::HEIGHT / 2;
  205.  
  206. uint16_t buffer[PicoDisplay::WIDTH * PicoDisplay::HEIGHT];
  207. PicoDisplay pico_display(buffer);
  208.  
  209. const u8 BUTTON_X = 0;
  210. const u8 BUTTON_Y = 1;
  211. const u8 BUTTON_A = 2;
  212. const u8 BUTTON_B = 3;
  213.  
  214. const u8 pico_button_map[] = {
  215.     pico_display.X,
  216.     pico_display.Y,
  217.     pico_display.A,
  218.     pico_display.B
  219. };
  220.  
  221. u8 buttons[4];
  222. u8 buttons_pressed[4];
  223. u8 buttons_released[4];
  224.  
  225. bool check_button(u8 button) {
  226.     return buttons[button];
  227. }
  228.  
  229. bool check_button_pressed(u8 button) {
  230.     return buttons_pressed[button];
  231. }
  232.  
  233. bool check_button_released(u8 button) {
  234.     return buttons_released[button];
  235. }
  236.  
  237. u16 color(u8 r, u8 g, u8 b) {
  238.     return pico_display.create_pen(r, g, b);
  239. }
  240.  
  241. void pixel(u16 x, u16 y, u16 color) {
  242.     x *= 2;
  243.     y *= 2;
  244.     pico_display.frame_buffer[x + y * 240] = color;
  245.     pico_display.frame_buffer[x + 1 + y * 240] = color;
  246.     y++;
  247.     pico_display.frame_buffer[x + y * 240] = color;
  248.     pico_display.frame_buffer[x + 1 + y * 240] = color;
  249. }
  250.  
  251. void rectangle(u16 x, u16 y, u16 width, u16 height, u16 color) {
  252.     for(u16 i = x; i < x + width; i++) {
  253.         for(u16 t = y; t < y + height; t++) {
  254.             pixel(i, t, color);
  255.         }
  256.     }
  257. }
  258.  
  259. const u16 background = color(64, 51, 83);
  260. const u16 field_background = color(36, 34, 52);
  261. const u16 block_colors[] = {
  262.     color(180, 32, 42),
  263.     color(250, 106, 10),
  264.     color(255, 213, 65),
  265.     color(89, 193, 53),
  266.     color(40, 92, 196),
  267.     color(188, 74, 155),
  268.     color(32, 214, 199)
  269. };
  270.  
  271. u8 piece_index = 0;
  272. u8 piece_angle = 0;
  273. u8 piece_x = 0;
  274. u8 piece_y = 0;
  275. u8 piece_dropping = false;
  276. u8 field[10][20];
  277.  
  278. inline void next_piece() {
  279.     piece_index = (piece_index + 1) % 7;
  280.     piece_angle = 0;
  281.     piece_x = 3;
  282.     piece_y = 0;
  283. }
  284.  
  285. inline void init() {
  286.     for(u8 i = 0; i < 10; ++i) {
  287.         for(u8 t = 0; t < 20; ++t) {
  288.             field[i][t] = 0;
  289.         }
  290.     }
  291.     next_piece();
  292. }
  293.  
  294. inline bool piece_position_allowed() {
  295.     const u8* piece = TETROMINOES[piece_index][piece_angle];
  296.     for(u8 i = 0; i < 4; ++i) {
  297.         for(u8 t = 0; t < 4; ++t) {
  298.             u8 block = piece[i + t * 4];
  299.             if(block) {
  300.                 u8 x = piece_x + i;
  301.                 u8 y = piece_y + t;
  302.                 if(x >= 10 || y >= 20 || field[x][y]) {
  303.                     return false;
  304.                 }
  305.             }
  306.         }
  307.     }
  308.     return true;
  309. }
  310.  
  311. inline void place_piece() {
  312.     piece_dropping = false;
  313.     const u8* piece = TETROMINOES[piece_index][piece_angle];
  314.     for(u8 i = 0; i < 4; ++i) {
  315.         for(u8 t = 0; t < 4; ++t) {
  316.             u8 block = piece[i + t * 4];
  317.             if(block) {
  318.                 u8 x = piece_x + i;
  319.                 u8 y = piece_y + t;
  320.                 field[x][y] = piece_index + 1;
  321.             }
  322.         }
  323.     }
  324.    
  325.     for(u8 t = 1; t < 20; ++t) {
  326.         bool line_filled = true;
  327.         for(u8 i = 0; i < 10; ++i) {
  328.             if(field[i][t] == 0) {
  329.                 line_filled = false;
  330.                 break;
  331.             }
  332.         }
  333.         if(line_filled) {
  334.             for(u8 j = t - 1; j > 0; --j) {
  335.                 for(u8 i = 0; i < 10; ++i) {
  336.                     field[i][j + 1] = field[i][j];
  337.                 }
  338.             }
  339.             for(u8 i = 0; i < 10; ++i) {
  340.                 field[i][0] = 0;
  341.             }
  342.             --t;
  343.         }
  344.     }
  345. }
  346.  
  347. inline void tick(bool update_board) {
  348.     pico_display.set_pen(64, 51, 83);
  349.     pico_display.clear();
  350.  
  351.     // Turn the piece
  352.     if(check_button_pressed(BUTTON_A)) {
  353.         piece_angle++;
  354.         if(!piece_position_allowed()) {
  355.             piece_angle--;
  356.         }
  357.         piece_angle = piece_angle % 4;
  358.     }
  359.  
  360.     if(check_button_pressed(BUTTON_B)) {
  361.         piece_dropping = true;
  362.     }
  363.     if(check_button(BUTTON_B) && piece_dropping) {
  364.         update_board = true;
  365.        
  366.     }
  367.  
  368.     if(check_button_pressed(BUTTON_Y)) {
  369.         piece_x++;
  370.         if(!piece_position_allowed()) {
  371.             piece_x--;
  372.         }
  373.     }
  374.     if(check_button_pressed(BUTTON_X)) {
  375.         piece_x--;
  376.         if(!piece_position_allowed()) {
  377.             piece_x++;
  378.         }
  379.     }
  380.  
  381.     if(update_board) {
  382.         piece_y++;
  383.         if(!piece_position_allowed()) {
  384.             piece_y--;
  385.             place_piece();
  386.             next_piece();
  387.         }
  388.     }
  389.  
  390.     u16 offset_x = 9;
  391.     u16 offset_y = 8;
  392.  
  393.     // Draw the field
  394.     rectangle(offset_x, offset_y, 100, 50, field_background);
  395.     for(u8 i = 0; i < 10; ++i) {
  396.         for(u8 t = 0; t < 20; ++t) {
  397.             u8 tile = field[i][t];
  398.             if(field[i][t] > 0) {
  399.                 rectangle(offset_x + t * 5, offset_y + i * 5, 5, 5, block_colors[tile - 1]);
  400.             }
  401.         }
  402.     }
  403.  
  404.     // Draw the active piece
  405.     const u8* piece = TETROMINOES[piece_index][piece_angle];
  406.     for(u8 i = 0; i < 4; ++i) {
  407.         for(u8 t = 0; t < 4; ++t) {
  408.             u8 block = piece[i + t * 4];
  409.             if(block) {
  410.                 u8 x = piece_x + i;
  411.                 u8 y = piece_y + t;
  412.                 if(x < 10 && y < 20) {
  413.                     rectangle(offset_x + (y) * 5, offset_y + (x) * 5, 5, 5, block_colors[piece_index]);
  414.                 }
  415.             }
  416.         }
  417.     }
  418. }
  419.  
  420. void input_init() {
  421.     for(u8 i = 0; i < 4; ++i) {
  422.         buttons[i] = false;
  423.         buttons_pressed[i] = false;
  424.         buttons_released[i] = false;
  425.     }
  426. }
  427.  
  428. const u8 button_gpio_map[] = { 12, 13, 14, 15 };
  429. #define EVENT_QUEUE_SIZE 128
  430. u16 event_queue[EVENT_QUEUE_SIZE];
  431. u16 event_queue_head = 0;
  432. u16 event_queue_tail = 0;
  433.  
  434.  
  435. bool event_queue_has_next() {
  436.     return event_queue_head != event_queue_tail;
  437. }
  438.  
  439. bool event_queue_full() {
  440.     return (event_queue_head + 1) % EVENT_QUEUE_SIZE == event_queue_tail;
  441. }
  442.  
  443. void event_queue_append(u16 value) {
  444.     if(!event_queue_full()) {
  445.         event_queue[event_queue_tail] = value;
  446.         event_queue_tail = (event_queue_tail + 1) % EVENT_QUEUE_SIZE;
  447.     }
  448. }
  449.  
  450. u16 event_queue_next() {
  451.     if(event_queue_has_next()) {
  452.         event_queue_tail = (event_queue_tail - 1) % EVENT_QUEUE_SIZE;
  453.         return event_queue[event_queue_tail];
  454.     }
  455.     return 0;
  456. }
  457.  
  458. void gpio_callback(unsigned int gpio, u32 events) {
  459.     if(events & (GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL)) {
  460.         u8 button;
  461.         if(gpio == 12) {
  462.             button = BUTTON_A;
  463.         } else if(gpio == 13) {
  464.             button = BUTTON_B;
  465.         } else if(gpio == 14) {
  466.             button = BUTTON_X;
  467.         } else if(gpio == 15) {
  468.             button = BUTTON_Y;
  469.         }
  470.         u8 pressed = GPIO_IRQ_EDGE_RISE & events;
  471.  
  472.         event_queue_append(button + pressed * 4);
  473.     }
  474. }
  475.  
  476. void input_start_frame() {
  477.     for(u8 i = 0; i < 4; ++i) {
  478.         buttons_pressed[i] = false;
  479.         buttons_released[i] = false;
  480.     }
  481.  
  482.     while(event_queue_has_next()) {
  483.         u32 event = event_queue_next();
  484.         u8 button = event % 4;
  485.         u8 pressed = event < 4;
  486.  
  487.         buttons[button] = pressed;
  488.         if(pressed) {
  489.             buttons_pressed[button] = true;
  490.         } else {
  491.             buttons_released[button] = true;
  492.         }
  493.     }
  494. }
  495.  
  496. int main() {
  497.     pico_display.init();
  498.     pico_display.set_backlight(255);
  499.  
  500.     gpio_set_irq_enabled_with_callback(12, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true, &gpio_callback);
  501.     gpio_set_irq_enabled_with_callback(13, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true, &gpio_callback);
  502.     gpio_set_irq_enabled_with_callback(14, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true, &gpio_callback);
  503.     gpio_set_irq_enabled_with_callback(15, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true, &gpio_callback);
  504.  
  505.     u8 tick_counter = 0;
  506.     u8 tick_interval = 30;
  507.  
  508.     init();
  509.     input_init();
  510.  
  511.     while(true) {
  512.         input_start_frame();
  513.         tick_counter++;
  514.         if(tick_counter > tick_interval) {
  515.             tick(true);
  516.             tick_counter = 0;
  517.         } else {
  518.             tick(false);
  519.         }
  520.         pico_display.update();
  521.     }
  522.  
  523.     return 0;
  524. }
  525.  
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×