ThirtyOddLinesOfCode ThirtyOddLinesOfCode - 16 days ago 5
Javascript Question

Javascript - Property of an object has the value of NaN, even when I explicitly assign it a number value

I am making a basic platform game in my spare time, and I am currently trying to add gravity. The game runs in a canvas, and so I am using black pixels as solid objects. The sprites I am making are supposed to fall when they have not contacted a solid black line. To do this I am using

context.getImageData()
and the x position, y position, width, and height properties of my sprite objects. When I create the player sprite I assign it an x position of 10, a y position of 10, a width of 50, and a height of 100:
var player = new Sprite (10, 10, 50, 100);
My problem is that when I try to draw the sprite or use its y position in
context.getImageData()
it says that the y position is Nan. The code below is a simplified version with only relevant variables.



//-----------SETUP-------------//
//----GLOBAL VARIABLES---//
var gravityValue = 1; //amount of change that gravity makes per move
var fallBoxThickness = 1; //thickness of fall-box check

var canvas = document.getElementById("canvas"); //get the canvas object
canvas.width = 800; //set the canvas width
canvas.height = 600; //set the canvas height
var context = canvas.getContext("2d"); //get the canvas's context, 2d


//--------OBJECTS---------//
function Sprite (x,y,width,height) { //sprite object
//components
this.x = x; //sprite x position
this.y = y; //sprite y position
this.width = width; //image width
this.height = height; //image height
this.dx = 0; //sprite x movement
this.dy = 0; //sprite y movement
this.gravityEnabled = true; //allows sprite falling, must be manually disabled

//methods
this.draw = function () { //draw method
//context.drawImage(this.src, this.x, this.y);
//draws the sprite to the canvas
//it used to do the above, now it outputs it to the output span
document.getElementById("output").innerHTML = this.y;
};

this.move = function () { //move method
if (this.gravityEnabled === true) { //if the sprite can fall
var hit = false; //a hit is not yet detected
var checkSpace = context.getImageData( //get pixels to see if the sprite ...
this.x, parseInt(this.y + this.height), //... will hit an object below it's lower edge
this.x + this.width, this.y + this.height, + fallBoxThickness);

var i = 0; //set i to 0
while (i < checkSpace.length && hit === false) {
//while the check hasn't finished and a hit isn't detected
if (checkSpace[i] < 5 //
&& checkSpace[i+1] < 5 //if there is a black pixel
&& checkSpace[i+2] < 5) { //
hit = true; //record that there is a hit
}
i = i + 4; //add 4 to i
}
if (hit === false) { //if the check didn't hit
this.dy += gravityValue; //add to the fall of the sprite
} else {
this.dy = 0;
}
}
this.y += this.dy;
};
}

//------------PLAYER CREATION---------//
var player = new Sprite (10, 10, 50, 100); //create the player object

//--------FUNCTIONS--------//
function drawCanvas () { //draw everything on the canvas
player.draw(); //draw the player
}

function moveSprites () {
player.move();
}
//----------MAIN-----------//
function main () {
moveSprites(); //move the sprites
drawCanvas(); //draw the screen
}

setInterval(main,100); //run main 10 times a second,
//start the program

<title>ptf2</title>
<canvas id="canvas" style="border:1px solid black;"></canvas>
there was images here but the javascript never gets far enough to render them because of the y-position error.<br>
Instead I am just outputting the value of the player sprite's y-position to the span below.<br>
:<span id="output">this is to prevent it from occasionally being undefined</span>





Also, I'm really not sure why this version works instead of what I had before, so now I will include the full version:



//-----------SETUP-------------//
//----IMAGES----//
document.getElementById("map").style.display = "none"; //hide the map image
document.getElementById("sprite").style.display = "none"; //hide the sprite image

//----GLOBAL VARIABLES---//
var gravityValue = 1; //amount of change that gravity makes per move
var fallBoxThickness = 1; //thickness of fall-box check

var canvas = document.getElementById("canvas"); //get the canvas object
canvas.width = 800; //set the canvas width
canvas.height = 600; //set the canvas height
var context = canvas.getContext("2d"); //get the canvas's context, 2d


//--------OBJECTS---------//
function Sprite (x,y,src,width,height,dx,dy) { //sprite object
//components
this.x = x; //sprite x position
this.y = y; //sprite y position
this.src = document.getElementById(src); //sprite source image
this.width = width; //image width
this.height = height; //image height
this.dx = dx; //sprite x movement
this.dy = dy; //sprite y movement
this.gravityEnabled = true; //allows sprite movement, must be manually disabled

//methods
this.draw = function () { //draw method
context.drawImage(this.src, this.x, this.y); //draws the sprite to the canvas
};

this.move = function () { //move method
if (this.gravityEnabled === true) { //if the sprite can fall
var hit = false; //a hit is not yet detected
var checkSpace = context.getImageData( //get pixels to see if the sprite ...
this.x, parseInt(this.y + this.height), //... will hit an object below it's lower edge
this.x + this.width, this.y + this.height, + fallBoxThickness);

var i = 0; //set i to 0
while (i < checkSpace.length && hit === false) {
//while the check hasn't finished and a hit isn't detected
if (checkSpace[i] < 5 //
&& checkSpace[i+1] < 5 //if there is a black pixel
&& checkSpace[i+2] < 5) { //
hit = true; //record that there is a hit
}
i = i + 4; //add 4 to i
}
if (hit === false) { //if the check didn't hit
this.dy += gravityValue; //add to the fall of the sprite
} else {
this.dy = 0;
}
}
this.y += this.dy;
};
}

var player = new Sprite (10, 10, "sprite", 50, 100); //create the player object
var map = new Sprite (0, 0, "map", 800, 600); //create the map sprite
map.gravityEnabled = false; //prevents the map from falling
//--------FUNCTIONS--------//
function drawCanvas () { //draw everything on the canvas
map.draw(); //draw the map
player.draw(); //draw the player
}

function moveSprites () {
player.move();
}
//----------MAIN-----------//
function main () {
moveSprites(); //move the sprites
drawCanvas(); //draw the screen
alert("run");
}

setInterval(main,100); //run main 10 times a second,
//start the program

<title>ptf2</title>
<canvas id="canvas" style="border:1px solid black;"></canvas>
<img id="map" src = "assets/map03.png">
<img id="sprite"src = "assets/sprite.png">
<script src = "main.js"></script>





Any enlightenment would be greatly appreciated as to why the one doesn't work with the exact same values. Thank you.

Answer

Your Sprite constructor has 7 arguments, but you are contructing it with only 5 arguments. Variables dx and dy are undefined, so they produce NaN after algebraic operations.