i have been trying to make a game using cocos2d. The map i'm using is made using Tiled and i'm trying to implement movement of character using accelerometer. I have tried myself but it didnt work. The movement is not smooth and very jumpy. Here is my code so far:
Hope someone can help me fix this...
Code:
#import "HelloWorldLayer.h"
#import "SimpleAudioEngine.h"
#define kFilterFactor 0.05
@implementation HelloWorldHud
-(id) init
{
if ((self = [super init])) {
CGSize winSize = [[CCDirector sharedDirector] winSize];
label = [CCLabelTTF labelWithString:@"0" dimensions:CGSizeMake(50, 20) alignment:UITextAlignmentRight fontName:@"Verdana-Bold" fontSize:18.0];
label.color = ccc3(0,0,0);
int margin = 10;
label.position = ccp(winSize.width - (label.contentSize.width/2) - margin, label.contentSize.height/2 + margin);
[self addChild:label];
totalTime = 60;
timeLabel = [CCLabelTTF labelWithString:@"60" fontName:@"Arial" fontSize:18];
timeLabel.color = ccc3(0, 0, 0);
timeLabel.position = CGPointMake(winSize.width/2, winSize.height);
timeLabel.anchorPoint = CGPointMake(0.5f, 1.0f);
[self addChild:timeLabel];
[self schedule: @selector(update:)];
}
return self;
}
- (void)numCollectedChanged:(int)numCollected {
[label setString:[NSString stringWithFormat:@"%d", numCollected]];
}
-(void)update:(ccTime)dt
{
totalTime -= dt;
currentTime = (int)totalTime;
if(totalTime > currentTime)
{
//myTime = currentTime;
[timeLabel setString:[NSString stringWithFormat:@"%02d:%02d", currentTime/60, currentTime%60]];
}
}
@end
// HelloWorldLayer implementation
@implementation HelloWorldLayer
@synthesize tileMap = _tileMap;
@synthesize background = _background;
@synthesize player = _player;
@synthesize meta = _meta;
@synthesize foreground = _foreground;
@synthesize numCollected = _numCollected;
@synthesize hud = _hud;
+(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];
layer.tag = 1;
HelloWorldHud *hud = [HelloWorldHud node];
[scene addChild:hud];
layer.hud = hud;
// return the scene
return scene;
}
// on "init" you need to initialize your instance
-(id) init
{
// always call "super" init
// Apple recommends to re-assign "self" with the "super" return value
if( (self=[super init])) {
[[SimpleAudioEngine sharedEngine] preloadEffect:@"pickup.caf"];
[[SimpleAudioEngine sharedEngine] preloadEffect:@"hit.caf"];
[[SimpleAudioEngine sharedEngine] preloadEffect:@"move.caf"];
[[SimpleAudioEngine sharedEngine] playBackgroundMusic:@"TileMap.caf"];
//self.isTouchEnabled = YES;
self.isAccelerometerEnabled = YES;
UIAccelerometer *accel = [UIAccelerometer sharedAccelerometer];
accel.delegate = self;
accel.updateInterval = 1.0f/60.0f;
//load background
self.tileMap = [CCTMXTiledMap tiledMapWithTMXFile:@"TileMap.tmx"];
self.background = [_tileMap layerNamed:@"Background"];
self.foreground = [_tileMap layerNamed:@"Foreground"];
//load collidable tile
self.meta = [_tileMap layerNamed:@"Meta"];
_meta.visible = NO;
//starting point
CCTMXObjectGroup *objects = [_tileMap objectGroupNamed:@"Objects"];
NSAssert(objects !=nil, @"'Objects' object group not found");
NSMutableDictionary *spawnPoint = [objects objectNamed:@"SpawnPoint"];
NSAssert(spawnPoint !=nil, @"SpawnPoint object not found");
int x = [[spawnPoint valueForKey:@"x"] intValue];
int y = [[spawnPoint valueForKey:@"y"] intValue];
int tileSpawnWidth = _tileMap.tileSize.width;
int tileSpawnHeight = _tileMap.tileSize.height;
x = (x - (x % tileSpawnWidth)) + (tileSpawnWidth/2);
y = (y - (y % tileSpawnHeight)) + (tileSpawnHeight/2);
//load player
self.player = [CCSprite spriteWithFile:@"Player.png"];
_player.position = ccp(x, y);
_player.tag = 2;
[self addChild:_player];
id setCamera = [CCFollow actionWithTarget:_player];
[self runAction:setCamera];
[self addChild: _tileMap z:-1];
}
return self;
}
-(CGPoint) tileCoordForPosition: (CGPoint)position {
int x = position.x / _tileMap.tileSize.width;
int y = ((_tileMap.mapSize.height * _tileMap.tileSize.height) - position.y) / _tileMap.tileSize.height;
return ccp(x,y);
}
-(void) registerWithTouchDispatcher
{
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];
}
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
return YES;
}
-(void) setPlayerPosition:(CGPoint)position
{
//Convert x, y coordinate of player into tile coordinate
CGPoint tileCoord = [self tileCoordForPosition:position];
int tileGid = [_meta tileGIDAt:tileCoord];
if(tileGid) {
NSDictionary *properties = [_tileMap propertiesForGID:tileGid];
if(properties) {
//Check if collide with wall/stone
NSString *collision = [properties valueForKey:@"Collidable"];
if(collision && [collision compare: @"True"] == NSOrderedSame) {
[[SimpleAudioEngine sharedEngine] playEffect:@"hit.caf"];
return;
}
//Check if collide with collectable item
NSString *collectable = [properties valueForKey:@"Collectable"];
if(collectable && [collectable compare:@"True"] == NSOrderedSame) {
[_meta removeTileAt:tileCoord];
[_foreground removeTileAt:tileCoord];
self.numCollected++;
[_hud numCollectedChanged:_numCollected];
[[SimpleAudioEngine sharedEngine] playEffect:@"pickup.caf"];
}
}
}
[[SimpleAudioEngine sharedEngine] playEffect:@"move.caf"];
//_player.position = position;
ccTime moveDuration = 0.3;
id playerMove = [CCMoveTo actionWithDuration:moveDuration position:position];
id cameraMove = [CCFollow actionWithTarget:_player worldBoundary:CGRectMake(0, 0, (_tileMap.mapSize.width * _tileMap.tileSize.width), (_tileMap.mapSize.height * _tileMap.tileSize.height))];
[_player runAction:playerMove];
[self runAction:cameraMove];
}
-(void) ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint touchLocation = [touch locationInView:[touch view]];
touchLocation = [[CCDirector sharedDirector] convertToGL:touchLocation];
touchLocation = [self convertToNodeSpace:touchLocation];
CGPoint playerPos = _player.position;
CGPoint diff = ccpSub(touchLocation, playerPos);
if(abs(diff.x) > abs(diff.y))
{
if(diff.x > 0)
{
playerPos.x += _tileMap.tileSize.width;
}
else
{
playerPos.x -= _tileMap.tileSize.width;
}
}
else
{
if(diff.y > 0)
{
playerPos.y += _tileMap.tileSize.height;
}
else
{
playerPos.y -= _tileMap.tileSize.height;
}
}
if(playerPos.x <= (_tileMap.mapSize.width * _tileMap.tileSize.width) &&
playerPos.y <= (_tileMap.mapSize.height * _tileMap.tileSize.height) &&
playerPos.y >= 0 &&
playerPos.x >= 0 )
{
[self setPlayerPosition:playerPos];
}
}
#define kPlayerSpeed 100
#define kHeroMovementAction 1
-(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
//UIAccelerationValue accelX, accelY;
//accelX = (acceleration.x*kFilterFactor) + (accelX*(1.0 - kFilterFactor));
//accelY = (acceleration.y*kFilterFactor) + (accelY*(1.0 - kFilterFactor));
HelloWorldLayer *layer = (HelloWorldLayer *) [[[CCDirector sharedDirector] runningScene] getChildByTag:1];
CCSprite *playerSprite = (CCSprite *) [layer getChildByTag:2];
CGPoint playerPos;
float destX, destY;
BOOL shouldMove = NO;
float currentX = playerSprite.position.x;
float currentY = playerSprite.position.y;
if(acceleration.x > 0.25)
{
destX = currentX - (acceleration.y * kPlayerSpeed);
destY = currentY + (acceleration.x * kPlayerSpeed);
shouldMove = YES;
} else
if(acceleration.x < -0.25)
{
destX = currentX - (acceleration.y * kPlayerSpeed);
destY = currentY + (acceleration.x * kPlayerSpeed);
shouldMove = YES;
} else
if(acceleration.y < -0.25)
{
destX = currentX - (acceleration.y * kPlayerSpeed);
destY = currentY + (acceleration.x * kPlayerSpeed);
shouldMove = YES;
} else
if(acceleration.y > 0.25)
{
destX = currentX - (acceleration.y * kPlayerSpeed);
destY = currentY + (acceleration.x * kPlayerSpeed);
shouldMove = YES;
} else
{
destX = currentX;
destY = currentY;
}
playerPos.x = destX;
playerPos.y = destY;
if(shouldMove)
{
CGSize wins = [[CCDirector sharedDirector] winSize];
if(destX < 30 || destX > wins.width - 30 || destY < 30 || destY > wins.height - 100)
{
[self setPlayerPosition:playerPos];
}
else
{
CCAction *action = [CCMoveTo actionWithDuration:1 position:CGPointMake(destX, destY)];
[action setTag:kHeroMovementAction];
[playerSprite runAction:action];
}
}
else
{
[playerSprite stopActionByTag:kHeroMovementAction];
}
}
// on "dealloc" you need to release all your retained objects
- (void) dealloc
{
// in case you have something to dealloc, do it in this method
// in this particular example nothing needs to be released.
// cocos2d will automatically release all the children (Label)
// don't forget to call "super dealloc"
self.tileMap = nil;
self.background = nil;
self.player = nil;
self.meta = nil;
self.foreground = nil;
self.hud = nil;
[super dealloc];
}
@end
Hope someone can help me fix this...