Maze About

Couldn't you put a sensor that triggers if the ball contacts from the outside and creates a gate?

Perhaps add two rectangles vis(false) at the sides and addPhysics(false)

new Rectangle(50,H).vis(false).reg(CENTER).loc(maze.x-25,H/2).addPhysics(false);
new Rectangle(50,H).vis(false).reg(CENTER).loc(maze.x+maze.width+25,H/2).addPhysics(false);

For adding another picture...

  1. Use let ctx and let maze - rather than const. Or var is fine too.

  2. when you want a new maze set maze dispose() the old maze and set maze to the new pic and cache it. And then set the ctx again to the new maze cacheCanavs.


I put the target rectangle inside the maze.
I will try to do what you said. I am new to physics so I don't know much. Thank you for your suggestion.

I usually use a container. To change it, I delete the container with removeAllChildren() and add a new one. But as you said, the container does not work for objects that use physics. For this reason, I only added the labyrinth images to the general container. and wrote the code below. I solved the renewal process. I solved my problem for now. Thank you for your help. But I need to study physics more and learn more.

function newCreate(){

    generalCont.removeAllChildren()
    maze = new Pic("maze4.png").pos(0,50,CENTER,CENTER,generalCont).cache();

    ball.dynamic = true;
    ball.vis(true);
    emitter.loc(ball).spurt(20);

    ctx = maze.cacheCanvas.getContext('2d');
    num = 20; // test a 10x10 grid around the ball
    space = 1; // the spacing of the points on the grid
    radius = 1; // the radius of a wall placed at a point
    walls = []; // an array to keep track of the active walls

}

Good. You probably would not need to recreate the ball, emitter, target, walls, etc. Just really the pic and the context.

1 Like

Dan can you make it a zapp to share? thankZ

Note in this one, we have simplified the getting pixel color because we added a getColorAt(x,y) method to the bitmap.

But the new with straight lines

We already did a maze with the straight lines - our 3D one. @Ferudun is working on ones in 2D - let's let him do it. You can work on it yourself too.

1 Like
new Label("RING MAZE", 40, "Fascinate Inline", pink)
	.pos(0, 0, CENTER, TOP)
	.noMouse();
const button = new Button({label: "BAŞLA", corner: 6}).sca(1).pos(10, 10, RIGHT, BOTTOM).tap(() => {
	button.removeFrom();
	timeout(1, () => {
		ball.dynamic = true;
	});
});


STYLE = {once: true, italic: true, bold: true};





// MAZE
// we can load in ANY picture of a maze as long as the walls are different than the backing
// we could even load two pictures... a hidden one to represent the walls and a visual more complex one
// we then use physics to apply a force to the ball to follow the mouse
// and we make physic walls dynamically around the ball's position
// the walls are placed only on the non-background color
// the walls are removed as the ball leaves the area and new ones are made

// thanks https://www.mazegenerator.net/ 
// note: we made a vertical maze to start at the top and bottom 
// then rotated the image to start at the sides



var generalCont=new Container().center()

var maze = new Pic("maze1.png").pos(0,50,CENTER,CENTER,generalCont).cache();



// cache the image so we have a second canvas to use later
// this allows us to get the color of the pixel under the ball
// without getting the color of the ball ;-)

// new Label("START",25,null,white).pos(90,-20,LEFT,CENTER,holder);
// new Label("END",25,null,white).pos(60,-20,RIGHT,CENTER,holder);

//new Rectangle(W,H,new GradientColor([blue,green,orange,yellow])).addTo(holder).ble("darken");

// create a Physics instance to handle making the ball bounce off walls
// we will make walls dynamically only in the area of the ball
// that way we don't make thousands of walls that we don't need
// use the default outer walls and set gravity to 0
const physics = new Physics(0);

// physics.debug()

const ball = new Circle(12, red).pos(-480,410,CENTER).addPhysics({dynamic:false, contract:3});
ball.startX = ball.x;
ball.startY = ball.y;



