4

I've been trying to fix this for about 3 days now, and I can't seem to find why it doesn't work.

I've got this function, which loads an image, and loads through all the pixels to create a grid of walls for A* pathfinding. I'm using CraftyJS to create this game, maybe it is that?

However, it seems to load perfectly fine, but when I try to use it in my game, it gives me loads of undefined values on most of the tiles. In fact, I feel like it only fills one row, instead of all 45.

This is the function that fills the GRID:

var babyStart = 0, babyNodes = [], grid = new Array(new Array());
function getGridFromImage(img, worldWidth, worldHeight) {
    var image = new Image(); //maak een image object
    var c = document.getElementById("mapLoader");
    var context = c.getContext("2d");
    image.src = img; //pak het plaatje erbij
    image.onload = function () {
        context.drawImage(image, 0, 0);
        var data = context.getImageData(0, 0, worldWidth, worldHeight); //Verkrijg de Pixeldata
        console.log(data); 
        var count = 0, tmr = null, length = data.data.length, x = 0, y = 0;
        babyNodes = [];
        while(count <= length) {
            grid[y] = new Array();
            //Verkrijg de kleuren DATA
            var r = data.data[count]; //Rood channel
            var g = data.data[count + 1]; //Groen channel
            var b = data.data[count + 2]; //Blauw channel
            //console.log(data[0]);
            //console.log("Count/length: " + count + "/" + length + ";r: " + r + ";g: " + g + ";b: " + b);
            if (r == 0 && g == 0 && b == 0) {
                grid[y][x] = 1;
            } else {
                grid[y][x] = 0;
            }

            if (b > 0) {
                babyNodes[b - 255] = count;
            }

            if (g == 255) {
                babyStart = count;
            }

            count += 4;
            x++;

            if (x >= worldWidth) {
                y += 1;
                x = 0;
            }
        }
        loading = false;
    };
};

Sorry the comments are dutch, but I think most of you don't even need these comments anyways :P.

I try to collect the data in another function in another JS file, it looks a little like this:

Crafty.scene("lvlWoonkamer", function () {
    Crafty.sprite("images/levels/Woonkamer.png", { 
        achtergrond: [0,0,1280,720]
    });

    Crafty.e("2D, DOM, achtergrond").attr({x: 0, y: 0});
    console.log("Starting grid count");
    for (var i = 0; i < 45; i++) {
        var str = "";
        for(var ii = 0; ii <= 80; ii++) {
            str += grid[i][ii] + ",";
            console.log("[" + i + "][" + ii + "]");
        }
        str += ";";
    }

    console.log(str);
});

This is the output I receive:

undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,0,undefined,;

Sorry for the bad code blocks and stuff, I have no idea how it works XD (Just pressed ctrl + K and copy paste).

