[Из песочницы] Создание логической игры для игровой платформы

as6q1-hlbbmoyubblbcs6hehog0.jpeg
#include 
#include 
#include 

#include "slotgag_assets.h"

#define TAG_BUTTON_LEFT    201
#define TAG_BUTTON_RIGHT   202
#define TAG_BUTTON_ROT     203
#define TAG_BUTTON_DROP    204

#define X_BUTTON_LEFT       50
#define Y_BUTTON_LEFT      222
#define X_BUTTON_RIGHT     430
#define Y_BUTTON_RIGHT     222
#define X_BUTTON_ROT       430
#define Y_BUTTON_ROT        50
#define X_BUTTON_DROP       50
#define Y_BUTTON_DROP       50

// Color definitions 
#define BLACK         0x000000
#define RED           0xFF0000 
#define GREEN         0x00FF00 
#define BLUE          0x0000FF 
#define YELLOW        0xFFFF00
#define MAGENTA       0xFF00FF 
#define CYAN          0x00FFFF
#define WHITE         0xFFFFFF 

#define DISPLAY_MAX_X      480
#define DISPLAY_MAX_Y      272

#define MaxX                 8 
#define MaxY                17
#define SmeX                 3
#define SmeY                 3
#define razmer              18
#define NumCol               6
#define MaxLevel             8
#define NextLevel           80
#define DISP_LEFT    ((DISPLAY_MAX_X - MaxX*razmer)/2 - 2)
#define DISP_RIGHT   ((DISPLAY_MAX_X + MaxX*razmer)/2 + 2)
#define DISP_TOP     ((DISPLAY_MAX_Y - (MaxY-4)*razmer)/2 - 2)
#define DISP_BOT     ((DISPLAY_MAX_Y + (MaxY-4)*razmer)/2 + 2)


uint8_t  MasSt[MaxX][MaxY], MasTmp[MaxX][MaxY], fignext[3];
uint8_t  Level=1, dx, dy, tr, flfirst=1; 
uint32_t MasCol[]={WHITE, BLACK, RED, BLUE, GREEN, YELLOW, MAGENTA, CYAN};
unsigned long Counter, Score=0, TScore=0, Record=0, myrecord;
uint16_t tempspeed = 1000;
bool fl, Demo=true, Arbeiten=false, FlZ=false;
int8_t   x,y;
int8_t   mmm [4][2]={{-1,0},{0,-1},{1,0},{0,1}};
uint16_t MasSpeed[MaxLevel]={500,450,400,350,300,250,200,100};
uint8_t  state_game = 0;
unsigned long time_count;
byte     prevkey;
uint32_t btn_color = 0xff0000;

/****************************************************************************************************************/

void  setup(void)
{
  Serial.begin(1000000);
  Serial.println("Columns");
  GD.begin();

  LOAD_ASSETS();
  GD.BitmapHandle(BACKGROUND_HANDLE);
  GD.BitmapSize(NEAREST, REPEAT, REPEAT, 480, 272);

  randomSeed(analogRead(5));
  
  myrecord = eeprom_read_byte((unsigned char *)1);
  time_count = millis() + 1000;
}

static struct {
  byte t, note;
} pacman[]  = {
  { 0, 71 },
  { 2, 83 },
  { 4, 78 },
  { 6, 75 },
  { 8, 83 },
  { 9, 78 },
  { 12, 75 },
  { 16, 72 },
  { 18, 84 },
  { 20, 79 },
  { 22, 76 },
  { 24, 84 },
  { 25, 79 },
  { 28, 76 },
  { 32, 71 },
  { 34, 83 },
  { 36, 78 },
  { 38, 75 },
  { 40, 83 },
  { 41, 78 },
  { 44, 75 },
  { 48, 75 },
  { 49, 76 },
  { 50, 77 },
  { 52, 77 },
  { 53, 78 },
  { 54, 79 },
  { 56, 79 },
  { 57, 80 },
  { 58, 81 },
  { 60, 83 },
  { 255, 255 }
};

