Clearing svg multiple children with a loop not working - javascript

I am currently trying to create a reset code so that when the player collides with the enemy, it clears all of the collectibles (I called them pellets) from the svg and then remakes them with a loop I have. For some reason it is clearing every pellet but one. It also does not recreate the pellets like it is supposed to for some reason. The svg variables are score, player, ghost(the enemy) and pellet.
This is the reset code:
function destroyPlayer()
{
alert("Game Over");
score = 0;
scoreElement.textContent = 'score: ' + score;
pelletCount=0;
constantCount = 1;
//need code to take out all pellets from svg
for(i = 0; i < 100; i++)
{
if(svg.children[i].id != "ghost" &&
svg.children[i].id != "score" &&
svg.children[i].id != "player")
{
svg.removeChild(svg.children[i]);
}
}
positionPellet();
positionGhost();
}
And this is the code that remakes the pellets: (the position pellet method)
function positionPellet()
{
while(pelletCount < constantCount*3)
{
var pellet = document.createElementNS( xmlns, 'circle' );
pellet.setAttribute( 'cx', Math.random() * 900 );
pellet.setAttribute( 'cy', Math.random() * 400 );
pellet.setAttribute( 'r' , 10 );
pellet.className.baseVal = "pelClass";
pelletCount++;
svg.appendChild(pellet);
}
}

Have you checked your browser developer console (press F12)? It should be displaying errors it finds in your Javascript.
If that's not helping much, you can log variables to the console to see why your code isn't working.
For instance, I can see immediately why your positionPellet() function isn't working. As a hint try adding some logging to check the value of pelletCount and constantCount.
function positionPellet()
{
console.log("pelletCount = "+pelletCount);
console.log("constantCount= "+constantCount);
while(pelletCount < constantCount*3)
{
...
When you run the code again, you should see those debugging lines with values showing as undefined. Why would that be?
Your other problem is a little more subtle. I'll give you a hint and say that when you remove element 0 from an array, the array is updated immediately. The array item that used to be at children[1] is now at children[0]. But in your next time through the loop, you will be looking at children[1], which won't be the next child any more, it will actually be the one that was after that (originally children[2]).

Related

jQuery run code after chunked $.each() is finished

With the below code:
$('#button').on('click', function () {
var longArray = searchArray; // assume this has 100 or more postalcodes init
var shortArrays = [], i, len;
for (i = 0, len = longArray.length; i < len; i += 100) {
shortArrays.push(longArray.slice(i, i + 100));
}
// Now we iterate over shortArrays which is an array of arrays where each array has 100 or fewer
// of the original postalcodes in it
for (i = 0, len = shortArrays.length; i < len; i++) {
// shortArrays[i] is an array of postalcodes of 100 or less
$.each(shortArrays[i], function(index, value){
setTimeout( function() {
// Each parent gets its own searchToggle class
$('.postcodes input[data-postcode*="' + value + '"]').parent().parent().addClass('searchToggle');
// Each parent also gets a data filter attribute for ordering the results
$('.postcodes input[data-postcode*="' + value + '"]').parent().parent().attr('data-filter' , index);
// We display the items in the search array
$('.postcodes input[data-postcode*="' + value + '"]').parent().parent().css('display', 'flex');
$('.postcodes .searchToggle .postcode input[data-postcode*="' + value + '"]').parent().css('display', 'flex');
}, 0 );
})
} // /for
alert('Finished message');
});
I try to show an alert message(for debugging) once the $.each() is finished. Since this each goes through an array that could be 1000s of postal codes long I broke it up in chunks of 100. This to prevent the dreaded browser is unresponsive. This is all working fine but the alert fires immediately on click.
I have tried several things already:
I tried by using a count: ABOVE THE EACH var count = 0; INSIDE THE EACH count++ if ( count == longArray.length ) { ALERT } But this also fired the alert immediately???
I tried it by using an interval but that became a mess almost instantly.
I tried a couple of other SO answers but all of them resulted in the alert to fire immediately.
When looking through the jQuery docs and previous codes that I have written it should just run the code after the each is finished but in this case it does not.
Any idea on why this is and how I can fix it.
PS: This alert could be other codes! Like sorting the results or something else.
PS2: I can change all the js/jQuery you see but I cannot change any of the HTML selectors.
PS3: Thank you for thinking about this issue and especially for commenting/answering!
I have solved it by adding another setTimeout.
So I replaced the alert (see Question) from
alert(Finished message);
To
setTimeout( function() {
// As an example I used alert in my question and here in this answer.
// This can be offcourse anything else. I use it for instance to sort the results.
alert(Finished message);
}, 0 );
This works for me, but it might not be the best way to deal with it. So I am still looking forward to what more experienced people think about the question or the answer.

Array values are not being read correctly inside gameloop

Im creating a program that displays random dots on a canvas, but I am running into problems when I give it rules specifying which dots are supposed to stay lit. I created a canvas with a matching array so for X number of pixels exist an object inside a 2D array. The array is created as follows:
<code>
//create array
ctx.grid = []
for (var i = 0; i < canvasSize; i++) {
ctx.grid.push([]);
for (var e = 0; e < canvasSize; e++) {
ctx.grid[i].push({light:false, clean:true})
}
}
</code>
The gameloop starts creates a random number from 0 to canvasSize*canvasSize
then maques a divicion to filter this number and get an exact location on my array ctx.grid and sets the light property to true.
the following loop finds all the objects in the array that have the property light set to true and draws a square on the canvas by calling the drawPoint() function.
<code>
setInterval(gameLoop,10);
function gameLoop() {
//Get a random number from 0 to canvasSize
var light = Math.floor(Math.random()*(canvasSize*canvasSize));
var row = parseInt(light/canvasSize);
var col = light%canvasSize;
ctx.grid[row][col].light = true;
//Find which points need to be drawn
for (var i = 0; i < ctx.grid.length; i++) {
for (var e = 0; e < ctx.grid[i].length; e++) {
if (ctx.grid[i][e].light) {
drawPoint(i,e);
findCorner(i,e);
clearPoint(i,e);
}
}
}
}
</code>
I have not included all the program's code because they are not essential to solving this problem.
Next is the beginning of what is supposed to be a set of rules,specified by findCorner(), that tell the program when some specific points are supposed to remain drawn on the canvas.
<code>
function findCorner(y,x) {
//Avoid corners
if (y != 0 || x != 0 || y != canvasSize || x != canvasSize) {
if (ctx.grid[y-1][x].light) { //Cannot read property '9' of undefined
//another set of rules
}
// console.log(ctx.grid);
// console.log(y);
// console.log(x);
// console.log(ctx.grid[y-1][x]);
</code>
When I run the program without the findCorners() function, it runs smoothly meaning my array is set up all right, but it is that if statement that is giving me problems. On the developer tools I get the following error:
Cannot read property '9' of undefined
This appears on the line I commented on my code, and the 'number' is always different.
I added the last console logs on my code because strangely enough when I run my program with those lines, the program runs without any errors though it does run very slowly and makes my browser crash after a while.
So it turns out I was wrong in my other comment.
The non-detection of edges was causing you to index into unset parts of your array causing those weird messages and was all of your problems
I scaled it back a bit to look at it
see https://jsfiddle.net/goujdwog/2/
the important thing to get from that is fixing the check at the start of findCorners():
if (y > 0 && x > 0 && y < canvasSize -1 && x < canvasSize -1)

For Loop Behaviour

This question is regarding Javascript for loops, where I've been having some weird behaviour.
My For loop currently looks like this:
var UnitAmount = 2;//(value verified, yet not declared like this)
var DamageAmount = [1,3];//(value verified, yet not declared like this)
function forcerefresh () {
for( i=0 ; i < UnitAmount ; i++ ) {
//(10 lines of Stuff)
var check = 0;
for (c = 0; c < DamageAmount[i] ; c++ ) {
debug[0] = damage[i][c].getElementsByClassName("writedamage")[0];
debug[1] = damage[i][c];
debug[2] = unit[i];
check = check + 1;
console.info("Unit:",i,"Loop:",c,"Debug:",debug,"Check:",check, "Race:",unitrace[i], unit[i].dataset.race);
alert("Debug:"+ debug );
damageCalc(damage[i][c].getElementsByClassName("writedamage")[0],damage[i][c],unit[i]);
}
}
}
In here, debug, alert, Check and the console write call are already added to attempt to find the problem - I'm getting an infinite loop here.
The output im getting in the console shows that while the i constant walks as intended, but the c Iteration count starts at 0, jumps to 2, and then stays 2 - and since the DamageAmount[1] = 3, this creates an infinite loop. And where the c might stick at value 2, the check values does walk up through the iterations.
As for the amount of variables involved, I've checked time and again with the console, and all of them are defined, and the values I expected. The Code is located at http://age-of-wonders-3.wikia.com/wiki/MediaWiki:Units.js, but if any parts are requested I'll of course post them here.
Any help is appreciated!
Try using for of or .forEach on an array

Simple arithmetic challenge function with limited attempts

Recently began studying Javascript, trying to read out of Javascript: The Definitive Guide and Eloquent Javascript, while going off on my own to experiment with things in order to really etch them in my memory. I thought a good way to get my head around arithmetic operations and conditional statements, I'd build a series of little games based around each Math operator, and began with addition.
function beginAdditionChallenge() {
var x = Math.ceiling(Math.random()*100);
alert(x);
for (var i = 0; i < 3; i++) {
var a = Number(prompt("Provide the first addend.", ""));
var b = Number(prompt("Provide the second addend.", ""));
if (a + b === x) {
alert("Well done!");
break;
}
else if (a + b !== x && i < 3) {
alert("Please try again.");
}
else {
alert("Fail.");
}
}
}
function initChallenge() {
var button = document.getElementById("challengeButton");
button.addEventListener("click", beginAdditionChallenge);
}
window.addEventListener("load", initChallenge);
You can see the whole thing thus far on JSFiddle, here. The idea is that clicking the button generates a random number between 1 and 100, displays it to the user, then prompts them to provide two addends, giving them 3 attempts. If the sum of these addends is equal to the RNG number, it congratulates the user and ends the program. If they do not provide suitable addends, the loop prompts them to try again, until they've hit 3 attempts, at which point the program snarks at them and ends.
I know the event listener is not the failure point here, as when I change beginAdditionChallenge to simply display a test alert, it works, but I don't know what exactly is wrong with the loop I've created.
You did it correctly. However, Math.ceiling isn't a function and should be Math.ceil. In addition, your code (in jsfiddle) should be set to wrap in head. Why? Because right now you call initChallenge when the page loads. However, in your jsfiddle example, the code runs onLoad so the load event never gets called. Essentially, you're adding a load event after the page has loaded.
http://jsfiddle.net/rNn32/
Edit: In addition, you have a for loop that goes up to three. Therefore
else if (a + b !== x && i < 3) {
alert("Please try again.");
}
should be
else if (a + b !== x && i < 2) {
alert("Please try again.");
}
because when i === 2, the user's last chance has ended.
Everything is fine. Just change:-
var x = Math.ceiling(Math.random()*100);
to:-
var x = Math.ceil(Math.random()*100);

Javascript, loops infinitely and freezes

So I'm making a simple physics simulation using HTML5 canvas and javascript. I'm trying to make some realistic collisions, but whenever a collision occurs the code begins to loop infinitely and freezes the page.
I am using Google Chrome 24.0.1312.32 beta-m
When looking at the javascript console the line "console.log("I am colliding with something")" goes crazy and is printed thousands of times per second and completely breaks the page.
I'm not really sure why its' happening and I have no idea what to do. Any help and/or input would really be appreciated.
for (i = 0; i <= 3; i++) {
if (collide(i)) {
console.log("I am colliding with something");
if (typeof getCollideIndx === 'undefined') {
console.log("collide index is not undefined");
if (!getCollideIndx(i)) {
console.log("Made it past null check");
//...update object based on collision
the collide() function is:
function collide(b) {
for (i = 0; i <= 3; i++) {
//Distance between each object
var distance = (Math.sqrt(Math.pow((balls[b].x - balls[i].x), 2) + Math.pow(balls[b].y - balls[i].y, 2)));
if (distance < 32) {
//must be less than 2*radius -- all radii are the same
//makes it so that it doesn't return true when checking its own index
if (!(balls[b].mass == balls[i].mass)) {
return true;
} else {
return false;
}
}
}
}
I cannot see an infinite loop in your code , my best guess would be this statement
if (typeof getCollideIndx === 'undefined')
fails every time and whatever function the below code is in is called continuously
for (i = 0; i <= 3; i++) {
if (collide(i)) {
console.log("I am colliding with something");
if (typeof getCollideIndx === 'undefined') {
console.log("collide index is not undefined");
if (!getCollideIndx(i)) {
console.log("Made it past null check");
//...update object based on collision
also in this , I do not see the point of the for loop as the control always goes back to the calling function (in the collide() function)
Well, being trapped in that for loop implies that the index variable i is getting set incorrectly somewhere. Without being able to see the entirety of the code I cannot say for sure, but the loop for(i=0; i<3; i++){... will be assigning i to the window object because you have not explicitly scoped it (i.e. for(var i...).
See for example this jsfiddle where the first function will only run once rather than three times because the same variable i is affected in the second function.
Obviously running once != infinite loop, but if the collide function does something to i (or maybe breaks after it finds a collision?) then the value of i will be reset to 0 at the beginning of its for loop each time it's called.
So yeah without some more code I can't say for sure; but my advice in this case is: always use var in for loops or weird things can happen!

Categories

Resources