P5.js inside sBasic

User avatar
rbytes
Posts: 1338
Joined: Sun May 31, 2015 12:11 am
My devices: iPhone 11 Pro Max
iPad Pro 11
MacBook
Dell Inspiron laptop
CHUWI Plus 10 convertible Windows/Android tablet
Location: Calgary, Canada
Flag: Canada
Contact:

P5 Code Comment Fix

Post by rbytes »

If you have used Operator's P5.js scripts to display code downloaded from the P5.js site, you will have discovered that you have to change every comment in the code from // in front of the comment to /* at the front and */ at the end. After editing dozens of comment lines by hand, and often having to repeat the job for comments I hadn't noticed, I came up with this short program to do that work for me. You specify the file you want corrected as n$. The properly-commented file will be saved as "Commented "&n$

Code: Select all

REM Comment Fix
REM by rbytes November 2016
n$="P5_code_lgradient.tx"
o$="Commented "&n$
file n$ setpos 0
while not file_end (n$)
  file n$ readline temp$
  found=instr(temp$,"//")
  if found<>-1 then
    temp$=mid$(temp$,0,found)&"/*"&mid$(temp$,found+2,len(temp$)-found)&" */"
  endif
  a$&=temp$&chr$(10)
endwhile
print "File '"&n$&"':"
print a$
if file_exists(o$) then file o$ delete
file o$ writeline a$
pause 10
end
Here is an example of a script I copied from an Example on the P5.js website. Notice the // in front of each comment.

Code: Select all

// Constants
var Y_AXIS = 1;
var X_AXIS = 2;
var b1, b2, c1, c2;
function setup() {
  createCanvas(710, 400);
  // Define colors
  b1 = color(255);
  b2 = color(0);
  c1 = color(204, 102, 0);
  c2 = color(0, 102, 153);
  noLoop();
}
function draw() {
  // Background
  setGradient(0, 0, width/2, height, b1, b2, X_AXIS);
  setGradient(width/2, 0, width/2, height, b2, b1, X_AXIS);
  // Foreground
  setGradient(50, 90, 540, 80, c1, c2, Y_AXIS);
  setGradient(50, 190, 540, 80, c2, c1, X_AXIS);
}
function setGradient(x, y, w, h, c1, c2, axis) {
  noFill();
  if (axis == Y_AXIS) {  // Top to bottom gradient
    for (var i = y; i <= y+h; i++) {
      var inter = map(i, y, y+h, 0, 1);
      var c = lerpColor(c1, c2, inter);
      stroke(c);
      line(x, i, x+w, i);
    }
  }  
  else if (axis == X_AXIS) {  // Left to right gradient
    for (var i = x; i <= x+w; i++) {
      var inter = map(i, x, x+w, 0, 1);
      var c = lerpColor(c1, c2, inter);
      stroke(c);
      line(i, y, i, y+h);
    }
  }
}
And here is the converted output, with /* */ surrounding each comment.

Code: Select all

/* Constants */
var Y_AXIS = 1;
var X_AXIS = 2;
var b1, b2, c1, c2;
function setup() {
  createCanvas(1024, 768);
  /* Define colors */
  b1 = color(255);
  b2 = color(0);
  c1 = color(204, 102, 0);
  c2 = color(0, 102, 153);
  noLoop();
}
function draw() {
  /* Background */
  setGradient(0, 0, width/2, height, b1, b2, X_AXIS);
  setGradient(width/2, 0, width/2, height, b2, b1, X_AXIS);
  /* Foreground */
  setGradient(50, 90, 540, 80, c1, c2, Y_AXIS);
  setGradient(50, 190, 540, 80, c2, c1, X_AXIS);
}
function setGradient(x, y, w, h, c1, c2, axis) {
  noFill();
  if (axis == Y_AXIS) {  /* Top to bottom gradient */
    for (var i = y; i <= y+h; i++) {
      var inter = map(i, y, y+h, 0, 1);
      var c = lerpColor(c1, c2, inter);
      stroke(c);
      line(x, i, x+w, i);
    }
  }  
  else if (axis == X_AXIS) {  /* Left to right gradient */
    for (var i = x; i <= x+w; i++) {
      var inter = map(i, x, x+w, 0, 1);
      var c = lerpColor(c1, c2, inter);
      stroke(c);
      line(i, y, i, y+h);
    }
  }
}
The result is a full-screen demo of horizontal and vertical color gradients.
Attachments
IMG_7939.PNG
IMG_7939.PNG (934.79 KiB) Viewed 5410 times
Last edited by rbytes on Sat Nov 26, 2016 6:02 pm, edited 3 times in total.
The only thing that gets me down is gravity...

