0

I am making a blackjack game in cocos2d-x here is the following code of the same where I am getting crash but can not understant why this is happening whats going wrong ? I tried several things thinking that crash might be because of string memory leak or something

CCSprite* _big = CCSprite::createWithSpriteFrameName(ptr);

Here is the card cpp file which inherits CCSprite

Card.cpp

#include "Card.h"

Card::Card() {
  }

Card::~Card() {
  }

void Card::init(int value, int suit) {
    mValue = value;
    mSuit = suit;
    mGameValue = 0;
    UnHide();
  }

void Card::UnHide() {

    mHidden = false;
    //if(this)
    //this->removeAllChildrenWithCleanup(true);
    //this->setDisplayFrame(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("card"));
    this->initWithSpriteFrameName("card");

    char strName[64]={0};

    //memset ( strName, 0, sizeof ( strName ));

    switch(mSuit){
    case 0: sprintf(strName,"%s","club_big");break;
    case 1: sprintf(strName,"%s","diamond_big");break;
    case 2: sprintf(strName,"%s","spade_big");break;
    case 3: sprintf(strName,"%s","heart_big");break;
    default :
            break;
    }

    const char *ptr = strdup(strName);  

    CCSprite* _big = CCSprite::createWithSpriteFrameName(ptr);
    delete  ptr;

   // CCSprite* big = CCSprite::create(strName);
    _big->setPosition(ccp(55, 44));
    this->addChild(_big);

    switch(mSuit){
        case 0: sprintf(strName,"%s","club");break;
        case 1: sprintf(strName,"%s","diamond");break;
        case 2: sprintf(strName,"%s","spade");break;
        case 3: sprintf(strName,"%s","heart");break;
        default :
            break;
    }

    const char *_ptr = strdup(strName); 

    CCSprite* _small = CCSprite::createWithSpriteFrameName(_ptr);
    delete _ptr;

   // CCSprite* small = CCSprite::create(str);
    _small->setPosition(ccp(16, 82));
    this->addChild(_small);

    if(mSuit==0 || mSuit==2){
        switch(mValue){
            case 1: sprintf(strName,"%s","blacka");mGameValue = 1;break;
            case 2: sprintf(strName,"%s","black2");mGameValue = mValue;break;
            case 3: sprintf(strName,"%s","black3");mGameValue = mValue;break;
            case 4: sprintf(strName,"%s","black4");mGameValue = mValue;break;
            case 5: sprintf(strName,"%s","black5");mGameValue = mValue;break;
            case 6: sprintf(strName,"%s","black6");mGameValue = mValue;break;
            case 7: sprintf(strName,"%s","black7");mGameValue = mValue;break;
            case 8: sprintf(strName,"%s","black8");mGameValue = mValue;break;
            case 9: sprintf(strName,"%s","black9");mGameValue = mValue;break;
            case 10: sprintf(strName,"%s","black10");mGameValue = mValue;break;
            case 11: sprintf(strName,"%s","blackj");mGameValue = 10;break;
            case 12: sprintf(strName,"%s","blackq");mGameValue = 10;break;
            case 13: sprintf(strName,"%s","blackk");mGameValue = 10;break;
            default :
            break;
        }
    }
    else {
        switch(mValue){
        case 1: sprintf(strName,"%s","reda");mGameValue = 1;break;
        case 2: sprintf(strName,"%s","red2");mGameValue = mValue;break;
        case 3: sprintf(strName,"%s","red3");mGameValue = mValue;break;
        case 4: sprintf(strName,"%s","red4");mGameValue = mValue;break;
        case 5: sprintf(strName,"%s","red5");mGameValue = mValue;break;
        case 6: sprintf(strName,"%s","red6");mGameValue = mValue;break;
        case 7: sprintf(strName,"%s","red7");mGameValue = mValue;break;
        case 8: sprintf(strName,"%s","red8");mGameValue = mValue;break;
        case 9: sprintf(strName,"%s","red9");mGameValue = mValue;break;
        case 10: sprintf(strName,"%s","red10");mGameValue = mValue;break;
        case 11: sprintf(strName,"%s","redj");mGameValue = 10;break;
        case 12: sprintf(strName,"%s","redq");mGameValue = 10;break;
        case 13: sprintf(strName,"%s","redk");mGameValue = 10;break;
        default :
            break;
        }
    }

    const char *_ptrr = strdup(strName);    

    CCSprite* _num = CCSprite::createWithSpriteFrameName(_ptrr);
    delete _ptrr;
   // CCSprite* _num = CCSprite::create(strName);
    _num->setPosition(ccp(18, 108));
    this->addChild(_num);
}

