479 lines
8.4 KiB
C++
479 lines
8.4 KiB
C++
#include <Arduino.h>
|
|
#include <utility>
|
|
#include "pins.h"
|
|
#include "bitmap.h"
|
|
#include "CDisplay.h"
|
|
#define MAX_ENEMIES 6
|
|
// #define BEQUIET
|
|
|
|
// #define F_CPU 16000000UL //Taktfrequenz 16 MHz
|
|
struct s_enemy
|
|
{
|
|
uint8_t luck = 0;
|
|
uint8_t x = 16;
|
|
uint16_t y = 1;
|
|
bool is_alive = false;
|
|
};
|
|
|
|
bool wall[12];
|
|
|
|
s_enemy enemies[MAX_ENEMIES];
|
|
|
|
uint16_t ud_adc = 0;
|
|
uint16_t lr_adc = 0;
|
|
uint32_t move_cooldown = 0;
|
|
bool ba = false;
|
|
bool bb = false;
|
|
bool ll = false;
|
|
int encount = 0;
|
|
bool nuke = true;
|
|
uint16_t killcounter = 0;
|
|
|
|
uint8_t ship_pos = 1;
|
|
uint8_t ship_anim = 0;
|
|
|
|
uint16_t score = 0;
|
|
|
|
CDisplay disp;
|
|
|
|
uint32_t millis(void)
|
|
{
|
|
return SysTick->CNT;
|
|
}
|
|
|
|
void initGame()
|
|
{
|
|
ud_adc = 0;
|
|
lr_adc = 0;
|
|
move_cooldown = 0;
|
|
ba = false;
|
|
bb = false;
|
|
ll = true;
|
|
encount = 0;
|
|
nuke = true;
|
|
killcounter = 0;
|
|
|
|
ship_pos = 1;
|
|
ship_anim = 0;
|
|
|
|
score = 0;
|
|
|
|
for(int i = 0; i < MAX_ENEMIES; i++)
|
|
{
|
|
enemies[i].is_alive = false;
|
|
}
|
|
|
|
enemies[0].is_alive = true;
|
|
enemies[0].x = 13;
|
|
enemies[0].y = 7;
|
|
enemies[0].luck = 20;
|
|
|
|
|
|
}
|
|
|
|
void USSR()
|
|
{
|
|
disp.beep(100, 15);
|
|
disp.beep(300, 10);
|
|
disp.beep(100, 15);
|
|
disp.beep(100, 13);
|
|
disp.beep(300, 11);
|
|
disp.beep(70, 19);
|
|
delay(10);
|
|
disp.beep(70, 19);
|
|
disp.beep(200,13);
|
|
disp.beep(100, 15);
|
|
disp.beep(100, 18);
|
|
disp.beep(200, 15);
|
|
disp.beep(70, 25);
|
|
delay(10);
|
|
disp.beep(70, 25);
|
|
disp.beep(185,23);
|
|
delay(10);
|
|
disp.beep(70,23);
|
|
disp.beep(70,20);
|
|
disp.beep(185,18);
|
|
delay(10);
|
|
disp.beep(70,18);
|
|
disp.beep(100, 15);
|
|
disp.beep(200, 13);
|
|
disp.beep(140, 11);
|
|
disp.beep(125, 10);
|
|
disp.beep(300, 8);
|
|
}
|
|
|
|
void displayButtonPresses()
|
|
{
|
|
// switch(row)
|
|
// {
|
|
// case 2:
|
|
// // display[row] |= ud_adc;
|
|
// break;
|
|
// case 3:
|
|
// if(ud_adc > 2200) display[row] |= 1<<10;
|
|
// break;
|
|
// case 4:
|
|
// if(ud_adc > 2200) display[row] |= 1<<10;
|
|
// break;
|
|
// case 5:
|
|
// if(ba) display[row] |= 1<<3;
|
|
// //Links
|
|
// if(lr_adc > 2200) display[row] |= 0b11 << 11;
|
|
// //Rechts
|
|
// if(lr_adc < 2000) display[row] |= 0b11 << 8;
|
|
// break;
|
|
// case 6:
|
|
// if(ud_adc < 2000) display[row] |= 1<<10;
|
|
// break;
|
|
|
|
// case 7:
|
|
// if(ud_adc < 2000) display[row] |= 1<<10;
|
|
// break;
|
|
|
|
// case 8:
|
|
// if(bb) display[row] |= 1<<6;
|
|
// break;
|
|
|
|
// case 10:
|
|
// // display[row] |= lr_adc;
|
|
// break;
|
|
// default:
|
|
// return;
|
|
// }
|
|
if(ud_adc > 2200)
|
|
{
|
|
disp.setPixelAt(10, 3, true);
|
|
disp.setPixelAt(10, 4, true);
|
|
}
|
|
|
|
if(ud_adc < 2000)
|
|
{
|
|
disp.setPixelAt(10, 6, true);
|
|
disp.setPixelAt(10, 7, true);
|
|
}
|
|
|
|
if(lr_adc > 2200)
|
|
{
|
|
disp.setPixelAt(11, 5, true);
|
|
disp.setPixelAt(12, 5, true);
|
|
}
|
|
|
|
if(lr_adc < 2000)
|
|
{
|
|
disp.setPixelAt(8, 5, true);
|
|
disp.setPixelAt(9, 5, true);
|
|
}
|
|
|
|
if(bb) disp.setPixelAt(6, 8, true);
|
|
if(ba) disp.setPixelAt(3, 5, true);
|
|
}
|
|
|
|
void readButtonPresses()
|
|
{
|
|
ba = digitalRead(BUT_A);
|
|
bb = digitalRead(BUT_B);
|
|
|
|
ud_adc = analogRead(ADC_UD);
|
|
lr_adc = analogRead(ADC_LR);
|
|
|
|
if(!ba) ll = false;
|
|
}
|
|
|
|
int get2Pow(uint8_t pow)
|
|
{
|
|
if(pow==0) return 1;
|
|
int cpow = 2;
|
|
for(int i = 1; i<pow; i++)
|
|
{
|
|
cpow = cpow * 2;
|
|
}
|
|
return cpow;
|
|
}
|
|
|
|
uint8_t checkCollision(int x)
|
|
{
|
|
for(uint8_t i = 0; i<MAX_ENEMIES; i++)
|
|
{
|
|
if(enemies[i].y == ship_pos)
|
|
{
|
|
if(enemies[i].is_alive)
|
|
{
|
|
if(abs(enemies[i].x - x) <= 2) return i;
|
|
}
|
|
}
|
|
}
|
|
return 255;
|
|
}
|
|
|
|
void explodeEnemy(uint8_t idx)
|
|
{
|
|
//Graphics
|
|
for(int i=0; i<7; i++)
|
|
{
|
|
disp.invertScreen();
|
|
disp.beep(24, rand()%21, 16, true);
|
|
}
|
|
//Code
|
|
enemies[idx].is_alive = false;
|
|
}
|
|
|
|
void fireLaser(uint8_t pos = 1)
|
|
{
|
|
if(ll) return;
|
|
//Spawn Laser and move it
|
|
uint16_t ship = disp.getRowAt(ship_pos);
|
|
uint16_t line = 0b0;
|
|
uint8_t coll;
|
|
|
|
for(int i=0; i<10; i++)
|
|
{
|
|
line = ship;
|
|
if(i < 5) line = line | (((get2Pow(2*i)-1)<<6)&0xFFFF);
|
|
else line = line | (0xFFFF << (2*i-4))&0xFFFF;
|
|
disp.setRow(pos, line);
|
|
disp.beep(12, i);
|
|
coll = checkCollision(6+i);
|
|
if(coll != 255)
|
|
{
|
|
//Enemy hit!
|
|
killcounter++;
|
|
if(killcounter >= 255) killcounter = 0;
|
|
if(killcounter > 20) nuke = true;
|
|
explodeEnemy(coll);
|
|
score +=3;
|
|
ll = true;
|
|
// return;
|
|
}
|
|
// disp.drawScreen();
|
|
}
|
|
|
|
ll = true;
|
|
}
|
|
|
|
void drawScr(int animCounter = 0);
|
|
void nukeEnemies()
|
|
{
|
|
if(!nuke) return;
|
|
for(int i = 0; i < MAX_ENEMIES; i++)
|
|
{
|
|
if(enemies[i].is_alive)
|
|
{
|
|
nuke = false;
|
|
drawScr();
|
|
disp.drawScreen(1);
|
|
explodeEnemy(i);
|
|
disp.drawScreen(1);
|
|
score += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
void moveShip()
|
|
{
|
|
if(millis() - move_cooldown > 100)
|
|
{
|
|
move_cooldown = millis();
|
|
//UP
|
|
if(ud_adc > 2200)
|
|
{
|
|
if(ship_pos >= 2)
|
|
{
|
|
ship_pos--;
|
|
}
|
|
}
|
|
|
|
if(ud_adc < 2000)
|
|
{
|
|
if(ship_pos < 11)
|
|
{
|
|
ship_pos++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void endGame();
|
|
void moveEnemies()
|
|
{
|
|
for(int i=0; i<MAX_ENEMIES; i++)
|
|
{
|
|
if(enemies[i].is_alive)
|
|
{
|
|
if(rand() % enemies[i].luck == 0)
|
|
{
|
|
if(enemies[i].x == 2 && enemies[i].y == (ship_pos - 1))
|
|
{
|
|
explodeEnemy(i);
|
|
endGame();
|
|
}
|
|
|
|
if(enemies[i].x >= 2 && enemies[i].x <=4 && enemies[i].y == ship_pos)
|
|
{
|
|
explodeEnemy(i);
|
|
endGame();
|
|
}
|
|
if(enemies[i].x == 0)
|
|
{
|
|
if(wall[enemies[i].y] == false)
|
|
{
|
|
wall[enemies[i].y] = true;
|
|
explodeEnemy(i);
|
|
}
|
|
else
|
|
{
|
|
explodeEnemy(i);
|
|
endGame();
|
|
}
|
|
}
|
|
else enemies[i].x--;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void drawScr(int animCounter = 0)
|
|
{
|
|
disp.clearScreen();
|
|
//Draw ship
|
|
disp.setPixelAt(2, ship_pos - 1, true);
|
|
disp.setPixelAt(2, ship_pos, true);
|
|
disp.setPixelAt(3, ship_pos, true);
|
|
disp.setPixelAt(4, ship_pos, true);
|
|
disp.setPixelAt(1, ship_pos, animCounter & 0b1);
|
|
disp.setPixelAt(0, ship_pos, animCounter > 2?1:0);
|
|
|
|
for(int i = 0; i < MAX_ENEMIES; i++)
|
|
{
|
|
if(enemies[i].is_alive) disp.setPixelAt(enemies[i].x, enemies[i].y, true);
|
|
}
|
|
|
|
if(rand() % 4 == 0)
|
|
{
|
|
for(int i = 0; i<12; i++)
|
|
{
|
|
if(!wall[i]) disp.setPixelAt(0, i, true);
|
|
}
|
|
}
|
|
|
|
disp.setPixelAt(15, 0, nuke);
|
|
}
|
|
|
|
void spawnEnemy()
|
|
{
|
|
for(int i = 0; i<MAX_ENEMIES; i++)
|
|
{
|
|
if(enemies[i].is_alive == false)
|
|
{
|
|
enemies[i].x = 15;
|
|
enemies[i].y = (rand() % 11) + 1;
|
|
enemies[i].luck = (rand() % 69) + 3;
|
|
enemies[i].is_alive = true;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void drawScore()
|
|
{
|
|
disp.flipScreen(false);
|
|
|
|
int potenz = 1;
|
|
uint16_t score_rows[6];
|
|
for(int i=0; i<5; i++) score_rows[i] = 0x0000;
|
|
//Display points
|
|
for (int tenners = 0; tenners < 3; tenners++)
|
|
{
|
|
for(int mul=0; mul<tenners; mul++) potenz = potenz * 10;
|
|
int sco = (score / potenz) % 10;
|
|
|
|
for(int i = 0; i < 6; i++)
|
|
{
|
|
score_rows[i] |= fnt_score[sco][i] << (5*tenners);
|
|
}
|
|
}
|
|
|
|
for(int i=0; i<6; i++)
|
|
{
|
|
disp.setRow(6+i, score_rows[i]);
|
|
}
|
|
disp.setRow(0, 0b1111011110111101);
|
|
disp.setRow(1, 0b1000010000100100);
|
|
disp.setRow(2, 0b1111010000111100);
|
|
disp.setRow(3, 0b0001010000110000);
|
|
disp.setRow(4, 0b1111011110101101);
|
|
disp.setRow(5, 0b0);
|
|
}
|
|
|
|
void endGame()
|
|
{
|
|
disp.flipScreen(false);
|
|
for(int i = 0; i<12; i++)
|
|
{
|
|
disp.setRow(i, gameover[i]);
|
|
}
|
|
drawScore();
|
|
bool draw_score = false;
|
|
|
|
while(!ba)
|
|
{
|
|
if(draw_score)
|
|
{
|
|
drawScore();
|
|
}
|
|
else
|
|
{
|
|
for(int i = 0; i<12; i++)
|
|
{
|
|
disp.setRow(i, gameover[i]);
|
|
}
|
|
}
|
|
readButtonPresses();
|
|
disp.drawScreen(1);
|
|
if(millis() - move_cooldown > 2000)
|
|
{
|
|
move_cooldown = millis();
|
|
draw_score = !draw_score;
|
|
}
|
|
}
|
|
|
|
initGame();
|
|
disp.flipScreen(true);
|
|
}
|
|
|
|
|
|
void setup() {
|
|
// USSR();
|
|
disp.initDisplay();
|
|
for(int i=0; i<12; i++) disp.setRow(i, bitmap[i]);
|
|
disp.beep(100, 15);
|
|
|
|
while(!ba)
|
|
{
|
|
ll = true;
|
|
readButtonPresses();
|
|
disp.drawScreen(1);
|
|
}
|
|
|
|
initGame();
|
|
|
|
disp.flipScreen(true);
|
|
}
|
|
|
|
void loop() {
|
|
// // put your main code here, to run repeatedly
|
|
// for(int i=0; i<12; i++) disp.setRow(i, buttons[i]);
|
|
readButtonPresses();
|
|
if(ba) fireLaser(ship_pos);
|
|
if(bb) nukeEnemies();
|
|
moveShip();
|
|
drawScr(ship_anim);
|
|
moveEnemies();
|
|
disp.drawScreen(1);
|
|
// disp.beep(12, rand()%13, 16, true);
|
|
if((millis() - move_cooldown) > 77) ship_anim++;
|
|
if(ship_anim >= 4) ship_anim = 0;
|
|
if(rand() % 48 == 0) spawnEnemy();
|
|
|
|
//Score cap
|
|
if(score > 999) score = 999;
|
|
} |