#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"
#include "sprites.h"
#define TFT_DC 9
#define TFT_CS 10
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
void clearScreen( uint16_t color=0 ){
  tft.startWrite();
  tft.setAddrWindow(0,0,320,240);
  for (byte b=0; b<32; b++){
    for (uint16_t i=0; i<2400; i++) {
      tft.SPI_WRITE16(color); 
    }
  }
  tft.endWrite(); 
}
void drawOneSprite(int x, int y, uint16_t* spr, int width, int height) {
  int length=width*height;
  tft.startWrite();
  tft.setAddrWindow(x,y,width,height);
  for (int n=0; n<length; n++) {
    tft.SPI_WRITE16( pgm_read_word( &spr[n] ) ); 
  }
  tft.endWrite(); 
}
void drawSprite( int i ){
  if (mas[i].type != NOT_USE) {
    if (mas[i].x < 0 || mas[i].x+mas[i].width > 319) return;
    tft.startWrite();
    tft.setAddrWindow(mas[i].x,mas[i].y,mas[i].width,mas[i].height);
    for (int n=0; n<mas[i].length; n++) {
      tft.SPI_WRITE16( pgm_read_word( &mas[i].sprite[n] ) ); 
    }
    tft.endWrite(); 
  }
}
void drawSprites(){
  for(int i=0; i<MAS_CNT; i++){
    drawSprite( i );
  }
}
void clearSprite(int i){
  if (mas[i].x < 0 || mas[i].x+mas[i].width > 319) return;
  tft.startWrite();
  tft.setAddrWindow(mas[i].x,mas[i].y,mas[i].width,mas[i].height);
  for (int n=0; n<mas[i].length; n++) {
    tft.SPI_WRITE16( F ); 
  }
  tft.endWrite(); 
}
void clearSprites(){
  for(int i=0; i<MAS_CNT; i++){
    if ( mas[i].type != NOT_USE ) {
      clearSprite( i );
    }
  }
}
void setup() {
  randomSeed( analogRead(A0) );
  pinMode(KEY, INPUT_PULLUP);
  Serial.begin(115200);
  tft.begin();
  tft.setRotation(1);
  tft.setTextColor(ILI9341_RED);
  tft.setTextSize(2);
  tft.setCursor(100,50);
}
void moveInvaderY(){
  if (invader_stepY > 0){
    invader_stepY--;
    if (invader_stepY == 0) {
      for (int i=0; i<MAS_CNT; i++){
        if (mas[i].type == INVADER){
          clearSprite(i);
          mas[i].y += 10;
        }
      }
    }
  }
}
void show_score(){
  for (int i=1; i<live; i++){
    drawOneSprite(i*(PLATFORM_W+5), 0, &platform1[0], PLATFORM_W, PLATFORM_H);
  }
  tft.fillRect(270,0,319,16,F );
  tft.setCursor(270,0);
  tft.setTextColor( Y );
  tft.print( score );
}
void loop() { 
  clearScreen( F );
  initMas();
  while ( ! endGame ) {
      for (int i=0; i<MAS_CNT; i++){
        if (mas[i].type != NOT_USE){
          clearSprite(i);
          mas[i].move(i);
          drawSprite(i);
        }
      }
      if  (invader_direction != direction){
        invader_direction = direction;
        moveInvaderY();
      }
      
      if ( time_rocket == 0 ) {
        if ( digitalRead(KEY) == 0 ) new_rocket();
      }
      else if ( millis() > time_rocket ) time_rocket = 0;
      if ( time_bomb ) {
        if ( millis() > time_bomb ) {
          time_bomb = millis() + random(500,1500);
          new_bomb();
        }
      }
      show_score();
      delay(2);
  }
  tft.setCursor(100,150);
  if ( !winner ) {
    live -- ;
    if ( live <= 0 ) {
      tft.setTextColor( R );
      tft.println("Game over!");
      live = FULL_LIVES;
      score = 0;
      delay(1000);
    }
  }
  
}