游戏开发论坛

 找回密码
 立即注册
搜索
查看: 2481|回复: 1

directdraw7入门(一) 全屏模式

[复制链接]

6

主题

103

帖子

103

积分

注册会员

Rank: 2

积分
103
发表于 2006-9-12 22:08:00 | 显示全部楼层 |阅读模式
源文链接
http://directx4vb.vbgamer.com/DirectX4VB/Tutorials/DirectX7/DD_Fullscreen.asp
本人才学DX7 看到这教材不错,就发过来了
全屏模式
    全屏模式是DirectDraw的最常用方式,各种用DX开发的商业游戏大都采用全屏模式.
      全屏模式下,你的(游戏)应用程序界面占据了整个屏幕空间,而且你几乎拥有了全部的控制计算机进行绘图的功能,而对应地,窗口模式只占据屏幕的一部分,二者区别的一个很重要之处就是:全屏模式下你可以设定屏幕的分辨率(屏幕的显示大小,单位:像素)和色深.上面谈到的分辨率其实就是Windows的分辨率,通过右击桌面查看其显示属性可以获取它们,如:
320 x 240
640 x 480
800 x 600
1024 x 76
      当然还不只这些,有些显卡支持60种以上的显示模式,显示模式=屏幕大小+色深的组合.色深定义了任一时刻可以(通过编程手段)显示在屏幕上的最大的色彩总数,它们遵循以下简单的规则:
色深数越高=程序运行速度越慢+视觉效果越好;
色深数越低=程序运行得越快+视觉效果越差;
     记住这个对你编程时为你的程序选择哪种显示方案很有用,如果你的游戏不打算使用高精度的画面就不要设置过高的色深,因为这会使游戏的运行速度打折扣,下面列出了编程时可能使用到的四种色深:
   8 bit - 256色
16 bit - 65536色
24 bit - 16百万色 *
32 bit - 16.7百万色 *(*表示相对占用较多的系统资源)

    24位显示模式与32位真彩色显示模式之间的差别其实很小,做一些关于它们之间效果比较的实验,或许你可以发现这种差别.

绘图页(注:有的地方称页面,图面):
      这是你有能力开始写代码任何实际的代码之前要明白的最后一件事情,DDraw使用一种叫"绘图页"的机制来承载图片信息,其实绘图页实际表示内存中某块特定的(图片数据)存储区,为便于理解,你可以把绘图页通俗地想象成内存中的一张白纸,向这张白纸上作贴图操作后绘图页中便有了这个图片的所有数据,这个绘图页便代表了这个图片,因此每个绘图页可以是不同的大小,绘图页可以通过加载硬盘里的某一张图片来填冲,也可以在系统后缓冲区由几张图片拼接形成,通过下面的学习,你将会对它们有一个更清的认识,但是到现在为止,你只要弄清主绘图页和后缓冲区绘图页的概念就行了,存储在主绘图页的任何内容都是屏幕当前实际显示的内容,在DX的全屏模式下,主绘图页的大小与屏幕大小等同,后缓冲区绘图页就是被设置成下一帧(或下一屏)要显示的页面内容,但是它在没有被设置成主绘图页之前,仅仅存在系统缓冲区内..
DX中引入后缓冲区绘图页可以防止屏幕闪烁,怎么理解呢?直接向主绘页图页贴图固然行得通,但当不断地向一个主绘图页贴大量的图片时(用静图制作动画效果时),或者当主绘图页由大量的小图组合而成的情况下直接在主绘图页上作拼接操作(主绘图页可能是由各种Tiles拼接起来的地图背景),由于主绘图页的内容会即时地显示在屏幕上,这二种情况下,屏幕的显示就会出现闪烁或延迟,而后缓冲区绘图页就解决了这个问题,首先这些小图可以先在内存中组合成一张大图贴在后缓冲区绘图页里,再把这个后缓冲区绘图页设置成主绘图页(术语称把后缓冲区绘图页拷贝到主绘图页,在程序中是调用一些页面复制函数来实现的,后面会讲到),这样就不会出现闪烁问题了

