Wio-Terminalの「Space Shooter」をplatformioでコンパイルして実行する
2020/7/29
PlatformIO cli Wio Terminal Space Shooter
PlatformIO cli Wio Terminal Space Shooter
概要
以下にあるWio-Terminalの「Space Shooter」(game)をplatformioでコンパイルして実行する(Seeeduino-Wio-Terminal/Arduino版)
platformioのインストールについては
「開発ツールPlatformIOをcliで使う(Seeeduino-Wio-Terminal/Arduino版)」を参照のこと。(ホストPCとしてはubuntuを想定している)
プロジェクト wiot-game のディレクトリを作成する
mkdir wiot-game
cd wiot-game
# 以下を実行して必要なファイルを作成する
pio init --board seeed_wio_terminal
# platformをupdateする
pio platform update
nano platformio.ini
以下にように編集する:
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:seeed_wio_terminal]
platform = atmelsam
board = seeed_wio_terminal
framework = arduino
upload_protocol = sam-ba
lib_ldf_mode = deep+
該当ライブラリとスケッチのダウンロード
cd wiot-game
cd src
wget https://macsbug.files.wordpress.com/2020/05/wio_space_shooter.zip_.pdf
mv wio_space_shooter.zip_.pdf wio_space_shooter.zip
unzip wio_space_shooter.zip
cp Wio_Space_Shooter/*.ino src/
cp Wio_Space_Shooter/*.h src/
#または、別のゲームをコンパイルする場合、以下を実行する
wget https://macsbug.files.wordpress.com/2020/05/wio_clappy_shooter.zip_.pdf
mv wio_clappy_shooter.zip_.pdf wio_clappy_shooter.zip
unzip wio_clappy_shooter.zip
cp Wio_Clappy_Shooter/*.ino src/
cp Wio_Clappy_Shooter/*.h src/
追加するdefine
Arduino-IDEでは未定義にならないが、platformioでは 未定義(原因不明)になるので、以下を*.inoのソースの先頭に追加する。
// #define for wio terminal (for platformio)
#define WIO_KEY_A 28
#define WIO_KEY_B 29
#define WIO_KEY_C 30
#define WIO_5S_UP 31
#define WIO_5S_DOWN 34
#define WIO_5S_LEFT 32
#define WIO_5S_RIGHT 33
#define WIO_5S_PRESS 35
#define WIO_BUZZER 12
//------------------
Patch
*.inoのソースにミスがあるので以下の修正を行なう:
(ミススペル)
pinMode(WIO_5S_DOWM, INPUT_PULLUP); //
→
pinMode(WIO_5S_DOWN, INPUT_PULLUP); //
コンパイル/書き込み/実行
# ボードをホストPCに接続する
# build&upload(flash)
pio run -t upload
# buildしないで書き込む場合は以下を実行する:
pio run -t nobuild -t upload -v
# -v は、詳細を表示するオプション
書き込み後、スペースインベーダー風のゲームが起動する。
実行するスケッチ(参考)
src/Wio_Space_Shooter.ino
//======================== intro =======================================
// Space Shooter, basically knock-off Space Invaders
// and also maybe a bit of Galaga
// Written by Tyler Edwards for the Hackerbox #0020 badge
// But should work on any ESP32 and Adafruit ILI9341 display
// I am sorry for the messy code, you'll just
// have to live with it
// Tyler on GitHub: https://github.com/HailTheBDFL/
// Hackerboxes: http://hackerboxes.com/
//=========================== setup ===================================
// Wio Space Shooter : 2020.05.27 : Transplant by macsbug
// https://macsbug.wordpress.com/2020/05/27/wio-space-shooter/
// Controller : KEY_B, 5S_PRESS = START, SHOOT.
// Controller : KEY_C, 5S_LEFT = LEFT. KEY_A, 5S_RIGHT =RIGHT.
// Space Shooter with M5STACK : 2018.01.12 Transplant by macsbug
// Controller : Buttons A = LEFT, B = RIGHT, C = START or SHOOTING
// Github:https://macsbug.wordpress.com/2018/01/12/esp32-spaceshooter-with-m5stack/
//===================================================================
// #define for wio terminal (for platformio)
#define WIO_KEY_A 28
#define WIO_KEY_B 29
#define WIO_KEY_C 30
#define WIO_5S_UP 31
#define WIO_5S_DOWN 34
#define WIO_5S_LEFT 32
#define WIO_5S_RIGHT 33
#define WIO_5S_PRESS 35
#define WIO_BUZZER 12
//------------------
#include "Free_Fonts.h"
#include <TFT_eSPI.h>
TFT_eSPI tft = TFT_eSPI();
//============================= game variables =========================
unsigned long offsetM = 0;
unsigned long offsetT = 0;
unsigned long offsetF = 0;
unsigned long offsetB = 0;
unsigned long offsetA = 0;
unsigned long offsetAF = 0;
unsigned long offsetAB = 0;
unsigned long offsetS = 0;
int threshold = 40;
boolean startPrinted = false;
boolean beginGame = false;
boolean beginGame2 = true;
boolean play = false;
int score = 0;
int scoreInc = 10;
int level = 1;
//---------------------Player---------------------------------------
int shipX = 147;
int shipY = 190;
int oldShipX = 0;
int oldShipY = 0;
int changeShipX = 0;
int changeShipY = 0;
int shipSpeed = 50;
boolean doSplode = false;
boolean fire = false;
int fFireX[5] = {0, 0, 0, 0, 0};
int fFireY[5] = {0, 0, 0, 0, 0};
int fFireAge[5] = {0, 0, 0, 0, 0};
//--------------------------Aliens----------------------------------
boolean alienLive[18];
int alienLiveCount = 18;
int alienX = 7;
int alienY = 25;
int oldAlienX = 7;
int oldAlienY = 25;
int changeAlienX = 6;
int changeAlienY = 0;
int alienSpeed = 200;
int oldAlienSpeed;
int aFireX[5];
int aFireY[5];
boolean aFireAge[5];
int chanceOfFire = 2;
//================================ bitmaps ========================
//your starship
const int shipImgW = 14; const int shipImgH = 16;
char shipImg[] =
//xxxxxxxxxxxxxx--------------xxxxxxxxxxxxxx--------------
"ZZZZZZWWZZZZZZZZZZZYWWYZZZZZZZZZZWWWWZZZZZZZZZZWWWWZZZZZ"
"ZZZZWWWWWWZZZZZZZZWWWWWWZZZZZYZZWWWWWWZZYZZYZZWWWWWWZZYZ"
"WWZZWWBBWWZZWWWWZZWBBBBWZZWWWWZWWBBBBWWZWWWWZWWWWWWWWZWW"
"WWWWWWWWWWWWWWWRWWWWWWWWWWRWZZWWWWWWWWWWZZZZZWRRWWRRWZZZ";
//flames
const int flamesImgW = 12; const int flamesImgH = 6;
char flamesImg[] =
//xxxxxxxxxxxxxx--------------xxxxxxxxxxxxxx--------------
"RZZZZZZZZZZRRZRYYRRYYRZRRZRYYRRYYRZRZZRYRZZRYRZZZZZRZZZZ"
"RZZZZZZRZZZZRZZZ";
//alien
const int alienImgW = 14; const int alienImgH = 11;
char alienImg[] =
//xxxxxxxxxxxxxx--------------xxxxxxxxxxxxxx--------------
"GGGZZZZZZZZGGGZZZGZZZZZZGZZZZZGGGGGGGGGGZZZGGGGGGGGGGGGZ"
"GGGZGGGGGGZGGGGGGZZGGGGZZGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG"
"GZZZGGZZGGZZZGZGGZGGZZGGZGGZZZZZZGZZGZZZZZ";
//ship 'sploded
const int splodedImgW = 14; const int splodedImgH = 16;
char splodedImg[] =
//xxxxxxxxxxxxxx--------------xxxxxxxxxxxxxx--------------
"ZZZZZZWWZZZZZZZZZZRYWWYRZZZYZZZRRWWRRRRZRWYZRRRRRYYRRRZW"
"YZRYRYYRYYRRRZWWRYYYRYYYYYRZWWRYYRYRYYYYRRWWRYYYRWRYBRRZ"
"RRRYRRWWWRYRWZZRYYRRBBWRYRWWZZRYYBBBRRYBWWRZZRYYYRRYYZZW"
"ZRRWRYYRBYRZZWZZRYBRYYYYYRRZZRWWYYYWWRRRZZZZWRRWWRRRWZZZ";
//=============================== setup and loop ==================
void setup() {
memset(alienLive, true, 18);
memset(aFireX, 0, 5);
memset(aFireY, 0, 5);
memset(aFireAge, 0, 5);
tft.begin();
tft.setRotation(3);
tft.fillScreen(TFT_BLACK);
tft.setFreeFont(FM24);
tft.setTextColor(TFT_GREEN);
randomSeed(analogRead(6));
//-----------------------------------// BUTTON & 5 Way Swicth ---
pinMode(WIO_KEY_A, INPUT_PULLUP); // RIGHT
pinMode(WIO_KEY_B, INPUT_PULLUP); // CENTER
pinMode(WIO_KEY_C, INPUT_PULLUP); // LEFT
pinMode(WIO_5S_UP, INPUT_PULLUP); //
//pinMode(WIO_5S_DOWM, INPUT_PULLUP); //
pinMode(WIO_5S_DOWN, INPUT_PULLUP); //
pinMode(WIO_5S_LEFT, INPUT_PULLUP); //
pinMode(WIO_5S_RIGHT, INPUT_PULLUP); //
pinMode(WIO_5S_PRESS, INPUT_PULLUP); //
//-----------------------------------//
}
//==================================================================
void loop() {
if(digitalRead(WIO_KEY_C)== LOW ||
digitalRead(WIO_5S_LEFT )== LOW){left ();}
if(digitalRead(WIO_KEY_A)== LOW ||
digitalRead(WIO_5S_RIGHT)== LOW){right ();}
if(digitalRead(WIO_KEY_B)== LOW ||
digitalRead(WIO_5S_PRESS)== LOW){select();}
//-------------Start Screen--------------
if (millis() - offsetS >= 900 and !beginGame) {
if (!startPrinted) {
tft.setTextColor(TFT_GREEN);
tft.setCursor(87, 105);tft.setFreeFont(FM18);
tft.print(">START<");
startPrinted = true;
offsetS = millis();
} else {
tft.fillRect(89, 85, 143, 22, TFT_BLACK);
startPrinted = false;
offsetS = millis();
}
}
if (beginGame and beginGame2) {
tft.fillRect(89, 85, 143, 22, TFT_BLACK);
beginGame2 = false;
play = true;
}
//-------------Player-----------------------------------------------
if (millis() - offsetM >= shipSpeed and play) {
moveShip();
offsetM = millis();
}
if (oldShipX != shipX or oldShipY != shipY) {
tft.fillRect(oldShipX, oldShipY, 28, 44, TFT_BLACK);
oldShipX = shipX;
oldShipY = shipY;
drawBitmap(shipImg, shipImgW, shipImgH, shipX, shipY, 2);
}
if (fire and play) { fireDaLazer();}
if (millis() - offsetB >= 50) {
for (int i = 0; i < 5; i++) {
if (fFireAge[i] < 20 and fFireAge[i] > 0){keepFirinDaLazer(i);}
if (fFireAge[i] == 20) { stopFirinDaLazer(i);}
}
offsetB = millis();
}
if (millis() - offsetT > 50){changeShipX = 0;changeShipY = 0;}
//---------------Aliens--------------------------------------------
if (millis() - offsetA >= alienSpeed and play) {
moveAliens(); offsetA = millis();
}
if (findAlienX(5) >= 294){changeAlienX = -3;changeAlienY = 7;}
if (alienX <= 6){changeAlienX = 3; changeAlienY = 7;}
alienLiveCount = 0;
for (int i = 0; i < 18; i++) {
if (alienLive[i]) {
alienLiveCount += 1;
if (alienShot(i)) {
tft.fillRect(findOldAlienX(i),findOldAlienY(i),28,22,TFT_BLACK);
alienLiveCount -= 1;
alienLive[i] = false;
score += scoreInc;
}
if (onPlayer(i) or exceedBoundary(i)) {
gameOver();
}
}
}
if (alienLiveCount == 1) {
oldAlienSpeed = alienSpeed;
if (alienSpeed > 50) {
alienSpeed -= 10;
}
else {
alienSpeed = 20;
}
}
if (alienLiveCount == 0) {
levelUp();
}
}
// functions =======================================================
void gameOver() {
play = false;
if (doSplode) {
drawBitmap(splodedImg,splodedImgW,splodedImgH,shipX,shipY,2);
}
tft.fillScreen(TFT_BLACK);
drawScore(false);
delay(1000);
tft.setCursor(17,168);tft.setFreeFont(FM9);
tft.print("(Reset device to replay)");
while (1) { }
}
//==================================================================
void drawScore(boolean win) {
tft.setCursor(53, 40);tft.setFreeFont(FM18);
tft.setTextColor(TFT_WHITE);
if (win) {
tft.print("LEVEL UP!");
}
else { tft.print("GAME OVER");
}
for (;millis() - offsetM <= 1000;)
tft.setCursor(59, 89);tft.setFreeFont(FM18);
tft.print("Score: "); tft.print(score);
offsetM = millis();
for (;millis() - offsetM <= 1000;) {
}
tft.setCursor(59, 128);tft.setFreeFont(FM18);
tft.print("Level: "); tft.print(level);
}
//==================================================================
void levelUp() {
play = false;
memset(alienLive, true, 18);
memset(aFireX, 0, 5);
memset(aFireY, 0, 5);
memset(aFireAge, 0, 5);
alienX = 7;
alienY = 25;
oldAlienX = 7;
oldAlienY = 25;
alienSpeed = oldAlienSpeed;
if (alienSpeed > 100) {
alienSpeed -= 10; chanceOfFire -= 10;
}
else if (alienSpeed > 50) {
alienSpeed -= 10; chanceOfFire -=5;
}
else if (alienSpeed > 25) {
alienSpeed -= 5; chanceOfFire -=1;
}
score += 50; scoreInc += 5;
changeShipX = 0; changeShipY = 0;
for (unsigned long i = millis(); millis() - i <= 1600;) {
if (millis() - offsetM >= 20) {
tft.fillRect(oldShipX, oldShipY, 28, 44, TFT_BLACK);
drawBitmap(shipImg,shipImgW,shipImgH,shipX,shipY,2);
drawBitmap(flamesImg,flamesImgW,flamesImgH,shipX+1,shipY+32,2);
oldShipX = shipX; oldShipY = shipY;
shipY -= 6;
offsetM = millis();
}
}
drawScore(true);
level += 1;
shipX = 147;
shipY = 190;
for (; millis() - offsetM <= 4000;) {
}
tft.fillScreen(TFT_BLACK);
offsetM = millis();
play = true;
}
//==================================================================
boolean alienShot(int num) {
for (int i=0; i < 5; i++) {
if (fFireAge[i] < 20 and fFireAge[i] > 0) {
if (fFireX[i] > findAlienX(num) - 4 and fFireX[i] <
findAlienX(num) + 28 and fFireY[i] < findAlienY(num) +
22 and fFireY[i] > findAlienY(num) + 4) {
fFireAge[i] = 20;
return true;
}
}
}
return false;
}
//==================================================================
boolean onPlayer(int num) {
if (findAlienX(num) - shipX < 24 and findAlienX(num) -
shipX > -28 and findAlienY(num) - shipY < 32 and
findAlienY(num) - shipY > -22) {
doSplode = true;
return true;
} else { return false;}
}
//==================================================================
boolean exceedBoundary(int num) {
if (findAlienY(num) > 218) { return true;
} else { return false;
}
}
//==================================================================
void moveAliens() {
for (int i = 0; i < 18; i++) {
if (alienLive[i]) {
tft.fillRect(findOldAlienX(i),findOldAlienY(i),28,22,TFT_BLACK);
drawBitmap(alienImg,alienImgW,alienImgH,findAlienX(i),
findAlienY(i),2);
}
}
oldAlienX = alienX; oldAlienY = alienY;
alienX += changeAlienX; alienY += changeAlienY;
if (changeAlienY != 0) { changeAlienY = 0; }
}
//==================================================================
int findAlienX (int num){ return alienX + 42*(num % 6);}
//==================================================================
int findAlienY (int num){ return alienY + 33*(num / 6);}
//==================================================================
int findOldAlienX(int num){ return oldAlienX + 42*(num % 6);}
//==================================================================
int findOldAlienY(int num){ return oldAlienY + 33*(num / 6);}
//---------------------------Player---------------------------------
void fireDaLazer() {
int bulletNo = -1;
for (int i = 0; i < 4; i++) {
if (fFireAge[i] == 0) { bulletNo = i;}
}
if (bulletNo != -1) {
fFireAge[bulletNo] = 1;
fFireX[bulletNo] = shipX + 13;
fFireY[bulletNo] = shipY - 4;
tft.fillRect(fFireX[bulletNo],fFireY[bulletNo],4,3,TFT_MAGENTA);
}
fire = false;
}
//==================================================================
void keepFirinDaLazer(int bulletNo) {
tft.fillRect(fFireX[bulletNo],fFireY[bulletNo],4,4,TFT_BLACK);
fFireY[bulletNo] -= 8;
tft.fillRect(fFireX[bulletNo],fFireY[bulletNo],4,4,TFT_MAGENTA);
fFireAge[bulletNo] += 1;
}
//==================================================================
void stopFirinDaLazer(int bulletNo) {
tft.fillRect(fFireX[bulletNo],fFireY[bulletNo],4,4,TFT_BLACK);
fFireAge[bulletNo] = 0;
}
//==================================================================
void moveShip() {
if (shipX + changeShipX < 288 and shipX + changeShipX >
6 and changeShipX != 0){
shipX += changeShipX;
}
if (shipY + changeShipY > 24 and shipY + changeShipY <
192 and changeShipY != 0){
shipY += changeShipY;
}
if (oldShipX != shipX or oldShipY != shipY) {
tft.fillRect(oldShipX, oldShipY, 28, 44, TFT_BLACK);
oldShipX = shipX; oldShipY = shipY;
drawBitmap(shipImg, shipImgW, shipImgH, shipX, shipY, 2);
}
}
//==================================================================
void drawBitmap(char img[],int imgW,int imgH,int x,int y,int scale){
uint16_t cellColor;
char curPix;
for (int i = 0; i < imgW*imgH; i++) {
curPix = img[i];
if (curPix == 'W') { cellColor = TFT_WHITE; }
else if (curPix == 'Y') { cellColor = TFT_YELLOW; }
else if (curPix == 'B') { cellColor = TFT_BLUE; }
else if (curPix == 'R') { cellColor = TFT_RED; }
else if (curPix == 'G') { cellColor = 0x5E85; }
if (curPix != 'Z' and scale == 1) {
tft.drawPixel(x + i % imgW, y + i / imgW, cellColor);
}
else if (curPix != 'Z' and scale > 1) {
tft.fillRect(x + scale*(i%imgW),y +
scale*(i/imgW),scale,scale,cellColor);
}
}
}
//=========================== button functions =====================
void up() {
if (millis() - offsetT >= 50 and play) {
changeShipX = 0; changeShipY = -6; offsetT = millis();
}
}
//==================================================================
void down() {
if (millis() - offsetT >= 50 and play) {
changeShipX = 0; changeShipY = 6; offsetT = millis();
}
}
//==================================================================
void left() {
if (millis() - offsetT >= 50 and play) {
changeShipX = -6; changeShipY = 0; offsetT = millis();
}
}
//==================================================================
void right() {
if (millis() - offsetT >= 50 and play) {
changeShipX = 6; changeShipY = 0; offsetT = millis();
}
}
//==================================================================
void select() {
if (millis() - offsetF >= 500 and play) {
fire = true; offsetF = millis();
}
if (!beginGame) { beginGame = true;}
}
//==================================================================
参考情報
色々なサンプルコードのURL:
https://wiki.seeedstudio.com/Wio-Terminal-LCD-Fonts/
wget https://raw.githubusercontent.com/Bodmer/TFT_eSPI/master/examples/320%20x%20240/Free_Font_Demo/Free_Fonts.h
https://wiki.seeedstudio.com/Wio-Terminal-Buttons/
https://wiki.seeedstudio.com/Wio-Terminal-Switch/
https://wiki.seeedstudio.com/Wio-Terminal-Buzzer/
https://wiki.seeedstudio.com/Wio-Terminal-Infrared-Emitter/
Wio Terminalをはじめよう(ピン配置、データシート、回路図など)
Platform/Wio Terminal/Network/Overview
download url:
https://files.seeedstudio.com/wiki/Wio-Terminal/res/ameba-image-Tool-v2.4.1.zip
https://files.seeedstudio.com/wiki/Wio-Terminal/res/20200601-rtl8720d-images-v2.2.0.0.zip
https://wiki.seeedstudio.com/Wio-Terminal-Wi-Fi/
# ESP8266ライブラリと互換性があるので以下が参考になる:
https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/readme.html
https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/udp-examples.html
以上
| 固定リンク
« Wio-Terminalで画像を表示する(Seeeduino-Wio-Terminal/Arduino版) | トップページ | Wio-Terminalの「Wio Audio Spectrum Display」をplatformioでコンパイルして実行する »
「linux」カテゴリの記事
- platfomioを使ってnaitive(linux/windows)のプログラムをビルドする方法(2021.03.10)
- micro:bit Yotta開発ツール(linux版)(2021.01.09)
- PlatformIOをRaspberryPi4で動かしてみる(実験)(2020.10.20)
- headless RaspberryPiインストール方法(v2)(2020.10.20)
- wio-terminalのファームウェア・アップデートについて(linux版)(2020.10.15)
「PlatformIO」カテゴリの記事
- NuEVI/NuRADのビルド(2022.08.18)
- Wio_ExtFlashLoad(WriteSampleMenu.ino)スケッチをplatformioでビルドする(2022.02.03)
- uncannyeyesスケッチをplatformioでビルドする(2022.01.31)
- LovyanGFX-Display ライブラリを使用したスケッチをplatformioでビルドする(2022.01.30)
- Wio-Terminal/M5Core2のWiFiAnallyzer(2022.01.24)
「Arduino」カテゴリの記事
- platformioのために新しいユーザーを設定する(2022.02.06)
- MAKER_PI_RP2040でI2Cを使う(Arduino編)(2022.01.09)
- M5Stamp-PICO Arduino Install(2021.12.12)
- M5Stamp-C3 Arduino Install(2021.12.12)
- Arduino-CLIのインストール(2021.05.19)
「Wio Terminal」カテゴリの記事
- Wio_ExtFlashLoad(WriteSampleMenu.ino)スケッチをplatformioでビルドする(2022.02.03)
- Wio-TerminalでMQTTを動かす(2022.01.20)
- wio-terminalでGROVEを使う(2022.01.17)
- nixieクロックにNTPクライアントの機能を追加する(V2)(2021.02.18)
- Wio-Terminal/M5Atom/ESP8622/ESP32ボードを共通のスケッチで動かす(v2)(STARWARS編)(2020.12.28)
コメント