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