I have used the tutorial from Here
and successfully made a similar puzzle game (with custom layout and imaged tiles)
My problem now is to recognize when the user finishes the puzzle..
I am and android developer, but this cocos2d is very new to me.
I have downloaded the source code to check what the writer of the tutorial have done to find when the user has finished the puzzle, but his code for this part is not working, and I need to find a way to check after every move if the user has finished or not.. if it were android I would not have any problem with it..
here is the relevant code:
public void generateTiles(){
//We create a Node element to hold all our tiles
CCNode tilesNode = CCNode.node();
tilesNode.setTag(TILE_NODE_TAG);
addChild(tilesNode);
float scalefactor ; // a value we compute to help scale our tiles
int useableheight ;
int tileIndex = 0 ;
//We attempt to calculate the right size for the tiles given the screen size and
//space left after adding the status label at the top
int nextval ;
int[] tileNumbers = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};//{12,1,10,2,7,11,4,14,5,0,9,15,8,13,6,3}; //random but solvable sequence of numbers
//TILE_SQUARE_SIZE = (int) ((screenSize.height *generalscalefactor)/NUM_ROWS) ;
int useablewidth = (int) (screenSize.width - statusLabel.getContentSize().width*generalscalefactor ) ;
useableheight = (int) (screenSize.height - 40*generalscalefactor - statusLabel.getContentSize().height * 1.3f*generalscalefactor) ;
TILE_SQUARE_SIZE = (int) Math.min((useableheight/NUM_ROWS) , (useablewidth/NUM_COLUMNS)) ;
toppoint = (int) (useableheight - (TILE_SQUARE_SIZE / 2) + 30*generalscalefactor) ;
scalefactor = TILE_SQUARE_SIZE / 125.0f ;
topleft = (int) ((TILE_SQUARE_SIZE / 2) + 15*generalscalefactor) ;
for (int j = toppoint ; j > toppoint - (TILE_SQUARE_SIZE * NUM_ROWS); j-= TILE_SQUARE_SIZE){
for (int i = topleft ; i < (topleft - 5*generalscalefactor) + (TILE_SQUARE_SIZE * NUM_COLUMNS); i+= TILE_SQUARE_SIZE){
if (tileIndex >= (NUM_ROWS * NUM_COLUMNS)) {
break ;
}
nextval = tileNumbers[tileIndex ];
//Generate tile by it's number and it's subfolder
Tile tile = new Tile();
tile.setIndex(nextval);
tile.setSprite(CCSprite.sprite(subFolder+"/"+subFolder+"_tile_"+String.valueOf(nextval+1)+".jpg"));
tiles.add(tile);
//CCSprite tile = CCSprite.sprite(subFolder+"/"+subFolder+"_tile_"+String.valueOf(nextval+1)+".jpg");
CCNodeExt eachNode = new CCNodeExt();
eachNode.setContentSize(tile.getSprite().getContentSize());
//
//Layout Node based on calculated postion
eachNode.setPosition(i, j);
eachNode.setNodeText(nextval + "");
//Add Tile number
if(showNumbers == true)
{
CCBitmapFontAtlas tileNumber = CCBitmapFontAtlas.bitmapFontAtlas ("00", "bionic.fnt");
tileNumber.setScale(1.4f);
eachNode.setScale(scalefactor);
eachNode.addChild(tile.getSprite(),1,1);
tileNumber.setString(nextval + "");
eachNode.addChild(tileNumber,2 );
}
else
{
eachNode.setScale(scalefactor);
eachNode.addChild(tile.getSprite(),1,1);
}
if( nextval != 0){
tilesNode.addChild(eachNode,1,nextval);
}else {
emptyPosition = CGPoint.ccp(i, j);
}
//Add each Node to a HashMap to note its location
tileIndex++;
}
}
}
@Override
public boolean ccTouchesBegan(MotionEvent event)
{
//Get touch location cordinates
CGPoint location = CCDirector.sharedDirector().convertToGL(CGPoint.ccp(event.getX(), event.getY()));
CGRect spritePos ;
CCNode tilesNode = (CCNode) getChildByTag(TILE_NODE_TAG) ;
//ccMacros.CCLOG("Began", "Began : " + location.x + " : " );
//We loop through each of the tiles and get its cordinates
for (int i = 1 ; i < (NUM_ROWS * NUM_COLUMNS); i++){
CCNodeExt eachNode = (CCNodeExt) tilesNode.getChildByTag(i) ;
//Log.d(String.valueOf(eachNode), String.valueOf(tiles.get(i).getIndex()));
//we construct a rectangle covering the current tiles cordinates
spritePos = CGRect.make(
eachNode.getPosition().x - (eachNode.getContentSize().width*generalscalefactor/2.0f),
eachNode.getPosition().y - (eachNode.getContentSize().height*generalscalefactor/2.0f),
eachNode.getContentSize().width*generalscalefactor ,
eachNode.getContentSize().height*generalscalefactor );
//Check if the user's touch falls inside the current tiles cordinates
if(spritePos.contains(location.x, location.y)){
//ccMacros.CCLOG("Began Touched Node", "Began touched : " + eachNode.getNodeText());
slideCallback(eachNode); // if yes, we pass the tile for sliding.
}
}
return true ;
}
public void slideCallback(CCNodeExt thenode) {
CGPoint nodePosition = thenode.getPosition();
//Determine the position to slide the tile to .. ofcourse only if theres an empty space beside it
if((nodePosition.x - TILE_SQUARE_SIZE)== emptyPosition.x && nodePosition.y == emptyPosition.y){
slideTile("Left", thenode,true);
}else if((nodePosition.x + TILE_SQUARE_SIZE) == emptyPosition.x && nodePosition.y == emptyPosition.y){
slideTile("Right", thenode,true);
}else if((nodePosition.x)== emptyPosition.x && nodePosition.y == (emptyPosition.y + TILE_SQUARE_SIZE )){
slideTile("Down", thenode,true);
}else if((nodePosition.x )== emptyPosition.x && nodePosition.y == (emptyPosition.y - TILE_SQUARE_SIZE)){
slideTile("Up", thenode,true);
}else{
slideTile("Unmovable", thenode,false);
}
}
public void slideTile(String direction, CCNodeExt thenode, boolean move){
CCBitmapFontAtlas moveslabel = (CCBitmapFontAtlas) getChildByTag(MOVES_LABEL_TAG);
if(move && !gameover){
// Increment the moves label and animate the tile
moves ++ ;
moveslabel.setString("Moves : " + CCFormatter.format("%03d", moves ));
//Update statuslabel
statusLabel.setString("Tile : " + thenode.getNodeText() + " -> " + direction);
//Animate the tile to slide it
CGPoint nodePosition = thenode.getPosition();
//Log.d("current pos",String.valueOf(nodePosition));
CGPoint tempPosition = emptyPosition ;
//Log.d("go to pos",String.valueOf(tempPosition));
CCMoveTo movetile = CCMoveTo.action(0.4f, tempPosition);
CCSequence movetileSeq = CCSequence.actions(movetile, CCCallFuncN.action(this, "handleWin"));
thenode.runAction(movetileSeq);
emptyPosition = nodePosition ;
//Play a sound
appcontext = CCDirector.sharedDirector().getActivity();
SoundEngine.sharedEngine().playEffect(appcontext, R.raw.tileclick);
thenode.runAction(movetileSeq);
}else{
}
}
public void handleWin(Object sender){
if(checkCorrect()){
gameover = true ;
Log.d("Game "+String.valueOf(gameover), "VICTORY!");
SoundEngine.sharedEngine().playEffect(appcontext, R.raw.tileclick);
//WinCallback(sender);
}
}
//This method checks if the puzzle has been correctly solved.
public boolean checkCorrect(){
CCNode tileNode = (CCNode) getChildByTag(TILE_NODE_TAG);
int nodeindex = 1 ;
boolean result = false;
int rowindex = 0 ;
for (int j = toppoint ; j > toppoint - (TILE_SQUARE_SIZE * NUM_ROWS); j-= TILE_SQUARE_SIZE){
for (int i = topleft ; i < (topleft - 5*generalscalefactor) + (TILE_SQUARE_SIZE * NUM_COLUMNS); i+= TILE_SQUARE_SIZE){
Log.d(String.valueOf(tileNode.getChildByTag(nodeindex).getPosition().x), String.valueOf(tileNode.getChildByTag(nodeindex).getPosition().y));
Log.d(String.valueOf(i), String.valueOf(j));
if(tileNode.getChildByTag(nodeindex).getPosition().x == i && tileNode.getChildByTag(nodeindex).getPosition().y == j ){
//Log.d(String.valueOf(tileNode.getChildByTag(nodeindex).getPosition().x), String.valueOf(tileNode.getChildByTag(nodeindex).getPosition().y));
//Log.d(String.valueOf(i), String.valueOf(j));
result = true ;
Log.d("Game "+String.valueOf(result), "result");
}else{
//Log.d("Game "+String.valueOf(false), "result");
return false ;
}
nodeindex++ ;
//Log.d("nodeindex "+String.valueOf(nodeindex), "index total");
if(nodeindex == (NUM_ROWS * NUM_COLUMNS)){
Log.d("Game "+String.valueOf(result), "result");
return result ;
}
}
}
rowindex = 0 ;
Log.d("Game "+String.valueOf(result), "result");
return result ;
}
}
basically I just need the last method to be fixed for me, all of the other code is just for reference and understanding of the last needed part..