Javascript stop repeating collision detection in canvas - javascript

I'm trying to do some simple collisions in javascript and html5 canvas. So far I have this:
checkCollision = (function(){
var l, i, ni,dis = 0;
var ob1,ob2 = {};
return function(){
//collisions is the array holding all the objects
l = collisions.length;
i = 0;
ni = 1;
while(i<l){
//grab the first object
ob1 = collisions[i];
while(ni<l){
//get the object to check against
ob2 = collisions[ni];
//find the distance between the two
dis = Math.sqrt(Math.pow((ob1.pos[0]-ob2.pos[0]),2)+Math.pow((ob1.pos[1]-ob2.pos[1]),2));
//rad is the radius
if(ob1.rad+ob2.rad >= dis){
console.log("collision")
}
//move forward second increment
ni++;
}
i++;
//keep one place ahead
ni=i+1;
}
};
})();
I did it without any help of any kind, but now I guess my brain is too much mush to figure this last part out. The collision is happening every frame, which I don't want. I just want it to fire once when the collision first happens. I've tried by giving each object a collide variable that's true if there's already a collision but it's not working very well. Some it fires once and some it fires constantly.
Does anyone have any pointers?

What do you mean by "happening every frame"? The algorithm seems ok, but there doesn't seem to be any conesquence from the collision, it is just logged. Do you want to break out of the loop?
Some comments that have nothing to do with your issue but might make your code a bit more readable and concise:
> checkCollision = (function(){
> var l, i, ni,dis = 0;
> var ob1,ob2 = {};
I don't know why you initialise dis and ob2, they are assigned values later. Using a closure like this means that the values persist to subesquent calls until new values are assigned. Is the closure really needed? It may be a performance hit for animations like this.
> ni = 1;
> while(i<l){
You can put ni after the while, like this:
while(i < l){
ni = i + 1;
and get rid of the last ni = i + 1. You can also do:
> ob1 = collisions[i++];
and get rid of the last i++;, an do the same for ni when assigning to ob2.
Doing the above reduces the number of lines of code so it is more digestable, e.g.
function checkCollision() {
var ni, dis, ob1, ob2;
//collisions is the array holding all the objects
var l = collisions.length;
var i = 0;
while (i < l) {
ni = i + 1;
//grab the first object
ob1 = collisions[i++];
while (ni < l) {
//get the object to check against
ob2 = collisions[ni++];
//find the distance between the two
dis = Math.sqrt(Math.pow((ob1.pos[0] - ob2.pos[0]), 2) +
Math.pow((ob1.pos[1] - ob2.pos[1]), 2));
//rad is the radius
if (ob1.rad + ob2.rad >= dis) {
console.log("collision");
// And what else?
}
}
}
}

Related

faild to move the element in between?

i have been try to solve the sudoku with Blacktracking algo, everything is good, canvar is called and i able to see the number but the things is number are not moving i.e the logic is not exectuing
current.i === 0; is where i'm get the error! even i have declared a sperate variable for the num also the problem is not sloved. only if i remove the .num current == 0 than its not showing any error but still the number is not moving
enter image description here
var cell = [];
var stack = [];
var sudoku = [2,3,0,9,4,0,6,7,0,
8,0,0,3,2,5,9,1,4,
9,0,0,7,6,0,3,2,0,
1,0,0,0,0,0,7,9,2,
5,0,3,2,1,0,4,8,6,
4,0,0,6,8,0,5,3,1,
7,0,0,1,0,0,0,0,9,
6,5,9,8,7,2,1,4,3,
3,0,0,0,9,0,0,0,7];
var current;
var number = 1;
function setup(){
createCanvas(450,450);
var a=0;
var b=0;
for(var i=0;i<81;i++){
if(a%9==0 && i!=0){
b = b+50;
a = 0;
}
each[i] = new each(a,b,i,sudoku[i]);
a = a+50;
}
current = cell[0];
}
function draw(){
background(10);
for(var i=0;i<81;i++){
each[i].show();
}
if(current.num === 0){ //the error is typeerror can't read the property of num
if(! sameColumn(current.i,number) && ! sameRow(current.i,number) && ! sameSquare(current.i,number) && number<(10)){
current.num = number;
stack.push(current);
number = 0;
current.each[current.i+1];
}
else {
if(number > 8){
current.num = 0;
current = stack.pop();
number = current.num;
current.num = 0;
}
}
}
else{
current = each[current+1];
number = 0;
}
number++;
}
function each(a,b,i,num){
this.a = a;
this.b = b;
this.i = i;
this.num = num;
this.show = function(){
noFill();
stroke(255);
rect(this.a,this.b,50,50);
textSize(32);
text(this.num,a+12,b+40);
}
}
The error is pretty much straight forward. current = cell[0]; becomes undefined since you defined cell as an empty array and didn't manipulated it after that.
From what I have observed so far, many parts of your code logically does not work, for example,
same Column(current.i,number) && ! sameRow(current.i,number) && ! sameSquare(current.i,number)
will definitely throw you an error is it is executed (it is not since the execution does not reach to that line), unless you have a separate js file that contains these functions.
Another one is
current = cell[current+1];
if the current variable is to store the cell object, it does not make sense to add 1 to it, and vice versa.
Now I believe this is how setup function was meant to look like:
function setup(){
createCanvas(450,450);
var a=0;
var b=0;
for(var i=0;i<81;i++){
if(a%9==0 && i!=0){
b = b+50;
a = 0;
}
cell[i] = new Cell(a,b,i,sudoku[i]); //changed each[i] to cell[i], also renamed the 'each' class
a = a+50;
}
current = cell[0];
}
If possible, please edit in a little more information about what exactly does your code do. Cheers :)

Evaluating Terminating Condition

I am learning javascript to enhance some of my daily work, and so I am learning the basics.
I am still pretty green with the syntax, but am picking up on the language pretty quickly.
What I am trying to understand is how i can create a terminating condition that is evaluating a function.
I know the coding is wrong here, which is what I am trying to fix - I attempted a bunch of different things, but I am having trouble evaluating the loop based on my product.
I tried using return to store the value each iteration, but every attempt resulted in the script flat out failing.
What I want the script to do is to stop the loop when my product reaches <=100.
The problem is, my research suggests that the loop criteria can ONLY be referencing the variable, i.
I'm stuck in terms of how to look at the resulting product as the terminating condition.
var one = 5;
var two = 10;
var end = 100;
function mult (one, two) {
var product = one * two;
document.writeln(product + "<br>");
}
for (var i = 1; i <= end; i++)
mult(i, two);
If you want your loop to terminate when the product is <= 100, use an if statement to decide whether you want to write a line.
I've changed some variable names to make it easier to understand.
/*var one = 5;*/ /*This is never being used*/
var ten = 10;
var end = 100;
function mult (a, b){
var product = a * b;
if (product <= 100){
document.writeln(product + "<br>");
}
}
for (var i = 1; i <= end; i++){
mult(i, ten);
}
"the loop criteria can ONLY be referencing the variable, i." that's false!
You can define multiple conditions in a for loop.
To access the 'product' variable after loop execution you can declare it in the outer scope of the mult() function (or you can rewrite the mult() function to returns the product variable).
Like this:
var two = 10;
var end = 100;
var someNumberGtThan100 = 100000;
var lastProduct = 0;
var product = 0;
function mult (one, two) {
lastProduct = product;
product = one * two;
document.writeln(product + "<br>");
}
for (var i = 1; i <= someNumberGtThan100 && product <= 100; i++) {
mult(i, two);
}
console.log(lastProduct); // 100
By using this condition you have to store the previous value in an auxiliary variable, because when 'product' reach the value of 100 the loop condition is still true, so the loop will be executed one time more.

Blackjack javascript game infinite loop

I have created an utterly simple blackjack game that stores the first value of a shuffled array of cards into corresponding players' arrays, dealing them as actual hands. For some odd reason, I can't seem to find a way to execute the core part of the code multiple times without getting an infinite loop. For the time being, I have only tried running the quite commonplace "for" command which is meant for multiple statements, but just doesn't seem to work here.
The programm on its primitive form is as follows...
var dealerCards = [];
var playerCards = [];
var firstDeck = [];
function shuffle(o){
for(var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
return o;
}
function createShuffledDeckNumber(array, x) {
for (i = 0; i < 4*x; i++) {
array.push(1,2,3,4,5,6,7,8,9,10,11,12,13);
}
shuffle(array);
}
function drawCard(playersHand, playerSoft, playerHard) {
playersHand.push(firstDeck[0]);
firstDeck.shift();
}
function checkDeckDrawOne(playersHand) {
if (firstDeck.length === 0) {
createShuffledDeckNumber(firstDeck, 1);
drawCard(playersHand);
}else{
for (i = 0; i < 1; i++) {
drawCard(playersHand);
}
}
}
for (i = 0; i < 4; i++) {
dealerCards = [];
playerCards = [];
checkDeckDrawOne(dealerCards);
checkDeckDrawOne(dealerCards);
checkDeckDrawOne(playerCards);
checkDeckDrawOne(playerCards);
console.log("dealerCards",dealerCards,"playerCards",playerCards);
console.log("firstDeckDrawn", firstDeck, "Number", firstDeck.length);
}
Additional Notes;
The presumed objective could be performing calculations to figure out the winner by imitating the effect of consecutive computing rounds based on a finite number of values stored in each player's array. Although, I've tried a seried of different things when it comes to emulating the real life circumstances of actually playing blackjack, this version seems to do just that, by also giving the programmer the ability to introduce counting systems like KO or HiLo. The main logic behind the whole thing is fairly simple; order x shuffled decks whenever a command that involves drawing a card is being executed unless the deck has at least one card.
It's rather fair to ponder why should I possibly bother creating multiple rounds in such a game. Reason is, that I want to create an autoplayer application that provides me with percentages on processed data.
Your variable i in function checkDeckDrawOne() has global scope, meaning it alters the value of i in the main loop:
for (i = 0; i < 4; i++) {
dealerCards = [];
playerCards = [];
checkDeckDrawOne(dealerCards);
checkDeckDrawOne(dealerCards);
checkDeckDrawOne(playerCards);
checkDeckDrawOne(playerCards);
console.log("dealerCards",dealerCards,"playerCards",playerCards);
console.log("firstDeckDrawn", firstDeck, "Number", firstDeck.length);
}
Change this:
for (i = 0; i < 1; i++) {
drawCard(playersHand);
}
to this:
for (var i = 0; i < 1; i++) {
drawCard(playersHand);
}
although why you need a loop here anyway is baffling.

JS crashes sometimes with Timer scramble

My Javascript timer is for people with a rubiks cube with generates a scramble (nevermind all this, but just to tell you I'm generating after each solve a new scramble will be generated) and my scrambles do actually have a while (true) statement. So that does crash my script, but it 95/100 times stops just before the script crashes but I don't wanna have any times.
Let me explain a bit more detailed about the problem.
Problem: javascript crashes because my script takes too long to generate a scramble.
Below you have 3 functions I use.
This function generates a scramble with the Fisher-Yates shuffle.
Timer.prototype.generateScramble = function(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
};
This function validates the input e.g. I receive an array as the following:
Here I only have to check the first character. That's why I use the seconds [ ] notation. I don't want people get an F with an F2 e.g.
var scr = ["F","R","U","B","L","D","F2","R2","U2","B2","L2","D2","F'","R'","U'","B'","L'","D'"]
Timer.prototype.validateScramble2 = function(array) {
var last = array.length-1;
for (var i = 0; i < array.length-1; i++) {
if (array[i][0] == array[i+1][0]) {
return false;
}
}
for (var i = 0; i < array.length-2; i++) {
if (array[i][0] == array[i+2][0]) {
return false;
}
}
if (array[0][0] == [last][0]) {
return false;
}
return true;
};
The above functions are just waiting to be called. Well in the function below I use them.
Timer.prototype.updateScramble2 = function(scrambleArr, len, type) {
var self = this;
var scramble = '', j, updatedArr = [];
while (updatedArr.length < len) {
j = (Math.floor(Math.random() * scrambleArr.length));
updatedArr.push(scrambleArr[j]);
}
while (!self.validateScramble2(updatedArr)) {
updatedArr = self.generateScramble(updatedArr);
}
for (var i = 0; i < updatedArr.length; i++) {
scramble += updatedArr[i] + ' ';
}
scrambleDiv.innerHTML = scramble;
};
I assume you guys understand it but let me explain it briefly.
The first while-loop adds a random value from the given array(scrambleArr) into a new array called updatedArr.
The next while-loop calls the validateScramble2() function if there isn't in an array F next to an F2.
The for-loop adds them into a new variable added with a whitespace and then later we show the scramble in the div: scrambleDiv.innerHTML = scramble;
What do I need know after all this information?
Well I wanna know why my updateScramble2() functions lets my browser crash every time and what I do wrong and how I should do it.
I'm not entirely sure I understand the question, but from the way your code looks, I think you have an infinite loop going on. It appears as if validateScramble2 always returns false which causes your second loop in updateScramble2 to perpetually run.
I suggest you insert a breakpoint in your code and inspect the values. You could also insert debugger; statements in your code, works the same way. Open dev tools prior to doing these.
A suggestion is instead of using loops, use a timer. This breaks up your loop into asynchronous iterations rather than synchronous. This allows the browser breathing space for other operations. Here's an example of a forEachAsync:
function forEachAsync(array, callback){
var i = 0;
var timer = setInterval(function(){
callback.call(null, array[i]);
if(++i >= array.length) clearInterval(timer);
}, 0);
}
forEachAsync([1,2,4], function(item){
console.log(item);
});
You can take this further and use Promises instead of callbacks.

access object variable from method javascript

i have a problem accessing an array within an object method.
While the log returns the value perfectly, the following line returns an error that allRect[n] is undefined.
I suppose it has something to do with variable accessibility, but the fact that it can be logged in one line and refuses it's existence in the next one leaves me a bit out of ideas.
Thanks all.
this.s = Snap('#'+id);
var allRects = [];
this.xPos = 0;
var scale = vizWidth/locationSum(data);
...
//methods
this.updateViz = function() {
apiRequest('datasets', 164, 'json').done(
function(data){
var n = 0;
data = locationDataIntoArray(data);
for(i = 0; i< allRects.length; i++){
console.log(allRects[n]);
allRects[n].animate({ width:parseInt(data[i][2]), opacity:evaluateMachine(data[i][0])},3000);
n++;
allRects[n].animate({ width:parseInt(data[i][3]), opacity:evaluateTech(data[i][1])},3000);
n++;
}
}
)
};
In this code:
for(i = 0; i< allRects.length; i++){
console.log(allRects[n]);
allRects[n].animate({ width:parseInt(data[i][2]), opacity:evaluateMachine(data[i][0])},3000);
n++;
allRects[n].animate({ width:parseInt(data[i][3]), opacity:evaluateTech(data[i][1])},3000);
n++;
}
you're incrementing n twice on each iteration. Halfway through the for loop, n will be beyond the end of the array.
The first time through the loop, when i and n are both zero, you'll animate allRects[0]. Then you increment n and animate allRects[1], and then increment n again. Thus, on the second time through the loop, you'll be animating allRects[2] and allRects[3], and so on.

Categories