科技行者

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

知识库

知识库 安全导航



ZDNet>软件频道>中间件-zhiding>用Visual Basic.NET实现你的游戏梦想

  • 扫一扫
    分享文章到微信

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

    游戏开发是许多程序员的梦想,看着游戏中那华丽的画面。有多少人会感叹,如果自己能做就好了。   然而开发游戏需要对DirectX的调用,原来除了C++没有其他语言可以胜任这份工作,虽然DirectX7.0SDK加入了对VB的支持。

来源:中国IT实验室 2007年10月02日

关键字:编程 vb.net 游戏

    游戏开发是许多程序员的梦想,看着游戏中那华丽的画面。有多少人会感叹,如果自己能做就好了。 

  然而开发游戏需要对DirectX的调用,原来除了C++没有其他语言可以胜任这份工作,虽然DirectX7.0SDK加入了对VB的支持,但是VB毕竟能力有限,无法胜任这份严峻的工作,游戏可以说是最吃资源的程序,VB的速度无法完成。即使做出个游戏也被人说做不入流。这样一来VB程序员无法实现自己的梦想了。

  .net推出了,VB.net的性能已经可以和VC++媲美,用微软的说法内核是一样的,只不过是语法的差异。VB程序员大喜,这样再也不会被C++程序员说成是傻瓜程序员了,你们能做的我们一样可以。

  好了现在切入正题,现在我们来做一个简单的游戏。

  首先先要对游戏有个整体构架才行,VB.net中对类的设定比较可爱,功能也非常强大,不用一用起不太对不起微软了。

  调用DirectX,首先先要安装DirectX7.0以上版本的SDK开发包,然后新建一个项目,选择Windwos应用程序。

  然后选择引用DirectX方法是,选择引用->COM->DirectX7 for VisualBasic Type Library

  好了,至此你已经引用了DirectX7.0

  首先为了方便使用我们调用DirectX7.0,所以我们声明

Imports DxVBLib

  然后我们定义一个DirectX7.0的对象

Public DirectX As New DirectX7

  声明一个DirectDraw对象,用于2D游戏的绘图

Public DDraw As DirectDraw7

DDraw = DirectX.DirectDrawCreate("")

  然后要设置DirectDraw的协作层

Call DDraw.SetCooperativeLevel(Me.Handle.ToInt32, CONST_DDSCLFLAGS.DDSCL_FULLSCREEN Or CONST_DDSCLFLAGS.DDSCL_ALLOWMODEX Or CONST_DDSCLFLAGS.DDSCL_EXCLUSIVE)

  其中用到的常数有

CONST_DDSCLFLAGS.DDSCL_FULLSCREEN表示全屏模式

CONST_DDSCLFLAGS.DDSCL_ALLOWMODEX表示允许使用ModeX

CONST_DDSCLFLAGS.DDSCL_EXCLUSIVE表示独占模式

  在DirectX的编程中会用到大量的常数,这里教你一个技巧,在使用的地方打空格,VB.net会列出可以使用的所有常数,非常好用。



  然后设置DirectDraw得显示模式

Call DDraw.SetDisplayMode(800, 600, 16, 0, CONST_DDSDMFLAGS.DDSDM_DEFAULT)

  800,600表示屏幕尺寸,16表示16位真彩

  然后定义缓存用于存储图片

Dim ddsPrimary As DirectDrawSurface7 '设置主面

Dim ddsBackBuffer As DirectDrawSurface7 '设置缓冲面

Public ddsMap As DirectDrawSurface7'设置地图

Public ddsHero As DirectDrawSurface7'设置人物

'定义设置表面

Dim ddsd As DDSURFACEDESC2 '表面

'为屏幕建立一个后备缓冲区

ddsd1.lFlags = CONST_DDSURFACEDESCFLAGS.DDSD_CAPS Or CONST_DDSURFACEDESCFLAGS.DDSD_BACKBUFFERCOUNT

ddsd1.ddsCaps.lCaps =
CONST_DDSURFACECAPSFLAGS.DDSCAPS_PRIMARYSURFACE Or CONST_DDSURFACECAPSFLAGS.DDSCAPS_FLIP Or
CONST_DDSURFACECAPSFLAGS.DDSCAPS_COMPLEX

ddsd1.lBackBufferCount = 1

ddsPrimary = DDraw.CreateSurface(ddsd1)

'设置后备缓冲区

Dim caps As DDSCAPS2

caps.lCaps = CONST_DDSURFACECAPSFLAGS.DDSCAPS_BACKBUFFER

ddsBackBuffer = ddsPrimary.GetAttachedSurface(caps)

ddsBackBuffer.GetSurfaceDesc(ddsd4)

'载入画面初始化

ddsd2.lFlags = CONST_DDSURFACEDESCFLAGS.DDSD_CAPS Or
CONST_DDSURFACEDESCFLAGS.DDSD_HEIGHT Or
CONST_DDSURFACEDESCFLAGS.DDSD_WIDTH

ddsd2.ddsCaps.lCaps = CONST_DDSURFACECAPSFLAGS.DDSCAPS_OFFSCREENPLAIN

