Javascript delete does not removed the desired property - javascript

I am using nodejs to create a game. It happens that this time I am not able to use Delete. It is not working and I have no idea why.
I execute this line:
delete Bullet.list[i]
And Bullet.list is an object with properties and after executing this line, the desired property is not removed.
Here is my code (you can see the above line of code in context here below):
var Map = require("./Map.js")
var Player = require("./Player.js");
var Bullet = require("./Bullet.js");
var Fly = require("./Fly.js");
var Settings = require("./Settings.js");
var Simulation = function(SOCKET_LIST){
//Update Bullets
for(var i in Bullet.list){
var bullet = Bullet.list[i];
bullet.update();
var shooter = Player.list[bullet.parent];
//Bullets collide with flies
for(var i in Fly.list){
var fly = Fly.list[i];
if(!bullet.toRemove && bullet.getDistance(fly) < 15){
if(shooter){
shooter.updateCoins(fly.killCoins);
shooter.updateXp(fly.killXp);
}
bullet.toRemove = true;
fly.toRemove = true;
}
}
//Collide with player
for(var i in Player.list){
var player = Player.list[i];
if(player.death) continue;
if(!bullet.toRemove && bullet.getDistance(player) < 32 && shooter !== player.id && shooter.team != player.team && !player.immune){
player.hp -= 1;
player.hpChanged = true;
if(player.hp <= 0){
if(shooter)
player.kill(shooter);
else
player.kill();
}
bullet.toRemove = true;
}
}
//Collide with map
if(typeof shooter == "undefined" || shooter.shootsCollideMap && Map.isColliding(bullet))
bullet.toRemove = true;
//Remove bullets
if(bullet.toRemove){
delete Bullet.list[i]; /*HERE IS THE PROBLEM. THE PROPERTY IS NOT BEING DELETED*/
Bullet.removePack.push[bullet.id];
}
}
I am not able to delete the property "i" from the object Bullet.list.

Your three for loops are all sharing the same variable i and thus you aren't deleting the i index you want to. This is because var i is function scoped, not scoped to the individual for loop.
When you do this:
delete Bullet.list[i];
The value of i is whatever i is after your previous for loop and probably not the item you actually want to delete. Perhaps you mean to break out of the for loop previously so that i will be a specific item you want to remove?
Or you need to separately save to another variable an index of an item that you want to remove. Or, just remove an item inside the for loop when the value of i is current.
Remember that var is function scoped. So both your var i declarations in your two nested for loops are actually referencing the exact same variable, not declaring a new one. I would recommend changing the name of the loop index in one of the two loops to be a separate variable.
If you are running in an environment where let is fully supported, you could use let i instead of var i and then the value of i would be uniquely scoped to only the for loop in which it was declared.

When you delete an array element, the array length is not affected. This holds even if you delete the last element of the array.
You could try Bullet.list.splice(i, 1) as an alternative to delete.
There is a lot going on in this code,, hope this helps!

Related

How to grab an objects property that is stored in an array on a click event

I have this Object and I spawn it onto the canvas after one is picked and pushed into my array.
function grabObjProp(){
var randomInt = Math.floor(Math.random() * 10) + 1;
goodProp = {};
goodProp["name"] = "goodguy";
goodProp["MC"] = new lib.goodObj();
badProp = {};
badProp["name"] = "badguy";
badProp["MC"] = new lib.badObj();
if(randomInt < 7)
ObjArray.push(goodProp);
else
ObjArray.push(badProp);
createObj();
}
I then run an if/else to see if I am clicking the good or the bad and based off that I then either run a gameOver function or I continue the game. My current issue is that my if/else checks the last array that was added and if I badguy is added when I click a goodguy the condition is met and the game ends. I wanted to know how to get the name of the object I clicked store it to a variable then compare that variable when I click and object.
function Click(e){
if(ObjArray[ObjArray.length - 1].name != "goodguy"){
addGameOverScreen();
}else{
numClicked +=1;
scoreTxt.text = numClicked;
exportRoot.removeChild(e.currentTarget);
grabObjProp();
//}
}
Edit** added -1 to if(ObjArray[ObjArray.length].name != "goodguy")so that the if was always check the last index of the array.

Javascript recursion for tree creation

i am trying to create funcion for creating decision tree with state of game in every node in game (doesnt matter what game). I wrote recursive function (DFS) like this:
function makeTree(anchor,count,player){
var subTree=null;
var nodes=[];
if(player)var newPlayer=false;
else var newPlayer=true;
for (var i = 0; i <= 9; i++) {
for (var j = 0; j <= 9; j++) {
if(anchor["state"][i][j]==0){
var newState=anchor["state"];
if(player)newState[i][j]=1;
else newState[i][j]=2;
var node={name:i+"_"+j, contents:[],state:newState, value:null, player:newPlayer};
if(count>0){
var newCount=count-1;
subTree=makeTree(node,newCount,newPlayer);
node["contents"]=subTree;
}
nodes.push(node);
}else{
continue;
}
}
}
return nodes;
}
And with call:
var tree={};
var hrac=true;
var plocha=[[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0]];
var state=plocha;
tree={name: "root",
contents:[],
state:state,
value:null,
player: hrac};
tree["contents"]=makeTree(tree,3,hrac);
But the function change variables in different scope, so the output tree will be like this:
"root" - node - node - node
- node
- node
- node
- node
I cant figure out what is going on with variable newState in that function, because after finish the recursion the original variable plocha has the value of the latest node["state"]. Any suggestions what to do?
EDIT: Thanks to Bergi i realize that i need to do deep copy of array insted of make reference to it, so i make funcion for copy of array and now this works. Thank you Bergi!
Your state property is an array, which is mutable. On every assignment, you change the one multidimensional array that is the state of all nodes. You'll want to make every newState a new array, instead of passing your plocha reference recursively through all functions:
…
var newState = anchor["state"].slice(); // create copy of the outer array
newState[i] = newState[i].slice(); // copy of the row to be modified
newState[i][j] = player ? 1 : 2;
…

Nested 'for' loop - array undefined

I am working on a JS where I want to create a simple game that starts by chosing number of players, name of each player and whether a player is a dealer or not. There can be only one dealer for each game:
function player(playerName, playerDealer) {
this.playerName = playerName;
this.playerDealer = playerDealer;
}
var playerNumber = prompt('Nr of players?');
var playersArray = [];
for (i = 0; i < playerNumber; i++) {
var j = i + 1;
var dealerAssigned = false; // control variable to check whether dealer has been assigned
var inputName = prompt('Name of player nr ' + j);
var inputDealer = prompt('Is player ' + inputName + ' also a dealer? (yes/no)');
playersArray[i] = new player(inputName, inputDealer);
for (k=0;k<playerNumber;k++){ // I want to go through the players array to check if dealer has been assigned
if (playersArray[k].playerDealer == 'yes') {
dealerAssigned=true;
break;
};
};
if(dealerAssigned){ //if dealer has been assigned, don't add the current player to the array and continue with the next iteration
alert("already assigned");
continue;
};
};
I need to include a simple test into the loop that would check if the dealer has been appointed. If so, I want the script only to alert 'already assigned' and skip to the next player. But I am constantly getting the following error
TypeError: playersArray[k] is undefined
Can anybody explain why is it undefined?/What am I doing wrong?
The bug you're specifically asking about appears to me to be that you're iterating over undefined array values, as the error you're getting suggests.
You're getting the number of players you want in line
var playerNumber = prompt('Nr of players?');
Then, you proceed to have two iterations (one nested in the other), in which the inner loop is trying to access values that haven't yet been assigned since the outer loop hasn't gotten there yet:
for (i = 0; i < playerNumber; i++) {
playersArray[i] = new player(inputName, inputDealer);
for (k=0; k < playerNumber; k++) {
if (playersArray[k].playerDealer == 'yes') {
...
}
}
}
It appears to me that the logical error here is the nested loop. I recommend just initializing all players in one loop, then verify that all players have an assigned dealer afterward.
I should add that I'm being intentionally myopic here and focusing very narrowly on the question asked and overlooking other issues I see.
Your for loop inside a for loop is iterating over an array that hasn't been filled yet.
First iteration playersArray[j] = new Player(...) makes the array [Player] or an array of one element! Yet the second loop is looking for an array of many elements. once you look for playersArray[1] but there is only playerArray[0] you get undefined and so undefined.playerDealer causes a TypeError.
`This is your structure stipped-down:
for (i = 0; i < playerNumber; i++) {
playersArray[i] = new player(inputName, inputDealer);
for (k=0;k<playerNumber;k++)...{
//anything with index k > i is undefined, since your outer loop
//hasn't initialized it yet.
}
}
It seems that your i-loop is trying to insert elements for the size of the array to be, but your k-loop is trying to also access the entire array instead of just the initialized portions. Limit this to for (k=0; k<i+1 ;k++) so you only check the previously initialized values of you playersArray

delete specific xml node Javascript

My xml file is like:
it contains different 'object' nodes and in different objects there are different parameters one is deleted parameter.
I want to delete the all 'object' nodes that contains the deleted parameter 1.
This is the code that deletes the node object which has a parameter node deleted =1:
x=xmlDoc.documentElement;
for(var count=0; count<5;count++){
var y=x.getElementsByTagName("deleted")[count]; //Find that nodes arent
if(y.textContent == "1") {
var z=y.parentNode; //delete the node from the parent.
x.removeChild(z);
Xml2String1= new XMLSerializer().serializeToString(x);
}
}
Your loop is incorrect:
for(var x1=0; x1<5;x1++){
var y=x.getElementsByTagName("deleted")[x1];
Your loop runs for 5 iterations without regard for the number of <deleted> elements are found. Each time through the loop you search again and get a new NodeList/HTMLCollection of the remaining <deleted> elements, but your loop counter is incremented regardless.
Try this instead:
var deletedNodesList = x.getElementsByTagName("deleted");
var nodesToDelete = [];
for (var index = 0; index < deletedNodes.length ; index += 1)
{
var node = deletedNodes[index];
if (node.textContent == "1")
{
nodesToDelete.push( node.parentNode ); //delete the node from the parent
}
}
nodesToDelete.forEach( function() { x.removeChild(this); } );
Note that, per the documentation on MDN, the NodeList is a live collection, so don't modify it while you are processing it.
PS.
I second raam86's recommendation to use sane (meaningful) variable names. Meaningful variable names make it easier to understand the code, which makes it easier to write correct code and to resolve problems in incorrect code.

Getting rid of two elements in an array at the same time

So I'm designing a game in JavaScript, and I'm having some trouble with the way things are removed relating to my collision detection function.
It's Asteroids, so some of the objects are named accordingly.
My collision detection function is designed to check if there are collisions between the player and an asteroid, or a bullet and an asteroid. In the case of a bullet and an asteroid, one would expect both the bullet and the asteroid to disappear.
However, given how I'm checking for collisions, removing both the bullet and the asteroid it's collided with seems to be a challenge. Here is my relevant code:
for (var i=0;i<$_.mapObjs.length;i++) { //get one object to check
var superBox = $_.mapObjs[i].hitBox; //get it's properties
var objectName = $_.mapObjs[i].name;
var isAsteroid =(objectName.indexOf("asteroid") == -1)?false:true; //is the object an asteroid?
for (var y=0;y<$_.mapObjs.length;y++) { //get the object to check it against
if (objectName !== $_.mapObjs[y].name) { //if we are not checking the object against its self
var subName = $_.mapObjs[y].name;
var subIsAsteroid = (subName.indexOf("asteroid") == -1)?false:true; //is the second object an asteroid?
if (!(isAsteroid) || !(subIsAsteroid)) { //if we are not checking two asteroids against each other
var subBox = $_.mapObjs[y].hitBox;
var collision = rectIntersectsRect(superBox,subBox); //check for a collision using rectIntersectsRect
if (collision) { //if there is a collision
if ((objectName == "player" && subIsAsteroid) || (isAsteroid && subName == "player")) { //if either of the objects are the player, then the player dies
if (!player.invincible)
player.death();
} else if ((objectName == "blankObject" && subIsAsteroid) || (isAsteroid && subName == "blankObject")) { //if either of the objects are a bullet, then we destroy the asteroid
Console.log(i + "," + y); //this is the problem area
Console.log("getting rid of " + objects[i].name + " and " + objects[y].name);
if (subIsAsteroid) { //splice the asteroid out of the second array
objects.splice(y,1);
} else { //splice the asteroid out of the first array
objects.splice(i,1);
}
}
}
}
}
}
}
Now, because I need both the asteroid and bullet to dissapear when they collide, I change
if (subIsAsteroid) {
objects.splice(y,1);
} else {
objects.splice(i,1);
}
to
objects.splice(y,1);
objects.splice(i,1);
but then, whenever there is a collision, the function randomly deletes two objects off the array, even though the positions of both y and i refer to the bullet and asteroid objects. What am i doing wrong?
.splice() doesn't just remove random elements, but after the .splice(y,1) operation removes one element the indexes of all the elements after y will be one less than before - all of these later elements "move up". So if i is greater than y it will no longer refer to the element you want it to.
If you remove whichever element has a higher index first it should be fine:
objects.splice(Math.max(y,i), 1);
objects.splice(Math.min(y,i), 1);
Having said that, I can't tell from your code what the relationship between $_.mapObjs and objects is but I think it might cause problems. You have nested loops iterating over $_.mapObjs with y and i as loop indexes, but then you remove elements from objects based on the y and i indexes from $_.mapObjs. Do these two arrays have the same elements in the same order? This could explain your "random" element removal. Should you be splicing out of $_.mapObjs? If so, you'd need to adjust y and i after the removal so that you don't skip elements on the next loop iteration.
This is probably because when you splice the first index, your array changes. This means that the second index may or may not be correct; because the indices of the elements have changed. I'd recommend you to do something like this:
objects[y] = null;
objects[i] = null;
while( (remIndex = objects.indexOf(null)) !== -1 ){
objects.splice(remIndex, 1);
}
Demo

Categories

Resources