Строительство автономных объектов
Весь код и библиотеки для этих руководств можно найти здесь: https://github.com/GeorgeGally/creative_coding
Мы делали довольно простые вещи, так что давайте поднимем их на ступеньку выше.
В предыдущих статьях я показал вам, как заставить мяч прыгать по экрану. Что, если нам нужно много мячей?
Но прежде чем мы дойдем до этого, всегда полезно немного очистить код и разделить рисование и вычислительную часть на отдельные функции. Что привело бы нас к чему-то вроде этого:
var ctx = createCanvas("canvas1"); var ball_size = 20; var ball_x = width/2; var ball_y = height/2; var speed_x = randomInt(-15, 15); var speed_y = randomInt(-15, 15); ctx.fillStyle = rgb(randomInt(255),randomInt(255),0); function draw(){ //ctx.background(255, 0.2); moveBall(); drawBall(); } function moveBall(){ ball_x = ball_x + speed_x; ball_y = ball_y + speed_y; if (bounce(ball_x, 0, w, ball_size)) { speed_x *=-1; ctx.fillStyle = rgb(randomInt(255),randomInt(255),0); } if (bounce(ball_y, 0 ,h, ball_size)) { speed_y *=-1; ctx.fillStyle = rgb(0, randomInt(255),randomInt(255)); } } function drawBall(){ ctx.fillEllipse(ball_x, ball_y, ball_size, ball_size); }
И давайте выделим наш код больше, превратив мяч в объект. Это позволяет нам получить доступ к переменным мячей через точечный синтаксис. Создаем такой объект:
var ball = { x: width/2, y: height/2, speed_x: random(-5, 5), speed_y: random(-5, 5), size: 20, colour: rgb(0) }
Теперь мы можем получить доступ к следующим свойствам мяча:
ball.x = ball.x + ball.speed_x;
Полный отредактированный код теперь выглядит примерно так:
var ctx = createCanvas("canvas1"); var ball = { x: width/2, y: height/2, speed_x: random(-5, 5), speed_y: random(-5, 5), size: 20, colour: rgb(0) } function draw(){ //ctx.background(255, 0.2); moveBall(); drawBall(); } function moveBall(){ // bounce() is a function I created, essentially the same as going // if (ball.x < ball.size/2 || ball.x > w - ball.size/2) if (bounce(ball.x, 0, w, ball.size)) { ball.speed_x *=-1; ctx.fillStyle = rgb(randomInt(255),randomInt(255),0); } if (bounce(ball.y, 0 ,h, ball.size)) { ball.speed_y *=-1; ctx.fillStyle = rgb(0, randomInt(255),randomInt(255)); } ball.x += ball.speed_x; ball.y += ball.speed_y; } function drawBall(){ ctx.fillEllipse(ball.x, ball.y, ball.size, ball.size); }
Пора поговорить о массивах. Я пойду быстро, потому что в Интернете есть много материалов, посвященных этому вопросу. По сути, массивы - это просто контейнеры, которые могут содержать объекты, переменные и строки, разделенные запятыми. Вот так:
var my_array = [ 1, 2, 3 ];
К первому значению массива обращается my_array [0], а ко второму - my_array [1] и т. Д. И мы можем получить длину массива, сказав my_array.length. Так…
var balls = []; // declare a variable with an empty array var colours = ['red', 'green', 'blue', 'indigo', 'violet']; console.log(colours.length); //outputs 5 console.log(colours[0]); //outputs red console.log(colours[4]); //outputs violet
И если мы хотим добавить что-то в конец массива, мы можем использовать push:
var colours = ['red']; console.log(colours); //outputs red colours.push('green'); //add to the front of the array console.log(colours); //outputs red, green
Еще один лучший друг для программирования - цикл for, который выглядит так:
// this will loop 10 times for (var i = 0; i < 10; i++) { // do something }
Цикл for повторяется до тех пор, пока не будет выполнено определенное условие. В этом случае мы увеличиваем нашу временную переменную i с 0 на единицу до тех пор, пока она не перестанет соответствовать условию «меньше 10».
Подробнее о цикле for можно прочитать здесь: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Loops_and_iteration
Наша система частиц - это просто массив шаров. И мы создаем это, создавая объект-мяч, а затем помещая его в массив:
var number_of_balls = 10; var balls = []; // push a ball and it's values into the array for (var i = 0; i < number_of_balls; i++) { var ball = { x: 200, y: height/2, speed_x: random(-5, 5), speed_y: random(-5, 5), size: 20, colour: rgb(0) } balls.push(ball); }
Чтобы получить доступ к свойствам нашего шара, теперь мы можем:
console.log(ball[2].x); //outputs 200
И мы можем перебрать все наши шары так:
for (var i = 0; i < balls.length; i++) { balls[i].x += balls[i].speed_x; balls[i].y += balls[i].speed_y; }
Но при манипулировании нашими частицами и их рисовании набирать шары [i] утомительно и часто, поэтому мы можем вместо этого назначить временную переменную для представления шаров [i], например:
for (var i = 0; i < balls.length; i++) { var b = balls[i]; b.x = b.x + b.speed_x; b.y = b.y + b.speed_y; }
Любые изменения, которые мы вносим в эту временную переменную, также изменят фактические значения частиц.
Собирая все вместе, мы получаем:
var ctx = createCanvas("canvas1"); var number_of_balls = 10; var balls = []; // push a ball and it's values into the array for (var i = 0; i < number_of_balls; i++) { var ball = { x: width/2, y: height/2, speed_x: random(-5, 5), speed_y: random(-5, 5), size: 20, colour: rgb(0) } balls.push(ball); } function draw(){ //ctx.background(255, 0.2); moveBall(); drawBall(); } function moveBall(){ for (var i = 0; i < balls.length; i++) { var b = balls[i]; b.x = b.x + b.speed_x; b.y = b.y + b.speed_y; if (bounce(b.x, 0, w, b.size)) { b.speed_x *=-1; b.colour = rgb(randomInt(55),randomInt(255),0); } if (bounce(b.y, 0 ,h, b.size)) { b.speed_y *=-1; b.colour = rgb(0, randomInt(255),randomInt(55)); } } } function drawBall(){ for (var i = 0; i < balls.length; i++) { var b = balls[i]; ctx.fillStyle = b.colour; ctx.fillEllipse(b.x, b.y, b.size, b.size); } }
И бум, у нас есть система частиц:
Раскомментируйте ctx.background, чтобы увидеть отдельные шарики, и давайте увеличим количество шариков до 100:
Давайте добавим шарики, когда будем двигать мышью. Давайте создадим функцию addBall (), которая устанавливает новое положение шара в положение мыши:
function addBall(){ var ball = { x: mouseX, y: mouseY, speed_x: random(-5, 5), speed_y: random(-5, 5), size: 20, colour: rgb(0) } balls.push(ball); }
Чтобы проверить, переместили ли мы мышь, чтобы избавить нас от лишних хлопот, я добавил в свою библиотеку прослушиватель и глобальную переменную под названием mouseMoved:
// check if mouse has moved and add if so, add a new ball if (mouseMoved) { addBall(); }
Переменная mouseMoved в моей библиотеке создается с помощью eventListener:
var mouseMoved = false; window.addEventListener('mousemove', function(e) { mouseMoved = true; });
А затем в моем цикле requestAnimationFrame () я просто сбрасываю его на false.
Если мы продолжаем перемещать мышь, в конечном итоге шаров будет так много, что наш компьютер будет замедляться и в конечном итоге зависнет, поэтому нам нужен способ удаления шаров, желательно самого старого шара, и это довольно просто, добавив проверку для максимальной длины шаров до конца нашей функции addBall ():
// syntax: splice(start, length) if (balls.length > 1000) balls.splice(0,1);
Splice просто вырезает массив из определенной точки на определенную величину, в нашем случае из позиции 0 нашего массива шаров (и самого старого из наших шаров) на 1.
Если мы уменьшим число до 20, мы начнем получать некоторые интересные эффекты следа:
var ctx = createCanvas("canvas1"); var max_balls = 10; var balls = []; // push a ball and it's values into the array function addBall(){ var ball = { x: mouseX, y: mouseY, speed_x: random(-5, 5), speed_y: random(-5, 5), size: 20, colour: rgb(randomInt(55),randomInt(255),0) } balls.push(ball); if (balls.length > max_balls) balls.splice(0,1); } function draw(){ ctx.background(255, 0.2); if (mouseMoved) { addBall(); } moveBall(); drawBall(); } function moveBall(){ for (var i = 0; i < balls.length; i++) { var b = balls[i]; b.x = b.x + b.speed_x; b.y = b.y + b.speed_y; if (bounce(b.x, 0, w, b.size)) { b.speed_x *=-1; b.colour = rgb(randomInt(55),randomInt(255),0); } if (bounce(b.y, 0 ,h, b.size)) { b.speed_y *=-1; b.colour = rgb(0, randomInt(255),randomInt(55)); } } } function drawBall(){ for (var i = 0; i < balls.length; i++) { var b = balls[i]; ctx.fillStyle = b.colour; ctx.fillEllipse(b.x, b.y, b.size, b.size); } }
Итак, это все для части 3. Поэкспериментируйте, уменьшив размер шариков по мере того, как они становятся старше, и удаляйте их, когда они становятся слишком маленькими. Поиграйте с цветами, прозрачностью фона и всем остальным, что делает вас счастливым. До следующего раза, удачного кодирования…
Подпишитесь на меня в Instagram здесь: https://www.instagram.com/radarboy3000/
И поставьте лайк на моей странице в Facebook: https://www.facebook.com/radarboy3000
Введение в творческое кодирование, часть 1: https://medium.com/@radarboy3000/creative-coding-basics-4d623af1c647#.hn9zzliob
Введение в творческое кодирование, часть 2: https://medium.com/@radarboy3000/introduction-to-creative-coding-part-2-d869832d9ffb#.fzxcom541
Весь код и библиотеки для этих руководств можно найти здесь: https://github.com/GeorgeGally/creative_coding
Хакерский полдень - это то, с чего хакеры начинают свои дни. Мы часть семьи @AMI. Сейчас мы принимаем заявки и рады обсуждать рекламные и спонсорские возможности.
Если вам понравился этот рассказ, мы рекомендуем прочитать наши Последние технические истории и Современные технические истории. До следующего раза не воспринимайте реалии мира как должное!