199 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			199 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			C++
		
	
	
	
| /*
 | |
|   Sketch to show how a 4 bit Sprite is created, how to draw pixels
 | |
|   and text within the Sprite and then push the Sprite onto
 | |
|   the display screen.
 | |
| 
 | |
|   The advantage of 4 bit sprites is:
 | |
|     1. Small memory footprint
 | |
|     2. Any set of 16 colours can be specified
 | |
|     3. Colours can be changed without redrawing in Sprite
 | |
|     4. Simple animations like flashing text can be achieved
 | |
|        by colour palette cycling and pushing sprite to TFT:
 | |
|        https://en.wikipedia.org/wiki/Color_cycling
 | |
| 
 | |
|   Example for library:
 | |
|   https://github.com/Bodmer/TFT_eSPI
 | |
| 
 | |
|   A Sprite is notionally an invisible graphics screen that is
 | |
|   kept in the processors RAM. Graphics can be drawn into the
 | |
|   Sprite just as it can be drawn directly to the screen. Once
 | |
|   the Sprite is completed it can be plotted onto the screen in
 | |
|   any position. If there is sufficient RAM then the Sprite can
 | |
|   be the same size as the screen and used as a frame buffer.
 | |
| 
 | |
|   A 4 bit Sprite occupies (width * height)/2 bytes in RAM.
 | |
| 
 | |
| */
 | |
| 
 | |
| // Set delay after plotting the sprite
 | |
| #define DELAY 1000
 | |
| 
 | |
| // Width and height of sprite
 | |
| #define WIDTH  128
 | |
| #define HEIGHT 128
 | |
| 
 | |
| #include <TFT_eSPI.h>                 // Include the graphics library (this includes the sprite functions)
 | |
| 
 | |
| TFT_eSPI    tft = TFT_eSPI();         // Declare object "tft"
 | |
| 
 | |
| TFT_eSprite spr = TFT_eSprite(&tft);  // Declare Sprite object "spr" with pointer to "tft" object
 | |
| 
 | |
| 
 | |
| void setup()
 | |
| {
 | |
|   Serial.begin(115200);
 | |
|   Serial.println();
 | |
| 
 | |
|   delay(500);
 | |
| 
 | |
|   // Initialise the TFT registers
 | |
|   tft.init();
 | |
| 
 | |
|   // Set the sprite colour depth to 4
 | |
|   spr.setColorDepth(4);
 | |
| 
 | |
|   // Create a sprite of defined size
 | |
|   spr.createSprite(WIDTH, HEIGHT);
 | |
| 
 | |
|   // Clear the TFT screen to blue
 | |
|   tft.fillScreen(TFT_BLUE);
 | |
| }
 | |
| 
 | |
| void loop(void)
 | |
