How do I assign a variable to an array in p5*js? - javascript

Here is my code:
var icons = [0]
var iconsx = [10]
var iconsy = [10]
var jog = 0
var iconxbuffer
var iconybuffer
function setup() {
createCanvas(650, 500);
}
function draw() {
background(255,199,248);
fill(255,248,184);
rect(175, 435, 300, 55, 45);
fill(255,38,241)
if (mouseIsPressed === true){
rect(winMouseX, winMouseY, 45, 55)
let iconsx[0] = winMouseX}
else{let iconxbuffer = iconsx[0]; let iconybuffer = iconsy[0]
rect(iconxbuffer, iconybuffer, 45, 55)}
console.log (iconsx)
}
On line 23 I attempt to assign winMouseX to iconsx[0], but when I run this code, I get the error:
🌸 p5.js says:
Syntax Error - Symbol present at a place that wasn't expected.
Usually this is due to a typo. Check the line number in the error for anything missing/extra.
+ More info: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Unexpected_token#What_went_wrong
I believe I understand the logic here because I am assigning iconsx[0] to the last location of the mouse when the mouse button was being held down in order to print the rectangle to this coordinate even after releasing the mouse button. There must be some weird p5*js syntax I am not understanding because I am not very familiar with JavaScript.
I have already tried leaving out the bracket in hopes js would default to the first value in the array, but it didn't work instead there was no change to the variable. I had a similar problem earlier in the development process were on line 26 I was trying to print the rectangle to iconsx[0] and iconsy[0]. When I ran this code, I got a similar error in which JavaScript said there was a syntax error relating to the use of "[" after the variable name. To counter this I mad the variables iconxbuffer and iconybuffer and then before printing the rectangle made iconxbuffer and iconybuffer equal iconsx[0] and iconsy[0] then made js print the rectangle print to iconxbuffer and iconybuffer instead which at that point equaled the first variables I was trying to print to. But I don't believe this would not function as a viable solution to my new problem because I am trying to assign a value to a variable not read from a preexisting variable.

Ok, so there are a few problems here.
First thing is that your code is extremely messy and is not indented correctly.
All your variables at the top have already been defined, so you get an error when you try to define them again. eg:
var x = 0;//remember a semicolon at the end of a line of code
let y = 1;
var x = y;//incorrect
let x = y;//incorrect
x=y;//correct
//"let" and "var" are basically the same thing.
Here is what your code should look like.
var icons = [0];
var iconsx = [10];
var iconsy = [10];
var jog = 0;
var iconxbuffer;
var iconybuffer;
function setup() {
createCanvas(650, 500);
}
function draw() {
background(255,199,248);
fill(255,248,184);
rect(175, 435, 300, 55, 45);
fill(255,38,241)
if (mouseIsPressed === true){
rect(winMouseX, winMouseY, 45, 55)
//Also, what is winMouseX? Did you mean mouseX?
//don't put let or var next to a variable already defined
iconsx[0] = winMouseX
}
else{
iconxbuffer = iconsx[0];
iconybuffer = iconsy[0]
rect(iconxbuffer, iconybuffer, 45, 55)}
console.log (iconsx)
}
}
//This should not return error. If it does and it says winMouseX not defined than replace it with mouseX and mouseY and it should work

Related

Cant set origin for an element in JavaScript

