Skip to navigation
Logo Penaz's Area

cat /dev/random > penaz

Pygame: Primitive Shooter!


Un piccolo progetto che ho creato nel tempo libero qualche mese fa, Primitive Shooter è uno shooter semplice creato con Python e Pygame.

Buongiorno a tutti, qualche mese fa ho voluto provare un po' le mie (scarse) competenze di programmazione in Python e Pygame scrivendo un piccolo shooter senza grafiche sfavillanti o effetti speciali (tutti gli elementi sono rettangoli!): grezzo, primitivo e rude; proprio come me.

Il gioco è completamente contenuto in 269 righe di codice, contenute a loro volta in un solo file.

I moduli principali sono:

Modulo Descrizione
Classe Player() Una semplice classe che rappresenta il giocatore
Classe Enemy() Un semplice nemico, rappresentato da un quadrato rosso
Classe Bullet() Un semplice proiettile
Classe PowerUp() Un semplice quadratino azzurro che rappresenta un potenziatore
Classe PowerBullet() Un Proiettile Più potente
Funzione Shoot() Controlla il cannone e la sua potenza
Funzione Level() Gestisce la generazione dei livelli

Le caratteristiche supportate dal gioco sono altamente all'avanguardia:

  • Movimento della nave e dei nemici
  • Grafica dignitosamente quadrettosa
  • Supporto per le vite
  • Supporto per i Powerup
  • Schermata finale di Game Over

Se volete provare il gioco è sufficiente scaricare il codice sorgente, presente qui sotto e avviarlo con il comando:

python shooter.py

Primitive Shooter è, diversamente dagli altri pezzi di codice contenuti nel blog, distribuito con la sola clausola di "Attribuzione", il programma potrà tranquillamente essere modificato e rivenduto, purchè venga citato il nome dell'autore.

Ecco il codice sorgente del programma:

#!/usr/bin/env python
import pygame
from pygame import *
from sys import exit
from random import randint
import Vector
from math import floor, ceil
from Vector import *
render_list=pygame.sprite.Group()
score=0
empower=False
tp=0
kills=0
killlevel=0
lv=1
empow=0
shlvl=1
lives=3
class Player(pygame.sprite.Sprite):
    move_x=0
    move_y=0
    def __init__(self,x,y):
        pygame.sprite.Sprite.__init__(self)
        self.image=pygame.Surface((20,20))
        self.image.fill((255,255,255))
        self.rect=self.image.get_rect()
        self.rect.x=x
        self.rect.y=y
        render_list.add(self)
    def update(self):
        if self.rect.x+self.move_x < 620 and self.rect.x+self.move_x >0:
            self.rect.x+=self.move_x
        if self.rect.y+self.move_y < 460 and self.rect.y+self.move_y >0:
            self.rect.y+=self.move_y
        collision=pygame.sprite.spritecollide(self,enemy_list,True)
        if collision:
            global lives
            lives-=1
            global kills
            kills+=1
pow_list=pygame.sprite.Group()
enemy_list=pygame.sprite.Group()
class Powerup(pygame.sprite.Sprite):
    def __init__(self,x,y):
        pygame.sprite.Sprite.__init__(self)
        self.image=pygame.Surface((15,15))
        self.image.fill((73,255,234))
        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+=2
        if self.rect.y>=480:
            self.kill()
        collide=pygame.sprite.spritecollide(player,pow_list,True)
        if collide:
            global shlvl
            shlvl+=1
            self.kill()
class Enemy(pygame.sprite.Sprite):
    destination=0
    def __init__(self,x,y):
        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
        enemy_list.add(self)
        render_list.add(self)
        self.destination=randint(0,620)
    def update(self):
        self.rect.y+=3
        if self.rect.y>=0:
            if self.rect.x>self.destination:
                self.rect.x-=randint(1,5)
            elif self.rect.x < self.destination:
                self.rect.x+=randint(1,5)
            if self.rect.y>480:
                self.kill()
                global kills
                kills+=1
bullets=pygame.sprite.Group()
class PowerBullet(pygame.sprite.Sprite):
    speed=10
    def __init__(self,x,y):
        pygame.sprite.Sprite.__init__(self)
        self.image=pygame.Surface((4,10))
        self.image.fill((17,128,255))
        self.rect=self.image.get_rect()
        self.rect.x=x
        self.rect.y=y
        bullets.add(self)
        render_list.add(self)
    def update(self):
        self.rect.y-=self.speed
        if self.rect.y<=-5:
            self.kill()
        collide=pygame.sprite.spritecollide(self,enemy_list,True)
        if collide:
            global score
            global kills
            score+=20
            kills+=1
            n=randint(0,2)
            if n==1:
                Powerup(320,0)
                global score
                score+=10

class Bullet(pygame.sprite.Sprite):
    speed=300
    direction=Vector()
    heading=Vector()
    move_x=0
    def __init__(self,x,y,dirx):
        pygame.sprite.Sprite.__init__(self)
        self.image=pygame.Surface((2,5))
        self.image.fill((255,128,12))
        self.rect=self.image.get_rect()
        self.rect.x=x
        self.rect.y=y
        bullets.add(self)
        render_list.add(self)
        self.direction=Vector.FromPoints((x,y),(x+dirx,-20))
        self.direction.normalize()
        self.move_x=(tp/1000.)*self.speed*self.direction.to_tuple()[0]
        if self.move_x<0:
            self.move_x=floor(self.move_x)
        elif self.move_x>0:
            self.move_x=ceil(self.move_x)
    def update(self):
        self.rect.x+=self.move_x
        self.rect.y+=(tp/1000.)*self.speed*self.direction.to_tuple()[1]
        if self.rect.y<=-5:
            self.kill()
        collide=pygame.sprite.spritecollide(self,enemy_list,True)
        if collide:
            self.kill()
            global score
            score+=20
            global kills
            kills+=1
            n=randint(0,15)
            if n==1:
                Powerup(320,0)
                global score
                score+=10
def Shoot():
    if shlvl==1:
        Bullet(player.rect.x+(player.rect.width/2),player.rect.y,0)
    elif shlvl==2:
        Bullet(player.rect.x,player.rect.y,0)
        Bullet(player.rect.x+player.rect.width,player.rect.y,0)
    elif shlvl==3:
        Bullet(player.rect.x+(player.rect.width/2),player.rect.y-10,0)
        Bullet(player.rect.x,player.rect.y,0)
        Bullet(player.rect.x+player.rect.width,player.rect.y,0)
    elif shlvl==4:
        Bullet(player.rect.x+(player.rect.width/2),player.rect.y-10,0)
        Bullet(player.rect.x,player.rect.y,-5)
        Bullet(player.rect.x+player.rect.width,player.rect.y,5)
    elif shlvl==5:
        Bullet(player.rect.x+(3*player.rect.width/4),player.rect.y-10,0)
        Bullet(player.rect.x,player.rect.y,-5)
        Bullet(player.rect.x+(player.rect.width/4),player.rect.y-10,0)
        Bullet(player.rect.x+player.rect.width,player.rect.y,5)
    elif shlvl==6:
        Bullet(player.rect.x+(3*player.rect.width/4),player.rect.y-10,0)
        Bullet(player.rect.x,player.rect.y,-5)
        Bullet(player.rect.x,player.rect.y+10,-7)
        Bullet(player.rect.x+player.rect.width,player.rect.y+10,7)
        Bullet(player.rect.x+(player.rect.width/4),player.rect.y-10,0)
        Bullet(player.rect.x+player.rect.width,player.rect.y,5)
    elif shlvl==7:
        Bullet(player.rect.x+(3*player.rect.width/4),player.rect.y-10,0)
        Bullet(player.rect.x,player.rect.y,-5)
        Bullet(player.rect.x+(player.rect.width/4),player.rect.y-10,0)
        Bullet(player.rect.x+player.rect.width,player.rect.y,5)
        Bullet(player.rect.x,player.rect.y+5,-200)
        Bullet(player.rect.x+player.rect.width,player.rect.y+5,200)
    elif shlvl>7:
        global shlvl
        shlvl=7
player=Player(320,440)
pygame.init()
screen=pygame.display.set_mode((640,480),0,32)
pygame.display.set_caption("Primitive Shooter!!")
clock=pygame.time.Clock()
f=pygame.font.SysFont("Arial",12)
g=pygame.font.SysFont("Arial",30,True,True)
gtext=g.render("Game Over",True,(255,0,0),None)
def Level():
        global killlevel
        killlevel=lv*20
        for n in range(20*lv):
            x=randint(0,640)
            y=randint(-5000,-100)
            Enemy(x,y)
Level()
while True:
    for event in pygame.event.get():
        if event.type==QUIT:
            exit()
        if event.type==KEYDOWN:
            if event.key==K_LEFT:
                player.move_x=-7
            if event.key==K_RIGHT:
                player.move_x=7
            if event.key==K_UP:
                player.move_y=-7
            if event.key==K_DOWN:
                player.move_y=7
            if event.key==K_z:
                if not empower:
                    Shoot()
                else:
                    PowerBullet(player.rect.x+(player.rect.width/2),player.rect.y)
        if event.type==KEYUP:
            if event.key==K_LEFT:
                player.move_x=0
            if event.key==K_RIGHT:
                player.move_x=0
            if event.key==K_UP:
                player.move_y=0
            if event.key==K_DOWN:
                player.move_y=0
            if event.key==K_e:
                empow=1
            if event.key==K_m and empow==1:
                empow=2
            if event.key==K_p and empow==2:
                empow=3
            if event.key==K_o and empow==3:
                empow=4
            if event.key==K_w and empow==4:
                empower=True
                player.image.fill((255,12,128))
    player.update()
    for bullet in bullets:
        bullet.update()
    screen.fill((0,0,0))
    render_list.draw(screen)
    s=f.render(str(score),True,(255,255,255),None)
    l=f.render("Level "+str(lv),True,(255,255,255),None)
    live=f.render("Lives: " +str(lives),True,(255,255,255),None)
    screen.blit(live,(400,460))
    screen.blit(l,(400,10))
    screen.blit(s,(10,10))
    for enemy in enemy_list:
        enemy.update()
    global kills
    for powerup in pow_list:
        powerup.update()
    if kills==killlevel:
        score+=1000
        lv+=1
        kills=0
        Level()
    if lives<=0:
        player.kill()
        for enemy in enemy_list:
            enemy.kill()
        screen.blit(gtext,(240,200))
    pygame.display.flip()
    global tp
    tp=clock.tick(60)

Questo è quanto!

Buona programmazione!

Penaz.