斜切在2D游戏中
使用过photoshop的人,大概都使用过“斜切”这种图形处理。斜切有什么用呢?在45度斜视角的游戏里,你有没有注意到城门上的字呢?它们就是使用了斜切。如果不使用斜切,字的视角和场景就会显得很不协调,看起来很别扭。斜切在2D的场景制作中是经常用到的功能。
斜切的算法
我们来看看photoshop是怎么实现斜切的吧。制作过程就不阐述了,
上图是制作后的效果。从图中可以知道,转换后的“日”字才会和背景黑板的视角一致,看起来才会真正融入到我们的游戏中,要不象第一幅一样,看起来很别扭。
我们留意一下,实际上两个“日”字的“竖”的长度都没变,“横”相对于竖的位置也没变。或许有些人说,这不是图象旋转吗?不是的,图象旋转的话,竖的长度会跟着变化。你看看和"Y"轴平行的那两"|""|",转换以后的长度都一样的。斜切和图象的旋转一样,都是属于图象的几何变换。
下面用伪代码给出实现。
//Bitmap是对bmp文件处理的一个类
//注意,该代码不能编译,只是给出实现算法
//参数bmp是源图,iAngle是斜切的角度,单位:度
#define PI 3.1415926535
#define RADIAN(angle) ((angle)*PI/180.0) //convert angle to radian
void Bitmap::BiasCut(const Bitmap& bmp,int iAngle)
{
int iWidth = bmp.GetW() ; //源图的高度
int iHeight = bmp.GetH(); //源图的宽度
float RotateAngle =(float)RADIAN(iAngle); //斜切的角度,就是黑板和X轴的交角,将角度转换为弧度
double tga = (double)tan( (double)RotateAngle ); //tan,就是y/x的值
DWORD dwNewW = iWidth; //转换后的图的宽度
DWORD dwNewH = (DWORD)(fabs( iWidth * tga ) + iHeight);//转换后的图的高度
Create( dwNewW, dwNewH );//创建转换后的的空白图
Clear( 0x0 ); //用黑色填充
Pixel* line_src = bmp.GetPixel() ;//源图图象数据
Pixel* line_des = GetPixel(); //转换后图象数据
DWORD x0,y0,x1,y1;
for(y1=0;y1<dwNewH;y1++)
{
for(x1=0;x1<dwNewW;x1++)
{
x0 = x1; //转换后的象素,x轴没变化
y0 = y1-x1*tga;//转换后y轴的值,对应源图y轴的值
if( (x0>=0) && (x0<(DWORD)iWidth) && (y0>=0) && (y0<(DWORD)iHeight))
{
line_des[y1][x1] = line_des[y0][x0];//第y1行第x1个象素点的象素 = 源图第y0行第x0个象素点的象素
}
}
}
}
其中,蓝色部分是算法的核心部分,相信大家都不难看懂。