歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Linux系統下用C語言編寫2D圖形游戲

Linux系統下用C語言編寫2D圖形游戲

日期:2017/3/1 10:38:09   编辑:Linux編程

在Linux系統下,不要以為C語言就只能寫那種只有字符的控制台程序,別忘了,Linux系統有FrameBuffer(幀緩沖),只要顯示器是彩色的,並且是linux系統的,就可以用C語言代碼通過讀寫FrameBuffer裡的數據在屏幕上繪制圖形;

圖形嘛,有png庫,用它的函數解碼圖片文件,得到圖片數組,共有red、green、blue、alpha四種數組,alpha用於圖片之間的組合,最終將RGB數組輸出到FrameBuffer就能顯示了;

想要動態圖形效果,自己用算法實現。

目前,我正在為自己的嵌入式設備開發一個游戲,圖形素材來源於互聯網,游戲截圖如下圖所示:


如上圖所示,主菜單中的紅色光標有閃爍效果,游戲畫面切換有淡入淡出效果。

下面有源碼,現在使用的按鍵控制方法的效果不理想。

linux系統環境,按鍵判斷,使用了getch()和kbhit()函數,函數是模擬實現的。

為了判斷按鍵是否為按住狀態,我使用一個變量count來計數,每循環一次自增,也就是按鍵檢測延遲的最大時間,超過了這段時間,如果getch()函數沒有再次返回接受到同樣的按鍵的鍵值,那麼就判斷為這個按鍵已經釋放,否則,該按鍵處於按住狀態,並繼續顯示之前的動作。

還有圖形顯示,目前沒掌握局部刷新的技術,游戲顯示的每一幀圖形都是全屏刷新的,效率低,每秒大概刷新4幀。

源碼只提供部分:

