انیمیشن Animation

آخرین به روزرسانی در 31 خرداد 1402
نوشته شده توسط علی خادم
انیمیشن

برای این که بتونید توی برنامه‌تون انیمیشن درست کنید، p5.js به صورت پیشفرض کدی که داخل draw نوشته باشیدو شصت بار در هر ثانیه اجرا می‌کنه؛ به هر بار اجرا شدن این کد، اصطلاحاً می‌گن یک «فرِیم».

فرِیم رِیت

یه اصطلاحی هست به نام «فرِیم رِیت» که ممکنه قبلاً توی نرم‌افزارای تولید انیمیشن باهاش برخورد کرده باشید یا توی بعضی از بازی‌ها دیده‌باشید. فرِیم رِیت یعنی در یک بازه زمانی مشخص، مثلاً یه ثانیه، چند فریم روی صفحه نمایش به تصویر درمیاد. برنامه‌ای که توی هر ثانیه شصت فریم نمایش بده، یعنی داره با فریم رِیتِ شصت فریم بر ثانیه اجرا می‌شه. توی برنامه‌های p5.js برای این که فریم رِیتو چک کنیم، می‌تونیم از تابع frameRate استفاده کنیم.

function setup() {
     createCanvas(windowWidth, windowHeight)
}
function draw() {
     console.log(frameRate())
}

اگه دوست نداشتید برنامه‌تون با این فریم رِیت اجرا بشه با همین تابع frameRate می‌تونید مشخص کنید که برنامه با چه فریم رِیتی اجرا بشه؛ فقط کافیه فریم رِیت مورد نظرتون رو در قالب یک پارامتر توی تابع frameRate مشخص کنید؛ دقت کنید که p5.js سعی می‌کنه فرِیم رِیت برنامه رو به اون حدی که شما مشخص کردید برسونه، اما در واقعیت فریم رِیتِ برنامه ممکنه نسبت به ویژگی‌های دستگاهی که برنامه داره توش اجرا می‌شه کاهش پیدا کنه.

function setup() {
     createCanvas(windowWidth, windowHeight);

     // specify frame rate
     frameRate(30)

}
function draw() {
     console.log(frameRate())
}

سرعت و جهت انیمیشن

برای این که بتونیم یه انیمیشنِ روان درست کنیم، متغیرهایی می‌سازیم تا بتونیم یه سری اعداد توش ذخیره کنیم و بعد با اجرای هر فریم، تغییرشون می‌دیم. مثال بعدی یه شکل رو از سمت چپ صفحه نمایش سمت به راست حرکت می‌ده:

let radius = 45
let x = -radius
let theSpeed = 5

function setup() {
     createCanvas(windowWidth, windowHeight);
     ellipseMode(RADIUS)
}
function draw() {
     background(0)

     // change the position based on speed
     x += theSpeed

     // draw the shape
     arc(x, windowHeight/2, radius, radius, 0.5, 5.5)
  
}

وقتی کد بالا رو اجرا کنید می‌بینید که شکل، بعد از مدتی از سمت راست تصویر خارج می‌شه و ما دیگه نمی‌بینیمش؛ یه شرط به کد بالا اضافه می‌کنم تا وقتی شکل از سمت راستِ تصویر خارج شد، برگرده به جای اولش و دوباره از سمت چپ شروع به حرکت کنه:

let radius = 45
let x = -radius
let theSpeed = 5

function setup() {
     createCanvas(windowWidth, windowHeight);
     ellipseMode(RADIUS)
}
function draw() {
     background(0)

     // change the position based on speed
     x += theSpeed

     // if the shape is off screen
     if(x > windowWidth + radius) {
     x = -radius
     }

     // draw the shape
     arc(x, windowHeight/2, radius, radius, 0.5, 5.5)

}

کد بالا توی هر فریم، شرطی که گذاشتیم رو چک می‌کنه: اگه مقدار x از عرض صفحه به‌علاوه شعاع دایره بیشتر شده بود، دوباره شکل رو برمی‌گردونه به جای اولش.

حرکت بین دو نقطه

بعضی وقتا نیاز داریم یه شکل بین دو نقطه جابجا بشه. با چند خط کُد، می‌شه نقطه شروع و پایانو مشخص کرد و بعد مختصات مسیرو محاسبه کرد. کد پایینو اجرا کنید و مقادیر متغیرها رو تغییر بدید و خودتون ببینید چطوری کار می‌کنه:

const startX = 50
const startY = 50
const stopX = 500
const stopY = 500
let x = startX
let y = startY

// speed
const step = 0.005

// percentage traveled
let pct = 0

function setup() {
     createCanvas(windowWidth, windowHeight);
}
function draw() {
     background(0)
     if(pct < 1) {
          x = startX + ((stopX - startX) * pct)
          y = startY + ((stopY - startY) * pct)
          pct += step
     }
     ellipse(x, y, 15, 15)
}

انیمیشن رندوم

