Animated random boxes in p5.js & python

Hello everyone.
I wanted to share with you my first job in Processing. A work with loops and animated random.
The interesting thing for me about this exercise was getting it to work with code for p5.js and then translating it to the python module and making it work as well.
All the best!

Code in p5.js:

function setup() {
  const width = 600
  const height = 600
  createCanvas (width, height);
  
}


function draw() {
  background ('#BFF2C5');
  const w = width * 0.10;
  const h = height * 0.10;
  const gap = width * 0.03;
  const ix = width * 0.17;
  const iy = height * 0.17;

  const off = width * 0.03;

  let x, y;

  for (let i = 0; i < 5; i++) {
    for (let j = 0; j < 5; j++) {
      x = ix + (w + gap) * i;
      y = iy + (h + gap) * j;
 
      strokeWeight(width * 0.01);
      rect(x, y, w, h);
      
    

      if (random() > 0.7) {
        frameRate(5);
        strokeWeight(width * 0.006);
        rect(x + off / 2, y + off / 2, w - off, h - off);
        
  
      }
    }
  }

}

function keyPressed() {
  if (key === 's') {
    saveGif('mySketch2', 5);
  }
}

Code in python:

def setup():

  size(600, 600)
  
def draw():
    background ('#BFF2C5')
    w = width * 0.10
    h = height * 0.10
    gap = width * 0.03
    ix = width * 0.17
    iy = height * 0.17

    off = width * 0.03


    i = 0
    j = 0
    for i in range (5):

        for j in range (5):
        
            x = ix + (w + gap) * i
            y = iy + (h + gap) * j
 
            strokeWeight(width * 0.01)
            rect(x, y, w, h)
        
            r = random(25)
            if (r > 10):
                frameRate(5)
                strokeWeight(width * 0.006)
                rect(x + off / 2, y + off / 2, w - off, h - off)
     
def keyPressed():
    if key == 's':
        saveGif('mySketch2', 5)

mySketch1

1 Like

You can use PyScript to write code in Processing’s p5*js or pjs flavors using Python syntax! :snake:
Take a look at some of my PyScript sketches to see how to do it: PyScript :eyeglasses:

2 Likes

Hey!
Very interesting!
Thanks!!

Just converted a p5js sketch I had called “Bouncing Colorful Balls” to PyScript:
https://PyScript.com/@gotoloop/bouncing-colorful-balls

The original p5*js sketch had 2 versions:

  1. Global Mode
  2. Instance Mode

And I made 2 versions for PyScript:

  1. Imports the original “ball.mjs” as a JS module.
  2. Imports its own converted “ball.py” Python module.

Besides those HTML files, “index.html” shows all 4 of them.

While “all.html” shows 4 p5*js sketches, 2 global & 2 instance mode versions.

Those 4 sketches teach many techniques on how to write/convert p5*js sketches to PyScript syntax.

1 Like

I have been looking for information and I don’t know how to use processing in pyscript. I am new at this. I would like to know how to use pyscript to make generative art. I don’t know how to use processing with pyscript or similar libraries that allow me to work with graphics and animations

In PyScript’s PoV, Processing JS libraries are just like any other JS library.

Visiting https://PyScript.com/@gotoloop you can check which code strategies I’ve applied to convert some existing Processing sketches I had to use PyScript instead.

However, the most difficult part isn’t converting but rather debugging code in PyScript!

After some research I’ve found this errorHandler() code snippet which is intended to be invoked from within an except block, so we can pinpoint where the error occurred:

from sys import exc_info

LF = '\n'

def errorHandler(e):
    err_type, err_obj, err_trace = exc_info()
    code = err_trace.tb_frame.f_code

    filename = code.co_filename
    functname = code.co_name
    lineno = err_trace.tb_lineno

    msg  = 'Exception: ' + str(err_type) + LF
    msg += 'Function: ' + functname + LF
    msg += 'File: ' + filename + LF
    msg += 'Line: ' + str(lineno) + LF
    msg += 'Error: ' + str(e)

    print(msg)


error_handler = errorHandler

B/c PyScript lacks proper debugging capabilities, we’re better off coding a sketch offline.

Only when we have a sketch working correctly we should attempt to convert it to PyScript so it runs online as well.

1 Like

I’m looking at some of your work to understand how it works. The truth is that it looks very good, really. It is very interesting although I find it a bit complex. But I think I’m going to do some tests to see if I’m interested.
If I can do something I’ll give you the link to my pyscript
Thanks for the information.

1 Like

Take a look at PyScript’s documentation as well: :books:
https://PyScript.GitHub.io/docs/latest/user-guide/configuration/

1 Like

I’ve converted your “Animated Random Boxes” sketch to PyScript! :snake:
Although I’ve done some tweaks to it before actual conversion: :gear:

“Animated_Random_Boxes.pyde”:

"""
 Animated Random Boxes
 by SalvaLnx (2024-Jan)
 mod GoToLoop (2024-Jan-18)

 Discourse.Processing.org/t/animated-random-boxes-in-p5-js-python/43612/10
 PyScript.com/@gotoloop/animated-random-boxes
"""

BG = 0xffBFF2C5
ROWS, COLS = range(5), range(6)

def setup():
    size(600, 500)
    frameRate(5)
    strokeWeight(.01 * width)

    global w, h, ix, iy, wgap, hgap, off2, woff, hoff, weight

    w = .10 * width
    h = .10 * height

    ix = .13 * width
    iy = .17 * height

    gap  = .03 * width
    wgap = w + gap
    hgap = h + gap

    off  = .03 * width
    off2 = .5 * off

    woff = w - off
    hoff = h - off

    weight = .006 * width


def draw():
    background(BG)

    for r in ROWS:
        y = hgap * r + iy

        for c in COLS:
            x = wgap * c + ix
            y = hgap * r + iy

            rect(x, y, w, h)

            if random(25) > 10:
                pushStyle()
                strokeWeight(weight)
                rect(x + off2, y + off2, woff, hoff)
                popStyle()

So here’s the Python Mode “.pyde” above converted to PyScript + Pjs ". :sparkler:
You can check it out online from these links: :link:

“pjs.py”:

"""
 Animated Random Boxes
 by SalvaLnx (2024-Jan)
 mod GoToLoop (2024-Jan-18)

 Discourse.Processing.org/t/animated-random-boxes-in-p5-js-python/43612/10
 PyScript.com/@gotoloop/animated-random-boxes
"""

from js import Processing, document
from types import MethodType

BG = 0xffBFF2C5
ROWS, COLS = range(5), range(6)

def setup(p):
    p.size(600, 500)
    p.frameRate(5)
    p.strokeWeight(.01 * p.width)

    global w, h, ix, iy, wgap, hgap, off2, woff, hoff, weight

    w = .10 * p.width
    h = .10 * p.height

    ix = .13 * p.width
    iy = .17 * p.height

    gap  = .03 * p.width
    wgap = w + gap
    hgap = h + gap

    off  = .03 * p.width
    off2 = .5 * off

    woff = w - off
    hoff = h - off

    weight = .006 * p.width


def draw(p):
    p.background(BG)

    for r in ROWS:
        y = hgap * r + iy

        for c in COLS:
            x = wgap * c + ix

            p.rect(x, y, w, h)

            if p.random(25) > 10:
                p.pushStyle()
                p.strokeWeight(weight)
                p.rect(x + off2, y + off2, woff, hoff)
                p.popStyle() # Not restoring previous strokeWeight!


def sketch(p):
    p.setup = MethodType(setup, p)
    p.draw = MethodType(draw, p)


def instantiatePjs():
    div = document.getElementById('pjs')
    canvas = document.createElement('canvas')

    div.appendChild(canvas)
    Processing.new(canvas, sketch)


__name__ == '__main__' and instantiatePjs()

And even a PyScript + p5*js too:

“p5js.py”:

"""
 Animated Random Boxes
 by SalvaLnx (2024-Jan)
 mod GoToLoop (2024-Jan-18)

 Discourse.Processing.org/t/animated-random-boxes-in-p5-js-python/43612/10
 PyScript.com/@gotoloop/animated-random-boxes
"""

from js import p5
from types import MethodType

ROWS, COLS = range(5), range(6)

def setup(p):
    p.createCanvas(600, 500)
    p.frameRate(5)
    p.strokeWeight(.01 * p.width)

    global w, h, ix, iy, wgap, hgap, off2, woff, hoff, weight, bg

    w = .10 * p.width
    h = .10 * p.height

    ix = .13 * p.width
    iy = .17 * p.height

    gap  = .03 * p.width
    wgap = w + gap
    hgap = h + gap

    off  = .03 * p.width
    off2 = .5 * off

    woff = w - off
    hoff = h - off

    weight = .006 * p.width
    bg = p.color('#BFF2C5')


def draw(p, _CHANCE = .7):
    p.background(bg)

    for r in ROWS:
        y = hgap * r + iy

        for c in COLS:
            x = wgap * c + ix

            p.rect(x, y, w, h)

            if p.random() > _CHANCE:
                p.push()
                p.strokeWeight(weight)
                p.rect(x + off2, y + off2, woff, hoff)
                p.pop()


def sketch(p):
    p.setup = MethodType(setup, p)
    p.draw = MethodType(draw, p)


def instantiateP5js(): p5.new(sketch, 'p5js')

__name__ == '__main__' and instantiateP5js()

And the “index.html” which loads both of them:

“index.html”:

<!DOCTYPE html>

<meta charset=utf-8>

<title>Animated Random Boxes</title>

<link rel=icon href=//PyScript.net/assets/images/favicon.ico>

<script defer src=//Unpkg.com/processing-js></script>
<script defer src=//cdn.JsDelivr.net/npm/p5></script>

<script type=module src=//Unpkg.com/@pyscript/core></script>

<py-config src=pyscript.toml></py-config>

<py-script src=pjs.py></py-script>
<py-script src=pjs.py></py-script>

<py-script src=p5js.py></py-script>
<py-script src=p5js.py></py-script>

<h3>Animated Random Boxes [pjs]</h3>
<div id=pjs></div>

<h3>Animated Random Boxes [p5js]</h3>
<div id=p5js></div>

And although not required in this sketch project, the TOML config file:

“pyscript.toml”:

name = 'Animated Random Boxes'
version = '1.0.3'
author_name = 'SalvaLnx & GoToLoop'
license = 'Unlicense'
description = 'Discourse.Processing.org/t/animated-random-boxes-in-p5-js-python/43612/10'
url = 'https://PyScript.com/@gotoloop/animated-random-boxes'

I believe by studying a Python Mode sketch you’ve made and comparing it to its corresponding PyScript versions will help you understand what are the necessary steps for it. :man_walking:

1 Like