programación con pygame ix

13

Click here to load reader

Upload: fernando-salamero

Post on 22-May-2015

1.949 views

Category:

Education


3 download

DESCRIPTION

Los archivos pueden encontrarse en http://sites.google.com/site/laislalibre/informatica/python/pygame

TRANSCRIPT

Page 1: Programación con Pygame IX

Cubo3D: Pyggel y OpenGL

(Basado en los tutoriales NeHe, http://nehe.gamedev.net )

Introducción

Cubo3D no es un juego, es un pequeño programa escrito para mostrar cómo se puede trabajar en Python con las 3 dimensiones. El guión está basado en uno de los famosos tutoriales NeHe, algunos de los cuales fueron convertidos a Python y PyGame por Paul Furber

http://www.pygame.org/gamelets/games/nehe1-10.zip

Pero ésta no va a ser nuestra aproximación (aunque incluimos al final el código correspondiente por completitud). Estos tutoriales utilizan una librería 3D genérica muy potente llamada OpenGL

http://www.opengl.org

sin lugar a dudas, la más extendida y con la que se programan multitud de videojuegos profesionales. Su implementación en Python se conoce como PyOpenGL

PROGRAMA: DRIVE CURSO: 1º BACHILLERATO

PÁGINA 1 DE 13 CC: FERNANDO SALAMERO

Page 2: Programación con Pygame IX

http://pyopengl.sourceforge.net

En cualquier caso, al ser una librería avanzada, su manejo es muy complejo (sólo tienes que mirar el código al que nos hemos referido antes). Existe una librería conocida como Pyggel

http://code.google.com/p/pyggel/

que hace de intermediario de PyOpenGL; incorpora clases, constantes y funciones que facilitan mucho el aprendizaje y uso de las tres dimensiones en nuestros programas, encargándose ella de gestionar de forma transparente las rutinas correspondientes de OpenGL. Además, la librería Pyggel se encarga de inicializar a su vez a PyGame. ¡Dos en uno! Si esto fuera poco, no necesitamos instalar nada más (bueno, en realidad sí que hay que tener instalado en el sistema a PyOpenGL y OpenGL); basta con que a nuestro proyecto le incorporemos la carpeta de la librería y a funcionar.

En resumen, con este documento incluimos dos programas distintos:

1. Cubo3D_Pyggel.py es nuestro tutorial y el que se va a describir en las próximas líneas. Utiliza el módulo Pyggel.

2. Cubo3D_PyOpenGL.py es el tutorial original de Paul Furber, conversión a Python del tutorial NeHe correspondiente. Trabaja directamente con PyOpenGL.

Vamos allá.

Importación e Inicialización

Después de la típica línea de declaración de codificación y del nombre del programa, nos encontramos con la importación del módulo pyggel. Observa la curiosa forma. Por una parte se importa tal cual

import pyggel, sys

y, por otra parte, se importa de nuevo en la forma

from pyggel import *

El resultado es que podemos llamar a cualquier objeto refiriéndonos a él directamente o con el prefijo pyggel. Es una cuestión de comodidad, aunque en general no es muy recomendable. En pyggel es importante que lo hagamos así pues, como ya hemos comentado previamente, esté módulo carga e inicializa automáticamente a su vez a PyGame y, de esta manera, podemos también acceder a sus objetos directamente.

Lo siguiente es inicializar el entorno (recuerda que al inicializar Pyggel se inicializa también PyGame). Fíjate que no escribimos simplemente init(). Pyggel admite en dicha función varios parámetros que nos permiten ajustar las características de la ventana de visualización. De paso se usa una característica de Python muy útil; no hace falta recordar el orden en el que hay que escribir los parámetros, podemos referirnos a ellos por su nombre. Así

pyggel.init(screen_size=(800,600))

tiene el efecto de invocar a la función init() del módulo pyggel dando el valor (800,600) al argumento llamado screen_size en su definición. Como adivinarás, eso hace que la ventana en la que veremos nuestra animación 3D tenga un tamaño de 800x600 pixeles.

PROGRAMA: DRIVE CURSO: 1º BACHILLERATO

PÁGINA 2 DE 13 CC: FERNANDO SALAMERO

Page 3: Programación con Pygame IX

Composición de la ESCENAHay una diferencia fundamental entre trabajar con dos dimensiones (como hasta ahora, con el estándar de PyGame) y trabajar con tres. Cuando dibujamos en 2D dibujamos exactamente lo que queremos, ya que la superficie sobre la que se dibuja (la pantalla del ordenador) también es bidimensional. Sin embargo, cuando queremos dibujar en 3D, debemos hacer proyección de los objetos, realizar una perspectiva. Y en tal caso, influyen muchos más factores; para empezar el lugar desde donde se mira (no es lo mismo mirar un cubo desde delante que desde un lado, o desde muy lejos). Dibujar en 3D en hacer un salto a una animación más realista en la que puedes tener en cuenta detalles como iluminación, atmósfera... Debes ponerte en el papel de un director de cine o de un fotógrafo:

1. Para empezar, todo lo que quieres incluir forma lo que se denomina una escena.

2. Tienes que determinar desde dónde vas a mirar, es decir, la posición de la cámara.

3. Y necesitas luces que iluminen los objetos, por supuesto.

Todo ello vas a tener que implementarlo. Veámoslo paso a paso.

La primera línea de código que encontramos es

escena = pyggel.scene.Scene()

es precisamente la creación de la escena. Observa que es un objeto de tipo Scene (definido en el módulo scene, es decir, en el archivo scene.py de la carpeta pyggel). De la misma manera que un Grupo de Pygame contenía una serie de Sprites, un objeto de tipo Scene contiene todos los objetos que forman la escena y, por lo tanto, a medida que los vayamos creando deberemos añadírselos.

En nuestro mundo tridimensional sólo vamos a tener un cubo, pero para que no sea aburrido vamos a añadirle una textura. Las texturas son imágenes que se colocan en las superficies de los objetos y simulan el tipo de material o la decoración. Si te has fijado en la captura de pantalla al inicio de este documento, la que vamos a emplear es una imagen de tipo vidriera (glass.bmp); pero si quisiéramos que nuestro cubo fuera de madera, por ejemplo, podríamos tomar una imagen con listones o similar. Las texturas son objetos de tipo Texture y se crean de la siguiente forma

textura = pyggel.data.Texture("glass.bmp")

Una vez cargada en memoria, usarla para crear un cubo es también sencillo:

cubo = pyggel.geometry.Cube(1, pos=(0, 0, 0), texture=textura)

En la línea anterior hemos creado un objeto de tipo Cube (como puedes adivinar, los diferentes tipos de objetos tridimensionales nativos están definidos en el archivo geometry.py de pyggel; analiza su código si tienes curiosidad). El parámetro pos indica claramente en qué posición pondremos al cubo; se necesitan tres coordenadas pues estamos en un mundo tridimensional (ya se encargará Pyggel, o más correctamente OpenGL, de proyectar la escena en la pantalla). En nuestro mundo tridimensional, el cubo está situado en el origen de coordenadas. Y el valor 1 del primer argumento indica su tamaño; nuestro cubo tiene una arista de 1 unidad.

PROGRAMA: DRIVE CURSO: 1º BACHILLERATO

PÁGINA 3 DE 13 CC: FERNANDO SALAMERO

Page 4: Programación con Pygame IX

Con los objetos tridimensionales, no sólo podemos situarlos en algún lugar, también podemos orientarlos. ¿Qué tal se te da la geometría...? Para orientar un objeto podemos girarlo adecuadamente, pero este giro podemos hacerlo con respecto a cualquiera de los tres ejes X, Y y Z. Así que, en general, un giro puede ser la composición de tres giros, uno en torno a cada eje coordenado. El que encontramos en el código,

cubo.rotation = (0,45,10)

el cubo se rota 45 grados con respecto al eje Y y 10 grados con respecto al eje Z.

Finalmente, hemos de incluir el cubo creado en la escena para que luego se visualice. Ello se consigue con la línea

escena.add_3d(cubo)

Nuestra escena ya tiene un objeto tridimensional.

Añadiendo LUCESComo hemos indicado, para poder la escena correctamente necesitamos iluminarla. Como en la realidad, hay muchos tipos de luces; direccionales (como un foco), de ambiente (repartida por todas partes de forma homogénea), puntuales (como una bombilla)... La forma de crear luces desde una librería de programación, por lo tanto, ha de ser muy flexible. Veamos cómo lo hemos implementado:

luz = pyggel.light.Light((0,0,2),

(0.5,0.5,0.5,1),

(1,1,1,1),

(50,50,50,10),

(0,0,0),

True)

Bien. Como viene siendo habitual, el sistema se basa en la creación de un objeto, en este caso de tipo Light (definido en el módulo de pyggel light). Los diferentes parámetros indican las propiedades que va a tener la iluminación:

1. (0,0,2)Se corresponde con la posición, en el espacio, de la fuente que emite la luz.

2. (0.5,0.5,0.5,1)Es el color de la luz ambiente; una luz que llena todo el espacio por igual (y que por lo tanto no produciría sombras). Está en formato RGBA, es decir, valores entre 0 y 1 que indicam la cantidad de rojo, verde, azul y canal alfa (la opacidad; 1 indica que es sólida; 0 completamente transparente).

3. (1,1,1,1)Color de la luz difusa; tipo de luz suave que viene desde una dirección dada y que produciría sombras (algo así como un Sol velado). También en formato RGBA

4. (50,50,50,10)Luz especular; similar a la anterior pero más brillante, como un Sol intenso (que puede producir brillos sobre las superficies que ilumina directamente).

PROGRAMA: DRIVE CURSO: 1º BACHILLERATO

PÁGINA 4 DE 13 CC: FERNANDO SALAMERO

Page 5: Programación con Pygame IX

5. (0,0,0)Dirección de la luz en el caso de que ésta sea direccional; con ello controlamos en qué dirección aparecerán las combras.

6. TrueIndica si la luz es direccional en cuyo caso se indica True, o la emite un punto de luz concreto en todas direcciones, indicado con False.

Juega con las diferentes opciones y prueba todo lo que quieras; sólo así podrás comprenderlo mejor.

Una vez creada la luz, hemos de añadirla a la escena para que el motor 3D de pyggel pueda luego generarla correctamente:

escena.add_light(luz)

¡Conseguido!

Posicionando la CÁMARAAhora hay que decidir desde dónde hay que mirarlo, es decir, hay que situar la cámara. Con Pyggel es muy sencillo...

camara = pyggel.camera.LookAtCamera((0,0,0), distance=3)

Fíjate en el código. Para crear una cámara se crea un objeto de la clase LookAtCamera, definida en el módulo camera (si miras su código verás que hay otras formas de crear cámaras). Los parámetros que hemos incluido son muy intuitivos; el primero es una tupla que indica en qué dirección miramos (en este caso, miramos hacia el punto (0,0,0), el lugar en el que hemos puesto el cubo) y el parámetro distance indica desde qué distancia se hace (valores negativos indicarían algo así como ‘desde el otro lado’; experimenta, como siempre, para ver la diferencia).

Bucle PrincipalJusto antes de entrar en el bucle de la animación nos encontramos con el habitual

reloj = pygame.time.Clock()

que controlará posteriormente la velocidad de los fotogramas con reloj.tick(60).

La gestión de eventos puede hacerse de la forma habitual en PyGame, pero ya que estamos usando en primer plano la librería Pyggel, podemos hacerlo con ella:

eventos = pyggel.event.Handler()

Con la línea anterior hemos creado un objeto de tipo Handler y lo hemos almacenado en la variable eventos. Un objeto de este tipo centraliza la detección y uso de los eventos que se producen en el programa. En seguida veremos cómo.

Una vez dentro del bucle, la línea

pyggel.view.set_title("FPS: %s"%int(reloj.get_fps()))

PROGRAMA: DRIVE CURSO: 1º BACHILLERATO

PÁGINA 5 DE 13 CC: FERNANDO SALAMERO

Page 6: Programación con Pygame IX

tiene una misión muy interesante; mostrar en la barra de título de la ventana la velocidad real conseguida en fotogramas por segundo; es un buen método para, en tiempo de desarrollo, comprobar si conseguimos la velocidad que queremos (si el ordenador no es lo suficientemente rápido, o le pedimos demasiadas tareas a la vez, es posible que no alcance la que hemos indicado, en nuestro caso los 60 fps).

¿Cómo lo hace? La función pyggel.view.set_title() toma como argumento una cadena de texto y la coloca como título de la ventana. Recuerda, además, que en “FPS: %s” el %s indica que vamos a pasarle un entero a la cadena de texto en cuestión. Y ese entero lo conseguimos usando el método get_fps() del objeto reloj, método que nos devuelve el valor real de la velocidad de la animación (con decimales, de ahí el int para convertirlo).

Lo siguiente es actualiza la lista de eventos que se puedan haber producido con

eventos.update()

y, por consiguiente, hemos de mirar cuáles tenemos y actuar en consecuencia. La forma de hacerlo es muy similar a la de PyGame, pero con sus características propias. Para empezar, los eventos que se producen con el teclado se corresponden con el objeto keyboard y los del ratón con el mouse. En este programa sólo vamos a responder a las pulsaciones de ciertas teclas, así que estamos en el primer caso. Para saber si se acaba de pulsar una tecla, hay que mirar si está en keyboard.hit mientras que la lista de teclas que están todavía pulsadas se encuentra en keyboard.active. De esta forma, para salir del programa si se cierra la ventana o si se pulsa la tecla escape escribimos

if eventos.quit or K_ESCAPE in eventos.keyboard.hit:

pyggel.quit()

sys.exit()

Si se pulsan ciertas teclas, lo que haremos es desplazar la cámara (y por lo tanto veremos la escena desde otras posiciones o perspectivas). Así, por ejemplo,

if K_LEFT in eventos.keyboard.active:

camara.roty -= .5

mira si se ha pulsado la tecla de desplazamiento izquierda del cursor y, en tal caso, resta 0.5 grados al ángulo de rotación sobre el eje Y de la cámara. Ejecuta el programa para ver el efecto que esto tiene. Observa que no es lo mismo girar la cámara que girar un objeto (según sea lo que quieres conseguir o cómo quieres que el programa responda a las acciones del usuario elegirás una u otra cosa); girar la cámara hace moverse al observador que contempla la escena; girar los objetos hace que la propia escena cambie.

Los demás giros sobre los diferentes ejes se implementan de forma similar. Como sólo tenemos las teclas de desplazamiento izquierda, derecha, arriba y abajo, para hacer el giro sobre el eje Z hemos usado, como puedes ver, las teclas 1 y 2. Por otra parte, para acercarnos o alejarnos de la escena, usando las teclas z y x, simplemente hemos de modificar el valor de camara.distance.

Cuando giramos la cámara, lo que hacemos es orbitar en torno al punto que estamos mirando, como hace la Luna con la Tierra. Desplazarla es algo distinto, pues es simplemente cambiar su posición (lo que hace que entonces no mire necesariamente en la dirección de antes). En el código, por poner un ejemplo, usamos las teclas a, d, s y w para desplazarla en los ejes X y Z. De nuevo, ejecuta el script y verás lo que sucede.

PROGRAMA: DRIVE CURSO: 1º BACHILLERATO

PÁGINA 6 DE 13 CC: FERNANDO SALAMERO

Page 7: Programación con Pygame IX

Una vez que hemos atendido a todos los eventos que queríamos usar en nuestro programa, lo único que nos queda es realizar el dibujado en pantalla para que se muestre en toda su gloria la imagen tridimensional. Análogamente a lo que ocurría en PyGame, en cada fotograma tienes que vigilar que sean borradas las imágenes que han cambiado y redibujar las que ahora han de visualizarse. Por lo tanto, lo primero es borrar toda la pantalla

pyggel.view.clear_screen()

y lo siguiente es generar la imagen tridimensional (lo que se conoce como renderizar)

escena.render(camara)

La línea anterior nos renderiza la escena tal como se vería por la camara. Para finalizar, como es habitual, debemos volcar la escena generada. Ello nos lleva a la última línea del programa:

pyggel.view.refresh_screen()

¡Perfecto! Nuestro cubo ha quedado realmente aparente. Y esto es sólo el comienzo. Con tiempo e imaginación, puedes crear cualquier Mundo que te propongas...

# -*- coding: utf-8 -*-# Ejemplo de escena en 3D

import pyggel, sysfrom pyggel import *

pyggel.init(screen_size=(800,600))

escena = pyggel.scene.Scene()

textura = pyggel.data.Texture("glass.bmp")cubo = pyggel.geometry.Cube(1, pos=(0, 0, 0), texture=textura) cubo.rotation = (0,45,10)

escena.add_3d(cubo)

luz = pyggel.light.Light((0,0,2), (0.5,0.5,0.5,1), (1,1,1,1), (50,50,50,10), (0,0,0), True)

escena.add_light(luz)

PROGRAMA: DRIVE CURSO: 1º BACHILLERATO

PÁGINA 7 DE 13 CC: FERNANDO SALAMERO

Page 8: Programación con Pygame IX

camara = pyggel.camera.LookAtCamera((0,0,0), distance=3)

reloj = pygame.time.Clock()

eventos = pyggel.event.Handler()

while 1: reloj.tick(60) pyggel.view.set_title("FPS: %s"%int(reloj.get_fps()))

eventos.update()

if eventos.quit or K_ESCAPE in eventos.keyboard.hit: pyggel.quit() sys.exit() if K_LEFT in eventos.keyboard.active: camara.roty -= .5 if K_RIGHT in eventos.keyboard.active: camara.roty += .5 if K_UP in eventos.keyboard.active: camara.rotx -= .5 if K_DOWN in eventos.keyboard.active: camara.rotx += .5 if K_1 in eventos.keyboard.active: camara.rotz -= .5 if K_2 in eventos.keyboard.active: camara.rotz += .5

if K_z in eventos.keyboard.active: camara.distance -= .05 if K_x in eventos.keyboard.active: camara.distance += .05

if K_a in eventos.keyboard.active: camara.posx -= .1 if K_d in eventos.keyboard.active: camara.posx += .1 if K_s in eventos.keyboard.active: camara.posz -= .1 if K_w in eventos.keyboard.active: camara.posz += .1

pyggel.view.clear_screen()

escena.render(camara) pyggel.view.refresh_screen()

PROGRAMA: DRIVE CURSO: 1º BACHILLERATO

PÁGINA 8 DE 13 CC: FERNANDO SALAMERO

Page 9: Programación con Pygame IX

Como hemos comentado, incluimos también el código de Paul Furber que usa directamente las librerías OpenGL a través de PyOpenGL. Como verás, el programa es mucho más complejo aunque más potente. Si lo ejecutas verás que, por ejemplo, con la tecla l se activa o desactiva la iluminación, mientras que con la tecla b se activan o desactivan efectos de transparencia...

#!/usr/bin/env python# pygame + PyOpenGL version of Nehe's OpenGL lesson08# Paul Furber 2001 - [email protected]

import osfrom OpenGL.GL import *from OpenGL.GLU import *import pygame, pygame.imagefrom pygame.locals import *

xrot = yrot = 0.0xspeed = yspeed = 0.0z = -5.0textures = []filter = 0light = 0blend = 0

LightAmbient = ( (0.5, 0.5, 0.5, 1.0) );LightDiffuse = ( (1.0, 1.0, 1.0, 1.0) );LightPosition = ( (0.0, 0.0, 2.0, 1.0) );

def resize((width, height)): if height==0: height=1.0 glViewport(0, 0, width, height) glMatrixMode(GL_PROJECTION) glLoadIdentity() gluPerspective(45, 1.0*width/height, 0.1, 100.0) glMatrixMode(GL_MODELVIEW) glLoadIdentity()

def init(): glEnable(GL_TEXTURE_2D) load_textures() glShadeModel(GL_SMOOTH) glClearColor(0.0, 0.0, 0.0, 0.0) glClearDepth(1.0) glEnable(GL_DEPTH_TEST)

PROGRAMA: DRIVE CURSO: 1º BACHILLERATO

PÁGINA 9 DE 13 CC: FERNANDO SALAMERO

Page 10: Programación con Pygame IX

glDepthFunc(GL_LEQUAL) glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST) glLightfv( GL_LIGHT1, GL_AMBIENT, LightAmbient ) glLightfv( GL_LIGHT1, GL_DIFFUSE, LightDiffuse ) glLightfv( GL_LIGHT1, GL_POSITION, LightPosition ) glEnable( GL_LIGHT1 ) glColor4f( 1.0, 1.0, 1.0, 0.5) glBlendFunc( GL_SRC_ALPHA, GL_ONE )

