Tu estás aquí: ¡Bienvenido! » Referencia » Artículos » Chimp, un juego paso a paso
Usuario
Buscar páginas
Esta Pagina
General

Chimp, un juego paso a paso

Esta traducción está siendo modificada y no está lista para publicar.
  • Título original: Line By Line Chimp
  • Autor original: Pete Shinners
  • Traducción por: Hugo Ruscitti

Introducción

En los ejemplos de pygame encontrará uno muy simple llamado “chimp”. Este ejemplo simula un mono que se mueve por una pantalla pequeña con la promesa de que si lo golpeas te dará una recompesa. El ejemplo en sí es muy simple, y un poco cutre en el manejo de errores, pero igualmente, este ejemplo muestra muchas de las habilidades de pygame, como la creación de una ventana gráfica, cargar archivos de imagen y sonido, dibujar textos TTF y un manejo básico de eventos de mouse.

El programa y las imagenes se pueden encontrar dentro de la distribución de código fuente de pygame. Este ejemplo se reescribió completamente en la versión 1.3 de pygame para agregar un grupo de características y manejo de errores. Este cambio duplicó el tamaño del ejemplo original, a cambio de brindar mucho mas para ver, y mucho mas código que te recomiendo reutilizar en tus propios proyectos.

Este tutorial te guiará a través del código bloque a bloque. Explicando como funciona el código. También se mencionará como se podría mejorar el código y que código de verificación de errores podría ayudar.

Este es un excelete tutorial para las personas que buscan dar un primer vistazo al código de pygame. Una vez pygame esté completamente instalado, encontrarás y podrás ejecutar este ejemplo tú mismo.

No, esto no es una publicidad, es una captura de pantalla del juego.

Incluyendo módulos

Este es el código que incluye todos los módulos necesarios dentro del programa. Incluso detecta la disponibilidad de ciertos componentes opcionales de pygame.

import os, sys
import pygame
from pygame.locals import *
 
if not pygame.font:
    print 'Warning, fonts disabled'
 
if not pygame.mixer:
    print 'Warning, sound disabled'

Primero, incluimos los módulos estándar de python “os” y “sys”. Estos nos permiten hacer cosas como crear rutas a archivos independientes de la plataforma.

En la siguiente linea, incluimos el paquete pygame. A su vez, pygame se encarga de incluir todos los submodulos que le pertenecen. Algunos paquetes de pygame son opcionales, y si no se encuentran sus valores serán “None”.

Existe un módulo especial de pygame llamado “locals”. Este módulo contiene un subconjunto de pygame. Los miembros de este módulo se utilizan frecuentemente en muchas partes de los juegos así que resulta útil colocarlas en el espacio de nombres global. Este módulo incluye funciones como “Rect”, para crear un objeto rectángulo y muchas otras constantes como “QUIT” o “HWSURFACE” que se utilizan para para interactura con el resto de pygame. Note que es opcional cargar este módulo en el espacio de nombres local, de todas formas los miembros del módulo “locals” siempre estarán disponibles dentro del módulo pygame.

Por último, decidimos imprimir un bonito mensaje de advertencia si los módulos “font” o “sound” de pygame no están disponibles.

Cargando recursos

Tenemos dos funciones para cargar imágenes y sonidos. Ahora veremos cada una de estas funciones de manera individual.

def load_image(name, colorkey=None):
    fullname = os.path.join('data', name)
    try:
        image = pygame.image.load(fullname)
    except pygame.error, message:
        print 'Cannot load image:', name
        raise SystemExit, message
    image = image.convert()
    if colorkey is not None:
        if colorkey is -1:
            colorkey = image.get_at((0,0))
        image.set_colorkey(colorkey, RLEACCEL)
    return image, image.get_rect()

Esta función toma el nombre de una imagen para cargar. Y toma de manera opcional un argumento que se utiliza para definir el color transparente de una imagen (argumento colorkey).

Lo primero que hace esta función es crear la ruta completa al archivo. En este ejemplo todos los recursos están en el subdirectorio “data”. La ruta al archivo ha sido creada usando “os.path.join” para que funcione en cualquier plataforma.

Luego cargamos la imagen usando la función “pygame.image.load”. También envolvemos el llamado a esta función en un bloque “try/except”, de forma que si existe un problema cargando la imagen podemos salir de manera cortez. Esta función también hace una copia nueva de la superficie y la convierte al formato de colores para que coincida con la pantalla. Así, se puede mejorar notablemente la velocidad de impresión en pantalla.

