两个小时学会DirectDraw编程

 

这并非哗众取宠, 通常学习一种电脑技术有两种方法. 一种是自己摸索, 在错误的方向上一错再错, 屡战屡败, 不过最后得道成功. 另一种是有人 或好的材料指导, 因而事半功倍, 在正确的方向上走了速成的捷径. 就象KFC 的鸡一样. 第一种学法能学出电脑天才, 因为所谓电脑高手, 其实就是排错试错的高手. 而第二种则出电脑专才. 这个两小时(?)的学习, 不能使你深入的掌握DD, 不过可以给你编制DD的框架. 能给你 一个起始点, 这个教程就算成功了. DirectDraw编程需要一些背景知识: DirectDraw是为在 Windows95/NT 下实现高速图形显示所写的程式库. 高速图形显示的基本方法是用一种叫做 Page Flipping的技术. 关于什么是 Page Flipping, 参见古技介绍.如果你 不急的话, 看到下面, 你也会看到. 在 Windows95/NT下做 Page Flipping 分为全屏的和窗口的两种. 在全屏下Page Flipping 叫做Flip, 在窗口下叫做 Blit. 知道了这些背景知识, 我们可以开始写程式了. 写所有 DirectDraw的程式, 差不多都有以下几个步骤, 1. 初始化, 这是每个程式都需要的劳什子. 2. 设置显示模式. 3. 在内存里建立PageFlipping所需要的两个页, 前页和后页. 4. 给显示的区域加个画框以免画到外面来. 5. 在后页画图, 然后"刷"的一下子换到前页来. 步骤一: 初始化 DirectDraw 是一个面向对象的函数库. "面向对象"的意思并不是指面对著你的女朋友, "对象" 在这里, 你可以简单地想象成是一个模板, 比方说,"政府", 一旦你说:"我成立了一个政府". 别人 就会立即把你套入"政府模板", 自然而然地认为你有印钞票的功能. 在我们的程式里, 你一旦声明 一个变量(比如 myDD)是 DirectDraw对象 (DirectDraw对象的正式名为 LPDIRECTDRAW) , 这个myDD就有了 DirectDraw对象的所有的功能和特性. 定义 的语法是: LPDIRECTDRAW pMyDD; 除了 DD的对象外, 还有几个重要的对象, "页面", "裁剪板" 和 "调色板". "页对象"用来定义"前页"和"后页". 定义如下: LPDIRECTDRAWSURFACE pMyDDSFront; LPDIRECTDRAWSURFACE pMyDDSBack; 一个"裁剪板对象", 在窗口模式下用来剪去画出窗口边界的部份. LPDIRECTDRAWCLIPPER pMyClipper; "调色板"设定屏幕的颜色表, 在读取256色的 Bitmap时要用到. LPDIRECTDRAWPALETTE myDDPal; 最最重要的"对象"就是这些了. 当然 DirectX还有很多复杂晦涩的对象. 这是速成不起来的. 编制 Windows 程式有一大堆变量和对象是 Windows所要求的, 这也是我最烦 Microsoft的地方. Microsoft 似乎知道这点. 所以在 VC4.0后的版本有了 Wizard的功能帮你自动生成代码. 尽量地去用它的 Wizard使我们的生活变得容易. 由于我们的程式可能会占用一个窗口, 就给这个窗口一个 handle: HWND myWnd 初始化的工作还没有完, 我们要把这些对象指向一个安全的地方 Null. pMyDD = NULL; pMyDDSFront = NULL; pMyDDSBack = NULL; pMyClipper = NULL; pMyDDPal=NULL; 最后, 在 Windows系统为我们的 myDD对象开辟相应的区域: DirectDrawCreate( NULL, //用当前的显示驱动 &pMyDD, NULL)) Okay, 烦人的初始化总算完了. 步骤二: 设置屏幕的显示方式. DirectDraw 有自己的设置屏幕的方式, 而且它的屏幕模式分为"全屏"( exclusive mode)和"窗口"( normal mode). 各有各的设置方法. 设置的主要区别在于 SetCooperativeLeve的参数. SetCooperativeLeve 在"窗口"模式下这样设置: pMyDD->SetCooperativeLevel(AfxGetMainWnd()->GetSafeHwnd(),DDSCL_NORMAL); 而在"全屏"模式下这样设置: pMyDD->SetCooperativeLevel( hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN ); 如果它们的返回值为 DD_OK表示成功. 我们就可以把屏幕调节成我们想要的样子, 例如 640x480x8. 也就是256色. 究竟有那些屏幕模式可用取决于你的显示卡 pMyDD->SetDisplayMode( 640, 480, 8 ); 现在, 我们已经有了一个屏幕, 不过还不能在上面画画, 我们需要步骤三来 替我们建立一个可供画画涂涂用的画板. 步骤三: 建立前后页(两块画板). // 本文转自 C++Builder研究 - http://www.ccrun.com/article.asp?i=440&d=qz1uyo br> 两块画板的好处是可以一边在一块上面画, 一边给别人看已经画好的另一块. 等这块画好了, 两块板就对调一下, 让别人看新画好的这块. 如果画的足够快, 换的足够快. 看的人就会看到动画了, 就象电影的效果一样. 我们把这叫做 Page Flipping. 这里先要介绍的是怎样在系统中建立两块画板( double buffering), 不过你也可以根据需要建立三块,四块画板. DDSURFACEDESC ddsd; //这个结构描述"页"的特徵. ddsd.dwFlags = DDSD_CAPS; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;//指定我们用的是前页. ddsd.dwSize = sizeof(ddsd); //尺寸 // 做前页: HRESULT result; result = pMyDD->CreateSurface(&ddsd, &pMyDDSFront, NULL); 当发生错误时, 要记得 Release对象. if (result!=DD_OK) { pMyDD->Release(); pMyDD = NULL; } ddsd.dwWidth = scr_width; //设定后页的大小, ddsd.dwHeight = scr_height; //指定 我们要后页 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; //做后页 result = pMyDD->CreateSurface(&ddsd, &pMyDDSBack, NULL); } 步骤四: 给显示区加一个画框(裁剪板). 在窗口下. 为了防止 DirectDraw 画到窗口外面去. 需要加一个画框(裁剪板). 可以用 CreateClipper来 创建剪贴板. result = pMyDD->CreateClipper(0, &pMyClipper, NULL); 创建后,把它套到窗口上去, 所以要知道是那一个窗口( Handle). myWnd = AfxGetMainWnd()->GetSafeHwnd();// 从系统中拿到窗口的 Handle result = pMyClipper->SetHWnd(0, myWnd); // 把剪贴板加到窗口上去 result = pMyDDSFront->SetClipper(myClipper); 步骤五: 在后页画图, 前后页互换. 其实到这里才是真正开始写游戏的地方, 以前在 DOS下写游戏, 就是直接从 这个步骤开始的. 以上这些工作, 都是 Microsoft强加给我们的. 写游戏之前我们先来解决前后互换的问题. // 如果前页的内存被 Windows"征用"了, 这里把它要回来. 这个检察常常会被忘记. if (pMyDDSFront->IsLost() == DDERR_SURFACELOST) pMyDDSFront->Restore(); DirectDraw 用来互换的语句有 Blt和 BltFast. BltFast据称比 Blt快10%. result = pMyDDSFront->Blt(&rcTo, pMyDDSBack, &rcFrom, DDBLT_WAIT,NULL); result = pMyDDSFront->BltFast( 0, 0, pMyDDSBack, &rcFrom, DDBLTFAST_SRCCOLORKEY); 如果程式工作在"全屏"模式下. 前后页互换容易得多, 只是一句: result = pMyDDSFront->Flip( NULL, 0 ); 现在就到了游戏的主要部份了, 我们称之为"游戏逻辑"部, 在普通的游戏中, "游戏逻辑" 通常 要做很多事, 如画游戏场景, 故事处理等等. 做完这些事后, 再和前页做换屏. 不过怎样做你的 游戏, 就没有我什么事了:-) 所有的步骤都讲完了. 是不是觉得特容易? 半个小时就够了? okay, 剩下的一个半小时让 你把它们变成真正的代码吧. 打开你的 Visual C++, 我用的是 VC5.0, 不过你也可以用 VC4.0. 再低恐怕就不可以了. 别忘了检查一下你的 DirectX SDK 有没有安装好. 打开VC, 选择 MFC app EXE Wizard 来生成程式的框架, 我假设学DirectDraw的人应该 会用VC, 所以怎样用 Wizard, 我就不再赘述. 进入 IDE环境后, 加入一个新 CPP file, 把上面用到的子函数的代码打入. 当然你还需要一个 .H file 来放变量名, 对象名和子程式名. MFC(Microsoft Fried Checken)的 Wizard会帮你生成 ::InitInstance() 和 ::OnIdle(LONG lCount), 把你的 初始化部份, 建页等步骤放在 InitInstance子类里. 把"游戏逻辑"和换页放在 OnIdle里.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 两个STM32 SPI DMA通信是指使用STM32微控制器中的SPI接口实现两个设备之间的数据传输,使用DMA(直接内存访问)来提高数据传输的效率。 首先,SPI(串行外设接口)是一种常用的串行通信协议,可以用于芯片间的数据传输。在STM32微控制器上,每个SPI接口都有多个DMA通道可以用来进行数据传输。 具体实现时,首先需要配置SPI接口的工作模式、数据位宽、时钟极性和相位等参数。然后,配置两个SPI接口的DMA通道使能,分别将数据发送与接收缓冲区的地址和数据长度装入DMA通道对应的寄存器。接下来,启动DMA传输,SPI模块就会在需要时请求DMA传输数据,而不需要CPU的干预。 通过使用SPI和DMA的组合,可以实现高效的设备间数据传输。SPI接口提供了双向的数据传输,可以通过一个设备发送数据,并由另一个设备接收数据。DMA通道可以在每次传输完成后自动更新缓冲区地址,从而实现连续的数据传输,减轻了CPU的负担。 总而言之,两个STM32微控制器通过SPI接口和DMA通信可以实现高效的双向数据传输。它需要配置SPI接口的参数,并为DMA通道加载数据和地址,然后启动DMA传输。通过使用SPI和DMA的组合,可以提高数据传输的效率,减少CPU的参与程度,从而提高系统的整体性能。 ### 回答2: 两个STM32的SPI DMA通信是指使用STM32微控制器中的SPI接口和DMA控制器进行数据传输。SPI(串行外设接口)是一种常见的通信协议,用于在微控制器之间或与外设之间进行高速数据传输。DMA(直接内存访问)是一种硬件机制,允许数据在不需要CPU干预的情况下在外设和内存之间直接传输。 两个STM32之间的SPI DMA通信可以通过以下步骤进行: 1. 初始化SPI和DMA:配置两个STM32的SPI接口和DMA控制器。设置SPI的通信模式(主从模式)、数据位宽、数据传输速率等参数。配置DMA通道、传输方向、数据长度等参数。 2. 缓冲区配置:为每个STM32准备一个发送缓冲区和接收缓冲区。这些缓冲区将用于存储待发送和接收的数据。 3. 启动DMA传输:在发送STM32上启动DMA传输。将待发送的数据放入发送缓冲区,并启动DMA通道以将数据传输到SPI发送寄存器。DMA将负责将数据从内存传输到SPI发送寄存器,而不需要CPU的干预。 4. 接收数据:在接收STM32上启动DMA传输。启动DMA通道以从SPI接收寄存器接收数据并将其传输到接收缓冲区。DMA将负责将数据从SPI接收寄存器传输到内存,而不需要CPU的干预。 5. 数据处理:从接收缓冲区中读取接收到的数据并进行相关处理。根据具体应用的需求,可以使用CPU对数据进行处理、分析、存储等操作。 6. 停止DMA传输:当数据传输完成后,停止DMA传输。 7. 清除中断标志:在SPI DMA通信结束后,清除相关的中断标志位。 通过使用SPI接口和DMA控制器,两个STM32之间可以实现高速的数据传输。这种通信方式具有高效、低延迟的特点,可以在一对多、多对一的场景中进行数据传输,适用于实时性要求较高的应用。 ### 回答3: STM32是意法半导体(STMicroelectronics)公司推出的一系列32位微控制器产品,具有强大的性能和丰富的外设功能。SPI(Serial Peripheral Interface)是一种串行外设接口协议,可用于多个设备之间进行全双工的通信。 在两个STM32微控制器之间使用SPI和DMA进行通信可以获得更高的数据传输效率和实时性。DMA(Direct Memory Access)是一种不需要CPU的介入,直接进行内存到外设或外设到内存的数据传输技术。 首先,要实现两个STM32之间的SPI通信,需要确定一个设为主机(Master),另一个设为从机(Slave)。主机负责发起通信请求和控制数据传输的时序,从机则响应主机的请求并处理数据。 接下来,需要在主机和从机上设置SPI外设。这包括设置SPI通信模式、数据帧大小、时钟极性和相位等参数。同时,还要配置DMA控制器以实现SPI数据的直接传输。 在主机中,通过配置DMA控制器,可以将要发送的数据从内存中直接传输到SPI数据寄存器,而不需要CPU的介入。在从机中,同样通过DMA控制器,将从SPI数据寄存器接收到的数据直接存储到内存中。 在数据传输过程中,主机可以通过SPI的片选信号选择特定的从机进行通信,以便实现和多个从机的通信。 由于使用DMA进行数据传输,可以大幅度减少CPU的负载,提高系统的实时性和响应速度。同时,SPI的全双工通信特性也保证了数据的高效传输。 总之,通过使用STM32的SPI和DMA功能,可以实现两个微控制器之间的高效通信。这将带来更好的系统性能和响应能力,为各种应用提供了一种可靠的通信方案。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值