Asterocks by Yoda. Ported from Gamebuino to Pokito by Jonne using automated parser.

Dependencies:   PokittoLib

Fork of HelloWorld by Pokitto Community Team

asterocks.cpp

Committer:
Pokitto
Date:
2018-05-02
Revision:
12:79c542632971
Parent:
4:46e28b959b54

File content as of revision 12:79c542632971:

/* This file was automatically parsed from an Arduino sourcefile  */
/* by PokittoParser v0.1 Copyright 2016 Jonne Valola              */
/* USE AT YOUR OWN RISK - NO GUARANTEES GIVEN OF 100% CORRECTNESS */
//#include <SPI.h>
#include "Pokitto.h"
#include "PokittoFakeavr.h"
#include "WString.h"

#define MAXASTEROCKS 32
#define MAXX LCDWIDTH*8  //880 //644
#define MINX -56
#define MAXY LCDHEIGHT*8 //704 //376
#define MINY -56

Pokitto::Core gb;
/* Auto-generated function declarations */
void setup();
void loop();
void newgame();
void newlevel();
void newlife();
void showscore();
void nextlevelcheck();
void handledeath();
void handleplayership();
void handleplayershots();
void handlerocks();
void ufoappears();
void moveufo();
void playershotufocollission();
void ufoshotrelease();
void moveufoshot();
void checkbonuslife();
void backgroundsound();
void showgameover();
void showtitle();
void playsoundfx(int,int);
//----------------------------------------------------------------------
//                            A S T E R O C K S
//                              by Yoda Zhang
//----------------------------------------------------------------------
// Please use this source-code for learning purposes only. If you make
// changes to the code, it may not compile to the same result as the
// provided HEX file, since I made changes to my compiler settings.
//----------------------------------------------------------------------


// define variables and constants
String gamestatus;
int score;
int highscore;
byte lives;
byte gamelevel;
int yeahtimer;
int deadtimer;
int i;
int u;
float x;
float y;

int playershipx;
int playershipy;
int playershiprotation;
int playershipxspeed;
int playershipyspeed;
byte playershipvisible;
byte playershipappear;
int xadd[16]={0,4,8,8,8,8,8,4,0,-4,-8,-8,-8,-8,-8,-4};
int yadd[16]={-8,-8,-8,-4,0,4,8,8,8,8,8,4,0,-4,-8,-8};
int rockxadd[12]={4,4,-4,-4,8,8,8,8,-8,-8,-8,-8};
int rockyadd[12]={-8,8,-8,8,-8,-4,4,8,8,4,-4,-8};
int playershotx[4];
int playershoty[4];
int playershotxspeed[4];
int playershotyspeed[4];
byte playershotcounter[4];
byte playershots;
int bonusscore;
byte soundspeed;
byte soundvalue;
byte soundcounter;

int asterockx[MAXASTEROCKS+1];
int asterocky[MAXASTEROCKS+1];
int asterockxspeed[MAXASTEROCKS+1];
int asterockyspeed[MAXASTEROCKS+1];
byte asterocktype[MAXASTEROCKS+1];
byte asterocksonscreen;
byte destroyed;
byte left;
byte right;

int ufox;
int ufoy;
byte ufotype;
int ufoxr;
int ufoyr;
int ufoshotx;
int ufoshoty;
int ufoshotxr;
int ufoshotyr;

// define images & sounds
extern const byte PROGMEM gamelogo[];
extern const byte PROGMEM playership[20][9];
extern const byte PROGMEM asterocks[12][22];
extern const byte PROGMEM ufo[2][7];
extern const byte PROGMEM bullet[];
extern const int soundfx[10][8];

