cocos2d-lua如何绘制圆角矩形?

cocos2d-lua如何绘制圆角矩形?

喜欢这个问题 | 分享 | 新建回答

回答

东方不败

Nov 15, 2023
1 赞

在该回答的基础上进行一个补充改写,将该回答中的第一种方法"drawRoundRect"也改写成类似"zhuanfou_create_solid_round_rect(node, x, y, w, h, radius, color)"的这种格式。

-- 画圆角矩形的另一种实现方式
-- 使用多段线的方式模拟画圆角矩形
function zhuanfou_create_solid_round_rect(node, rx, ry, rwidth, rheight, radius, fillColor)
  -- pointsCount表示圆角的精细度,值越大越精细
  -- pointsCount是段数,也就是cocos2d-lua的api中的segments参数
  -- 即使是画圆,也是有该参数的
  ry = ry + rheight
  local color = cc.c4f(0,0,0,0) -- border-color设置为透明
  local borderWidth = 0
  local pointsCount = 100
  local origin      = cc.p(rx, ry)
  local destination = cc.p(rx + rwidth, ry - rheight)
  local points      = {}
  -- 算出1/4圆
  local coef     = math.pi / 2 / pointsCount
  local vertices = {}
  for i=0, pointsCount do
    local rads = (pointsCount - i) * coef
    local x    = radius * math.sin(rads)
    local y    = radius * math.cos(rads)
    table.insert(vertices, cc.p(x, y))
  end
  local tagCenter      = cc.p(0, 0)
  local minX           = math.min(origin.x, destination.x)
  local maxX           = math.max(origin.x, destination.x)
  local minY           = math.min(origin.y, destination.y)
  local maxY           = math.max(origin.y, destination.y)
  local dwPolygonPtMax = (pointsCount + 1) * 4
  local pPolygonPtArr  = {}
  -- 左上角
  tagCenter.x = minX + radius;
  tagCenter.y = maxY - radius;
  for i=0, pointsCount do
    local x = tagCenter.x - vertices[i + 1].x
    local y = tagCenter.y + vertices[i + 1].y
    table.insert(pPolygonPtArr, cc.p(x, y))
  end
  -- 右上角
  tagCenter.x = maxX - radius;
  tagCenter.y = maxY - radius;
  for i=0, pointsCount do
    local x = tagCenter.x + vertices[#vertices - i].x
    local y = tagCenter.y + vertices[#vertices - i].y
    table.insert(pPolygonPtArr, cc.p(x, y))
  end
  -- 右下角
  tagCenter.x = maxX - radius;
  tagCenter.y = minY + radius;
  for i=0, pointsCount do
    local x = tagCenter.x + vertices[i + 1].x
    local y = tagCenter.y - vertices[i + 1].y
    table.insert(pPolygonPtArr, cc.p(x, y))
  end
  -- 左下角
  tagCenter.x = minX + radius;
  tagCenter.y = minY + radius;
  for i=0, pointsCount do
    local x = tagCenter.x - vertices[#vertices - i].x
    local y = tagCenter.y - vertices[#vertices - i].y
    table.insert(pPolygonPtArr, cc.p(x, y))
  end
  if fillColor == nil then
    fillColor = cc.c4f(0, 0, 0, 0)
  end
  node:drawPolygon(pPolygonPtArr, #pPolygonPtArr, fillColor, borderWidth, color)
end

以上这种方式的本质就是通过画多边形的方式来实现圆角矩形,因为只要顶点足够多,那在肉眼下就可以模拟出圆角多边形。上面的这种方式是画实色填充的圆角矩形,把描边功能阉割掉了,多边形的border可自行修改上述代码实现。



jerkzhang

Apr 16, 2023
1 赞

示例代码如下,以下代码是网上别人的代码改的,并非我原创,仅供参考,其本质是把圆角分为多个点去模拟出来,最终是一个模拟出的完美的多边形。(备注,下述程序坐标系的y轴是向下增大的)

-- 返回画圆角矩形的drawNode对象
function drawRoundRect(rx, ry, rwidth, rheight, borderWidth, radius, color, fillColor)
  -- pointsCount表示圆角的精细度,值越大越精细
  -- pointsCount是段数,也就是cocos2d-lua的api中的segments参数
  -- 即使是画圆,也是有该参数的
  local pointsCount    = 100
  local origin      = cc.p(rx, ry)
  local destination = cc.p(rx + rwidth, ry - rheight)
  local points      = {}
  -- 算出1/4圆
  local coef     = math.pi / 2 / pointsCount
  local vertices = {}
  for i=0, pointsCount do
    local rads = (pointsCount - i) * coef
    local x    = radius * math.sin(rads)
    local y    = radius * math.cos(rads)
    table.insert(vertices, cc.p(x, y))
  end
  local tagCenter      = cc.p(0, 0)
  local minX           = math.min(origin.x, destination.x)
  local maxX           = math.max(origin.x, destination.x)
  local minY           = math.min(origin.y, destination.y)
  local maxY           = math.max(origin.y, destination.y)
  local dwPolygonPtMax = (pointsCount + 1) * 4
  local pPolygonPtArr  = {}
  -- 左上角
  tagCenter.x = minX + radius;
  tagCenter.y = maxY - radius;
  for i=0, pointsCount do
    local x = tagCenter.x - vertices[i + 1].x
    local y = tagCenter.y + vertices[i + 1].y
    table.insert(pPolygonPtArr, cc.p(x, y))
  end
  -- 右上角
  tagCenter.x = maxX - radius;
  tagCenter.y = maxY - radius;
  for i=0, pointsCount do
    local x = tagCenter.x + vertices[#vertices - i].x
    local y = tagCenter.y + vertices[#vertices - i].y
    table.insert(pPolygonPtArr, cc.p(x, y))
  end
  -- 右下角
  tagCenter.x = maxX - radius;
  tagCenter.y = minY + radius;
  for i=0, pointsCount do
    local x = tagCenter.x + vertices[i + 1].x
    local y = tagCenter.y - vertices[i + 1].y
    table.insert(pPolygonPtArr, cc.p(x, y))
  end
  -- 左下角
  tagCenter.x = minX + radius;
  tagCenter.y = minY + radius;
  for i=0, pointsCount do
    local x = tagCenter.x - vertices[#vertices - i].x
    local y = tagCenter.y - vertices[#vertices - i].y
    table.insert(pPolygonPtArr, cc.p(x, y))
  end
  if fillColor == nil then
    fillColor = cc.c4f(0, 0, 0, 0)
  end
  local drawNode = cc.DrawNode:create()
  drawNode:drawPolygon(pPolygonPtArr, #pPolygonPtArr, fillColor, borderWidth, color)
  return drawNode
endda




但是,如果不需要考虑border问题,只考虑填充图形是一个圆角矩形的话,可以考虑通过画方(drawSolidRect )和画圆(drawSolidCircle)的组合。如下所示。(备注,下程序的坐标系的y轴与cocos2d-x的坐标系一致,y轴向上增大的。)

function zhuanfou_create_solid_round_rect(node, x, y, w, h, radius, color)
    local angle = math.pi / 2
    local segments = 100
    node:drawSolidCircle(cc.p(x+radius,y+radius), radius, angle, segments, 1, 1, color)
    node:drawSolidCircle(cc.p(x+w-radius,y+radius), radius, angle, segments, 1, 1, color)
    node:drawSolidCircle(cc.p(x+radius,y+h-radius), radius, angle, segments, 1, 1, color)
    node:drawSolidCircle(cc.p(x+w-radius,y+h-radius), radius, angle, segments, 1, 1, color)
    node:drawSolidRect(cc.p(x+radius, y), cc.p(x+w-radius, y+h), color)
    node:drawSolidRect(cc.p(x, y+radius), cc.p(x+radius, y+h-radius), color)
    node:drawSolidRect(cc.p(x+w-radius, y+radius), cc.p(x+w, y+h-radius), color)
end