鱼C论坛

 找回密码
 立即注册
查看: 755|回复: 5

[已解决]python cocos2d画多个圆、实心圆

[复制链接]
发表于 2024-11-13 19:10:14 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
以下代码画圆,只显示一个圆,圆周有小缺口。如何画多个圆呢,能画完美的圆吗,能画实心圆吗,
如何将显示窗口放到屏幕中间位置呢?
  1. import cocos
  2. from cocos.director import director
  3. from pyglet.gl import *
  4. from math import cos, tan, pi

  5. class TestLayer(cocos.layer.Layer):
  6.     def __init__(self):
  7.         super().__init__()

  8.         # 画圆
  9.         circle_centers=[(100, 540), (260,540), (420,540), (260,380)]
  10.         for circle_center in circle_centers:
  11.             self.circle_center = circle_center
  12.         self.circle_radius = 50

  13.     def draw(self):
  14.         super().draw()

  15.         # 设置颜色为红色并绘制圆
  16.         glColor4ub(255, 0, 0, 255)
  17.         glLineWidth(10)
  18.         num_segments = 350
  19.         theta = 2 * pi / num_segments
  20.         tangetial_factor = tan(theta)  # Calculate the tangential factor
  21.         radial_factor = cos(theta)  # Calculate the radial factor
  22.         x = self.circle_radius  # Start at angle = 0
  23.         y = 0
  24.         glBegin(GL_LINE_LOOP)
  25.         for i in range(num_segments):
  26.             glVertex2f(x + self.circle_center[0], y + self.circle_center[1])
  27.             tx = -y
  28.             ty = x
  29.             x += tx * tangetial_factor
  30.             y += ty * tangetial_factor
  31.             x *= radial_factor
  32.             y *= radial_factor
  33.         glEnd()

  34. def main():
  35.     director.init(resizable=True, width=520, height=640, caption="szq")
  36.     test_layer = TestLayer()
  37.     main_scene = cocos.scene.Scene(test_layer)
  38.     director.run(main_scene)

  39. if __name__ == '__main__':
  40.     main()
复制代码

