#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define PIXEL_WIDTH 4
#define PIXEL_HEIGHT 4
#define TILE_WIDTH 8
#define TILE_HEIGHT 8
#define COUNT_TILES 216
#define MAX_FRAMES_ANIMATION_WALKING 3
#define CENTER 8
#define WALK_CYCLE_COUNT 32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
const uint8_t guiTileDatabase[COUNT_TILES] = {
0b00000000, 0b00000111, 0b00001000, 0b00011011, 0b01100001, 0b10000011,
0b11110000, 0b01000000, 0b00000000, 0b11000000, 0b00100000, 0b00010000,
0b10010000, 0b10001000, 0b00001000, 0b00001000, 0b00111110, 0b00011000,
0b00101000, 0b00111000, 0b00001100, 0b00110011, 0b01010010, 0b01111110,
0b00010000, 0b01010000, 0b10001000, 0b11101000, 0b00100100, 0b11000100,
0b10101010, 0b11111110, 0b00000000, 0b00000000, 0b00000011, 0b00000100,
0b00001101, 0b00110000, 0b01000001, 0b01111000, 0b00000000, 0b00000000,
0b11100000, 0b00010000, 0b10001000, 0b11001000, 0b11000100, 0b00000100,
0b00100000, 0b00011111, 0b00001100, 0b00010100, 0b00010100, 0b00011010,
0b00101001, 0b00111111, 0b00000100, 0b00001000, 0b00101000, 0b01000100,
0b01010100, 0b00100010, 0b11010101, 0b01111111, 0b00000111, 0b01111000,
0b10000001, 0b01110011, 0b00001011, 0b00001000, 0b00111000, 0b01000000,
0b11100000, 0b00100000, 0b10010000, 0b00010000, 0b00001000, 0b00001000,
0b00001000, 0b00001000, 0b00000000, 0b00000000, 0b00000011, 0b00000100,
0b00001100, 0b00110000, 0b01000010, 0b01110001, 0b00000000, 0b00000000,
0b11100000, 0b00010000, 0b00001000, 0b00001000, 0b00000100, 0b10000100,
0b01111111, 0b10010000, 0b10011111, 0b10110101, 0b10101010, 0b10011111,
0b10000000, 0b01111111, 0b11111100, 0b00010010, 0b11110010, 0b01011010,
0b10101010, 0b11110010, 0b00000010, 0b11111100, 0b00111111, 0b01001000,
0b01001111, 0b01011010, 0b01010101, 0b01001111, 0b01000000, 0b00111111,
0b11111110, 0b00001001, 0b11111001, 0b10101101, 0b01010101, 0b11111001,
0b00000001, 0b11111110, 0b00000000, 0b00000000, 0b00000111, 0b00001000,
0b00010001, 0b01100010, 0b10000000, 0b11111000, 0b00000000, 0b00000000,
0b11000000, 0b00100000, 0b00010000, 0b00010000, 0b00001000, 0b00001000,
0b01000100, 0b01110000, 0b10001000, 0b11111000, 0b00001000, 0b00110100,
0b01010011, 0b01111110, 0b00001000, 0b00011100, 0b00000010, 0b00011110,
0b01001000, 0b10000100, 0b10101010, 0b11111110, 0b00000111, 0b01111000,
0b10000001, 0b01110010, 0b00001000, 0b00001000, 0b00111000, 0b01000000,
0b11100000, 0b00100000, 0b10010000, 0b01010000, 0b00001000, 0b00001000,
0b00001000, 0b00001000, 0b00000000, 0b00000000, 0b00000011, 0b00000100,
0b00001100, 0b00110000, 0b01000001, 0b01111000, 0b00000000, 0b00000000,
0b11100000, 0b00010000, 0b00001000, 0b00001000, 0b00000100, 0b11000100,
0b00000000, 0b00000000, 0b11100000, 0b00010000, 0b00001000, 0b00001000,
0b11000100, 0b00000100, 0b00000000, 0b01100000, 0b11111000, 0b11111110,
0b11111111, 0b11111110, 0b11111000, 0b01100000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,
};
const uint16_t guiSpriteTileIndexAgumon0[] = {0, 8, 16, 24};
const uint16_t guiSpriteTileIndexAgumon1[] = {32, 40, 48, 56};
const uint16_t guiSpriteTileIndexAgumon2[] = {64, 72, 16, 24};
const uint16_t guiSpriteTileIndexAgumon3[] = {80, 88, 96, 104};
const uint16_t guiSpriteTileIndexAgumon4[] = {80, 88, 112, 120};
const uint16_t guiSpriteTileIndexAgumon5[] = {128, 136, 144, 152};
const uint16_t guiSpriteTileIndexAgumon6[] = {160, 168, 16, 24};
const uint16_t guiSpriteTileIndexAgumon7[] = {176, 184, 48, 56};
const uint16_t guiSpriteTileIndexAgumon8[] = {176, 192, 48, 56};
const uint16_t guiSpriteTileIndexAgumon9[] = {200};
const uint8_t *const guiDigimonProjectileSprites = &guiTileDatabase[200];
const uint16_t
*const guiDigimonWalkingAnimationDatabase[MAX_FRAMES_ANIMATION_WALKING] = {
guiSpriteTileIndexAgumon0, guiSpriteTileIndexAgumon1,
guiSpriteTileIndexAgumon2,
};
static const int8_t uiWalkCycleMove[WALK_CYCLE_COUNT] = {
-2, -2, 0, 2, 0, -2, -2, 2, -2, -2, 2, 0, 0, 0, 2, 2,
2, 2, 2, 0, -2, 0, 2, 0, 2, 2, -2, 2, -2, -2, -2, -2};
static const uint8_t uiWalkCycleFlips[WALK_CYCLE_COUNT] = {0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0,
0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1,
1, 0, 1, 1, 1, 1, 1, 0, 0, 0};
static const uint8_t uiWalkCycleIndices[WALK_CYCLE_COUNT] = {
0, 1, 1, 0, 0, 1, 1, 1, 1, 2, 1,
2, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0,
0, 1, 1, 2, 1, 2, 1, 1, 0, 0};
void drawTile(uint8_t* tile, uint8_t x, uint8_t y, bool flip) {
for (size_t i = y; i < y + TILE_HEIGHT; i++) {
uint8_t currentLine = *tile;
if (flip) {
currentLine = (currentLine & 0xF0) >> 4 |
(currentLine & 0x0F) << 4;
currentLine = (currentLine & 0xCC) >> 2 |
(currentLine & 0x33) << 2;
currentLine = (currentLine & 0xAA) >> 1 |
(currentLine & 0x55) << 1;
}
for (size_t j = x; j < x + TILE_WIDTH; j++) {
const uint8_t currentPixel = (currentLine & 0b10000000) >> 7;
currentLine <<= 1;
if (currentPixel) {
display.fillRect(
j * PIXEL_WIDTH,
i * PIXEL_HEIGHT,
PIXEL_WIDTH,
PIXEL_HEIGHT,
SSD1306_BLACK
);
}
}
tile++;
}
}
void drawSprite(uint16_t* sprite, uint8_t x, uint8_t y, bool flip) {
uint8_t xLeft = flip ? x + TILE_WIDTH : x;
uint8_t xRight = flip ? x : x + TILE_WIDTH;
drawTile(guiTileDatabase + sprite[0], xLeft, y, flip);
drawTile(guiTileDatabase + sprite[1], xRight, y, flip);
drawTile(guiTileDatabase + sprite[2], xLeft, y + TILE_HEIGHT, flip);
drawTile(guiTileDatabase + sprite[3], xRight, y + TILE_HEIGHT, flip);
}
static uint8_t indexWalkCycle = 0xff;
static uint8_t xPos = CENTER;
void setup() {
Serial.begin(9600);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3c)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
}
void loop() {
// put your main code here, to run repeatedly:
display.clearDisplay();
display.fillRect(
0,
0,
SCREEN_WIDTH,
SCREEN_HEIGHT,
SSD1306_WHITE
);
drawSprite(
guiDigimonWalkingAnimationDatabase[indexWalkCycle == 0xff ? 0 : uiWalkCycleIndices[indexWalkCycle]],
xPos,
0,
uiWalkCycleFlips[indexWalkCycle]
);
display.display();
delay(500);
indexWalkCycle = (indexWalkCycle + 1) % WALK_CYCLE_COUNT;
xPos += uiWalkCycleMove[indexWalkCycle];
}