Nape柔体贴图教程2
上一节,我们大致学习了Nape柔体的贴图方法,最后我们还试着用一张图片进行贴图,但可惜的是图像并没有像我们预想的一样,随柔体形状改变,今天我们就来实现逼真的柔体贴图效果。
首先看一下拉登大叔实现的效果。貌似是不错,仔细看看确实很不错,哈哈!
[swfobject]1089[/swfobject]
没错,这就是我们想要实现的效果,很上一节教程一样,我们还是要遍历外围刚体的,但不同的是,现在我们不再使用lineTo和moveTo,而是使用另外一个稍微复杂一点的绘图API,叫做drawTriangles,具体我曾在《Foundation ActionScript3.0 Image effects》中的1.3.5 渲染三角形DrawTriangles一节讲过,具体请点开链接查看。
看过对应的教程之后,可以知道drawTriangles主要有三个参数,分别是vertices,indices和uvtData。首先我们来计算最后一个uvtData。
我们知道uvtData对应的三角形的顶点映射到图像上的位置,下面是柔体里的代码:
var uvX:Number = (1 + Math.sin(angle))/2; var uvY:Number = (1 + Math.cos(angle))/2; uvData.push(uvX , uvY);
上面的代码我们不想解释的太复杂,看过下面的图示你就明白了。
然后一个是vertices数组,它包含了所有的顶点,这就简单了,和上一节我们用的lineTo()参数是一样的,代码如下:
for(var i:int=0; i<bodyList.length; i++){ var pos:Vec2 = bodyList.at(i).position.sub(centerBody.position); vertices.push(pos.x,pos.y); indices.push(0,i+1,((i+2)>bodyList.length?(i+2)%bodyList.length:(i+2))); }
最后一个是indices数组,上面的代码已经展现出来了。假设现在我们用4个三角形模拟一个圆形,如下图所示,
图中用5个顶点组成了4个三角形,那么它们对应的indices数组应该是:
indices=[ 0,1,2, 0,2,3, 0,3,4, 0,4,1 ]
好了这就是本节的内容,具体代码如下:
package learnNape { import flash.events.KeyboardEvent; import flash.display.Bitmap; import flash.display.BitmapData; import flash.events.Event; import flash.display.Sprite; import nape.constraint.PivotJoint; import nape.phys.BodyList; import nape.geom.Vec2; import ldEasyNape.LDEasyNape; import nape.phys.Body; import learnNape.AbstractNapeTest; /** * @author yangfei */ public class T39_SoftBodyWithGraphic3 extends AbstractNapeTest { private var centerBody : Body; private var cx:Number = 200; private var cy:Number = 200; private var bodyNumbers:int = 20; private var radius : Number = 50; private var bodyList:BodyList; // use to add Graphic to softbody private var softBodyGraphic:Sprite; [Embed(source="../assets/ladeng6666.jpg")] private var LADENG : Class; private var ladeng6666:BitmapData; private var vertices:Vector.<Number>; private var indices:Vector.<int>; private var uvData:Vector.<Number>; override protected function onNapeWorldReady() : void { initGraphic(); createSoftBody(); } private function initGraphic() : void { softBodyGraphic = new Sprite(); addChild(softBodyGraphic); ladeng6666 = Bitmap(new LADENG()).bitmapData; //initialize vertices , indices and uv par vertices = new Vector.<Number>(); indices = new Vector.<int>(); uvData = new Vector.<Number>(); uvData.push(0.5,0.5); } private function createSoftBody() : void { centerBody = LDEasyNape.createCircle(cx, cy, 10); bodyList = new BodyList(); for (var i:int = 0; i<bodyNumbers; i++){ var angle : Number = Math.PI*2*i/bodyNumbers; var px : Number = cx + Math.sin(angle)*radius; var py : Number = cy + Math.cos(angle)*radius; var body :Body = LDEasyNape.createCircle(px, py, 5); bodyList.push(body); var uvX:Number = (1 + Math.sin(angle))/2; var uvY:Number = (1 + Math.cos(angle))/2; uvData.push(uvX , uvY); } var prevBody:Body, currBody:Body; for (var j:int=0;j< bodyList.length; j++){ prevBody=bodyList.at((j-1+bodyList.length)%bodyList.length); currBody=bodyList.at(j); var sToSJoint : PivotJoint = new PivotJoint(prevBody, currBody, Vec2.weak(), currBody.worldPointToLocal(prevBody.position)); sToSJoint.stiff = false; sToSJoint.space = napeWorld; var sToCJoint : PivotJoint = new PivotJoint(centerBody, currBody, centerBody.worldPointToLocal(currBody.position),Vec2.weak()); sToCJoint.stiff = false; sToCJoint.damping = 1; sToCJoint.frequency = 3; sToCJoint.space = napeWorld; } } override protected function loop(event : Event) : void { super.loop(event); softBodyGraphic.x = centerBody.position.x; softBodyGraphic.y = centerBody.position.y; drawGraphic(); } private function drawGraphic() : void { softBodyGraphic.graphics.clear(); softBodyGraphic.graphics.beginBitmapFill(ladeng6666); vertices=new Vector.<Number>(); indices = new Vector.<int>(); vertices.push(0,0); for(var i:int=0; i<bodyList.length; i++){ var pos:Vec2 = bodyList.at(i).position.sub(centerBody.position); vertices.push(pos.x,pos.y); indices.push(0,i+1,((i+2)>bodyList.length?(i+2)%bodyList.length:(i+2))); } softBodyGraphic.graphics.drawTriangles(vertices,indices,uvData); softBodyGraphic.graphics.endFill(); softBodyGraphic.graphics.lineStyle(2); for(var j:int=0; j<bodyList.length; j++){ var p:Vec2 = bodyList.at(j).position.sub(centerBody.position); softBodyGraphic.graphics.lineTo(p.x, p.y); } } override protected function keyBoardEventHanlder(event : KeyboardEvent) : void { super.keyBoardEventHanlder(event); if(event.type == KeyboardEvent.KEY_DOWN && event.keyCode ==32){ centerBody.applyImpulse(Vec2.weak(0,-2000)); } } } }
联系作者
会有bug,节点间容易错位造成图形扭曲
不错, 好玩!
是的呢,还有待改善的!后面继续完善!
实用度MAX的教程啊~ 再次感谢!