尝试使用Cocos2d 2.X实现径向重力

时间:2012-08-13 20:24:02

标签: iphone ios cocos2d-iphone gravity game-development

我正在尝试学习如何对特定对象实施径向引力,而我正在使用该教程(http://www.vellios.com/2010/06/11/radial-gravity-w-box2d-source/ ),但是本教程是用旧版本的Cocos2d编写的。我试图尽可能地修复它。如果有人能指出我正确的方向,我真的很感激。这是我到目前为止所拥有的。我评论了我遇到问题的地方。谢谢。

HelloWorldLayer.h

#import <GameKit/GameKit.h>

// When you import this file, you import all the cocos2d classes
#import "cocos2d.h"
#import "Box2D.h"
#import "GLES-Render.h"

#define PTM_RATIO 32

// HelloWorldLayer
@interface HelloWorldLayer : CCLayer <GKAchievementViewControllerDelegate, GKLeaderboardViewControllerDelegate>
{
    b2World* world;                 // strong ref
    GLESDebugDraw *m_debugDraw;     // strong ref
}

// returns a CCScene that contains the HelloWorldLayer as the only child
+(CCScene *) scene;

@end

HelloWorldLayer.mm

// Import the interfaces
#import "HelloWorldLayer.h"

// Needed to obtain the Navigation Controller
#import "AppDelegate.h"
#define PTM_RATIO 32

#define kRADIAL_GRAVITY_FORCE 250.0f
enum {
    kTagParentNode = 1,
    kTagTileMap = 1,
    kTagSpriteSheet = 1,
    kTagAnimation1 = 1,
};


#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 screenSize = [CCDirector sharedDirector].winSize;
        CCLOG(@"Screen width %0.2f screen height %0.2f",screenSize.width,screenSize.height);


        b2Vec2 gravity;
        gravity.Set(0.0f, -10.0f);


        // This will speed up the physics simulation
        bool doSleep = true;

        // Construct a world object, which will hold and simulate the rigid bodies.
        world = new b2World(gravity);
        world->SetAllowSleeping(doSleep);
        world->SetContinuousPhysics(true);


        //Set up sprite

        CCSprite *sheet = [CCSprite spriteWithFile:@"blocks.png"];
        [self addChild:sheet z:0 tag:kTagSpriteSheet];

    [self addNewSpriteAtPosition:ccp(screenSize.width/2, screenSize.height/2)];

     //ERROR Use of undeclared identifier 'CCLabel'
    //ERROR Use of undeclared identifier 'label'    
       CCLabel *label = [CCLabel labelWithString:@"Tap Screen" fontName:@"Marker Felt" fontSize:32];
        // ERROR Use of undeclared identifier 'label'   
        [self addChild:label z:0];
        //ERROR Use of undeclared identifier 'label'
        [label setColor:ccc3(0,0,255)];
        //ERROR Use of undeclared identifier 'label'
        label.position = ccp( screenSize.width/2, screenSize.height-50);

        // Create our static "Planet" - Nick
        b2CircleShape shape;
        shape.m_radius = 1.0f;
        shape.m_p.Set(8.0f, 8.0f);
        b2FixtureDef fd;
        fd.shape = &shape;
        //ERROR Use of undeclared identifier 'planet'
        planet = groundBody->CreateFixture(&fd);
        // End Create Planet - Nick

        [self schedule: @selector(tick:)];


        // init physics
        [self initPhysics];

        [self scheduleUpdate];
    }
    return self;

}

-(void) dealloc
{
    delete world;
    world = NULL;

    delete m_debugDraw;
    m_debugDraw = NULL;

    [super dealloc];
}   

-(void) createMenu
{


}

-(void) initPhysics
{

    CGSize s = [[CCDirector sharedDirector] winSize];

    b2Vec2 gravity;
    gravity.Set(0.0f, -10.0f);
    world = new b2World(gravity);


    // Do we want to let bodies sleep?
    world->SetAllowSleeping(true);

    world->SetContinuousPhysics(true);


    // Debug Draw functions
    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);
}

