看完了了童晶老師的《做游戲智蝠,學(xué)編程》網(wǎng)課,自己嘗試著用C做了一個小游戲亥揖,主要實現(xiàn)了三個功能:galgame幻燈片劇情切換珊擂,打飛機小游戲,找不同游戲费变。利用了easyX的交互和圖形界面功能摧扇。下面對代碼實現(xiàn)進行總結(jié),以免遺忘胡控。
github:(https://github.com/iMaxmoe/game_saultyFish)
幻燈片切換
由于對easyX的函數(shù)并不熟悉扳剿,這里使用的是笨辦法旁趟,通過加載新圖片來實現(xiàn)劇情切換昼激。這種方法適用于于小體量的galgame庇绽,但一旦文本量大了,就會造成不小的負擔(dān)橙困。更優(yōu)解還是加載一張背景圖片瞧掺,變更文本框。
- 加載
IMAGE
對象凡傅,使用loadimage(&pic,"path")
函數(shù)辟狈。為了防止圖片切換過快,自定義了load()
函數(shù)夏跷,由putimage()
和Sleep()
兩部分組成哼转。 - 幻燈片切換主要依靠
while()
和switch()
語句,定義了click和jump兩個變量槽华,來控制切換圖片和跳出循環(huán)壹蔓。此處才深刻體會到了while()
和for()
的本質(zhì)區(qū)別。 - easyX的鼠標(biāo)交互函數(shù)
MOUSEMSG m;
while (MouseHit())
{
m = GetMouseMsg();
if (m.uMsg == WM_LBUTTONDOWN)
click++;
}
打飛機游戲
設(shè)置了3種攻擊對象猫态,引入了時間函數(shù)佣蓉,是三個主要功能中最復(fù)雜的部分。
對象繪制
- 由于畫面需要不斷更新亲雪,為免卡頓勇凭,使用了
BeginBatchDraw()
,FlushBatchDraw()
以及EndBatchDraw()
三個函數(shù)义辕。 - “退而求其次大法”:由于蠢虾标,給炮彈只設(shè)置了長度為3的數(shù)組,因此在連續(xù)射擊時出現(xiàn)了炮彈消失的Bug终息。這里炮彈并不是真正的消失夺巩,而是被重新定位到畫面外的位置。這也是游戲處理圖形對象的常用技巧周崭。
- easyX的
putimage()
函數(shù)非常好用柳譬,只需要定義兩個關(guān)于x和y坐標(biāo)的變量,就可以通過該函數(shù)實現(xiàn)圖形位置切換续镇。此處依舊是while()
函數(shù)美澳,在每個循環(huán)都需要更新畫面,幀切換實現(xiàn)動畫效果摸航。
炮彈邏輯
主要是速度調(diào)節(jié)(依賴循環(huán))和重新定位兩個功能制跟。
for (int j = 0; j < 3; j++)
{
if (speedBbl == 2)
{
bblY[j] -= 3;
speedBbl = 0;
}
if (bblY[j] <= 0) //bubble is out of the canvas
{
bblY[j] = -3000;//redirect and wait for the new launch
}
speedBbl++;
}
擊中怪物
由于怪物數(shù)量多,也需要設(shè)置數(shù)組酱虎,此處用for()
循環(huán)雨膨,同時涉及定位容錯問題。我采用的方法:用photoshop處理怪物遮罩圖读串,并且記錄圖片大小聊记。
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if ((bblX[j] < mons1X[i] + 35) && (bblX[j] > mons1X[i] - 35) && (bblY[j] < mons1Y[i] + 35) && (bblY[j] > mons1Y[i] - 35))
{
mons1X[i] = (rand() % 750) + 20;
mons1Y[i] = -200;
score++;
for (int j = 0; j<3; j++)
bblY[j] = -3000;
//set the music
mciSendString("close jpmusic", NULL, 0, NULL);
mciSendString("open .\\gameImage\\mons1.mp3 alias jpmusic", NULL, 0, NULL);
mciSendString("play jpmusic", NULL, 0, NULL);
}
}
同樣撒妈,需要定義怪物坐標(biāo)變量,并且在循環(huán)中更新怪物位置以實現(xiàn)降落效果排监。
怪物重生成則運用了隨機數(shù)狰右。
鼠標(biāo)交互
easyX()鼠標(biāo)定位函數(shù)以及click感知函數(shù)。
MOUSEMSG m;
while (MouseHit())
{
m = GetMouseMsg();
if (m.uMsg == WM_MOUSEMOVE)
{
fishX = m.x;
}
//for bubble 1
if ((m.uMsg == WM_LBUTTONDOWN) && (bblY[0] == -3000))
{
bblX[0] = fishX + 25;
bblY[0] = fishY - 50;
}
//for bubble after one
for (int j = 1; j < 3; j++)
{
if ((m.uMsg == WM_LBUTTONDOWN)&&(bblY[j-1]!=-3000))
{
bblX[j] = fishX + 25;
bblY[j] = fishY - 50;
}
}
}
}
通關(guān)判定
在while()
框架下嵌入兩個if()
判斷
void level1()
{
startup1();
while (1)
{ /*end of shooting*/
if (anger <= 0)
{
EndBatchDraw();
break;
}
if (left <= 0)
gameover1();
show1();
updateWithoutInput1();
updateWithInput1();
}
}
找不同游戲
主要利用的是鼠標(biāo)交互功能舆床。笨辦法:photoshop標(biāo)尺定位不同點的像素位置棋蚌。圖片處理時間遠超代碼時間XD。邏輯很簡單挨队。
void forPic1()
{
//pic1
while ((pic1[0] == 0) || (pic1[1] == 0) || (pic1[2] == 0) || (pic1[3] == 0) || (pic1[4] == 0))
{
MOUSEMSG m1;
FlushMouseMsgBuffer();
m1 = GetMouseMsg();
setlinecolor(COLORREF RGB(256, 256, 256));
setlinestyle(PS_SOLID | PS_JOIN_BEVEL, 3);
if (m1.uMsg == WM_LBUTTONDOWN)
{
m1 = GetMouseMsg();
if ((m1.x < 636) && (m1.x > 592) && (m1.y < 225) && (m1.y > 200))
{
pic1[0] = 1;
circle(614, 212.5, 15);
right();
}
if ((m1.x < 473) && (m1.x > 447) && (m1.y < 131) && (m1.y > 114))
{
pic1[1] = 1;
circle(460, 122.5, 15);
right();
}
if ((m1.x < 748) && (m1.x > 676) && (m1.y < 174) && (m1.y > 94))
{
pic1[2] = 1;
circle(712, 134, 30);
right();
}
if ((m1.x < 514) && (m1.x > 414) && (m1.y < 497) && (m1.y > 419))
{
pic1[3] = 1;
circle(464, 458, 40);
right();
}
if ((m1.x < 620) && (m1.x > 580) && (m1.y < 190) && (m1.y > 164))
{
pic1[4] = 1;
circle(600, 177, 20);
right();
}
}
}
Sleep(500);
}
雜七雜八
- 音樂設(shè)置包含背景音樂和音效兩部分谷暮,注意切換音樂時需要關(guān)閉前一個。
mciSendString("close bkmusic", NULL, 0, NULL);
mciSendString("open .\\gameImage\\bgm1.mp3 alias bkmusic", NULL, 0, NULL);
mciSendString("play bkmusic", NULL, 0, NULL);
mciSendString("close jpmusic", NULL, 0, NULL);
mciSendString("open .\\gameImage\\mons3.mp3 alias jpmusic", NULL, 0, NULL);
mciSendString("play jpmusic", NULL, 0, NULL);
- 使用了童晶老師教的游戲模塊化框架:
int main()
{
startup();
while(1)
{
show();
updateWithoutInput();
updateWithInput();
}
}
- 使用了頭文件的方法來分類編寫不同關(guān)卡盛垦。
- 自己繪制和處理立繪和素材坷备,photoshop技術(shù)++。
總結(jié)
第一次獨立完成的千行項目情臭,有太多可以優(yōu)化的地方省撑,不過還是蠻有意思的。接下來想深入學(xué)java俯在,開發(fā)一個安卓游戲~