最佳答案
2024-11-13 21:14:37
ydwb 发表于 2024-11-13 21:14
以上窗口居中方法正确。画实心圆比较圆滑,画线框圆( ...


要在实心圆内再画一个小一点的背景色实心圆以实现圆环的效果,可以按照以下步骤修改代码:

1. **画大圆:** 先画出具有指定颜色的大圆。
2. **画小圆:** 在大圆内部画一个稍小的圆,颜色与背景色一致,这样就能形成一个圆环效果。

以下是修改后的代码示例:

  1. import cocos
  2. from cocos.director import director
  3. from pyglet.gl import *
  4. from math import cos, sin, pi

  5. class TestLayer(cocos.layer.Layer):
  6.     def __init__(self):
  7.         super().__init__()

  8.         # 定义多个圆心及其半径、颜色
  9.         self.circles = [
  10.             # 示例:圆心(x, y),半径,颜色
  11.             (200, 200, 100, (255, 0, 0)),  # 红色大圆
  12.             (400, 300, 70, (0, 255, 0))   # 绿色大圆
  13.         ]
  14.         self.background_color = (255, 255, 255)  # 背景色,白色

  15.     def draw(self):
  16.         super().draw()
  17.         num_segments = 100  # 用于更平滑的圆
  18.         theta = 2 * pi / num_segments

  19.         for circle_center_x, circle_center_y, circle_radius, color in self.circles:
  20.             # 画大圆 (环的外圈,实际可见)
  21.             R, G, B = color
  22.             glColor4ub(R, G, B, 255)  # 设置颜色
  23.             x, y = circle_radius, 0
  24.             glBegin(GL_TRIANGLE_FAN)
  25.             glVertex2f(circle_center_x, circle_center_y)
  26.             for _ in range(num_segments + 1):
  27.                 glVertex2f(circle_center_x + x, circle_center_y + y)
  28.                 t = x
  29.                 x = cos(theta) * x - sin(theta) * y
  30.                 y = sin(theta) * t + cos(theta) * y
  31.             glEnd()

  32.             # 画小圆 (环的内圈,用背景色覆盖)
  33.             inner_radius = circle_radius - 10  # 调整这个值来设置环的厚度
  34.             if inner_radius > 0:
  35.                 glColor4ub(*self.background_color, 255)  # 设置背景色
  36.                 x, y = inner_radius, 0
  37.                 glBegin(GL_TRIANGLE_FAN)
  38.                 glVertex2f(circle_center_x, circle_center_y)
  39.                 for _ in range(num_segments + 1):
  40.                     glVertex2f(circle_center_x + x, circle_center_y + y)
  41.                     t = x
  42.                     x = cos(theta) * x - sin(theta) * y
  43.                     y = sin(theta) * t + cos(theta) * y
  44.                 glEnd()

  45. def main():
  46.     # 初始化舞台
  47.     window_width = 640
  48.     window_height = 480
  49.     director.init(resizable=True, width=window_width, height=window_height, caption="szq")

  50.     # 将窗口放置于屏幕中央
  51.     display = director.window.display
  52.     screen_width, screen_height = display.get_default_screen().width, display.get_default_screen().height
  53.     window_x = (screen_width - window_width) // 2
  54.     window_y = (screen_height - window_height) // 2
  55.     director.window.set_location(window_x, window_y)

  56.     test_layer = TestLayer()
  57.     main_scene = cocos.scene.Scene(test_layer)
  58.     director.run(main_scene)

  59. if __name__ == '__main__':
  60.     main()
复制代码


### 说明:
- **颜色设置:** 使用`glColor4ub`设置绘制的颜色。
- **内外圆:** 外圆用指定颜色绘制,内圆用背景色绘制,从而形成环形。
- **环厚度:** 通过调整`inner_radius`相对于`circle_radius`的大小,改变环的厚度。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2024-11-13 19:10:38 | 显示全部楼层
要解决您遇到的问题,可以按照以下步骤改进代码:

1. **画多个圆:** 您需要将圆心的坐标存储在一个列表中,然后在`draw`方法中遍历该列表,绘制每一个圆。

2. **画完美的圆:** 增加`num_segments`的数量可以让圆更加平滑。

3. **画实心圆:** 使用`GL_TRIANGLE_FAN`代替`GL_LINE_LOOP`绘制实心圆。

4. **将窗口放到屏幕中间:** 调整窗口创建的参数。

以下是修正后的代码示例:

  1. import cocos
  2. from cocos.director import director
  3. from pyglet.gl import *
  4. from math import cos, sin, pi

  5. class TestLayer(cocos.layer.Layer):
  6.     def __init__(self):
  7.         super().__init__()

  8.         # 定义多个圆心及其半径
  9.         self.circles = [
  10.             ((100, 150), 50),
  11.             ((200, 300), 70),
  12.             ((300, 450), 90)
  13.         ]

  14.     def draw(self):
  15.         super().draw()

  16.         # 设置颜色为红色,默认透明度为不透明
  17.         glColor4ub(255, 0, 0, 255)

  18.         num_segments = 100  # 用于更平滑的圆
  19.         theta = 2 * pi / num_segments

  20.         for circle_center, circle_radius in self.circles:
  21.             x = circle_radius
  22.             y = 0

  23.             # 绘制实心圆
  24.             glBegin(GL_TRIANGLE_FAN)
  25.             glVertex2f(circle_center[0], circle_center[1])  # 圆心
  26.             for i in range(num_segments + 1):  # 包含终点以闭合圆
  27.                 glVertex2f(circle_center[0] + x, circle_center[1] + y)
  28.                 t = x
  29.                 x = cos(theta) * x - sin(theta) * y
  30.                 y = sin(theta) * t + cos(theta) * y
  31.             glEnd()

  32. def main():
  33.     # 初始化舞台
  34.     director.init(resizable=True, width=640, height=480, caption="szq")
  35.    
  36.     # 将窗口放置于屏幕中央(仅适用于某些操作系统)
  37.     screen = director.get_window().screen
  38.     window_position = (screen.width - 640) // 2, (screen.height - 480) // 2
  39.     director.window.set_location(*window_position)

  40.     test_layer = TestLayer()
  41.     main_scene = cocos.scene.Scene(test_layer)
  42.     director.run(main_scene)

  43. if __name__ == '__main__':
  44.     main()
复制代码


### 解释:
- **多个圆:** 使用`self.circles`定义圆心和半径的列表。
- **平滑圆:** 调整`num_segments`来增加圆的平滑度。
- **实心圆:** 使用`GL_TRIANGLE_FAN`来填充圆。
- **居中窗口:** 获取当前屏幕的大小,然后设置窗口的位置。这部分代码在不同操作系统上可能表现不同。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-11-13 20:09:21 | 显示全部楼层
画多个圆、实心圆的方法是对的。调整`num_segments`来增加圆的平滑度,基本没效果。
居中窗口也不行。
    screen = director.get_window().screen
AttributeError: 'Director' object has no attribute 'get_window'
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-11-13 20:14:52 | 显示全部楼层
ydwb 发表于 2024-11-13 20:09
画多个圆、实心圆的方法是对的。调整`num_segments`来 ...


关于调节圆的平滑度以及居中窗口的需求,我们可以尝试以下几个步骤进行改进:

1. **调节圆的平滑度:** 如果增大 `num_segments` 似乎效果不明显,可以检查是否设置到了足够高的值。一般来说 `num_segments` 设置为 100 已经比较平滑了,如果还不够尝试 200 或 300。

2. **居中窗口的位置:** 使用 Pyglet 提供的方法直接设置窗口的位置,而不用通过 `Director` 的方法。

以下是修订后的代码:

  1. import cocos
  2. from cocos.director import director
  3. from pyglet.gl import *
  4. from math import cos, sin, pi

  5. class TestLayer(cocos.layer.Layer):
  6.     def __init__(self):
  7.         super().__init__()

  8.         # 定义多个圆心及其半径
  9.         self.circles = [(150, 150, 50), (300, 300, 75), (450, 150, 100)]

  10.     def draw(self):
  11.         super().draw()

  12.         # 设置颜色为红色
  13.         glColor4ub(255, 0, 0, 255)

  14.         num_segments = 100  # 用于更平滑的圆
  15.         theta = 2 * pi / num_segments

  16.         for circle_center_x, circle_center_y, circle_radius in self.circles:
  17.             x = circle_radius
  18.             y = 0

  19.             # 绘制实心圆
  20.             glBegin(GL_TRIANGLE_FAN)
  21.             glVertex2f(circle_center_x, circle_center_y)  # 圆心
  22.             for i in range(num_segments + 1):  # 包含终点以闭合圆
  23.                 glVertex2f(circle_center_x + x, circle_center_y + y)
  24.                 t = x
  25.                 x = cos(theta) * x - sin(theta) * y
  26.                 y = sin(theta) * t + cos(theta) * y
  27.             glEnd()

  28. def main():
  29.     # 初始化舞台
  30.     window_width = 640
  31.     window_height = 480
  32.     director.init(resizable=True, width=window_width, height=window_height, caption="szq")
  33.    
  34.     # 将窗口放置于屏幕中央
  35.     display = director.window.display
  36.     screen_width, screen_height = display.get_default_screen().width, display.get_default_screen().height
  37.     window_x = (screen_width - window_width) // 2
  38.     window_y = (screen_height - window_height) // 2
  39.     director.window.set_location(window_x, window_y)

  40.     test_layer = TestLayer()
  41.     main_scene = cocos.scene.Scene(test_layer)
  42.     director.run(main_scene)

  43. if __name__ == '__main__':
  44.     main()
复制代码


### 解释:
- **多圆和实心圆绘制:** 使用适合的 `GL_TRIANGLE_FAN` 方法进行绘制。
- **窗口居中:** 使用 Pyglet 的 `display` 和 `get_default_screen` 方法来获得屏幕尺寸,并通过 `set_location` 函数来设置窗口的位置到屏幕的中心。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-11-13 21:14:14 | 显示全部楼层
以上窗口居中方法正确。画实心圆比较圆滑,画线框圆(如线宽10)增大 `num_segments`效果不好,
即使到10000,1000000直到电脑无反应,也达不到预计效果。现考虑在实心圆内再画一个小一点的
背景色实心圆来实现。以下代码应如何修改呢?
import cocos
from cocos.director import director
from pyglet.gl import *
from math import cos, sin, pi

class TestLayer(cocos.layer.Layer):
    def __init__(self):
        super().__init__()

        # 定义多个圆心及其半径、颜色
        self.circles = [(150, 150, 50,'red'), (300, 300, 75,'red'), (450, 150, 100,'red'),
                        (150, 150, 40,'black'),(300, 300, 65,'black'), (450, 150, 90,'black')]

    def draw(self):
        super().draw()
        num_segments = 100  # 用于更平滑的圆
        theta = 2 * pi / num_segments

        for circle_center_x, circle_center_y, circle_radius,color in self.circles:
            x = circle_radius
            y = 0
            glBegin(GL_TRIANGLE_FAN)
            glVertex2f(circle_center_x, circle_center_y)  # 圆心
            for i in range(num_segments+1 ):  # 包含终点以闭合圆
                glVertex2f(circle_center_x + x, circle_center_y + y)
                t = x
                x = cos(theta) * x - sin(theta) * y
                y = sin(theta) * t + cos(theta) * y
            glEnd()

def main():
    # 初始化舞台
    window_width = 640
    window_height = 480
    director.init(resizable=True, width=window_width, height=window_height, caption="szq")

    # 将窗口放置于屏幕中央
    display = director.window.display
    screen_width, screen_height = display.get_default_screen().width, display.get_default_screen().height
    window_x = (screen_width - window_width) // 2
    window_y = (screen_height - window_height) // 2
    director.window.set_location(window_x, window_y)

    test_layer = TestLayer()
    main_scene = cocos.scene.Scene(test_layer)
    director.run(main_scene)

if __name__ == '__main__':
    main()
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-11-13 21:14:37 | 显示全部楼层    本楼为最佳答案   
ydwb 发表于 2024-11-13 21:14
以上窗口居中方法正确。画实心圆比较圆滑,画线框圆( ...


要在实心圆内再画一个小一点的背景色实心圆以实现圆环的效果,可以按照以下步骤修改代码:

1. **画大圆:** 先画出具有指定颜色的大圆。
2. **画小圆:** 在大圆内部画一个稍小的圆,颜色与背景色一致,这样就能形成一个圆环效果。

以下是修改后的代码示例:

  1. import cocos
  2. from cocos.director import director
  3. from pyglet.gl import *
  4. from math import cos, sin, pi

  5. class TestLayer(cocos.layer.Layer):
  6.     def __init__(self):
  7.         super().__init__()

  8.         # 定义多个圆心及其半径、颜色
  9.         self.circles = [
  10.             # 示例:圆心(x, y),半径,颜色
  11.             (200, 200, 100, (255, 0, 0)),  # 红色大圆
  12.             (400, 300, 70, (0, 255, 0))   # 绿色大圆
  13.         ]
  14.         self.background_color = (255, 255, 255)  # 背景色,白色

  15.     def draw(self):
  16.         super().draw()
  17.         num_segments = 100  # 用于更平滑的圆
  18.         theta = 2 * pi / num_segments

  19.         for circle_center_x, circle_center_y, circle_radius, color in self.circles:
  20.             # 画大圆 (环的外圈,实际可见)
  21.             R, G, B = color
  22.             glColor4ub(R, G, B, 255)  # 设置颜色
  23.             x, y = circle_radius, 0
  24.             glBegin(GL_TRIANGLE_FAN)
  25.             glVertex2f(circle_center_x, circle_center_y)
  26.             for _ in range(num_segments + 1):
  27.                 glVertex2f(circle_center_x + x, circle_center_y + y)
  28.                 t = x
  29.                 x = cos(theta) * x - sin(theta) * y
  30.                 y = sin(theta) * t + cos(theta) * y
  31.             glEnd()

  32.             # 画小圆 (环的内圈,用背景色覆盖)
  33.             inner_radius = circle_radius - 10  # 调整这个值来设置环的厚度
  34.             if inner_radius > 0:
  35.                 glColor4ub(*self.background_color, 255)  # 设置背景色
  36.                 x, y = inner_radius, 0
  37.                 glBegin(GL_TRIANGLE_FAN)
  38.                 glVertex2f(circle_center_x, circle_center_y)
  39.                 for _ in range(num_segments + 1):
  40.                     glVertex2f(circle_center_x + x, circle_center_y + y)
  41.                     t = x
  42.                     x = cos(theta) * x - sin(theta) * y
  43.                     y = sin(theta) * t + cos(theta) * y
  44.                 glEnd()

  45. def main():
  46.     # 初始化舞台
  47.     window_width = 640
  48.     window_height = 480
  49.     director.init(resizable=True, width=window_width, height=window_height, caption="szq")

  50.     # 将窗口放置于屏幕中央
  51.     display = director.window.display
  52.     screen_width, screen_height = display.get_default_screen().width, display.get_default_screen().height
  53.     window_x = (screen_width - window_width) // 2
  54.     window_y = (screen_height - window_height) // 2
  55.     director.window.set_location(window_x, window_y)

  56.     test_layer = TestLayer()
  57.     main_scene = cocos.scene.Scene(test_layer)
  58.     director.run(main_scene)

  59. if __name__ == '__main__':
  60.     main()
复制代码


### 说明:
- **颜色设置:** 使用`glColor4ub`设置绘制的颜色。
- **内外圆:** 外圆用指定颜色绘制,内圆用背景色绘制,从而形成环形。
- **环厚度:** 通过调整`inner_radius`相对于`circle_radius`的大小,改变环的厚度。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-21 10:54

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表