User avatar
rbytes
Posts: 1338
Joined: Sun May 31, 2015 12:11 am
My devices: iPhone 11 Pro Max
iPad Pro 11
MacBook
Dell Inspiron laptop
CHUWI Plus 10 convertible Windows/Android tablet
Location: Calgary, Canada
Flag: Canada
Contact:

Spinning 3D Cone

Post by rbytes »

The P5.js scripts can do some amazing things with 3D graphics. This script creates a 3D multi-colored spinning cone when loaded with Operator's "P5 HTML sandwich". See the first post in this thread for his code. You will need to modify the values in createCanvas() to your screen size. Mine are set for the point size of my iPad Air screen, 1024 x 768.

Code: Select all

/*draw a spinning cone with radius 250 and height 500*/
function setup(){
  createCanvas(1024, 768, WEBGL);
}

function draw(){
  background(600);
  rotateX(frameCount * 0.01);
  rotateZ(frameCount * 0.01);
  cone(250, 500);
}
Attachments
IMG_7943.PNG
IMG_7943.PNG (214.77 KiB) Viewed 5408 times
IMG_7942.PNG
IMG_7942.PNG (328.26 KiB) Viewed 5408 times
The only thing that gets me down is gravity...

User avatar
rbytes
Posts: 1338
Joined: Sun May 31, 2015 12:11 am
My devices: iPhone 11 Pro Max
iPad Pro 11
MacBook
Dell Inspiron laptop
CHUWI Plus 10 convertible Windows/Android tablet
Location: Calgary, Canada
Flag: Canada
Contact:

All 6 3D shapes available in P5.js

Post by rbytes »

What a treat to be able to do virtual 3D inside smart Basic. Here are all 6 of the primitive objects available. In this script, each is animated with its own rotation direction(s) and speed(s). Left to right and top to bottom they are: torus, plane, cone, box, cylinder and sphere.

News Flash: Although the P5.js site has an example supposedly showing all of the 6 3D primitive shapes, it needs updating. Elsewhere on the site they list 7 primitives. This example is missing the ellipsoid, so I will look for a good example to demonstrate it. (Nov. 27)

Code: Select all

function setup() {
  createCanvas(1024, 768, WEBGL);
}
function draw() {
  background(0);
  noStroke();
  push();
  translate(-300, 150);
  rotateY(1.25);
  rotateX(-0.9);
  rotateZ(frameCount * 0.1);
  box(200,150,50);
  pop();
  translate(0, 200, 0);
  push();
  rotateZ(frameCount * 0.01);
  rotateX(frameCount * 0.01);
  rotateY(frameCount * 0.01);
  cylinder(20, 420);
  pop();
  translate(-300, -400, 0);
  push();
  rotateZ(frameCount * 0.01);
  rotateX(frameCount * 0.01);
  rotateY(frameCount * 0.01);
  torus(100, 40);
  pop();
  noFill();
  stroke(255);
  push();
  translate(650, 400, -200);
  rotateZ(frameCount * 0.02);
  rotateY(frameCount * 0.01);
  sphere(150);
  pop();
  translate(300, 50, 200);
  normalMaterial();
  push();
  rotateZ(frameCount * 0.01);
  rotateX(frameCount * 0.02);
  rotateY(frameCount * 0.01);
  plane(140,100);
  pop();
  translate(370, -100, -400);
  rotateX(frameCount * 0.05);
  rotateZ(frameCount * 0.01);
  rotateY(frameCount * 0.03);
  cone(150, 300);
}
Attachments
IMG_7978.PNG
IMG_7978.PNG (938.55 KiB) Viewed 5388 times
Last edited by rbytes on Mon Nov 28, 2016 2:19 am, edited 2 times in total.
The only thing that gets me down is gravity...

User avatar
rbytes
Posts: 1338
Joined: Sun May 31, 2015 12:11 am
My devices: iPhone 11 Pro Max
iPad Pro 11
MacBook
Dell Inspiron laptop
CHUWI Plus 10 convertible Windows/Android tablet
Location: Calgary, Canada
Flag: Canada
Contact:

How to set display size within P5.js

Post by rbytes »

Operator asked if there was a way to detect the display size in P5.js and set the canvas size to match. There is, but with my iPad in landscape mode, P5.js REVERSES the two parameters.

Here is my first version of a script displaying a sphere with the camera zooming in and out repeatedly. The first screen shot shows an error in the display size when I set the canvas to displayWidth, displayHeight as the Reference advises.

Code: Select all

function setup(){
  createCanvas(displayWidth, displayHeight, WEBGL);
}
function draw(){
 /* move the camera away from and toward the sphere with a sine wave */
 background(0);
 camera(0, 0, sin(frameCount * 0.05) * 2000);
 translate(0, 0, -1570);
 sphere(120);
}
Now here is the same script with displayWidth and displayHeight reversed. Now the display size fits my iPad landscape display perfectly, as you can see in the second image.

News Flash - I found a way to correct for this error in the P5.js library, and will post it soon (Nov. 27)

Code: Select all

function setup(){
  createCanvas(displayHeight, displayWidth, WEBGL);
}
function draw(){
 /* move the camera away from and toward the sphere with a sine wave */
 background(0);
 camera(0, 0, sin(frameCount * 0.05) * 2000);
 translate(0, 0, -1570);
 sphere(120);
}
Ignore the size of the sphere. It is constantly growing and shrinking on the screen, so when I do a screengrab, I never know quite what size it will appear.
Attachments
IMG_7985.PNG
IMG_7985.PNG (552.66 KiB) Viewed 5383 times
IMG_7982.PNG
IMG_7982.PNG (408.64 KiB) Viewed 5383 times
The only thing that gets me down is gravity...

User avatar
rbytes
Posts: 1338
Joined: Sun May 31, 2015 12:11 am
My devices: iPhone 11 Pro Max
iPad Pro 11
MacBook
Dell Inspiron laptop
CHUWI Plus 10 convertible Windows/Android tablet
Location: Calgary, Canada
Flag: Canada
Contact:

P5.js - the mysteries of displayWidth and displayHeight

Post by rbytes »

What I thought was a fix of the P5.js code for sensing screen size turned out not to be. Well, it helped a little. I was finding that when I used these variables, the canvas in my code was always set incorrectly, with height and width being swapped.

So I searched in the P5.js code for "displayWidth", and found it in this excerpt. The reference I set to bold.

{this._curElement.elt.style.cursor="none"},h.prototype.displayWidth=screen.width,h.prototype.displayHeight=screen.height,h.prototype.windowWidth=d(),h.prototype.windowHeight=e(),h.prototype._onresize=function(a)


Since the values that were being produced for screen.width and screen.height seemed to be reversed, I reversed the settings in the code like this:

{this._curElement.elt.style.cursor="none"},h.prototype.displayWidth=screen.height,h.prototype.displayHeight=screen.width,h.prototype.windowWidth=d(),h.prototype.windowHeight=e(),h.prototype._onresize=function(a)

That helped, because nearly all of my code samples so far seem to work best in landscape mode, and now that was set correctly.

But I got a shock when I tried running all my code snippets in portrait orientation. The values of displayWidth and displayHeight did not adjust themselves! I made up a quick piece of code that would display these values, and ran it on my iPad Air and the my iPhone 6 in both landscape and portrait. The screen shots show the results. Everything is shown to scale.

That wasn't the end of the surprises. On my iPhone 6, displayWidth was 568 and displayHeight was 320 no matter which orientation my phone was in. But those readouts weren't correct in either orientation - they match an iPhone 5 or 5s! The iPhone 6 screen size is 667 x 375. One more mystery. You would think that since the canvas was being set to 568 x 320, it shouldn't completely fill the screen of my iPhone 6 - but it does.

My head hurts!
Attachments
iPad landscape
iPad landscape
IMG_8116.PNG (108.09 KiB) Viewed 5343 times
iPad portrait
iPad portrait
IMG_8121.JPG (168.54 KiB) Viewed 5343 times
iPhone landscape
iPhone landscape
IMG_8117.JPG (128.29 KiB) Viewed 5346 times
iPhone portrait
iPhone portrait
IMG_8119.JPG (125.93 KiB) Viewed 5346 times
The only thing that gets me down is gravity...

