Las modificaciones, con respecto al original del tutorial han sido:
Cambio de control con teclado a control con raton
Añadido sistema de puntuacion, asi como sistema de vidas(grafico)
Funcion reboot que "reinicia" el juego cada vez que te matan
Creacion de un Game Over
Implementacion de choques entre:la nave y los laseres enemigos(faltaba en el tutorial),entre los propios laseres y entre la nave buena y la mala
Ahi va el codigo:
- Código: Seleccionar todo
"""Space Invaders de StarWars
Autor Original:dvl de la pagina linuxjuegos.com
Modificaciones:Juan Guerrero(Yo)
"""
import random,os,pygame
from pygame.locals import *
#Tamaño de pantalla
SCREEN_WIDTH=800
SCREEN_HEIGHT=600
#Nombre de la carpeta con los archivos
DATOS="datos"
#Cargar Imagen#
def load_image(name,colorkey=False):
"asignamos la ruta de la carpeta donde guardaremos las imagenes"
fullname=os.path.join(DATOS,name)
try: image=pygame.image.load(fullname)
except pygame.error,message:
print 'No se puede cargar la imagen: ',fullname
raise SystemExit,message
image=image.convert()
if (colorkey):
colorkey=image.get_at((0,0))
image.set_colorkey(colorkey,RLEACCEL)
return image,image.get_rect()
#Cargar Sonido#
def load_SoundFile(name):
class NoneSound:
def play(self): pass
if not pygame.mixer or not pygame.mixer.get_init():
return NoneSound()
fullname=os.path.join(DATOS,name)
try:
sound=pygame.mixer.Sound(fullname)
except pygame.error,message:
print'No se pudo cargar el sonido: ',fullname
raise SystemExit,message
return sound
#Nave Buena#
class XWing(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image,self.rect=load_image("xwing.bmp",True)
"posicion inicial"
self.rect.centerx=SCREEN_WIDTH
self.rect.centery=(SCREEN_HEIGHT-40)
def update(self):
posicion=pygame.mouse.get_pos()
self.rect.center=posicion
"""Evitamos salidas de pantalla
restringimos el movimiento vertical a media pantalla
"""
if self.rect.left<0:
self.rect.left=0
elif self.rect.right>SCREEN_WIDTH:
self.rect.right=SCREEN_WIDTH
if self.rect.top<=SCREEN_HEIGHT/2:
self.rect.top=SCREEN_HEIGHT/2
elif self.rect.bottom>=SCREEN_HEIGHT:
self.rect.bottom=SCREEN_HEIGHT
#Los Malos#
class TIEFighter(pygame.sprite.Sprite):
def __init__(self,startx):
pygame.sprite.Sprite.__init__(self)
self.image,self.rect=load_image("tie_fighter.bmp",True)
self.rect.centerx=startx
self.rect.centery=0
self.x_velocity=random.randint(-5,5)
self.y_velocity=random.randint(1,5)
def update(self):
self.rect.move_ip((self.x_velocity,self.y_velocity))
if self.rect.left<=0:
self.x_velocity=-(self.x_velocity)
elif self.rect.right>=SCREEN_WIDTH:
self.x_velocity=-(self.x_velocity)
"""Si se sale de pantalla, lo eliminamos para liberar
espacio"""
if self.rect.bottom>=SCREEN_HEIGHT:
self.kill()
"Disparos Aleatorios"
fire=random.randint(1,60)
if fire==1:
tiefighterLaserSprites.add(TIEFighterLaser(self.rect.midbottom))
tiefighterShotFX.play()
#Laser de XWing#
class XWingLaser(pygame.sprite.Sprite):
def __init__(self,startpos):
pygame.sprite.Sprite.__init__(self)
self.image,self.rect=load_image("rebel_laser.bmp",True)
self.rect.center=startpos
def update(self):
if self.rect.bottom<=0:
self.kill()
else:
self.rect.move_ip((0,-4))
#Laser de TIEFighter#
class TIEFighterLaser(pygame.sprite.Sprite):
def __init__(self,startpos):
pygame.sprite.Sprite.__init__(self)
self.image,self.rect=load_image("empire_laser.bmp",True)
self.rect.midtop = startpos
def update(self):
"""Si se sale de pantalla, lo eliminamos para liberar
espacio"""
if self.rect.bottom>=SCREEN_HEIGHT:
self.kill()
else:
self.rect.move_ip((0,4))
#puntaje#
def puntuacion(puntos):
puntos=puntos+1
#vidas
class corazon(pygame.sprite.Sprite):
def __init__(self,posini):
pygame.sprite.Sprite.__init__(self)
self.image,self.rect=load_image("corazon.gif",True)
self.rect.centerx=posini
self.rect.centery=25
"""limpia la pantalla del juego cuando te matan"""
def reboot(TIEFighterContainer):
"Carga los 4 'malos' iniciales"
TIEFighterContainer.add(TIEFighter(650))
TIEFighterContainer.add(TIEFighter(50))
TIEFighterContainer.add(TIEFighter(650))
TIEFighterContainer.add(TIEFighter(50))
return TIEFighterContainer
def main():
random.seed()
pygame.init()
screen=pygame.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT),HWSURFACE|DOUBLEBUF)
pygame.display.set_caption("STAR WARS INVADERS")
"Limita el movimiento del raton a la pantalla de juego"
pygame.event.set_grab(True)
background_image,background_rect=load_image("background.bmp")
screen.blit(background_image,(0,0))
"Imagen de final de juego"
gameover_image,gameover_rect=load_image("Vader.bmp")
"Cargamos los sonidos"
explode1FX=load_SoundFile("explode1.wav")
global tiefighterShotFX
tiefighterShotFX=load_SoundFile("empire_laser.wav")
xwingShotFX=load_SoundFile("rebel_laser.wav")
explode2FX=load_SoundFile("explode2.wav")
risamalvadaFX=load_SoundFile("risa.mp3")
#Creamos los containers
xwingSprite=pygame.sprite.RenderClear()
xwing=XWing()
xwingSprite.add(xwing)
xwingLaserSprites=pygame.sprite.RenderClear()
#4 malos iniciales
tiefighterSprites=pygame.sprite.RenderClear()
reboot(tiefighterSprites)
global tiefighterLaserSprites
tiefighterLaserSprites=pygame.sprite.RenderClear()
"Variable para bucle principal"
running=True
"Contador para aparicion de nuevos enemigos"
addTieFighterCounter=0
clock=pygame.time.Clock()
gameover=False
puntos=0
nivel=0
pygame.mouse.set_visible(False)
#creamos las vidas
vidas=pygame.sprite.RenderClear()
vida3=corazon(30)
vida2=corazon(70)
vida1=corazon(110)
vidas.add(vida1)
vidas.add(vida2)
vidas.add(vida3)
#numero inicial de vidas
nvidas=3
#Fuente para el texto
fuente=pygame.font.Font(None,40)
while running is True:
clock.tick(60)
"Comprobamos si se produce algun evento de entrada"
for event in pygame.event.get():
if event.type == QUIT:
running = False # Se acaba el juego
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False # Se acaba el juego
"Dispara un laser cuando pulsemos la barra espaciadora"
elif event.key == K_SPACE:
xwingLaserSprites.add(XWingLaser(xwing.rect.midtop))
xwingShotFX.play()
"""Creamos un laser a cada lado de la nave
pulsando el boton izq del raton"""
elif event.type == MOUSEBUTTONDOWN:
xwingLaserSprites.add(XWingLaser(xwing.rect.midleft))
xwingLaserSprites.add(XWingLaser(xwing.rect.midright))
xwingShotFX.play()
"Ajustamos el nivel"
if puntos>=5:
nivel+=1
puntos=0
"Incrementamos el contador para crear nuevos enemigos"
addTieFighterCounter+=1
if addTieFighterCounter>=(100-15*nivel):"Cada nivel apareceran mas rapido"
tiefighterSprites.add(TIEFighter(random.randint(100,700)))
addTieFighterCounter=0
"Actualizamos los containers"
xwingSprite.update()
xwingLaserSprites.update()
tiefighterSprites.update()
tiefighterLaserSprites.update()
"""Comprobamos si ha habido choques
Las diferentes posibilidades son:
Malo vs LaserBueno
Bueno vs LaserMalo
Bueno vs Malo
LaserBueno vs LaserMalo
"""
for hit in pygame.sprite.groupcollide(tiefighterSprites,xwingLaserSprites,1,1):
explode1FX.play()
puntos+=1
for hit in pygame.sprite.groupcollide(xwingSprite,tiefighterLaserSprites,0,1):
explode2FX.play()
"Vamos eliminando los corazones en pantalla y restando vidas"
if nvidas==3:
vidas.remove(vida1)
elif nvidas==2:
vidas.remove(vida2)
else:
vidas.remove(vida3)
nvidas-=1
if nvidas==0:
gameover=True
else:
"Vaciamos todos los containers y limpiamos la pantalla"
tiefighterLaserSprites.empty()
tiefighterSprites.empty()
pygame.mouse.set_pos((SCREEN_WIDTH/2),SCREEN_HEIGHT-40)
xwingLaserSprites.empty()
tiefighterLaserSprites.clear(screen,background_image)
tiefighterSprites.clear(screen,background_image)
xwingSprite.clear(screen,background_image)
xwingLaserSprites.clear(screen,background_image)
vidas.clear(screen,background_image)
fuente=pygame.font.Font(None,40)
Puntaje=fuente.render(str(puntos),1,(255,255,255))
Nivel=fuente.render(str(nivel),1,(255,255,255))
screen.blit(background_image,(0,0))
screen.blit(Puntaje,(SCREEN_WIDTH/2,0))
screen.blit(Nivel,(SCREEN_WIDTH/2+20,0))
tiefighterLaserSprites.draw(screen)
xwingLaserSprites.draw(screen)
xwingSprite.draw(screen)
tiefighterSprites.draw(screen)
vidas.draw(screen)
"Establecemos un tiempo de espera antes de reiniciar"
pygame.time.wait(800)
"reiniciamos con los 4 malos del comienzo
reboot(tiefighterSprites)
"""Este caso es igual que el anterior, solo que en esta ocasion se trata
de choques entre naves"""
for hit in pygame.sprite.groupcollide(xwingSprite,tiefighterSprites,0,1):
explode2FX.play()
explode1FX.play()
if nvidas==3:
vidas.remove(vida1)
elif nvidas==2:
vidas.remove(vida2)
else:
vidas.remove(vida3)
nvidas-=1
if nvidas==0:
gameover=True
else:
tiefighterLaserSprites.empty()
tiefighterSprites.empty()
pygame.mouse.set_pos((SCREEN_WIDTH/2),10)
xwingLaserSprites.empty()
tiefighterLaserSprites.clear(screen,background_image)
tiefighterSprites.clear(screen,background_image)
xwingSprite.clear(screen,background_image)
xwingLaserSprites.clear(screen,background_image)
vidas.clear(screen,background_image)
fuente=pygame.font.Font(None,40)
Puntaje=fuente.render(str(puntos),1,(255,255,255))
Nivel=fuente.render(str(nivel),1,(255,255,255))
screen.blit(background_image,(0,0))
screen.blit(Puntaje,(SCREEN_WIDTH/2,0))
screen.blit(Nivel,(SCREEN_WIDTH/2+20,0))
tiefighterLaserSprites.draw(screen)
xwingLaserSprites.draw(screen)
xwingSprite.draw(screen)
tiefighterSprites.draw(screen)
vidas.draw(screen)
pygame.time.wait(800)
reboot(tiefighterSprites)
for hit in pygame.sprite.groupcollide(xwingLaserSprites,tiefighterLaserSprites,1,1):
explode1FX.play()
if gameover: pygame.time.delay(1000)
"Borramos y pintamos los elementos de la pantalla"
tiefighterLaserSprites.clear(screen,background_image)
tiefighterSprites.clear(screen,background_image)
xwingSprite.clear(screen,background_image)
xwingLaserSprites.clear(screen,background_image)
vidas.clear(screen,background_image)
fuente=pygame.font.Font(None,40)
Puntaje=fuente.render(str(puntos),1,(255,255,255))
Nivel=fuente.render(str(nivel),1,(255,255,255))
screen.blit(background_image,(0,0))
screen.blit(Puntaje,(SCREEN_WIDTH/2,0))
screen.blit(Nivel,(SCREEN_WIDTH/2+20,0))
tiefighterLaserSprites.draw(screen)
xwingLaserSprites.draw(screen)
xwingSprite.draw(screen)
tiefighterSprites.draw(screen)
vidas.draw(screen)
pygame.display.flip()
"Final de juego"
if gameover:
screen.blit(gameover_image,(0,0))
pygame.display.flip()
risamalvadaFX.play()
running=False
pygame.event.set_grab(False)
if __name__=='__main__':
main()
Como podreis comprobar, este juego tiene una serie de mejoras posibles:
creacion de una funcion que se encargue de la actualizacion(puesto que llegamos a repetir el mismo codigo tres veces), el hecho de que a partir de cierto nivel, el tiempo de aparicion entre malo y malo es cero(para esto se podria añadir que cada cinco niveles, apareciera un malo malisimo,en plan estrealla de la muerte, y el tiempo entre malo y malo se restableciera)
Otro fallo que no entiendo es el hecho d que el sonido de la risa malvada no suena,alguien sabe por que??
Espero comentarios y criticas