從C語言到第一個黑框游戲
0.序言
經過一整個學期的學習,同學們對於C語言是從入門到放棄呢?還是從入門到絕望?
其實與純粹的理論學習不同,編程是一門實踐性很強的學問,擅於將書中所學用於實踐才能真正學好編程,發現編程的樂趣。在此,我想簡單講講如何用大一上學期學會的C語言,來編寫一個簡單的貪吃蛇游戲。(ps:在這里,我只想寫思路,而不介紹具體的編程細節,因為希望你更多的能從這篇文章中學習將知識應用於實踐中的思考方式和能力。)
1. 准備
我們知道,剛開始學習編程,用C語言在黑框框中將數據輸入,然后經過一系列邏輯處理再輸出出來,好像就是C語言所能達到的極限了?其實不然,只要善於發揮想象力。不過,在一切開始之前,我們需要對任務進行簡單的分析:
2. 功能需求
首先,我們要有一條蛇,其次我們要讓它動起來,接着再隨機生成一些“食物”,當蛇頭碰到食物時,蛇的長度便增加,如果蛇頭撞到牆,那么游戲結束。為了美觀,我們用特殊符號●表示蛇,用★表示食物,用■表示牆。這些符號不難找到,但是我們還需要知道他們對應的ASC碼,怎么做呢?很簡單,輸入符號型,輸出整型即可。
3. 一些必要的工具
根據功能分析,我們需要在屏幕上的任意位置打印出蛇和食物,所以我們需要一個能夠將光標移動到運行框任意位置的函數:
#include<windows.h>
int gotoxy(int x,int y)
{
COORD cd;
cd.X=x;
cd.Y=y;
return SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),cd);
}
我們還需要能夠實時獲取鍵盤輸入的函數,這里要稍微提一下,我們用輸入設備進行輸入時,操作系統會將這些輸入以隊列(先進先出)的形式存儲在輸入緩沖區中,然后依次讀出給相應的應用使用。所以我們需要有一個函數判斷,當前鍵盤輸入緩沖區中是否有值,如果有,則讀出來。這個判斷的函數我使用:kbhit()。所以就有:
if(kbhit())
{
getch();
}
在寫貪吃蛇之前,我也不知道有這些函數的存在,所以說需求永遠是學習的第一生產力。
4. 讓蛇動起來
相信大家都能很輕松的將界面和蛇打印出來,例如這樣:
而對於如何讓它動起來可能毫無頭緒。遇到毫無頭緒的問題時,我們需要將問題稍微分解一下:
- 怎樣做會有動畫的效果?我們知道,當變化的圖片的刷新速度快達30幀時,在人眼看來就會有動畫的效果。所以我們要做的就是不停的更新蛇的位置,並且打印出來
- 如何更新蛇的位置?最朴素的方法是,我把原來的位置“擦除”,然后在再新的位置重新設定一條蛇,這樣做未嘗不可,但其實我們有更好的方法,那就是擦除蛇尾,並且在蛇頭前進的方向添加一個蛇頭,怎么做? 對應數組的寫法就是 :
二維數組對應鏈表的寫法就是 : 就是鏈表插入和刪除嘛,圖不好做,不做了
皮的嘛,就不談了 - 蛇如何轉向?首先你要限定蛇是不能向目前前進方向或者其反方向轉向的,其次你要定義一個全局變量direction(上下左右)表示蛇目前會一直往這個方向走,最后只要在讀取到鍵盤輸入時,根據輸入改變前進方向,並在那個方向添加一個蛇頭,前進方向自然就變了
- 數據更新完打印界面一閃一閃的?正常,因為你把整個界面都擦除再打印,如果程序跑的不夠快,那么就會出現這種情況,這里我想提一下,雖然我們是很朴素的寫一個貪吃蛇,但是這里其實就已經涉及到一個很重要的知識,畫面刷新。我們知道,畫面的繪制對於計算機來說是一個巨大的負擔,所以我們為了提高繪圖的速度,在需要自己實現繪圖的一些底層應用或者游戲引擎中,往往采用局部刷新、圖層疊加,緩沖區繪制等的方式優化性能,即只更新需要變化的局部畫面,對於可以覆蓋更新的圖層直接覆蓋,對於需要多個圖層繪制的畫面繪制先在緩沖區中“繪制”,繪制完再進行真正的屏幕繪制
5. 碰撞檢測
和現實世界不同,游戲世界的碰撞是我們通過數學和邏輯方法判斷的,所以碰撞檢測就變得極為重要,它是你的游戲世界成型的根本。如果你的目標是成為一個游戲開發人員,相信我碰撞檢測將是你的朋友,和繪圖方法一樣,碰撞檢測是一灘極深的水,而這里我們講的是最簡單的碰撞檢測,點和點之間的碰撞檢測,這其實很簡單,判斷兩個點是否重復,就看坐標(x,y)值是否相同就好了,以屏幕左上角為坐標原點,建立xy坐標系,你的蛇頭就是一個坐標點(x1,y1),而牆上每一塊磚有它的坐標,食物也是如此。
6. 結束
其實到這里,做一個貪吃蛇游戲會遇到的一些基本難題我已經幫你一一列舉並提供了基本的解決方案,而具體實現中其實你還會遇到許多邏輯上的問題,不過這都不重要,重要的是,我們通過做一個貪吃蛇,學到了最基礎的繪圖方法和碰撞檢測。記住這些名詞,它們將是你裝逼的利器。
逼是一樣的逼,裝上見高低
-----某不知名java老師如此說道
©宇
