对 verlet-rope-latest 做了一下扩展:

1。可以添加绳子端点的sprite

2。以 b2RopeJoint 对绳联体做最大距离限制

3。可以在body的fixture上面任取一点作为连接点(原版仅仅支持连接到物体的中心点),这个也是推动我做修改的初衷~

废话不多说:

上效果图:

上相关代码:

//

//  BYRope.h

//  HungryBear

//

//  Created by Bruce Yang on 12-2-26.

//  Copyright (c) 2012年 EricGameStudio. All rights reserved.

//

#import <Foundation/Foundation.h>

#import "cocos2d.h"

#import "Box2D.h"

#import "VPoint.h"

#import "VStick.h"

#import "GCfg.h"

#import "GameConfig.h"

@interface BYRope : NSObject {

b2Body *_b1;

b2Body *_b2;

b2Vec2 _p1Original;

b2Vec2 _p2Original;

b2RopeJoint *_ropeJoint;

int _pointsCount;

float _antiSagHack;

NSMutableArray *_vPoints;

NSMutableArray *_vSticks;

CCSprite *_spriteBar1;

CCSprite *_spriteBar2;

NSMutableArray *_segmentSprites;

CCSpriteBatchNode *_batchBar;

CCSpriteBatchNode *_batchSegment;

/**

* 用于标识使用何种 update 方法( 即根据调用构造方法的不同,调用不同的 update 方法)~

* true 表示绳子连接的两个点为两 body 的中心点~

* false 表示不以两 body 的中心点为连接点~

*/

BOOL _isBodyCenter;

}

/** 1.简化调用的静态方法~ */

+(id) ropeWithBody1:(b2Body*)body1

body2:(b2Body*)body2

batchSegment:(CCSpriteBatchNode*)batchSegment

batchBar:(CCSpriteBatchNode*)batchBar;

+(id) ropeWithBody1:(b2Body*)body1

body2:(b2Body*)body2

posi1:(b2Vec2)posi1

posi2:(b2Vec2)posi2

batchSegment:(CCSpriteBatchNode*)batchSegment

batchBar:(CCSpriteBatchNode*)batchBar;

/** 2.初始化~ */

-(id) initWithBody1:(b2Body*)body1

body2:(b2Body*)body2

batchSegment:(CCSpriteBatchNode*)batchSegment

batchBar:(CCSpriteBatchNode*)batchBar;

-(id) initWithBody1:(b2Body*)body1

body2:(b2Body*)body2

posi1:(b2Vec2)posi1

posi2:(b2Vec2)posi2

batchSegment:(CCSpriteBatchNode*)batchSegment

batchBar:(CCSpriteBatchNode*)batchBar;

/** 3.重置~ */

-(void) reset;

/** 4.逻辑更新:施加重力并更新 points 的位置、紧缩小棍儿~ */

-(void) update:(float)dt; // --> GameScene.tick~ Essential!

/**

* 5.更新 sprites 的位置

* (因为绳子的受力逻辑并不受 box2d 物理引擎掌控,没有一个所依附的 body,因此 sprite 的位置需手动来调整)~

*/

-(void) updateSprites; // --> GameScene.draw~ Essential!

/** 6.调试~ */

-(void) debugDraw;

/** 7.清理,dealloc~ */

-(void) removeSprites;

-(void) dealloc;

@end

//

//  BYRope.mm

//  HungryBear

//

//  Created by Bruce Yang on 12-2-26.

//  Copyright (c) 2012年 EricGameStudio. All rights reserved.

//

#import "BYRope.h"

@implementation BYRope

#pragma mark-

#pragma mark Quick Static Interface~

/**

* 1.简化调用的静态方法~

*/

+(id) ropeWithBody1:(b2Body*)body1

body2:(b2Body*)body2

batchSegment:(CCSpriteBatchNode*)batchSegment

