Help with swap mechanism

image

At the end of my create(), i called addSwapBlockListener.
In the function, I get the main block(brown) position and use if case to get the side blocks. After that i added and event to capture touch.

I used on(“pointerdown”) on the top, left, bot, and right side of the main block(brown) which will call a swapBlock function to swap the main and the side block with tween and added oncomplete to change the x,y position of both blocks to ensure that the position has really been changed.

At the end of the swap function, I called the addSwapBlockListener function to the main block position and the side blocks position

But swapping only work once or twice, the second and the following messed up the swap (and errors occurs).
At times the on("pointerdown) don’t work.
I’ve been trying to solve this for half a day. Help me T.T

there were many errors like setInteractive() is null, and others.
I’ve spent around 6 hours trying to get it working but errors keep appearing after solving one.

What I’ve tried:-
-I tried to add removeAllListener at each side of the block on the on(pointerdown)

sorry for broken english

It will be hard to figure out without seeing your code, but I might have a suggestion.

Instead of adding the event listener on those 4 blocks only, and having to re-add it every time your make a swap, you could add a listener to ALL your blocks and act on it only if it is next to the main block. That way you never have to add/remove event listeners and you can base your logic on the position of the blocks only.

Let me know if that doesn’t make sense :slight_smile:

1 Like
addFirstMoveListeners(){
    // find main block 
    let objects = this.scene.scene.children.list;
    let blockEmptyIndex = this.scene.scene.children.list.findIndex(o => o.frame.name == "block_empty"); 
    let blockEmpty = objects[blockEmptyIndex];
    let blockPos = {"x": blockEmpty.x, "y": blockEmpty.y};
    // console.log(blockEmpty);
    // define side block (top, left, bot right)
    let outerLeftBlock; let outerBotBlock; let outerRightBlock; let outerTopBlock;
    if(blockEmpty.x > "104"){ // if main block is not at the most left of the 5x5 block
        outerLeftBlock = this.scene.scene.children.list[this.scene.scene.children.list.findIndex(o => o.x == (blockEmpty.x - 128) && o.y == blockEmpty.y)];
        // if (outerLeftBlock != null){if(!outerLeftBlock.input.enabled){outerLeftBlock.setInteractive();}}
        let sideBlockPosLeft = {"x": outerLeftBlock.x, "y": outerLeftBlock.y};
        // add event to swap block and main block after click or touch
        outerLeftBlock.once("pointerdown", ()=>{
            // call moveBlock to simplify code 
            // // outerLeftBlock.removeInteractive();
            // outerLeftBlock.removeAllListeners();
            this.moveBlock(blockEmpty, outerLeftBlock, blockPos, sideBlockPosLeft);
            
            // console.log(sideBlockPosLeft, blockPos);
            console.log("clicked left");
        })
    }
    if (blockEmpty.x < "616") { // if main block is not at the most right of the 5x5 block
        outerRightBlock = this.scene.scene.children.list[this.scene.scene.children.list.findIndex(o => o.x == (blockEmpty.x + 128) && o.y == blockEmpty.y)];
        // if (outerRightBlock != null) {if(!outerRightBlock.input.enabled){outerRightBlock.setInteractive();}}
        // outerRightBlock.setInteractive();
        let sideBlockPosRight = {"x": outerRightBlock.x, "y": outerRightBlock.y};
        
        outerRightBlock.once("pointerdown", ()=>{
            // outerRightBlock.removeInteractive();
            // outerRightBlock.removeAllListeners();
            this.moveBlock(blockEmpty, outerRightBlock, blockPos, sideBlockPosRight);
            
            // console.log(sideBlockPosRight, blockPos);
            console.log("clicked right");
        })
    }
    if (blockEmpty.y > "600") { // if main block is not at top of the 5x5 block
        outerTopBlock = this.scene.scene.children.list[this.scene.scene.children.list.findIndex(o => o.y == (blockEmpty.y - 128) && o.x == blockEmpty.x)];
        // if (outerTopBlock != null) {if(!outerTopBlock.input.enabled){outerTopBlock.setInteractive();}}
        // outerTopBlock.setInteractive();
        let sideBlockPosTop = {"x": outerTopBlock.x, "y": outerTopBlock.y};
        outerTopBlock.once("pointerdown", ()=>{
            // outerTopBlock.removeInteractive();
            // outerTopBlock.removeAllListeners();
            this.moveBlock(blockEmpty, outerTopBlock, blockPos, sideBlockPosTop);
            
            // console.log(sideBlockPosTop, blockPos);
            console.log("clicked top");
        })
    }
    if (blockEmpty.y < "1112") { // if main block is not at the bottom of the 5x5 block
        outerBotBlock = this.scene.scene.children.list[this.scene.scene.children.list.findIndex(o => o.y == (blockEmpty.y + 128) && o.x == blockEmpty.x)];
        // if (outerBotBlock != null) {if(!outerBotBlock.input.enabled){outerBotBlock.setInteractive();}}
        // outerBotBlock.setInteractive();
        let sideBlockPosBot = {"x": outerBotBlock.x, "y": outerBotBlock.y};
        outerBotBlock.once("pointerdown", ()=>{
            // outerBotBlock.removeInteractive();
            // outerBotBlock.removeAllListeners();
            this.moveBlock(blockEmpty, outerBotBlock, blockPos, sideBlockPosBot);
            
            // console.log(sideBlockPosBot, blockPos);
            console.log("clicked bot");
        })
    }
         

}

moveBlock(blockEmpty, sideBlock, tempBlockPos, sideBlockPos){
    console.log("before swapped");
    console.log(sideBlock, blockEmpty);
    this.tweens.add({
        targets: blockEmpty,
        x: sideBlockPos.x,
        y: sideBlock.y,
        ease: 'Power1',
        duration: 50,
        onComplete: ()=>{
            blockEmpty.x = sideBlockPos.x;
            blockEmpty.y = sideBlockPos.y;
        }
    });
    this.tweens.add({
        targets: sideBlock,
        x: tempBlockPos.x,
        y: tempBlockPos.y,
        ease: 'Power1',
        duration: 50,
        onComplete: ()=>{
            sideBlock.x = tempBlockPos.x;
            sideBlock.y = tempBlockPos.y;
        }
    });
    let newBlockPos = {"x": blockEmpty.x, "y": blockEmpty.y};
    console.log("after swapped");
    console.log(sideBlock, blockEmpty);

    // call back new add move listener because the side block changed and the main block position is changed
    setTimeout(this.addFirstMoveListeners(),51);
}

^ code
Thanks man, I’ll try your suggestions first and update after.(I think i understand your logic there, basically use if and check if main block is on side. what im unsure is the position of the new mainblocks, whether other blocks will be able to update input function with the new position. ( i tested handling input with update() function but when i console.log(), it called a lot instead of once.)

IT WORKS!! not only that, also shorten my codes.
at first i stumbled into an error undefined tweens., so i tried to use different methods then i rewrite it back to original and it just works lol.
below are my code (note that my blocks are dynamically? generated) so i have to create new array to store the blocks and to loop to add listener, i called createField on create()

createField(fieldSize, blockSize, addEmpty, offsetPos, maxColor){
    let row = offsetPos.y;
    let column = offsetPos.x;
    // console.log( this.game.scale.displayScale.x);
    // console.log(fieldSize);
    let blocksPos = [];
    let centerPos = [];
    let centerIndex = [{"x": 1, "y": 1}, {"x": 1, "y": 2},{"x": 1, "y": 3},{"x": 2, "y": 1},{"x": 2, "y": 2},{"x": 2, "y": 3},{"x": 3, "y": 1},{"x": 3, "y": 2},{"x": 3, "y": 3}];
    // console.log(centerIndex);

    for(let i = 0; i < fieldSize; i++){//row
        row = ((i) * blockSize) + offsetPos.y;
        // console.log(" . row " + (i+1) + " - " + row);
        for(let j = 0; j < fieldSize; j++){//column              
            column = ((j) * blockSize) + offsetPos.x;
            let blockPos = {"x": column, "y": row} 
            blocksPos.push(blockPos);
            if(centerIndex.findIndex(pos => pos.x === i && pos.y === j) > -1){
                centerPos.push(blockPos);
            }
            
        }
    }
    Phaser.Math.RND.shuffle(blocksPos);
    Phaser.Math.RND.sow([139]);
    let color = 1;
    let j = 1;
    let blocktba;
    let blocks = [];
    for(let i = 0; i < fieldSize*fieldSize; i++){//row
        if(color != 7){
            if(centerPos.findIndex(pos => pos.x === blocksPos[i].x && pos.y === blocksPos[i].y) > -1 && addEmpty){
                blocktba = this.add.image(blocksPos[i].x, blocksPos[i].y, "blockAtlas", ('block'+(color)+ "_center"));
            } else{
                blocktba = this.add.image(blocksPos[i].x, blocksPos[i].y, "blockAtlas", ('block'+(color)));

            }
            if(j % maxColor == 0){
                color++;
            } 
            j++;
        } else{
            if(addEmpty){
                blocktba = this.add.image(blocksPos[i].x, blocksPos[i].y, "blockAtlas", ('block_empty'));
            }
        }
        let blockScale = blockSize / blocktba.width;
        blocktba.setScale(blockScale).setInteractive();
        blocks.push(blocktba);
    }
    if(blocks.length > 9){
        for(let i = 0; i < blocks.length; i++){
            blocks[i].on("pointerdown", ()=>{
                let itemPos = {"x": blocks[i].x, "y": blocks[i].y};
                let mainBlock = blocks.find(o=> o.frame.name == "block_empty");
                let mainPos = {"x": mainBlock.x, "y": mainBlock.y};
                // let diffPos = {"x": (itemPos.x - mainBlock.x), "y": (itemPos.y - mainBlock.y)};
                // console.log(diffPos);
                if ((Math.abs(itemPos.x - mainBlock.x) == 128 && Math.abs(itemPos.y - mainBlock.y) == 0) || (Math.abs(itemPos.x - mainBlock.x) == 0 && Math.abs(itemPos.y - mainBlock.y) == 128)){
                    // this.moveBlock(mainBlock, blocks[i], mainPos, itemPos);
                    this.tweens.add({
                        targets: mainBlock,
                        x: itemPos.x,
                        y: itemPos.y,
                        ease: 'Power1',
                        duration: 150,
                        onComplete: () => {
                            mainBlock.x = itemPos.x;
                            mainBlock.y = itemPos.y;
                        }
                    });
                    this.tweens.add({
                        targets: blocks[i],
                        x: mainPos.x,
                        y: mainPos.y,
                        ease: 'Power1',
                        duration: 150,
                        onComplete: () => {
                            blocks[i].x = mainPos.x;
                            blocks[i].y = mainPos.y;
                        }
                    });
                }
            })
        }
        
    }
    // console.log(blocksPos);
    // let block = this.add.image(column, row, "blockAtlas", ("block"+(color)));

}

Awesome! Glad it helped :slight_smile:

1 Like