2

For my first (proper) game created in JavaScript I'm making a Snake game. I'm storing all of the information about the snake in a class like this:

var snake={

    //The width and height of each "segment" of the snake (in pixels)
    size : 20,


    /*Direction that the snake's moving in

    Left=0
    Right=1
    Up=2
    Down=3*/
    direction : rand_int_between(0,3),


    /*Positions of the snake's "segments" (1 is the snake's head, then 2 (when it's created) will be the next segment of the snake,
    then 3 will be the next, and so on*/
    positions : {
        1 : {
            "x" : rand_int_between(0, 35)*snake.size, //There are 36 possible "columns" that the snake can be in
            "y" : rand_int_between(0, 23)*snake.size
        }
    },


    //Will be set to False if the game hasn't started or of it's paused
    moving : false
}

//Alert(snake.size);

Now this for some reason breaks my code. I've pinpointed it to when I multiply the random integer by "snake.size", because if I change those lines to simply multiplying it by 20 then the script works fine.

I'm getting the feeling that this is one of those questions where you won't be able to believe you missed it once you hear it!

Can someone please help because this is driving me insane, haha. I don't think I'm accessing the "size" property incorrectly because if I uncomment the last line of that code, and then remove the "snake.size" bit from the positions property, it alerts "20" as you'd expect.

Here is rand_int_between():

function rand_int_between(min, max) { //Will include min and max
    return Math.floor(Math.random() * (max - min + 1)) + min;
}
  • 2
    Where is `rand_int_between` defined? – willy Nov 11 '13 at 20:45
  • What's `a` while it's still being defined? Hint: not something you can use in math. – Dave Newton Nov 11 '13 at 20:46
  • 1
    try multiplying by "this.size" – Vic Nov 11 '13 at 20:46
  • 1
    You can't access elements of `snake` when declaring it. – sroes Nov 11 '13 at 20:46
  • @willy The general structure of my code is that the code I've copied here is (part of) an init() function, which is first called when the page has loaded. rand_int_between() is defined after init() is defined, however I don't think this is the problem because as I said, init() is only called when the page has loaded, or when rand_int_between() has been defined. –  Nov 11 '13 at 20:48
  • You should probably read tutorials on OO programming in JS, and write a proper constructor function instead of assigning an object literal. – Barmar Nov 11 '13 at 20:50
  • 1
    What I should've asked is, post the code for `rand_int_between`. My guess is that it's not returning what you expect. You could do `console.log(rand_int_between(0, 25))` and check the js console to double-check. – willy Nov 11 '13 at 20:50
  • 1
    @willy As all the other comments indicate, while that might be an issue, it's not the *underlying* issue. – Dave Newton Nov 11 '13 at 20:51
  • @willy `rand_int_between()` is irrelevant. The problem is clearly with the multiplication by `snake.size`, which won't work because that variable doesn't exist yet. – Barmar Nov 11 '13 at 20:51
  • 2
    @Vic - `this` definitely won't work either. – nnnnnn Nov 11 '13 at 20:51
  • @willy I've edited my post to contain the code for rand_int_between(), but I don't think that's the problem. (I got the code from: http://stackoverflow.com/questions/13997793/generate-random-number-between-2-numbers ) –  Nov 11 '13 at 20:54

3 Answers3

6

You can't access elements of an object (snake) while you're declaring it. Try moving the declaration of Positions:

var snake={

    //The width and height of each "segment" of the snake (in pixels)
    size : 20,


    /*Direction that the snake's moving in

    Left=0
    Right=1
    Up=2
    Down=3*/
    direction : rand_int_between(0,3),


    //Will be set to False if the game hasn't started or of it's paused
    moving : false
};


/*Positions of the snake's "segments" (1 is the snake's head, then 2 (when it's created) will be the next segment of the snake,
    then 3 will be the next, and so on*/
snake.Positions = {
    1 : {
        "x" : rand_int_between(0, 35)*snake.size, //There are 36 possible "columns" that the snake can be in
        "y" : rand_int_between(0, 23)*snake.size
    }
};
sroes
  • 14,663
  • 1
  • 53
  • 72
3

As Samy explained, you're trying to access the object while it's being constructed, but that's not possible. One workaround is using an outside variable for the size (you can wrap the whole thing in an immediately-executed function to avoid polluting the global scope):

var snake = (function() {
    var size = 20;
    return {
       size : size,
       /* ... */
       positions : {
            1 : {
                "x" : rand_int_between(0, 35) * size,  
                "y" : rand_int_between(0, 23) * size
            }
       },
       /* ... */
    };
}());
bfavaretto
  • 71,580
  • 16
  • 111
  • 150
-4

snkae is not yet defined. I think what you need is the other class creation syntax:

function snake() {

    //The width and height of each "segment" of the snake (in pixels)
    var size = 20;


    /*Direction that the snake's moving in

    Left=0
    Right=1
    Up=2
    Down=3*/
    var direction = rand_int_between(0,3);


    /*Positions of the snake's "segments" (1 is the snake's head, then 2 (when it's created) will be the next segment of the snake,
    then 3 will be the next, and so on*/
    var positions = {
        1 : {
            "x" : rand_int_between(0, 35)* size, //There are 36 possible "columns" that the snake can be in
            "y" : rand_int_between(0, 23)* size
        }
    };


    //Will be set to False if the game hasn't started or of it's paused
    var moving = false;
}

var snake = new snake();

Then it works.

Samuel
  • 2,106
  • 1
  • 17
  • 27