概要
今回はSpriteに付いてです。そもそもSpriteとはメモリ領域に定義された画像データを一気にLCDに書き込むもので、 イメージ的にはスタンプを押す様に描画すると言ったところでしょうか。表示速度が速いのが一番の特徴でしょうか
Rotated_Sprite_1
このスケッチは ファイルー>スケッチ例ー>TFT_eSPIー>Spriteー>Rotated_Sprite_1 に有ります。 文字列 "Hello" のSpriteを作成し、それを LCD 上に角度を付けて表示しています。 下記はスケッチの最初の画面
スケッチからキーの部分を抜き取ると
#include <TFT_eSPI.h>
TFT_eSPI tft = TFT_eSPI(); // TFT object
TFT_eSprite spr = TFT_eSprite(&tft); // Sprite object
// =======================================================================================
// Setup
// =======================================================================================
void setup() {
Serial.begin(250000); // Debug only
tft.begin(); // initialize
tft.setRotation(0);
}
// =======================================================================================
// Loop
// =======================================================================================
void loop() {
int xw = tft.width()/2; // xw, yh is middle of screen
int yh = tft.height()/2;
showMessage("90 degree angles");
tft.setPivot(xw, yh); // Set pivot to middle of TFT screen
drawX(xw, yh); // Show where screen pivot is
// Create the Sprite
spr.setColorDepth(8); // Create an 8bpp Sprite of 60x30 pixels
spr.createSprite(64, 30); // 8bpp requires 64 * 30 = 1920 bytes
spr.setPivot(32, 55); // Set pivot relative to top left corner of Sprite
spr.fillSprite(TFT_BLACK); // Fill the Sprite with black
spr.setTextColor(TFT_GREEN); // Green text
spr.setTextDatum(MC_DATUM); // Middle centre datum
spr.drawString("Hello", 32, 15, 4); // Plot text, font 4, in Sprite at 30, 15
spr.pushRotated(0);
spr.pushRotated(90);
spr.pushRotated(180);
spr.pushRotated(270);
delay(2000);
- 32行:TFT_eSPI tft = TFT_eSPI(); LCD用オブジェクトを宣言
- 34行:TFT_eSprite spr = TFT_eSprite(&tft);
- Sprite用オブジェクトを宣言。LCDでは無くメモリ上に画像を描く為のエリアを確保
- 引数は LCD オブジェクトを指定。ここがキー。 これでメモリに LCD での表示に合わせてデータが書き込まれます
- 58行:tft.setPivot(xw, yh);
- Spriteの LCD 上の回転中心を指定。左上が (0,0) なのでLCDのほぼ中心にXマーク。
- 62から69行でSprite Dataを作成しています。それぞれの位置関係はこんな感じ
白枠の部分のみメモリー内に描かれています。 LCD には描写されません。
- 71から74行: Spriteを0,90,180,270度回転させています。
spr.pushRotated(); ここで初めて LCD に描写されます。 画像は既に出来上がっているので表示が速い。
- 回転の設定によってはこんな表示もできる様です
Sprite を利用すれば文字列を傾けて(角度を付けて)表示出来ます。
Sprite_scroll_16bit
このスケッチは ファイルー>スケッチ例ー>TFT_eSPIー>Spriteー>Sprite_scroll_16bit に有ります。 虹色の帯の上を文字列が横にスクロールするデモです。
デモの簡単な説明は以下の通り。(Sprite内書き込み:"img:" LCD内での表示:"tft" と区別)
- tft:バックを青く塗り潰す
- img:img.createSprite(IWIDTH, IHEIGHT);でSprite領域を作成
- 領域内に虹の帯を描画
- 領域内の中心に四角と丸の絵を描画
- 指定した位置に ”Hello World” と表示
- そこから間隔を開けて ”Hello World” と表示
- tft:出来上がったSpriteを LCD に表示
- tft:メッセージを"TFT_eSPI sprite"に変えて上記2を実行し、Spriteを LCD に表示
- tft:文字列を横にスクロール
- tft:スクロール完了
- img:新たに箱と文字のSprtieを作成して
- tft:LCDに表示
上記2の作業をLCDで行うと作業の様子(虹や文字を書いている所)が表示されてしまいスムーズなスクロールにはなりません。 Spriteで作業し、結果のみをLCDに表示しているのできれいにスクロールして見えます。
横スクロールはvoid build_banner(String msg, int xpos)が処理しています
void build_banner(String msg, int xpos)
{
int h = IHEIGHT;
// We could just use fillSprite(color) but lets be a bit more creative...
// Fill with rainbow stripes
while (h--) img.drawFastHLine(0, h, IWIDTH, rainbow(h * 4));
// Draw some graphics, the text will apear to scroll over these
img.fillRect (IWIDTH / 2 - 20, IHEIGHT / 2 - 10, 40, 20, TFT_YELLOW);
img.fillCircle(IWIDTH / 2, IHEIGHT / 2, 10, TFT_ORANGE);
// Now print text on top of the graphics
img.setTextSize(1); // Font size scaling is x1
img.setTextFont(4); // Font 4 selected
img.setTextColor(TFT_BLACK); // Black text, no background colour
img.setTextWrap(false); // Turn of wrap so we can print past end of sprite
// Need to print twice so text appears to wrap around at left and right edges
img.setCursor(xpos, 2); // Print text at xpos
img.print(msg);
img.setCursor(xpos - IWIDTH, 2); // Print text at xpos - sprite width
img.print(msg);
}
- 上記0:虹色の帯部をSpriteに描画。座標の原点は左上
- 上記1:文字列をStritの原点に描画。この時表示幅(IWIDTH)を開けた所にも表示していました。
- このSprite機能、領域外を指定した場合それは無視される様です。
- 最初に書いた "Hello World" は領域内なのでそのままSpriteに書き込まれる
- 次に書いた "Hello World" は完全に領域外なので全くSpriteに書かれない
- 上記2:文字列の表示位置x座標にマイナスの値を指定すると、この様に書き出しがSpriteの範囲外になります。
- この場合、最初に書いた "Hello World" は先頭が、次は後部がクリップされてSpriteに書き込まれます
- 上記3,4:文字列の表示位置を動かしながらSpriteを作り出来たSpriteをLCDに表示。
- 上記5:表示幅(IWIDTH)最初文字を動かしたらSpriteは上記1の状態と同じになるので同じ動作を繰り返す
表示欄より長い文字列を表示させたい時にスクロールを使いたくなります。 今回の表示欄は240ドット。表示する文字列を”Hello World Scroll Sample”とすると文字列の長さは317ドットになります。 以下の様にコードを書き換えれば表示欄より長い文字列をスクロールさせる事が出来ます
#define IWIDTH 240
#define IHEIGHT 30
// Pause in milliseconds to set scroll speed
#define WAIT 10
#include <TFT_eSPI.h> // Include the graphics library (this includes the sprite functions)
TFT_eSPI tft = TFT_eSPI(); // Create object "tft"
TFT_eSprite img = TFT_eSprite(&tft); // Create Sprite object "img" with pointer to "tft" object
// // the pointer is used by pushSprite() to push it onto the TFT
// -------------------------------------------------------------------------
// Setup
// -------------------------------------------------------------------------
void setup(void) {
Serial.begin(115200);
tft.init();
tft.setRotation(0);
tft.fillScreen(TFT_BLUE);
}
// -------------------------------------------------------------------------
// Main loop
// -------------------------------------------------------------------------
void loop() {
int str_len, pos;
String str;
img.createSprite(IWIDTH, IHEIGHT);
img.setTextSize(1); // Font size scaling is x1
img.setTextFont(4); // Font 4 selected
img.setTextColor(TFT_BLACK); // Black text, no background colour
img.setTextWrap(false); // Turn of wrap so we can print past end of sprite
str = "Hello World Scroll Sample";
Serial.println("length: " + String(str_len));
str += " ";
str_len = img.textWidth(str);
Serial.println("length: " + String(str_len));
while (1){
for (pos = 0; pos > - str_len ; pos --){
build_banner(str, pos, str_len + pos);
img.pushSprite(0, 0);
delay(WAIT);
}
}
}
// #########################################################################
// Build the scrolling sprite image from scratch, draw text at x = xpos
// #########################################################################
void build_banner(String msg, int xpos, int xpos1)
{
img.fillRect (0,0,IWIDTH,IHEIGHT,TFT_ORANGE);
img.setCursor(xpos, 2); // Print text at xpos
img.print(msg);
img.setCursor(xpos1, 2); // Print text at xpos - sprite width
img.print(msg);
}
文字がスクロールするとなんか嬉しくなります。
Rotated_Sprite_2
このスケッチは ファイルー>スケッチ例ー>TFT_eSPIー>Spriteー>Rotated_Sprite_2 に有ります。 スピードメータの様にメータの針と値が表示されるデモです。このデモの特徴は複数のSpriteを使って LCDに描写している所です。
- メータの土台、針用 Spriteのインスタンスを宣言
- TFT_eSprite dial = TFT_eSprite(&tft); // Sprite object for dial
- TFT_eSprite needle = TFT_eSprite(&tft);
- メータの土台のSprite
- 91x91の表示領域を確保し "TFT_TRANSPARENT" で塗りつぶす。
- "TFT_TRANSPARENT" は "TFT_eSPI.h" で定義していました。
- #define TFT_TRANSPARENT 0x0120 // This is actually a dark green
- そこに土台用に円を描きます。
- 針用のSprite(needle)で一時的に目盛り(3x3の四角)用の Sprite を作る。
- これを土台に配置。
- 目盛りの内側に背景が黒の文字表示用の丸を書いて文字を書き込む。
- 91x91の表示領域を確保し "TFT_TRANSPARENT" で塗りつぶす。
- 針のSpriteと LCD への描写
- 背景が黒で 49x11 のSprite用エリアに針の形状を描写。これが針用Sprite。
- 土台用Spriteにスピード等の文字列を書き込む。
- 土台のSpriteの上に針のSpriteを書き込む。この時 "黒" を透明色に指定しているので土台の文字は消えない(上書きされない)。
- 針の乗った土台のSpriteを LCD に描く時 "TFT_TRANSPARENT" を透明色に指定するので四隅が消えてメータ部分が残る。
タコメータ見たいでかっこいいです。
Sprite_TFT_Rainbow
このスケッチはhttps://hp.hatakekara.com/contents/esp32/works/tft_espi/tft_espi_3.html ファイルー>スケッチ例ー>TFT_eSPIー>Spriteー>Sprite_TFT_Rainbow に有ります。 バックの虹色が綺麗に流れるデモです。
このデモのキーはこの部分
// Colour changing state machine
for (int i = 0; i < 160; i++) {
img.drawFastVLine(i, 0, img.height(), colour);
switch (state) {
case 0:
green += 2;
if (green == 64) {
green = 63;
state = 1;
}
break;
case 1:
red--;
if (red == 255) {
red = 0;
state = 2;
}
break;
case 2:
blue ++;
if (blue == 32) {
blue = 31;
state = 3;
}
break;
case 3:
green -= 2;
if (green == 255) {
green = 0;
state = 4;
}
break;
case 4:
red ++;
if (red == 32) {
red = 31;
state = 5;
}
break;
case 5:
blue --;
if (blue == 255) {
blue = 0;
state = 0;
}
break;
}
colour = red << 11 | green << 5 | blue;
}
- 160 x 128 の Sprite 領域を宣言
- 関数 img.drawFastVLine(i, 0, img.height(), colour); で Sprite に縦160本の線を色を変えて書く。
- 描き終わった Sprite を LCD に表示。
- 縦線の色をずらして次の Sprite を作成し LCD に表示しているのですが、虹色のグラデーションが綺麗なアニメに見えます。
次は
Sprite の色々は応用を見て来ました。Spriteは使い方によってはアニメーションをみている様でした。 文字のスクロールは自作機器での利用する機会が多いと思います。とても有り難い機能です。
次回は日本語の表示に付いて説明したいと思います。