I2C OLED s řadičem SSD1306

Uživatelský avatar
kiRRow
Příspěvky: 1152
Registrován: 07 kvě 2019, 07:03
Reputation: 0
Bydliště: Opava

Re: I2C OLED s řadičem SSD1306

Příspěvek od kiRRow » 03 čer 2022, 15:17

Ta dvojtečka co se tam vypálila, tak blikala - třeba to má vliv. Zahrej si na něm tetris :lol:
Obrázek : https://ctrlv.cz/ulsl
Potřebuješ: rotační enkodér, a nějaké knihovny. Nebo si ten program uprav na tlačítka. Zapojení se dá okoukat z obrázku.
Víceméně jsem si jen hrál, v kódu můžou být chyby, nesmysly, bugy

Kód: Vybrat vše

#include <ClickEncoder.h>
#include <TimerOne.h>
#include <U8glib.h>

U8GLIB_SSD1306_128X32 u8g(U8G_I2C_OPT_NONE);

#define bW 4
#define bH 4
#define ROW 23
#define COL 10
#define bOffX 1
#define bOffY 33
#define nextX 4
#define nextY 4
#define bP 3

#define DOWN_SCORE 1+1*lvl

int board[ROW][COL];


boolean isStarted = 0;
//long int lastTick = 0;
unsigned long int gameTime = 0;

unsigned long int score = 0;
unsigned int lines = 0;
int lvl = 0;

int gameSpeed = 1000;
boolean gameOver = 1;

//unsigned int IBlock[4] = {0x4444,0x0F00,0x2222,0x00F0};
unsigned int IBlock[4] = {0x4444,0x0F00,0x4444,0x0F00};
unsigned int JBlock[4] = {0x2260,0x4700,0x3220,0x0710};
unsigned int LBlock[4] = {0x4460,0x0E80,0xC440,0x2E00};
unsigned int OBlock[4] = {0x6600,0x6600,0x6600,0x6600};
unsigned int SBlock[4] = {0x6C00,0x4620,0x06C0,0x8C40};
unsigned int TBlock[4] = {0x0270,0x4640,0x7200,0x1310};
unsigned int ZBlock[4] = {0xC600,0x2640,0x0C60,0x4C80};

unsigned int nextBlock;
unsigned int activeBlock[4];
int nbR;
int nbID;

int abID;
int abX;
int abY;
int abR;

byte mID;
bool mActive;

ClickEncoder *encoder;
int16_t last, value;

void timerIsr() {
  encoder->service();
}

void setup(void) {
  u8g.setRot90();
  encoder = new ClickEncoder(3, 4, 5, 4);
  Timer1.initialize(1000);
  Timer1.attachInterrupt(timerIsr);
  encoder->setAccelerationEnabled(false);
  last = 0;
  
  abX = 0;
  abY = 0;
  abR = 0;
  //lastTick = millis();
  isStarted = 0;
  gameOver = 1;
  gameSpeed = 1200;

  mID = 0;
  mActive = 0;
  
  randomSeed(analogRead(A0));
  
  delay(500);
}