def load_textures(): global LightAmbient, LightDiffuse, LightPosition, textures #texturefile = os.path.join('data','glass.bmp') textureSurface = pygame.image.load('glass.bmp') textureData = pygame.image.tostring(textureSurface, "RGBX", 1)

textures = glGenTextures(3) glBindTexture(GL_TEXTURE_2D, textures[0]) glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, textureSurface.get_width(), textureSurface.get_height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData ) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)

glBindTexture(GL_TEXTURE_2D, textures[1]) glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ) glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ) glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, textureSurface.get_width(), textureSurface.get_height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData )

glBindTexture( GL_TEXTURE_2D, textures[2]) glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST ) glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ) gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, textureSurface.get_width(), textureSurface.get_height(), GL_RGBA, GL_UNSIGNED_BYTE, textureData);

def draw(): global xrot, yrot, xspeed, yspeed, z, filter glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glLoadIdentity() glTranslatef(0.0, 0.0, z)

PROGRAMA: DRIVE CURSO: 1º BACHILLERATO

PÁGINA 10 DE 13 CC: FERNANDO SALAMERO

Page 11: Programación con Pygame IX

glRotatef(xrot, 1.0, 0.0, 0.0) glRotatef(yrot, 0.0, 1.0, 0.0)

