Cocos2d iphone Box2d径向重力极限coco2d
我一直在使用下面的代码创建径向重力 现在它可以正常工作了,但是我想要它,例如,只有当我的当前精灵在精灵的特定距离内时,才会触发此代码 我需要一些向导,我没有给这个世界重力,所以现在我的精灵在漂浮,但我想做如下的事情 一个精灵在X的项目路径上移动,因为我已经关闭了重力,所以没有重力应用于此。如果我们称之为D的物体在这条路径上的某个极限内,那么径向重力代码就会生效,换句话说,它会沿着它的投影路径继续 有人知道如何修改这段代码来做到这一点吗?我已经在这方面做了很多年了,我似乎无法接近创建一个范围并将这段代码应用到其中Cocos2d iphone Box2d径向重力极限coco2d,cocos2d-iphone,box2d,box2d-iphone,gravity,Cocos2d Iphone,Box2d,Box2d Iphone,Gravity,我一直在使用下面的代码创建径向重力 现在它可以正常工作了,但是我想要它,例如,只有当我的当前精灵在精灵的特定距离内时,才会触发此代码 我需要一些向导,我没有给这个世界重力,所以现在我的精灵在漂浮,但我想做如下的事情 一个精灵在X的项目路径上移动,因为我已经关闭了重力,所以没有重力应用于此。如果我们称之为D的物体在这条路径上的某个极限内,那么径向重力代码就会生效,换句话说,它会沿着它的投影路径继续 有人知道如何修改这段代码来做到这一点吗?我已经在这方面做了很多年了,我似乎无法接近创建一个范围并将
// Import the interfaces
#import "HelloWorldLayer.h"
// Needed to obtain the Navigation Controller
#import "AppDelegate.h"
#import "PhysicsSprite.h"
enum {
kTagParentNode = 1,
};
CGPoint location;
CGPoint nodePosition;
#pragma mark - HelloWorldLayer
@interface HelloWorldLayer()
-(void) initPhysics;
-(void) addNewSpriteAtPosition:(CGPoint)p;
-(void) createMenu;
@end
@implementation HelloWorldLayer
+(CCScene *) scene
{
// 'scene' is an autorelease object.
CCScene *scene = [CCScene node];
// 'layer' is an autorelease object.
HelloWorldLayer *layer = [HelloWorldLayer node];
// add layer as a child to scene
[scene addChild: layer];
// return the scene
return scene;
}
-(id) init
{
if( (self=[super init])) {
// enable events
self.isTouchEnabled = YES;
self.isAccelerometerEnabled = YES;
CGSize s = [CCDirector sharedDirector].winSize;
// init physics
[self initPhysics];
// create reset button
[self createMenu];
//Set up sprite
#if 1
// Use batch node. Faster
CCSpriteBatchNode *parent = [CCSpriteBatchNode batchNodeWithFile:@"blocks.png" capacity:100];
spriteTexture_ = [parent texture];
#else
// doesn't use batch node. Slower
spriteTexture_ = [[CCTextureCache sharedTextureCache] addImage:@"blocks.png"];
CCNode *parent = [CCNode node];
#endif
[self addChild:parent z:0 tag:kTagParentNode];
[self addNewSpriteAtPosition:ccp(s.width/2 - 150, s.height/2)];
[self scheduleUpdate];
}
return self;
}
-(void) dealloc
{
delete world;
world = NULL;
delete m_debugDraw;
m_debugDraw = NULL;
[super dealloc];
}
-(void) createMenu
{
// Default font size will be 22 points.
[CCMenuItemFont setFontSize:22];
// Reset Button
CCMenuItemLabel *reset = [CCMenuItemFont itemWithString:@"Reset" block:^(id sender){
[[CCDirector sharedDirector] replaceScene: [HelloWorldLayer scene]];
}];
CCMenu *menu = [CCMenu menuWithItems:reset, nil];
[menu alignItemsVertically];
CGSize size = [[CCDirector sharedDirector] winSize];
[menu setPosition:ccp( size.width/2, size.height/2)];
[self addChild: menu z:-1];
}
-(void) initPhysics
{
CGSize s = [[CCDirector sharedDirector] winSize];
b2Vec2 gravity;
gravity.Set(0.0f, 0.0f);
world = new b2World(gravity);
// Do we want to let bodies sleep?
world->SetAllowSleeping(true);
world->SetContinuousPhysics(true);
m_debugDraw = new GLESDebugDraw( PTM_RATIO );
world->SetDebugDraw(m_debugDraw);
uint32 flags = 0;
flags += b2Draw::e_shapeBit;
// flags += b2Draw::e_jointBit;
// flags += b2Draw::e_aabbBit;
// flags += b2Draw::e_pairBit;
// flags += b2Draw::e_centerOfMassBit;
m_debugDraw->SetFlags(flags);
// Define the ground body.
b2BodyDef groundBodyDef;
groundBodyDef.position.Set(0, 0); // bottom-left corner
// Call the body factory which allocates memory for the ground body
// from a pool and creates the ground box shape (also from a pool).
// The body is also added to the world.
b2Body* groundBody = world->CreateBody(&groundBodyDef);
// Define the ground box shape.
b2EdgeShape groundBox;
// bottom
groundBox.Set(b2Vec2(0,0), b2Vec2(s.width/PTM_RATIO,0));
groundBody->CreateFixture(&groundBox,0);
// top
groundBox.Set(b2Vec2(0,s.height/PTM_RATIO), b2Vec2(s.width/PTM_RATIO,s.height/PTM_RATIO));
groundBody->CreateFixture(&groundBox,0);
// left
groundBox.Set(b2Vec2(0,s.height/PTM_RATIO), b2Vec2(0,0));
groundBody->CreateFixture(&groundBox,0);
// right
groundBox.Set(b2Vec2(s.width/PTM_RATIO,s.height/PTM_RATIO), b2Vec2(s.width/PTM_RATIO,0));
groundBody->CreateFixture(&groundBox,0);
b2CircleShape shape;
shape.m_radius = 0.5f;
shape.m_p.Set(8.0f, 5.0f);
b2FixtureDef fd;
fd.shape = &shape;
planet = groundBody->CreateFixture(&fd);
}
-(void) draw
{
//
// IMPORTANT:
// This is only for debug purposes
// It is recommend to disable it
//
[super draw];
ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );
kmGLPushMatrix();
world->DrawDebugData();
kmGLPopMatrix();
}
-(void) addNewSpriteAtPosition:(CGPoint)p
{
CCLOG(@"Add sprite %0.2f x %02.f",p.x,p.y);
CCNode *parent = [self getChildByTag:kTagParentNode];
//We have a 64x64 sprite sheet with 4 different 32x32 images. The following code is
//just randomly picking one of the images
int idx = (CCRANDOM_0_1() > .5 ? 0:1);
int idy = (CCRANDOM_0_1() > .5 ? 0:1);
PhysicsSprite *sprite = [PhysicsSprite spriteWithTexture:spriteTexture_ rect:CGRectMake(16 * idx,16 * idy,16,16)];
[parent addChild:sprite];
sprite.position = ccp( p.x, p.y);
// Define the dynamic body.
//Set up a 1m squared box in the physics world
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
bodyDef.position.Set(p.x/PTM_RATIO, p.y/PTM_RATIO);
b2Body *body = world->CreateBody(&bodyDef);
// Define another box shape for our dynamic body.
b2PolygonShape dynamicBox;
dynamicBox.SetAsBox(.3f, .3f);//These are mid points for our 1m box
// Define the dynamic body fixture.
b2FixtureDef fixtureDef;
fixtureDef.shape = &dynamicBox;
fixtureDef.density = 2.0f;
fixtureDef.friction = 0.3f;
body->CreateFixture(&fixtureDef);
[sprite setPhysicsBody:body];
b2Vec2 currentPosition = body->GetPosition();
b2Vec2 desiredPosition;
desiredPosition.Set(467.0f/PTM_RATIO, 169.0f/PTM_RATIO);
b2Vec2 necessaryMovement = desiredPosition - currentPosition;
float necessaryDistance = necessaryMovement.Length();
necessaryMovement.Normalize();
float forceMagnitude = b2Min(150.0f, necessaryDistance *PTM_RATIO /2);
b2Vec2 force = forceMagnitude * necessaryMovement;
body->ApplyForce( force, body->GetWorldCenter() );
}
-(void) update: (ccTime) dt
{
//It is recommended that a fixed time step is used with Box2D for stability
//of the simulation, however, we are using a variable time step here.
//You need to make an informed choice, the following URL is useful
//http://gafferongames.com/game-physics/fix-your-timestep/
int32 velocityIterations = 8;
int32 positionIterations = 1;
// Instruct the world to perform a single step of simulation. It is
// generally best to keep the time step and iterations fixed.
world->Step(dt, velocityIterations, positionIterations);
for (b2Body* b = world->GetBodyList(); b; b = b->GetNext())
{
b2Body* ground = planet->GetBody();
b2CircleShape* circle = (b2CircleShape*)planet->GetShape();
// Get position of our "Planet"
b2Vec2 center = ground->GetWorldPoint(circle->m_p);
// Get position of our current body in the iteration
b2Vec2 position = b->GetPosition();
// Get the distance between the two objects.
b2Vec2 d = center - position;
// The further away the objects are, the weaker the gravitational force is
float force = 0.0f / d.LengthSquared(); // 150 can be changed to adjust the amount of force
d.Normalize();
b2Vec2 F = force * d;
// Finally apply a force on the body in the direction of the "Planet"
b->ApplyForce(F, position);
if (b->GetUserData() != NULL) {
CCSprite *myActor = (CCSprite*)b->GetUserData();
myActor.position = CGPointMake( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO);
myActor.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle());
}
}
}
- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
//Add a new body/atlas sprite at the touched location
for( UITouch *touch in touches ) {
location = [touch locationInView: [touch view]];
location = [[CCDirector sharedDirector] convertToGL: location];
nodePosition = [self convertToNodeSpace: location];
[self addNewSpriteAtPosition: location];
}
}
@end
你没有对你的身体施加任何力量
float force = 0.0f / d.LengthSquared();
不管d的值是多少,它总是为零
这是一个线性重力井的简单公式。这当然不是重力真正的工作原理,但它可能足以满足你的需要
如果要在某个最大距离maxDistance处应用零力,在某个最大距离maxDistance处应用最大力maxForce,则力的大小仅为:
Force = maxForce * (maxDistance - d)/maxDistance;
因此,当d=maxDistance时,力为0,当d=0时,力为maxForce
就像我说的,这不是真正的重力是如何工作的,因为实际上重力与距离的平方成正比,所以如果这对你来说不起作用,你可能需要进行实验。感谢Sylvan关于这个问题,我如何确定最大距离?这让我大吃一惊。比如,我怎么能给它一个变量,然后全部检查a体是否在范围内?我想这取决于你,基于反复试验和什么“感觉正确”。你可以任意选择一个你认为重力应该影响的距离,然后细化它直到你喜欢它的行为方式。你所要做的就是选择一个最大范围开始,并将其与每帧计算的距离进行比较。我正在这样做,但它给了我一个b2vec2无效操作数到二进制表达式<代码>b2Vec2 e=中心位置;浮动最大距离=20.0f;如果(e