【问题标题】:How can I make my circles fly off the screen in pygame?如何让我的圈子在 pygame 中飞出屏幕?
【发布时间】:2012-08-08 08:14:55
【问题描述】:

我是 python 的初学者,我正在尝试制作一个圆形游戏。到目前为止,当您单击时,它会在您的鼠标上绘制一个具有随机颜色和半径的圆圈。

接下来,我希望圆圈以随机方向飞出屏幕。我该怎么做呢?到目前为止,这是我代码的主要部分:

check1 = None
check2 = None

while True:

    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit

        if event.type == MOUSEBUTTONDOWN:
            last_mouse_pos = pygame.mouse.get_pos()



    if last_mouse_pos:

        global check

        color1 = random.randint(0,255)
        color2 = random.randint(0,255)
        color3 = random.randint(0,255)
        color = (color1,color2,color3)

        radius = random.randint (5,40)
        posx,posy = last_mouse_pos

        if posx != check1 and posy != check2:
            global check1, check2
            screen.lock()
            pygame.draw.circle(screen, color, (posx,posy), radius)
            screen.unlock()
            check1,check2 = posx,posy


    pygame.display.update()

再次,我希望圆圈以随机方向飞出屏幕。 我做了一些尝试,但还没有成功。 另外,感谢 jdi 帮助我

【问题讨论】:

  • 您必须编写一个函数,每帧将圆的位置改变一点点。
  • 我有一个使用 HTML5 和 JavaScript 开发的演示,它可以在随机方向上为许多球设置动画。球在改变方向时也会随机改变大小和颜色。您可以在 codentronix.com/2012/01/24/html5-canvas-crazy-balls 看到演示。我可以帮助你用 pygame 做同样的事情。如果你想要的话,请检查并告诉我。

标签: python animation random pygame game-loop


【解决方案1】:

创建圆圈时(点击时),生成 2 个随机数。这些将是二维 Euclidean velocity 向量的 (x,y) 分量:

# interval -1.0 to 1.0, adjust as necessary
vx, vy = ( (random.random()*2) -1, (random.random()*2) - 1 )

然后在创建球后,在游戏循环的每次迭代中,将球的位置增加速度向量:

posx, posy = posx + vx, posy + vy

请注意,整体速度可能是可变的。如果您希望始终保持每秒 1.0 的速度,请对向量进行归一化:

normalize这个向量,你将它除以它的magnitude

所以在你的情况下:

因此:

所以在 Python 中,在导入 mathimport math 之后:

mag = math.sqrt(vx*vx + vy*vy)
v_norm = vx/mag, vy/mag
# use v_norm instead of your (vx, vy) tuple

然后你可以将它与一些speed 变量相乘,以获得可靠的速度。


一旦你让多个对象四处移动并可能离开屏幕,删除那些没有机会回来且与你的程序无关的屏幕外对象很有用。否则,如果您在创建更多对象的同时继续跟踪所有这些屏幕外对象,则本质上会发生内存泄漏,并且如果有足够的时间/操作,内存将耗尽。


虽然您现在正在做的事情很简单,但假设您还没有,学习一些基本的向量数学很快就会得到回报。最终,您可能需要涉足一些矩阵数学来进行某些转换。如果您是新手,它并不像最初看起来那么难。不学习它也许可以侥幸成功,但如果你以后开始尝试做更有野心的事情,你会节省自己的精力。

