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 partially 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!
|
|
}
|