如何让我的圈子在pygame中飞出屏幕?

Mad*_*ung 2 python random animation pygame game-loop

我是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()
Run Code Online (Sandbox Code Playgroud)

同样,我希望圆圈以随机方向飞离屏幕.我做了几次尝试,但还没有成功.还有,感谢帮助我的jdi

Pre*_*eti 6

创建圆时(单击时),生成2个随机数.这些将是您的二维欧几里德 速度矢量的(x,y)分量:

在此输入图像描述

# interval -1.0 to 1.0, adjust as necessary
vx, vy = ( (random.random()*2) -1, (random.random()*2) - 1 )
Run Code Online (Sandbox Code Playgroud)

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

在此输入图像描述

posx, posy = posx + vx, posy + vy
Run Code Online (Sandbox Code Playgroud)

请注意,总体速度可能是变化的.如果您希望每秒的速度始终为1.0,请对矢量进行标准化:

要对矢量进行标准化,请将其除以其大小:

在此输入图像描述

所以在你的情况下:

在此输入图像描述

因此:

在此输入图像描述

所以在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
Run Code Online (Sandbox Code Playgroud)

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


一旦你开始让多个物体四处移动并可能在屏幕外移动,删除无法返回的屏幕外物体非常有用,并且与你的程序无关.否则,如果您在创建更多内容时继续跟踪所有这些屏幕外对象,则基本上会导致内存泄漏,并且在给定足够时间/操作的情况下将耗尽内存.


虽然你现在正在做的事情非常简单,假设你还没有,学习一些基本的矢量数学将很快就能收回成功.最终你可能需要进行一些矩阵数学来进行某些变换.如果你是新手,它并不像它最初看起来那么难.如果你开始尝试做更多雄心勃勃的事情,你可能会在没有学习的情况下侥幸逃脱.


Mar*_*eth 5

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

while True:
    if the mouse was clicked:
        draw a circle on the screen where the mouse was clicked
Run Code Online (Sandbox Code Playgroud)

让我们让事情变得更容易一点,并逐步建立起来。

从圆圈开始,无需用户点击

为了简单起见,让我们将圆圈放在屏幕左上方附近,这样我们就可以始终假设会有一个圆圈(使一些逻辑更容易)

circle_x, circle_y = 10,10
while True:
    draw the circle at circle_x, circle_y

    pygame.display.update()
Run Code Online (Sandbox Code Playgroud)

为圆设置动画

在过多讨论“随机方向”之前,让我们简单一点,朝一个方向前进(比方说,始终向下和向右)。

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
Run Code Online (Sandbox Code Playgroud)

现在,每次循环时,圆心都会移动一点,然后将其绘制到新位置。请注意,您可能需要减少添加到 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
Run Code Online (Sandbox Code Playgroud)

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

现在,您可以开始将其余的内容重新添加到代码中。

跟踪多个圈子

您可以通过使用圆列表而不是两个圆变量来完成此操作

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
Run Code Online (Sandbox Code Playgroud)

需要注意的一件事是,如果您跟踪元组中的圆圈位置,则将无法更改它们的值。如果您熟悉面向对象编程,则可以创建一个 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
Run Code Online (Sandbox Code Playgroud)

让圆圈朝随机方向移动

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

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

其他一些想法

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

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

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