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

 找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 2625|回復(fù): 1
打印 上一主題 下一主題
收起左側(cè)

STM32單片機(jī)打磚塊游戲機(jī)制作 附源程序

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:970990 發(fā)表于 2022-12-14 10:44 | 只看該作者 |只看大圖 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
用STM32做一個(gè)游戲機(jī)

游戲視頻地址:https://www.bilibili.com/video/BV1i84y1t7ro
制作出來的實(shí)物圖如下:
游戲運(yùn)行圖片如下:


單片機(jī)主函數(shù)如下:

  1. int main()
  2. {  

  3.    
  4.     OLED_Init();
  5.     Key_Init();
  6.     InitAllVariable();
  7.     OLED_ShowString(1,1,"Press any key to");
  8.     OLED_ShowString(2,1,"start game");
  9.     while(1)
  10.     {
  11.         Game();
  12.     }
  13. }
復(fù)制代碼




主函數(shù)中的 “Game()”用于開始游戲、暫停游戲以及游戲重新開始,內(nèi)容如下:

  1. void Game(void)
  2. {
  3.     i=KEY_ValueReturn();
  4.     if(i)
  5.     {
  6.         i=0;
  7.         OLED_Clear();
  8.         while(1)
  9.         {
  10.             GameBody();
  11.             i=KEY_ValueReturn();
  12.             if(ReturnGameOverFlag()==1)//檢測(cè)到游戲結(jié)束標(biāo)志
  13.             {
  14.                 OLED_Clear();
  15.                 while(1)
  16.                 {
  17.                     if(Counter_1_FullFlagReturn()){j=!j;}
  18.                     if(j)
  19.                     {
  20.                         OLED_Clear();
  21.                     }else
  22.                     {
  23.                         OLED_ShowString(1,1,"SCORE:");
  24.                         OLED_ShowNum(1,7,GameScore,6);
  25.                         OLED_ShowString(3,1,"Press key 3 to");
  26.                         OLED_ShowString(4,1,"restart");
  27.                     }
  28.                     i=KEY_ValueReturn();
  29.                     if(i==3){ OLED_Clear();Restart=1; break;}
  30.                 }
  31.             }
  32.             if(ReturnGameOverFlag()==0 && Restart==0)

  33.             {
  34.                 if(i==3 )
  35.                 {
  36.                     OLED_Clear();
  37.                     while(1)
  38.                     {
  39.                         if(Counter_1_FullFlagReturn()){j=!j;}
  40.                         if(j){
  41.                             OLED_Clear();
  42.                         }else
  43.                         {
  44.                             OLED_ShowString(1,1,"     PAUSED ");
  45.                         }
  46.                         i=KEY_ValueReturn();
  47.                         if(i==3){OLED_Clear(); break;}
  48.                     }
  49.                 }
  50.             }      
  51.         }
  52.     }  
  53. }
復(fù)制代碼



