Intro PygameCapitulo 3

19
Curso de: Programación de Juegos con PyGame Por: Ricardo D. Quiroga – L2Radamanthys [email protected] Programación de Juegos con PyGame Capitulo 3: Módulos: Event, Mouse y Draw 1

Transcript of Intro PygameCapitulo 3

Page 1: Intro PygameCapitulo 3

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

Programación de Juegos con PyGame

Capitulo 3: Módulos: Event, Mouse y Draw

1

Page 2: Intro PygameCapitulo 3

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

Eventos en PyGamePyGame nos proporciona un modulo especifico para manejar e interactuar con dichos

eventos, el manejo de los mismos los hace atraves de la implementación de una Cola de Eventos. Algo importante a resaltar es que la cola de eventos no funcionara a menos que se halla inicializado el modulo display y el de video.

La cola de eventos es una lista de Objectos Event, y posee varios métodos para trabajar con los eventos, ya sea desde consultar por si se lanzo un evento determinado, borrar dicho evento, extraerlo de la cola etc. Hay que notar que todos los eventos tienen un tipo definido, los tipo de eventos mas comunes son:

QUIT noneACTIVEEVENT gain, stateKEYDOWN unicode, key, modKEYUP key, modMOUSEMOTION pos, rel, buttonsMOUSEBUTTONUP pos, buttonMOUSEBUTTONDOWN pos, buttonJOYAXISMOTION joy, axis, valueJOYBALLMOTION joy, ball, relJOYHATMOTION joy, hat, valueJOYBUTTONUP joy, buttonJOYBUTTONDOWN joy, buttonVIDEORESIZE size, w, hVIDEOEXPOSE noneUSEREVENT code

Aunque para obtener el estado de los dispositivos de entrada de una manera mas limpia es preferible acceder a ellos mediante los modulos encargados de manejarlos en ves de estar accediendo a la cola de eventos, si usa este método, recuerde que pygame requiere alguna forma de comunicación con el sistema de ventanas y otras partes del sistema. Para mantener a pygame en coherencia con el sistema necesita llamar a pygame.event.pump periódicamente, usualmente una vez por ciclo del bucle de juego.

La cola de eventos ofrece una forma de filtro simple. Esto puede ayudar a mejorar el rendimiento bloqueando ciertos tipos de eventos de la cola, use las funciones pygame.event.set_allowed() y pygame.event.set_blocked() para trabajar con este filtrado. Por defecto todos los eventos están permitidos.

Nota: Los Controles del Joystick no emitiran ningún evento a menos que estos estén inicializado.

Event

Un objecto de tipo Evento contiene un tipo de evento y un conjunto de miembros, o atributos, de solo lectura. El objeto Evento no contiene métodos, solo información. Estos objetos se obtienen desde la cola de eventos. E incluso puede crear sus propios eventos con una llamada a pygame.event.Event().

pygame.event.Event(type, dict): return Eventpygame.event.Event(type, * * attributes): return Event

2

Page 3: Intro PygameCapitulo 3

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

Genera un nuevo evento a partir del tipo de evento dado. El evento se construye con los valores y atributos dados. Los atributos pueden venir desde un argumento diccionario, o como cadenas claves de un diccionario.

Todos los objetos Event contienen un identificador de tipo en el atributo Event.type. Usted puede obtener acceso a todos los atributos del evento a través el método Event.dict. Todas las otras búsquedas de atributos pasarán a través de los valores de diccionario del evento.

Ademas Su programa debe seguir ciertos pasos para evitar que la cola de eventos se sobrepase del límite. Si el programa no limpia o elimina los eventos de la cola de eventos en intervalos regulares, esta podría desbordarse. Se lanzará una excepción si la cola desborda.

Pump

Normalmente durante cada bucle o ciclo de juego se deve hacer alguna clase de llamada a la cola de eventos para poder permitirle a PyGame interactuar con el Sistema Operativo, ya que hay varias tareas importantes que PyGame internamente deven realizarse , por ejemplo: La ventana principal podría necesitar responderle al sistema o ser re-dibujada. Si usted no consulta la cola de eventos por mucho tiempo, el sistema podría interpretar que su programa está inactivo o que hubo un error.

Esta funcion deja que pygame se encargue internamente de la cola de eventos, la misma no es necesaria si usted maneja los eventos a traves de otras funciones del modulo pygame.event.

