Reputation: 195
You can make an infinitely-lasting window pop-up using an infinite while loop in python:
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)
Now, this code does what we want it to do and it also makes sense. As we enter our code inside an infinite while-loop, it runs forever. But I tried something different:
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
Surprisingly, this is able to create an infinitely lasting window as well. This is weird. The code isn't inside the while loop; why does then it do what we want it to do? It's true that the while-loop is still infinite, but our code isn't inside the while-loop. Why does it work then?
Upvotes: 0
Views: 638
Reputation: 101052
I'll try to give you a rough idea:
You code isn't the only code running on your computer. There are also things called operating systems, display managers, device drivers and many more.
So when you call e.g.
pygame.display.set_mode((800, 600))
it's not your code that magically creates a window on your desktop. You code calls functions in the pygame module which in turn calls functions the SDL library which in turn calls functions of the operation system (or display manager on non-Windows systems).
So if you're on Windows, the function 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 between your application, the window, and the operating system (or the display manager; on Windows it's dwm.exe
).
This is called Event-driven programming
. One part (the window created and run by the display manager) communicates with another part (your python application) via events. And that's also the reason you have to call pygame.event.get()
in your application: to process the message loop. On non-Windows system it works similiar; on Linux you probaly use Xlib internally.
Think about what happens when you move your mouse: there's a device driver translating signals from your hardware to commands for your display manager. There's a driver responsible for drawing the mouse cursor on the screen. There's a display manager managing the windows.
So when you finally click cross-button, the display manager puts an event into your application's thread message queue. So far, your code is not involved in any of these things. The window is managed and run by the display manager.
As long as your application runs, the window will stay open, because it's tied to your application's thread.
Upvotes: 1
Reputation: 48
The window appears because you have not quit it and the while loop is infinite loop. As of that, the code runs until you are inside the while loop. also, try making a object move or some animations the you will notice that it will not get updated because the code is not inside the loop.
how the game works when we do it the correct way then? => your code is constantly getting updated inside the loop and the whole thing works. (like this is sample of a game)
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()
In the example you can see that the loop contains only the parts where the screen needs to be updated. and that is what needs to go there you can only use it to call a function (which updates the screen) and it still will work fine
Upvotes: 0