Reference Error: 'Variable_Name' is undefined - HTML5 Canvas Image - javascript

Background: For a university project I have been tasked with creating a Flappy Bird clone. Originally it worked fine, then as I began adding more images, they stopped loading within Chrome. Firefox was fine (unless I did a fresh reload, but every subsequent reload was fine).
I was making a new 'Sprite' object for each image and within that sprite object's initialiser I would create an Image object and assign the src. I eventually realised this was the problem, so I rearranged my structure like this:
var ent_player_img = new Image();
ent_player_img.onload = function()
{
window.ent_player = new Sprite(ent_player_img);
};
ent_player_img.src = "../images/ent_player.png";
I would assign ent_player.img to the new Image object within the constructor. However, this was throwing reference errors within my game loop.
To combat this I put all of the functions in my game loop that called these objects within an if statement.
if (typeof ent_player !== undefined)
{
//Draw image
}
And yet I was still getting the errors. Inside the if statement I used a console.log saying typeof ent_player which returned as undefined.
Very puzzled as to why this code was still running and causing issues, I used my debugger of choice (Firebug).
I put a breakpoint on the if statement, however, whenever I step through the code with the debugger it works perfectly. Correct outputs, etc. Then as soon as I try it again without the debugger, same issue.
Can anyone give me an idea as to why this is happening and how I can fix it?
Thank you very much.
Edit: Sprite constructor looks like this:
function Sprite(image)
{
this.img = image;
this.height = this.img.height;
this.width = this.img.width;
this.x = 0;
this.y = 0;
}

Related

Three.js : Box3 from an object not in scene

I have a problem adding a Bounding Box from an object in a different module. Right now, it is working fine as long as I write everything in my main function, but as soon as I create my function in a different file, and import in in the main file, it's not working anymore.
The error code I get :
Uncaught TypeError: Cannot read properties of undefined (reading 'updateWorldMatrix')
at Box3.expandByObject (three.module.js:4934:10)
at Box3.setFromObject (three.module.js:4852:15)
at camCollision (camColliders.js:68:37)
at HTMLDocument.<anonymous> (World.js:355:7)
camColliders.js being the file I'm trying to put the function in, and World.js my main file.
Here is the function :
function camCollision() {
const camBB = new Box3().setFromObject(camSphereDetector);
const boule1BB = new Box3().setFromObject(boule1Obj);
boule1BB.name = 'first';
const boule2BB = new Box3().setFromObject(boule2Obj);
boule2BB.name = 'second';
const boule3BB = new Box3().setFromObject(boule3Obj);
boule3BB.name = 'third';
const boulesBB = [boule1BB, boule2BB, boule3BB];
boulesBB.forEach((bbs) => {
if (bbs.intersectsBox(camBB)) {
console.log('got it');
}
});
}
document.addEventListener('mouseup', () => {
camCollision();
});
When I'm doing this in a separate file, i'm first importing the objects from another file and they are all Mesh.
I believe the problem is that I can't create the Bounding Boxes in a separate file, because it needs to be added to the scene first, and I'm only adding them in the scene in World.js. Yet, the error is leading me to line 68, the variable for 'boule1BB', which is weird because 'camBB' should have the problem first ?
Here is how I'm creating the Box3 (these are just copying some GLTF objects position and size, cause I can't manage to get a Box3 from it) :
const boule1Obj = new Mesh(
new SphereGeometry(2, 32, 16),
new MeshBasicMaterial({ color: 'red', transparent: true, opacity: 0 }),
);
boule1Obj.position.set(10, -3.5, 0);
Then, I would like to know, if I got the problem right : is there a way to create a Box3 in a different js file, from an object that is not added to the scene yet (even if it should when the function is being called) ? With a different way than 'setFromObject' maybe ? Or am I not understanding the real problem.
For a bit of context, the aim is to provide some informations about each model when the user clicks on it, and I'm planning on putting the informations as '.name' for each Mesh corresponding to a model. So I don't want to write all this stuff in the main file, but rather on a separate one.
I hope this is clear enough, and I've given enough content for a solution to be found. I couldn't find anyone else having this problem. If you need anything else, please tell me !
Thanks already for your help !
I believe the problem is that I can't create the Bounding Boxes in a separate file, because it needs to be added to the scene in World.js.
Not so. Since a constructed THREE.Mesh has a shape with extents (from its geometry) and a transform (by default, translated to the origin, with no scaling or rotation), Three.js can and will determine a bounding box from that information as though the mesh were in the scene. I've posted a demo of this on CodePen.
Nor should defining the object in one file and referencing it another make any difference, as long as the object is in scope and initialized at the time it's bound to.
Here, I suspect that you're assigning boule1Obj, boule2Obj, and boule3Obj in World.js. In that case, the imported function is being hoisted before the variables are assigned, and the function is seeingbinding to them as unassignedundefined.
Try changing camCollision() to accept the bouleXObjs as arguments.
function camCollision(...objs) {
const camBB = new Box3().setFromObject(camSphereDetector);
for(let i = 0; i < objs.length; i++) {
const objBB = new Box3().setFromGeometry(objs[i]);
objBB.name = `Bounding Box ${i + 1}`;
if(objBB.intersectsBox(camBB)) {
console.log("Got it!");
}
}
}
And then call it as
document.addEventListener("mouseup", () => {
camCollision(boule1Obj, boule2Obj, boule3Obj);
});

