1. 程式人生 > >手繪&碼繪 P2

手繪&碼繪 P2

前言:上一篇文章我們對比了同一幅畫手繪與碼繪的不同,本文著重考慮動態圖的繪製。

PS:考慮到p5與processing區別不大,這裡參考資料都出自p5

背景知識:noise(),返回所定義座標的柏林噪聲值。柏林噪聲是個用來生成比 random() 所能生成更自然及更諧波的隨機數字系列。在 1980 年代有 Ken Perlin 所發明,柏林噪聲至今常被用在圖形應用程式中生成程式紋理、自然運動、形狀、地形等等。

首先我們來看p5.js文件裡所給出的示例:
在這裡插入圖片描述
在這裡插入圖片描述
在p5.js官網給出的示例當中,我們可以看見一組有noise()定義的圖形可跟隨滑鼠有規律生成(gif中滑鼠未能擷取),細看如同自然界中的一輪起起伏伏的山脈。由此為靈感,我們可以適當利用noise()函式完成山脈的繪製。

因而,我們可以先定義一個山脈的函式,Mountain(speed, c, w, h),裡面四個引數分別為速度、顏色、寬度與高度,利用noise()函式生成山巒,並在底部增加一根水平線使其閉合便於填充顏色。
在這裡插入圖片描述
我們先試著生成一組山脈:
在這裡插入圖片描述
暫時看來效果比較搞笑-_-||

沒關係我們生成四組疊加起來看看在這裡插入圖片描述
這樣看來就比較……(好吧)稍微好一點了!

我們在加個藍天:
在這裡插入圖片描述
現在的效果就比較接近真實的藍天與山脈了

為了使得畫面比較豐富,我們接著生成一組雲彩:
在這裡插入圖片描述
雲彩的生成主要是利用一條水平線與若干半圓組合而成
在這裡插入圖片描述
然後為了白雲動起來更加自然,我們隨機生成了其位置、大小與速度:
在這裡插入圖片描述

好了,最後再加上太陽就大功告成了!
在這裡插入圖片描述


附上(拙劣的)手繪作品:
在這裡插入圖片描述


小結:通過本次實驗,我們完成了“同一幅”作品手繪與碼繪的比較,其感想如下:

技法:手繪注重繪畫功底,側重於藝術性;碼繪注重程式設計能力,側重於對數學與程式碼的完美結合。

工具:傳統的手繪多采用鉛筆、水彩等繪圖工具,隨著電腦技術的不斷髮展,出現了數位板等輔助繪圖工具;而在碼繪中,可以採用的程式設計工具層出不窮,且近年來不斷完善,使得創作者具有更多的選擇。

創作體驗:若是繪製動態影象,手繪的工作量大,需要創作者繪製一幀幀畫面,而碼繪在程式碼中本身嵌入了動態效果,使得這一方面的實現相對輕鬆簡單,作品的互動性也大大提高。

視覺效果:手繪的線條更加自由,創作物件更加天馬行空,全由創作者決定,是創作者自我意識的表達,但這可能也導致與現實的割裂;而碼繪擁有大量嚴謹的函式,其呈現效果更接近的自然的鬼斧神工,觀者看起來也更加舒服。

完整程式碼

var clouds = [];
var x, y, z;

function setup() {
	createCanvas(666, 366);

	//初始化山脈
	a = new Mountain(0.5, '#73b9a2', 90, -30);
	b = new Mountain(1, '#367459', 70, 0);
	c = new Mountain(2, '#005344', 50, 30);
	d = new Mountain(3, '#274d3d', 30, 80);

	//初始化白雲
	for (var i = 0; i < 14; i++) {
		clouds.push(new Cloud(random(1001), random(30, 111), random(0.7, 1.1), random(-2, -0.4)));
	}


  	
}

function draw() {
	background('#afdfe4');
  
	//顯示山脈
	a.display();
	b.display();
	c.display();
	d.display();

	//顯示太陽
	noStroke();
	fill('#ffc20e');
	ellipse(100,80,80,80);

	//移動白雲
	for (var i = 0; i < clouds.length; i++) {
		clouds[i].display();
		if (clouds[i].x < -60) {
			clouds[i].x = 1040;
			clouds[i].y = random(10, 100);
			clouds[i].size = random(0.7, 1.1);
			clouds[i].speed = random(-2, -0.4);
		}
	}
}

function Mountain(speed, c, w, h) {
	this.n = 0.01; 
	this.inc = speed; 
	this.w = w;
	this.h = h;

	this.color = color(c);

	this.display = function () {
		for (var x = 0; x < width; x++) {
			var p = (this.n + x) / this.w; 
			var nv = noise(p); 
			var y = ((nv * height) + this.h); 

			stroke(this.color);
			line(x, height, x, y); 
		}
		this.n += this.inc; 
	}
}

function Cloud(x, y, size, speed) {

	this.x = x; 
	this.y = y; 
	this.size = size;

	this.display = function () {

		this.x += speed;

	
		fill('#fffffb');
		noStroke();
		arc(this.x, y, 25 * size, 18 * size, PI + TWO_PI, TWO_PI);
		arc(this.x + 16, y, 22 * size, 45 * size, PI + TWO_PI, TWO_PI);
		arc(this.x + 25, y, 22 * size, 35 * size, PI + TWO_PI, TWO_PI);
		arc(this.x + 38, y, 32 * size, 20 * size, PI + TWO_PI, TWO_PI);
	}
}

參考資料
[1]:https://www.rand-on.com/projects/2016_dusk_mountains/dusk_mountains.html
[2]:https://blog.csdn.net/magicbrushlv/article/details/77840565