====== PyGame ======
===== Básico =====
PyGame se compone de distintos módulos que se utilizan para acceder a los distintos dispositivos o recursos que gestiona, estos son:
* //pygame.camera// - Acceso a la webcam.
* //pygame.cdrom// - Acceso a los lectores de cd.
* //pygame.cursors// - Acceso al cursor.
* //pygame.display// - Acceso a la pantalla\ventana.
* //pygame.draw// - Dibujo.
* //pygame.event// - Encargado de gestionar eventos.
* //pygame.font// - Encargado del uso de las fuentes del sistema.
* //pygame.image// - Acciones con las imágenes.
* //pygame.joystick// - Acceso a joysticks y dispositivos de entrada.
* //pygame.key// - Lectura de teclado.
* //pygame.mixer// - Acciones con sonido.
* //pygame.mouse// - Gestiona el ratón.
* //pygame.movie// - Gestiona la reproducción de archivos de video.
* //pygame.music// - Gestiona el trabajo de archivos de audio (en streaming).
* //pygame.overlay// -
* //pygame// - Funciones de PyGame
* //pygame.rect// - Gestión de áreas rectangulares.
* //pygame.sndarray// - Gestiona datos de audio.
* //pygame.sprite// - Gestiona el movimiento de imágenes.
* //pygame.surface// - Gestiona la relación entre las imágenes y la ventana.
* //pygame.surfarray// - Manipula el array de píxels.
* //pygame.time// - Gestiona el tiempo.
* //pygame.transform// - Realiza los movimientos de imágenes.
Es posible que un módulo no esté activo, esto puede ser debido a que, por ejemplo, no estén instalados los lectores de cds. En ese caso ese módulo queda asignado como ''None''.
if pygame.font is None:
print "The font module is not available!"
exit()
==== Inicializando ====
Para utilizar estos módulos, al principio de cada script deberemos importar ''pygame'' y luego ''pygame.locals'' que es donde están todas las funciones y constantes.
import pygame
from pygame.locals import *
Para inicializar los módulos podemos hacerlo llamando a la función ''init'' de cada uno de los módulos por separado (por ejemplo, ''pygame.sound.init()'') o llamar a la función dentro de ''pygame''.
pygame.init()
==== Creación de la ventana ====
Una ventana, a partir de ahora //display//, puede estar en modo normal, como una ventana del sistema, o en fullscreen. La llamada a '' pygame.display.set_mode'' retorna el objeto ''Surface'' que representa a dicha ventana. Este método recibe tres parámetros, de los cuales sólo el primero es necesario:
* Una tupla de dos elementos correspondientes al ancho y alto de la ventana.
* Los flags de creación que podremos combinar mediante el signo de OR (|), estos pueden ser:
* FULLSCREEN, que crea una ventana en fullscreen.
* DOUBLEBUF, crea una ventana con doble buffer. Recomendada para HWSURFACE o OPENGL.
* HWSURFACE, que crea una ventana con aceleración de hardware, ha de ser combinada con la flag de FULLSCREEN.
* OPENGL, que crea una ventana OpenGL.
* RESIZABLE, crea una ventana que puede cambiar de tamaño.
* NOFRAME, crea una ventana sin bordes.
* El bit de profundidad de color (24, 32...). Si ponemos 0 se pondrá el del escritorio.
Si todo ha ido bien en la llamada a ''set_mode'' se retornará el objeto Suface.
El método de ''pygame.display.set_caption'' colocará el título en la ventana.
screen = pygame.display.set_mode((640, 480), 0, 32)
pygame.display.set_caption("Hello, World!")
Otros métodos:
* ''flip'': Actualiza toda la ventana (que no la surface).
* ''set_icon'': Cambia el icono de la ventana.
* ''get_driver'': Devuelve el nombre del driver que está utilizando pygame.
=== Gestión de la ventana ===
Para que la ventana se mantenga activa tendremos que poner nuestro juego en un bucle. \\
Luego buscaremos que no exista ningún evento ''QUIT'' que indique que el usuario desea salir de la aplicación, si es así deberemos cerrar el progama.
Para que todas las imágenes sean pintadas sobre la ventana utilizaremos el método ''pygame.display.update()''.
while True:
for event in pygame.event.get():
if event.type == QUIT:
sys.exit()
...
pygame.display.update()
* {{fw:pygame:pygame01.rar|Ejemplo 01}}
==== Imágenes\Surface ====
La función ''pygame.image.load'' carga una imágen como ''Surface''. Los objetos ''Surface'' tienen métodos que hacen la imágen compatible con nuestra ventana y a la vez permiten manipularla. Para dibujar una imágen en la ventana haremos: ''.blit(,)'':
screen.blit(background, (0,0))
Para **saber el ancho y el alto** de un objeto imágen utilizaremos sus métodos ''get_width'' y ''get_height''. \\
Otras funciones de una ''surface'':
* ''blit'': Dibuja una imágen sobre otra.
* ''convert'': Cambia el formato de píxel de una imágen.
* ''convert_alpha'': Cambia el formato de píxel de una imágen que tenga indicado el canal alpha.
* ''copy'': Copia una surface en otra.
* ''fill'': Rellena la surface de un color sólido.
* ''scroll'': Mueve\Desplaza el contenido de una surface.
* ''set_colorkey''\''get_colorkey'': Asigna\recoge el colorkey de la imágen, el color que se mostrará como transparente (la imágen no ha de tener canal alpha).
Y más (copiado de la documentación):
* Surface.set_alpha - set the alpha value for the full Surface image.
* Surface.get_alpha - get the current Surface transparency value.
* Surface.get_palette - get the color index palette for an 8bit Surface.
* Surface.get_palette_at - get the color for a single entry in a palette.
* Surface.set_palette - set the color palette for an 8bit Surface.
* Surface.set_palette_at - set the color for a single index in an 8bit Surface palette.
* Surface.map_rgb - convert a color into a mapped color value.
* Surface.unmap_rgb - convert a mapped integer color value into a Color.
* Surface.set_clip - set the current clipping area of the Surface.
* Surface.get_clip - get the current clipping area of the Surface.
* Surface.subsurface - create a new surface that references its parent.
* Surface.get_parent - find the parent of a subsurface.
* Surface.get_abs_parent - find the top level parent of a subsurface.
* Surface.get_offset - find the position of a child subsurface inside a parent.
* Surface.get_abs_offset - find the absolute position of a child subsurface inside its top level parent.
* Surface.get_size - get the dimensions of the Surface.
* Surface.get_width - get the width of the Surface.
* Surface.get_height - get the height of the Surface.
* Surface.get_rect - get the rectangular area of the Surface.
* Surface.get_bitsize - get the bit depth of the Surface pixel format.
* Surface.get_bytesize - get the bytes used per Surface pixel.
* Surface.get_flags - get the additional flags used for the Surface.
* Surface.get_pitch - get the number of bytes used per Surface row.
* Surface.get_masks - the bitmasks needed to convert between a color and a mapped integer.
* Surface.set_masks - set the bitmasks needed to convert between a color and a mapped integer.
* Surface.get_shifts - the bit shifts needed to convert between a color and a mapped integer.
* Surface.set_shifts - sets the bit shifts needed to convert between a color and a mapped integer.
* Surface.get_losses - the significant bits used to convert between a color and a mapped integer.
* Surface.get_bounding_rect - find the smallest rect containing data find the smallest rect containing data.
* Surface.get_buffer - acquires a buffer object for the pixels of the Surface.
=== Recoger sub-imágenes dentro de una imágen ===
Para ello usaremos la función: ''master_image.subsurface''. Por ejemplo la siguiente función devuelve un array de imágenes indicándole la imágen inicial y el número de subimágenes que contiene, entonces va cogiendolas y agregándolas a un array:
def load_sliced_sprites(num, filename):
images = []
master_image = pygame.image.load(filename).convert_alpha()
master_width, master_height = master_image.get_size()
w = master_width / num
for i in range(0, num):
images.append(master_image.subsurface((i*w,0,w,master_height)))
return images
* {{fw:pygame:pygame02.rar|Ejemplo de animación}}
=== Acceso a píxels ===
(Documentación)
* Surface.lock - lock the Surface memory for pixel access.
* Surface.unlock - unlock the Surface memory from pixel access.
* Surface.mustlock - test if the Surface requires locking.
* Surface.get_locked - test if the Surface is current locked.
* Surface.get_locks - Gets the locks for the Surface.
* Surface.get_at - get the color value at a single pixel.
* Surface.set_at - set the color value for a single pixel.
=== Clipping ===
Es una técnica en la que se utiliza el método ''surface.set_clip'', este indica qué porción de la surface se redibujará, de esta forma no se repinta toda la pantalla y el dibujado es más ágil.
screen.set_clip((100,10,100,90))
screen.fill((200,200,200))
==== Dibujar elementos simples ====
A partir de ''pygame.draw'' podemos dibujar elementos como:
* ''line'', una línea. Se le pasan la surface, el color, la posición incial y la final.
* ''rect''
* ''circle''
import pygame
from pygame.locals import *
import sys
w = 640
h = 489
screen = pygame.display.set_mode((w,h))
pygame.draw.line(screen, (255, 0, 0), (0,0), (w,h))
pygame.display.flip()
while True:
for event in pygame.event.get():
if event.type == QUIT:
sys.exit()
pygame.display.update()
==== Gestión de eventos ====
Los eventos se encuentran en una cola en ''pygame.event'', recogeremos dichos eventos llamando al método ''get()''; estos tendrán un tipo (''type''), los posibles están definidos en ''pygame.locals'' y significan:
* ''QUIT'' que el usuario ha hecho click en el botón de cerrar.
* ''KEYDOWN'' o ''KEYUP'' que el usuario ha pulsado una tecla, tendrán una propiedad llamada ''key'' que define (como ''K_XXX'') la tecla pulsada.
* Respecto al uso del ratón los eventos posibles son MOUSEMOTION (que tiene las propiedades ''pos'', ''rel'', ''buttons'') o ''MOUSEBUTTONUP'' y ''MOUSEBUTTONDOWN'' (que tienen las propiedades ''pos'' y ''button'').
for event in pygame.event.get():
if event.type == QUIT:
exit()
if event.type == KEYDOWN:
if event.key == K_LEFT:
self.snake.direction = [-1, 0]
elif event.key == K_RIGHT:
self.snake.direction = [1, 0]
elif event.key == K_UP:
self.snake.direction = [0, -1]
elif event.key == K_DOWN:
self.snake.direction = [0, 1]
elif event.key == K_ESCAPE:
exit()
if event.type == pygame.MOUSEMOTION:
x, y = event.pos
* Mediante el método ''pygame.event.clear()'' eliminaremos los eventos existentes en la cola.
* Mediante ''pygame.event.post(Event)'' agregaremos un evento a la cola.
* El objeto correspondiente a un evento es el ''pygame.event.Event''. Su constructor recibe el tipo y un diccionario de los atributos.
==== Dibujar texto ====
Para dibujar texto lo que utilizamos es la clase ''pygame.font.Font'', a esta se le pasa por parámetros el fichero donde está la fuente (o sino ''None'' y cogerá el por defecto de la fuente) y el tamaño. Luego se utiliza el método ''render'' para dibujar el texto (devuelve una surface).
font = pygame.font.Font(None, 37)
text = font.render('Powered by Python and PyGame', True, (255, 255, 255), (159, 182, 205))
screen.blit(text, (100,210))
==== Transformaciones ====
Todos los métodos retornan una superficie nueva y destruyen la anterior.
* ''pygame.transform.flip(surface, xbool, ybool)'': Invierte una superficie en x o en y, se le pasa ''True''\''False'' com ''xbool'' o ''ybool''.
* ''pygame.transform.scale(surface, (width, height))'': Escala una superficie al tamaño indicado.
* ''pygame.transform.rotate(Surface, angle)'': Rota una superficie en el ángulo, expresado en grados, indicado.
* ''pygame.transform.rotozoom(Surface, angle, scale)'': Es una combinación de escalado y rotación. Se utiliza un algoritmo de antializing. El escalado se expresará en floats, si, por ejemplo su valor es 2.0 significará que se escala el doble.
* ''pygame.transform.scale2x(surface)'': Duplica la imágen en tamaño.
* ''pygame.transform.smoothscale(surface, (width, height))'': Hace un escalado smooth.
=== Y otras más técnicas ===
* ''pygame.transform.get_smoothscale_backend'' y ''pygame.transform.set_smoothscale_backend'' para indicar el motor de escalado.
* ''pygame.transform.chop'' elimina un área del interior de la imágen.
* ''pygame.transform.laplacian'' encuentra los bordes internos de la surface.
* ''pygame.transform.average_surfaces''
* ''pygame.transform.average_color'': Encuentra el color general de la imágen.
* ''pygame.transform.threshold'': Encuentra los píxels en la imágen son del color indicado.
==== Controlar el tiempo ====
En ''pygame.time'' tenemos clases y funciones para controlar\monitorizar el tiempo.
* ''get_ticks'': Recoge los milisegundos que han pasado desde que se llamó a ''pygame.init''.
* ''delay'': Pausa el proceso el número de milisegundos indicado.
* ''set_timer'': Crea un evento al cual se llamará cada ''x'' milisegundos indicados.
=== Clase Clock ===
Es la clase //helper// para ayudar a controlar el tiempo. Tiene los siguientes métodos:
* ''tick''
* ''tick_busy_loop''
* ''get_time''
* ''get_rawtime''
* ''get_fps''
==== Cómo... ====
* Coger la **posición actual del mouse** mediante la línea ''x, y = pygame.mouse.get_pos()''
===== Cómo... (avanzado) =====
==== Utilizar PyGame sin la ventana ====
Para así utilizar otro motor de rendirazado o realizar test... Antes de importar pygame definimos las variables con las que se inicializará este.
import os
os.environ['SDL_VIDEODRIVER'] = 'dummy'
import pygame
pygame.init()
pygame.display.set_mode((1,1))
while 1:
events = pygame.event.get()
for e in events:
pass
==== Toggle Fullscreen ====
def toggle_fullscreen():
screen = pygame.display.get_surface()
tmp = screen.convert()
caption = pygame.display.get_caption()
cursor = pygame.mouse.get_cursor() # Duoas 16-04-2007
w,h = screen.get_width(),screen.get_height()
flags = screen.get_flags()
bits = screen.get_bitsize()
pygame.display.quit()
pygame.display.init()
screen = pygame.display.set_mode((w,h),flags^FULLSCREEN,bits)
screen.blit(tmp,(0,0))
pygame.display.set_caption(*caption)
pygame.key.set_mods(0) #HACK: work-a-round for a SDL bug??
pygame.mouse.set_cursor( *cursor ) # Duoas 16-04-2007
return screen
===== Notas =====
* Elementos que podrían estar bien mirarse: ''sprite'', ''camera'' o ''movie''.
==== Un ejemplo significativo ====
import pygame, random
pygame.init()
screen = pygame.display.set_mode([300,100])
screen.fill([255,255,255])
mainloop, x,y, color, fontsize, delta, fps = True, 25 , 0, (32,32,32), 35, 1, 30
clock = pygame.time.Clock() # create clock object
while mainloop:
tick_time = clock.tick(fps) # milliseconds since last frame
pygame.display.set_caption("press Esc to quit. FPS: %.2f" % (clock.get_fps()))
fontsize = random.randint(35, 150)
myFont = pygame.font.SysFont("None", fontsize)
color = (random.randint(0,255), random.randint(0,255), random.randint(0,255))
screen.fill((255,255,255))
screen.blit(myFont.render("I love the pygame cookbook", 0, (color)), (x,y))
for event in pygame.event.get():
if event.type == pygame.QUIT:
mainloop = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
mainloop = False
pygame.display.update()
==== Ejemplos ====
* {{fw:pygame:scrolling.zip|Scrolling}}, de [[http://blog.shinylittlething.com/2009/08/08/pygame-parallax-scrolling-in-2d-games/]].
==== Otros... ====
=== GameObjects ===
Es un paquete que se encuentra en [[http://code.google.com/p/gameobjects/]] con varias clases de ayuda para la creación de juegos con Python.
* {{fw:pygame:gameobjects.0.0.3.rar}}