久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

標題: 51單片機+LCD12864俄羅斯方塊游戲程序+PCB+Proteus仿真 [打印本頁]

作者: zck4188    時間: 2019-7-4 16:43
標題: 51單片機+LCD12864俄羅斯方塊游戲程序+PCB+Proteus仿真
Altium Designer畫的基于51單片機的俄羅斯方塊電路原理圖和PCB圖如下:(51hei附件中可下載工程文件)


仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)


                                               俄羅斯方塊元件清單        
元件編號    參數    數量
R11    10K電阻    1
C2    10uF電解電容    1
Y1    12M晶振    1
C1, C3    30pf瓷片電容    2
VR1    103滑動變阻器    1
P4    4針插針    1
LCD1    LCD12864液晶    1
U1    STC89C51單片機    1
K1, K2, K3, K4, K5, K6    大按鍵    6
K7    小輕觸按鍵    1
J1    電源接口    1
SW1    自鎖開關    1

單片機源程序如下:
  1. #include <REGX52.H>
  2. #include"pic.c"
  3. #include <intrins.h>
  4. #define LCD_DATA P2
  5. #define button_delay 150  //按鍵延時
  6. #define button_acceleration 65  //按鍵加速度閾值
  7. #define GAME_LOCATION 30
  8. sbit button_a = P3^4;         //變形
  9. sbit button_b = P3^5;        //開始
  10. sbit up = P3^2;           //暫停開始
  11. sbit down = P3^0;
  12. sbit left = P3^1;
  13. sbit right = P3^3;
  14. sbit speaker=P3^6;

  15. sbit LCD_RS=P1^0;
  16. sbit LCD_RW=P1^1;
  17. sbit LCD_E=P1^2;
  18. sbit LCD_CS2=P1^4;                //右屏選擇(左右屏有時候相反)
  19. sbit LCD_CS1=P1^3;                //左屏選擇
  20. sbit LCD_RST=P3^7;

  21. unsigned int up_reg=button_delay;       //按鍵up累加器
  22. unsigned int down_reg=button_delay;     //按鍵down累加器
  23. unsigned int left_reg=button_delay;     //按鍵left累加器
  24. unsigned int right_reg=button_delay;    //按鍵right累加器
  25. unsigned int button_a_reg=button_delay; //按鍵button_a累加器
  26. unsigned int button_b_reg=button_delay; //按鍵button_b累加器
  27. unsigned int right_acceleration=0;                //按鍵right加速度寄存器
  28. unsigned int left_acceleration=0;                //按鍵left加速度寄存器

  29. unsigned int idata Box_Ram[19];//定義游戲點陣緩存10*16
  30. unsigned char box_down_reg;//定義方塊下落累加寄存器
  31. unsigned char time0_reg;//定義定時器0累加寄存器
  32. unsigned char next_mode;//定義下一個方塊的類型
  33. unsigned char next_shape;//定義下一個方塊的形狀
  34. unsigned int destroy_row_num=0;//定義所消的行數
  35. unsigned char speed_num=0;//定義游戲速度等級
  36. unsigned char level_num;//定義游戲難度等級
  37. bit game_over_flag;//游戲結束標志位置0表示游戲未結束
  38. bit pause_game_flag;//游戲暫停標志位置0表示游戲未暫停

  39. struct
  40. {
  41.         unsigned char mode;//類型
  42.         unsigned char shape;//形狀
  43.         unsigned char x;//x坐標
  44.         unsigned char y;//y坐標
  45.         unsigned int box;//定義方塊緩存
  46. }s_box;        //定義方塊結構體
  47. //LCD檢測忙狀態函數
  48. void LCD_check_busy()
  49. {
  50.         unsigned char temp;
  51.         LCD_RS=0;
  52.         LCD_RW=1;
  53.         do
  54.         {
  55.                 LCD_DATA=0xff;
  56.                 LCD_E=1;
  57.                 temp=LCD_DATA;
  58.                 LCD_E=0;
  59.         }while((temp&0x80)==0x80);               
  60. }
  61. //寫指令代碼(cs為0選左屏,cs為1選右屏)
  62. void LCD_W_code(unsigned char tpcode,bit cs)
  63. {
  64.         LCD_RS=0;
  65.         LCD_RW=0;
  66.         LCD_CS2=~cs;
  67.         LCD_CS1=cs;
  68.         LCD_DATA=tpcode;
  69.         LCD_E=1;
  70.         _nop_();
  71.         LCD_E=0;
  72. }
  73. //寫顯示數據(cs為0選左屏,cs為1選右屏)
  74. void LCD_W_data(unsigned char tpdata,bit cs)
  75. {
  76.         LCD_check_busy();
  77.         LCD_RS=1;
  78.         LCD_RW=0;
  79.         LCD_CS2=~cs;
  80.         LCD_CS1=cs;       
  81.         LCD_DATA=tpdata;
  82.         LCD_E=1;       
  83.         _nop_();
  84.         LCD_E=0;
  85. }

  86. //LCD初始化函數
  87. void LCD_initialize()
  88. {
  89.         LCD_RST=0;
  90.         _nop_();
  91.         _nop_();
  92.         LCD_RST=1;
  93.         LCD_W_code(0x3f,0);                //開顯示設置       
  94.         LCD_W_code(0xc0,0);                //設置顯示起始行為第一行       
  95.         LCD_W_code(0xb8,0);                //頁面地址設置       
  96.         LCD_W_code(0x40,0);                //列地址設為0
  97.         LCD_W_code(0x3f,1);
  98.         LCD_W_code(0xc0,1);       
  99.         LCD_W_code(0xb8,1);
  100.         LCD_W_code(0x40,1);
  101. }
  102. //LCD清屏函數
  103. void LCD_clear()
  104. {
  105.         unsigned char i,j;
  106.         for(j=0;j<8;j++)
  107.         {
  108.                 LCD_W_code(0xb8+j,0);
  109.                 LCD_W_code(0x40,0);
  110.                 LCD_W_code(0xb8+j,1);
  111.                 LCD_W_code(0x40,1);
  112.                 for(i=0;i<64;i++)
  113.                         {       
  114.                                 LCD_W_data(0x00,0);       
  115.                                 LCD_W_data(0x00,1);
  116.                         }
  117.         }
  118. }
  119. //LCD顯示字符串函數(word表示要顯示的字符串,
  120. //length表示要顯示的字符串寬度,
  121. //x表示首字符所在行數,
  122. //y表示首字符所在列數)
  123. void LCD_display_word(unsigned char word[],
  124.                       unsigned int length,
  125.                                           unsigned char x,
  126.                                           unsigned char y)
  127. {
  128.         unsigned char i;
  129.         for(i=0;i<length;i++)
  130.         {
  131.                
  132.                 LCD_W_code(0xb8+x,0);
  133.                 LCD_W_code(0xb8+x,1);
  134.                 if(y+i<64)
  135.                 {
  136.                         LCD_W_code(0x40+y+i,0);       
  137.                         LCD_W_data(word[i],0);
  138.                 }
  139.                 else
  140.                 {
  141.                         LCD_W_code(y+i,1);       
  142.                         LCD_W_data(word[i],1);
  143.                 }
  144.         }
  145. }
  146. //LCD畫全屏函數
  147. void LCD_full_draw(unsigned char word[])
  148. {
  149.         unsigned char i,j;
  150.         for(i=0;i<8;i++)
  151.         {
  152.                 LCD_W_code(0xb8+i,0);
  153.                 LCD_W_code(0x40,0);       
  154.                 for(j=0;j<64;j++)
  155.                 {
  156.                         LCD_W_data(word[i*128+j],0);
  157.                 }
  158.                 LCD_W_code(0xb8+i,1);
  159.                 LCD_W_code(0x40,1);       
  160.                 for(j=0;j<64;j++)
  161.                 {
  162.                         LCD_W_data(word[i*128+64+j],1);
  163.                 }                       
  164.         }
  165. }
  166. //LCD顯示一個字節函數(
  167.   //x表示x坐標,
  168.   //y表示y坐標,
  169.   //tpdata表示要顯示的數據)
  170. void LCD_display_byte(unsigned char x,
  171.                                           unsigned char y,
  172.                                           unsigned char tpdata)
  173. {
  174.         if(x<64)
  175.         {
  176.                 LCD_W_code(0xb8+y,0);
  177.                 LCD_W_code(0x40+x,0);
  178.                 LCD_W_data(tpdata,0);       
  179.         }
  180.         else
  181.         {
  182.                 LCD_W_code(0xb8+y,1);
  183.                 LCD_W_code(x,1);
  184.                 LCD_W_data(tpdata,1);       
  185.         }
  186. }

  187. void LCD_draw(unsigned char word[])
  188. {
  189.   unsigned char i,j;
  190.   for(i=0;i<8;i++)
  191.   {
  192.     LCD_W_code(0xb8+i,1);
  193.         LCD_W_code(0x40+20,1);
  194.         for(j=0;j<44;j++)
  195.         {
  196.           LCD_W_data(word[i*44+j],1);
  197.         }
  198.   }
  199. }
  200. //基本界面顯示函數
  201. void display_basic()
  202. {
  203.         unsigned char i;
  204.         for(i=0;i<8;i++)
  205.         {
  206.                 LCD_display_byte(GAME_LOCATION,i,0xff);
  207.                 LCD_display_byte(GAME_LOCATION+41,i,0xff);
  208.         }
  209. }
  210. //刷新游戲區域函數
  211. void refurbish_display()
  212. {
  213.         unsigned char i,j,tpdata;
  214.         for(i=0;i<8;i++)
  215.         {
  216.                 for(j=0;j<10;j++)
  217.                 {
  218.                         tpdata=0x00;
  219.                         if(  (Box_Ram[2*i]>>(12-j))&0x0001==1  )
  220.                         {
  221.                                 tpdata=0x0f;
  222.                         }
  223.                         if(  (Box_Ram[2*i+1]>>(12-j))&0x0001==1  )
  224.                         {
  225.                                 tpdata|=0xf0;
  226.                         }
  227.                         LCD_display_byte(GAME_LOCATION+1+j*4,i,tpdata);
  228.                         LCD_display_byte(GAME_LOCATION+2+j*4,i,0xbb&tpdata);
  229.                         LCD_display_byte(GAME_LOCATION+3+j*4,i,0xdd&tpdata);
  230.                         LCD_display_byte(GAME_LOCATION+4+j*4,i,tpdata);
  231.                 }
  232.         }
  233. }
  234. //基本按鍵程序(返回0表示沒按鍵被按下,返回1表示down被按下,返回2表示up被按下,返回3表示button_a被按下,返回4表示left被按下,返回5表示right被按下)
  235. //游戲中按鍵識別程序(有優先級,從高到低依次是button_a_reg>down>left>right>up)
  236. unsigned char basic_button()
  237. {
  238.         unsigned char tpflag=0;
  239.         if(button_b==0)
  240.         {
  241.             if(button_b_reg<button_delay*8)
  242.                 {
  243.                   button_b_reg++;
  244.                 }
  245.                 else
  246.                 {
  247.                   button_b_reg=0;
  248.                   tpflag=6;
  249.                 }
  250.         }
  251.         else
  252.         {
  253.                 button_b_reg=button_delay*8;
  254.         }
  255.         if(down==0)
  256.         {
  257.                 if(down_reg<button_delay)//按鍵一直被按下時設置時間間隔觸發
  258.                 {
  259.                         down_reg++;
  260.                 }
  261.                 else
  262.                 {
  263.                         down_reg=0;
  264.                         tpflag=1;//返回1表示down被按下
  265.                 }               
  266.         }
  267.         else
  268.         {
  269.                 down_reg=button_delay;//釋放按鍵時置按鍵緩存為button_delay,以便在下次按鍵時及時響應
  270.         }
  271.         if(up==0)
  272.         {
  273.                 if(up_reg<button_delay)//按鍵一直被按下時設置時間間隔觸發
  274.                 {
  275.                         up_reg++;
  276.                 }
  277.                 else
  278.                 {
  279.                         up_reg=0;
  280.                         tpflag=2;//返回2表示up被按下
  281.                 }               
  282.         }
  283.         else
  284.         {
  285.                 up_reg=button_delay;//釋放按鍵時置按鍵緩存為button_delay,以便在下次按鍵時及時響應
  286.         }
  287.         if(button_a==0)
  288.         {
  289.                 if(button_a_reg<button_delay*8)//按鍵一直被按下時設置時間間隔觸發
  290.                 {
  291.                         button_a_reg++;
  292.                 }
  293.                 else
  294.                 {
  295.                         button_a_reg=0;
  296.                         tpflag=3;//返回3表示button_a被按下
  297.                 }               
  298.         }
  299.         else
  300.         {
  301.                 button_a_reg=button_delay*8;//釋放按鍵時置按鍵緩存為button_delay,以便在下次按鍵時及時響應
  302.         }
  303.         if(left==0)
  304.         {
  305.                 if(left_reg<(button_delay))//按鍵一直被按下時設置時間間隔觸發
  306.                 {
  307.                         left_reg++;
  308.                 }
  309.                 else
  310.                 {
  311.                         left_reg=left_acceleration*button_acceleration;
  312.                         if(left_acceleration<2)left_acceleration++;
  313.                         tpflag=4;//返回4表示left被按下
  314.                 }               
  315.         }
  316.         else
  317.         {
  318.                 left_acceleration=0;
  319.                 left_reg=button_delay;//釋放按鍵時置按鍵緩存為button_delay,以便在下次按鍵時及時響應
  320.         }
  321.         if(right==0)
  322.         {
  323.                 if(right_reg<(button_delay))//按鍵一直被按下時設置時間間隔觸發
  324.                 {
  325.                         right_reg++;
  326.                 }
  327.                 else
  328.                 {
  329.                         right_reg=right_acceleration*button_acceleration;
  330.                         if(right_acceleration<2)right_acceleration++;
  331.                         tpflag=5;//返回5表示right被按下
  332.                 }               
  333.         }
  334.         else
  335.         {
  336.                 right_acceleration=0;
  337.                 right_reg=button_delay;//釋放按鍵時置按鍵緩存為button_delay,以便在下次按鍵時及時響應
  338.         }
  339.         return(tpflag);
  340. }
  341. //檢查覆蓋函數(檢查此時帶入的參數所確定的方塊是否會覆蓋原有圖形,不會覆蓋返回1,覆蓋返回0)
  342. bit check_cover(unsigned char tpx,unsigned char tpy,unsigned int tpbox)
  343. {
  344.         unsigned char i;
  345.         bit tpflag=1;
  346.         unsigned int temp;
  347.         temp=s_box.box;
  348.         for(i=0;i<4;i++)
  349.         {
  350.                 Box_Ram[3-i+s_box.y]&=(~((temp&0x000f)<<(9-s_box.x)));
  351.                 temp=temp>>4;
  352.         }//先將現有的方塊從游戲點陣緩存中刪除
  353.         temp=tpbox;
  354.         for(i=0;i<4;i++)
  355.         {
  356.                 if((((temp&0x000f)<<(9-tpx))&Box_Ram[3-i+tpy])!=0x0000)
  357.                 {
  358.                         tpflag=0;
  359.                 }
  360.                 temp=temp>>4;
  361.         }//檢查方塊是否和原有圖形重疊,重疊置標志位tpflag為0,不重疊不置標志位,即tpflag為1
  362.         temp=s_box.box;
  363.         for(i=0;i<4;i++)
  364.         {
  365.                 Box_Ram[3-i+s_box.y]|=((temp&0x000f)<<(9-s_box.x));
  366.                 temp=temp>>4;
  367.         }//在游戲點陣緩存中恢復原有方塊
  368.         return(tpflag);
  369. }
  370. //方塊緩存數據函數(輸入方塊類型和形狀即可獲得方塊緩存數據)
  371. unsigned int box_read_data(unsigned char tpmode,unsigned char tpshape)
  372. {
  373.         unsigned int tpbox;
  374.         switch(tpmode)
  375.         {
  376.                 case 0: switch(tpshape)
  377.                                 {
  378.                                         case 0: tpbox=0xf000;break;
  379.                                         case 1: tpbox=0x4444;break;
  380.                                         case 2: tpbox=0xf000;break;
  381.                                         case 3: tpbox=0x4444;break;
  382.                                         default:;
  383.                                 }break;       
  384.                 case 1: switch(tpshape)
  385.                                 {
  386.                                         case 0: tpbox=0xe800;break;
  387.                                         case 1: tpbox=0xc440;break;
  388.                                         case 2: tpbox=0x2e00;break;
  389.                                         case 3: tpbox=0x88c0;break;
  390.                                         default:;
  391.                                 }break;       
  392.                 case 2: switch(tpshape)
  393.                                 {
  394.                                         case 0: tpbox=0xe200;break;
  395.                                         case 1: tpbox=0x44c0;break;
  396.                                         case 2: tpbox=0x8e00;break;
  397.                                         case 3: tpbox=0xc880;break;
  398.                                         default:;
  399.                                 }break;       
  400.                 case 3: switch(tpshape)
  401.                                 {
  402.                                         case 0: tpbox=0xcc00;break;
  403.                                         case 1: tpbox=0xcc00;break;
  404.                                         case 2: tpbox=0xcc00;break;
  405.                                         case 3: tpbox=0xcc00;break;
  406.                                         default:;
  407.                                 }break;       
  408.                 case 4: switch(tpshape)
  409.                                 {
  410.                                         case 0: tpbox=0xc600;break;
  411.                                         case 1: tpbox=0x4c80;break;
  412.                                         case 2: tpbox=0xc600;break;
  413.                                         case 3: tpbox=0x4c80;break;
  414.                                         default:;
  415.                                 }break;       
  416.                 case 5: switch(tpshape)
  417.                                 {
  418.                                         case 0: tpbox=0x6c00;break;
  419.                                         case 1: tpbox=0x8c40;break;
  420.                                         case 2: tpbox=0x6c00;break;
  421.                                         case 3: tpbox=0x8c40;break;
  422.                                         default:;
  423.                                 }break;
  424.                 case 6: switch(tpshape)
  425.                                 {
  426.                                         case 0: tpbox=0x4e00;break;
  427.                                         case 1: tpbox=0x8c80;break;
  428.                                         case 2: tpbox=0xe400;break;
  429.                                         case 3: tpbox=0x4c40;break;
  430.                                         default:;
  431.                                 }break;
  432.                 default:;
  433.         }
  434.         return(tpbox);
  435. }
  436. //方塊載入函數
  437. void box_load()
  438. {
  439.         s_box.box=box_read_data(s_box.mode,s_box.shape);
  440. }
  441. //方塊映射游戲點陣緩存函數(參數是原來方塊的位置、緩存,先消去原有位置的方塊)
  442. void box_to_Box_Ram(unsigned char tpx,unsigned char tpy,unsigned int tpbox)
  443. {
  444.         unsigned char i;
  445.         unsigned int temp;
  446.         temp=tpbox;
  447.         for(i=0;i<4;i++)
  448.         {
  449.                 Box_Ram[3-i+tpy]=Box_Ram[3-i+tpy]&(~((temp&0x000f)<<(9-tpx)));
  450.                 temp=temp>>4;
  451.         }//從游戲點陣緩存中刪除以前的方塊
  452.         temp=s_box.box;
  453.         for(i=0;i<4;i++)
  454.         {
  455.                 Box_Ram[3-i+s_box.y]=((temp&0x000f)<<(9-s_box.x))|Box_Ram[3-i+s_box.y];
  456.                 temp=temp>>4;
  457.         }//在游戲點陣緩存中加入新的方塊
  458. }
  459. //顯示數字函數(
  460.   //x表示x坐標,
  461.   //y表示y坐標,
  462.   //tpdata表示要顯示的數字)
  463. //顯示速度函數
  464. void show_num(unsigned char x,
  465.                                           unsigned char y,
  466.                                           unsigned char tpdata)
  467. {
  468.         unsigned char i;
  469.         for(i=0;i<4;i++)
  470.         {
  471.                 LCD_display_byte(x+i,y,num_data[tpdata*4+i]);       
  472.         }
  473. }
  474. void show_speed_num(unsigned char x,unsigned char y)
  475. {
  476.         show_num(x,y,speed_num);
  477. }
  478. //顯示得分函數
  479. void show_score_num(unsigned char x,unsigned char y)
  480. {
  481.         show_num(x,y,destroy_row_num/10000);
  482.         show_num(x+=5,y,(destroy_row_num%10000)/1000);
  483.         show_num(x+=5,y,(destroy_row_num%1000)/100);
  484.         show_num(x+=5,y,(destroy_row_num%100)/10);
  485.         show_num(x+=5,y,destroy_row_num%10);
  486. }
  487. //消行函數
  488. void destroy_row()
  489. {
  490.         unsigned char i,j=0;
  491.         unsigned char tpflag[4]={0,0,0,0};//最多一次只能消四行,所以設置四個標志位即可,初值為0
  492.         for(i=0;i<16;i++)
  493.         {
  494.                 if((Box_Ram[i]&0x3ffc)==0x3ffc)
  495.                 {
  496.                         tpflag[j]=i+1;//tpflag為0表示不標志,1表示第0行緩存為0xffff,n表示第n+1行緩存為0xffff
  497.                         destroy_row_num++;//消除的行數加一
  498.                         /*如不把Box_Ram[19]定義成idata類型的話加入這段代碼顯示數據區就溢出了*/
  499.                         if(destroy_row_num%30==0&&speed_num!=9)
  500.                         {
  501.                                 speed_num++;//消夠三十行游戲速度加一
  502.                                 show_speed_num(13,4);//調用顯示游戲速度函數
  503.                         }
  504.                         /*如不把Box_Ram[19]定義成idata類型的話加入這段代碼顯示數據區就溢出了*/
  505.                         j++;
  506.                         if(j==4)
  507.                         {
  508.                                 break;
  509.                         }//檢查完有四行要消除則退出檢查循環
  510.                 }
  511.         }//依次檢測是否有行緩存為0xffff,如果是則標志tpflag為此行的行號
  512.         for(j=0;j<4;j++)
  513.         {
  514.                 if(tpflag[j]!=0)
  515.                 {
  516.                         for(i=tpflag[j]-1;i>0;i--)
  517.                         {
  518.                         Box_Ram[i]=Box_Ram[i-1];
  519.                         Box_Ram[0]=0x2004;
  520.                         }
  521.                 }
  522.         }//被標志的行依次被上一行所取代,即被消去
  523.         show_score_num(3,1);
  524. }
  525. //顯示下一個方塊函數
  526. void show_next_box()
  527. {
  528.         unsigned char i,tpdata;
  529.         unsigned int temp;
  530.         temp=box_read_data(next_mode,next_shape);
  531.         for(i=0;i<4;i++)
  532.         {
  533.                 tpdata=0x00;
  534.                 if(  ((temp>>(15-i))&0x0001)==1  )
  535.                 {
  536.                         tpdata=0x0f;
  537.                 }
  538.                 if(  ((temp>>(11-i))&0x0001)==1  )
  539.                 {
  540.                         tpdata|=0xf0;
  541.                 }
  542.                 LCD_display_byte(7+i*4,6,tpdata);
  543.                 LCD_display_byte(8+i*4,6,0xbb&tpdata);
  544.                 LCD_display_byte(9+i*4,6,0xdd&tpdata);
  545.                 LCD_display_byte(10+i*4,6,tpdata);       
  546.                 tpdata=0x00;
  547.                 if(  ((temp>>(7-i))&0x0001)==1  )
  548.                 {
  549.                         tpdata=0x0f;
  550.                 }
  551.                 if(  ((temp>>(3-i))&0x0001)==1  )
  552.                 {
  553.                         tpdata|=0xf0;
  554.                 }
  555.                 LCD_display_byte(7+i*4,7,tpdata);
  556.                 LCD_display_byte(8+i*4,7,0xbb&tpdata);
  557.                 LCD_display_byte(9+i*4,7,0xdd&tpdata);
  558.                 LCD_display_byte(10+i*4,7,tpdata);               
  559.         }
  560. }
  561. //方塊生成函數
  562. void box_build()
  563. {
  564.         s_box.mode=next_mode;
  565.         s_box.shape=next_shape;
  566.         s_box.x=3;
  567.         s_box.y=0;
  568.         next_mode=TL0%7;//產生隨機數,但是是偽隨機的
  569.         next_shape=TL0%4;//產生隨機數,但是是偽隨機的
  570.         show_next_box();//放到game_execute()函數中不知道為什么就是不正常顯示
  571. }
  572. void game_button()
  573. {
  574.        
  575.     switch(basic_button())
  576.     {
  577.         case 3: if(s_box.y!=0)//3表示button_a被按下
  578.                 {
  579.                     EA=0;//關中斷,如果不關的話可能引起游戲顯示混亂
  580.                     speaker=0;
  581.                     if(s_box.shape==3&&check_cover(s_box.x,s_box.y,box_read_data(s_box.mode,0)))
  582.                     {
  583.                                                        
  584.                         s_box.shape=0;
  585.                         box_load();
  586.                         box_to_Box_Ram(s_box.x,s_box.y,box_read_data(s_box.mode,3));
  587.                     }
  588.                     else if(check_cover(s_box.x,s_box.y,box_read_data(s_box.mode,0)))
  589.                     {        if(check_cover(s_box.x,s_box.y,box_read_data(s_box.mode,s_box.shape+1)))
  590.                                                         {       
  591.                                                                 s_box.shape++;
  592.                                                                 box_load();
  593.                                                                 box_to_Box_Ram(s_box.x,s_box.y,box_read_data(s_box.mode,s_box.shape-1));
  594.                                                         }
  595.                      }
  596.                     EA=1;//開中斷
  597.                     speaker=1;
  598.                                         }break;
  599.         case 1: if(s_box.y!=0)//1表示down被按下
  600.         {
  601.             EA=0;//關中斷,如果不關的話可能引起游戲顯示混亂
  602.             speaker=0;
  603.             while(check_cover(s_box.x,s_box.y+1,s_box.box))//檢測是否能下降,指導不能再下降為止
  604.             {
  605.                 s_box.y++;
  606.                 box_to_Box_Ram(s_box.x,s_box.y-1,s_box.box);
  607.             }
  608.             destroy_row();
  609.             box_build();
  610.             box_load();
  611.                                         //        game_over_flag=check_game_over();//游戲結束標志位置1表示游戲結束
  612.                                         //        next_box();
  613.             box_to_Box_Ram(s_box.x,s_box.y,s_box.box);
  614.             EA=1;//開中斷
  615.             speaker=1;
  616.             }break;
  617.         case 4: if(s_box.y!=0)//4表示left被按下
  618.         {
  619.             EA=0;//關中斷,如果不關的話可能引起游戲顯示混亂
  620.             speaker=0;
  621.             if(check_cover(s_box.x-1,s_box.y,s_box.box))
  622.             {
  623.                 s_box.x--;
  624.                 box_to_Box_Ram(s_box.x+1,s_box.y,s_box.box);
  625.             }
  626.             EA=1;//開中斷
  627.             speaker=1;
  628.         }break;
  629.         case 5: if(s_box.y!=0)//5表示right被按下
  630.                 {
  631.                     EA=0;//關中斷,如果不關的話可能引起游戲顯示混亂
  632.                     speaker=0;
  633.                     if(check_cover(s_box.x+1,s_box.y,s_box.box))
  634.                     {
  635.                         s_box.x++;
  636.                         box_to_Box_Ram(s_box.x-1,s_box.y,s_box.box);
  637.                     }
  638.                                                 EA=1;//開中斷
  639.                                                 speaker=1;
  640.                                         }break;
  641.         case 2: //2表示up被按下
  642.             speaker=0;
  643.             pause_game_flag=~pause_game_flag;//游戲暫停標志取反
  644.             while(up==0);
  645.             speaker=1;
  646.             break;
  647.         default:;
  648.     }       
  649. }
  650. //檢查游戲結束函數(游戲結束返回1,游戲沒有結束返回0)
  651. bit check_game_over()
  652. {
  653.         unsigned char i;
  654.         bit tpflag=0;
  655.         unsigned int temp;
  656.         temp=s_box.box;
  657.         for(i=0;i<4;i++)
  658.         {
  659.                 if((((temp&0x000f)<<(9-s_box.x))&Box_Ram[3-i+s_box.y])!=0x0000)
  660.                 {
  661.                         tpflag=1;
  662.                 }
  663.                 temp=temp>>4;
  664.         }//檢查新建方塊是否和原有圖形重疊,重疊置標志位tpflag為1,不重疊不置標志位,即tpflag為0
  665.         return(tpflag);
  666. }
  667. //游戲執行函數(控制方塊下落,檢測是否到底,如果到底調用消行函數)
  668. void game_execute()
  669. {
  670.         if(box_down_reg<20-(speed_num<<1))
  671.         {                                  
  672.                 box_down_reg++;
  673.         }
  674.         else
  675.         {
  676.                 box_down_reg=0;
  677.                 if(check_cover(s_box.x,s_box.y+1,s_box.box))
  678.                 {
  679.                         s_box.y++;
  680.                         box_to_Box_Ram(s_box.x,s_box.y-1,s_box.box);
  681.                 }//檢測是否還可以下降,如果還能下降則繼續下降
  682.                 else
  683.                 {
  684.                         destroy_row();
  685.                         box_build();
  686.                         box_load();
  687.                         game_over_flag=check_game_over();//游戲結束標志位置1表示游戲結束
  688.                         box_to_Box_Ram(s_box.x,s_box.y,s_box.box);
  689.                         box_down_reg=(20-(speed_num<<1)-1);//為了使方塊一出現就能變換形狀,所以需要盡快使得方塊下降一行,不知道為什么最高行不能變換形狀
  690.                 }//如果不能下降則調用消行函數檢查是否可以消行,之后重新建立方塊
  691.         }       
  692. }
  693. //選擇游戲速度函數
  694. void select_speed()
  695. {
  696.         unsigned char i;
  697.         bit tpflag=1;//置循環標志位為1
  698.         LCD_clear();
  699.         for(i=0;i<128;i++)
  700.         {
  701.                 LCD_display_byte(i,0,0xff);
  702.                 LCD_display_byte(i,7,0xff);
  703.         }
  704.         LCD_display_byte(60,4,0x7f);
  705.         LCD_display_byte(59,4,0x3e);
  706.         LCD_display_byte(58,4,0x1c);
  707.         LCD_display_byte(57,4,0x08);
  708.         LCD_display_byte(67,4,0x7f);
  709.         LCD_display_byte(68,4,0x3e);
  710.         LCD_display_byte(69,4,0x1c);
  711.         LCD_display_byte(70,4,0x08);
  712.         LCD_display_word(speed_data,24,3,52);
  713.         show_speed_num(62,4);
  714.         while(tpflag)
  715.         {
  716.                 switch(basic_button())
  717.                 {
  718.                         case 4: if(speed_num!=0)
  719.                                         {
  720.                                                 speaker=0;
  721.                                                 speed_num--;
  722.                                                 show_speed_num(62,4);
  723.                                                 speaker=1;
  724.                                         }
  725.                                         while(left==0);
  726.                                         break;
  727.                         case 5: if(speed_num!=9)
  728.                                         {
  729.                                             speaker=0;
  730.                                                 speed_num++;
  731.                                                 show_speed_num(62,4);
  732.                                                 speaker=1;
  733.                                         }
  734.                                         while(right==0);
  735.                                         break;
  736.                         case 6: tpflag=0;
  737.                                  speaker=0;
  738.                                         while(button_b==0);
  739.                                         speaker=1;
  740.                                         break;
  741.                         default:;
  742.                 }
  743.         }//選擇游戲速度循環
  744. }
  745. //游戲開始顯示畫面
  746. void game_start_show()
  747. {
  748.         bit tpflag=1;//置循環標志位為1
  749.         LCD_full_draw(start_pic);
  750.         while(tpflag)
  751.         {
  752.                 switch(basic_button())
  753.                 {
  754.                         case 6: tpflag=0;
  755.                                 speaker=0;
  756.                                         while(button_b==0);
  757.                                         speaker=1;
  758.                                         break;
  759.                         default:;
  760.                 }
  761.         }//game_start_show循環
  762. }
  763. //游戲初始化函數
  764. void game_initialize()
  765. {
  766.         box_down_reg=0;
  767.         next_mode=6;
  768.         next_shape=2;
  769.         destroy_row_num=0;
  770.         game_over_flag=0;
  771.         pause_game_flag=0;
  772.         LCD_clear();
  773.         time0_reg=0;
  774.         display_basic();       
  775.         LCD_display_word(score_data,24,0,3);
  776.         LCD_display_word(speed_data,24,3,3);
  777.         show_score_num(3,1);
  778.         show_speed_num(13,4);
  779. }
  780. //定時器0初始化函數
  781. void time0_initialize()
  782. {
  783.         TMOD=0x03;//定時器0,16位工作方式
  784.         TR0=1; //啟動定時器
  785.         ET0=1; //打開定時器0中斷
  786.                         //默認中斷優先級為低
  787.         EA=1; //打開總中斷
  788. }
  789. //俄羅斯方塊游戲主函數
  790. void Tetris_main()
  791. {
  792.         unsigned char i;
  793.         for(i=0;i<19;i++)
  794.         {
  795.                 Box_Ram[i]=Box_Ram_data[i];
  796.         };//載入游戲初始顯示畫面
  797.         LCD_draw(mpic);
  798.         game_over_flag=0;//游戲結束標志位置0表示游戲未結束
  799.         box_build();
  800.         box_load();
  801. //        next_box();
  802.         box_to_Box_Ram(s_box.x,s_box.y,s_box.box);
  803.         box_down_reg=(20-(speed_num<<1)-1);//為了使方塊一出現就能變換形狀,所以需要盡快使得方塊下降一行,不知道為什么最高行不能變換形狀
  804.         time0_initialize();
  805.         while(!game_over_flag)//如果游戲結束標志位置1,表示游戲結束,打破循環,調用游戲結束畫面顯示函數
  806.         {
  807.                 game_button();
  808.         }
  809.         EA=0;//游戲結束后關中斷
  810. }
  811. //游戲結束畫面顯示函數
  812. void game_over_show()
  813. {
  814.         unsigned char i;
  815.         bit tpflag=1;//置循環標志位為1
  816.         LCD_full_draw(over_pic);
  817.         while(button_a==0);
  818.         while(tpflag)
  819. ……………………

  820. …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼


所有資料51hei提供下載:
俄羅斯方塊完整資料.7z (1.25 MB, 下載次數: 382)



作者: amj12321    時間: 2019-7-25 14:43
哇這個看起來很清楚,想試一試
作者: zj381137260    時間: 2019-7-25 17:13
下載學習一下LCD使用方法,謝謝分享
作者: YXun    時間: 2019-7-25 17:30
膜拜大佬!
作者: yaofengy    時間: 2020-3-21 09:54
代碼報錯
作者: 11111111111s    時間: 2020-3-27 15:40
看起來不錯
作者: cy009    時間: 2020-3-29 19:15
大神
作者: Kethno    時間: 2020-3-30 13:46
膜拜大佬!
作者: vungocduong    時間: 2021-2-22 22:59
精彩的比賽
作者: NONGNONG    時間: 2021-2-23 13:40
好家伙,剛好拿來學習。
作者: 5.1_phantom    時間: 2021-2-26 10:47
牛逼!!!!
作者: sh-fluke    時間: 2021-3-2 19:16
下載學習一下LCD使用方法,謝謝分享。
作者: blue_sea    時間: 2021-3-6 12:38
取模方式是啥

作者: aktuan007    時間: 2021-3-6 22:01
對我來說不可實現。。。
作者: 多喝燙水    時間: 2021-7-7 15:18
膜拜大佬
作者: wssbwssb    時間: 2021-11-23 10:50
實物LCD12864,,好像不顯示圖案,不知道是不是接錯腳了




歡迎光臨 (http://www.zg4o1577.cn/bbs/) Powered by Discuz! X3.1
主站蜘蛛池模板: 嫩草91在线| www.日韩| 亚洲大片 | 伊人欧美视频 | 久草福利 | 欧洲性生活视频 | 日韩精品久久一区 | 久久久久久999 | 丁香一区二区 | 亚洲国产福利视频 | 亚洲视频www | 日韩视频国产 | 超碰在线久| 日韩在线观看一区 | 中文字幕在线欧美 | 久久国产婷婷国产香蕉 | 久久久网 | 日韩1区2区 | 国产一区不卡在线观看 | 密室大逃脱第六季大神版在线观看 | 国产偷久久一级精品60部 | 欧美精品在线免费观看 | 欧美日韩成人影院 | 91精品国产高清久久久久久久久 | 欧美日韩中文在线观看 | 国产精品一区二区久久久久 | 美女视频黄的免费 | 久久久久久成人 | 97精品久久 | 国产精品区一区二 | 亚洲aⅴ一区二区 | 久久神马| 国产激情91久久精品导航 | 男插女下体视频 | 超级碰在线 | japanhd成人| 欧美极品视频 | 精品一区二区电影 | 99久久日韩精品免费热麻豆美女 | 日韩精品一区二区三区中文在线 | 日韩中文视频 |