Operator
Posts: 138
Joined: Mon May 06, 2013 5:52 am

Re: P5.js inside sBasic

Post by Operator »

Maybe this gives a hint (last section):
http://creative-coding.decontextualize.com/mobile/

You could also check the behavior
of this in other apps like Javascript Anywhere
or Coffee Script at Once (where I started) before
"porting" the P5.js to sBasic...

And the P5 Forum will sure have further hints..

User avatar
rbytes
Posts: 1338
Joined: Sun May 31, 2015 12:11 am
My devices: iPhone 11 Pro Max
iPad Pro 11
MacBook
Dell Inspiron laptop
CHUWI Plus 10 convertible Windows/Android tablet
Location: Calgary, Canada
Flag: Canada
Contact:

Re: P5.js inside sBasic

Post by rbytes »

Thanks, Operator.

I now have dozens of working scripts. I also have a small collection of scripts that don't work. I have gotten fairly good at debugging, but there are a few that just won't run. The screen stays blank.

But the ones that work are great. Here is a fantastic bit of P5.js code that creates never-ending patterns on screen using the sine function. The animation is amazingly fast. It is my favorite so far.

Code: Select all

function setup(){
  createCanvas(displayWidth,displayHeight, WEBGL);
}
function draw(){
  background(0);
  rotateY(frameCount * 0.01);
  for(var j = 0; j < 5; j++){
    push();
    for(var i = 0; i < 80; i++){
      translate(sin(frameCount * 0.001 + j) * 100, sin(frameCount * 0.001 + j) * 100, i * 0.1);
      rotateZ(frameCount * 0.002);
      push();
      sphere(8, 6, 4); 
      pop();
    }
    pop();
  }
}
Attachments
IMG_8178.PNG
IMG_8178.PNG (768.04 KiB) Viewed 5313 times
IMG_8177.PNG
IMG_8177.PNG (468.61 KiB) Viewed 5313 times
IMG_8176.PNG
IMG_8176.PNG (550.63 KiB) Viewed 5313 times
The only thing that gets me down is gravity...

User avatar
GeorgeMcGinn
Posts: 435
Joined: Sat Sep 10, 2016 6:37 am
My devices: IPad Pro 10.5in
IMac
Linux i386
Windows 7 & 10
Location: Venice, FL
Flag: United States of America
Contact:

Re: P5.js inside sBasic

Post by GeorgeMcGinn »

Hello,

I made a few changes to the SmartBASIC program so you do not have to worry about line numbers.

I changed the FOR/NEXT to WHILE/ENDWHILE, and before each P5 is read in, I set an end of file switch to ZERO for logic checking in the WHILE statement.

Thank you Operator for sharing, and thank you Ricardo for all the coding examples.