游戲主體Gamebody用于實(shí)現(xiàn)整個(gè)游戲的運(yùn)行,代碼如下:

  1. #include "stm32f10x.h"                  // Device header

  2. #include "KEY.h"

  3. #include "OLED.h"



  4. int8_t First_Enemy[9]={16,16,16,16,16,16,16,16,16};//每隊(duì)第一個(gè)敵人的坐標(biāo)
  5. int8_t Bullet_X[15],Bullet_Y[15];//儲(chǔ)存子彈坐標(biāo)
  6. uint32_t GameScore=0,LastScore;
  7. int8_t Restart=0;//重新開始標(biāo)志位
  8. typedef struct {
  9.     uint8_t FireFlag;
  10.     int8_t ShowBullet;
  11.     uint8_t ShowEnemy;
  12.     uint8_t GameOver;//
  13.     uint8_t BulletSpeedUp;
  14. }FlagDef;

  15. typedef struct {
  16.     int8_t X;
  17.     int8_t Y;
  18. }PlayerDef;

  19. typedef struct {
  20.     int8_t X;
  21.     int8_t Y;
  22. }BulletDef;

  23. typedef struct {
  24.     uint8_t X;
  25.     uint8_t Y;

  26. }EnemyDef;

  27. PlayerDef My_loaction;

  28. FlagDef Flag;
  29. BulletDef Bullet_Location;

  30. BulletDef BulletNum;

  31. EnemyDef EnemyTarget;

  32. /****
  33.     *@brief 初始化所有結(jié)構(gòu)體變量
  34.     *@parameter 無
  35.     *@ReturnValue 無
  36.     */
  37. void InitAllVariable(void)
  38. {
  39.     My_loaction.X=4;//初始化玩家X坐標(biāo)
  40.     My_loaction.Y=1;//初始化玩家Y坐標(biāo)
  41.     Flag.FireFlag=0;//初始化開火標(biāo)志位
  42.     Flag.ShowBullet=0;//子彈顯示
  43.     Flag.GameOver=0;//游戲結(jié)束標(biāo)志
  44.     Flag.BulletSpeedUp=0;//子彈加速標(biāo)志位
  45.     Bullet_Location.X=My_loaction.X;//初始化子彈位置
  46.     Bullet_Location.Y=My_loaction.Y;//初始化子彈位置
  47.     EnemyTarget.X=8;//首位敵軍的位置
  48.     EnemyTarget.Y=16;//首位敵軍的位置
  49. }

  50. /****
  51.     *@brief 按鍵返回值處理
  52.     *@parameter 無
  53.     *@ReturnValue 無
  54.     */
  55. void KeyNumReturn(void)
  56. {
  57.     int8_t i,temp=0;
  58.     temp=KEY_ValueReturn();
  59.     if(temp){i=temp;}
  60.     if(i==1){ My_loaction.X--; i=0; if(My_loaction.X<=1)My_loaction.X=1;}//1號(hào)鍵按下,玩//家上移一格
  61.     if(i==2){ My_loaction.X++; i=0; if(My_loaction.X>=8)My_loaction.X=8; }//2號(hào)鍵按下,玩//家下移一格
  62.     if(i==3) { i=0; }
  63.     if(i==4) { Flag.FireFlag=1; i=0; }  //四號(hào)鍵按下,開火標(biāo)志位置一
  64. }


  65. /****
  66.     *@brief 顯示玩家
  67.     *@parameter
  68.     *@ReturnValue
  69.     */
  70. void ShowPlayer(void)
  71. {
  72.     uint8_t i;
  73.     OLED_ShowBlock(My_loaction.X,My_loaction.Y);//根據(jù)坐標(biāo)顯示玩家
  74.     for(i=1;i<=8;i++)//清除玩家移動(dòng)后,上一次留下的影子(oled不會(huì)自動(dòng)清屏,玩家移動(dòng)后,上一次的方塊//依然會(huì)顯示)
  75.     {
  76.         if(i!=My_loaction.X)
  77.         {
  78.             OLED_DeleteBlock(i,My_loaction.Y);
  79.         }
  80.     }
  81.    
  82. }

  83. /****
  84.     *@brief 子彈處理
  85.     *@parameter 無
  86.     *@ReturnValue 無
  87.     */
  88. void Bullet_process(void)
  89. {
  90.     if(Flag.FireFlag==1)//開火標(biāo)志位
  91.     {
  92.         if(Flag.ShowBullet==0)
  93.         {
  94.             Bullet_Location.X=My_loaction.X;
  95.             Bullet_Location.Y=My_loaction.Y+1;
  96.             Flag.ShowBullet=1;//子彈顯示標(biāo)志位  

  97.         }else if(Flag.ShowBullet==1)
  98.         {
  99.             Flag.BulletSpeedUp=1;
  100.         }  
  101.     }  
  102.     Flag.FireFlag=0;
  103.    
  104.     LastScore=GameScore;
  105.     if(Flag.ShowBullet)
  106.     {
  107.         if(Bullet_Location.Y >=1 && Bullet_Location.Y <17)
  108.         {
  109.             if(Counter_0_FullFlagReturn() || Flag.BulletSpeedUp==1)
  110.             {
  111.                 Bullet_Location.Y++;
  112.                
  113.                 Flag.BulletSpeedUp=0;
  114.             }
  115.             if(Bullet_Location.Y>2)//手動(dòng)清除上一次子彈所在位置,OLED不會(huì)自動(dòng)清屏。
  116.             {
  117.                 OLED_DeleteBlock(Bullet_Location.X,Bullet_Location.Y-1);
  118.             }
  119.         }
  120.         EnemyTarget.Y=First_Enemy[Bullet_Location.X];//
  121.         if(Bullet_Location.Y<EnemyTarget.Y+1)//子彈沒有碰到敵人或墻壁則根據(jù)坐標(biāo)顯示子彈
  122.         {
  123.             OLED_ShowBullet(Bullet_Location.X,Bullet_Location.Y);  
  124.         }else //子彈碰到敵人或墻壁則清除子彈
  125.         {
  126.             if(Bullet_Location.X<16){First_Enemy[Bullet_Location.X]++;}
  127.             Flag.ShowBullet=0;
  128.             GameScore++;//增加游戲分?jǐn)?shù)
  129.         }
  130.         if(Bullet_Location.Y>=17)Flag.ShowBullet=0;
  131.     }

  132. }
  133. /****
  134.     *@brief 返回游戲結(jié)束標(biāo)志位
  135.     *@parameter 無
  136.     *@ReturnValue 無
  137.     */
  138. uint8_t ReturnGameOverFlag(void)
  139. {
  140.     return Flag.GameOver;
  141. }

  142. /****
  143.     *@brief 根據(jù)關(guān)卡顯示敵人
  144.     *@parameter 無
  145.     *@ReturnValue 無
  146.     */
  147. void Enemy_Process(void)
  148. {
  149.     uint8_t i,j;
  150.     if(Counter_EnemyMovingFlag()==1 )//時(shí)間到,讓所有敵人往前走一步
  151.     {
  152.         for(i=1;i<=8;i++)
  153.         {
  154.             First_Enemy[i]--;
  155.         }
  156.         for(i=1;i<=8;i++)
  157.         {
  158.             for(j=First_Enemy[i];j<17;j++)
  159.             {
  160.                 OLED_ShowAnemy(i,j);
  161.             }
  162.         }
  163.     }else if(Counter_EnemyMovingFlag()==0)//時(shí)間沒到,所有敵人原地不動(dòng)
  164.     {
  165.         for(i=1;i<=8;i++)
  166.         {
  167.             for(j=First_Enemy[i];j<17;j++)
  168.             {
  169.                 OLED_ShowAnemy(i,j);
  170.             }
  171.         }
  172.     }
  173.     for(i=1;i<=8;i++)//判斷是否有敵人走到了玩家面前
  174.     {
  175.         if(First_Enemy[i]<=2)
  176.         {
  177.             Flag.GameOver=1;//將游戲結(jié)束位置一;
  178.             for(j=1;j<=8;j++)
  179.             {
  180.                 First_Enemy[j]=16;
  181.                
  182.             }
  183.         }
  184.     }
  185. }

  186. /****
  187.     *@brief 根據(jù)分?jǐn)?shù)控制蜂鳴器以及燈光
  188.     *@parameter 無
  189.     *@ReturnValue 無
  190.     */
  191. void Score_Process(void)
  192. {
  193.     if(GameScore>LastScore)
  194.     {
  195.         GPIO_ResetBits(GPIOC,GPIO_Pin_13);
  196.     }else
  197.     {
  198.         GPIO_SetBits(GPIOC,GPIO_Pin_13);
  199.     }
  200.    
  201.     if(Counter_0_FullFlagReturn())
  202.     {
  203.         GPIO_SetBits(GPIOC,GPIO_Pin_13);
  204.     }
  205. }

  206. /****
  207.     *@brief 游戲重新開始處理函數(shù)
  208.     *@parameter 無
  209.     *@ReturnValue 無
  210.     */
  211. void GameRestart(void)
  212. {
  213.     if(Restart==1 && Flag.GameOver==1)
  214.     {
  215.         OLED_Clear();
  216.         GameScore=0;
  217.         Flag.GameOver=0;
  218.         Restart=0;
  219.     }

  220. }

  221. /****
  222.     *@brief //游戲主體,在主函數(shù)中循環(huán)調(diào)用該函數(shù),運(yùn)行當(dāng)前游戲。
  223.     *@parameter 無
  224.     *@ReturnValue 無
  225.     */
  226. void GameBody(void)
  227. {
  228.     KeyNumReturn();
  229.     ShowPlayer();
  230.     Enemy_Process();
  231.     GameRestart();
  232.     Bullet_process();
  233.     Score_Process();   
  234. }