关于代码
本代码指导你建立简单的direcdraw程序,首先创建direcdraw对象,然后设立显示模式和色深,然后建立页面并将一图片绘制上面
part 1: 连接 Direct7对象库
工程=>引用=> Direct7 for visual basic type library
part 2: 定义directx 和 directdraw的变量
以下是全部的声明部分在主窗体
Option Explicit 'DirectX likes all it's variables to be predefined

Dim binit As Boolean 'A simple flag (true/false) that states whether we've initialised or not. If the initialisation is successful 'this changes to true, the program also checks before doing any drawing if this flag is true. If the initialisation failed and we 'try and draw things we'll get lots of errors...

Dim dx As New DirectX7 'This is the root object. DirectDraw is created from this
Dim dd As DirectDraw7 'This is DirectDraw, all things DirectDraw come from here
Dim Mainsurf As DirectDrawSurface7 'This holds our bitmap
Dim primary As DirectDrawSurface7 'This surface represents the screen - see earlier in the tutorial
Dim backbuffer As DirectDrawSurface7 'This was mentioned earlier on...
Dim ddsd1 As DDSURFACEDESC2 'this describes the primary surface
Dim ddsd2 As DDSURFACEDESC2 'this describes the bitmap that we load
Dim ddsd3 As DDSURFACEDESC2 'this describes the size of the screen

Dim brunning As Boolean 'this is another flag that states whether or not the main game loop is running.
Dim CurModeActiveStatus As Boolean 'This checks that we still have the correct display mode
Dim bRestore As Boolean 'If we don't have the correct display mode then this flag states that we need to restore the display mode



part 3:初始化 directdraw
现在我们需要使用上部分定义的变量。首先我们要创建DirectDraw对象,这个需要通过Directx对象。然后我们设立显示模式,然后创建主页面和后台缓存。一旦初始化完毕后我们把一图片放到页面中去,然后进入游戏主循环。
Sub Init()
On Local Error GoTo errOut 'If there is an error we end the program.

Set dd = dx.DirectDrawCreate("") 'the ("") means that we want the default driver
Me.Show 'maximises the form and makes sure it's visible


'The first line links the DirectDraw object to our form, It also sets the parameters
'that are to be used - the important ones being DDSCL_FULLSCREEN and DDCSL_EXCLUSIVE. Making it
'exclusive is important, it means that while our application is running nothing else can
'use DirectDraw, and it makes windows give us more time/attention
Call dd.SetCooperativeLevel(Me.hWnd, DDSCL_FULLSCREEN Or DDSCL_ALLOWMODEX Or DDSCL_EXCLUSIVE)
'This is where we actually see a change. It states that we want a display mode
'of 640x480 with 16 bit colour (65526 colours). the fourth argument ("0") is the
'refresh rate. leave this to 0 and DirectX will sort out the best refresh rate. It is advised
'that you don't mess about with this variable. the fifth variable is only used when you
'want to use the more advanced resolutions (usually the lower, older ones)...
Call dd.SetDisplayMode(640, 480, 16, 0, DDSDM_DEFAULT)


'get the screen surface and create a back buffer too
ddsd1.lFlags = DDSD_CAPS Or DDSD_BACKBUFFERCOUNT
ddsd1.ddsCaps.lCaps = DDSCAPS_PRIMARYSURFACE Or DDSCAPS_FLIP Or DDSCAPS_COMPLEX
ddsd1.lBackBufferCount = 1
Set primary = dd.CreateSurface(ddsd1)

'Get the backbuffer
Dim caps As DDSCAPS2
caps.lCaps = DDSCAPS_BACKBUFFER
Set backbuffer = primary.GetAttachedSurface(caps)
backbuffer.GetSurfaceDesc ddsd3


