【问题标题】:Understanding infinite while-loops in python了解python中的无限while循环
【发布时间】:2020-04-30 16:57:38
【问题描述】:

您可以在python中使用无限while循环来制作一个无限持久的窗口弹出:

import pygame

#Game-loop

while True:

    # Initialize the pygame
    pygame.init()

    # create the screen
    screen = pygame.display.set_mode((800, 600))

    # Title and icon
    pygame.display.set_caption("RPS Pro")
    icon = pygame.image.load('icon.png')
    pygame.display.set_icon(icon)

现在,这段代码完成了我们希望它做的事情,而且它也很有意义。当我们在一个无限的while循环中输入我们的代码时,它会永远运行。但我尝试了一些不同的东西:

import pygame

# Initialize the pygame
pygame.init()

#create the screen
screen = pygame.display.set_mode((800, 600))

#Title and icon
pygame.display.set_caption("RPS Pro")
icon = pygame.image.load('icon.png')
pygame.display.set_icon(icon)

#Game-loop
while True:
    pass

令人惊讶的是,这也能够创建一个无限持久的窗口。这很奇怪。代码不在 while 循环内;为什么它会做我们希望它做的事情?确实,while 循环仍然是无限的,但我们的代码不在 while 循环内。那为什么会起作用呢?

【问题讨论】:

    标签: python while-loop pygame popup infinite-loop


    【解决方案1】:

    我会试着给你一个粗略的想法:

    您的代码并不是您计算机上运行的唯一代码。还有称为操作系统、显示管理器、设备驱动程序等等的东西。

    所以当你打电话时,例如

    pygame.display.set_mode((800, 600))
    

    不是您的代码神奇地在您的桌面上创建了一个窗口。您在 pygame 模块中调用函数,后者又调用函数 SDL 库,后者又调用操作系统(或非 Windows 系统上的显示管理器)的函数。

    因此,如果您使用的是 Windows,则会调用函数 CreateWindow,从而将 Windows 引导至 create a window。 Windows 还会为您的应用程序线程创建一个Message queue,它允许在您的应用程序、窗口和操作系统(或显示管理器;在 Windows 上为dwm.exe)之间使用Inter-process communication

    这称为Event-driven programming。一部分(由显示管理器创建和运行的窗口)通过事件与另一部分(您的 python 应用程序)通信。这也是您必须在应用程序中调用pygame.event.get() 的原因:处理message loop。在非 Windows 系统上,它的工作原理类似;在 Linux 上,您可能在内部使用 Xlib。


    想想当您移动鼠标时会发生什么:有一个设备驱动程序将来自硬件的信号转换为显示管理器的命令。有一个驱动程序负责在屏幕上绘制鼠标光标。有一个显示管理器管理窗口。

    因此,当您最终单击十字按钮时,显示管理器会将事件放入应用程序的线程消息队列中。到目前为止,您的代码不涉及任何这些事情。该窗口由显示管理器管理和运行。

    只要您的应用程序运行,窗口就会保持打开状态,因为它与您的应用程序线程绑定。

    【讨论】:

      【解决方案2】:

      这个窗口出现是因为你没有退出它并且while循环是无限循环。至此,代码将一直运行,直到您进入 while 循环。另外,尝试使对象移动或一些动画,您会注意到它不会得到更新,因为代码不在循环内。

      那么当我们以正确的方式进行游戏时,游戏是如何运作的呢? => 你的代码在循环内不断更新,整个事情都有效。 (就像这是一个游戏的样本)

      import pygame
      import time
      import numpy as np
      gravity =0
      pygame.init()
      gamewin = pygame.display.set_mode((650,400))
      pygame.display.set_caption("flappy bird ")
      
      bg = pygame.image.load("background-day.png")
      pipes = pygame.image.load("pipe-green.png")
      flipped_pipes = pygame.transform.flip(pipes,1,1)
      play = [pygame.image.load("bird.png"),pygame.image.load("bird2.png"),pygame.image.load("bird3.png"),pygame.image.load("bird.png"),pygame.image.load("bird2.png"),pygame.image.load("bird3.png"),pygame.image.load("bird.png"),pygame.image.load("bird2.png"),pygame.image.load("bird3.png")]
      
      pipe = False
      
      def text_objects(text, font):
          textSurface = font.render(text, True,(0,0,0))
          return textSurface, textSurface.get_rect()
      def message_display(text):
          largeText = pygame.font.Font('freesansbold.ttf',70)
          TextSurf, TextRect = text_objects(text, largeText)
          TextRect.center = ((700/2),(400/2))
          gamewin.blit(TextSurf, TextRect)
          pygame.display.update()
          time.sleep(2)
      
      
      
      def seecollisions(x1,y1,w1,h1,x2,y2,w2,h2):
          if(x2+w2>=x1>=x2 and y2+h2>=y1>=y2):
              return True
          elif(x2+w2>=x1+w1>=x2 and y2+h2>=y1>=y2):
              return True
          elif(x2+w2>=x1>=x2 and y2+h2>=y1+h1>=y2):
              return True
          elif(x2+w2>=x1+w1>=x2 and y2+h2>=y1+h1>=y2):
              return True
          else:
              return False
      
      
      class birdy(pygame.sprite.Sprite):
          def __init__(self,x,y,width,height):
              self.x = x
              self.y = y
              self.width = width
              self.height = height
              self.pipe = False
              self.jumpcount= 0
              self.space = False
              self.hitbox= (self.x,self.y,self.width,self.height)
              self.rect = pygame.Rect(self.hitbox)
      
          def draw(self,win,obj):
              if self.jumpcount+1 > 27:
                  self.jumpcount =0
      
              if self.space:
      
                  win.blit(pygame.transform.rotate(obj[self.jumpcount//3],6%360),(self.x,self.y))
                  #pygame.draw.rect(gamewin,(255,0,0),self.hitbox,2)
      
      
      
              else:
      
                  win.blit(pygame.transform.rotate(obj[self.jumpcount//3],-6%360),(self.x,self.y))
      
                  self.hitbox= (self.x,self.y,self.width,self.height)
      
                  #pygame.draw.rect(gamewin,(255,0,0),self.hitbox,2)
                  self.rect = pygame.Rect(self.hitbox)
      
      
              self.jumpcount +=1
      
      
      
      class piper(pygame.sprite.Sprite):
          def __init__(self,box_x,box_y,bxuppery,width,height):
              self.width = width
              self.height = height
              self.box_x =box_x
              self.box_y = box_y
              self.bxuppery = bxuppery
              self.hitbox= (self.box_x,self.box_y,64,64)
              self.rect = pygame.Rect(self.hitbox)
              self.hitboxup= (self.box_x,self.box_y-self.bxuppery,self.width,self.height-180)
      
      
      
          def draw(self,win,obj,fobj):
              win.blit(obj,(self.box_x,self.box_y))
              self.hitbox= (self.box_x,self.box_y,self.width,self.height)
              self.hitboxup= (self.box_x,self.box_y-self.bxuppery,self.width,self.height-180)
      
      
              #pygame.draw.rect(gamewin,(255,0,0),self.hitbox,2)
              #pygame.draw.rect(gamewin,(255,0,0),self.hitboxup,2)
      
              self.rect = pygame.Rect(self.hitbox)
      
      
              win.blit(fobj,(self.box_x,self.box_y-self.bxuppery))
      
      
      
      bird = birdy(20,200,34,26)
      
      def redrawgame():
      
          gamewin.blit(bg,(0,0))
          bird.draw(gamewin,play)
      
          if pipe:
              pipspawn1.draw(gamewin,pipes,flipped_pipes)
              pipspawn2.draw(gamewin,pipes,flipped_pipes)
              pipspawn3.draw(gamewin,pipes,flipped_pipes)
              pipspawn4.draw(gamewin,pipes,flipped_pipes)
      
      
      
      
          pygame.display.update()
      
      
      box_x = 740
      box_x2 = box_x + 250
      box_x3 = box_x2 + 250
      box_x4 = box_x3 +250
      
      
      rin = True 
      upperboxy = 432
      
      collidedpipe = False
      box_y1 = np.random.randint(low=100,high=380)
      box_y2 = np.random.randint(low=100,high=380)
      box_y3 = np.random.randint(low=100,high=380)
      box_y4 = np.random.randint(low=100,high=380)
      pipspawn1=piper(box_x, box_y1,upperboxy,52,500)
      pipspawn2=piper(box_x2, box_y2,upperboxy,52,500)
      pipspawn3=piper(box_x3, box_y3,upperboxy,52,500)
      pipspawn4=piper(box_x4, box_y4,upperboxy,52,500)
      while rin:
          pygame.time.delay(30)
          for event in pygame.event.get():
              if event.type == pygame.QUIT:
                  pygame.quit()
                  quit()
          keys = pygame.key.get_pressed()
          if keys[pygame.K_UP] :
      
              if collidedpipe == False:
                  bird.y-= 25
                  bird.space = True
                  gravity = 7
      
      
          if bird.x < 220:
              bird.x+=2
          if collidedpipe == False:
              bird.y+=1/2 * gravity 
              pygame.time.delay(50)
              gravity +=1.3
      
      
          if bird.y > 380:
              collidedpipe = True
      
          if bird.x > 120:
              pipe = True
              if collidedpipe == False:
                  pipspawn1.box_x -= 10
                  pipspawn2.box_x -= 10
                  pipspawn3.box_x -= 10
                  pipspawn4.box_x -= 10
      
          if pipspawn1.box_x <- 80:   
              pipspawn1.box_x= 880
              pipspawn1.box_y =  np.random.randint(low=100,high=380)
      
      
          if pipspawn2.box_x <- 80:   
              pipspawn2.box_x= 880
              pipspawn2.box_y =  np.random.randint(low=100,high=380)
      
      
          if pipspawn3.box_x <- 80:   
              pipspawn3.box_x=880
              pipspawn3.box_y =  np.random.randint(low=100,high=380)
      
          if pipspawn4.box_x <- 80:   
              pipspawn4.box_x= 880
              pipspawn4.box_y =  np.random.randint(low=100,high=380)
      
      
          # if score>1:
          #   print("score is",score+1)
          #print(bird.hitbox[0],bird.hitbox[1],bird.hitbox[2],bird.hitbox[3])
          #print(pipspawn1.hitboxup[0],pipspawn1.hitboxup[1],pipspawn1.hitboxup[2],pipspawn1.hitboxup[3])
          collision1 = seecollisions(bird.hitbox[0],bird.hitbox[1],bird.hitbox[2],bird.hitbox[3],pipspawn1.hitboxup[0],pipspawn1.hitboxup[1],pipspawn1.hitboxup[2],pipspawn1.hitboxup[3])
          collision2 = seecollisions(bird.hitbox[0],bird.hitbox[1],bird.hitbox[2],bird.hitbox[3],pipspawn2.hitboxup[0],pipspawn2.hitboxup[1],pipspawn2.hitboxup[2],pipspawn2.hitboxup[3])
          collision3 = seecollisions(bird.hitbox[0],bird.hitbox[1],bird.hitbox[2],bird.hitbox[3],pipspawn3.hitboxup[0],pipspawn3.hitboxup[1],pipspawn3.hitboxup[2],pipspawn3.hitboxup[3])
          collision4 = seecollisions(bird.hitbox[0],bird.hitbox[1],bird.hitbox[2],bird.hitbox[3],pipspawn4.hitboxup[0],pipspawn4.hitboxup[1],pipspawn4.hitboxup[2],pipspawn4.hitboxup[3])
          #print(collision1,collision2,collision3,collision4)
          if(collision2 or collision1 or collision3 or collision4):
              collidedpipe= True
          if(pygame.sprite.collide_rect(bird,pipspawn1)):
              collidedpipe = True
          if(pygame.sprite.collide_rect(bird,pipspawn2)):
              collidedpipe = True
          if(pygame.sprite.collide_rect(bird,pipspawn3)):
              collidedpipe = True
          if(pygame.sprite.collide_rect(bird,pipspawn4)):
              collidedpipe = True
          if collidedpipe:
              message_display("Game over")
              box_y1 = np.random.randint(low=100,high=380)
              box_y2 = np.random.randint(low=100,high=380)
              box_y3 = np.random.randint(low=100,high=380)
              box_y4 = np.random.randint(low=100,high=380)
              pipspawn1=piper(box_x, box_y1,upperboxy,52,500)
              pipspawn2=piper(box_x2, box_y2,upperboxy,52,500)
              pipspawn3=piper(box_x3, box_y3,upperboxy,52,500)
              pipspawn4=piper(box_x4, box_y4,upperboxy,52,500)
      
              bird = birdy(20,200,34,26)
              collidedpipe = False
      
          redrawgame()
          bird.space = False
      
      pygame.quit()
      

      在示例中,您可以看到循环仅包含屏幕需要更新的部分。 这就是需要去那里的东西,你只能用它来调用一个函数(更新屏幕),它仍然可以正常工作

      【讨论】:

      • 尝试制作动画并与它们一起工作,然后您就会知道第一次使用 pygame 或任何类型的游戏本身就可以准确猜出它了吗?
      猜你喜欢
      • 2012-08-28
      • 2017-10-12
      • 2020-11-30
      • 2015-05-22
      • 2018-08-30
      • 2014-03-29
      • 2020-05-27
      • 2012-12-24
      • 2020-08-18
      相关资源
      最近更新 更多