今天我们继续探索Canvas(画布)技术。玩过War3和StarCraft2的同学一定会对游戏中探路的重要性了然于胸,游戏开始时,地图上全是黑乎乎的什么也看不清,当我们派个农民去探路时,黑暗的地带就被照亮而可以看到地形了。War3和StarCraft2都是3D游戏,它们可以运用3D中的光照Light完成这个效果,但像StarCraft1这样的2D游戏,就可以采用Canvas来达到相类似的效果。

CanvasAdvanced    演示如何在2D中模拟光照Light的效果

程序运行的效果图如下:

Demo03CanvasAdvanced程序中我们主要构建了一个模拟白天黑夜效果的背景和一个跟随鼠标移动的光圈。我们可以看到光圈的颜色,即limegreen的那个圆。

要实现这个效果其实很简单,就是在背景之上再绘制一层蒙板,然后在蒙板上剪掉光照部位的内容使背景透出来就OK了。可以按照下面的步骤来完成:

  1. 首先绘制背景图片 background.png
  2. 绘制光照图片 light.png (可以用Photoshop绘制一个圆,并将光照范围外的区域不透明度设为0,即alpha = 0.0f)
  3. 选择full_mask.png为Canvas,根据白天黑夜状态改变整幅图的alpha值
  4. 在Canvas上,在第二步绘制light.png的位置上,用blend_mode = erase再绘制一遍light.png
  5. 将Canvas绘制到gc上

过程中用到的图像素材也贴出来,以供大家参考:

background full_mask light

具体代码

void Draw(CL_GraphicContext &gc)
{
	CL_Draw::gradient_fill(gc, CL_Rectf(window.get_viewport()),
		CL_Gradient(CL_Colorf::blue, CL_Colorf::greenyellow));

	// draw the background image
	background.draw(gc, 0, 0);

	// draw the mouse light
	// skip this step will cause no light-color in the final scene.
	image_light.draw(gc, light_x, light_y);

	// change the canvas
	gc.set_frame_buffer(fb_background_mask);
	gc.clear(CL_Colorf(0.0f, 0.0f, 0.0f, time_position));

	// draw the mouse light		
	gc.set_blend_mode(erase);
	gc.set_texture(0, light_clip);
	gc.push_translate(light_x, light_y);
	gc.mult_scale(3.0f, 3.0f);
	CL_Draw::texture(gc, CL_Rectf(light_clip.get_size()));
	gc.pop_modelview();
	gc.reset_texture(0);
	gc.reset_blend_mode();
	gc.reset_frame_buffer();

	// draw the canvas
	gc.set_texture(0, background_mask);
	CL_Draw::texture(gc, CL_Rectf(background_mask.get_size()));
	gc.reset_texture(0);
}
其中重要变量的声明和初始化如下:
CL_Image background;
CL_Texture background_mask;
CL_FrameBuffer fb_background_mask;
float time_position;
float delta;

CL_Image image_light;
CL_Point mouse_pos;
int light_y;
int light_x;

CL_BlendMode erase;
CL_Texture light_clip;

void LoadContent(CL_GraphicContext &gc)
{
	background = CL_Image(gc, cl_text("background.png"));
	background_mask = CL_Texture(gc, cl_text("full_mask.png"));

	fb_background_mask = CL_FrameBuffer(gc);
	fb_background_mask.attach_color_buffer(0, background_mask); 

	erase.enable_blending(true);
	erase.set_blend_function(
		cl_blend_zero, cl_blend_one_minus_src_alpha,
		cl_blend_zero, cl_blend_one_minus_src_alpha);

	time_position = 0.3f;
	delta = 0.005f;

	image_light = CL_Image(gc, cl_text("light.png"));
	image_light.set_scale(3.0f, 3.0f);
	image_light.set_color(CL_Colorf::limegreen);
	image_light.set_alpha(0.2f);

	light_clip = CL_Texture(gc, cl_text("light.png"));
}

响应sig_pointer_move信号时,更新mouse_pos,并在Update中计算light_x、light_y。白天黑夜的实现实际上是将full_mask.png clear 为黑色、不透明度alpha在0.0f~1.0f之间变化来实现的。

总结

关于Canvas的技术就到此为止了,这个主要是用来达到一些特殊的地形、背景的效果。好的,今天就到这里!

posted on 2010-05-22 17:16  evil_heart  阅读(718)  评论(0)    收藏  举报