| {
 | |
|   // Fill the whole sprite with color 0 (Sprite is in memory so not visible yet)
 | |
|   spr.fillSprite(0);
 | |
| 
 | |
|    // create a color map with known colors (16 maximum for 4 bit Sprite
 | |
|   uint16_t cmap[16];
 | |
| 
 | |
| 
 | |
|   cmap[0]  = TFT_BLACK; // We will keep this as black
 | |
|   cmap[1]  = TFT_NAVY;
 | |
|   cmap[2]  = TFT_DARKGREEN;
 | |
|   cmap[3]  = TFT_DARKCYAN;
 | |
|   cmap[4]  = TFT_MAROON;
 | |
|   cmap[5]  = TFT_PURPLE;
 | |
|   cmap[6]  = TFT_PINK;
 | |
|   cmap[7]  = TFT_LIGHTGREY;
 | |
|   cmap[8]  = TFT_YELLOW;
 | |
|   cmap[9]  = TFT_BLUE;
 | |
|   cmap[10] = TFT_GREEN;
 | |
|   cmap[11] = TFT_CYAN;
 | |
|   cmap[12] = TFT_RED;
 | |
|   cmap[13] = TFT_MAGENTA;
 | |
|   cmap[14] = TFT_WHITE;  // Keep as white for text
 | |
|   cmap[15] = TFT_BLUE;   // Keep as blue for sprite border
 | |
| 
 | |
|   // Pass the palette to the Sprite class
 | |
|   spr.createPalette(cmap);
 | |
| 
 | |
|   // Push Sprite parially off-screen to test cropping
 | |
|   spr.pushSprite(-40, -40);
 | |
|   spr.pushSprite(tft.width() / 2 - WIDTH / 2, tft.height() / 2 - HEIGHT / 2, 10);
 | |
|   spr.pushSprite(tft.width() - WIDTH + 40, tft.height() - HEIGHT + 40);
 | |
| 
 | |
|   // Number of pixels to draw
 | |
|   uint16_t n = 100;
 | |
| 
 | |
|   // Draw 100 random color pixels at random positions in sprite
 | |
|   while (n--)
 | |
|   {
 | |
|     uint16_t color = random(0x10); // Returns color 0 - 0x0F (i.e. 0-15)
 | |
|     int16_t x = random(WIDTH);     // Random x coordinate
 | |
|     int16_t y = random(HEIGHT);    // Random y coordinate
 | |
|     spr.drawPixel(x, y, color);    // Draw pixel in sprite
 | |
|   }
 | |
| 
 | |
|   // Draw some lines
 | |
|   spr.drawLine(1, 0, WIDTH, HEIGHT-1, 10);
 | |
|   spr.drawLine(0, 0, WIDTH, HEIGHT, 10);
 | |
|   spr.drawLine(0, 1, WIDTH-1, HEIGHT, 10);
 | |
|   spr.drawLine(0, HEIGHT-1, WIDTH-1, 0, 12);
 | |
|   spr.drawLine(0, HEIGHT, WIDTH, 0, 12);
 | |
|   spr.drawLine(1, HEIGHT, WIDTH, 1, 12);
 | |
| 
 | |
|  // Draw some text with Middle Centre datum
 | |
|   spr.setTextDatum(MC_DATUM);
 | |
|   spr.setTextColor(14); // White text
 | |
|   spr.drawString("Sprite", WIDTH / 2, HEIGHT / 2, 4);
 | |
| 
 | |
|   // Now push the sprite to the TFT at 3 positions on screen
 | |
|   spr.pushSprite(-40, -40);
 | |
|   spr.pushSprite(tft.width() / 2 - WIDTH / 2, tft.height() / 2 - HEIGHT / 2);
 | |
|   spr.pushSprite(tft.width() - WIDTH + 40, tft.height() - HEIGHT + 40);
 | |
| 
 | |
|   delay(DELAY * 4);
 | |
| 
 | |
|   // create a new color map for colours 1-13 and use it instead
 | |
|   for (auto i = 1; i <= 13; i++)
 | |
|   {
 | |
|     cmap[i] = random(0x10000);
 | |
|   }
 | |
| 
 | |
|   spr.createPalette(cmap, 16);
 | |
|   // Now push the sprite to the TFT at position 0,0 on screen
 | |
| 
 | |
|   spr.pushSprite(-40, -40);
 | |
|   spr.pushSprite(tft.width() / 2 - WIDTH / 2, tft.height() / 2 - HEIGHT / 2);
 | |
|   spr.pushSprite(tft.width() - WIDTH + 40, tft.height() - HEIGHT + 40);
 | |
| 
 | |
|   delay(DELAY);
 | |
| 
 | |
|     // Fill TFT screen with blue
 | |
|   tft.fillScreen(TFT_BLUE);
 | |
| 
 | |
|   // Draw a blue rectangle in sprite so when we move it 1 pixel it does not leave a trail
 | |
|   // on the blue screen background
 | |
|   spr.createPalette(cmap);
 | |
| 
 | |
|   spr.drawRect(0, 0, WIDTH, HEIGHT, 15); // Blue rectangle
 | |
| 
 | |
|   int x = tft.width() / 2  -  WIDTH / 2;
 | |
|   int y = tft.height() / 2 - HEIGHT / 2;
 | |
| 
 | |
|   uint32_t updateTime = 0;       // time for next update
 | |
| 
 | |
|   while (true)
 | |
|   {
 | |
|     // Random movement direction
 | |
|     int dx = 1; if (random(2)) dx = -1;
 | |
|     int dy = 1; if (random(2)) dy = -1;
 | |
| 
 | |
|     // Pull it back onto screen if it wanders off
 | |
|     if (x < -WIDTH/2) dx = 1;
 | |
|     if (x >= tft.width()-WIDTH/2) dx = -1;
 | |
|     if (y < -HEIGHT/2) dy = 1;
 | |
|     if (y >= tft.height()-HEIGHT/2) dy = -1;
 | |
| 
 | |
|     // Randomise the palette to change colours without redrawing
 | |
|     // the sprite
 | |
|     for (auto i = 1; i <= 13; i++)
 | |
|     {
 | |
|       cmap[i] = random(0x10000);
 | |
|     }
 | |
|     spr.createPalette(cmap); // Update sprite class palette
 | |
| 
 | |
|     // Draw it 50 times, moving in random direct or staying still
 | |
|     n = 50;
 | |
|     int wait = random (50);
 | |
|     while (n)
 | |
|     {
 | |
|       if (updateTime <= millis())
 | |
|       {
 | |
|         // Use time delay so sprite does not move fast when not all on screen
 | |
|         updateTime = millis() + wait;
 | |
| 
 | |
|         // Push the sprite to the TFT screen
 | |
|           spr.pushSprite(x, y);
 | |
| 
 | |
|         // Change coord for next loop
 | |
|         x += dx;
 | |
|         y += dy;
 | |
|         n--;
 | |
|         yield(); // Stop watchdog reset
 | |
|       }
 | |
|     }
 | |
|   } // Infinite while, will not exit!
 | |
| }
 |