Por último, definirmos el colorkey de la imagen. Si el usuario suministra un valor para el argumento colorkey usaremos ese valor como el color transparente de la image. El valor generalmente será un compuesto RGB, como (255, 255, 255) para representar el color blanco. También puede enviar -1 como valor para colokey. En ese caso la función buscará el color que se encuente en la esquina superior izquierda de la imagen, y usará ese color como colorkey.

def load_sound(name):
    class NoneSound:
        def play(self): pass
    if not pygame.mixer:
        return NoneSound()
    fullname = os.path.join('data', name)
    try:
        sound = pygame.mixer.Sound(fullname)
    except pygame.error, message:
        print 'Cannot load sound:', wav
        raise SystemExit, message
    return sound

Luego en la función para cargar un archivo de sonido, lo primero que hace esta función es verificar si el módulo pygame.mixer se ha incorporado correctamente. En caso negativo, retorna un objeto que tiene un método play ficticio, y que funcionará de manera bastante similar al objeto Sound normal; de esta forma el juego podrá funcionar sin tener que realizar otro chequeo de error posterior.

Esta función es similar a la función para cargar una imagen, pero maneja algunos problemas diferentes. Primero creamos la ruta completa al archivo de sonido, cargamos el archivo de sonido en un bloque “try/except” y luego simplemente retornamos el objeto Sound generado.

Clases de objetos para juegos

Aquí hemos creado dos clases para representar los objetos en nuestro juego. La mayoría de la lógica del juego se hace dentro de estas dos clases. Veremos una a una.

class Fist(pygame.sprite.Sprite):
    """moves a clenched fist on the screen, following the mouse"""
    def __init__(self):
        pygame.sprite.Sprite.__init__(self) #call Sprite initializer
        self.image, self.rect = load_image('fist.bmp', -1)
        self.punching = 0
 
    def update(self):
        "move the fist based on the mouse position"
        pos = pygame.mouse.get_pos()
        self.rect.midtop = pos
        if self.punching:
            self.rect.move_ip(5, 10)
 
    def punch(self, target):
        "returns true if the fist collides with the target"
        if not self.punching:
            self.punching = 1
            hitbox = self.rect.inflate(-5, -5)
            return hitbox.colliderect(target.rect)
 
    def unpunch(self):
        "called to pull the fist back"
        self.punching = 0

Primero creamos una clase para representar a los jugadores, esta clase deriva de Sprite, que viene incluida en el módulo 'pygame.sprite`. La función 'init' se llama cuando se genera una nueva instancia de objeto de esta clase. Lo primero que hacemos es llamar al método init de la clase base, esto permite que el método de Sprite prepare nuestro objeto para ser tratado como un sprite.

Este juego usa una de las clases 'Group' para dibujar sprites. Estas clases pueden dibujar sprites que tengan los atributos 'image' y 'rect'. De forma que, cambiando estos dos atributos podemos dibujar la imagen actual en la posición que queramos.

Todos los sprites tiene un método 'update()'. Este método se llama generalmente una vez por cuadro de impresión. Y es donde podrías poner el código que mueve y actualiza las variables del sprite. El método 'update()' para el puño se mueve a la posición en donde está el puntero del mouse. Y también desplaza ligeramente la posición del puño cuando este pasa al estado “golpeando”.

Las dos funciones que le siguen cambian el estado del puño, que puede estar golpeando o no. El método 'punch()' también retorna 'True' si el puño está colisionando con el sprite indicado como 'target'.

class Chimp(pygame.sprite.Sprite):
    """moves a monkey critter across the screen. it can spin the
       monkey when it is punched."""
    def __init__(self):
        pygame.sprite.Sprite.__init__(self) #call Sprite intializer
        self.image, self.rect = load_image('chimp.bmp', -1)
        screen = pygame.display.get_surface()
        self.area = screen.get_rect()
        self.rect.topleft = 10, 10
        self.move = 9
        self.dizzy = 0
 
    def update(self):
        "walk or spin, depending on the monkeys state"
        if self.dizzy:
            self._spin()
        else:
            self._walk()
 
    def _walk(self):
        "move the monkey across the screen, and turn at the ends"
        newpos = self.rect.move((self.move, 0))
        if not self.area.contains(newpos):
	if self.rect.left < self.area.left or \
		self.rect.right > self.area.right:
            self.move = -self.move
            newpos = self.rect.move((self.move, 0))
            self.image = pygame.transform.flip(self.image, 1, 0)
        self.rect = newpos
 
    def _spin(self):
        "spin the monkey image"
        center = self.rect.center
        self.dizzy += 12
        if self.dizzy >= 360:
            self.dizzy = 0
            self.image = self.original
        else:
            rotate = pygame.transform.rotate
            self.image = rotate(self.original, self.dizzy)
        self.rect = self.image.get_rect(center=center)
 
    def punched(self):
        "this will cause the monkey to start spinning"
        if not self.dizzy:
            self.dizzy = 1
            self.original = self.image