I have no idea why it's doing this, I tried all kinds of things with the multi-dimensional arrays, looked up a lot, copy pasted a lot but it just doesn't seem to work... (I'm already glad it loads the image tbh XD).

I'm kinda new to JavaScript and HTML5 and all that, so please be easy on me.

Sem Wong.

Edit: So I found out that I was clearing the Array everytime I did grid[y] = new Array();, so I changed it to if (grid[y] == null) grid[y] = new Array();. Now it works partly better, still getting some undefines but I'll get to the bottom of it :).

Edit 2: I fixed it completely and pathfinding is working also (A* OP). Thanks everyone for helping! It was the getGridFromImage function that was failing me, because it constantly cleared my grid[y]. I got a fixed version below for those who had the same problem as I did (Don't think there's anyone as stupid as me , but I guess new developers might have the same issue)

var babyStartX = 0, babyStartY = 0, babyNodes = [], grid = new Array(new Array());
function getGridFromImage(img, worldWidth, worldHeight) {
var image = new Image(); //maak een image object
var context = document.getElementById("mapLoader").getContext("2d");
image.src = img; //pak het plaatje erbij
image.onload = function() {
    context.drawImage(image, 0, 0);

    var data = context.getImageData(0, 0, worldWidth, worldHeight); //Verkrijg de Pixeldata
    console.log(data); 

    var count = 0, length = data.data.length, x = 0, y = 0;

    while(count <= length) {
        if (grid[x] == null) grid[x] = new Array();
        //Verkrijg de kleuren DATA
        var r = data.data[count]; //Rood channel
        var g = data.data[count + 1]; //Groen channel
        var b = data.data[count + 2]; //Blauw channel
        //console.log(data[0]);
        //console.log("Count/length: " + count + "/" + length + ";r: " + r + ";g: " + g + ";b: " + b);
        if (r == 0 && g == 0 && b == 0) {
            grid[x][y] = 1;
        } else {
            grid[x][y] = 0;
        }

        if (b > 0 && g == 0 && r == 0) {
            babyNodes[b - 254] = [x,y];
        }

        if (g == 255 && b == 0 && r == 0) {
            babyStartX = x;
            babyStartY = y;
            babyNodes[0] = [x,y];
        }

        count += 4;
        x++;

        if (x >= worldWidth) {
            y += 1;
            x = 0;
        }
    }
    loading = false;
}; };
Sem Wong
  • 78
  • 6
  • 1
    Did you try `console.log(grid)` to see what's really in that array (if anything)? – Marc B Dec 24 '13 at 18:55
  • I'm not following everything here, but from what I see, you're making an asynchronous call load the image, but your function neither accepts a callback to report when its done nor returns a Promise to allow listeners to register for notification. Somehow or another, you probably want to do one of these. – Scott Sauyet Dec 24 '13 at 19:10
  • @MarcB I put the grid in a console.log and it shows my an Array with 45x Array[80] (which should be fine, I give 80 width and 45 height with the function). but when I open for example column 0, I get 79: 0 length: 80. Aren't I supposed to get 0 to 79 all values? – Sem Wong Dec 24 '13 at 21:00
  • @MarcB it was mostly your comment that helped me get through this, because I looked at it and thought "Why is it so empty =/". Thanks very much I got it fixed and the fix is in the OP :) – Sem Wong Dec 24 '13 at 21:47

1 Answers1

0

I am not familiar with Crafty, so sorry if I am wrong, but I suppose Scott Sauyet is right. JavaScript is by default asynchronous, so perhaps you are calling the second function before the first one finished?

There is some background information on callbacks here: http://recurial.com/programming/understanding-callback-functions-in-javascript/

The concept behind callbacks is that you can call a module inside another so they are always ran sequentially.

function build(argument1, argument2) {
  // Do things
  check;
}

function check() {
  // Do things
}

Your case would probably be something like this, but I can't really tell from your code.

function getGridFromImage(img, worldWidth, worldHeight) {
  // Rest of your function
  check;
}

function check() {
  Crafty.scene("lvlWoonkamer", function () {
    Crafty.sprite("images/levels/Woonkamer.png", { 
        achtergrond: [0,0,1280,720]
    });

    Crafty.e("2D, DOM, achtergrond").attr({x: 0, y: 0});
    console.log("Starting grid count");
    for (var i = 0; i < 45; i++) {
        var str = "";
        for(var ii = 0; ii <= 80; ii++) {
            str += grid[i][ii] + ",";
            console.log("[" + i + "][" + ii + "]");
        }
        str += ";";
    }

    console.log(str);
  });
}

// Actually start the first function here;
getGridFromImage(img, worldWidth, worldHeight);
Neograph734
  • 1,714
  • 2
  • 18
  • 39
  • What I do is that I have the loading boolean checked, once the function is finished, I set it to true and the application goes to another scene, where I do the check (from Crafty.scene("Loading") to Crafty.scene("lvlWoonkamer"), in which I do the check). So it's kinda the same isn't it?" Edit: Or rather, I set it to false but you get the idea – Sem Wong Dec 24 '13 at 20:51