batchBar:(CCSpriteBatchNode*)batchBar {

return [[[self alloc] initWithBody1:body1

body2:body2

batchSegment:batchSegment

batchBar:batchBar]autorelease];

}

+(id) ropeWithBody1:(b2Body*)body1

body2:(b2Body*)body2

posi1:(b2Vec2)posi1

posi2:(b2Vec2)posi2

batchSegment:(CCSpriteBatchNode*)batchSegment

batchBar:(CCSpriteBatchNode*)batchBar {

return [[[self alloc] initWithBody1:body1

body2:body2

posi1:posi1

posi2:posi2

batchSegment:batchSegment

batchBar:batchBar]autorelease];

}

#pragma mark-

#pragma mark Init~

/**

* 2.初始化~

*/

-(void) createRope:(CGPoint)pointA pointB:(CGPoint)pointB {

_vPoints = [[NSMutableArrayalloc]init];

_vSticks = [[NSMutableArrayalloc]init];

_segmentSprites = [[NSMutableArrayalloc]init];

float distance = ccpDistance(pointA, pointB);

// increase value to have less segments per rope, decrease to have more segments

int segmentFactor =16;// 最好是能和绳子小节图片的长度相一致~

_pointsCount = distance / segmentFactor;

CGPoint diffVector = ccpSub(pointB, pointA);

float multiplier = distance / (_pointsCount -1);

// HACK: scale down rope points to cheat sag. set to 0 to disable, max suggested value 0.1

_antiSagHack =0.01f;

for(int i =0; i <_pointsCount; ++ i) {

CGPoint tmpVector =ccpAdd(pointA,ccpMult(ccpNormalize(diffVector),multiplier*i*(1-_antiSagHack)));

VPoint *tmpPoint = [VPointvPoint];

[tmpPoint setPos:tmpVector.xy:tmpVector.y];

[_vPoints addObject:tmpPoint];

}

for(int i =0; i <_pointsCount - 1; ++ i) {

VStick *tmpStick = [VStickvStick:[_vPointsobjectAtIndex:i] pointb:[_vPointsobjectAtIndex:i +1]];

[_vSticks addObject:tmpStick];

}

if(_batchSegment ==nil ||_batchBar ==nil) {

// 多亏了这个,不然我又得找半天,真是瞎猫碰上死耗子了

printf("\nBYRope: _batchSegment == nil || _batchBar == nil\n");

}

float segmentHeight = [[[_batchSegmenttextureAtlas]texture] pixelsHigh]/[GCfggetInstance].factor;

for(int i = 0; i < _pointsCount - 1; ++ i) {

VPoint *point1 = [[_vSticksobjectAtIndex:i]getPointA];

VPoint *point2 = [[_vSticksobjectAtIndex:i]getPointB];

CGPoint stickVector = ccpSub(ccp(point1.x, point1.y),ccp(point2.x, point2.y));

float stickAngle = ccpToAngle(stickVector);

CGRect rect = CGRectMake(0,0, multiplier, segmentHeight);

CCSprite *tmpSprite = [CCSpritespriteWithBatchNode:_batchSegmentrect:rect];

ccTexParams params = {GL_LINEAR,GL_LINEAR, GL_REPEAT,GL_REPEAT };

[tmpSprite.texture setTexParameters:&params];

[tmpSprite setPosition:ccpMidpoint(ccp(point1.x, point1.y),ccp(point2.x, point2.y))];

[tmpSprite setRotation:-1 *CC_RADIANS_TO_DEGREES(stickAngle)];

[_batchSegment addChild:tmpSprite];

[_segmentSprites addObject:tmpSprite];

}

// 绳子端点的 sprite~

CGRect barRect = CGRectMake(0,0,8.0f, 8.0f);

_spriteBar1 = [CCSpritespriteWithBatchNode:_batchBarrect:barRect];

_spriteBar2 = [CCSpritespriteWithBatchNode:_batchBarrect:barRect];

VPoint *firstPoint = (VPoint*)[_vPointsobjectAtIndex:0];

VPoint *lastPoint = (VPoint*)[_vPointsobjectAtIndex:(_pointsCount -1)];

[_spriteBar1 setPosition:ccp(firstPoint.x, firstPoint.y)];

[_spriteBar2 setPosition:ccp(lastPoint.x, lastPoint.y)];

[_batchBar addChild:_spriteBar1];

[_batchBar addChild:_spriteBar2];

}