復(fù)制代碼

按鍵處理Key.c用于處理按鍵,讓按鍵按下后產(chǎn)生對(duì)應(yīng)的動(dòng)作,本次的按鍵處理在《單片機(jī)定時(shí)器中斷掃描按鍵程序思路詳解》(http://www.zg4o1577.cn/bbs/dpj-225674-1.html)內(nèi)容上進(jìn)行修改,修改后Key.c內(nèi)容如下:

  1. #include "stm32f10x.h"                  // Device header

  2. #include "delay.h"


  3. uint8_t KEY_Num,KEY_Value;
  4. static uint8_t KEY_LastState,KEY_NowState;
  5. uint8_t Counter_0,Counter_0_FullFlag;
  6. uint8_t Counter_1,Counter_1_FullFlag;
  7. //uint8_t TEST_i;

  8. uint16_t Counter_2=0,Counter_EnemyMoving;
  9. /****
  10.     *@brief 初始化按鍵
  11.     *@parameter 無
  12.     *@ReturnValue 無
  13.     */
  14. void Key_Init(void)
  15. {
  16.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);// 開啟GPIOB時(shí)鐘
  17.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);// 開啟GPIOB時(shí)鐘
  18.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//開啟TIM2時(shí)鐘
  19.    
  20.     GPIO_InitTypeDef GPIO_InitStructure;//GPIO初始化
  21.     GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
  22.     GPIO_InitStructure.GPIO_Pin=GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
  23.     GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
  24.     GPIO_Init(GPIOB,&GPIO_InitStructure);
  25.    
  26.     GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
  27.     GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13;
  28.     GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
  29.     GPIO_Init(GPIOC,&GPIO_InitStructure);
  30.     GPIO_SetBits(GPIOC,GPIO_Pin_13);
  31.    
  32.     TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//TIM2定時(shí)器初始化

  33.     TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;//不對(duì)內(nèi)部時(shí)鐘分頻
  34.     TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//向上計(jì)數(shù)模式
  35.     TIM_TimeBaseInitStructure.TIM_Period=20-1;
  36.     TIM_TimeBaseInitStructure.TIM_Prescaler=7200-1;//設(shè)置時(shí)鐘計(jì)數(shù)周期為72000000/7200=10000us=1
  37.     TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//通用定時(shí)器沒有重復(fù)計(jì)數(shù)器,設(shè)置為0
  38.     TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
  39.    
  40.     TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//打開TIM2的更新中斷
  41.    
  42.     TIM_InternalClockConfig(TIM2);//選擇內(nèi)部時(shí)鐘源
  43.    
  44.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中斷分組
  45.    
  46.     NVIC_InitTypeDef NVIC_InitStructure;
  47.     NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;
  48.     NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
  49.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
  50.     NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;
  51.     NVIC_Init(&NVIC_InitStructure);
  52.    
  53.     TIM_Cmd(TIM2,ENABLE);
  54. }

  55. //uint8_t Test_return(void)

  56. //{
  57. //  return TEST_i;
  58. //}
  59. /****
  60.     *@brief 判斷哪個(gè)按鍵被按下
  61.     *@parameter 無
  62.     *@ReturnValue 無
  63.     */
  64. uint8_t KEY_Numble(void)
  65. {
  66.     uint8_t i=0;
  67.     if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)==0) { i=1; }
  68.     if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)==0) { i=2; }
  69.     if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==0) { i=3; }
  70.     if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15)==0) { i=4; }
  71. //  TEST_i=i;
  72.     return i;
  73. }
  74. /****
  75.     *@brief 返回按鍵的值
  76.     *@parameter 無
  77.     *@ReturnValue 根據(jù)對(duì)應(yīng)的按鍵返回i(1~4)
  78.     */
  79. uint8_t KEY_ValueReturn(void)
  80. {
  81.     uint8_t i;
  82.     i=KEY_Value;
  83.     KEY_Value=0;
  84.     return i;
  85. }
  86. /****
  87.     *@brief 返回計(jì)數(shù)器Counter_0的狀態(tài)
  88.     *@parameter 無
  89.     *@ReturnValue i:Counter_0計(jì)數(shù)滿則返回1,否則返回0
  90.     */
  91. uint8_t Counter_0_FullFlagReturn(void)
  92. {
  93.     uint8_t i;
  94.     i=Counter_0_FullFlag;
  95.     Counter_0_FullFlag=0;
  96.     return i;
  97. }
  98. /****
  99.     *@brief 每間隔一定時(shí)間返回?cái)耻娗耙茦?biāo)志位,控制敵軍前移一格
  100.     *@parameter無
  101.     *@ReturnValue i:計(jì)數(shù)器滿則返回1,否則返回0;
  102.     */
  103. uint8_t Counter_EnemyMovingFlag(void)
  104. {
  105.     uint8_t i;
  106.     i=Counter_EnemyMoving;
  107.     Counter_EnemyMoving=0;
  108.     return i;
  109. }
  110. /****
  111.     *@brief 返回計(jì)數(shù)器Counter_1的狀態(tài)
  112.     *@parameter 無
  113.     *@ReturnValue i:Counter_1計(jì)滿則為1,否則為0
  114.     */
  115. uint8_t Counter_1_FullFlagReturn(void)

  116. {
  117.     uint8_t i;
  118.     i=Counter_1_FullFlag;
  119.     Counter_1_FullFlag=0;
  120.     return i;
  121. }

  122. /****
  123.     *@brief //TIM2定時(shí)器中斷函數(shù)
  124.     *@parameter 無
  125.     *@ReturnValue 無
  126.     */
  127. void TIM2_IRQHandler(void)//TIM2定時(shí)器中斷函數(shù)
  128. {
  129.     KEY_LastState=KEY_NowState;//保存好按鍵上一次狀態(tài)
  130.     KEY_NowState=KEY_Numble();//刷新按鍵當(dāng)前狀態(tài)
  131.    
  132.     Counter_0++;
  133.     Counter_2++;
  134.     if(Counter_0==25){Counter_0=0;Counter_0_FullFlag=1;Counter_1++;}

  135.     if(Counter_1==30){Counter_1=0;Counter_1_FullFlag=1;}
  136.     if(Counter_2==2500){Counter_EnemyMoving=1;Counter_2=0;}

  137.    
  138.     if(KEY_LastState ==1 && KEY_NowState ==0)//根據(jù)前后兩次狀態(tài)來決定返回值

  139.     {
  140.         KEY_Value=1;
  141.     }
  142.     if(KEY_LastState ==2 && KEY_NowState ==0)

  143.     {
  144.         KEY_Value=2;
  145.     }
  146.     if(KEY_LastState ==3 && KEY_NowState ==0)

  147.     {
  148.         KEY_Value=3;
  149.     }
  150.     if(KEY_LastState ==4 && KEY_NowState ==0)

  151.     {
  152.         KEY_Value=4;
  153.     }
  154.     TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
  155. }
