فهرست
چه چیزایی میکشیم؟
p5.js شامل گروهی از تابعهاس که میشه باهاشون شکل کشید؛ توی این درس با 6 تا از این توابع آشنا میشیم تا بتونیم این اشکال رو خلق کنیم:
- مثلت
- چهارضلعی
- مربع و مستطیل
- دایره
- اشکال دلخواه
- آرک
- اسپلاین
با ترکیب شکلهای ساده میشه شکلهای پیچیدهتر ساخت. قبل از این که بریم سراغ شکلهای پیچیده، ببینیم چطوری میشه یه خط ساده کشید؟ میدونیم که خط، کوتاهترین فاصله بین دو نقطه رو به ما نشون میده؛ پس برای کشیدن یه خط نیاز به چهار پارامتر داریم: دو تا برای مشخص کردن نقطه شروع و دو تا برای مشخص کردن نقطه پایان:
function setup() {
createCanvas(windowWidth, windowHeight)
}
function draw() {
background(200)
line(30, 50, 300, 100)
}
بر اساس همین الگو، کشیدن یه مثلث نیاز به شش پارامتر داره، چون داره سه تا نقطه رو به هم وصل میکنه و کشیدن یه چهارضلعی نیاز به هشت پارامتر داره چون داره چهار تا نقطه رو بهم وصل میکنه:
function setup() {
createCanvas(windowWidth, windowHeight)
}
function draw() {
background(200)
quad(158, 55, 199, 14, 392, 66, 351, 107)
triangle(347, 54, 392, 9, 392, 66)
triangle(158, 55, 290, 91, 290, 112)
}
برای کشیدن مربع و دایره، به ترتیب از تابعهای rect
و ellippse
استفاده میکنیم که هر جفتشون نیاز به چهار پارامتر دارن: اولی و دومی x
و y
هستن که محل قرارگیری شکل رو مشخص میکنن، سومی عرضِ شکله و چهارمی ارتفاع:
function setup() {
createCanvas(windowWidth, windowHeight)
rectMode(CENTER)
}
function draw() {
background(200)
rect(windowWidth/2, windowHeight/2, 300, 300)
}
ترتیب کشیده شدن شکل ها
وقتی برنامه شما اجرا میشه، مرورگر از اولین خطِ کد شما شروع میکنه و به ترتیب پایین میاد و به آخر میرسه. اگه بخواید یه شکل روی همه شکلهای دیگه کشیده بشه، باید توی کُدتون اون شکل رو بعد از همه شکلها بکشید. ببینید:
function setup() {
createCanvas(windowWidth, windowHeight)
}
function draw() {
background(200)
ellipse(300, 300, 200, 200)
rect(300, 300, 250, 30)
}
کشیدن شکل دلخواه
برای کشیدن شکل توی p5.js محدود به این تابعهایی که تا این جا دیدید نیستید. تابع beginShape
برای شروع کشیدن یه شکلِ جدیدِ دلخواه استفاده میشه، تابع vertex
یه رأس ساده درست میکنه و مختصات x
و y
اون رأس رو توی خودش تعریف میکنه و در نهایت، تابع endShape
برای نشون دادن پایان یه شکل استفاده میشه:
function setup() {
createCanvas(windowWidth, windowHeight)
}
function draw() {
background(200)
translate(0, 100)
// a new shape
beginShape()
vertex(180, 82)
vertex(207, 36)
vertex(214, 63)
vertex(407, 11)
vertex(412, 30)
vertex(219, 82)
vertex(226, 109)
endShape(CLOSE)
}
شکلِ آرک
برای کشیدن منحنیها توی p5.js چند تا راه داریم. سادهترین منحنیها آرکها هستن که بخشی از دایره یا بیضی رو تشکیل میدن. تابع arc
شش تا پارامتر داره: اولی و دومی مختصات محل قرارگیری شکل، سومی و چهارمی عرض و ارتفاع شکل، پنجمی و ششمی هم زاویه شروع و پایانِ کشیده شدن شکل هستن:
function setup() {
createCanvas(windowWidth, windowHeight)
}
function draw() {
background(200)
arc(90, 60, 80, 80, 0, HALF_PI)
arc(190, 60, 80, 80, 0, PI+HALF_PI)
arc(290, 60, 80, 80, PI, TWO_PI+HALF_PI)
arc(390, 60, 80, 80, QUARTER_PI, PI+QUARTER_PI)
}
توی p5.js زاویهها به صورت پیشفرض بر اساس رادیان تعریف میشن. رادیان، واحد اندازهگیری زاویه بر اساس عدد پای، یا همون پی، هست. چهار تا از مقادیر رادیان هستن که کاربردشون زیاده و برای همین توی p5.js اسامی خاصی براشون در نظر گرفته شده؛ این مقادیر PI
و QUARTER_PI
و HALF_PI
و TWO_PI
هستن.
شکلِ اسپلاین
کشیدن آرک کار راحتیه ولی اگه بخوایم منحنیهایی بکشیم که بخشی از یه دایره یا بیضی نیستن چی؟ تابع curveVertex
بهمون اجازه میده این کارو بکنیم و یه اسپلاین بکشیم؛ برای این کار باید دوباره از تابعهای beginShape
و endShape
استفاده کنیم و با استفاده از تابع curveVertex
مختصات نقاط منحنی رو مشخص کنیم:
function setup() {
createCanvas(windowWidth, windowHeight);
background(200);
noFill();
stroke(0);
}
function draw() {
beginShape();
curveVertex(40, 40);
curveVertex(40, 40);
curveVertex(80, 60);
curveVertex(100, 100);
curveVertex(60, 120);
curveVertex(50, 150);
curveVertex(50, 150);
endShape();
}
هزارتو
تا این جا چیزای سادهای درباره برنامهنویسی یاد گرفتیم: یاد گرفتیم چطوری از متغیرها استفاده کنیم، چطوری تابع بنویسیم و چطوری از تابعهای آماده توی p5.js استفاده کنیم تا شکلهای مختلف درست کنیم. حالا وقتشه که از همه چیزایی که یاد گرفتیم استفاده کنیم.
توی این اسکیس میخوام یه برنامه بنویسم که هر بار اجرا میشه با استفاده از خطوط مورّب یه هزارتوی تصادفی درست کنه. قبل از هر چیز دو تا خط مورّب میکشم که اجزای اصلی سازنده هزارتو هستن و یه متغیر میسازم که اندازه هر خط رو توی خودش ذخیره کنه:
let x = 0
let y = 0
let lineSize = 50
function setup() {
createCanvas(windowWidth, windowHeight)
background(220)
strokeWeight(5)
}
function draw() {
line(x, y, lineSize, lineSize)
line(lineSize, y, x, lineSize)
}
ویژگی اصلی یک اثر مولد (Generative Art) اینه که هر بار کد اجرا میشه و خروجی رو به نمایش میذاره، به شکل تصادفی بخشهایی از اثر تغییر میکنه. توی این پروژه هم میخوام هر بار که برنامه اجرا میشه یه هزارتوی جدید تولید بشه. میخوام هر بار که draw
اجرا میشه به صورت تصادفی فقط یکی از این خطوط مورب کشیده بشه؛ برای این کار یه متغیر میسازم به نام leftOrRight
و با استفاده از تابع random
توش یه عدد تصادفی بین صفر و یک ذخیره میکنم؛ بعد یه شرط مینویسم که چک کنم این عدد بزرگتر از نیمه یا کوچکتر از نیم:
let x = 0
let y = 0
let lineSize = 50
function setup() {
createCanvas(windowWidth, windowHeight)
background(220)
strokeWeight(5)
}
function draw() {
// random
const leftOrRight = random()
if (leftOrRight> 0.5) {
line(x, y, x+lineSize, y+lineSize)
} else {
line(x, y+lineSize, x+lineSize, y)
}
x += lineSize
}
حالا فقط باید یه شرط بذارم و چک کنم که اگه x
از عرض صفحه بیشتر شده، از خط بعدی شروع به کشیدن شکلها کنه:
let x = 0
let y = 0
let lineSize = 50
function setup() {
createCanvas(windowWidth, windowHeight)
background(220)
strokeWeight(5)
}
function draw() {
// random
var leftOrRight = random();
if (leftOrRight > 0.5) {
line(x, y, x+lineSize, y+lineSize)
} else {
line(x, y+lineSize, x+lineSize, y);
}
x += lineSize
// fill next line
if(x > windowWidth) {
x = 0
y += lineSize
}
}
اگه دوست داشته باشید میتونید با متغیرهایی که توی این کد هست بازی کنید و ببینید خروجی کُد چطوری تغییر میکنه. مثلاً الان احتمال این که خطها از چپ به راست یا از راست به چپ کشیده بشن رو نیم یا همون پنجاهدرصد گذاشتیم؛ اگه احتمال کشیده شدن یکی از این دو نوع خط رو افزایش بدیم شکلمون خیلی تغییر میکنه: