Capitulo 4

41
Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys [email protected] Programación de Juegos con PyGame Capitulo 4: Modulos Key, Image, Surface, Rect 1

description

Capitulo 4 del curso

Transcript of Capitulo 4

Page 1: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

Programación de Juegos con PyGame

Capitulo 4: Modulos Key, Image, Surface, Rect

1

Page 2: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

pygame.keyModulo que permite gestionar el disposito del teclado (Si no saben cual es el teclado

miren hacia abajo y lo veran :P)

Como ya vimos en el capitulo anterior la cola de eventos obtiene eventos como pygame.KEYDOWN y pygame.KEYUP cuando se pulsan o sueltan las teclas del teclado respectivamente. Cada evento tiene una atributo llamado key que es un identificador en entero que representa cada tecla del teclado.

El evento pygame.KEYDOWN tiene un atributo adicional llamado unicode, y otro scancode. unicode representa un único caracter que es la traducción completa del caracter ingresado por teclado. Teniendo en cuenta las teclas de composición y mayúsculas. scancode representa el código de tecla específico de la plataforma. Este código podría ser diferente de un teclado a otro, aunque es útil para la selección de teclas raras como las teclas multimedia.

Existen muchas constantes de teclado que se utilizadan para representar teclas. La siguiente es una lista con todas esas constantes:

Constante ASCII Nombre habitualK_BACKSPACE \b backspaceK_TAB \t tabK_CLEAR clearK_RETURN \r returnK_PAUSE pauseK_ESCAPE escapeK_SPACE spaceK_EXCLAIM ! exclaimK_QUOTEDBL ” quotedblK_HASH # hashK_DOLLAR $ dollarK_AMPERSAND & ampersandK_QUOTE quoteK_LEFTPAREN ( left parenthesisK_RIGHTPAREN ) right parenthesisK_ASTERISK * asteriskK_PLUS + plus signK_COMMA , commaK_MINUS - minus signK_PERIOD . periodK_SLASH / forward slashK_0 0 0K_1 1 1K_2 2 2K_3 3 3K_4 4 4K_5 5 5K_6 6 6K_7 7 7K_8 8 8K_9 9 9K_COLON : colonK_SEMICOLON ; semicolonK_LESS < less-than signK_EQUALS = equals signK_GREATER > greater-than sign

2

Page 3: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

