賈莉
引言
我在剛開始學習C語言的時候只有一個目的,就是給51單片機機器人編寫程序。每學習一個抽象的知識點,就可以通過機器人的動作,形象地表現(xiàn)出來,每完成一段程序會很有成就感。這種學習方式有兩個好處,即可以加深理解和正向激勵。后期,我接觸到java和C++之類的語言,感覺奮斗了半天,只是在屏幕上出現(xiàn)了“Hello world!”,或者控制臺出現(xiàn)了“0110”之類的數(shù)字,瞬間積極性被打消很多。人們更容易理解形象直觀的東西,通過一些實驗發(fā)現(xiàn),做一些小游戲或者網(wǎng)頁動畫,更容易讓初學者喜歡上編程。
現(xiàn)在市面流行的青少年代碼編程語言,有Python,JavaScript,HTML等可以做小游戲的語言(小學段),還有C++語言,學習它是用來參加信息學奧林匹克競賽的(初高中段)。細看學習內(nèi)容,兩個年齡段銜接是有縫隙的。Python雖然熱度高,但學習的知識點無外乎“變量”“if else”“for while”之類的基礎知識。如果直接用C++語言來制作小游戲,用這種方式學習能達到相同的效果。而且在以后,可以直接銜接到高級別的比賽如“信息學奧賽”等。因此,我制作了一個“飛機大戰(zhàn)”的小游戲,拆分以后即可用于課堂教學。
研究目的
利用“飛機大戰(zhàn)”小游戲,探究在小學階段C++語言的學習方式。
實驗環(huán)境
環(huán)境:Visual Studio-2019,Easy_X圖形庫,C++語言。
當初計劃使用Turbo C來編寫這個程序,但通過實踐環(huán)節(jié)驗證,這個環(huán)境太老了,復制粘貼都不太方便。最后選擇了安裝VS2019集成開發(fā)環(huán)境,這個軟件兼容很多語言,對非企業(yè)版本用戶是免費的,非常方便使用。
然后下載安裝easyX圖形庫插件,借助VS2019優(yōu)秀的編輯和調(diào)試環(huán)境,再用easyX避開了注冊窗口等非常復雜的操作,這樣就能輕松繪制出圖片或者圖形。這對于初學者來說,是非常容易接受的。
實驗內(nèi)容及實驗原理
1.需求分析(如圖1)
2.流程設計(如下頁圖2)
3.詳細設計
(1)繪制背景
背景圖比較好做,把找到的背景圖片直接放到窗口坐標(0,0)的位置。窗口的大小與背景圖大小一致。
解決背景不能動的問題:
這樣背景的是不能動的,為了模擬飛機和背景的“相對移動”,可以讓背景向上移動。在這里我們需要兩個背景圖,當?shù)谝粡埍尘皥D移動步數(shù)超過本身的長度像素數(shù)值時,就恢復(0,0)從頭開始。第二張背景圖一直跟在第一張背景圖的下面,這樣循環(huán)起來,就能實現(xiàn)動態(tài)的背景。
(2)繪制飛機
先從網(wǎng)上找一些飛機的圖片素材,再使用ps軟件,把圖片處理成透明圖,起名叫hero.png,導入到窗體。直接把飛機的透明圖hero.png放到背景上,會有黑色的邊緣。如何處理這種情況呢?需要制作一張掩碼圖。另外,利用三元光柵操作,可以制作出沒有黑邊的飛機。
(3)按鍵控制
點擊鍵盤的上下左右按鍵,來控制英雄飛機的移動。飛機的移動即坐標的加減,增減量的多少,就是飛機的速度。
首先聲明一個名字叫key的子函數(shù)。
子函數(shù)內(nèi)容是:①先判斷“鍵盤按鍵”是否被按下,當_kbhit()等于1的時候,鍵盤被按了。②如果鍵盤被按下,就把_getch()獲取的按鍵值賦予變量mo儲存起來。③else否則,也就是鍵盤沒有被按下的時候,mo一直賦值為0。這段程序,就完成了檢測按鍵值的任務。
下面就可以根據(jù)mo的值的不同來完成不同的動作:當按下“向上”按鍵的時候,mo的值為72;當按下“向下”按鍵的時候,mo的值為80;當按下“向左”按鍵的時候,mo的值為75;當按下“向右”按鍵的時候,mo的值為77。
用switch語句來判斷mo的值:如果mo等于72,也就是按了“向上”按鍵,我方飛機(英雄機)的y坐標減少10;如果mo等于80,也就是按了“向下”按鍵,我方飛機(英雄機)的y坐標增加10;如果mo等于75,也就是按了“向左”按鍵,我方飛機(英雄機)的x坐標減少10;如果mo等于77,也就是按了“向右”按鍵,我方飛機(英雄機)的x坐標增加10;如果不是以上幾個數(shù)字,直接break,不做任何變化。
(4)發(fā)射子彈,讓子彈動起來
為了實現(xiàn)發(fā)射子彈的效果,首先處理了兩張子彈的圖片,一張是“透明圖”,一張是“掩碼圖”。然后利用三元光柵操作,制作出透明的子彈圖片。在這里,子彈的原圖不要做得太大,除了子彈的主體圖之外,邊緣部分盡可能減少,這樣能方便后期制作“子彈”碰到“敵飛機”的效果,減少誤差。
第一種發(fā)射子彈的方式:直接將子彈圖片的左上角坐標——變量初始值設定為飛機頭部的坐標(x+20,y-10),讓子彈的y坐標每隔一段時間就減少一定量。這樣就能實現(xiàn)發(fā)射子彈的效果,但是屏幕上只能存在一顆子彈?!暗谝活w”子彈不消失,“第二顆”子彈就不能發(fā)射出來。其實,它們本來就是同一個。
第二種發(fā)射子彈的方式:要想實現(xiàn)連續(xù)發(fā)射子彈的效果,需要聲明一個隊列儲存子彈的變量。讓子彈在飛機頭部發(fā)射,子彈每隔一段時間,坐標減少5,實現(xiàn)了子彈向上飛。當子彈變量減少到小于0的時候,不再壓入隊列,子彈消失。這樣能實現(xiàn)連續(xù)發(fā)射的效果,所以我采用了這種方式。
(5)碰撞檢測
子彈與敵飛機的碰撞檢測程序:先遍歷fire隊列里面的子彈坐標,再把每一個子彈的坐標和敵飛機的坐標做比較。如果子彈與敵飛機碰撞,被擊中的敵飛機坐標就不再壓入隊列。后面在運行Print_fire()的時候,這架被擊中的敵機就不會被繪制出來。每檢測一個子彈的坐標,先把KillEnemy變量改為0,當有敵機被擊中的時候,KillEnemy變量改為1,KillEnemy作為一個標記。如果這顆子彈擊中了敵機,那它也消失,就是不再繼續(xù)壓入隊列了。這樣就實現(xiàn)了當子彈擊中敵機的時候,敵機消失、子彈消失的效果。
(6)設置時間間隔
這個相當于兩個計時器,主函數(shù)每執(zhí)行一次,程序會Sleep(5)5毫秒,切T和T2變量都加1。
當T>=a,也就是主函數(shù)重復執(zhí)行了a次的時候,產(chǎn)生一個新的子彈,然后T賦值為0,重新開始計時。
當T2>=b,也就是主函數(shù)重復執(zhí)行了b次的時候,產(chǎn)生一個新的敵飛機,然后T2賦值為0,重新開始計時。
總的來說,a越大,子彈出現(xiàn)的時間間隔就越大,b越大,敵飛機出現(xiàn)的時間間隔就越大。
(7)打印我方飛機
在打印我方飛機之前,先遍歷每一架敵飛機的坐標。如果我方飛機與敵飛機相撞則life生命值減1,主函數(shù)檢測到生命值小于0,則游戲停止。
檢測碰撞的方式跟檢測子彈碰撞敵飛機的方式相同。
首先設定我方英雄機的坐標(x, y),英雄機的像素是57*45,那么子彈的中心坐標大約是(t.x+30, t.y+22)。接著確定敵飛機的坐標(u.x, u.y) ,敵飛機的像素是50*68,那么敵飛機的中心坐標大約是(u.x+25, u.y+12)。然后把敵飛機和英雄機的外形類比成一個圓,英雄機的圓半徑p大約是12,敵飛機的圓半徑R大約是34。如果英雄機的圓心到敵飛機圓心的距離小于p+R的和,那么就證明英雄機與敵飛機相撞了。
(8)顯示英雄機的生命值Life和得分Score(如圖3)
結論
繪制圖片→變量控制坐標→按鍵控制→敵飛機及子彈的(隊列)繪制→循環(huán)遍歷(碰撞檢測)。這幾個步驟能直觀地呈現(xiàn)學習效果,能由淺入深地進入編程的學習之路。
參考文獻:
[1]殷志堅,段曉磊.基于EasyX的俄羅斯方塊游戲的設計和分析[J].科技傳播,2015,7(21):137+157.
[2]趙敏,龐蕊.基于EasyX圖形庫的C語言課程改革研究與實踐[J].電腦知識與技術,2015,11(32):124-125.