這篇教程主要講解下用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;
以上就是打地鼠的主體部分的主要代碼,這個部分可以分為編程思路中的三個模塊來實現。每個模塊的實現代碼都比較長,從這裡也可以看出,一個游戲的規劃和設計是非常重要的,最好能有一個書面的游戲設計書或設計規劃之類的參考對象。否則到了游戲的後期代碼編制階段,常常會出現顧此失彼的想象。在參考對象中,要對各個模塊有比較詳細的部署。這樣編制出來的游戲才不會虎頭蛇尾。