// >>>>> T-I-N-Y B-O-M-B-E-R for ATTINY85 GPL v3 <<<<
// Programmer: Daniel C 2018-2021
// Contact EMAIL: [email protected]
// https://sites.google.com/view/arduino-collection
// Tiny BOMBER is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//for TINY JOYPAD rev2 (attiny85)
//the code work at 16MHZ internal
//Program the chip with an arduino uno in "Arduino as ISP" mode.
// ...
//#include "TinyDriver.h"
#include "spritebank.h"
// Defines for OLED output
#define SSD1306XLED_H
#define SSD1306_SCL PORTB0 // SCL, Pin 4 on SSD1306 Board - for webbogles board
#define SSD1306_SDA PORTB2 // SDA, Pin 3 on SSD1306 Board - for webbogles board
#define SSD1306_SA 0x78 // Slave address
#define DIGITAL_WRITE_HIGH(PORT) PORTB |= (1 << PORT)
#define DIGITAL_WRITE_LOW(PORT) PORTB &= ~(1 << PORT)
// Routines to set and clear bits (used in the sleep code)
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
// Drawing functions - adapted from those at https://bitbucket.org/tinusaur/ssd1306xled
void ssd1306_init(void);
void ssd1306_xfer_start(void);
void ssd1306_xfer_stop(void);
void ssd1306_send_byte(uint8_t byte);
void ssd1306_send_command(uint8_t command);
void ssd1306_send_data_start(void);
void ssd1306_send_data_stop(void);
void ssd1306_setpos(uint8_t x, uint8_t y);
void ssd1306_fillscreen(uint8_t fill_Data);
void ssd1306_char_f6x8(uint8_t x, uint8_t y, const char ch[]);
void ssd1306_draw_bmp(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t bitmap[]);
void ssd1306_init(void) {
DDRB |= (1 << SSD1306_SDA); // Set port as output
DDRB |= (1 << SSD1306_SCL); // Set port as output
ssd1306_send_command(0xAE); // display off
ssd1306_send_command(0x00); // Set Memory Addressing Mode
ssd1306_send_command(0x10); // 00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
ssd1306_send_command(0x40); // Set Page Start Address for Page Addressing Mode,0-7
ssd1306_send_command(0x81); // Set COM Output Scan Direction
ssd1306_send_command(0xCF); // ---set low rowumn address
ssd1306_send_command(0xA1); // ---set high rowumn address
ssd1306_send_command(0xC8); // --set start line address
ssd1306_send_command(0xA6); // --set contrast control register
ssd1306_send_command(0xA8);
ssd1306_send_command(0x3F); // --set segment re-map 0 to 127
ssd1306_send_command(0xD3); // --set normal display
ssd1306_send_command(0x00); // --set multiplex ratio(1 to 64)
ssd1306_send_command(0xD5); //
ssd1306_send_command(0x80); // 0xa4,Output follows RAM content;0xa5,Output ignores RAM content
ssd1306_send_command(0xD9); // -set display offset
ssd1306_send_command(0xF1); // -not offset
ssd1306_send_command(0xDA); // --set display clock divide ratio/oscillator frequency
ssd1306_send_command(0x12); // --set divide ratio
ssd1306_send_command(0xDB); // --set pre-charge period
ssd1306_send_command(0x40); //
ssd1306_send_command(0x20); // --set com pins hardware configuration
ssd1306_send_command(0x02);
ssd1306_send_command(0x8D); // --set vcomh
ssd1306_send_command(0x14); // 0x20,0.77xVcc
ssd1306_send_command(0xA4); // --set DC-DC enable
ssd1306_send_command(0xA6); //
ssd1306_send_command(0xAF); // --turn on oled panel
}
void ssd1306_xfer_start(void) {
DIGITAL_WRITE_HIGH(SSD1306_SCL); // Set to HIGH
DIGITAL_WRITE_HIGH(SSD1306_SDA); // Set to HIGH
DIGITAL_WRITE_LOW(SSD1306_SDA); // Set to LOW
DIGITAL_WRITE_LOW(SSD1306_SCL); // Set to LOW
}
void ssd1306_xfer_stop(void) {
DIGITAL_WRITE_LOW(SSD1306_SCL); // Set to LOW
DIGITAL_WRITE_LOW(SSD1306_SDA); // Set to LOW
DIGITAL_WRITE_HIGH(SSD1306_SCL); // Set to HIGH
DIGITAL_WRITE_HIGH(SSD1306_SDA); // Set to HIGH
}
void ssd1306_send_byte(uint8_t byte) {
uint8_t i;
for (i = 0; i < 8; i++)
{
if ((byte << i) & 0x80)
DIGITAL_WRITE_HIGH(SSD1306_SDA);
else
DIGITAL_WRITE_LOW(SSD1306_SDA);
DIGITAL_WRITE_HIGH(SSD1306_SCL);
DIGITAL_WRITE_LOW(SSD1306_SCL);
}
DIGITAL_WRITE_HIGH(SSD1306_SDA);
DIGITAL_WRITE_HIGH(SSD1306_SCL);
DIGITAL_WRITE_LOW(SSD1306_SCL);
}
void ssd1306_send_command(uint8_t command) {
ssd1306_xfer_start();
ssd1306_send_byte(SSD1306_SA); // Slave address, SA0=0
ssd1306_send_byte(0x00); // write command
ssd1306_send_byte(command);
ssd1306_xfer_stop();
}
void ssd1306_send_data_start(void) {
ssd1306_xfer_start();
ssd1306_send_byte(SSD1306_SA);
ssd1306_send_byte(0x40); //write data
}
void ssd1306_send_data_stop(void) {
ssd1306_xfer_stop();
}
void ssd1306_setpos(uint8_t x, uint8_t y)
{
if (y > 7) return;
ssd1306_xfer_start();
ssd1306_send_byte(SSD1306_SA); //Slave address,SA0=0
ssd1306_send_byte(0x00); //write command
ssd1306_send_byte(0xb0 + y);
ssd1306_send_byte(((x & 0xf0) >> 4) | 0x10); // |0x10
ssd1306_send_byte((x & 0x0f) | 0x01); // |0x01
ssd1306_xfer_stop();
}
void ssd1306_fillscreen(uint8_t fill_Data) {
uint8_t m, n;
for (m = 0; m < 8; m++)
{
ssd1306_send_command(0xb0 + m); //page0-page1
ssd1306_send_command(0x00); //low rowumn start address
ssd1306_send_command(0x10); //high rowumn start address
ssd1306_send_data_start();
for (n = 0; n < 128; n++)
{
ssd1306_send_byte(fill_Data);
}
ssd1306_send_data_stop();
}
}
/*
void ssd1306_char_f6x8(uint8_t x, uint8_t y, const char ch[]) {
uint8_t c, i, j = 0;
while (ch[j] != '\0')
{
c = ch[j] - 32;
if (c > 0) c = c - 12;
if (c > 15) c = c - 6;
if (c > 40) c = c - 9;
if (x > 126)
{
x = 0;
y++;
}
ssd1306_setpos(x, y);
ssd1306_send_data_start();
for (i = 0; i < 6; i++)
{
ssd1306_send_byte(pgm_read_byte(&ssd1306xled_font6x8[c * 6 + i]));
}
ssd1306_send_data_stop();
x += 6;
j++;
}
}
*/
void TinyOLED_init(){
ssd1306_init();
ssd1306_fillscreen(0x00);
TinyOLED_Data_Start(0,6);
TinyOLED_Send(0x89);
}
void TinyOLED_Data_Start(uint8_t X, uint8_t Y){
ssd1306_setpos(X,Y);
}
void TinyOLED_Send(uint8_t byte_) {
ssd1306_send_data_start();
ssd1306_send_byte(byte_);
ssd1306_send_data_stop();
}
void TinyOLED_End() {
}
// var public
uint8_t SPEEDBOMBER=0;
int8_t BOMBXY[4]={-10,-10,0,0};
uint8_t live;
uint8_t INGAME;
int8_t Level;
uint8_t Frame;
uint8_t BlocBombMem[14];
// fin var public
void LoadLevel(uint8_t LeveL){
for (uint8_t t=0;t<14;t++){
BlocBombMem[t]=pgm_read_byte(&level[t+(LeveL*14)]);
}}
void ResetVar(PERSONAGE * Sprite){
live=3;
Level=-1;
INGAME=0;
SPEEDBOMBER=0;
resetMonster(Sprite);
}
void resetMonster(PERSONAGE *Sprite){
Sprite[1].dead=0;
Sprite[2].dead=0;
Sprite[3].dead=0;
Sprite[4].dead=0;
}
void resetBomb(void){
BOMBXY[0]=-10;
BOMBXY[1]=-10;
BOMBXY[2]=0;
BOMBXY[3]=0;
}
void setup() {
// DDRB = 0b00000010; // set PB1 as output (for the speaker)
// PCMSK = 0b00000001; // pin change mask: listen to portb bit 1
// GIMSK |= 0b00100000; // enable PCINT interrupt
// sei(); // enable all interrupts
TinyOLED_init();
pinMode(1,INPUT);
pinMode(A0,INPUT);
pinMode(A3,INPUT);
DDRB =DDRB|0b00010000;
INGAME=1;
}
void StartGame(void){
if (INGAME==0) {
while(1){if (digitalRead(1)==1){break;}}
_delay_ms(40);
INGAME=1;}
}
void loop() {
// for (int y = 0; y < 8; y++){
// // TinyOLED_Data_Start(0,y);
// for (int x = 0; x < 128; x++){
// TinyOLED_Data_Start(x,y);
// TinyOLED_Send(0x76);
// }
// }
ssd1306_init();
PERSONAGE Sprite[5];
// ResetVar(&Sprite[0]);
// Tiny_Flip(0,&Sprite[0]);
NEWGAME:
ResetVar(&Sprite[0]);
while(1){
Tiny_Flip(1,&Sprite[0]);
if (digitalRead(1)==0) {StartGame();break;}
}
NEWLEVEL:
if (Level<2) {
if (Level>-1) {
{for(uint8_t t=0;t<=4;t++){Sound(80,100);delay(300);}}
}
Level++;
}else{
{for(uint8_t t=0;t<=4;t++){Sound(80,100);delay(300);}}
SPEEDBOMBER=1;Level=0;}
resetMonster(Sprite);
LoadLevel(Level);
RESTARTLEVEL:
resetBomb();
Sprite[0].type=0;
Sprite[0].x=9;
Sprite[0].y=7;
Sprite[0].Decalagey=0;
Sprite[0].DirectionV=2;
Sprite[0].DirectionH=2;
Sprite[0].DirectionAnim=0;
Sprite[0].dead=0;
Sprite[1].type=1;
Sprite[1].x=56;
Sprite[1].y=1;
Sprite[1].Decalagey=0;
Sprite[2].type=1;
Sprite[2].x=120;
Sprite[2].y=2;
Sprite[2].Decalagey=0;
Sprite[3].type=1;
Sprite[3].x=119;
Sprite[3].y=7;
Sprite[3].Decalagey=0;
Sprite[4].type=1;
Sprite[4].x=24;
Sprite[4].y=5;
Sprite[4].Decalagey=0;
INGAME:
while(1){
if (digitalRead(1)==0) {StartGame();}
if (INGAME) {
if ((analogRead(A0)>=750)&&(analogRead(A0)<950)){Sprite[0].DirectionV=0;}
else if ((analogRead(A0)>500)&&(analogRead(A0)<750)) {Sprite[0].DirectionV=1;}else{if (((Sprite[0].x)%8)==0) Sprite[0].DirectionV=2;}
if ((analogRead(A3)>=750)&&(analogRead(A3)<950)) {Sprite[0].DirectionH=1;}
else if ((analogRead(A3)>500)&&(analogRead(A3)<750)) {Sprite[0].DirectionH=0;}else{if (Sprite[0].Decalagey==0) Sprite[0].DirectionH=2;}
if ((digitalRead(1)==0)&&(BOMBXY[2]==0)) {
BOMBXY[0]=(uint8_t((Sprite[0].x+3)/8))*8;
BOMBXY[1]=(uint8_t(((Sprite[0].y*8)+(Sprite[0].Decalagey)+3)/8));
BOMBXY[2]=5;
{uint8_t t;for(t=155;t<255;t++){Sound(2+t,2);Sound(25+t,1);}}
}}
if (Frame<24) {Frame++;}else{Frame=0;}
if (CollisionTiny2Caracter(&Sprite[0])==0) {
RefreshCaracter(&Sprite[0]);}
else{
DeadSong();
if (live>0) {live--;goto RESTARTLEVEL;}else{
delay(200);
{for(uint8_t t=0;t<5;t++){Sound (100,100);Sound (1,100);}}
goto NEWGAME;}}
if ((Frame==0)||(Frame==8)||(Frame==16)) {
if (BOMBXY[2]>1) {
if (BOMBXY[3]<2) {BOMBXY[3]++;}else{BOMBXY[3]=0;BOMBXY[2]--;}
}}
if (Frame%4==0) {
if (BOMBXY[2]==1) {
if (BOMBXY[3]<2) {
if (BOMBXY[3]==1) {DestroyEnemy(&Sprite[0]);DestroyBloc();}
BOMBXY[3]++;
}else{
resetBomb();
{for(uint8_t t=210;t<255;t++){Sound(2+t,1);Sound(255-t,2);}
}}}}
if (Frame%2==0) {
Tiny_Flip(0,&Sprite[0]);
if (INGAME==1){INGAME=2;
{for (uint8_t t=0;t<=42;t=t+2){Sound(pgm_read_byte(&Music[t]),pgm_read_byte(&Music[t+1]));}
delay(500);
}}}
if (Sprite[0].dead==1) {if (live>0) {DeadSong();live--;goto RESTARTLEVEL;}else{DeadSong();
delay(200);
{for(uint8_t t=0;t<5;t++){Sound (100,100);Sound (1,100);}}
goto NEWGAME;}}
if (Frame==12) {
if (CheckLevelEnded(&Sprite[0])==1) goto NEWLEVEL;
}}}
////////////////////////////////// main end /////////////////////////////////
uint8_t CheckLevelEnded(PERSONAGE *Sprite){
for (uint8_t t=1;t<=4;t++){
if (Sprite[t].dead==0) {return 0;}
}return 1;}
void DeadSong(void){
for (uint8_t t=1;t<255;t++){
Sound(t,1);
Sound(255-t,2);
}delay(300);}
void DestroyBloc(void){
uint8_t x=((BOMBXY[0]-8)/8);
uint8_t y=(BOMBXY[1]-1);
if (y!=0) BOOLWRITE0(x+((y-1)*15));
BOOLWRITE0(x+((y)*15));
if (y!=6) BOOLWRITE0(x+((y+1)*15));
if (x!=0) BOOLWRITE0((x-1)+((y)*15));
if (x!=14) BOOLWRITE0((x+1)+((y)*15));
}
void DestroyEnemy(PERSONAGE *Sprite){
#define xminf(I) (Sprite[I].x)
#define yminf(I) ((Sprite[I].y*8)+Sprite[I].Decalagey)
for (uint8_t t=0;t<=4;t++){
if (COLLISION11(xminf(t),yminf(t),7,7,BOMBXY[0]+1,(BOMBXY[1]*8)-6,6,21)) {
Sprite[t].y=0;
Sprite[t].Decalagey=0;
if (Sprite[t].dead!=1) {Sprite[t].dead=1;}}}
for (uint8_t t=0;t<=4;t++){
if (COLLISION11(xminf(t),yminf(t),7,7,BOMBXY[0]-6,(BOMBXY[1]*8)+1,21,6)) {
Sprite[t].y=0;
Sprite[t].Decalagey=0;
if (Sprite[t].dead!=1) {Sprite[t].dead=1;}
}}}
uint8_t COLLISION11(uint8_t x1,uint8_t y1,uint8_t w1,uint8_t h1,uint8_t x2,uint8_t y2,uint8_t w2,uint8_t h2){
if ((x1+w1<x2)||(y1+h1<y2)||(x1>x2+w2)||(y1>y2+h2)) {return 0;}else{return 1;}
}
uint8_t CollisionTiny2Caracter(PERSONAGE *Sprite){
uint8_t ReturnCollision=0;
#define xmax(I) (Sprite[I].x+6)
#define xmin(I) (Sprite[I].x)
#define ymax(I) ((Sprite[I].y*8)+Sprite[I].Decalagey+6)
#define ymin(I) ((Sprite[I].y*8)+Sprite[I].Decalagey)
if ((INGAME)) {
for (uint8_t t=1;t<=4;t++){
if (Sprite[t].dead!=1) {
if ((xmax(0)<xmin(t))||(xmin(0)>xmax(t))||(ymax(0)<ymin(t))||(ymin(0)>ymax(t))) {}else{
ReturnCollision=1;
}}
}}return ReturnCollision;}
void RefreshCaracter(PERSONAGE *Sprite){
uint8_t memx,memy,memdecalagey;
for (uint8_t t=0;t<=4;t++){
if (((t!=0)&&(SPEEDBOMBER==1))||(Frame%2==0)){
memx=Sprite[t].x;
memy=Sprite[t].y;
memdecalagey=Sprite[t].Decalagey;
if (Sprite[t].DirectionV==1) {Sprite[t].x++;}
if (Sprite[t].DirectionV==0) {Sprite[t].x--;}
if (CheckCollisionWithBack(t,1,Sprite)) {
if (t!=0) {Sprite[t].DirectionV=random()%2;}else{ Sprite[t].DirectionV=2;}
Sprite[t].x=memx;}
if (Sprite[t].DirectionH==1) {if (Sprite[t].Decalagey<7) {Sprite[t].Decalagey++;}else{Sprite[t].Decalagey=0;Sprite[t].y++;}}
if (Sprite[t].DirectionH==0) {if (Sprite[t].Decalagey>0) {Sprite[t].Decalagey--;}else{Sprite[t].Decalagey=7;Sprite[t].y--;}}
if (CheckCollisionWithBack(t,0,Sprite)) {
if (t!=0) {Sprite[t].DirectionH=random()%2;}else{Sprite[t].DirectionH=2;}
Sprite[t].y=memy;
Sprite[t].Decalagey=memdecalagey;}
if (t==0) {
if (Frame%2==0) {
if (Sprite[t].DirectionH==1) {Sprite[t].DirectionAnim=0;}
if (Sprite[t].DirectionH==0) {Sprite[t].DirectionAnim=(2*3);}
if (Sprite[t].DirectionV==1) {Sprite[t].DirectionAnim=(3*3);}
if (Sprite[t].DirectionV==0) {Sprite[t].DirectionAnim=(1*3);}
}}else{
if ((Frame==0)||(Frame==12)) {
Sprite[t].DirectionAnim=0;
if (Sprite[t].DirectionH==1) {Sprite[t].DirectionAnim=0;}
if (Sprite[t].DirectionH==0) {Sprite[t].DirectionAnim=0;}
}}
if (t==0) {
if (Frame%2==0) {
if (Sprite[0].switchanim==0) {
if ((Sprite[0].anim<2)&&((Sprite[t].DirectionH!=2)||(Sprite[t].DirectionV!=2))) {Sprite[0].anim++;}else{Sprite[0].switchanim=1;}
}else{
if (Sprite[0].anim>0) {Sprite[0].anim--;}else{Sprite[0].switchanim=0;}
}}}else{
if (Frame%6==0) {
if (Sprite[t].anim<2) {Sprite[t].anim++;}else{Sprite[t].anim=0;}
}}}}}
uint8_t CheckCollisionWithBack(uint8_t SpriteCheck,uint8_t HorVcheck,PERSONAGE *Sprite){
uint8_t BacktoComp;
if (HorVcheck==1) {
BacktoComp=RecupeBacktoCompV(SpriteCheck,Sprite);
}else{
BacktoComp=RecupeBacktoCompH(SpriteCheck,Sprite);}
BacktoComp=BacktoComp+CheckCollisionWithBlock(SpriteCheck,Sprite);
BacktoComp=BacktoComp+CheckCollisionWithBomb(SpriteCheck,Sprite);
if ((BacktoComp)!=0) {return 1;}else{return 0;}}
uint8_t CheckCollisionWithBomb(uint8_t SpriteCheck,PERSONAGE *Sprite){
if (SpriteCheck==0) {return 0;}
return COLLISION11(Sprite[SpriteCheck].x,(Sprite[SpriteCheck].y*8)+Sprite[SpriteCheck].Decalagey,7,7,BOMBXY[0],(BOMBXY[1]*8),7,7);
}
uint8_t CheckCollisionWithBlock(uint8_t SpriteCheck,PERSONAGE *Sprite){
#define A (Sprite[SpriteCheck].x)
#define AA ((A+7))
uint8_t B=((((Sprite[SpriteCheck].y-1)*8)+Sprite[SpriteCheck].Decalagey)/8);
uint8_t BB=(((((Sprite[SpriteCheck].y-1)*8)+Sprite[SpriteCheck].Decalagey)+7)/8);
uint8_t Rest=0;
uint8_t ReadBloc=pgm_read_byte(&BlocDetect[A]);
if ((ReadBloc!=0xff)&&(ReadBloc!=0xfE)) {
Rest=Rest+BOOLREAD(ReadBloc+(B*15));
Rest=Rest+BOOLREAD(ReadBloc+(BB*15));
}
ReadBloc=pgm_read_byte(&BlocDetect[AA]);
if ((ReadBloc!=0xff)&&(ReadBloc!=0xfE)) {
Rest=Rest+BOOLREAD(ReadBloc+(B*15));
Rest=Rest+BOOLREAD(ReadBloc+(BB*15));
}return Rest;}
uint8_t RecupeBacktoCompV(uint8_t SpriteCheck,PERSONAGE *Sprite){
uint8_t Y1=0b00000000;
uint8_t Y2=Y1;
#define SpriteWide 6
#define MAXV (Sprite[SpriteCheck].x+SpriteWide)
#define MINV (Sprite[SpriteCheck].x)
if (Sprite[SpriteCheck].DirectionV==1) {
Y1=pgm_read_byte(&back[((Sprite[SpriteCheck].y)*128)+(MAXV)]);
Y2=pgm_read_byte(&back[((Sprite[SpriteCheck].y+1)*128)+(MAXV)]);
}else if (Sprite[SpriteCheck].DirectionV==0) {
Y1=pgm_read_byte(&back[((Sprite[SpriteCheck].y)*128)+(MINV)]);
Y2=pgm_read_byte(&back[((Sprite[SpriteCheck].y+1)*128)+(MINV)]);
}else{Y1=0;Y2=0;}
//decortique
Y1=Trim(0,Y1,Sprite[SpriteCheck].Decalagey);
Y2=Trim(1,Y2,Sprite[SpriteCheck].Decalagey);
if (((Y1)!=0b00000000)||((Y2)!=0b00000000) ) {return 1;}else{return 0;}
}
uint8_t Trim(uint8_t Y1orY2,uint8_t TrimValue,uint8_t Decalage){
uint8_t Comp;
if (Y1orY2==0) {
Comp=0b01111111<<Decalage;
return (TrimValue&Comp);
}else{
Comp=(0b01111111>>(8-Decalage));
return (TrimValue&Comp);
}}
uint8_t ScanHRecupe(uint8_t UporDown,uint8_t Decalage){
if (UporDown==0){
return 0b01111111<<Decalage;}
else{
return 0b01111111>>(8-Decalage);
}}
uint8_t RecupeBacktoCompH(uint8_t SpriteCheck,PERSONAGE *Sprite){
uint8_t TempPGMByte;
if (Sprite[SpriteCheck].DirectionH==0) {
uint8_t RECUPE=(ScanHRecupe(0,Sprite[SpriteCheck].Decalagey));
for(uint8_t t=0;t<=6;t++){
if ((((Sprite[SpriteCheck].y)*128)+(Sprite[SpriteCheck].x+t)>1023)||(((Sprite[SpriteCheck].y)*128)+(Sprite[SpriteCheck].x+t)<0)) {TempPGMByte=0x00;}else{
TempPGMByte=(pgm_read_byte(&back[((Sprite[SpriteCheck].y)*128)+(Sprite[SpriteCheck].x+t)]));
}
#define CHECKCOLLISION ((RECUPE)&(TempPGMByte))
if (CHECKCOLLISION!=0) {return 1;}
}}else if (Sprite[SpriteCheck].DirectionH==1) {
uint8_t tadd=0;
if (Sprite[SpriteCheck].Decalagey>2) { tadd=1;}else{tadd=0;}
uint8_t RECUPE=(ScanHRecupe(tadd,Sprite[SpriteCheck].Decalagey));
for(uint8_t t=0;t<=6;t++){
if (((((Sprite[SpriteCheck].y+tadd)*128)+(Sprite[SpriteCheck].x+t))>1023)||((((Sprite[SpriteCheck].y+tadd)*128)+(Sprite[SpriteCheck].x+t))<0)) {TempPGMByte=0x00;}else{
TempPGMByte=pgm_read_byte(&back[((Sprite[SpriteCheck].y+tadd)*128)+(Sprite[SpriteCheck].x+t)]);
}
#define CHECKCOLLISION2 ((RECUPE)&(TempPGMByte))
if (CHECKCOLLISION2!=0) {return 1;}
}}return 0;}
void Tiny_Flip(uint8_t render0_picture1,PERSONAGE *Sprite){
uint8_t y,x;
uint8_t Div2x=0;
for (y = 0; y < 8; y++){
TinyOLED_Data_Start(-1,y);
for (x = 0; x < 128; x++){
if (render0_picture1==0) {
if (INGAME) {TinyOLED_Send(PrintLive(x,y)&((background(x,y)|SpriteWrite(x,y,Sprite)|BlockBomb(x,y,Div2x)|BombBlitz(x,y)|Explose(x,y))));}else{
}}else if (render0_picture1==1){
TinyOLED_Send((pgm_read_byte(&BackBlitz[x+(y*128)])));}Div2x=!Div2x;}
TinyOLED_End();
}}
uint8_t PrintLive(uint8_t x,uint8_t y){
uint8_t rest=0xFF;
if ((x>7)||(x<1)) return 0xFF;
switch (live){
case 0:if (y==6) rest=0x00;
case 1:if (y==5) rest=0x00;
case 2:if (y==4) rest=0x00;
case 3:
default:break;
}return rest;}
uint8_t Explose(uint8_t x,uint8_t y){
#define XPOSFIRE (BOMBXY[0]-8)
#define YPOSFIRE (BOMBXY[1]-1)
if (BOMBXY[2]==1) {
if ((x>7)&&(y>0)){
if ((x>=XPOSFIRE)&&(x<XPOSFIRE+24)&&(y>=YPOSFIRE)&&(y<=YPOSFIRE+2)) {
return pgm_read_byte(&fire[((x-(XPOSFIRE))+((y-(YPOSFIRE))*72))+(BOMBXY[3]*24)]);
}}}return 0x00;}
uint8_t BombBlitz(uint8_t x,uint8_t y){
if ((x>=BOMBXY[0])&&(x<=BOMBXY[0]+7)&&(y==BOMBXY[1])) {
return pgm_read_byte(&bomb[(x-BOMBXY[0])+(BOMBXY[3]*8)]);
}else{return 0x00;}
}
uint8_t BlockBomb(uint8_t x,uint8_t y,uint8_t Divx){
if ((y>0)){
uint8_t BLOCVAL=pgm_read_byte(&BlocDetect[x]);
if (BLOCVAL==0xFE) BLOCVAL=0x01;
if (BLOCVAL==0xFF) return 0x00;
if (BOOLREAD(BLOCVAL+((y-1)*15))){
if (Divx==0) {
return 0b10101010;
}else{
return 0b01010101;}
}}return 0x00;}
void BOOLWRITE0(uint8_t BoolNumber){
uint8_t REST=BoolNumber;
uint8_t DOTBOOLPOSITION=0;
uint8_t SOUSTRAIRE;
DECREASE:
if (REST>=8) {REST=REST-8;DOTBOOLPOSITION=DOTBOOLPOSITION+1;goto DECREASE;}
switch(REST){
case (0):SOUSTRAIRE=0b01111111;break;
case (1):SOUSTRAIRE=0b10111111;break;
case (2):SOUSTRAIRE=0b11011111;break;
case (3):SOUSTRAIRE=0b11101111;break;
case (4):SOUSTRAIRE=0b11110111;break;
case (5):SOUSTRAIRE=0b11111011;break;
case (6):SOUSTRAIRE=0b11111101;break;
case (7):SOUSTRAIRE=0b11111110;break;
}
BlocBombMem[DOTBOOLPOSITION]=BlocBombMem[DOTBOOLPOSITION]&SOUSTRAIRE;
}
uint8_t BOOLREAD(uint8_t Numero){
if (Numero>105) return 0;
uint8_t BYTECHECK=Numero;
uint8_t INT8CHOSE=0;
while(BYTECHECK>7){
BYTECHECK=BYTECHECK-8;
INT8CHOSE++;}
uint8_t Var0=0;
switch (BYTECHECK){
case 0:Var0=0b10000000;break;
case 1:Var0=0b01000000;break;
case 2:Var0=0b00100000;break;
case 3:Var0=0b00010000;break;
case 4:Var0=0b00001000;break;
case 5:Var0=0b00000100;break;
case 6:Var0=0b00000010;break;
case 7:Var0=0b00000001;break;
default:Var0=0b00000000;break;}
if ((BlocBombMem[INT8CHOSE]&Var0)!=0) {return 1;}else{return 0;}
}
uint8_t SplitSpriteDecalageY(uint8_t decalage,uint8_t Input,uint8_t UPorDOWN){
if (UPorDOWN) {
return Input<<decalage;
}else{
return Input>>(8-decalage);
}}
uint8_t SpriteWrite(uint8_t x,uint8_t y,PERSONAGE *Sprite){
uint8_t var1=0;
uint8_t AddBin=0b00000000;
while(1){
if (Sprite[var1].y==y) {
if (Sprite[var1].dead!=1) AddBin=AddBin|SplitSpriteDecalageY(Sprite[var1].Decalagey,return_if_sprite_present(x,Sprite,var1),1);
}else if (((Sprite[var1].y+1)==y)&&(Sprite[var1].Decalagey!=0)) {
if (Sprite[var1].dead!=1) AddBin=AddBin|SplitSpriteDecalageY(Sprite[var1].Decalagey,return_if_sprite_present(x,Sprite,var1),0);
}var1++;
if (var1==5) {break;}
}return AddBin;}
uint8_t return_if_sprite_present(uint8_t x,PERSONAGE *Sprite,uint8_t SpriteNumber){
if ((x>=Sprite[SpriteNumber].x)&&(x<(Sprite[SpriteNumber].x+8))) {
if ((INGAME==0)&&(SpriteNumber==0)) { return 0;}
return pgm_read_byte(&caracters[((x-Sprite[SpriteNumber].x)+(8*(Sprite[SpriteNumber].type*12)))+(Sprite[SpriteNumber].anim*8)+(Sprite[SpriteNumber].DirectionAnim*8)]);
}return 0;}
uint8_t background(uint8_t x,uint8_t y){
return pgm_read_byte(&BackBlitz[((y)*128)+((x))]);
}
void Sound(uint8_t freq,uint8_t dur){
for (uint8_t t=0;t<dur;t++){
if (freq!=0) PORTB =PORTB|0b00010000;
for (uint8_t t=0;t<(255-freq);t++){
_delay_us(1);}
PORTB =PORTB&0b11101111;
for (uint8_t t=0;t<(255-freq);t++){
_delay_us(1); }}}