Portal is a p5.js sketch that integrates numerous external components into p5.js in a straightforward manner, doing rapid prototyping.
Go to this sketch and duplicate it.
Portal is a p5.js sketch that integrates numerous external components into p5.js in a straightforward manner, doing rapid prototyping.
Go to this sketch and duplicate it.
The colour system is based on Red, Green and Blue, so copy the RGB values in the picker.
When you start combining multiple colors, you can use adobes color trends to learn from the best when it comes to color combinations. I am using the one above this tutorial.
Colours are represented by Red, Green, and Blue, each ranging from 0 to 255. By mixing those three colours, you can get more than 16 million different colours.
If you want the background to be blue, then write:
background(0,0,255);
If you want to fill an ellipse with a semitransparent red colour, then add another parameter for fill like this:
fill(255,0,0,150);
ellipse(40,40,50,50);
If you want to set the stroke and not have fill, then do the following
stroke(255,0,150);
noFill();
ellipse(40,40,50,50);
Line:
line(x1, y1, x2, y2)
Rectangle:
rect(x, y, w, h, [r])
Ellipse:
ellipse(x, y, w, h)
Triangle
triangle(x1, y1, x2, y2, x3, y3)
Line thickness:
strokeWeight(3)
Line colour:
stroke(red,green,blue)
Fill colour:
fill(red,green,blue)
No stroke
noStroke()
No Fill:
noFill()
Copy this into your draw function:
fill(200, 255, 200);
noStroke();
ellipse(200, 200, 150, 100);
fill(173, 216, 230);
stroke(0);
rect(100, 100, 200, 150, 20);
Visually, you have three strategies for making visual illustrations. You can use the code-based drawing tools (ellipse, etc.), you can use a photo, or you can use a vector illustration. They are aesthetically very different, and mixing them usually results in a very messy expression. So you can choose wisely and be mindful of how the overall expression comes together.
If you want to design your own vector illustrations you can use google drawing or inkscape. If you want manipulate photos gimp is a free editor. The illustration above has been made with google drawing.
First, upload the image. Then load the image in setup. Draw the image in the draw function at a specific position. Specific commands marked in bold below:
Before the setup function
let imgStar;
In the setup function
imgStar = await loadImage('portal/assets/star.png');
In the draw function
image(imgStar, 40, 40);
Use dist() to calculate the distance between two points. Combine this with an if statement, and you can change the colour when the distance to the mouse is within the circle size. Add the following to the draw function:
if (dist(mouseX, mouseY, 240, 240) < 150 / 2) {
fill(255, 0, 0, 150);
} else {
fill(209, 157, 44, 70);
}
ellipse(240, 240, 150);
You can use the function keyReleased() to register a keypress
function keyPressed() {
if (key == 'a') {
print("An A was pressed");
}
}
Notice that the function "keyPressed()" is already present in the sketches. This is because it is used to fill the screen when you press "f". So you only need to add the if statement within the outer curly brackets.
https://p5js.org/reference/#/p5/keyPressed
You can also make an if statement in your draw() function. Then it will do something until you release the key (e.g. moving a ball forward).
function draw() {
if (keyIsPressed === true && key='a') {
print("An A is pressed down");
}
}
Notice that the function "draw()" is already present in the sketches. So you only need to add the if statement within the outer curly brackets to the existing draw function.
https://p5js.org/reference/#/p5/keyIsPressed
Instead of using a default font, you can use Google fonts. You can visit the website to find the name and type of the font (e.g., Sans or Serif) and load it accordingly.
Add to setup()
loadGoogleFont("Bitcount"); // loads the font
textFont("Bitcount"); // set the font
textSize(60);
Add to draw()
text('hi', 50, 50);
Obs dynamically loading font from Google only works in 2D mode in WEBGL/3D mode; you need to download the font and upload it to your sketch.
When a gamepad is present, you can get the different parameters with e.g.:
gamePads[0].state["LEFT_STICK_X"]
Other names for buttons and sticks:
FACE_1, FACE_2, FACE_3, FACE_4, LEFT_TOP_SHOULDER, RIGHT_TOP_SHOULDER, LEFT_BOTTOM_SHOULDER, RIGHT_BOTTOM_SHOULDER, SELECT_BACK, START_FORWARD, LEFT_STICK, RIGHT_STICK, DPAD_UP, DPAD_DOWN, DPAD_LEFT, DPAD_RIGHT, HOME, LEFT_STICK_X, LEFT_STICK_Y, RIGHT_STICK_X, RIGHT_STICK_Y
Add to setup():
await loadScript("portal/gamepad.js");
await setupGamepad();
Add to draw():
// only do the following if there is a gamepad connected
if (gamePads !== undefined && gamePads.length >0) {
fill(255, 255, 255);
textSize(32);
text(gamePads[0].state["FACE_1"], 100, 100 + 40);
if (gamePads[0].state["FACE_1"]) {
background(100);
}
text(gamePads[0].state["LEFT_STICK_X"], 100 + 40, 100 + 40);
ellipse(map(gamePads[0].state["LEFT_STICK_X"], -1, 1, 0, windowWidth), map(gamePads[0].state["LEFT_STICK_Y"], -1, 1, 0, windowHeight), 20, 20);
}
Test that your gamepad works here:
https://hardwaretester.com/gamepad
Also gamepads often only appears when you press a button
Projection mapping is used to map visuals onto uneven surfaces with a video projector.
let mapper; // ProjectionMapper
let surface1, surface2; // p5.Graphics returned by mapper.add
async function setup() {
createCanvas(windowWidth, windowHeight, WEBGL);
await pSetup();
pixelDensity(1);
await loadScript("portal/mapper.js");
mapper = new ProjectionMapper();
mapper.setFont(baseFont);
surface1 = mapper.add(1024, 768, "Front");
surface2 = mapper.add(800, 400, "Side");
mapper.loadAll();
}
let posX = 0;
function draw() {
background(0);
// --- draw content into surface1 ---
const t = millis() * 0.001;
surface1.background("pink");
surface1.noStroke();
surface1.textFont(baseFont);
surface1.fill(0);
surface1.textAlign(CENTER, CENTER);
surface1.textSize(250);
surface1.text("#1", surface1.width / 2, surface1.height / 2);
// --- draw content into surface2 ---
posX = (posX + 1) % surface2.width;
surface2.background("yellow");
surface2.textFont(baseFont);
surface2.fill(0);
surface2.textAlign(CENTER, CENTER);
surface2.ellipse(posX, surface2.height / 2, 100, 100);
surface2.textSize(250);
surface2.text("#2", surface2.width / 2, surface2.height / 2);
// --- render all mapped surfaces ---
mapper.render();
}
function keyPressed() {
if (key == "f") {
fullScreenToggle();
}
mapper.keyPressed(key);
}
function mousePressed() {
mapper.mousePressed();
}
function mouseDragged() {
mapper.mouseDragged();
}
function mouseReleased() {
mapper.mouseReleased();
}
Surprisingly often, it is needed to mathematically draw a circle or have something rotate in an orbit. To do so, we need to have basic trigonometry at hand to determine the x and y coordinates from a position, length, and angle:
let p = pointFromAngle(startX, startY, len, angle);
This example shows how to use cos and sin to get x and y for a circle:
for (var a = 0; a < 360; a = a + 20) {
let p = pointFromAngle(200, 200, 100, a)
ellipse(p.x, p.y,20,20);
}
When things get more advanced, you often want to draw on an image instead of directly to the canvas. This allows you to send the image to machine learning, save the image and refresh elements on the screen without affecting the drawing you are making
Before the setup function
let drawing;
In the setup function
drawing = createGraphics(100, 100);
In the draw function
drawing.background(0);
drawing.ellipse(50,50,20,20);
image(drawing, 50, 50);
This script generates a QR Code and show it on the canvas
Before the setup function
let qrCode;
In the setup function
await loadScript("portal/qrCodeGen.js");
qrCode = createQRCode("http://google.com");
In the draw function
drawQRCode(qrCode, 100, 100, 200);
Script for reading qr codes - needs to be encapsulated in a module.
let canvas;
let capture, graphics, p;
let codeReader;
let qrCodeText = "";
async function setup() {
canvas = createCanvas(windowWidth, windowHeight);
await pSetup();
await loadScript("https://unpkg.com/@zxing/library@latest");
codeReader = new ZXing.BrowserMultiFormatReader();
let constraints = {
video: {
facingMode: { ideal: "environment" },
},
audio: false
};
capture = createCapture(constraints);
capture.hide();
codeReader.decodeFromVideoDevice(null, capture.elt, (result, err) => {
if (result) {
qrCodeText =result.text;
} else if (err && !(err instanceof ZXing.NotFoundException)) {
console.error(err);
resultText = "Error reading barcode!";
}
});
}
async function draw() {
background(255);
background(1, 31, 38);
if(qrCodeText == "??")
{
background(255,0,0);
}
image(capture, 0, 0,capture.width/2,capture.height/2);
fill(255);
textSize(20);
text("qrCode: " + qrCodeText, 50,capture.height/2+100);
}
function keyPressed() {
if (key == "f") {
fullScreenToggle();
}
}
If you need to convert video formats, then this tool is good https://handbrake.fr/ MP4 is recommended as the encoding format.
let canvas;
async function setup() {
canvas = createCanvas(windowWidth, windowHeight);
await pSetup();
vid = createVideo(["portal/assets/videoOne.mp4"], vidLoaded);
vid.hide(); // hides the html video loader
}
function vidLoaded() {
vid.loop();
vid.volume(0);
print("video loaded");
}
async function draw() {
background(255);
background(1, 31, 38);
let img = vid.get();
image(img, 20, 20); // redraws the video frame by frame
}
function keyPressed() {
if (key == "f") {
fullScreenToggle();
}
}
Creating more organic patterns with a computer can be challenging, but multiple algorithms have been developed to facilitate this process. Try to add the following code to your draw function:
background(0, 10);
pSetNoiseRange(-100, 100);
let t = frameCount/50
let nX = pNoise1D(t+100);
let nY = pNoise2D(t);
ellipse(nX + windowWidth / 2, nY + windowHeight / 2, 20, 20);
It will draw an ellipse which will move like a bird og fly around in the 2D space. Functions that you can call:
Make it start randomly each time: pSetNoiseSeed(Date.now());
Set the range that it should return: pSetNoiseRange(0, 0100);
Noise in one dimension: pNoise1D(time);
Noise in two dimensions: pNoise2D(x, y);
Noise in three dimensions: pNoise3D(x, y, z);