這是在Hackster.io上發(fā)布的一個(gè)項(xiàng)目,基于STM32F4 Discovery板制作的游戲機(jī)。采用編寫游戲的方式來學(xué)習(xí)嵌入式系統(tǒng)是比較好的方式,寓教于樂,培養(yǎng)成就感,并不需要學(xué)習(xí)完模電、數(shù)電就可以編程。
下面是這個(gè)項(xiàng)目的硬件部分,主要的器件:
一個(gè)STM32F4 Discovery板
一個(gè)3.2寸、320*240分辨率、帶觸摸的TFT LCD顯示屏(ILI9341為控制器)
一個(gè)2軸游戲手柄
一只4ohm,3W的喇叭
兩個(gè)按鍵
原理圖:
關(guān)于游戲手柄及按鍵的功能定義參見原文 - 點(diǎn)擊左下角的“閱讀原文”即可到達(dá),在這里不再贅述。
下面是板子的正面和背面器件布局示意圖:
下圖為軟件模塊的構(gòu)成及調(diào)用關(guān)系
下圖為數(shù)據(jù)流:
游戲手柄在兩個(gè)方向的變化通過其內(nèi)部兩個(gè)獨(dú)立的可變電阻來實(shí)現(xiàn),電阻的改變以變化的電壓送到控制器的12位精度的ADC,變換后的數(shù)據(jù)以40Hz的頻度被控制器的游戲引擎讀取。
下面是游戲的流程圖:
ISR的程序:
void TIM6_DAC_IRQHandler (void){ TIM_intrpt_handler(TIM6); frameUpdate = SET;}
前景:
int main (void){ RTE_init(); RTE_display_start_screen(); while(SHOOT_BUTTON_READ); while(1){ RTE_display_black_background(); RTE_create_player_spaceship(&PlayerSpaceship); RTE_draw_player_spaceship(&PlayerSpaceship); RTE_create_asteroid(&AsteroidVect,Asteroid,numOfAsteroidInWave[currentWa ve],&PlayerSpaceship); RTE_draw_asteroid(&AsteroidVect); RNG_deinit(); RTE_start_update_frame(); while(1){ if(frameUpdate == SET){ RTE_display_score(); RTE_update_player_spaceship(&PlayerSpaceship); RTE_draw_player_spaceship(&PlayerSpaceship); RTE_create_rocket(&RocketVect,Rocket,&PlayerSpaceship); RTE_update_rocket(&RocketVect,&AsteroidVect); RTE_draw_rocket(&RocketVect); RTE_update_asteroid(&AsteroidVect,&PlayerSpaceship); RTE_draw_asteroid(&AsteroidVect); if(PlayerSpaceship.Object_Property.aliveFlag == RTE_ALIVE_FALSE){ PROTOBOARD_GREEN_LED_ON; RTE_display_game_over_screen(); while(SHOOT_BUTTON_READ); RTE_reset_game(); PROTOBOARD_GREEN_LED_OFF; break; } if(AsteroidVect.total == 0){ TIM_ctr(TIM6,STOP); currentWave++; RNG_init(); RTE_create_asteroid(&AsteroidVect,Asteroid,numOfAsteroidInWave[currentWave],&PlayerSpaceship); TIM_ctr(TIM6,START); } frameUpdate = CLEAR; } } }}
第二個(gè)周期性的中斷產(chǎn)生DAC需要的數(shù)據(jù),以產(chǎn)生相應(yīng)的音頻效果:
#ifdef SPEAKER_USE_TIMER7 void TIM7_IRQHandler (void){ TIM_intrpt_handler(TIM7); DAC_write(&DACxHandle,*(soundPtrGlobal++)); if(soundPtrGlobal == soundEnd){ speaker_stop_sound(); } }#endif
創(chuàng)建特殊的空間維度:
/***********************************************************************Private function: Wrap coordinate***********************************************************************/void RTE_wrap_cordinate (int16_t *xPtr, int16_t *yPtr){ if (*xPtr < 0){ *xPtr += ILI9341_config.width; } if (*xPtr >= ILI9341_config.width){ *xPtr -= ILI9341_config.width; } if (*yPtr < 0){ *yPtr += ILI9341_config.height; } if (*yPtr >= ILI9341_config.height){ *yPtr -= ILI9341_config.height; }}
下面的示意 - 右邊慢慢消失,出現(xiàn)在左側(cè)
下面的代碼就是在左側(cè)重畫出圖像中右側(cè)消失掉的部分:
/***********************************************************************External function: Overwrite draw pixel function in ILI9341 driver library (in order to draw pixels going off screen)***********************************************************************/void ILI9341_draw_pixel (int16_t x, int16_t y, uint16_t color){ RTE_wrap_cordinate(&x,&y); ILI9341_set_active_area(x,x,y,y); ILI9341_send_command(ILI9341_MEM_WRITE); ILI9341_send_parameter_16_bits(color);}
碰撞檢測:
/***********************************************************************Private function: Detect collision between 2 object using AABB algorithm***********************************************************************/uint8_t RTE_collision_detect (Space_Object_t *Object1Ptr, Space_Object_t *Object2Ptr){ int16_t Obj1BottomRight_X = Object1Ptr->Object_Property.x + Object1Ptr->Object_Image.imageWidth; int16_t Obj1BottomRight_Y = Object1Ptr->Object_Property.y + Object1Ptr->Object_Image.imageHeight; int16_t Obj2BottomRight_X = Object2Ptr->Object_Property.x + Object2Ptr->Obje ct_Image.imageWidth; int16_t Obj2BottomRight_Y = Object2Ptr->Object_Property.y + Object2Ptr->Object_Image.imageHeight; if (Object1Ptr->Object_Property.x < Obj2BottomRight_X && Object2Ptr->Object_Property.x < Obj1BottomRight_X && Object1Ptr->Object_Property.y < Obj2BottomRight_Y && Object2Ptr->Object_Property.y < Obj1BottomRight_Y){ return RTE_COLLISION_TRUE; } return RTE_COLLISION_FALSE;}
責(zé)任編輯:xjx
原文標(biāo)題:基于STM32F4的手持式游戲機(jī)如何實(shí)現(xiàn)?
文章出處:【微信公眾號(hào):FPGA入門到精通】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
-
STM32
+關(guān)注
關(guān)注
2290文章
11017瀏覽量
362467 -
手持設(shè)備
+關(guān)注
關(guān)注
0文章
48瀏覽量
24274 -
游戲機(jī)
+關(guān)注
關(guān)注
9文章
302瀏覽量
34323
原文標(biāo)題:基于STM32F4的手持式游戲機(jī)如何實(shí)現(xiàn)?
文章出處:【微信號(hào):xiaojiaoyafpga,微信公眾號(hào):電子森林】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
STM32F3系列、STM32F4系列、STM32L4系列和STM32L4+系列Cortex-M4編程手冊
松下4K手持式攝錄一體機(jī)AJ-UPX380介紹
手持式移動(dòng)智能終端如何做到濕手或佩戴手套也能使用?

智慧工廠為什么要使用手持式智能終端

樹莓派復(fù)古游戲機(jī):用科技重現(xiàn)經(jīng)典,讓童年永不落幕!

使用SPI進(jìn)行通信,STM32F4做從機(jī),通信時(shí)數(shù)據(jù)異常怎么解決?
stm32f4 sdio時(shí)鐘如何獲取通過什么函數(shù)?
手持式地物光譜儀的優(yōu)勢解析

Simcenter SCADAS XS手持式數(shù)據(jù)采集系統(tǒng)

手持式RFID讀寫器可以當(dāng)pda手持終端用嗎

STM32項(xiàng)目實(shí)戰(zhàn):基于STM32F4的智能燈光控制系統(tǒng)(LVGL),附項(xiàng)目教程/源碼

手持式地物光譜儀:野外遙感環(huán)境監(jiān)測的革命性工具

評論