I am making a simple game in js which consists of a grid and some cells
This is what it currently looks like and it works perfectly. The thing is that while making this I set the margin to 0 but I
would like to move the canvas to center. To do that, I got the margin from this function
var test = document.querySelector('.test');
var left_margin = window.getComputedStyle(test).getPropertyValue("margin-
left "); // returns margin e.g. '655px'
left_margin = left_margin.match(/\d+/);
Then I made some changes in the whole thing to account for this offset but for some reason when I try to add the offset to the x-axis, it returns NaN. To make sure there wasnt some problem I performed some basic mathematical operations on this value and they worked. Can someone tell me what is going on with this? and also, is there a simple way to just redefine the origin for an element(a canvas in my case), to avoid this hassle?
Edit:
I dont understand this. When i simply do var a = blockWidth + 0;The game doesnt start and then do console.log(a) this also return NaN. and i get**(Uncaught TypeError: Cannot set property 'strokeStyle' of undefined)**
function grid(){
var a = blockWidth + left_margin;
var b = blockHeight;
while (a != widthWin){
drawLine(a, 0, a, heightWin, 1, 'gray');
a += blockWidth;
}
while (b != heightWin){
drawLine(left_margin, b, widthWin+left_margin, b, 1, 'gray');
b += blockHeight;
}
}
What you get with
left_margin = left_margin.match(/\d+/);
is an array ["655"] not an int as you are assuming.
Therefore, you need to access its first element and parse it to a number before using it for doing any math:
left_margin = parseInt(left_margin.match(/\d+/)[0]);

Getting TypeError when trying to call multiline string in p5.js

I've been trying to work out a solution for taking single-line sentences (which I call "statements" in my code) and turning them into multiline sentences on my sketch. This question relates directly to another question I posted on SO, and I have been asked to post this new issue as a new question.
The solution from #KevinWorkman got me the to this point. What's happening, though, is that I'm getting a TypeError: Cannot read property 'display' of undefined when I try to run the program. The sketch loads, but when I click within the sketch to start the animation, I get that error. I think it's because my original statements[] array is now no longer of a type that can be called in my draw() function as it is. But I'm not knowledgeable enough to know what the issue is and I've looked through all of my JS and p5.js references and can't find a solution.
I'm posting my complete code in an effort to provide a minimal, complete, verifiable example. Despite the fact, as a writer, I find "minimal" and "complete" to be contradictory terms and, therefore, very confusing, here goes:
var clContext;
var speed = 0.8;
var statements = [];
var canvas;
//load the table of Clinton's statements and their polarity
function preload() {
clContext = loadTable("cl_context_rev.csv", "header");
}
function setup() {
canvas = createCanvas(680, 420);
canvas.mousePressed(inWidth);
background(51);
noStroke();
// iterate over the table rows called in 'preload()' from .csv file
for (var i = 0; i < clContext.getRowCount(); i++) {
var statement = clContext.get(i, "statement");
var polarity = clContext.get(i, "polarity");
}
statements[i] = new Statement(polarity, statement);
}
function draw() {
if (mouseIsPressed) {
background(51);
for (var i = 0; i < statements.length; i++) {
statements[i].display();
}
}
}
// Function to align statements, categories, and polarity
function Statement(polarity, statement) {
// Break up single-line statements in order to display as multiline
this.statement = split(statement, "<br>");
this.polarity = polarity;
this.x = random(width);
this.y = random(height);
this.dx = random(-speed, speed);
this.dy = random(-speed, speed);
}
// Attach pseudo-class methods to prototype;
// Maps polarity to color and x,y to random placement on canvas
Statement.prototype.display = function() {
this.x += this.dx;
this.y += this.dy;
// Make statements reappear if they move off of the sketch display
if(this.x > width+10){
this.x = -10
}
if(this.y > height+10) {
this.y = -10
}
// Map positive/negative statements to colors
if(this.polarity == -1){
fill(229,121,59);
}
else if(this.polarity == 1){
fill(97,93,178);
}
textSize(14);
// Was directed to add both 'text' statements
text(this.statement[0], this.x, this.y);
text(this.statement[1], this.x, this.y+25);
}
// Create functions for hiding and showing statements
function inWidth() {
width = width+5;
};
Note:
console.log(typeof this.statement[0]) // returns 'undefined'
console.log(typeof this.statement[1]) // returns 'undefined'
console.log(split(statement, "<br>")) // returns 'undefined'
console.log(statements) // returns 'object'
console.log(statements.length) // returns 20
for (var i = 0; i < clContext.getRowCount(); i++) {
var statement = clContext.get(i, "statement");
var polarity = clContext.get(i, "polarity");
}
statements[i] = new Statement(polarity, statement);
I think the last line here should be inside the for loop for this to do what you want.
Your error means that you are trying to call the display() method on a value that's undefined. The only place you are calling the display() method is inside your draw() function, when you loop through the statements array. This means that at one point your statements array contains an undefined value. You can verify this, by console logging the array.
I suspect the reason why you have undefined values, is because when you attempt to fill up the statements array in the setup() function, you only call statements[i] = once, after your for loop has finished. At this point the value of i is whatever it was at the end of the for loop, therefore your statements array becomes an array, where the i-th element is whatever you've set it, all the previous elements are undefined.
correct code:
for (var i = 0; i < clContext.getRowCount(); i++) {
var statement = clContext.get(i, "statement");
var polarity = clContext.get(i, "polarity");
statements[i] = new Statement(polarity, statement);
// OR statements.push(new Statement(polarity, statement));
}
As a generic JavaScript coding style principle it's also a good idea to Array.push() instead of direct assignment to add items to an array.
Marton's answer is correct. I'm giving it an upvote, and I think you should accept it. But I'll try to expand on it, since I'm not sure you're understanding what it's saying.
Let's look at these lines:
for (var i = 0; i < clContext.getRowCount(); i++) {
var statement = clContext.get(i, "statement");
var polarity = clContext.get(i, "polarity");
}
statements[i] = new Statement(polarity, statement);
Please run through this code with some example data. Let's say that you have 3 rows.
The first time you run through the loop, i is 0. You get a statement and a polarity, but you don't do anything with them.
The second time you run through the loop, i is 1. You get a statement and a polarity, but you don't do anything with them.
The third time you run through the loop, i is 2. You get a statement and a polarity, but you don't do anything with them.
The loop then exits. The statement and polarity variables go out of scope, so they're undefined. Same with the i variable.
Basically, that loop doesn't do anything. We then get to this line:
statements[i] = new Statement(polarity, statement);
But we know that i, polarity, and statement are undefined, so what you're really doing is this:
statements[undefined] = new Statement(undefined, undefined);
You say that this use to work, but I highly doubt that. What you're doing here doesn't make any sense. That statement definitely belongs inside the for loop, which is where it was in my answer to your other question.
But with how you have it now, nothing has been added to the array, except maybe something at an undefined index. So then we get to this line:
for (var i = 0; i < statements.length; i++) {
statements[i].display();
}
Now, I'd bet that statements.length is 1, since you have something at one undefined index (maybe that index is the last value of i, I don't know). But you certainly don't have anything at index 0. So then when you enter this loop, i is 0, but you don't have anything at that index. In other words, statements[0] is undefined. So the inner line is really doing this:
undefined.display();
That's what's causing your error. Fixing the first problem will get rid of this error, since you'll actually be adding stuff to your array.
Also, please note that these lines:
// Was directed to add both 'text' statements
text(this.statement[0], this.x, this.y);
text(this.statement[1], this.x, this.y+25);
This code I gave you was just an example. You're going to have to do something more intelligent here. I was just showing you how you might access two indexes of the statement array. You'll have to actually check the length of this array and loop through the sentences to do something. What that is depends entirely on what you want to happen.
On General Debugging
You seem to be having a lot of issues because you're trying to do everything at once. You'll save yourself a lot of headaches if you start working in smaller chunks. Instead of trying to add this functionality to your big main sketch, why don't you try to get a smaller example sketch working first? Try hardcoding the values so you can see exactly what's happening with the split() function. Use println() statements to understand what's going on. Trying to add everything all at once is just going to be confusing, for you and for us.
Please note that this is not a request for an MCVE (since you got angry last time I mentioned it), but honestly, the best thing you can do to help yourself is to start working in smaller steps.
You might also consider switching to regular Processing (Java mode), since it can give you more information on errors like this.
I was finally able to fix this with a few easy changes to the code. It seems so very obvious once I thought of it that I'm not at all sure why it took me so long to figure it out.
I started by making changes to the setup() code:
function setup() {
canvas = createCanvas(680, 420);
canvas.mousePressed(inWidth);
background(51);
noStroke();
// iterate over the table rows called in 'preload()' from .csv file
for (var i = 0; i < clContext.getRowCount(); i++) {
var statement = clContext.get(i, "statement");
var polarity = clContext.get(i, "polarity");
var stateSplit = split(statement, "<br>"); // split the statements in setup to avoid issues elsewhere
for (var j = 0; j < stateSplit.length; j++) {
var stateJoin = join(stateSplit, "\n"); // join the statements, inserting a line break, to make a new array
statements[i] = new Statement(polarity, stateJoin); // put this in the for loop (per #marton)
}
}
}
Then I modified my constructor and prototype display function as follows:
Got rid of this, since it only broke up the statements, but didn't join them:
this.statement = split(statement, "<br>");
And replaced it with this:
this.stateJoin = stateJoin;
Then I got rid of these:
text(this.statement[0], this.x, this.y);
text(this.statement[1], this.x, this.y+25);
And used this, instead:
text(this.stateJoin, this.x, this.y)
And voila! Thanks to #marton and #KevinWorkman for suggestions.