// setup
void setup(){
    /** Set colors for this game **/
    //palette[0] = pokConvertRGBto565(0xcb,0xc8,0x74); // background
    //palette[1] = pokConvertRGBto565(0x00,0x00,0x00); // background
    gb.display.palette[8] = gb.display.RGBto565(0xff,0xfc,0); // small mob
    gb.display.palette[7] = gb.display.RGBto565(0x18,0x9a,0x61); // shrub shadow
    gb.display.palette[5] = gb.display.RGBto565(0x2c,0xff,0x0b); //world (shrubs)
    gb.display.palette[6] = gb.display.RGBto565(0xf7,0xb2,0);// crate
    gb.display.palette[9] = gb.display.RGBto565(0xfc,0x14,4);// big mob fc1404
    gb.display.palette[10] = gb.display.RGBto565(0,0x53,0xae); // blue shadow
    gb.display.palette[15] = gb.display.RGBto565(0xff,0xfd,0xbf); // bright sunlight


  //gb.begin();
  gb.setFrameRate(25);
  //gb.titleScreen(F("    Yoda's"),gamelogo);
  gb.display.setFont(font3x5);
  gb.display.fontSize=1;
  gb.pickRandomSeed();
  gamestatus="title";
  gb.battery.show=false;
}

// loop
void loop(){
  if(gb.update()){

    if (gamestatus=="newgame") { newgame(); } // new game

    if (gamestatus=="newlevel") { newlevel(); } // new level

    if (gamestatus=="newlife") { newlife(); } // new life

    if (gamestatus=="running"){ // game running

      gb.display.setColor(2);
      handleplayership(); // move and draw playership, check buttons etc.
      gb.display.setColor(3);
      handleplayershots(); // handle playershots
      gb.display.setColor(1);
      handlerocks(); // handle asterocks
      nextlevelcheck(); // level finished?
      ufoappears(); // ufo appears?
      moveufo(); // move ufo
      playershotufocollission(); // check collission playershot & ufo
      ufoshotrelease();  // ufo shot release
      moveufoshot(); // move ufoshot
      checkbonuslife(); // bonuslife?
      gb.display.setColor(6);
      showscore();  // show lives, score, level
      backgroundsound(); // make background sounds
    }

    if (gamestatus=="title") { showtitle(); } // title

    if (gamestatus=="gameover") { showgameover(); } // game over

  } // end of gb.update
 } // end of loop
const byte PROGMEM gamelogo[]=
{
  64,26,
 B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,
 B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
 B00111000,B00111101,B11110111,B11011111,B00000111,B00000111,B01110111,B00011110,
 B01111100,B01111101,B11110111,B11011111,B10001111,B10001111,B01110111,B00111110,
 B11111110,B11111101,B11110111,B11011111,B11011111,B11011111,B01110111,B01111110,
 B11111110,B11111101,B11110111,B11011111,B11011111,B11011111,B01110111,B01111110,
 B11101110,B11100000,B11100111,B00011101,B11011101,B11011100,B01110111,B01110000,
 B11101110,B11100000,B11100111,B00011101,B11011101,B11011100,B01111110,B01110000,
 B11101110,B11100000,B11100111,B10011101,B11011101,B11011100,B01111100,B01110000,
 B11111110,B11111000,B11100111,B10011111,B10011101,B11011100,B01111000,B01111100,
 B11111110,B01111100,B11100111,B10011111,B00011101,B11011100,B01111100,B00111110,
 B11111110,B00111110,B11100111,B00011111,B10011101,B11011100,B01111110,B00011111,
 B11101110,B00001110,B11100111,B00011101,B11011101,B11011100,B01110111,B00000111,
 B11101110,B00001110,B11100111,B00011101,B11011101,B11011100,B01110111,B00000111,
 B11101110,B11111110,B11100111,B11011101,B11011111,B11011111,B01110111,B01111111,
 B11101110,B11111110,B11100111,B11011101,B11011111,B11011111,B01110111,B01111111,
 B11101110,B11111100,B11100111,B11011101,B11001111,B10001111,B01110111,B01111110,
 B11101110,B11111000,B11100111,B11011101,B11000111,B00000111,B01110111,B01111100,
 B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
 B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,
 B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
 B10100110,B11000110,B01101010,B11101100,B11100110,B01101110,B01100110,B11001110,
 B10101010,B10101010,B10001010,B01001010,B10001010,B10101010,B10001010,B10101000,
 B10101010,B10101110,B11101010,B01001010,B11001010,B11101100,B10001110,B10101100,
 B01001010,B10101010,B00101010,B01001010,B10001010,B10101010,B10001010,B10101000,
 B01001110,B11001010,B11100100,B11101100,B11101110,B10101010,B11101010,B11001110,
};

