//
// 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:¶ms];
[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
|
相关推荐
5分算比较多了,但我相对于...《verlet-rope-latest 的扩展—— BYRope》 有点儿小不满意的地方就是绳子端点sprite可能会出现抖的情况,不过也很好解决,将端点sprite的位置和 b2RopeJoint 的两个anchor绑定起来即可!
verlet-js, 在javascript中,编写了一个简单的Verlet物理引擎 verlet-js一个简单的Verlet ( 发音'in') 物理引擎,。粒子。距离约束和 Angular 约束都受 verlet-js支持。 从这些原语中可以构造出任何你能想象到的东西...
var Point = require ( 'verlet-point' ) var array = require ( 'array-range' ) var random = require ( 'randf' ) //create a world where points stay within window bounds var world = require ( 'verlet-...
var Point = require ( 'verlet-point' )var p = Point ( { position : [ 25 , 25 ]} )p . addForce ( [ 15 , 15 ] ) 而对于裸对象,它可能看起来像这样: var p = { position : [ 25 , 25 ] , previous : [ 25 , ...
这个是verlet rope for cocos2d-x,修改自vrope for cocos2d 。供大家借鉴
基于改进的Velocity-Verlet算法的交互式衣服仿真系统,马光辉,万毅,交互式衣服仿真系统,可以应用到网上试衣系统,计算机辅助设计和游戏等商业领域。衣服仿真模型通常采用质点-弹簧模型进行简化处
svg-verlet.js, 在Coffeescript中,一个基于verlet的物理库被 SvgVerlet.js 版基于Coffeescript的基于verlet的物理库。这个库实现了SVG规范的一部分,但是仍然有很多漏洞。 我建议使用包含的SVG文件作为将要工作的...
使用 verlet 算法生成 verlet 列表来计算非键相互作用 - 分子动力学- 将算法转换为 MATLAB 脚本
A dissipative scheme based on the Verlet time-stepping algorithm is proposed to decrease the numerical dispersive error and eliminate spurious modes in unstructured grid-based discontinuous Galerkin ...
使用速度 verlet 算法的分子动力学——需要校正径向分布函数以考虑恒定的 bin 大小,而不是将其留给 matplotlib.pyplot.hist——更正并行化实现以测量力 使用蒙特卡罗的NVT硬球——修正径向分布函数 使用蒙特卡罗的...
物理引擎_verlet.js
verlet算法求解单摆运动方程,最简单方法
茎被建模为失重的绳索,并通过Verlet集成进行动画处理。 鼠标可用于与花朵互动。 看到它住。细节该项目的灵感来自用户的静态图片。绳索物理学花梗被建模为绳索。 绳索被视为由非常坚硬的弹簧连接而成的节点链。 有...
Verly.js 易于集成Verlet物理引擎。 还有另一个物理引擎? 真的吗? 是的,因为我热爱物理 :red_heart: 。 阅读有关媒体的文章Verly.js制作的很棒的东西查看更多需要更多信息? 查看API实验性Reactjs集成-签出安装...
利用verlet.js在H5canvas中模拟重力效果
模拟太阳运动中地球自转、围绕太阳公转,更好的可视化
d3力 该模块实现了数值积分器,用于模拟粒子上的物理力。 模拟得到简化:假设每个步骤的单位时间步长Δt = 1,所有粒子的单位质量m = 1。 结果,作用在粒子上的力F等于在时间间隔Δt上的恒定加速度a ,可以简单地...
看不到源码Verlet 集成 这个 repo 使用 verlet 集成来模拟一个世界: 积分 棒连接点 一块布 A(摆动)块 它的灵感主要来自 . 我解释了这段代码。 安装 先决条件: 已安装 已安装 git clone 在 java8 上测试。 用法 ...
【GAMES101】作业8 显式/半隐式欧拉与Verlet方法模拟绳子运动
PixelFlow A Processing/Java library for high performance GPU-Computing (GLSL). ... - Verlet Integration - FlowField/SDF(Signed Distance Field) based - Streamlines - ... Softbody Dyn