glBindTexture(GL_TEXTURE_2D, textures[filter]) glBegin(GL_QUADS) glNormal3f(0.0, 0.0, 1.0) glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, 1.0) glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, -1.0, 1.0) glTexCoord2f(1.0, 1.0); glVertex3f( 1.0, 1.0, 1.0) glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, 1.0) glNormal3f(0.0, 0.0, -1.0) glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, -1.0) glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, -1.0) glTexCoord2f(1.0, 1.0); glVertex3f( 1.0, 1.0, -1.0) glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, -1.0, -1.0) glNormal3f(0.0, 1.0, 0.0) glTexCoord2f(1.0, 1.0); glVertex3f(-1.0, 1.0, -1.0) glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, 1.0, 1.0) glTexCoord2f(0.0, 0.0); glVertex3f( 1.0, 1.0, 1.0) glTexCoord2f(0.0, 1.0); glVertex3f( 1.0, 1.0, -1.0) glNormal3f(0.0, -1.0, 0.0) glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, -1.0, -1.0) glTexCoord2f(1.0, 1.0); glVertex3f( 1.0, -1.0, -1.0) glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, -1.0, 1.0) glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, 1.0) glNormal3f(1.0, 0.0, 0.0) glTexCoord2f(0.0, 0.0); glVertex3f( 1.0, -1.0, -1.0) glTexCoord2f(0.0, 1.0); glVertex3f( 1.0, 1.0, -1.0) glTexCoord2f(1.0, 1.0); glVertex3f( 1.0, 1.0, 1.0) glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, -1.0, 1.0) glNormal3f(-1.0, 0.0, 0.0) glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0, -1.0) glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, 1.0) glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, 1.0) glTexCoord2f(1.0, 1.0); glVertex3f(-1.0, 1.0, -1.0) glEnd(); xrot += xspeed yrot += yspeed