sintaxis:

pygame.event.pump(): return None

Get

Permite obtener todos los eventos de la cola de eventos ademas de eliminarlos de la cola. opcionalmente se puede pasar como parametro el tipo o listado de tipo de eventos aunque hay que tener cuidado al extraer un solo tipo o grupo de eventos ya que eventualmente podria haber un desbordamiento en la cola de eventos.

sintaxis:

pygame.event.get(): return Eventlistpygame.event.get(type): return Eventlistpygame.event.get(typelist): return Eventlist

Poll

Permite obtener un solo evento de la cola, al igual que con Get el evento obtenido es eliminado de la cola de eventos, su sintaxis es:

pygame.event.poll(): return Event

3

Page 4: Intro PygameCapitulo 3

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

Wait

Este metodo coloca al programa en espera (lo duerme) hasta que se genere un nuevo evento, si es que la cola de eventos esta vacia.

sintaxis:

pygame.event.wait(): return Event

Peek

Consulta si un tipo especifico de evento esta esperando en la cola de eventos, si se pasa una lista de eventos retornara True si hay alguno de esos eventos esperando en la cola.

sintaxis:

pygame.event.peek(type): return boolpygame.event.peek(typelist): return bool

Clear

Sirve para Limpiar la cola de evento, opcionalmente se puede pasar el tipo o la lista con los tipo de eventos que se desean borrar de la cola de eventos.

sintaxis:

pygame.event.clear(): return Nonepygame.event.clear(type): return Nonepygame.event.clear(typelist): return None

Set_blocked y Set_allowed

El primero permite escluir un tipo de evento, o listados de tipos de eventos para que no aparescan en la cola, el segundo tiene efecto inverso y permite incluir un tipo de evento a la cola.

Nota: por defecto todos los eventos podran ser colocados en la cola de eventos.

sintaxis:

pygame.event.set_blocked(type): return Nonepygame.event.set_blocked(typelist): return Nonepygame.event.set_blocked(None): return Nonepygame.event.set_allowed(type): return Nonepygame.event.set_allowed(typelist): return Nonepygame.event.set_allowed(None): return None

4

Page 5: Intro PygameCapitulo 3

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

Get_blocked

permite consultar si un tipo de evento esta bloqueado, su sintaxis es:

pygame.event.get_blocked(type): return bool

Set_grab

Permite controlar la posibilidad, de compartir o no los dispositivos de entrada, por ejemplo cuando ejecutamos nuestro programa en modo ventana este comparte los dispositivos con otras aplicaciones que esten selecionadas, si el programa llama a set_grab(True) este bloqueara todos los dispositivos de entrada. S recomienda usar con cuidado este metodo ya que imposibilita al usuario realizar otra tarea en el sistema.

sintaxis

pygame.event.set_grab(bool): return None

Get_grab

Consulta si el programa está compartiendo los dispositivos en entrada, retornara True cuando los eventos de entrada son exclusivos de esta aplicación. Use pygame.event.set_grab() para controlar este estado.

sintaxis

pygame.event.get_grab(): return bool

Post

Permite colocar manualmente un evento al final de la cola de eventos, estos eventos seran leidos mas tarde que los eventos previamente existentes en la cola, se utiliza normalmente para colocar eventos de tipo USEREVENT aunque es posible agregar eventos de cualquier tipo:

sintaxis

pygame.event.post(Event): return None

Concluciones

Aunque PyGame proporciona un modulo para el manejo de eventos, este es raramente es usado explicitamente para manejar la cola de eventos normalmente solo bastara con agregar las siguientes lineas dentro del bucle de principal del juego para procesar todos los eventos, ya que posiblemente el unico evento en particular que nos ha de interesar sera cuando se genere un evento QUIT osea que se pida finalizar la ejecucion del programa, por que al manejo de los dispositivos de entrada lo haremos mediantes los modulos que nos ofrece PyGame:

5

Page 6: Intro PygameCapitulo 3

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

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

#terminar el bucle de juego y salirreturn

Otra posible variacion es que normalmente tambien nos interese capturar cuando se precione la tecla Escape salir automaticamente del juego:

for evento in pygame.event.get(): if evento.type == pygame.QUIT or ((evento.type == KEYDOWN) \

and (event.key == K_ESCAPE)):#terminar el bucle de juego y salirreturn