//==================================================
void  loop(void)
{
  GD.get_inputs();
  byte    key = GD.inputs.tag;
  int8_t  VAL = 0;
  if (prevkey == 0x00) 
  {
    switch (key) {
      case TAG_BUTTON_LEFT:
        VAL = -1;
        break;

      case TAG_BUTTON_RIGHT:
        VAL = 1;
        break;

      case TAG_BUTTON_ROT:
        if (!FlZ)
        {
          GD.play(HIHAT);
          byte aa=MasSt[x][y];
          MasSt[x][y]=MasSt[x][y+2];
          MasSt[x][y+2]=MasSt[x][y+1];
          MasSt[x][y+1]=aa;
        }
        break;

      case TAG_BUTTON_DROP:
        if (Arbeiten) {
          if (!FlZ) {
            tempspeed=50;
            GD.play(NOTCH);
          }
        } else {
          GD.play(CLICK);
          Demo=false;
          NewGame();
        }
        break;
    }
  }
  prevkey = key;

  if (VAL!=0 && fig_shift(VAL) && !FlZ) {
    for (byte i=0;i<3;i++) {
      MasSt[x+VAL][y+i]=MasSt[x][y+i];
      MasSt[x][y+i]=0; 
    }
    x=x+VAL; 
  }
  ProcGame();
  ViewStacan();
  GD.swap();
}

//==================================================
// redraw one square 
void  ViewQuad(byte i,byte  j,byte mycolor)
{
  if (j<3) return; 
  uint16_t wy=DISP_TOP + SmeY+(j-3)*razmer-j;
  uint16_t wx=DISP_LEFT + SmeX+i*razmer-i;
  if (mycolor!=0) {
    GD.LineWidth(16*1);
    GD.ColorRGB(WHITE);
    GD.Begin(LINE_STRIP);
    GD.Vertex2ii(wx,wy);
    GD.Vertex2ii(wx + razmer-1,wy);
    GD.Vertex2ii(wx + razmer-1,wy + razmer-1);
    GD.Vertex2ii(wx,wy + razmer-1);
    GD.Vertex2ii(wx,wy);
    GD.Begin(RECTS);
    GD.ColorRGB(MasCol[mycolor]);
    GD.Vertex2ii(wx+1, wy+1); GD.Vertex2ii(wx+1 + razmer-2 - 1, wy+1 + razmer-2 - 1);
  } else {
  }
}

//==================================================
void  ViewStacan(void)
{
  char myStr2[5];

  // Draw background fone
  GD.Clear();
  GD.ColorMask(1, 1, 1, 0);
  GD.Begin(BITMAPS);
  GD.BitmapHandle(BACKGROUND_HANDLE);
  GD.BitmapSize(NEAREST, REPEAT, REPEAT, 480, 272);
  GD.Vertex2ii(0, 0, BACKGROUND_HANDLE);

  // Print text
  GD.ColorRGB(WHITE);
  GD.cmd_text(DISP_LEFT  - 30, DISP_TOP +   3, 27, OPT_CENTER, "LEVEL");
  GD.cmd_text(DISP_RIGHT + 30, DISP_TOP +   3, 27, OPT_CENTER, "NEXT");
  GD.cmd_text(DISP_RIGHT + 30, DISP_TOP + 100, 27, OPT_CENTER, "SCORE");
  GD.cmd_text(DISP_LEFT  - 30, DISP_TOP + 100, 27, OPT_CENTER, "TOP");

  // Print digit Score
  GD.ColorRGB(RED);
  sprintf(myStr2,"%05d",Score );
  GD.cmd_text(DISP_RIGHT + 30, DISP_TOP + 130, 27, OPT_CENTER, myStr2);
 
  // Print digit Top
  sprintf(myStr2,"%05d",myrecord );
  GD.cmd_text(DISP_LEFT  - 30, DISP_TOP + 130, 27, OPT_CENTER, myStr2);

  // Print digit Level
  sprintf(myStr2,"%02d",Level );
  GD.cmd_text(DISP_LEFT  - 30, DISP_TOP +  40, 31, OPT_CENTER, myStr2);

  // Draw color squares
  for (byte j=3;j=0 && ny>=0 && nx1 || MasTmp[i][j]>2 )) {
      MasTmp[nx][ny]=3; 
      MasTmp[i][j]=3;
    } else {
      if (mode==3 && MasTmp[nx][ny]==3) {
        if (MasTmp[i][j]!=3) {
          MasTmp[i][j]=3; 
          fl=true;
        }
      }
    }
  }
}