PS: In my copy, I also cleaned up the filenames some, so be sure to change fname$ (1-3) either back to whatever you use, or you can use my filename conventions. (I did this partly because I plan to include this in the Programmer's Guide I am writing for SmartBASIC).

George.

Code: Select all

GRAPHICS
GRAPHICS CLEAR 1,1,1
SET TOOLBAR OFF
GET SCREEN SIZE SW,SH

'-----------------------------------------------------------------
'*** HTML file was split in three files
'*** The second file (P5_Code.js) has the P5-code to be executed.
'*** Edit it to code.
'
'*** NOTE: set editor capsyntax off" to avoid syntax errors with 
'***       reserved words of sBasic
'

fname1$ = "P5_HTML.js"
fname2$ = "P5_Code.js"
fname3$ = "P5_Library.js"
a$ = ""
temp$ = ""
b$ = "1"

'-------------------------------------------------------------------------
'*** read all 3 files into one string and load into a BROWSER to execute
'*** Javascript code


'*** Load the HTML headers and <script> open tag
end_of_file=0
FILE fname1$ SETPOS 0
WHILE NOT end_of_file
      FILE fname1$ READLINE temp$
      a$ &= temp$&""
      IF FILE_END (fname1$) THEN end_of_file=1
ENDWHILE


'*** Loads the P5 Javascript code
end_of_file=0
FILE fname2$ SETPOS 0
WHILE NOT end_of_file
      FILE fname2$ READLINE temp$
      a$ &= temp$&""
      IF FILE_END (fname2$) THEN end_of_file=1
ENDWHILE


'*** Load the P5 JS library
end_of_file=0
FILE fname3$ SETPOS 0
WHILE NOT end_of_file
      FILE fname3$ READLINE temp$
      a$ &= temp$&""
      IF FILE_END (fname3$) THEN end_of_file=1
ENDWHILE


'------------------------------------------------------------------------------
'*** Load BROWSER and execute P5 Javascript code
'*** (NOTE: P5 Javascript automatically executed when a$ loads in the BROWSER)
'
BROWSER b$ AT -1,-1 SIZE SW+1,SH+1      ' otherwise a white border can be seen!
BROWSER b$ hide
BROWSER b$ TEXT a$
BROWSER b$ SHOW
BUTTON "quit" text "Q" at 990,10 size 24,30

'*** Loop to check for buttons pressed and terminate program
LOOP:
   IF BUTTON_PRESSED("quit") THEN
      BROWSER b$ DELETE
      a$ = ""
      temp$ = ""
      text
      END
   ENDIF

GOTO LOOP
George McGinn
Computer Scientist/Cosmologist/Writer/Photographer
Member: IEEE, IEEE Computer Society
IEEE Sensors Council & IoT Technical Community
American Association for the Advancement of Science (AAAS)

User avatar
GeorgeMcGinn
Posts: 435
Joined: Sat Sep 10, 2016 6:37 am
My devices: IPad Pro 10.5in
IMac
Linux i386
Windows 7 & 10
Location: Venice, FL
Flag: United States of America
Contact:

Re: Suggested change to the Test File

Post by GeorgeMcGinn »

Sorry Ricardo, this post was so small, I missed it when I posted my program with basically the same changes.

I like this way as well (more direct coding approach) than setting and resetting switches.

George.
rbytes wrote:In the Test file, there is a code section to load each of three files - an HTML, a P5 code file, and another HTML. The loading is done via loops. If someone happens to create a code file with more lines than the loop is set to read, the code will not be read completely. It would be better to use this type of structure:

file fname2$ setpos 0
while not file_end (fname2$)
file fname2$ readline temp$
a$ &= temp$
endwhile

Then the program will always read exactly the number of lines in the file, no more and no less.
George McGinn
Computer Scientist/Cosmologist/Writer/Photographer
Member: IEEE, IEEE Computer Society
IEEE Sensors Council & IoT Technical Community
American Association for the Advancement of Science (AAAS)

User avatar
GeorgeMcGinn
Posts: 435
Joined: Sat Sep 10, 2016 6:37 am
My devices: IPad Pro 10.5in
IMac
Linux i386
Windows 7 & 10
Location: Venice, FL
Flag: United States of America
Contact:

Re: P5.js inside sBasic

Post by GeorgeMcGinn »

Hello Operator,

I haven't tried it yet, but I looked over your VBScript response awhile back, and I am thinking this technique might work for not only VBScript, but PHP as well. Both are client-side languages.

George.
Operator wrote:Hello rBytes..., your sample is bare html/js
so no need of any js-lib (as P5) and therefore
the strange 3-file splitt is also not needed...

Just load your sample code out of one file
and you are done....


Code for single html-js-file-player:

Code: Select all

REM Html-JS File Player in sBasic
REM (bare js -> no js-libs)
REM
REM sB5.6/iOS6.1/iPhone4/by Operator
REM (thxs to rBytes)

GRAPHICS
GRAPHICS CLEAR 1,1,1

button "quit" text "Quit" at 0,400 size 100,30

'html-js file to run/play
fname$ = "Html-js-File.txt"

a$ = ""
temp$ = ""

'read file into one string
FILE fname$ SETPOS 0
FOR t=1 TO 200
    FILE fname$ READLINE temp$
    a$ &= temp$&""
NEXT t

'create browser and load string = text
BROWSER 1 AT 0,0 SIZE 320,400
BROWSER 1 TEXT a$


LOOP:
if button_pressed("quit") then
  browser 1 delete
  a$ = ""
  temp$ = ""
  end
end if
GOTO LOOP

George McGinn
Computer Scientist/Cosmologist/Writer/Photographer
Member: IEEE, IEEE Computer Society
IEEE Sensors Council & IoT Technical Community
American Association for the Advancement of Science (AAAS)

Post Reply