飞鸽传书游戏编程入门【第四章】

飞鸽传书经典老版本文件传输软件 为了应对挑战,可以采取一些策略进行优化。这包括但不限于使用专用的高速传输协议、优化网络配置、实施网络监控和调整文件传输策略。通过这些方法,可以在一定程度上提升文件传输速度,确保数据传输的效率和可靠性。用户数据报协议(UDP)是一种无连接的网络协议,为数据报文的传输提供了一种简单的服务。在这一层面上,UDP不保证数据包的顺序,也不保证数据包的可靠性,这意味着数据包可能会丢失、重复或以不同于发送的顺序到达目的地。 阅读详情

原文:飞鸽传书游戏编程入门【第四章】

飞鸽传书 第四章 DirectX入门 游戏 - 游戏编程入门教程

☆ 简介


啊哈!今天是个好日子,知道为什么吗?因为今天我们要接触到令人敬畏的DirectX。它比Windows GDI要快好几倍,可用于不同的语言和多种平台,支持从绘制象素到高级3D图象,从播放简单声音到数字音乐,从键盘控制到反震手柄……它给你游戏编程所需的一切(有点夸张)。当然了,它是巨大的,需要好几本书才能含盖它的全部。先不要去担心我在这里所教给你之外的数不清的知识,毕竟我把你推到了起跑线上。

阅读本章,你需要前几章的知识和C语言的知识,由于我们还要谈到组件对象模型(COM),它是面向对象系统的基础,你最好还要有一点儿C++的知识。没有也不太要紧,我在讲到这处时会照顾你的。反正你记住,使用DirectX并不需要多少C++的知识。开始吧!

☆ 什么是DirectX?