const byte PROGMEM playership[20][9] = {

  {7,7, B00010000,B00010000,B00101000,B00101000,B01000100,B01111100,B00000000},
  {7,7, B00001100,B00010100,B00100100,B01000100,B01101000,B00011000,B00000000},
  {7,7, B00000110,B00011010,B01100100,B01000100,B00101000,B00011000,B00000000},
  {7,7, B00000000,B00011110,B01100010,B01000100,B00101000,B00110000,B00000000},
  {7,7, B00000000,B01100000,B01011000,B01000110,B01011000,B01100000,B00000000},
  {7,7, B00000000,B00110000,B00101000,B01000100,B01100010,B00011110,B00000000},
  {7,7, B00000000,B00011000,B00101000,B01000100,B01100100,B00011010,B00000110},
  {7,7, B00000000,B00011000,B01101000,B01000100,B00100100,B00010100,B00001100},
  {7,7, B00000000,B01111100,B01000100,B00101000,B00101000,B00010000,B00010000},
  {7,7, B00000000,B00110000,B00101100,B01000100,B01001000,B01010000,B01100000},
  {7,7, B00000000,B00110000,B00101000,B01000100,B01001100,B10110000,B11000000},
  {7,7, B00000000,B00011000,B00101000,B01000100,B10001100,B11110000,B00000000},
  {7,7, B00000000,B00001100,B00110100,B11000100,B00110100,B00001100,B00000000},
  {7,7, B00000000,B11110000,B10001100,B01000100,B00101000,B00011000,B00000000},
  {7,7, B11000000,B10110000,B01001100,B01000100,B00101000,B00110000,B00000000},
  {7,7, B01100000,B01010000,B01001000,B01000100,B00101100,B00110000,B00000000},
  {7,7, B00000000,B00100000,B00101000,B01000100,B01001100,B00111000,B00001000},
  {7,7, B00000000,B01000000,B01001100,B10000010,B00001000,B01001000,B00110000},
  {7,7, B01000000,B10000100,B00000010,B00000000,B00001000,B01001000,B00100000},
  {7,7, B10000000,B00000010,B00000000,B00000000,B00000000,B00000100,B01000000},
};

const byte PROGMEM asterocks[12][22] = {
  {10,10, B00110110,B00000000,B01001001,B00000000,B10000000,B10000000,B01000000,B01000000,B00100000,B01000000,B01000000,B01000000,B10000000,B01000000,B10000000,B10000000,B01000001,B00000000,B00111110,B00000000},
  {10,10, B00010001,B00000000,B00101010,B10000000,B01000100,B01000000,B10000000,B10000000,B10000000,B01000000,B10000000,B01000000,B10000000,B01000000,B01000000,B10000000,B00100001,B00000000,B00011110,B00000000},
  {10,10, B00011110,B00000000,B00100001,B00000000,B01000000,B10000000,B10000000,B01000000,B10000000,B01000000,B01000000,B01000000,B01000000,B01000000,B10001000,B10000000,B01010101,B00000000,B00100010,B00000000},
  {10,10, B00011111,B00000000,B00100000,B10000000,B01000000,B01000000,B10000000,B01000000,B10000000,B10000000,B10000001,B00000000,B10000000,B10000000,B01000000,B01000000,B00100100,B10000000,B00011011,B00000000},
  {10,10, B00000000,B00000000,B00000000,B00000000,B00011100,B00000000,B00100010,B00000000,B00010001,B00000000,B00100001,B00000000,B00101010,B00000000,B00010100,B00000000,B00000000,B00000000,B00000000,B00000000},
  {10,10, B00000000,B00000000,B00000000,B00000000,B00010110,B00000000,B00101001,B00000000,B00100010,B00000000,B00100001,B00000000,B00010010,B00000000,B00001100,B00000000,B00000000,B00000000,B00000000,B00000000},
  {10,10, B00000000,B00000000,B00000000,B00000000,B00001100,B00000000,B00010010,B00000000,B00100001,B00000000,B00010001,B00000000,B00100101,B00000000,B00011010,B00000000,B00000000,B00000000,B00000000,B00000000},
  {10,10, B00000000,B00000000,B00000000,B00000000,B00001100,B00000000,B00010010,B00000000,B00100001,B00000000,B00100010,B00000000,B00101001,B00000000,B00010110,B00000000,B00000000,B00000000,B00000000,B00000000},
  {10,10, B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000100,B00000000,B00001010,B00000000,B00010010,B00000000,B00001100,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000},
  {10,10, B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001000,B00000000,B00010100,B00000000,B00010010,B00000000,B00001100,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000},
  {10,10, B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001100,B00000000,B00010010,B00000000,B00001010,B00000000,B00000100,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000},
  {10,10, B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001100,B00000000,B00010010,B00000000,B00010100,B00000000,B00001000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000},
};