[cpp]
  1. void next_frames(void)
  2. {//更新到下一幀
  3. frames[0] += speed[0];//玩家1的
  4. frames[1] += speed[1];//AI的
  5. }
  6. void init_player_data(void)
  7. //初始化各個玩家的數據
  8. {
  9. direction[0] = IS_RIGHT;//玩家朝向右邊
  10. direction[1] = IS_LEFT;//AI角色朝向左邊
  11. //各個角色的初始位置
  12. map_site_x[0] = 100;
  13. map_site_x[1] = 300;
  14. map_site_y[1] = map_hight - 20;
  15. map_site_y[0] = map_hight - 20;//在地圖上的坐標
  16. speed[0] = 1;//每次循環幀frames自增的的值,之前是想做能設置游戲刷新速度的功能,現在已拋棄,這個變量貌似沒用了。
  17. speed[1] = 1;
  18. need_move[0] = 0;//玩家是否需要移動
  19. need_move[1] = 0;//AI是否需要移動
  20. can_use_next[0] = 0;//可以使用下一個動作
  21. can_use_next[1] = 0;//AI可以使用下一個動作
  22. status[0] = STANCE;//玩家為站立狀態
  23. status[1] = STANCE;//AI為站立狀態
  24. shock_wave_num = 0;//沖擊波的總數為0
  25. need_view_shock_wave = 0;//不需要顯示沖擊波
  26. }
  27. int play_game(void)
  28. {
  29. unsigned char **game_map;//游戲地圖
  30. int map_id,temp_key = 0,count = 0,key = 0,man_id;//人物代號
  31. //分配內存
  32. man_id = ICHIGO;//人物動畫選擇黑崎一護
  33. init_player_data();//初始化玩家數據
  34. map_id = 1;
  35. if(map_id == 1) {
  36. game_map = load_map_1();//載入地圖數據
  37. }
  38. while(1){
  39. update_graph();//規定鏡頭,顯示玩家所在的區域的圖形
  40. view_map_area(game_map[0],game_map[1],game_map[2]);//根據主角的位置,顯示地圖中的某個區域
  41. if(kbhit()){//調用kbhit()函數檢測是否有按鍵輸入
  42. key = getch();//有按鍵輸入就用getch()函數獲取鍵值並賦給key,下面開始判斷key的值
  43. if(key == KEY_BACK) break;
  44. if(key == 'w' || key == 'W' || key == KEY_UP) {
  45. temp_key = key;
  46. }
  47. else if((key == 'd' || key == 'D' || key == KEY_RIGHT) && status[0] != JUMP_ATTACK){//如果按的是a鍵或者左鍵
  48. if((temp_key == 'd' || temp_key == 'D' || temp_key == KEY_RIGHT)&& count < 5) {
  49. next_action[0] = WALK;//下一個動作還是行走
  50. }
  51. else if(can_use_next[0] == 0){//如果之前沒有按過a鍵或者左鍵,並且,可以使用下一個動作
  52. if(temp_status[0] != JUMP) {//如果之前不是跳躍狀態
  53. status[0] = WALK;
  54. if(temp_status[0] != WALK) frames[0] = 0;//如果之前不是行走狀態
  55. else if(temp_status[0] == WALK){//如果之前是行走狀態
  56. next_action[0] = WALK;//下一個動作還是行走
  57. }
  58. }
  59. else need_move[0] = 1;//否則,需要移動
  60. }
  61. direction[0] = IS_RIGHT;
  62. need_move[0] = 1;
  63. temp_key = key;
  64. count = 0;//計數清零
  65. }
  66. else if((key == 'a' || key == 'A' || key == KEY_LEFT) && status[0] != JUMP_ATTACK){//如果按的是a鍵或者左鍵
  67. if((temp_key == 'a' || temp_key == 'A' || temp_key == KEY_LEFT)&& count < 5) {
  68. next_action[0] = WALK;//下一個動作還是行走
  69. }
  70. else if(can_use_next[0] == 0){//如果之前沒有按過a鍵或者左鍵,並且,可以使用下一個動作
  71. if(temp_status[0] != JUMP) {//如果之前不是跳躍狀態
  72. status[0] = WALK;
  73. if(temp_status[0] != WALK) frames[0] = 0;//如果之前不是行走狀態
  74. else if(temp_status[0] == WALK){//如果之前是行走狀態
  75. next_action[0] = WALK;//下一個動作還是行走
  76. }
  77. }
  78. else need_move[0] = 1;//否則,需要移動
  79. }
  80. direction[0] = IS_LEFT;
  81. need_move[0] = 1;
  82. temp_key = key;
  83. count = 0;//計數清零
  84. }
  85. else if(key == 's' || key == 'S' || key == KEY_DOWN){//如果按的是s鍵或者是下鍵
  86. if(can_use_next[0] == 0){
  87. status[0] = BLOCK;
  88. if((temp_key == 's' || temp_key == 'S' || temp_key == KEY_DOWN) && count <10){
  89. //如果之前按過s鍵或者是下鍵,並且在最大延遲時間內
  90. if(temp_status[0] == BLOCK && status[0] == BLOCK)//如果之前的動作是防御
  91. {
  92. frames[0] = 2;speed[0] = 0;
  93. }
  94. }
  95. else {
  96. frames[0] = 0;//幀數歸零www.linuxidc.com
  97. speed[0] = 1;
  98. }
  99. }
  100. temp_key = key;//保存按鍵的鍵值
  101. count = 0;//計數歸零
  102. }
  103. else if(key == 'j' || key == 'J'){//如果按的是j鍵
  104. if(temp_status[0] == JUMP || temp_status[0] == JUMP_ATTACK)//如果之前還處於跳躍狀態
  105. {
  106. if(jump_attack_num == 0) {
  107. status[0] = JUMP_ATTACK;//跳躍攻擊
  108. jump_attack_num = 1;
  109. }
  110. }
  111. else if(status[0] == DOWN_ATTACK || status[0] == BLOCK || temp_key == KEY_DOWN || temp_key == 's' || temp_key == 'S'){
  112. status[0] = DOWN_ATTACK;
  113. if(temp_status[0] != DOWN_ATTACK) frames[0] = 0;//幀數歸零
  114. }
  115. else if(temp_key == KEY_UP || temp_key == 'w' || temp_key == 'W'){
  116. if(can_use_next[0] == 0){//如果可以使用下一個動作
  117. status[0] = UP_ATTACK;
  118. frames[0] = 0;//幀數歸零
  119. }
  120. }
  121. else if((temp_key == 'j' || temp_key == 'J') && count <5){//如果之前按過j鍵,並且在最大延遲時間內
  122. if(temp_status[0] == FIRST_ATTACK && status[0] == FIRST_ATTACK)//如果之前處於第一段攻擊狀態下
  123. {
  124. status[0] = FIRST_ATTACK;
  125. if(can_use_next[0] == 0 && first_attack_complete[0] == 0){//如果可以使用下一個動作
  126. status[0] = SECOND_ATTACK;//開始進行第二段攻擊
  127. frames[0] = 0;//幀數歸零www.linuxidc.com
  128. }
  129. else{
  130. next_action[0] = SECOND_ATTACK;//保存下一個動作,等待之前的動作完成
  131. }
  132. }
  133. else if(temp_status[0] == SECOND_ATTACK || status[0] == SECOND_ATTACK)//如果之前處於第二段攻擊狀態下
  134. {
  135. status[0] = SECOND_ATTACK;
  136. if(can_use_next[0] == 0 && second_attack_complete[0] == 0){//如果可以使用下一個動作
  137. status[0] = THIRD_ATTACK;//開始進行第二段攻擊
  138. frames[0] = 0;//幀數歸零
  139. }
  140. else{
  141. next_action[0] = THIRD_ATTACK;//保存下一個動作,等待之前的動作完成
  142. }
  143. }
  144. else if(temp_status[0] == THIRD_ATTACK || status[0] == THIRD_ATTACK)//如果之前處於第二段攻擊狀態下
  145. {
  146. status[0] = THIRD_ATTACK;
  147. if(can_use_next[0] == 0 && third_attack_complete[0] == 0){//如果可以使用下一個動作
  148. status[0] = FIRST_ATTACK;//開始進行第一段攻擊
  149. frames[0] = 0;//幀數歸零
  150. }
  151. else{
  152. //next_action = FIRST_ATTACK;//保存下一個動作,等待之前的動作完成
  153. }
  154. }
  155. else{
  156. status[0] = FIRST_ATTACK;
  157. frames[0] = 0;
  158. }
  159. }
  160. else {
  161. status[0] = FIRST_ATTACK;
  162. if(temp_status[0] != FIRST_ATTACK) frames[0] = 0;
  163. }
  164. speed[0] = 1;
  165. count = 0;
  166. temp_key = key;//保存按鍵的鍵值
  167. }
  168. else if((key == 'k' || key == 'K') && can_use_next[0] == 0){//如果按的是k鍵,並且能使用下一個動作
  169. status[0] = JUMP;
  170. count = 0;
  171. jump_attack_num = 0;
  172. frames[0] = 0;
  173. }
  174. else if(key == 'U' || key == 'u'){
  175. if(status[0] == DOWN_Y_ATTACK || status[0] == BLOCK || temp_key == KEY_DOWN || temp_key == 's' || temp_key == 'S'){
  176. speed[0] = 1;
  177. status[0] = DOWN_Y_ATTACK;
  178. if(temp_status[0] != DOWN_Y_ATTACK) frames[0] = 0;//幀數歸零
  179. }
  180. else if(can_use_next[0] == 0){//如果可以使用下一個動作
  181. status[0] = Y_ATTACK;//開始進行第二段攻擊
  182. frames[0] = 0;//幀數歸零
  183. }
  184. else{
  185. next_action[0] = Y_ATTACK;//保存下一個動作,等待之前的動作完成
  186. }
  187. count = 0;
  188. temp_key = key;
  189. }
  190. else if(key == 'L' || key == 'l'){
  191. if(can_use_next[0] == 0){//如果可以使用下一個動作
  192. status[0] = DASH;
  193. frames[0] = 0;//幀數歸零
  194. }
  195. else{
  196. next_action[0] = DASH;//保存下一個動作,等待之前的動作完成
  197. }
  198. need_move[0] = 1;//需要移動
  199. }
  200. }
  201. else if(count > 5 && can_use_next[0] == 0) {//如果在計數大於5時還沒有接收到按鍵輸入,並且可以使用下一個動作
  202. status[0] = STANCE;//狀態改為站立
  203. speed[0] = 1;
  204. temp_key = 0;
  205. count = 0;//計數清零www.linuxidc.com
  206. }
  207. if_need_move(0,count);//判斷是否需要移動
  208. if(man_id == ICHIGO) ichigo(0);//使用黑崎一護的動作圖形
  209. ichigo(1);
  210. next_frames();//更新到下一個幀
  211. write_to_fb(screen[0],screen[1],screen[2]);//顯示圖形
  212. //usleep(10000);//之前用過usleep(30000),犧牲幀的刷新速度,獲得按鍵響應效果的提升,我認為這不值
  213. count++;//計數自增
  214. }
  215. //釋放背景圖占用的內存
  216. free(game_map[0]);
  217. free(game_map[1]);
  218. free(game_map[2]);
  219. free(game_map);
  220. return 0;
  221. }
  222. int main()
  223. {
  224. init_game();//初始化游戲,獲取屏幕尺寸,分配內存
  225. game_boot();//顯示游戲啟動畫面
  226. main_menu();//顯示游戲主菜單
  227. system("stty echo");
  228. return 0;
  229. }
Copyright © Linux教程網 All Rights Reserved