بر خلاف حرکت خطی‌ای که توی اسکیس‌های قبل دیدید، توی دنیای واقعی معمولاً سرعت‌ها متغیر و بعضاً تصادفی هستن. مثل جابجا شدن یه برگ توی باد یا حرکت مورچه روی زمین؛ می‌شه تلاش کرد و این طور کیفیت‌های پیش‌بینی‌ناپذیرِ دنیای واقعی رو با به وجود آوردن اعداد تصادفی شبیه‌سازی کرد. قبلاً درباره روش استفاده کردن از اعداد تصادفی نوشته بودم. تابع random توی p5.js این طور مقادیرو محاسبه می‌کنه؛ می‌تونیم دو تا عدد به عنوان پارامترهای این تابع استفاده کنیم و برای تولید یه عدد تصادفی از یه بازه‌ی عددی استفاده کنیم. توی اسکیس بعدی، جای دایره‌هایی که داره کشیده می‌شه توسط مقادیر تصادفی مشخص می‌شه. دقت کنید که این بار از تابع background داخل draw استفاده نمی‌کنیم تا بتونیم همه دایره‌هایی که کشیده می‌شن رو ببینیم:

const theSpeed = 10
const diameter = 100
let x
let y

function setup() {
     createCanvas(windowWidth, windowHeight);
     x = windowWidth/2
     y = windowHeight/2
     background(205)
}
function draw() {
     x += random(-theSpeed, theSpeed)
     y += random(-theSpeed, theSpeed)
     ellipse(x, y, diameter, diameter)
}
با استفاده از اعداد تصادفی، می توان انیمیشن های مختلفی ایجاد کرد

استفاده از مثلثات برای ساختن انیمیشن

امیدوارم مثلثاتِ محدودی که توی این دوره استفاده می‌کنیم شما رو کنجکاو کنه درباره مثلثات مطالعه کنید. ما توی این دوره خیلی عمیق وارد ریاضیات و مثلثات نمی‌شیم، اما چند تا از کاربردای مثلثات توی انیمیشنو با هم‌دیگه می‌بینیم.

تابع‌های sin و cos در p5.js مقادیری بین 1 و -1 به ما برمی‌گردونن که همون سینوس و کسینوس زاویه‌ایه که مشخص می‌کنیم؛ زاویه‌ها باید با واحد رادیان مشخص بشن. معمولاً اعدادی که توابع sin و cos به ما می‌دن باید در یه عددی ضرب بشن که بشه خوب ازشون استفاده کرد:

let angle = 0
const scalar = 100
const theSpeed = 0.1

function setup() {
     createCanvas(windowWidth, windowHeight);
}
function draw() {

     // adjust the angle
     angle += theSpeed

     // set y position
     const y1 = sin(angle + 0.25) * scalar
     const y2 = sin(angle + 0.50) * scalar
     const y3 = sin(angle + 0.75) * scalar

     // create 3 circles
     ellipse(width/2 - 50, height/2 + y1, 45, 45)
     ellipse(width/2 + 00, height/2 + y2, 45, 45)
     ellipse(width/2 + 50, height/2 + y3, 45, 45)

}
یک فریم از انیمیشن سه دایره

وقتی sin و cos با هم استفاده بشن، می‌تونن حرکت دورانی به وجود بیارن. توی مثال بعدی، مقادیر تابع cos مختصات x رو تعیین می‌کنن و مقادیر تابع sin مشخص‌کننده مختصات y هستن:

let angle = 0
const scalar = 100
const theSpeed = 0.1

function setup() {
     createCanvas(windowWidth, windowHeight);
}
function draw() {

     // adjust the angle
     angle += theSpeed

     // positions
     const x = cos(angle) * scalar
     const y = sin(angle) * scalar

     // create the circles
     ellipse(width/2 + x, height/2 + y, 50, 50)

}
یک فریم از انیمیشن یک دایره

اگه توی کد قبلی یه تغیر کوچیک ایجاد کنیم و مقدار scalar رو توی هر فریم یه خُرده زیاد کنیم، می‌تونیم به جای دایره، یه مارپیچ درست کنیم:

let angle = 0
let scalar = 100
const theSpeed = 0.1

function setup() {
     createCanvas(windowWidth, windowHeight);
}
function draw() {

     // adjust the angle and scalar
     angle += theSpeed
     scalar += theSpeed * 3

     // positions
     const x = cos(angle) * scalar
     const y = sin(angle) * scalar

     // create the circles
     ellipse(width/2 + x, height/2 + y, 50, 50)

}

می‌بینید یه تغییر کوچیک چقدر می‌تونه توی تصویر خروجی تأثیر داشته باشه؟ حالا وقتشه از چیزایی که یاد گرفتید استفاده کنید، یه خُرده خلاقیت به خرج بدید و هر جوری که دوست دارید با کد بازی کنید. خروجی‌های مختلف رو تست کنید، من یه تغییراتی روی کد انجام دادم و خروجی کارم این طوری شد:

اصلاً انیمیشن نمی‌خوام

اگه برنامه شما نیاز به انیمیشن نداشت، می‌تونید از تابع noLoop داخل setup استفاده کنید، این طوری هر چیزی که داخل draw باشه هم فقط یک بار فراخوانی می‌شه.

ارسال نظر

ایمیل شما منتشر نخواهد شد. بخش‌های ضروری با * مشخص شده‌اند.