前言

最近在做的一款遊戲中,用到點與旋轉矩形的判定來獲得一個選中的物體。在此做個記錄

如圖所示,黃色的顏料屏是旋轉的,如果不做處理直接判斷點是否在矩形中,那麼點擊紅點的位置會判定爲選中物體。顯然這是不對的。

如果物體沒有旋轉,判斷方法就很簡單了。

static isPositionInRect(point: cc.Vec2, rect: cc.Rect) {
        return point.x <= rect.x + rect.width/2 && point.x >= rect.x  - rect.width/2 && point.y <= rect.y + rect.height /2&& point.y >= rect.y - rect.height /2;
    }

我這個矩形錨點爲爲(0.5,0.5),如果錨點不是(0.5,0.5)可以自行修改。

但是判斷一個點在旋轉後的矩形中就沒有這麼簡單了。

怎麼判斷呢?

  1. 首先我想到的是WebGL編程指南第92頁講到的內容。(x,y)在旋轉O角度後得到(x2,y2)
x2 = x * cos(O) - y * sin(O)
 y2 = x * sin(O) + y * cos(O)
  1. 得到了這個公式,我們接下來就是要旋轉觸摸點了。不過這個時候我們要確定要繞哪個點旋轉,是座標系的原點嗎?不是的,而是我們要碰撞的矩形的中心點,因爲矩形是繞這個點旋轉的。

  2. 最終我們得到一個完整的判定函數

/**
     * 判斷點是否在旋轉後的矩形中
     * @param point 觸摸點的座標
     * @param node 碰撞節點,錨點必須爲(0.5,0.5)
     */
    static isPosInRotationRect(point: cc.Vec2, node: cc.Node) {
        let hw = node.width / 2;
        let hh = node.height / 2
        let O = node.angle;
        let center = node.position;
        let X = point.x
        let Y = point.y
        let r = -O * (Math.PI / 180)
        let nTempX = center.x + (X - center.x) * Math.cos(r) - (Y - center.y) * Math.sin(r);
        let nTempY = center.y + (X - center.x) * Math.sin(r) + (Y - center.y) * Math.cos(r);
        if (nTempX > center.x - hw && nTempX < center.x + hw && nTempY > center.y - hh && nTempY < center.y + hh) {
            return true;
        }
        return false
    }
  1. 這裏邊需要注意的是角度O我們用的是反方向的。因爲我們判定使用的矩形的座標和寬高是未旋轉的,也就是下圖的紅色框。所以我們的觸摸點需要反方向旋轉角度O才能使用之前的判定方法。

    當你點擊了1的位置,經過反方向的旋轉後會到達2的位置,然後與紅色框的矩形判斷,纔會得到正確的判定結果。如果觸摸點旋轉的角度與矩形旋轉的角度相同,那麼點擊1的位置就會向左移動,也會判定爲選中,就會得到不正確的結果了。

結語

以上就是如何判定一個點在旋轉後的矩形中的一種方式。在網上搜索的時候發現有很多種實現方式,但是感覺都比較繁瑣。有興趣的小夥伴可以自己去研究研究。不過用我這個判定函數已經可以達到目的了。

參考

  1. https://www.jianshu.com/p/bde70668b1bc
  2. https://www.deanhan.cn/js-point-in-rotate-rect.html
  3. https://blog.csdn.net/C_panpan/article/details/50476965?utm_source=blogxgwz1

長按下方二維碼,關注《微笑遊戲》公衆號,獲取更多精彩內容。

歡迎掃碼關注公衆號《微笑遊戲》,瀏覽更多內容。

相關文章