我一向是伸手党,只爱看别人的,从来不回复,更不用说自己写了。但是最近的学习经历让我觉得很有必要写出来,一是用来提醒自己以后再碰到类似的问题又忘了解决办法的时候,二是确实的体会到了当遇到困难用尽各种办法都解决不了的时候那种无力和懊恼感。
最近刚看完windows游戏编程大师技巧技巧的第二版,觉得有必要自己也写一遍实现出来,不然到底掌握了没有心里根本没底。这本书由于距离现在有些年代了,所以可能是因为历史原因,一些API函数调用在IDE里各种出问题。
昨晚到现在一直都在解决绘制位图的问题,刚刚终于凭借自己的聪明才智给解决了(哈哈哈),心里那股爽劲甭提了。书里第7章的7.75载入24位位图的DEMO7——12.cpp里出现了两个重大问题,有一个网上搜了半天勉强解决了,但是没人给出原因。就是_lseek(file_handle,-(long)(bitmap->bitmapinfoheader.biSizeImage),SEEK_END)这个函数,意思很明显,把文件指针定位到图像数据之前,怎么看怎么对,编译也通过了,一运行就是出错,网上找不到答案,希望有高手看到这篇文章的时候能给小弟一个答案,在这里先谢过您了:)
第二个问题,我觉得是作者犯错了,为什用我觉得,首先没看到网上有人提出质疑,第二这本书都出这么久了也再版了难道作者和出版社没发现?我不确定。。。但是这个问题确实是存在的,还是这个cpp里,Game_Main函数中用于把bitmap.buffer中的图像数据填充到primary_buffer中时所用的循环,原来的cpp中是这么写的
for (int index_y = 0; index_y < SCREEN_HEIGHT; index_y++)
{
for (int index_x = 0; index_x < SCREEN_WIDTH; index_x++)
{
// get BGR values
UCHAR blue = (bitmap.buffer[index_y*SCREEN_WIDTH*3 + index_x*3 + 0]),
green = (bitmap.buffer[index_y*SCREEN_WIDTH*3 + index_x*3 + 1]),
red = (bitmap.buffer[index_y*SCREEN_WIDTH*3 + index_x*3 + 2]);
// this builds a 32 bit color value in A.8.8.8 format (8-bit alpha mode)
DWORD pixel = _RGB32BIT(0,red,green,blue);
// write the pixel
primary_buffer[index_x + (index_y*ddsd.lPitch >> 2)] = pixel;
} // end for index_x
} // end for index_y
第一遍的时候没细看,觉得意思差不多就过了,调试的时候断点到这里就出错了,总是非法访问内存,就认真的看了了一下发现问题了。循环的用意是把图片数据拷到显示表面的内存里,但是循环设置的x和y的条件是 分别小于屏幕的长宽值,把图片中对应于屏幕的坐标数据复制到显示表面上,问题来了。图片的大小怎么可能和和屏幕一样大呢,举个例子说,假如图片是100*100的,而屏幕是1024*768,那么在图片100*100之外而在屏幕之内的地方这些像素点通通都是不存在图片上的!那么通过下标运算读取图片中的内存数据当然就非法了,不是典型的越界吗!应该只是把图片的数据拷到屏幕上,那么应该改两个地方。一是index_x和index_y的循环条件改成图片的长宽,即cpp里的bitmap.bitmapinfoheader.biHeight和bitmap.bitmapinfoheader.biWidth; 二是下标运算里的SCREEN_WIDTH应该改成图片的宽度bitmap.bitmapinfoheader.biWidth。下面是我改正之后的
for (int index_y = 0; index_y < bitmap.bitmapinfoheader.biHeight; index_y++)
{
for (int index_x = 0; index_x < bitmap.bitmapinfoheader.biWidth; index_x++)
{
// get BGR values
UCHAR blue = (bitmap.buffer[index_y*(bitmap.bitmapinfoheader.biWidth)*3 + index_x*3 + 0]),
green = (bitmap.buffer[index_y*(bitmap.bitmapinfoheader.biWidth)*3 + index_x*3 + 1]),
red = (bitmap.buffer[index_y*(bitmap.bitmapinfoheader.biWidth)*3 + index_x*3 + 2]);
// this builds a 32 bit color value in A.8.8.8 format (8-bit alpha mode)
DWORD pixel = _RGB32BIT(0,red,green,blue);
// write the pixel
primary_buffer[index_x + (index_y*ddsd.lPitch >> 2)] = pixel;
} // end for index_x
} // end for index_y
改过之后编译运行都OK。美腻的图像出乃了:)希望这篇文章能给同样有困惑的同学提供一点帮助哈。