La clase chimp hace algo mas de trabajo que el puño, pero no es mas complejo. Esta clase moverá al mono de un lado a otro por la pantalla. Y cuando se lo golpee, éste dará un giro en el lugar.

Note que esta clase también deriva de Sprite, y se inicializa de la misma forma que el puño. Cuando se inicializa también se define el atributo 'area' que tiene el tamaño de la ventana.


La función de actualización de “chimp” se ve simplemente “mareado” en estado actual, lo cual es cierto cuando el mono esta girando por un puñetazo. Esto lama a los métodos _spin o _walk, estas funciones están precedidas por un guion. Esto es sólo lenguaje estándar de Python, el cual sugiere que estos métodos sólo son utilizados por la clase “chimp”. podriamos ir tan lejos como para darles un segundo guion, que le diría a Python para hacer realmente los métodos privados, pero no necesitan de esa protección. ;¬)

El método _walk crea una nueva posición para el mono moviendo el rect actual de una posición dada. Si esta nueva posición cruza fuera de la zona de visualización de la pantalla, se invierte el movimiento de desplazamiento (el monito dará media vuelta).También refleja la imagen utilizando la función pyagame.trasform.flip, este es un brusco efecto que hace que el mono cambie la dirección del movimiento.

El método _ spin se llama cuando el mono se encuentra “mareado”. El atributo de “mareado” se utiliza para almacenar la cantidad actual de la rotación. Cuando el mono ha girado toda la vuelta (360 grados) que restablece la imagen del mono y vuelve a la versión original sin rotar. Antes de llamar a la función transform.rotate, verás el código hace una referencia local a la función simplemente llamada rotate “girar”. No hay necesidad de hacer que para este ejemplo, se acaba de hacer aquí para mantener la longitud de la línea siguiente es un poco más corto. Tenga en cuenta que cuando se llama a la función rotate para “el giro”, siempre estamos de volteando la imagen de mono original. Al girar, hay una ligera pérdida de calidad. Repetir en varias ocasiones el giro de la imagen y la calidad seria cada vez peor. Además, cuando gira una imagen, el tamaño de la imagen en realidad va a cambiar. Esto se debe a las esquinas de la imagen será rotada hacia fuera, haciendo la imagen más grande. Nos aseguramos de que el centro de la “nueva imagen” coincide con el centro de la “vieja imagen”, por lo que gira sin moverse.

El último método es “punched()”, que llamara al sprite para que entre en su estado mareado. Esto hará que la imagen para empezar a girar “mareado”. Esto hace también una copia de la imagen actual llamada “original”.

Iniciarlo Todo

Antes de que podamos hacer mucho con pygame, es necesario asegurarse de que sus módulos se iniciaran. En este caso también se abrirá una ventana de gráficos simple. Ahora estamos en la función main () del programa, que en realidad ejecuta todo.

pygame.init()
screen = pygame.display.set_mode((468, 60))
pygame.display.set_caption('Monkey Fever')
pygame.mouse.set_visible(0)

La primera linea que se utiliza para inicializar pygame se toma la precaución de hacer algo de trabajo por nosotros.

A continuación se estableció el modo de visualización de gráficos . Note que el módulo de pygame.display se utiliza para controlar todos los ajustes de pantalla. En ese caso estamos pidiendo por una ventana de borde simple. Hay un tutorial separado todo sobre la configuración del modo gráfico, pero si realmente no les importa, pygame hará un buen trabajo en algo que funciona. Pygame elegirá la mejor profundidad de color, ya que no han proporcionado una.

En la última colocamos el título de la ventana y “apaga” el cursor del ratón al pasar por la ventana. Muy facil que hacer, y ahora tenemos una pequeña ventana en negro dispuesta a hacer nuestra voluntad. Normalmente, el cursor por defecto es visible, así que no hay realmente necesidad de establecer el estado si no queremos ocultarlo.

Creando la imagen de fondo (Background)

Nuestro programa va a tener mensaje de texto en el fondo.Sería bueno para nosotros para crear una única superficie para representar el fondo (background) y que se usara en repetidas ocasiones. El primer paso es crear la superficie.

background = pygame.Surface(screen.get_size())
background = background.convert()
background.fill((250, 250, 250))
 
referencia/articulos/chimp_line_by_line.txt · Última modificación: 08/01/2010 a las 17:57 por xd_yo
Este sitio funciona sobre el motor wiki de DokuWiki.
© 2003-2008 Hugo Ruscitti