P5.JS .show() is not a function, why? - javascript

Not sure if i'm getting the scope wrong but iv'e tried moving the function around a bit but it just gives me that is not a function error.
let bubbles = [];
function setup() {
createCanvas(400, 400);
for (let i = 0; i < 10; i++){
bubbles[i] = new Bubble(200, 200, 40)
}
}
function draw() {
background(0);
for (i = 0; i < bubbles.length; i++){
bubbles[i].show();
}}
function show() {
stroke(20);
strokeWeight(2);
fill(random(255), 0, random(255))
ellipse(this.x, this.y, this.r * 2)
}
class Bubble {
constuctor(x, y, r){
this.x = x;
this.y = y;
this.r = r;
}}

As said in the comments by Rabbid76, your main problem is that you are calling a function within the Bubble object which doesn't exist. So you should pop that into the Bubble class:
class Bubble {
constructor(x, y, r){
this.x = x;
this.y = y;
this.r = r;
}
show() {
stroke(20);
strokeWeight(2);
fill(random(255), 0, random(255))
ellipse(this.x, this.y, this.r * 2)
}
}
Also, just so you know you misspelt constructor and if you're using the p5 online editor it doesn't flag it as an error, it thinks you've defined a new function called constuctor it is completely valid syntax.
One more thing, you are passing in the x and y location of each bubble as 200, 200, which basically means each bubble is going to be on top of each other, I'm assuming you'd want them to be spread out around the screen:
bubbles[i] = new Bubble(random(width), random(height), 20);
Oh and also, you may want to store the r,g,b colours in the Bubble object so it doesn't choose a new colour each frame!

Related

Beginner here. Code isn't obeying. I think the problem has something to do with accessing a variable that's within a class?

So I'm learning about how to use classes and I've made this code (it's exactly 100 lines long!) using P5.JS which is just supposed to draw three rectangles and three circles. One of the circles is able to be moved with the arrow keys, and the other two follow that one around. Here's the part that doesn't work: when the follower circles move over the squares, it's supposed to make them slow down as they move over it. I've tried everything.
function setup() {
createCanvas(windowWidth, windowHeight);
noStroke();
character1 = new character(250, 200, 30, 4);
follower1 = new enemy(100, 20, 30, 2);
follower2 = new enemy(200, 20, 30, 2);
obstacle1 = new obstacle(200, 200, 100, 50, follower1.x, follower1.y, follower1.s);
obstacle2 = new obstacle(300, 300, 50, 25, follower1.x, follower1.y, follower1.s);
obstacle3 = new obstacle(200, 400, 25, 50, follower1.x, follower1.y, follower1.s);
}
function draw() {
background(0);
character1.drawCharacter();
follower1.drawEnemy();
follower2.drawEnemy();
obstacle2.drawObstacle();
obstacle1.drawObstacle();
obstacle3.drawObstacle();
}
class character {
constructor(x, y, d, s) {
this.x = x;
this.y = y;
this.d = d;
this.s = s;
}
drawCharacter() {
fill(255);
ellipse(character1.x, character1.y, character1.d);
if (keyIsDown(UP_ARROW)) {
character1.y -= character1.s;
}
if (keyIsDown(DOWN_ARROW)) {
character1.y += character1.s;
}
if (keyIsDown(LEFT_ARROW)) {
character1.x -= character1.s;
}
if (keyIsDown(RIGHT_ARROW)) {
character1.x += character1.s;
}
}
}
class enemy {
constructor(x, y, d, s) {
this.x = x;
this.y = y;
this.d = d;
this.s = s;
}
drawEnemy() {
fill(255, 0, 0);
ellipse(this.x, this.y, this.d);
if (this.x < character1.x - this.d) {
this.x += this.s;
}
if (this.x > character1.x + this.d) {
this.x -= this.s;
}
if (this.y < character1.y - this.d) {
this.y += this.s;
}
if (this.y > character1.y + this.d) {
this.y -= this.s;
}
}
}
class obstacle {
constructor(x, y, w, h, enemyX, enemyY, enemyS) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
enemyX = enemyX;
enemyY = enemyY;
enemyS = enemyS;
}
drawObstacle(enemyX, enemyY, enemyS) {
fill(255);
rectMode(CENTER);
rect(this.x, this.y, this.w, this.h);
if (
this.x - this.w / 2 - 10 < enemyX &&
this.x + this.w / 2 + 10 > enemyX &&
this.y - this.h / 2 - 10 < enemyY &&
this.y + this.h / 2 + 10 > enemyY
) {
enemyS = 0.5;
} else {
enemyS = 2.5;
}
}
}
Try only having one obstacle. Here's my guess:
draw calls obstacle.drawObstacle three times, and if an enemy should be slowed down by obstacle1 or obstacle2, it doesn't matter because enemy.s will be reset by obstacle3.drawObstacle
I highly recommend that each of your character and enemy class have a draw and a move method, and put everything about how enemies move within the enemy class. Maybe the obstacle class should have a draw and maybe a isCollidingWith method that enemy.move would call.
Keeping all your logic for an class within the class means that you can do variants much more easily. For example, maybe later you'll want to have an enemy that's much slower but isn't hindered by obstacles at all. Having all the logic within the class makes that easy. Putting the logic within the obstacle class would quickly become a nightmare if you have enough different types of enemies.
Also, you could have a game object that holds everything about the game including character, enemies, and obstacles properties and draw and move methods that call the respective methods on character, enemy, and obstacle objects, and a destroy or quit method that clears its properties and such. (In some languages this is important, because if you were to add a game property to each piece in the game, they'd have handles to each other and since (in some languages) garbage collection only reaps objects that have no references to them, they'll take up memory much longer than you want.)

