2. p5.js (creative coding, упрощённая работа с 2D/3D)


1. Что такое p5.js

p5.js – это библиотека, созданная для художников, дизайнеров и начинающих программистов. Она упрощает работу с графикой, анимацией, звуком, взаимодействием. Изначально p5.js является портом языка Processing для JavaScript. Основная идея – сделать код максимально доступным.

2. Структура скетча

Любая программа на p5.js состоит из двух основных функций:

setup() – вызывается один раз при старте, используется для инициализации.

draw() – вызывается циклически (по умолчанию 60 раз в секунду), в ней происходит отрисовка кадра.

Подключение

Через CDN в HTML:

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title>Первый скетч p5.js</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.0/p5.js"></script>
</head>
<body>
    <script>
        function setup() {
            createCanvas(400, 400);
        }
        
        function draw() {
            background(220);
            ellipse(mouseX, mouseY, 50, 50);
        }
    </script>
</body>
</html>

3. Рисование базовых фигур

В p5.js есть множество функций для рисования:

  • rect(x, y, width, height) – прямоугольник (по умолчанию верхний левый угол – точка отсчёта).
  • ellipse(x, y, w, h) – эллипс (центр по умолчанию).
  • line(x1, y1, x2, y2) – линия.
  • fill(r, g, b) – заливка.
  • stroke(r, g, b) – цвет обводки.
  • noStroke() – убрать обводку.
  • background(r, g, b) – цвет фона.

Пример:

function setup() {
    createCanvas(400, 400);
}

function draw() {
    background(255);
    fill(255, 0, 0);
    stroke(0, 255, 0);
    strokeWeight(2);
    rect(50, 50, 100, 100);
    
    fill(0, 0, 255);
    ellipse(200, 200, 80, 80);
}

4. Анимация и движение

Чтобы анимировать объект, используем переменные, которые изменяются в draw().

let x = 0;

function setup() {
    createCanvas(400, 400);
}

function draw() {
    background(220);
    ellipse(x, height/2, 50, 50);
    x += 2;
    if (x > width) x = 0;
}

5. Взаимодействие с пользователем

p5.js предоставляет глобальные переменные mouseX, mouseY, mouseIsPressed, key, keyIsPressed. Также есть функции-обработчики: mousePressed(), keyPressed() и т.д.

let colorR = 0;

function setup() {
    createCanvas(400, 400);
}

function draw() {
    background(colorR, 100, 150);
    fill(255);
    ellipse(mouseX, mouseY, 30, 30);
}

function mousePressed() {
    colorR = random(255);
}

6. 3D в p5.js (WebGL режим)

p5.js поддерживает 3D-графику через режим WEBGL. Для этого в createCanvas нужно передать третий аргумент:

function setup() {
    createCanvas(400, 400, WEBGL);
}

function draw() {
    background(200);
    rotateX(frameCount * 0.01);
    rotateY(frameCount * 0.01);
    box(100); // куб
}

В 3D-режиме доступны:

  • box(size) – куб.
  • sphere(radius) – сфера.
  • cylinder(radius, height) – цилиндр.
  • plane(width, height) – плоскость.
  • Освещение: ambientLight(), directionalLight(), pointLight().

Пример с освещением:

function setup() {
    createCanvas(400, 400, WEBGL);
}

function draw() {
    background(0);
    ambientLight(100, 100, 100);
    directionalLight(255, 255, 255, 1, 1, 1);
    
    rotateX(frameCount * 0.01);
    rotateY(frameCount * 0.02);
    sphere(100);
}

8. Пример интерактивного скетча p5.js (2D)

Создадим программу, в которой шарики отталкиваются от курсора.

let balls = [];

function setup() {
    createCanvas(400, 400);
    for (let i = 0; i < 10; i++) {
        balls.push({
            x: random(width),
            y: random(height),
            vx: random(-2, 2),
            vy: random(-2, 2)
        });
    }
}

function draw() {
    background(0);
    for (let b of balls) {
        // Движение
        b.x += b.vx;
        b.y += b.vy;
        // Отражение от границ
        if (b.x < 0 || b.x > width) b.vx *= -1;
        if (b.y < 0 || b.y > height) b.vy *= -1;
        
        // Отталкивание от мыши
        let d = dist(b.x, b.y, mouseX, mouseY);
        if (d < 30) {
            let angle = atan2(b.y - mouseY, b.x - mouseX);
            let force = 2;
            b.vx += cos(angle) * force;
            b.vy += sin(angle) * force;
        }
        
        ellipse(b.x, b.y, 10, 10);
    }
}