Control del MouseLas funciones de este módulo se pueden usar para obtener el estado actual del

mouse. Estas funciones también pueden modificar el tipo de cursor del sistema. Cuando se define el modo de video, la cola de eventos comenzará a recibir eventos de mouse. Los botones del mouse generan los eventos:

pygame.MOUSEBUTTONDOWNpygame.MOUSEBUTTONUP

Estos eventos contienen un atributo button que representa el botón que se ha pulsado. La rueda del mouse generará eventos pygame.MOUSEBUTTONDOWN, el atributo button será 4 si la rueda gira hacia arriba y 5 cuando la rueda gire hacia abajo. Se generará el evento pygame.MOUSEMOTION en cualquier momento que se mueva el mouse. El movimiento de mouse se divide en pequeños y precisos eventos MOUSEMOTION. Los eventos de movimiento que no se eliminan de la cola de eventos apropiadamente son la razón principal de que la cola de eventos se llene.

Listado de Metodos

Aca abajo enlisto todos los metodos que nos brinda PyGame para manejar el mouse, no hago una explicacion detallada de cada uno de los metodos por considerarlo imnecesario ya que la mayoria de ellos y su uso se explican por si solos.

pygame.mouse.get_pressed(): return (button1, button2, button3) Permite obtener el estado de todos los botones del Mouse

pygame.mouse.get_pos(): return (x, y) Obtiene la posicion actual del cursor dentro de la ventana.

pygame.mouse.get_rel(): return (x, y)Obtiene la distancia de movimiento del mouse, desde la llamada previa del mismo.

pygame.mouse.set_pos([x, y]): return None Define la posicion antual del mouse dentro de la ventana

pygame.mouse.set_visible(bool): return boolMuestra o Oculta el cursor del mouse

6

Page 7: Intro PygameCapitulo 3

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

pygame.mouse.get_focused(): return boolRetorna True si la ventana tiene Foco y esta reciviendo eventos del mouse

pygame.mouse.set_cursor(size, hotspot, xormasks, andmasks): return None Permite definir la imagen del cursor del Mouse, existen cursores predefinidos, que se pueden usar para cambiar la imagen del cursor, ellos son:

-pygame.cursors.arrow-pygame.cursors.diamond-pygame.cursors.broken_x-pygame.cursors.tri_left-pygame.cursors.tri_right

pygame.mouse.get_cursor(): return (size, hotspot, xormasks, andmasks) Obtiene la imagen actual del cursor.

Aqui dejo un pequeño ejemplo que lo que hara es cambiar la imagen del cursos cada ves que el usuario haga click en la ventana de PyGame, paso muestro lo sencillo que es manejar el cursor en PyGame:

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

""" Descripcion: Ejemplo canbia el cursor del mouse cada ves que se hace click sobre la ventana."""

import pygamefrom pygame.locals import *

#Datos de PantallaANCHO = 400ALTO = 400RESOLUCION = (ANCHO, ALTO)

def main(): pygame.init() #inicializo pygame #defino el tamaño de la ventana y la variable que hara referencia screen = pygame.display.set_mode(RESOLUCION) reloj = pygame.time.Clock() #temporizador para el juego

#coloque aqui sus variables cursores = [ #lista con todos los cursores por defecto pygame.cursors.arrow, pygame.cursors.diamond, pygame.cursors.broken_x, pygame.cursors.tri_left, pygame.cursors.tri_right ]

7

Page 8: Intro PygameCapitulo 3

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

indice = 0 #identificador para el array de cursores

loop = True while loop: # escriba aca el codigo del juego screen.fill((255,255,255)) #pinto la pantalla de blanco #redusco la velocidad de actualizacion de pantalla a 10 cuadros #o frames por segundo para que el efecto se note reloj.tick(10)

#retorna el estado de los botones btns = pygame.mouse.get_pressed()

#si se preciono el boton izquierdo incremento el indice if btns[0]: indice += 1 #si se preciono el boton derecho decremento el indice elif btns[2]: indice -= 1

#controlo que la variable indice no se salga de rango if indice < 0: indice = 0 elif indice >= len(cursores): indice = len(cursores) - 1

#defino el cursor actual pygame.mouse.set_cursor(*cursores[indice])

#actualizo la pantalla pygame.display.flip()

