科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件利用Visual Basic开发飞船着陆游戏

利用Visual Basic开发飞船着陆游戏

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

VB不是一个常用的游戏开发工具,不过只要巧妙地运用API知识,就可以做所有的事情。

作者:刘涛 来源:天极网 2007年10月19日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
三、程序实现

  现在我们已经拥有了着陆程序所有必需的元素,但是正象开药方一样,我们还需要小心的将它们组合在一起。首先生成一个新的工程,在FORM1上放置三个图片控件,分别命名为:picEarth, picLander 和 picSmash。在picLander和 picSmash图片框中分别装载着陆的飞船 和毁坏的飞船 图片,对于这两个图片控件,将BorderStyle属性设置为: 0 - None, ScaleMode 属性设置为 3 - Pixels, Visible属性设置为 False, AutoRedraw 属性设置为 True, AutoSize 属性设置为 True。对于picEarth控件,设置 BorderStyle 属性为 0 -None,ScaleMode属性设置为3 - Pixels。确定该控制大小合适,我程序中使用的是336x568 pixels (5040x8520 twips), 它看上去非常合适。

  现在,在窗体上放置一个timer控件,将其命名为tmrGravity,将其Enabled属性设置为False,时间间隔设置为1秒;放置一个按钮控件,命名为cmdGo,"caption"属性设为"Start",另外 在窗体上绘制三个文本控件,并伴有标签。分别命名为txtFuel, txtVSpeed 和txtHeight,它们将用于提供一些飞行参数。好了,界面已经设计好了,下面是添加代码。

  首先,我们需要对GetTickCount, BitBlt, SetPixelV and GetAsyncKeyState等API函数及VK_DOWN常量进行声明,将它们剪贴至窗体的声明部分,确定将它们声明为"Private"而不是"Public"类型,另外,我们还需要vSpeed, LandY和 Fuel等三个变量来用于控制飞船,所有的类型都是double,目前为止,我们已有了如下代码:

Option Explicit
 ’API Declares
 Private Declare Function GetTickCount _
  Lib "kernel32" () As Long
 Private 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
 Private Declare Function SetPixelV Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, _
  ByVal y As Long, ByVal crColor As Long) As Long
 Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
 Private Const VK_DOWN = &H28
 ’ Vertical speed of the craft
 Private vSpeed As Double
 ’ The y coordinate of the craft
 Private LandY As Double
 ’ The amount of fuel left
 Private Fuel As Double

  对于这些变量,我们需要设置默认值,所以在Form_Load 事件中,设置Fuel为700,这个数值设置的恰到好处,使游戏有一定难度。vSpeed 和 LandY设置为0。因为我们不想显示这些实数的小数部分,所以我们需要格式命令来显示数字。height也有一点小窍门,因为它必须来自于LandY变量,它代表着离开地面的高度。下面的代码将三个数值都设置为1位小数。

txtvspeed.Text = Format(vSpeed, "0.0")
txtfuel.Text = Format(Fuel, "0.0")
txtheight.Text = Format(picEarth.ScaleHeight - piclander.ScaleHeight - 30 - LandY, "0.0")

  迄今为止所有的代码都是非常容易的,我们还需要在命令按钮中添加代码来激活定时器,从而开始游戏。为了使程序统一整洁,还需要是命令按钮无效。

  对于定时器tmrGravity来说,需要一些技巧。虽然定时器被设置为每毫秒启动一次,但这并不意味着它一秒要运行1000次,所以我们必须寻找另外一种方法来测量两次调用之间的时间间隔,我们将使用一个静态变量,这种变量在两次过程调用之间数值保持不变,所以,如果在一次调用结束后该值为1,那么在下一次调用时它仍然保持为1。为此,需要在定时器事件中添加如下声明:

Static curtime As Long
Dim timenow As Long
Dim timediff As Long

  GetTickCount这个API函数,返回自从Windows启动后到目前为止流逝的时间,单位是毫秒,所以它非常适用于我们的要求。在每一次定时器事件中,静态变量将被设置为当前流逝的毫秒数,在下一次定时事件触发后,我们可以计算两次调用之间的时间,因此可以计算速度。
第一次定时事件被触发时这个静态变量被设置为0,因为它以前没有被设置过。所以,当这个值等于0时,我们要绘制星星图案及用于着陆的水平面,代码如下:

If curtime = 0 Then
 ’ Draw the earth
 picEarth.Line (0, picEarth.ScaleHeight - 30) -(picEarth.ScaleWidth, picEarth.ScaleHeight), vbWhite, BF

 Randomize Timer
 Dim starx As Long, stary As Long
 For starx = 0 To picEarth.ScaleWidth
  For stary = 0 To picEarth.ScaleHeight - 30
   If Rnd * 1000 < 5 Then
    SetPixelV picEarth.hdc, starx, stary, vbYellow
   End If
  Next
 Next

 timenow = GetTickCount
 curtime = timenow

