# Wrapping preload(), setup() and draw() in an ES6 class

**URL:** <https://discourse.processing.org/t/wrapping-preload-setup-and-draw-in-an-es6-class/13071>\
**Category:** Libraries\
**Created:** [July 30, 2019, 8:41pm UTC](https://discourse.processing.org/t/wrapping-preload-setup-and-draw-in-an-es6-class/13071 "2019-07-30T20:41:30Z")\
**Posts on this page:** 1\
**Showing post:** 5

<div class="post-metadata">

**Author:** ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)\
**Post date:** [July 31, 2019, 4:29pm UTC](https://discourse.processing.org/t/wrapping-preload-setup-and-draw-in-an-es6-class/13071/5 "2019-07-31T16:29:29Z")

</div>

> [@kenny83](#):
>
> I also tried extending from `p5.prototype.constructor` instead of just `p5` , since that was the solution to my first problem,

Class p5 is the original _constructor_ already. 😛  
It’s not been hacked like the reference stored in p5.prototype.Sprite. 👾  
Here’s a very simple “index.html” code proving so: 🤓

* * *

## index.html:

```auto
<script src=https://cdn.JsDelivr.net/npm/p5></script>
<script src=https://MolleIndustria.GitHub.io/p5.play/lib/p5.play.js></script>

<script>
  console.log('p5 constructor', p5 === p5.prototype.constructor);
  const Sprite = p5.prototype.Sprite;
  console.log('Sprite constructor', Sprite === Sprite.prototype.constructor);
</script>

```

* * *

> [@kenny83](#):
>
> The only thing left to do now is extend the p5 instance into a Level `class`! 😛  
> Any idea how I could do that using ES6 `class` syntax?

> [@How i extends class in p5.js?](https://discourse.processing.org/t/how-i-extends-class-in-p5-js/894/5):
>
> Yes, it is possible. But in order to use an extended p5 subclass, you’re gonna need to write your code using the dreadful “instance mode” approach: roll_eyes[https://GitHub.com/processing/p5.js/wiki/Global-and-instance-mode](https://GitHub.com/processing/p5.js/wiki/Global-and-instance-mode) “index.html”: \<script defer src=https://CDN.JsDelivr.net/npm/p5\>\</script\> \<script defer src=sketch.js\>\</script\> “sketch.js”: /\*\* \* Class p5 Extended (v1.0.1) \* GoToLoop (2018-Jun-13) \* https://Discourse.Processing.org/t/how-i-extends-class-in-p5-js/894/5 \*/ "use st…

> [@kenny83](#):
>
> But it doesn’t work! ☹

Here’s my attempt on subclassing p5, based on my previous “Class p5 Extended” sketch: 🕶

* * *

## index.html:

```auto
<script defer src=https://cdn.JsDelivr.net/npm/p5></script>
<script defer src=sketch.js></script>

```

* * *

## sketch.js:

```auto
/**
 * Class p5 Extended II (v1.1.1)
 * GoToLoop (2019-Jul-31)
 *
 * https://Discourse.Processing.org/t/
 * wrapping-preload-setup-and-draw-in-an-es6-class/13071/5
 *
 * https://Discourse.Processing.org/t/how-i-extends-class-in-p5-js/894/5
 *
 * https://CodePen.io/GoSubRoutine/pen/voJozR/left?editors=0011
 */

'use strict';

class Level extends p5 {
  static get FILENAME() {
    return 'https://upload.Wikimedia.org/wikipedia/commons/thumb/2/2e/' +
           'Processing_3_logo.png/480px-Processing_3_logo.png';
  }

  static redirectP5Callbacks(p) {
    p.preload = p.loadLevel.bind(p); // preload() callback has to be bind()
    p.setup = p.initLevel; // but callback setup() doesn't need bind()
    p.draw = p.runLevel.bind(p); // draw() has to be bind() like preload()
    p.mousePressed = p.mouseDragged = p.restartLevel; // optional for mouse
    p.touchStarted = p.touchMoved = p.restartLevel; // optional for touch
    p.keyPressed = p.keyReleased = p.restartLevel.bind(p); // required for key
  }

  constructor(levelNum) {
    super(Level.redirectP5Callbacks);
    this.levelNum = levelNum;
  }

  loadLevel() {
    this.img = this.loadImage(Level.FILENAME);
  }

  initLevel() {
    this.createCanvas(this.img.width, this.img.height);
    this.noLoop();

    this.rectMode(this.CORNER).ellipseMode(this.CENTER);
    this.colorMode(this.RGB).blendMode(this.BLEND);
    this.fill('yellow').stroke(0).strokeWeight(1.5).strokeCap(this.ROUND);
  }

  runLevel() {
    this.background('#' + this.hex(~~this.random(0x1000), 3));
    this.set(0, 0, this.img);
  }

  restartLevel() {
    this.redraw();
    return false;
  }

  // When bind() isn't needed, we can directly override the callback method:
  windowResized() {
    this.print('LevelNum: ' + this.levelNum);
    return false;
  }
}

// const levels = [new Level(0), new Level(1)];
const levels = Array.from({ length: 2 }, (v, i) => new Level(i));

```

* * *

BtW, I’ve hacked the callbacks w/ Function::**bind()**: 🤖

> **[Function.prototype.bind() - JavaScript | MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind)**
>
> The bind() method of Function instances creates a new function that, when called, calls this function with its this keyword set to the provided value, and a given sequence of arguments preceding any provided when the new function is called.

---

_[View the full topic](https://discourse.processing.org/t/wrapping-preload-setup-and-draw-in-an-es6-class/13071)._
