Button to scramble a jigsaw puzzle

I have worked through the tutorial on creating a jigsaw puzzle. I am just wondering if I can extend the code to have a button that will regenerate the puzzle. I have the button (replay) with a listener. I can hide the tick that appears when the puzzle is completed, but I can't seem to regenerate the puzzle.

Here is the code, and I have attached the compressed Animate files.

If you get a moment, would you mind looking to see if this is possible.
20_bike-puzzle-zim.zip (835.7 KB)

const tick = zimify(this.tick);
tick.vis(false);
replay = zimify(this.replay)
//const puzzle;
F.loadAssets("bike.png", "pics/");
F.on("complete", () => {
	const pic = new Pic("bike.png");
	const puzzle = new Scrambler(chop((pic), 3, 1))
		.sca(.8)
		.center();
		
		puzzle.on("complete", ()=>{
		tick.vis(true);
		puzzle.scramble(1, 2, 3);
	});
});

replay.addEventListener("click", reset.bind(this));

function reset() {
	tick.vis(false);
	//puzzle.scramble(1, 2, 3);
}

You just have to make your code more modular. So instead of creating the puzzle on load complete. Wrap that in a function like makePuzzle(). Then include a way to dispose of the puzzle then recreate it. Here is an example:

I have been able to get to the point where I can press the replay button and generate the puzzle. The one thing I cannot work out is how to get rid of the old puzzle when a new one is generated. The new one that is generated sits on top of the old one and keeps piling the puzzles on top of each other. I wonder if you can see what I have missed. I think it may have to do with the dispose(0 command, but not quite sure.

Here is the code, and I will attach the full folder to see what I mean. I am SO close!!!

const tick = zimify(this.tick);
tick.vis(false);
replay = zimify(this.replay)
let puzzle;

replay.addEventListener("click", reset.bind(this));

function reset() {
	if(puzzle) puzzle.dispose();
	puzzle=null;
	stage.update();
	tick.vis(false);
	F.loadAssets("bike.png", "pics/");	
	F.on("complete", () => {
		const pic = new Pic("bike.png");
		const puzzle = new Scrambler(chop((pic), 3, 1))
						.sca(.8)
						.center();
		
		puzzle.on("complete", ()=>{
			tick.vis(true);
		});
	});
}

jigsaw1.zip (834.7 KB)

If puzzle.dispose() isn't doing it, maybe try this:

if (puzzle) {
    puzzle.dispose();
    puzzle.parent.removeChild(puzzle);
    // or puzzle.parent?.removeChild(puzzle);
}

...alternatively if you don't care about the "if" as visual clue of replaying, drop the if...

puzzle?.dispose();
puzzle?.parent?.removeChild(puzzle);

@rodecss I see your issue. You are declaring a puzzle variable that is accessible to child functions but in F.on(complete) you are declaring it's own puzzle variable which never sets your global puzzle variable. Just remove const.

NEW CODE:

const tick = zimify(this.tick);
tick.vis(false);
replay = zimify(this.replay)
let puzzle;

replay.addEventListener("click", reset.bind(this));

function reset() {
	if(puzzle) puzzle.dispose();
	puzzle=null;
	stage.update();
	tick.vis(false);
	F.loadAssets("bike.png", "pics/");	
	F.on("complete", () => {
		const pic = new Pic("bike.png");
		puzzle = new Scrambler(chop((pic), 3, 1))
						.sca(.8)
						.center();
		
		puzzle.on("complete", ()=>{
			tick.vis(true);
		});
	});
}
1 Like

Success - thank you very much for your help.

1 Like