-(id) initWithBody1:(b2Body*)body1

body2:(b2Body*)body2

batchSegment:(CCSpriteBatchNode*)batchSegment

batchBar:(CCSpriteBatchNode*)batchBar {

if((self = [superinit])) {

_isBodyCenter = YES;

_b1 = body1;

_b2 = body2;

b2Vec2 p1 = body1->GetPosition();

b2Vec2 p2 = body2->GetPosition();

// 创建绳子关节限定两点间的最大距离~

b2RopeJointDef rjd;

rjd.bodyA = body1;

rjd.bodyB = body2;

rjd.localAnchorA =b2Vec2_zero;

rjd.localAnchorB =b2Vec2_zero;

rjd.maxLength = (p2 - p1).Length();

_ropeJoint = (b2RopeJoint*)body1->GetWorld()->CreateJoint(&rjd);

CGPoint pointA = ccp(p1.x * PTM_RATIO, p1.y *PTM_RATIO);

CGPoint pointB = ccp(p2.x * PTM_RATIO, p2.y*PTM_RATIO);

_batchSegment = batchSegment;

_batchBar = batchBar;

[self createRope:pointA pointB:pointB];

}

return self;

}

-(id) initWithBody1:(b2Body*)body1

body2:(b2Body*)body2

posi1:(b2Vec2)posi1

posi2:(b2Vec2)posi2

batchSegment:(CCSpriteBatchNode*)batchSegment

batchBar:(CCSpriteBatchNode*)batchBar {

if((self = [superinit])) {

_isBodyCenter = NO;

_b1 = body1;

_b2 = body2;

// 创建绳子关节限定两点间的最大距离~

b2RopeJointDef rjd;

rjd.bodyA = body1;

rjd.bodyB = body2;

rjd.localAnchorA = posi1 - body1->GetPosition();

rjd.localAnchorB = posi2 - body2->GetPosition();

rjd.maxLength = (posi2 - posi1).Length();

_ropeJoint = (b2RopeJoint*)body1->GetWorld()->CreateJoint(&rjd);

_p1Original = posi1 - body1->GetPosition();

_p2Original = posi2 - body2->GetPosition();

CGPoint pointA = ccp(posi1.x *PTM_RATIO, posi1.y *PTM_RATIO);

CGPoint pointB = ccp(posi2.x *PTM_RATIO, posi2.y *PTM_RATIO);

_batchSegment = batchSegment;

_batchBar = batchBar;

[self createRope:pointA pointB:pointB];

}

return self;

}

#pragma mark-

#pragma mark Reset~

/** 3.重置~ */

-(void) resetWithPoints:(CGPoint)pointA pointB:(CGPoint)pointB {

float distance = ccpDistance(pointA, pointB);

CGPoint diffVector = ccpSub(pointB, pointA);

float multiplier = distance / (_pointsCount -1);

for(int i =0; i <_pointsCount; ++ i) {

CGPoint tmpVector =ccpAdd(pointA,ccpMult(ccpNormalize(diffVector), multiplier*i*(1-_antiSagHack)));

VPoint *tmpPoint = [_vPointsobjectAtIndex:i];

[tmpPoint setPos:tmpVector.xy:tmpVector.y];

}

}

