// // HelloWorldLayer.mm // maliaobox2d // // Created by ivt on 6/3/13. // Copyright __MyCompanyName__ 2013. All rights reserved. // // Import the interfaces #import "HelloWorldLayer.h" // Needed to obtain the Navigation Controller #import "AppDelegate.h" #import "PhysicsSprite.h" #import "CAnimationHelper.h" #import <vector> #import <algorithm> #import "MyContactListener.h" enum { kTagParentNode = 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; } -(void) menuItem1Touched:(id)sender{ } -(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]; // CCTMXTiledMap *map = [CCTMXTiledMap tiledMapWithTMXFile:@"map.tmx"]; //[self addChild:map]; //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, s.height/2)]; CCLabelTTF *label = [CCLabelTTF labelWithString:@"Tap screen" fontName:@"Marker Felt" fontSize:32]; [self addChild:label z:0]; [label setColor:ccc3(0,0,255)]; label.position = ccp( s.width/2, s.height-50); [self scheduleUpdate]; _contactListener =new MyContactListener(); world->SetContactListener(_contactListener); } 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]]; }]; // Achievement Menu Item using blocks CCMenuItem *itemAchievement = [CCMenuItemFont itemWithString:@"Achievements" block:^(id sender) { GKAchievementViewController *achivementViewController = [[GKAchievementViewController alloc] init]; achivementViewController.achievementDelegate = self; AppController *app = (AppController*) [[UIApplication sharedApplication] delegate]; [[app navController] presentModalViewController:achivementViewController animated:YES]; [achivementViewController release]; }]; // Leaderboard Menu Item using blocks CCMenuItem *itemLeaderboard = [CCMenuItemFont itemWithString:@"Leaderboard" block:^(id sender) { GKLeaderboardViewController *leaderboardViewController = [[GKLeaderboardViewController alloc] init]; leaderboardViewController.leaderboardDelegate = self; AppController *app = (AppController*) [[UIApplication sharedApplication] delegate]; [[app navController] presentModalViewController:leaderboardViewController animated:YES]; [leaderboardViewController release]; }]; CCMenuItemFont* right= [CCMenuItemFont itemFromString:@"right!" block:^(id sender){ b2Vec2 v=maliaobody->GetLinearVelocity(); v.x=5.0f; maliaobody->SetLinearVelocity(v); }]; CCMenuItemFont* left= [CCMenuItemFont itemFromString:@"left" block:^(id sender){ b2Vec2 v=maliaobody->GetLinearVelocity(); v.x=-5.0f; maliaobody->SetLinearVelocity(v); }]; CCMenuItemFont* jump= [CCMenuItemFont itemFromString:@"jump" block:^(id sender){ b2Vec2 v=maliaobody->GetLinearVelocity(); v.y=8.0f; maliaobody->SetLinearVelocity(v); }]; CCMenu *menu = [CCMenu menuWithItems:itemAchievement, reset, right,left,jump, 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, -10.0f); world = new b2World(gravity); // Do we want to let bodies sleep? world->SetAllowSleeping(true); world->SetContinuousPhysics(true); _contactListener =new MyContactListener(); world->SetContactListener(_contactListener); 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); //利用帧缓存中的文件名创建动作 [[CCSpriteFrameCache sharedSpriteFrameCache]addSpriteFramesWithFile:@"game.plist"]; PhysicsSprite *mySpriteByF =[PhysicsSprite spriteWithSpriteFrameName:@"Frame0.swf"]; mySpriteByF.tag=10; [self addChild:mySpriteByF]; CCAnimation *anim=[CCAnimation animationWithFrame:@"Frame" frameCount:5 delay:0.1]; CCAnimate *animate = [CCAnimate actionWithAnimation:anim]; CCSequence *seq = [CCSequence actions:animate,nil]; CCRepeatForever *repeat = [CCRepeatForever actionWithAction:seq]; [mySpriteByF runAction:repeat]; b2BodyDef bodyDef; bodyDef.type = b2_dynamicBody; bodyDef.position.Set(0.5,1); bodyDef.userData=mySpriteByF; maliaobody = world->CreateBody(&bodyDef); maliaobody->SetFixedRotation(true); // Define another box shape for our dynamic body. b2PolygonShape dynamicBox; dynamicBox.SetAsBox(.1f, .2f);//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; maliaobody->CreateFixture(&fixtureDef); [mySpriteByF setPhysicsBody:maliaobody]; [[CCSpriteFrameCache sharedSpriteFrameCache]addSpriteFramesWithFile:@"game1.plist"]; m_Score=[CCSprite spriteWithSpriteFrameName:@"Score0.swf"]; m_Score.position=ccp(80,s.height*0.5); [self addChild:m_Score]; CCAnimation *anim1=[CCAnimation animationWithFrame:@"Score" frameCount:25 delay:0.1]; CCAnimate *animate1= [CCAnimate actionWithAnimation:anim1]; CCSequence *seq1 = [CCSequence actions:animate1,nil]; CCRepeatForever *repeat1 = [CCRepeatForever actionWithAction:seq1]; [m_Score runAction:repeat1]; } -(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) addWallSpriteAtPosition { //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(32 * idx,32 * idy,32,32)]; sprite.tag=11; [parent addChild:sprite]; sprite.position = ccp( 3,3); // Define the dynamic body. //Set up a 1m squared box in the physics world b2BodyDef bodyDef; bodyDef.type = b2_dynamicBody; bodyDef.position.Set(3,3); bodyDef.userData=sprite; b2Body *body = world->CreateBody(&bodyDef); // Define another box shape for our dynamic body. b2PolygonShape dynamicBox; dynamicBox.SetAsBox(.5f, 0.5f);//These are mid points for our 1m box // Define the dynamic body fixture. b2FixtureDef fixtureDef; fixtureDef.shape = &dynamicBox; fixtureDef.density = 100.0f; fixtureDef.friction = 0.3f; body->CreateFixture(&fixtureDef); [sprite setPhysicsBody:body]; } -(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(32 * idx,32 * idy,32,32)]; sprite.tag=2; [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); bodyDef.userData=sprite; b2Body *body = world->CreateBody(&bodyDef); body->SetGravityScale(0); // Define another box shape for our dynamic body. b2PolygonShape dynamicBox; dynamicBox.SetAsBox(.5f, 0.5f);//These are mid points for our 1m box // Define the dynamic body fixture. b2FixtureDef fixtureDef; fixtureDef.shape = &dynamicBox; fixtureDef.density = 100.0f; fixtureDef.friction = 0.3f; body->CreateFixture(&fixtureDef); [sprite setPhysicsBody:body]; } -(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); std::vector<b2Body *>toDestroy; std::vector<MyContact>::iterator pos; for(pos = _contactListener->_contacts.begin(); pos != _contactListener->_contacts.end(); ++pos) { MyContact contact =*pos; b2Body *bodyA = contact.fixtureA->GetBody(); b2Body *bodyB = contact.fixtureB->GetBody(); if (bodyA->GetUserData() != NULL && bodyB->GetUserData() != NULL) { CCSprite *spriteA = (CCSprite *) bodyA->GetUserData(); CCSprite *spriteB = (CCSprite *) bodyB->GetUserData(); if (spriteA.tag ==10&& spriteB.tag ==2) { NSLog(@"collision"); b2Vec2 v=bodyB->GetLinearVelocity(); //v.y=50.0f; // v.x=50.0f; bodyB->SetLinearVelocity(v); // toDestroy.push_back(bodyA); } else if (spriteA.tag ==2&& spriteB.tag ==10) { NSLog(@"collision"); // toDestroy.push_back(bodyB); } } } std::vector<b2Body *>::iterator pos2; for(pos2 = toDestroy.begin(); pos2 != toDestroy.end(); ++pos2) { b2Body *body =*pos2; if (body->GetUserData() != NULL) { CCSprite *sprite = (CCSprite *) body->GetUserData(); //[_spriteSheet removeChild:sprite cleanup:YES]; } // world->DestroyBody(body); } } - (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]; } } #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