這篇教程主要講解下用Delphi編寫打地鼠游戲的主體控制部分,在上一篇中我們主要是介紹了游戲主體界面的設計實現(Delphi打地鼠游戲界面設計部分代碼分析),程序運行後,鼠標單擊左上角的老鼠圖標,會彈出一個控制菜單。按下右上角的倒三角圖標就會退出程序。
編程思路:在主體控制部分,主要有以下幾個部分:
1、 用定時器實現老鼠的出現和隱沒在本例中,首先構造一些函數用於實現存放老鼠出現和隱沒位置,然後通過定時器來加載這些數據。
2、 錘子不同狀態的變化。錘子有三種不同的狀態:松開、敲擊和擊中。這三種狀態與鼠標的OnMouseDown事件和OnMouseDown事件對應著。
3、 菜單以及相應圖標事件的處理。主要用於實現游戲的重新開始、暫停、恢復或退出等事件,而圖標對應的事件則除了實現一定的游戲功能外,還要對圖標自身的更換處理。
游戲的主體部分詳細代碼和說明見【編程步驟】部分。由於篇幅有限,完整的代碼可以參考光中的內容,在此只給出代碼的主要部分。
編程步驟:
1.用定時器實現老鼠的出現和隱沒。在實現這個功能時,首先要構造一些函數LoadRatSpr、LoadRat、InitData、DrawRats、PopupRats和UpdateRats等,用於存放鼠標位置和繪制鼠標。
procedure LoadRatSpr(i, ox, oy, x, y, w, h : integer);
begin
{老鼠變換的坐標值}
RatSpr[i].ox :=ox;
RatSpr[i].oy :=oy;
RatSpr[i].x :=x;
RatSpr[i].y :=y;
RatSpr[i].w :=w;
RatSpr[i].h :=h;
end;
procedure LoadRat(row, col, x, y : integer);
begin
{老鼠出現的坐標值}
Rat[row, col].x := x;
Rat[row, col].y := y;
Rat[row, col].pos := 0;
Rat[row, col].speed := 0;
end;
procedure InitData;
begin
{老鼠出現的位置}
LoadRat(0, 0, 187, 48);
LoadRat(1, 0, 127, 79);
LoadRat(2, 0, 75, 116);
LoadRat(0, 1, 247, 58);
LoadRat(1, 1, 189, 90);
LoadRat(2, 1, 146, 126);
LoadRat(0, 2, 304, 66);
LoadRat(1, 2, 262, 98);
LoadRat(2, 2, 222, 134);
LoadRatSpr(1, $00, $00, $5E, $36, $3C, $39);
LoadRatSpr(2, $01, $02, $61, $02, $38, $36);
LoadRatSpr(3, $01, $0a, $D8, $4E, $38, $2E);
LoadRatSpr(4, $02, $0E, $D7, $24, $38, $2A);
LoadRatSpr(5, $02, $16, $D8, $00, $38, $22);
LoadRatSpr(6, $02, $1A, $D7, $82, $35, $1E);
LoadRatSpr(7, $02, $1A, $A0, $85, $35, $1E);
LoadRatSpr(8, $02, $1A, $9F, $68, $35, $1E);
LoadRatSpr(9, $02, $1A, $9F, $4B, $35, $1E);
LoadRatSpr(10, $02, $1A, $9E, $2D, $35, $1E);
LoadRatSpr(11, $02, $1D, $9E, $12, $35, $1B);
LoadRatSpr(12, $02, $2A, $9E, $01, $35, $0E);
LoadRatSpr(13, $01, $21, $5E, $70, $3D, $25);
LoadRatSpr(14, $01, $21, $5D, $94, $3D, $1A);
LoadRatSpr(15, $00, $00, $00, $00, $00, $00);
end;
procedure DrawRats(x, y, c : integer);
begin
{繪制老鼠}
if c > 0 then
begin
BitBlt(BufferBitmap.Canvas.Handle, x+RatSpr[c].ox, y+RatSpr[c].oy, RatSpr[c].w, RatSpr[c].h,
MaskBitmap.Canvas.Handle, RatSpr[c].x, RatSpr[c].y, SRCAND);
BitBlt(BufferBitmap.Canvas.Handle, x+RatSpr[c].ox, y+RatSpr[c].oy, RatSpr[c].w, RatSpr[c].h,
SpriteBitmap.Canvas.Handle, RatSpr[c].x, RatSpr[c].y, SRCINVERT);
end;
end;
procedure PopupRats;
var i, j : integer;
begin
{老鼠隨機出現}
if Frames mod 5 = 0 then
begin
i := random(3);
j := random(3);
if Rat[i,j].pos = 0 then
begin
Rat[i,j].pos := 12;
Rat[i,j].speed := random(1)+1;
end;
end;
end;
procedure UpdateRats(row, col : integer);
begin
{老鼠位置的更新}
if (Rat[row, col].pos <= 12) and (Rat[row, col].pos > 0) then
begin
if (Frames mod Rat[row, col].speed = 0) then
Rat[row, col].pos := Rat[row, col].pos - 1;
end
else
if Rat[row,col].pos >12 then
begin
if (Frames mod Rat[row, col].speed = 0) then Rat[row, col].pos := Rat[row, col].pos + 1;
if Rat[row, col].pos >= 15 then Rat[row, col].pos := 0;
end;
end;
在構造了這些函數之後,就可以在定時器RatTimer的OnTimer事件中加入下列代碼,實現鼠標的顯示和隱沒。
procedure TMainForm.RatTimerTimer(Sender: TObject);
var row, col : integer;
begin
{老鼠的顯示和隱沒}
Frames := Frames + 1;
FormPaint(Self);
PopupRats;
for row := 0 to 2 do
begin
for col := 0 to 2 do
begin
UpdateRats(row, col);
end;
end;
if LeftTime <= 0 then
begin
RatTimer.Enabled := FALSE;
Cursor := 0;
GameRunning := FALSE;
GamePause := FALSE;
MainForm.Canvas.Draw(0, 0, BackgroundBitmap);
end;
end;
2、錘子不同狀態的變化,首先構造一個錘子繪制函數,然後在窗口的OnMouseDown和OnMouseUp中實現錘子的狀態變化。下面是這些功能代碼。
procedure TMainForm.DrawHand;
begin
{處理敲擊老鼠的錘子的一些事件}
case HandStatus of
Hand_Up : begin //錘子松開
BitBlt(BufferBitmap.Canvas.Handle, HandXPos, HandYPos, 97, 54,
MaskBitmap.Canvas.Handle, 0, 0, SRCAND);
BitBlt(BufferBitmap.Canvas.Handle, HandXPos, HandYPos, 97, 54,
SpriteBitmap.Canvas.Handle, 0, 0, SRCINVERT);
end;
Hand_Down : begin //錘子敲下
BitBlt(BufferBitmap.Canvas.Handle, HandXPos, HandYPos - 6, 90, 64,
MaskBitmap.Canvas.Handle, 0, 54, SRCAND);
BitBlt(BufferBitmap.Canvas.Handle, HandXPos, HandYPos - 6, 90, 64,
SpriteBitmap.Canvas.Handle, 0, 54, SRCINVERT);
end;
Hand_Hit : begin //錘子擊中老鼠
BitBlt(BufferBitmap.Canvas.Handle, HandXPos, HandYPos, 90, 64,
MaskBitmap.Canvas.Handle, 0, 118, SRCAND);
BitBlt(BufferBitmap.Canvas.Handle, HandXPos, HandYPos, 90, 64,
SpriteBitmap.Canvas.Handle, 0, 118, SRCINVERT);
end;
end;
end;
procedure TMainForm.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
row, col : integer;
sp, d : integer;
begin
{窗口OnMouseUp事件}
if (GameRunning = FALSE) or (GamePause = TRUE) then
exit;
d := 10;
if Button = mbLeft then
HandStatus := Hand_Down; //錘子敲下
for row := 0 to 2 do
begin
for col :=0 to 2 do
begin
sp := Rat[row, col].pos;
if (sp > 0) and (sp <= 12) then
begin
if (X > Rat[row, col].x + RatSpr[sp].ox + d) and
(X < Rat[row, col].x + RatSpr[sp].ox + RatSpr[sp].w - d) and
(Y > Rat[row, col].y + RatSpr[sp].oy ) and
(Y < Rat[row, col].y + RatSpr[sp].oy + RatSpr[sp].h ) then
begin
Rat[row, col].pos := 13;
Rat[row, col].speed := 5;
if Button = mbLeft then
begin
HandStatus := Hand_Hit; //錘子擊中老鼠
PlaySound('HIT', hInstance, SND_RESOURCE or SND_ASYNC);
end;
end;
end;
end;
FormPaint(self);
end;
end;
procedure TMainForm.FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
{窗口OnMouseUp事件}
if (GameRunning = FALSE) or (GamePause = TRUE) then
exit;
if Button = mbLeft then
HandStatus := Hand_Up; //錘子松開
FormPaint(self);
end;
3、彈出式菜單的功能主要是用來控制游戲的,下面只給出“開始新游戲”的代碼。其余的可以參考光盤內容。
procedure TMainForm.NewClick(Sender: TObject);
begin
{開始游戲的一些必要設置}
LeftTime := 59;
RatTimer.Enabled := TRUE;
ScoreTimer.Enabled := TRUE;
GameRunning := TRUE;
GamePause := FALSE;
Cursor := -1;
Frames := 0;
InitData;
Randomize;
FormPaint(self);
end;
以上就是打地鼠的主體部分的主要代碼,這個部分可以分為編程思路中的三個模塊來實現。每個模塊的實現代碼都比較長,從這裡也可以看出,一個游戲的規劃和設計是非常重要的,最好能有一個書面的游戲設計書或設計規劃之類的參考對象。否則到了游戲的後期代碼編制階段,常常會出現顧此失彼的想象。在參考對象中,要對各個模塊有比較詳細的部署。這樣編制出來的游戲才不會虎頭蛇尾。