游戏开发是许多程序员的梦想,看着游戏中那华丽的画面。有多少人会感叹,如果自己能做就好了。
然而开发游戏需要对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,所以我们声明
然后我们定义一个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
|
查看本文来源