#leo todos los eventos en busqueda de un evento QUIT for evento in pygame.event.get(): if evento.type == pygame.QUIT or ((evento.type == KEYDOWN) \ and (event.key == K_ESCAPE)): #terminar el bucle de juego y salir loop = False

if __name__ == '__main__': main()

Bueno como se ve el manejo del cursor es muy sencillo, y no requiere mucho esfuerzo el manejo del mismo. Sobre el codigo creo que este esta muy bien documentado y se explica por si solo ademas casi todos los modulos que se utilizan en el fueron explicados en su momento, solo puede que tenga una duda con la tercera linea de la funcion main:

reloj = pygame.time.Clock()

Bueno por el momento solo dire que este objecto funciona como temporizador y permite que el juego se ejecute a la misma velocidad en todos los ordenadores (bueno todos los ordenadores o PC donde corra Python y PyGame no creo que nadie tenga u n 386 o una Comodore usando para programar juegos :P).

Sobre los cursores que se pueden usar, PyGame solo maneja cursores en Blanco y

8

Page 9: Intro PygameCapitulo 3

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

Negro y probee y probee un modulo llamado pygame.cursors para cargarlos desde un XBM, si desean saber mas acerca de ese modulo pueden mirar la documentacion de PyGame su uso es sencillo y no requiere mucho esfuerzo ademas mas adelante veremos como subsanar el problema de solo poder usar cursores en Blanco y Negro.

Figuras BasicasAl igual que la mayoria de las librerias graficas, PyGame trae consigo un conjunto de

métodos para el dibujado de figuras basicas, que son lineas rectangulos, circulos, arcos, etc.

Todas la funciones requieren como primer argumento un objecto Surface, que es la superficie donde se dibujara la figura, el segundo argumento el el color el cual puede ser pasado mediante un objecto color o una tupla que represente un color. Otro atributo que casi todas tienen es el atributo width o ancho, que se refiere al ancho de la linea si el valor de width es 0, pygame dibujara una figura rellena con ese color.

Estas funciones bloquearan temporalmente la superficie donde están operante. Así que muchas llamadas de dibujo se pueden acelerar bloqueando y desbloqueando la superficie donde se trabaja antes y después de llamar a las funciones de dibujo.

Rect

dibuja una figura rectangular, el parametro rectangulo puede ser un objecto pygame.Rect o una tupla con alguno de estos 2 formas:

(x, y, ancho, alto) ((x, y), (ancho, alto))

sintaxis:

pygame.draw.rect(Surface, color, Rect, width=0): return Rect

Ejemplos:

pygame.draw.rect(screen, VERDE, (50, 50, 250, 100), 0)

pygame.draw.rect(screen, VERDE, (50, 50, 250, 100), 2)

9

Page 10: Intro PygameCapitulo 3

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

Circle

Dibuja un circulo, el agumentos pos es una tupla (x, y) con la posicion central del mismo, el argumento radius representa el radio del circulo en pixels, el radio no puede ser menor que el grosor.

sintaxis

pygame.draw.circle(Surface, color, pos, radius, width=0): return Rect

Ejemplo:

pygame.draw.circle(screen, CYAN, (200, 200), 70, 6)

Ellipse

El circulo en matematica es un caso especial de elipse, y este ocurre cuando la distancia del centro a borde o radio se mantiene constante. Pygame utilizan un atributo para definir una elipse.

Sintaxis

pygame.draw.ellipse(Surface, color, Rect, width=0): return Rect

Ejemplos:

si pasamos un rectangulo cuadrado como parametro obtendremos un ciruculo

pygame.draw.ellipse(screen, ROJO, (10, 10, 100, 100), 0)

10

Page 11: Intro PygameCapitulo 3

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

pygame.draw.ellipse(screen, MAGENTA, (100, 100, 250, 80), 0)

Arc

Dibuja un arco elíptico en una superficie. La figura se dibujará en el área delimitada por el rectángulo. Los dos argumentos angle son los ángulos inicial y final en radianes, donde 0 representa la izquierda. Sintaxis:

pygame.draw.arc(Surface, color, Rect, start_angle, stop_angle, width=1): return Rect

Ejemplo:

pygame.draw.arc(screen, NEGRO, (100, 100, 200, 200), radians(45), radians(180), 2)

line

