#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 128
#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[] PROGMEM = {
0b00001101, 0b00010110, 0b00011110, 0b00100100, 0b00101000, 0b00110011,
0b00100110, 0b00011001, 0b10000000, 0b10000000, 0b11110000, 0b00010000,
0b01101110, 0b01110010, 0b01001100, 0b10000100, 0b00011110, 0b00110001,
0b01010011, 0b01011111, 0b00111001, 0b00101011, 0b01001101, 0b01111001,
0b11011000, 0b11101000, 0b00101000, 0b00110000, 0b11110000, 0b00010000,
0b01001000, 0b11111000, 0b00000000, 0b00001101, 0b00010110, 0b00011110,
0b00100100, 0b00101000, 0b00110011, 0b00100110, 0b00000000, 0b10000000,
0b10000000, 0b11110000, 0b00010000, 0b01101110, 0b01110010, 0b01001100,
0b00011001, 0b00011110, 0b00110001, 0b01010011, 0b01011111, 0b01101001,
0b10001011, 0b11111100, 0b10000100, 0b11011000, 0b11101000, 0b00101000,
0b00110000, 0b11001000, 0b10100100, 0b11111100, 0b00001101, 0b00010110,
0b00011110, 0b00100100, 0b00101001, 0b00110010, 0b00100000, 0b00011110,
0b10000000, 0b10000000, 0b11110000, 0b00010000, 0b01101110, 0b11110010,
0b01001100, 0b10000100, 0b00011100, 0b00110011, 0b01011101, 0b01010011,
0b00111101, 0b00101011, 0b01001101, 0b01111001, 0b00000000, 0b00001101,
0b00010110, 0b00011110, 0b00100100, 0b00101000, 0b00110010, 0b00100101,
0b00000000, 0b00000000, 0b00000000, 0b00001101, 0b00010110, 0b00011110,
0b00100100, 0b00101000, 0b00000000, 0b00000000, 0b00000000, 0b10000000,
0b10000000, 0b11110000, 0b00010000, 0b01101110, 0b00110011, 0b00100000,
0b00011001, 0b01111111, 0b10101011, 0b10001111, 0b10001000, 0b11111111,
0b01110010, 0b01001100, 0b10000100, 0b11111000, 0b10101000, 0b10001000,
0b10001000, 0b11111000, 0b00000000, 0b00000000, 0b00001101, 0b00010110,
0b00011110, 0b00100100, 0b00101000, 0b00110011, 0b00000000, 0b00000000,
0b10000000, 0b10000000, 0b11110000, 0b00010000, 0b01101110, 0b01110010,
0b00100000, 0b00011001, 0b00011110, 0b01110001, 0b10101011, 0b10001111,
0b10001000, 0b11111111, 0b01001100, 0b10000100, 0b11011000, 0b11111000,
0b10101000, 0b10001000, 0b10001000, 0b11111000, 0b00000000, 0b00001101,
0b00010110, 0b00011110, 0b00100100, 0b00101000, 0b00110001, 0b00100010,
0b00011001, 0b00111110, 0b01010001, 0b01010011, 0b00111111, 0b01101001,
0b10001011, 0b11111100, 0b10000100, 0b11011000, 0b00111000, 0b00101000,
0b11110000, 0b11001000, 0b10100100, 0b11111100, 0b00111110, 0b01010001,
0b01011110, 0b00110011, 0b00011100, 0b00101011, 0b01001101, 0b01111001,
0b11101000, 0b10010100, 0b10010100, 0b01101000, 0b11110000, 0b00010000,
0b01001000, 0b11111000, 0b00001110, 0b00010001, 0b00101110, 0b00101001,
0b00011111, 0b00101011, 0b01001101, 0b01111001, 0b11110100, 0b01101000,
0b10001000, 0b10010000, 0b11110000, 0b00010000, 0b01001000, 0b11111000,
0b00000000, 0b00001101, 0b00010110, 0b00011110, 0b00100100, 0b00101000,
0b00110100, 0b00100110, 0b00011001, 0b00011110, 0b01110001, 0b10010010,
0b10111110, 0b01101001, 0b01001011, 0b01111100, 0b10000100, 0b11011000,
0b11101000, 0b01001000, 0b01010000, 0b11111000, 0b10100100, 0b11111100,
0b00000000, 0b00000000, 0b00001101, 0b00010110, 0b00011110, 0b00100100,
0b00101000, 0b00110100, 0b00100110, 0b00011001, 0b00011110, 0b00110001,
0b01010010, 0b01111110, 0b10001111, 0b11111001, 0b01001100, 0b10000100,
0b11011000, 0b11101000, 0b01001000, 0b01111000, 0b10100100, 0b11111100,
0b00000110, 0b00001011, 0b00001111, 0b00010010, 0b00010100, 0b00011001,
0b00010011, 0b00001100, 0b11000000, 0b01000000, 0b01111000, 0b00001000,
0b00111110, 0b10110010, 0b00101100, 0b11000100, 0b01111111, 0b10001000,
0b10011001, 0b01100111, 0b00001100, 0b00010101, 0b00100110, 0b00111100,
0b01111100, 0b10010100, 0b10001000, 0b11110000, 0b11011000, 0b10001100,
0b10100100, 0b11111100, 0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b01100000,
0b11111000, 0b11111110, 0b11111111, 0b11111110, 0b11111000, 0b01100000
};
const uint16_t guiSpriteTileIndexMagnamonX0[] PROGMEM = {0, 8, 16, 24};
const uint16_t guiSpriteTileIndexMagnamonX1[] PROGMEM = {32, 40, 48, 56};
const uint16_t guiSpriteTileIndexMagnamonX2[] PROGMEM = {64, 72, 80, 24};
const uint16_t guiSpriteTileIndexMagnamonX3[] PROGMEM = {88, 40, 48, 56};
const uint16_t guiSpriteTileIndexMagnamonX4[] PROGMEM = {96, 104, 112, 120};
const uint16_t guiSpriteTileIndexMagnamonX5[] PROGMEM = {128, 136, 144, 152};
const uint16_t guiSpriteTileIndexMagnamonX6[] PROGMEM = {160, 40, 168, 176};
const uint16_t guiSpriteTileIndexMagnamonX7[] PROGMEM = {64, 72, 184, 192};
const uint16_t guiSpriteTileIndexMagnamonX8[] PROGMEM = {64, 8, 200, 208};
const uint16_t guiSpriteTileIndexMagnamonX9[] PROGMEM = {216, 40, 224, 232};
const uint16_t guiSpriteTileIndexMagnamonX10[] PROGMEM = {240, 136, 248, 256};
const uint16_t guiSpriteTileIndexMagnamonX11[] PROGMEM = {264, 272, 280, 288};
const uint16_t guiSpriteTileIndexMagnamonX12[] PROGMEM = {296, 296, 296, 296};
const uint16_t guiSpriteTileIndexMagnamonX13[] PROGMEM = {304};
const uint8_t* const guiDigimonProjectileSprites PROGMEM = &guiTileDatabase[304];
const uint16_t* const
guiDigimonWalkingAnimationDatabase[MAX_FRAMES_ANIMATION_WALKING] PROGMEM = {
guiSpriteTileIndexMagnamonX0, guiSpriteTileIndexMagnamonX1,
guiSpriteTileIndexMagnamonX2};
static const int8_t uiWalkCycleMove[WALK_CYCLE_COUNT] PROGMEM = {
-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] PROGMEM = {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] PROGMEM = {
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 = pgm_read_byte_near(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 + pgm_read_byte_near(sprite + 0), xLeft, y, flip);
drawTile(guiTileDatabase + pgm_read_byte_near(sprite + 1), xRight, y, flip);
drawTile(guiTileDatabase + pgm_read_byte_near(sprite + 2), xLeft, y + TILE_HEIGHT, flip);
drawTile(guiTileDatabase + pgm_read_byte_near(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(;;);
}
Serial.print(sizeof(guiTileDatabase));
Serial.print(",");
Serial.print(sizeof(guiSpriteTileIndexMagnamonX0));
Serial.print(",");
Serial.print(sizeof(guiDigimonProjectileSprites));
Serial.print(",");
Serial.print(sizeof(guiDigimonWalkingAnimationDatabase));
Serial.print(",");
Serial.print(sizeof(uiWalkCycleMove));
Serial.print(",");
Serial.print(sizeof(uiWalkCycleFlips));
Serial.print(",");
Serial.println(sizeof(uiWalkCycleIndices));
}
void loop() {
// put your main code here, to run repeatedly:
display.clearDisplay();
display.fillRect(
0,
0,
SCREEN_WIDTH,
SCREEN_HEIGHT,
SSD1306_WHITE
);
int offsetWalkCycle = 0;
if (indexWalkCycle != 0xff) {
offsetWalkCycle = pgm_read_byte_near(uiWalkCycleIndices + indexWalkCycle);
}
drawSprite(
// guiDigimonWalkingAnimationDatabase[],
pgm_read_ptr_near(guiDigimonWalkingAnimationDatabase + offsetWalkCycle),
xPos,
0,
pgm_read_byte_near(uiWalkCycleFlips + indexWalkCycle)
);
display.display();
delay(500);
indexWalkCycle = (indexWalkCycle + 1) % WALK_CYCLE_COUNT;
xPos += pgm_read_byte_near(uiWalkCycleMove + indexWalkCycle);
}