Creating own class with p5 functions inside (having "not defined error")

Hello.

I want to create a simple class for graphical objects and typographie, in order to simplify coding for my pupils.

But as i test my (basic) code, I have a 'createVector() not defined' error thrown.

As far as I understand, it's because p5 is not evaluated before the setup, so my code just can't use p5 internal function as simply as that.

Here is a very simplified (it's not the real one) and minimalist version of my code and classes


    /*
        basic object
    */
    function GraphicObject(x,y,a) {
        this.position = createVector(x||0,y||0);
        this.angle=a||0;
    
        this.deplace = function(dx,dy) {
            this.position.x += dx;
            this.position.y += dy;
        }
    }
    
    /*
        son of GraphicObject
    */
    
    function Typo(texte,x,y,t,a) {
        this.texte=texte||"";
        this.base = GraphicObejct;
        this.base(x,y,a);
        this.taille=t||10;
    
        this.dessine = function() {
                 /* draw the text with some tweaks */
        }
    
    }
    
    Typo.Prototype = new GraphicObject;

How should I alter the code in order it is not evaluated before p5 is loaded ? How should I make it a new p5 librarie (the tutorial on p5js is not enough clear on new class creatin for me)

Thanks in advance

Tagged:

Answers

  • edited February 2016

    You can use instance mode and assign the p5 instance to a global variable. Not sure if you could apply something similar in global mode: I prefer not to use it...

  • edited February 2016

    I've also tried using p5.prototype with this syntax :

        /*
            basic object
        */
        p5.prototype.GraphicObject = function(x,y,a) {
            this.position = createVector(x||0,y||0);
            this.angle=a||0;
         
            this.deplace = function(dx,dy) {
                this.position.x += dx;
                this.position.y += dy;
            }
        }
         
        /*
            son of GraphicObject
        */
         
        p5.prototype.Typo = function(texte,x,y,t,a) {
            this.texte=texte||"";
            this.base = GraphicObejct;
            this.base(x,y,a);
            this.taille=t||10;
         
            this.dessine = function() {
                     /* draw the text with some tweaks */
            }
         
        }
         
        p5.prototype.Typo.Prototype = new p5.prototype.GraphicObject;
    

    Still getting the "createVector is not defined" javascript error...

  • Thanks blindfish for your answer. Instance mode is not a solution yet for me.

    But, I've made a mistake (I think) by using base AND the prototype along.

    using this.base is enough.

    Typo.prototype = new GraphicObject is then useless indeed. Deleting it, it works ....

  • edited February 2016 Answer ✓

    I'm confused. Is the problem getting a reference to p5 from within your class or the implementation of JS Class inheritance? Since in global mode p5 mercilessly pollutes the global namespace (the clue is in the name) you have access to it from within your class; assuming you instantiate you class in setup():

    var s, c;
    
    setup = function () {
        createCanvas(600, 400);
        // instantiated from pseudo-classes
        s = new Shape(10,10);
        c = new Circle(width/2, height/2, 200, 200);
    };
    
    draw = function () {
        background('#39d');
        s.draw();
        c.draw();
    };
    
    // - - - - - - - - - - - - - - - - - - //
    
    
    // pseudo-class
    var Shape = function(x, y) {
        console.log("Shape instantiated");
        this.x = x;
        this.y = y;
    };
    
    Shape.prototype.draw = function() {
        // all these function calls are to methods p5 has put in the global namespace
        fill('#000');
        noStroke();
        rect(this.x, this.y, 10, 10);
    };
    
    // pseudo-class inherits from Shape
    var Circle = function(x,y,w,h) {
        // call Shape constructor
        Shape.call(this, x,y);
        this.w = w;
        this.h = h;
    };
    
    Circle.prototype.draw = function() {
        fill('#f90');
        noStroke();
        ellipse(this.x, this.y, this.w, this.h);
    };
    
  • Thank you very much for your answer. I'm a beginner in javascript. Was more of a C / PHP / Perl programmer before, and some concepts or syntax are strange to me. Your help is very much appreciated.

  • No worries. If you're looking for learning resources to help you get your head round JavaScripts 'special features' I'd highly recommend the You don't know JS series.

  • edited February 2016

    ... and some concepts or syntax are strange to me.

    That is fixed w/ Java ECMA6 syntax. We can finally use keywords class & extends!

    I suggest you to stake a look at my examples from: https://forum.Processing.org/two/discussion/14798/how-to-split-a-p5-js-sketch-into-multiple-files#Item_9

  • I've read about EcmaScript 6 on MDN developper network, and class and extend. But the actual version of Firefox, and Chrome I use don't understant ECS6. canIuse doesn't even have an EcmaScript 6 entry for now (just for EcmaScript 5)

    You know, a lot of people still use IE8 ............ especially in education in France where network administration is very very low on budget

  • That is fixed w/ Java ECMA6 syntax

    Some would argue quite the opposite >:)

    I like the gorilla argument myself...

  • edited February 2016 Answer ✓

    ... a lot of people still use IE8... where network administration is very very low on budget.

    AFaIK, all existing available browsers are gratis! $-)

    While developing an app, we can use more advanced tools, even a more modern browser for it:
    https://www.Mozilla.org/en-US/firefox/developer/

    Once the app is finished, we need to deploy it. And of course ECMA5 is still the prevalent version.
    But it's pretty easy to turn our ES6/ES7 code transpiled as ES5. Just paste it here: https://BabelJS.io/repl/

    Try this 1 ES6 p5.js code out there: :P

    "use strict"
     
    class Animal {
      constructor (name) {
        this.name = name
      }
     
      speak() {
        console.log(`${this.name} makes some noise...`)
      }
    }
    
    "use strict"
     
    class Dog extends Animal {
      speak() {
        console.log(`${this.name} barks!`)
      }
    }
    
    "use strict"
     
    class Cat extends Animal {
      speak() {
        console.log(`${this.name} meows!`)
      }
    }
     
    "use strict"
     
    class Lion extends Cat {
      speak() {
        super.speak()
        console.info('... and then ROARS!!!')
      }
    }
     
    function setup() {
      "use strict"
     
      background('blue')
     
      console.log(p5.SoundFile)  // check "p5.sound.js"
      console.log(createElement) // check "p5.dom.js"
      console.log('\n')
       
      new Animal('GoToLoop').speak() // GoToLoop makes some noise...
      new Dog('Spark').speak()       // Spark barks!
      new Cat('Fifi').speak()        // Fifi meows!
      new Lion('King').speak()       // King meows! ... and then ROARS!!!
    }
    

    It's gonna output its corresponding ES5 version, ready to deploy: :bz

    "use strict";
    
    var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
    
    var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
    
    function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
    
    function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
    
    var Animal = (function () {
      function Animal(name) {
        _classCallCheck(this, Animal);
    
        this.name = name;
      }
    
      _createClass(Animal, [{
        key: "speak",
        value: function speak() {
          console.log(this.name + " makes some noise...");
        }
      }]);
    
      return Animal;
    })();
    
    "use strict";
    
    var Dog = (function (_Animal) {
      _inherits(Dog, _Animal);
    
      function Dog() {
        _classCallCheck(this, Dog);
    
        _get(Object.getPrototypeOf(Dog.prototype), "constructor", this).apply(this, arguments);
      }
    
      _createClass(Dog, [{
        key: "speak",
        value: function speak() {
          console.log(this.name + " barks!");
        }
      }]);
    
      return Dog;
    })(Animal);
    
    "use strict";
    
    var Cat = (function (_Animal2) {
      _inherits(Cat, _Animal2);
    
      function Cat() {
        _classCallCheck(this, Cat);
    
        _get(Object.getPrototypeOf(Cat.prototype), "constructor", this).apply(this, arguments);
      }
    
      _createClass(Cat, [{
        key: "speak",
        value: function speak() {
          console.log(this.name + " meows!");
        }
      }]);
    
      return Cat;
    })(Animal);
    
    "use strict";
    
    var Lion = (function (_Cat) {
      _inherits(Lion, _Cat);
    
      function Lion() {
        _classCallCheck(this, Lion);
    
        _get(Object.getPrototypeOf(Lion.prototype), "constructor", this).apply(this, arguments);
      }
    
      _createClass(Lion, [{
        key: "speak",
        value: function speak() {
          _get(Object.getPrototypeOf(Lion.prototype), "speak", this).call(this);
          console.info('... and then ROARS!!!');
        }
      }]);
    
      return Lion;
    })(Cat);
    
    function setup() {
      "use strict";
    
      background('blue');
    
      console.log(p5.SoundFile); // check "p5.sound.js"
      console.log(createElement); // check "p5.dom.js"
      console.log('\n');
    
      new Animal('GoToLoop').speak(); // GoToLoop makes some noise...
      new Dog('Spark').speak(); // Spark barks!
      new Cat('Fifi').speak(); // Fifi meows!
      new Lion('King').speak(); // King meows! ... and then ROARS!!!
    }
    
  • @blindfish, class syntax opens JS doors for devs coming from various other programming languages. Those include Java, C#, C++, Python, etc. \m/

  • AFaIK, all existing available browsers are gratis!

    Tell that to sysadmins who haven't got the resource to upgrade the supported OS from Windoze XP but won't install browsers that can't be controlled via M$ enterprise tools :/

    The Real World can be an uncomfortable place to work... :(

    class syntax opens JS doors for devs coming from various other programming languages.

    Some would argue those 'doors' are trapdoors to dark; horrible and inefficient places :P

    Seriously though; if you come to JS trying to impose the structures you're used to from other languages you may miss out on some really powerful and flexible functionality (that should still be approached with caution: it can bite). So you should take the time to learn the features that made JS so powerful; even before ES2015 class syntax arrived.

  • edited February 2016

    Tell that to sysadmins who haven't got the resource to upgrade the supported OS from Windoze XP

    https://www.Mozilla.org/en-US/firefox/46.0a2/system-requirements/

    Some would argue those 'doors' are trapdoors to dark; horrible and inefficient places.

    I daresay those who are against Java style syntax finally arriving in JS are ignorant about the history of JS:
    https://en.Wikipedia.org/wiki/Brendan_Eich#Netscape_and_JavaScript

    "Having originally joined intending to put Scheme "in the browser", Eich was instead commissioned to create a new language that resembled Java, JavaScript for the Netscape Navigator Web browser."

    The creator of JS was hired to make a Java copycat language for his Netscape boss! ;))
    Therefore, bringing more Java stuff into JS is nothing more than completing his past job!

    Besides, given Eich started JS as a derived Scheme language and had to include Java in it afterwards, JS was already born multi-paradigm. It means JS programmers can choose their own paths!

    There ain't no motive whatsoever to request removing stuff belonging to other paradigms b/c we don't like them! That's pure evil intolerance censorship iMO! :-&

    ... you may miss out on some really powerful and flexible functionality...

    Even though my default is OOP, I love to learn about functional paradigm too.
    For example, I weekly watch "FunFunFunction" on YouTube:
    https://www.YouTube.com/channel/UCO1cgjhGzsSYb1rsB4bFe4Q

    Indeed folks can end up missing diff. paradigms. But its their decision to search for them. (:|

Sign In or Register to comment.