【讨论】:

    【解决方案2】:

    现在,您正在执行以下操作(大大简化您的代码)...

    while True:
        if the mouse was clicked:
            draw a circle on the screen where the mouse was clicked
    

    让我们让事情变得简单一些,并逐步建立起来。

    从没有用户点击的圆圈开始

    为了简单起见,让我们在屏幕左上角附近画一个圆圈,这样我们总是可以假设会有一个圆圈(使一些逻辑更容易)

    circle_x, circle_y = 10,10
    while True:
        draw the circle at circle_x, circle_y
    
        pygame.display.update()
    

    动画圆

    在过多地讨论“随机方向”之前,让我们简单一点,朝一个方向走(比如说,总是向下和向右)。

    circle_x, circle_y = 0,0
    while True:
        # Update
        circle_x += 0.1
        circle_y += 0.1
    
        # Draw
        draw the circle at circle_x, circle_y
        update the display
    

    现在,每次循环时,圆心都会移动一点,然后将其绘制到新位置。请注意,您可能需要减少添加到 circle_x 和 y 的值(在我的代码中为 0.1),以防圆移动得太快。

    但是,您会注意到您的屏幕现在被圆圈填满了!而不是一个“移动”的圆圈,你只是画了很多次圆圈!为了解决这个问题,我们将在每次绘制之前“清除”屏幕...

    screen = ....
    BLACK = (0,0,0) # Defines the "black" color
    circle_x, circle_y = 0,0
    while True:
        # Update
        circle_x += 0.1
        circle_y += 0.1
    
        # Draw
        screen.fill(BLACK)
        draw the circle at circle_x, circle_y
        update the display
    

    请注意,在绘制圆圈之前,我们通过将整个物体涂成黑色来“清除”屏幕。

    现在,您可以开始将您想要的其余内容重新写入代码。

    跟踪多个圈子

    您可以通过使用圆圈列表而不是两个圆圈变量来做到这一点

    circles = [...list of circle positions...]
    while True:
        # Update
        for circle in circles:
            ... Update the circle position...
    
    
        # Draw
        screen.fill(BLACK)
        for circle in circles:
            draw the circle at circle position # This will occur once for each circle
        update the display
    

    需要注意的一点是,如果您跟踪元组中的圆位置,您将无法更改它们的值。如果您熟悉面向对象编程,您可以创建一个 Circle 类,并使用它来跟踪与您的圈子相关的数据。否则,您可以在每个循环中为每个圆创建一个更新坐标列表。

    用户点击时添加圆圈

    circles = []
    while True:
        # event handling
        for event in pygame.event.get():
            if event.type == MOUSEBUTTONDOWN:
                pos = pygame.mouse.get_pos()
                circles.append( pos ) # Add a new circle to the list
    
        # Update all the circles
        # ....
    
        # Draw
        clear the screen
        for circle_position in circles:
            draw the circle at circle_position # This will occur once for each circle
        update the display
    

    让圆圈沿随机方向移动

    这就是很好的数学帮助发挥作用的地方。基本上,您需要一种方法来确定每个循环更新圆的 x 和 y 坐标的方法。请记住,完全有可能只说您希望它在每个轴(X,y)的 -1 和 1 之间移动,但这不一定是正确的。您可能使 X 和 Y 都为零,在这种情况下,圆根本不会移动!下一个 Circle 可能是 1 和 1,它会比其他圈快。

    我不确定您的数学背景是什么,因此您可能需要学习一些知识才能了解如何将“方向”(有时称为“矢量”)存储在程序。您可以尝试 Preet 的回答,看看是否有帮助。有几何学和三角学背景的人更容易真正理解(尽管如果你找到了一个好的资源,你可能没有它也能过得去)。

    其他一些想法

    您需要记住的其他一些事项:

    1. 现在,我们正在使用“取决于帧速率”的代码。也就是说,圆圈在屏幕上移动的速度完全取决于计算机的运行速度;较慢的计算机会看到圆圈像蜗牛一样移动,而较快的计算机在圆圈飞出屏幕之前几乎看不到圆圈!有一些方法可以解决这个问题,您可以自行查找(在您最喜欢的搜索引擎中搜索“帧率依赖性”或其他术语)。

    2. 现在,您有 screen.lock() 和 screen.unlock()。你不需要这些。如果表面需要(某些表面不需要)并且您要手动访问像素数据,您只需要锁定/解锁屏幕表面。做一些事情,比如在屏幕上画圆圈,pygame 会自动为你锁定/解锁表面。简而言之,您现在不需要处理锁定/解锁。

    【讨论】:

    • 你的教程风格的答案比我的更有节奏和友好。赞成:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多