欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136
標題:
STM32F103ZET6貪吃蛇游戲程序設計
[打印本頁]
作者:
NOTHIN9
時間:
2019-1-5 21:47
標題:
STM32F103ZET6貪吃蛇游戲程序設計
基于STM32F103的貪吃蛇
單片機源程序如下:
///***************************************************
//程序名:貪吃蛇
//平臺:STM32F103ZET6精英版
//
//程序功能:貪吃蛇游戲,吃到食物后,速度增加,長度變長,咬到自己游戲結束,復位重新開始
//
//程序調用:自制手柄按鍵,AD產生隨機數,正點原子4.3寸屏幕,FreeRTOS操作系統
//
//設計思路:創建若干任務,按鍵任務控制蛇方向,顯示任務控制屏幕的顯示與坐標更新,事件任務為數據處理任務,并控制著其他任務能否運行
//
//知識準備:AD采樣,GPIO設置,FreeRTOS創建任務與掛起
//
//注意:屏幕被裁剪成4.3寸版本,其它屏幕請修改為原程序
//
///****************************************************
//系統文件
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
//內部驅動
#include "rand.h"
//外圍電路
#include "led.h"
#include "key.h"
#include "lcd_4_3.h"
//用戶算法
#include "my_task.h"
#define GAME_WIDTH 480 //設置屏幕分辨率為800*480,為了維持正方形,分成80*48等分
#define GAME_HEIGHT 800
#define GAME_XPART 48
#define GAME_YPART 80
enum sta //枚舉狀態
{
OFF,//0
ON //1
} station;
enum dir //枚舉貪吃蛇方向
{
UP, //上
DOWN, //下
LEFT, //左
RIGHT //右
}direction;
typedef struct //貪吃蛇重要參數集
{
u16 speed; //速度
u16 length; //長度
u16 energybuf; //能量緩存
u16 width; //蛇寬 //未使用
u16 life; //生命數 //未使用
u16 firstx; //蛇頭坐標x
u16 firsty; //蛇頭坐標y
u16 lastx; //蛇尾坐標x
u16 lasty; //蛇尾坐標y
u16 color; //蛇顏色 //未使用
}snakes;
snakes snake;
void Snake_Init(snakes * snake)//貪吃蛇參數初始化
{
snake->speed=5;
snake->length=10;
snake->energybuf=0;
snake->width=1;
snake->life=3;
snake->firstx=4;
snake->firsty=5;
snake->lastx=0;
snake->lasty=0;
snake->color=RED;
}
typedef struct //食物重要參數集
{
u16 energy ;//食物能量
u16 x ; //食物坐標x
u16 y ; //食物坐標y
}apples;
apples apple;
void Apple_Init(apples * apple)//食物參數初始化
{
apple->energy=1;
// apple->x=24; //坐標由隨機數計算出來
// apple->y=40;
}
typedef struct //事件重要參數集
{
u16 Process ;//是否游戲暫停
u16 GameSta ;//是否游戲結束
u16 AppleSta;//食物狀態
u16 Direction;//蛇前進方向
}events;
events event;
void Event_Init(events * event)//事件參數初始化
{
event->Process=ON;
event->GameSta=ON;
event->AppleSta=ON;
event->Direction=DOWN;//初始方向向下
}
typedef struct //貪吃蛇坐標參數
{
u16 x;
u16 y;
}axiss;
axiss snake_axis[100]; //設蛇身最大長度可以達到100
void Display(u16 x,u16 y,u16 color)//按照80*48的坐標映射到800*480的屏幕上
{
LCD_Fill(GAME_WIDTH/GAME_XPART*x,GAME_HEIGHT/GAME_YPART*y,GAME_WIDTH/GAME_XPART*(x+1),GAME_HEIGHT/GAME_YPART*(y+1),color);
}
void DisplayInit(void) //蛇身初始化,默認在該位置,并蛇頭向下
{
u16 i;
for(i=0;i<5;i++)//將初始坐標存入蛇身坐標內
{
snake_axis[i].x=i;
snake_axis[i].y=0;
}
for(i=5;i<10;i++)
{
snake_axis[i].x=4;
snake_axis[i].y=i-4;
}
LCD_Clear(WHITE);
for(i=0;i<10;i++)
{
Display(snake_axis[i].x,snake_axis[i].y,RED);//按照初始坐標打印出蛇身
}
}
void GameOver(void)//游戲結束函數,打印"GAME OVER",掛起核心數據處理函數
{
LCD_ShowString(180,388,200,24,24,"GAME OVER !");
vTaskSuspend(EVENTTask_Handler);
}
//全局變量//////////////////////////////////////
int main(void)
{
delay_init(); //延時函數初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //設置NVIC中斷分組2:2位搶占優先級,2位響應優先級
Rand_Adc_Init(); //隨機數初始化
LED_Init(); //LED端口初始化
KEY_PLAY_Init(); //按鍵初始化,自制按鍵上/下/左/右/暫停,分別連接PF0/1/2/3/4,低電平接通
LCD_Init(0);//默認為豎屏模式
DisplayInit();//打印初始蛇身
Snake_Init(&snake);//貪吃蛇參數初始化
Apple_Init(&apple);//食物參數初始化
Event_Init(&event);//事件參數初始化
xTaskCreate((TaskFunction_t )start_task, //任務函數
(const char* )"start_task", //任務名稱
(uint16_t )START_STK_SIZE, //任務堆棧大小
(void* )NULL, //傳遞給任務函數的參數
(UBaseType_t )START_TASK_PRIO, //任務優先級
(TaskHandle_t* )&StartTask_Handler); //任務句柄
vTaskStartScheduler(); //開啟任務調度
}
//開始任務任務函數
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //進入臨界區
//創建貪吃蛇任務
xTaskCreate((TaskFunction_t )snake_task,
(const char* )"snake_task",
(uint16_t )SNAKE_STK_SIZE,
(void* )NULL,
(UBaseType_t )SNAKE_TASK_PRIO,
(TaskHandle_t* )&SNAKETask_Handler);
//創建食物任務
xTaskCreate((TaskFunction_t )apple_task,
(const char* )"apple_task",
(uint16_t )APPLE_STK_SIZE,
(void* )NULL,
(UBaseType_t )APPLE_TASK_PRIO,
(TaskHandle_t* )&APPLETask_Handler);
//創建事件任務
xTaskCreate((TaskFunction_t )event_task,
(const char* )"event_task",
(uint16_t )EVENT_STK_SIZE,
(void* )NULL,
(UBaseType_t )EVENT_TASK_PRIO,
(TaskHandle_t* )&EVENTTask_Handler);
//創建顯示任務
xTaskCreate((TaskFunction_t )display_task,
(const char* )"display_task",
(uint16_t )DISPLAY_STK_SIZE,
(void* )NULL,
(UBaseType_t )DISPLAY_TASK_PRIO,
(TaskHandle_t* )&DISPLAYTask_Handler);
//創建閃爍任務
xTaskCreate((TaskFunction_t )led_task,
(const char* )"led_task",
(uint16_t )LED_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED_TASK_PRIO,
(TaskHandle_t* )&LEDTask_Handler);
//創建輸入任務
xTaskCreate((TaskFunction_t )key_task,
(const char* )"key_task",
(uint16_t )KEY_STK_SIZE,
(void* )NULL,
(UBaseType_t )KEY_TASK_PRIO,
(TaskHandle_t* )&KEYTask_Handler);
vTaskDelete(StartTask_Handler); //刪除開始任務
taskEXIT_CRITICAL(); //退出臨界區
}
//事件任務函數,核心數據處理函數
void event_task(void *pvParameters)
{
while(1)
{
if(event.GameSta==ON)//如果游戲正常則繼續
{
if(event.Process==ON)//如果沒有暫停則繼續
{
switch(event.Direction)//檢測按鍵情況,根據方向調整蛇頭坐標
{
case UP:
{
snake.firsty-=1;
if(snake.firsty>GAME_YPART-1)
{
snake.firsty=GAME_YPART-1;
}
}break;
case DOWN:
{
snake.firsty+=1;
if(snake.firsty>GAME_YPART-1)
{
snake.firsty=0;
}
}break;
case LEFT:
{
snake.firstx-=1;
if(snake.firstx>GAME_XPART-1)
{
snake.firstx=GAME_XPART-1;
}
}break;
case RIGHT:
{
snake.firstx+=1;
if(snake.firstx>GAME_XPART-1)
{
snake.firstx=0;
}
}break;
}
snake.lastx=snake_axis[0].x;//保存下蛇尾坐標
snake.lasty=snake_axis[0].y;
if(snake.firstx==apple.x&&snake.firsty==apple.y)//如果此時的坐標與食物坐標相同
{
event.AppleSta=OFF; //食物被吃掉
snake.energybuf+=apple.energy;//蛇的能量加一
vTaskResume(APPLETask_Handler); //使能生成食物函數
}
vTaskResume(DISPLAYTask_Handler); //使能顯示函數
}
}else GameOver();//如果游戲為結束狀態則游戲結束
delay_ms(1000/snake.speed); //按照蛇的速度調整此核心數據處理函數的時間間隔
}
}
//輸入任務函數,根據按鍵調整蛇的方向,數據處理函數之前最后一次按鍵視為有效
void key_task(void *pvParameters)
{
u8 key;
while(1)
{
key=KEY_PLAY_Scan(0);//按鍵掃描函數,此處是自制的手柄,上/下/左/右/暫停,分別連接PF0/1/2/3/4,低電平接通
switch(key)
{
case KEY_UP_PRES:
{
if(event.Direction!=DOWN)//如果當前方向與按鍵方向相反,則不響應
event.Direction=UP;
}break;
case KEY_DOWN_PRES:
{
if(event.Direction!=UP)
event.Direction=DOWN;
}break;
case KEY_LEFT_PRES:
{
if(event.Direction!=RIGHT)
event.Direction=LEFT;
}break;
case KEY_RIGHT_PRES:
{
if(event.Direction!=LEFT)
event.Direction=RIGHT;
}break;
case KEY_PASS_PRES://按下切換暫停/繼續狀態
{
event.Process=!event.Process;
}break;
}
delay_ms(20);//每20ms響應一次
}
}
//食物任務函數,食物被吃掉時觸發此函數
void apple_task(void *pvParameters)
{
u16 flag,i;
while(1)
{
flag=1;
while(flag)//生成新的食物坐標
{
flag=0;
apple.x=Get_Rand()%(u16)(GAME_XPART);
apple.y=Get_Rand()%(u16)(GAME_YPART);
for(i=0;i<snake.length;i++) //食物坐標不能在蛇身上
{
if(snake_axis[i].x==apple.x&&snake_axis[i].y==apple.y)
{
flag++;
}
}
}
Display(apple.x,apple.y,RED);//按照坐標將食物顯示出來
vTaskSuspend(APPLETask_Handler);//掛起任務
}
}
//貪吃蛇任務函數 ,此任務作廢
void snake_task(void *pvParameters)
{
while(1)
{
//LED0=!LED0;
delay_ms(500);
}
}
//顯示任務函數,顯示蛇頭,消去蛇尾,并更新蛇的坐標
void display_task(void *pvParameters)
{
u16 i;
while(1)
{
Display(snake.firstx,snake.firsty,RED);//顯示蛇頭
if(snake.energybuf==0) //如果沒有吃到食物
{
Display(snake.lastx,snake.lasty,WHITE);//消去蛇尾
for(i=0;i<snake.length-1;i++)
{
snake_axis[i].x=snake_axis[i+1].x;//挨個更新坐標
snake_axis[i].y=snake_axis[i+1].y;
}
}else //如果吃到了食物
{
snake.energybuf--;//能量緩沖區減一
snake.length++; //蛇身加一
// if(snake.length%2==0)snake.speed++;
snake.speed++; //由于地圖很大,故設置蛇身加一則速度加一
}
snake_axis[snake.length-1].x=snake.firstx;//最新的坐標更新為蛇頭的坐標
snake_axis[snake.length-1].y=snake.firsty;
for(i=0;i<snake.length-1;i++)//檢查有沒有咬到自己
{
if(snake_axis[i].x==snake.firstx&&snake_axis[i].y==snake.firsty)
{
event.GameSta=OFF; //遍歷蛇身坐標是否與蛇頭坐標相同
}
}
vTaskSuspend(DISPLAYTask_Handler);
}
}
//閃爍任務函數,證明程序沒有死機
void led_task(void *pvParameters)
{
while(1)
{
LED0=!LED0;
delay_ms(500);
}
}
復制代碼
所有資料51hei提供下載:
貪吃蛇游戲F1.7z
(356.21 KB, 下載次數: 147)
2019-1-6 04:18 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
作者:
蔥姜蒜5
時間:
2019-1-15 22:46
小白求助,我就改主函數里分辨率的定義 我用stm32戰艦v3
作者:
蔥姜蒜5
時間:
2019-1-15 22:49
小白求助,我就改了主函數分辨率的定義 用stm32戰艦v3不能實現效果 蛇的初始位置什么的,是不是也要自己定義,看不懂代碼
作者:
xiaokeai5023
時間:
2020-6-14 22:55
小白求助,這個需要用到proteus嗎
作者:
都非常才
時間:
2023-7-5 19:14
xiaokeai5023 發表于 2020-6-14 22:55
小白求助,這個需要用到proteus嗎
好像用不到
作者:
weere
時間:
2023-12-28 17:41
感謝樓主的代碼,但是燒錄之后屏幕沒有反應,用的是正點原子F103ZET6精英板
作者:
大胖鴨
時間:
2024-1-4 23:00
小白求助,這個需要自己設計電路嗎
歡迎光臨 (http://www.raoushi.com/bbs/)
Powered by Discuz! X3.1