#import "GameEngine.h" //Problems //1 speed isnt always the same probs due to frame rate - ~gettransform //3 not true time //To Do //1 level selector... //2 white holes to slow down time /black speed it up / gravity change / teleport spot / bridge /mulcocsotiple mes to push big object int step=0; int jumpallowed=0;//1=yes @implementation GameEngine +(CCScene *)scene{ CCScene *scene = [CCScene node]; GameEngine *layer = [GameEngine node]; [scene addChild:layer]; return scene; } -(id)init{ if ((self=[super init])) { [self createButtons]; [self createMainCharacterAndWorld]; [self setTouchEnabled:YES]; [self schedule:@selector(tick:) interval:1.f/30.f]; repeatx=[NSMutableArray new]; repeaty=[NSMutableArray new]; pastMovementsx=[NSMutableArray new]; pastMovementsy=[NSMutableArray new]; teleportationSpots=[NSMutableArray new]; [self resetLevel]; } return self; } -(void)createMainCharacterAndWorld{ CGSize winSize = [CCDirector sharedDirector].winSize; // Create a world b2Vec2 gravity = b2Vec2(0.0f, -10.0); world = new b2World(gravity); _contactListener=new ContactListener(); world->SetContactListener(_contactListener); // Create edges around the entire screen b2BodyDef groundBodyDef; groundBodyDef.position.Set(0,0); groundBody = world->CreateBody(&groundBodyDef); b2EdgeShape groundEdge; b2FixtureDef boxShapeDef; boxShapeDef.shape = &groundEdge; groundEdge.Set(b2Vec2(0,72/PTM_RATIO), b2Vec2(winSize.width/PTM_RATIO, 76/PTM_RATIO));///changed y='d 0 bottomFixture=groundBody->CreateFixture(&boxShapeDef); //this is bottom fixture thing groundEdge.Set(b2Vec2(0,0), b2Vec2(0, winSize.height/PTM_RATIO)); groundBody->CreateFixture(&boxShapeDef); groundEdge.Set(b2Vec2(0, winSize.height/PTM_RATIO), b2Vec2(winSize.width/PTM_RATIO, winSize.height/PTM_RATIO)); groundBody->CreateFixture(&boxShapeDef); groundEdge.Set(b2Vec2(winSize.width/PTM_RATIO, winSize.height/PTM_RATIO), b2Vec2(winSize.width/PTM_RATIO, 0)); boxShapeDef.filter.groupIndex=1;//to make collision with players groundBody->CreateFixture(&boxShapeDef); // Create sprite and add it to the layer character = [CCSprite spriteWithFile:@"Icon-Small.png"]; character.position = ccp(25, 108); [self addChild:character]; // Create body and shape b2BodyDef characterBodyDef; characterBodyDef.type = b2_dynamicBody; characterBodyDef.position.Set(25/PTM_RATIO, 108/PTM_RATIO); characterBodyDef.userData =character; body = world->CreateBody(&characterBodyDef); b2PolygonShape characterShape; characterShape.SetAsBox(character.contentSize.width/PTM_RATIO/2,character.contentSize.height/PTM_RATIO/2); b2FixtureDef characterShapeDef; characterShapeDef.shape = &characterShape; characterShapeDef.density = 1.f; characterShapeDef.friction = .0f; characterShapeDef.restitution = 0.f; characterShapeDef.filter.groupIndex=-1;//to disable collision between players body->CreateFixture(&characterShapeDef); body->SetFixedRotation(true); } -(void)createCharacters{ for(int i=0;i<[pastMovementsx count];i++){ pastcharacter = [CCSprite spriteWithFile:@"Icon-Small.png"]; NSValue *positionSet=[teleportationSpots objectAtIndex:i]; [pastcharacter setPosition:[positionSet CGPointValue]]; pastcharacter.tag=i; [self addChild:pastcharacter]; // Define the dynamic body. b2BodyDef bodyDef; bodyDef.type = b2_dynamicBody; bodyDef.position.Set([positionSet CGPointValue].x/PTM_RATIO, [positionSet CGPointValue].y/PTM_RATIO); bodyDef.userData =pastcharacter; pastbody = world->CreateBody(&bodyDef); // Define another box shape for our dynamic body. b2PolygonShape dynamicBox; dynamicBox.SetAsBox(character.contentSize.width/PTM_RATIO/2,character.contentSize.height/PTM_RATIO/2); // Define the dynamic body fixture. b2FixtureDef fixtureDef; fixtureDef.shape = &dynamicBox; fixtureDef.density = 1.f; fixtureDef.friction = 0.f; fixtureDef.restitution = 0.f; fixtureDef.filter.groupIndex=-1;//to disable collision between players pastbody->CreateFixture(&fixtureDef); pastbody->SetFixedRotation(true); } } -(void)createButtons{ leftButton = [CCMenuItemImage itemWithNormalImage:@"Icon-72.png" selectedImage: @"Icon-Small.png" target:self selector:@selector(left)]; rightButton = [CCMenuItemImage itemWithNormalImage:@"Icon-72.png" selectedImage: @"Icon-Small.png" target:self selector:@selector(right)]; CCMenu *movementMenu=[CCMenu menuWithItems:leftButton,rightButton, nil]; [movementMenu alignItemsHorizontally]; movementMenu.opacity=100; movementMenu.color=ccBLUE; movementMenu.position=ccp(72,72/2); [self addChild:movementMenu]; //Jump button jumpButton = [CCMenuItemImage itemWithNormalImage:@"Icon-72.png" selectedImage: @"Icon-Small.png" target:self selector:@selector(jump)]; CCMenu *myMenu=[CCMenu menuWithItems:jumpButton, nil]; [myMenu alignItemsHorizontally]; myMenu.position=ccp(480-72/2,36); myMenu.color=ccMAGENTA; [self addChild:myMenu]; //travel back button CCMenuItemToggle *setBackTime = [CCMenuItemImage itemWithNormalImage:@"Icon-72.png" selectedImage: @"Icon-Small.png" target:self selector:@selector(setBackTime)]; CCMenu *aMenu=[CCMenu menuWithItems:setBackTime, nil]; [aMenu alignItemsHorizontally]; aMenu.position=ccp(480/2,36); [self addChild:aMenu]; CCMenuItemToggle *resetLevel = [CCMenuItemImage itemWithNormalImage:@"Icon-72.png" selectedImage: @"Icon-Small.png" target:self selector:@selector(resetLevel)]; CCMenu *bMenu=[CCMenu menuWithItems:resetLevel, nil]; [bMenu alignItemsHorizontally]; bMenu.position=ccp(480-36,360-72); bMenu.opacity=100; [self addChild:bMenu]; //timer timeLabel=[CCLabelTTF labelWithString:@"Relative Time: 0" fontName:@"Marker Felt" fontSize:24]; timeLabel.color=ccWHITE; timeLabel.anchorPoint=ccp(0,1); timeLabel.position=ccp(0,320); [self addChild:timeLabel]; } -(void)left{} -(void)right{} -(void)jump{} -(void)resetLevel{ step=0; [self deleteCharacters]; [repeatx removeAllObjects]; [repeaty removeAllObjects]; [pastMovementsx removeAllObjects]; [pastMovementsy removeAllObjects]; [teleportationSpots removeAllObjects]; character.position = ccp(25, 108); body->SetTransform(b2Vec2(25/PTM_RATIO,108/PTM_RATIO), 0); [teleportationSpots addObject:[NSValue valueWithCGPoint:character.position]]; [[CCDirector sharedDirector]replaceScene:[HelloWorldLayer node]];//temporary place } -(void)moveCurrentBodyAndRecordMovements{ std::vector::iterator pos; for(pos =_contactListener->_contacts.begin();pos!=_contactListener->_contacts.end();++pos) { MyContact contact =*pos; if((contact.fixtureA==bottomFixture && contact.fixtureB==body->GetFixtureList()) || (contact.fixtureA == body->GetFixtureList() && contact.fixtureB == bottomFixture)) jumpallowed=1; } if(rightButton.isSelected==YES){ body->SetLinearVelocity(b2Vec2(3,body->GetLinearVelocity().y)); [repeatx addObject:[NSNumber numberWithInt:1]]; } else if(leftButton.isSelected==YES){ body->SetLinearVelocity(b2Vec2(-3,body->GetLinearVelocity().y)); [repeatx addObject:[NSNumber numberWithInt:-1]]; } else{ body->SetLinearVelocity(b2Vec2(0,body->GetLinearVelocity().y)); [repeatx addObject:[NSNumber numberWithInt:0]]; } if(jumpButton.isSelected==YES && jumpallowed==1){ body->SetLinearVelocity(b2Vec2(body->GetLinearVelocity().x,7)); [repeaty addObject:[NSNumber numberWithInt:1]]; jumpallowed=0; } else [repeaty addObject:[NSNumber numberWithInt:0]]; jumpallowed=0; } -(void)setBackTime{ step=0; [self teleportSpot]; [self addToMovementArray]; [self deleteCharacters]; [self createCharacters]; } -(void)teleportSpot{ [teleportationSpots addObject:[NSValue valueWithCGPoint:character.position]]; } -(void)addToMovementArray{ NSMutableArray *tempx=[[NSMutableArray alloc]initWithArray:repeatx copyItems:YES]; NSMutableArray *tempy=[[NSMutableArray alloc]initWithArray:repeaty copyItems:YES]; [pastMovementsx addObject:tempx]; [pastMovementsy addObject:tempy]; [repeatx removeAllObjects]; [repeaty removeAllObjects]; } -(void)deleteCharacters{ for(b2Body *b = world->GetBodyList(); b; b=b->GetNext()) { if (b->GetUserData() != NULL) { CCSprite *bodyData = (CCSprite *)b->GetUserData(); for(int i=0;i<[pastMovementsx count];i++) { if (bodyData.tag==i) { [self removeChildByTag:i cleanup:YES]; world->DestroyBody(b); break; } } } } } -(void)tick:(ccTime)dt{ [self moveCurrentBodyAndRecordMovements]; [self movePastBodies]; world->Step(dt,8,8); for(b2Body *b = world->GetBodyList(); b; b=b->GetNext()) { if (b->GetUserData() != NULL) { CCSprite *bodyData = (CCSprite *)b->GetUserData(); bodyData.position = ccp(b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO); } } [timeLabel setString:[NSString stringWithFormat:@"Relative Time: %i",step/30]]; step++; } -(void)movePastBodies{ for(b2Body *b = world->GetBodyList(); b; b=b->GetNext()) { if (b->GetUserData() != NULL) { CCSprite *bodyData = (CCSprite *)b->GetUserData(); for(int i=0;i<[pastMovementsx count];i++){ if (bodyData.tag==i) { if (step<[[pastMovementsx objectAtIndex:i] count]) { int xx=[[[pastMovementsx objectAtIndex:i] objectAtIndex:step] intValue]; int yy=[[[pastMovementsy objectAtIndex:i] objectAtIndex:step] intValue]; int onground=0; b->SetLinearVelocity(b2Vec2(xx*3,b->GetLinearVelocity().y)); std::vector::iterator pos; for(pos =_contactListener->_contacts.begin();pos!=_contactListener->_contacts.end();++pos) { MyContact contact =*pos; if((contact.fixtureA==bottomFixture && contact.fixtureB==b->GetFixtureList()) || (contact.fixtureA == b->GetFixtureList() && contact.fixtureB == bottomFixture)) onground=1; } if(yy==1 && onground==1) b->SetLinearVelocity(b2Vec2(b->GetLinearVelocity().x,7)); } else if(step>=[[pastMovementsx objectAtIndex:i] count]){ [self removeChildByTag:i cleanup:YES]; world->DestroyBody(b); break; } } } } } } -(void)dealloc{ delete world; character = NULL; world = NULL; pastbody=NULL; delete _contactListener; [super dealloc]; } @end