' init the surfaces
InitSurfaces

'This is the main loop. It only runs whilst brunning=true
binit = True
brunning = True
Do While brunning
blt
DoEvents 'you MUST have a doevents in the loop, otherwise you'll overflow the
'system (which is bad). All your application does is keep sending messages to DirectX
'and windows, if you dont give them time to complete the operation they'll crash.
'adding doevents allows windows to finish doing things that its doing.
Loop


errOut:
'If there is an error we want to close the program down straight away.
EndIt
End Sub



part 4: 初始化页面
此时DirectDraw已经初始化完毕,我们需要建立页面并把图片数据放里面。首先,你必须懂得描述(descriptions)的使用。
你在建立后台缓冲和前台缓冲的时候你必须进行描述,在你在建立页面的时候你需要设置它的描述,它的特有的或者其它。比如是创建主页面必须使用描述中的DDSCAPS_PRIMARYSURFACE标记.在前面设立好标记后面部分就能使用。(详见代码,本人水平有限很难解释清楚,看完代码也不难理解)
Sub InitSurfaces()
'This procedure may look small, but when you make a program this procedure could
'take a good 60-120 seconds to process, and run into 1000's of lines of code.

Set Mainsurf = Nothing 'Although the first time we call this procedure this
'variable will be empty, it must be cleared. As you'll see in the blt procedure
'the program may try and re-load the surfaces, at which point the "mainsurf" object
'will have some information in it. If we try and recreate a surface that already has
'information in it DirectDraw will crash, because of this we must clear the buffer first.


'load the bitmap into a surface - backdrop.bmp
ddsd2.lFlags = DDSD_CAPS Or DDSD_HEIGHT Or DDSD_WIDTH 'default flags
ddsd2.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN
'An offscreenplain means that
'the user never actually gets to see the surface - it is just an are in memory.
ddsd2.lWidth = ddsd3.lWidth 'the ddsd3 structure already holds the size
'of the screen. We could replace it with 640 and 480 - it would have the same effect
ddsd2.lHeight = ddsd3.lHeight
'this is where the surface is created. You use the DDraw object to create a
'surface from the specified file name using the above description.
Set Mainsurf = dd.CreateSurfaceFromFile(App.Path & "\backdrop.bmp", ddsd2)

End Sub



注意:
你在建立页面的时候只能使用位图。directdraw不支持载入.jpg .gif等文件格式。这将引起一个很大的问题-文件大小。比如一个640*480的位图有500kb,如果是.jpg格式的话只有37kb.不过有资料可以把.JPG .GIF 载入到页面.
5 绘制到屏幕上
在这里你将会看到你编写的程序在屏幕上显示。这时你应该有很高兴的心情学习 blit
blit 是复制整个或部分页面到别的页面.以下有五个不同的函数可以实现:
1.        Blt(destRect As RECT, ddS As DirectDrawSurface7, srcRect As RECT, flags As CONST_DDBLTFLAGS) As Long
This is the safer method, but is slightly slower. You must tell the function the destination rectangle and the source rectangle. This is useful, because you can apply basic stretching functions. ie. the source defines a rectangle of size 100x100, the destination rectangle is 200x200 - Directdraw will stretch the 100x100 section to fit a 200x200 section, basically doubling the size.
2.        BltColorFill(destRect As RECT, fillvalue As Long) As Long
This function doesn't actually copy a picture from or to anywhere. This fills the rectangle area with a colour.
3.        BltFast(dx As Long, dy As Long, ddS As DirectDrawSurface7, srcRect As RECT, trans As CONST_DDBLTFASTFLAGS) As Long
This method is used the most, simply because it is faster. You can't apply any transformations on this blit - it copies the rectangle to the destination as the same size. This is used in the following code.
4.        BltFx(destRect As RECT, ddS As DirectDrawSurface7, srcRect As RECT, flags As CONST_DDBLTFLAGS, BltFx As DDBLTFX) As Long
This function is used for applying transformations to the image, such as alpha-blending, mirroring, stretching and many more. It is very simliar to the blt function.
5.        BltToDC(hdc As Long, srcRect As RECT, destRect As RECT)
This is for interaction between DirectDraw and the Windows graphics functions. If you've used the windows API extensively then you'll have used DC surfaces at some point - this allows you to copy from a directdraw surface to a DC.
Sub blt()
'again, this procedure looks fairly simple - it is!
'You should try and keep this procedure as short as possible, and as fast as possible