Dibuja un segmento de linea recto en una superficie. No se dibujan puntas en los extremos de la linea, las terminaciones serán cuadradas para lineas muy gruesas. sintaxis

pygame.draw.line(Surface, color, start_pos, end_pos, width=1): return Rect

ejemplo:

11

Page 12: Intro PygameCapitulo 3

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

pygame.draw.line(screen, NEGRO, (100, 100), (200, 200), 10)

lines

Dibuja una secuencia de lineas en una superficies. El argumento pointlist es una serie de puntos que se conectarán por una linea. Si el argumento closed es true se dibujará un segmento de linea adicional entre el primer y último punto.Esta función no dibuja ninguna punta o nodo. Las lineas con esquinas afiladas y grosor de linea muy grande podrían mostrar las intersecciones de segmentos de manera inapropiada.

Sintaxis:

pygame.draw.lines(Surface, color, closed, pointlist, width=1): return Rect

ejemplo:

pygame.draw.lines(screen, ROJO, False, [(100, 100), (200, 200), (320, 45)], 5)

aaline

Dibuja una linea suavizada en una superficie. Esta función estima el rectángulo afectado. Se retorna el rectángulo que representa el área afectada. Si el parámetro blend está en valor True, las figuras se mezclarán con la tonalidad de los pixels existentes en lugar de sobre-escribirlos. Esta función acepta valores en números realizar para los extremos de los segmentos.

Sintaxis:

pygame.draw.aaline(Surface, color, startpos, endpos, blend=1): return Rect

12

Page 13: Intro PygameCapitulo 3

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

aalines

Dibuja una secuencia de lineas en una superficie. Debe indicar al menos dos puntos en la secuencia de puntos (parámetro pointlist). El argumento closed es un valor booleano, si es True se dibujará un segmento de linea adicional entre el primer y último punto. Si el argumento blend se define a True la figura se dibujará con las tonalidades existentes en lugar de reemplazarlas. Esta función acepta valores en números reales para especificar los puntos.

Sintaxis:

pygame.draw.aalines(Surface, color, closed, pointlist, blend=1): return Rect

Polygon

Dibuja una figura poligonal en una superficie. El argumento pointlist es una lista de los vértices del polígono. El argumento width es el espesor para dibujar el borde de la figura. Si width es 0 entonces el polígono se pinta por completo.

sintaxis:

pygame.draw.polygon(Surface, color, pointlist, width=0): return Rect

Ejemplo:

puntos = [ (10, 150), (120, 150), (340, 50), (250, 330)]pygame.draw.polygon(screen, NARANJADO, puntos, 0)

13

Page 14: Intro PygameCapitulo 3

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

Como se ve dibujar figuras basicas no es cosa de otro mundo, pero bueno no son pocas las cosas que se pueden hacer dibujando solamente figuras basicas muchos fisicos que usan pygame (Si como oyero PyGame no se usa solo para hacer Juegos) las utilizan en sus simulaciones.

Un Reloj AnalogicoComo ultimo ejemplo practico de este capitulo, aunque no es un Juego, vamos a

hacer paso por paso un pequeño reloj Analogico, osea de Agujas :P. queremo llegar a algo como lo siguiente:

Bien Empecemos:

A primera vista vemos que el reloj nos tiene que mostrar la hora actual de nuestra PC por lo que aparte de pygame vamos a necesitar importar el modulo time estandar y algunas funciones matematicas del modulo math ya que trabajaremos con un poco de trigonometria, pues bien los ingredientes son:

import timefrom math import cos, sin, degrees, radiansimport pygamefrom pygame.locals import *

Segundo, es necesario definir algunas constantes, tanto para la resolcion de la ventana, como algunas tuplas que representen los colores que usaremos:

#coloresBLANCO = (250, 250, 250)NEGRO = (0, 0, 0)GRIS = (100, 100, 100)AZUL = (0, 0, 255)ROJO = (255, 0, 0)VERDE = (0, 255, 0)

#datos de pantallaANCHO = 120ALTO = 120RESOLUCION = (ANCHO, ALTO)CENTRO = (ANCHO / 2, ALTO / 2)RADIO = (ANCHO + ALTO)/ 4

14

Page 15: Intro PygameCapitulo 3

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

Bien despues de haver definido todo esto, llego la hora de empesar a escribir codigo; yo para separar un poco el mismo decidi separar las diferentes tareas que conllevan a dibujar el reloj y las separe en:

dibujar la base del relojdibujar la aguja de las horadibujar la aguja de los minutosdibujar la aguja de los segundos

Para dibujar la base del reloj, notaran que lo primero que devemos hacer es dibujar un circulo, pues bien hagamoslo:

pygame.draw.circle(surface, NEGRO, CENTRO, RADIO, 1)

Ahora para dibujar los indicadores de horas y minutos la cosa se nos complicara un poco, por que vamos a tener que hacer algunos calculos trigonometricos (a los que no sepan trigonometria les recomiendo leer un poco de el tema antes de continuar, en internet hay varios apuntes relacionados con el tema).

Sabemos que una hora tiene 60 minutos y 1 minuto 60 segundos, pero ademas sabemos que un circulo tiene 360 grados, por lo que necesitamos saber cuantos grados ocupa un segundo o minuto osea:

360 / 60 = 6 grados

Y hacer lo mismos con las horas, con la salvedad de que un reloj analogico marca 12 y no 24 horas.

360 / 12 = 30 grados

Ahora con todo esto podemos dibujar los indicadores de hora y minuto, antes que ello recordar que en un circulo la posicion x, y en el borde se calcula como sigue:

x = cos(alfa) * radioy = sen(alfa) * radio

Donde alfa, es el angulo formado por anbos puntos, lo que haremos sera trazar pequeñas lineas de longitud 5 y para ello vamos a hacerlo mediante 2 ciclos for, comenzaremos en cada caso con alfa = 0 y recordando que para los segundo el incremento es de 6 grados y para las horas de 30 grados, por lo que el codigo quedaria asi:

for a in range(60): ang = radians(6) #* a - radians(90) x1 = CENTRO[0] + cos(ang) * (RADIO - 3) y1 = CENTRO[1] + sin(ang) * (RADIO - 3)

15

Page 16: Intro PygameCapitulo 3

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

x2 = x1 + cos(ang) * 3 y2 = y1 + sin(ang) * 3 pygame.draw.line(surface, NEGRO, (x1,y1), (x2,y2), 1)

for a in range(12): ang = radians(30) * a - radians(90) x1 = CENTRO[0] + cos(ang) * (RADIO - 5) y1 = CENTRO[1] + sin(ang) * (RADIO - 5)

x2 = x1 + cos(ang) * 5 y2 = y1 + sin(ang) * 5 pygame.draw.line(surface, GRIS, (x1,y1), (x2,y2), 2)

Hasta ahora hemos logrado lo siguiente y solo nos faltan dibujar las agujas que marcan las horas:

Algo a recalcar el angulo 0 normalmente enpieza donde el reloj daria las 3, por lo que tendremos que descontarles 3 * 30 = 90 grados para que empieze en las 12, sobre el centido de giro no habra problema, ya que este se deplazara en sentido horario y no en sentido antihorario como tendria que ser.

Ahora devemos obtener la Hora, los minutos y los segundos, es para ello que utilizaremos el modulo time:

hh = time.localtime().tm_hour % 12mm = time.localtime().tm_minss = time.localtime().tm_sec

Bien ahora para finalizar solo tendremos que dibujar las agujas del reloj de manera similar a como lo hicimos anteriormente con los indicadores de segundos y horas, la longitud de las agujas puede ser cualquiera yo use las siguientes longitudes:

long_aguja_de_hora = radio – 15long_aguja_de_minuto = radio – 10long_aguja_de_segundo = radio – 5

Ahora tendremos que calcular las posiciones x, y y dibujar una linea desde el centro hacia la posicion de cada aguja dependiendo alngulo y el radio:

#dibujo la aguja de la horaang = radians(30) * hh - radians(90)x = CENTRO[0] + cos(ang) * (RADIO - 15)y = CENTRO[1] + sin(ang) * (RADIO - 15)

16

Page 17: Intro PygameCapitulo 3

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

pygame.draw.line(surface, VERDE, CENTRO, (x,y), 3)

#aguja de los minutosang = radians(6) * mm - radians(90)x = CENTRO[0] + cos(ang) * (RADIO - 10)y = CENTRO[1] + sin(ang) * (RADIO - 10)pygame.draw.line(surface, AZUL, CENTRO, (x,y), 2)