void Card::Hide() {

    mHidden = true;
    this->removeAllChildrenWithCleanup(true);
    this->setDisplayFrame(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("deck"));
    //this->initWithSpriteFrameName("deck");
}

Intialization of cards is as per this

for (int suit = 0; suit < 4; suit++) {
            for (int value = 0; value < 13; value++) {
                Card* card = new Card;
                //card->init
                card->init(value+1, suit);
              mCard[suit*13 + value] = card;
            }
          }

The crash I get is on the line of initWithSpriteFrameName but it doesnt occur frequently

user1169079
  • 3,053
  • 5
  • 42
  • 71
  • You might find this a good, unrelated read: http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier – chris Oct 02 '12 at 04:20
  • 2
    I'd recommend cutting out the use of `new` and using containers instead for arrays, and smart pointers for single newed entities. As it is, you aren't even cleaning up `mcard` properly, as all of the `new`ed pointers in the array are never `delete`d. – chris Oct 02 '12 at 04:24
  • @chris : I just went through that link ...will change variable name as per that.... – user1169079 Oct 02 '12 at 04:26
  • @chris : O yes you are talking about this line Card *card = new Card are never getting deleted right? ... I did not understood about mCard cleaning up I am deleting it in destructor ? and also you said use containers you are suggesting me to use vectors ? instead of array but where? – user1169079 Oct 02 '12 at 04:30
  • Yes, that line will create memory that isn't freed. In the current state, the destructor should loop through the array and `delete` everything inside, followed by `delete[]`ing the array. However, vectors do that for you and offer very similar syntax. From what it looks like, storing `Card *` isn't necessary (but I didn't look too hard), in which case changing `mcards` to be a `std::vector`, or `std::array` if you use C++11, would do the trick. – chris Oct 02 '12 at 04:35
  • @chris : Ok, I will incorporate those changes and get back to you with the results ... – user1169079 Oct 02 '12 at 04:39
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/17429/discussion-between-user1201239-and-chris) – user1169079 Oct 02 '12 at 04:39
  • what I suggest is, as long as you are using cocos2d-x, and cocos2d-x have an amazing memory management system by itself, why don't you take the advantage of the framework? what you should do is make your Card or whatever as a subclass of CCObject, and write the static create method according to cocos2d-x standard, that will make your life a lot easier. – m.ding Oct 02 '12 at 06:50
  • @m.ding - I did not understood ...Correct me if i am wrong ..you saying class Card : public cocos2d::CCObject { static Create(); } and In cpp file Card::Create() { mCard = CCSprite::Create() ... and other things ....here } .. right ? – user1169079 Oct 02 '12 at 08:43
  • @m.ding : Hey bro can u give me example of what you trying to tell me about making Card as a subclass of CCObject...that would be very great ... – user1169079 Oct 02 '12 at 12:42
  • @user1201239 sorry I back home from work yesterday, here I provided an example – m.ding Oct 03 '12 at 00:35
  • @m.ding : Thanks dude ...I understood now what exactly you were trying to say ..with that example ... – user1169079 Oct 03 '12 at 12:34

1 Answers1

0

h file:

class Card : public cocos2d::Node
{
public:
int mValue;
int mSuit;
bool mHidden;
int mGameValue;
CCSprite* front;
CCSprite* back;

static Card* create();
bool init(int value, int suit);
void UnHide();
void Hide();
};

cpp file

Card* Card::create(int value, int suit){
    Card* card = new Card();
    if(card && card->init(value, suit)){
        card->autorelease();
        return card;
    }
    else{
        CC_SAFE_DELETE(card);
        return NULL;
    }
}

bool Card::init(int value, int suit) {
    if(CCNode::init()){
        mValue = value;
        mSuit = suit;
        mGameValue = 0;

        //create your front and back sprite here as what you did in Unhide
        CCSprite* back = blablabla;
        CCSprite* front = blablabla;

        //add them as a child of current node
        this->addChild(back);
        this->addChild(front);


        this->UnHide();
        return true;
    }
    return false;
}

void Card::UnHide() {
    back->setVisible(false);
    front->setVisible(true);
}

void Card::Hide() {
    back->setVisible(true);
    front->setVisible(false); 
}

and for your deck, from my understanding,

CCArray::createWithCapacity(52);

will be a better choice.

m.ding
  • 3,172
  • 19
  • 27