PROGRAMA: DRIVE CURSO: 1º BACHILLERATO

PÁGINA 11 DE 13 CC: FERNANDO SALAMERO

Page 12: Programación con Pygame IX

def handle_keys(key): global filter, light, z, xspeed, yspeed, blend

if key == K_ESCAPE: return 0 if key == K_f: filter = filter + 1 if filter == 3: filter = 0 elif key == K_l: light = not light if not light: glDisable(GL_LIGHTING) else: glEnable(GL_LIGHTING) elif key == K_b: blend = not blend if blend: glEnable(GL_BLEND) glDisable(GL_DEPTH_TEST) else: glEnable(GL_DEPTH_TEST) glDisable(GL_BLEND) elif key == K_PAGEUP: z -= 0.05 elif key == K_PAGEDOWN: z += 0.05 elif key == K_UP: xspeed -= 0.01 elif key == K_DOWN: xspeed += 0.01 elif key == K_LEFT: yspeed -= 0.01 elif key == K_RIGHT: yspeed += 0.01 return 1

def main():

video_flags = OPENGL|DOUBLEBUF pygame.init() surface = pygame.display.set_mode((640,480), video_flags)

resize((640,480)) init()

frames = 0

PROGRAMA: DRIVE CURSO: 1º BACHILLERATO

PÁGINA 12 DE 13 CC: FERNANDO SALAMERO

Page 13: Programación con Pygame IX

ticks = pygame.time.get_ticks() while 1: event = pygame.event.poll() if event.type == QUIT: break if event.type == KEYDOWN: if handle_keys(event.key) == 0: break draw() pygame.display.flip() frames = frames+1

print "fps: %d" % ((frames*1000)/(pygame.time.get_ticks()-ticks))

if __name__ == '__main__': main()

PROGRAMA: DRIVE CURSO: 1º BACHILLERATO

PÁGINA 13 DE 13 CC: FERNANDO SALAMERO