摘要:物理學(xué)中提到物體的速度通常是指其瞬時(shí)速度。相對(duì)論框架中,物體的速度上限是光速。緩動(dòng)緩動(dòng)是指物體的速度與它到目標(biāo)點(diǎn)的距離成比例,即基于距離的比例速度,這個(gè)比例會(huì)影響速度的大小。特別注意,距離為時(shí)加速度也為,但速度不一定為。
前言
上一篇基本已經(jīng)對(duì)canvas打好了基礎(chǔ),本篇主要將引入經(jīng)典物理概念速度和加速度,探討他們?cè)诰幊虅?dòng)畫中的應(yīng)用。
在閱讀之前請(qǐng)先自行了解速度和加速度的基礎(chǔ)知識(shí),以及向量與向量加法。
本人能力有限,歡迎牛人共同討論,批評(píng)指正。
【科普】速度是描述物體運(yùn)動(dòng)快慢和方向的物理量。物理學(xué)中提到物體的速度通常是指其瞬時(shí)速度。速度在國際單位制中的單位是米每秒,國際符號(hào)是m/s,中文符號(hào)是米/秒。相對(duì)論框架中,物體的速度上限是光速。
在動(dòng)畫編程中,速度是最基礎(chǔ)的要素,在本系列教程的第2篇講到三角函數(shù)時(shí)就有所體現(xiàn)。
動(dòng)畫編程中的速度見下圖,我們這里要討論的計(jì)算機(jī)動(dòng)畫中的速度跟物理學(xué)上概念相似,都是矢量,也就是既有大小又有方向,而方向的體現(xiàn)就是其值的正負(fù),回顧系列第1篇中講到的坐標(biāo)系,沿著正半軸運(yùn)動(dòng)速度就是正,沿著負(fù)半軸運(yùn)動(dòng)速度就是負(fù)。
另外一點(diǎn)不同就是單位,不一定會(huì)以時(shí)間為單位,可能是以幀為單位,比如“像素/幀”。
也正因?yàn)樗俣仁鞘噶浚侨魏我粋€(gè)速度都可以分解為x軸和y軸上的速度,這就是編程動(dòng)畫基本思想。
將系列第2篇的“一個(gè)會(huì)跟蹤鼠標(biāo)位置的箭頭”改造成“跟隨鼠標(biāo)的箭頭”。代碼很基礎(chǔ),看注釋就行,基本思路:
計(jì)算目標(biāo)點(diǎn)與物體的夾角;
依據(jù)夾角分解速度到x軸和y軸;
分別將每條軸上的速度與物體的位置坐標(biāo)相加。
特別說明,因?yàn)檫@個(gè)例子中的動(dòng)畫循環(huán)是基于幀,所以速度單位是像素每幀。
完整例子:跟隨鼠標(biāo)的箭頭
/** * 跟隨鼠標(biāo)的箭頭 * */ window.onload = function () { const canvas = document.getElementById("canvas"); const context = canvas.getContext("2d"); const mouse = utils.captureMouse(canvas); const arrow = new Arrow(); // 設(shè)定速度 const speed = 3; (function drawFrame() { window.requestAnimationFrame(drawFrame, canvas); context.clearRect(0, 0, canvas.width, canvas.height); // 計(jì)算鼠標(biāo)與箭頭的相對(duì)距離 const dx = mouse.x - arrow.x; const dy = mouse.y - arrow.y; // 求箭頭指向鼠標(biāo)的夾角 const angle = Math.atan2(dy, dx); // 將速度分解到x軸和y軸 const vx = Math.cos(angle) * speed; const vy = Math.sin(angle) * speed; // 設(shè)置箭頭的角度 arrow.rotation = angle; // 將分解后的速度加到箭頭的兩軸位置上 arrow.x += vx; arrow.y += vy; // 重新繪制箭頭 arrow.draw(context); }()); };加速度
【科普】加速度是物理學(xué)中的一個(gè)物理量,是一個(gè)矢量,主要應(yīng)用于經(jīng)典物理當(dāng)中,一般用字母a表示,在國際單位制中的單位為米每二次方秒。加速度是速度矢量對(duì)于時(shí)間的變化率,描述速度的方向和大小變化的快慢。動(dòng)畫編程中的加速度
計(jì)算機(jī)動(dòng)畫中的加速度就是速度的變化量,跟前面的速度一樣是矢量,也可以分解為x軸和y軸上的加速度,方法同上。單位可以是像素每二次方幀,與“力學(xué)”有很大聯(lián)系。
加速度可以讓運(yùn)動(dòng)更加自然,在計(jì)算機(jī)動(dòng)畫中模擬真實(shí)運(yùn)動(dòng)是必要的基礎(chǔ)。
請(qǐng)明確加速度是速度的變化量,也就是加速度的方向與速度相同即加速,方向相反即減速,如果加速度為零,速度將恒定,物體做勻速直線運(yùn)動(dòng)。
繼續(xù)改造前面的例子跟隨鼠標(biāo)的箭頭為“往鼠標(biāo)方向加速的箭頭”。改造量不大,就是把加速度分解后疊加給速度,基本思路:
計(jì)算目標(biāo)點(diǎn)與物體的夾角;
將加速度同樣分解到x,y軸上;
分別將每條軸上的加速度與速度相加;
再分別將每條軸上的速度與物體的位置坐標(biāo)相加。
完整例子:往鼠標(biāo)方向加速的箭頭
觀察實(shí)例,你會(huì)發(fā)現(xiàn)這個(gè)箭頭雖然運(yùn)動(dòng)比前面例子自然了不少,但卻永遠(yuǎn)都不會(huì)停下,這是由于這里的加速度不變的,而現(xiàn)實(shí)中由于摩擦力等因素加速度是會(huì)被削減的。
/** * 往鼠標(biāo)方向加速的箭頭 * */ window.onload = function () { const canvas = document.getElementById("canvas"); const context = canvas.getContext("2d"); const mouse = utils.captureMouse(canvas); const arrow = new Arrow(); // 初始化速度 let vx = 0; let vy = 0; // 設(shè)定加速度 const force = 0.02; (function drawFrame() { window.requestAnimationFrame(drawFrame, canvas); context.clearRect(0, 0, canvas.width, canvas.height); // 計(jì)算鼠標(biāo)與箭頭的相對(duì)距離 const dx = mouse.x - arrow.x; const dy = mouse.y - arrow.y; // 求箭頭指向鼠標(biāo)的夾角 const angle = Math.atan2(dy, dx); // 將加速度分解到x軸和y軸 const ax = Math.cos(angle) * force; const ay = Math.sin(angle) * force; // 設(shè)置箭頭的角度 arrow.rotation = angle; // 將分解后的加速度加到箭頭的兩軸速度上 vx += ax; vy += ay; // 將分解后的速度加到箭頭的兩軸位置上 arrow.x += vx; arrow.y += vy; // 重新繪制箭頭 arrow.draw(context); }()); };比例運(yùn)動(dòng)
這里會(huì)介紹兩個(gè)較高級(jí)的常見技術(shù),緩動(dòng)和彈動(dòng)。
所謂比例運(yùn)動(dòng),就是運(yùn)動(dòng)程度與目標(biāo)點(diǎn)距離是成正比,簡(jiǎn)單來說就是“距離越遠(yuǎn),運(yùn)動(dòng)程度越大”,這里的運(yùn)動(dòng)程度是指但不局限于速度和加速度的與運(yùn)動(dòng)有關(guān)的變量。
緩動(dòng)是指物體的速度與它到目標(biāo)點(diǎn)的距離成比例,即基于距離的比例速度,這個(gè)比例會(huì)影響速度的大小。
緩動(dòng)的運(yùn)動(dòng)特質(zhì)不止一種,你可以先快后慢,也可以先慢后快,還可以先慢后快再慢等,我們這里只以最簡(jiǎn)單的先快后慢為例,即距離越大,速度越大,距離縮進(jìn)到0,速度也為0。
還是改造前面的跟隨鼠標(biāo)的箭頭,代碼如下,基本思路:
確定一個(gè)比例系數(shù),這是一個(gè)0~1之間的小數(shù);
確定目標(biāo)點(diǎn),并計(jì)算相對(duì)距離;
計(jì)算速度,速度=距離×比例系數(shù);
用當(dāng)前位置加上速度來計(jì)算新的位置;
重復(fù)第2~4步,直到物體到達(dá)目標(biāo)點(diǎn)。
完整例子:緩動(dòng)到鼠標(biāo)位置的箭頭
/** * 往鼠標(biāo)方向緩動(dòng)的箭頭 * */ window.onload = function () { const canvas = document.getElementById("canvas"); const context = canvas.getContext("2d"); const mouse = utils.captureMouse(canvas); const arrow = new Arrow(); // 比例系數(shù) const easing = 0.05; (function drawFrame() { window.requestAnimationFrame(drawFrame, canvas); context.clearRect(0, 0, canvas.width, canvas.height); // 計(jì)算鼠標(biāo)與箭頭的相對(duì)距離 const dx = mouse.x - arrow.x; const dy = mouse.y - arrow.y; // 求箭頭指向鼠標(biāo)的夾角 const angle = Math.atan2(dy, dx); // 根據(jù)距離緩動(dòng) const vx = dx * easing; const vy = dy * easing; // 設(shè)置箭頭的角度 arrow.rotation = angle; // 將分解后的速度加到箭頭的兩軸位置上 arrow.x += vx; arrow.y += vy; // 重新繪制箭頭 arrow.draw(context); }()); };彈動(dòng)
彈動(dòng)是指物體的加速度與它到目標(biāo)點(diǎn)的距離成比例,即基于距離的比例加速度,這個(gè)比例會(huì)影響加速度的大小。
彈動(dòng)會(huì)使運(yùn)動(dòng)自然且有靈性,你會(huì)發(fā)現(xiàn)物體會(huì)沖過目標(biāo)點(diǎn),然后開始回彈,往復(fù)。這樣就能模擬出彈簧或橡皮筋的效果。
特別注意,距離為0時(shí)加速度也為0,但速度不一定為0。
還是改造前面的往鼠標(biāo)方向加速的箭頭,代碼如下,你會(huì)發(fā)現(xiàn)這個(gè)跟前面的加速度例子很像,都是不斷的往復(fù)運(yùn)動(dòng),其原因都是加速度和速度很難同時(shí)為0導(dǎo)致的,這里我們加了削減系數(shù)讓它停下來,基本思路:
確定一個(gè)比例系數(shù),這是一個(gè)0~1之間的小數(shù);
確定目標(biāo)點(diǎn),并計(jì)算相對(duì)距離;
計(jì)算速度,加速度=距離×比例系數(shù);
用當(dāng)前速度加上加速度;
用當(dāng)前位置加上速度來計(jì)算新的位置;
重復(fù)第2~5步。
完整例子:往鼠標(biāo)方向彈動(dòng)的箭頭
/** * 往鼠標(biāo)方向彈動(dòng)的箭頭 * */ window.onload = function () { const canvas = document.getElementById("canvas"); const context = canvas.getContext("2d"); const mouse = utils.captureMouse(canvas); const arrow = new Arrow(); // 設(shè)定彈動(dòng)系數(shù) const spring = 0.02; // 初始化速度 let vx = 0; let vy = 0; // 削減系數(shù) const friction = 0.95; (function drawFrame() { window.requestAnimationFrame(drawFrame, canvas); context.clearRect(0, 0, canvas.width, canvas.height); // 計(jì)算鼠標(biāo)與箭頭的相對(duì)距離 const dx = mouse.x - arrow.x; const dy = mouse.y - arrow.y; // 求箭頭指向鼠標(biāo)的夾角 const angle = Math.atan2(dy, dx); // 根據(jù)距離彈動(dòng) const ax = dx * spring; const ay = dy * spring; // 設(shè)置箭頭的角度 arrow.rotation = angle; // 將分解后的加速度加到箭頭的兩軸速度上 vx += ax; vy += ay; // 削減速度 vx *= friction; vy *= friction; // 將分解后的速度加到箭頭的兩軸位置上 arrow.x += vx; arrow.y += vy; // 重新繪制箭頭 arrow.draw(context); }()); };
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/93727.html
摘要:物理學(xué)中提到物體的速度通常是指其瞬時(shí)速度。相對(duì)論框架中,物體的速度上限是光速。緩動(dòng)緩動(dòng)是指物體的速度與它到目標(biāo)點(diǎn)的距離成比例,即基于距離的比例速度,這個(gè)比例會(huì)影響速度的大小。特別注意,距離為時(shí)加速度也為,但速度不一定為。 前言 上一篇基本已經(jīng)對(duì)canvas打好了基礎(chǔ),本篇主要將引入經(jīng)典物理概念速度和加速度,探討他們?cè)诰幊虅?dòng)畫中的應(yīng)用。 在閱讀之前請(qǐng)先自行了解速度和加速度的基礎(chǔ)知識(shí),以...
摘要:前言解決運(yùn)動(dòng)和碰撞問題后,我們?yōu)榱俗屵\(yùn)動(dòng)環(huán)境更加自然,需要加入一些環(huán)境因子,比如常見的重力加速度和模擬摩擦力。核心代碼如下完整示例重力加速度演示模擬摩擦力科普阻礙物體相對(duì)運(yùn)動(dòng)或相對(duì)運(yùn)動(dòng)趨勢(shì)的力叫做摩擦力。 前言 解決運(yùn)動(dòng)和碰撞問題后,我們?yōu)榱俗屵\(yùn)動(dòng)環(huán)境更加自然,需要加入一些環(huán)境因子,比如常見的重力加速度和模擬摩擦力。 閱讀本篇前請(qǐng)先打好前面的基礎(chǔ)。 本人能力有限,歡迎牛人共同討論,...
摘要:前言解決運(yùn)動(dòng)和碰撞問題后,我們?yōu)榱俗屵\(yùn)動(dòng)環(huán)境更加自然,需要加入一些環(huán)境因子,比如常見的重力加速度和模擬摩擦力。核心代碼如下完整示例重力加速度演示模擬摩擦力科普阻礙物體相對(duì)運(yùn)動(dòng)或相對(duì)運(yùn)動(dòng)趨勢(shì)的力叫做摩擦力。 前言 解決運(yùn)動(dòng)和碰撞問題后,我們?yōu)榱俗屵\(yùn)動(dòng)環(huán)境更加自然,需要加入一些環(huán)境因子,比如常見的重力加速度和模擬摩擦力。 閱讀本篇前請(qǐng)先打好前面的基礎(chǔ)。 本人能力有限,歡迎牛人共同討論,...
閱讀 3104·2021-11-22 09:34
閱讀 607·2021-11-22 09:34
閱讀 2457·2021-10-08 10:18
閱讀 3390·2021-09-22 15:57
閱讀 2603·2021-09-22 15:25
閱讀 2423·2019-08-30 15:54
閱讀 2139·2019-08-30 15:44
閱讀 1811·2019-08-29 11:18