initial
@@ -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()
|
||||
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 75 KiB |
|
After Width: | Height: | Size: 578 B |
|
After Width: | Height: | Size: 8.9 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 170 B |
|
After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 143 B |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 6.4 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 129 B |
|
After Width: | Height: | Size: 1.2 KiB |
@@ -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()))
|
||||