// add an optional little finder
new Circle(30, black.toAlpha(.3)).center(ball, 0).wiggle("scale", 1, .1, .2, .7, 1.5);

const end = new Rectangle(20, 40, red).pos(480,330,CENTER,BOTTOM,maze).addTo(S)

// create a Ticker to constantly apply a force to the ball
// and make the walls near the ball
// the factor is for the force
// balance the speed with a tendency to go through walls if too fast

const emitter = new Emitter({
	startPaused: true,
	obj: new Circle(ball.radius * 1.3, clear, purple, 3),
	animation: {scale: {min: .5, max: 1.5}},
	force: {min: .5, max: 1.5},
	gravity: 0
})

const factor = .005; // force is incremental in time (make small)
const max = .5; // limit the mouse distance (which limits force)

Ticker.add(() => {
	// make the walls
	makeWalls();

	// apply a force towards the mouse
	// do not use stage.mouseX and stage.mouseY
	// as they do not catch touch location
	// use any mouse event's mouseX and mouseY instead
	// we did that and stored the values in mouseX and mouseY
	let dX = constrain((F.mouseX - ball.x) * factor, -max, max);
	let dY = constrain((F.mouseY - ball.y) * factor, -max, max);
	ball.force(dX, dY);

	if (ball.hitTestBounds(end)) {
		emitter.loc(ball).spurt(20);
		ball.dynamic = false;
		ball.vis(false);
		ball.body.loc(ball.startX, ball.startY);
		timeout(3.5, () => {


            newCreate()


		});

	}
});


// we want to find the color of the maze picture around where the ball is
// we will put a wall at anywhere that is not the background color
// so we access the context 2D of the cached picture
var ctx = maze.cacheCanvas.getContext('2d');
var num = 24; // test a 10x10 grid around the ball
var space = 1; // the spacing of the points on the grid
var radius = 1; // the radius of a wall placed at a point
var walls = []; // an array to keep track of the active walls


function newCreate(){

    generalCont.removeAllChildren()
    maze = new Pic("maze4.png").pos(0,50,CENTER,CENTER,generalCont).cache();



    ctx = maze.cacheCanvas.getContext('2d');
    num = 24; // test a 10x10 grid around the ball
    space = 1; // the spacing of the points on the grid
    radius = 1; // the radius of a wall placed at a point
    walls = []; // an array to keep track of the active walls


    ball.dynamic = true;
    ball.vis(true);
    emitter.loc(ball).spurt(20);


}

function makeWalls() {

	// remove any walls from the last time
	loop(walls, wall => {
		physics.remove(wall);
	});
	walls = [];

	// loop through our grid
	loop(num, i => {
		loop(num, j => {				

			const pointIn = maze.globalToLocal(ball.x, ball.y);

			// locate the x and y point on the grid for this i,j index
			const x = pointIn.x - num / 2 * space + i * space;
			const y = pointIn.y - num / 2 * space + j * space;

			if (x < 0 || y < 2 || x > maze.width || y > maze.height-2) return;
		

			// get the color data of the pixel at this grid location
			const data = ctx.getImageData(x, y, 1.2, 1.2).data;
			

			// Physics lets you automatically map physics bodies to ZIM objects
			// but in this case, we do not need visual objects
			// and we are creating many objects - so do not make the ZIM objects
			// Physics has methods to add only physics objects
			// so this is what we do in this case

			// make the wall if the color is darker than the background color
			if (data[0] < 150) {
				let wall = physics.makeCircle(radius, false);
				const pointOut = maze.localToGlobal(x,y);
				wall.x = pointOut.x, 
				wall.y = pointOut.y;
				// add the wall to our array of walls
				walls.push(wall);
			}
		});
	});
}

This may work for now, I'll work on it further.
You can create any maze you want from the site below.
https://codebox.net/pages/maze-generator/online

1 Like