Skip to navigation
Logo Penaz's Area

cat /dev/random > penaz

Pygame: Primitive Shooter II 0.2 beta


Qualche tempo dopo la pubblicazione (e molto tempo dopo la sua creazione con pygame) ecco la nuova versione di Primitive Shooter II.

Buongiorno a tutti, con molta fatica, molto impegno e poco tempo a disposizione sono riuscito a migliorare un po' il mio modesto tentativo di creare uno shooter a scorrimento verticale con tutti i crismi; ecco perciò la nuova versione di Primitive Shooter II completamente programmata in python e pygame!

Fra le nuove caratteristiche del gioco troviamo:

  • Suoni con Stereo Panning.
  • Sfondo scorrevole a 3 livelli di parallasse che reagisce ai movimenti della navetta.
  • 7 tipi diversi di PowerUps.
  • Battaglia col boss ogni 5 livelli.
  • Supporto per le vite e schermata di Game Over.
  • 3 Tipi di Nemici: Normale, Shooter e Kamikaze.

Nelle prossime pagine analizzeremo in dettaglio le caratteristiche del gioco, per poi vedere il codice sorgente finale scritto in Python e Pygame.

Le Classi

Per prima cosa vediamo un po' che classi abbiamo a disposizione:

Classe Descrizione
Player La classe che rappresenta il giocatore ed i "kompanions"
Enemy Un nemico generico, con qualche modificatore in più rispetto alla vecchia versione
Bullet Un semplice proiettile
BigBullet Un Proiettile più grande (e presto pi potente)
PowerUp Un Generico PowerUp Raccoglibile
Star Una generica stella sullo sfondo
EnemyBullet Un proiettile lanciato dal nemico
Boss Un grosso, enorme boss arrabbiato

La maggior parte delle classi sono derivate direttamente da Sprite, ereditando così tutti i metodi che Pygame ci offre per velocizzare e facilitare il disegno delle immagini.

Primitive Shooter II fa ancora uso della Classe Vector Appositamente creata, potete trovarla in questo articolo .

Le Funzioni e i bachi conosciuti

Le funzioni sono davvero poche ma essenziali:

Funzione Descrizione
Shoot Sparo temporizzato, che ci permette di sparare senza dover massacrare la tastiera.
Level Gestisce la creazione dei livelli, le battaglie col boss e l'aumento di difficoltà
SoundInit Un posto separato dove tenere i suoni
Stereo_Pan Permette di modificare il volume delle casse destra e sinistra a seconda della posizione sullo schermo dell'evento collegato al suono

I bachi (bugs) trovati e non risolti finora sono:

  • Sotto Windows i suoni vengono riprodotti in ritardo
  • A volte uno dei due kompanions si blocca ad un lato dello schermo, seguendo solo i movimenti verticali della navetta
  • Le stelle sullo sfondo si "appiccicano" ai lati sinistro e superiore dello schermo.
  • Se finite addosso al boss, morirete e il boss sparirà. Il gioco potrebbe non proseguire.

Un po' di parole sul Gioco in sè...

Per quanto riguarda il lato "ludico" del gioco, troviamo per prima cosa una navetta che è in grado di sparare a 9 livelli di potenza diversi.

Successivamente troviamo 4 tipi di nemici + 1 boss:

Nemico Descrizione
Normale La classica "Carne da cannone": un nemico inerme che si muove a caso sullo schermo. Se ci finite addosso perderete una vita però...
Shooter Un nemico un po' più cattivo che vi lancerà addosso proiettili con lo scopo di colpirvi.
Kamikaze Un pazzo scatenato che cercherà in tutti i modi di venirvi addosso.
Shooter-Kamikaze Un pazzo veramente cattivo che compare di rado, vi spara addosso mentre cerca di centrarvi con la propria navetta
Boss Un grande, grosso, enorme e resistentissimo nemico un po' pigro, non fa altro che andare da destra a sinistra sparandovi addosso.

Inoltre troviamo ben 7 powerups diversi che permettono di facilitare la nostra battaglia:

PowerUp Descrizione
Potenza Aumenta di una unità la potenza di fuoco della vostra navetta
Velocità Cannone Aumenta il rateo di fuoco del vostro cannone
FullPower! Per 20 secondi vi di massima potenza e ritmo di fuoco, per un rapido sterminio.
Velocità Nave Aumenta la velocità della vostra nave, per movimenti più rapidi e repentini.
Kompanions Affianca alla vostra nave altre due piccole navette per aumentare la potenza di fuoco. Dura 60 secondi.
Shield Fa esattamente quello che dice, vi da uno scudo che vi protegge da tutto per 60 secondi
Assistance Un piccolo soccorso dalla base missilistica più vicina, un'orda di grossi proiettili si abbatte sul campo.

Per giocare è sufficiente una tastiera, si usano le freccette direzionali per muoversi e "Z" per sparare.

Il codice sorgente

14000 righe di codice? Non voglio arrivare a questi livelli per avere un rettangolo che spara...

Ecco qui di seguito il codice sorgente completo del gioco, per un totale di 822 righe:

#!/usr/bin/env python
#Imports
import pygame
from pygame.locals import *
from sys import exit
import Vector
from Vector import *
from math import pi
from random import randint,random
#Dichiarazioni
GameOver=False
tp=0
sht=False
showtime=False
totime=0.
shieldonscreen=False
time=0
xmove=0.
ymove=1.
render_list=pygame.sprite.Group()
enen=1
starlist=pygame.sprite.Group()
enemy_list=pygame.sprite.Group()
bullet_list=pygame.sprite.Group()
pow_list=pygame.sprite.Group()
player_list=pygame.sprite.Group()
enemy_bull_list=pygame.sprite.Group()
shtinterval=0.5
shlvl=1
shieldtime=0.
oldshlvl=0
oldinterval=0
lev=0
komtimer=0.
kom1=None
kom2=None
kompanion=False
komonscreen=False
fptimer=0
fullpower=False
fponscreen=False
charge=0
score=0
pows=""
maxpower=9
enemysm=1
#Classi
class Player(pygame.sprite.Sprite):
    move_x=0
    move_y=0
    player=False
    komp=0
    speed=1.
    lives=3
    shielded=False
    def __init__(self,x,y,play,kom):
        pygame.sprite.Sprite.__init__(self)
        if play:
            self.image=pygame.Surface((20,20))
        else:
            self.image=pygame.Surface((20,10))
        self.image.fill((255,255,255))
        self.rect=self.image.get_rect()
        self.rect.x=x
        self.rect.y=y
        self.player=play
        self.komp=kom
        render_list.add(self)
        player_list.add(self)
    def update(self):
        if self.player:
            if self.shielded:
                self.image.fill((57,255,252))
            else:
                self.image.fill((255,255,255))
            if self.rect.x+self.move_x<=0 or self.rect.x+self.move_x>=620:
                self.move_x=0
                movex=0
            else:
                global xmove
                self.rect.x+=self.move_x
                if pygame.key.get_pressed()[K_LEFT]:
                    xmove=0.5
                elif pygame.key.get_pressed()[K_RIGHT]:
                    xmove=-0.5
                elif not pygame.key.get_pressed()[K_RIGHT] or not pygame.key.get_pressed()[K_LEFT]:
                    xmove=0
            if self.rect.y+self.move_y<=0 or self.rect.y+self.move_y>=460:
                self.move_y=0
                global ymove
                ymove=1.
            else:
                global ymove
                self.rect.y+=self.move_y
                if pygame.key.get_pressed()[K_UP]:
                    ymove=+1.5
                elif pygame.key.get_pressed()[K_DOWN]:
                    ymove=0.5
                elif not pygame.key.get_pressed()[K_UP] or not pygame.key.get_pressed()[K_DOWN]:
                    ymove=1
            collide=pygame.sprite.spritecollide(self,enemy_list,True)
            collide2=pygame.sprite.spritecollide(self,enemy_bull_list,True)
            if (collide or collide2) and not self.shielded:
                global shlvl,fullpower,oldshlvl,shtinterval,oldinterval,fptime
                self.lives-=1
                global pexp_snd
                exch=pexp_snd.play()
                if exch is not None:
                    left,right=Stereo_Pan(player.rect.x,640)
                    exch.set_volume(left,right)
                if not fullpower:
                    if shlvl>=2:
                        shlvl-=2
                    if shtinterval<=0.3:
                        shtinterval+=0.2
                else:
                    if oldshlvl<=2:
                        oldshlvl-=2
                    if oldinterval<=0.3:
                        shtinterval+=0.2
                fptime=0
                fullpower=False
                if player.speed>=1.4:
                    player.speed-=0.4
                self.shield()
                global shieldtime
                shieldtime=5.
                global komtimer
                komtimer=0.
            if self.lives<=0:
                self.kill()
        else:
            if self.rect.y+self.move_y<=0 or self.rect.y+self.move_y>=460:
                self.move_y=0
            else:
                self.rect.y+=self.move_y
            if self.komp==1:
                if self.rect.x+self.move_x<=-50 or self.rect.x+self.move_x>=570:
                    self.move_x=0
                else:
                    self.rect.x+=self.move_x
            elif self.komp==2:
                if self.rect.x+self.move_x>=670 or self.rect.x+self.move_x<=50:
                    self.move_x=0
                else:
                    self.rect.x+=self.move_x
    def shield(self):
        self.shielded=True
    def unshield(self):
        self.shielded=False
#---------------------------------------------------------
class Enemy(pygame.sprite.Sprite):
    state="flying"
    waittime=0
    direction=Vector()
    move_x=0
    move_y=0
    speed=150
    time=0
    d=0
    endwait=False
    shooter=False
    kamikaze=False
    energy=1
    def __init__(self,x,y,speedmod,sh,km,en):
        self.d=randint(0,1)
        pygame.sprite.Sprite.__init__(self)
        self.image=pygame.Surface((20,20))
        self.image.fill((255,0,0))
        self.rect=self.image.get_rect()
        self.rect.x=x
        self.rect.y=y
        render_list.add(self)
        self.time=0
        enemy_list.add(self)
        self.direction=Vector.FromAngle((random()*(pi/2))+pi/4)
        self.direction.Normalize()
        self.move_x=self.direction.to_tuple()[0]
        self.move_y=self.direction.to_tuple()[1]
        self.speed*=speedmod
        self.shooter=sh
        self.kamikaze=km
        self.energy=en
    def update(self):
        if self.state=="flying":
            if not self.kamikaze:
                if self.rect.x>=20 and self.rect.x<=620:
                    self.rect.x+=self.move_x*(tp/1000.)*self.speed
                else:
                    self.move_x=(-self.move_x)
                    self.rect.x+=self.move_x*(tp/1000.)*self.speed
            else:
                v=Vector.FromPoints((self.rect.x,self.rect.y),(player.rect.x+(player.rect.width/2),player.rect.y))
                v.Normalize()
                self.rect.x+=self.speed*v.to_tuple()[0]*(tp/1000.)
            self.rect.y+=self.move_y*(tp/1000.)*self.speed
            if self.rect.y in range(220,225):
                self.state="waiting"
        elif self.state=="waiting" and not self.endwait:
            if self.waittime>=2:
                self.direction=Vector.FromAngle(random()*3*pi/4)
                self.direction.Normalize()
                self.move_x=self.direction.to_tuple()[0]
                self.move_y=self.direction.to_tuple()[1]
                self.state="flying"
                self.endwait=True
            else:
                if self.d:
                    if self.rect.x+self.move_x<=620:
                        self.rect.x+=(tp/1000.)*self.speed
                    else:
                        self.move_x=0
                        self.d=0
                else:
                    if self.rect.x-self.move_x>=20:
                        self.rect.x-=(tp/1000.)*self.speed
                    else:
                        self.move_x=0
                        self.d=1
                self.waittime+=tp/1000.
        else:
            self.state="flying"
        if self.shooter:
            #E' uno shooter
            global tp
            self.time+=tp/1000.
            if self.time>=3.+randint(0,5) and self.rect.y>=0:
                EnemyBullet(self.rect.x+(self.rect.width/2),self.rect.y)
                self.time=0
        collide=pygame.sprite.spritecollide(self,bullet_list,True)
        if collide:
            self.energy-=1
            n=randint(0,3)
            global score
            score+=20
            if n==1 and self.energy==0:
                PowerUp(self.rect.x+self.rect.width/2,self.rect.y)
        if self.energy==0:
            global exp_snd
            expch=exp_snd.play()
            if expch is not None:
                left,right=Stereo_Pan(self.rect.x,640)
                expch.set_volume(left,right)
            self.kill()
        if self.rect.y>=490:
            self.kill()
#----------------------------------------------------------
class Bullet(pygame.sprite.Sprite):
    dir_x=0
    dir_y=0
    speed=500
    def __init__(self,x,y,theta,mirror=False):
        pygame.sprite.Sprite.__init__(self)
        self.image=pygame.Surface((2,10))
        self.image.fill((255,74,42))
        self.rect=self.image.get_rect()
        self.rect.x=x
        self.rect.y=y
        self.dir_x,self.dir_y=Vector.FromAngle(theta).to_tuple()
        if mirror:
            self.dir_x*=(-1)
        bullet_list.add(self)
        render_list.add(self)
    def update(self):
        self.rect.x+=self.dir_x*(tp/1000.)*self.speed
        self.rect.y+=self.dir_y*(tp/1000.)*self.speed
        if self.rect.y<=-20:
            self.kill()
class BigBullet(pygame.sprite.Sprite):
    speed=200
    def __init__(self,x,y):
        pygame.sprite.Sprite.__init__(self)
        self.image=pygame.Surface((20,50))
        self.image.fill((255,74,42))
        self.rect=self.image.get_rect()
        self.rect.x=x
        self.rect.y=y
        bullet_list.add(self)
        render_list.add(self)
    def update(self):
        self.rect.y-=tp/1000.*self.speed
        if self.rect.y<=-100:
            self.kill()
#----------------------------------------------------------
class PowerUp(pygame.sprite.Sprite):
    powtype=0
    speed=50
    def __init__(self,x,y):
        self.powtype=randint(1,7)
        pygame.sprite.Sprite.__init__(self)
        if self.powtype==1:
            self.image=PowTxt.render(" S ",True,(255,255,0),(255,0,0))
        elif self.powtype==2:
            self.image=PowTxt.render(" F ",True,(27,42,255),(255,128,0))
        elif self.powtype==3:
            global fponscreen
            if not fullpower and not fponscreen:
                self.image=PowTxt.render(" FP!! ", True, (255,0,0),(255,255,255))
                fponscreen=True
            else:
                return None
        elif self.powtype==4:
            self.image=PowTxt.render(" SS ", True, (0,0,0),(0,255,0))
        elif self.powtype==5:
            if not kompanion and not komonscreen:
                global komonscreen
                komonscreen=True
                self.image=PowTxt.render(" K ", True, (255,255,0), (160,39,134))
            else:
                return None
        elif self.powtype==6:
            global shieldonscreen
            if not shieldonscreen and not player.shielded:
                self.image=PowTxt.render("  SH  ", True, (0,0,0),(57,255,252))
                shieldonscreen=True
            else:
                return None
        elif self.powtype==7:
            self.image=PowTxt.render("  A  ", True, (255,255,255),(189,0,3))
        self.rect=self.image.get_rect()
        self.rect.x=x
        self.rect.y=y
        render_list.add(self)
        pow_list.add(self)
    def update(self):
        self.rect.y+=(tp/1000.)*self.speed
        collide=pygame.sprite.spritecollide(self,player_list,False)
        if collide:
            #PowerUp Potenza
            if self.powtype==1:
                global shlvl
                if not fullpower:
                    shlvl+=1
                else:
                    oldshlvl+=1
                if shlvl==maxpower:
                    global score
                    score+=2000
                else:
                    score+=1000
            #PowerUp Velocita' Cannone
            elif self.powtype==2:
                global shtinterval
                global score
                if not fullpower:
                    if shtinterval>0.2:
                        shtinterval-=0.1
                        score+=500
                    else:
                        shtinterval=0.1
                        score+=1000
                else:
                    if oldinterval>0.2:
                        oldinterval-=0.1
                        score+=500
                    else:
                        oldinterval=0.1
                        score+=1000
            #PowerUp FullPower
            elif self.powtype==3:
                global shlvl
                global oldshlvl
                global oldinterval
                global fponscreen
                fponscreen=False
                global shtinterval
                oldinterval=shtinterval
                shtinterval=0.1
                oldshlvl=shlvl
                shlvl=maxpower
                global fullpower
                fullpower=True
                global fptimer
                fptimer=20.
                global score
                score+=1000
            #PowerUp Velocita' Nave
            elif self.powtype==4:
                player.speed+=0.2
                if player.speed>=2:
                    player.speed=2
                global score
                score+=500
            #PowerUp Kompanion
            elif self.powtype==5:
                global score
                global kompanion
                kompanion=True
                global komonscreen
                komonscreen=False
                global kom1,kom2
                score+=1000
                global komtimer
                komtimer=60.
                kom1=Player((player.rect.x+(player.rect.width/2))-50,player.rect.y,False,int(1))
                kom1.move_x=player.move_x
                kom1.move_y=player.move_y
                kom2=Player((player.rect.x+(player.rect.width/2))+30,player.rect.y,False,int(2))
                kom2.move_x=player.move_x
                kom2.move_y=player.move_y
            #PowerUp Shield
            elif self.powtype==6:
                player.shield()
                global shieldtime
                shieldtime=60.
                shieldonscreen=False
                global score
                score+=750
            #PowerUp Assistance
            elif self.powtype==7:
                for n in xrange(20,620,40):
                    BigBullet(n,510)
            global pow_sound
            pow_ch=pow_sound.play()
            if pow_ch is not None:
                left,right=Stereo_Pan(player.rect.x,640)
                pow_ch.set_volume(left,right)
            self.kill()
#----------------------------------------------------------
# Classe Star
#----------------------------------------------------------
class Star(pygame.sprite.Sprite):
    speed=0
    rnd=0
    rnd2=0
    def __init__(self,mode,ry):
        pygame.sprite.Sprite.__init__(self)
        while self.rnd<=0.1:
            self.rnd=random()
        while self.rnd2<=0.2:
            self.rnd2=random()
        if mode==1:
            self.image=pygame.Surface((6*self.rnd2,6*self.rnd2))
            self.image.fill((255*self.rnd,255*self.rnd,255*self.rnd))
            self.speed=200
        elif mode==2:
            self.image=pygame.Surface((5*self.rnd2,5*self.rnd2))
            self.image.fill((102*self.rnd,255*self.rnd,252*self.rnd))
            self.speed=100
        elif mode==3:
            self.image=pygame.Surface((self.rnd2*4,self.rnd2*4))
            self.image.fill((0,255*self.rnd,255*self.rnd))
            self.speed=50
        self.rect=self.image.get_rect()
        self.rect.x=randint(-500,1000)
        if ry:
            self.rect.y=randint(0,480)
        else:
            self.rect.y=-10
        starlist.add(self)
    def update(self):
        global xmove,ymove
        self.rect.x+=self.speed*xmove*(tp/1000.)
        self.rect.y+=self.speed*ymove*(tp/1000.)
        if self.rect.y>480:
            self.kill()
#----------------------------------------------------------
# Classe Boss
#----------------------------------------------------------
class Boss(pygame.sprite.Sprite):
    energy=0
    movex=0
    speed=0
    time=0
    def __init__(self,x,y):
        pygame.sprite.Sprite.__init__(self)
        self.image=pygame.Surface((200,50))
        self.image.fill((147,67,10))
        self.rect=self.image.get_rect()
        self.rect.x=x
        self.rect.y=y
        self.energy=500
        self.movex=1
        self.speed=100
        render_list.add(self)
        enemy_list.add(self)
    def update(self):
        global tp
        self.time+=tp/1000.
        num=randint(0,100)
        if num==50:
            self.movex=-self.movex
        if self.time>=1.+randint(0,3):
            EnemyBullet(self.rect.x+(self.rect.width/2),self.rect.y+self.rect.height)
            self.time=0
        if self.rect.x>=440:
            self.movex=-1
        elif self.rect.x<=0:
            self.movex=1
        global tp
        self.rect.x+=self.movex*self.speed*(tp/1000.)
        collide=pygame.sprite.spritecollide(self,bullet_list,True)
        if collide:
            self.energy-=1
            global bhit_snd
            bhch=bhit_snd.play()
            if bhch is not None:
                left,right=Stereo_Pan(self.rect.x,640)
                bhch.set_volume(left,right)
        if self.energy==0:
            global score
            score+=10000
            self.kill()
            global bossex_snd
            bexpch=bossex_snd.play()
            if bexpch is not None:
                left,right=Stereo_Pan(self.rect.x,640)
                bexpch.set_volume(left,right)
            global showtime
            showtime=False
#----------------------------------------------------------
#Classe EnemyBullet
#----------------------------------------------------------
class EnemyBullet(pygame.sprite.Sprite):
    speed=200
    movex=0
    movey=0
    def __init__(self,x,y):
        pygame.sprite.Sprite.__init__(self)
        self.image=pygame.Surface((10,10))
        self.image.fill((255,255,0))
        self.rect=self.image.get_rect()
        self.rect.x=x
        self.rect.y=y
        v=Vector.FromPoints((x,y),(player.rect.x+(player.rect.width/2),player.rect.y+(player.rect.height/2)))
        v.Normalize()
        self.movex,self.movey=v.to_tuple()
        render_list.add(self)
        enemy_bull_list.add(self)
        global esht_snd
        eshtch=esht_snd.play()
        if eshtch is not None:
            left,right=Stereo_Pan(player.rect.x,640)
            eshtch.set_volume(left,right)
    def update(self):
        global tp
        self.rect.x+=self.movex*self.speed*(tp/1000.)
        self.rect.y+=self.movey*self.speed*(tp/1000.)
#----------------------------------------------------------
#Funzioni
#----------------------------------------------------------
def Shoot():
    global charge
    if charge==100 and bool(pygame.key.get_pressed()[122]):
        BigBullet(player.rect.x+(player.rect.width/2),player.rect.y-50)
        BigBullet(player.rect.x+(player.rect.width/2)+40,player.rect.y-50)
        BigBullet(player.rect.x+(player.rect.width/2)-40,player.rect.y-50)
        global charge
        charge=0
    if time>=shtinterval and bool(pygame.key.get_pressed()[122]):
        global sht
        sht=True
        time=0
        if charge-(tp/1000.)*600>0:
            charge-=(tp/1000.)*600
        else:
            charge=0.1
    else:
        global sht
        global time
        sht=False
        time+=tp/1000.
    if sht:
        global shlvl
        if shlvl==1:
            Bullet(player.rect.x+player.rect.width/2,player.rect.y-10,-pi/2)
        elif shlvl==2:
            Bullet(player.rect.x,player.rect.y-10,-pi/2)
            Bullet(player.rect.x+player.rect.width,player.rect.y-10,-pi/2)
        elif shlvl==3:
            Bullet(player.rect.x,player.rect.y-10,-pi/2)
            Bullet(player.rect.x+player.rect.width,player.rect.y-10,-pi/2)
            Bullet(player.rect.x+player.rect.width/2,player.rect.y-15,-pi/2)
        elif shlvl==4:
            Bullet(player.rect.x+player.rect.width/2,player.rect.y-15,-pi/2)
            Bullet(player.rect.x,player.rect.y-10,-4*pi/9,True)
            Bullet(player.rect.x+player.rect.width,player.rect.y-10,-4*pi/9)
        elif shlvl==5:
            Bullet(player.rect.x+player.rect.width,player.rect.y-10,-pi/2)
            Bullet(player.rect.x,player.rect.y-10,-4*pi/9,True)
            Bullet(player.rect.x+player.rect.width,player.rect.y-10,-4*pi/9)
            Bullet(player.rect.x,player.rect.y-10,-pi/2)
        elif shlvl==6:
            Bullet(player.rect.x+player.rect.width,player.rect.y-10,-pi/2)
            Bullet(player.rect.x,player.rect.y-10,-4*pi/9,True)
            Bullet(player.rect.x+player.rect.width,player.rect.y-10,-4*pi/9)
            Bullet(player.rect.x,player.rect.y-10,-pi/2)
            Bullet(player.rect.x+player.rect.width/2,player.rect.y-15,-pi/2)
        elif shlvl==7:
            Bullet(player.rect.x+player.rect.width/2,player.rect.y-15,-pi/2)
            Bullet(player.rect.x,player.rect.y-10,-4*pi/9,True)
            Bullet(player.rect.x+player.rect.width,player.rect.y-10,-4*pi/9)
            Bullet(player.rect.x+player.rect.width,player.rect.y-10,-2*pi/3,True)
            Bullet(player.rect.x,player.rect.y-10,-2*pi/3)
        elif shlvl==8:
            Bullet(player.rect.x+player.rect.width,player.rect.y-10,-pi/2)
            Bullet(player.rect.x,player.rect.y-10,-pi/2)
            Bullet(player.rect.x,player.rect.y-10,-4*pi/9,True)
            Bullet(player.rect.x+player.rect.width,player.rect.y-10,-4*pi/9)
            Bullet(player.rect.x+player.rect.width,player.rect.y-10,-2*pi/3,True)
            Bullet(player.rect.x,player.rect.y-10,-2*pi/3)
        elif shlvl==9:
            Bullet(player.rect.x+player.rect.width/2,player.rect.y-15,-pi/2)
            Bullet(player.rect.x+player.rect.width, player.rect.y-10, -pi/2)
            Bullet(player.rect.x,player.rect.y-10, -pi/2)
            Bullet(player.rect.x,player.rect.y-10,-4*pi/9,True)
            Bullet(player.rect.x+player.rect.width,player.rect.y-10,-4*pi/9)
            Bullet(player.rect.x+player.rect.width,player.rect.y-10,-2*pi/3,True)
            Bullet(player.rect.x,player.rect.y-10,-2*pi/3)
        else:
            shlvl=9
        global sht_snd
        shtch=sht_snd.play()
        if shtch is not None:
            left,right=Stereo_Pan(player.rect.x,640)
            shtch.set_volume(left,right)
        if kompanion:
            Bullet(kom1.rect.x+kom1.rect.width/2,kom1.rect.y-10,-pi/2)
            Bullet(kom2.rect.x+kom2.rect.width/2,kom2.rect.y-10,-pi/2)

    else:
        if charge=3.0:
            enemysm=3.0
    if lev%10==0:
        player.lives+=1
        global enen
        enen+=1
    for n in xrange(0,20*(lev)):
        global enen
        Enemy(randint(20,620),randint(-5000,-500),enemysm,not bool(randint(0,20)),not bool(randint(0,6)),enen)
    if lev%5==0:
        global boss
        boss=Boss(320,100)
        global showtime
        showtime=True
def SoundInit():
    global pow_sound,pexp_snd,exp_snd,sht_snd,esht_snd,bossex_snd,bhit_snd
    pow_sound=pygame.mixer.Sound("pow.wav")
    pexp_snd=pygame.mixer.Sound("selfexp.wav")
    exp_snd=pygame.mixer.Sound("expl.wav")
    sht_snd=pygame.mixer.Sound("sht.wav")
    esht_snd=pygame.mixer.Sound("enemysht.wav")
    bossex_snd=pygame.mixer.Sound("bossexp.wav")
    bhit_snd=pygame.mixer.Sound("bhit.wav")
def Stereo_Pan(x,sw):
    rvol=float(x)/sw
    lvol=1.-rvol
    return (lvol,rvol)
#----------------------------------------------------------
#Inizio Programma
#----------------------------------------------------------
pygame.init()
SoundInit()
screen=pygame.display.set_mode((640,480),0,32)
pygame.display.set_caption("Primitive Shooter II!!!")
clock=pygame.time.Clock()
player=Player(320,455,True,0)
PowTxt=pygame.font.SysFont("Arial",10)
for f in xrange(0,100):
    Star(1,True)
    Star(2,True)
    Star(3,True)
while True:
    screen.fill((0,0,0))
    for s in starlist:
        s.update()
    starlist.draw(screen)
    for event in pygame.event.get():
        if event.type==QUIT:
            exit()
        if event.type==KEYDOWN:
            if event.key==K_LEFT:
                player.move_x=-5*player.speed
                if kompanion:
                    kom1.move_x=player.move_x
                    kom2.move_x=player.move_x
            if event.key==K_RIGHT:
                player.move_x=5*player.speed
                if kompanion:
                    kom1.move_x=player.move_x
                    kom2.move_x=player.move_x
            if event.key==K_UP:
                player.move_y=-5*player.speed
                if kompanion:
                    kom1.move_y=player.move_y
                    kom2.move_y=player.move_y
            if event.key==K_DOWN:
                player.move_y=5*player.speed
                if kompanion:
                    kom1.move_y=player.move_y
                    kom2.move_y=player.move_y
            if event.key==K_z:
                sht=True
        if event.type==KEYUP:
            if event.key==K_LEFT:
                player.move_x=0
                if kompanion:
                    kom1.move_x=0
                    kom2.move_x=0
            if event.key==K_RIGHT:
                player.move_x=0
                if kompanion:
                    kom1.move_x=0
                    kom2.move_x=0
            if event.key==K_UP:
                player.move_y=0
                if kompanion:
                    kom1.move_y=0
                    kom2.move_y=0
            if event.key==K_DOWN:
                player.move_y=0
                if kompanion:
                    kom1.move_y=0
                    kom2.move_y=0
            if event.key==K_z:
                sht=False