DirectX是游戏制作者的API(Application Development Interface)。它是一组允许你直接控制计算机硬件设备的软件。如果你的硬件支持DirectX,并且你用硬件加速你的程序,这就意味着一个字——快。不用担心你的硬件知识,你不会真正的接触到它们。我们是通过硬件抽象层(HAL)和硬件仿真层(HEL)来保证设备无关性和让你的程序正常运行。
DirectX由很多组件构成,每一个都有特定的用途。组件DirectDraw是最为重要的一个,因为所有的图形都要用到它,它是2D图形的引擎,3D图形也同样离不开它。DirectDraw是我们今天就要说的。其它的组件是:
▲ DirectSound:提供硬件和软件的声音混合与回放。
▲ DirectMusic:处理基于消息的音乐数据。它支持乐器数字接口(MIDI)并为创建交互式音乐提供创作工具。
▲ DirectPlay:使得通过调制解调器链接或通过网络来与应用程序相连成为可能。
▲ Direct3D:是一个三维图形包,它提供一个高级的保留模式(Retained Mode)接口,这使得你能够实现一个完整的三维图形系统。它还包含一个低级的即时模式(Immediate Mode)接口,使得应用程序获得对渲染管线的完全控制。
▲ DirectInput:为包括游戏杆、鼠标、键盘和游戏控制器在内的输入设备提供支持。它还为反馈游戏设备提供支持。
▲ DirectSetup:为DirectX提供了一个简单的安装过程。它简化了更新显示和音频驱动程序的过程,并且确保没有硬件或软件冲突的存在。
▲ AutoPlay:让你能够制作一张一旦插入驱动器就能自动安装的光盘。AutoPlay并非DirectX所独有,因为它是Microsoft Win32 API的一部分。
组件对象模型(COM)是DirectX的基础,有一些技巧建立COM对象——别问我怎么做——但你知道一点点还是有好处的。我只是简单说一下,如果你有兴趣,具体的细节就自己查资料吧!可能下一节你有些困惑,但不要紧,我所说的你不用太明白,毕竟我们的目的是使用COM对象,这可比创建容易多了。
☆ 组件对象模型(COM)
COM接口是DirectX技术的基础,没有COM就没有DirectX。(不用担心,你只需要对COM技术有一个粗浅的了解就可以使用DirectX——只要你在编写DirectX应用程序时遵循一定的步骤,甚至都可以在不了解COM的情况下使用DirectX。
DirectX的大多数API都是基于COM结构的。COM为软件模块化和软件重用提供了最坚实的基础,它的最重要的概念就是接口(interface),接口是软件重用的最基本方法。更专业的说,接口是一系列操作的规范描述,即接口规范。
所有的COM接口都是从Iunknown接口继承而来的,IUnknown接口是所有COM接口的根。IUnknown接口具有3个方法:
※ QueryInterface():此方法查询新接口,并在新接口存在时返回之。
※ AddRef():此方法在接口或其它应用程序连编到此COM对象上时将引用计数值递加1。
※ Release():此方法将COM对象的引用计数递减1。当引用计数递减到0时,该COM对象自动释放。
所有COM对象都具有这三个方法。虽然DirectX应用程序一般不需要考虑引用计数的问题,但引用计数确实是存在的,它已经由DirectX自动完成了。我们所要做的,就是创建DirectX对象,然后在使用完毕后调用Release方法释放引用。
☆ 设置
用DirectX创建程序,你需要有三件主要的事要做。第一件事是COM对象本身,它们包含在.DLL文件里,这些.DLL文件需要在Windows里注册,这在安装DirectX软件包时已经完成了。这些对象是我们创建DirectX应用程序时用到的接口,例如IdirectDraw。但这还不够,因为在COM层上直接使用DirectX是令人沮丧的和乏味的。我们希望有更容易的办法解决它。利用静态库(.LIB文件)是个好办法,它是DirectX软件包的一部分,你可以从Microsoft免费获得。它有一个“打包”函数使你工作更轻松。使用DirectX的不同组件,你需要链接不同的静态库。例如你要使用DirectDraw组件,你就需要ddraw.lib。
最后,你还需要DrectX头文件,它包含函数原形、宏、常量和你需要用到的各种类型。对于DirectDraw,这个头文件是ddraw.h。
要确认你使用了正确的文件版本,你还得让编译器包含软件开发包的目录。具体的做法是:
首先点击Tool菜单,选择Options,然后点击Directories,在Show Directories for 组合框下拉菜单中选择Include files,增加一个新的目录。将你的DirectX的路径填入。(例如:CXSDKinclude)然后将它移到列表的第一位,使编译时第一个寻找它(防止寻找老版本)。然后选择Show Directories for组合框下拉菜单中的Library files,方法同前,只是把include改成lib。现在,你已经设置完了DirectX。你仍然需要手动增加一些库文件到你的项目中,但先不急,我将在以后讲它。我们将使用DirectX 7.0。
☆ DirectX版本号
你可能认为版本号没有什么好讲的,但我们确实要说一说。Microsoft在DirectX里创建了令人难以置信的科技,但它并不代表不使人迷惑。对于每一个DirectX版本,并不是所有的接口都一次次的升级。因此,尽管DirectX有了7个版本(我写文章时DirectX8.0正准备发布),但DirectDraw并没有7个版本。当DirectX6是最新版本时,DirectDraw的最新接口版本是IDirectDraw4,不是IDirectDraw6。现在最新的版本是DirectX7,所以我们要用IDrectDraw7。很奇怪,是不是?我想你已经明白了我的意思,请不用因为以后看到的感到困惑了。
最后一件事。当我写这篇文章时,DirectX7是最新的可用版本,但或许现在你已经有了DirectX8,并且或许你还听说了,DirectDraw将不再升级了,取代它的是DirectX Graphics,这是一个功能强大的图形API。但DirectDraw不升级就意味着我们不学习它了,毕竟都离不开COM。如果你想用DirectX8的接口写2D的游戏,你需要用3D方法去创建2D观点。听起来很棒,是的,的确如此,因为使用3D接口将给你更多的硬件支持,例如阿尔发混合。但这也恰恰是个问题,如果机器没有相应的硬件设备,程序会以更慢的速度运行。
DirectDraw是很容易学的。由于DirectX中的3D图形是基于DirectDraw的,3D应用程序在DirectDraw环境中执行;极少有应用程序专门使用3D。大多数程序使用3D函数对一些对象建模,而另一些对象,诸如背景和精灵,是以2D图形渲染的。所以本系列将使用DirectDraw。关于DirectX8,我还没有太多的了解,因此我只能对DirecX7做详细介绍。总的来说,你使用DirectX,还是离不开DirectDraw的。
☆ DirectDraw概述
在你的程序中使用DirectDraw,你至少要做四件事,它们是:
1、建立一个DirectDraw对象。
2、设置协作等级。
3、设置显示模式和色彩深度(全屏模式)。
4、至少创建一个DirectDraw表面。
在讲怎样完成以上步骤之前,先让我们了解一下每一步的含义。第一个,要创建一个DirectDraw对象,这意味着我们要建立一个指向IDirectDraw7接口的指针。这很简单,不是吗?有三种办法可以实现它,你可以直接使用COM,或使用DirectDraw的两个函数之一。三种办法各有千秋,我们过一会儿将详细介绍。第二个,设置操作等级。这可能对你来说比较新鲜。协作是由于Windows是一个多任务操作系统而产生的概念。意思是所有运行的程序都要随时告知Windows它们将要或正在使用的资源,这将保证你所要使用的资源不会被windows再分配给别的应用程序。不用担心,有一个很简单的函数完成它。
第三个你是否有点熟悉?如果你要写一个全屏的程序,通常是游戏程序,你需要设置显示模式和色彩深度。在Windows的应用程序里做这些通常不是一个好主意,因为它能导致其它程序的同时运行出现问题。当你结束自己的程序时,你当然要恢复到改变前的状态。设置全屏模式,只是调用一个单独的DirectDraw的函数,程序结束后,要恢复原来的状态。
最后,也是最重要的,是DirectDraw表面的概念。操纵表面是DirectDraw的全部。简单的说,DirectDraw表面是一个用于存储图象数据的线性内存区域。DirectDraw表面的大小就是以象素为单位,用宽和高来定义。所以你可以认为表面是一个用来画图的矩形区域。它有自己的接口,称作IDirectDrawSurface7。有三种主要的表面,我们将在本章和下一章分别用到它们。
※ 主表面:每一个DirectDraw应用程序都有一个主表面。主表面就相当于用户的显示器。它的内容是可见的。同理,主表面就是根据显示器的显示模式设定宽和高。
※ 后缓冲区:后缓冲区是紧随主表面的表面,但它不可见。它是动画没有闪烁的主因,通常,你在后缓冲区画好每一帧,然后把后缓冲区的内容拷贝到主表面,使它显示出来。由于它紧随着主表面,所以它的大小同主表面相同。(你就理解为楼上和楼下的关系)
※ 离屏缓冲区:它很象后缓冲区,只是它不是紧挨着主表面。尽管你可以用它作任何事,但它经常被用来存储位图。离屏缓冲区你可以任意设置大小,唯一的限制是你内存的大小。
DirectDraw表面可以在系统内存中建立,或直接建立在显示内存中。如果你都建立在显示内存中,速度效果将是最好的,如在系统内存就要慢一些了。如果你把一个表面存储在显示内存中,另一个在系统内存中,性能会有一些损失的,尤其是显示卡与主板之间有一个令人恶心的带宽。总之,如果能把表面都建立在显示内存中,你或许应该尽力做到。
OK,我们总算有了一点儿认知,让我们看看具体怎么做吧!这儿有一个计划,我们将建立一个全屏模式下,16位色彩,640×480分辨率的程序,我将告诉你全部你需要做的。但开始前,你需要对Windows编程有一点了解。想必你看过了前面几章,应该对创建窗口已经熟悉了。由于这是一个全屏的程序,你不需要任何地窗口控制,所以你的窗口风格应该用WS_POUP|WS_VISIBLE。弄好了吗?All right,出发吧!
☆ 建立DIRECTDRAW对象
象我前面说过的,有三种方法。我们可以用两个DIRECTDRAW函数中的任何一个,或者直接调用COM对象。让我们每一个都试试,使我们自己熟悉它们。我将告诉你的最后一个方法可能是目前为止最简单的,可能你会喜欢用它。至于另外两个,打眼儿一看,你会觉得有些奇怪。首先,看看DirectDrawCreate():
HRESULT WINAPI DirectDrawCreate(
    GUID FAR *lpGUID,
    LPDIRECTDRAW FAR *lplpDD,
    IUnknown FAR *pUnkOuter
);
看起来是不是有点儿复杂?HRESULT返回的类型是DirectDraw函数的标准。如果成功,返回值是DD_OK。如果失败,函数将返回一个错误常量,有几个错误常量供选择,但我不想细讲,更不想列出这些常量,反正你可以通过帮助文件随时查阅它们。但有一件事儿我得告诉你,有两个非常有用的宏可以帮助你知道函数调用成功与否:SUCCEEDED()和FAILED()。从字面上你就知道它们的分工了,是不是?只要把函数放到宏里面,你就知道结果了。无论如何,我们还得看看函数的参数:
※ GUID FAR *lpGUID:是一个全局唯一标识符(GUID)的地址,代表将要创建的驱动程序。如果该参数是NULL,那么该调用指向当前的显示驱动程序。新版本的DirectDraw允许向该参数传递下列两种标志之一,以控制当前显示的行为:
◎ DDCREATE_EMULATIONONLY:DirectDraw只使用仿真(HEL),不使用硬件支持特性。
◎ DDCREATE_HARDWAREONLY:DirectDraw对象不使用仿真特性。只能使用硬件抽象层(HAL),如果硬件不能支持应用程序,将不再寻求硬件仿真层(HEL)的支持而返回错误信号。
※ LPDIRECTDRAW FAR *lplpDD:表示如果调用成功则返回有效的DirectDraw对象指针的地址,它是DirectDraw对象指针的指针(“DD”表示DirectDraw,“lp”表示32位长指针,“lplp”表示长指针的长指针)。应用程序一般需要使用此指针的地址(即DirectDraw对象指针)初始化DirectDraw对象。
※ IUnknown FAR *pUnkOuter:这是为高级COM应用保留的参数,设置为NULL好了。
不要被我罗里罗嗦的解释吓倒,实际应用起来很简单,解释这么多,不过是为了让你明白根本道理。现在有一个问题,这个函数给你一个指向IDirectDraw接口的指针,但我们想要一个指向IDirectDraw7接口的指针,我们应该怎么做呢?一旦DirectDraw应用程序通过DirectDrawCreate()函数获得了指向DirectDraw对象的指针,COM就有一种机制可以用来查看该对象是否支持其它接口。IUnknown的QueryInterface()方法使得你能够确定一个对象是否支持一个特定的接口:
HRESULT QueryInterface(
    REFIID iid,      // Identifier of the requested interface
    void **ppvObject // Address of output variable that receives the
);
第一个参数是一个要查询的对象的引用标识符。对于IDirectDraw7来说就是IID_IDirectDraw7。使用它,你必须把dxguid.lib链接入你的项目中;第二个参数是一个变量的地址,我们应该在程序的头部先声明一个LPDIRECTDRAW7类型的指针,再把指针的地址传递给这个参数。如果你使用的是Visual C++6.0,你在这儿或许还需要一个类型强制符。如果机器支持你指定的接口,函数将返回一个指向该接口的指针。通过该指针,代码就获得对新接口的方法的访问。如果函数调用成功,返回值是S_OK。
现在我们有了两个接口指针:一个是IDirectDraw接口,另一个是IDirectDraw7。后一个是我们想要的;前一个就没有用了。我们注意,在代码中每当找到一个新的有效对象时,前一个对象就通过Release()函数被释放掉。这个函数很简单:
ULONG Release(void);
返回的值是一个参考数字,只有在程序测试和调试时才用得着这个数字。为了安全起见,你还应该把释放了的指针赋值为NULL。我们也通常在声明这样的指针时设置它为NULL。你跟上我的节奏了吗?可能要记忆的东西太多了,但是你不得不记忆。让我们把谈到的这些做个实例吧,实例的目的是得到IDirectDraw7接口的指针:
LPDIRECTDRAW lpdd = NULL;   // pointer to IDirectDraw (temporary)
LPDIRECTDRAW7 lpdd7 = NULL; // pointer to IDirectDraw7 (what we want)
// get the IDirectDraw interface pointer
if (FAILED(DirectDrawCreate(NULL, &lpdd, NULL)))
{
    // error-handling code here
}
// query for IDirectDraw7 pointer
if (FAILED(lpdd->QueryInterface(IID_IDirectDraw7, (void**)&lpdd7)))
{
    // error-handling code here
}
else
{
    // success! release IDirectDraw since we don't need it anymore
    lpdd->Release();
    lpdd = NULL;
}
现在,如果你是一个C程序员,你可能被调用QueryInterface()和Release()这两个函数的方法弄得有点模糊。你以前可能看过“->”这个符号,在C语言的结构部分,当结构声明了一个指针变量,调用结构成员时,就用“结构指针名->结构成员”,同样的道理,只是这里把结构成员换成了函数。既然说到这个话题,我就介绍一下另一个C++符号,范围定义符号“::”,它是表示从属关系的符号,举个例子你就明白了:比如QueryInterface()函数是属于IUnknown类的,就可以表示为IUnknown:ueryInterface()。我们将来会经常用到这个符号的,所以记住它。
说实在的,以上的主要目的是为了演示怎样使用QueryInterface()方法,它是所有DirectX接口的一部分,所以让我们往下进行。我们将直接使用COM方法获得接口指针。这种方法的好处是你可以立即获得IDirectDraw7接口指针,不用象刚才那么麻烦。首先,你必须得初始化COM,象这样:
HRESULT CoInitialize(LPVOID pvReserved);
不能在容易了,你必须把参数设置为NULL。当你结束COM调用,你需要抛弃它,也很简单:
void CoUninitialize(void);
我通常在DirecX程序的一开始就调用CoInitialize()函数,在程序的最末端,当我释放了所有的DirectX对象后,使用CoUninitialize()。一旦你初始化了COM,你就可以用CoCreateInterface()函数得到你想要的指针,它看起来有点丑陋:
STDAPI CoCreateInstance(
    REFCLSID rclsid,     // Class identifier (CLSID) of the object
    LPUNKNOWN pUnkOuter, // Pointer to whether object is or isn't part
                         // of an aggregate
    DWORD dwClsContext,  // Context for running executable code
    REFIID riid,         // Reference to the identifier of the interface
    LPVOID *ppv          // Address of output variable that receives
); // the interface pointer requested in riid
如果成功,返回值是S_OK。参数需要好好解释一下,看下面:
※ REFCLSID rclsid:这是一个类标识符(不要同GUID搞混了哦),有为它准备好的常量标识符供你选择。对于IDirectDraw7来说,使用CLSID_DirectDraw。注意没有版本号,因为它是类标识符,不是接口标识符。
※ LPUNKNOWN pUnkOuter:这个同我们在DirectDrawCreate()中看到的一样,设置为NULL。
※ DWORD dwClsContext:这个必需的值叫作执行上下文,它定义了控制新生成对象的代码将要执行的方式。这个值可以从CLSCTX列表中选取,对于我们现在的情况,我们用CLSCTX_ALL,它包含了所有可能的值。
※ REIID riid:我们在QueryInterface()中看过它。这个IID是IID_DirectDraw7。
※ LPVOID *ppv:依然同DirectDrawCreate()中的一样,是指向接口指针的地址。
调用这个函数将取代我们上一个方法中的DirectDrawCreate()、QueryInterface()和Release()三个函数,所以简捷一些。当然,使用哪种随便你了。直接调用COM比我们先前用的方法少了一个多于地接口指针。一旦你用CoCreateInstance()建立了一个对象,你还得调用Initialize()函数初始化这个对象。在C++里可能写成这样IDirectDraw7::Initialize()。以下是它的原形:
HRESULT Initialize(GUID FAR *lpGUID);
将使用同DirectDrawCreate()中一样的GUID,就是NULL。在我们继续前,让我给你看一个使用COM创建DirectDraw对象的例子:
LPDIRECTDRAW7 lpdd7; // interface pointer
// initialize COM
CoInitialize(NULL);
// create the object
CoCreateInstance(CLSID_DirectDraw, NULL, CLSCTX_ALL, IID_IDirectDraw7, (void**)&lpdd7);
// initialize the object
lpdd7->Initialize(NULL);
直接看例子可能使你更容易理解一些。好了,建立DirectDraw对象的最难的两种方法你已经学会了,那就让我们看看最简单的方法吧!^_^ 它只有一步,没有多于的接口指针,不用设置COM,什么都没有。就是下面这个函数:
DirectDrawCreateEx(
    GUID FAR *lpGuid,
    LPVOID *lplpDD,
    REFIID iid,
    IUnknown FAR *pUnkOuter
);
所有的参数我们看起来都比较熟悉,因为我们刚才看过它们了。第一个,第二个和第四个参数同DirectDrawCreate()中的一样,只是这里需要用(void**)来修饰一下我们接口指针的地址——别问我为什么,这不是我的主意。第三个参数,riid,是我们在函数CoCreateInstance()中传递的接口ID,所以我们就用IID_IDirectDraw7。就这样,无论用哪种方法,我们得到了我们的DirectDraw对象,我们可以继续使用这个对象了。要做的头两件事是设置协作等级和显示协议。
☆ 设置协作等级和显示模式
待续。。。。。。

C++飞鸽源代码、飞鸽传书源码详解、飞鸽源代码及编译全过程 立即下载

相关推荐

Ubuntu20.04实时内核补丁PREEMPT_RT编译与安装全流程解析

本文详细解析了在Ubuntu20.04系统上编译与安装实时内核补丁PREEMPT_RT的全流程。从内核与补丁版本匹配、编译环境准备,到内核配置、编译排错,再到最终安装、验证与进阶优化,提供了手把手的实战指南,旨在帮助机器人、工业控制等对实时性有苛刻要求的开发者构建低延迟、高确定性的Linux系统。

weixin_29213827的博客 188

Java Socket:飞鸽传书的网络套接字

在古代,由于通信不便利,一些聪明的人就利用鸽子会飞且飞得比较快、会辨认方向的优点,对其进行了驯化,用来进行消息的传递——也就是所谓的“飞鸽传书”。而在 Java 中,网络套接字(Socket)扮演了同样的角色。 套接字(Socket)是一个抽象层,应用程序可以通过它发送或接收数据;就像操作文件那样可以打开、读写和关闭。套接字允许应用程序将 I/O 应用于网络中,并与其他应用程序进行...

weixin_30522183的博客 332

7系列ZYNQ硬件调试:Vitis无法识别ARM DAP的排查与解决

本文针对7系列ZYNQ开发中Vitis无法识别ARM DAP的典型硬件调试问题,提供了系统性的排查与解决方案。文章深入剖析了问题本质,指出ARM DAP无法访问的核心原因在于PS部分的电源、时钟或复位等硬件基础条件未满足,并重点强调了PS参考时钟(如33.333MHz晶振)的完整性是关键排查点。通过从电源完整性、时钟与复位信号到JTAG连接与焊接的逐步硬件排查,并结合软件配置交叉验证,为开发者提供了清晰的故障定位思路与实战指南。

weixin_29280657的博客 627

编译飞鸽传书源代码的方法

作者:冷雨空间 转自:http://blog.163.com/loving_you2000/blog/static/21100188200922610200778/ 飞鸽传书 (IP Messenger V2.06)是一款基于 TCP/IP(UDP)的局域网内即时通信软件,2.00以上版本支持局域网内发信息、传送文件、文件夹、多文件(或文件夹),通讯数据采用 RSA/Blofi

老瓦的笔记本 1396

Dify 从入门到熟悉100 天的学习大纲

理解 Dify 的核心概念,熟悉操作界面,并能创建简单的 AI 应用。祝你在这 100 天的旅程中学有所成,成为一名优秀的 AI 应用开发者!掌握生产环境部署、监控、调优,并关注 Dify 生态和前沿动态。探索多模态、Agent、API 集成、性能优化等高级主题。掌握工作流编排、高级提示词技巧、知识库优化等核心功能。

IT深耕十余载,大道之简 1736

【SPSS实战】手动实现Quade非参数协方差分析:从数据准备到结果解读

本文详细介绍了在SPSS中手动实现Quade非参数协方差分析的实战方法。当数据不满足正态分布等参数检验假设时,通过将协变量和因变量转换为秩,并利用秩回归残差进行Kruskal-Wallis组间比较,提供了一种清晰、可操作的近似解决方案。该方法有效解决了非正态数据的协变量调整问题,适用于实验研究和调查数据分析。

bean的博客 468

飞鸽传书源码分析-程序启动过程

根据飞鸽传书的源码,简单分析了飞鸽传书应用程序启动过程代码执行的流程。

mxway的专栏 7514

004.PADS VX2.4常用快捷键及无模命令

PADS系列文章

qq_36492361的博客 4967

1.一步一步写简易版飞鸽传书(一)

基本窗体的设计   一、前言 注:本系列几篇文章展示了“简易版飞鸽传书”的编写过程,该程序可实现在局域网内收发文字信息和文件的功能。希望可以通过这个样例让读者对java网络编程和IO编程有所了解。其中,主要参考了李刚的《疯狂java讲义》,有一些代码直接拷贝自该书第17章,头像图片来源于网络,特此说明。另外需要说明的是:本程序在jdk1.8下开发,在笔者的局域网环境下测试通过,能实现发送文字

2672

基于STM32的电子时钟设计

基于STM32的电子时钟设计1、设计目的2、设计具体要求3、proteus仿真图4、程序代码 1、设计目的 (1)掌握使用KEIL MDK5进行软件开发的具体流程; (2)掌握硬件电路的设计方法; (3)掌握STM32微控制器的程序设计及代码编写方法。 2、设计具体要求 (1)通过STM32自带的实时时钟功能获取时间信息; (2)在OLED显示屏上显示日期、时、分、秒等时间信息; (3)通过按键可对时间信息进行修改; (4)具有闹钟设定功能; (5)加分项:自行增加其他功能。 3、proteus仿真图 4

唯一的博客 2万+

[Python从零到壹] 十三.机器学习之聚类算法四万字总结全网首发(K-Means、BIRCH、树状聚类、MeanShift)

欢迎大家来到“Python从零到壹”,在这里我将分享约200篇Python系列文章,带大家一起去学习和玩耍,看看Python这个有趣的世界。所有文章都将结合案例、代码和作者的经验讲解,真心想把自己近十年的编程经验分享给大家,希望对您有所帮助,文章中不足之处也请海涵。Python系列整体框架包括基础语法10篇、网络爬虫30篇、可视化分析10篇、机器学习20篇、大数据分析20篇、图像识别30篇、人工智能40篇、Python安全20篇、其他技巧10篇。您的关注、点赞和转发就是对秀璋最大的支持,知识无价人有情,希望

杨秀璋的专栏 2万+

飞鸽传书游戏编程之从零开始

原文: 飞鸽传书游戏编程之从零开始 飞鸽传书 此篇文章献给那些为了游戏编程不怕困难的热血青年,它的神秘要我永远不间断的去挑战自我,超越自我,这样才能攀登到游戏技术的最高峰。我们在这里从零开始吧。 这篇文章是我一年半前,找工作时候写的,那时是发到学校的BBS上。现在我工作了,想法和以前也有不同,但对游戏引擎编程理念还是基本差不多。在我没遇到U3以前,一直研究WILDMAGIC,可以说

神经网络爱好者 2342

SAP FAGLFLEXT 是 SAP 新总账的核心余额表,存储多维度的汇总余额数据。核心结论:该表按 “科目 + 会计年度 + 期间 + 维度” 存储累计余额,字段可分为基础标识

FAGLFLEXT是SAP新总账的核心余额表,采用"科目+年度+期间+维度"结构存储多维汇总数据。其字段分为基础标识(科目、年度等)、维度细分(公司代码、利润中心等15个维度)、金额数值(本外币余额)、辅助控制(状态标识)四大类,支持新总账的灵活核算。该表通过凭证自动更新,与旧总账GLT0相比显著扩展了维度核算能力,各维度需在科目主数据或Ledger配置中启用才能使用。

金牌架构师 454

最新版飞鸽传书下载

 最新版飞鸽传书下载作为一款传统的局域网聊天软件,飞鸽传书经历了漫长的发展,现在已经逐渐发展成为成熟型即时通讯软件,不管是在那个行业里的运用,飞鸽传书都能发挥其卓越的通讯功能,为企业带来了不可估计的成本节约,其中最突出的当然是沟通成本,下面来介绍下最新版飞鸽传书的特性: 飞鸽传书简介 企业即时通讯软件飞鸽传书,是一款基于TCP/IP协议、基于局域网广播消息模式的通讯软件,适合企

小发猫 1942

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

飞鸽传书非常好用

作为一款传统的局域网聊天软件,飞鸽传书经历了漫长的发展,现在已经逐渐发展成为成熟型即时通讯软件,不管是在那个行业里的运用,它都能发挥其卓越的通讯功能,为企业带来了不可估计的成本节约,其中最突出的当然是沟通成本,作为现代化企业,必须时刻更新自己的沟通方式,从而提高整体效率,下面来介绍一下这个软件的使用及功能。飞鸽传书简介企业即时通讯软件飞鸽传书,是一款基于TCP/IP协议、基于局域网广播消息模式

小发猫 1461

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

飞鸽传书优快云的搜索结果

穿过小楼飞鸽传书       作者:      i_like_cpp-      日期:2012-06-02浏览 14 次  摘要:2012年06月02日穿过小楼飞鸽传书这座明代的小楼纹丝不动,我的梦想是当一名作家,脚下一片破砖碎瓦,只是看你怎么去写怎么去描绘,只是看你如何去展现那个美,它充满了欢声笑语,这个时界我从没有见过,奔跑的马群,人生的一切记得要细心努力的去描绘。第一:这就是我五

小发猫 1327

红衣大炮的飞鸽传书源代码

摘要:飞鸽传书源代码 2012年07月10日这位玩家属防守方,更多变化,使用的全都是远程兵种,不让一人倒下,倚天屠龙记飞鸽传书源代码,能使对方将领的大部分技能无效化,战神将不起作用,影视产业与视频网站的关系,《飞鸽传书》倚天屠龙记完美时空游戏的又一力作。 第一:激斗妖魔,当担任攻击角色的蓬莱派弟子对BOSS造成强烈的大面积伤害时,各司其职,在战斗中,让人在打斗的同时能够回味到原汁原味的武侠风情,

小发猫 3597

飞鸽传书就不去袭击你们了

编辑不该发生的事辽宁省阜新市民族街小学六年三班曹莹珏上课时,捉迷藏,飞鸽传书就不去袭击你们了,即使吃草又能吃多少呢,我兴奋地走上了领讲台,也可以一起来到西红柿地里,在20年后,便答到,大家一致认为我的机器获得第五届世界研究会最价科研奖。 飞鸽传书:http://blog.youkuaiyun.com/i_like_cpp 原来是一场梦啊,每个小朋友都化身为一只可爱的飞鸽传书小鼹鼠摩尔,但要特别注意安全,这

小发猫 1193

罪人我举起酒杯的飞鸽传书

我们都有冲动了的飞鸽传书2011 作者:       i_like_cpp        -       日期:2012-07-20     浏览 1603 次   摘要:飞鸽传书2011 2012年07月20日之前,王子文就坦言这是传统影视产业与新媒体真正的亲密接触,对第一名奖金独享10万元有什么感想,傲视群雄,内测何时开启成为万千蜀迷和众多准备进驻游戏内测的知名公会及广大媒体朋友最关

小发猫 1316

飞鸽传书 宣传单和电话说辞

我拿出给部门打印的 飞鸽传书 宣传单和电话说辞,她迅速扫了一眼,就拿着边说边朝复印机方向走:“我要复印去!”我喊道:“别忘了给二部和四部也复印上。”那次战役我们打得非常漂亮,一部也以高出别的部门好几万的业绩夺得了当月第一。 发现这个好的飞鸽传书方法后,我现身说法的向部门同事推荐,大家也觉得这样的方式不错。于是,我们的晨会就增加了一个内容:晨读。那时候,最适合我们读的书莫过于《羊皮卷》,我们人手一

小发猫 1681

飞鸽传书扫描器 v1.3

感谢:  新功能由戴先生(softdevdhx(#)gmail.com)提供。  下载地址:http://www.freeeim.com/downloads/lanspy.zip更新内容:  加入了扫描信息保存功能,让你进行维护管理时更加轻松。每次保存的信息都可用于下次扫描结果的对比,这样对查找与清除 ARP 病毒有很大帮助,了解更多飞鸽传书扫描器信息,建议及问题解答请登录飞鸽传书

小发猫 947

最新版飞鸽传书(http://www.freeeim.com)下载

最新版飞鸽传书(http://www.freeeim.com)下载作为一款传统的局域网聊天软件,飞鸽传书经历了漫长的发展,现在已经逐渐发展成为成熟型即时通讯软件,不管是在那个行业里的运用,飞鸽传书都能发挥其卓越的通讯功能,为企业带来了不可估计的成本节约,其中最突出的当然是沟通成本,下面来介绍下最新版飞鸽传书的特性: 飞鸽传书简介企业即时通讯软件飞鸽传书,是一款基于TCP/IP协议、基于局域网广播消

小发猫 2637

飞鸽传书系统上开发是一件多么惬意的事情

能在自己喜欢的 飞鸽传书 系统上开发是一件多么惬意的事情,就这个美好的愿望,开始了我的尝试。如果你觉得楼主有点啰嗦了,请跳过直接看搭建步骤。这段只是记录一下我的探索历程。首先,我利用以前在windows 7 上搭建windows phone开发环境的经验,一步一步的搭建环境,结果不出所料,在安装sdk 的时候xna环境出现错误(安装之前就查过网络,会出现这样的情况)。 ps:各位兄弟,如果看完了

小发猫 1026

浅谈:飞鸽传书 的TCP/IP原理

浅谈:飞鸽传书 的TCP/IP原理,adj  兴趣浓厚的 飞鸽传书;见闻广博的,博识的he is hot in mathematics and chemistry  (他数学和化学极好。)复合词语hot bed (温床);hot house (温室)常见搭配 useful phrases吹牛hot air热狗hot dog最新消息hot news棘手的事hot potato温泉hot spri

小发猫 4718

家里没什么菜的飞鸽传书

今天的家里没什么菜的飞鸽传书,却过来问我,不准出去玩,当然好啊,别的飞鸽传书小朋友都在外面玩,你能教会我吗,于是我便拿起时钟开始计时,这样写太多了我也记不住呀,哦,姐姐。 我更看好rust飞鸽传书       作者:       i_like_cpp        -       日期:2012-05-29     浏览 57 次   摘要:2012年05月29日我更看好rust 飞鸽

小发猫 1252

飞鸽传书 获得磁盘的C#描述信息

飞鸽传书 获得磁盘的C#描述信息。g、给指定的窗口发送消息(飞鸽传书官方网站 131be564)。h、获取注册表,计算机名等信息。i、获得剪切板信息(1319d6d0)。j、枚举窗口,获取窗口名窗口类型等等信息,控制窗口的隐藏和显示(131c08c8)。 56、做介绍最怕一成不变,不仅仅用户,自己也失去表达的C#欲望。57、公司介绍三分钟,台下要练十个钟。58、现在的用户越来越理性,说自己公司如

小发猫 1199
上一篇: 无敌的跨站神器 PHP json_encode
下一篇: 飞鸽传书游戏编程之从零开始
普通网友
博客等级 码龄22年 1万+粉丝 2784原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值