Unable to dynamically increment a property of an object

I'm trying to create a dynamic canvas animation using javascript. The intent is to increment the x property of many image objects and then draw them in the x position of the updated x property each time a draw() function runs. I'm not able to successfully increment this x property though - for some reason it always resets to 0.
I defined this global array to contain all the objects I will draw:
window.character = [];
I have this object constructor to create new image objects:
function Character(name, x, y){
//define the image object within the Character
this.imageObject = new Image();
this.imageObject.src = name+'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAW0lEQVR42mL8//8/AzpgZGTcC6KBcs5wMRwK/0MVMsLEmLAoEmXAApiwiKUhaRJCltgLsQVsWwIQ/wTx0fBeRigD7B6Y24i1mj4Kn4KI7Uie2Y7FI8+B2AMgwABjRynfWgpcxQAAAABJRU5ErkJggg==';
window.character.push(this);
window.characterPosition = window.character.indexOf(this);
//set natural width and natural height once the image is loaded
if (this.imageObject.addEventListener){
this.imageObject.addEventListener('load', function(){
window.imgWidth = this.naturalWidth/2;
window.imgHeight = this.naturalHeight/2;
//set natural width and natural height to object
window.character[characterPosition]['imageObject']['w'] = window.character[characterPosition]['imageObject']['w0'] = window.imgWidth;
window.character[characterPosition]['imageObject']['h'] = window.character[characterPosition]['imageObject']['h0'] = window.imgHeight;
//set initial x and y position
console.log(x);
window.character[characterPosition]['imageObject']['x'] = x;
window.character[characterPosition]['imageObject']['y'] = y;
console.log(window.character[characterPosition]['imageObject']['x']);
//set loaded property for the object once loading is done
window.character[characterPosition]['imageObject']['loaded'] = true;
function imageLoaded(element, index, array){
return element['imageObject']['loaded'] == true;
}
//test whether every object in array has the image loaded
if(character.every(imageLoaded)){
$('button#play').show();
};
});
} //end object constructor
Inside that constructor function, there is some weird behavior. I created a new object using:
var sun0 = new Character('data:text/javascript;base64,', 12, 12);
Then here's what I see from the console.log messages inside the object constructor:
console.log(x); //returns 12, as expected
window.character[characterPosition]['imageObject']['x'] = x;
window.character[characterPosition]['imageObject']['y'] = y;
console.log(window.character[characterPosition]['imageObject']['x']); //returns 0. Thought it would be 12
Ultimately, here's how I intend to animate the object across the screen. This draw() function runs on an interval every 10ms.
function draw(){
clear();
//draw characters
drawCharacter(window.character[0]['imageObject'],window.character[0]['imageObject']['x'],window.character[0]['imageObject']['y'],window.character[0]['imageObject']['w'],window.character[0]['imageObject']['h']);
window.character[0]['imageObject']['x'] += 10;
console.log(window.character[0]['imageObject']['x']); //returning 0 every time, not incrementing the way I expected it to.
}
How can I get this 'x' property to increment?
here's the JS Fiddle
Pointy answered your question in the comments, but to expand on this... you're trying to set x on an Image which can't be set. For instance, try this in your browser's console:
var img = new Image();
img.x = 1;
console.log(img.x); // this will be zero
That's effectively what you're doing. Additionally, in your code try changing ['x'] to ['myX'] and then it will work as expected.

Argument 1 of CanvasRenderingContext2D.drawImage could not be converted ( attempting draw image on canvas object )

I am trying to make a cache of objects that can be used with canvas.drawImage() to display images but only draw them once. I keep getting this error, I have tried some answers found online like: canvasObject.get(0) and canvasObject[0] and unwrap(canvasObject) before putting them in the draw context, but none of that works. I cant find anything on it. hopefully someone can help. here is my code:
var canvas = full canvas that cached drawings should draw to
var temp = {};
var h = heightOfGridSquare;
var w = widthOfGridSquare;
var canvasElementForCache = document.createElement('canvas');
canvasElementForCache.width = w * 2; // so that i can draw pictures larger then single grid square
canvasElementForCache.height = h * 2;
var cachedCanvas = canvasElementForCache.getContext(ctx);
// cache drawing in app object
var cacheDrawing = function ( name ){
app.cache[name] = objectRepo[name](cachedCanvas);
};
var objectRepo = {
someObjectName: function (canv) {
var m = temp.coordinates;
canv.fillStyle = "rgba(0,0,200,0.9)";
canv.fillRect(m.x + 25, m.y + 25,50, 50); // random filler (x and y are coordinates defined in the draw object funciton )
return canv;
},
};
var drawObejectAtCoordinates = function ( x, y ) {
var px = ( x - ( w / 2 ));
var py = ( y + ( h / 2 ));
if ( app.cache[name] === undefined ){
temp.coordinates = { x:px, y:py };
cacheDrawing(name);
}
// drawing on actual canvas
canvas.drawImage( app.cache[name], px, py );
};
var render = function () {
drawObejectAtCoordinates( coordinateX, coordinateY );
// this is just a place holder, my actual code is very long and has different rendering methods..
// just know that it is being rendered ( not super important though since the error occurs at drawImage not render )
window.requestAnimationFrame(render);
}
this mostly exact, i have changed small parts for brevity.. but there is nothing left out that would be related to the issue im having. if anyone can help I would appreciate it greatly!
the error message is:
TypeError: Argument 1 of CanvasRenderingContext2D.drawImage could not be converted to any of: HTMLImageElement, HTMLCanvasElement, HTMLVideoElement.
and when I console log the contents of the cached canvas object it looks like this:
CanvasRenderingContext2D { canvas: <canvas>, globalAlpha: 1, globalCompositeOperation: "source-over", strokeStyle: "#41471d", fillStyle: "#ff8800", shadowOffsetX: 0, shadowOffsetY: 0, shadowBlur: 0, shadowColor: "rgba(0, 0, 0, 0)", mozCurrentTransform: Array[6] }
heres a jsFiddle example: https://jsfiddle.net/1krgqeq7/3/
There are a number of issues here that make this code rather difficult to follow:
1) You are reusing the variable cachedDrawing in a confusing way (is it an element or a function?)
2) You use a variable named temp which is usually a code smell, especially when you don't use it close to its declaration (not present in the code sample). Its also not clear why your stashing coords in there.
3) You use a fair number of descriptive variable names but in addition to temp you also use the rather non-descript 'obj'
But the answer to your question (related to 1 above) is that you are passing a context, not the canvas it was gotten from. Don't reassign that var and pass it into the cache instead.
Problems like this will likely be easier to spot with more descriptive variable names like cachedCanvas being a canvas and cachedCtx being its context.

