学习PSP游戏制作实况记录(二)载入和显示PNG档



掌叔
2009-02-08 18:17:32

摘自:[url]http://bbs.khors.com[/url]
作者:Dr.Watson

无意中发现了读写PNG的代码, 大喜过望, 马上"盗为己用" :)

PNG读写的原代码请参考:

[url=http://svn.ps2dev.org/filedetails.php?repname=psp&path=/trunk/libpng/screenshot/main.c&rev=0&sc=0]PNG Sample[/url]

先给大家看一下截图:

[attach]724[/attach]

背景来自[url=http://forums.qj.net/showthread.php?t=1429]QJ Forum[/url]

我把showimage 改成 LoadImage, 而自定了一个Image 的 struct 把像素资料存在记忆内, 留作后用:

[code=c]typedef struct
{
int mWidth;
int mHeight;
u32* mBits;
} Image;[/quote]

LoadImage基本上和本来的showimage差不多, 只是现在把相关的资料写进记忆内而不是VRAM:

[quote]Image* image = (Image*) malloc(sizeof(Image));
if (image)
{
image->mBits = (u32*) malloc(width * height * sizeof(u32));
if (image->mBits)
{
image->mWidth = width;
image->mHeight = height;

p32 = image->mBits;
p16 = (u16*) p32;

for (y = 0; y < height; y++)
{
png_read_row(png_ptr, (u8*) line, png_bytep_NULL);
for (x = 0; x < width; x++)
{
u32 color32 = line[x];
u16 color16;
int r = color32 & 0xff;
int g = (color32 >> 8) & 0xff;
int b = (color32 >> 16) & 0xff;

// 本文的程式只用了32bit像素模式, 但本函数是支持psp所有像素格式的
// 参考下面, 就可以看出不同像素格式的颜色编排
switch (pixelformat) {
case PSP_DISPLAY_PIXEL_FORMAT_565:
color16 = (r >> 3) | ((g >> 2) << 5) | ((b >> 3) << 11);
*(p16+x) = color16;
break;
case PSP_DISPLAY_PIXEL_FORMAT_5551:
color16 = (r >> 3) | ((g >> 3) << 5) | ((b >> 3) << 10);
*(p16+x) = color16;
break;
case PSP_DISPLAY_PIXEL_FORMAT_4444:
color16 = (r >> 4) | ((g >> 4) << 4) | ((b >> 4) << 8);
*(p16+x) = color16;
break;
case PSP_DISPLAY_PIXEL_FORMAT_8888:
color32 = r | (g << 8) | (b << 16);
*(p32+x) = color32;
break;
}
}
p32 += width;
p16 += width;
}

}
else
{
free(image);
image = NULL;
}[/code]

我把上一篇和这篇所弄出来的有关图像functions都放到另一个独立档内, 一来方便整理和查看, 二来为可能转去c++做点准备. 现在的代码包内有以下的档桉:

* main.c
* common.h
* gfx.c
* gfx.h


好了, 到了要介绍本篇主角的时候了! 我们把图像存在记忆, 接着要做的, 当然是把它显示在萤幕, 这就是新函数DrawImage 的功能, 因为不想任意写进VRAM以外的地方, 我也加了些避免画出界的简单测试:

[code=c]void DrawImage(Image* image, int x, int y)
{
int xImage = 0;
int yImage = 0;
int width = image->mWidth;
int height = image->mHeight;

if (x < 0) // 把画图限制在萤幕范围
{
xImage = 0-x;
width -= xImage;
x = 0;
}
if (y < 0)
{
yImage = 0-y;
height -= yImage;
y = 0;
}

if (width<=0 || height<=0) return; // 要是图在萤幕外, 干脆不用画

if (x+width>SCREEN_WIDTH)
width = SCREEN_WIDTH-x;

if (y+height>SCREEN_HEIGHT)
height = SCREEN_HEIGHT-y;

// 计算第一个像素的位置
u32* pFrameBuffer = pVRAM + y * FRAME_BUFFER_WIDTH + x;
u32* pImage = image->mBits + yImage * image->mWidth + xImage;

int i, j;
u32* pSrc;
u32* pDest;
for (i=0;i{
pSrc = pImage;
pDest = pFrameBuffer;

for (j=0;j*pDest++ = *pSrc++;

pImage += image->mWidth;
pFrameBuffer += FRAME_BUFFER_WIDTH; // 到下一行
}

}[/code]

用devkitPro 或用PSPSDK而没有libpng和zlib的朋友, 请把附件libpng_zlib.zip的*.h放在".../pspdev/psp/include"内和把*.a放在".../pspdev/psp /lib"内, 我在devkitPro 测试过, 应该可以顺利编译.

本篇到此为止了, 和上一篇一样, 当程式结束时, 会把一张画面截图放在根目录, 不同的是, 今次用的是PNG档. 相同的情况, 要是大家不想截图, 请把有关命令从代码里拿掉.

[code=c]ScreenShot("ms0:/screenshot.png");[/code]


TW241
2009-08-07 21:46:36

支持你 哈哈


824102727
2009-08-07 21:53:48

相当支持