Businesscard-V2/Software/Game-Test/src/main.cpp
2024-10-18 20:29:50 +02:00

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;
}