JSON corrupted attributes

I'm having difficulties understanding behavior of Javascript.
Code:
function getPosition(element){
var position = {
x:$(".line div").has(element).index(),
y:$(".line").has(element).index()
};
console.log(position.y);
console.log(position)
return position;
}
Now while calling it from function I'm getting results like this:
0
Object
x: 8
y: 3
What I don't understand is how is it possible to change object attributes when trying to access it via object reference, but not directly.
But when I call same function from console I get this:
0
Object
x: 8
y: 0
This is the same element passed to function. And it seems that it fails always when X or Y is 0(zero), when it's another number it's ok.
Could anyone explain what I'm doing wrong? Or is it somekind of JS bug? O_o
EDIT:
So I finally found out what the problem was. I always thought that I was passing values but unfortunately I was wrong all the time. During some searches on stackoverflow, I found topic about JS values and references.
If anyone is interested and too lazy to read the topic, you can look at this example. It's pretty much self explanatory.
function test(){
var a = 5;
var b = a; //b now has value of 5
console.log("a:"+a+":b:"+b);
b = 4;//a still has value of 5 and b is assinged to 4
console.log("a:"+a+":b:"+b);
var c = {val:1};
var d = c; //d now has reference to c
d.val = 2; //c.val changes because it is a reference
console.log(c);
}
EDIT2:
oh and by the way, how can I mark my question as answered?
console.log delays converting values to string until the application slows down so that logging doesn't slow down the application unnecessarily.
If the console.log(position) is showing a value that is different from that at the time console.log was called its because the position has been modified between the call and the time the console widget decided to format the value for display.
You can see this by trying the following HTML:
<script>
// Emits the JSON form when converted to a string.
var obj = {
x: 1,
toString: function () {
return JSON.stringify(this);
}
};
console.log(obj); // Often {x:2}
console.log("" + obj); // Reliably {x:1}
obj.x = 2;
</script>
Look for code that does something like
obj = getPosition(...);
...
obj.y = <expression that evaluates to zero>
Alternatively, you can force eager formatting by changing
console.log(position)
to
console.log("" + position)
So I finally found out what the problem was. I always thought that I was passing values but unfortunately I was wrong all the time. During some searches on stackoverflow, I found topic about JS values and references.
If anyone is interested and too lazy to read the topic, you can look at this example. It's pretty much self explanatory.
function test(){
var a = 5;
var b = a; //b now has value of 5
console.log("a:"+a+":b:"+b);
b = 4;//a still has value of 5 and b is assinged to 4
console.log("a:"+a+":b:"+b);
var c = {val:1};
var d = c; //d now has reference to c
d.val = 2; //c.val changes because it is a reference
console.log(c);
}

Categories