This commit is contained in:
Nielson Tschá
2021-03-16 13:35:01 +01:00
commit a0f3d0edd7
898 changed files with 196589 additions and 0 deletions
@@ -0,0 +1,41 @@
#!/usr/bin/env python
"""Proof of concept gfxdraw example"""
import pygame
import pygame.gfxdraw
def main():
pygame.init()
screen = pygame.display.set_mode((500, 500))
screen.fill((255, 0, 0))
s = pygame.Surface(screen.get_size(), pygame.SRCALPHA, 32)
pygame.draw.line(s, (0, 0, 0), (250, 250), (250 + 200, 250))
width = 1
for a_radius in range(width):
radius = 200
pygame.gfxdraw.aacircle(s, 250, 250, radius - a_radius, (0, 0, 0))
screen.blit(s, (0, 0))
pygame.draw.circle(screen, pygame.Color("GREEN"), (50, 100), 10)
pygame.draw.circle(screen, pygame.Color("BLACK"), (50, 100), 10, 1)
pygame.display.flip()
try:
while 1:
event = pygame.event.wait()
if event.type == pygame.QUIT:
break
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE or event.unicode == "q":
break
pygame.display.flip()
finally:
pygame.quit()
if __name__ == "__main__":
main()
@@ -0,0 +1,410 @@
#!/usr/bin/env python
""" pygame.examples.aliens
Shows a mini game where you have to defend against aliens.
What does it show you about pygame?
* pg.sprite, the difference between Sprite and Group.
* dirty rectangle optimization for processing for speed.
* music with pg.mixer.music, including fadeout
* sound effects with pg.Sound
* event processing, keyboard handling, QUIT handling.
* a main loop frame limited with a game clock from pg.time.Clock
* fullscreen switching.
Controls
--------
* Left and right arrows to move.
* Space bar to shoot
* f key to toggle between fullscreen.
"""
import random
import os
# import basic pygame modules
import pygame as pg
# see if we can load more than standard BMP
if not pg.image.get_extended():
raise SystemExit("Sorry, extended image module required")
# game constants
MAX_SHOTS = 2 # most player bullets onscreen
ALIEN_ODDS = 22 # chances a new alien appears
BOMB_ODDS = 60 # chances a new bomb will drop
ALIEN_RELOAD = 12 # frames between new aliens
SCREENRECT = pg.Rect(0, 0, 640, 480)
SCORE = 0
main_dir = os.path.split(os.path.abspath(__file__))[0]
def load_image(file):
""" loads an image, prepares it for play
"""
file = os.path.join(main_dir, "data", file)
try:
surface = pg.image.load(file)
except pg.error:
raise SystemExit('Could not load image "%s" %s' % (file, pg.get_error()))
return surface.convert()
def load_sound(file):
""" because pygame can be be compiled without mixer.
"""
if not pg.mixer:
return None
file = os.path.join(main_dir, "data", file)
try:
sound = pg.mixer.Sound(file)
return sound
except pg.error:
print("Warning, unable to load, %s" % file)
return None
# Each type of game object gets an init and an update function.
# The update function is called once per frame, and it is when each object should
# change it's current position and state.
#
# The Player object actually gets a "move" function instead of update,
# since it is passed extra information about the keyboard.
class Player(pg.sprite.Sprite):
""" Representing the player as a moon buggy type car.
"""
speed = 10
bounce = 24
gun_offset = -11
images = []
def __init__(self):
pg.sprite.Sprite.__init__(self, self.containers)
self.image = self.images[0]
self.rect = self.image.get_rect(midbottom=SCREENRECT.midbottom)
self.reloading = 0
self.origtop = self.rect.top
self.facing = -1
def move(self, direction):
if direction:
self.facing = direction
self.rect.move_ip(direction * self.speed, 0)
self.rect = self.rect.clamp(SCREENRECT)
if direction < 0:
self.image = self.images[0]
elif direction > 0:
self.image = self.images[1]
self.rect.top = self.origtop - (self.rect.left // self.bounce % 2)
def gunpos(self):
pos = self.facing * self.gun_offset + self.rect.centerx
return pos, self.rect.top
class Alien(pg.sprite.Sprite):
""" An alien space ship. That slowly moves down the screen.
"""
speed = 13
animcycle = 12
images = []
def __init__(self):
pg.sprite.Sprite.__init__(self, self.containers)
self.image = self.images[0]
self.rect = self.image.get_rect()
self.facing = random.choice((-1, 1)) * Alien.speed
self.frame = 0
if self.facing < 0:
self.rect.right = SCREENRECT.right
def update(self):
self.rect.move_ip(self.facing, 0)
if not SCREENRECT.contains(self.rect):
self.facing = -self.facing
self.rect.top = self.rect.bottom + 1
self.rect = self.rect.clamp(SCREENRECT)
self.frame = self.frame + 1
self.image = self.images[self.frame // self.animcycle % 3]
class Explosion(pg.sprite.Sprite):
""" An explosion. Hopefully the Alien and not the player!
"""
defaultlife = 12
animcycle = 3
images = []
def __init__(self, actor):
pg.sprite.Sprite.__init__(self, self.containers)
self.image = self.images[0]
self.rect = self.image.get_rect(center=actor.rect.center)
self.life = self.defaultlife
def update(self):
""" called every time around the game loop.
Show the explosion surface for 'defaultlife'.
Every game tick(update), we decrease the 'life'.
Also we animate the explosion.
"""
self.life = self.life - 1
self.image = self.images[self.life // self.animcycle % 2]
if self.life <= 0:
self.kill()
class Shot(pg.sprite.Sprite):
""" a bullet the Player sprite fires.
"""
speed = -11
images = []
def __init__(self, pos):
pg.sprite.Sprite.__init__(self, self.containers)
self.image = self.images[0]
self.rect = self.image.get_rect(midbottom=pos)
def update(self):
""" called every time around the game loop.
Every tick we move the shot upwards.
"""
self.rect.move_ip(0, self.speed)
if self.rect.top <= 0:
self.kill()
class Bomb(pg.sprite.Sprite):
""" A bomb the aliens drop.
"""
speed = 9
images = []
def __init__(self, alien):
pg.sprite.Sprite.__init__(self, self.containers)
self.image = self.images[0]
self.rect = self.image.get_rect(midbottom=alien.rect.move(0, 5).midbottom)
def update(self):
""" called every time around the game loop.
Every frame we move the sprite 'rect' down.
When it reaches the bottom we:
- make an explosion.
- remove the Bomb.
"""
self.rect.move_ip(0, self.speed)
if self.rect.bottom >= 470:
Explosion(self)
self.kill()
class Score(pg.sprite.Sprite):
""" to keep track of the score.
"""
def __init__(self):
pg.sprite.Sprite.__init__(self)
self.font = pg.font.Font(None, 20)
self.font.set_italic(1)
self.color = pg.Color("white")
self.lastscore = -1
self.update()
self.rect = self.image.get_rect().move(10, 450)
def update(self):
""" We only update the score in update() when it has changed.
"""
if SCORE != self.lastscore:
self.lastscore = SCORE
msg = "Score: %d" % SCORE
self.image = self.font.render(msg, 0, self.color)
def main(winstyle=0):
# Initialize pygame
if pg.get_sdl_version()[0] == 2:
pg.mixer.pre_init(44100, 32, 2, 1024)
pg.init()
if pg.mixer and not pg.mixer.get_init():
print("Warning, no sound")
pg.mixer = None
fullscreen = False
# Set the display mode
winstyle = 0 # |FULLSCREEN
bestdepth = pg.display.mode_ok(SCREENRECT.size, winstyle, 32)
screen = pg.display.set_mode(SCREENRECT.size, winstyle, bestdepth)
# Load images, assign to sprite classes
# (do this before the classes are used, after screen setup)
img = load_image("player1.gif")
Player.images = [img, pg.transform.flip(img, 1, 0)]
img = load_image("explosion1.gif")
Explosion.images = [img, pg.transform.flip(img, 1, 1)]
Alien.images = [load_image(im) for im in ("alien1.gif", "alien2.gif", "alien3.gif")]
Bomb.images = [load_image("bomb.gif")]
Shot.images = [load_image("shot.gif")]
# decorate the game window
icon = pg.transform.scale(Alien.images[0], (32, 32))
pg.display.set_icon(icon)
pg.display.set_caption("Pygame Aliens")
pg.mouse.set_visible(0)
# create the background, tile the bgd image
bgdtile = load_image("background.gif")
background = pg.Surface(SCREENRECT.size)
for x in range(0, SCREENRECT.width, bgdtile.get_width()):
background.blit(bgdtile, (x, 0))
screen.blit(background, (0, 0))
pg.display.flip()
# load the sound effects
boom_sound = load_sound("boom.wav")
shoot_sound = load_sound("car_door.wav")
if pg.mixer:
music = os.path.join(main_dir, "data", "house_lo.wav")
pg.mixer.music.load(music)
pg.mixer.music.play(-1)
# Initialize Game Groups
aliens = pg.sprite.Group()
shots = pg.sprite.Group()
bombs = pg.sprite.Group()
all = pg.sprite.RenderUpdates()
lastalien = pg.sprite.GroupSingle()
# assign default groups to each sprite class
Player.containers = all
Alien.containers = aliens, all, lastalien
Shot.containers = shots, all
Bomb.containers = bombs, all
Explosion.containers = all
Score.containers = all
# Create Some Starting Values
global score
alienreload = ALIEN_RELOAD
clock = pg.time.Clock()
# initialize our starting sprites
global SCORE
player = Player()
Alien() # note, this 'lives' because it goes into a sprite group
if pg.font:
all.add(Score())
# Run our main loop whilst the player is alive.
while player.alive():
# get input
for event in pg.event.get():
if event.type == pg.QUIT:
return
if event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE:
return
elif event.type == pg.KEYDOWN:
if event.key == pg.K_f:
if not fullscreen:
print("Changing to FULLSCREEN")
screen_backup = screen.copy()
screen = pg.display.set_mode(
SCREENRECT.size, winstyle | pg.FULLSCREEN, bestdepth
)
screen.blit(screen_backup, (0, 0))
else:
print("Changing to windowed mode")
screen_backup = screen.copy()
screen = pg.display.set_mode(
SCREENRECT.size, winstyle, bestdepth
)
screen.blit(screen_backup, (0, 0))
pg.display.flip()
fullscreen = not fullscreen
keystate = pg.key.get_pressed()
# clear/erase the last drawn sprites
all.clear(screen, background)
# update all the sprites
all.update()
# handle player input
direction = keystate[pg.K_RIGHT] - keystate[pg.K_LEFT]
player.move(direction)
firing = keystate[pg.K_SPACE]
if not player.reloading and firing and len(shots) < MAX_SHOTS:
Shot(player.gunpos())
if pg.mixer:
shoot_sound.play()
player.reloading = firing
# Create new alien
if alienreload:
alienreload = alienreload - 1
elif not int(random.random() * ALIEN_ODDS):
Alien()
alienreload = ALIEN_RELOAD
# Drop bombs
if lastalien and not int(random.random() * BOMB_ODDS):
Bomb(lastalien.sprite)
# Detect collisions between aliens and players.
for alien in pg.sprite.spritecollide(player, aliens, 1):
if pg.mixer:
boom_sound.play()
Explosion(alien)
Explosion(player)
SCORE = SCORE + 1
player.kill()
# See if shots hit the aliens.
for alien in pg.sprite.groupcollide(shots, aliens, 1, 1).keys():
if pg.mixer:
boom_sound.play()
Explosion(alien)
SCORE = SCORE + 1
# See if alien boms hit the player.
for bomb in pg.sprite.spritecollide(player, bombs, 1):
if pg.mixer:
boom_sound.play()
Explosion(player)
Explosion(bomb)
player.kill()
# draw the scene
dirty = all.draw(screen)
pg.display.update(dirty)
# cap the framerate at 40fps. Also called 40HZ or 40 times per second.
clock.tick(40)
if pg.mixer:
pg.mixer.music.fadeout(1000)
pg.time.wait(1000)
pg.quit()
# call the "main" function if running this script
if __name__ == "__main__":
main()
@@ -0,0 +1,129 @@
#!/usr/bin/env python
""" pygame.examples.arraydemo
Welcome to the arraydemo!
Use the numpy array package to manipulate pixels.
This demo will show you a few things:
* scale up, scale down, flip,
* cross fade
* soften
* put stripes on it!
"""
import os
import pygame as pg
from pygame import surfarray
main_dir = os.path.split(os.path.abspath(__file__))[0]
def surfdemo_show(array_img, name):
"displays a surface, waits for user to continue"
screen = pg.display.set_mode(array_img.shape[:2], 0, 32)
surfarray.blit_array(screen, array_img)
pg.display.flip()
pg.display.set_caption(name)
while 1:
e = pg.event.wait()
if e.type == pg.MOUSEBUTTONDOWN:
break
elif e.type == pg.KEYDOWN and e.key == pg.K_s:
# pg.image.save(screen, name+'.bmp')
# s = pg.Surface(screen.get_size(), 0, 32)
# s = s.convert_alpha()
# s.fill((0,0,0,255))
# s.blit(screen, (0,0))
# s.fill((222,0,0,50), (0,0,40,40))
# pg.image.save_extended(s, name+'.png')
# pg.image.save(s, name+'.png')
# pg.image.save(screen, name+'_screen.png')
# pg.image.save(s, name+'.tga')
pg.image.save(screen, name + ".png")
elif e.type == pg.QUIT:
raise SystemExit()
def main():
"""show various surfarray effects
"""
import numpy as N
from numpy import int32, uint8, uint
pg.init()
print("Using %s" % surfarray.get_arraytype().capitalize())
print("Press the mouse button to advance image.")
print('Press the "s" key to save the current image.')
# allblack
allblack = N.zeros((128, 128), int32)
surfdemo_show(allblack, "allblack")
# striped
# the element type is required for N.zeros in numpy else
# an array of float is returned.
striped = N.zeros((128, 128, 3), int32)
striped[:] = (255, 0, 0)
striped[:, ::3] = (0, 255, 255)
surfdemo_show(striped, "striped")
# rgbarray
imagename = os.path.join(main_dir, "data", "arraydemo.bmp")
imgsurface = pg.image.load(imagename)
rgbarray = surfarray.array3d(imgsurface)
surfdemo_show(rgbarray, "rgbarray")
# flipped
flipped = rgbarray[:, ::-1]
surfdemo_show(flipped, "flipped")
# scaledown
scaledown = rgbarray[::2, ::2]
surfdemo_show(scaledown, "scaledown")
# scaleup
# the element type is required for N.zeros in numpy else
# an #array of floats is returned.
shape = rgbarray.shape
scaleup = N.zeros((shape[0] * 2, shape[1] * 2, shape[2]), int32)
scaleup[::2, ::2, :] = rgbarray
scaleup[1::2, ::2, :] = rgbarray
scaleup[:, 1::2] = scaleup[:, ::2]
surfdemo_show(scaleup, "scaleup")
# redimg
redimg = N.array(rgbarray)
redimg[:, :, 1:] = 0
surfdemo_show(redimg, "redimg")
# soften
# having factor as an array forces integer upgrade during multiplication
# of rgbarray, even for numpy.
factor = N.array((8,), int32)
soften = N.array(rgbarray, int32)
soften[1:, :] += rgbarray[:-1, :] * factor
soften[:-1, :] += rgbarray[1:, :] * factor
soften[:, 1:] += rgbarray[:, :-1] * factor
soften[:, :-1] += rgbarray[:, 1:] * factor
soften //= 33
surfdemo_show(soften, "soften")
# crossfade (50%)
src = N.array(rgbarray)
dest = N.zeros(rgbarray.shape) # dest is float64 by default.
dest[:] = 20, 50, 100
diff = (dest - src) * 0.50
xfade = src + diff.astype(uint)
surfdemo_show(xfade, "xfade")
# alldone
pg.quit()
if __name__ == "__main__":
main()
@@ -0,0 +1,80 @@
#!/usr/bin/env python
""" pygame.examples.audiocapture
A pygame 2 experiment.
* record sound from a microphone
* play back the recorded sound
"""
import pygame as pg
import time
if pg.get_sdl_version()[0] < 2:
raise SystemExit("This example requires pygame 2 and SDL2.")
from pygame._sdl2 import (
get_audio_device_name,
get_num_audio_devices,
AudioDevice,
AUDIO_F32,
AUDIO_ALLOW_FORMAT_CHANGE,
)
from pygame._sdl2.mixer import set_post_mix
pg.mixer.pre_init(44100, 32, 2, 512)
pg.init()
# init_subsystem(INIT_AUDIO)
names = [get_audio_device_name(x, 1) for x in range(get_num_audio_devices(1))]
print(names)
iscapture = 1
sounds = []
sound_chunks = []
def callback(audiodevice, audiomemoryview):
""" This is called in the sound thread.
Note, that the frequency and such you request may not be what you get.
"""
# print(type(audiomemoryview), len(audiomemoryview))
# print(audiodevice)
sound_chunks.append(bytes(audiomemoryview))
def postmix_callback(postmix, audiomemoryview):
""" This is called in the sound thread.
At the end of mixing we get this data.
"""
print(type(audiomemoryview), len(audiomemoryview))
print(postmix)
set_post_mix(postmix_callback)
audio = AudioDevice(
devicename=names[0],
iscapture=1,
frequency=44100,
audioformat=AUDIO_F32,
numchannels=2,
chunksize=512,
allowed_changes=AUDIO_ALLOW_FORMAT_CHANGE,
callback=callback,
)
# start recording.
audio.pause(0)
print("recording with :%s:" % names[0])
time.sleep(5)
print("Turning data into a pg.mixer.Sound")
sound = pg.mixer.Sound(buffer=b"".join(sound_chunks))
print("playing back recorded sound")
sound.play()
time.sleep(5)
@@ -0,0 +1,115 @@
#!/usr/bin/env python
""" pygame.examples.blend_fill
BLEND_ing colors in different ways with Surface.fill().
Keyboard Controls:
* Press R, G, B to increase the color channel values,
* 1-9 to set the step range for the increment,
* A - ADD, S- SUB, M- MULT, - MIN, + MAX to change the blend modes
"""
import os
import pygame as pg
from pygame import K_1, K_2, K_3, K_4, K_5, K_6, K_7, K_8, K_9
def usage():
print("Press R, G, B to increase the color channel values,")
print("1-9 to set the step range for the increment,")
print("A - ADD, S- SUB, M- MULT, - MIN, + MAX")
print(" to change the blend modes")
main_dir = os.path.split(os.path.abspath(__file__))[0]
data_dir = os.path.join(main_dir, "data")
def main():
color = [0, 0, 0]
changed = False
blendtype = 0
step = 5
pg.init()
screen = pg.display.set_mode((640, 480), 0, 32)
screen.fill((100, 100, 100))
image = pg.image.load(os.path.join(data_dir, "liquid.bmp")).convert()
blendimage = pg.image.load(os.path.join(data_dir, "liquid.bmp")).convert()
screen.blit(image, (10, 10))
screen.blit(blendimage, (200, 10))
pg.display.flip()
pg.key.set_repeat(500, 30)
usage()
going = True
while going:
for event in pg.event.get():
if event.type == pg.QUIT:
going = False
if event.type == pg.KEYDOWN:
usage()
if event.key == pg.K_ESCAPE:
going = False
if event.key == pg.K_r:
color[0] += step
if color[0] > 255:
color[0] = 0
changed = True
elif event.key == pg.K_g:
color[1] += step
if color[1] > 255:
color[1] = 0
changed = True
elif event.key == pg.K_b:
color[2] += step
if color[2] > 255:
color[2] = 0
changed = True
elif event.key == pg.K_a:
blendtype = pg.BLEND_ADD
changed = True
elif event.key == pg.K_s:
blendtype = pg.BLEND_SUB
changed = True
elif event.key == pg.K_m:
blendtype = pg.BLEND_MULT
changed = True
elif event.key == pg.K_PLUS:
blendtype = pg.BLEND_MAX
changed = True
elif event.key == pg.K_MINUS:
blendtype = pg.BLEND_MIN
changed = True
elif event.key in (K_1, K_2, K_3, K_4, K_5, K_6, K_7, K_8, K_9):
step = int(event.unicode)
if changed:
screen.fill((100, 100, 100))
screen.blit(image, (10, 10))
blendimage.blit(image, (0, 0))
# blendimage.fill (color, (0, 0, 20, 20), blendtype)
blendimage.fill(color, None, blendtype)
screen.blit(blendimage, (200, 10))
print(
"Color: %s, Pixel (0,0): %s"
% (tuple(color), [blendimage.get_at((0, 0))])
)
changed = False
pg.display.flip()
pg.quit()
if __name__ == "__main__":
main()
@@ -0,0 +1,198 @@
#!/usr/bin/env python
""" pygame.examples.blit_blends
Blending colors in different ways with different blend modes.
It also shows some tricks with the surfarray.
Including how to do additive blending.
Keyboard Controls
-----------------
* R, G, B - add a bit of Red, Green, or Blue.
* A - Add blend mode
* S - Subtractive blend mode
* M - Multiply blend mode
* = key BLEND_MAX blend mode.
* - key BLEND_MIN blend mode.
* 1, 2, 3, 4 - use different images.
"""
import os
import pygame as pg
import time
main_dir = os.path.split(os.path.abspath(__file__))[0]
data_dir = os.path.join(main_dir, "data")
try:
import pygame.surfarray
import numpy
except ImportError:
print("no surfarray for you! install numpy")
def main():
pg.init()
pg.mixer.quit() # remove ALSA underflow messages for Debian squeeze
screen = pg.display.set_mode((640, 480))
im1 = pg.Surface(screen.get_size())
# im1= im1.convert()
im1.fill((100, 0, 0))
im2 = pg.Surface(screen.get_size())
im2.fill((0, 50, 0))
# we make a srcalpha copy of it.
# im3= im2.convert(SRCALPHA)
im3 = im2
im3.set_alpha(127)
images = {}
images[pg.K_1] = im2
images[pg.K_2] = pg.image.load(os.path.join(data_dir, "chimp.bmp"))
images[pg.K_3] = pg.image.load(os.path.join(data_dir, "alien3.gif"))
images[pg.K_4] = pg.image.load(os.path.join(data_dir, "liquid.bmp"))
img_to_blit = im2.convert()
iaa = img_to_blit.convert_alpha()
blits = {}
blits[pg.K_a] = pg.BLEND_ADD
blits[pg.K_s] = pg.BLEND_SUB
blits[pg.K_m] = pg.BLEND_MULT
blits[pg.K_EQUALS] = pg.BLEND_MAX
blits[pg.K_MINUS] = pg.BLEND_MIN
blitsn = {}
blitsn[pg.K_a] = "BLEND_ADD"
blitsn[pg.K_s] = "BLEND_SUB"
blitsn[pg.K_m] = "BLEND_MULT"
blitsn[pg.K_EQUALS] = "BLEND_MAX"
blitsn[pg.K_MINUS] = "BLEND_MIN"
screen.blit(im1, (0, 0))
pg.display.flip()
clock = pg.time.Clock()
print("one pixel is:%s:" % [im1.get_at((0, 0))])
going = True
while going:
clock.tick(60)
for event in pg.event.get():
if event.type == pg.QUIT:
going = False
if event.type == pg.KEYDOWN:
usage()
if event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE:
going = False
elif event.type == pg.KEYDOWN and event.key in images.keys():
img_to_blit = images[event.key]
iaa = img_to_blit.convert_alpha()
elif event.type == pg.KEYDOWN and event.key in blits.keys():
t1 = time.time()
# blits is a dict keyed with key -> blit flag. eg BLEND_ADD.
im1.blit(img_to_blit, (0, 0), None, blits[event.key])
t2 = time.time()
print("one pixel is:%s:" % [im1.get_at((0, 0))])
print("time to do:%s:" % (t2 - t1))
elif event.type == pg.KEYDOWN and event.key in [pg.K_t]:
for bkey in blits.keys():
t1 = time.time()
for x in range(300):
im1.blit(img_to_blit, (0, 0), None, blits[bkey])
t2 = time.time()
# show which key we're doing...
onedoing = blitsn[bkey]
print("time to do :%s: is :%s:" % (onedoing, t2 - t1))
elif event.type == pg.KEYDOWN and event.key in [pg.K_o]:
t1 = time.time()
# blits is a dict keyed with key -> blit flag. eg BLEND_ADD.
im1.blit(iaa, (0, 0))
t2 = time.time()
print("one pixel is:%s:" % [im1.get_at((0, 0))])
print("time to do:%s:" % (t2 - t1))
elif event.type == pg.KEYDOWN and event.key == pg.K_SPACE:
# this additive blend without clamp two surfaces.
# im1.set_alpha(127)
# im1.blit(im1, (0,0))
# im1.set_alpha(255)
t1 = time.time()
im1p = pygame.surfarray.pixels2d(im1)
im2p = pygame.surfarray.pixels2d(im2)
im1p += im2p
del im1p
del im2p
t2 = time.time()
print("one pixel is:%s:" % [im1.get_at((0, 0))])
print("time to do:%s:" % (t2 - t1))
elif event.type == pg.KEYDOWN and event.key in [pg.K_z]:
t1 = time.time()
im1p = pygame.surfarray.pixels3d(im1)
im2p = pygame.surfarray.pixels3d(im2)
im1p16 = im1p.astype(numpy.uint16)
im2p16 = im1p.astype(numpy.uint16)
im1p16 += im2p16
im1p16 = numpy.minimum(im1p16, 255)
pygame.surfarray.blit_array(im1, im1p16)
del im1p
del im2p
t2 = time.time()
print("one pixel is:%s:" % [im1.get_at((0, 0))])
print("time to do:%s:" % (t2 - t1))
elif event.type == pg.KEYDOWN and event.key in [pg.K_r, pg.K_g, pg.K_b]:
# this adds one to each pixel.
colmap = {}
colmap[pg.K_r] = 0x10000
colmap[pg.K_g] = 0x00100
colmap[pg.K_b] = 0x00001
im1p = pygame.surfarray.pixels2d(im1)
im1p += colmap[event.key]
del im1p
print("one pixel is:%s:" % [im1.get_at((0, 0))])
elif event.type == pg.KEYDOWN and event.key == pg.K_p:
print("one pixel is:%s:" % [im1.get_at((0, 0))])
elif event.type == pg.KEYDOWN and event.key == pg.K_f:
# this additive blend without clamp two surfaces.
t1 = time.time()
im1.set_alpha(127)
im1.blit(im2, (0, 0))
im1.set_alpha(255)
t2 = time.time()
print("one pixel is:%s:" % [im1.get_at((0, 0))])
print("time to do:%s:" % (t2 - t1))
screen.blit(im1, (0, 0))
pg.display.flip()
pg.quit()
def usage():
print("press keys 1-5 to change image to blit.")
print("A - ADD, S- SUB, M- MULT, - MIN, + MAX")
print("T - timing test for special blend modes.")
if __name__ == "__main__":
usage()
main()
@@ -0,0 +1,105 @@
#!/usr/bin/env python
""" pygame.examples.camera
Basic image capturing and display using pygame.camera
Keyboard controls
-----------------
- 0, start camera 0.
- 1, start camera 1.
- 9, start camera 9.
- 10, start camera... wait a minute! There's not 10 key!
"""
import pygame as pg
import pygame.camera
class VideoCapturePlayer(object):
size = (640, 480)
def __init__(self, **argd):
self.__dict__.update(**argd)
super(VideoCapturePlayer, self).__init__(**argd)
# create a display surface. standard pygame stuff
self.display = pg.display.set_mode(self.size, 0)
self.init_cams(0)
def init_cams(self, which_cam_idx):
# gets a list of available cameras.
self.clist = pygame.camera.list_cameras()
print(self.clist)
if not self.clist:
raise ValueError("Sorry, no cameras detected.")
try:
cam_id = self.clist[which_cam_idx]
except IndexError:
cam_id = self.clist[0]
# creates the camera of the specified size and in RGB colorspace
self.camera = pygame.camera.Camera(cam_id, self.size, "RGB")
# starts the camera
self.camera.start()
self.clock = pg.time.Clock()
# create a surface to capture to. for performance purposes, you want the
# bit depth to be the same as that of the display surface.
self.snapshot = pg.surface.Surface(self.size, 0, self.display)
def get_and_flip(self):
# if you don't want to tie the framerate to the camera, you can check and
# see if the camera has an image ready. note that while this works
# on most cameras, some will never return true.
self.snapshot = self.camera.get_image(self.display)
# if 0 and self.camera.query_image():
# # capture an image
# self.snapshot = self.camera.get_image(self.snapshot)
# if 0:
# self.snapshot = self.camera.get_image(self.snapshot)
# # self.snapshot = self.camera.get_image()
# # blit it to the display surface. simple!
# self.display.blit(self.snapshot, (0, 0))
# else:
# self.snapshot = self.camera.get_image(self.display)
# # self.display.blit(self.snapshot, (0,0))
pg.display.flip()
def main(self):
going = True
while going:
events = pg.event.get()
for e in events:
if e.type == pg.QUIT or (e.type == pg.KEYDOWN and e.key == pg.K_ESCAPE):
going = False
if e.type == pg.KEYDOWN:
if e.key in range(pg.K_0, pg.K_0 + 10):
self.init_cams(e.key - pg.K_0)
self.get_and_flip()
self.clock.tick()
print(self.clock.get_fps())
def main():
pg.init()
pygame.camera.init()
VideoCapturePlayer().main()
pg.quit()
if __name__ == "__main__":
main()
@@ -0,0 +1,203 @@
#!/usr/bin/env python
""" pygame.examples.chimp
This simple example is used for the line-by-line tutorial
that comes with pygame. It is based on a 'popular' web banner.
Note there are comments here, but for the full explanation,
follow along in the tutorial.
"""
# Import Modules
import os
import pygame as pg
from pygame.compat import geterror
if not pg.font:
print("Warning, fonts disabled")
if not pg.mixer:
print("Warning, sound disabled")
main_dir = os.path.split(os.path.abspath(__file__))[0]
data_dir = os.path.join(main_dir, "data")
# functions to create our resources
def load_image(name, colorkey=None):
fullname = os.path.join(data_dir, name)
try:
image = pg.image.load(fullname)
except pg.error:
print("Cannot load image:", fullname)
raise SystemExit(str(geterror()))
image = image.convert()
if colorkey is not None:
if colorkey == -1:
colorkey = image.get_at((0, 0))
image.set_colorkey(colorkey, pg.RLEACCEL)
return image, image.get_rect()
def load_sound(name):
class NoneSound:
def play(self):
pass
if not pg.mixer or not pg.mixer.get_init():
return NoneSound()
fullname = os.path.join(data_dir, name)
try:
sound = pg.mixer.Sound(fullname)
except pg.error:
print("Cannot load sound: %s" % fullname)
raise SystemExit(str(geterror()))
return sound
# classes for our game objects
class Fist(pg.sprite.Sprite):
"""moves a clenched fist on the screen, following the mouse"""
def __init__(self):
pg.sprite.Sprite.__init__(self) # call Sprite initializer
self.image, self.rect = load_image("fist.bmp", -1)
self.punching = 0
def update(self):
"""move the fist based on the mouse position"""
pos = pg.mouse.get_pos()
self.rect.midtop = pos
if self.punching:
self.rect.move_ip(5, 10)
def punch(self, target):
"""returns true if the fist collides with the target"""
if not self.punching:
self.punching = 1
hitbox = self.rect.inflate(-5, -5)
return hitbox.colliderect(target.rect)
def unpunch(self):
"""called to pull the fist back"""
self.punching = 0
class Chimp(pg.sprite.Sprite):
"""moves a monkey critter across the screen. it can spin the
monkey when it is punched."""
def __init__(self):
pg.sprite.Sprite.__init__(self) # call Sprite intializer
self.image, self.rect = load_image("chimp.bmp", -1)
screen = pg.display.get_surface()
self.area = screen.get_rect()
self.rect.topleft = 10, 10
self.move = 9
self.dizzy = 0
def update(self):
"""walk or spin, depending on the monkeys state"""
if self.dizzy:
self._spin()
else:
self._walk()
def _walk(self):
"""move the monkey across the screen, and turn at the ends"""
newpos = self.rect.move((self.move, 0))
if not self.area.contains(newpos):
if self.rect.left < self.area.left or self.rect.right > self.area.right:
self.move = -self.move
newpos = self.rect.move((self.move, 0))
self.image = pg.transform.flip(self.image, 1, 0)
self.rect = newpos
def _spin(self):
"""spin the monkey image"""
center = self.rect.center
self.dizzy = self.dizzy + 12
if self.dizzy >= 360:
self.dizzy = 0
self.image = self.original
else:
rotate = pg.transform.rotate
self.image = rotate(self.original, self.dizzy)
self.rect = self.image.get_rect(center=center)
def punched(self):
"""this will cause the monkey to start spinning"""
if not self.dizzy:
self.dizzy = 1
self.original = self.image
def main():
"""this function is called when the program starts.
it initializes everything it needs, then runs in
a loop until the function returns."""
# Initialize Everything
pg.init()
screen = pg.display.set_mode((468, 60))
pg.display.set_caption("Monkey Fever")
pg.mouse.set_visible(0)
# Create The Backgound
background = pg.Surface(screen.get_size())
background = background.convert()
background.fill((250, 250, 250))
# Put Text On The Background, Centered
if pg.font:
font = pg.font.Font(None, 36)
text = font.render("Pummel The Chimp, And Win $$$", 1, (10, 10, 10))
textpos = text.get_rect(centerx=background.get_width() / 2)
background.blit(text, textpos)
# Display The Background
screen.blit(background, (0, 0))
pg.display.flip()
# Prepare Game Objects
clock = pg.time.Clock()
whiff_sound = load_sound("whiff.wav")
punch_sound = load_sound("punch.wav")
chimp = Chimp()
fist = Fist()
allsprites = pg.sprite.RenderPlain((fist, chimp))
# Main Loop
going = True
while going:
clock.tick(60)
# Handle Input Events
for event in pg.event.get():
if event.type == pg.QUIT:
going = False
elif event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE:
going = False
elif event.type == pg.MOUSEBUTTONDOWN:
if fist.punch(chimp):
punch_sound.play() # punch
chimp.punched()
else:
whiff_sound.play() # miss
elif event.type == pg.MOUSEBUTTONUP:
fist.unpunch()
allsprites.update()
# Draw Everything
screen.blit(background, (0, 0))
allsprites.draw(screen)
pg.display.flip()
pg.quit()
# Game Over
# this calls the 'main' function when this script is executed
if __name__ == "__main__":
main()
@@ -0,0 +1,105 @@
#!/usr/bin/env python
""" pygame.examples.cursors
Click a mouse button (if you have one!) and the cursor changes.
"""
import pygame as pg
arrow = (
"xX ",
"X.X ",
"X..X ",
"X...X ",
"X....X ",
"X.....X ",
"X......X ",
"X.......X ",
"X........X ",
"X.........X ",
"X......XXXXX ",
"X...X..X ",
"X..XX..X ",
"X.X XX..X ",
"XX X..X ",
"X X..X ",
" X..X ",
" X..X ",
" X..X ",
" XX ",
" ",
" ",
" ",
" ",
)
no = (
" ",
" ",
" XXXXXX ",
" XX......XX ",
" X..........X ",
" X....XXXX....X ",
" X...XX XX...X ",
" X.....X X...X ",
" X..X...X X..X ",
" X...XX...X X...X ",
" X..X X...X X..X ",
" X..X X...X X..X ",
" X..X X.,.X X..X ",
" X..X X...X X..X ",
" X...X X...XX...X ",
" X..X X...X..X ",
" X...X X.....X ",
" X...XX X...X ",
" X....XXXXX...X ",
" X..........X ",
" XX......XX ",
" XXXXXX ",
" ",
" ",
)
def TestCursor(arrow):
hotspot = None
for y in range(len(arrow)):
for x in range(len(arrow[y])):
if arrow[y][x] in ["x", ",", "O"]:
hotspot = x, y
break
if hotspot is not None:
break
if hotspot is None:
raise Exception("No hotspot specified for cursor '%s'!" % cursorname)
s2 = []
for line in arrow:
s2.append(line.replace("x", "X").replace(",", ".").replace("O", "o"))
cursor, mask = pg.cursors.compile(s2, "X", ".", "o")
size = len(arrow[0]), len(arrow)
pg.mouse.set_cursor(size, hotspot, cursor, mask)
def main():
pg.init()
pg.font.init()
font = pg.font.Font(None, 24)
bg = pg.display.set_mode((800, 600), 0, 24)
bg.fill((255, 255, 255))
bg.blit(font.render("Click to advance", 1, (0, 0, 0)), (0, 0))
pg.display.update()
for cursor in [no, arrow]:
TestCursor(cursor)
going = True
while going:
pg.event.pump()
for e in pg.event.get():
if e.type == pg.MOUSEBUTTONDOWN:
going = False
pg.quit()
if __name__ == "__main__":
main()
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 578 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

File diff suppressed because one or more lines are too long
@@ -0,0 +1,76 @@
#!/usr/bin/env python
""" pygame.examples.dropfile
Drag and drop an image on here.
Uses these events:
* DROPBEGIN
* DROPCOMPLETE
* DROPTEXT
* DROPFILE
"""
import pygame as pg
if pg.get_sdl_version() < (2, 0, 0):
raise Exception("This example requires SDL2.")
pg.init()
def main():
Running = True
surf = pg.display.set_mode((640, 480))
font = pg.font.SysFont("Arial", 24)
clock = pg.time.Clock()
spr_file_text = font.render("Feed me some file or image!", 1, (255, 255, 255))
spr_file_text_rect = spr_file_text.get_rect()
spr_file_text_rect.center = surf.get_rect().center
spr_file_image = None
spr_file_image_rect = None
while Running:
for ev in pg.event.get():
if ev.type == pg.QUIT:
Running = False
elif ev.type == pg.DROPBEGIN:
print(ev)
print("File drop begin!")
elif ev.type == pg.DROPCOMPLETE:
print(ev)
print("File drop complete!")
elif ev.type == pg.DROPTEXT:
print(ev)
spr_file_text = font.render(ev.text, 1, (255, 255, 255))
spr_file_text_rect = spr_file_text.get_rect()
spr_file_text_rect.center = surf.get_rect().center
elif ev.type == pg.DROPFILE:
print(ev)
spr_file_text = font.render(ev.file, 1, (255, 255, 255))
spr_file_text_rect = spr_file_text.get_rect()
spr_file_text_rect.center = surf.get_rect().center
# Try to open the file if it's an image
filetype = ev.file[-3:]
if filetype in ["png", "bmp", "jpg"]:
spr_file_image = pg.image.load(ev.file).convert()
spr_file_image.set_alpha(127)
spr_file_image_rect = spr_file_image.get_rect()
spr_file_image_rect.center = surf.get_rect().center
surf.fill((0, 0, 0))
surf.blit(spr_file_text, spr_file_text_rect)
if spr_file_image:
surf.blit(spr_file_image, spr_file_image_rect)
pg.display.flip()
clock.tick(30)
pg.quit()
if __name__ == "__main__":
main()
@@ -0,0 +1,182 @@
#!/usr/bin/env python
""" pygame.examples.eventlist
Learn about pygame events and input.
At the top of the screen are the state of several device values,
and a scrolling list of events are displayed on the bottom.
"""
usage = """
Mouse Controls
==============
- 1st button on mouse (left click) to toggle events 'grabed'.
- 3rd button on mouse (right click) to toggle mouse visible.
- The window can be resized.
- Mouse the mouse around to see mouse events.
- If events grabbed and mouse invisible show virtual mouse coords.
Keyboard Joystick Controls
==========================
- press keys up an down to see events.
- you can see joystick events if any are plugged in.
"""
import pygame as pg
img_on_off = []
font = None
last_key = None
# these are a running counter of mouse.get_rel() calls.
virtual_x = 0
virtual_y = 0
def showtext(win, pos, text, color, bgcolor):
textimg = font.render(text, 1, color, bgcolor)
win.blit(textimg, pos)
return pos[0] + textimg.get_width() + 5, pos[1]
def drawstatus(win):
global virtual_x, virtual_y
bgcolor = 50, 50, 50
win.fill(bgcolor, (0, 0, 640, 120))
win.blit(font.render("Status Area", 1, (155, 155, 155), bgcolor), (2, 2))
pos = showtext(win, (10, 30), "Mouse Focus", (255, 255, 255), bgcolor)
win.blit(img_on_off[pg.mouse.get_focused()], pos)
pos = showtext(
win, (pos[0] + 50, pos[1]), "Mouse visible", (255, 255, 255), bgcolor
)
win.blit(img_on_off[pg.mouse.get_visible()], pos)
pos = showtext(win, (330, 30), "Keyboard Focus", (255, 255, 255), bgcolor)
win.blit(img_on_off[pg.key.get_focused()], pos)
pos = showtext(win, (10, 60), "Mouse Position(rel)", (255, 255, 255), bgcolor)
rel = pg.mouse.get_rel()
virtual_x += rel[0]
virtual_y += rel[1]
mouse_data = tuple(list(pg.mouse.get_pos()) + list(rel))
p = "%s, %s (%s, %s)" % mouse_data
showtext(win, pos, p, bgcolor, (255, 255, 55))
pos = showtext(win, (330, 60), "Last Keypress", (255, 255, 255), bgcolor)
if last_key:
p = "%d, %s" % (last_key, pg.key.name(last_key))
else:
p = "None"
showtext(win, pos, p, bgcolor, (255, 255, 55))
pos = showtext(win, (10, 90), "Input Grabbed", (255, 255, 255), bgcolor)
win.blit(img_on_off[pg.event.get_grab()], pos)
is_virtual_mouse = pg.event.get_grab() and not pg.mouse.get_visible()
pos = showtext(win, (330, 90), "Virtual Mouse", (255, 255, 255), bgcolor)
win.blit(img_on_off[is_virtual_mouse], pos)
if is_virtual_mouse:
p = "%s, %s" % (virtual_x, virtual_y)
showtext(win, (pos[0] + 50, pos[1]), p, bgcolor, (255, 255, 55))
def drawhistory(win, history):
img = font.render("Event History Area", 1, (155, 155, 155), (0, 0, 0))
win.blit(img, (2, 132))
ypos = 450
h = list(history)
h.reverse()
for line in h:
r = win.blit(line, (10, ypos))
win.fill(0, (r.right, r.top, 620, r.height))
ypos -= font.get_height()
def draw_usage_in_history(history, text):
lines = text.split("\n")
for line in lines:
if line == "" or "===" in line:
continue
img = font.render(line, 1, (50, 200, 50), (0, 0, 0))
history.append(img)
def main():
pg.init()
print(usage)
win = pg.display.set_mode((640, 480), pg.RESIZABLE)
pg.display.set_caption("Mouse Focus Workout. h key for help")
global font
font = pg.font.Font(None, 26)
global img_on_off
img_on_off.append(font.render("Off", 1, (0, 0, 0), (255, 50, 50)))
img_on_off.append(font.render("On", 1, (0, 0, 0), (50, 255, 50)))
# stores surfaces of text representing what has gone through the event queue
history = []
# let's turn on the joysticks just so we can play with em
for x in range(pg.joystick.get_count()):
j = pg.joystick.Joystick(x)
j.init()
txt = "Enabled joystick: " + j.get_name()
img = font.render(txt, 1, (50, 200, 50), (0, 0, 0))
history.append(img)
if not pg.joystick.get_count():
img = font.render("No Joysticks to Initialize", 1, (50, 200, 50), (0, 0, 0))
history.append(img)
going = True
while going:
for e in pg.event.get():
if e.type == pg.KEYDOWN:
if e.key == pg.K_ESCAPE:
going = False
else:
global last_key
last_key = e.key
if e.key == pg.K_h:
draw_usage_in_history(history, usage)
if e.type == pg.MOUSEBUTTONDOWN and e.button == 1:
pg.event.set_grab(not pg.event.get_grab())
if e.type == pg.MOUSEBUTTONDOWN and e.button == 3:
pg.mouse.set_visible(not pg.mouse.get_visible())
if e.type != pg.MOUSEMOTION:
txt = "%s: %s" % (pg.event.event_name(e.type), e.dict)
img = font.render(txt, 1, (50, 200, 50), (0, 0, 0))
history.append(img)
history = history[-13:]
if e.type == pg.VIDEORESIZE:
win = pg.display.set_mode(e.size, pg.RESIZABLE)
if e.type == pg.QUIT:
going = False
drawstatus(win)
drawhistory(win, history)
pg.display.flip()
pg.time.wait(10)
pg.quit()
raise SystemExit
if __name__ == "__main__":
main()
@@ -0,0 +1,101 @@
#!/usr/bin/env python
""" pygame.examples.fastevents
This is a stress test for the fastevents module.
If you are using threads, then fastevents is useful.
"""
import time as pytime
from threading import Thread
import pygame as pg
# the config to try different settings out with the event queues.
# use the fastevent module or not.
event_module = pg.fastevent
# event_module = event
# use pg.display.flip().
# otherwise we test raw event processing throughput.
with_display = 1
# limit the game loop to 40 fps.
slow_tick = 0
NUM_EVENTS_TO_POST = 200000
class PostThem(Thread):
def __init__(self):
Thread.__init__(self)
self.done = []
self.stop = []
def run(self):
self.done = []
self.stop = []
for x in range(NUM_EVENTS_TO_POST):
ee = pg.event.Event(pg.USEREVENT)
try_post = 1
# the pg.event.post raises an exception if the event
# queue is full. so wait a little bit, and try again.
while try_post:
try:
event_module.post(ee)
try_post = 0
except pg.error:
pytime.sleep(0.001)
try_post = 1
if self.stop:
return
self.done.append(1)
def main():
pg.init()
if hasattr(event_module, "init"):
event_module.init()
c = pg.time.Clock()
pg.display.set_mode((640, 480), pg.RESIZABLE)
pg.display.set_caption("fastevent Workout")
poster = PostThem()
t1 = pytime.time()
poster.start()
going = True
while going:
for e in event_module.get():
if e.type == pg.QUIT:
print(c.get_fps())
poster.stop.append(1)
going = False
if e.type == pg.KEYDOWN:
if e.key == pg.K_ESCAPE:
print(c.get_fps())
poster.stop.append(1)
going = False
if poster.done:
print(c.get_fps())
print(c)
t2 = pytime.time()
print("total time:%s" % (t2 - t1))
print("events/second:%s" % (NUM_EVENTS_TO_POST / (t2 - t1)))
going = False
if with_display:
pg.display.flip()
if slow_tick:
c.tick(40)
pg.quit()
if __name__ == "__main__":
main()
@@ -0,0 +1,269 @@
#!/usr/bin/env python
""" pygame.examples.font_viewer
Scroll through your system fonts from a list of surfaces or one huge buffer.
This example exhibits:
* iterate over available fonts using font.get_fonts and font.SysFont()
* scroll using virtual mouse input
* save a surface to disk
* work with a very large surface
* simple mouse and keyboard scroll speed acceleration
By default this example uses the fonts returned by pygame.font.get_fonts()
and opens them using pygame.font.SysFont().
Alternatively, you may pass a path to the command line. The TTF files found
in that directory will be used instead.
Mouse Controls:
* Click in the window to toggle scrolling. The cursor will vanish and pygame
will enter virtual mouse mode until you click again.
Keyboard Controls:
* Press up or down to scroll
* Press escape to exit
"""
import sys
import os
import pygame as pg
use_big_surface = False # draw into large buffer and save png file
class FontViewer:
"""
This example is encapsulated by the fontviewer class
It initializes the pygame window, handles input, and draws itself
to the screen.
"""
KEY_SCROLL_SPEED = 10
def __init__(self, **dparams):
pg.init()
self.font_dir = dparams.get("folder", None)
# create a window that uses 80 percent of the screen
info = pg.display.Info()
w = info.current_w
h = info.current_h
pg.display.set_mode((int(w * 0.8), int(h * 0.8)))
self.font_size = h // 20
self.clock = pg.time.Clock()
self.y_offset = 0
self.grabbed = False
self.render_fonts("&N abcDEF789")
if use_big_surface or "big" in sys.argv:
self.render_surface()
self.display_surface()
self.save_png()
else:
self.display_fonts()
def get_font_list(self):
"""
Generate a font list using font.get_fonts() for system fonts or
from a path from the command line.
"""
path = ""
if len(sys.argv) > 1 and os.path.exists(sys.argv[1]):
path = os.path.join(sys.argv[1], "")
fonts = []
if os.path.exists(path):
# this list comprehension could replace the following loop
# fonts = [f in os.listdir(path) if f.endswith('.ttf')]
for font in os.listdir(path):
if font.endswith(".ttf"):
fonts.append(font)
return fonts or pg.font.get_fonts(), path
def render_fonts(self, text="A display of font &N", **dparams):
"""
Build a list that includes a surface and the running total of their
height for each font in the font list. Store the largest width and
other variables for later use.
"""
font_size = dparams.get("size", 0) or self.font_size
color = dparams.get("color", (255, 255, 255))
self.back_color = dparams.get("back_color", (0, 0, 0))
fonts, path = self.get_font_list()
font_surfaces = []
total_height = 0
max_width = 0
load_font = pg.font.Font if path else pg.font.SysFont
# display instructions at the top of the display
font = pg.font.SysFont(pg.font.get_default_font(), font_size)
lines = (
"Click in this window to enter scroll mode",
"The mouse will be grabbed and hidden until you click again",
"Foreign fonts might render incorrectly",
"Here are your {} fonts".format(len(fonts)),
"",
)
for line in lines:
surf = font.render(line, 1, color, self.back_color)
font_surfaces.append((surf, total_height))
total_height += surf.get_height()
max_width = max(max_width, surf.get_width())
# render all the fonts and store them with the total height
for name in sorted(fonts):
try:
font = load_font(path + name, font_size)
except IOError:
continue
line = text.replace("&N", name)
print(name, line, surf.get_height())
try:
surf = font.render(line, 1, color, self.back_color)
except pg.error as e:
print(e)
break
max_width = max(max_width, surf.get_width())
font_surfaces.append((surf, total_height))
total_height += surf.get_height()
# store variables for later usage
self.total_height = total_height
self.max_width = max_width
self.font_surfaces = font_surfaces
self.max_y = total_height - pg.display.get_surface().get_height()
def display_fonts(self):
"""
Display the visible fonts based on the y_offset value(updated in
handle_events) and the height of the pygame window.
"""
display = pg.display.get_surface()
clock = pg.time.Clock()
center = display.get_width() // 2
while True:
# draw visible surfaces
display.fill(self.back_color)
for surface, top in self.font_surfaces:
if top >= self.y_offset:
x = center - surface.get_width() // 2
display.blit(surface, (x, top - self.y_offset))
# get input and update the screen
if not self.handle_events():
break
pg.display.flip()
clock.tick(30)
def render_surface(self):
"""
Note: this method uses twice the memory and is only called if
big_surface is set to true or big is added to the command line.
Optionally generates one large buffer to draw all the font surfaces
into. This is necessary to save the display to a png file and may
be useful for testing large surfaces.
"""
large_surface = pg.surface.Surface(
(self.max_width, self.total_height)
).convert()
large_surface.fill(self.back_color)
print("scrolling surface created")
# display the surface size and memory usage
byte_size = large_surface.get_bytesize()
total_size = byte_size * (self.max_width * self.total_height)
print(
"Surface Size = {}x{} @ {}bpp: {:,.3f}mb".format(
self.max_width, self.total_height, byte_size, total_size / 1000000.0
)
)
y = 0
center = int(self.max_width / 2)
for surface, top in self.font_surfaces:
w = surface.get_width()
x = center - int(w / 2)
large_surface.blit(surface, (x, y))
y += surface.get_height()
self.max_y = large_surface.get_height() - pg.display.get_surface().get_height()
self.surface = large_surface
def display_surface(self, time=10):
"""
Display the large surface created by the render_surface method. Scrolls
based on the y_offset value(set in handle_events) and the height of the
pygame window.
"""
screen = pg.display.get_surface()
# Create a Rect equal to size of screen. Then we can just change its
# top attribute to draw the desired part of the rendered font surface
# to the display surface
rect = pg.rect.Rect(
0,
0,
self.surface.get_width(),
min(self.surface.get_height(), screen.get_height()),
)
x = int((screen.get_width() - self.surface.get_width()) / 2)
going = True
while going:
if not self.handle_events():
going = False
screen.fill(self.back_color)
rect.top = self.y_offset
screen.blit(self.surface, (x, 0), rect)
pg.display.flip()
self.clock.tick(20)
def save_png(self, name="font_viewer.png"):
pg.image.save(self.surface, name)
file_size = os.path.getsize(name) // 1024
print("font surface saved to {}\nsize: {:,}Kb".format(name, file_size))
def handle_events(self):
"""
This method handles user input. It returns False when it receives
a pygame.QUIT event or the user presses escape. The y_offset is
changed based on mouse and keyboard input. display_fonts() and
display_surface() use the y_offset to scroll display.
"""
events = pg.event.get()
for e in events:
if e.type == pg.QUIT:
return False
elif e.type == pg.KEYDOWN:
if e.key == pg.K_ESCAPE:
return False
elif e.type == pg.MOUSEBUTTONDOWN:
# enter or exit virtual mouse mode for scrolling
self.grabbed = not self.grabbed
pg.event.set_grab(self.grabbed)
pg.mouse.set_visible(not self.grabbed)
# allow simple accelerated scrolling with the keyboard
keys = pg.key.get_pressed()
if keys[pg.K_UP]:
self.key_held += 1
self.y_offset -= int(self.KEY_SCROLL_SPEED * (self.key_held // 10))
elif keys[pg.K_DOWN]:
self.key_held += 1
self.y_offset += int(self.KEY_SCROLL_SPEED * (self.key_held // 10))
else:
self.key_held = 20
# set the y_offset for scrolling and keep it between 0 and max_y
y = pg.mouse.get_rel()[1]
if y and self.grabbed:
self.y_offset += (y / 2) ** 2 * (y / abs(y))
self.y_offset = min((max(self.y_offset, 0), self.max_y))
return True
viewer = FontViewer()
@@ -0,0 +1,97 @@
#!/usr/bin/env python
""" pygame.examples.fonty
Here we load a .TTF True Type font file, and display it in
a basic pygame window.
Demonstrating several Font object attributes.
- basic window, event, and font management.
"""
import pygame as pg
from pygame.compat import unicode_
import sys
import locale
if sys.version_info >= (3,):
def print_unicode(s):
e = locale.getpreferredencoding()
print(s.encode(e, "backslashreplace").decode())
else:
def print_unicode(s):
e = locale.getpreferredencoding()
print(s.encode(e, "backslashreplace"))
def main():
# initialize
pg.init()
resolution = 400, 200
screen = pg.display.set_mode(resolution)
## pg.mouse.set_cursor(*pg.cursors.diamond)
fg = 250, 240, 230
bg = 5, 5, 5
wincolor = 40, 40, 90
# fill background
screen.fill(wincolor)
# load font, prepare values
font = pg.font.Font(None, 80)
text = "Fonty"
size = font.size(text)
# no AA, no transparancy, normal
ren = font.render(text, 0, fg, bg)
screen.blit(ren, (10, 10))
# no AA, transparancy, underline
font.set_underline(1)
ren = font.render(text, 0, fg)
screen.blit(ren, (10, 40 + size[1]))
font.set_underline(0)
a_sys_font = pg.font.SysFont("Arial", 60)
# AA, no transparancy, bold
a_sys_font.set_bold(1)
ren = a_sys_font.render(text, 1, fg, bg)
screen.blit(ren, (30 + size[0], 10))
a_sys_font.set_bold(0)
# AA, transparancy, italic
a_sys_font.set_italic(1)
ren = a_sys_font.render(text, 1, fg)
screen.blit(ren, (30 + size[0], 40 + size[1]))
a_sys_font.set_italic(0)
# Get some metrics.
print("Font metrics for 'Fonty': %s" % a_sys_font.metrics(text))
ch = unicode_("%c") % 0x3060
msg = unicode_("Font metrics for '%s': %s") % (ch, a_sys_font.metrics(ch))
print_unicode(msg)
## #some_japanese_unicode = u"\u304b\u3070\u306b"
##some_japanese_unicode = unicode_('%c%c%c') % (0x304b, 0x3070, 0x306b)
# AA, transparancy, italic
##ren = a_sys_font.render(some_japanese_unicode, 1, fg)
##screen.blit(ren, (30 + size[0], 40 + size[1]))
# show the surface and await user quit
pg.display.flip()
while 1:
# use event.wait to keep from polling 100% cpu
if pg.event.wait().type in (pg.QUIT, pg.KEYDOWN, pg.MOUSEBUTTONDOWN):
break
if __name__ == "__main__":
main()
@@ -0,0 +1,177 @@
#!/usr/bin/env python
""" pygame.examples.freetype_misc
Miscellaneous (or misc) means:
"consisting of a mixture of various things that are not
usually connected with each other"
Adjective
All those words you read on computers, magazines, books, and such over the years?
Probably a lot of them were constructed with...
The FreeType Project: a free, high-quality and portable Font engine.
https://freetype.org
Next time you're reading something. Think of them.
Herein lies a *BOLD* demo consisting of a mixture of various things.
Not only is it a *BOLD* demo, it's an
italics demo,
a rotated demo,
it's a blend,
and is sized to go nicely with a cup of tea*.
* also goes well with coffee.
Enjoy!
"""
import os
import pygame as pg
import pygame.freetype as freetype
colors = {
"grey_light": pg.Color(200, 200, 200),
"grey_dark": pg.Color(100, 100, 100),
"green": pg.Color(50, 255, 63),
"red": pg.Color(220, 30, 30),
"blue": pg.Color(50, 75, 245),
}
def run():
pg.init()
fontdir = os.path.dirname(os.path.abspath(__file__))
font = freetype.Font(os.path.join(fontdir, "data", "sans.ttf"))
screen = pg.display.set_mode((800, 600))
screen.fill(colors["grey_light"])
font.underline_adjustment = 0.5
font.pad = True
font.render_to(
screen,
(32, 32),
"Hello World",
colors["red"],
colors["grey_dark"],
size=64,
style=freetype.STYLE_UNDERLINE | freetype.STYLE_OBLIQUE,
)
font.pad = False
font.render_to(
screen,
(32, 128),
"abcdefghijklm",
colors["grey_dark"],
colors["green"],
size=64,
)
font.vertical = True
font.render_to(screen, (32, 200), "Vertical?", colors["blue"], None, size=32)
font.vertical = False
font.render_to(
screen, (64, 190), "Let's spin!", colors["red"], None, size=48, rotation=55
)
font.render_to(
screen, (160, 290), "All around!", colors["green"], None, size=48, rotation=-55
)
font.render_to(
screen, (250, 220), "and BLEND", pg.Color(255, 0, 0, 128), None, size=64
)
font.render_to(
screen, (265, 237), "or BLAND!", pg.Color(0, 0xCC, 28, 128), None, size=64
)
# Some pinwheels
font.origin = True
for angle in range(0, 360, 45):
font.render_to(
screen, (150, 420), ")", pg.Color("black"), size=48, rotation=angle
)
font.vertical = True
for angle in range(15, 375, 30):
font.render_to(
screen, (600, 400), "|^*", pg.Color("orange"), size=48, rotation=angle
)
font.vertical = False
font.origin = False
utext = pg.compat.as_unicode(r"I \u2665 Unicode")
font.render_to(screen, (298, 320), utext, pg.Color(0, 0xCC, 0xDD), None, size=64)
utext = pg.compat.as_unicode(r"\u2665")
font.render_to(
screen, (480, 32), utext, colors["grey_light"], colors["red"], size=148
)
font.render_to(
screen,
(380, 380),
"...yes, this is an SDL surface",
pg.Color(0, 0, 0),
None,
size=24,
style=freetype.STYLE_STRONG,
)
font.origin = True
r = font.render_to(
screen,
(100, 530),
"stretch",
pg.Color("red"),
None,
size=(24, 24),
style=freetype.STYLE_NORMAL,
)
font.render_to(
screen,
(100 + r.width, 530),
" VERTICAL",
pg.Color("red"),
None,
size=(24, 48),
style=freetype.STYLE_NORMAL,
)
r = font.render_to(
screen,
(100, 580),
"stretch",
pg.Color("blue"),
None,
size=(24, 24),
style=freetype.STYLE_NORMAL,
)
font.render_to(
screen,
(100 + r.width, 580),
" HORIZONTAL",
pg.Color("blue"),
None,
size=(48, 24),
style=freetype.STYLE_NORMAL,
)
pg.display.flip()
while 1:
if pg.event.wait().type in (pg.QUIT, pg.KEYDOWN, pg.MOUSEBUTTONDOWN):
break
pg.quit()
if __name__ == "__main__":
run()
@@ -0,0 +1,168 @@
#!/usr/bin/env python
""" pygame.examples.glcube
Draw a cube on the screen.
Amazing.
Every frame we orbit the camera around a small amount
creating the illusion of a spinning object.
First we setup some points of a multicolored cube. Then we then go through
a semi-unoptimized loop to draw the cube points onto the screen.
OpenGL does all the hard work for us. :]
Keyboard Controls
-----------------
* ESCAPE key to quit
* f key to toggle fullscreen.
"""
import pygame as pg
try:
import OpenGL.GL as GL
import OpenGL.GLU as GLU
except ImportError:
print("The GLCUBE example requires PyOpenGL")
raise SystemExit
# Some simple data for a colored cube here we have the 3D point position and color
# for each corner. A list of indices describes each face, and a list of
# indicies describes each edge.
CUBE_POINTS = (
(0.5, -0.5, -0.5),
(0.5, 0.5, -0.5),
(-0.5, 0.5, -0.5),
(-0.5, -0.5, -0.5),
(0.5, -0.5, 0.5),
(0.5, 0.5, 0.5),
(-0.5, -0.5, 0.5),
(-0.5, 0.5, 0.5),
)
# colors are 0-1 floating values
CUBE_COLORS = (
(1, 0, 0),
(1, 1, 0),
(0, 1, 0),
(0, 0, 0),
(1, 0, 1),
(1, 1, 1),
(0, 0, 1),
(0, 1, 1),
)
CUBE_QUAD_VERTS = (
(0, 1, 2, 3),
(3, 2, 7, 6),
(6, 7, 5, 4),
(4, 5, 1, 0),
(1, 5, 7, 2),
(4, 0, 3, 6),
)
CUBE_EDGES = (
(0, 1),
(0, 3),
(0, 4),
(2, 1),
(2, 3),
(2, 7),
(6, 3),
(6, 4),
(6, 7),
(5, 1),
(5, 4),
(5, 7),
)
def drawcube():
"draw the cube"
allpoints = list(zip(CUBE_POINTS, CUBE_COLORS))
GL.glBegin(GL.GL_QUADS)
for face in CUBE_QUAD_VERTS:
for vert in face:
pos, color = allpoints[vert]
GL.glColor3fv(color)
GL.glVertex3fv(pos)
GL.glEnd()
GL.glColor3f(1.0, 1.0, 1.0)
GL.glBegin(GL.GL_LINES)
for line in CUBE_EDGES:
for vert in line:
pos, color = allpoints[vert]
GL.glVertex3fv(pos)
GL.glEnd()
def init_gl_stuff():
GL.glEnable(GL.GL_DEPTH_TEST) # use our zbuffer
# setup the camera
GL.glMatrixMode(GL.GL_PROJECTION)
GL.glLoadIdentity()
GLU.gluPerspective(45.0, 640 / 480.0, 0.1, 100.0) # setup lens
GL.glTranslatef(0.0, 0.0, -3.0) # move back
GL.glRotatef(25, 1, 0, 0) # orbit higher
def main():
"run the demo"
# initialize pygame and setup an opengl display
pg.init()
fullscreen = True
pg.display.set_mode((640, 480), pg.OPENGL | pg.DOUBLEBUF | pg.FULLSCREEN)
init_gl_stuff()
going = True
while going:
# check for quit'n events
events = pg.event.get()
for event in events:
if event.type == pg.QUIT or (
event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE
):
going = False
elif event.type == pg.KEYDOWN:
if event.key == pg.K_f:
if not fullscreen:
print("Changing to FULLSCREEN")
pg.display.set_mode(
(640, 480), pg.OPENGL | pg.DOUBLEBUF | pg.FULLSCREEN
)
else:
print("Changing to windowed mode")
pg.display.set_mode((640, 480), pg.OPENGL | pg.DOUBLEBUF)
fullscreen = not fullscreen
init_gl_stuff()
# clear screen and move camera
GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)
# orbit camera around by 1 degree
GL.glRotatef(1, 0, 1, 0)
drawcube()
pg.display.flip()
pg.time.wait(10)
if __name__ == "__main__":
main()
@@ -0,0 +1,50 @@
#!/usr/bin/env python
""" pygame.examples.headless_no_windows_needed
How to use pygame with no windowing system, like on headless servers.
Thumbnail generation with scaling is an example of what you can do with pygame.
NOTE: the pygame scale function uses mmx/sse if available, and can be run
in multiple threads.
"""
useage = """-scale inputimage outputimage new_width new_height
eg. -scale in.png out.png 50 50
"""
import os
import sys
# set SDL to use the dummy NULL video driver,
# so it doesn't need a windowing system.
os.environ["SDL_VIDEODRIVER"] = "dummy"
import pygame as pg
# Some platforms need to init the display for some parts of pg.
pg.display.init()
screen = pg.display.set_mode((1, 1))
def scaleit(fin, fout, w, h):
i = pg.image.load(fin)
if hasattr(pg.transform, "smoothscale"):
scaled_image = pg.transform.smoothscale(i, (w, h))
else:
scaled_image = pg.transform.scale(i, (w, h))
pg.image.save(scaled_image, fout)
def main(fin, fout, w, h):
"""smoothscale image file named fin as fout with new size (w,h)"""
scaleit(fin, fout, w, h)
if __name__ == "__main__":
if "-scale" in sys.argv:
fin, fout, w, h = sys.argv[2:]
w, h = map(int, [w, h])
main(fin, fout, w, h)
else:
print(useage)
@@ -0,0 +1,88 @@
#!/usr/bin/env python
""" pygame.examples.liquid
This example demonstrates a simplish water effect of an
image. It attempts to create a hardware display surface that
can use pageflipping for faster updates. Note that the colormap
from the loaded GIF image is copied to the colormap for the
display surface.
This is based on the demo named F2KWarp by Brad Graham of Freedom2000
done in BlitzBasic. I was just translating the BlitzBasic code to
pygame to compare the results. I didn't bother porting the text and
sound stuff, that's an easy enough challenge for the reader :]
"""
import pygame as pg
import os
from math import sin
import time
main_dir = os.path.split(os.path.abspath(__file__))[0]
def main():
# initialize and setup screen
pg.init()
screen = pg.display.set_mode((640, 480), pg.HWSURFACE | pg.DOUBLEBUF)
# load image and quadruple
imagename = os.path.join(main_dir, "data", "liquid.bmp")
bitmap = pg.image.load(imagename)
bitmap = pg.transform.scale2x(bitmap)
bitmap = pg.transform.scale2x(bitmap)
# get the image and screen in the same format
if screen.get_bitsize() == 8:
screen.set_palette(bitmap.get_palette())
else:
bitmap = bitmap.convert()
# prep some variables
anim = 0.0
# mainloop
xblocks = range(0, 640, 20)
yblocks = range(0, 480, 20)
stopevents = pg.QUIT, pg.KEYDOWN, pg.MOUSEBUTTONDOWN
while 1:
for e in pg.event.get():
if e.type in stopevents:
return
anim = anim + 0.02
for x in xblocks:
xpos = (x + (sin(anim + x * 0.01) * 15)) + 20
for y in yblocks:
ypos = (y + (sin(anim + y * 0.01) * 15)) + 20
screen.blit(bitmap, (x, y), (xpos, ypos, 20, 20))
pg.display.flip()
time.sleep(0.01)
if __name__ == "__main__":
main()
"""BTW, here is the code from the BlitzBasic example this was derived
from. i've snipped the sound and text stuff out.
-----------------------------------------------------------------
; Brad@freedom2000.com
; Load a bmp pic (800x600) and slice it into 1600 squares
Graphics 640,480
SetBuffer BackBuffer()
bitmap$="f2kwarp.bmp"
pic=LoadAnimImage(bitmap$,20,15,0,1600)
; use SIN to move all 1600 squares around to give liquid effect
Repeat
f=0:w=w+10:If w=360 Then w=0
For y=0 To 599 Step 15
For x = 0 To 799 Step 20
f=f+1:If f=1600 Then f=0
DrawBlock pic,(x+(Sin(w+x)*40))/1.7+80,(y+(Sin(w+y)*40))/1.7+60,f
Next:Next:Flip:Cls
Until KeyDown(1)
"""
@@ -0,0 +1,211 @@
#!/usr/bin/env python
""" pygame.examples.mask
A pygame.mask collision detection production.
Brought
to
you
by
the
pixels
0000000000000
and
111111
This is 32 bits:
11111111111111111111111111111111
There are 32 or 64 bits in a computer 'word'.
Rather than using one word for a pixel,
the mask module represents 32 or 64 pixels in one word.
As you can imagine, this makes things fast, and saves memory.
Compute intensive things like collision detection,
and computer vision benefit greatly from this.
This module can also be run as a stand-alone program, excepting
one or more image file names as command line arguments.
"""
import sys
import os
import random
import pygame as pg
def maskFromSurface(surface, threshold=127):
return pg.mask.from_surface(surface, threshold)
def vadd(x, y):
return [x[0] + y[0], x[1] + y[1]]
def vsub(x, y):
return [x[0] - y[0], x[1] - y[1]]
def vdot(x, y):
return x[0] * y[0] + x[1] * y[1]
class Sprite:
def __init__(self, surface, mask=None):
self.surface = surface
if mask:
self.mask = mask
else:
self.mask = maskFromSurface(self.surface)
self.setPos([0, 0])
self.setVelocity([0, 0])
def setPos(self, pos):
self.pos = [pos[0], pos[1]]
def setVelocity(self, vel):
self.vel = [vel[0], vel[1]]
def move(self, dr):
self.pos = vadd(self.pos, dr)
def kick(self, impulse):
self.vel[0] += impulse[0]
self.vel[1] += impulse[1]
def collide(self, s):
"""Test if the sprites are colliding and
resolve the collision in this case."""
offset = [int(x) for x in vsub(s.pos, self.pos)]
overlap = self.mask.overlap_area(s.mask, offset)
if overlap == 0:
return
"""Calculate collision normal"""
nx = self.mask.overlap_area(
s.mask, (offset[0] + 1, offset[1])
) - self.mask.overlap_area(s.mask, (offset[0] - 1, offset[1]))
ny = self.mask.overlap_area(
s.mask, (offset[0], offset[1] + 1)
) - self.mask.overlap_area(s.mask, (offset[0], offset[1] - 1))
if nx == 0 and ny == 0:
"""One sprite is inside another"""
return
n = [nx, ny]
dv = vsub(s.vel, self.vel)
J = vdot(dv, n) / (2 * vdot(n, n))
if J > 0:
"""Can scale up to 2*J here to get bouncy collisions"""
J *= 1.9
self.kick([nx * J, ny * J])
s.kick([-J * nx, -J * ny])
return
# """Separate the sprites"""
# c1 = -overlap/vdot(n,n)
# c2 = -c1/2
# self.move([c2*nx,c2*ny])
# s.move([(c1+c2)*nx,(c1+c2)*ny])
def update(self, dt):
self.pos[0] += dt * self.vel[0]
self.pos[1] += dt * self.vel[1]
def main(*args):
"""Display multiple images bounce off each other using collision detection
Positional arguments:
one or more image file names.
This pg.masks demo will display multiple moving sprites bouncing
off each other. More than one sprite image can be provided.
"""
if len(args) == 0:
raise ValueError("Require at least one image file name: non given")
print("Press any key to quit")
screen = pg.display.set_mode((640, 480))
if any("fist.bmp" in x for x in args):
pg.display.set_caption("Punch Nazis")
images = []
masks = []
for impath in args:
images.append(pg.image.load(impath).convert_alpha())
masks.append(maskFromSurface(images[-1]))
numtimes = 10
import time
t1 = time.time()
for x in range(numtimes):
unused_mask = maskFromSurface(images[-1])
t2 = time.time()
print("python maskFromSurface :%s" % (t2 - t1))
t1 = time.time()
for x in range(numtimes):
unused_mask = pg.mask.from_surface(images[-1])
t2 = time.time()
print("C pg.mask.from_surface :%s" % (t2 - t1))
sprites = []
for i in range(20):
j = i % len(images)
s = Sprite(images[j], masks[j])
s.setPos(
(
random.uniform(0, screen.get_width()),
random.uniform(0, screen.get_height()),
)
)
s.setVelocity((random.uniform(-5, 5), random.uniform(-5, 5)))
sprites.append(s)
pg.time.set_timer(pg.USEREVENT, 33)
while 1:
event = pg.event.wait()
if event.type == pg.QUIT:
return
elif event.type == pg.USEREVENT:
# Do both mechanics and screen update
screen.fill((240, 220, 100))
for i in range(len(sprites)):
for j in range(i + 1, len(sprites)):
sprites[i].collide(sprites[j])
for s in sprites:
s.update(1)
if s.pos[0] < -s.surface.get_width() - 3:
s.pos[0] = screen.get_width()
elif s.pos[0] > screen.get_width() + 3:
s.pos[0] = -s.surface.get_width()
if s.pos[1] < -s.surface.get_height() - 3:
s.pos[1] = screen.get_height()
elif s.pos[1] > screen.get_height() + 3:
s.pos[1] = -s.surface.get_height()
screen.blit(s.surface, s.pos)
pg.display.update()
elif event.type == pg.KEYDOWN:
return
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: mask.py <IMAGE> [<IMAGE> ...]")
print("Let many copies of IMAGE(s) bounce against each other")
print("Press any key to quit")
main_dir = os.path.split(os.path.abspath(__file__))[0]
imagename = os.path.join(main_dir, "data", "fist.bmp")
main(imagename)
else:
main(*sys.argv[1:])
@@ -0,0 +1,878 @@
#!/usr/bin/env python
""" pygame.examples.midi
midi input, and a separate example of midi output.
By default it runs the output example.
python -m pygame.examples.midi --output
python -m pygame.examples.midi --input
python -m pygame.examples.midi --input
"""
import sys
import os
import pygame as pg
import pygame.midi
def print_device_info():
pygame.midi.init()
_print_device_info()
pygame.midi.quit()
def _print_device_info():
for i in range(pygame.midi.get_count()):
r = pygame.midi.get_device_info(i)
(interf, name, input, output, opened) = r
in_out = ""
if input:
in_out = "(input)"
if output:
in_out = "(output)"
print(
"%2i: interface :%s:, name :%s:, opened :%s: %s"
% (i, interf, name, opened, in_out)
)
def input_main(device_id=None):
pg.init()
pg.fastevent.init()
event_get = pg.fastevent.get
event_post = pg.fastevent.post
pygame.midi.init()
_print_device_info()
if device_id is None:
input_id = pygame.midi.get_default_input_id()
else:
input_id = device_id
print("using input_id :%s:" % input_id)
i = pygame.midi.Input(input_id)
pg.display.set_mode((1, 1))
going = True
while going:
events = event_get()
for e in events:
if e.type in [pg.QUIT]:
going = False
if e.type in [pg.KEYDOWN]:
going = False
if e.type in [pygame.midi.MIDIIN]:
print(e)
if i.poll():
midi_events = i.read(10)
# convert them into pygame events.
midi_evs = pygame.midi.midis2events(midi_events, i.device_id)
for m_e in midi_evs:
event_post(m_e)
del i
pygame.midi.quit()
def output_main(device_id=None):
"""Execute a musical keyboard example for the Church Organ instrument
This is a piano keyboard example, with a two octave keyboard, starting at
note F3. Left mouse down over a key starts a note, left up stops it. The
notes are also mapped to the computer keyboard keys, assuming an American
English PC keyboard (sorry everyone else, but I don't know if I can map to
absolute key position instead of value.) The white keys are on the second
row, TAB to BACKSLASH, starting with note F3. The black keys map to the top
row, '1' to BACKSPACE, starting with F#3. 'r' is middle C. Close the
window or press ESCAPE to quit the program. Key velocity (note
amplitude) varies vertically on the keyboard image, with minimum velocity
at the top of a key and maximum velocity at bottom.
Default Midi output, no device_id given, is to the default output device
for the computer.
"""
# A note to new pygamers:
#
# All the midi module stuff is in this function. It is unnecessary to
# understand how the keyboard display works to appreciate how midi
# messages are sent.
# The keyboard is drawn by a Keyboard instance. This instance maps Midi
# notes to musical keyboard keys. A regions surface maps window position
# to (Midi note, velocity) pairs. A key_mapping dictionary does the same
# for computer keyboard keys. Midi sound is controlled with direct method
# calls to a pygame.midi.Output instance.
#
# Things to consider when using pygame.midi:
#
# 1) Initialize the midi module with a to pygame.midi.init().
# 2) Create a midi.Output instance for the desired output device port.
# 3) Select instruments with set_instrument() method calls.
# 4) Play notes with note_on() and note_off() method calls.
# 5) Call pygame.midi.Quit() when finished. Though the midi module tries
# to ensure that midi is properly shut down, it is best to do it
# explicitly. A try/finally statement is the safest way to do this.
#
# GRAND_PIANO = 0
CHURCH_ORGAN = 19
instrument = CHURCH_ORGAN
# instrument = GRAND_PIANO
start_note = 53 # F3 (white key note), start_note != 0
n_notes = 24 # Two octaves (14 white keys)
bg_color = Color("slategray")
key_mapping = make_key_mapping(
[
pg.K_TAB,
pg.K_1,
pg.K_q,
pg.K_2,
pg.K_w,
pg.K_3,
pg.K_e,
pg.K_r,
pg.K_5,
pg.K_t,
pg.K_6,
pg.K_y,
pg.K_u,
pg.K_8,
pg.K_i,
pg.K_9,
pg.K_o,
pg.K_0,
pg.K_p,
pg.K_LEFTBRACKET,
pg.K_EQUALS,
pg.K_RIGHTBRACKET,
pg.K_BACKSPACE,
pg.K_BACKSLASH,
],
start_note,
)
pg.init()
pygame.midi.init()
_print_device_info()
if device_id is None:
port = pygame.midi.get_default_output_id()
else:
port = device_id
print("using output_id :%s:" % port)
midi_out = pygame.midi.Output(port, 0)
try:
midi_out.set_instrument(instrument)
keyboard = Keyboard(start_note, n_notes)
screen = pg.display.set_mode(keyboard.rect.size)
screen.fill(bg_color)
pg.display.flip()
background = pg.Surface(screen.get_size())
background.fill(bg_color)
dirty_rects = []
keyboard.draw(screen, background, dirty_rects)
pg.display.update(dirty_rects)
regions = pg.Surface(screen.get_size()) # initial color (0,0,0)
keyboard.map_regions(regions)
pg.event.set_blocked(pg.MOUSEMOTION)
mouse_note = 0
on_notes = set()
while 1:
e = pg.event.wait()
if e.type == pg.MOUSEBUTTONDOWN:
mouse_note, velocity, __, __ = regions.get_at(e.pos)
if mouse_note and mouse_note not in on_notes:
keyboard.key_down(mouse_note)
midi_out.note_on(mouse_note, velocity)
on_notes.add(mouse_note)
else:
mouse_note = 0
elif e.type == pg.MOUSEBUTTONUP:
if mouse_note:
midi_out.note_off(mouse_note)
keyboard.key_up(mouse_note)
on_notes.remove(mouse_note)
mouse_note = 0
elif e.type == pg.QUIT:
break
elif e.type == pg.KEYDOWN:
if e.key == pg.K_ESCAPE:
break
try:
note, velocity = key_mapping[e.key]
except KeyError:
pass
else:
if note not in on_notes:
keyboard.key_down(note)
midi_out.note_on(note, velocity)
on_notes.add(note)
elif e.type == pg.KEYUP:
try:
note, __ = key_mapping[e.key]
except KeyError:
pass
else:
if note in on_notes and note != mouse_note:
keyboard.key_up(note)
midi_out.note_off(note, 0)
on_notes.remove(note)
dirty_rects = []
keyboard.draw(screen, background, dirty_rects)
pg.display.update(dirty_rects)
finally:
del midi_out
pygame.midi.quit()
def make_key_mapping(key_list, start_note):
"""Return a dictionary of (note, velocity) by computer keyboard key code"""
mapping = {}
for i in range(len(key_list)):
mapping[key_list[i]] = (start_note + i, 127)
return mapping
class NullKey(object):
"""A dummy key that ignores events passed to it by other keys
A NullKey instance is the left key instance used by default
for the left most keyboard key.
"""
def _right_white_down(self):
pass
def _right_white_up(self):
pass
def _right_black_down(self):
pass
def _right_black_up(self):
pass
null_key = NullKey()
def key_class(updates, image_strip, image_rects, is_white_key=True):
"""Return a keyboard key widget class
Arguments:
updates - a set into which a key instance adds itself if it needs
redrawing.
image_strip - The surface containing the images of all key states.
image_rects - A list of Rects giving the regions within image_strip that
are relevant to this key class.
is_white_key (default True) - Set false if this is a black key.
This function automates the creation of a key widget class for the
three basic key types. A key has two basic states, up or down (
depressed). Corresponding up and down images are drawn for each
of these two states. But to give the illusion of depth, a key
may have shadows cast upon it by the adjacent keys to its right.
These shadows change depending on the up/down state of the key and
its neighbors. So a key may support multiple images and states
depending on the shadows. A key type is determined by the length
of image_rects and the value of is_white.
"""
# Naming convention: Variables used by the Key class as part of a
# closure start with 'c_'.
# State logic and shadows:
#
# A key may cast a shadow upon the key to its left. A black key casts a
# shadow on an adjacent white key. The shadow changes depending of whether
# the black or white key is depressed. A white key casts a shadow on the
# white key to its left if it is up and the left key is down. Therefore
# a keys state, and image it will draw, is determined entirely by its
# itself and the key immediately adjacent to it on the right. A white key
# is always assumed to have an adjacent white key.
#
# There can be up to eight key states, representing all permutations
# of the three fundamental states of self up/down, adjacent white
# right up/down, adjacent black up/down.
#
down_state_none = 0
down_state_self = 1
down_state_white = down_state_self << 1
down_state_self_white = down_state_self | down_state_white
down_state_black = down_state_white << 1
down_state_self_black = down_state_self | down_state_black
down_state_white_black = down_state_white | down_state_black
down_state_all = down_state_self | down_state_white_black
# Some values used in the class.
#
c_down_state_initial = down_state_none
c_down_state_rect_initial = image_rects[0]
c_updates = updates
c_image_strip = image_strip
c_width, c_height = image_rects[0].size
# A key propagates its up/down state change to the adjacent white key on
# the left by calling the adjacent key's _right_black_down or
# _right_white_down method.
#
if is_white_key:
key_color = "white"
else:
key_color = "black"
c_notify_down_method = "_right_%s_down" % key_color
c_notify_up_method = "_right_%s_up" % key_color
# Images:
#
# A black key only needs two images, for the up and down states. Its
# appearance is unaffected by the adjacent keys to its right, which cast no
# shadows upon it.
#
# A white key with a no adjacent black to its right only needs three
# images, for self up, self down, and both self and adjacent white down.
#
# A white key with both a black and white key to its right needs six
# images: self up, self up and adjacent black down, self down, self and
# adjacent white down, self and adjacent black down, and all three down.
#
# Each 'c_event' dictionary maps the current key state to a new key state,
# along with corresponding image, for the related event. If no redrawing
# is required for the state change then the image rect is simply None.
#
c_event_down = {down_state_none: (down_state_self, image_rects[1])}
c_event_up = {down_state_self: (down_state_none, image_rects[0])}
c_event_right_white_down = {
down_state_none: (down_state_none, None),
down_state_self: (down_state_self, None),
}
c_event_right_white_up = c_event_right_white_down.copy()
c_event_right_black_down = c_event_right_white_down.copy()
c_event_right_black_up = c_event_right_white_down.copy()
if len(image_rects) > 2:
c_event_down[down_state_white] = (down_state_self_white, image_rects[2])
c_event_up[down_state_self_white] = (down_state_white, image_rects[0])
c_event_right_white_down[down_state_none] = (down_state_white, None)
c_event_right_white_down[down_state_self] = (
down_state_self_white,
image_rects[2],
)
c_event_right_white_up[down_state_white] = (down_state_none, None)
c_event_right_white_up[down_state_self_white] = (
down_state_self,
image_rects[1],
)
c_event_right_black_down[down_state_white] = (down_state_white, None)
c_event_right_black_down[down_state_self_white] = (down_state_self_white, None)
c_event_right_black_up[down_state_white] = (down_state_white, None)
c_event_right_black_up[down_state_self_white] = (down_state_self_white, None)
if len(image_rects) > 3:
c_event_down[down_state_black] = (down_state_self_black, image_rects[4])
c_event_down[down_state_white_black] = (down_state_all, image_rects[5])
c_event_up[down_state_self_black] = (down_state_black, image_rects[3])
c_event_up[down_state_all] = (down_state_white_black, image_rects[3])
c_event_right_white_down[down_state_black] = (down_state_white_black, None)
c_event_right_white_down[down_state_self_black] = (
down_state_all,
image_rects[5],
)
c_event_right_white_up[down_state_white_black] = (down_state_black, None)
c_event_right_white_up[down_state_all] = (down_state_self_black, image_rects[4])
c_event_right_black_down[down_state_none] = (down_state_black, image_rects[3])
c_event_right_black_down[down_state_self] = (
down_state_self_black,
image_rects[4],
)
c_event_right_black_down[down_state_white] = (
down_state_white_black,
image_rects[3],
)
c_event_right_black_down[down_state_self_white] = (
down_state_all,
image_rects[5],
)
c_event_right_black_up[down_state_black] = (down_state_none, image_rects[0])
c_event_right_black_up[down_state_self_black] = (
down_state_self,
image_rects[1],
)
c_event_right_black_up[down_state_white_black] = (
down_state_white,
image_rects[0],
)
c_event_right_black_up[down_state_all] = (down_state_self_white, image_rects[2])
class Key(object):
"""A key widget, maintains key state and draws the key's image
Constructor arguments:
ident - A unique key identifier. Any immutable type suitable as a key.
posn - The location of the key on the display surface.
key_left - Optional, the adjacent white key to the left. Changes in
up and down state are propagated to that key.
A key has an associated position and state. Related to state is the
image drawn. State changes are managed with method calls, one method
per event type. The up and down event methods are public. Other
internal methods are for passing on state changes to the key_left
key instance.
"""
is_white = is_white_key
def __init__(self, ident, posn, key_left=None):
"""Return a new Key instance
The initial state is up, with all adjacent keys to the right also
up.
"""
if key_left is None:
key_left = null_key
rect = pg.Rect(posn[0], posn[1], c_width, c_height)
self.rect = rect
self._state = c_down_state_initial
self._source_rect = c_down_state_rect_initial
self._ident = ident
self._hash = hash(ident)
self._notify_down = getattr(key_left, c_notify_down_method)
self._notify_up = getattr(key_left, c_notify_up_method)
self._key_left = key_left
self._background_rect = pg.Rect(rect.left, rect.bottom - 10, c_width, 10)
c_updates.add(self)
def down(self):
"""Signal that this key has been depressed (is down)"""
self._state, source_rect = c_event_down[self._state]
if source_rect is not None:
self._source_rect = source_rect
c_updates.add(self)
self._notify_down()
def up(self):
"""Signal that this key has been released (is up)"""
self._state, source_rect = c_event_up[self._state]
if source_rect is not None:
self._source_rect = source_rect
c_updates.add(self)
self._notify_up()
def _right_white_down(self):
"""Signal that the adjacent white key has been depressed
This method is for internal propagation of events between
key instances.
"""
self._state, source_rect = c_event_right_white_down[self._state]
if source_rect is not None:
self._source_rect = source_rect
c_updates.add(self)
def _right_white_up(self):
"""Signal that the adjacent white key has been released
This method is for internal propagation of events between
key instances.
"""
self._state, source_rect = c_event_right_white_up[self._state]
if source_rect is not None:
self._source_rect = source_rect
c_updates.add(self)
def _right_black_down(self):
"""Signal that the adjacent black key has been depressed
This method is for internal propagation of events between
key instances.
"""
self._state, source_rect = c_event_right_black_down[self._state]
if source_rect is not None:
self._source_rect = source_rect
c_updates.add(self)
def _right_black_up(self):
"""Signal that the adjacent black key has been released
This method is for internal propagation of events between
key instances.
"""
self._state, source_rect = c_event_right_black_up[self._state]
if source_rect is not None:
self._source_rect = source_rect
c_updates.add(self)
def __eq__(self, other):
"""True if same identifiers"""
return self._ident == other._ident
def __hash__(self):
"""Return the immutable hash value"""
return self._hash
def __str__(self):
"""Return the key's identifier and position as a string"""
return "<Key %s at (%d, %d)>" % (self._ident, self.rect.top, self.rect.left)
def draw(self, surf, background, dirty_rects):
"""Redraw the key on the surface surf
The background is redrawn. The altered region is added to the
dirty_rects list.
"""
surf.blit(background, self._background_rect, self._background_rect)
surf.blit(c_image_strip, self.rect, self._source_rect)
dirty_rects.append(self.rect)
return Key
def key_images():
"""Return a keyboard keys image strip and a mapping of image locations
The return tuple is a surface and a dictionary of rects mapped to key
type.
This function encapsulates the constants relevant to the keyboard image
file. There are five key types. One is the black key. The other four
white keys are determined by the proximity of the black keys. The plain
white key has no black key adjacent to it. A white-left and white-right
key has a black key to the left or right of it respectively. A white-center
key has a black key on both sides. A key may have up to six related
images depending on the state of adjacent keys to its right.
"""
my_dir = os.path.split(os.path.abspath(__file__))[0]
strip_file = os.path.join(my_dir, "data", "midikeys.png")
white_key_width = 42
white_key_height = 160
black_key_width = 22
black_key_height = 94
strip = pg.image.load(strip_file)
names = [
"black none",
"black self",
"white none",
"white self",
"white self-white",
"white-left none",
"white-left self",
"white-left black",
"white-left self-black",
"white-left self-white",
"white-left all",
"white-center none",
"white-center self",
"white-center black",
"white-center self-black",
"white-center self-white",
"white-center all",
"white-right none",
"white-right self",
"white-right self-white",
]
rects = {}
for i in range(2):
rects[names[i]] = pg.Rect(
i * white_key_width, 0, black_key_width, black_key_height
)
for i in range(2, len(names)):
rects[names[i]] = pg.Rect(
i * white_key_width, 0, white_key_width, white_key_height
)
return strip, rects
class Keyboard(object):
"""Musical keyboard widget
Constructor arguments:
start_note: midi note value of the starting note on the keyboard.
n_notes: number of notes (keys) on the keyboard.
A Keyboard instance draws the musical keyboard and maintains the state of
all the keyboard keys. Individual keys can be in a down (depressed) or
up (released) state.
"""
_image_strip, _rects = key_images()
white_key_width, white_key_height = _rects["white none"].size
black_key_width, black_key_height = _rects["black none"].size
_updates = set()
# There are five key classes, representing key shape:
# black key (BlackKey), plain white key (WhiteKey), white key to the left
# of a black key (WhiteKeyLeft), white key between two black keys
# (WhiteKeyCenter), and white key to the right of a black key
# (WhiteKeyRight).
BlackKey = key_class(
_updates, _image_strip, [_rects["black none"], _rects["black self"]], False
)
WhiteKey = key_class(
_updates,
_image_strip,
[_rects["white none"], _rects["white self"], _rects["white self-white"]],
)
WhiteKeyLeft = key_class(
_updates,
_image_strip,
[
_rects["white-left none"],
_rects["white-left self"],
_rects["white-left self-white"],
_rects["white-left black"],
_rects["white-left self-black"],
_rects["white-left all"],
],
)
WhiteKeyCenter = key_class(
_updates,
_image_strip,
[
_rects["white-center none"],
_rects["white-center self"],
_rects["white-center self-white"],
_rects["white-center black"],
_rects["white-center self-black"],
_rects["white-center all"],
],
)
WhiteKeyRight = key_class(
_updates,
_image_strip,
[
_rects["white-right none"],
_rects["white-right self"],
_rects["white-right self-white"],
],
)
def __init__(self, start_note, n_notes):
"""Return a new Keyboard instance with n_note keys"""
self._start_note = start_note
self._end_note = start_note + n_notes - 1
self._add_keys()
def _add_keys(self):
"""Populate the keyboard with key instances
Set the _keys and rect attributes.
"""
# Keys are entered in a list, where index is Midi note. Since there are
# only 128 possible Midi notes the list length is managable. Unassigned
# note positions should never be accessed, so are set None to ensure
# the bug is quickly detected.
#
key_map = [None] * 128
start_note = self._start_note
end_note = self._end_note
black_offset = self.black_key_width // 2
prev_white_key = None
x = y = 0
if is_white_key(start_note):
is_prev_white = True
else:
x += black_offset
is_prev_white = False
for note in range(start_note, end_note + 1):
ident = note # For now notes uniquely identify keyboard keys.
if is_white_key(note):
if is_prev_white:
if note == end_note or is_white_key(note + 1):
key = self.WhiteKey(ident, (x, y), prev_white_key)
else:
key = self.WhiteKeyLeft(ident, (x, y), prev_white_key)
else:
if note == end_note or is_white_key(note + 1):
key = self.WhiteKeyRight(ident, (x, y), prev_white_key)
else:
key = self.WhiteKeyCenter(ident, (x, y), prev_white_key)
is_prev_white = True
x += self.white_key_width
prev_white_key = key
else:
key = self.BlackKey(ident, (x - black_offset, y), prev_white_key)
is_prev_white = False
key_map[note] = key
self._keys = key_map
kb_width = key_map[self._end_note].rect.right
kb_height = self.white_key_height
self.rect = pg.Rect(0, 0, kb_width, kb_height)
def map_regions(self, regions):
"""Draw the key regions onto surface regions.
Regions must have at least 3 byte pixels. Each pixel of the keyboard
rectangle is set to the color (note, velocity, 0). The regions surface
must be at least as large as (0, 0, self.rect.left, self.rect.bottom)
"""
# First draw the white key regions. Then add the overlapping
# black key regions.
#
cutoff = self.black_key_height
black_keys = []
for note in range(self._start_note, self._end_note + 1):
key = self._keys[note]
if key.is_white:
fill_region(regions, note, key.rect, cutoff)
else:
black_keys.append((note, key))
for note, key in black_keys:
fill_region(regions, note, key.rect, cutoff)
def draw(self, surf, background, dirty_rects):
"""Redraw all altered keyboard keys"""
changed_keys = self._updates
while changed_keys:
changed_keys.pop().draw(surf, background, dirty_rects)
def key_down(self, note):
"""Signal a key down event for note"""
self._keys[note].down()
def key_up(self, note):
"""Signal a key up event for note"""
self._keys[note].up()
def fill_region(regions, note, rect, cutoff):
"""Fill the region defined by rect with a (note, velocity, 0) color
The velocity varies from a small value at the top of the region to
127 at the bottom. The vertical region 0 to cutoff is split into
three parts, with velocities 42, 84 and 127. Everything below cutoff
has velocity 127.
"""
x, y, width, height = rect
if cutoff is None:
cutoff = height
delta_height = cutoff // 3
regions.fill((note, 42, 0), (x, y, width, delta_height))
regions.fill((note, 84, 0), (x, y + delta_height, width, delta_height))
regions.fill(
(note, 127, 0), (x, y + 2 * delta_height, width, height - 2 * delta_height)
)
def is_white_key(note):
"""True if note is represented by a white key"""
key_pattern = [
True,
False,
True,
True,
False,
True,
False,
True,
True,
False,
True,
False,
]
return key_pattern[(note - 21) % len(key_pattern)]
def usage():
print("--input [device_id] : Midi message logger")
print("--output [device_id] : Midi piano keyboard")
print("--list : list available midi devices")
def main(mode="output", device_id=None):
"""Run a Midi example
Arguments:
mode - if 'output' run a midi keyboard output example
'input' run a midi event logger input example
'list' list available midi devices
(default 'output')
device_id - midi device number; if None then use the default midi input or
output device for the system
"""
if mode == "input":
input_main(device_id)
elif mode == "output":
output_main(device_id)
elif mode == "list":
print_device_info()
else:
raise ValueError("Unknown mode option '%s'" % mode)
if __name__ == "__main__":
try:
device_id = int(sys.argv[-1])
except ValueError:
device_id = None
if "--input" in sys.argv or "-i" in sys.argv:
input_main(device_id)
elif "--output" in sys.argv or "-o" in sys.argv:
output_main(device_id)
elif "--list" in sys.argv or "-l" in sys.argv:
print_device_info()
else:
usage()
@@ -0,0 +1,71 @@
#!/usr/bin/env python
""" pygame.examples.moveit
This is the full and final example from the Pygame Tutorial,
"How Do I Make It Move". It creates 10 objects and animates
them on the screen.
Note it's a bit scant on error checking, but it's easy to read. :]
Fortunately, this is python, and we needn't wrestle with a pile of
error codes.
"""
import os
import pygame as pg
main_dir = os.path.split(os.path.abspath(__file__))[0]
# our game object class
class GameObject:
def __init__(self, image, height, speed):
self.speed = speed
self.image = image
self.pos = image.get_rect().move(0, height)
def move(self):
self.pos = self.pos.move(self.speed, 0)
if self.pos.right > 600:
self.pos.left = 0
# quick function to load an image
def load_image(name):
path = os.path.join(main_dir, "data", name)
return pg.image.load(path).convert()
# here's the full code
def main():
pg.init()
screen = pg.display.set_mode((640, 480))
player = load_image("player1.gif")
background = load_image("liquid.bmp")
# scale the background image so that it fills the window and
# successfully overwrites the old sprite position.
background = pg.transform.scale2x(background)
background = pg.transform.scale2x(background)
screen.blit(background, (0, 0))
objects = []
for x in range(10):
o = GameObject(player, x * 40, x)
objects.append(o)
while 1:
for event in pg.event.get():
if event.type in (pg.QUIT, pg.KEYDOWN):
return
for o in objects:
screen.blit(background, o.pos, o.pos)
for o in objects:
o.move()
screen.blit(o.image, o.pos)
pg.display.update()
if __name__ == "__main__":
main()
@@ -0,0 +1,249 @@
#!/usr/bin/env python
""" pygame.examples.music_drop_fade
Fade in and play music from a list while observing several events
Adds music files to a playlist whenever played by one of the following methods
Music files passed from the commandline are played
Music files and filenames are played when drag and dropped onto the pygame window
Polls the clipboard and plays music files if it finds one there
Keyboard Controls:
* Press space or enter to pause music playback
* Press up or down to change the music volume
* Press left or right to seek 5 seconds into the track
* Press escape to quit
* Press any other button to skip to the next music file in the list
"""
import pygame as pg
import os, sys
VOLUME_CHANGE_AMOUNT = 0.02 # how fast should up and down arrows change the volume?
def add_file(filename):
"""
This function will check if filename exists and is a music file
If it is the file will be added to a list of music files(even if already there)
Type checking is by the extension of the file, not by its contents
We can only discover if the file is valid when we mixer.music.load() it later
It looks in the file directory and its data subdirectory
"""
if filename.rpartition(".")[2].lower() not in music_file_types:
print("{} not added to file list".format(filename))
print("only these files types are allowed: ", music_file_types)
return False
elif os.path.exists(filename):
music_file_list.append(filename)
elif os.path.exists(os.path.join(main_dir, filename)):
music_file_list.append(os.path.join(main_dir, filename))
elif os.path.exists(os.path.join(data_dir, filename)):
music_file_list.append(os.path.join(data_dir, filename))
else:
print("file not found")
return False
print("{} added to file list".format(filename))
return True
def play_file(filename):
"""
This function will call add_file and play it if successful
The music will fade in during the first 4 seconds
set_endevent is used to post a MUSIC_DONE event when the song finishes
The main loop will call play_next() when the MUSIC_DONE event is received
"""
global starting_pos
if add_file(filename):
try: # we must do this in case the file is not a valid audio file
pg.mixer.music.load(music_file_list[-1])
except pg.error as e:
print(e) # print description such as 'Not an Ogg Vorbis audio stream'
if filename in music_file_list:
music_file_list.remove(filename)
print("{} removed from file list".format(filename))
return
pg.mixer.music.play(fade_ms=4000)
pg.mixer.music.set_volume(volume)
if filename.rpartition(".")[2].lower() in music_can_seek:
print("file supports seeking")
starting_pos = 0
else:
print("file does not support seeking")
starting_pos = -1
pg.mixer.music.set_endevent(MUSIC_DONE)
def play_next():
"""
This function will play the next song in music_file_list
It uses pop(0) to get the next song and then appends it to the end of the list
The song will fade in during the first 4 seconds
"""
global starting_pos
if len(music_file_list) > 1:
nxt = music_file_list.pop(0)
try:
pg.mixer.music.load(nxt)
except pg.error as e:
print(e)
print("{} removed from file list".format(nxt))
music_file_list.append(nxt)
print("starting next song: ", nxt)
else:
nxt = music_file_list[0]
pg.mixer.music.play(fade_ms=4000)
pg.mixer.music.set_volume(volume)
pg.mixer.music.set_endevent(MUSIC_DONE)
if nxt.rpartition(".")[2].lower() in music_can_seek:
starting_pos = 0
else:
starting_pos = -1
def draw_text_line(text, y=0):
"""
Draws a line of text onto the display surface
The text will be centered horizontally at the given y postition
The text's height is added to y and returned to the caller
"""
screen = pg.display.get_surface()
surf = font.render(text, 1, (255, 255, 255))
y += surf.get_height()
x = (screen.get_width() - surf.get_width()) / 2
screen.blit(surf, (x, y))
return y
def change_music_postion(amount):
"""
Changes current playback postition by amount seconds.
This only works with OGG and MP3 files.
music.get_pos() returns how many milliseconds the song has played, not
the current postion in the file. We must track the starting postion
ourselves. music.set_pos() will set the position in seconds.
"""
global starting_pos
if starting_pos >= 0: # will be -1 unless play_file() was OGG or MP3
played_for = pg.mixer.music.get_pos() / 1000.0
old_pos = starting_pos + played_for
starting_pos = old_pos + amount
pg.mixer.music.play(start=starting_pos)
print("jumped from {} to {}".format(old_pos, starting_pos))
MUSIC_DONE = pg.event.custom_type() # event to be set as mixer.music.set_endevent()
main_dir = os.path.split(os.path.abspath(__file__))[0]
data_dir = os.path.join(main_dir, "data")
starting_pos = 0 # needed to fast forward and rewind
volume = 0.75
music_file_list = []
music_file_types = ("mp3", "ogg", "mid", "mod", "it", "xm", "wav")
music_can_seek = ("mp3", "ogg", "mod", "it", "xm")
def main():
global font # this will be used by the draw_text_line function
global volume, starting_pos
running = True
paused = False
# we will be polling for key up and key down events
# users should be able to change the volume by holding the up and down arrows
# the change_volume variable will be set by key down events and cleared by key up events
change_volume = 0
pg.init()
pg.display.set_mode((640, 480))
font = pg.font.SysFont("Arial", 24)
clock = pg.time.Clock()
pg.scrap.init()
pg.SCRAP_TEXT = pg.scrap.get_types()[0] # TODO remove when scrap module is fixed
clipped = pg.scrap.get(pg.SCRAP_TEXT).decode(
"UTF-8") # store the current text from the clipboard TODO remove decode
# add the command line arguments to the music_file_list
for arg in sys.argv[1:]:
add_file(arg)
play_file("house_lo.ogg") # play default music included with pygame
# draw instructions on screen
y = draw_text_line("Drop music files or path names onto this window", 20)
y = draw_text_line("Copy file names into the clipboard", y)
y = draw_text_line("Or feed them from the command line", y)
y = draw_text_line("If it's music it will play!", y)
y = draw_text_line("SPACE to pause or UP/DOWN to change volume", y)
y = draw_text_line("LEFT and RIGHT will skip around the track", y)
draw_text_line("Other keys will start the next track", y)
"""
This is the main loop
It will respond to drag and drop, clipboard changes, and key presses
"""
while running:
for ev in pg.event.get():
if ev.type == pg.QUIT:
running = False
elif ev.type == pg.DROPTEXT:
play_file(ev.text)
elif ev.type == pg.DROPFILE:
play_file(ev.file)
elif ev.type == MUSIC_DONE:
play_next()
elif ev.type == pg.KEYDOWN:
if ev.key == pg.K_ESCAPE:
running = False # exit loop
elif ev.key in (pg.K_SPACE, pg.K_RETURN):
if paused:
pg.mixer.music.unpause()
paused = False
else:
pg.mixer.music.pause()
paused = True
elif ev.key == pg.K_UP:
change_volume = VOLUME_CHANGE_AMOUNT
elif ev.key == pg.K_DOWN:
change_volume = -VOLUME_CHANGE_AMOUNT
elif ev.key == pg.K_RIGHT:
change_music_postion(+5)
elif ev.key == pg.K_LEFT:
change_music_postion(-5)
else:
play_next()
elif ev.type == pg.KEYUP:
if ev.key in (pg.K_UP, pg.K_DOWN):
change_volume = 0
# is the user holding up or down?
if change_volume:
volume += change_volume
volume = min(max(0, volume), 1) # volume should be between 0 and 1
pg.mixer.music.set_volume(volume)
print("volume:", volume)
# TODO remove decode when SDL2 scrap is fixed
new_text = pg.scrap.get(pg.SCRAP_TEXT).decode("UTF-8")
if new_text != clipped: # has the clipboard changed?
clipped = new_text
play_file(clipped) # try to play the file if it has
pg.display.flip()
clock.tick(9) # keep CPU use down by updating screen less often
pg.quit()
if __name__ == "__main__":
main()
@@ -0,0 +1,66 @@
#!/usr/bin/env python
""" pygame.examples.overlay
The overlay module is deprecated now.
It is an olden days way to draw video quickly.
"""
import sys
import pygame as pg
from pygame.compat import xrange_
SR = (800, 600)
ovl = None
########################################################################
# Simple video player
def vPlayer(fName):
global ovl
f = open(fName, "rb")
fmt = f.readline().strip()
res = f.readline().strip()
unused_col = f.readline().strip()
if fmt != "P5":
print("Unknown format( len %d ). Exiting..." % len(fmt))
return
w, h = [int(x) for x in res.split(" ")]
h = (h * 2) / 3
# Read into strings
y = f.read(w * h)
u = []
v = []
for _ in xrange_(0, h / 2):
u.append(f.read(w / 2))
v.append(f.read(w / 2))
u = "".join(u)
v = "".join(v)
# Open overlay with the resolution specified
ovl = pg.Overlay(pg.YV12_OVERLAY, (w, h))
ovl.set_location(0, 0, w, h)
ovl.display((y, u, v))
while 1:
pg.time.wait(10)
for ev in pg.event.get():
if ev.type in (pg.KEYDOWN, pg.QUIT):
return
def main(fname):
"""play video file fname"""
pg.init()
try:
pg.display.set_mode(SR)
vPlayer(fname)
finally:
pg.quit()
# Test all modules
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: play_file <file_pattern>")
else:
main(sys.argv[1])
@@ -0,0 +1,140 @@
#!/usr/bin/env python
""" pygame.examples.pixelarray
PixelArray does array processing of pixels.
Sort of like another array processor called 'numpy' - But for pixels.
Flip it,
stripe it,
rotate it.
Controls
--------
To see different effects - press a key or click a mouse.
"""
import os
import pygame as pg
from pygame.compat import xrange_
main_dir = os.path.split(os.path.abspath(__file__))[0]
data_dir = os.path.join(main_dir, "data")
def show(image):
screen = pg.display.get_surface()
screen.fill((255, 255, 255))
screen.blit(image, (0, 0))
pg.display.flip()
while 1:
event = pg.event.wait()
if event.type == pg.QUIT:
raise SystemExit
if event.type in [pg.MOUSEBUTTONDOWN, pg.KEYDOWN]:
break
def main():
pg.init()
pg.display.set_mode((255, 255))
surface = pg.Surface((255, 255))
pg.display.flip()
# Create the PixelArray.
ar = pg.PixelArray(surface)
# Do some easy gradient effect.
for y in xrange_(255):
r, g, b = y, y, y
ar[:, y] = (r, g, b)
del ar
show(surface)
# We have made some gradient effect, now flip it.
ar = pg.PixelArray(surface)
ar[:] = ar[:, ::-1]
del ar
show(surface)
# Every second column will be made blue
ar = pg.PixelArray(surface)
ar[::2] = (0, 0, 255)
del ar
show(surface)
# Every second row will be made green
ar = pg.PixelArray(surface)
ar[:, ::2] = (0, 255, 0)
del ar
show(surface)
# Manipulate the image. Flip it around the y axis.
surface = pg.image.load(os.path.join(data_dir, "arraydemo.bmp"))
ar = pg.PixelArray(surface)
ar[:] = ar[:, ::-1]
del ar
show(surface)
# Flip the image around the x axis.
ar = pg.PixelArray(surface)
ar[:] = ar[::-1, :]
del ar
show(surface)
# Every second column will be made white.
ar = pg.PixelArray(surface)
ar[::2] = (255, 255, 255)
del ar
show(surface)
# Flip the image around both axes, restoring it's original layout.
ar = pg.PixelArray(surface)
ar[:] = ar[::-1, ::-1]
del ar
show(surface)
# Rotate 90 degrees clockwise.
w, h = surface.get_size()
surface2 = pg.Surface((h, w), surface.get_flags(), surface)
ar = pg.PixelArray(surface)
ar2 = pg.PixelArray(surface2)
ar2[...] = ar.transpose()[::-1, :]
del ar, ar2
show(surface2)
# Scale it by throwing each second pixel away.
surface = pg.image.load(os.path.join(data_dir, "arraydemo.bmp"))
ar = pg.PixelArray(surface)
sf2 = ar[::2, ::2].make_surface()
del ar
show(sf2)
# Replace anything looking like the blue color from the text.
ar = pg.PixelArray(surface)
ar.replace((60, 60, 255), (0, 255, 0), 0.06)
del ar
show(surface)
# Extract anything which might be somewhat black.
surface = pg.image.load(os.path.join(data_dir, "arraydemo.bmp"))
ar = pg.PixelArray(surface)
ar2 = ar.extract((0, 0, 0), 0.07)
sf2 = ar2.surface
del ar, ar2
show(sf2)
# Compare two images.
surface = pg.image.load(os.path.join(data_dir, "alien1.gif"))
surface2 = pg.image.load(os.path.join(data_dir, "alien2.gif"))
ar1 = pg.PixelArray(surface)
ar2 = pg.PixelArray(surface2)
ar3 = ar1.compare(ar2, 0.07)
sf3 = ar3.surface
del ar1, ar2, ar3
show(sf3)
if __name__ == "__main__":
main()
@@ -0,0 +1,152 @@
#!/usr/bin/env python
""" pygame.examples.playmus
A simple music player.
Use pygame.mixer.music to play an audio file.
A window is created to handle keyboard events for playback commands.
Keyboard Controls
-----------------
space - play/pause toggle
r - rewind
f - fade out
q - stop
"""
import sys
import pygame as pg
import pygame.freetype
class Window(object):
"""The application's Pygame window
A Window instance manages the creation of and drawing to a
window. It is a singleton class. Only one instance can exist.
"""
instance = None
def __new__(cls, *args, **kwds):
"""Return an open Pygame window"""
if Window.instance is not None:
return Window.instance
self = object.__new__(cls)
pg.display.init()
self.screen = pg.display.set_mode((600, 400))
Window.instance = self
return self
def __init__(self, title):
pg.display.set_caption(title)
self.screen.fill(pg.Color("white"))
pg.display.flip()
pygame.freetype.init()
self.font = pygame.freetype.Font(None, 20)
self.font.origin = True
self.ascender = int(self.font.get_sized_ascender() * 1.5)
self.descender = int(self.font.get_sized_descender() * 1.5)
self.line_height = self.ascender - self.descender
self.write_lines(
"'q', ESCAPE or close this window to quit\n"
"SPACE to play/pause\n"
"'r' to rewind\n"
"'f' to faid out over 5 seconds\n",
0,
)
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.close()
return False
def close(self):
pg.display.quit()
Window.instance = None
def write_lines(self, text, line=0):
w, h = self.screen.get_size()
line_height = self.line_height
nlines = h // line_height
if line < 0:
line = nlines + line
for i, text_line in enumerate(text.split("\n"), line):
y = i * line_height + self.ascender
# Clear the line first.
self.screen.fill(pg.Color("white"), (0, i * line_height, w, line_height))
# Write new text.
self.font.render_to(self.screen, (15, y), text_line, pg.Color("blue"))
pg.display.flip()
def show_usage_message():
print("Usage: python playmus.py <file>")
print(" python -m pygame.examples.playmus <file>")
def main(file_path):
"""Play an audio file with pg.mixer.music"""
with Window(file_path) as win:
win.write_lines("Loading ...", -1)
pg.mixer.init(frequency=44100)
try:
paused = False
pg.mixer.music.load(file_path)
# Make sure the event loop ticks over at least every 0.5 seconds.
pg.time.set_timer(pg.USEREVENT, 500)
pg.mixer.music.play()
win.write_lines("Playing ...\n", -1)
while pg.mixer.music.get_busy():
e = pg.event.wait()
if e.type == pg.KEYDOWN:
key = e.key
if key == pg.K_SPACE:
if paused:
pg.mixer.music.unpause()
paused = False
win.write_lines("Playing ...\n", -1)
else:
pg.mixer.music.pause()
paused = True
win.write_lines("Paused ...\n", -1)
elif key == pg.K_r:
pg.mixer.music.rewind()
if paused:
win.write_lines("Rewound.", -1)
elif key == pg.K_f:
win.write_lines("Fading out ...\n", -1)
pg.mixer.music.fadeout(5000)
# when finished get_busy() will return 0.
elif key in [pg.K_q, pg.K_ESCAPE]:
pg.mixer.music.stop()
# get_busy() will now return 0.
elif e.type == pg.QUIT:
pg.mixer.music.stop()
# get_busy() will now return 0.
pg.time.set_timer(pg.USEREVENT, 0)
finally:
pg.mixer.quit()
if __name__ == "__main__":
# Check the only command line argument, a file path
if len(sys.argv) != 2:
show_usage_message()
else:
main(sys.argv[1])
@@ -0,0 +1,88 @@
#!/usr/bin/env python
""" pygame.examples.prevent_display_stretching
Prevent display stretching on Windows.
On some computers, the display environment can be configured to stretch
all windows so that they will not appear too small on the screen for
the user. This configuration is especially common on high-DPI displays.
pygame graphics appear distorted when automatically stretched by the
display environment. This script demonstrates a technique for preventing
this stretching and distortion.
Limitations:
This script makes an API call that is only available on Windows (versions
Vista and newer).
"""
# Ensure that the computer is running Windows Vista or newer
import os
import sys
if os.name != "nt" or sys.getwindowsversion()[0] < 6:
raise NotImplementedError("this script requires Windows Vista or newer")
import pygame as pg
import ctypes
# Determine whether or not the user would like to prevent stretching
if os.path.basename(sys.executable) == "pythonw.exe":
selection = "y"
else:
from pygame.compat import raw_input_
selection = None
while selection not in ("y", "n"):
selection = raw_input_("Prevent stretching? (y/n): ").strip().lower()
if selection == "y":
msg = "Stretching is prevented."
else:
msg = "Stretching is not prevented."
# Prevent stretching
if selection == "y":
user32 = ctypes.windll.user32
user32.SetProcessDPIAware()
# Show screen
pg.display.init()
RESOLUTION = (350, 350)
screen = pg.display.set_mode(RESOLUTION)
# Render message onto a surface
pg.font.init()
font = pg.font.Font(None, 36)
msg_surf = font.render(msg, 1, pg.Color("green"))
res_surf = font.render("Intended resolution: %ix%i" % RESOLUTION, 1, pg.Color("green"))
# Control loop
running = True
clock = pg.time.Clock()
counter = 0
while running:
for event in pg.event.get():
if event.type == pg.QUIT:
running = False
screen.fill(pg.Color("black"))
# Draw lines which will be blurry if the window is stretched
# or clear if the window is not stretched.
pg.draw.line(screen, pg.Color("white"), (0, counter), (RESOLUTION[0] - 1, counter))
pg.draw.line(screen, pg.Color("white"), (counter, 0), (counter, RESOLUTION[1] - 1))
# Blit message onto screen surface
msg_blit_rect = screen.blit(msg_surf, (0, 0))
screen.blit(res_surf, (0, msg_blit_rect.bottom))
clock.tick(10)
pg.display.flip()
counter += 1
if counter == RESOLUTION[0]:
counter = 0
@@ -0,0 +1,157 @@
#!/usr/bin/env python
""" pygame.examples.scaletest
Shows an interactive image scaler.
"""
import sys
import time
import pygame as pg
def main(imagefile, convert_alpha=False, run_speed_test=False):
"""show an interactive image scaler
Args:
imagefile - name of source image (required)
convert_alpha - use convert_alpha() on the surf (default False)
run_speed_test - (default False)
"""
# initialize display
pg.display.init()
# load background image
background = pg.image.load(imagefile)
if run_speed_test:
if convert_alpha:
# convert_alpha() requires the display mode to be set
pg.display.set_mode((1, 1))
background = background.convert_alpha()
SpeedTest(background)
return
# start fullscreen mode
screen = pg.display.set_mode((1024, 768), pg.FULLSCREEN)
if convert_alpha:
background = background.convert_alpha()
# turn off the mouse pointer
pg.mouse.set_visible(0)
# main loop
bRunning = True
bUp = False
bDown = False
bLeft = False
bRight = False
cursize = [background.get_width(), background.get_height()]
while bRunning:
image = pg.transform.smoothscale(background, cursize)
imgpos = image.get_rect(centerx=512, centery=384)
screen.fill((255, 255, 255))
screen.blit(image, imgpos)
pg.display.flip()
for event in pg.event.get():
if event.type == pg.QUIT or (
event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE
):
bRunning = False
if event.type == pg.KEYDOWN:
if event.key == pg.K_UP:
bUp = True
if event.key == pg.K_DOWN:
bDown = True
if event.key == pg.K_LEFT:
bLeft = True
if event.key == pg.K_RIGHT:
bRight = True
if event.type == pg.KEYUP:
if event.key == pg.K_UP:
bUp = False
if event.key == pg.K_DOWN:
bDown = False
if event.key == pg.K_LEFT:
bLeft = False
if event.key == pg.K_RIGHT:
bRight = False
if bUp:
cursize[1] -= 2
if cursize[1] < 1:
cursize[1] = 1
if bDown:
cursize[1] += 2
if bLeft:
cursize[0] -= 2
if cursize[0] < 1:
cursize[0] = 1
if bRight:
cursize[0] += 2
def SpeedTest(image):
print("\nImage Scaling Speed Test - Image Size %s\n" % str(image.get_size()))
imgsize = [image.get_width(), image.get_height()]
duration = 0.0
for i in range(128):
shrinkx = (imgsize[0] * i) // 128
shrinky = (imgsize[1] * i) // 128
start = time.time()
tempimg = pg.transform.smoothscale(image, (shrinkx, shrinky))
duration += time.time() - start
del tempimg
print(
"Average transform.smoothscale shrink time: %.4f ms." % (duration / 128 * 1000)
)
duration = 0.0
for i in range(128):
expandx = (imgsize[0] * (i + 129)) // 128
expandy = (imgsize[1] * (i + 129)) // 128
start = time.time()
tempimg = pg.transform.smoothscale(image, (expandx, expandy))
duration += time.time() - start
del tempimg
print(
"Average transform.smoothscale expand time: %.4f ms." % (duration / 128 * 1000)
)
duration = 0.0
for i in range(128):
shrinkx = (imgsize[0] * i) // 128
shrinky = (imgsize[1] * i) // 128
start = time.time()
tempimg = pg.transform.scale(image, (shrinkx, shrinky))
duration += time.time() - start
del tempimg
print("Average transform.scale shrink time: %.4f ms." % (duration / 128 * 1000))
duration = 0.0
for i in range(128):
expandx = (imgsize[0] * (i + 129)) // 128
expandy = (imgsize[1] * (i + 129)) // 128
start = time.time()
tempimg = pg.transform.scale(image, (expandx, expandy))
duration += time.time() - start
del tempimg
print("Average transform.scale expand time: %.4f ms." % (duration / 128 * 1000))
if __name__ == "__main__":
# check input parameters
if len(sys.argv) < 2:
print("\nUsage: %s imagefile [-t] [-convert_alpha]" % sys.argv[0])
print(" imagefile image filename (required)")
print(" -t run speed test")
print(" -convert_alpha use convert_alpha() on the image's " "surface\n")
else:
main(
sys.argv[1],
convert_alpha="-convert_alpha" in sys.argv,
run_speed_test="-t" in sys.argv,
)
@@ -0,0 +1,94 @@
#!/usr/bin/env python
""" pygame.examples.scrap_clipboard
Demonstrates the clipboard capabilities of pygame.
Copy/paste!
Keyboard Controls
-----------------
g - get and print types in clipboard. If, image blit to screen.
p - place some text into clipboard
a - print types available in the clipboard
i - put image into the clipboard
"""
import os
import pygame as pg
import pygame.scrap as scrap
from pygame.compat import as_bytes
BytesIO = pygame.compat.get_BytesIO()
def usage():
print("Press the 'g' key to get all of the current clipboard data")
print("Press the 'p' key to put a string into the clipboard")
print("Press the 'a' key to get a list of the currently available types")
print("Press the 'i' key to put an image into the clipboard")
main_dir = os.path.split(os.path.abspath(__file__))[0]
pg.init()
screen = pg.display.set_mode((200, 200))
c = pg.time.Clock()
going = True
# Initialize the scrap module and use the clipboard mode.
scrap.init()
scrap.set_mode(SCRAP_CLIPBOARD)
usage()
while going:
for e in pg.event.get():
if e.type == QUIT or (e.type == pg.KEYDOWN and e.key == pg.K_ESCAPE):
going = False
elif e.type == KEYDOWN and e.key == pg.K_g:
# This means to look for data.
print("Getting the different clipboard data..")
for t in scrap.get_types():
r = scrap.get(t)
if r and len(r) > 500:
print("Type %s : (large %i byte buffer)" % (t, len(r)))
elif r is None:
print("Type %s : None" % (t,))
else:
print("Type %s : '%s'" % (t, r.decode("ascii", "ignore")))
if "image" in t:
namehint = t.split("/")[1]
if namehint in ["bmp", "png", "jpg"]:
f = BytesIO(r)
loaded_surf = pg.image.load(f, "." + namehint)
screen.blit(loaded_surf, (0, 0))
elif e.type == KEYDOWN and e.key == pg.K_p:
# Place some text into the selection.
print("Placing clipboard text.")
scrap.put(SCRAP_TEXT, as_bytes("Hello. This is a message from scrap."))
elif e.type == KEYDOWN and e.key == pg.K_a:
# Get all available types.
print("Getting the available types from the clipboard.")
types = scrap.get_types()
print(types)
if len(types) > 0:
print("Contains %s: %s" % (types[0], scrap.contains(types[0])))
print("Contains _INVALID_: ", scrap.contains("_INVALID_"))
elif e.type == KEYDOWN and e.key == pg.K_i:
print("Putting image into the clipboard.")
scrap.set_mode(SCRAP_CLIPBOARD)
fp = open(os.path.join(main_dir, "data", "liquid.bmp"), "rb")
buf = fp.read()
scrap.put("image/bmp", buf)
fp.close()
elif e.type in (pg.KEYDOWN, pg.MOUSEBUTTONDOWN):
usage()
pg.display.flip()
c.tick(40)
@@ -0,0 +1,191 @@
#!/usr/bin/env python
""" pygame.examples.scroll
An zoomed image viewer that demonstrates Surface.scroll
This example shows a scrollable image that has a zoom factor of eight.
It uses the Surface.scroll function to shift the image on the display
surface. A clip rectangle protects a margin area. If called as a function,
the example accepts an optional image file path. If run as a program
it takes an optional file path command line argument. If no file
is provided a default image file is used.
When running click on a black triangle to move one pixel in the direction
the triangle points. Or use the arrow keys. Close the window or press ESC
to quit.
"""
import sys
import os
import pygame as pg
from pygame.transform import scale
main_dir = os.path.dirname(os.path.abspath(__file__))
DIR_UP = 1
DIR_DOWN = 2
DIR_LEFT = 3
DIR_RIGHT = 4
zoom_factor = 8
def draw_arrow(surf, color, posn, direction):
x, y = posn
if direction == DIR_UP:
pointlist = ((x - 29, y + 30), (x + 30, y + 30), (x + 1, y - 29), (x, y - 29))
elif direction == DIR_DOWN:
pointlist = ((x - 29, y - 29), (x + 30, y - 29), (x + 1, y + 30), (x, y + 30))
elif direction == DIR_LEFT:
pointlist = ((x + 30, y - 29), (x + 30, y + 30), (x - 29, y + 1), (x - 29, y))
else:
pointlist = ((x - 29, y - 29), (x - 29, y + 30), (x + 30, y + 1), (x + 30, y))
pg.draw.polygon(surf, color, pointlist)
def add_arrow_button(screen, regions, posn, direction):
draw_arrow(screen, pg.Color("black"), posn, direction)
draw_arrow(regions, (direction, 0, 0), posn, direction)
def scroll_view(screen, image, direction, view_rect):
src_rect = None
zoom_view_rect = screen.get_clip()
image_w, image_h = image.get_size()
if direction == DIR_UP:
if view_rect.top > 0:
screen.scroll(dy=zoom_factor)
view_rect.move_ip(0, -1)
src_rect = view_rect.copy()
src_rect.h = 1
dst_rect = zoom_view_rect.copy()
dst_rect.h = zoom_factor
elif direction == DIR_DOWN:
if view_rect.bottom < image_h:
screen.scroll(dy=-zoom_factor)
view_rect.move_ip(0, 1)
src_rect = view_rect.copy()
src_rect.h = 1
src_rect.bottom = view_rect.bottom
dst_rect = zoom_view_rect.copy()
dst_rect.h = zoom_factor
dst_rect.bottom = zoom_view_rect.bottom
elif direction == DIR_LEFT:
if view_rect.left > 0:
screen.scroll(dx=zoom_factor)
view_rect.move_ip(-1, 0)
src_rect = view_rect.copy()
src_rect.w = 1
dst_rect = zoom_view_rect.copy()
dst_rect.w = zoom_factor
elif direction == DIR_RIGHT:
if view_rect.right < image_w:
screen.scroll(dx=-zoom_factor)
view_rect.move_ip(1, 0)
src_rect = view_rect.copy()
src_rect.w = 1
src_rect.right = view_rect.right
dst_rect = zoom_view_rect.copy()
dst_rect.w = zoom_factor
dst_rect.right = zoom_view_rect.right
if src_rect is not None:
scale(image.subsurface(src_rect), dst_rect.size, screen.subsurface(dst_rect))
pg.display.update(zoom_view_rect)
def main(image_file=None):
if image_file is None:
image_file = os.path.join(main_dir, "data", "arraydemo.bmp")
margin = 80
view_size = (30, 20)
zoom_view_size = (view_size[0] * zoom_factor, view_size[1] * zoom_factor)
win_size = (zoom_view_size[0] + 2 * margin, zoom_view_size[1] + 2 * margin)
background_color = pg.Color("beige")
pg.init()
# set up key repeating so we can hold down the key to scroll.
old_k_delay, old_k_interval = pg.key.get_repeat()
pg.key.set_repeat(500, 30)
try:
screen = pg.display.set_mode(win_size)
screen.fill(background_color)
pg.display.flip()
image = pg.image.load(image_file).convert()
image_w, image_h = image.get_size()
if image_w < view_size[0] or image_h < view_size[1]:
print("The source image is too small for this example.")
print("A %i by %i or larger image is required." % zoom_view_size)
return
regions = pg.Surface(win_size, 0, 24)
add_arrow_button(screen, regions, (40, win_size[1] // 2), DIR_LEFT)
add_arrow_button(
screen, regions, (win_size[0] - 40, win_size[1] // 2), DIR_RIGHT
)
add_arrow_button(screen, regions, (win_size[0] // 2, 40), DIR_UP)
add_arrow_button(
screen, regions, (win_size[0] // 2, win_size[1] - 40), DIR_DOWN
)
pg.display.flip()
screen.set_clip((margin, margin, zoom_view_size[0], zoom_view_size[1]))
view_rect = pg.Rect(0, 0, view_size[0], view_size[1])
scale(
image.subsurface(view_rect),
zoom_view_size,
screen.subsurface(screen.get_clip()),
)
pg.display.flip()
# the direction we will scroll in.
direction = None
clock = pg.time.Clock()
clock.tick()
going = True
while going:
# wait for events before doing anything.
# events = [pg.event.wait()] + pg.event.get()
events = pg.event.get()
for e in events:
if e.type == pg.KEYDOWN:
if e.key == pg.K_ESCAPE:
going = False
elif e.key == pg.K_DOWN:
scroll_view(screen, image, DIR_DOWN, view_rect)
elif e.key == pg.K_UP:
scroll_view(screen, image, DIR_UP, view_rect)
elif e.key == pg.K_LEFT:
scroll_view(screen, image, DIR_LEFT, view_rect)
elif e.key == pg.K_RIGHT:
scroll_view(screen, image, DIR_RIGHT, view_rect)
elif e.type == pg.QUIT:
going = False
elif e.type == pg.MOUSEBUTTONDOWN:
direction = regions.get_at(e.pos)[0]
elif e.type == pg.MOUSEBUTTONUP:
direction = None
if direction:
scroll_view(screen, image, direction, view_rect)
clock.tick(30)
finally:
pg.key.set_repeat(old_k_delay, old_k_interval)
pg.quit()
if __name__ == "__main__":
if len(sys.argv) > 1:
image_file = sys.argv[1]
else:
image_file = None
main(image_file)
@@ -0,0 +1,60 @@
#!/usr/bin/env python
""" pygame.examples.setmodescale
On high resolution displays(4k, 1080p) and tiny graphics games (640x480)
show up very small so that they are unplayable. SCALED scales up the window
for you. The game thinks it's a 640x480 window, but really it can be bigger.
Mouse events are scaled for you, so your game doesn't need to do it.
Passing SCALED to pygame.display.set_mode means the resolution depends
on desktop size and the graphics are scaled.
"""
import pygame as pg
pg.init()
RES = (160, 120)
FPS = 30
clock = pg.time.Clock()
print ("desktops", pg.display.get_desktop_sizes())
screen = pg.display.set_mode(RES, pg.SCALED | pg.RESIZABLE)
# MAIN LOOP
done = False
i = 0
j = 0
r_name, r_flags = pg.display.get_renderer_info()
print("renderer:", r_name, "flags:", bin(r_flags))
for flag, name in [(1, "software"), (2, "accelerated"), (4, "VSync"), (8, "render to texture")]:
if (flag & r_flags):
print(name)
while not done:
for event in pg.event.get():
if event.type == pg.KEYDOWN and event.key == pg.K_q:
done = True
if event.type == pg.QUIT:
done = True
if event.type == pg.KEYDOWN and event.key == pg.K_f:
pg.display.toggle_fullscreen()
if event.type == pg.VIDEORESIZE:
pg.display.resize_event(event)
i += 1
i = i % screen.get_width()
j += i % 2
j = j % screen.get_height()
screen.fill((255, 0, 255))
pg.draw.circle(screen, (0, 0, 0), (100, 100), 20)
pg.draw.circle(screen, (0, 0, 200), (0, 0), 10)
pg.draw.circle(screen, (200, 0, 0), (160, 120), 30)
pg.draw.line(screen, (250, 250, 0), (0, 120), (160, 0))
pg.draw.circle(screen, (255, 255, 255), (i, j), 5)
pg.display.flip()
clock.tick(FPS)
@@ -0,0 +1,44 @@
#!/usr/bin/env python
""" pygame.examples.sound
Playing a soundfile and waiting for it to finish. You'll need the
pygame.mixer module for this to work. Note how in this simple example
we don't even bother loading all of the pygame package.
Just pick the mixer for sound and time for the delay function.
Optional command line argument: audio file name
"""
import os
import sys
import pygame as pg
main_dir = os.path.split(os.path.abspath(__file__))[0]
def main(file_path=None):
"""Play an audio file as a buffered sound sample
:param str file_path: audio file (default data/secosmic_low.wav)
"""
# choose a desired audio format
pg.mixer.init(11025) # raises exception on fail
# load the sound
sound = pg.mixer.Sound(file_path)
# start playing
print("Playing Sound...")
channel = sound.play()
# poll until finished
while channel.get_busy(): # still playing
print(" ...still going...")
pg.time.wait(1000)
print("...Finished")
if __name__ == "__main__":
if len(sys.argv) > 1:
main(sys.argv[1])
else:
main(os.path.join(main_dir, "data", "secosmic_lo.wav"))
@@ -0,0 +1,217 @@
#!/usr/bin/env python
""" pygame.examples.sound_array_demos
Creates an echo effect on any Sound object.
Uses sndarray and numpy to create offset faded copies of the
original sound. Currently it just uses hardcoded values for the
number of echos and the delay. Easy for you to recreate as
needed.
version 2. changes:
- Should work with different sample rates now.
- put into a function.
- Uses numpy by default, but falls back on Numeric.
"""
import os
import pygame as pg
from numpy import zeros, int32, int16
import time
# pg.mixer.init(44100, -16, 0)
pg.mixer.init()
# pg.mixer.init(11025, -16, 0)
# pg.mixer.init(11025)
def make_echo(sound, samples_per_second, mydebug=True):
""" returns a sound which is echoed of the last one.
"""
echo_length = 3.5
a1 = pg.sndarray.array(sound)
if mydebug:
print("SHAPE1: %s" % (a1.shape,))
length = a1.shape[0]
# myarr = zeros(length+12000)
myarr = zeros(a1.shape, int32)
if len(a1.shape) > 1:
# mult = a1.shape[1]
size = (a1.shape[0] + int(echo_length * a1.shape[0]), a1.shape[1])
# size = (a1.shape[0] + int(a1.shape[0] + (echo_length * 3000)), a1.shape[1])
else:
# mult = 1
size = (a1.shape[0] + int(echo_length * a1.shape[0]),)
# size = (a1.shape[0] + int(a1.shape[0] + (echo_length * 3000)),)
if mydebug:
print(int(echo_length * a1.shape[0]))
myarr = zeros(size, int32)
if mydebug:
print("size %s" % (size,))
print(myarr.shape)
myarr[:length] = a1
# print (myarr[3000:length+3000])
# print (a1 >> 1)
# print ("a1.shape %s" % (a1.shape,))
# c = myarr[3000:length+(3000*mult)]
# print ("c.shape %s" % (c.shape,))
incr = int(samples_per_second / echo_length)
gap = length
myarr[incr : gap + incr] += a1 >> 1
myarr[incr * 2 : gap + (incr * 2)] += a1 >> 2
myarr[incr * 3 : gap + (incr * 3)] += a1 >> 3
myarr[incr * 4 : gap + (incr * 4)] += a1 >> 4
if mydebug:
print("SHAPE2: %s" % (myarr.shape,))
sound2 = pg.sndarray.make_sound(myarr.astype(int16))
return sound2
def slow_down_sound(sound, rate):
""" returns a sound which is a slowed down version of the original.
rate - at which the sound should be slowed down. eg. 0.5 would be half speed.
"""
raise NotImplementedError()
# grow_rate = 1 / rate
# make it 1/rate times longer.
# a1 = pg.sndarray.array(sound)
# surf = pg.surfarray.make_surface(a1)
# print (a1.shape[0] * grow_rate)
# scaled_surf = pg.transform.scale(surf, (int(a1.shape[0] * grow_rate), a1.shape[1]))
# print (scaled_surf)
# print (surf)
# a2 = a1 * rate
# print (a1.shape)
# print (a2.shape)
# print (a2)
# sound2 = pg.sndarray.make_sound(a2.astype(int16))
# return sound2
def sound_from_pos(sound, start_pos, samples_per_second=None, inplace=1):
""" returns a sound which begins at the start_pos.
start_pos - in seconds from the begining.
samples_per_second -
"""
# see if we want to reuse the sound data or not.
if inplace:
a1 = pg.sndarray.samples(sound)
else:
a1 = pg.sndarray.array(sound)
# see if samples per second has been given. If not, query the pg.mixer.
# eg. it might be set to 22050
if samples_per_second is None:
samples_per_second = pg.mixer.get_init()[0]
# figure out the start position in terms of samples.
start_pos_in_samples = int(start_pos * samples_per_second)
# cut the beginning off the sound at the start position.
a2 = a1[start_pos_in_samples:]
# make the Sound instance from the array.
sound2 = pg.sndarray.make_sound(a2)
return sound2
def main():
"""play various sndarray effects
"""
main_dir = os.path.split(os.path.abspath(__file__))[0]
print("mixer.get_init %s" % (pg.mixer.get_init(),))
samples_per_second = pg.mixer.get_init()[0]
print(("-" * 30) + "\n")
print("loading sound")
sound = pg.mixer.Sound(os.path.join(main_dir, "data", "car_door.wav"))
print("-" * 30)
print("start positions")
print("-" * 30)
start_pos = 0.1
sound2 = sound_from_pos(sound, start_pos, samples_per_second)
print("sound.get_length %s" % (sound.get_length(),))
print("sound2.get_length %s" % (sound2.get_length(),))
sound2.play()
while pg.mixer.get_busy():
pg.time.wait(200)
print("waiting 2 seconds")
pg.time.wait(2000)
print("playing original sound")
sound.play()
while pg.mixer.get_busy():
pg.time.wait(200)
print("waiting 2 seconds")
pg.time.wait(2000)
# if 0:
# #TODO: this is broken.
# print (("-" * 30) + "\n")
# print ("Slow down the original sound.")
# rate = 0.2
# slowed_sound = slow_down_sound(sound, rate)
# slowed_sound.play()
# while pg.mixer.get_busy():
# pg.time.wait(200)
print("-" * 30)
print("echoing")
print("-" * 30)
t1 = time.time()
sound2 = make_echo(sound, samples_per_second)
print("time to make echo %i" % (time.time() - t1,))
print("original sound")
sound.play()
while pg.mixer.get_busy():
pg.time.wait(200)
print("echoed sound")
sound2.play()
while pg.mixer.get_busy():
pg.time.wait(200)
sound = pg.mixer.Sound(os.path.join(main_dir, "data", "secosmic_lo.wav"))
t1 = time.time()
sound3 = make_echo(sound, samples_per_second)
print("time to make echo %i" % (time.time() - t1,))
print("original sound")
sound.play()
while pg.mixer.get_busy():
pg.time.wait(200)
print("echoed sound")
sound3.play()
while pg.mixer.get_busy():
pg.time.wait(200)
if __name__ == "__main__":
main()
@@ -0,0 +1,102 @@
#!/usr/bin/env python
""" pygame.examples.sprite_texture
Experimental! Uses APIs which may disapear in the next release (_sdl2 is private).
Hardware accelerated Image objects with pygame.sprite.
_sdl2.video.Image is a backwards compatible way with to use Texture with
pygame.sprite groups.
"""
import os
import pygame as pg
if pg.get_sdl_version()[0] < 2:
raise SystemExit("This example requires pygame 2 and SDL2.")
from pygame._sdl2 import Window, Texture, Image, Renderer
data_dir = os.path.join(os.path.split(os.path.abspath(__file__))[0], "data")
def load_img(file):
return pg.image.load(os.path.join(data_dir, file))
pg.display.init()
pg.key.set_repeat(10, 10)
win = Window("asdf", resizable=True)
renderer = Renderer(win)
tex = Texture.from_surface(renderer, load_img("alien1.gif"))
class Something(pg.sprite.Sprite):
def __init__(self, img):
pg.sprite.Sprite.__init__(self)
self.rect = img.get_rect()
self.image = img
self.rect.w *= 5
self.rect.h *= 5
img.origin = self.rect.w / 2, self.rect.h / 2
sprite = Something(Image(tex, (0, 0, tex.width / 2, tex.height / 2)))
sprite.rect.x = 250
sprite.rect.y = 50
# sprite2 = Something(Image(sprite.image))
sprite2 = Something(Image(tex))
sprite2.rect.x = 250
sprite2.rect.y = 250
sprite2.rect.w /= 2
sprite2.rect.h /= 2
group = pg.sprite.Group()
group.add(sprite2)
group.add(sprite)
import math
t = 0
running = True
clock = pg.time.Clock()
renderer.draw_color = (255, 0, 0, 255)
while running:
for event in pg.event.get():
if event.type == pg.QUIT:
running = False
elif event.type == pg.KEYDOWN:
if event.key == pg.K_ESCAPE:
running = False
elif event.key == pg.K_LEFT:
sprite.rect.x -= 5
elif event.key == pg.K_RIGHT:
sprite.rect.x += 5
elif event.key == pg.K_DOWN:
sprite.rect.y += 5
elif event.key == pg.K_UP:
sprite.rect.y -= 5
renderer.clear()
t += 1
img = sprite.image
img.angle += 1
img.flipX = t % 50 < 25
img.flipY = t % 100 < 50
img.color[0] = int(255.0 * (0.5 + math.sin(0.5 * t + 10.0) / 2.0))
img.alpha = int(255.0 * (0.5 + math.sin(0.1 * t) / 2.0))
# img.draw(dstrect=(x, y, 5 * img.srcrect['w'], 5 * img.srcrect['h']))
group.draw(renderer)
renderer.present()
clock.tick(60)
win.title = str("FPS: {}".format(clock.get_fps()))
@@ -0,0 +1,102 @@
#!/usr/bin/env python
""" pg.examples.stars
We are all in the gutter,
but some of us are looking at the stars.
-- Oscar Wilde
A simple starfield example. Note you can move the 'center' of
the starfield by leftclicking in the window. This example show
the basics of creating a window, simple pixel plotting, and input
event management.
"""
import random
import math
import pygame as pg
# constants
WINSIZE = [640, 480]
WINCENTER = [320, 240]
NUMSTARS = 150
def init_star():
"creates new star values"
dir = random.randrange(100000)
velmult = random.random() * 0.6 + 0.4
vel = [math.sin(dir) * velmult, math.cos(dir) * velmult]
return vel, WINCENTER[:]
def initialize_stars():
"creates a new starfield"
stars = []
for x in range(NUMSTARS):
star = init_star()
vel, pos = star
steps = random.randint(0, WINCENTER[0])
pos[0] = pos[0] + (vel[0] * steps)
pos[1] = pos[1] + (vel[1] * steps)
vel[0] = vel[0] * (steps * 0.09)
vel[1] = vel[1] * (steps * 0.09)
stars.append(star)
move_stars(stars)
return stars
def draw_stars(surface, stars, color):
"used to draw (and clear) the stars"
for vel, pos in stars:
pos = (int(pos[0]), int(pos[1]))
surface.set_at(pos, color)
def move_stars(stars):
"animate the star values"
for vel, pos in stars:
pos[0] = pos[0] + vel[0]
pos[1] = pos[1] + vel[1]
if not 0 <= pos[0] <= WINSIZE[0] or not 0 <= pos[1] <= WINSIZE[1]:
vel[:], pos[:] = init_star()
else:
vel[0] = vel[0] * 1.05
vel[1] = vel[1] * 1.05
def main():
"This is the starfield code"
# create our starfield
random.seed()
stars = initialize_stars()
clock = pg.time.Clock()
# initialize and prepare screen
pg.init()
screen = pg.display.set_mode(WINSIZE)
pg.display.set_caption("pygame Stars Example")
white = 255, 240, 200
black = 20, 20, 40
screen.fill(black)
# main game loop
done = 0
while not done:
draw_stars(screen, stars, black)
move_stars(stars)
draw_stars(screen, stars, white)
pg.display.update()
for e in pg.event.get():
if e.type == pg.QUIT or (e.type == pg.KEYUP and e.key == pg.K_ESCAPE):
done = 1
break
elif e.type == pg.MOUSEBUTTONDOWN and e.button == 1:
WINCENTER[:] = list(e.pos)
clock.tick(50)
# if python says run, then we should run
if __name__ == "__main__":
main()
# I prefer the time of insects to the time of stars.
#
# -- Wisława Szymborska
@@ -0,0 +1,262 @@
#!/usr/bin/env python
""" pg.examples.testsprite
Like the testsprite.c that comes with libsdl, this pygame version shows
lots of sprites moving around.
It is an abomination of ugly code, and mostly used for testing.
See pg.examples.aliens for some prettyier code.
"""
import sys
import os
from random import randint
from time import time
import pygame as pg
from pygame.compat import xrange_
if "-psyco" in sys.argv:
try:
import psyco
psyco.full()
except Exception:
print("No psyco for you! psyco failed to import and run.")
main_dir = os.path.split(os.path.abspath(__file__))[0]
data_dir = os.path.join(main_dir, "data")
# use this to use update rects or not.
# If the screen is mostly full, then update rects are not useful.
update_rects = True
if "-update_rects" in sys.argv:
update_rects = True
if "-noupdate_rects" in sys.argv:
update_rects = False
use_static = False
if "-static" in sys.argv:
use_static = True
use_layered_dirty = False
if "-layered_dirty" in sys.argv:
update_rects = True
use_layered_dirty = True
flags = 0
if "-flip" in sys.argv:
flags ^= DOUBLEBUF
if "-fullscreen" in sys.argv:
flags ^= FULLSCREEN
if "-sw" in sys.argv:
flags ^= SWSURFACE
use_rle = True
if "-hw" in sys.argv:
flags ^= HWSURFACE
use_rle = False
if "-scaled" in sys.argv:
flags ^= SCALED
screen_dims = [640, 480]
if "-height" in sys.argv:
i = sys.argv.index("-height")
screen_dims[1] = int(sys.argv[i + 1])
if "-width" in sys.argv:
i = sys.argv.index("-width")
screen_dims[0] = int(sys.argv[i + 1])
if "-alpha" in sys.argv:
use_alpha = True
else:
use_alpha = False
print(screen_dims)
##class Thingy(pg.sprite.Sprite):
## images = None
## def __init__(self):
## pg.sprite.Sprite.__init__(self)
## self.image = Thingy.images[0]
## self.rect = self.image.get_rect()
## self.rect.x = randint(0, screen_dims[0])
## self.rect.y = randint(0, screen_dims[1])
## #self.vel = [randint(-10, 10), randint(-10, 10)]
## self.vel = [randint(-1, 1), randint(-1, 1)]
##
## def move(self):
## for i in [0, 1]:
## nv = self.rect[i] + self.vel[i]
## if nv >= screen_dims[i] or nv < 0:
## self.vel[i] = -self.vel[i]
## nv = self.rect[i] + self.vel[i]
## self.rect[i] = nv
class Thingy(pg.sprite.DirtySprite):
images = None
def __init__(self):
## pg.sprite.Sprite.__init__(self)
pg.sprite.DirtySprite.__init__(self)
self.image = Thingy.images[0]
self.rect = self.image.get_rect()
self.rect.x = randint(0, screen_dims[0])
self.rect.y = randint(0, screen_dims[1])
# self.vel = [randint(-10, 10), randint(-10, 10)]
self.vel = [randint(-1, 1), randint(-1, 1)]
self.dirty = 2
def update(self):
for i in [0, 1]:
nv = self.rect[i] + self.vel[i]
if nv >= screen_dims[i] or nv < 0:
self.vel[i] = -self.vel[i]
nv = self.rect[i] + self.vel[i]
self.rect[i] = nv
class Static(pg.sprite.DirtySprite):
images = None
def __init__(self):
pg.sprite.DirtySprite.__init__(self)
self.image = Static.images[0]
self.rect = self.image.get_rect()
self.rect.x = randint(0, 3 * screen_dims[0] / 4)
self.rect.y = randint(0, 3 * screen_dims[1] / 4)
def main(
update_rects=True,
use_static=False,
use_layered_dirty=False,
screen_dims=[640, 480],
use_alpha=False,
flags=0,
):
"""Show lots of sprites moving around
Optional keyword arguments:
update_rects - use the RenderUpdate sprite group class (default True)
use_static - include non-moving images (default False)
use_layered_dirty - Use the FastRenderGroup sprite group (default False)
screen_dims - Pygame window dimensions (default [640, 480])
use_alpha - use alpha blending (default False)
flags - additional display mode flags (default no additional flags)
"""
if use_layered_dirty:
update_rects = True
# pg.init()
pg.display.init()
# if "-fast" in sys.argv:
screen = pg.display.set_mode(screen_dims, flags)
# this is mainly for GP2X, so it can quit.
pg.joystick.init()
num_joysticks = pg.joystick.get_count()
if num_joysticks > 0:
stick = pg.joystick.Joystick(0)
stick.init() # now we will receive events for the joystick
screen.fill([0, 0, 0])
pg.display.flip()
sprite_surface = pg.image.load(os.path.join(data_dir, "asprite.bmp"))
sprite_surface2 = pg.image.load(os.path.join(data_dir, "static.png"))
if use_rle:
sprite_surface.set_colorkey([0xFF, 0xFF, 0xFF], pg.SRCCOLORKEY | pg.RLEACCEL)
sprite_surface2.set_colorkey([0xFF, 0xFF, 0xFF], pg.SRCCOLORKEY | pg.RLEACCEL)
else:
sprite_surface.set_colorkey([0xFF, 0xFF, 0xFF], pg.SRCCOLORKEY)
sprite_surface2.set_colorkey([0xFF, 0xFF, 0xFF], pg.SRCCOLORKEY)
if use_alpha:
sprite_surface = sprite_surface.convert_alpha()
sprite_surface2 = sprite_surface2.convert_alpha()
else:
sprite_surface = sprite_surface.convert()
sprite_surface2 = sprite_surface2.convert()
Thingy.images = [sprite_surface]
if use_static:
Static.images = [sprite_surface2]
if len(sys.argv) > 1:
try:
numsprites = int(sys.argv[-1])
except Exception:
numsprites = 100
else:
numsprites = 100
sprites = None
if use_layered_dirty:
## sprites = pg.sprite.FastRenderGroup()
sprites = pg.sprite.LayeredDirty()
else:
if update_rects:
sprites = pg.sprite.RenderUpdates()
else:
sprites = pg.sprite.Group()
for i in xrange_(0, numsprites):
if use_static and i % 2 == 0:
sprites.add(Static())
sprites.add(Thingy())
frames = 0
start = time()
background = pg.Surface(screen.get_size())
background = background.convert()
background.fill([0, 0, 0])
going = True
while going:
if not update_rects:
screen.fill([0, 0, 0])
## for sprite in sprites:
## sprite.move()
if update_rects:
sprites.clear(screen, background)
sprites.update()
rects = sprites.draw(screen)
if update_rects:
pg.display.update(rects)
else:
pg.display.flip()
for event in pg.event.get():
if event.type in [pg.QUIT, pg.KEYDOWN, pg.QUIT, pg.JOYBUTTONDOWN]:
going = False
frames += 1
end = time()
print("FPS: %f" % (frames / ((end - start))))
pg.quit()
if __name__ == "__main__":
main(update_rects, use_static, use_layered_dirty, screen_dims, use_alpha, flags)
@@ -0,0 +1,177 @@
#!/usr/bin/env python
""" pg.examples.textinput
A little "console" where you can write in text.
Shows how to use the TEXTEDITING and TEXTINPUT events.
"""
import sys
import pygame as pg
import pygame.freetype as freetype
# Version check
if pg.get_sdl_version() < (2, 0, 0):
raise Exception("This example requires pygame 2.")
###CONSTS
# Set to true or add 'showevent' in argv to see IME and KEYDOWN events
PRINT_EVENT = False
# frames per second, the general speed of the program
FPS = 50
# size of window
WINDOWWIDTH, WINDOWHEIGHT = 640, 480
BGCOLOR = (0, 0, 0)
# position of chatlist and chatbox
CHATLIST_POS = pg.Rect(0, 20, WINDOWWIDTH, 400)
CHATBOX_POS = pg.Rect(0, 440, WINDOWWIDTH, 40)
CHATLIST_MAXSIZE = 20
TEXTCOLOR = (0, 255, 0)
# Add fontname for each language, otherwise some text can't be correctly displayed.
FONTNAMES = [
"notosanscjktcregular",
"notosansmonocjktcregular",
"notosansregular,",
"microsoftjhengheimicrosoftjhengheiuilight",
"microsoftyaheimicrosoftyaheiuilight",
"msgothicmsuigothicmspgothic",
"msmincho",
"Arial",
]
# Initalize
pg.init()
Screen = pg.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
pg.display.set_caption("TextInput example")
FPSClock = pg.time.Clock()
# Freetype
# "The font name can be a comma separated list of font names to search for."
FONTNAMES = ",".join(str(x) for x in FONTNAMES)
Font = freetype.SysFont(FONTNAMES, 24)
FontSmall = freetype.SysFont(FONTNAMES, 16)
print("Using font: " + Font.name)
# Main loop process
def main():
global BGCOLOR, PRINT_EVENT, CHATBOX_POS, CHATLIST_POS, CHATLIST_MAXSIZE
global FPSClock, Font, Screen
"""
https://wiki.libsdl.org/SDL_HINT_IME_INTERNAL_EDITING
https://wiki.libsdl.org/Tutorials/TextInput
Candidate list not showing due to SDL2 problem ;w;
"""
pg.key.start_text_input()
input_rect = pg.Rect(80, 80, 320, 40)
pg.key.set_text_input_rect(input_rect)
_IMEEditing = False
_IMEText = ""
_IMETextPos = 0
_IMEEditingText = ""
_IMEEditingPos = 0
ChatList = []
while True:
for event in pg.event.get():
if event.type == pg.QUIT:
pg.quit()
return
elif event.type == pg.KEYDOWN:
if PRINT_EVENT:
print(event)
if _IMEEditing:
if len(_IMEEditingText) == 0:
_IMEEditing = False
continue
if event.key == pg.K_BACKSPACE:
if len(_IMEText) > 0 and _IMETextPos > 0:
_IMEText = (
_IMEText[0 : _IMETextPos - 1] + _IMEText[_IMETextPos:]
)
_IMETextPos = max(0, _IMETextPos - 1)
elif event.key == pg.K_DELETE:
_IMEText = _IMEText[0:_IMETextPos] + _IMEText[_IMETextPos + 1 :]
elif event.key == pg.K_LEFT:
_IMETextPos = max(0, _IMETextPos - 1)
elif event.key == pg.K_RIGHT:
_IMETextPos = min(len(_IMEText), _IMETextPos + 1)
elif (
event.key in [pg.K_RETURN, pg.K_KP_ENTER]
and len(event.unicode) == 0
):
# Block if we have no text to append
if len(_IMEText) == 0:
continue
# Append chat list
ChatList.append(_IMEText)
if len(ChatList) > CHATLIST_MAXSIZE:
ChatList.pop(0)
_IMEText = ""
_IMETextPos = 0
elif event.type == pg.TEXTEDITING:
if PRINT_EVENT:
print(event)
_IMEEditing = True
_IMEEditingText = event.text
_IMEEditingPos = event.start
elif event.type == pg.TEXTINPUT:
if PRINT_EVENT:
print(event)
_IMEEditing = False
_IMEEditingText = ""
_IMEText = _IMEText[0:_IMETextPos] + event.text + _IMEText[_IMETextPos:]
_IMETextPos += len(event.text)
# Screen updates
Screen.fill(BGCOLOR)
# Chat List updates
chat_height = CHATLIST_POS.height / CHATLIST_MAXSIZE
for i in range(len(ChatList)):
FontSmall.render_to(
Screen,
(CHATLIST_POS.x, CHATLIST_POS.y + i * chat_height),
ChatList[i],
TEXTCOLOR,
)
# Chat box updates
start_pos = CHATBOX_POS.copy()
ime_textL = ">" + _IMEText[0:_IMETextPos]
ime_textM = (
_IMEEditingText[0:_IMEEditingPos] + "|" + _IMEEditingText[_IMEEditingPos:]
)
ime_textR = _IMEText[_IMETextPos:]
rect_textL = Font.render_to(Screen, start_pos, ime_textL, TEXTCOLOR)
start_pos.x += rect_textL.width
# Editing texts should be underlined
rect_textM = Font.render_to(
Screen, start_pos, ime_textM, TEXTCOLOR, None, freetype.STYLE_UNDERLINE
)
start_pos.x += rect_textM.width
Font.render_to(Screen, start_pos, ime_textR, TEXTCOLOR)
pg.display.update()
FPSClock.tick(FPS)
if __name__ == "__main__":
if "showevent" in sys.argv:
PRINT_EVENT = True
main()
@@ -0,0 +1,100 @@
#!/usr/bin/env python
""" pg.examples.vgrade
This example demonstrates creating an image with numpy
python, and displaying that through SDL. You can look at the
method of importing numpy and pg.surfarray. This method
will fail 'gracefully' if it is not available.
I've tried mixing in a lot of comments where the code might
not be self explanatory, nonetheless it may still seem a bit
strange. Learning to use numpy for images like this takes a
bit of learning, but the payoff is extremely fast image
manipulation in python.
For Pygame 1.9.2 and up, this example also showcases a new feature
of surfarray.blit_surface: array broadcasting. If a source array
has either a width or height of 1, the array is repeatedly blitted
to the surface along that dimension to fill the surface. In fact,
a (1, 1) or (1, 1, 3) array results in a simple surface color fill.
Just so you know how this breaks down. For each sampling of
time, 30% goes to each creating the gradient and blitting the
array. The final 40% goes to flipping/updating the display surface
The window will have no border decorations.
The code also demonstrates use of the timer events.
"""
import os
import pygame as pg
try:
import numpy as np
import numpy.random as np_random
except ImportError:
raise SystemExit("This example requires numpy and the pygame surfarray module")
timer = 0
def stopwatch(message=None):
"simple routine to time python code"
global timer
if not message:
timer = pg.time.get_ticks()
return
now = pg.time.get_ticks()
runtime = (now - timer) / 1000.0 + 0.001
print("%s %s %s" % (message, runtime, ("seconds\t(%.2ffps)" % (1.0 / runtime))))
timer = now
def VertGradientColumn(surf, topcolor, bottomcolor):
"creates a new 3d vertical gradient array"
topcolor = np.array(topcolor, copy=False)
bottomcolor = np.array(bottomcolor, copy=False)
diff = bottomcolor - topcolor
width, height = surf.get_size()
# create array from 0.0 to 1.0 triplets
column = np.arange(height, dtype="float") / height
column = np.repeat(column[:, np.newaxis], [3], 1)
# create a single column of gradient
column = topcolor + (diff * column).astype("int")
# make the column a 3d image column by adding X
column = column.astype("uint8")[np.newaxis, :, :]
# 3d array into 2d array
return pg.surfarray.map_array(surf, column)
def DisplayGradient(surf):
"choose random colors and show them"
stopwatch()
colors = np_random.randint(0, 255, (2, 3))
column = VertGradientColumn(surf, colors[0], colors[1])
pg.surfarray.blit_array(surf, column)
pg.display.flip()
stopwatch("Gradient:")
def main():
pg.init()
pg.mixer.quit() # remove ALSA underflow messages for Debian squeeze
size = 600, 400
os.environ["SDL_VIDEO_CENTERED"] = "1"
screen = pg.display.set_mode(size, pg.NOFRAME, 0)
pg.event.set_blocked(pg.MOUSEMOTION) # keep our queue cleaner
pg.time.set_timer(pg.USEREVENT, 500)
while 1:
event = pg.event.wait()
if event.type in (pg.QUIT, pg.KEYDOWN, pg.MOUSEBUTTONDOWN):
break
elif event.type == pg.USEREVENT:
DisplayGradient(screen)
if __name__ == "__main__":
main()
@@ -0,0 +1,161 @@
#!/usr/bin/env python
""" pg.examples.video
Experimental!
* dialog message boxes with messagebox.
* multiple windows with Window
* driver selection
* Renderer, Texture, and Image classes
* Drawing lines, rects, and such onto Renderers.
"""
import os
import pygame as pg
if pg.get_sdl_version()[0] < 2:
raise SystemExit(
"This example requires pygame 2 and SDL2. _sdl2 is experimental and will change."
)
from pygame._sdl2 import Window, Texture, Image, Renderer, get_drivers, messagebox
data_dir = os.path.join(os.path.split(os.path.abspath(__file__))[0], "data")
def load_img(file):
return pg.image.load(os.path.join(data_dir, file))
pg.display.init()
pg.key.set_repeat(1000, 10)
for driver in get_drivers():
print(driver)
import random
answer = messagebox(
"I will open two windows! Continue?",
"Hello!",
info=True,
buttons=("Yes", "No", "Chance"),
return_button=0,
escape_button=1,
)
if answer == 1 or (answer == 2 and random.random() < 0.5):
import sys
sys.exit(0)
win = Window("asdf", resizable=True)
renderer = Renderer(win)
tex = Texture.from_surface(renderer, load_img("alien1.gif"))
running = True
x, y = 250, 50
clock = pg.time.Clock()
backgrounds = [(255, 0, 0, 255), (0, 255, 0, 255), (0, 0, 255, 255)]
bg_index = 0
renderer.draw_color = backgrounds[bg_index]
win2 = Window("2nd window", size=(256, 256), always_on_top=True)
win2.opacity = 0.5
win2.set_icon(load_img("bomb.gif"))
renderer2 = Renderer(win2)
tex2 = Texture.from_surface(renderer2, load_img("asprite.bmp"))
renderer2.clear()
tex2.draw()
renderer2.present()
del tex2
full = 0
tex = Image(tex)
surf = pg.Surface((64, 64))
streamtex = Texture(renderer, (64, 64), streaming=True)
tex_update_interval = 1000
next_tex_update = pg.time.get_ticks()
while running:
for event in pg.event.get():
if event.type == pg.QUIT:
running = False
elif getattr(event, "window", None) == win2:
if (
event.type == pg.KEYDOWN
and event.key == pg.K_ESCAPE
or event.type == pg.WINDOWEVENT
and event.event == pg.WINDOWEVENT_CLOSE
):
win2.destroy()
elif event.type == pg.KEYDOWN:
if event.key == pg.K_ESCAPE:
running = False
elif event.key == pg.K_LEFT:
x -= 5
elif event.key == pg.K_RIGHT:
x += 5
elif event.key == pg.K_DOWN:
y += 5
elif event.key == pg.K_UP:
y -= 5
elif event.key == pg.K_f:
if full == 0:
win.set_fullscreen(True)
full = 1
else:
win.set_windowed()
full = 0
elif event.key == pg.K_s:
readsurf = renderer.to_surface()
pg.image.save(readsurf, "test.png")
elif event.key == pg.K_SPACE:
bg_index = (bg_index + 1) % len(backgrounds)
renderer.draw_color = backgrounds[bg_index]
renderer.clear()
# update texture
curtime = pg.time.get_ticks()
if curtime >= next_tex_update:
for x_ in range(streamtex.width // 4):
for y_ in range(streamtex.height // 4):
newcol = (
random.randint(0, 255),
random.randint(0, 255),
random.randint(0, 255),
255,
)
area = (4 * x_, 4 * y_, 4, 4)
surf.fill(newcol, area)
streamtex.update(surf)
next_tex_update = curtime + tex_update_interval
streamtex.draw(dstrect=pg.Rect(64, 128, 64, 64))
tex.draw(dstrect=(x, y))
# TODO: should these be?
# - line instead of draw_line
# - point instead of draw_point
# - rect(rect, width=1)->draw 1 pixel, instead of draw_rect
# - rect(rect, width=0)->filled ? , instead of fill_rect
#
# TODO: should these work with pg.draw.line(renderer, ...) functions?
renderer.draw_color = (255, 255, 255, 255)
renderer.draw_line((0, 0), (64, 64))
renderer.draw_line((64, 64), (128, 0))
renderer.draw_point((72, 32))
renderer.draw_rect(pg.Rect(0, 64, 64, 64))
renderer.fill_rect(pg.Rect(0, 128, 64, 64))
renderer.draw_color = backgrounds[bg_index]
renderer.present()
clock.tick(60)
win.title = str("FPS: {}".format(clock.get_fps()))