Como ya enseñé en otro hilo, estoy haciendo un juego con una navecita. En este hilo iré posteando los progresos según vaya consiguiendo avances más o menos importantes. De momento cuenta con lo siguiente:
- Nave protagonista
- Misiles para la nave protagonista
- Enemigos aleatorios
De momento se parece mucho al Invaders de Juanxo, aunque tengo pensado hacer algo distinto. Tenía pensado dividir el juego en varias tandas, unas de enemigos aleatorios, como los que hay ahora en las que tuvieras que matar x enemigos sin que se te escape ningno por la parte de abajo de la ventana. Otra con enemigos más fuertes que no se desplacen demasiado pero que disparen. Estos no sería aleatorios si no que irían definidos. Finalmente un enemigo final.
De momento no tengo ninguna duda. Lo único que quiero preguntar es si estoy mezclando demasiado las calses de Nave y Misil. Es que le paso muchos atributos de la clase misil a nave para no tener que cargarlos una y otra vez.

- Código: Seleccionar todo
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ------------------------------
# Autor: Rafael Álvarez García
# e-mail: algarafa@gmail.com
# ------------------------------
# ------------------------------
# Importación de módulos
# ------------------------------
import pygame
from pygame.locals import *
import sys
import os
import random
# ------------------------------
# Constantes
# ------------------------------
SCREEN_WIDTH = 400
SCREEN_HEIGHT = 600
IMG_DIR = 'images'
SOUND_DIR = 'sounds'
# ------------------------------
# Funciones y clases
# ------------------------------
# Creamos la función para cargar imágenes.
def load_image(name, dir, alpha = False):
# Unimos la ruta de la imágen.
ruta = os.path.join(dir, name)
# Probamos a cargarla y si no devolvemos error.
try:
image = pygame.image.load(ruta)
print 'Cargando imagen', ruta, '...¡éxito!'
except:
print 'No se pudo cargar la imagen', ruta
sys.exit(1)
# Comprobamos si hay alpha.
if alpha:
image = image.convert_alpha()
else:
image = image.convert()
return image
# Función para cargar sonidos.
def load_sound(name, dir_sound):
ruta = os.path.join(dir_sound, name)
try:
sound = pygame.mixer.Sound(ruta)
print 'Cargando sonido', ruta, '...¡éxito!'
except:
sound = None
print 'No se pudo cargar el sonido', ruta
return sound
# Clase para la nave.
class Nave(pygame.sprite.Sprite):
def __init__(self, sprites, misiles, misil_img, misil_sound):
pygame.sprite.Sprite.__init__(self)
self.image = load_image('nave.png', IMG_DIR, alpha = True)
self.rect = self.image.get_rect()
self.sprites = sprites
self.misiles = misiles
self.misil_img = misil_img
self.misil_sound = misil_sound
self.counter = 0
self.rect.centerx = SCREEN_WIDTH / 2
self.rect.centery = SCREEN_HEIGHT - 60
self.speed = [0, 0]
def update(self):
# Hacemos que no salga de la pantalla.
if self.rect.top < 0:
self.rect.top = 0
self.speed[1] = 0
elif self.rect.bottom > SCREEN_HEIGHT + 1:
self.rect.bottom = SCREEN_HEIGHT
self.speed[1] = 0
elif self.rect.left < -1:
self.rect.left = 0
self.speed[0] = 0
elif self.rect.right > SCREEN_WIDTH + 1:
self.rect.right = SCREEN_WIDTH
self.speed[0] = 0
# Actualiza el contador para simular la recarga de munición.
if self.counter > 0:
self.counter -= 1
self.rect.move_ip(self.speed)
# Indica si podemos disparar o no.
def can_shoot(self):
return self.counter == 0
# Dispara los misiles.
def shoot(self):
if self.can_shoot():
misil = Misil(self.rect.midtop, self.misiles, self.misil_img)
self.sprites.add(misil)
self.misiles.add(misil)
self.misil_sound.play()
# Actualiza el tiempo de recarga.
self.counter = 40
# Clase para los enemigos.
class Enemigo(pygame.sprite.Sprite):
def __init__(self, image):
pygame.sprite.Sprite.__init__(self)
self.image = image
self.rect = self.image.get_rect()
self.generar_pos()
self.generar_vel()
self.vida = 1
def update(self):
if self.rect.left < 0:
self.speed[0] = -self.speed[0]
if self.rect.right > SCREEN_WIDTH:
self.speed[0] = -self.speed[0]
# Si se queda sin vida o si sale de pantalla lo matamos.
if self.vida == 0:
self.kill()
if self.rect.top == SCREEN_HEIGHT:
self.kill()
self.rect.move_ip(self.speed)
def generar_pos(self):
# Genera uns posición de x aleatoria.
pos = random.randrange(50, SCREEN_WIDTH -50)
self.rect.centerx = pos
self.rect.centery = 25
def generar_vel(self):
# Genera una velocidad aleatoria.
x = random.randrange(-5, 5)
y = random.randrange(1, 3)
self.speed = [x, y]
# Clase para el misil.
class Misil(pygame.sprite.Sprite):
def __init__(self, initial_pos, misiles, image):
pygame.sprite.Sprite.__init__(self)
self.image = image
self.rect = self.image.get_rect()
self.rect.midbottom = initial_pos
self.speed = [0, -4]
self.poder_destruccion = 1
misiles.add(self)
# Si se sale de pantalla lo matamos, si no lo movemos.
def update(self):
if self.rect.bottom < 0:
self.kill
else:
self.rect.move_ip(self.speed)
# Comprobamos las colisiones con enemigos.
def colisiones(self, objetivos): # Objetivos debe ser una lista.
for objetivo in objetivos:
if self.rect.colliderect(objetivo):
objetivo.vida -= self.poder_destruccion
self.kill()
# ------------------------------
# Función principal
# ------------------------------
def main():
pygame.init()
pygame.mixer.init()
print 'Iniciando juego...'
# Creamos la ventana e indicamos nombre e icono.
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption('Provisional')
icon = pygame.image.load('images/nave.png').convert_alpha()
pygame.display.set_icon(icon)
print 'Creando ventana... ¡éxito!'
# Cargamos e imprimimos el fondo.
fondo = load_image('background.jpg', IMG_DIR)
screen.blit(fondo, (0, 0))
# Cargamos las imágenes y sonidos que usaremos mucho para no tener
# que cargarlas cada vez que creemos un objeto de esa clase.
misil_img = load_image('misil.png', IMG_DIR, alpha = True)
misil_sound = load_sound('misil.wav', SOUND_DIR)
enemigo_img = load_image('enemigo.png', IMG_DIR, alpha = True)
# Cremoas el frupo de sprites.
sprites = pygame.sprite.Group()
# Creamos un contador para los enemigos aleatorios.
contador = 0
# Creamos un grupo para los misiles y otra para los enemigos.
misiles = pygame.sprite.Group()
enemigos = pygame.sprite.Group()
# Creamos la nave y la añadimos al grupo sprites.
nave = Nave(sprites, misiles, misil_img, misil_sound)
sprites.add(nave)
# Creamos el reloj.
clock = pygame.time.Clock()
# Activamos la repetición de teclas.
pygame.key.set_repeat(1, 25)
# Hacemos el ratón invisible.
pygame.mouse.set_visible(False)
# Bucle principal.
while True:
clock.tick(60)
# Comprobamos los eventos.
for event in pygame.event.get():
if event.type == pygame.QUIT:
print 'Cerrando juego...'
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == K_UP:
nave.speed[1] -= 0.3
elif event.key == K_DOWN:
nave.speed[1] += 0.3
elif event.key == K_LEFT:
nave.speed[0] -= 0.3
elif event.key == K_RIGHT:
nave.speed[0] += 0.3
elif event.key == K_SPACE:
nave.shoot()
elif event.key == K_ESCAPE:
print 'Cerrando juego...'
sys.exit()
# Actualizamos el contador de enemigos aleatorios.
if contador > 0:
contador -= 1
# Generamos los enemigos aleatorios.
if contador == 0:
enemigo = Enemigo(enemigo_img)
sprites.add(enemigo)
enemigos.add(enemigo)
contador = 100
# Comprobamos las colisiones.
for misil in misiles:
misil.colisiones(enemigos)
# Actualizamos los sprites.
sprites.update()
# Actualizamos la pantalla.
sprites.clear(screen, fondo)
sprites.draw(screen)
pygame.display.flip()
if __name__ == "__main__":
main()
En próximos posts pondré un link de descarga para que no tengáis que buscar imágenes para probarlo. Es que le quiero buscar un nombre para crearle una página dentro de mi blog y así ir subiendolo periódicamente.
¡Un saludo!

P.D.: Cuando el juego esté listo, losersjuegos tendrá su lugar em los créditos