Instanciating an object via DOM element inside setup() on p5

I'm facing a problem where I'm trying to instantiate an object inside the setup function of p5, using a callback to do so:
This is the part of sketch.js relevant to the problem:
var g; //for graph instance
var dropzone; //for the file dropping area
function setup() {
createCanvas(640, 480);
dropzone = select('#dropzone'); //selects the <p> element I'm using as dropzone
dropzone.drop(process_file, unhighlight); //unhighlight is just a function to make the drop area not-highlighted
}
function draw() {
background(200);
if (g) {
g.show();
}else{
msg = "Please, load a file by dropping it in the box above";
text(msg, width/2, height/2);
}
}
// callback being used to process the text file content
function process_file(file){
data = file.data; //gets file data(content)
lines = data.split('\n'); // split the lines
digraph = lines[0] == 1 ? true : false; // is it a digraph?
v = int(lines[1]);
g = Graph(digraph, v); //the class I"m using to instantiate the graph
console.log(g); // <-- says undefined
g.init_graph(); // initialize all vertices
for (var i = 2; i < lines.length; i++) {
edge = lines[i].split(' ');
g.add_edge(edge[0], edge[1], edge[2]);
}
}
I already checked using console.log() and the content of the file is being correctly loaded, and the values are correct in what I was expecting. the Graph() class is in another file, but it is being imported as well as the sketch.js. I also tried to put the script importing at the end of the page, but got the same result, the g is still saying undefined.
What I didn't try is to put the whole code of my Graph class into the sketch.js file, but I will need to put more 15 algorithms on the class later, so the sketch file will grow in a unneeded size. I thought the by declaring g as a global variable I would have no problems with it.
I'm fairly inexperienced with JavaScript, so this is probably a rookie mistake about some kind of loading order, so please, if you answer this question, show me the why it is not working as it is. If there's need of any other piece of code, please let me know.
Thanks in advance.
Looking at this line:
g = Graph(digraph, v);
I think you meant to do this:
g = new Graph(digraph, v);
This creates a new instance and stores a reference to that instance in the g variable.

p5js positioning canvas Uncaught Type Error

I'm not sure what I'm doing wrong in this problem. I'm using OpenProcessing and trying to put a canvas element within a container but I'm running into an Uncaught TypeError, Cannot read property "id"
I'm copying the same code from https://github.com/processing/p5.js/wiki/Positioning-your-canvas
function setup() {
var cnv = createCanvas(100, 100);
var x = (windowWidth - width) / 2;
var y = (windowHeight - height) / 2;
cnv.position(x, y);
background(255, 0, 200);
}
This is my code...
function setup() {
var cnv = createCanvas(500, 100);
cnv.id("hello");
cnv.position(0,0);
}
function draw() {
}
Here is a link to my sketch...
https://www.openprocessing.org/sketch/407956
It has something to do with OpenProcessing because your code works absolutely fine on p5 editor (and locally).
The createCanvas method returns an object so calling the id function on it should not return "Cannot read property 'id' of undefined" as it did on OpenProcessing so createCanvas possibly isn't returning anything, and it should return an object according to p5 documentation..
You can try positioning the canvas using css as described in p5 wiki by adding a stylesheet that uses flexible box layout or try not using OpenProcessing if possible.
The createCanvas() function is not returning anything. This doesn't jive with what's in the P5.js reference, so I understand your confusion.
My guess is that OpenProcessing uses a slightly modified version of P5.js, because it doesn't really require any positioning. The canvas is always centered in the screen.
If you're going to continue using OpenProcessing, then I'd stop worrying about positioning the canvas yourself. Or I'd search for existing sketches that reposition the canvas and see how they do it.
Even if the createCanvas() function returns soemthing, I'm not sure what the id() function is supposed to do in this case. Nothing in the link you posted uses that function. Nonetheless, it seems to work fine if I run it locally.

Weird Javascript IOS 7 Issue