-(void) reset {

CGPoint pointA;

CGPoint pointB;

if(_isBodyCenter ==YES) {

pointA = ccp(_b1->GetPosition().x*PTM_RATIO,_b1->GetPosition().y*PTM_RATIO);

pointB = ccp(_b2->GetPosition().x*PTM_RATIO,_b2->GetPosition().y*PTM_RATIO);

} else {

b2Vec2 vec1 = _b1->GetWorldPoint(_p1Original);

b2Vec2 vec2 = _b2->GetWorldPoint(_p2Original);

pointA = ccp(vec1.x *PTM_RATIO, vec1.y *PTM_RATIO);

pointB = ccp(vec2.x *PTM_RATIO, vec2.y *PTM_RATIO);

}

[selfresetWithPoints:pointApointB:pointB];

}

#pragma mark-

#pragma mark Logic Update~

/**

* 4.逻辑更新:施加重力并更新 points 的位置、紧缩小棍儿~

*/

-(void) updateWithPoints:(CGPoint)pointA pointB:(CGPoint)pointB dt:(float)dt {

// manually set position for first and last point of rope

[[_vPoints objectAtIndex:0]setPos:pointA.xy:pointA.y];

[[_vPoints objectAtIndex:_pointsCount -1]setPos:pointB.xy:pointB.y];

// update points, apply gravity

for(int i =1; i <_pointsCount - 1; ++ i) {

[[_vPoints objectAtIndex:i] applyGravity:dt];

[[_vPointsobjectAtIndex:i]update];

}

// contract sticks

int iterations = 4;

for(int j =0; j < iterations; ++ j) {

for(int i =0; i <_pointsCount - 1; ++ i) {

[[_vSticksobjectAtIndex:i]contract];

}

}

}

-(void) update:(float)dt {

CGPoint pointA;

CGPoint pointB;

if(_isBodyCenter ==YES) {

pointA = ccp(_b1->GetPosition().x*PTM_RATIO,_b1->GetPosition().y*PTM_RATIO);

pointB = ccp(_b2->GetPosition().x*PTM_RATIO,_b2->GetPosition().y*PTM_RATIO);

} else {

b2Vec2 vec1 = _b1->GetWorldPoint(_p1Original);

b2Vec2 vec2 = _b2->GetWorldPoint(_p2Original);

pointA = ccp(vec1.x *PTM_RATIO, vec1.y *PTM_RATIO);

pointB = ccp(vec2.x *PTM_RATIO, vec2.y *PTM_RATIO);

}

[self updateWithPoints:pointApointB:pointBdt:dt];

}

#pragma mark-

#pragma mark Sprite Update~

/**

* 5.更新 sprites 的位置

* (因为绳子的受力逻辑并不受 box2d 物理引擎掌控,没有一个所依附的 body,因此 sprite 的位置需手动来调整)~

*/

-(void) updateSprites {

for(int i = 0; i < _pointsCount - 1; ++ i) {

VPoint *point1 = [[_vSticksobjectAtIndex:i]getPointA];

VPoint *point2 = [[_vSticksobjectAtIndex:i]getPointB];

CGPoint point1_ = ccp(point1.x, point1.y);

CGPoint point2_ = ccp(point2.x, point2.y);

float stickAngle = ccpToAngle(ccpSub(point1_, point2_));

CCSprite *tmpSprite = [_segmentSpritesobjectAtIndex:i];

[tmpSprite setPosition:ccpMidpoint(point1_, point2_)];

[tmpSprite setRotation: -CC_RADIANS_TO_DEGREES(stickAngle)];

}

/** 以下代码无法消除端点抖动的情况~ */

//    VPoint *firstPoint = (VPoint*)[_vPoints objectAtIndex:0];

//    VPoint *lastPoint = (VPoint*)[_vPoints objectAtIndex:(_pointsCount - 1)];

//    [_spriteBar1 setPosition:ccp(firstPoint.x, firstPoint.y)];

//    [_spriteBar2 setPosition:ccp(lastPoint.x, lastPoint.y)];

/** 消抖(将端点 sprite的 position与 b2RopeJoint 对象的两个 anchor 绑定),可能报错!舍弃~ */

//    b2Vec2 vec1 = _ropeJoint->GetAnchorA();

//    b2Vec2 vec2 = _ropeJoint->GetAnchorB();

/** 消抖2(采用和更新点一样的思路),最终方案~ */

b2Vec2 vec1 = _b1->GetWorldPoint(_p1Original);

b2Vec2 vec2 = _b2->GetWorldPoint(_p2Original);

[_spriteBar1 setPosition:ccp(vec1.x *PTM_RATIO, vec1.y *PTM_RATIO)];

[_spriteBar2 setPosition:ccp(vec2.x *PTM_RATIO, vec2.y *PTM_RATIO)];

}

