0

so I'm trying to make a game using html canvas and js, and I'm spawning in characters/items, but sometimes they bunch up together, so I wrote a little while loop to keep re-spawning them till they have a certain gap between themselves. However, whenever I insert the while loop, the game/browser freezes/crashes. Am I doing something wrong?

My code:

let mx = Math.floor(Math.random() * (Math.floor(1536) - Math.ceil(512)) + Math.ceil(512));
let m = new Image;
m.src = "./Mushroom.png";

let bx = Math.floor(Math.random() * (Math.floor(3072) - Math.ceil(512)) + Math.ceil(512));
let b = new Image;
b.src = "./Bee.png";

let cx = Math.floor(Math.random() * (Math.floor(4608) - Math.ceil(512)) + Math.ceil(512));
let c = new Image;
c.src = "./Coin.png";

while (true) {
  if (mx - bx < 128 || mx - cx < 128 || bx - mx < 128 || bx - cx < 128 || cx - mx < 128 || cx - bx < 128) {
    mx = Math.floor(Math.random() * (Math.floor(1536) - Math.ceil(512)) + Math.ceil(512));
    bx = Math.floor(Math.random() * (Math.floor(3072) - Math.ceil(512)) + Math.ceil(512));
    cx = Math.floor(Math.random() * (Math.floor(4608) - Math.ceil(512)) + Math.ceil(512));
  } else {
    break;
  };
};
4
  • 1
    nothing else can happen while that loop is running, so if it takes millions of iterations to reach the else clause and break out of the loop, it'll behave pretty much as you describe. (I haven't done the non-trivial math to figure out what the odds are of hitting all those conditions.) Commented Mar 18, 2021 at 22:44
  • 2
    Math.floor(1536) or Math.ceil(512) don't do anything you can just write 1536 and 512 Commented Mar 18, 2021 at 22:44
  • 1
    @RobinZigmond - the odds are precisely 0 the way it is currently written. See my answer. Commented Mar 18, 2021 at 22:59
  • @Vilx- - thanks, I see now (I hadn't analysed the if conditions very closely before my comment, as it seemed too much like work! But now I see it is indeed obvious.) Commented Mar 18, 2021 at 23:03

2 Answers 2

3

The loop will be infinite because it will never reach the break. That's because your if statement will always take the first branch. Consider:

if ( a-b < 128 || b-a < 128 ) {
    console.log("yay");
}

It doesn't matter what values are in a or b, the condition will always be true.

What you want is:

if ( Math.abs(a-b) < 128 ) {
    console.log("yay");
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks a lot. This helped me tremendously!
1

You have created an infinite loop, that never breaks, as the if condition is always true (see answer from Vilx).

while (true) {
  if (true)
    ...
  } else {
    break;
  };
}

This causes the browser to freeze.

In general: Create a function that ensures the distance and call it after every move of your items/characters. Make sure not to compute the movement of your items/characters in an infinite loop, too, but use setInterval instead in order to call the function that a) computes the moves and b) ensures the separation of your items.

Example (this is still doing something strange, but it works at least) - don't know what your final objective is. I've also corrected some other minor errors. Enjoy!

<html>
<head>
<script type="text/javascript" type="text/javascript">   
function nextMove() {
let mx = Math.floor(Math.random() * (Math.floor(1536) - Math.ceil(512)) + Math.ceil(512));
let m = new Image();
m.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABySURBVDhP7ZFLDsAgCES9/7V6MDpkUBFJ1HbRTV9i5DPPjUUyyoQtRuKU0WuCcwtVhj7VPMHvzdIk3rdq0yTN1+vIJPTfyQ9MouYvH6Dmd/+Mc+rTVIsX2PSbCXoFlr43wdAArNMnOLdQJfaEUY8tPCI3hStcGseO1cgAAAAASUVORK5CYII=";

let bx = Math.floor(Math.random() * (Math.floor(3072) - Math.ceil(512)) + Math.ceil(512));
let b = new Image();
b.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABySURBVDhP7ZFLDsAgCES9/7V6MDpkUBFJ1HbRTV9i5DPPjUUyyoQtRuKU0WuCcwtVhj7VPMHvzdIk3rdq0yTN1+vIJPTfyQ9MouYvH6Dmd/+Mc+rTVIsX2PSbCXoFlr43wdAArNMnOLdQJfaEUY8tPCI3hStcGseO1cgAAAAASUVORK5CYII=";

let cx = Math.floor(Math.random() * (Math.floor(4608) - Math.ceil(512)) + Math.ceil(512));
let c = new Image();
c.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABySURBVDhP7ZFLDsAgCES9/7V6MDpkUBFJ1HbRTV9i5DPPjUUyyoQtRuKU0WuCcwtVhj7VPMHvzdIk3rdq0yTN1+vIJPTfyQ9MouYvH6Dmd/+Mc+rTVIsX2PSbCXoFlr43wdAArNMnOLdQJfaEUY8tPCI3hStcGseO1cgAAAAASUVORK5CYII=";

  if (mx - bx < 128 || mx - cx < 128 || bx - mx < 128 || bx - cx < 128 || cx - mx < 128 || cx - bx < 128) {
    mx = Math.floor(Math.random() * (Math.floor(1536) - Math.ceil(512)) + Math.ceil(512));
    bx = Math.floor(Math.random() * (Math.floor(3072) - Math.ceil(512)) + Math.ceil(512));
    cx = Math.floor(Math.random() * (Math.floor(4608) - Math.ceil(512)) + Math.ceil(512));
  }

let myCanvas = document.getElementById('myCanvas');
myCanvas.appendChild(m); 
myCanvas.appendChild(b); 
myCanvas.appendChild(c); 

m.style.marginLeft = mx;
m.style.martinTop = 100;
b.style.marginLeft = bx;
b.style.martinTop = 100;
c.style.marginLeft = cx;
c.style.martinTop = 100;
}

var myIntervalTimer = setInterval(nextMove, 100); // call every 100 milliseconds
</script>
<body id='myCanvas'>
</body>
</html>

2 Comments

That's not the issue here. There is a break statement that under normal circumstances would stop the loop after just a few iterations. Unfortunately the condition in the if statement is wrong and the break will never be reached.
@Vilx: I agree. I will update my answer - thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.