//==================================================
void  Sos(int i,int j, byte mode)
{
  for (byte k=0;k<4;k++)
    Sosed(i,j,mmm[k][0],mmm[k][1],mode);      
}

//==================================================
// create next figure
void  GetNext(void)
{
  x=3; y=0;
  for (byte i=0;i<3;i++) {
    if (!Demo) MasSt[x][i]=fignext[i];
    fignext[i]=random(NumCol)+2;
  }
  if (!Demo) {
    Counter++;
    if (Counter==NextLevel) {
      Counter=0; 
      Level++; 
      if (Level>MaxLevel) Level=MaxLevel;
    }
    tempspeed=MasSpeed[Level-1];
  }
}

//==================================================
// find onecolor elements
bool  FindFull(void)
{ 
  byte i,j,k; bool res; 
  res=false; 

  for (byte k=2;k<8;k++) { // by every color
    ClearMas(MasTmp);
    for (j=3;j1) Sos(i,j,2);
    do {
      fl=false;
      for (j=3;j0) Sos(i,j,3);
    } while (fl);

    for (j=3;j0 && !FlZ) {
    if (y+dy+2>MaxY-1  || MasSt[x+dx][y+dy+2]>0) {
      if (y<3) {
        gameover();
      } else {
        return true;
      }
    } else {
      if (y+dy+dy+2>MaxY-1  || MasSt[x+dx][y+dy+dy+2]>0) {
        GD.play(COWBELL);
      }
      for (byte i=0;i<3;i++) MasSt[x][y+2-i+dy]=MasSt[x][y+2-i];
      MasSt[x][y]=0;
      y=y+dy;
    }
  }
  return(false);
}

//================================================
// move figure left/right (shift)
bool  fig_shift(int dx)
{
  if (x+dx<0 || x+dx>MaxX-1) {
    GD.play(COWBELL);
    return(false);
  }
  if (dx!=0) {
    if (MasSt[x+dx][y+dy+2]==0) {
      if (x+dx+dx<0 || x+dx+dx>MaxX-1)
        GD.play(COWBELL);
      else
        GD.play(CHACK);
      return(true);
    } else {
      GD.play(COWBELL);
      return(false);
    }
  }
  return(false);
}

//==================================================
// State-machine
void  ProcGame(void)
{
  byte i,j,k; bool res = false; 

  if (time_count < millis()) {
    if (Arbeiten)
      time_count = millis() + tempspeed;
    else
      time_count = millis() + 1000;

    switch (state_game) {
      // Demo
      case 0:
        Score=0;
        GetNext();
        for (byte j=3;j0)
        {
          FlZ=true;
          time_count = millis() + 500;
        }
        state_game = 2;
        break;

      case 2:
        for (j=0;j7) Score=Score+TScore+(TScore-8)*2;
          else Score=Score+TScore;
          state_game = 1;
        } else {
          state_game = 0;
        }
        break;

      // Arbeiten
      case 3:
        if (fig_drop(1))
        {
          tempspeed=MasSpeed[Level-1];
          TScore=0;
          FindFull();
          if (TScore>0)
          {
            GD.play(KICKDRUM);
            FlZ=true;
            state_game = 4;
          } else {
            FlZ=false;
            GetNext();
          }
        }
        break;

      case 4:
        for (j=0;j7) Score=Score+TScore+(TScore-8)*2;
          else Score=Score+TScore;
          state_game = 5;
          FlZ=true;
          GD.play(CLACK);
        } else {
          state_game = 3;
          FlZ=false;
          time_count = millis() + 100;
        }
        break;

      case 5:
        state_game = 3;
        FlZ=false;
        break;

      default:
        break;
    }
  }
}

//================================================
// start new game
void  NewGame()
{
  Score      = 0;
  FlZ        = false;
  ClearMas(MasSt);
  Arbeiten   = true;
  GetNext();
  Counter    = 0;
  Level      = 1;
  tempspeed  = MasSpeed[0];
  Record     = myrecord;
  state_game = 3;
}

//================================================
// draw "GAME OVER"
void  gameover()
{
  if (Arbeiten==true) {
    GD.play(SWITCH);
    Arbeiten=false;
    if (Score>myrecord) {
      myrecord=Score;
      eeprom_write_byte((unsigned char *) 1, myrecord);
    }
  }
}

© Habrahabr.ru