#pragma mark-

#pragma mark Debug Draw~

/**

* 6.调试~

*/

-(void) debugDraw {

glColor4f(0.0f,0.0f,1.0f, 1.0f);

glLineWidth(5.0f);

for(int i =0; i <_pointsCount - 1; ++ i) {

VPoint *pointA = [[_vSticksobjectAtIndex:i]getPointA];

VPoint *pointB = [[_vSticksobjectAtIndex:i]getPointB];

ccDrawPoint(ccp(pointA.x, pointA.y));

ccDrawPoint(ccp(pointB.x, pointB.y));

ccDrawLine(ccp(pointA.x, pointA.y),ccp(pointB.x, pointB.y));

}

// restore to white and default thickness

glColor4f(1.0f,1.0f,1.0f, 1.0f);

glLineWidth(1);

}

#pragma mark-

#pragma mark Clear & Dealloc~

/**

* 7.清理,dealloc~

*/

-(void) removeSprites {

// 1.从 _batchSegment中将绳子小节 sprite移除~

for(int i=0;i<_pointsCount-1;i++) {

[(CCSprite*)[_segmentSpritesobjectAtIndex:i]removeFromParentAndCleanup:YES];

}

[_segmentSpritesremoveAllObjects];

// 2.从 _batchBar中将绳子端点 _spriteBar1, _spriteBar2移除~

[_spriteBar1removeFromParentAndCleanup:YES];

[_spriteBar2removeFromParentAndCleanup:YES];

}

-(void) dealloc {

[_segmentSprites release];

[_vPoints release];

[_vSticks release];

[superdealloc];

}

@end

上全部下载连接:

http://download.csdn.net/detail/yang3wei/4092594

PS:

(仅仅只是绳子的代码部分,不是完整的项目,留给各位自己来探究一下如何运用,

也可以参照我之前写过的关于绳子的文章,那里有 verlet-rope-latest 的原文出处,

而且,verlet-rope-latest      VRope.mm 文件的注释中详细点明了绳子类的使用方法,

创建,在 Scene 的 tick 方法里面做逻辑更新,在 draw 方法里面做sprite 位置更新,清理等等,一应俱全)

还有可以更进一步的地方,绳子的端点有点儿抖动的现象可以通过将端点sprite附着到 b2RopeJoint的两个 anchor上解决~

转载于:https://www.cnblogs.com/yang3wei/archive/2012/02/27/2739463.html

