M5Stackにパックマンを移植する

このwebサイトを参考にM5StackでPACMANを動作させようとしたものの上手く動かなかった人用の記事です。
https://macsbug.wordpress.com/2018/03/07/pacman-with-m5stack/
おまけでアナログスティックやボタンを追加するためのコードも紹介します。

#コードの変更点
基本的には上記のwebサイトを参考にコードを変更するのですが、元のファイルに変更点があったのか、そのままでは上手く動作しません。そのため動作させるための変更点を順に紹介していきます。

以下のファイルをダウンロードして変更していきます
https://github.com/MhageGH/esp32_ILI9328_Pacman

【esp32_ILI9328_Pacman.ino】
24行目に追加

```
#include <M5Stack.h>
```

次の3行を削除(ctrl+fなどで検索してください)

```
const char ssid[] = "ESP32";
const char password[] = "esp32pass";
const int localPort = 10000;
```

次の3行を削除

```
#include <SPI.h>
#include <WiFi.h>
#include <WiFiUdp.h>
```

次の4行を削除

```
#define CS 5
#define RESET 17
ili9328SPI tft(CS, RESET);
WiFiUDP udp;
```

drawIndexedmapの呼び出しを次のように変更

```
//元はdrawIndexedmap(&tft, tile, x, y);
drawIndexedmap(tile, x, y);
```

setup()内を次のように変更

```
void setup() {
  randomSeed(analogRead(0));
  Serial.begin(115200);
  M5.begin();
  Wire.begin();
  M5.Lcd.setRotation(0);//ここで画面の向きを変更可
  M5.Lcd.fillScreen(TFT_BLACK);
  pinMode(5, INPUT_PULLUP);
  dacWrite(25, 0);
  delay(100);
}
```

KeyPadLoopをFACES GameBoy用に変更(FACESを持っていないため未確認)

```
void KeyPadLoop(){
  char r;
  if(digitalRead(5) == LOW) {
    Wire.requestFrom(0X88, 1);         // request 1 byte from keyboard
    while (Wire.available()) { 
      uint8_t key_val = Wire.read();   // receive a byte as character
      if ( key_val == 191) { r = 'z';} // select
      if ( key_val == 127) { r = 'x';} // start
      if ( key_val == 247) { r = '8';} // up
      if ( key_val == 251) { r = '2';} // down
      if ( key_val == 254) { r = '4';} // left
      if ( key_val == 253) { r = '6';} // right
    }
  }
  if (r == 'z') { ClearKeys(); but_A=true; delay(300); } //else but_A=false;
  if (r == 'x') { ClearKeys(); but_B=true; delay(300); } //else but_B=false;
  if (r == '8') { ClearKeys(); but_UP=true; }  //else but_UP=false;
  if (r == '2') { ClearKeys(); but_DOWN=true; }  //else but_DOWN=false;
  if (r == '4') { ClearKeys(); but_LEFT=true; }   //else but_LEFT=false;
  if (r == '6') { ClearKeys(); but_RIGHT=true; }  //else but_RIGHT=false;
}
```

【DrawindexedMap.h】
次を削除

```
#include “ili9328.h”
```

drawIndexedmapを引数も含めて次のように変更

```
void drawIndexedmap(uint8_t* indexmap, int16_t x, uint16_t y) {
  byte i = 0;
  uint16_t color = _paletteW[indexmap[0]];
  for (byte tmpY = 0; tmpY < 8; tmpY++) {
    byte width = 1;
    for (byte tmpX = 0; tmpX < 8; tmpX++) {
      uint16_t next_color = _paletteW[indexmap[++i]];
      if ((color != next_color && width >= 1) || tmpX == 7) {
        M5.Lcd.drawFastHLine(x + tmpX - width+1, y + tmpY-1, width, color);
        color = next_color;
        width = 0;
      }
      width++;
    }
  }
}
```

これで動作すると思います。

#おまけ
自分はFACESを使わずにアナログスティックを用いて操作したのでアナログスティックを使用するための手順を紹介します。


1.アナログスティックをM5Stackに接続する

M5Stackの35、36にアナログスティックのx軸、y軸を入力し、アナログスティックの押し込みを2に入力することとします。

2.コードを編集する

define BLACK 0x0000の後に次の様にコードを挿入

```
#define BLACK 0x0000 // 16bit BLACK Color
#define JOY_X 35
#define JOY_Y 36
```

setup()内のpinMode(5, INPUT_PULLUP);の後に次のようにコードを挿入

```
pinMode(5, INPUT_PULLUP);
pinMode(2, INPUT_PULLUP);
pinMode(JOY_X, INPUT);
pinMode(JOY_Y, INPUT);
```

KeyPadLoop()のchar rの前に次のようにコードを挿入
joyX, joyYの入力範囲は自由に決めてください

```
if(digitalRead(2) == 0) {
    ClearKeys();
    but_B=true; delay(300);
    return;
  }
  uint16_t joyX = analogRead(JOY_X);
  uint16_t joyY = analogRead(JOY_Y);
    if(joyX<=1400)  { ClearKeys(); but_LEFT=true;  }
    if(joyX>=2200) { ClearKeys(); but_RIGHT=true;    }
    if(joyY<=1400)  { ClearKeys(); but_UP=true;  }
    if(joyY>=2200) { ClearKeys(); but_DOWN=true; }
  char r;
```

これでアナログスティックも使用できるようになったかと思います。

#参考
https://macsbug.wordpress.com/2018/03/07/pacman-with-m5stack/

https://github.com/tobozo/M5Stack-Pacman-JoyPSP