-(void) draw
{
    //
    // IMPORTANT:
    // This is only for debug purposes
    // It is recommend to disable it
    //
    [super draw];
    // Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
    // Needed states:  GL_VERTEX_ARRAY,
    // Unneeded states: GL_TEXTURE_2D, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
    glDisable(GL_TEXTURE_2D);
    glDisable(GL_COLOR_BUFFER_BIT);


    world->DrawDebugData();

}

-(void) addNewSpriteAtPosition:(CGPoint)p
{

    CCLOG(@"Add sprite %0.2f x %02.f",p.x,p.y);
    CCSprite *sheet = (CCSprite*) [self getChildByTag:kTagSpriteSheet];
    int idx = (CCRANDOM_0_1() > .5 ? 0:1);
    int idy = (CCRANDOM_0_1() > .5 ? 0:1);

    //ERROR Cannot initialize a parameter of type 'CCTexture2D *' with an lvalue of type 'CCSprite *'

    CCSprite *sprite = [CCSprite spriteWithTexture:sheet rect:CGRectMake(32 * idx,32 * idy,32,32)];
    [sheet 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);
    bodyDef.userData = sprite;
    b2Body *body = world->CreateBody(&bodyDef);

    // Define another box shape for our dynamic body.
    b2PolygonShape dynamicBox;
    dynamicBox.SetAsBox(.5f, .5f);//These are mid points for our 1m box

    // Define the dynamic body fixture.
    b2FixtureDef fixtureDef;
    fixtureDef.shape = &dynamicBox;
    fixtureDef.density = 1.0f;
    fixtureDef.friction = 0.3f;
    body->CreateFixture(&fixtureDef);

    }

-(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);


    //Iterate over the bodies in the physics world
    for (b2Body* b = world->GetBodyList(); b; b = b->GetNext())
    {
        b2Body* ground = planet->GetBody();
        b2CircleShape* circle = (b2CircleShape*)planet->GetShape();
        // Get position of our "Planet" - Nick
        b2Vec2 center = ground->GetWorldPoint(circle->m_p);
        // Get position of our current body in the iteration - Nick
        b2Vec2 position = b->GetPosition();
        // Get the distance between the two objects. - Nick
        b2Vec2 d = center - position;
        // The further away the objects are, the weaker the gravitational force is - Nick
        float force = kRADIAL_GRAVITY_FORCE / d.LengthSquared(); // 150 can be changed to adjust the amount of force - Nick
        d.Normalize();
        b2Vec2 F = force * d;
        // Finally apply a force on the body in the direction of the "Planet" - Nick
        b->ApplyForce(F, position);

        if (b->GetUserData() != NULL) {
            //Synchronize the AtlasSprites position and rotation with the corresponding body
            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 ) {
        CGPoint location = [touch locationInView: [touch view]];

        location = [[CCDirector sharedDirector] convertToGL: location];
        [self addNewSpriteAtPosition:location];

    }
}

- (void)accelerometer:(UIAccelerometer*)accelerometer didAccelerate:(UIAcceleration*)acceleration
{
    static float prevX=0, prevY=0;

    //#define kFilterFactor 0.05f
#define kFilterFactor 1.0f  // don't use filter. the code is here just as an example

    float accelX = (float) acceleration.x * kFilterFactor + (1- kFilterFactor)*prevX;
    float accelY = (float) acceleration.y * kFilterFactor + (1- kFilterFactor)*prevY;

    prevX = accelX;
    prevY = accelY;

    // accelerometer values are in "Portrait" mode. Change them to Landscape left
    // multiply the gravity by 10
    b2Vec2 gravity( -accelY * 10, accelX * 10);

    world->SetGravity( gravity );
}



#pragma mark GameKit delegate

-(void) achievementViewControllerDidFinish:(GKAchievementViewController *)viewController
{
    AppController *app = (AppController*) [[UIApplication sharedApplication] delegate];
    [[app navController] dismissModalViewControllerAnimated:YES];
}

-(void) leaderboardViewControllerDidFinish:(GKLeaderboardViewController *)viewController
{
    AppController *app = (AppController*) [[UIApplication sharedApplication] delegate];
    [[app navController] dismissModalViewControllerAnimated:YES];
}

@end

0 个答案:

没有答案