【问题标题】:Creating a circle in pygame with points on circumference在pygame中用圆周上的点创建一个圆
【发布时间】:2018-10-21 08:28:43
【问题描述】:

我希望在 pygame 中创建一个圆圈,我可以在边缘带有“传感器”的空间中移动。我希望圆周上有一个“前”、“左”和“右”传感器,我可以用它来操纵圆的运动。

基本上,这些点是为了帮助检测周围的障碍物,并允许圆圈在移动时旋转(以帮助控制移动)。

在下图中你可以看到这个想法,圆圈从一个位置开始,有指针,在空间中移动并避开方形障碍物,我可以在不同的角度转动它而不会失去感觉它的“前”和“后”是什么。

我不在乎圆圈边缘上用于识别“传感器”的点是否在整体图形中看到,只是绘制并标记它们以说明这个想法。

旁注:我意识到看着图像,考虑到圆本身的方向,R 和 L 标签是向后的,但仍然是相同的想法。

【问题讨论】:

  • 圆圈边缘的这些“传感器”是用于检查碰撞,还是用于获取圆圈的方向并查看“前”在哪里?如果是前者,如果你有圆的中心,你可以计算从中心到矩形四个角中的每一个的距离。如果圆心到这些角中的任何一个角的距离小于半径,你就知道圆和矩形一定重叠!如果是后者,只需指定一个点为前,然后添加 CW 90 度得到右边或 90 度 CCW 得到左边。
  • @CodeSurgeon 主要是为了得到圆的方位,看看它的前面在哪里,以免发生碰撞(我在做一个模糊逻辑的实现,它的设置方式是circle 正在复制一个机器人,该机器人将有传感器来查看周围的事物,并使用模糊规则避开周围环境)。如果指定前点是什么,有没有办法在机器人/圆在空间中移动时跟踪这个点? (例如,我不希望它始终是最南端之类的)。
  • 您可能希望将代理的位置和方位与其表示为一个圆圈分开
  • @ReblochonMasque 你能详细说明一下吗? (仍然认为自己在其中一些方面处于初学者水平)
  • 我没有看到明确的问题。

标签: python python-2.7 pygame geometry collision-detection


【解决方案1】:

您可以为这三个点定义一些vectors。如果你用圆的半径创建一个向量并将它添加到中心坐标,你会在圆周上得到一个点。然后您可以将此向量旋转 -90 度和 90 度以获得另外两个向量。当agent旋转时,可以先旋转前面的向量,然后再用它得到左右向量。

这是一个完整的例子:

import pygame as pg
from pygame.math import Vector2


class Agent(pg.sprite.Sprite):

    def __init__(self, pos, *groups):
        super(Agent, self).__init__(*groups)
        self.radius = 25
        self.image = pg.Surface((50, 50), pg.SRCALPHA)
        pg.draw.circle(self.image, pg.Color('dodgerblue4'),
                       (self.radius, self.radius), self.radius)
        self.rect = self.image.get_rect(center=pos)
        self.speed = 0
        self.angular_speed = 0
        self.pos = Vector2(pos)
        # If you add this vector to the center pos, you get a point
        # on the circumference of the circle.
        self.front = Vector2(0, -self.radius)  # Pointing upward.
        # Just rotate the front vector by -90 and 90 degrees to get
        # the left and right vectors. `rotate` returns a new vector.
        self.left = self.front.rotate(-90)
        self.right = self.front.rotate(90)

    def update(self):
        # Use the front vector as the velocity.
        self.pos += self.front.normalize() * self.speed
        self.rect.center = self.pos

        if self.angular_speed != 0:
            self.rotate()

    def rotate(self):
        """Rotate the front vector and use it to update the other two."""
        self.front.rotate_ip(self.angular_speed)
        self.left = self.front.rotate(-90)
        self.right = self.front.rotate(90)

    def draw_vectors(self, screen):
        """Draw the three vectors."""
        pg.draw.circle(screen, (0, 240, 50), list(map(int, self.pos+self.front)), 3)
        pg.draw.circle(screen, (240, 0, 50), list(map(int, self.pos+self.left)), 3)
        pg.draw.circle(screen, (240, 240, 0), list(map(int, self.pos+self.right)), 3)
        pg.draw.line(screen, (0, 240, 50), self.pos, self.pos+self.front, 2)
        pg.draw.line(screen, (240, 0, 50), self.pos, self.pos+self.left, 2)
        pg.draw.line(screen, (240, 240, 0), self.pos, self.pos+self.right, 2)


def main():
    screen = pg.display.set_mode((640, 480))
    clock = pg.time.Clock()
    all_sprites = pg.sprite.Group()
    agent = Agent((100, 300), all_sprites)

    done = False

    while not done:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                done = True
            elif event.type == pg.KEYDOWN:
                if event.key == pg.K_w:
                    agent.speed = 5
                elif event.key == pg.K_a:
                    agent.angular_speed = -10
                elif event.key == pg.K_d:
                    agent.angular_speed = 10
            elif event.type == pg.KEYUP:
                if event.key == pg.K_w:
                    agent.speed = 0
                elif event.key == pg.K_a:
                    agent.angular_speed = 0
                elif event.key == pg.K_d:
                    agent.angular_speed = 0

        all_sprites.update()

        screen.fill((30, 30, 30))
        all_sprites.draw(screen)
        agent.draw_vectors(screen)

        pg.display.flip()
        clock.tick(30)


if __name__ == '__main__':
    pg.init()
    main()
    pg.quit()

【讨论】:

  • 概念问题,对对象使用 sprite 类与简单地使用 pygame.draw.circle 有什么区别/好处?
  • 另外,启动你的代码,看看它是如何工作的,天哪,你是美丽的人类,谢谢!它看起来很酷(如果这意味着我对简单的事情印象深刻,如果这对你来说很简单,或者只是暴露了我仍然是多少初学者)。这对于学习如何让它工作非常有帮助!!!
  • 使用pygame.sprite.Sprite 子类和精灵组通常更方便。他们有方法可以自动从精灵组中删除(kill),sprite 模块中有一些有用的碰撞检测功能。它们还针对性能进行了优化(至少有一点)。
  • 我认为在这种情况下使用精灵对象有助于以更好的方式组织代码,因为您可以将状态和行为捆绑在一个对象中。但是,您可以使用其他一些数据结构(例如列表或字典)和单独的函数来实现相同的目的。
  • 另外一个关于代码的问题,init函数中的rect有什么用?现在我正在尝试创建检测圆左侧和右侧的象限,而我发现的唯一解决方案是使用矩形允许的象限。如果我可以为此目的使用 init 中的矩形,那就太好了!但是知道它在做什么,不想把它搞砸。有什么建议吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-26
  • 1970-01-01
  • 2016-08-26
  • 1970-01-01
  • 2014-03-08
  • 1970-01-01
相关资源
最近更新 更多