这个例子中我们来实现Box2D中切割刚体的效果,先看下效果。
切割前:
切割后:
首先我们来制作用鼠标绘制切割线的效果:
我们利用cocos2d中的绘图函数来绘制切割线。
使用cocos2diOS with Box2d模板创建Box2d工程(本文使用的是Box2d 2.3.1版本),接着在HelloWorldLayer类中添加4个成员变量:
CGPointlineStart;
CGPointlineEnd;
CGPointlineStartSave;
CGPointlineEndSave;
lineStart和lineEnd用来临时记录在拖拽过程中线段的起点和终点,在拖拽过程中我们在HelloWorldLayer的draw函数内绘制直线, lineStart和lineEnd的值分别使用lineStartSave和lineEndSave来保存,松开后lineEnd的值重置,绘制的直线消失。切割的时候使用lineStartSave和lineEndSave两个值来计算切割结果。
要响应touch事件,HelloWorldLayer要继承CCTouchOneByOneDelegate协议,实现下面三个方法:
-(BOOL)ccTouchBegan:(UITouch*)touch withEvent:(UIEvent *)event
-(void)ccTouchMoved:(UITouch*)touch withEvent:(UIEvent *)event
-(void)ccTouchEnded:(UITouch*)touch withEvent:(UIEvent *)event
重写下面的两个方法,addTargetedDelegate方法用来将HelloWorldLayer类注册为touchDispatcher的委托类,以便收到分发的touch事件,removeDelegate用来移除委托注册:
-(void)onEnterTransitionDidFinish{
[[[CCDirector sharedDirector] touchDispatcher] addTargetedDelegate:selfpriority:1 swallowsTouches:true];
}
-(void)onExit{
[[[CCDirector sharedDirector] touchDispatcher] removeDelegate:self];
}
实现后,HelloWorldLayer就能接受touch事件了。
下面是touch的三个事件的具体实现:
-(BOOL)ccTouchBegan:(UITouch*)touch withEvent:(UIEvent *)event {
lineEnd = ccp(-1, -1);
lineStart = [[CCDirector sharedDirector] convertToGL:[touchlocationInView:[touch view]]];
lineStartSave = lineStart;
return YES;
}
-(void)ccTouchMoved:(UITouch*)touch withEvent:(UIEvent *)event {
lineEnd = [[CCDirector sharedDirector] convertToGL:[touch locationInView:[touchview]]];
if (lineStart.x != lineEnd.x || lineStart.y != lineEnd.y) {
lineEndSave = lineEnd;
}
}
-(void)ccTouchEnded:(UITouch*)touch withEvent:(UIEvent *)event {
lineEnd = ccp(-1, -1);
}
使用[[CCDirectorsharedDirector] convertToGL:[touch locationInView:[touchview]]]来获取用户在屏幕上的触点的位置,并将其转换为全局坐标系下的坐标。
接着在draw方法中添加下面的代码:
if(lineEnd.x > 0) {
ccDrawColor4F(255, 255, 255, 255);
ccDrawLine(lineStart, lineEnd);
}
这里我们判断lineEnd的横坐标是否大于0,如果小于0不进行绘制,以便每次停止接触屏幕后,绘制的直线能够自动消失(因为在ccTouchEnded中我们将lineEnd的横纵坐标都置为了-1)。接着调用ccDrawColor4F方法来设置用来绘制图形的颜色,这里由于默认背景是黑色的,因此我们使用白色(255,255,255)来绘制,最后一个255是alpha值。接着使用ccDrawLine方法在lineStart和lineEnd之间绘制一条直线。
完成后运行,可以看到我们点击屏幕就可以拖动出一条白色直线,直线随我们拖动而改变,松开后直线消失。
(注:默认的HelloWorldLayer中会为我们添加一个Box物体,并会为我们创建菜单项,将这部分代码注释掉即可)
接着我们在场景中添加一个多边形用于切割。
添加下面的方法:
-(void)createPolygonForCut{
//屏幕尺寸
CGSize s = [[CCDirector sharedDirector] winSize];
//在屏幕中央,创建一个动态多边形
b2BodyDef polygonDef;
polygonDef.type = b2_dynamicBody;
polygonDef.position.Set(0.5 * s.width / PTM_RATIO, 0.5 * s.height / PTM_RATIO);
b2Body* polygon = world->CreateBody(&polygonDef);
//定义8个节点(我们创建一个8变形),len参数作为调节多边形大小的算子
b2Vec2 vertexes[8];
float len = 5.0f;
//多边形形状
b2PolygonShape* shape = new b2PolygonShape();
//注意,节点要按照逆时针方向添加
vertexes[0].Set(-len * 0.4f, -len);
vertexes[1].Set(len * 0.4f, -len);
vertexes[2].Set(len, -len * 0.4f);
vertexes[3].Set(len, len * 0.4f);
vertexes[4].Set(len * 0.4f, len);
vertexes[5].Set(-len * 0.4f, len);
vertexes[6].Set(-len, len * 0.4f);
vertexes[7].Set(-len, -len * 0.4f);
//设置形状
shape->Set(vertexes, 8);
//定义装置,将形状赋予装置,设置摩擦力和质量等
b2FixtureDef fixtureDef;
fixtureDef.shape = shape;
fixtureDef.friction = 0.2f;
fixtureDef.density = 2.0f;
//创建装置
polygon->CreateFixture(&fixtureDef);
}
添加了相关注释,这里不做解释了。在init方法中调用上面的方法来添加多边形(可以多次调用添加多个),下面是运行效果:
篇幅有限,本篇先制作到这里,下一篇中我们继续添加代码完成多边形的切割。