Cocos2d iphone Cocos2d-CCNode用户数据的替代方案

Cocos2d iphone Cocos2d-CCNode用户数据的替代方案,cocos2d-iphone,user-data,Cocos2d Iphone,User Data,我使用CCNode userData属性来定义一个被触摸的精灵是否有一个构建在它上面的节点(使用) 我遇到的问题是,对于我接触和建造的每一个新的精灵位置,以前的位置都不会保留,因为我无法使用我的出售方法出售建造在上面的建筑 将数据保存到通过触摸选择并通过for循环由属性定义的单个CCSprite的最佳方式是什么 我读到过,将CCSprite子类化是一种选择,或者为userData等创建一个结构。我尝试过实现这些策略,但都没有成功 具有sprite属性的触摸方法: -(void)ccTouches

我使用CCNode userData属性来定义一个被触摸的精灵是否有一个构建在它上面的节点(使用)

我遇到的问题是,对于我接触和建造的每一个新的精灵位置,以前的位置都不会保留,因为我无法使用我的出售方法出售建造在上面的建筑

将数据保存到通过触摸选择并通过for循环由属性定义的单个CCSprite的最佳方式是什么

我读到过,将CCSprite子类化是一种选择,或者为userData等创建一个结构。我尝试过实现这些策略,但都没有成功

具有sprite属性的触摸方法:

-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

    for(UITouch *touch in touches){
    CGPoint location = [touch locationInView:[touch view]];
    location = [[CCDirector sharedDirector] convertToGL:location];

    for(CCSprite *tb in self.BuildPositions){
//BuildPositions contains CCSprites from a class defining build positions and contained in a mutable array.
        if(CGRectContainsPoint([tb textureRect],[tb convertToNodeSpace:location ])){

            _selectedBuildPosition = tb;
            [self buildMenuTapped];
      }
    }
  }
}
-(void)buildMenuTapped{

[self removeChild:_buildSelectMenu cleanup:YES];
[self removeChild:_sellBuildingMenu cleanup:YES];

if (_selectedBuildPosition.userData == nil) {

    CCMenuItem *buildOption = [CCMenuItemImage itemWithNormalImage:@"building.png" selectedImage:@"building.png" target:self selector:   @selector(buildOption)];
    buildOption.position = ccpAdd(_selectedBuildPosition.position,ccp(0,40));

    _buildSelectMenu = [CCMenu menuWithItems:BuildOption, nil];
    _buildSelectMenu.position = CGPointZero;
    [self addChild:_buildSelectMenu z:100];

}else{

    [self sellBuildingMenu];
}
}
-(void)buildOption{

if([self canBuyBuilding] && !_selectedBuildPosition.userData){

    _playerEssence -= kBUILD_COST;

    _lvl1BuildNodeInstance = [lvl1BuildNode nodeWithTheGame:self location:_selectedBuildPosition.position];
//method as seen in RW tutorial. Generates a lvl1BuildNode class node within the HelloWorldLayer.

    _selectedBuildPosition.userData = (__bridge void*)(_lvl1BuildNodeInstance);

  }
}
-(void)sellBuildingMenu{
[self removeChild:_buildSelectMenu cleanup:YES];
[self removeChild:_sellBuildingMenu cleanup:YES];

CCMenuItem *buildingSell = [CCMenuItemImage itemWithNormalImage:@"sell.png" selectedImage:@"sell.png" target:self selector:@selector(sellBuilding)];
buildingSell.position =  ccpAdd(_selectedBuildPosition.position,ccp(40,0));

_sellBuildingMenu = [CCMenu menuWithItems:buildingSell, nil];
_sellBuildingMenu.position = CGPointZero;
[self addChild:_sellBuildingMenu z:100];
}
-(void)sellBuilding{
    if (_selectedBuildPosition.userData == (__bridge void*)(_lvl1BuildNodeInstance)){

        [self removeChild:_lvl1GemNodeInstance cleanup:YES];

        [_buildings removeObject:_lvl1BuildNodeInstance];

        _playerEssence += kBUILD_COST;

        _selectedBuildPosition.userData = nil;

    }else{
    }
}
构建菜单方法:

-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

    for(UITouch *touch in touches){
    CGPoint location = [touch locationInView:[touch view]];
    location = [[CCDirector sharedDirector] convertToGL:location];

    for(CCSprite *tb in self.BuildPositions){
//BuildPositions contains CCSprites from a class defining build positions and contained in a mutable array.
        if(CGRectContainsPoint([tb textureRect],[tb convertToNodeSpace:location ])){

            _selectedBuildPosition = tb;
            [self buildMenuTapped];
      }
    }
  }
}
-(void)buildMenuTapped{

[self removeChild:_buildSelectMenu cleanup:YES];
[self removeChild:_sellBuildingMenu cleanup:YES];

if (_selectedBuildPosition.userData == nil) {

    CCMenuItem *buildOption = [CCMenuItemImage itemWithNormalImage:@"building.png" selectedImage:@"building.png" target:self selector:   @selector(buildOption)];
    buildOption.position = ccpAdd(_selectedBuildPosition.position,ccp(0,40));

    _buildSelectMenu = [CCMenu menuWithItems:BuildOption, nil];
    _buildSelectMenu.position = CGPointZero;
    [self addChild:_buildSelectMenu z:100];

}else{

    [self sellBuildingMenu];
}
}
-(void)buildOption{

if([self canBuyBuilding] && !_selectedBuildPosition.userData){

    _playerEssence -= kBUILD_COST;

    _lvl1BuildNodeInstance = [lvl1BuildNode nodeWithTheGame:self location:_selectedBuildPosition.position];
//method as seen in RW tutorial. Generates a lvl1BuildNode class node within the HelloWorldLayer.

    _selectedBuildPosition.userData = (__bridge void*)(_lvl1BuildNodeInstance);

  }
}
-(void)sellBuildingMenu{
[self removeChild:_buildSelectMenu cleanup:YES];
[self removeChild:_sellBuildingMenu cleanup:YES];

CCMenuItem *buildingSell = [CCMenuItemImage itemWithNormalImage:@"sell.png" selectedImage:@"sell.png" target:self selector:@selector(sellBuilding)];
buildingSell.position =  ccpAdd(_selectedBuildPosition.position,ccp(40,0));

_sellBuildingMenu = [CCMenu menuWithItems:buildingSell, nil];
_sellBuildingMenu.position = CGPointZero;
[self addChild:_sellBuildingMenu z:100];
}
-(void)sellBuilding{
    if (_selectedBuildPosition.userData == (__bridge void*)(_lvl1BuildNodeInstance)){

        [self removeChild:_lvl1GemNodeInstance cleanup:YES];

        [_buildings removeObject:_lvl1BuildNodeInstance];

        _playerEssence += kBUILD_COST;

        _selectedBuildPosition.userData = nil;

    }else{
    }
}
建立在方法之上:

-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

    for(UITouch *touch in touches){
    CGPoint location = [touch locationInView:[touch view]];
    location = [[CCDirector sharedDirector] convertToGL:location];

    for(CCSprite *tb in self.BuildPositions){
//BuildPositions contains CCSprites from a class defining build positions and contained in a mutable array.
        if(CGRectContainsPoint([tb textureRect],[tb convertToNodeSpace:location ])){

            _selectedBuildPosition = tb;
            [self buildMenuTapped];
      }
    }
  }
}
-(void)buildMenuTapped{

[self removeChild:_buildSelectMenu cleanup:YES];
[self removeChild:_sellBuildingMenu cleanup:YES];

if (_selectedBuildPosition.userData == nil) {

    CCMenuItem *buildOption = [CCMenuItemImage itemWithNormalImage:@"building.png" selectedImage:@"building.png" target:self selector:   @selector(buildOption)];
    buildOption.position = ccpAdd(_selectedBuildPosition.position,ccp(0,40));

    _buildSelectMenu = [CCMenu menuWithItems:BuildOption, nil];
    _buildSelectMenu.position = CGPointZero;
    [self addChild:_buildSelectMenu z:100];

}else{

    [self sellBuildingMenu];
}
}
-(void)buildOption{

if([self canBuyBuilding] && !_selectedBuildPosition.userData){

    _playerEssence -= kBUILD_COST;

    _lvl1BuildNodeInstance = [lvl1BuildNode nodeWithTheGame:self location:_selectedBuildPosition.position];
//method as seen in RW tutorial. Generates a lvl1BuildNode class node within the HelloWorldLayer.

    _selectedBuildPosition.userData = (__bridge void*)(_lvl1BuildNodeInstance);

  }
}
-(void)sellBuildingMenu{
[self removeChild:_buildSelectMenu cleanup:YES];
[self removeChild:_sellBuildingMenu cleanup:YES];

CCMenuItem *buildingSell = [CCMenuItemImage itemWithNormalImage:@"sell.png" selectedImage:@"sell.png" target:self selector:@selector(sellBuilding)];
buildingSell.position =  ccpAdd(_selectedBuildPosition.position,ccp(40,0));

_sellBuildingMenu = [CCMenu menuWithItems:buildingSell, nil];
_sellBuildingMenu.position = CGPointZero;
[self addChild:_sellBuildingMenu z:100];
}
-(void)sellBuilding{
    if (_selectedBuildPosition.userData == (__bridge void*)(_lvl1BuildNodeInstance)){

        [self removeChild:_lvl1GemNodeInstance cleanup:YES];

        [_buildings removeObject:_lvl1BuildNodeInstance];

        _playerEssence += kBUILD_COST;

        _selectedBuildPosition.userData = nil;

    }else{
    }
}
销售菜单方法:

-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

    for(UITouch *touch in touches){
    CGPoint location = [touch locationInView:[touch view]];
    location = [[CCDirector sharedDirector] convertToGL:location];

    for(CCSprite *tb in self.BuildPositions){
//BuildPositions contains CCSprites from a class defining build positions and contained in a mutable array.
        if(CGRectContainsPoint([tb textureRect],[tb convertToNodeSpace:location ])){

            _selectedBuildPosition = tb;
            [self buildMenuTapped];
      }
    }
  }
}
-(void)buildMenuTapped{

[self removeChild:_buildSelectMenu cleanup:YES];
[self removeChild:_sellBuildingMenu cleanup:YES];

if (_selectedBuildPosition.userData == nil) {

    CCMenuItem *buildOption = [CCMenuItemImage itemWithNormalImage:@"building.png" selectedImage:@"building.png" target:self selector:   @selector(buildOption)];
    buildOption.position = ccpAdd(_selectedBuildPosition.position,ccp(0,40));

    _buildSelectMenu = [CCMenu menuWithItems:BuildOption, nil];
    _buildSelectMenu.position = CGPointZero;
    [self addChild:_buildSelectMenu z:100];

}else{

    [self sellBuildingMenu];
}
}
-(void)buildOption{

if([self canBuyBuilding] && !_selectedBuildPosition.userData){

    _playerEssence -= kBUILD_COST;

    _lvl1BuildNodeInstance = [lvl1BuildNode nodeWithTheGame:self location:_selectedBuildPosition.position];
//method as seen in RW tutorial. Generates a lvl1BuildNode class node within the HelloWorldLayer.

    _selectedBuildPosition.userData = (__bridge void*)(_lvl1BuildNodeInstance);

  }
}
-(void)sellBuildingMenu{
[self removeChild:_buildSelectMenu cleanup:YES];
[self removeChild:_sellBuildingMenu cleanup:YES];

CCMenuItem *buildingSell = [CCMenuItemImage itemWithNormalImage:@"sell.png" selectedImage:@"sell.png" target:self selector:@selector(sellBuilding)];
buildingSell.position =  ccpAdd(_selectedBuildPosition.position,ccp(40,0));

_sellBuildingMenu = [CCMenu menuWithItems:buildingSell, nil];
_sellBuildingMenu.position = CGPointZero;
[self addChild:_sellBuildingMenu z:100];
}
-(void)sellBuilding{
    if (_selectedBuildPosition.userData == (__bridge void*)(_lvl1BuildNodeInstance)){

        [self removeChild:_lvl1GemNodeInstance cleanup:YES];

        [_buildings removeObject:_lvl1BuildNodeInstance];

        _playerEssence += kBUILD_COST;

        _selectedBuildPosition.userData = nil;

    }else{
    }
}
销售方式:

-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

    for(UITouch *touch in touches){
    CGPoint location = [touch locationInView:[touch view]];
    location = [[CCDirector sharedDirector] convertToGL:location];

    for(CCSprite *tb in self.BuildPositions){
//BuildPositions contains CCSprites from a class defining build positions and contained in a mutable array.
        if(CGRectContainsPoint([tb textureRect],[tb convertToNodeSpace:location ])){

            _selectedBuildPosition = tb;
            [self buildMenuTapped];
      }
    }
  }
}
-(void)buildMenuTapped{

[self removeChild:_buildSelectMenu cleanup:YES];
[self removeChild:_sellBuildingMenu cleanup:YES];

if (_selectedBuildPosition.userData == nil) {

    CCMenuItem *buildOption = [CCMenuItemImage itemWithNormalImage:@"building.png" selectedImage:@"building.png" target:self selector:   @selector(buildOption)];
    buildOption.position = ccpAdd(_selectedBuildPosition.position,ccp(0,40));

    _buildSelectMenu = [CCMenu menuWithItems:BuildOption, nil];
    _buildSelectMenu.position = CGPointZero;
    [self addChild:_buildSelectMenu z:100];

}else{

    [self sellBuildingMenu];
}
}
-(void)buildOption{

if([self canBuyBuilding] && !_selectedBuildPosition.userData){

    _playerEssence -= kBUILD_COST;

    _lvl1BuildNodeInstance = [lvl1BuildNode nodeWithTheGame:self location:_selectedBuildPosition.position];
//method as seen in RW tutorial. Generates a lvl1BuildNode class node within the HelloWorldLayer.

    _selectedBuildPosition.userData = (__bridge void*)(_lvl1BuildNodeInstance);

  }
}
-(void)sellBuildingMenu{
[self removeChild:_buildSelectMenu cleanup:YES];
[self removeChild:_sellBuildingMenu cleanup:YES];

CCMenuItem *buildingSell = [CCMenuItemImage itemWithNormalImage:@"sell.png" selectedImage:@"sell.png" target:self selector:@selector(sellBuilding)];
buildingSell.position =  ccpAdd(_selectedBuildPosition.position,ccp(40,0));

_sellBuildingMenu = [CCMenu menuWithItems:buildingSell, nil];
_sellBuildingMenu.position = CGPointZero;
[self addChild:_sellBuildingMenu z:100];
}
-(void)sellBuilding{
    if (_selectedBuildPosition.userData == (__bridge void*)(_lvl1BuildNodeInstance)){

        [self removeChild:_lvl1GemNodeInstance cleanup:YES];

        [_buildings removeObject:_lvl1BuildNodeInstance];

        _playerEssence += kBUILD_COST;

        _selectedBuildPosition.userData = nil;

    }else{
    }
}

谢谢您的时间。

首先,请使用userObject(id)而不是userData(void*),因为这样这些对象将由ARC进行正确的内存管理,您不需要桥接转换。然后考虑,不是直接分配节点,可以将USER对象存储为字典或包装类,以向其添加多个节点。最后,存储对节点的引用(而不是它们创建/添加到的类)是一种非常糟糕的做法,因为这会很快导致保留周期,防止对象被释放。感谢Steffen的输入。我将尝试使用userObject。关于将用户对象编入词典,最好的方法是什么?我认为它必须是可变的,因为我们将在CCSprite用户对象更改后添加条目?是的,需要是可变的。只需创建一个字典并将其分配给userObject。太棒了,这种方法很管用。我仍然在销售正确选择的建筑时遇到问题,但是removeChild仅适用于最近创建的节点。我将尝试一下if语句和方法。干杯,斯蒂芬。