Why will my animation not work if I declare my variable locally?

I'm quite new to JS so please excuse my ignorance but I can't figure out why my animation if statement doesn't work if I declare my speed variable locally in the move() function.
If I don't declare the speed variable globally, the girl gets to the windowWidth and gets stuck moving a couple of pixels back and forth. Basically staying there rather than moving the other way.
let speed = 2;
class Girl {
constructor(x, y) {
this.x = x,
this.y = y
}
body() {
noStroke();
fill(239, 101, 233);
rect(this.x, this.y, 20, 40);
fill(249, 192, 155);
triangle(this.x, this.y, this.x + 20, this.y, this.x + 10, this.y + 15);
}
move() {
if (this.x > windowWidth + 50 || this.x < -50) {
speed = speed * -1;
}
this.x = this.x + speed;
}
}
I should mention I'm using the p5 library in case I'm using any funky functions. It works but I'm sure I could tidy this up a little bit. Any advice would be more than welcome.
Thanks in advance!
You should not declare it as a local variable inside the move method (as that would make it get re-initialised to 2 on every call), but you should make it a property of the instance that gets initialised in the constructor and modified in the move method (just like x and y).
class Girl {
constructor(x, y) {
this.x = x;
this.y = y;
this.speed = 2;
}
body() {
noStroke();
fill(239, 101, 233);
rect(this.x, this.y, 20, 40);
fill(249, 192, 155);
triangle(this.x, this.y, this.x + 20, this.y, this.x + 10, this.y + 15);
}
move() {
if (this.x > windowWidth + 50 || this.x < -50) {
this.speed = this.speed * -1;
}
this.x = this.x + this.speed;
}
}
Because the value of speed is shared across multiple calls to move. If you declare it inside move then it gets created for each call to move, thus any previous value of speed will be ignored.
If you don't want speed to be a global variable, then you can make it a property of the class Girl:
class Girl {
constructor(x, y) {
this.x = x;
this.y = y;
this.speed = 2; // make 'speed' a property of the class
}
/* ... */
// use 'this.speed' inside 'move' instead of just 'speed'
move() {
if (this.x > windowWidth + 50 || this.x < -50) {
this.speed = this.speed * -1;
}
this.x = this.x + this.speed;
}
}
Problem here is this.x > windowWidth + 50 || this.x < -50. Try to log this inside move() function and you will see that it is referring to move().x instead of Girl.x. So this.x is undefined and undefined > 10 + 50 is always false.
P.s. I dont know p5 so this is vanilla.
So to fix this you need to declare another variable to get Girl scope.
var Girl = function(){
var self = this;
//code goes here
function move(){
self.x = setValue;
console.log(this.x) //undefined
}
}

