I have recently been trying to implement Dijkstra’s Algorithm in Javascript using the tutorial here. I'm able to make it go around obstacles successfully, but the paths it makes are simply not optimal, usually coming off as very straight. I think the problem is with how he implemented finding the neighbors. His code seems to pick the neighbors in a near-random order while mine always picks them in a set order, so that's probably a good place to look. I couldn't for the life of me figure it out. I tried everything I could think of.
My filling implementation is this:
function floodFill(array,sx,sy,dx,dy){
var frontier=[[sx,sy]];
array[sy][sx].visited=true;
var look=[[-1,0],[0,-1],[1,0],[0,1]];
var looks=0;
while(frontier.length>0){
if(frontier.length>0){
var current=frontier[0];
frontier.splice(0,1);
if(current[0]==dx && current[1]==dy){
console.log("Broke early!");
break;
}
for(var i=0;i<look.length;i++){
var y=current[0]+look[i][0];
var x=current[1]+look[i][1];
if((y>=0 && y<array[current[0]].length) && (x>=0 && x<array.length)){
if(array[y][x].visited==false && array[y][x].type==0){
frontier.push([y,x]);
looks++;
array[y][x].visited=true;
array[y][x].origin=[current[0],current[1]];
array[y][x].order=looks;
}
}
}
}
}
}
You can find a demo here (you need to open up your javascript console to see it)
Thank you very much for your time.
Here's an image of my problem
Figured out the answer. To put it simply, I wasn't checking diagonals when I was finding the neighbors.
You can find a working version here
The part that I changed
var look=[[-1,-1],[-1,0],[-1,1],[0,-1],[0,1],[1,-1],[1,0],[1,1]];
Related
(Sorry for bad english) Hi, I'm trying to make a JavaScript app which is basically a music player and I can't figure out why one thing is not working. There's a chart that displays the music percentage (here's a screenshot) made with jQuery CDN and a GitHub source. The percentage resets at the beginning of the song (and this works) because of songTime.dataset.percent = 0;.
Then, there's the songTime.dataset.percent = sliderPosition; in a function that calculate at what point are you in the song
function chartUpdate() {
let sliderPosition = 0;
if (currentSong.duration != NaN) {
sliderPosition = Math.round(currentSong.currentTime * (100 / currentSong.duration));
songTime.dataset.percent = sliderPosition;
}}
It is in an if statement which is in a function, but this doesn't work (it's not because of the variable, I've checked it).
I've tested it several times, and the only difference between the two lines is that the one that doesn't work is in an if statement (as I already said, which is in a function).
I know it can be difficult to understand me because there isn't any code (I tried to add it, but in stackoverflow it doesn't work, I don't know why), but if you need (I don't know if it can be helpful) I hosted the non-working website here. Summing up, my problem is that the data-percent works only sometimes.
Your if statement contains invalid syntax. Replace
if (currentSong.duration != NaN)
with
if ( ! isNaN(currentSong.duration) )
I am working on a portion of a project that I am trying to detect when certain divs hit each other. In the code that I made, that doesn't work, I basically say take the first div's left amount, compare it to the other div's left amount, if they are within a certain amount it triggers an alert. If I get that much to work I am going to implant a way to say that if the distance between the two divs is 0 then it will run a certain function. I am afraid the scope of this project is too big for me, even though I am basically at the last part, because I have spent hours researching a simple way to add collision detection, but everything I find looks like rocket science to me, that is why I tried to create my own way below. So in summary, what I want to know is why my collision detection code doesn't work, how I can make it work if possible, and if not possible what is the next best option that I should use.
//Collision
function collision(){
var tri = $('#triangle');
var enemyPos = $('.object1').css('left');
var minHit = enemyPos - 32.5;
var maxHit = enemyPos + 32.5;
var triLoc = tri.css('left');
if(triLoc > minHit && triLoc < maxHit){
alert('hit');
}
}
collision();
}
}
full code: https://jsfiddle.net/kc59vzpy/
If the code you have above is definitely where the problem is, then you need to look at the enemyPos variable. Getting the left position also adds px, so enemyPos is 100px or something like that. When you add 32.5, you get 100px32.5 and when you subtract you get NaN, neither of which you want.
Before you add or subtract, use enemyPos = parseInt($('.object1').css('left')); to turn it into an actual number.
I have a question over at collision-detection about a similar issue, but it's not exactly the same. I had an issue with a new game project (I'm trying to learn more about HTML5 Canvases and Socket.io) in which my collisions weren't working. I thought that my issue was centered on collisions, but now I'm starting to think something different. The reason I have a different issue posted here at the for-loop area is because I'm not sure if my issue is for-loop related or collision-detection related. Either way, I'd be happy to take one of my questions down.
This code is looping every frame to get the active positions of bullets and ships. If the bullet touches the ship, it'll be removed and some health points will be removed from the ship.
Tutorial I was using: http://jlongster.com/Making-Sprite-based-Games-with-Canvas
That aside, here's my checkCollisions code. It seems that the collision function is working, because when I started to log all the positions every time we had an iteration, it seemed that the position of my object was changing every single time. Is this one of those for-loop issues where I'm going to need a callback?
Thank you so much in advance for all your help. I'll be sure to upvote/select every response that helps out! :)
SOLVED! Turns out one of my arrays wasn't being passed in correctly. I'd like to thank you guys for telling me to always split it into multiple functions, that really helped me figure that one out!
// Let's start out here: I have a players[] array
//that's essentially a list of all players on the server
// and their positions. I omitted server connection functionality since that's not my error
// source.
function checkCollisions() {
for (var i = 0; i < players.length; i++) { // Iterating through all players
var pos = [players[i].posX, players[i].posY];
var size = [SHIP_WIDTH, SHIP_HEIGHT]; // This is the size of each player, it's a ship game. So these are constants.
if (players[i].userId != PLAYER.userId) { // Each player has a userId object, this is just doublechecking if we're not uselessly iterating
for (var j = 0; j < bullets.length; j++) { // We're now looping through bullets, an array of all the bullets being shot by players
var pos2 = bullets[j].pos;
var size2 = BULLET_SIZE;
var sender = bullets[j].sender;
if (boxCollides(pos, size, pos2, size2)) { // Collision code
if (sender != players[i].userId) {
bullets.splice(j, 1);
i--; // Tried here with j--, and by removing the entire line. Unfortunately it doesn't work :(
break;
}
}
}
}
}
}
Have you tried using console.log to see where the program is breaking? This might help you determine if there are multiple bugs or if it's just this one. If there's something wrong in a previous statement, you may not know it if you've fixed the i-- / j-- ...?
Edit: AH I see that you've fixed things, after I'd posted this. Well congrats and good job!
I am playing around with a great simplex algorithm I have found here: https://github.com/JWally/jsLPSolver/
I have created a jsfiddle where I have set up a model and I solve the problem using the algorithm above. http://jsfiddle.net/Guill84/qds73u0f/
The model is basically a long array of variables and constraints. You can think of it as trying to find the cheapest means of transportation of passengers between different hubs (countries), where each country has a minimum demand for passengers, a maximum supply of passengers, and each connection has a price. I don't care where passengers go, I just want to find the cheapest way to distribute them. To achieve this I use the following minimising objective:
model = {
"optimize": "cost",
"opType": "min",
"constraints": { \\etc...
I am happy with the model and the answer provided by the algorithm ... but the latter takes a very long time to run (>15 seconds...) Is there any possible way I can speed up the calculation?
Kind regards and thank you.
G.
It sounds as though you have a minimum-cost flow problem. There's a reasonable-looking TopCoder tutorial on min-cost flow by Zealint, who covers the cycle-canceling algorithm that would be my first recommendation (assuming that there's no quick optimization that can be done for your LP solver). If that's still too slow, there's a whole literature out there.
Since you're determined to solve this problem with an LP solver, my suggestion would be to write a simpler solver that is fast and greedy but suboptimal and use it as a starting point for the LP by expressing the LP in terms of difference from the starting point.
#Noobster, I'm glad that someone other than me is getting use out of my simplex library. I went through, looked at it, and was getting around the same runtime as you (10 - 20 seconds). There was a piece of the code that was needlessly transposing array to turn the RHS into a 1d array from a 2d array. With your problem, this killed performance eating up 60ms every time it happened (for your problem, 137 times).
I've corrected this in the repo and am seeing runtimes around 2 seconds. There are probably a ton of code clean up optimizations like this that need to happen but the problem set I built this (http://mathfood.com) for are so small that I never knew this was an issue. Thanks!
For what its worth, I took the simplex algo out of a college textbook and turned it into code; the MILP piece came from wikipedia.
Figured it out. The most expensive piece of the code was the pivoting operation; which it turns out was doing a lot of work to update the matrix by adding 0. Doing a little logic up front to prevent this dropped my run-time down on node from ~12 seconds to ~0.5.
for (i = 0; i < length; i++) {
if (i !== row) {
pivot_row = tbl[i][col];
for (j = 0; j < width; j++) {
// No point in doing math if you're just adding
// Zero to the thing
if (pivot_row !== 0 && tbl[row][j] !== 0) {
tbl[i][j] += -pivot_row * tbl[row][j];
}
}
}
}
I've got a basic Space Invaders type game going, and I can't get it to recognise when the shot from the player hits the alien. (I'm only checking Alien2 atm, the one second from the left). Since they're both moving, I've decided the only way to check for collisions is with either a range-based if statement (with 2 top coordinates and one left coordinate), or directly comparing the positions along the Y axis with Jquery.
I'm using the range-based solution at the moment, but so far it hasn't worked (not sure why).
My code so far:
if (key == "87"/*&& document.getElementById('BarrelOne').id=='BarrelOne'*/){
var Invader2 = document.getElementById('Alien2');
var Shot1 = document.getElementById('ShortShot');
Shot1.style.webkitAnimationPlayState="running";
setTimeout(function(){
Shot1.style.webkitAnimationPlayState="paused";
}, 1200);
if(document.elementFromPoint(625.5, 265.5) == Shot1){
Invader2.style.visibility="hidden";
}
};
Jsfiddle:
http://jsfiddle.net/ZJxgT/2/
I did something similar, and i found that it was much easier to achieve using gameQuery.
to test for collisions:
var collided = $("#div1").collision("#div2");
you can see full working example here
EDIT
If you're having trouble check out the API. For example, to find out how to use collisions check this part of the API.
the collision works in the following way:
This method returns the list of elements collisioning with the selected one but only those that match with the filter given as parameter. It takes two optional arguments (their order is not important). The filter is a string filtering element used to detect collision, it should contain all the elements the function should search collision into. For example if you look for collision with element of the class ‘foo’ that may be contained in a group you will use the filter ".group,.foo".
So, write something like this:
$("#ShortShot").collision("#Alien2").hide();
// will return the alien if it collides with ShortShot
or, to hide them both:
if (($("#ShortShot").collision("#Alien2")).length) {
$("#ShortShot").remove();
$("#Alien2").remove();
}
Instead of losing hours reinventing the wheel, I would suggest to switch (if still possible, depending on your time deadline) to a real 2D game engine for Javascript, with easy collision detection.
Check as well: 2D Engines for Javascript