How do I get the clicked() function that I made to work?

Viewed 41

I'm following along with a Coding Train coding challenge, challenge #6: Mitosis. I'm stuck on the part where it is supposed to detect a click on one of the cells. If you put this into your web browser, you'll see what I mean - it says that cells[i].clicked is not a function and soon after it says cells[i].moved is not a function even though it was working just fine before. Can anyone fix it??? I am using the atom code editor, and the p5.js library. If you don't know p5.js, you might still know what is wrong... I already have it referenced in the code below though.

./index.html USE THIS EXACT CODE, IT HAS REFERENCE TO P5.JS

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <!-- This next part referneces p5.js -->
    <script src="https://cdn.jsdelivr.net/npm/p5@1.1.9/lib/p5.js"></script> 
    <title>Mitosis Simulation</title>
  </head>
  <body>
    <script src="script.js" ></script>
    <script src="cell.js" ></script>
  </body>
</html>

./script.js

var cells = [];

function setup() {
  createCanvas(600, 600);
  //make two cells
  cells.push(new Cell());
  cells.push(new Cell());
}

function draw() {
  background(51);
  //make the cells move and show
  for(var i = 0; i < cells.length; i ++) {
    cells[i].move();
    cells[i].show();
  }
}

function mousePressed() {
  //this SHOULD detect a click but it doesn't
  for(var i = 0; i < cells.length; i ++) {
    if(cells[i].clicked(mouseX, mouseY)) {

      cells.push(cells[i].mitosis);
    }
  }
}

./cell.js The code for a cell, I guess you could call it object-oriented programming

function Cell(pos, r) {
  //gives the cell either the argument pos, or a random place on the canvas
  this.pos = pos || createVector(random(width), random(height));
  //gives it either the argument r or the radius of 80
  this.r = r || 80;
  //gives a random rgb color
  this.c = color(0, random(150, 255), random(150, 255));

  //move the cell
  this.move = function() {
    //define the direction that it moves
    var vel = p5.Vector.random2D();
    //move in that direction
    this.pos.add(vel);
  }

  //show the cell
  this.show = function() {
    fill(this.c);
    noStroke();
    //display a cell at this.pos.x, this.pos.y with a radius of this.r
    ellipse(this.pos.x, this.pos.y, this.r, this.r);
  }

  //return true when clicked
  this.clicked = function(x, y) {
    //find distance between mouseX, mouseY and its position
    var d = dist(this.pos.x, this.pos.y, x, y);
    //if distance is in the circle, return true
    if(d < this.r / 2) {
      return true;
    } else {
      return false;
    }
  }
  
  //split in two
  this.mitosis = function() {
    //make a new cell exactly like its predeccesor and return it
    var cellss = new Cell(this.pos, this.r/2, this.c);
    return cellss;
  }
}

I'm sure it was a silly mistake or something, but be sure to tell me!

1 Answers

The error is in your mousePressed(): you aren't calling mitosis as a function, you're just saying cells[i].mitosis. When you do this, it doesn't run the mitosis function, it actually just returns a reference to the function.

function mousePressed() {
  // detects clicks, and if there is a click, it runs the mitosis function
  for(var i = 0; i < cellLength; i ++) {
    if(cells[i].clicked(mouseX, mouseY)) {
      cells.push(cells[i].mitosis());
    }
  }
}

Some other things to note:

  1. Creating a new cell with 1/2 the radius isn't actually making something half the size, it's actually makes something smaller than half the area because of the way 2d things work. Imagine you have a square, and reduce each side length by a factor of 1/2: it will have 1/4 the area. Actual halving of the area would require doing some complicated math with length of the diagonal. So you have to do a similar thing with pi, and Shiffman goes over this in his agar.io tutorial
  2. It's best practice to reference all of your classes (or in this case, closures) before your main JavaScript code, like this in your HTML:
    <script src="cell.js" ></script>
    <script src="script.js" ></script>
Related