Calling a nested function from global scope [duplicate]

This question already has answers here:
Loop (for each) over an array in JavaScript
(40 answers)
Closed 4 years ago.
So, i have the following code:
this.balls = [];
function setup() {
createCanvas(800, 800);
noStroke();
balls.push(new Ball(width / 2, height / 2, 20))
}
function draw() {
for (var ball in this.balls) {
ball.drawCircle();
}
}
this.Ball = function(x, y, r) {
console.log("Ball created");
this.x = x;
this.y = y;
this.r = r;
this.drawCircle = function (){
ellipse(x, y, r);
}
}
The problem is that i get the following error:
Uncaught TypeError: ball.drawCircle is not a function
at draw (sketch.js:12)
at e.d.redraw (p5.min.js:6)
at e.<anonymous> (p5.min.js:4)
at e.<anonymous> (p5.min.js:4)
at new e (p5.min.js:5)
at e (p5.min.js:4)
So it should call the drawcircle funtion for every ball in the balls array, however it says that drawCircle is not a function. The problem is that I just don't understand why. I have tried using var drawCircle instead of this.drawCirle, I also tried using funcion drawCircle.
Kind regards.
p.s. this code uses p5.js, the Ball created log is executed
Try using a class so you don't have issues with this context:
function Ball(x, y, r) {
console.log("Ball created");
this.x = x;
this.y = y;
this.r = r;
}
Ball.prototype.drawCircle = function() {
ellipse(x, y, r);
};
Or in ES6:
class Ball {
constructor(x, y, r) {
console.log("Ball created");
this.x = x;
this.y = y;
this.r = r;
}
drawCircle() {
ellipse(x, y, r);
}
}

Particle (made with constructor) expand and fade upon collision