復(fù)制代碼

Keil代碼下載: 23-打磚塊游戲.7z (180.88 KB, 下載次數(shù): 29)

評(píng)分

參與人數(shù) 1黑幣 +90 收起 理由
admin + 90 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏5 分享淘帖 頂2 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:1082094 發(fā)表于 2023-6-5 14:31 來自手機(jī) | 只看該作者
為什么不能左右移動(dòng)
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 国产成人久久精品 | 在线观看亚洲专区 | 99国产精品99久久久久久 | 成人三级影院 | 日本不卡免费新一二三区 | 久久天堂网 | 久久久久国产一区二区三区不卡 | 国产精品欧美精品 | 91视频入口 | 欧美一级视频免费看 | 国产精品区一区二区三 | 请别相信他免费喜剧电影在线观看 | 性视频一区 | 国产一区二区三区高清 | 日韩精品在线一区二区 | 精品国产欧美 | 精品国产一区二区在线 | 久久精品99国产精品日本 | 国产日韩欧美精品一区二区 | 国产亚洲精品久久久优势 | 国产成人免费视频 | 久久久久一区二区三区 | 男女羞羞视频在线 | 日韩久久久久久久 | 成人精品国产免费网站 | 欧美日韩国产精品一区 | 91成人在线| 三区在线 | 成人精品一区二区 | 久久久久久国产精品久久 | 日批的视频| 久久i| 中文字幕日韩欧美 | 成人在线免费 | 成人激情视频在线播放 | 亚洲一区二区三区乱码aⅴ 四虎在线视频 | 日韩精品在线网站 | 91偷拍精品一区二区三区 | 一区二区三区中文字幕 | 欧美五月婷婷 | 国产精品福利一区二区三区 |