了解 python 中的无限循环
Understanding infinite while-loops in python
您可以在 python 中使用无限 while 循环制作一个无限持久的 window 弹出窗口:
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
令人惊讶的是,这也能创造出无限持久的window。这很奇怪。代码不在 while 循环内;为什么它会做我们想让它做的事情呢?的确,while 循环仍然是无限的,但我们的代码不在 while 循环内。为什么它会起作用?
出现window是因为你还没有退出,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.display.set_mode((800, 600))
不是您的代码在您的桌面上神奇地创建了一个 window。您在 pygame 模块中编写调用函数,该模块又调用 SDL 库的函数,而 SDL 库又调用操作系统(或非 Windows 系统上的显示管理器)的函数。
因此,如果您在 Windows 上,您的应用程序、window 和操作系统(或显示管理器;在 [=37= 上)之间的函数 CreateWindow
gets called that induces Windows to create a window. Windows also creates a Message queue for your applications's thread which allows Inter-process communication ] 是 dwm.exe
).
这叫做Event-driven programming
。一部分(显示管理器创建的 window 和 运行)通过事件与另一部分(您的 python 应用程序)通信。这也是您必须在应用程序中调用 pygame.event.get()
的原因:处理 message loop。在非 Windows 系统上,它的工作原理类似; Linux 你可能在内部使用 Xlib。
想一想当您移动鼠标时会发生什么:有一个设备驱动程序将硬件信号转换为显示管理器的命令。有一个驱动程序负责在屏幕上绘制鼠标光标。有一个显示管理器管理 windows。
因此,当您最终单击交叉按钮时,显示管理器会将一个事件放入应用程序的线程消息队列中。到目前为止,您的代码不涉及任何这些事情。 window 由显示管理器管理,运行 由显示管理器管理。
只要您的应用程序 运行s,window 就会保持打开状态,因为它与您的应用程序的线程相关联。
您可以在 python 中使用无限 while 循环制作一个无限持久的 window 弹出窗口:
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
令人惊讶的是,这也能创造出无限持久的window。这很奇怪。代码不在 while 循环内;为什么它会做我们想让它做的事情呢?的确,while 循环仍然是无限的,但我们的代码不在 while 循环内。为什么它会起作用?
出现window是因为你还没有退出,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.display.set_mode((800, 600))
不是您的代码在您的桌面上神奇地创建了一个 window。您在 pygame 模块中编写调用函数,该模块又调用 SDL 库的函数,而 SDL 库又调用操作系统(或非 Windows 系统上的显示管理器)的函数。
因此,如果您在 Windows 上,您的应用程序、window 和操作系统(或显示管理器;在 [=37= 上)之间的函数 CreateWindow
gets called that induces Windows to create a window. Windows also creates a Message queue for your applications's thread which allows Inter-process communication ] 是 dwm.exe
).
这叫做Event-driven programming
。一部分(显示管理器创建的 window 和 运行)通过事件与另一部分(您的 python 应用程序)通信。这也是您必须在应用程序中调用 pygame.event.get()
的原因:处理 message loop。在非 Windows 系统上,它的工作原理类似; Linux 你可能在内部使用 Xlib。
想一想当您移动鼠标时会发生什么:有一个设备驱动程序将硬件信号转换为显示管理器的命令。有一个驱动程序负责在屏幕上绘制鼠标光标。有一个显示管理器管理 windows。
因此,当您最终单击交叉按钮时,显示管理器会将一个事件放入应用程序的线程消息队列中。到目前为止,您的代码不涉及任何这些事情。 window 由显示管理器管理,运行 由显示管理器管理。
只要您的应用程序 运行s,window 就会保持打开状态,因为它与您的应用程序的线程相关联。