void loop(void) {
  //if (millis()-lastTick > 15) {
  value += encoder->getValue();

  if (value != last) {
    if(value > last) {
      if(gameOver == 0){
        moveRight();
      }else{
        if(!mActive){
          mID = (mID + 1) % 3;
        }else{
          if(lvl < 9 && mID == 1){lvl++;}
        }
      }
    }else{
      if(gameOver == 0){
        moveLeft();
      }else{
        if(!mActive){
          if(mID == 0){mID = 2;}else{mID = (mID - 1) % 3;}
        }else{
          if(lvl > 0 && mID == 1){lvl--;}
        }
      }
    }
    last = value;
  }
  
  ClickEncoder::Button b = encoder->getButton();
  if (b != ClickEncoder::Open) {
    
    switch (b) {
      //VERBOSECASE(ClickEncoder::Pressed);
      //VERBOSECASE(ClickEncoder::Held)
      //VERBOSECASE(ClickEncoder::Released)
      //VERBOSECASE(ClickEncoder::Clicked)
      case ClickEncoder::Clicked:
        if(gameOver == 0){
          moveRotate();
        }else{
          menuOpen();
          //isStarted = 1;
          //gameOver = 0;
        }
        break;
      case ClickEncoder::Held:
        if(gameOver == 0){
          moveDown();
          score += DOWN_SCORE;
          moveDown();
          score += DOWN_SCORE;
        }
        break;
      case ClickEncoder::DoubleClicked:
          lvl++;
        break;
    }
  }
    u8g.firstPage();
    do {
      draw();
    } while( u8g.nextPage() );
    //lastTick = millis();
  //}

  if(!gameOver){
  if (millis()-gameTime > (gameSpeed-lvl*100)) {
    moveDown();
    gameTime = millis();
  }
  }

    if(isStarted && gameOver == 0){
      //gameOver = 0;
      score = 0;
      lines = 0;
      isStarted = 0;
      prepareNext();
      createBlock();
    }

}

void menuOpen(){
  if(mID == 0){
    isStarted = 1;
    gameOver = 0;
  }else{
    mActive = !mActive;
  }
}

void drawMenu(){
  if(!mActive || mID == 1){
    u8g.setFont(u8g_font_5x7);
    u8g.setPrintPos(4, 42);
    u8g.print(F("Start"));
    u8g.setPrintPos(4, 52);
    u8g.print(F("Level"));
    u8g.setPrintPos(4, 62);
    u8g.print(F("Score"));
  
    u8g.drawLine(2,42+mID*10,28,42+mID*10);
    if(mActive){
      u8g.drawLine(2,42-8+mID*10,28,42-8+mID*10);
      u8g.drawLine(2,42-7+mID*10,2,42+mID*10);
      u8g.drawLine(28,42-7+mID*10,28,42+mID*10);
    }
  }
}

void drawGUI(void){
  u8g.drawFrame(2, 2, 16, 16);
  u8g.drawFrame(0, 32, COL*bP+2, ROW*bP+2);
  //u8g.drawFrame(0, 0, 32, 100);
  u8g.setFont(u8g_font_7x14);//lvl
  u8g.setPrintPos(22, 15);
  u8g.print(lvl);
  drawScore();
}

void drawScore(){
  u8g.setFont(u8g_font_5x7);//score
  u8g.setPrintPos(1, 28);
  u8g.print(score);  
}

void drawBlock(int x, int y){
  u8g.drawFrame(x ,y , bP, bP);  
}

void drawNextBlock(void){
  int b = 15;
  for(int s=0;s < bW; s++){
    for(int r=0;r < bH; r++){
      if(!bitRead(nextBlock, b)){ b--;continue;}        
        drawBlock(r*bP+nextX, s*bP+nextY);
        b--;
    }
  }
}

void drawBoard(){
  for(int y=0;y < ROW; y++){
    for(int x=0;x < COL; x++){
      if(!board[y][x]){continue;}      
      drawBlock(x*bP+bOffX, y*bP+bOffY);
    }
  }
}

void drawActiveBlock(){
int b = 15;
  for(int s=0;s < bW; s++){
    for(int r=0;r < bH; r++){
      if(!bitRead(activeBlock[abR], b)){ b--;continue;}        
        drawBlock(r*bP+bOffX+abX*bP, s*bP+bOffY+abY*bP);
        b--;
    }
  }  
}

void prepareNext(){
  nbID = random(6);
  nbR = random(3);

  switch(nbID){
    case 0:
      nextBlock = IBlock[nbR];
      break;
    case 1:
      nextBlock = JBlock[nbR];
      break;
    case 2:
      nextBlock = LBlock[nbR];
      break;
    case 3:
      nextBlock = OBlock[nbR];
      break;
    case 4:
      nextBlock = SBlock[nbR];
      break;
    case 5:
      nextBlock = TBlock[nbR];
      break;
    case 6:
      nextBlock = ZBlock[nbR];
      break;
  } 
}

