C'est un petit jeu de tir dans lequel on contrôle une tourelle qui doit détruire des virus. Il se joue à la souris et ne contient aucune image. Tout est dessiné à l'aide du module pygame.draw.
Source / Exemple :
#!/usr/bin/python
#-*- coding:UTF-8 -*-
# -----
# VirShoot
# Créé par KS
# -----
###############################################################################
# Initialisation ##############################################################
###############################################################################
####################
# Modules ##########
####################
import pygame, sys
from pygame.locals import *
from math import sin, cos, atan2, pi
from random import random, randrange
pygame.font.init()
#####################
# Constantes ########
#####################
size = width, height = 800, 600
screen = 0
background = ((0, 150, 0), (0, 255, 0))
infos = ((0, 0, 255), (150, 150, 255), (255, 255, 0))
hero = ((255, 255, 0),(0,0,0), (100, 100, 100), (255, 0, 0), (200, 200, 200))
ennemi = ((150, 0, 0), (255, 150, 150))
################################################################################
# Fonctions ####################################################################
################################################################################
def arriereplan(surface):
#Trafce les lignes à l'arrière plan. C'est la fonction utilisée pour effacer l'écran.
global background, width, height
surface.fill(background[0])
i = width / 10
while i < width:
pygame.draw.line(surface, background[1], (i, 0), (i, height))
i += width / 10
i = height / 10
while i < height:
pygame.draw.line(surface, background[1], (0, i), (width, i))
i += height / 10
def intro(ecran):
#Début du jeu - Affichage du titre, du meilleur score.
global screen, background, size
#Récupération du score
score = open("best.sc", "r")
scoretxt = score.readline()
infos = ["","",""]
i = 0
j = 0
while i < len(scoretxt):
if not scoretxt[i] == ":":
infos[j] += scoretxt[i]
else:
j += 1
i += 1
#Boucle de présentation
continuer = 1
while continuer:
arriereplan(ecran)
titreu = pygame.font.Font("freesansbold.ttf", 100).render("VIRTUAL", 1, background[1])
titruect = titreu.get_rect()
titruect.center = (width/2 - 100, 60)
titred = pygame.font.Font("freesansbold.ttf", 100).render("SHOOTER", 1, background[1])
titrdrect = titred.get_rect()
titrdrect.center = (width/2 + 100, 160)
meilleur = pygame.font.Font("freesansbold.ttf", 50).render(infos[0]+" a fait "+infos[1] + " points en "+ infos[2] + " frames", 1, background[1])
if meilleur.get_width() > width:
meilleur = pygame.transform.scale(meilleur, (width - 100, meilleur.get_height() * (width - 100) / meilleur.get_width()))
meilleurect = meilleur.get_rect()
meilleurect.center = (width / 2, height / 2)
press = pygame.font.Font("freesansbold.ttf", 20).render("Entree pour continuer - F7 pour le mode plein ecran", 1, background[1])
pressrect = press.get_rect()
pressrect.center = (width / 2, height - 30)
ecran.blit(titreu, titruect)
ecran.blit(titred, titrdrect)
ecran.blit(meilleur, meilleurect)
ecran.blit(press, pressrect)
pygame.display.flip()
#On quitte si le joueur appuie sur echap, on alterne plein écran/fenêtré si le joueur appuie sur F7
# et on lance le jeu si le joueur appuie sur entrée
for event in pygame.event.get():
if event.type == QUIT or pygame.key.get_pressed()[K_ESCAPE]:
bye()
if pygame.key.get_pressed()[K_RETURN]:
continuer = 0
if pygame.key.get_pressed()[K_F7]:
screen = chgscreen(ecran, size, screen)
def jeu(ecran,curseur):
#Le jeu en lui-même
global width, height, screen
heros = Hero((width/2, height/2), ecran)
ennemis = Controlleur(heros, ecran)
#Boucle de jeu
while heros.vie > 0:
arriereplan(ecran)
heros.update()
ennemis.update()
curseur.update()
pygame.display.flip()
for event in pygame.event.get():
if event.type == QUIT or pygame.key.get_pressed()[K_ESCAPE]:
bye()
if pygame.key.get_pressed()[K_F7]:
screen = chgscreen(ecran, size, screen)
pygame.time.delay(10)
end(ecran, ennemis.score, ennemis.temps)
def end(surface, score, temps):
#Fin de la partie - écriture du score si c'est le meilleur
global background, width, height
highscores = open("best.sc","r")
highscore = highscores.readline()
highscores.close()
ligne = ["","",""]
i = 0
j = 0
while i < len(highscore):
if not highscore[i] == ":":
ligne[j] += highscore[i]
else:
j += 1
i += 1
bestscore = int(ligne[1]) + int(ligne[2])
#Si le joueur a fait le meilleur score...
if score + temps > bestscore:
nom = ""
while not pygame.key.get_pressed()[K_RETURN]:
arriereplan(surface)
#Affichage du score
infoscore = pygame.font.Font("freesansbold.ttf", 50).render("Score: "+str(score+temps), 1, background[1])
inforect = infoscore.get_rect()
inforect.center = (width / 2, 20)
#Affichage du nom choisi
nomtxt = pygame.font.Font("freesansbold.ttf", 50).render("Votre nom: "+nom, 1, background[1])
#On diminue la surface du texte s'il dépasse la fenêtre
if nomtxt.get_width() > width:
nomtxt = pygame.transform.scale(nomtxt, (width - 100, nomtxt.get_height() * (width-100) / nomtxt.get_width()))
nomrect = nomtxt.get_rect()
nomrect.center = (width/2, height/2)
press = pygame.font.Font("freesansbold.ttf",20).render("Appuyez sur entree pour continuer", 1, background[1])
pressrect = press.get_rect()
pressrect.center = (width/2, height - 30)
#Entrée du nom
for event in pygame.event.get():
keys = pygame.key.get_pressed()
lettres = {keys[K_q]:"a",keys[K_b]:"b",keys[K_c]:"c",keys[K_d]:"d",keys[K_e]:"e",keys[K_f]:"f",keys[K_g]:"g",keys[K_h]:"h",keys[K_i]:"i",keys[K_j]:"j",keys[K_k]:"k",keys[K_l]:"l",keys[K_SEMICOLON]:"m",
keys[K_n]:"n",keys[K_o]:"o",keys[K_p]:"p",keys[K_a]:"q",keys[K_r]:"r",keys[K_s]:"s",keys[K_t]:"t",keys[K_u]:"u",keys[K_v]:"v",keys[K_z]:"w",keys[K_x]:"x",keys[K_y]:"y",keys[K_w]:"z",
keys[K_SPACE]:" "}
try:
nom += lettres[1]
except:
pass
if pygame.key.get_pressed()[K_BACKSPACE]:
i = 0
temp = ""
while i < len(nom) - 1:
temp += nom[i]
i += 1
nom = temp
if event.type == QUIT or pygame.key.get_pressed()[K_ESCAPE]:
bye()
surface.blit(infoscore, inforect)
surface.blit(nomtxt, nomrect)
surface.blit(press, pressrect)
pygame.display.flip()
#Ecriture du score
writescore = open("best.sc", "w")
writescore.write(nom + ":" + str(score) + ":" + str(temps))
writescore.close()
#Sinon...
else:
while not pygame.key.get_pressed()[K_RETURN]:
arriereplan(surface)
infoscore = pygame.font.Font("freesansbold.ttf", 50).render("Score: "+str(score.temps), 1, background[1])
inforect = infoscore.get_rect()
inforect.center = (width / 2, 20)
press = pygame.font.Font("freesansbold.ttf",20).render("Appuyez sur entree pour continuer", 1, background[1])
pressrect = press.get_rect()
pressrect.center = (width/2, height - 10)
surface.blit(infoscore, inforect)
surface.blit(press, pressrect)
pygame.display.flip()
def chgscreen(surface, size, state):
#On alterne entre plein écran/fenêtré
if state == 0:
surface = pygame.display.set_mode(size, FULLSCREEN)
state = 1
else:
surface = pygame.display.set_mode(size)
state = 0
return state
def bye():
#On qutte le programme
pygame.quit()
sys.exit()
################################################################################
# Classes ######################################################################
################################################################################
class Hero():
"Classe du heros"
speed = 30
viemax = 10
vie = 10
rayon = 20
canon = 50
tirs = []
delaimax = 5
delai = 0
def __init__(self, pos, surface, colors=hero):
"Initialisation"
self.pos = pos
self.colors = colors
self.surface = surface
def update(self):
"Actions et mise à jour de la tourelle"
if not pygame.mouse.get_pressed()[2]:
self.pos = (self.pos[0] + (pygame.mouse.get_pos()[0] - self.pos[0]) / self.speed, self.pos[1] + (pygame.mouse.get_pos()[1] - self.pos[1]) / self.speed)
angle = atan2(pygame.mouse.get_pos()[1] - self.pos[1], pygame.mouse.get_pos()[0] - self.pos[0])
#On dessine le rectangle avec la fonction draw.polygon
pygame.draw.polygon(self.surface, self.colors[2], [(self.pos[0] + cos(angle + pi/2) * 5, self.pos[1] + sin(angle+pi/2) *5),
(self.pos[0] + cos(angle - pi/2) * 5, self.pos[1] + sin(angle-pi/2) *5),
(self.pos[0] + cos(angle) * self.canon + cos(angle - pi /2) * 5, self.pos[1] + sin(angle) *self.canon + sin(angle - pi/2) *5),
(self.pos[0] + cos(angle) * self.canon + cos(angle + pi/2) *5, self.pos[1] + sin(angle) *self.canon + sin(angle + pi/2) *5)]
)
pygame.draw.polygon(self.surface, self.colors[1], [(self.pos[0] + cos(angle + pi/2) * 5, self.pos[1] + sin(angle+pi/2) *5),
(self.pos[0] + cos(angle - pi/2) * 5, self.pos[1] + sin(angle-pi/2) *5),
(self.pos[0] + cos(angle) * self.canon + cos(angle - pi /2) * 5, self.pos[1] + sin(angle) *self.canon + sin(angle - pi/2) *5),
(self.pos[0] + cos(angle) * self.canon + cos(angle + pi/2) *5, self.pos[1] + sin(angle) *self.canon + sin(angle + pi/2) *5)],
1)
#Dessin du corps de la tourelle
pygame.draw.circle(self.surface, self.colors[0], self.pos, self.rayon)
pygame.draw.circle(self.surface, self.colors[1], self.pos, self.rayon, 1)
if self.vie < self.viemax:
pygame.draw.circle(self.surface, self.colors[3], self.pos, (self.viemax-self.vie) * self.rayon / self.viemax)
#Gestion des tirs
if pygame.mouse.get_pressed()[0] and self.delai == 0:
self.tirs.append(Tir((self.pos[0] + cos(angle) * self.canon, self.pos[1] + sin(angle) * self.canon), angle + (random() - 0.5) * (20*pi/180), len(self.tirs), self, self.surface))
self.delai = self.delaimax
if self.delai:
self.delai -= 1
#Mise à jour des tirs
i = 0
while i < len(self.tirs):
self.tirs[i].update()
i += 1
def delete(self, nom):
"Efface les tirs de la tourelle"
self.tirs[nom: nom+1] = []
i = nom
while i < len(self.tirs):
self.tirs[i].id = i
i += 1
class Tir():
"Classe de tirs"
speed = 10
rayon = 5
def __init__(self, pos, angle, nom, maitre, surface):
"Initialisation"
self.pos = pos
self.move = (cos(angle), sin(angle))
self.id = nom
self.maitre = maitre
self.surface = surface
def update(self):
"Mise à jour du tir"
global width, height
i = 0
while i < self.speed:
self.pos = (self.pos[0] + self.move[0], self.pos[1] + self.move[1])
if 0 >= self.pos[0] >= width or 0 >= self.pos[1] >= height:
self.maitre.delete(self.id)
i += 1
pygame.draw.circle(self.surface, self.maitre.colors[4], self.pos, self.rayon)
pygame.draw.circle(self.surface, self.maitre.colors[1], self.pos, self.rayon, 1)
class Ennemi():
"Classe de l'ennemi"
speed = 3
def __init__(self, pos, vie, ennemi, nom, groupe, surface):
self.pos = pos
self.angle = 0
self.vie = vie
self.ennemi = ennemi
self.id = nom
self.groupe = groupe
self.surface = surface
def update(self):
global ennemi
#Calcul du nouvel angle de la rotation
angle = atan2(self.ennemi.pos[1] - self.pos[1], self.ennemi.pos[0] - self.pos[0])
self.pos = (self.pos[0] + cos(angle) * self.speed, self.pos[1] + sin(angle) * self.speed)
self.angle += pi / 18
if self.angle >= 2 * pi:
self.angle = self.angle - 2 * pi
#Gestion des collisions avec nos tirs
for i in self.ennemi.tirs:
if self.pos[0] - 5 * self.vie <= i.pos[0] <= self.pos[0] + 5 * self.vie and\
self.pos[1] - 5 * self.vie <= i.pos[1] <= self.pos[1] + 5 * self.vie:
self.vie -= 1
i.maitre.delete(i.id)
#Gestion des collisions avec le joueur
if self.pos[0] - 5 * self.vie <= self.ennemi.pos[0] <= self.pos[0] + 5 * self.vie and\
self.pos[1] - 5 * self.vie <= self.ennemi.pos[1] <= self.pos[1] + 5 * self.vie:
self.ennemi.vie -= 1
self.groupe.delete(self.id, 0)
#Mort de l'ennemi
if self.vie <= 0:
self.groupe.delete(self.id, 100)
#Dessin de l'ennemi
pygame.draw.polygon(self.surface, ennemi[0], [
(self.pos[0] + cos(self.angle) * self.vie * 5, self.pos[1] + sin(self.angle) * self.vie * 5),
(self.pos[0] + cos(self.angle + pi/2) * self.vie / 2 * 5, self.pos[1] + sin(self.angle + pi/2) * self.vie / 2 * 5),
(self.pos[0] + cos(self.angle + pi) * self.vie * 5, self.pos[1] + sin(self.angle + pi) * self.vie * 5),
(self.pos[0] + cos(self.angle - pi/2) * self.vie / 2 * 5, self.pos[1] + sin(self.angle - pi/2) * self.vie / 2 * 5)])
pygame.draw.polygon(self.surface, ennemi[1], [
(self.pos[0] + cos(self.angle) * self.vie * 5, self.pos[1] + sin(self.angle) * self.vie * 5),
(self.pos[0] + cos(self.angle + pi/2) * self.vie / 2 * 5, self.pos[1] + sin(self.angle + pi/2) * self.vie / 2 * 5),
(self.pos[0] + cos(self.angle + pi) * self.vie * 5, self.pos[1] + sin(self.angle + pi) * self.vie * 5),
(self.pos[0] + cos(self.angle - pi/2) * self.vie / 2 * 5, self.pos[1] + sin(self.angle - pi/2) * self.vie / 2 * 5)], 3)
class Controlleur():
"Controle les ennemis"
unites = []
score = 0
temps = 0
def __init__(self,ennemi, surface):
self.ennemi = ennemi
self.surface = surface
def update(self):
global width, height, infos
if not randrange(0, 50):
x = randrange(0, 2)
if x:
x *= width
y = randrange(0, 2) * height
else:
y = randrange(0, height)
x = randrange(0, 2) * width
self.unites.append(Ennemi((x, y), randrange(0, 11), self.ennemi, len(self.unites), self, self.surface))
for i in self.unites:
i.update()
self.temps += 1
score = pygame.font.Font("freesansbold.ttf", 20).render("score: "+str(self.score)+" temps:"+str(self.temps), 1, infos[2])
scorect = score.get_rect()
scorect.left = 10
scorect.top = 10
cadre = Rect(0, 0, scorect.width + 20, scorect.height + 20)
pygame.draw.rect(self.surface, infos[0], cadre)
pygame.draw.rect(self.surface, infos[1], cadre, 3)
self.surface.blit(score, scorect)
def delete(self, nom, add):
"Efface l'ennemi"
self.unites[nom:nom+1] = []
i = nom
while i < len(self.unites):
self.unites[i].id = i
i += 1
self.score += add
class Curseur():
"Classe du curseur"
def __init__(self, surface):
pygame.mouse.set_visible(0)
self.surface = surface
def update(self):
pygame.draw.circle(self.surface, (255, 255, 255), pygame.mouse.get_pos(), 5, 1)
#Jeu
ecran = pygame.display.set_mode(size)
pygame.display.set_caption("VIRTUAL SHOOTING")
pygame.key.set_repeat()
curseur = Curseur(ecran)
while 1:
intro(ecran)
jeu(ecran, curseur)
Conclusion :
Si jamais vous trouvez un bug, que vous trouvez que je n'ai pas assez commenté (les commentaires c'est pa smon fort >_<), ou que vous pensez à des améliorations, n'hésitez pas à me le faire savoir.
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.