I'm trying to figure out why my Google Chrome console is giving me the error "undefined is not a function." I have a hunch, but maybe I'm on the wrong track. My function boxCollision(...)
is defined at the bottom of my class. Nearer to the top I have a statement
if (this.boxCollision(this.food.getBBox(), this.body[0].getBBox()))
this.food.translate(this.linkSize, 0);
the first line of which is causing the error I mentioned. I think that's maybe because I haven't yet defined boxCollision
, so it's essentially nonexistent. Is that right? The getBBox()
functions are recognized because they're from an external JavaScript file.
function snakegame(C, C_w, C_h, spd)
{
/* NOTE TO SELF: C is a Raphel object. Can't find a method to return the height
and width of a Raphael object in the documentation:
http://raphaeljs.com/reference.html#Raphael.
Using C_h and C_w for now, but should probably change it later.
*/
this.linkSize = 50; /* size of a snake unit, in pixels; must divide C_h and C_w */
this.link = C.rect(C_h/2, C_w/2, this.linkSize, this.linkSize);
this.link.attr("fill", "#E9E581");
this.body = [this.link];
this.food = C.rect(randInt(0,C_w/this.linkSize-1) * this.linkSize, randInt(0,C_h/this.linkSize-1) * this.linkSize, this.linkSize, this.linkSize);
if (this.boxCollision(this.food.getBBox(), this.body[0].getBBox()))
this.food.translate(this.linkSize, 0);
this.food.attr("fill","#B43535");
this.maxSnakeSize = C_h * C_w / (this.linkSize * this.linkSize);
/* On instantiation, the snake direction is down and has 1 link */
this.dy = 0;
this.dx = 0;
this.score = 0;
/* Event listener for changing the direction of the
snake with arroy keys on the keyboard
*/
this.redirect = function(dirnum)
{
switch (dirnum)
{
/*
dirnum corresponds to
1 ---> right
2 ---> down
3 ---> left
4 ---> up
*/
case 1:
this.dx = this.linkSize;
this.dy = 0;
break;
case 2:
this.dx = 0;
this.dy = this.linkSize;
break;
case 3:
this.dx = -this.linkSize;
this.dy = 0;
break;
case 4:
this.dx = 0;
this.dy = -this.linkSize;
break;
default: /* never happens */
break;
}
}
this.move = function()
{
if (this.body.length == this.maxSnakeSize)
{
this.destruct();
return;
}
var addLink = false;
var BBhead = this.body[0].getBBox();
if (this.hitWall(BBhead) || this.hitSnake(BBhead))
{
document.getElementById("snakescorediv").innerHTML = "<p>GAME OVER!</p><p>Score: "+ this.score +"</p>";
this.destruct();
return;
}
var BBfood = this.food.getBBox();
if (this.boxCollision(BBhead, BBfood))
{
this.moveFood();
this.score += 10;
document.getElementById("snakescorediv").innerHTML = this.score.toString();
addLink = true;
}
if (addLink)
this.body.push(this.body[this.body.length - 1].clone());
for (var i = this.body.length - 1; i > 0; --i)
{
var prevBB = this.body[i-1].getBBox();
var thisBB = this.body[i].getBBox();
this.body[i].translate(prevBB.x-thisBB.x, prevBB.y-thisBB.y)
}
this.body[0].translate(this.dx, this.dy);
}
this.mover = setInterval(this.move.bind(this), spd);
this.hitWall = function(bb)
{
return bb.x < 0 || bb.x2 > C_w || bb.y < 0 || bb.y2 > C_h;
}
this.hitSnake = function(bb)
{
var retval = false;
for (var i = 1, j = this.body.length; i < j; ++i)
{
var thisbb = this.body[i].getBBox();
if (this.boxCollision(bb, thisbb))
{
retval = true;
break;
}
}
return retval;
}
this.moveFood = function()
{
var bbf = this.food.getBBox(); // bounding box for food
do {
/* tx, ty: random translation units */
tx = randInt(0, C_w / this.linkSize - 1) * this.linkSize - bbf.x;
ty = randInt(0, C_h / this.linkSize - 1) * this.linkSize - bbf.y;
// translate copy of food
this.food.translate(tx, ty);
bbf = this.food.getBBox(); // update bbf
} while (this.hitSnake(bbf));
}
this.boxCollision = function(A, B)
{
return A.x == B.x && A.y == B.y;
}
this.destruct = function()
{
clearInterval(this.mover);
for (var i = 0, j = this.body.length; i < j; ++i)
{
this.body[i].removeData();
this.body[i].remove();
}
this.food.removeData();
this.food.remove();
this.score = 0;
}
}