C語言實(shí)現(xiàn)飛機(jī)游戲(2)
本文實(shí)例為大家分享了C語言實(shí)現(xiàn)飛機(jī)游戲的具體實(shí)現(xiàn)代碼,供大家參考,具體內(nèi)容如下
本節(jié)我們將在上一節(jié)的基礎(chǔ)上對(duì)飛機(jī)游戲進(jìn)行改造完善。
基本框架
從本節(jié)起,為了避免把所有代碼都放進(jìn)main函數(shù)而使得代碼看起來臃腫,我們將通過以下基本框架來實(shí)現(xiàn)游戲內(nèi)容。
//全局變量定義 int main(){ ?? ?startup(); //游戲初始化 ?? ?while(1) //游戲循環(huán)體 ?? ?{ ?? ??? ?show(); //顯示界面 ?? ??? ?updateWithoutInput(); //與輸入無關(guān)的更新 ?? ??? ?updateWithInput(); //與輸入有關(guān)的更新 ?? ?} ?? ?return 0; }
代碼重構(gòu)
現(xiàn)在我們要對(duì)上一節(jié)的代碼通過基本框架來重構(gòu)一遍。
#include <stdio.h> #include <stdlib.h> #include <conio.h> //全局變量 int position_x,position_y; //飛機(jī)坐標(biāo) int high,width; //畫面尺寸 void startup() //數(shù)據(jù)初始化 { ?? ?high = 20; ?? ?width = 30; ?? ?position_x = high/2; ?? ?position_y = width/2; } void show() //顯示畫面 { ?? ?system("cls"); //清屏函數(shù),linux使用clear命令 ?? ?int i,j; ?? ?for(i=0; i<high; i++){ ?? ??? ?for(j=0; j<width; j++){ ?? ??? ??? ?if((i==position_x)&&(j==position_y)) ?? ??? ??? ??? ?printf("*"); //輸出飛機(jī) *? ?? ??? ??? ?else ?? ??? ??? ??? ?printf(" "); //輸出空格 ?? ??? ?} ?? ??? ?printf("\n"); ?? ?} } void updateWithoutInput() //與輸入無關(guān)的更新 { } void updateWithInput() //與輸入有關(guān)的更新 { ?? ?char input; ?? ?if(kbhit()) //判斷是否有輸入 ?? ?{ ?? ??? ?input = getch(); ?? ??? ?if(input=='a') ?? ??? ??? ?position_y --; ?? ??? ?if(input=='d') ?? ??? ??? ?position_y ++; ?? ??? ?if(input=='w') ?? ??? ??? ?position_x --; ?? ??? ?if(input=='s') ?? ??? ??? ?position_x ++;?? ??? ? ?? ?} } int main(){ ?? ?startup(); ?? ?while(1){ ?? ??? ?show(); ?? ??? ?updateWithoutInput(); ?? ??? ?updateWithInput(); ?? ?} ?? ?return 0; }
新款子彈
之前我們實(shí)現(xiàn)的激光是覆蓋整條線的,對(duì)于敵人來說比較不友好(反正挨打的是敵人),那么為了保證游戲體驗(yàn)(并沒有),我們?cè)诖私o游戲加一個(gè)新款子彈。
可以設(shè)置初始化子彈坐標(biāo):
// 子彈在飛機(jī)上方 bullet_x = position_x - 1; // 子彈 y 坐標(biāo)不變 bullet_y = position_y; // 每次循環(huán)子彈往上飛 1 bullet_x --;?
所以我們需要在 show() 函數(shù) 與 update 中加入控制子彈的代碼:
// 定義子彈坐標(biāo)變量 int bullet_x,bullet_y; //初始化子彈 bullet_x = -1; bullet_y = position_y; // 寫在輸出循環(huán)中 if ... else if ((i==bullet_x)&&(j==bullet_y)) ?? ?printf("|"); //輸出子彈 else ... // 子彈前進(jìn) void updateWithoutInput() { ?? ?if(bullet_x > -1) ?? ??? ?bullet_x --; } // 寫在用戶輸入判斷中 if(input == ' ') {?? ? ?? ?// 子彈在飛機(jī)上方 ?? ?bullet_x = position_x - 1; ?? ?// 子彈 y 坐標(biāo)不變 ?? ?bullet_y = position_y; }
敵機(jī)【終于來了】
用“@”表示敵機(jī),用 enemy_x 和 enemy_y 表示敵機(jī)坐標(biāo),使用和加入子彈大致一樣的方法加入敵機(jī)。
注意:敵機(jī)的移動(dòng)不能和子彈那樣,不然每回你只能看到一個(gè)大黑耗子跑過去了。
// 敵機(jī)位置 int enemy_x,enemy_y; // 數(shù)據(jù)初始化 enemy_x = 0; enemy_y = position_y; // 加入輸出循環(huán) if ... else if ((i==enemy_x)&&(j==enemy_y)) ?? ?printf("@"); else ... // 控制敵機(jī)移動(dòng) static int speed = 0; if(speed<10) ?? ?speed ++; if(speed == 10){ ?? ?enemy_x ++; ?? ?speed = 0; }
可以看到,在實(shí)現(xiàn)敵機(jī)移動(dòng)時(shí),我們?yōu)榱吮苊獬霈F(xiàn)大黑耗子嗖一下就過去的問題使用了 static 關(guān)鍵字來定義一個(gè)靜態(tài)變量 speed 從而實(shí)現(xiàn)敵機(jī)緩慢移動(dòng)。
由 static 定義的局部變量在每次循環(huán)不會(huì)重新定義它的值,第一次循環(huán)會(huì)根據(jù)語句把 speed 定義為 0 ,而在之后的循環(huán)中不會(huì)重新執(zhí)行該賦值語句。
每次循環(huán)判斷當(dāng)其值小于 10 時(shí)則加一,并繼續(xù)以后語句。若其值等于 10 ,則將敵機(jī) x 坐標(biāo)加一(也就是敵機(jī)移動(dòng)),并重新將 speed 歸零。
擊殺與得分
沒錯(cuò),在完成以上代碼之后你就會(huì)發(fā)現(xiàn):
屏幕上出現(xiàn)了兩個(gè)鎖血掛!!
怎么打都打不死,而且一個(gè)飛著飛著就沒了!
所以我們需要增加擊殺功能,當(dāng)然還有得分(擊殺獲得)。
而且在每次擊殺以后都要生成新的敵機(jī)(其實(shí)就是敵機(jī)坐標(biāo)重新賦值)。
// 加入updateWithoutInput更新循環(huán) if((bullet_x == enemy_x)&&(bullet_y == enemy_y)) { //子彈擊中敵機(jī) ?? ?score ++; //得分加一 ?? ?// 敵機(jī)刷新 ?? ?enemy_x = -1; ?? ?enemy_y = rand() % width; ?? ?bullet_x = -2; //子彈無效,如果你希望子彈能穿透的話可以去掉 } if(enemy_x > high) // 敵機(jī)飛出邊界 { ?? ?// 敵機(jī)刷新 ?? ?enemy_x = -1; ?? ?enemy_y = rand() % width; ?? ?// 可選,敵機(jī)出界得分減一 ?? ?score --; } // 定義得分并顯示 int score; // 顯示部分加在 show() 函數(shù)尾部 printf("得分: %d\n", score);
清屏升級(jí)
在實(shí)現(xiàn)以上代碼后,我們發(fā)現(xiàn)游戲時(shí)屏幕閃爍很嚴(yán)重,這里提供優(yōu)化清屏的方法。
//清屏前移動(dòng)光標(biāo) #include <windows.h> void gotoxy(int x, int y){ ?? ?HANDLE handle = GetStdHandle(STD_UOTPUT_HANDLE); ?? ?CROOD pos; ?? ?pos.X = x; ?? ?pos.Y = y; ?? ?SetConsoleCursorPosition(handle, pos); } //解決光標(biāo)閃爍 void HideCursor(){ ?? ?CONSOLE_CURSOR_INFO cursor_info = {1, 0}; //第二個(gè)值為0表示隱藏光標(biāo) ?? ?SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info); }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
解析C++中的for循環(huán)以及基于范圍的for語句使用
這篇文章主要介紹了解析C++中的for循環(huán)以及基于范圍的for語句使用,是C++入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2016-01-01如何利用最簡(jiǎn)單的C語言實(shí)現(xiàn)AI五子棋
這篇文章主要給大家介紹了關(guān)于如何利用最簡(jiǎn)單的C語言實(shí)現(xiàn)AI五子棋的相關(guān)資料,包含了一些五子棋常見的功能,文中也通過詳細(xì)的實(shí)例代碼和圖片介紹的非常詳細(xì),需要的朋友可以參考下2021-07-07C++跳轉(zhuǎn)語句之Goto對(duì)變量定義的影響詳解
goto語句也被稱為無條件轉(zhuǎn)移語句,這篇文章主要介紹了C++跳轉(zhuǎn)語句之Goto對(duì)變量定義的影響,文中通過示例代碼解文字介紹的很詳細(xì),相信對(duì)大家的理解和學(xué)習(xí)具有一定的參考借鑒價(jià)值,有需要的朋友們下面跟著小編一起來學(xué)習(xí)學(xué)習(xí)吧。2016-11-11