End If

   在前面,我曾提到要使用vbSrcInvert方式将飞船绘制在背景上,vbSrcInvert操作是:

Destination = Source XOR Destination

  这仅仅是将飞船贴到星星中的一种方法,但是使用XOR的好处是它是可逆的,如果你第二次重复这个操作,第一次调用所取得的效果将被取消,这意味着我们可以在定时器的末尾调用这种操作在星星中绘制飞船,然后 在下一次定时器事件中删除飞船,并准备新的位置。
所以,如果不是第一次调用定时器,我们需要做这些绘制工作,所以,在上节代码的"End If"之前添加如下代码:

’etc...curtime = timenow
Else
 timenow = GetTickCount
 ’ If it isn’t the first time, put back the previous background
  BitBlt picEarth.hdc, 150, LandY, piclander.ScaleWidth, _
 piclander.ScaleHeight, piclander.hdc, 0, 0, vbSrcInvert
’ End If...

  我们现在有了一个完全空白的星空图案,并可以计算出自上次调用以来流逝的时间,

timediff = timenow - curtime

  下一件事就是考虑飞船的速度,以及作用在它上面的重力效果,这就需要下面的代码:

’ Calculate new vertical speed based on g
vSpeed = vSpeed - ((timediff / 1000) * 10)

  上面等式中的"10"是重力加速度,它的单位常常是米每秒每秒,因为时间间隔是以毫秒计算的,所以我们在使用之前必须转换为秒,
让推进器工作需要做两件事,一是必须按下向下的方向键,第二,必须要有一定的燃料,下面的代码 实现了这两个功能 ,如果没有燃料了,将发出蜂鸣声。

If GetAsyncKeyState(VK_DOWN) <> 0 Then
 If Fuel > 0 Then
  ’ Apply thrust: 15 is the acceleration produced
  vSpeed = vSpeed + ((timediff / 1000) * 15)

  Fuel = Fuel - ((timediff / 1000) * 150)
  
  ’ Check that fuel does not go below 0
  If Fuel < 0 Then Fuel = 0
  Else
   Beep
  End If
End If

  正如你看到的,这里的公式与重力有点相象,除了它的实际方向是向上而不是向下(因此vSpeed = vSpeed+而不是-)。

  现在,我们需要更改飞船的位置、文本框及上次调用调用的时间。

LandY = LandY - vSpeed

’ Update text boxes
txtvspeed.Text = Format(vSpeed, "0.0")
txtfuel.Text = Format(Fuel, "0.0")
txtheight.Text = Format(picEarth.ScaleHeight _
- piclander.ScaleHeight - 30 - LandY, "0.0")

’ Update the ’last called time’
curtime = timenow

  最后一个需要考虑的问题是飞船着陆问题,这通过检测LandY变量来判断是否已经进行陆地。如果飞船已经着陆,我们需要检测速度,以使它不至于坠毁,同时,飞船必须被重新绘制,或者成功着陆或者是坠毁状态。如果飞船没有着陆,就要按照正常程序进行重新绘制。

’ If it has touched down...
If LandY >= picEarth.ScaleHeight - 30 - piclander.ScaleHeight Then

 ’ Make sure that it is on the surface
 LandY = picEarth.ScaleHeight - 30 - piclander.ScaleHeight
 txtheight.Text = Format(picEarth.ScaleHeight - piclander.ScaleHeight - 30 - LandY, "0.0")

 ’ Stop the timer and disable the pause button...
 ’ the game is over!
 tmrgravity.Enabled = False

 ’ Figure out if it was a safe landing or not,
 ’ and paint the appropriate craft
 If vSpeed > -2 Then
  ’ If it was safe, then the craft remains intact
  BitBlt picEarth.hdc, 150, LandY, piclander.ScaleWidth, piclander.ScaleHeight, piclander.hdc, 0, 0, vbSrcInvert
  MsgBox "Congratulations! You have landed successfully!"
 Else
  ’ If it was moving too fast, it blows up!
  BitBlt picEarth.hdc, 150, LandY, piclander.ScaleWidth, piclander.ScaleHeight, picsmash.hdc, 0, 0, vbSrcInvert
  MsgBox "Smash! Oooops!"
 End If

Else

’ paint the craft into its new position.
BitBlt picEarth.hdc, 150, LandY, piclander.ScaleWidth, _
piclander.ScaleHeight, piclander.hdc, 0, 0, vbSrcInvert

End If

  四、小结

  通过上面的介绍,我们已经完成了着陆程序的编写,虽然它没有漂亮的外观,没有3D的效果,但它是一个游戏编程的开始,而且具有一定的趣味性。当然,这个程序还有亟待完善的地方,例如,你们还可以试着给这个程序添加一些特殊功能,如声音、记分系统及其它一些所能想到的特点等,这里就不再赘述,相信读者朋友们一定会利用自己的聪明才智解决上述问题。

查看本文来源

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章