原码:
主要包括主窗口和选择飞机的窗口,3个小模块。
主窗口:
Option Explicit
'//ALL STAR FIELD STUFF
'//for our starfield
Private Type udtStar
X As Integer
Y As Integer
Z As Single '//distance from us(aka drawwidth AND how fast it goes past us)
Taken As Boolean
End Type
'//FPS
Private FrameCounter As Integer
Private FPSTimer As Long
Private FPS As Integer
Private Sub GetFPS()
If GetTickCount >= (FPSTimer + 1000) Then
FPS = FrameCounter
FrameCounter = 0
FPSTimer = GetTickCount
Else
FrameCounter = FrameCounter + 1
End If
frmMain.Caption = "Asteroids running at " & FPS & " frames per second"
End Sub
Private Sub InitStars()
Dim X As Long
For X = 0 To NUM_MAX_STARS - 1
Stars(X).Taken = True
Stars(X).X = Int(Rnd * picGame.Width)
Stars(X).Y = Int(Rnd * picGame.Width)
Stars(X).Z = Int(Rnd * 5) + 1
Next X
End Sub
Private Sub DoStars()
Dim X As Long
For X = 0 To NUM_MAX_STARS - 1
If Stars(X).Taken = False Then
Stars(X).Taken = True
Stars(X).X = Int(Rnd * picGame.Width)
Stars(X).Y = 0
Stars(X).Z = Int(Rnd * 5) + 1
Else
DrawWidth = 1
Stars(X).Y = Stars(X).Y + Stars(X).Z
picGame.PSet (Stars(X).X, Stars(X).Y), vbWhite
If Stars(X).Y > picGame.Height Then
Stars(X).Taken = False
End If
End If
Next X
End Sub
Public Sub MainLoop()
'//tmp time
Dim tmpTime As Long
'//Initialize Game Data and graphics
InitStars 'Star field
InitSurfaces 'graphics
Pilot.X = (picGame.Width / 2) - (bbsShips(Pilot.PilotShip).Width / 2)
Pilot.Y = picGame.Height - bbsShips(Pilot.PilotShip).Height
Pilot.BulletDelay = 100
tmrLevel.Enabled = True
ReDim Asteroids((Pilot.PilotLevel * 5) - 1)
Do While GameRunning = 1 Or GameRunning = 2
tmpTime = timeGetTime()
If GameRunning = 1 Then
'//clear the screen
BitBlt bbsBackbuffer.hdc, 0, 0, picGame.Width, picGame.Height, bbsBackbuffer2.hdc, 0, 0, SRCCOPY
DoStars '//update all the stars
DoPilot '//update our pilot
DoAsteroids '//update our asteroids
DoBullets 'update our bullets
'//blt backbuffer to main hdc
BitBlt ScreenHDC, 0, 0, picGame.Width, picGame.Height, bbsBackbuffer.hdc, 0, 0, SRCCOPY
'//check for deaths
If Pilot.PilotHealth <= 0 Then
'//any live left?
If Pilot.PilotLevel > 0 Then
Pilot.PilotLevel = Pilot.PilotLevel - 1
End If
GameRunning = 0
lblLose.Visible = True
End If
'//set form data
lblHealth.Caption = Pilot.PilotHealth
lblScore.Caption = Pilot.PilotScore
lblLives.Caption = Pilot.PilotLives
lblLevel.Caption = Pilot.PilotLevel
GetFPS
End If
'//frame cap limiter
Do Until timeGetTime >= tmpTime + 30
Loop
DoEvents
Loop
End Sub
Private Sub Form_Load()
'//global variable for picGame.HDC, easier use
ScreenHDC = picGame.hdc
mpMIDI.FileName = App.Path & "\Audio\Theme1.mid"
mpMIDI.Play
End Sub
Private Sub Form_Unload(Cancel As Integer)
'//clear memory of all Device Contexts created
modEngine.DestroyHdcs
End Sub
Private Sub lblHealth_Click()
Pilot.PilotHealth = Pilot.PilotHealth + 1000
End Sub
Private Sub mnuNew_Click()
lblLose.Visible = False
Pilot.PilotName = InputBox("What is your Pilot's Name?", "Asteroids!")
If Pilot.PilotName <> "" Then
frmShipChoose.Show
End If
End Sub
Private Sub mnuTheme1_Click()
mpMIDI.Stop
mpMIDI.FileName = App.Path & "\Audio\Theme1.mid"
mpMIDI.Play
End Sub
Private Sub mnuTheme2_Click()
mpMIDI.Stop
mpMIDI.FileName = App.Path & "\Audio\Theme2.mid"
mpMIDI.Play
End Sub
Private Sub tmrLevel_Timer()
Randomize Timer
Pilot.PilotLevel = Pilot.PilotLevel + 1
ReDim Preserve Asteroids((Pilot.PilotLevel * 5) - 1)
Me.BackColor = RGB(Int(Rnd * 255), Int(Rnd * 255), Int(Rnd * 255))
End Sub
选择飞机的窗口:
Option Explicit
Private Sub imgShip_Click(Index As Integer)
If MsgBox("Are you sure you want this ship?", vbYesNo) = vbYes Then
Pilot.PilotShip = Index
Pilot.PilotHealth = 100
Pilot.PilotLives = 3
Pilot.PilotLevel = 1
Pilot.PilotScore = 0
Pilot.Strength = Val(lblStr(Index).Caption)
Pilot.Defense = Val(lblDef(Index).Caption)
Pilot.Speed = Val(lblSpeed(Index).Caption)
Pilot.ShipHeight = Val(lblHeight(Index).Caption)
Pilot.ShipWidth = Val(lblWidth(Index).Caption)
frmMain.Enabled = True
Me.Hide
GameRunning = 1
frmMain.MainLoop
End If
End Sub
Public Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
二、GetASyncKeyState
这个函数很更加简单,这里我地不用Form_keyPress/KeyDown/KeyUp事件,而用这个函数更容易地完成按键捕获。
函数原形:
Public Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
vKey - 检测你输入一个按键
[Code Start]
Dim btnDown as Boolean
btnDown = GetAsyncKeyState(vbKeyDown)
If btnDown = True Then ‘//如果这个键被按下
‘//符合这个条件的代码
Else
‘//符合这个条件的代码
End If
[Code Stop]
三、SndPlaySound
这个函数也非常简单,不过有一个小问题,系标识常量(flags)使用到。好,我地衣家来体下泥个函数。
Public Declare Function sndPlaySound Lib "winmm.dll" Alias "sndPlaySoundA" (ByVal lpszSoundName As String, ByVal uFlags As Long) As Long
LpszSoundName = wave文件名
UFlags - 标识常量
SND_ASYNC - &H1 播放新的音乐,然后中断其他
SND_LOOP - &H8 循环播放
SND_NODEFAULT - &H2 如果改文件不存在,就不做任何事
SND_SYNC - &H0 程序不控制直到播完
SND_NOSTOP - &H10 如果已经有个文件正在播放,则不播放(术语叫不中断)
[Code Start]
sndPlaySound App.Path & “\Audio\Sound.wav”, SND_ASYNC or SND_NODEFAULT
[Code Start]
‘//建立临时集合、玩家集合、电脑集合;几个尺寸坐标变量
Dim tmpRECT as RECT
Dim PlayerX as Integer, PlayerY As Integer
Dim CompX As Integer, CompY as Integer
Dim PlayerRect as RECT, CompRect As RECT
Option Explicit
'================= player1 0
' | |
'================= player2 0
' | |
'================= newgame
' | |
'================= exit
'
'
'上面是一个游戏界面的构造图,这个游戏广东话叫<井字过三关>,下面介绍它的组件.
'用line和label控件作出左图,9个方格是label可以显示叉和圈。
'player1,player2,0,0都是label;newgame,exit 是按钮.
'
'\1\界面讲完,我们来看代码,查看代码,应该先由通用区开始.这里讲名有3个变量.
Dim bytPlayerTurn As Byte '0 = No Game, 1 = Player One, 2 = Player Two
Dim intP1Score As Integer
Dim intP2Score As Integer
Private Sub cmdNewGame_Click()
'\3\newgame按钮按下时触发事件过程,这里我们调用一个startgame子过程,转到子过程看看有什么东西.
StartGame
End Sub
Private Sub Form_Load()
'\2\程序入口点应从这里,这里我们知道他把3个变量清零.
'//Initialize the variables
bytPlayerTurn = 0 'No Game started
intP1Score = 0
intP2Score = 0
End Sub
Private Sub StartGame()
'//游戏的开始
Dim X As Long
'//清除之前的游戏,9个label,显示清空,注意这里9个label是1个对象数组.
For X = 0 To 8
lblSquare(X).Caption = ""
Next X
'//轮到玩家1下棋
bytPlayerTurn = 1
End Sub
Private Sub lblSquare_Click(Index As Integer)
'//输入X或O时,先检测
If bytPlayerTurn = 0 Then
'//没有游戏
MsgBox "Sorry, no game is in progress at this time!"
Exit Sub '//如果bytplayerturn=0,退出这个进程
End If
'//轮到谁了?
If bytPlayerTurn = 1 Then
'//如果轮到player1
'//检测格子是否已经被下了棋子。
If lblSquare(Index).Caption <> "" Then
MsgBox "Sorry, this spot is already taken!"
Exit Sub
End If
'//填入X
lblSquare(Index).Caption = "X"
'//检查是否已经获胜
If CheckWin("X") = True Then
'//CheckWin()是个函数,最下边有定义。
MsgBox "Player One is the winner!"
intP1Score = intP1Score + 1
lblP1Score.Caption = intP1Score
bytPlayerTurn = 0 '//两个变量完成记分操作。
Exit Sub
End If
'//如果没获胜,则轮到player2.
bytPlayerTurn = 2
ElseIf bytPlayerTurn = 2 Then
'//同样检查格子是否已经被下过棋了。
If lblSquare(Index).Caption <> "" Then
MsgBox "Sorry, this spot is already taken!"
Exit Sub
End If
'//填入O
lblSquare(Index).Caption = "O"
'//查看是否已经获胜。
If CheckWin("O") = True Then
'//
MsgBox "Player Two is the winner!"
intP2Score = intP2Score + 1
lblP2Score.Caption = intP2Score
bytPlayerTurn = 0 '//两个变量完成记分操作。
Exit Sub
End If
'//如果没有获胜,将用来轮回的变量置1.
bytPlayerTurn = 1
End If
End Sub
Private Function CheckWin(strLetter As String) As Boolean
'//
'//第一行相同时
If lblSquare(0).Caption = strLetter And lblSquare(1).Caption = strLetter And lblSquare(2).Caption = strLetter Then
CheckWin = True
Exit Function
End If
'//第二行相同时
If lblSquare(3).Caption = strLetter And lblSquare(4).Caption = strLetter And lblSquare(5).Caption = strLetter Then
'//Win!!
CheckWin = True
Exit Function
End If
'//第三行相同时
If lblSquare(6).Caption = strLetter And lblSquare(7).Caption = strLetter And lblSquare(8).Caption = strLetter Then
'//Win!!
CheckWin = True
Exit Function
End If
'//。。。。
If lblSquare(0).Caption = strLetter And lblSquare(3).Caption = strLetter And lblSquare(6).Caption = strLetter Then
'//Win!!
CheckWin = True
Exit Function
End If
'//。。。。
If lblSquare(1).Caption = strLetter And lblSquare(4).Caption = strLetter And lblSquare(7).Caption = strLetter Then
'//Win!!
CheckWin = True
Exit Function
End If
'//。。。。
If lblSquare(2).Caption = strLetter And lblSquare(5).Caption = strLetter And lblSquare(8).Caption = strLetter Then
'//Win!!
CheckWin = True
Exit Function
End If
'//。。。。。
If lblSquare(0).Caption = strLetter And lblSquare(4).Caption = strLetter And lblSquare(8).Caption = strLetter Then
'//Win!!
CheckWin = True
Exit Function
End If
'//。。。。。
If lblSquare(2).Caption = strLetter And lblSquare(4).Caption = strLetter And lblSquare(6).Caption = strLetter Then
'//Win!!
CheckWin = True
Exit Function
End If
'//。。。。
CheckWin = False
End Function
'//其实除了可以定义一个2唯数组,即A[n*n]矩阵,同行,同列,对角线就能获胜。