I've recently made the leap from using Khan Academy's processing.js environment to the real deal and am getting a little confused.
I have a simple processing.js program that basically draws a circle, and I want the size of this circle to be determined by the width of the canvas.
If I print the width within a processing.js function, like setup, I'm shown the correct 500px width. Unfortunately, whenever I try to access the width property outside of a processing.js function, it shows the default 100px size, even though the canvas itself is 500px wide.
I think I might be using a fairly ugly mix of processing and javascript, which could be the root of my problems. Your help would be much appreciated!
Processing.js
///* PROCESSING.JS SETUP *///
void setup() {
size(500, 500);
println(width); // WORKS! :)
}
println(width); // DOESN'T WORK... :(
///* GLOBAL VARIABLES *///
var moleculeQuantity = 1;
///* OBJECT CONSTUCTORS *///
var Molecule = function(x, y) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
};
Molecule.prototype.draw = function() {
noStroke();
fill(88, 91, 183);
ellipse(this.x, this.y, 70, 70);
fill(225, 227, 228);
ellipse(this.x, this.y, 40, 40);
};
// Fill array with molecule objects
var molecules = [];
for (var i = 0; i < moleculeQuantity; i++) {
molecules[i] = new Molecule(200, 100);
}
///* DRAW FUNCTION *///
void draw() {
background(225, 227, 228);
molecules[0].draw();
}
Your problem has nothing to do with mixing Processing and JavaScript, and it has nothing to do with asynchronous execution. It's much simpler than that.
Think of the order your code executes in. Anything outside of a method will execute before your setup() function is called. In your case, that means you're accessing the width variable before you've changed it by calling the size() function.
You have to change your code so that your code is triggered after setup() is called. The simplest way to do that is to just move your code to the end of your setup() function, or into a function that's called after setup(), such as the draw() or event methods.
You might think that because your function call is below the setup() function in your code that the setup() call happens first, but it doesn't. You've simply defined the setup() function- it hasn't been called (by Processing) yet! Try moving any code that's outside of a function to the top of your sketch to make it more obvious:
println(width); // this happens first, so width is still 100
void setup() {
size(500, 500);
println(width); //now that size() has been called, the width is 500
}
Edit: I'll try to explain the order of events. Here is what happens when you load a page that contains a Processing.js sketch:
The page is loaded.
Processing.js itself is loaded.
Processing.js compiles your Processing code into JavaScript code.
Your code (which is now JavaScript code) is loaded. Functions like setup() and draw() are defined at this step, but not called yet. Code outside of your functions is called. This is when you see 100 being printed out.
Processing.js calls the setup() function that was defined in step 4. This is when the width is set.
Processing.js starts calling the draw() function 60 times per second.
As for where you should place your variables and functions, that completely depends on what you want to do with them. But you might place a variable's declaration at the top of your sketch and its initialization inside the setup() function. That way you can access its value anywhere, but you know it won't be set until setup() has run. Something like this:
float middleX;
void setup(){
size(500, 500);
middleX = width/2;
}
void draw(){
background(0);
ellipse(middleX, mouseY, 10, 10);
}
Related
I am trying to make my cursor be a PNG image that I have already preloaded in an art game I am designing on P5.js.
I have tried so many things, but it still won't work!
Can someone please let me know where to put the cursor function as well as what to put inside the parentheses? Thanks so much!
function preload() {
uImg = loadImage('assets/ufo.png');
rImg = loadImage('assets/asteroid.png');
bImg3 = loadImage('assets/bimg3.jpg');
}
function setup() {
createCanvas(1200, 600);
mode = 3; //level 3 in game
noCursor();
}
// END OF SET UP
function draw() {
levelThree();
}
// END OF DRAW
function levelThree() {
clear();
if (mode == 3) {
lost = false;
score = 0;
background(bImg3);
cursor(uImg,mouseX,mouseY);
}
}
I think simply using image() instead of cursor() will do what you want. I don't know why, but I think that when using cursor() you can't input a p5.Image, you have to put a string of a URL to an image that exists on the internet.
Also, when using cursor(), the other two parameters should be between 0 and 31. They describe where the "active point" of the cursor is, relative to where the actual mouse point is.
You could just do something like this:
let img
function preload(){
img = loadImage('cursor.png')
}
function setup() {
createCanvas(400, 400);
imageMode(CENTER)
noCursor()
}
function draw() {
background(20);
image(img,mouseX,mouseY)
}
And you should put the option stuff in setup() so the imageMode() and fill() and idk rectMode()... in setup, though what ever you're going to draw multiple times in draw() and you should load images in preload, cause javascript doesn't reallly care if images are loaded in or not and callback functions are meh, preload is good in my opinion. I also don't think that you really need the assets in assets/image.png
And also why exactly do you have mouseX and mouseY in the cursor() at the end of your code snippet???
hope this is actually answering the right question...
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.
I need to draw fractal using js turtle library so, the fractal is animated until it is drawn totally like the python turtle example here
I've tried in the command here. There's a function called animate in the docs but I'm not able to use it, it only waits for some time then draw the fractal without any animation.
I type in the command input animate(demo, 1000)
Is there any suggestion?
if I can't use animation in js turtle Is there another fast easy library that can do the job of drawing fractals?!
You're not using animate() correctly. You can't just apply it to a finished program and expect its behavior to change. Instead, you need to incorporate it into the program. There should be a function that draws a portion of the animation each time it's called. Then have it called over and over by animate(). Rewritting your example:
function square(side) {
repeat(4, function () {
forward(side);
right(90);
});
}
var s = 100
function draw() {
square(s);
right(36)
s -= 10
if (s < 0) {
s = 100
clear()
}
}
function demo() {
hideTurtle();
colour(0, 0, 255, 1);
animate(draw, 500);
}
Invoke it via demo(), don't call animate() on it. It's basic animation unit is the square. If you want to see the squares being drawn, then you need to redesign the code to make the basic animation unit the side of a square (i.e. line.)
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);
}
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);
}