K_QUESTION ? question markK_AT @ atK_LEFTBRACKET [ left bracketK_BACKSLASH \ backslashK_RIGHTBRACKET ] right bracketK_CARET caretK_UNDERSCORE _ underscoreK_BACKQUOTE ` graveK_a a aK_b b bK_c c cK_d d dK_e e eK_f f fK_g g gK_h h hK_i i iK_j j jK_k k kK_l l lK_m m mK_n n nK_o o oK_p p pK_q q qK_r r rK_s s sK_t t tK_u u uK_v v vK_w w wK_x x xK_y y yK_z z zK_DELETE deleteK_KP0 keypad 0K_KP1 keypad 1K_KP2 keypad 2K_KP3 keypad 3K_KP4 keypad 4K_KP5 keypad 5K_KP6 keypad 6K_KP7 keypad 7K_KP8 keypad 8K_KP9 keypad 9K_KP_PERIOD . keypad periodK_KP_DIVIDE / keypad divideK_KP_MULTIPLY * keypad multiplyK_KP_MINUS - keypad minusK_KP_PLUS + keypad plusK_KP_ENTER \r keypad enterK_KP_EQUALS = keypad equalsK_UP up arrowK_DOWN down arrowK_RIGHT right arrowK_LEFT left arrowK_INSERT insertK_HOME home

3

Page 4: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

K_END endK_PAGEUP page upK_PAGEDOWN page downK_F1 F1K_F2 F2K_F3 F3K_F4 F4K_F5 F5K_F6 F6K_F7 F7K_F8 F8K_F9 F9K_F10 F10K_F11 F11K_F12 F12K_F13 F13K_F14 F14K_F15 F15K_NUMLOCK numlockK_CAPSLOCK capslockK_SCROLLOCK scrollockK_RSHIFT right shiftK_LSHIFT left shiftK_RCTRL right ctrlK_LCTRL left ctrlK_RALT right altK_LALT left altK_RMETA right metaK_LMETA left metaK_LSUPER left windows keyK_RSUPER right windows keyK_MODE mode shiftK_HELP helpK_PRINT print screenK_SYSREQ sysrqK_BREAK breakK_MENU menuK_POWER powerK_EURO euro

El teclado tambien tiene una lista de estados de combinaciones que pueden ser montados a través de una lógica binaria.

KMOD_NONE KMOD_LSHIFT KMOD_RSHIFT KMOD_SHIFT KMOD_CAPS KMOD_LCTRL KMOD_RCTRL KMOD_CTRL KMOD_LALT KMOD_RALT KMOD_ALT KMOD_LMETA KMOD_RMETA KMOD_META KMOD_NUM

4

Page 5: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

KMOD_MODE

get_focused

Esta función devolvera verdadero cuando la ventana de visualización contiene el foco del teclado. Si se necesita que la ventana no pierda el foco del teclado, se puede utilizar pygame.event.set_grab para capturar todas las entradas de teclado.

sintaxis:pygame.key.get_focused() -> return bool

get_pressed

Devuelve una secuencia de valores lógicos (booleans) representando el estado de cada tecla en el teclado. Utilice los valores de constante de tecla como índice de la secuencia. Un valor verdadero significa que el botón esta presionado.

Tenga en cuenta que obtener la lista de las teclas pulsadas con esta función no es la forma apropiada de gestionar la entrada de texto por parte del usuario. No hay forma de conocer el orden de las teclas pulsadas, y las pulsaciones muy rápidas de teclas pueden pasar desapercibidas entre dos llamadas a get_pressed. Tampoco hay forma de trasladar las teclas pulsadas a un valor de caracter completamente imprimible por lo que para un mejor manejo de las entradas de teclado por parte de usuario se recomienda realizar un manejo mediante la cola de eventos con los eventos pygame.KEYDOWN.

sintaxis:pygame.key.get_pressed() -> return bools

get_mods

Devuelve un entero representando una mascara con todos las teclas que estan siendo presionadas. Utilizando lógica binaria puedes verificar si una tecla como shift está pulsada, el estado de capslock y más.

sintaxis:pygame.key.get_mods() -> return int

set_mods

Crea una mascara binaria con las constantes de las teclas que deseas imponer sobre tu programa.

sintaxis:pygame.key.set_mods(int) -> return None

set_repeat

5

Page 6: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

Cuando la funcionalidad de repetición de teclas está habilitada en el teclado, las teclas que quedan presionadas generan múltiples eventos de tipo pygame.KEYDOWN. El parrámetro delay (tiempo de retraso) es el número de milisegundos transcurridos antes de enviar el primer evento. Luego el resto de los eventos se enviarán en ese intervalo de milisegundos.

Si no especifica argumentos la repetición de teclas quedará deshabilitada.

sintaxis:pygame.key.set_repeat() -> return Nonepygame.key.set_repeat(delay, interval) -> return None

Nota: Cuando se inicializa pygame la repetición de teclas está deshabilitada.

get_repeat

Esta función cumple una tarea similar a set_repeat, solo que nos muestra el intervalo de milisegundos en lugar de definirlo.

sintaxis:pygame.key.get_repeat() -> return (delay, interval)

name

Devuelve el nombre descriptivo de la constante del telclado, ya que no todas los caracteres se pueden representar (en realidad todos los caracteres se pueden representar mediente su codigo).

sintaxis: pygame.key.name(key) -> return string

pygame.imageEs el Módulo de pygame encargador de la transferencia (leer/grabar imagenes desde ficheros) de imagen.

El módulo image contiene funciones para leer y grabar imágenes, como así también para transferir superficies a formatos accesibles para otros paquetes.

Note que no hay una clase Image, todas la imagenes se cargan como objetos Surface. La clase Surface es la que se encarga de su manipulacion, la misma permite operaciones como dibujar lineas, pintar pixeles, capturar regiones, etc.

El módulo image es una dependencia importante de pygame, aunque el soporte extendido a formatos es opcional. Por defecto solo puede cargar imágenes BMP sin compresión; pero cuando pygame se provee con soporte de imágenes completo, la función pygame.image.load() puede interpretar los siguientes formatos:

6

Page 7: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

JPG PNG GIF(sin animación) BMP PCX TGA (sin compresión) TIF LBM (y PBM) PBM (y PGM, PPM) XPM

La funcionalidad de guardado imágenes solo soporta un conjunto reducido de estos formatos. Puede grabar o almacenar imagenes en los siguientes formatos:

BMP TGA PNG JPEG

Aun asi la ide de PyGame no es especificamete cargar imagenes, por ello el grupo reducido de formatos de imagenes soportados por la API para cargar y guardar imagenes desde ficheros, aun asi no estamos del todo perdidos ya que la funcionalidad de este modulo se puede extender utilizando la liberia PIL junto con PyGame.

load

Funcion para cargar una nueva imagen desde un archivo. se puede pasar como parametro tanto la ruta del archivo como un objecto file de python.

Pygame determina automaticamente el tipo de formato archivo (por ejemplo, si es un gif o bmp) y generará un nuevo objeto Surface de acuerdo a esa información. En algunos casos necesitará conocer la extensión del archivo (por ejemplo las imagenes GIF deberían terminar en ”.gif”). Si utiliza un objeto archivo en formato crudo, seguramente necesitará enviar el nombre original del archivo como el argumento namehint.

La superficie retornada contendrá el mismo formato de color, colores clave o transparencia alpha que el fichero del que proviene. Generalmente cuando cargue imagenes que uilicen algun algoritmo de comprecion o canal alfa devera llamar al metodo Surface.convert() sin argumentos para crear una copia que se pueda imprimir mas rápido en pantalla.

Para imágenes con transparencia alpha, como en las imágenes .png, use el método convert_alpha() luego de cargar la imágen, así la superficie resultante también tendrá transparencia.

Tener en Cuenta que PyGame no siempre tendrá soporte para todos los formatos. Como mínimo soportará el formato BMP sin compresión. Si pygame.image.get_extended() retorna True, usted podría ser capaz de cargar la mayoría de las imágenes, incluyendo png, jpg y gif.

sintaxis:pygame.image.load(filename): return Surfacepygame.image.load(fileobj, namehint=""): return Surface

7

Page 8: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

save

Permite guardar o almacenar una imagen en el disco.

Como ya se mencion pygame solo puede guardar la superficie como algunos de los posibles tipos de formato de imagen BMP, TGA, PNG o JPEG. Si la extensión del nombre de archivo no se reconoce, se utilizará por defecto .TGA. Tanto los formatos TGA como BMP generan archivos sin compresión.

sintaxis:pygame.image.save(Surface, filename): return None

get_extended

Consulta si se pueden cargar los formatos de imagen extendidos.

Si el paquete de pygame fue construido (Compilado Recordar que PyGame aunque extiende muchas cosas internamente sigue siendo un envoltorio de la Libreria SDL) con los formatos de imagen extendido esta función retornará True. Aún así no es posible determinar que formatos estarán disponibles, generalmente en la mayoria de los paquetes podrá manipular todos los formatos.

sintaxis:pygame.image.get_extended(): return bool

tostring

Transfiere una imagen a una cadena de texto string.

Genera una cadena que pude transferirse con el método fromstring en otros paquetes de imágenes de python. Algunos paquetes de imagen de python prefieren sus imágenes en el formato “de abajo hacia arriba”, por ejemplo el paquete PyOpenGL). Se invertirá verticalmente la cadena retorno si envía True como valor para el argumento flipped.

El argumento format es una cadena con uno de los siguiente valores. Note que solo las superficies de 8 bits pueden usar el formato “P”. Los otros formatos funcionarán con cualquier superficie. Ademas note que otros paquetes de imágenes de python suportan mas formatos que pygame.

Cadena Formato SuperficieP superficies de 8 bits con paleta.RGB imagen de 24 bits.RGBX imagen de 32 bits con un espacio sin utilizar.RGBA imagen de 32 bits con un canal alpha (transparencia).ARGB imagen de 32 bits con canal alpha en primer lugar.RGBA_PREMULT imagen de 32 bits bajo la escala del canal alpha.ARGB_PREMULT imagen de 32 bits bajo la escala del canal alpha en primer lugar.

sintaxis:

8

Page 9: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

pygame.image.tostring(Surface, format, flipped=False): return string

fromstring

Genera una nueva superficie desde una cadena.

Esta función toma argumentos similares a pygame.image.tostring(). El argumento size es una tupla con números que representan el ancho y alto. Puede destruir la cadena original una vez que la nueva superficie se ha creado.

El formato y tamaño de la imagen debe coincidir exactamente con el mismo tamaño de la cadena. Se lanzará una excepción en caso contrario.

sintaxis:pygame.image.fromstring(string, size, format, flipped=False): return

Surface

frombuffer

Genera una nueva superficie que comparte los datos dentro de una cadena.

Genera una nueva superficie que comparte los datos de los pixeles directamente desde la cadena. Esta función toma los mismos argumentos que pygame.image.fromstring(), pero no puede invertir verticalmente los datos de origen.

Esta Funcion Funcionará mucho mas rápido que pygame.image.fromstring dado que no se alojan o copian datos de pixeles.

sintaxis:pygame.image.frombuffer(string, size, format): return Surface

SurfaceObjecto que pygame utiliza para representar y trabajar con las superficies (Imagenes

en memoria del programa o script)

Un objeto Surface de pygame se utiliza para representar cualquier imagen. La superficie tiene un formato de pixel y resolución fija. Las superficies con pixeles de 8 bits usan una paleta de 256 colores.

Invoque pygame.Surface() para crear un nuevo objeto image. La superficie será completamente negra. El único argumento requerido es el tamaño. La superficie se creará con el formato que mejor coincida con la pantalla actual si no se especifican los argumentos adicionales.

El formato de pixel se puede controlar especificando la profundidad de colores o una superficie existente. El argumento flags es una combinación de características adiciones para la superficie. Puede utilizar cualquier combinación de estas:

9

Page 10: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

HWSURFACE: Genera la imagen en la memoria de video. SRCALPHA: El formato de pixel incluirá transparencias por pixel.

Ambas opciones son solo una solicitud, tal vez no sea posible para todos los modos de video

Los usuarios avanzados pueden combinar un conjunto de opciones con un valor depth. El argumento masks es un conjunto de 4 números enteros que especifica cuales bits representan a cada color en el pixel. Las superficies normales no requieren el argumento mask.

Las superficies pueden tener varios atributos adicionales como planos alpha, colores clave o recortes. Estas funciones afectan principalmente a la forma en que se imprime la superficie sobre otra. Las rutinas blit intentarán usar aceleración de hardware cuando sea posible, en caso contrario usarán métodos de impresión por software muy optimizados.

Existen tres tipos de transparencia en pygame: colores clave, transparencia de superficie, y transparencia de pixel. La transparencia de superficie se puede combinar con colores clave, pero las imágenes con transparencia de pixel no puede usar los otros modos. La transparencia por color clave hace transparente un solo color. No se imprimirán los pixeles que coincidan con el color clave. La transparencia de superficie es un valor individual que cambia la transparencia de la imagen completa. Una transparencia de superficie de 255 será opaca mientras que un valor de 0 será completamente transparente.

La transparencia de pixel es diferente porque se almacena el valor de transparencia de cada pixel. Esto permite crear efectos de transparencia mas precisos, pero es algo mas lento. La transparencia de pixel no se puede mezclar con los otros tipos de transparencia.

Existe soporte para acceder a los pixels de la superficie. El acceso pixels en superficies de hardware es lento y no se recomienda. Estos métodos son adecuados para acceso simple, pero serán considerablemente lentos cuando realice mucho trabajo de pixels con ellos. Si planea realizar mucho trabajo a nivel de pixels se recomienda usar el módulo pygame.surfarray que puede tratar a las superficies como vectores de varias dimensiones (y es bastante veses mas rapido rápido).

Cualquier función que acceda directamente a los datos de pixels de la superficie necesitarán que la superficie esté bloqueada. Estas funciones pueden bloquear (block()) o desbloquear (unlock()) las superficies por ellas mismas si ayuda, pero, si habrá una sobrecarga muy grande de múltiples bloqueos o desbloqueos si se llama a esta función muchas veces. Es mejor bloquear manualmente la superficie antes de llamar a las funciones muchas veces, y luego desbloquear la superficie cuando se halla finalizado. Todas las funciones que necesitan bloquear la superficie lo indican en la documentación. Recuerde dejar la superficie bloqueada solo mientras sea necesario.

Los pixels de la superficie se almacenan internamente como un número individual que tiene todos los colores agrupados. Use las funciones Surface.map_rgb() y Surface.unmap_rgb() para convertir entre valores individuales (rojo, verde y azul) en colores agrupados para la superficie.

Las superficies también pueden ser una referencia a una sección de otra superficie. Se generan con el método Surface.subsurface(). Cualquier cambio en alguna de las dos superficie que verá reflejado en ambas.

Cada superficie contiene un área de recorte. Por defecto el área de recorte cubre la superficie entera. Si esta área de modifica, todas las operaciones de dibujado solo afectarán

10

Page 11: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

un área mas pequeña.

sintaxis:pygame.Surface( (width, height), flags=0, depth=0, masks=None): return

Surfacepygame.Surface( (width, height), flags=0, Surface): return Surface

blit

La operacion mas comun en todo juego diria yo, que es la de copiar una imagen o parte de una imagen y pegarla o imprimirla sobre otra superficie, este metodo lo realiza o deve llamarlo la superficie destino (superficie donde quiero imprimir imagen) casi siempre sera la superficie que representa la pantalla osea screen que es el nombre como la vine llamando durante todo este curso. El metodo tiene varios argumentos que a continuacion listare de acuerdo a como deven ser colocados y explicare su funcion, el unico obligatorio es source el resto son opcionales:

source: Se refiere a la superficie origen osea de la que se quiere copiar la superficie completa o parte de ella, este deve ser un atributo de tipo Surface.

dest: Este atributo puede ser tanto una tupla (x, y), como un objecto Rect, representa en que posicion de la superficie destino se dibujara (comenzara a dibuar) la superficie origen, como referencia es donde aparecera dibujada la esquina superior izquierda de la superfice origen, si no se pasa argumento a este parametro asumira como posicion destino a los valores (0, 0).

area: Este argumento es opcional, y representa la porcion rectangular de imagen que queremos copiar, si el parametro es None se copiara toda la imagen. El parametro area puede ser algunos de los siguientes:

rect(x, y, w, h)((x, y), (w, h))

Donde x,y son la posicion x,y desde donde se empezara a copiar, w(width) es el ancho y h (height) es el alto del area de recorte. opcionalmete se puede utilizar un objecto rect para pasar estos parametros.

Special_flags: La opción special_flags puede tomar los siguientes valores:

BLEND_ADD BLEND_SUB BLEND_MULT BLEND_MIN BLEND_MAX BLEND_RGBA_ADD BLEND_RGBA_SUB BLEND_RGBA_MULT BLEND_RGBA_MIN BLEND_RGBA_MAX BLEND_RGB_ADD BLEND_RGB_SUB BLEND_RGB_MULT

11

Page 12: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

BLEND_RGB_MIN BLEND_RGB_MAX

Nota: tal vez se agreguen mas opciones de impresión en el futuro. El rectángulo retornado representa el área de los pixels afectados, excluyendo cualquier pixel fuera de la superficie destino o el área de recorte. Ademas Se ignorarán los pixels alpha cuando se imprima sobre una superficie de 8 bits.

sintaxis:surface.blit(source, dest, area=None, special_flags = 0): return Rect

Aqui muestro algunos codigo de ejemplo para terminar de aclarar la situacion y evitar confuciones en el Futuro:

Suponer que tenemos 2 superfices, por sinplicidad las llamaremos sup_origen y sup_destino (que en el codigo fuente sera screen) ambas de 400x300 pixeles osea para quien no leyo el capitulo 1, 400 pixeles de ancho por 300 pixeles de alto, Nota las imagenes podrian ser de cualquier tamaño en fin estas son mis superficies (imagenes en memoria):

sup_origen

12

Page 13: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

sup_destino

El color con tono semi amarillo es a proposito para que puedan diferenciar la superficie de la Hoja. ahora vamos a proponer varios problemas sencillos (que resolvere y mostrare el resultado), todas estas pruevas seran via consola, a no preocuparse si a primera vista la pantalla de pygame parece estar tildada o no responder, lo que pasa es que no actualizamos los eventos.

Antes de todo, importar e inicializar pygame

>>> import os>>> import pygame>>> from pygame.locals import *>>> pygame.init()(6, 0)

Crear la superficie que representa la pantalla y cargar las imagenes

>>> screen = pygame.display.set_mode((400, 300))>>> path = 'D:\\Cursos\\Juegos\\Curso PyGame'

Nota: la variable path es el directorio donde actualmente tengo las imagenes, como veran estoy en windows, en linux pondriamos lo siguiente suponiendo que las imagenes esten en /home/username/fotos/. path seria:

>>> path = '/home/username/fotos'

>>> sup_origen = pygame.image.load(os.path.join(path, 'l2c5.bmp'))>>> sup_destino = pygame.image.load(os.path.join(path, 'blank.bmp'))

para ver que estas son las superficies cargadas las mostrare:

>>> screen.blit(sup_origen, (0, 0))<rect(0, 0, 400, 300)>>>> pygame.display.flip()

13

Page 14: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

>>> screen.blit(sup_destino, (0, 0))<rect(0, 0, 400, 300)>>>> pygame.display.flip()

Ya vimos como copiar la imagen completamente Ahora supongamos que queremos copiar (lo correcto a decir es blitear) al sup_origen sobre la sup_destino en la posicion central osea en la pos 200, 150

>>> sup_destino.blit(sup_origen, (200, 150))<rect(200, 150, 200, 150)>>>> pygame.display.flip()

14

Page 15: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

Si quisieramos copiar solo una porcion por ejemplo el area (150, 0, 100, 100)

>>> screen.blit(sup_origen, (200, 150), (150, 0, 100, 100))<rect(200, 150, 100, 100)>>>> pygame.display.flip()

convert

15

Page 16: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

Cambia el formato de pixel de una imagen.

Genera una nueva copia de la superficie con un formato de pixel modificado. El nuevo formato de pixel se puede determinar a partir de otra superficie existente. Otra posibilidad es especificar los argumentos depth, flags y mask, de manera similar a pygame.Surface()

La superficie nueva tendrá el mismo formato de pixel de la pantalla si no envía ningún argumento. Este formato será el mas rápido de imprimir. Es una buena idea convertir todas las superficies antes de imprimirlas varias veces.

La superficie convertida podría no tener pixels alpha, dado que serán eliminados si la superficie original los tenía. Vea la función Surface.convert_alpha() para crear o preservar superficies con canal alpha.

sintaxis:Surface.convert(Surface): return SurfaceSurface.convert(depth, flags=0): return SurfaceSurface.convert(masks, flags=0): return SurfaceSurface.convert(): return Surface

convert_alpha

Genera una nueva copia de la superficie con el formato de pixel deseado. La superficie nueva tendrá un formato adecuado para imprimirse mas rápidamente el formato indicado con canal alpha. Si no se especifica el argumento surface, la nueva superficie se optimizará para el formato de pantalla actual.

A diferencia del método Surface.convert(), el formato de pixel para la imagen nueva podría no ser exactamente el mismo que se pide, aunque se optimizará para imprimirse sobre la superficie destino.

sintaxis:Surface.convert_alpha(Surface): return SurfaceSurface.convert_alpha(): return Surface

Nota: tanto al usar convert() como convert_alfa() adaptamos la superficie para que obtimize su manejo, pero esto avese trae perdida de definicion en algunos formatos de imagenes.

copy

Genera una nueva copia de la superficie.

Hace una copia duplicada de un superficie. La superficie nueva tendrá el mismo formato de pixel, paletas de colores y configuración de transparencia que la original.

sintaxis:Surface.copy(): return Surface

fill

16

Page 17: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

Pinta la superficie con un color solido. Se pintará la superficie entera si no se especifica el argumento rect. El argumento rect limitará la modificación al área especificada. La operación de pintado también se limitará por el área de recorte de la superficie.

El argumento color puede ser una secuencia RGB, RGBA o un índice de una paleta de colores. Si usa el formato RGB se ignorará el componente alpha (una parte de RGBA) a menos que la superficie use transparencia por pixel (atributo SRCALPHA).

BLEND_ADD BLEND_SUB BLEND_MULT BLEND_MIN BLEND_MAX BLEND_RGBA_ADD BLEND_RGBA_SUB BLEND_RGBA_MULT BLEND_RGBA_MIN BLEND_RGBA_MAX BLEND_RGB_ADD BLEND_RGB_SUB BLEND_RGB_MULT BLEND_RGB_MIN BLEND_RGB_MAX

sintaxis:Surface.fill(color, rect=None, special_flags=0): return Rect

Esta función retornará el área afectada de la superficie.

set_colorkey

Define el color clave de transparencia.

Define el color clave para la superficie. Cuando imprima esta superficie sobre otra, cualquier pixel que tenga el mismo color que el color clave no se imprimirá. El argumento color puede ser un color RGB o un indice de una paleta de colores. Si se envía None como argumento entonces se deshabilitará el color clave.

Se ignorará el color clave si la superficie tiene un formato para usar valores alpha por pixel. La transparencia por color clave se puede mezclar con la transparencia a nivel de superficie.

Se puede definir el argumento opcional flags a pygame.RLEACCEL para obtener mejor rendimiento en pantallas que no tengan aceleración de video. Una superficie RLEACCEL puede ser mas lenta de modificar, pero se imprimirá mas rápido.

El color que mas comunmente se usa como canal Alfa es el MAGENTA por ser raro que aparesca en pantalla. aca muestro como se vera una misma imagen sin y con color_key().

Sintaxis:Surface.set_colorkey(Color, flags=0): return NoneSurface.set_colorkey(None): return None

17

Page 18: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

(ejemplo_01.py)

get_colorkey

Obtiene el color clave de transparencia actual. Retorna el color clave actual de la superficie. Si la superficie no tiene color clave la función retornará None.

sintaxis:Surface.get_colorkey(): return RGB or None

set_alpha

Define el valor de transparencia para la superficie. Cuando se imprima esta superficie sobre otra los pixels se dibujarán ligeramente transparentes. El valor de transparencia es un número entero de 0 a 255, 0 representa completamente transparente y 255 completamente opaco. Se deshabilitará la transparencia de la superficie si se pasa None como valor de transparencia.

Esta transparencia es diferente a la transparencia por pixel. Se ignorará este valor de transparencia si la superficie contiene pixels con transparencia. Si la superficie contiene transparencia por pixel, cuando llame a esta función con el argumento None se deshabilitará esa transparencia por pixel.

El argumento adicional flags se puede definir como pygame.RLEACCEL para obtener mayor rendimiento en pantallas que no tengan aceleración de video. Una superficie RLEACCEL será mas lenta de modificar, aunque será mas rápido imprimirla sobre otra.

sintaxis:Surface.set_alpha(value, flags=0): return NoneSurface.set_alpha(None): return None

(ejemplo_02.py)

get_alpha

18

Page 19: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

Obtiene el valor de transparencia de la superficie, Retorna el valor de transparencia actual para la superficie. Se retornará None si el valor de transparencia no está definido.

sintaxis:Surface.get_alpha(): return int_value or None

lock

Bloquea los datos de pixel de una superficie para acceder a ellos. En la superficies aceleradas, los datos de pixels podrían estar almacenados en memoria de video volátil o en formas no lineales bajo compresión. Cuando se bloquea una superficie la información de pixels se convierte en un formato accesible. El código que lee o escribe valores de pixels necesitará que la superficie se bloquee para realizar esas tareas.

Las superficies no deberían permanecer bloqueadas mas de lo necesario. Una superficie bloqueada podría no mostrarse o ser manipulada por pygame.

No todas las superficies necesitan bloquease. El método Surface.mustlock() puede determinar si la superficie requiere bloquease. De todas formas, no hay desventaja al bloquear o desbloquear una superficie que no lo necesita.

Todas las funciones de pygame bloquearán o desbloquearán automáticamente los datos de la superficie si es necesario. Si una sección de código hace varias llamas para modificar la superficie, entonces se bloqueará y desbloqueará muchas veces la superficie. Por este motivo, es mucho mas útil bloquear la superficie manualmente, luego modificarla muchas veces y luego desbloquearla manualmente.

Es seguro anidar llamas para bloquear y desbloquear. La superficie solo se desbloqueará después de soltar el último bloqueo.

sintaxis:Surface.lock(): return None

unlock

Desbloquea los datos de pixels de la superficie luego de que ha sido bloqueada. La superficie desbloqueada podrá imprimirse nuevamente por pygame. Vea la documentación de Surface.lock() para mas detalles.

Todas las funciones de pygame bloquearán o desbloquearán automáticamente los datos de la superficie si es necesario. Si una sección de código hace varias llamas para modificar la superficie, entonces se bloqueará y desbloqueará muchas veces la superficie. Por este motivo, es mucho mas útil bloquear la superficie manualmente, luego modificarla muchas veces y luego desbloquearla manualmente.

Es seguro anidar llamas para bloquear y desbloquear. La superficie solo se desbloqueará después de soltar el último bloqueo.

sintaxis:Surface.unlock(): return None

19

Page 20: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

mustlock

Verifica si la superficie necesita bloquearse., Retorna True si la superficie se debe bloquear para acceder a sus datos de pixel. Usualmente las superficies de software pura no necesitan bloquease. Este método no se usa con frecuencia, dado que es seguro y mas rápido directamente bloquear todas las superficies como sea necesario.

Todas las funciones de pygame bloquearán o desbloquearán automáticamente los datos de la superficie si es necesario. Si una sección de código hace varias llamas para modificar la superficie, entonces se bloqueará y desbloqueará muchas veces la superficie. Por este motivo, es mucho mas útil bloquear la superficie manualmente, luego modificarla muchas veces y luego desbloquearla manualmente.

sintaxis:Surface.mustlock(): return bool

get_locked

Consulta si la superficie está bloqueada, Retorna True cuando la superficie está bloqueada. Esta función no se fija o preocupa sobre cuantas veces se ha bloqueado la superficie.

sintaxis:Surface.get_locked(): return bool

get_locks

Obtiene los bloqueos de la superficie. Retorna los bloqueos existentes para la superficie.

sintaxis:Surface.get_locks(): return tuple

get_at

Retorna el valor de color RGBA en la posición indicada. Si la superficie no tiene transparencia por pixel, entonces el valor alpha del color será siempre 255 (completamente opaco). Se lanzará una excepción IndexError si la posición del pixel está fuera del área de la superficie.

Obtener y definir los pixels de a uno a la vez es una tarea generalmente lenta para ser utilizada en un juego o una situación de tiempo real. Esta función bloqueará y desbloqueará la superficie temporalmente como sea necesario.

sintaxis:Surface.get_at( (x, y) ): return Color

20

Page 21: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

set_at

Define el valor de color RGBA o entero (si utiliza paleta) de un pixel. Si la superficie no tiene transparencia por pixel, entonces el valor alpha se ignorará. No tendrá ningún efecto definir pixels fuera del área total o el área de recorte de la superficie.

Obtener y definir los pixels de a uno a la vez es una tarea generalmente lenta para ser utilizada en un juego o una situación de tiempo real. Esta función bloqueará y desbloqueará la superficie temporalmente como sea necesario.

sintaxis:Surface.set_at( (x, y), Color): return None

set_clip

Define el área de recorte para la superficie. Cada superficie tiene una área de recorte activa. Este recorte es un rectángulo que representa a los pixels que se pueden modificar en una superficie. Toda la superficie se podrá modificar si se pasa None como área de recorte.

El área de recorte está siempre limitada al área de la superficie en sí misma. Si el rectángulo de recorte es mas grande, entonces se encogerá para caber dentro de la superficie.

sintaxis:Surface.set_clip(rect): return NoneSurface.set_clip(None): return None

get_clip

Obtiene el área de recorte actual de la superficie. Retorna una rectángulo que representa el área de recorte. La superficie siempre retornará un rectángulo válido que nunca estará por afuera de los bordes de la superficie. La superficie retornará el área completa de la misma si no se ha definido un área de recorte.

sintaxis:Surface.get_clip(): return Rect

subsurface

Retorna una nueva superficie que comparte sus pixels con su superficie pariente. La nueva superficie se considera hija de la original. Las modificaciones a los pixels de cualquier de las dos superficies afectará a la otra. La información de la superficie como el área de recorte o los colores clave son únicos para cada superficie.

La nueva superficie heredará la paleta, colores clave y configuración de transparencia de su padre.

21

Page 22: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

Es posible tener cualquier número de sub-superficies y sub-sub-superficies de una superficie. También es posible tener una sub-superficie de la pantalla principal si el modo de video no está acelerado por software.

sintaxis:Surface.subsurface(Rect): return Surface

get_size

Obtiene las dimensiones de una superficie. Retorna el ancho y alto de una superficie medida en pixels.

sintaxis:Surface.get_size(): return (width, height)

get_width

Obtiene el ancho de una superficie. Retorna el ancho de una superficie medida en pixels.

sintaxis:Surface.get_width(): return width

get_height

Obtiene la altura de una superficie.Retorna la altura de una superficies medida en pixels.

sintaxis:Surface.get_height(): return height

get_rect

Obtiene el área rectangular de una superficie. Retorna un nuevo rectángulo que cubre la superficie entera. Este rectángulo siempre comenzará en la posición (0, 0) y tendrá el ancho y alto idéntico al tamaño de la imagen.

Puede pasar valores clave como argumentos a esta función. Estos argumentos se aplicarán a los atributos del rectángulo antes de ser retornado. Un ejemplo podría ser mysurf.get_rect(center=(100,100)) para crear un rectángulo de la superficie con centro en la posición (100, 100).

sintaxis:Surface.get_rect(*\*kwargs): return Rect

22

Page 23: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

get_bitsize

Obtiene la profundidad de colores en bits del formato de pixel de la superficie. Retorna el número de bits utilizados para representar cada pixel. Este valor podría no coincidir exactamente con el número de bytes usados por pixel. Por ejemplo, una superficie de 15 bits requiere 2 bytes completos.

sintaxis:Surface.get_bitsize(): return int

get_bytesize

Obtiene el número de bytes utilizados por pixel de la superficie. Retorna el número de bytes utilizados por pixel.

sintaxis:Surface.get_bytesize(): return int

get_flags

Obtiene las opciones adicionales utilizadas por la superficie. Retorna el conjunto de propiedades de la superficie. Cada propiedad es un bit en la máscara de bits flags. Las propiedades habituales son HWSURFACE, RLEACCEL, SRCALPHA y SRCCOLORKEY. La lista completa de estas propiedades se puede encontrar en el archivo sdl_video.h.

sintaxis:Surface.get_flags(): return int

get_masks

Obtiene la máscara de bits necesaria para convertir entre un color RGB y un color empaquetado. Retorna la máscara de bits que se utiliza para empaquetar cada color en un número entero. Este valor no se necesita para el uso normal de pygame.

sintaxis:Surface.get_masks(): return (R, G, B, A)

set_masks

Define la máscara de bits necesaria para convertir entre un color RGB en un color en formato empaquetado. Esta función no se necesita para el uso habitual de pygame.

sintaxis:Surface.set_masks( (r,g,b,a) ): return None

23

Page 24: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

get_buffer

Obtiene un objeto buffer para los pixels de la superficie. Retorna un objeto buffer para los pixels de la superficie. El buffer se puede usar para acceder y manipular directamente los pixels.

Este método bloquea y desbloquea la superficie de forma implícita. El bloqueo a la superficie se anulará una vez que el objeto BufferProxy sea eliminado.

sintaxis:Surface.get_buffer(): return BufferProxy

Otros metodos que pertenecen a este modulo que no fueron explicados por considerar que no son metodos de mucha relevancia o importancia.

get_paletteget_palette_atset_paletteset_palette_atmap_rgbunmap_rgbget_parentget_abs_parentget_offsetget_abs_offsetget_pitchget_shiftsset_shiftsget_lossesget_bounding_rect

Rect

Pygame utiliza objetos Rect para almacenar y manipular areas rectangulares (Normalmente superficies). Un objeto Rect se puede crear a partir de una combinación de valores izquierda, arriba, ancho y alto. También se pueden crear desde objetos python que ya sean un objeto Rect o tengan un atributo de nombre rect.

Cualquier función de pygame que requiera un argumento Rect también acepta cualquiera de eso valores para construir un rectángulo. Esto hace mas sencillo crear objetos Rect en el aire como argumentos a funciones.

Los métodos de Rect que cambian la posición o el tamaño del rectángulo retornan una nueva copia del objeto con los cambios realizados. El rectángulo original no se modifica. Algunos métodos tiene una versión alternativa de estas funcionalidades pero que actúan sobre el objeto mismo y retornan None. Estos métodos alternativos se denotan con el sufijo “ip”.

El objeto Rect tiene varios atributos virtuales que se pueden usar para mover ,alinear o simplemente consultar de un rectángulo.

24

Page 25: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

top, left, bottom, right topleft, bottomleft, topright, bottomright midtop, midleft, midbottom, midright center, centerx, centery size, width, height w,h

Todos estos atributos se pueden consultar y asignar de la siguiente manera:

rect1.right = 10rect2.center = (20, 30)rect.width = 140 #es equivalente a rect.w = 140

Asignar un valor a size, width o height (tambien a w, h) cambia las dimensiones del rectángulo, todas las otras asignaciones mueven el rectángulo pero sin alterar el tamaño. Note que algunos atributos son números enteros y otros son pares de números enteros.

Si un rectángulo tiene atributos width o height distintos de cero, entonces retornarán True por una consulta distinta de cero. Algunos métodos retornan un rectángulo con tamaño 0 para representar un rectángulo inválido.

Las coordenadas para objetos Rect siempre son números enteros. Los valores de tamaño se pueden programar para tener valores negativos, pero estos se consideran no válidos para la mayoría de las operaciones.

Existen varios métodos para consultar colisiones con otros rectángulos. La mayoría de los contenedores de python se pueden utilizar para buscar colisiones entre varios rectángulos contra uno.

El área cubierta por un rectángulo no incluye los pixeles que se encuentran en el límite inferior y derecho. Si el borde inferior de un rectángulo es igual al borde superior de otro rectángulo (por ejemplo rect1.bottom = rect2.top), los dos ocupan la misma linea en pantalla pero no se superponen, y la consulta a rect1.colliderect(rect2) retornará False.

sintaxis:pygame.Rect(left, top, width, height): return Rectpygame.Rect((left, top), (width, height)): return Rectpygame.Rect(object): return Rect

move

Retorna una copia (copia no referencia) del rectángulo que está desplazado en la cantidad indicada. Los argumento dx e dy pueden ser cualquier valor entero, positivo o negativo.

sintaxisRect.move(dx, dy): return Rect

move_ip

permite mover al rectangulo las cantidades dx, dy. afecta al objeto receptor.

25

Page 26: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

sintaxis:Rect.move_ip(dx, dy): return None

clamp

Retorna una nuevo rectángulo desplazado para estar completamente dentro de otro rectángulo dado como parámetro. Si el rectángulo es demasiado grande para caber dentro del otro rectángulo, se posicionará en el mismo centro que el rectángulo del argumento, pero su tamaño no se cambiará.

sintaxis:Rect.clamp(Rect): return Rect

clamp_ip

Similar al método clamp, pero afecta al objeto receptor.

sintaxis:Rect.clamp_ip(Rect): return None

clip

Recorta un rectángulo dentro de otro. Retorna un nuevo rectángulo que se recorta para estar completamente dentro de otro indicado por parámetro. Si los dos rectángulos no están en colisión, se retornará un rectángulo de tamaño 0.

sintaxis:Rect.clip(Rect): return Rect

union

Retorna un nuevo rectángulo que cubre completamente el área de otros dos rectángulos dados como parámetro. Pueden haber áreas dentro del nuevo rectángulo que no estén en el área de los originales.

sintaxis:Rect.union(Rect): return Rect

union_ip

Similar al método union, pero que afecta al rectángulo receptor.

sintaxis:Rect.union_ip(Rect): return None

26

Page 27: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

unionall

Retorna la unión de un rectángulo con una secuencia de varios rectángulos.

sintaxis:Rect.unionall(Rect_sequence): return Rect

unionall_ip

La unión de varios rectángulos, afectando al objeto receptor. Similar al método unionall.

sintaxis:Rect.unionall_ip(Rect_sequence): return None

fit

Cambia el tamaño o mueve el rectángulo pero respetando su aspecto. Retorna un nuevo rectángulo desplazado y redimensionado para caber dentro de otro. Se preserva la proporción de aspecto del rectángulo original, por lo tanto el nuevo rectángulo puede ser mas pequeño que el ancho o alto del rectángulo final.

sintaxis: Rect.fit(Rect): return Rect

normalize

Corrige los tamaños negativos. Invertirá el ancho o alto de un rectángulo si tiene algún tamaño negativo. El rectángulo conservará la misma posición, pero con los lados alternados.

sintaxis:Rect.normalize(): return None

contains

Consulta si un rectángulo está dentro de otro. Retorna True cuando el argumento está completamente dentro del objeto receptor.

sintaxis:Rect.contains(Rect): return bool

collidepoint

Consulta si un punto está dentro de un rectángulo. Retorna True si el punto dado está dentro del rectángulo. Un punto sobre el costado derecho o inferior del rectángulo no se

27

Page 28: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

considera que está dentro del rectángulo.

sintaxis:Rect.collidepoint(x, y): return boolRect.collidepoint((x, y)): return bool

colliderect

onsulta si dos rectángulos están en contacto Retorna True si cualquier parte de alguno de los rectángulos están en contacto (excepto los bordes superior+inferior o derecha+izquierda), es el metodo que normalmente se usara en el control de coliciones entre Sprites.

sintaxis:Rect.colliderect(Rect): return bool

collidelist

Consulta si un rectángulo entra en contacto con una lista. onsulta si el rectángulo colisiona con otro de una secuencia de rectángulos. Se retorna el índice de la primer colisión que se encuentra. Se retorna el índice -1 si no se encuentran colisiones.

sintaxis:Rect.collidelist(list): return index

collidelistall

dem a collidelist solo que retorna una lista con el indice de todos los rectangulos con los que coliciona:

sintaxis:Rect.collidelistall(list): return indices

collidedict, collidedictall

Son Similares a collidelist y collidelistall en funcionamiento solo que estos toman como argumento un dicionario con rectangulos.

sintaxis:Rect.collidedict(dict): return (key, value)Rect.collidedictall(dict): return [(key, value), ...]

28

Page 29: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

Mi Primer Juego (Feo :P) un Pong

Introducion

Aunque este primer modulo apunta mas a aprender a usar la API PyGame para programar juegos y el curso en si se llama Programacion de Juegos con PyGame que seria de un curso de juego si lo unico que se esta haciendo es explicar que hacen los modulos a, b ,etc.. bueno ya explique la mayoria de los modulos importantes por lo que podemos avanzar un nivel mas y empezar a programar juegos, y que seria de un curso de programacion de juegos si como primer juego a programar no te colocaran un Pong, no es por que solo lo hagan en todos los cursos, yo lo hago mas como tributo al primer juego que revoluciono el mundo de las computadoras.

En todo desarrollo de un videojuego siempre suelen trabajar un GRUPO de personas, unas que llevaran la parte grafica, otras que llevaran la parte de programacion, otras que llevaran el guion, otras que llevaran la parte de sonido... Lo que pretendo decir es que tu no tienes porque saber de todo porque normalmente si te dedicas a esto trabajaras con otra gente y no tu solo, por lo que si eres programador, buscate a alguien que sea grafista o sepa dibujar para que te haga unos buenos graficos y no te pases horas y horas intentando dibujar una cosilla cuando hay gente que la va a hacer mucho mejor y en mucho menos tiempo u sino busca en internet ya que hay varios Sitios donde te puedes bajar los sprites.

Yo soy programador y no conozco a ningun grafista por lo que los graficos que utilizar‚ seran sacados de internet o dibujados por mi por lo que la calidad grafica no va ser excesiva (mas bien decepcionante, no tanto use formas basicas y un poco de degrado en Inskape para crearlas) enn fin haremos‚ lo que podamos.

La Idea

Como ya se menciono arriba vamos a hacer un juego sencillo llamdo pong o ping-pong, tenis o como quieran llamarle, en fin es un sencillo juego clasico, lo tomo como primer juego por ser dentro de todo sencillo de programar. Para los que no tengan idea de como es aca les dejo un captura de pantalla.

El Objectivo

El Objectivo del Juego va a ser marcar un gol, el primero de los participantes que meta 3 goles, sera declarado ganador y el juego acabara. Ahora analicemos los elementos que intervienen en el Juego:

Paleta o Raquetasolo se podra mover en forma vertical entre los limites inferiores y superiores.

PelotaTendra un movimiento rectilineo (se movera en linea recta sin hacer ninguna curva

estraña), aumentara su velocidad a medida de que rebota contra las raquetas, En funcion de

29

Page 30: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

la posicion en que golpee en las raquetas tomara una trayectoria u otra, es decir si se golpea con la parte superior tendera a ir hacia arriba y si es en la inferior tendera a ir hacia abajo.

Los Graficos

Como vimos es un juego sencillo que requiere solo 3 graficos (paleta_1, paleta_2 y pelota), a la cancha la dibujaremos mediante figuras basicas. aparte de eso necesitaremos 2 imagenes mas 1 para la pantalla de presentacion y otra para el menu (aunque esa parte la realizaran ustedes como ejercicio). bueno por el momento yo me encargare de los graficos de las raquetas y las pelotas, para acelerar esto las dibuje mediante Inkscape usando formas basicas y algo de degradado.

pueden verlas en la carpeta 'pong/imagenes/'

Armazon Principal

En Nuestro Juego deberiamos notar 2 bucles bien definidos el primero y mas externo visualizar la pantalla de presentacion hasta que se pulsa una tecla y en funcion de la tecla pulsada hace dos cosas: Empieza la partida o sale del juego. En el primer caso vemos el segundo bucle, que es la duracion de la partida, estara en ‚ el hasta que uno de los jugadores obtenga 3 puntos o se pulse la tecla ESCAPE.

Por lo tanto y usando nuestra plantilla basica para aplicaciones en pygame (al menos yo lo hago siempre ustedes haganlo como deseen :P), los datos de pantallas y otras constanstes que utilizaremos a lo largo del juego estaran definidos en el fichero constantes.py otro modulo que usare y que notaran que solo posee un grupo de constantes que representan colores:

#!/usr/bin/env python# -*- coding: utf-8 -*-

import pygamefrom pygame.locals import *

from colores import *

from constantes import *

def dibuja_cancha(surface): """ funcion que permite dibujar la cancha del juego utilizando funciones de dibujo basicas """ pygame.draw.rect(surface, VERDE_MEDIO, ((10,10),(ANCHO-20, ALTO-20)), 0) pygame.draw.rect(surface, BLANCO, ((30,30),(ANCHO-60, ALTO-60)), 2) pygame.draw.line(surface, BLANCO, (ANCHO/2,30), (ANCHO/2, ALTO-30), 2)

def main(): """ funcion principal donde se implementara el Juego """

30

Page 31: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

pygame.init() screen = pygame.display.set_mode(RESOLUCION) pygame.display.set_caption('Ping Pang Pong 0.0.1')

titulo = pygame.image.load('imagenes/fondo.png').convert_alpha()

jugando = False #bandera que avisa si se esta jugando la partida loop = True while loop: #screen.fill(NEGRO) screen.blit(titulo, (0, 0))

teclas = pygame.key.get_pressed()

#si se preciona la tecla escape Finaliza el Juego del juego if teclas[K_ESCAPE]: loop = False jugando = False

#estando en el bucle principal iniciara el juego elif teclas[K_RETURN]: jugando = True

#loop de la partida while jugando: screen.fill(NEGRO) dibuja_cancha(screen)

pygame.display.flip()

for evento in pygame.event.get(): if evento.type == pygame.QUIT: loop = False

pygame.display.flip()

for evento in pygame.event.get(): if evento.type == pygame.QUIT: loop = False

#finalizamos el juego antes de salir pygame.quit()

if __name__ == '__main__': main()

(vease el codigo en pong/paso_01.py)

Como vemos ej juego posee una extructura sencilla, se destaca la utilizacion de modulo pygame.key para captura del teclado, otro punto importante es que a la cancha la dibujamos usando funciones de dibujo basicas. Por el momento nuestro juego no esta completo ya que solo tenemos el menu pero seguiremos avanzando. Una primera captura para ver el menu y la pantalla de juego:

31

Page 32: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

menu

pantalla de juego

Las Paletas o Raquetas

En esta secion vamos a crear 1 clase paleta base y de ella derivaremos las clases que permitiran a los jugadores manejarlas, opcionalmente podriamos derivar una clase para implementar la AI del juego. En fin vamos a usar algunas herramientas de las que aprendimos hasta ahora de pygame.

32

Page 33: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

La Clase base Paleta:

Nuestra clase base necesita tener todo lo necesario para manejar las paletas y las imagenes y demas objectos que las componen, ademas devemos definir algunos metodos que nos permitan controlarla, para no complicar la sintaxis definiremos las paletas en otro archivo distinto llamado paleta.py aqui coloco el constructor de la clase, el metodo de reinicio, el metodo para controlar que la paleta no se salga de pantalla, el metodo que permitira moverla, y el metodo para dibujarla. Ademas agregaremos algunas constantes mas:

FRAME_RATE = 30 #cantidad de cuadros por segundoPALETA_SPEED = 5 #velocidad de la paletaMARGEN_SUP = 30 #limitante del margen superior de la canchaMARGEN_INF = ANCHO - 30 #limitante del margen inferior de la canchaISO_ARRIBA = 0 #constante que define la direcion hacia arribaISO_ABAJO = 1 #constante que define la direcion hacia abajo

class Paleta: """ Clase base para definir las raquetas o paletas del juego """ def __init__(self, img): """ constructor de la clase, el unico parametro que recibe es el de la imagen que se usara. """ #cargamos la imagen y la convertimos (yo use unos *.png) para #representar todas las imagenes del juego self.imagen = pygame.image.load(img).convert_alpha() #obtenemos un objecto rect a partir de la imagen, el cual usaremos #para manipularla self.rect = self.imagen.get_rect() #variable que almacenara los goles del jugador self.puntaje = 0

def init(self, pos): """ metodo que usaremos para inicializar las paletas antes de comensar cada partida nueva pos : tupla que representa la posicion (x,y) donde se centrara la imagen de la paleta y el rectangulo que maneja las coliciones """ self.rect.center = pos self.self.puntaje = 0 #reiniciamos la puntuacion

def mover(self, dir): """ metodo que permite mover la paleta, tanto hacia arriba como hacia abajo, o arriba. dir : parametro donde se especifica la direcion los parametros validos son: ISO_ARRIBA o ISO_ABAJO """ if dir == ISO_ARRIBA: self.rect.y -= PALETA_SPEED

33

Page 34: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

elif dir == ISO_ABAJO: self.rect.y += PALETA_SPEED

def controla(self): """ metodo que se usa para controlar que la paleta no se salga de la pantalla """ if self.rect.y < MARGEN_SUP: self.rect.y = MARGEN_SUP

elif (self.rect.y + self.rect.h) > MARGEN_INF: self.rect.y = MARGEN_INF

def update(self): pass

def drawn(self, surface): """ metodo para dibujar la paleta sobre una superficie, normalmente esa superficie sera la pantalla principal. """ surface.blit(self.imagen, self.rect)

Los Jugadores (Herenciando la Clase Paleta)

Como habran notado el metodo update() (Actualizar) esta vacio, y eso se deve a que como mencionamos anteriormente se herenciara la clase paleta para definir las clases que manejaran los jugadores y alli es donde definiremos dicho metodo, las paletas solo necesitan ser controladas por 2 teclas cada una para controlar la paleta del jugador 1 usaremos las teclas (A;B) y para controlar la paleta del jugador 2 usaremos las teclas direcionales (ARRIBA;ABAJO).

class Jugador1(Paleta): """ Clase que manipulara la paleta del jugador 1 """ def update(self): """ metodo que permitira actualizar la posicion de las paletas """ #capturo todas las teclas que hayan sido pulsadas teclas = pygame.key.get_pressed()

#mover arriba if teclas[K_q]: self.mover(ISO_ARRIBA)

#mover abajo elif teclas[K_q]: self.mover(ISO_ABAJO)

34

Page 35: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

class Jugador2(Paleta): """ Clase que manipulara la paleta del jugador 2 """ def update(self): """ metodo que permitira actualizar la posicion de las paletas """ #capturo todas las teclas que hayan sido pulsadas teclas = pygame.key.get_pressed()

#mover arriba if teclas[K_UP]: self.mover(ISO_ARRIBA)

#mover abajo elif teclas[K_DOWN]: self.mover(ISO_ABAJO)

Ahora que tenemos implementadas las clases que manejaran las paletas (para mas detalle vease pong/paleta.py) procedamos a importarlas y probarlas junto con el esqueleto de juego que habiamos diseñado con anterioridad.

#!/usr/bin/env python# -*- coding: utf-8 -*-

import pygamefrom pygame.locals import *

from colores import *

from paleta import Jugador1, Jugador2from constantes import *

def dibuja_cancha(surface): """ funcion que permite dibujar la cancha del juego utilizando funciones de dibujo basicas """ pygame.draw.rect(surface, VERDE_MEDIO, ((10,10),(ANCHO-20, ALTO-20)), 0) pygame.draw.rect(surface, BLANCO, ((30,30),(ANCHO-60, ALTO-60)), 2) pygame.draw.line(surface, BLANCO, (ANCHO/2,30), (ANCHO/2, ALTO-30), 2)

def main(): """ funcion principal donde se implementara el Juego """ pygame.init() screen = pygame.display.set_mode(RESOLUCION) reloj = pygame.time.Clock() #temporizador del juego pygame.display.set_caption('Ping Pang Pong 0.0.1')

#imagen del titulo titulo = pygame.image.load('imagenes/fondo.png').convert_alpha()

#instanciamos los objectos que manejara las paletas

35

Page 36: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

pal_1 = Jugador1('imagenes/paleta_a.png') pal_2 = Jugador2('imagenes/paleta_b.png')

jugando = False #bandera que avisa si se esta jugando la partida loop = True while loop: reloj.tick(FRAME_RATE) screen.blit(titulo, (0, 0))

teclas = pygame.key.get_pressed()

#si se preciona la tecla escape Finaliza el Juego del juego if teclas[K_ESCAPE]: loop = False jugando = False

#estando en el bucle principal iniciara el juego elif teclas[K_RETURN]: jugando = True #inicializamos las paletas pal_1.init((30, ALTO / 2)) pal_2.init((ANCHO - 30, ALTO/2 ))

#loop de la partida while jugando: #~ reloj.tick(FRAME_RATE) screen.fill(NEGRO) dibuja_cancha(screen)

#actualizamos los objectos pal_1.update() pal_2.update()

#los dibujamos sobre la pantalla pal_1.drawn(screen) pal_2.drawn(screen)

pygame.display.flip()

for evento in pygame.event.get(): if evento.type == pygame.QUIT: loop = False

pygame.display.flip()

for evento in pygame.event.get(): if evento.type == pygame.QUIT: loop = False

#finalizamos el juego antes de salir pygame.quit()

if __name__ == '__main__': main()

(vease pong/paso_02.py)

36

Page 37: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

Observar que ademas de agregar los 2 objectos paletas, en el bloque que pregunta si se preciono la tecla enter colocamos los metodos para resetear la poscicion de cada paleta, mas adelante agregaremos el metodo para resetear la pelota y por ultimo dentro del loop de juego introducio los metodos update() y drawn() para cada paleta, como vimos dichos metodos se encargan de mover y dibujar respectivamente las paletas. otro elemento agrega es el temporizador que aunque no he explicado todavia el modulo ya deven tener una idea de como funciona. Aca una captura de nuestro juego hasta el momento.

La Pelota

Bueno por lo visto el juego ya esta tomando forma solo nos esta faltando implementar el control de la pelota y sus coliciones con las paletas que es lo que trataremos en esta ultima parte de este capitulo. Programar la pelota es la parte mas complicada del juego por eso la deje para el final del mismo ya que tenemos que hacer que se mueva, cambie de direcion, aumente su velocidad, controlar si hace gol etc, lo bueno de esto es que no usaremos ninguna cosa estraña solo un poco de matematica simple. la clase aparte de contener la imagen y el rectangulo que la representara tendra los atributos x,y que representaran su poscion real (el rectangulo representara su posicion aproximada) y dos incrementadores dx y dy que definiran el incremento en cada una de las variables, los metodos tendran los mismos nombres que en las paletas pero su funcionamiento y argumentos diferiran un poco. Como siempre agregamos nuevas constantes:

class Pelota: """ Clase que se utilizara para manejar la pelota. """

37

Page 38: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

def __init__(self, imagen): """ constructor de la clase pelota el unico parametro que pide es la imagen que se usara para representar la pelota """ self.imagen = pygame.image.load(imagen).convert_alpha() self.rect = self.imagen.get_rect()

#posicion exacta del centro de la pelota dentro de la pantalla self.x = 0.0 self.y = 0.0

#imcrementos en las direciones x,y self.dx = 0.0 self.dy = 0.0

def reset(self): """ reseteala posicion de la pelota en la pantalla, normalmente esta deberia iniciar en el centro de la misma """ #centro la pelota en el centro de la pantalla self.rect.center = (ANCHO / 2, ALTO / 2) self.x = float(ANCHO / 2) self.y = float(ALTO / 2)

#calculo el incremento inicial de dy if random.random() > 0.5: self.dy = +1.5 else: self.dy = -1.5

#calculo el incremento inicial de dx if random.random() > 0.5: self.dx = +1.5 else: self.dx = -1.5

def controla(self, pal_a, pal_b): """ Esto no se deveria hacer (digo por lo de pasar una referencias a de las paletas ya que esto crea un enlace fuerte y ello se considera malo en la programacion orientada a objectos). En fin este metodo se encargara de controlar que la pelota no se salga de pantalla si choca con los bordes o las paletas ademas de incrementar su velocidad y cambiar su direcion. """

#pregunta si choco con la paleta A que esta a la izquierda if self.rect.colliderect(pal_a.rect): #compruebo si choco de la mitad para arriba if self.rect.centery < pal_a.rect.centery: self.dy -= 0.5

#sino choco con la parte de abajo else:

38

Page 39: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

self.dy += 0.5

#por ultimo invierto la direcion x y aumento la velocidad self.dx -= 0.5 self.dx = -self.dx

#ahora pregunta si choco con la paleta B que esta a la izquierda if self.rect.colliderect(pal_b.rect): #compruebo si choco de la mitad para arriba if self.rect.centery < pal_a.rect.centery: self.dy -= 0.5

#sino choco con la parte de abajo else: self.dy += 0.5

#por ultimo invierto la direcion x y aumento la velocidad self.dx += 0.5 self.dx = -self.dx

#ahora pregunto si choco con algunas de las paredes y cambio el #signo del incremento de y osea dy if self.rect.y < MARGEN_SUP or (self.rect.y + self.rect.h) > MARGEN_INF: self.dy = -self.dy

#ahora por ultimo compruevo si se hizo un gol e incrementos el contador #goles del jugador rival y ademas hay que reiniciar la posicion de la #pelota

#si la pelota toca el borde izquierdo de la pantalla implica que el #jugador B hizo un gol if self.rect.x < 0: # nota: los objectos son pasados por referencia por lo que la #siguiente operacion no se perdera pal_a.puntaje += 1 self.reset()

#si la pelota toca el borde izquierdo de la pantalla implica que el #jugador A hizo un gol elif (self.rect.x + self.rect.w) > ANCHO: # nota: los objectos son pasados por referencia por lo que la #siguiente operacion no se perdera pal_b.puntaje += 1 self.reset()

#en el titulo de la ventana colocaremos el puntaje de cada uno pygame.display.set_caption('Azul %d - Rojo %d' %(pal_a.puntaje, pal_b.puntaje))

def update(self, pal_a, pal_b): """ actualiza la posicion, velocidad y direcion y ademas devuelve el estado del juego: 0 - el juego sigue 1 - gano el jugador A

39

Page 40: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

2 - gano el jugador B """ self.controla(pal_a, pal_b)

#actualizo la posicion de la pelota self.x += self.dx self.y += self.dy self.rect.center = int(self.x), int(self.y)

#pregunto cuantos goles tiene cada jugador, si alguno tiene 3 o mas #retorno 1 o 2 avizando que el juego termino caso contrario devuelvo 0 if pal_a.puntaje >= 3: return 1 elif pal_b.puntaje >= 3: return 2 else: return 0

def drawn(self, surface): """ metodo para dibujar la pelota sobre una superficie, normalmente esa superficie sera la pantalla principal y ademas la pelota sera el ultimo objecto que se dibuje. """ surface.blit(self.imagen, self.rect)

Bueno por ultimo hay que modificar el esqueleto principal y agregar la pelota. Despues de tanto sufrimiento tenemos un Juego Completo. Aca pueden ver una captura de pantalla del juego corriendo para jugarlo y ver el codigo del juego en su version final vea o ejecute el script pong/final.py

Antes de de terminar: El juego se llama pong pero mientras escribia y documentaba el codigo de este juego se me ocurrio ponerle Ping, Pang, Pong el nombre no lo invente yo,

40

Page 41: Capitulo 4

Curso de: Programacion de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys → [email protected]

por si no saben era el nombre del Equipo de Bolos (Nada que ver con esto que supuestamente es un juego de tenis) de Homero en un capitulo de Los Simpson. Bue solo queria aclarar eso.

Saludos

41