"NS_ERROR_NOT_AVAILABLE" after trying to draw an Image on Canvas - javascript

I have this Problem where whenever I try to draw an Image on Canvas I get this error message in the Console:
Uncaught Exception [...]
name: "NS_ERROR_NOT_AVAILABLE"
result: 2147746065
I use HTML and Javascript.
When using the context.DrawImage(); command outside of that specific function, there is no error.
even with the same variables and numbers.
function rendering(dt) {
mainContext.clearRect(0,0, mainCanvas.width, mainCanvas.height);
renderMap();
} [...]
var SpritePosX;
var SpritePosY;
//this function wont run
function renderMap() {
SpritePosX = PlayerX + SpriteX - 100;
SpritePosY = PlayerY + SpriteY - 100;
sprite.onload = function () {ctx.drawImage(sprite, SpritePosX, SpritePosY, 50, 50);
}
Trying to draw the image from console will not work as long as the function is inside the code.
If I remove the "problematic" function it will work in the rendering function and inside of the console.
the rendering(dt); function is hooked up to a gameloop, everything is ok with that.
Every Variable is defined.

I am an Idiot.
The code inside the rendering.js part of the project was fine,
the problem was that I made a spelling mistake while defining the source of the picture.

Related

Creating a sprite inside of setInterval

Using the setInterval function, I'm trying to create a sprite once every second on code.org using javascript, so my first version of the code looks like
setInterval( function() {
createSprite(200,200,20,20)
}, 1000)
My problem is that putting setInterval inside of the Draw function causes it to not work properly and a sprite is created every tick after one second has passed, and when the setInterval is not put into function Draw it does not draw the sprite like I want it too.
One solution I have tried is putting the Draw function inside of setInterval but it is not recognized and gives the error message "Draw is defined, but it is not called in your program".
Is there a different version of setInterval that works inside of Draw function, a way to put Draw inside of setInterval successfully, a way to make the sprite show up even though it is outside Draw, or a different way to solve this problem?
Specifically what I'm looking for is to create a sprite once every second, have it show up on screen, be able to choose different velocities for each sprite each time a new one is spawned, and being able to put this function inside of an if function and still have it work as intended.
a piece of code showing something that partially works is shown here:
https://studio.code.org/projects/gamelab/ApXezLpMzV3TfEfHx1CrhFyuteYDSKWe_6Hx0NdJgnc
It works in the regards that it spawns a sprite every second, but if I try to assign one of the sprites that got spawned a velocity, It only works for the first one, as shown here:
https://studio.code.org/projects/gamelab/ApXezLpMzV3TfEfHx1CrhFyuteYDSKWe_6Hx0NdJgnc
the only way I think a solution could be made would be by declaring a class, and then creating a sprite of this class inside the setInterval function, but I do not know exactly how to do this.
So i think that your problem is that the sprite generates only after a second, right?
If so, please try this:
createSprite(200,200,20,20);
setInterval( function(){ createSprite(200,200,20,20)},1000);
See comments:
// just a helper function to generate random velocities
function random_in_range(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min }
var monster = createSprite(200,200,20,20);
monster.velocityX = 5;
setInterval(function() {
// as you needed to set velocity for a newly created sprite
// you need to have this sprite as a variable
var fireball = createSprite(monster.x,monster.y,4,4);
// now you can set it's velocity
fireball.velocityX = random_in_range(1,6);
// basically that's it.
// as you don't do anything else with a "fireball"
// you can just forget about it, and you don't need to save it anywhere
}, 1000);
function draw() {
background("white");
createEdgeSprites();
monster.bounceOff(edges);
drawSprites();
}
The link with the working code
Looking at your original code and your question I think that you may have some basic misconseptions about JS (sorry if I misjudged). Explained them in the comments to your code. I also added some lines to illustrate my points:
var spawner = createSprite(200,200,20,20);
var remember_spawner = spawner // ADDED
// After a new sprite created it does't change 'spawner' variable
createSprite(150,200,15,15).velocityY = 3; // ADDED
console.log(remember_spawner === spawner) // ADDED // you see it's the same
// you need to assign the newly created sprite to a variable
// you can think of this as:
// I need give them different names so that they can understand to whom am I taking to
// and if you don't name them they won't listen to you at all
var spawner2 = createSprite(100,200,10,10); // ADDED
spawner2.velocityY = 1 // ADDED // now you cat change velocity of another sprite
console.log(spawner !== spawner2) // ADDED // and it is another sprite
// var thing_to_be_spawned = createSprite(spawner.x,spawner.y,4,4);
// You probably don't need this. And you don't use the variable anyway.
// This sprite created at the same time as the spawner.
// But if you need it, and you want it to move - change it's velocity (thing_to_be_spawned.velocityX = something) not the velocity of spawner
// And it would be better if you'll name the function passed to setInterval
// and call it instead of repeating it. Like so:
// function fire() { ... } // define the function
// fire() // call the function
// setInterval(fire, 1000) // call the function every second
setInterval(function(){
console.log("This function executed every second") // ADDED
console.log("Fire!") // ADDED
createSprite(spawner.x,spawner.y,4,4);
console.log("Done") // ADDED
},1000);
console.log("Next line executed only once") // ADDED
spawner.velocityX=5;
// The fact that it's placed after setInterval() does mean that
// it will be executed after call to setInterval()
// but it doesn't mean that it will be executed after the function passed to setInterval(). Let's call it fire(), shall we?
// Actually, the fire() function will be called only after all the code in this file
// And setInterval() is also called only once, only the fire() passed to it called every second
function draw() { // Here you don't call draw() you only define it, so that code.org can call it whenever it wants
// looking at the code draw function we can't tell when or how often it's called
// it depends on the implementation details of code.org.
// We can add console.log to find out
console.log("Draw called") // ADDED
background("white");
createEdgeSprites();
spawner.bounceOff(edges);
drawSprites();
}
console.log("'fire()' not called yet") // ADDED
Console logs can be seeing in Debug Console of studio.code.org. It opens with a click on Debug Commands. Use it! I mean console.log(). I could also say "use Debug Commands!" but debug is poorly implemented in studio.code.org and can be misleading... You should definitely give it a try, but your trust you should put in console.log().

Upload Image to Canvas p5js

I am a beginner at p5js, and I was learning how to upload an image. This is my code:
PImage img;
function setup() {
size(1400, 1400)
img = loadImage("india-map.gif");
}
function draw() {
background(0)
image(img, 100, 100);
}
When I run it, it says that there is a problem with line 1. The error message reads:
SyntaxError: Expected ;but found img.
I don't know what this means and what I should do. Can anyone help me?
Edit:
I changed the code to
var image1;
function preload(){
image1= loadImage("india-map.jpg");
}
function setup(){
creatCanvas(1350,600)
}
function draw(){
image(image1, 100, 100);
}
My page just says ...loading without loading any image.
In addition to kemicofa great answer, I think it is also important to note the loadImage is asynchronous. This means that when we call loadImage it will take some time for the method to retrieve and load the image data into memory. As a result of this, loadImage doesn't happen instantly like the rest of your code.
Thus, while your image is being loaded, the rest of your code is still able to run, including the draw method. This means that if your draw method only runs once (you can make it run only once by using noLoop(), your image will not be displayed because it hasn't yet been loaded in.
There are a couple of solutions to this issue such as using a callback. However, p5js offers another method which runs before setup called preload. In this function, you can load your image to make sure that it is ready for setup and draw to use.
Using all these ideas you will end up with code which looks somewhat like:
let img;
function preload() {
img = loadImage('india-map.gif'); // load media and other data
}
function setup() { // only executed once preload is has finished loading data
createCanvas(400, 400);
}
function draw() { // only executed once preload is has finished loading data
image(img, 0, 0, width, height);
noLoop(); // stop draw from looping (to show img has been loaded)
}
You can find a working example here
Explanation:
PImage is a type coming from the Processing3 library.
In javascript, when declaring a variable use const, let or var.
Additionally, the size method comes from Processing3 as well. Instead use createCanvas method and pass the size as a parameter.
Go over the documentation and make sure the methods you wish to use exist.
Solution:
let img;
function setup() {
createCanvas(100, 50);
img = loadImage("india-map.gif");
}
function draw() {
background(0);
image(img, 100, 100);
}

Random Ball Speed in P5.js

I have the following code:
var posX1 = 0, posY1 = 100;
var speedX1 = random(1,3), speedY1 = random(1,3);
var posX2 = 0, posY2 = 200;
var speedX2 = 2, speedY2 = 0;
function setup()
{
createCanvas(640, 480);
}
function draw()
{
// redraw the background so you blank the screen
background(255);
if(posX1 > width)
{
speedX1 = -speedX1;
}
// update the position based on the speed
posX1 += speedX1;
posY1 += speedY1;
// draw a ball
strokeWeight(20);
point(posX1, posY1);
//
posX2 += speedX2;
posY2 += speedY2;
//draw a ball
strokeWeight(20);
point(posX2, posY2);
}
Its in P5. I basically want the two circles to race each other at random speeds between 1 and 3 but instead they dont even appear on the screen. Can anyone point out where I'm going wrong?
You can't use P5.js functions before setup() is called.
If you run this code and look at the JavaScript console (which should always be your first step) you'll see that you're getting an error saying that random() is not defined. If you then Google that error, you'll get a ton of results explaining what's going on.
From the P5.js FAQ:
Why can't I assign variables using p5 functions and variables before setup()?
The explanation for this is a little complicated, but it has to do
with the way the library is setup in order to support both global and
instance mode. To understand what's happening, let's first look at the
order things happen when a page with p5 is loaded (in global mode).
Scripts in <head> are loaded.
<body> of HTML page loads (when this is complete, the onload event fires, which then triggers step 3).
p5 is started, all functions are added to the global namespace.
So the issue is that the scripts are loaded and evaluated before p5 is
started, when it's not yet aware of the p5 variables. If we try to
call them here, they will cause an error. However, when we use p5
function calls inside setup() and draw() this is ok, because the
browser doesn't look inside functions when the scripts are first
loaded. This is because the setup() and draw() functions are not
called in the user code, they are only defined, so the stuff inside of
them isn't run or evaluated yet.
It's not until p5 is started up that the setup() function is actually
run (p5 calls it for you), and at this point, the p5 functions exist
in the global namespace.
In other words, you have to define your variables at the top of your sketch, but only assign them inside the setup() function:
var speedX1;
var speedY1;
function setup()
{
createCanvas(640, 480);
speedX1 = random(1,3);
speedY1 = random(1,3);
}

Javascript Uncaught TypeError: undefined is not a function

I am trying to make a simple game using the Phaser engine, but I keep getting the above error.
var mainState = {
...
playerJump: function(){
yVelocity = -jumpPower;
},
spacePressed: function(){
if(started)
{
return;
}
started = true;
this.playerJump();
},
...
updatePlayer: function(){
if(player.body.x < game.world.centerX)
{
player.body.x += xVelocity;
}
player.body.y += yVelocity;
yVelocity += gravity;
if(player.body.y + player.body.height > floor)
{
this.playerJump();
}
},
...}
As you can see I have defined the function playerJump. All variables you see in the sample are properly defined and working. When I call the function "playerJump" from "updatePlayer" I get no error. However, if I try to call it from "spacePressed" I get the "undefined is not a function exception.
The engine I am using is Phaser and all of my code is in one file, if that makes any difference. The function "spacePressed" is invoked from a callback function when the key is pressed. The "updatePlayer" on is called from the main Update loop of the game.
Do you have any ideas why this might be happening? Why am does it work when I call it from one function but not from the other? Happy to provide more code and details if necessary.
When you use a object method as an event handler or a callback function,
this will no longer refer to the object.
The simplest way to solve this:
var mainState = { ... };
element.addEventListener(type, mainState.spacePressed.bind(mainState), false);
This method might not be supported with every browser / version so you can use this instead:
var mainState = { ... };
element.addEventListener(type, function() {
mainState.spacePressed.call(mainState);
}, false);
I assume you have created an input handler to detect if space is pressed.
This is the code to detect a mouse click on a button (for example). Just pass in "this" to the second parameter so that the callback will receive the mainState context, so that you can invoke this.playerJump()later on.
spaceButton.events.onInputDown.add(this.spacePressed,this)
will solve your problem when you call this.playerJump() inside the spacePressed() method.

Javascript Image.onload callback to object function

This is driving me nuts - I have been round and round in circles, and this no joy. I am loading multiple dynamic images, and have a simple Javascript object which I instantiate for each image, and which has a callback to render the image once it has loaded asynchronously.
I have verified that the callback code works just fine on a stand-alone basis (ie. I can call the callback 'manually' after the image has loaded, and the image is rendered correctly), and I have verified that the image itself is successfully loaded (by switching the object's callback for a simple one line logging function), but when I try to tie it all together, the callback apparently never gets invoked.
I'm relatively new to JS and I suspect that I am missing something fundamental about the way functions within objects are defined, but despite a lot of Googling, can't work out what.
Please can someone show me the error of my ways?
function ImageHolder(aX,aY,aW,aH, anImageURL) {
this.posx=aX;
this.posy=aY;
this.posw=aW;
this.posh=aH;
this.url=anImageURL;
this.myImage = new Image();
this.myImage.onload=this.onload;
this.myImage.src=anImageURL;
this.onload=function() {
try {
var d=document.getElementById("d");
var mycanvas=d.getContext('2d');
mycanvas.drawImage(this.myImage, this.posx, this.posy, this.posw, this.posh);
} catch(err) {
console.log('Onload: could not draw image '+this.url);
console.log(err);
}
};
}
You have two problems: first, this.onload is not defined at the point at which you assign it to the image. You can fix this by missing out the stage of storing the onload handler function as a property of this. The second problem is that when the onload handler function is called, this is not set to what you think it is (in fact, it's a reference to the Image object that has just loaded). You need to store a reference to the current ImageHolder object and use it instead of this within the event handler function.
New code:
var that = this;
this.myImage = new Image();
this.myImage.onload=function() {
try {
var d=document.getElementById("d");
var mycanvas=d.getContext('2d');
mycanvas.drawImage(that.myImage, that.posx, that.posy, that.posw, that.posh);
} catch(err) {
console.log('Onload: could not draw image '+that.url);
console.log(err);
}
};
this.myImage.src = anImageURL;

Categories

Resources