void createBlock(){
abX = 3;
abY = 0;
abR = nbR;
abID = nbID;
  switch(abID){
    case 0:
      for(int i=0; i < 4;i++){activeBlock[i] = IBlock[i];}
      break;
    case 1:
      for(int i=0; i < 4;i++){activeBlock[i] = JBlock[i];}
      break;
    case 2:
      for(int i=0; i < 4;i++){activeBlock[i] = LBlock[i];}
      break;
    case 3:
      for(int i=0; i < 4;i++){activeBlock[i] = OBlock[i];}
      break;
    case 4:
      for(int i=0; i < 4;i++){activeBlock[i] = SBlock[i];}
      break;
    case 5:
      for(int i=0; i < 4;i++){activeBlock[i] = TBlock[i];}
      break;
    case 6:
      for(int i=0; i < 4;i++){activeBlock[i] = ZBlock[i];}
      break;
  }
  
prepareNext();
}

void moveRight(){
  if(notColision(abX+1,abY,abR)){
    abX++;
  }
}

void moveLeft(){
  if(notColision(abX-1,abY,abR)){
  abX--;
  }
}

void moveDown(){
  if(notColision(abX,abY+1,abR)){
  abY++;
  }else{
  lockBlock();
  }
}

void moveRotate(){
  byte kOff = 1;
  if(notColision(abX,abY,(abR + 1) % 4)){
  abR = (abR + 1) % 4;
  }else{
    if(abX <= 0){
      if(notColision(abX+1,abY,(abR + 1) % 4)){
        abX++;
        abR = (abR + 1) % 4;      
      }
    }
    if(abX >= 7){
      if(abID == 0 && abX == 8){kOff = 2;}
      if(notColision(abX-kOff,abY,(abR + 1) % 4)){
        abX -= kOff;
        abR = (abR + 1) % 4;
      }
    }
  }
}

void lockBlock(){
  int b = 15;
  int fullRowCounter = 0;
  for(int s=0;s < bW; s++){
    for(int r=0;r < bH; r++){
      if(!bitRead(activeBlock[abR], b)){ b--;continue;}
      
      board[abY+s][abX+r] = 1;

      b--;
      if(abY == 0){
        gameOver = 1;
      }
    }
  }
  if(!gameOver){
    for(int y=0;y < ROW; y++){
      boolean isRowFull = true;
      
      for(int x=0;x < COL; x++){
        isRowFull = isRowFull && board[y][x];
      }

      if(isRowFull){
        for(int r = y;r > 1; r--){
          for(int s = 0; s < COL; s++){
            board[r][s] = board[r-1][s];
          }
        }
      score += 10 + (10*fullRowCounter);      
      fullRowCounter++;
      }
    }
    
    createBlock();
  } else {
    eraseGame();
  }
}

boolean notColision(int newX, int newY, int newR){
boolean nocolide = true;  
int b = 15;
  for(int s=0;s < bW; s++){
    for(int r=0;r < bH; r++){
      if(!bitRead(activeBlock[newR], b)){b--; continue;}
      
      if((newX+r >= COL)||(newX+r < 0)){nocolide=false;}
      if(newY+s >= ROW){nocolide=false;}
      if(board[newY+s][newX+r]){nocolide=false;}

      b--;
    }
  }

return nocolide;  
}

void eraseGame(){
  for(int y=0;y < ROW; y++){
  for(int x=0;x < COL; x++){
    board[y][x] = 0;
  }
  }
  gameOver = 1;
  isStarted = 0;
}

void draw(void) {
  /*if(!isStarted){
    drawActiveBlock();    
  }*/
  drawGUI();
  drawScore();
  
  if(gameOver) {
    drawMenu();    
  }else{
    drawActiveBlock();
    drawNextBlock();
    drawBoard();
  }
}

Odpovědět

Kdo je online

Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 12 hostů