#aguja de los segundosang = radians(6) * ss - radians(90)x = CENTRO[0] + cos(ang) * (RADIO - 5)y = CENTRO[1] + sin(ang) * (RADIO - 5)pygame.draw.line(surface, ROJO, CENTRO, (x,y), 1)

Y eso es todo, omiti el codigo del la secion de incializar pygame, crear la pantalla, leer los eventos etc, por que no venian al caso y casi siempre es lo mismo, bueno en fin aca esta el codigo completo con todas las cosas que no mencione incluidas:

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

import timefrom math import cos, sin, degrees, radiansimport pygamefrom pygame.locals import *

#coloresBLANCO = (250, 250, 250)NEGRO = (0, 0, 0)GRIS = (100, 100, 100)AZUL = (0, 0, 255)ROJO = (255, 0, 0)VERDE = (0, 255, 0)

#datos de pantallaANCHO = 120ALTO = 120RESOLUCION = (ANCHO, ALTO)CENTRO = (ANCHO / 2, ALTO / 2)RADIO = (ANCHO + ALTO)/ 4

def draw_hhline(surface, color, hh): """ funcion para dibujar la aguja de la hora """ ang = radians(30) * hh - radians(90) x = CENTRO[0] + cos(ang) * (RADIO - 15) y = CENTRO[1] + sin(ang) * (RADIO - 15) pygame.draw.line(surface, color, CENTRO, (x,y), 3)

def draw_mmline(surface,color,mm): """ funcion para dibujar la aguja del minutero""" ang = radians(6) * mm - radians(90) x = CENTRO[0] + cos(ang) * (RADIO - 10) y = CENTRO[1] + sin(ang) * (RADIO - 10)

17

Page 18: Intro PygameCapitulo 3

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

pygame.draw.line(surface, color, CENTRO, (x,y), 2)

def draw_ssline(surface,color,ss): """ funcion para dibujar la aguja del segundero """ ang = radians(6) * ss - radians(90) x = CENTRO[0] + cos(ang) * (RADIO - 5) y = CENTRO[1] + sin(ang) * (RADIO - 5) pygame.draw.line(surface, color ,CENTRO, (x,y), 1)

def draw_rl(surface): """ dibuja el fondo del reloj """ pygame.draw.circle(surface, NEGRO, CENTRO, RADIO, 1)

for a in range(60): ang = radians(6) * a x1 = CENTRO[0] + cos(ang) * (RADIO - 3) y1 = CENTRO[1] + sin(ang) * (RADIO - 3)

x2 = x1 + cos(ang) * 3 y2 = y1 + sin(ang) * 3 pygame.draw.line(surface, NEGRO, (x1,y1), (x2,y2), 1)

for a in range(12): ang = radians(30) * a x1 = CENTRO[0] + cos(ang) * (RADIO - 5) y1 = CENTRO[1] + sin(ang) * (RADIO - 5)

x2 = x1 + cos(ang) * 5 y2 = y1 + sin(ang) * 5 pygame.draw.line(surface, GRIS, (x1,y1), (x2,y2), 2)

def main(): pygame.init() screen = pygame.display.set_mode(RESOLUCION)

loop = True while loop: screen.fill(BLANCO)

hh = time.localtime().tm_hour % 12 mm = time.localtime().tm_min ss = time.localtime().tm_sec

draw_rl(screen) draw_hhline(screen,VERDE,hh) draw_mmline(screen,AZUL,mm) draw_ssline(screen,ROJO,ss)

pygame.display.flip()

for evento in pygame.event.get():

18

Page 19: Intro PygameCapitulo 3

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

if evento.type == pygame.QUIT: loop = False return

if __name__ == '__main__': main()

La unica variacion que notaran es que yo coloque todo el codigo que venia mostrando dentro de algunas funciones.

Despedida

Para terminar y para que no se aburran con los ejemplos de este capitulo y ya que esto es un curso de programacion de Juegos inclui un sencillo tic-tac-toe sin IA para 2 jugadores, escrito en apenas 300 lineas incluyendo comentarios separacion por lineas en blanco, en fin yo diria buen estilo de codigo, el mismo esta realizado esclusivamente usando formas basicas. Espero que les guste el juego y hasta el proximo capitulo, aquí dejo una captura de pantalla del juego:

(véase tictactoe.pyw)

19