const byte PROGMEM ufo[2][7] = {
  {7,5, B00010000,B00101000,B11111110,B01000100,B00111000},
  {7,5, B00100000,B11011000,B01110000,B00000000,B00000000},
};

const byte PROGMEM bullet[] = { 3,3, B01000000,B11100000,B01000000, };
//----------------------------------------------------------------------------
void newgame() {
  score=0;
  lives=3;
  gamelevel=0;
  ufotype=0;
  ufoshotx=-1;
  playershiprotation=0;
  bonusscore=10000;
  gamestatus="newlevel";
}
//----------------------------------------------------------------------------
void newlevel() {
  asterocksonscreen=4+gamelevel*2;
  if (asterocksonscreen>MAXASTEROCKS) { asterocksonscreen=MAXASTEROCKS; }
  for (int i=0; i<asterocksonscreen; i++) {
    int x=random(320);
    if (x>160) { x=x+448; }
    int y=random(128);
    asterockx[i]=x;
    asterocky[i]=y;
    asterocktype[i]=random(4);
    asterockxspeed[i]=rockxadd[random(4)]/4+8;
    asterockyspeed[i]=rockyadd[random(12)]/4+8;
  }
  playershipvisible=2;
  gamestatus="newlife";
  soundspeed=40;
  soundvalue=0;
}
//----------------------------------------------------------------------------
void newlife() {
  yeahtimer=0;
  deadtimer=-1;
  playershipx=320;
  playershipy=176;
  playershipxspeed=0;
  playershipyspeed=0;
  if (playershipvisible==1) { // after dead
    playershipvisible=0;
    playershiprotation=0;
  } else { // after level done
    playershipvisible=1;
  }
  gamestatus="running";
}
//----------------------------------------------------------------------------
void showscore() {
  i=1;
  while (lives>i) {
    gb.display.drawBitmap(i*6-6,0,playership[0]);
    i++;
  }
  gb.display.cursorX=40-2*(score>9)-2*(score>99)-2*(score>999)-2*(score>9999)-2*(score>99999);
  gb.display.cursorY=0;
  gb.display.print(score);
  gb.display.cursorX=76;
  gb.display.print(gamelevel+1);
}
//----------------------------------------------------------------------------
void nextlevelcheck() {
  if (yeahtimer>0) {
    yeahtimer--;
    if (yeahtimer==0) {
      gamelevel=gamelevel+1;
      gamestatus="newlevel";
    }
  }
}
//----------------------------------------------------------------------------
void handledeath() {
  deadtimer--;
  if (deadtimer % 5 == 0) {
    playsoundfx(1,0);
  }
  // draw dead animation
  i=19 - deadtimer / 10;
  gb.display.drawBitmap(playershipx/8,playershipy/8,playership[i]);
  if (deadtimer==0) {
    deadtimer=-1;
    lives--;
    if (lives == 0) {
      gamestatus = "gameover";
    } else {
      gamestatus = "newlife";
    }
  }
}
const int soundfx[10][8] = {
  {0,36,57,1,1,1,5,6}, // 0 = sound shoot - channel 0
  {1,15,57,1,1,2,7,8}, // 1 = hit big rock / player spaceship - channel 2
  {1,20,57,1,1,2,7,8}, // 2 = hit medium rock - channel 2
  {1,25,57,1,1,2,7,8},  // 3 = hit small rock / ufo - channel 2
  {0,0,2,1,0,0,4,5}, // 4 = ufo sound - channel 3
  {0,58,0,0,0,0,7,8}, // 5 = bonus life - channel 3
  {0,0,0,0,2,1,7,3}, // 6 = background 1 - channel 1
  {0,2,0,0,2,1,7,3}, // 7 = background 2 - channel 1
  {1,12,58,0,0,0,7,2}, // 8 = thrust - channel 0
  {0,40,57,1,1,1,6,6}, // 9 = ufoshot - channel 0
};
//----------------------------------------------------------------------------
void handleplayership() {
  if (playershipvisible==1) {
    //draw playership
    if (deadtimer==-1) {
      //move playership
      playershipx=playershipx+playershipxspeed;
      playershipy=playershipy+playershipyspeed;
      //draw ship
      gb.display.drawBitmap(playershipx/8,playershipy/8,playership[playershiprotation]);
      // check buttons
      if (gb.buttons.repeat(BTN_B,0)) { // thrust
        playsoundfx(8,0);
        playershipxspeed=playershipxspeed+xadd[playershiprotation]/8;
        playershipyspeed=playershipyspeed+yadd[playershiprotation]/8;
        if (playershipxspeed>8) { playershipxspeed=8; }
        if (playershipxspeed<-8) { playershipxspeed=-8; }
        if (playershipyspeed>8) { playershipyspeed=8; }
        if (playershipyspeed<-8) { playershipyspeed=-8; }
      }
      if (gb.buttons.repeat(BTN_DOWN,0)) {  // hyperspace
        playershipx=random(592)+40;
        playershipy=random(304)+40;
        playershipxspeed=0;
        playershipyspeed=0;
      }
      if (gb.buttons.repeat(BTN_LEFT,0)) { // rotate left
        playershiprotation--;
        if (playershiprotation<0) { playershiprotation=playershiprotation+16; }
      }
      if (gb.buttons.repeat(BTN_RIGHT,0)) { // rotate right
        playershiprotation++;
        playershiprotation%=16;
      }
      if (gb.buttons.pressed(BTN_A) and playershots<4) { // release shoot
        playershotxspeed[playershots]=xadd[playershiprotation];
        playershotyspeed[playershots]=yadd[playershiprotation];
        playershotx[playershots]=playershipx+16+playershotxspeed[playershots];
        playershoty[playershots]=playershipy+16+playershotyspeed[playershots];
        playershotcounter[playershots]=0;
        playershots=playershots+1;
        playsoundfx(0,0);
      }
    } else { // death
      handledeath();
    } // end of deadtimer
    i++;
  } // end of ship visible

  // ship off screen -> appear at opposite side
  if (playershipx<-56) { playershipx=playershipx+MAXX; }
  if (playershipx>MAXX) { playershipx=playershipx-MAXX; }
  if (playershipy<-56) { playershipy=playershipy+MAXY; }
  if (playershipy>MAXY) { playershipy=playershipy-MAXY; }

  // player ship appears?
  if (playershipappear==1) { playershipvisible=1; }

  if (gb.buttons.pressed(BTN_C)) {
    gb.titleScreen(("Yoda's"),gamelogo);
    gamestatus="title";
  }
}
//----------------------------------------------------------------------------
void handleplayershots() {
  // move playershots
  i=0;
  while (i<playershots) {
    playershotx[i]=playershotx[i]+playershotxspeed[i];
    playershoty[i]=playershoty[i]+playershotyspeed[i];
    if (playershotx[i]<0) { playershotx[i]=playershotx[i]+MAXX; }
    if (playershotx[i]>MAXX) { playershotx[i]=playershotx[i]-MAXX; }
    if (playershoty[i]<0) { playershoty[i]=playershoty[i]+MAXY; }
    if (playershoty[i]>MAXY) { playershoty[i]=playershoty[i]-MAXY; }
    playershotcounter[i]=++playershotcounter[i];

    // draw playershots
    gb.display.drawBitmap(playershotx[i]/8,playershoty[i]/8,bullet);

    // remove shot if neccesary
    if (playershotcounter[i]>30) {
      playershotx[i]=playershotx[playershots-1];
      playershoty[i]=playershoty[playershots-1];
      playershotxspeed[i]=playershotxspeed[playershots-1];
      playershotyspeed[i]=playershotyspeed[playershots-1];
      playershotcounter[i]=playershotcounter[playershots-1];
      playershots=--playershots;
    }
    i=++i; // next playershot
  }
}
//----------------------------------------------------------------------------
void handlerocks() {
  // move asterocks
  playershipappear=1;
  i=0;
  while (i<asterocksonscreen) {
    x=asterockxspeed[i]-8;
    y=asterockyspeed[i]-8;
    asterockx[i]=asterockx[i]+x;
    asterocky[i]=asterocky[i]+y;
    if (asterockx[i]<-80) { asterockx[i]=MAXX; }
    if (asterockx[i]>MAXX) { asterockx[i]=-80; }
    if (asterocky[i]<-80) { asterocky[i]=MAXY; }
    if (asterocky[i]>MAXY) { asterocky[i]=-80; }

    // draw asterocks
    gb.display.drawBitmap(asterockx[i]/8,asterocky[i]/8,asterocks[asterocktype[i]]);

    // set collission offset depending on rock size
    left = 8 + 16*(asterocktype[i]>3) + 8*(asterocktype[i]>7);
    right = 72 - 16*(asterocktype[i]>3) - 8*(asterocktype[i]>7);

    // check collission with player ship
    if ((playershipx+8 < asterockx[i]+right) and (playershipx+40 > asterockx[i]+left) and (playershipy+8 < asterocky[i]+right) and (playershipy+40 > asterocky[i]+left) and playershipvisible==1 and deadtimer==-1) {
      deadtimer=40;
      destroyed=1;
    }

    // check collission with ufo
    if ((asterockx[i]+left < ufox+32+16*(ufotype==1)) and (asterockx[i]+right > ufox) and (asterocky[i]+left < ufoy+16+16*(ufotype==1)) and (asterocky[i]+right > ufoy) and ufotype != 0) {
      score=score+200+800*(ufotype==2);
      destroyed=1;
      ufotype=0;
    }

    // check collission with ufoshot
    if ((ufoshotx < asterockx[i]+right) and (ufoshotx+16 > asterockx[i]+left) and (ufoshoty < asterocky[i]+right) and (ufoshoty+16 > asterocky[i]+left) and ufoshotx>-1) {
      destroyed=1;
      ufoshotx=-1;
    }

    // check collission with playershots
    u=0;
    while (u<playershots) {
      if ((playershotx[u] < asterockx[i]+right) and (playershotx[u]+16 > asterockx[i]+left) and (playershoty[u] < asterocky[i]+right) and (playershoty[u]+16 > asterocky[i]+left) and playershotcounter[u]<50) {
        destroyed=1;
        playershotcounter[u]=50;
      }
      u++;
    }

    //split or remove rock
    if (destroyed==1) {
      soundspeed=soundspeed-2*(soundspeed>5);
      playsoundfx(1+(asterocktype[i]>3)+(asterocktype[i]>7),2);
      destroyed=0;
      score=score+20+30*(asterocktype[i]>3)+50*(asterocktype[i]>7);
      if (asterocktype[i]<8) { //big or medium rock -> split
        asterockx[asterocksonscreen]=asterockx[i]+16;
        asterocky[asterocksonscreen]=asterocky[i]+16;
        asterockx[i]=asterockx[i]+16;
        asterocky[i]=asterocky[i]+16;
        int a;
        a= 4+random(4)+4*(asterocktype[i]>=4);
        if (a>11) a=11;
        asterocktype[asterocksonscreen]=a;
        a= 3+random(4)+4*(asterocktype[i]>=4);
        if (a>11) a=11;
        asterocktype[i]=a;
        asterockxspeed[asterocksonscreen]=rockxadd[random(12)]/4+8;
        asterockyspeed[asterocksonscreen]=rockyadd[random(12)]/4+8;
        asterockxspeed[i]=rockxadd[random(12)]/2+8;
        asterockyspeed[i]=rockyadd[random(12)]/2+8;
        if (asterockxspeed[i]==asterockxspeed[asterocksonscreen] and asterockyspeed[i]==asterockyspeed[asterocksonscreen]) {
          asterockxspeed[i]=-asterockxspeed[i];
          asterockyspeed[i]=-asterockyspeed[i];
        }
        if (asterocktype[asterocksonscreen]>7 or random(2)==1) {
          asterockxspeed[asterocksonscreen]=rockxadd[random(12)]/2+8;
          asterockyspeed[asterocksonscreen]=rockyadd[random(12)]/2+8;
        }
        if (asterocktype[i]>7 or random(2)==1) {
          asterockxspeed[i]=rockxadd[random(12)]/2+8;
          asterockyspeed[i]=rockyadd[random(12)]/2+8;
        }
        asterocksonscreen=asterocksonscreen+(asterocksonscreen<32);
      } else { // small rock -> remove
        asterocksonscreen--;
        asterockx[i]=asterockx[asterocksonscreen];
        asterocky[i]=asterocky[asterocksonscreen];
        asterocktype[i]=asterocktype[asterocksonscreen];
        asterockxspeed[i]=asterockxspeed[asterocksonscreen];
        asterockyspeed[i]=asterockyspeed[asterocksonscreen];
        if (asterocksonscreen==0) { // all rocks removed?
          yeahtimer=60;
        }
      }
    }

    // check if playership can appear (no rock in inside square)
    if ((asterockx[i]+right > 184 and asterockx[i]+left < 488) and (asterocky[i]+right > 72 and asterocky[i]+left < 312)) {
      playershipappear=0;
    }
    i=++i; // next asterock
  } // end of rock handling
}
//----------------------------------------------------------------------------
void ufoappears() {
  if (asterocksonscreen<8 and score>500 and ufotype==0 and random(250)<2) {
    ufotype=1+(random(4+gamelevel)>2); // which ufo?
    ufox=-56;
    ufoxr=3;
    if (random(2)==0) {
      ufox=672;
      ufoxr=-3;
    }
    ufoy=random(320)+32;
    ufoyr=(random(3)-1)*3;
  }
}
//----------------------------------------------------------------------------
void moveufo() {
  if (ufotype != 0) {
    ufox=ufox+ufoxr;
    ufoy=ufoy+ufoyr;
    if (ufox % 5 == 0) { playsoundfx(4,3); }
    if (ufoy<-40) { ufoy=384; }
    if (ufoy>384) { ufoy=-40; }
    if (random(50)<2) { // change direction
      ufoyr=(random(3)-1)*3;
    }
    if (ufox<-56 or ufox>672) { ufotype=0; }
    gb.display.drawBitmap(ufox/8,ufoy/8,ufo[ufotype-1]);
    // check collission playership & ufo
    if ((ufox < playershipx+40) and (ufox+32+16*(ufotype==1) > playershipx+8) and (ufoy < playershipy+40) and (ufoy+16+16*(ufotype==1) > playershipy+8) and ufotype != 0 and playershipvisible==1 and deadtimer==-1) {
      ufotype=0;
      deadtimer=40;
      playsoundfx(1,2);
    }
  }
}
//----------------------------------------------------------------------------
void playershotufocollission() {
  u=0;
  while (u<playershots) {
    if ((playershotx[u] < ufox+32+16*(ufotype==1)) and (playershotx[u]+16 > ufox) and (playershoty[u] < ufoy+16+16*(ufotype==1)) and (playershoty[u]+16 > ufoy) and playershotcounter[u]<50 and ufotype != 0) {
      playsoundfx(3,0);
      score=score+200+800*(ufotype==2);
      ufotype=0;
      playershotcounter[u]=50;
    }
    u=++u;
  }
}
//----------------------------------------------------------------------------
void ufoshotrelease() {
  if (ufotype != 0 and ufoshotx == -1 and ufox>40 and ufox<608) {
    playsoundfx(9,0);
    ufoshotx=ufox+24;
    ufoshoty=ufoy+16;
    ufoshotxr=(random(3)-1)*8;
    ufoshotyr=(random(3)-1)*8;
    if (ufotype == 2) {
      ufoshotxr=-8+16*(ufox<playershipx);
      ufoshotyr=-8+16*(ufoy<playershipy);
    }
    if (ufoshotxr==0 and ufoshotyr==0) { ufoshotxr=8; }
  }
}
//----------------------------------------------------------------------------
void moveufoshot() {
  if (ufoshotx != -1) {
    ufoshotx=ufoshotx+ufoshotxr;
    ufoshoty=ufoshoty+ufoshotyr;
    gb.display.drawBitmap(ufoshotx/8,ufoshoty/8,bullet);
    if (ufoshotx<0 or ufoshotx>MAXX or ufoshoty<0 or ufoshoty>MAXY) {
      ufoshotx=-1;
    }
    // check collission ufoshot & player
    if ((ufoshotx < playershipx+40) and (ufoshotx+16 > playershipx+8) and (ufoshoty < playershipy+40) and (ufoshoty+16 > playershipy+8) and ufoshotx>-1 and playershipvisible==1 and deadtimer==-1) {
      ufoshotx=-1;
      deadtimer=40;
      playsoundfx(1,2);
    }
  }
}
//----------------------------------------------------------------------------
void checkbonuslife() {
  if (score>=bonusscore) {
    playsoundfx(5,3);
    lives=++lives;
    bonusscore=bonusscore+10000;
      }
}
//----------------------------------------------------------------------------
void backgroundsound() {
  soundcounter++;
  if (soundcounter>soundspeed) {
    soundcounter=0;
    soundvalue=++soundvalue % 2;
    playsoundfx(soundvalue+6,1);
  }
}
//----------------------------------------------------------------------------
void showgameover() {
  gb.display.setColor(0);
  gb.display.fillRect(22,16,39,9);
  gb.display.setColor(1);
  gb.display.cursorX=24;
  gb.display.cursorY=18;
  gb.display.print("GAME OVER");
  gb.display.drawRect(22,16,39,9);
  gb.display.cursorX=4;
  gb.display.cursorY=42;
  gb.display.print("PRESS B TO CONTINUE");
  if (gb.buttons.pressed(BTN_B)) {
    gamestatus="title";
    gb.sound.playOK();
  }
}
//----------------------------------------------------------------------------
void showtitle() {
  if (score > highscore) { highscore = score; }
  gb.display.cursorX=0;
  gb.display.cursorY=0;
  gb.display.print("  LAST         HIGH");
  gb.display.cursorX=14-2*(score>9)-2*(score>99)-2*(score>999);
  gb.display.cursorY=6;
  gb.display.print(score);
  gb.display.cursorX=66-2*(highscore>9)-2*(highscore>99)-2*(highscore>999);
  gb.display.cursorY=6;
  gb.display.print(highscore);
  gb.display.drawBitmap(10,13,gamelogo);
  gb.display.cursorX=0;
  gb.display.cursorY=42;
  gb.display.print(" A: PLAY     ");
  if (gb.buttons.pressed(BTN_A)) {
    gamestatus="newgame";
    gb.sound.playOK();
  }
  if (gb.buttons.pressed(BTN_C)) {
    //gb.jumpToLoader();
    //gb.titleScreen(F("Yoda's"),gamelogo);
  }
}
//----------------------------------------------------------------------------
void playsoundfx(int fxno, int channel) {
  gb.sound.command(0,soundfx[fxno][6],0,channel); // set volume
  gb.sound.command(1,soundfx[fxno][0],0,channel); // set waveform
  gb.sound.command(2,soundfx[fxno][5],-soundfx[fxno][4],channel); // set volume slide
  gb.sound.command(3,soundfx[fxno][3],soundfx[fxno][2]-58,channel); // set pitch slide
  gb.sound.playNote(soundfx[fxno][1],soundfx[fxno][7],channel); // play note
}