观察一下发布格式。
Category: Uncategorized
Chinese old article
《于瑜与余欲渔遇雨》于瑜找我去捕鱼,没想到却下雨了。于瑜欲渔,遇余于寓。于瑜想捕鱼,于是决定和我在我们家那大宅子开个碰头会,策划一个捕鱼X计划。语余:“余欲渔于渝淤,与余渔渝欤?”于瑜跟我说:“我想在重庆嘉陵江的河床搞个捕鱼X计划,开发当地经济,跟我一起合股搞吗?”余语于瑜:“余欲鬻玉,俞禹欲玉,余欲遇俞于俞寓。”我跟于瑜说:“我想搞玉器买卖,听过黄金有价玉无价吗,这活是三年不开张,开张吃三年,现在就有个叫俞禹的衣食父母要供我三年的消费,所以我想到俞禹家跟进一下这个重大事件。要不你就跟着我干吧,兄弟我吃饭,就保你有粥喝。余与于瑜遇俞于俞寓,逾俞隅,欲鬻玉与俞,遇雨,雨逾俞宇。于瑜一听着买卖感情好,一本万利啊。于是改行了,P掂P掂的跟着我上了俞禹家,想一睹俞禹那冲头的样儿。刚到他家墙脚,本想把和田玉(之所以说是和田玉,是因为和田羊脂籽玉是玉中极品,其他玉太次,而一般不懂行又有钱想玩玉的就喜欢砸钱,所以和田玉概率高一点。而翡翠则不用玉字)卖给这冲头的,没想到老天知道我要坑他,于是哭了,那眼泪使他家积水了。”余语于俞:“余欲渔于渝淤,遇雨俞宇,欲渔欤?鬻玉欤?”于是我就跟俞禹摆了个噱头:“我想去重庆嘉陵江捕鱼的,不走这条路的,因为你想买玉,我饶路过来了,没想到在你家遇到大雨,现在连我自己也搞不清楚到底是该去捕鱼呢还是把玉卖给你呢?”我的目的是让他过意不去,坑他买我的玉。于瑜与余御雨于俞寓,俞鬻玉与余禹,雨愈,余与于瑜踽踽逾 。于瑜和我在俞禹家躲雨,顺便我和俞禹就在大水的伴奏下敲定了这笔买卖,老天看没法挽回了,再哭只是浪费眼泪,于是也就不哭了。我和于瑜虽然内心狂喜,但却不露声色,耷拉着脑袋离开了他家。
XP WLM
今天又收到了微软WLM beta的邀请Mail,哈哈哈。先体验一下微软下一代IM。
XP the mail beta
今天收到了微软Mail Beta发来的体验邀请信。现在开始就可以用Live平台的邮件系统了。基本上就是Live的色彩风格。
简短的Direct3D8知识点小结
Direct3D8 Direct3DDevice8 VertexBuffer IndexBuffer CUSTOMVERTEX Structure (2D, 3D) CUSTOMVERTEX Macro (2D, 3D) ImageSurface Texture Cursor ———————————- Three Coordinates ( Local, World, View) Projection ———————————- Before Rendering , don’t forget to set the VertexShader, Stream and Texture DrawPrimitive DrawPrimitive(UP) (This will reset the zero stream) Don’t forget to SetTexture and SetStreamSource to NULL ———————————– CameraX, CameraY… Continue reading 简短的Direct3D8知识点小结
DirectAudio
DirectAudio是以前的DirectSound和DirectMusic的组合,事实上我们现在用到的还是原来的那两个(DirectSound和DirectMusic),只是可能微软给了他们一个组合后的新名词(DirectAudio),但是实际上的内容还是那些。毕竟不可能那么快的对那两个DirectX中最复杂的组成部分进行大的改变。对,确实是最复杂的,而且对我这个没有任何音乐细胞的人来说更是如此。 DirectSound 创建DirectSound对象步骤: 创建DirectSound对象(LPDIRECTSOUND) 设置协作级别 创建声音缓冲(LPDIRECTSOUNDBUFFER, DSBUFFERDESC, WAVEFORMATEX) 把声音数据写入声音缓冲(类似于写入DD中的后备缓冲,只是有两个按照降序排列的指针) 播放声音 停止声音 控制音量(-10000 – 0,其实也就是设置衰减程度) 调整频率(100 – 100000 Hz) 调整声道平衡(最左:-10000, 最右:10000) 以上这些步骤都是比较固定的,其中难点在于4,声音数据那里来?当然我们可以自己乱写一些数据(我就写过一个正弦波形到缓冲区中让DirectSound播放,其结果就是虐待耳朵),但是最常用的就是从一个已有的WAV文件导入。但是问题是WAV的读取非常的复杂,比BMP文件复杂得多。但是我们可以使用一些已经有的函数。对于WAV文件格式的研究我想暂时搁浅一下。好,如果不算这个问题,那么DS的使用就基本没有问题了。适当调用7-9的步骤可以播放出来一些声音上的特效。 这一章不是我学习DirectX的重点,所以我并没有投入学得太多,这里就都简要介绍一下。 DirectMusic DirectMusic是整个DirectX中纯的COM最初出现在DirectX 6.0中,也是最复杂的,也是最强大的。以下介绍一下如何用DirectMusic来播放一个MIDI文件。 DirectMusic创建步骤: 初始化COM 创建一个演奏对象(IDirectMusicPerformance) 给演奏对象增加端口(IDirectMusicPort) 加载一个MIDI段(IDirectMusicLoader) 播放MIDI(由演奏对象IDirectMusicPerformance控制) 停止MIDI 检查MIDI段状态 释放一个MIDI段 这些步骤确实非常复杂,很多都是需要直接调用COM中的函数,而不是DirectMusic提供的。但是它给我们播放MIDI文件带来了统一和方便,DirectMusic为我们作了一切。另外需要注意的是DirectMusic如此只能播放一个MIDI文件,也就是当你播放另外一个MIDI的时候,前一个会自动停止。而不象DirectSound中那样可以同时播放多个WAV。 关于DirectSound和DirectMusic就说这些吧,真的是非常非常少,甚至漏掉了很多东西,但是少并不表示他简单,而事实正是声音部分是最复杂的,但是我不想涉及太多声音的问题,我只是想先照顾画面:)
DirectInput
在看了一大篇的2D图形基础(没有写blog,因为太难用语言表达了,需要绘图)之后,感觉游戏设计中真是与数学的关系太紧密了。简直就是在摆弄数学,呈现在我们面前的画面都掌握在数学之中。现在回过神来再继续看DirectX的组成部分——DirectInput。 DirectInput是DirectX中对于输入设备这一块硬件的封装,提供了快速的对于输入设备的查询。要使用DirectInput来获得输入基本步骤如下(在知道了DirectDraw以后再看DirectInput就觉得DirectX各个部件总有那么点相似处): 创建IDirectInput8接口,它提供对整个DirectInput的支持。LPDIRECTINPUT8 lpdi;DirectInput8Create(main_instance, DIRECTINPUT_VERSION, IID_IDirectInput8, (LPVOID*)&lpdi, NULL); 查询设备的GUID。这一步基本上只对于JoyStick之类需要调用,特殊的如果有多个鼠标也需要调用,一般对于键盘和鼠标不需要,因为有全局定义的默认键盘鼠标的GUID:GUID_SysKeyboard和GUID_SysMouse(需要#define INITGUID, #include <OBJBASE.H>或者连上DXGUID.LIB)。 调用CreateDevice方法来创建一个设备。IDIRECTINPUTDEVICE8 lpdikey;lpdi->CreateDevice(GUID_SysKeyboard, &lpdikey, NULL); 对于你创建的设备设置协作等级。lpdikey->SetCooperativeLevel(main_window_handle, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE);这两个是常用的属性,表示程序在后台可以使用设备并且非独占使用。如果有另外一个独占/前台运行的程序,那么这个调用就会失败。 设置数据格式。这里设置了什么数据格式,在最后查询的时候就用相应的数据结构。对于键盘,数据格式为256个元素的UCHAR的数组,对于其他设备则有相应的数据结构(DIMOUSESTATE, DIJOYSTATE, DIJOYSTATE2)lpdikey->SetDataFormat(&c_dfDIKeyboard);c_dfDIKeyboard, c_dfDIMouse, c_dfDIJoystick, c_dfDIJoystick2为预定义的DIDATAFORMAT结构。 设置设备的性能。这个步骤一般不用,即使对于复杂的JoyStick也只是需要设置其中的很少部分。因为这个调用相当可怕。 获得设备。lpdikey->Acquire(); 轮询设备。lpdikey->Poll(); 从设备获得数据。这是我们真正需要的。以上的一切都是为了这个。UCHAR keystate[256];lpdikey->GetDeviceState(sizeof(keystate), (LPVOID)keystate);然后就可以对每个数组元素进行查询,来确定按键的情况。(&0x80 != 0 表示按下)DirectInput中对于虚拟键的定义以DIK_开头。 最后,说一下释放设备的过程。lpdikey->Unacquire();lpdikey->Release();lpdi->Release(); 以上这些步骤就是对于最简单的设备——键盘的使用。不过其他的设备和他也并没有差开多少。只是Joystick在开始的时候需要用回调函数和枚举的方法来获取GUID,然后就可以顺着下面的步骤做下来。 下面还有另外一个问题:在DirectInput工作过程中输入设备很可能发生各种各样的意外。比如你不小心拉掉了手柄线。这个时候你可以检测并且重新获取设备。利用GetDeviceState函数的返回值我们可以知道设备的情况。如下是GetDeviceState()可能返回的错误代码: DIERR_INPUTLOST 设备已经丢失。 DIERR_INVALIDPARAM 函数的参数无效 DIERR_NOTACQUIRED 已经完全失去设备 DIERR_NOTINITIALIZED 设备没有准备好 E_PENDING 数据还未准备好 所以如果出现了DIERR_INPUTLOST的错误,我们可以尝试重新获取设备。一般来说对于键盘丢失的几率几乎为零,多数时候,你只会丢失Joystick。 下面说一下对于Mouse 和 Joystick的不同之处。 Mouse的数据输入默认的为相对模式,也就是每次读入的为相对于上一次位置数据的相对值(偏移值)。对于DIMOUSESTATE结构中的rgbButtons数组,0,1,2下标分别表示左键,右键,中键。 对于游戏杆,我真是不想说了。因为在CreateDevice前为了得到GUID实在是有太多的要说了。调用枚举函数EnumDevices(),设置回调函数,记录下回调函数中传入的设备GUID和其他一些信息。说起来真怕自己说不清楚,还是直接给出一个例子,这样好理解一些。 其实就是在CreateDevice前多做了一些事:char joyname[256];GUID joystickGUID;… Continue reading DirectInput
高级DirectDraw(二)
使用Blitter DirectDraw中在各个表面之间进行Blitter和Windows编程中的各个DC之间Blt有点类似,不过DirectDraw中可以做的更加好,更加快。有两个达到这个功能的函数:Blt() 和 BltFast()。他们的不同是前者会调用裁减器而后者不用但是速度更快。 示例代码: DDBLTFX ddbltfx; RECT dest_rect; memset(&ddbltfx, 0, sizeof(ddbltfx)); ddbltfx.dwSize = sizeof(ddbltfx); ddbltfx.dwFillColor = RGB(0, 0, 0); // or color index in 8 bit mode dest_rect.left = x1; dest_rect.top = y1; dest_rect.right = x2; dest_rect.bottom = y2; lpddsprimary->Blt(&dest_rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); 在上面的例子中,调用Blt函数有两个参数是NULL,因为这个例子比较特殊,他并没有从另外一个已有表面复制,而是用一种颜色对自己进行填充。这是Blt的一个特殊用法。一般情况下,我们总是从另外一个表面(可能是离屏表面)向目标表面(可能是后备缓冲)进行填充。注意,函数调用的参数中的那个表面是源表面。 上面Blt函数中的第一个NULL参数表示源表面要复制过来的区域,那么要是这块区域对应到目标表面的区域出现了问题怎么办?也就是说,他超出了整个目标表面。如要从源(0,0, 100, 100)复制到目标的(600, 400, 700, 600)(这里保持两个RECT大小一样,不一样的情况以后会说),但是目标表面只有640*480的大小,也就是说没有(700,600)这点,有一部分会超出表面。所以这个时候我们只要复制(600, 400, 640,… Continue reading 高级DirectDraw(二)
高级DirectDraw(一)
使用高彩模式 上一章中说了可以用16位的色彩深度,但是16位的色彩深度的数据表示模式可以有两种:Alpha.5.5.5(or X.5.5.5) 和 5.6.5(这是16位色彩最常用的)。对于使用哪种16位的色彩模式这个是由硬件决定的,我们不能决定。但是我们可以查询,然后按照硬件支持的模式来填写。 我们可以调用方法IDIRECTDRAWSURFACE7::GetPixelFormat(),同时这个函数需要一个LPDDPIXELFORMAT的结构,其中的dwFlags 和 dwRGBBitCount成员记录着像素格式(8位索引或者RGB模式) 示例代码如下: DDPIXELFORMAT ddpixel; memset(&ddpixel, 0, sizeof(ddpixel) ); ddpixel.dwSize = sizeof(ddpixel); lpddsprimary->GetPixelFormat(&ddpixel); if (ddpixel.dwFlags & DDPF_RGB) // RGB Mode { switch(ddpixel.dwRGBBitCount) { case 15: // 5.5.5 break; case 16: // 5.6.5 break; case 24: break; case 32: break; default: break; } } else // ddpixel.dwFlags & DDPF_PALETTEINDEXED8 == TRUE { } … Continue reading 高级DirectDraw(一)
主角登场——显示表面
显示在屏幕上的图像只不过是以某种格式存储在内存中的有色象素组成的矩阵,或是调色板化的或是RGB模式的。DirectDraw中有两种显示表面:主显示表面 和 从显示表面。 主显示表面直接对应于被显示卡光栅化的实际显存,且任何时候都是可见的。 从显示表面是比较灵活的,可以是任意大小,驻留在VRAM或者系统内存中的数据块。一般为了达到显示平滑的效果,总是会创建一个或两个从显示表面,他们和主显示表面有同样的色彩深度和几何分布。这称为双缓冲或者三缓冲。 那么怎么创建一个和你的显示模式同样大小的简单主显示表面呢?步骤如下: 填充一个DDSURFACEDESC2的数据结构,描述你所希望创建的显示表面。 调用IDIRECTDRAW7::CreateSurface()来创建显示表面。 对于DDSURFACEDESC2结构,我们只需要填充里面的部分成员。代码如下: LPDIRECTDRAWSURFACE7 lpddsprimary = NULL;DDSURFACEDESC2 ddsd; memset(&ddsd, 0, sizeof(ddsd) ) ; ddsd.dwSize = sizeof(ddsd);ddsd.dwFlags = DDSD_CAPS; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; lpdd7->CreateSurface(&ddsd, &lpddsprimary, NULL); 对于不同的显示表面的创建,只需要修改DDSURFACEDESC2结构。具体可以查阅DirectX SDK。 接下来要做的就是对这个显示表面关联调色板(因为我们这里所讨论的是256色的情况,也是初学者容易开始的模式)。 代码如此简单: lpddsprimary->SetPalette(lpddpal); 这都要感谢DirectDraw的设计精良,给我们带来了如此简单的代码。 有了以上的一切,我们下来就可以到真正激动人心的时候了。我们可以干什么?来点看得见的东西——绘制象素 在此之前,我想对整个过程做一个小小的回顾:我们要绘制象素,需要先做些什么呢?首先必须建立DirectDraw对象,设置协作级别,设定一个显示模式,并创建至少一个主显示表面,然后你需要为他关联一个调色板(256色模式的情况)。对,就是那么简单。 我们要绘制象素,也就是写表面,就必须要先获得表面的控制权,并且告诉DirectX不能有其他的进程来访问。这也很容易,DirectDraw提供了加锁的功能。 代码也如此简单: memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); lpddsprimary->Lock(NULL, // destination rect to lock &ddsd, // address of struct to receive… Continue reading 主角登场——显示表面