When a user clicks on any particle I want it to expand and fade and upon collision with any other particle and that particle will also expand and fade. Now my problem is that I want to know if there is a way in which I can get those particles (made with constructor in this case) to effect each other when they get collide. Link to Codepen
var bubbles = [];
function setup() {
frameRate(25);
// Creates Canvas
createCanvas(windowWidth, windowHeight);
//Genrates 100 Particles with random a & y
for (var i = 0; i < 80; i++) {
var x = random(width);
var y = random(height);
bubbles[i] = new Bubble(x, y);
}
}
function mousePressed() {
for (var i = 0; i < bubbles.length; i++) {
bubbles[i].clicked();
}
}
function draw() {
clear();
//Adds color and motion
for (var bubble of bubbles) {
fill(bubble.color.red, bubble.color.green, bubble.color.blue);
bubble.move();
bubble.display();
}
}
function Bubble(x, y) {
this.x = x;
this.y = y;
this.wh = 15;
this.speedX = random(1, 5);
this.speedY = random(1, 5);
//Individual Particle Creation
this.display = function() {
noStroke();
ellipse(this.x, this.y, this.wh, this.wh);
};
//Interactivity
this.clicked = function() {
var d = dist(this.x, this.y, mouseX, mouseY);
if (d < 8) {
this.wh = 100;
}
};
//Randomizes colors
this.color = {
red: random(255),
green: random(255),
blue: random(255)
};
//Particle Motion
this.move = function() {
//Motion in X direction
this.x += this.speedX;
//Bouncing back on X-axis
if (this.x > windowWidth || this.x < 0) {
this.speedX = -this.speedX;
}
//Motion in Y Direction
this.y += this.speedY;
//Bouncing back on Y-axis
if (this.y > windowHeight || this.y < 0) {
this.speedY = -this.speedY;
}
};
}
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
}
::-webkit-scrollbar{
display:none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.10/p5.js"></script>
Use a nested for loop.
Step 1: Loop over the bubbles. Do this with a for loop.
Step 2: For each bubble, loop over the rest of the bubbles (if you're on bubble 4, start with bubble 5). Do this with another for loop inside the first one.
Step 3: Now that you have two bubbles, do the collision between them.
If you're having trouble getting that working, then please start smaller. Start with a simpler program that just shows two hard-coded bubbles and does collision detection between them.

JS object inheritance with attributes

Im trying to get a very simple inheritance pattern for my Project going, extending from a base class into a specialized class. However, my specialized class's attributes are being overwritten by the parent's attributes.
Why is that and how can i fix it ?
thanks,
function Ship(className, x, y){
this.className = className;
this.x = x;
this.y = y;
this.speed = 0;
}
function Corvette(className, x, y){
this.className = className;
this.x = x;
this.y = y;
this.speed = 100;
Ship.call(this, className, x, y)
}
Corvette.prototype = Object.create(Ship.prototype);
var ship = new Ship("Biggie", 50, 50);
var corvette = new Corvette("Smallish", 50, 50);
console.log(Corvette.className) // "Smallish" - correct via parameter.
console.log(Corvette.speed) // should be 100, is 0 - not correct, "static" from parent attribute
console.log(Corvette.constructor.name) // Ship
Why you have the same properties in the child object which are already in the parent's?
I suggest you to do
function Ship(className, x, y, speed = 0) {
this.className = className;
this.x = x;
this.y = y;
this.speed = speed;
}
function Corvette(className, x, y, speed = 100) {
Ship.call(this, className, x, y, speed);
}
Corvette.prototype = Object.create(Ship.prototype);
Corvette.prototype.constructor = Corvette;
var ship = new Ship("Biggie", 50, 50);
var corvette = new Corvette("Smallish", 50, 50);
console.log(corvette.className) // "Smallish" - correct via parameter.
console.log(corvette.speed) // should be 100, is 0 - not correct, "static" from parent attribute
console.log(corvette.constructor.name) // Ship
and if your browser supports some features of ES6 use this feature ES6 classes.
class Ship { // And also Ship is an abstractionm so you can use `abstract` keyword with it
constructor(className, x, y, speed = 0) {
this.className = className;
this.x = x;
this.y = y;
this.speed = speed;
}
}
class Corvette extends Ship {
constructor(className, x, y, speed = 100) {
super(className, x, y, speed);
}
}
var ship = new Ship("Biggie", 50, 50);
var corvette = new Corvette("Smallish", 50, 50);
console.log(corvette.className) // "Smallish" - correct via parameter.
console.log(corvette.speed) // should be 100, is 0 - not correct, "static" from parent attribute
console.log(corvette.constructor.name) // Ship
You only need to move Ship.call(this, className, x, y) at the start of Corvette function.
Also, next time, before posting code, check it is correct, you wrote console.log(Corvette) instead of console.log(corvette)
Another thing: you do not need to repeat params you do not want to overwrite
function Ship(className, x, y){
this.className = className;
this.x = x;
this.y = y;
this.speed = 0;
}
function Corvette(className, x, y){
Ship.call(this, className, x, y)
this.speed = 100;
}
Corvette.prototype = Object.create(Ship.prototype);
var ship = new Ship("Biggie", 50, 50);
var corvette = new Corvette("Smallish", 50, 50);
console.log(corvette.className)
console.log(corvette.speed)
console.log(corvette.constructor.name)
You should invoke the parentclass contructor first and then override the properties, this way the properties set by Corvette will not be changed by the parent class i.e.:
function Corvette(className, x, y){
Ship.call(this, className, x, y)
this.speed = 100;
}

Categories

Resources