verlet-rope-latest 的扩展—— BYRope相关推荐

  1. verlet rope

    https://github.com/MitaPirsLud/UnityFishing https://www.youtube.com/watch?v=w_qdI6daqyo https://www. ...

  2. brew gd php_PHPBrew 使用指南

    前言 咋一看,这个名字取得,肯定是跟 Homebrew 学的.既然 Homebrew 的定位是 macOS 上的 包管理器,那 PHPBrew 肯定也跟 包管理器 沾点边.没错,它可以用来 构建 和 ...

  3. Appium笔记1--基于python windows下的环境搭建

    Appium自动化架构和Selenium有很大的相似之处 包含了 3 个主体部分 : Test script --- 即我们的测试程序,是测试逻辑的实现部分.就像以前我们的Selenium自动化脚本. ...

  4. Appnuim作业题

    Appium 作业 1 根据课堂视频,安装搭建Appium运行环境,并运行示例代码 安装Appium Python Client 包 安装Appium Python Client 包的命令 pip i ...

  5. 2020牛客国庆集训派对day8 G-Shuffle Cards(扩展STL容器,rope可持久化平衡树)

    2020牛客国庆集训派对day8 G-Shuffle Cards(扩展STL容器,rope可持久化平衡树) 题目 https://ac.nowcoder.com/acm/contest/7865/G ...

  6. 2021年大数据Flink(四十四):​​​​​​扩展阅读 End-to-End Exactly-Once

    目录 扩展阅读 End-to-End Exactly-Once 流处理的数据处理语义 At-most-once-最多一次 At-least-once-至少一次 Exactly-once-精确一次 En ...

  7. MATLAB可以打开gms文件吗,GMS文件扩展名 - 什么是.gms以及如何打开? - ReviverSoft...

    你在这里因为你有,有一个文件扩展名结尾的​​文件 .gms. 文件与文件扩展名 .gms 只能通过特定的应用程序推出.这有可能是 .gms 文件是数据文件,而不是文件或媒体,这意味着他们并不是在所有观 ...

  8. Open3D面向机器学习的扩展库

    点击"蓝字"关注点云PCL,选择"星标"获取最新文章 Open3D-ML是Open3D的一个扩展,用于3D机器学习任务.它建立在Open3D核心库之上,并通过机 ...

  9. Redis以及Redis的php扩展安装无错版

    安装Redis 下载最新的 官网:http://redis.io/  或者  http://code.google.com/p/redis/downloads/list 第一步:下载安装编译 #wge ...

  10. php改7z,PHP的7z扩展名? - php

    我找不到一个,也不知道PHP Compression and Archive Extensions中的任何一个是否可以工作. 您认为我可以使用compression stream从7z文件读取数据吗? ...

最新文章

  1. 使用vlc播放m3u8网络视频教程
  2. koa --- [MVC实现之二]Controller层的实现
  3. Python+numpy实现矩阵QR分解
  4. jupyter怎么安装jieba_解决Jupyter无法导入已安装的 module问题
  5. Android运行时修改Manifest,Android如何动态修改Manifest文件
  6. python有哪些好的学习资料或者博客
  7. [转]Google 发现的十大真理
  8. 踩坑事件:windows操作系统下的eclipse中编写SparkSQL不能从本地读取或者保存parquet文件
  9. amd显卡风扇调节_显卡风扇转速调节
  10. CVPR 2020评审结果放出,魏秀参博士教你如何rebuttal!!!
  11. 行为经济学_为什么所有数据科学家都应该了解行为经济学
  12. Lightroom Classic全版本软件安装包(含最新2023)
  13. CSSCI来源期刊(2010-2011年)
  14. 用pip安装django
  15. python3安装setuptools步骤_简单python2.7.3安装setuptools模块
  16. Mac OS命令行清洗硬盘空间
  17. CS224W-6-message passing and node classification 第3部分
  18. 长沙理工计算机竞赛黑马,2018年五大学科成绩出炉,长沙杀出一匹黑马!
  19. 2022年电商系统开发平台测评体验
  20. 吃白菜一样用micropython玩esp32(二)—— 点灯大师

热门文章

  1. Android开发16——获取网络资源之基础应用
  2. MPLS ××× Carrier Supporting Carrier Option AB(一)
  3. E人E本的android突破与行业走向
  4. [前端随笔][Javascript][物理引擎] 给元素添加简单的物理属性
  5. 基础训练 龟兔赛跑预测
  6. 第三周阶段性小结——Object对象、String类、StringBuffer、StringBuilder、System、Runtime、Date...
  7. 菜鸟学开店—最简收银POS系统
  8. flash 与javascrip的t交互和注意事项
  9. 中国互联网100个Web2.0网站名单
  10. Android+WebServer的GPS监控系统(设想)