Pygame: Difference between revisions
From ICO wiki
Jump to navigationJump to search
No edit summary |
|||
(3 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
Pygame is a library for programming games with Python. It handles event loop and simplifies drawing the scene. | Pygame is a library for programming games with Python. It handles event loop and simplifies drawing the scene. | ||
=Installation= | |||
Ubuntu users can simply apt-get the package: | Ubuntu users can simply apt-get the package: | ||
Line 11: | Line 11: | ||
pip3 install pygame-1.9.2a0-cp35-none-win_amd64.whl | pip3 install pygame-1.9.2a0-cp35-none-win_amd64.whl | ||
=Flappy Bird clones= | |||
==Code example== | ==Code example== | ||
Line 127: | Line 129: | ||
import pygame | import pygame | ||
from pygame.locals import * | from pygame.locals import * | ||
def main_loop(screen): | def main_loop(screen): | ||
Line 133: | Line 135: | ||
bird = pygame.image.load("img/bird.png") | bird = pygame.image.load("img/bird.png") | ||
background = pygame.image.load("img/bg.png") | background = pygame.image.load("img/bg.png") | ||
pygame.display.set_caption('Floppy Bird') | pygame.display.set_caption('Floppy Bird') | ||
pygame.mouse.set_visible(0) | pygame.mouse.set_visible(0) | ||
Line 139: | Line 141: | ||
print "Pipe dimensions:", pipe.get_size() | print "Pipe dimensions:", pipe.get_size() | ||
print "Background dimensions:", background.get_size() | print "Background dimensions:", background.get_size() | ||
print "Bird dimensions:", bird.get_size() | |||
bird_left = background.get_width() / 3 | |||
bird_top = background.get_height() / 2 | |||
bird_velocity = 0 | |||
level = [0,0,0,0,0,0,0,0,1,2,3,1,2,3,1,2,3] | |||
flipped_pipe = pygame.transform.flip(pipe, 0, 1) | |||
frames = 0 # Here we count frames | frames = 0 # Here we count frames | ||
scene = pygame.Surface((240,180)) # This is where we compose the scene | scene = pygame.Surface((240,180)) # This is where we compose the scene | ||
Line 156: | Line 159: | ||
return | return | ||
elif event.type == KEYDOWN and event.key == K_SPACE: | elif event.type == KEYDOWN and event.key == K_SPACE: | ||
bird_velocity -= 0.2 | |||
print "Space was pressed!" | print "Space was pressed!" | ||
bird_velocity += 0.001 # Gravity! | |||
bird_top += bird_velocity # v = v0 + a*t | |||
frames += 1 | |||
pipe_scroll = frames / 2 | |||
background_scroll = frames / 10 | |||
for index in range(0, 3): | |||
for | scene.blit(background, (index * background.get_width() - background_scroll % pipe.get_height(), 0)) | ||
scene.blit(background, ( | |||
# This is basically the inverse of calculation of pipe_left below | |||
current_pipe = int((pipe_scroll + bird_left)/(pipe.get_width() * 3)) | |||
# This is basically the inverse of calculation of | |||
current_pipe = int(( | |||
for | for pipe_index, pipe_height in enumerate(level): | ||
if pipe_height == 0: continue # Skip pipes whose height is 0 | if pipe_height == 0: continue # Skip pipes whose height is 0 | ||
pipe_left = pipe_index * pipe.get_width() * 3 - pipe_scroll | |||
pipe_top = 170 - pipe_height * 15 | |||
scene.blit(pipe, (pipe_left, pipe_top)) | |||
scene.blit(flipped_pipe, (pipe_left, pipe_top - 250)) | |||
# Highlight the next pipe we could bump into | |||
if | if pipe_index == current_pipe: | ||
if bird_top > pipe_top: | |||
#pygame.draw.rect(scene, (255,0,0), (px, py, 32, 160)) | #pygame.draw.rect(scene, (255,0,0), (px, py, 32, 160)) | ||
print "Game over: You bumped into pipe below!" | print "Game over: You bumped into pipe below!" | ||
return | return | ||
if | if bird_top < pipe_top-250: | ||
#pygame.draw.rect(scene, (255,0,0), (px, py-250, 32, 160)) | #pygame.draw.rect(scene, (255,0,0), (px, py-250, 32, 160)) | ||
print "Game over: You bumped into pipe above!" | print "Game over: You bumped into pipe above!" | ||
Line 195: | Line 199: | ||
print "You win! You've passed all the roadblocks!" | print "You win! You've passed all the roadblocks!" | ||
return | return | ||
if bird_top + bird.get_height() > scene.get_height(): | |||
print "Game over: Bird fell down!" | print "Game over: Bird fell down!" | ||
return | return | ||
if | if bird_top < 0: | ||
print "Game over: You're aiming too high!" | print "Game over: You're aiming too high!" | ||
return | return | ||
scene.blit(bird, ( | scene.blit(bird, (bird_left, int(bird_top)), (18 * (int(frames/100) % 3), 0, 18, 13)) | ||
pygame.transform.scale(scene, screen.get_size(), screen) # Here we scale it up and paste to screen | pygame.transform.scale(scene, screen.get_size(), screen) # Here we scale it up and paste to screen | ||
pygame.display.flip() | pygame.display.flip() | ||
def game_over(screen, score): | def game_over(screen, score): | ||
# This does nothing yet! | |||
pass | |||
def __main__(): | def __main__(): | ||
pygame.init() | pygame.init() | ||
Line 224: | Line 222: | ||
score = main_loop(screen) | score = main_loop(screen) | ||
game_over(screen, score) | game_over(screen, score) | ||
if __name__ == "__main__": | if __name__ == "__main__": | ||
__main__() | __main__() | ||
</source> | |||
==A perhaps easier to follow version== | |||
<source lang="python"> | |||
import os, sys | |||
import pygame | |||
from pygame.locals import * | |||
pygame.init() | |||
screen = pygame.display.set_mode((800,600)) | |||
pipe = pygame.image.load("img/pipe.png") | |||
bird = pygame.image.load("img/bird.png") | |||
background = pygame.image.load("img/bg.png") | |||
pygame.display.set_caption('Floppy Bird') | |||
pygame.mouse.set_visible(0) | |||
print "Pipe dimensions:", pipe.get_size() | |||
print "Background dimensions:", background.get_size() | |||
print "Bird dimensions:", bird.get_size() | |||
def game_loop(): | |||
pipe_gap = 70 | |||
bird_left = background.get_width() / 3 | |||
bird_top = background.get_height() / 2 | |||
bird_velocity = 0 | |||
level = [0,0,0,0,0,0,0,0,1,2,3,1,2,3,1,2,3] | |||
flipped_pipe = pygame.transform.flip(pipe, 0, 1) | |||
frames = 0 # Here we count frames | |||
scene = pygame.Surface((240,180)) # This is where we compose the scene | |||
while True: | |||
scene.fill(0) # This fills the buffer with black pixels | |||
for event in pygame.event.get(): | |||
if event.type == QUIT: | |||
return | |||
elif event.type == KEYDOWN and event.key == K_ESCAPE: | |||
return | |||
elif event.type == KEYDOWN and event.key == K_SPACE: | |||
bird_velocity -= 0.2 | |||
bird_velocity += 0.001 # Gravity! | |||
bird_top += bird_velocity # v = v0 + a*t | |||
frames += 1 | |||
pipe_scroll = frames / 2 | |||
background_scroll = frames / 10 | |||
for index in range(0, 3): | |||
scene.blit(background, (index * background.get_width() - background_scroll % pipe.get_height(), 0)) | |||
# This is basically the inverse of calculation of pipe_left below | |||
current_pipe = int((pipe_scroll + bird_left)/(pipe.get_width() * 3)) | |||
for pipe_index, pipe_height in enumerate(level): | |||
if pipe_height == 0: continue # Skip pipes whose height is 0 | |||
pipe_left = pipe_index * pipe.get_width() * 3 - pipe_scroll | |||
pipe_top = 170 - pipe_height * 15 | |||
scene.blit(pipe, (pipe_left, pipe_top)) | |||
scene.blit(flipped_pipe, (pipe_left, pipe_top - pipe.get_height() - pipe_gap)) | |||
# Highlight the next pipe we could bump into | |||
if pipe_index == current_pipe: | |||
if bird_top > pipe_top: | |||
#pygame.draw.rect(scene, (255,0,0), (pipe_left, pipe_top, pipe.get_width(), pipe.get_height())) | |||
print "Game over: You bumped into pipe below!" | |||
return | |||
if bird_top < pipe_top - pipe_gap: | |||
#pygame.draw.rect(scene, (255,0,0), (pipe_left, pipe_top - pipe.get_height() - pipe_gap, pipe.get_width(), pipe.get_height())) | |||
print "Game over: You bumped into pipe above!" | |||
return | |||
if current_pipe > len(level): | |||
print "You win! You've passed all the roadblocks!" | |||
return | |||
if bird_top + bird.get_height() > scene.get_height(): | |||
print "Game over: Bird fell down!" | |||
return | |||
if bird_top < 0: | |||
print "Game over: You're aiming too high!" | |||
return | |||
scene.blit(bird, (bird_left, int(bird_top)), (18 * (int(frames/100) % 3), 0, 18, 13)) | |||
pygame.transform.scale(scene, screen.get_size(), screen) # Here we scale it up and paste to screen | |||
pygame.display.flip() | |||
def game_over(): | |||
font = pygame.font.SysFont("sans", 72) | |||
text = font.render("Game over!", True, (255, 0, 0)) | |||
position = screen.get_width() / 2 - text.get_width() / 2, screen.get_height() / 2 - text.get_height() / 2 | |||
screen.blit(text, position) | |||
while True: | |||
for event in pygame.event.get(): | |||
if event.type == QUIT: | |||
return False | |||
elif event.type == KEYDOWN and event.key == K_ESCAPE: | |||
return False | |||
elif event.type == KEYDOWN and event.key == K_SPACE: | |||
return True | |||
pygame.display.flip() | |||
again = True | |||
while again: | |||
game_loop() | |||
again = game_over() | |||
</source> | </source> |
Latest revision as of 18:10, 24 March 2016
Pygame is a library for programming games with Python. It handles event loop and simplifies drawing the scene.
Installation
Ubuntu users can simply apt-get the package:
apt-get install python-pygame
Windows users should download pygame .whl file corresponding to their Python runtime version. On Python 3.5 use following to install the module:
pip3 install pygame-1.9.2a0-cp35-none-win_amd64.whl
Flappy Bird clones
Code example
An example pygame code:
import os, sys
import pygame
from pygame.locals import *
def __main__():
pygame.init()
pipe = pygame.image.load("img/pipe.png")
bird = pygame.image.load("img/bird.png")
background = pygame.image.load("img/bg.png")
screen = pygame.display.set_mode((640,480))
pygame.display.set_caption('Floppy Bird')
pygame.mouse.set_visible(0)
while True:
for event in pygame.event.get():
if event.type == QUIT:
return
elif event.type == KEYDOWN and event.key == K_ESCAPE:
return
screen.blit(background, (50, 50))
screen.blit(bird, (100, 100))
pygame.display.flip()
if __name__ == "__main__":
__main__()
Download graphics:
wget http://enos.itcollege.ee/~lvosandi/floppy-gfx.zip unzip floppy-gfx.zip
Execrises:
- Implement panning of background
- Draw the pipes on the screen, use pygame.transform.flip to flip the pipe image
Improved example
import os, sys
import pygame
from pygame.locals import *
def __main__():
pygame.init()
pipe = pygame.image.load("img/pipe.png")
bird = pygame.image.load("img/bird.png")
background = pygame.image.load("img/bg.png")
screen = pygame.display.set_mode((800,600))
pygame.display.set_caption('Floppy Bird')
pygame.mouse.set_visible(0)
print "Pipe dimensions:", pipe.get_size()
print "Background dimensions:", background.get_size()
y = 0
vy = 0
level = [0, 1, 0, 0, 2, 0, 0, 3,0, 1, 0, 0, 2, 0, 0, 3,0, 1, 0, 0, 2, 0, 0, 3,]
antipipe = pygame.transform.flip(pipe, 0, 1)
frames = 0 # Here we count frames
scene = pygame.Surface((240,180)) # This is where we compose the scene
while True:
scene.fill(0) # This fills the buffer with black pixels
for event in pygame.event.get():
if event.type == QUIT:
return
elif event.type == KEYDOWN and event.key == K_ESCAPE:
return
elif event.type == KEYDOWN and event.key == K_SPACE:
vy -= 0.02
print "Space was pressed!"
vy += 0.0001
y += vy
for i in range(0, 3):
scene.blit(background, (i*148 - (frames/10) % 148, 0), (0, 0, 200, 300))
frames += 1
for offset, pipe_height in enumerate(level):
if pipe_height == 0: continue # Skip pipes whose height is 0
scene.blit(pipe, (400-frames/2 + offset * 32, 180 - pipe_height * 32), (0, 0, 100,160))
scene.blit(antipipe, (400-frames/2 + offset * 32, 180 - pipe_height * 32 - 250), (0, 0, 100,160))
scene.blit(bird, (100, 100+int(y)), (18 * (int(frames/100) % 3), 0, 18, 13))
pygame.transform.scale(scene, screen.get_size(), screen) # Here we scale it up and paste to screen
pygame.display.flip()
if __name__ == "__main__":
__main__()
Exercises:
- Add collision detection
- Add text overlays and scoring using pygame.font
- Attempt to get fixed FPS
Almost there!
import os, sys
import pygame
from pygame.locals import *
def main_loop(screen):
pipe = pygame.image.load("img/pipe.png")
bird = pygame.image.load("img/bird.png")
background = pygame.image.load("img/bg.png")
pygame.display.set_caption('Floppy Bird')
pygame.mouse.set_visible(0)
print "Pipe dimensions:", pipe.get_size()
print "Background dimensions:", background.get_size()
print "Bird dimensions:", bird.get_size()
bird_left = background.get_width() / 3
bird_top = background.get_height() / 2
bird_velocity = 0
level = [0,0,0,0,0,0,0,0,1,2,3,1,2,3,1,2,3]
flipped_pipe = pygame.transform.flip(pipe, 0, 1)
frames = 0 # Here we count frames
scene = pygame.Surface((240,180)) # This is where we compose the scene
while True:
scene.fill(0) # This fills the buffer with black pixels
for event in pygame.event.get():
if event.type == QUIT:
return
elif event.type == KEYDOWN and event.key == K_ESCAPE:
return
elif event.type == KEYDOWN and event.key == K_SPACE:
bird_velocity -= 0.2
print "Space was pressed!"
bird_velocity += 0.001 # Gravity!
bird_top += bird_velocity # v = v0 + a*t
frames += 1
pipe_scroll = frames / 2
background_scroll = frames / 10
for index in range(0, 3):
scene.blit(background, (index * background.get_width() - background_scroll % pipe.get_height(), 0))
# This is basically the inverse of calculation of pipe_left below
current_pipe = int((pipe_scroll + bird_left)/(pipe.get_width() * 3))
for pipe_index, pipe_height in enumerate(level):
if pipe_height == 0: continue # Skip pipes whose height is 0
pipe_left = pipe_index * pipe.get_width() * 3 - pipe_scroll
pipe_top = 170 - pipe_height * 15
scene.blit(pipe, (pipe_left, pipe_top))
scene.blit(flipped_pipe, (pipe_left, pipe_top - 250))
# Highlight the next pipe we could bump into
if pipe_index == current_pipe:
if bird_top > pipe_top:
#pygame.draw.rect(scene, (255,0,0), (px, py, 32, 160))
print "Game over: You bumped into pipe below!"
return
if bird_top < pipe_top-250:
#pygame.draw.rect(scene, (255,0,0), (px, py-250, 32, 160))
print "Game over: You bumped into pipe above!"
return
if current_pipe > len(level):
print "You win! You've passed all the roadblocks!"
return
if bird_top + bird.get_height() > scene.get_height():
print "Game over: Bird fell down!"
return
if bird_top < 0:
print "Game over: You're aiming too high!"
return
scene.blit(bird, (bird_left, int(bird_top)), (18 * (int(frames/100) % 3), 0, 18, 13))
pygame.transform.scale(scene, screen.get_size(), screen) # Here we scale it up and paste to screen
pygame.display.flip()
def game_over(screen, score):
# This does nothing yet!
pass
def __main__():
pygame.init()
screen = pygame.display.set_mode((800,600))
score = main_loop(screen)
game_over(screen, score)
if __name__ == "__main__":
__main__()
A perhaps easier to follow version
import os, sys
import pygame
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((800,600))
pipe = pygame.image.load("img/pipe.png")
bird = pygame.image.load("img/bird.png")
background = pygame.image.load("img/bg.png")
pygame.display.set_caption('Floppy Bird')
pygame.mouse.set_visible(0)
print "Pipe dimensions:", pipe.get_size()
print "Background dimensions:", background.get_size()
print "Bird dimensions:", bird.get_size()
def game_loop():
pipe_gap = 70
bird_left = background.get_width() / 3
bird_top = background.get_height() / 2
bird_velocity = 0
level = [0,0,0,0,0,0,0,0,1,2,3,1,2,3,1,2,3]
flipped_pipe = pygame.transform.flip(pipe, 0, 1)
frames = 0 # Here we count frames
scene = pygame.Surface((240,180)) # This is where we compose the scene
while True:
scene.fill(0) # This fills the buffer with black pixels
for event in pygame.event.get():
if event.type == QUIT:
return
elif event.type == KEYDOWN and event.key == K_ESCAPE:
return
elif event.type == KEYDOWN and event.key == K_SPACE:
bird_velocity -= 0.2
bird_velocity += 0.001 # Gravity!
bird_top += bird_velocity # v = v0 + a*t
frames += 1
pipe_scroll = frames / 2
background_scroll = frames / 10
for index in range(0, 3):
scene.blit(background, (index * background.get_width() - background_scroll % pipe.get_height(), 0))
# This is basically the inverse of calculation of pipe_left below
current_pipe = int((pipe_scroll + bird_left)/(pipe.get_width() * 3))
for pipe_index, pipe_height in enumerate(level):
if pipe_height == 0: continue # Skip pipes whose height is 0
pipe_left = pipe_index * pipe.get_width() * 3 - pipe_scroll
pipe_top = 170 - pipe_height * 15
scene.blit(pipe, (pipe_left, pipe_top))
scene.blit(flipped_pipe, (pipe_left, pipe_top - pipe.get_height() - pipe_gap))
# Highlight the next pipe we could bump into
if pipe_index == current_pipe:
if bird_top > pipe_top:
#pygame.draw.rect(scene, (255,0,0), (pipe_left, pipe_top, pipe.get_width(), pipe.get_height()))
print "Game over: You bumped into pipe below!"
return
if bird_top < pipe_top - pipe_gap:
#pygame.draw.rect(scene, (255,0,0), (pipe_left, pipe_top - pipe.get_height() - pipe_gap, pipe.get_width(), pipe.get_height()))
print "Game over: You bumped into pipe above!"
return
if current_pipe > len(level):
print "You win! You've passed all the roadblocks!"
return
if bird_top + bird.get_height() > scene.get_height():
print "Game over: Bird fell down!"
return
if bird_top < 0:
print "Game over: You're aiming too high!"
return
scene.blit(bird, (bird_left, int(bird_top)), (18 * (int(frames/100) % 3), 0, 18, 13))
pygame.transform.scale(scene, screen.get_size(), screen) # Here we scale it up and paste to screen
pygame.display.flip()
def game_over():
font = pygame.font.SysFont("sans", 72)
text = font.render("Game over!", True, (255, 0, 0))
position = screen.get_width() / 2 - text.get_width() / 2, screen.get_height() / 2 - text.get_height() / 2
screen.blit(text, position)
while True:
for event in pygame.event.get():
if event.type == QUIT:
return False
elif event.type == KEYDOWN and event.key == K_ESCAPE:
return False
elif event.type == KEYDOWN and event.key == K_SPACE:
return True
pygame.display.flip()
again = True
while again:
game_loop()
again = game_over()