摘要:前言本篇主要講坐標(biāo)旋轉(zhuǎn)及其應(yīng)用,這是編程動(dòng)畫必不可少的技術(shù)。坐標(biāo)旋轉(zhuǎn)模擬場(chǎng)景已知一個(gè)中心點(diǎn),旋轉(zhuǎn)前物體,旋轉(zhuǎn)弧度求旋轉(zhuǎn)后物體。坐標(biāo)旋轉(zhuǎn)常見的應(yīng)用就是處理這種情況,將不規(guī)律方向的復(fù)雜問(wèn)題簡(jiǎn)單化。
前言
本篇主要講坐標(biāo)旋轉(zhuǎn)及其應(yīng)用,這是編程動(dòng)畫必不可少的技術(shù)。
閱讀本篇前請(qǐng)先打好前面的基礎(chǔ)。
本人能力有限,歡迎牛人共同討論,批評(píng)指正。
模擬場(chǎng)景:已知一個(gè)中心點(diǎn)(centerX,centerY),旋轉(zhuǎn)前物體ball(x1,y1),旋轉(zhuǎn)弧度(rotation);求旋轉(zhuǎn)后物體(x2,y2)。(如下圖)
坐標(biāo)旋轉(zhuǎn)就是說(shuō)圍繞某個(gè)點(diǎn)旋轉(zhuǎn)坐標(biāo),我們要依據(jù)旋轉(zhuǎn)的角度(弧度),計(jì)算出物體旋轉(zhuǎn)前后的坐標(biāo),一般有兩種方法:
簡(jiǎn)單坐標(biāo)旋轉(zhuǎn)靈活運(yùn)用前章節(jié)的三角函數(shù)知識(shí)可以很容易解決,基本思路:
計(jì)算物體初始相對(duì)于中心點(diǎn)的位置;
使用atan2計(jì)算弧度angle;
使用勾股定理計(jì)算半徑radius;
angle+rotation后使用cos計(jì)算旋轉(zhuǎn)后x軸位置,用sin計(jì)算旋轉(zhuǎn)后y軸位置。
下面是示例是采用這種方法的圓周運(yùn)動(dòng),其中vr為ball相對(duì)于中心點(diǎn)的弧度變化速度,由于旋轉(zhuǎn)半徑是固定的,所以沒有在動(dòng)畫循環(huán)里每次都獲取。
完整示例:簡(jiǎn)單坐標(biāo)旋轉(zhuǎn)演示
/** * 簡(jiǎn)單坐標(biāo)旋轉(zhuǎn)演示 * */ window.onload = function () { const canvas = document.getElementById("canvas"); const context = canvas.getContext("2d"); const ball = new Ball(); ball.x = 300; ball.y = 200; // 弧度變化速度 const vr = 0.05; // 中心點(diǎn)位置設(shè)定在畫布中心 const centerX = canvas.width / 2; const centerY = canvas.height / 2; // ball相對(duì)與中心點(diǎn)的距離 const dx = ball.x - centerX; const dy = ball.y - centerY; // ball相對(duì)與中心點(diǎn)的弧度 let angle = Math.atan2(dy, dx); // 旋轉(zhuǎn)半徑 const radius = Math.sqrt(dx ** 2 + dy ** 2); (function drawFrame() { window.requestAnimationFrame(drawFrame, canvas); context.clearRect(0, 0, canvas.width, canvas.height); ball.x = centerX + Math.cos(angle) * radius; ball.y = centerY + Math.sin(angle) * radius; angle += vr; ball.draw(context); }()); };坐標(biāo)旋轉(zhuǎn)公式
上面的方法對(duì)于單個(gè)物體來(lái)說(shuō)是很合適的,特別是角度和半徑只需計(jì)算一次的情況。但是在更動(dòng)態(tài)的場(chǎng)景中,可能需要旋轉(zhuǎn)多個(gè)物體,而他們相對(duì)于中心點(diǎn)的位置各不相同。所以每一幀都要計(jì)算每個(gè)物體的距離、角度和半徑,然后把vr累加在角度上,最后計(jì)算物體新的坐標(biāo)。這樣顯然不會(huì)是優(yōu)雅的做法。
理想的做法是用數(shù)學(xué)方法推導(dǎo)出旋轉(zhuǎn)角度與位置的關(guān)系,直接每次代入計(jì)算即可。推導(dǎo)過(guò)程如下圖:
其實(shí)推導(dǎo)過(guò)程不重要,我們只需要記住如下兩組公式,其中dx2和dy2是ball結(jié)束點(diǎn)相對(duì)于中心點(diǎn)的距離,所以得到物體結(jié)束點(diǎn),還要分別加上中心點(diǎn)坐標(biāo)。
// 正向選擇 dx2 = (x1 - centerX) * cos(rotation) - (y1 - centerY) * sin(rotation) dy2 = (y1 - centerY) * cos(rotation) + (x1 - centerX) * sin(rotation) // 反向選擇 dx2 = (x1 - centerX) * cos(rotation) + (y1 - centerY) * sin(rotation) dy2 = (y1 - centerY) * cos(rotation) - (x1 - centerX) * sin(rotation)
下面是示例是采用這種方法的圓周運(yùn)動(dòng),其中dx1和dy1是ball起始點(diǎn)相對(duì)于中心點(diǎn)的距離,dx2和dy2是ball結(jié)束點(diǎn)相對(duì)于中心點(diǎn)的距離。
完整示例:高級(jí)坐標(biāo)旋轉(zhuǎn)演示
/** * 高級(jí)坐標(biāo)旋轉(zhuǎn)演示 * */ window.onload = function () { const canvas = document.getElementById("canvas"); const context = canvas.getContext("2d"); const ball = new Ball(); ball.x = 300; ball.y = 200; // 弧度變化速度 const vr = 0.05; // 中心點(diǎn)位置設(shè)定在畫布中心 const centerX = canvas.width / 2; const centerY = canvas.height / 2; // 由于vr是固定的可以先計(jì)算正弦和余弦 const cos = Math.cos(vr); const sin = Math.sin(vr); (function drawFrame() { window.requestAnimationFrame(drawFrame, canvas); context.clearRect(0, 0, canvas.width, canvas.height); // ball相對(duì)與中心點(diǎn)的距離 const dx1 = ball.x - centerX; const dy1 = ball.y - centerY; // 代入公式求出ball在結(jié)束相對(duì)與中心點(diǎn)的距離 const dx2 = dx1 * cos - dy1 * sin; const dy2 = dy1 * cos + dx1 * sin; // 求出x2,y2 ball.x = centerX + dx2; ball.y = centerY + dy2; ball.draw(context); }()); };斜面反彈
前面的章節(jié)中我們介紹過(guò)越界的一種處理辦法是反彈,由于邊界是矩形,反彈面垂直或水平,所以可以直接將對(duì)應(yīng)軸的速度取反即可,但對(duì)于非垂直或水平的反彈面這種方法是不適用的。
坐標(biāo)旋轉(zhuǎn)常見的應(yīng)用就是處理這種情況,將不規(guī)律方向的復(fù)雜問(wèn)題簡(jiǎn)單化。
基本思路:(旋轉(zhuǎn)前后如圖)
使用旋轉(zhuǎn)公式,旋轉(zhuǎn)整個(gè)系統(tǒng),將斜面場(chǎng)景轉(zhuǎn)變?yōu)樗綀?chǎng)景;
在水平場(chǎng)景中處理反彈;
再旋轉(zhuǎn)回來(lái)。
示例是一個(gè)球掉落到一條線上,球受到重力加速度影響下落,碰到斜面就會(huì)反彈,每次反彈都會(huì)損耗速度。
完整示例:斜面反彈示例
window.onload = function () { const canvas = document.getElementById("canvas"); const context = canvas.getContext("2d"); const ball = new Ball(); // line類構(gòu)造函數(shù)參數(shù)(開始點(diǎn)x軸坐標(biāo),開始點(diǎn)y軸坐標(biāo),結(jié)束點(diǎn)x軸坐標(biāo),結(jié)束點(diǎn)y軸坐標(biāo)) const line = new Line(0, 0, 500, 0); // 設(shè)置重力加速度 const gravity = 0.2; // 設(shè)置反彈系數(shù) const bounce = -0.6; ball.x = 100; ball.y = 100; line.x = 0; line.y = 200; line.rotation = 10 * Math.PI / 180; const cos = Math.cos(line.rotation); const sin = Math.sin(line.rotation); (function drawFrame() { window.requestAnimationFrame(drawFrame, canvas); context.clearRect(0, 0, canvas.width, canvas.height); ball.vy += gravity; ball.x += ball.vx; ball.y += ball.vy; // 獲取ball與line的相對(duì)位置 let x1 = ball.x - line.x; let y1 = ball.y - line.y; // 旋轉(zhuǎn)坐標(biāo)系(反向) let y2 = y1 * cos - x1 * sin; // 依據(jù)旋轉(zhuǎn)值執(zhí)行反彈 if (y2 > -ball.radius) { // 旋轉(zhuǎn)坐標(biāo)系(反向) const x2 = x1 * cos + y1 * sin; // 旋轉(zhuǎn)速度(反向) const vx1 = ball.vx * cos + ball.vy * sin; let vy1 = ball.vy * cos - ball.vx * sin; y2 = -ball.radius; vy1 *= bounce; // 將所有東西回轉(zhuǎn)(正向) x1 = x2 * cos - y2 * sin; y1 = y2 * cos + x2 * sin; ball.vx = vx1 * cos - vy1 * sin; ball.vy = vy1 * cos + vx1 * sin; ball.x = line.x + x1; ball.y = line.y + y1; } ball.draw(context); line.draw(context); }()); };
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/52112.html
摘要:前言本篇主要講坐標(biāo)旋轉(zhuǎn)及其應(yīng)用,這是編程動(dòng)畫必不可少的技術(shù)。坐標(biāo)旋轉(zhuǎn)模擬場(chǎng)景已知一個(gè)中心點(diǎn),旋轉(zhuǎn)前物體,旋轉(zhuǎn)弧度求旋轉(zhuǎn)后物體。坐標(biāo)旋轉(zhuǎn)常見的應(yīng)用就是處理這種情況,將不規(guī)律方向的復(fù)雜問(wèn)題簡(jiǎn)單化。 前言 本篇主要講坐標(biāo)旋轉(zhuǎn)及其應(yīng)用,這是編程動(dòng)畫必不可少的技術(shù)。 閱讀本篇前請(qǐng)先打好前面的基礎(chǔ)。 本人能力有限,歡迎牛人共同討論,批評(píng)指正。 坐標(biāo)旋轉(zhuǎn) 模擬場(chǎng)景:已知一個(gè)中心點(diǎn)(centerX...
摘要:前言上篇主要是理論的概述,本篇會(huì)多些實(shí)踐,來(lái)講講的基礎(chǔ)用法,并包含一些基礎(chǔ)三角函數(shù)的應(yīng)用,推薦沒有基礎(chǔ)的朋友閱讀,熟悉的朋友可以跳過(guò)。完整實(shí)例一個(gè)會(huì)跟蹤鼠標(biāo)位置的箭頭三角函數(shù)上下運(yùn)動(dòng)終于順利過(guò)渡到三角函數(shù)的話題笑。 前言 上篇主要是理論的概述,本篇會(huì)多些實(shí)踐,來(lái)講講canvas的基礎(chǔ)用法,并包含一些基礎(chǔ)三角函數(shù)的應(yīng)用,推薦沒有canvas基礎(chǔ)的朋友閱讀,熟悉的朋友可以跳過(guò)。 本人能力...
摘要:前言上篇主要是理論的概述,本篇會(huì)多些實(shí)踐,來(lái)講講的基礎(chǔ)用法,并包含一些基礎(chǔ)三角函數(shù)的應(yīng)用,推薦沒有基礎(chǔ)的朋友閱讀,熟悉的朋友可以跳過(guò)。完整實(shí)例一個(gè)會(huì)跟蹤鼠標(biāo)位置的箭頭三角函數(shù)上下運(yùn)動(dòng)終于順利過(guò)渡到三角函數(shù)的話題笑。 前言 上篇主要是理論的概述,本篇會(huì)多些實(shí)踐,來(lái)講講canvas的基礎(chǔ)用法,并包含一些基礎(chǔ)三角函數(shù)的應(yīng)用,推薦沒有canvas基礎(chǔ)的朋友閱讀,熟悉的朋友可以跳過(guò)。 本人能力...
閱讀 1123·2021-10-12 10:11
閱讀 903·2019-08-30 15:53
閱讀 2325·2019-08-30 14:15
閱讀 2989·2019-08-30 14:09
閱讀 1228·2019-08-29 17:24
閱讀 1004·2019-08-26 18:27
閱讀 1308·2019-08-26 11:57
閱讀 2184·2019-08-23 18:23