#Orologio
    tp=clock.tick(40)
#Starfield
    global totime
    totime+=tp
    if totime>2.:
        Star(1,False)
        Star(2,False)
        Star(3,False)
#Sparo Temporizzato
    if not GameOver:
        Shoot()
#Eventuale Fullpower
    if fullpower:
        global fptimer
        fptimer-=tp/1000.
        if fptimer<=0:
            global shlvl
            global oldshlvl
            global oldinterval
            global shtinterval
            shtinterval=oldinterval
            shlvl=oldshlvl
            global fullpower
            fullpower=False
#Eventuale Kompanion
    if kompanion:
        global komtimer
        komtimer-=tp/1000.
        if komtimer<=0:
            global kom1,kom2,kompanion
            kom1.kill()
            kom2.kill()
            kompanion=False
#Aggiornamenti di schermo
    player.update()
    if kompanion:
        kom1.update()
        kom2.update()
    render_list.draw(screen)
    ch=PowTxt.render(str(charge)+ " %",True,(255,255,255))
    screen.blit(ch,(10,10))
    powrec=pygame.Surface((150*(charge/100.),10))
    powrec.fill((255-((charge*250)/100),(charge*250)/100,0))
    screen.blit(powrec,(60,10))
    ch2=PowTxt.render("Score: "+str(score),True,(255,255,255))
    screen.blit(ch2,(500,10))
    for bullet in bullet_list:
        bullet.update()
    for powerup in pow_list:
        powerup.update()
    for enemy in enemy_list:
        enemy.update()
    if len(enemy_list)==0:
        global lev
        lev+=1
        Level()
    if player.lives==0 or GameOver:
        go=PowTxt.render("Game Over",True,(255,0,0))
        screen.blit(go,(320,240))
        GameOver=True
    ch3=PowTxt.render("Level: "+str(lev)+", Lives: "+str(player.lives),True,(255,255,255))
    pow1=""
    pow2=""
    pow3=""
    if fullpower:
        global fptimer
        pow1="FP: "+str(round(fptimer,2))
    else:
        pow1=""
    if player.shielded:
        global shieldtime
        shieldtime-=tp/1000.
        pow3="SH: "+str(round(shieldtime,2))
        if shieldtime<=0:
            player.unshield()
    else:
        pow3=""
    if kompanion:
        global komtimer
        pow2="K: "+str(round(komtimer,2))
    else:
        pow2=""
    chboss=PowTxt.render("BOSS: ", True, (255,0,0))
    if showtime:
        screen.blit(chboss,(10,50))
        global boss
        energy=pygame.Surface((boss.energy/2,10))
        energy.fill((255,0,0))
        screen.blit(energy,(50,50))
    pows=pow1 + "  " + pow2 + "  " + pow3
    for bullet in enemy_bull_list:
        bullet.update()
    ch4=PowTxt.render(pows,True,(255,255,255))
    screen.blit(ch4,(20,470))
    screen.blit(ch3, (300,470))
    pygame.display.flip()

I Suoni e le differenze

Il pacchetto di suoni che potete scaricare da questo link è stato creato con SFXR.

Il soundPack è necessario affinchè il gioco funzioni. Basta estrarne il contenuto nella stessa cartella dove si trovano Game.py e Vector.py