I have a web application which behaves fine on all desktop browsers and mobile devices however since IOS 7 I am encountering a weird issue.
Example:
I am setting an object like
(function(){
//CONSTRUCTOR*
sampleObject= new function(){
alert("loaded constructor "+ new Date().getTime()); //only outputted once
//swfobject dom load event
}
...//functions and propeties related to sampleObject
})();
//ASSIGNING THE OBJECT
sampleObject = new sampleObject();
alert("finished assigning object "+ new Date().getTime()); //only outputted once
Issue:
On ios 7 it seems to randomly lose what sampleObject is and instead reverts to what is inside the snippet with constructor*. So for example, I have been debugging it at intervals where I am calling a public method on my object such as sampleObject.getResource("a");
And the traces are coming back like:
sampleObject = [Object] //Correct
sampleObject = [Object]
and then randomly it does this:
sampleObject = function(){
//swfobject dom load event
}
Which basically is the code inside the constructor*.
This then causes my code to throw a reference error as the public properties/methods which I am using throughout such as getResource are not defined...
Things Tried:
Code only initiates once (alerts fire once with single Date / random string)
I Identified where an error was occuring due to this issue, wrapped around a try/catch however although the code is clearly failing it is not going into the catch.
Tried it on different IOS versions, all fine except IOS 7
*CONSTRUCTOR - not sure if this is classified as a constructor but that is what it seems to me.
**Unfortunately I cannot post my code publicly as it is part of a commercial project and quite extensive.... However any suggestions or has anyone had any similar issues?
Thanks!
Thanks for all the comments above. That pointed me in the right direction.
The problem seems to be that IOS 7 seems to randomly loses scope of the javascript object, and because we werent specifically assigning the sampleObject to the window then it wasnt working all the time.
Therefore solution to my problem was simply to change:
//ASSIGNING THE OBJECT
sampleObject = new sampleObject();
to
//ASSIGNING THE OBJECT
window.sampleObject = new sampleObject();

'Date' is undefined in IE9 in javascript loaded by FacePile

I'm currently getting an error within Facebook's FacePile code, and I'm baffled by the cause.
facepile.php loads a script which, among other things, has these lines (when pretty-printed):
...
o = document.createElement('script');
o.src = l[n];
o.async = true;
o.onload = h;
o.onreadystatechange = function() {
if (o.readyState in c) {
h();
o.onreadystatechange = null;
}
};
d++;
a.appendChild(o);
...
(a == document.body, d++ is irrelevant here)
This code loads a script with src = http://static.ak.fbcdn.net/rsrc.php/v1/yW/r/pmR8u_Z_9_0.js or something equally cryptic (the filename changes occasionally).
In that script, there are these lines at the very top (also when pretty-printed):
/*1331654128,176820664*/
if (window.CavalryLogger) {
CavalryLogger.start_js(["\/8f24"]);
}
window.__DEV__ = window.__DEV__ || 0;
if (!window.skipDomainLower && document.domain.toLowerCase().match(/(^|\.)facebook\..*/))
document.domain = window.location.hostname.replace(/^.*(facebook\..*)$/i, '$1');
function bagofholding() {
}
function bagof(a) {
return function() {
return a;
};
}
if (!Date.now)
Date.now = function now() {
return new Date().getTime();
};
if (!Array.isArray)
Array.isArray = function(a) {
return Object.prototype.toString.call(a) == '[object Array]';
};
...
And I'm getting an error which says "SCRIPT5009: 'Date' is undefined", right at the if (!Date.now) portion. Debugging near that point reveals that Date, Array, Object, Function, etc are all undefined.
Er... how? window exists, as does document (though document.body is null) and a handful of others, but plenty of pre-defined objects aren't. Earlier versions of IE don't seem to have this problem, nor do any other browsers, but multiple machines running IE9 (including a clean VM) all have the same issue.
I doubt I can do anything about it, but I'm very curious how this is happening / what the underlying problem is. Does anyone know, or can they point me to something that might help?
-- edit:
Prior to posting this question, I had found this site: http://www.guypo.com/technical/ies-premature-execution-problem/
While it seemed (and still does) like it might be the source of the problem, I can't replicate it under any smaller circumstances. All combinations I've tried still have Date, etc defined ; which isn't too surprising, as otherwise I'm sure others would be seeing many more problems with IE.
If you step through with a javascript debugger at the first point any JS gets run. At the same time add a watch for Date/Array etc. and note when it goes to null. Might be slow and laborious but I can't see why it wouldn't work.
You may want to try adding the script in a document.ready function. In other words, insure that the FB script is processed only after the DOM is ready. But, based on the link you give to Guy's Pod (great article, by the way), it seems you're right in the assertion that IE is downloading and executing the script pre-maturely (hence my suggestion to add a wrapper so that it only executes after the DOM ready event). IE9 is probably sandboxing the executing script (outside the document/window scope).

Categories

Resources