On Local Error GoTo errOut 'If there is an error don't do anything - just skip
'the procedure
If binit = False Then Exit Sub 'If we haven't initiaised then don't try anything
'DirectDraw related.

Dim ddrval As Long 'Every drawing procedure returns a value, so we must have a
'variable to hold it. From this value we can check for errors.

Dim rBack As RECT 'a RECT is the rectangle that i've mentioned.



' this will keep us from trying to blt in case we lose the surfaces (alt-tab)
bRestore = False
Do Until ExModeActive
DoEvents
bRestore = True
Loop

' if we lost and got back the surfaces, then restore them
DoEvents
If bRestore Then
bRestore = False
dd.RestoreAllSurfaces 'this just re-allocates memory back to us. we must
'still reload all the surfaces.
InitSurfaces ' must init the surfaces again if they we're lost
End If


'get the area of the screen where our window is
'this sets the rectangle to be the size of the screen.
rBack.Bottom = ddsd3.lHeight
rBack.Right = ddsd3.lWidth

'blt to the backbuffer from our surface to
'the screen surface such that our bitmap
'appears over the window
'This Blits to the screen starting from 0,0 on the screen. the DDBLTFAST_WAIT
'flag tells Directdraw to wait if the blitter is busy at the time of the call.
ddrval = backbuffer.BltFast(0, 0, Mainsurf, rBack, DDBLTFAST_WAIT)


'flip the back buffer to the screen
primary.Flip Nothing, DDFLIP_WAIT
'At this point we have completed one cycle, and we can now see something on screen

errOut: 'Skip everything if there is an error. Don't stick a message box in here - because
'you're likely to be running the program at 100's of frames per second, in just one second the
'program will try and generate 100 message boxes...
End Sub



6 完毕释放对象
Sub EndIt()
'This procedure is called at the end of the loop, or whenever there is an error.
'Although you can get away without these few lines it is a good idea to keep them
'as you can get unpredictable results if you leave windows to "clear-up" after you.

'This line restores you back to your default (windows) resolution.
Call dd.RestoreDisplayMode
'This tells windows/directX that we no longer want exclusive access
'to the graphics features/directdraw
Call dd.SetCooperativeLevel(Me.hWnd, DDSCL_NORMAL)
'Stop the program:
End
End Sub

Private Sub Form_Click()
'Clicking the form will result in the program closing down.
'because the form is maximised (and therefore covers the whole screen)
'where you click is not important.
EndIt
End Sub

Private Sub Form_Load()
'Starts the whole program.
Init
End Sub

Private Sub Form_Paint()
'If windows sends a "paint" message translate this into a call
'to DirectDraw.
blt
End Sub
Function ExModeActive() As Boolean
'This is used to test if we're in the correct resolution.
Dim TestCoopRes As Long
TestCoopRes = dd.TestCooperativeLevel
If (TestCoopRes = DD_OK) Then
ExModeActive = True
Else
ExModeActive = False
End If
End Function




0

主题

291

帖子

291

积分

中级会员

Rank: 3Rank: 3

积分
291
QQ
发表于 2006-9-19 03:51:00 | 显示全部楼层

Re:directdraw7入门(一) 全屏模式

*(*表示相对占用较多的系统资源)

*表示需pay attention 的地方
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-25 11:33

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表