owen gerig
owen gerig

Reputation: 6172

positioning with cocos2d

Here is the source

The problem is that the start and end positions of my projectiles are way off. I have NSLog'd all the CGPoints and from what I can see the points being fed into the CCSequence are correct. But from what Im seeing on the screen says different.

A big clue to whats wrong I think is that if create a new CCSprite and use it like I do the projectile the pathing works.

Here is the addProjectile method on the game level layer (GameLevels:Level1Layer)

-(void)addProjectile:(Projectiles*)projectile
{
    NSLog(@"projectile position %@",NSStringFromCGPoint(projectile.position));
    NSLog(@"wizard position %@",NSStringFromCGPoint(self.wizardHero.position));
    NSLog(@"wizard position worldspace %@",NSStringFromCGPoint([self convertToWorldSpace:self.wizardHero.position]));
    NSLog(@"destination position %@",NSStringFromCGPoint(projectile.destination.position));

    [self addChild:projectile];

    // Determine where we wish to shoot the projectile to
    int realX;

    CGPoint diff = ccpSub(projectile.destination.position,projectile.position);
    if (diff.x > 0)
    {
        realX = (self.tileMap.mapSize.width * self.tileMap.tileSize.width) +
        (projectile.contentSize.width/2);
    } else {
        realX = -(self.tileMap.mapSize.width * self.tileMap.tileSize.width) -
        (projectile.contentSize.width/2);
    }
    float ratio = (float) diff.y / (float) diff.x;
    int realY = ((realX - projectile.position.x) * ratio) + projectile.position.y;
    CGPoint realDest = ccp(realX, realY);

    // Determine the length of how far we're shooting
    int offRealX = realX - projectile.position.x;
    int offRealY = realY - projectile.position.y;
    float length = sqrtf((offRealX*offRealX) + (offRealY*offRealY));
    float velocity = 280/1; // 280pixels/1sec
    float realMoveDuration = length/velocity;

    // Move projectile to actual endpoint
    id actionMoveDone = [CCCallFuncN actionWithTarget:self
                                             selector:@selector(projectileMoveFinished:)];
    [projectile runAction:
     [CCSequence actionOne:
      [CCMoveTo actionWithDuration: realMoveDuration
                          position: realDest]
                       two: actionMoveDone]];

    [self.projectiles addObject:projectile];
}

and output from those NSLog statements would be (FYI: the projectile is being added from the self.wizardHero and thus that is its starting position; destination would be self.redEnemy):

2013-03-27 10:41:57.295 GridWars[13025:c07] projectile position {105, 178}

2013-03-27 10:41:57.296 GridWars[13025:c07] wizard position {105, 178}

2013-03-27 10:41:57.297 GridWars[13025:c07] wizard position worldspace {105, 178}

2013-03-27 10:41:57.298 GridWars[13025:c07] destination position {299, 174}

2013-03-27 11:34:46.608 GridWars[13344:c07] realDest {650, 166}

2013-03-27 11:34:46.608 GridWars[13344:c07] length 545.132080

2013-03-27 11:34:46.610 GridWars[13344:c07] realMoveDuration 1.946900

I realize that with the super classes I have its a little hard to tell whats going on (kinda why I included the source). Basically though I have three main super classes which are subclassed from CCNode

Projectiles : CCNode
        sprite : CCSprite
        destination : GameCharacters
        damage : int


GameLevels : CCNode
        hud : HudLayer
        tileMap : CCTMXTiledMap
        enemies : NSMutablArray
        projectiles : NSMutablArray

GameCharacters : CCNode
        hp : int
        juice : int
        sprite : CCSprite
        selectedTargets : NSMutablArray
        hostLayer : GameLevels

Then the three classes that actually implement these

        BasicProjectile : Projectiles
        Level1Layer : GameLevels
        WizardHero : GameCharacter
        RedEnemy : GameCharacter

Though the problem has slightly evolved I have posted this on the cocos2d forums and received some help, which got me to this point (seeing projectiles, but path is wrong vs not seeing them at all). But its been a few days so Hoping for more help.

GameProjectiles:CCNode

#import "CCNode.h"

//forward declaration because we just need to hold a reference
@class GameCharacters;

@interface GameProjectiles : CCNode

@property(nonatomic, strong) CCSprite * sprite;
@property(nonatomic,strong) GameCharacters * destination;
@property(nonatomic) int damage;
-(id)initWithDestination:(GameCharacters*)Destination;
-(CGSize)contentSize;

@end


#import "GameProjectiles.h"

@implementation GameProjectiles

-(id)initWithDestination:(GameCharacters*)Destination
{

    if (self = [super init]) {
        _damage = 0;
        _destination = Destination;
    }
    return self;
}

-(CGSize)contentSize{
    return self.sprite.contentSize;
}

-(void)setPosition:(CGPoint)position
{
    [super setPosition:position];
    self.sprite.position = position;
}
@end

BasicProjectile

#import "GameProjectiles.h"

@interface BasicProjectile : GameProjectiles

@end


#import "BasicProjectile.h"

@implementation BasicProjectile

-(id)initWithDestination:(GameCharacters*)Destination
{
    if (self = [super init]) {
        self.damage = 25;
        self.sprite = [CCSprite spriteWithFile:@"Projectile.png"];
        [self addChild:self.sprite z:1000 ];
        self.destination = Destination;
    }
    return self;
}

@end

Upvotes: 0

Views: 180

Answers (1)

Shubhank
Shubhank

Reputation: 21805

since your projectiles and targets are inside a separate CCNode, their bounding box returns their position inside their parent and not in actual screen coordinates (which you want in your case).

To convert the pos you can do like this

    CGPoint targetPos = [basicProjectile.destination.sprite.parent convertToWorldSpace:basicProjectile.destination.sprite.position];
    NSLog(@"targetPos  %@",NSStringFromCGPoint(targetPos));
    CGRect targetRect = [self boundingRectForSprite:basicProjectile.destination.sprite andPos:targetPos];

    CGPoint projectilePos = [basicProjectile.sprite.parent convertToWorldSpace:basicProjectile.sprite.position];
    NSLog(@"projectilePos  %@",NSStringFromCGPoint(projectilePos));
    CGRect projectileRect = [self boundingRectForSprite:basicProjectile.destination.sprite andPos:projectilePos];

the boundingRectForSprite method makes the uses the sprite bounding box and position and then calculates the final rect taking anchor point of (0.5,0.5).

now the targetRect and projectileRect are of actual screen coordinates.

Upvotes: 1

Related Questions