ddsd2.lWidth = ddsd4.lWidth

ddsd2.lHeight = ddsd4.lHeight

'读取地图

ddsMap = DDraw.CreateSurfaceFromFile("Map\001.bmp", ddsd2)

'载入精灵

ddsd3.lFlags = CONST_DDSURFACEDESCFLAGS.DDSD_CAPS

ddsd3.lHeight = CONST_DDSURFACEDESCFLAGS.DDSD_ALL

ddsd3.ddsCaps.lCaps = CONST_DDSURFACECAPSFLAGS.DDSCAPS_OFFSCREENPLAIN

'读取人物

ddsHero = DDraw.CreateSurfaceFromFile("BMP\H00.bmp", ddsd3)

'把人物从背景中抠出来,用Key设置背景色

Dim key As DDCOLORKEY

'这里的背景色为黑色

key.low = 0

key.high = 0

ddsHero.SetColorKey(CONST_DDCKEYFLAGS.DDCKEY_SRCBLT, key)

 

查看本文来源

  



'在后备缓存中绘制地图

Dim rMap As RECT

ddsBackBuffer.BltFast(0, 0, Map.ddsMap, rMap, CONST_DDBLTFASTFLAGS.DDBLTFAST_WAIT)

'在后备缓存中绘制人物

Dim rPlayer As RECT

Dim ddrval As Boolean

'rPlayer表示从图片中截取那块,从哪到哪。如果你打开很多游戏的位图看看的话你会发现一个人物的多种动态往往放在一张位图中,截取其中的不同块显示出来就形成了动画。

'表示从(0,0)这个位置开始取

rPlayer.Top = 0

rPlayer.Left = 0

'表示取到(32,32)这个位置

rPlayer.Right = 32

rPlayer.Bottom = 32

'其中0,0表示绘制的位置。

ddrval = ddsBackBuffer.BltFast(0, 0, ddsHero, rPlayer, CONST_DDBLTFASTFLAGS.DDBLTFAST_SRCCOLORKEY Or CONST_DDBLTFASTFLAGS.DDBLTFAST_WAIT)

'好了,后备缓存已经绘制完成了,可以翻转过来了,其实写屏的方法就是不停的翻转主面和缓存面

ddsPrimary.Flip(Nothing, CONST_DDFLIPFLAGS.DDFLIP_WAIT)



   制作2D游戏的基本知识就这些了,我们现在来说一下游戏的构架。我们以一个简单的回合制RPG游戏为例。

  我建议把所有DirectX的接口全部封装起来。这样操作起来方便很多。

  游戏中需要英雄类、物品类、怪物类、地图类

  首先先说英雄类包含的内容有HP、MP、技能、身上装备、所会武功、人物坐标。

  其中比如所会技能此技能等级,做成一个自定义类型,方法是

Public Structure myGest

Public GestID As Int16 '武功编号

Public GestLV As Int16 '武功等级

End Structure

  比如最多会十种就可以定义为Public Guest(9) As myGest

  同样的道理人物坐标也一样

Public Structure myXY

Public iX As Int16 'X轴坐标

Public iY As Int16 'Y轴坐标

Public iAsp as Int16 '头朝的方向

End Structure

  当然还有其他的一些属性,这里就不一一列举了。

  物品类

  比如物品分种类的,每种物品功能不同,比如头盔就不能装备在身上当然也不能吃,这里我们用到一个枚举类型,定义方法是

Public Enum myResClass '物品分类

Head '头装备

Body '身上装备

Hand '手上装备

Eat '食品

Other '其他

End Enum

Public ResClass As myResClass '物品类型

End Class

  其它当然还有很多属性,如名称,重量,性能等等。

  怪物类

  类似于英雄类有也相似的属性。

  地图类

  这里我们把显示得地图单独拿出来作为一个类,是因为,一张地图并不是每个地方都可以走的,从位图中可是很难识别出那些是阻挡物的。并且地图上还有一些NPC,可以与其对话等等。这一切都要从地图文件中读取。

  地图文件象一张二维表,与你地图位图相对应,比如人物向上移动TOP-=5然后判断,现在所在点在二维表中是否可以行走,是否有阻挡,如果阻挡取消操作,人物不做移动。

  然后设定整体流程,为了操作不会因按键点击速度而影响移动速度,所以我们用时间来控制,设置一个Timer控件,然后根据当前状态不同而设定操作的不同,比如操作开始界面、移动模块、对话模块、战斗模块、交易模块、主菜单模块。当前状态用iNowState变量存储

Select Case iNowState

Case 0

'开始界面

Case 1

'移动模块

Case 2

'对话模块

Case 3

'战斗模块

Case 4

'交易模块

Case 5

'主菜单

End Select

用eInput来存储键盘事件。定义如下:

Public eInput As System.Windows.Forms.Keys = Keys.None

'读取存储键盘信息

Protected Overrides Sub OnKeyDown(ByVal e As System.Windows.Forms.KeyEventArgs)

eInput = e.KeyCode

end sub

查看本文来源