#include <Adafruit_SSD1306.h>
#include <Wire.h>
#define SW 1
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
void displayInit() {
display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS);
}
void clearDisplay() {
display.clearDisplay();
}
void showDisplay() {
display.display();
}
void setPixel(int8_t x, int8_t y) {
display.drawPixel(x, y, 1);
}
//================================================================================
//================================================================================
//================================================================================
// 'ship', 15x15px
const uint8_t ship_img [] PROGMEM = {
0x38, 0x00, 0x38, 0x00, 0x3c, 0x00, 0x36, 0x00, 0x33, 0x80, 0x7f, 0xf0, 0xfe, 0xfc, 0xbc, 0x36,
0xfe, 0xfc, 0x7f, 0xf0, 0x33, 0x80, 0x36, 0x00, 0x3c, 0x00, 0x38, 0x00, 0x38, 0x00, 0x00, 0x00
};
const uint8_t jet_img [3][3] PROGMEM = {
{0x08, 0xb8, 0x18},
{0xb8, 0x18, 0x08},
{0x18, 0x08, 0xb8}
};
// 'UFO', 16x10px
const uint8_t ufo_img [] PROGMEM = {
0x03, 0xc0, 0x0c, 0x30, 0x18, 0x18, 0x10, 0x08, 0x1f, 0xf8, 0x20, 0x04, 0x40, 0x02, 0xf6, 0xdf,
0x12, 0x48, 0x0f, 0xf0
};
// 'exp1', 15x15px
const unsigned char exp_img [3][30] PROGMEM = {
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x40, 0x00, 0x20, 0x00, 0x00,
0x08, 0x00, 0x04, 0x40, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
},
// 'exp2', 15x15px
{
0x00, 0x40, 0x20, 0x80, 0x02, 0x04, 0x10, 0x10, 0x02, 0x00, 0x84, 0x40, 0x40, 0x28, 0x00, 0x00,
0x28, 0x04, 0x04, 0x42, 0x00, 0x80, 0x10, 0x10, 0x40, 0x80, 0x04, 0x08, 0x08, 0x00
},
// 'exp3', 15x15px
{
0x00, 0x40, 0x20, 0x80, 0x02, 0x04, 0x10, 0x10, 0x00, 0x00, 0x80, 0x00, 0x40, 0x08, 0x00, 0x00,
0x20, 0x04, 0x00, 0x02, 0x00, 0x00, 0x10, 0x10, 0x40, 0x80, 0x04, 0x08, 0x08, 0x00
}
};
struct T_ship {
bool dir = false;
uint8_t x = 6;
uint8_t y = 16;
} ship;
#define ammo_max 5
struct T_ammo {
bool e = false;
uint8_t x = 0;
uint8_t y = 0;
} ammo[ammo_max];
#define ufo_max 1
struct T_ufo {
bool e = true;
uint8_t x = 111;
uint8_t y = 16;
} ufo[ufo_max];
struct T_bomb {
bool e = false;
uint8_t f = 0;
uint8_t x = 0;
uint8_t y = 0;
} bomb[ufo_max];
void (*CB_keyShortPress) (void);
void (*CB_keyLongPress) (void);
void (*CB_keyRelease) (void);
void btnScan() {
static bool start_expire = false;
static char step = 0;
static unsigned long mil_press = 0;
static unsigned long mil_expire = 0;
static bool dir = true;
bool SW_press = !digitalRead(SW);
unsigned long mil_now = millis();
switch(step) {
case 0: if (!SW_press) {
mil_press = mil_now;
step++;
}
break;
case 1: if (mil_now - mil_press >= 50) {
if (!SW_press) {
step++;
} else {
step = 0;
}
}
break;
case 2: if (SW_press) {
mil_press = mil_now;
step++;
}
break;
case 3: if (mil_now - mil_press >= 50) {
if (SW_press) {
step++;
} else {
step = 0;
}
}
break;
case 4: if (SW_press) {
if (mil_now - mil_press >= 500) {
Serial.println("Long Press");
mil_expire = mil_now;
start_expire = true;
step = 0;
//CB_keyLongPress();
}
} else {
mil_press = mil_now;
step++;
}
break;
case 5: if (mil_now - mil_press >= 50) {
if (!SW_press) {
Serial.println("Short Press");
mil_expire = mil_now;
start_expire = true;
step = 0;
CB_keyShortPress();
} else {
step--;
}
}
break;
default: step = 0;
break;
}
if ((start_expire) && (mil_now - mil_expire >= 10000)) {
start_expire = false;
//CB_keyExpire();
}
}
void drawImg(int16_t org_x, int16_t org_y, int16_t width, int16_t height, const uint8_t *xbm) {
int16_t widthInXbm = (width + 7) / 8;
uint8_t data = 0;
for(int16_t y = 0; y < height; y++)
for(int16_t x = 0; x < width; x++) {
if (x & 7) data <<= 1;
else data = pgm_read_byte(xbm + (x / 8) + y * widthInXbm);
if (data & 0x80)
setPixel(org_x + x, org_y + y);
}
}
void doFire() {
for (int8_t i = 0; i < ammo_max; i++) {
if (!ammo[i].e) {
ammo[i].e = true;
ammo[i].y = ship.y + 7;
ammo[i].x = ship.x + 15;
break;
}
}
}
void drawShip() {
drawImg(ship.x, ship.y, 15, 15, ship_img);
drawImg(ship.x - 6, ship.y + 6, 5, 3, jet_img[random(3)]);
}
void moveAmmo() {
for (int8_t i = 0; i < ammo_max; i++)
if (ammo[i].e) {
ammo[i] .x += 1;
if (ammo[i].x >= 128)
ammo[i].e = false;
}
}
void drawAmmo() {
for (int8_t i = 0; i < ammo_max; i++)
if (ammo[i].e) {
setPixel(ammo[i].x - 0, ammo[i].y);
setPixel(ammo[i].x - 1, ammo[i].y);
}
}
void drawBomb() {
for (int8_t i = 0; i < ufo_max; i++)
if (bomb[i].e) {
drawImg(bomb[i].x, bomb[i].y, 15, 15, exp_img[bomb[i].f]);
if (++bomb[i].f >= 3) {
bomb[i].e = false;
}
}
}
void checkFired() {
for (int8_t i = 0; i < ammo_max; i++)
for (int8_t j = 0; j < ufo_max; j++)
if ((ammo[i].e) && (ufo[j].e))
if (ammo[i].x == ufo[j].x)
if (ammo[i].y >= ufo[j].y)
if (ammo[i].y <= ufo[j].y + 10) {
ammo[i].e = false;
ufo[j].e = false;
bomb[j].e = true;
bomb[j].f = 0;
bomb[j].x = ufo[j].x;
bomb[j].y = ufo[j].y;
}
}
void newUFO () {
for (int8_t i = 0; i < ufo_max; i++)
if (!ufo[i].e) {
ufo[i].e = true;
ufo[i].x = 64 + random(48);
ufo[i].y = 16 + random(38);
}
}
void drawUFO() {
for (int8_t i = 0; i <ufo_max; i++)
if (ufo[i].e)
drawImg(ufo[i].x, ufo[i].y, 16, 10, ufo_img);
}
void setup() {
delay(1000);
pinMode(SW, INPUT_PULLUP);
Serial.begin(115200);
displayInit();
CB_keyShortPress = &doFire;
}
unsigned long now;
unsigned long mil_ship;
unsigned long mil_ammo;
void loop() {
now = millis();
clearDisplay();
if (now - mil_ammo > 10) {
mil_ammo = now;
moveAmmo();
}
if (now - mil_ship > 50) {
mil_ship = now;
if (ship.dir) {
if (++ship.y + 15 > 63) {
ship.dir = false;
ship.y = 63 - 15;
}
} else {
if (--ship.y < 16) {
ship.dir = true;
ship.y = 16;
}
}
}
drawShip();
drawAmmo();
drawUFO();
drawBomb();
showDisplay();
checkFired();
newUFO();
btnScan();
}