begin process at 2013 06 20 02:40:18
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Jeux

 > UN SERPENT PYTHON ... PAS COMME LES AUTRES !

UN SERPENT PYTHON ... PAS COMME LES AUTRES !


 Information sur la source

Note :
10 / 10 - par 2 personnes
10,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10
Catégorie :Jeux Classé sous :collisions, jeu, serpent Niveau :Initié Date de création :19/12/2005 Date de mise à jour :20/06/2006 08:43:06 Vu / téléchargé :10 279 / 535

Auteur : HCD

Ecrire un message privé
Commentaire sur cette source (9)
Ajouter un commentaire et/ou une note

 Description

Cliquez pour voir la capture en taille normale
Ce script est présenté sous la forme d'un JEU.
Il fait intervenir un SERPENT orientable en direction et "armé" :
     - d'une FLECHE rétractable
     - d'un MISSILE à autoguidage terminal
Le but du jeu consiste pour le serpent à détruire le plus rapidement possible plusieurs cibles.
Cinq niveaux de jeu sont proposés.

Source

  • #! /usr/bin/env python
  • # -*- coding: Latin-1 -*-
  • # Python version 2.4.2
  • # Tk version 8.4
  • # IDLE version 1.1.2
  • # <<< Serpent PYTHON >>>
  • ############# PRESENTATION #################
  • # Ce script est présenté sous la forme d'un JEU.
  • # Il fait intervenir un SERPENT orientable en direction et "armé" :
  • # - d'une FLECHE rétractable
  • # (commmande de tir par la touche < Espace > du clavier
  • # - d'un MISSILE à autoguidage terminal
  • # (commmande de tir par la touche de la lettre < X > du clavier
  • #
  • # La "FLECHE" est représentée par un cercle blanc ancré au nez du serpent, auquel elle est reliée
  • # par un "fil" extensible losqu'elle est projetée. Elle change de couleur, en bleu, lorsqu'elle est
  • # "désactivée".
  • # Le missile est représenté aussi par un cercle blanc, plus petit.Il est situé à l'extrémité de la queue
  • # du serpent et s'en détache quand il est mis en oeuvre. Il revient à sa place après un tir suivi d'une collision.
  • #
  • # Le but du jeu consiste pour le serpent à détruire le plus rapidement possible plusieurs CIBLES.
  • #
  • # Les CIBLES, de couleur marron, sont immobiles au départ.
  • # Elles peuvent se mettre en mouvement dans le courant de la partie.
  • # Elles deviennent alors DANGEREUSES pour le serpent qui risque la DESTRUCTION en cas de collision.
  • # Lorsque le serpent tire avec sa flèche rétractable, la cible est normalement détruite immédiatement.
  • # Mais cette flèche peut se désactiver; dans ce cas, la cible n'est pas détruite et, surtout, elle devient MOBILE.
  • # La flèche se réactive au tir suivant ... si le serpent a survécu.
  • # Qand elle est désactivée, un message d'avertissement apparait dans le panneau rouge situé à droite
  • # du plan de jeu.
  • # Les cibles sont également entourées d'un cercle de détection pour les tirs de missile.
  • # Dès que le missile entre en contact avec l'un de ces cercles, il change d'orientation et
  • # se dirige automatiquement vers le centre de la cible détectée.
  • # La cible se met en mouvement, puis elle est rapidement détruite au contact du missile.
  • # Lorsqu'il y a une détection multiple, les autres cibles deviennent aussi mobiles, et donc DANGEREUSES.
  • #
  • # Dix OBSTACLES fixes sont placés sur le jeu. Ils sont alignés et de couleur bleue. Indestructibles, ils
  • # permettent au serpent de rebondir et ainsi de multiplier les changements de trajectoire.
  • # Les cibles peuvent s'y cacher.
  • #
  • # La partie n'est donc pas gagnée d'avance !!!
  • #
  • # La fenêtre de jeu comprend:
  • # - un plan carré à l'intérieur duquel évoluent le serpent et les cibles
  • # - un champ de saisie du niveau de jeu choisi (1, 2, 3, 4)
  • # - quatre boutons de commande :
  • # . < Mise en place ! >
  • # . < Lancer le jeu ! >
  • # . < Stop ! >
  • # . < Quitter le jeu ! >
  • # - un bouton donnant la :
  • # . < Règle du jeu ! >
  • # - un compteur visualisant le temps écoulé
  • # - un compteur visualisant le nombre de cibles détruites
  • # - un panneau rouge pour le message d'avertissement
  • #
  • #
  • # Commencer -comme il est d'usage- par prendre connaissance de la < Règle du jeu ! >.
  • # and "enjoy it !!!"
  • ############# COMMENTAIRE #################
  • # Le programme fait intervenir l'interface graphique Tkinter, avec quatre modules :
  • # math, random, tkMessageBox, time.
  • # L'utilisation de LISTES (pour les coordonnées et les diamètres des cercles) et d'une BIBLIOTHEQUE
  • # pour leur identification, permet de réduire considérablement le nombre de lignes de code.
  • # C'est l'intérêt de ce script.
  • # L'algorithme de collision des cercles est celui que j'avais présenté dans les codes intitulés:
  • # "BILLARD Français", et "COLLISIONS multiples".
  • ######################################################################################
  • from Tkinter import*
  • from math import hypot,sqrt,floor,log
  • from random import randrange
  • from tkMessageBox import askokcancel
  • from time import time
  • import tkFont
  • ######################################################################################
  • nS=40# nombre de cercles constituant le serpent
  • nC=39# nombre de cibles
  • nO=10# nombre d'obstacles
  • ######################################################################################
  • def niveau_jeu():
  • " choix du niveau de jeu "
  • global V,TD,nS
  • if activation_cases==1:
  • N=choix_niveau.get()# entrée du niveau de jeu choisi (de 1 à 5)
  • # V est un paramètre de réglage de la vitesse du serpent
  • # TD est un paramètre de réglage du nombre total de cibles détruites, pour lequel un tir de flèche
  • # devient dangereux pour le serpent : les cibles détectées deviennent en effet mobiles ...et susceptibles
  • # de le détruire en cas de collision par le travers :
  • if N==1: V=2.0; TD=20;nS=40# correspond à la 20ème cible détruite
  • if N==2: V=2.0; TD= 5;nS=40# correspond aux destructions de rang multiple de 5 : 5ème, 10ème, 15ème,...,35ème
  • if N==3: V=2.0; TD= 4;nS=45# rang multiple de 4 : 4ème, 8ème, 12ème,..., 36ème cible détruite
  • if N==4: V=2.5; TD= 3;nS=40# rang multiple de 3 : 3ème, 6ème, 9ème,..., 39ème cible détruite
  • if N==5: V=3.0; TD= 2;nS=32# rang multiple de 2 : 2ème, 4ème, 6ème,..., 38ème cible détruite
  • def mise_en_place():
  • " commande de mise en place du jeu "
  • global flag,top_start,score_time
  • flag=1
  • ST.configure(state=NORMAL)# activation du bouton de commande < Stop !>
  • LJ.configure(state=NORMAL)# id <Lancer le jeu !>
  • MP.configure(state=DISABLED)# désactivation du bouton de commande < Mise en place !>
  • niveau_jeu()# prise en compte du niveau de jeu choisi, en provenance du module ci-dessus
  • score_time=0# mise à zéro du compteur de temps écoulé
  • can.score.config(text='%s'%score_time)# visualisation de ce compteur
  • top_start=time()# top départ
  • can.delete(ALL)# nettoyage" du plan de jeu
  • serpent()# activation du module (ci-dessous)
  • cibles()# id
  • obstacles()# id
  • def lancer_le_jeu():
  • " commandes de lancement des mouvements et de gestion des collisions "
  • global activation_cases
  • LJ.configure(state=DISABLED)# désactivation du bouton de commande <Lancer le jeu !>
  • activation_cases
  • if flag==1:
  • mouvements_serpent()# activation du module (ci-dessous)
  • mouvements_fleche()# id
  • mouvements_cibles()# id
  • collisions_serpent_obstacles()# id
  • collisions_serpent_cibles()# id
  • collisions_missile_cibles()# id
  • if total_destruction == nC:# arrêt lorsque toutes les cibles sont détruites
  • top_end=time()# top fin de partie
  • score_time=int(round(top_end-top_start,0))# calcul de la durée de la partie
  • for i in range(0,nO):can.delete(O[i])# effacement des obstacles fixes
  • for i in range(1,150):sapin();can.delete(ALL)# activation en boucle du module animé "sapin+neige"
  • for i in range(1,150):sapin()
  • can.create_text(L/2,H/3-50,text='Joyeuses fêtes !!!',fill="white",font="Arial 12")
  • root.after(10000,stop)# l'animation finale dure 10 secondes
  • if hypot(x[nS-2]-x[1],y[nS-2]-y[1])>200*V-80:# critère de désintégration du serpent
  • destruction()# destruction du serpent
  • score_time=int(round(time()-top_start,0))# calcul de la durée de la partie
  • can.score.config(text='%s'%score_time)# visualisation du temps écoulé
  • can.total_destruction.config(text='%s'%total_destruction)# visualisation du nombre de cibles détruites
  • activation_cases=0
  • root.after(10,lancer_le_jeu)
  • ######################################################################################
  • def serpent():
  • " création du serpent PYTHON (S) et de sa flèche (F) "
  • global S,LF,x,y,dx,dy,DS
  • x=[L-(i+2)*V*n for i in range(0,nS)]# liste des abscisses des 40 cercles constituant le serpent
  • y=[H-(i+2)*2*V*n for i in range(0,nS)]# liste des ordonnées
  • dx=[-V*n for i in range(0,nS)]# liste des vitesses horizontales
  • dy=[-2*V*n for i in range(0,nS)]# liste des vitesses verticales
  • DS=[7]
  • for i in range(0,nS-1):DS.append(1+d*(1+i)/nS) # liste des diamètres
  • S={}# bibliothèque des cercles
  • LF=can.create_line(x[nS-1],y[nS-1],x[nS-2],y[nS-2],fill="orange")# ligne reliant la flèche à la tête du serpent
  • for i in range(0,nS):
  • S[i]=can.create_oval(x[i]-DS[i]/2,y[i]-DS[i]/2,x[i]+DS[i]/2,y[i]+DS[i]/2,fill="orange",outline="orange")
  • can.itemconfig(S[nS-4],width=9);can.itemconfig(S[nS-3],width=6);can.itemconfig(S[nS-2],width=3)# dessin de la tête du serpent
  • can.itemconfig(S[0],fill="white")# couleur blanche pour le missile (en queue)
  • can.itemconfig(S[nS-1],fill="white",width=1,outline="blue")# dessin de la flèche rétractable (extrémité en forme de cercle)
  • def cibles():
  • " création des cibles (C) "
  • global C,Q,xC,yC,dxC,dyC,DC,DQ
  • xC=[randrange(10,780) for i in range(0,25)]# liste des abscisses des 39 cibles (distribution aléatoire)
  • for i in range(25,39):xC.append(randrange(10,520))# pour éviter au départ de placer une cible sur le serpent
  • yC=[10+i*19 for i in range(0,nC)]# liste des ordonnées (régulièrement espacées)
  • dxC=[0 for i in range(0,nC)]# les cibles sont immobiles
  • dyC=[0 for i in range(0,nC)]# id
  • DC=[randrange(10,20) for i in range(0,nC)]# diamètres compris entre 10 et 20
  • DQ=[100 for i in range(0,nC)]# diamètres des cercles de détection des cibles
  • C={}# bibliothèque des cibles
  • Q={}# bibliothèque des cercles de détection
  • for i in range(0,nC):
  • Q[i]=can.create_oval(xC[i]-DQ[i]/2,yC[i]-DQ[i]/2,xC[i]+DQ[i]/2,yC[i]+DQ[i]/2,outline='#007000')
  • C[i]=can.create_oval(xC[i]-DC[i]/2,yC[i]-DC[i]/2,xC[i]+DC[i]/2,yC[i]+DC[i]/2,fill="brown",outline="yellow")
  • def obstacles():
  • " création des obstacles fixes (C) "
  • global O,xO,yO,dxO,dyO,DO
  • xO=[L/4+i*50 for i in range(0,nO)]# liste des abscisses des 10 obstacles (distribution régulière)
  • yO=[H/4+i*50 for i in range(0,nO)]# liste des ordonnées (id)
  • dxO=[0 for i in range(0,nO)]# les cibles sont immobiles
  • dyO=[0 for i in range(0,nO)]# id
  • DO=[40 for i in range(0,nO)]# diamètre des obstacles
  • O={}# bibliothèque des obstacles
  • for i in range(0,nO):
  • O[i]=can.create_oval(xO[i]-DO[i]/2,yO[i]-DO[i]/2,xO[i]+DO[i]/2,yO[i]+DO[i]/2,fill="blue",outline="yellow")
  • ######################################################################################
  • def mouvements_serpent():
  • " mouvements du serpent (S) "
  • global x,y,dx,dy,DS
  • global vF,tirF,GC,DR,HT,BS,iG,iD,iH,iB
  • if tirF==1:desactiver_touches()# concerne les flèches du clavier
  • if tirF==0:activer_touches()# id
  • for i in range(0,nS):
  • # commandes de direction
  • if GC==1:# clavier : activation de la flèche gauche
  • desactiver_touches();X,Y=x[i]-u,y[i]-v;Z=hypot(X,Y)
  • if Z==0 :iG+=1;dx[i],dy[i]=-hypot(du,dv),0
  • if iG==nS-1:activer_touches();GC=0;iG=0
  • if DR==1:# clavier : activation de la flèche droite
  • desactiver_touches();X,Y=x[i]-u,y[i]-v;Z=hypot(X,Y)
  • if Z==0 :iD+=1;dx[i],dy[i]=hypot(du,dv),0
  • if iD==nS-1:activer_touches();DR=0;iD=0
  • if HT==1:# clavier : activation de la flèche haute
  • desactiver_touches();X,Y=x[i]-u,y[i]-v;Z=hypot(X,Y)
  • if Z==0 :iH+=1;dx[i],dy[i]=0,-hypot(du,dv)
  • if iH==nS-1:activer_touches();HT=0;iH=0
  • if BS==1:# clavier : activation de la flèche basse
  • desactiver_touches();X,Y=x[i]-u,y[i]-v;Z=hypot(X,Y)
  • if Z==0 :iB+=1;dx[i],dy[i]=0,hypot(du,dv)
  • if iB==nS-1:activer_touches();BS=0;iB=0
  • # mouvements
  • x[i],y[i]=x[i]+(1+collisionF/nC)*dx[i],y[i]+(1+collisionF/nC)*dy[i]# le mouvement du serpent s'accélère avec la destruction des cibles
  • if tirM==0:
  • x[0],y[0]=x[1]-dx[1],y[1]-dy[1]# le missile est maintenu en queue
  • can.coords(S[i],x[i]-DS[i]/2,y[i]-DS[i]/2,x[i]+DS[i]/2,y[i]+DS[i]/2)
  • # collisions avec les bordures
  • for i in range(0,nS-1):# maintien dans les limites du jeu par rebond sur les bords
  • collision_bordures(x[i],y[i],dx[i],dy[i],DS[nS-1])
  • x[i],y[i],dx[i],dy[i]=pp,qq,rr,ss
  • def mouvements_fleche():
  • " mouvements de la flèche (F) "
  • global x,y,dx,dy
  • global vF,tirF,activationF,total_destruction
  • can.coords(LF,x[nS-1],y[nS-1],x[nS-2],y[nS-2])
  • if tirF==1:# la flèche du serpent est lancée dans l'axe à une vitesse supérieure
  • dx[nS-1],dy[nS-1]=vF*dx[nS-1]/hypot(dx[nS-1],dy[nS-1]),vF*dy[nS-1]/hypot(dx[nS-1],dy[nS-1])
  • x[nS-1],y[nS-1]=x[nS-1]+dx[nS-1],y[nS-1]+dy[nS-1]
  • if tirF==1 and x[nS-1]>L-d/2 or x[nS-1]<d/2 or y[nS-1]>H-d/2 or y[nS-1]<d/2:# maintien dans les limites du jeu
  • x[nS-1],y[nS-1],dx[nS-1],dy[nS-1]=x[nS-2],y[nS-2],dx[nS-2],dy[nS-2]
  • vF,tirF=0,0
  • if tirF==0 and x[nS-1]>L-d/2 or x[nS-1]<d/2 or y[nS-1]>H-d/2 or y[nS-1]<d/2:# maintien dans les limites du jeu
  • x[nS-1],y[nS-1],dx[nS-1],dy[nS-1]=x[nS-2],y[nS-2],dx[nS-2],dy[nS-2]
  • total_destruction = collisionF + collisionM
  • for i in range(1,13):
  • if total_destruction==TD*i:# si le nombre de cibles détruites est un multiple de TD (voir le module niveau_jeu ci-dessus)
  • activationF=1
  • can.itemconfig(S[nS-1],fill="blue")# la flèche du serpent change de couleur
  • avertissement.config(bg="yellow",fg="red")# un message d'avertissement apparait dans la fenêtre
  • if total_destruction==TD*i+1:# pour les valeurs suivantes
  • activationF=0
  • can.itemconfig(S[nS-1],fill="white")# la flèche reprend sa couleur
  • avertissement.config(bg="brown",fg="brown")# le message disparait
  • def mouvements_cibles():
  • " petits mouvements des cibles lors des collisions(O) "
  • global xC,yC,dxC,dyC
  • for i in range(0,nC):
  • # mouvement
  • xC[i],yC[i]=xC[i]+dxC[i],yC[i]+dyC[i]
  • dxC[J],dyC[J]=0.9995*dxC[J],0.9995*dyC[J]
  • can.coords(C[i],xC[i]-DC[i]/2,yC[i]-DC[i]/2,xC[i]+DC[i]/2,yC[i]+DC[i]/2)
  • can.coords(Q[i],xC[i]-DQ[i]/2,yC[i]-DQ[i]/2,xC[i]+DQ[i]/2,yC[i]+DQ[i]/2)
  • # collisions avec les bordures
  • collision_bordures(xC[i],yC[i],dxC[i],dyC[i],DC[i])
  • xC[i],yC[i],dxC[i],dyC[i]=pp,qq,rr,ss
  • ######################################################################################
  • def collisions_serpent_obstacles():
  • " gestion des collisions Serpent / Obstacles "
  • global x,y,dx,dy,DS
  • global xO,yO
  • for j in range(0,nO):
  • if tirF==1:# après un tir
  • X,Y=xO[j]-x[nS-1],yO[j]-y[nS-1]
  • Z=hypot(X,Y)
  • if Z<=DS[nS-1]/2+DO[j]/2:# s'il y a collision Flèche / Obstacle
  • x[nS-1],y[nS-1],dx[nS-1],dy[nS-1]=x[nS-2],y[nS-2],dx[nS-2],dy[nS-2]# la flèche revient en place
  • for i in range(0,nS):# collisions Serpent / Obstacles
  • collisions(x[i],y[i],xO[j],yO[j],dx[i],dy[i],dxO[j],dyO[j],DS[nS-1],DO[j])
  • x[i],y[i],xO[j],yO[j]=rxa,rya,rxb,ryb
  • dx[i],dy[i]=rdxa,rdya
  • def collisions_serpent_cibles():
  • " gestion des collisions Serpent / Cibles "
  • global x,y,dx,dy
  • global xC,yC
  • global collisionF,tirF,vF,activationF,J
  • for j in range(0,nC):
  • if tirF==1:# après un tir
  • X,Y=xC[j]-x[nS-1],yC[j]-y[nS-1]
  • Z=hypot(X,Y)
  • if Z<=DS[nS-1]/2+(1+collisionF/3)*DC[j]/2:# s'il y a collision Serpent / Cibles
  • J=j# rang (dans la liste) des cibles détectées
  • if activationF==1:# si la flèche est activée (couleur bleue)
  • xC[J],yC[J]=xC[j],yC[j]
  • dxC[J],dyC[J]=4*dy[nS-1]/hypot(dx[nS-1],dy[nS-1])/Z,-4*dx[nS-1]/hypot(dx[nS-1],dy[nS-1]/Z)# les cibles touchées se mettent en mouvement
  • can.itemconfig(C[J],fill="green")# et changent de couleur
  • collisionF==-1# le tir n'est pas compté
  • else:
  • xC[j],yC[j],DC[j],DQ[j]=0,0,0,0# la cible est détruite
  • x[nS-1],y[nS-1],dx[nS-1],dy[nS-1]=x[nS-2],y[nS-2],dx[nS-2],dy[nS-2]# la flèche revient en place
  • collisionF+=1# le tir est comptabilisé
  • vF,tirF=0,0
  • can.create_rectangle(L*(collisionF-1)/nC,H-10,L*collisionF/nC,H,fill="pink",outline="blue")
  • can.create_text(50,H-15,text='flèche',fill="white")
  • if collisionM!=0:# s'il y a eu, en outre, destruction d'une cible, une nouvelle cible apparait
  • dxC[j],dyC[j]=0,0# immobilisation de celle-ci
  • for i in range(0,nS):# collisions Serpent / Cibles
  • collisions(x[i],y[i],xC[j],yC[j],dx[i],dy[i],dxC[j],dyC[j],DS[nS-1],DC[j])
  • x[i],y[i],xC[j],yC[j]=rxa,rya,rxb,ryb
  • dx[i],dy[i]=rdxa,rdya
  • def collisions_missile_cibles():
  • " gestion des collisions Missile de queue / Cibles / Cercle de détection "
  • global x,y,dx,dy,DS
  • global tirM,collisionM
  • global xC,yC,dxC,dyC,DC
  • global DQ
  • if tirM==1:# lorsque le missile est tiré
  • for j in range(0,nC):
  • DQ[j]=DQ[j]+0.05# le diamètre des cercles de détection augmente à chaque tir
  • X,Y=x[0]-xC[j],y[0]-yC[j]
  • Z=hypot(X,Y)
  • if Z<=DQ[j]/2+DS[0]/2:# s'il y a contact du missile avec le cercle de détection
  • dx[0],dy[0]=-X/Z*hypot(dx[0],dy[0]),-Y/Z*hypot(dx[0],dy[0])# le missile s'oriente en direction de la cible
  • DQ[j]=0.97*DQ[j]# le cercle de détection rétrécit lentement
  • can.itemconfig(C[j],fill='#00FF00')# la couleur des cibles détectées passe au vert
  • dxC[j],dyC[j]=0.25*randrange(1,2),0.25*randrange(1,2)# les cibles détectées se mettent en mouvement
  • " ATTENTION !!! A partir de ce moment, les cibles mises en mouvement sont DANGEREUSES. "
  • " Le serpent est détruit s'il entre à leur contact : il lui faut donc les détruire en priorité "
  • " et, sinon, les éviter "
  • if DQ[j]<0.97*nC:# collision du missile avec la cible visée
  • collisionM+=1
  • tirM=0
  • xC[j],yC[j],dxC[j],dyC[j],DC[j],DQ[j]=0,0,0,0,0,0# destruction de la cible
  • x[0],y[0]=x[1]-dx[1],y[1]-dy[1]# le missile revient à sa place (en queue du serpent)
  • can.create_rectangle(L-L*collisionM/nC,H-10,L-L*(collisionM-1)/nC,H,fill="grey",outline="blue")
  • can.create_text(L-50,H-15,text='missile',fill="white")
  • if tirM==0 :
  • x[0],y[0]=x[0],y[0]
  • ######################################################################################
  • def collision_bordures(p,q,r,s,D):
  • " algorithme commun de collision avec les bordures "
  • global pp,qq,rr,ss
  • if p>L-D/2:pp,qq,rr,ss=L-D/2,q,-r,s
  • if p<D/2:pp,qq,rr,ss=D/2,q,-r,s
  • if q>H-D/2:pp,qq,rr,ss=p,H-D/2,r,-s
  • if q<D/2:pp,qq,rr,ss=p,D/2,r,-s
  • if p<=L-D/2 and p>=D/2 and q<=H-D/2 and q>=D/2:
  • pp,qq,rr,ss=p,q,r,s
  • def collisions(xa,ya,xb,yb,dxa,dya,dxb,dyb,da,db):
  • " algorithme commun de collisions entre cercles "
  • global rxa,rya,rxb,ryb
  • global rdxa,rdya
  • X,Y=xb-xa,yb-ya
  • Z=hypot(X,Y)
  • if Z<=(da+db)/2:
  • dX,dY=dxb-dxa,dyb-dya
  • dZ=hypot(dX,dY)
  • if dZ==0:m=0
  • else:
  • k,K=dZ*dZ,X*dX+Y*dY
  • m=(K+sqrt(K*K-k*(Z*Z-(da+db)/2*(da+db)/2)))/k
  • rxa,rya,rxb,ryb=xa-m*dxa,ya-m*dya,xb-m*dxb,yb-m*dyb
  • X,Y=rxb-rxa,ryb-rya
  • Z=hypot(X,Y)
  • if Z<=(da+db)/2:
  • dxb,dyb=0,0
  • dX,dY=dxb-dxa,dyb-dya
  • dZ=hypot(dX,dY)
  • if dZ==0:m=0
  • else:
  • k,K=dZ*dZ,X*dX+Y*dY
  • m=(K+sqrt(K*K-k*(Z*Z-(da+db)/2*(da+db)/2)))/k
  • rxa,rya,rxb,ryb=xa-m*dxa,ya-m*dya,xb-m*dxb,yb-m*dyb
  • xx,xy,yy=X*X/Z/Z,X*Y/Z/Z,Y*Y/Z/Z
  • rdxa,rdya=(yy-xx)*dxa-2*xy*dya,-2*xy*dxa-(yy-xx)*dya
  • else:
  • rxa,rya,rxb,ryb=xa,ya,xb,yb
  • rdxa,rdya=dxa,dya
  • ######################################################################################
  • # Fonctions de déplacement des touches :
  • def left(event):
  • " S à gauche "
  • global u,v,du,dv,GC
  • GC+=1
  • u,v,du,dv=x[nS-1],y[nS-1],dx[nS-1],dy[nS-1]
  • def right(event):
  • " S à droite "
  • global u,v,du,dv,DR
  • DR+=1
  • u,v,du,dv=x[nS-1],y[nS-1],dx[nS-1],dy[nS-1]
  • def up(event):
  • " S vers le haut "
  • global u,v,du,dv,HT
  • HT+=1
  • u,v,du,dv=x[nS-1],y[nS-1],dx[nS-1],dy[nS-1]
  • def down(event):
  • " S vers le bas "
  • global u,v,du,dv,BS
  • BS+=1
  • u,v,du,dv=x[nS-1],y[nS-1],dx[nS-1],dy[nS-1]
  • def tirer_fleche(event):
  • " commande touche < Espace > "
  • global vF,tirF
  • tirF=1
  • vF=10
  • def tirer_missile(event):
  • " commande touche < x > ou < X > "
  • global tirM
  • tirM=1
  • def activer_touches():
  • ""
  • root.bind("<Left>",left)
  • root.bind("<Right>",right)
  • root.bind("<Up>",up)
  • root.bind("<Down>",down)
  • def desactiver_touches():
  • ""
  • root.unbind("<Left>")
  • root.unbind("<Right>")
  • root.unbind("<Up>")
  • root.unbind("<Down>")
  • ######################################################################################
  • def destruction():
  • " message explicatif "
  • stop()
  • can.delete(texte)
  • texte2=can.create_text(L/2,420,text='''Le serpent a été détruit après collision avec une cible mobile (de couleur verte) !\n\n
  • Lorsque le serpent tire un missile, il peut arriver que plusieurs cibles fixes soient détectées.
  • Dans ce cas, les cibles détectées changent de couleur : elles passent du marron au vert.
  • et, surtout, elles entrent en mouvement.
  • Le missile se dirige vers la première détectée et la détruit.
  • Mais les autres cibles, devenues mobiles, sont dangereuses pour le serpent.
  • Elles doivent être détruites le plus rapidement possible et, surtout, absolument évitées.\n\n
  • Vous pouvez continuer en appuyant sur : Mise en place !
  • et, sinon, sur : Quitter le jeu !\n''',fill="white",font="Arial 12")
  • ######################################################################################
  • def stop():
  • " arrêt des mouvements et mise à zéro de tous les compteurs "
  • global flag,tirF,collisionF,tirM,collisionM,activationF,GC,DR,HT,BS,texte,arrivée,activation_cases
  • ST.configure(state=DISABLED)
  • LJ.configure(state=DISABLED)
  • MP.configure(state=NORMAL)
  • avertissement.configure(bg="brown",fg="brown")
  • flag=0
  • tirF,collisionF=0,0
  • tirM,collisionM=0,0
  • root.bind("<Left>",left)
  • root.bind("<Right>",right)
  • root.bind("<Up>",up)
  • root.bind("<Down>",down)
  • GC,DR,HT,BS=0,0,0,0
  • for i in range(0,nO):can.delete(O[i])
  • for i in range(0,nC):can.delete(C[i]),can.delete(Q[i])
  • texte=can.create_text(L/3,100,text='''MERCI\net\nn' hésitez pas à commenter (et à coter...) ce script !''',fill="white",font="Arial 12")
  • top_end=time()
  • activationF=0
  • activation_cases=1
  • def quitter():
  • " façon classique de quitter l'application "
  • ans=askokcancel('Serpent PYTHON',"Voulez-vous réellement quitter ?")
  • if ans:root.quit()
  • def sapin():
  • " petit dessin en guise de récompense !!!"
  • can.create_polygon(400,400 ,385,455 ,415,455,fill="green")
  • can.create_polygon(400,440 ,375,495 ,425,495,fill="green")
  • can.create_polygon(400,480 ,365,530 ,435,530,fill="green")
  • can.create_polygon(400,510 ,355,570 ,445,570,fill="green")
  • can.create_polygon(400,540 ,345,610 ,455,610,fill="green")
  • can.create_rectangle(392,610 ,408,625 ,fill="green")
  • a,b,c=randrange(0,800),randrange(0,800),randrange(2,8)
  • can.create_oval(a,b,a+c,b+c,fill="white")
  • ######################################################################################
  • def presentation():
  • "Fenêtre-message contenant la description sommaire du principe du jeu"
  • msg =Toplevel()
  • Message(msg, bg ="dark green", fg ="white", width =810,font ="Arial 10",
  • text =''' PRESENTATION\n
  • Au lancement du jeu, le bouton < Mise en place > fait apparaître:\n
  • - le serpent PYTHON constitué de 40 cercles de diamètres décroissants, de la tête vers la queue
  • - la FLECHE (rétractable) du serpent : cercle blanc placé au niveau du nez
  • - le MISSILE (à autoguidage terminal) : petit cercle blanc situé en queue
  • - 10 obstacles fixes indestructibles de couleur bleue et de même diamètre
  • (sur lesquels rebondissent serpent, flèche et missile)
  • - 39 cibles à détruire, de couleur marron et de diamètre variable
  • (leurs abscisses ont des valeurs aléatoires, leurs ordonnées sont échelonnées régulièrement)
  • (ces cibles sont toute entourées d'un cercle de détection dont le diamètre est constant au départ, puis variable ensuite)\n\n
  • Le jeu consiste pour le serpent à détruire les 39 cibles, le plus rapidement possible, sans être lui-même détruit.
  • (la durée de la partie et le nombre de cibles détruites sont affichés à droite de la fenêtre de jeu)\n
  • Les moyens dont le serpent dispose sont:
  • - sa FLECHE, qui peut être tirée par pression rapide ou continue sur la touche < Espace > du clavier
  • - le MISSILE, qui est tirable par pression rapide sur la touche < X > du clavier
  • (la progression des destructions est visualisée en bas du plan de jeu)\n\n
  • Utilisation de la FLECHE\n
  • Au début, les tirs de la flèche doivent être précis pour pouvoir détruire les cibles.
  • Ils deviennent plus faciles ensuite, car la distance d'interception augmente lentement avec le nombre de succès.
  • Mais il ne sont pas sans risques pour le serpent, car à une certaine occurence, fonction du niveau de jeu choisi, cette flèche s'active.
  • Ceci a pour effet, lors du tir suivant, de neutraliser sa capacité de destruction, et surtout de mettre en mouvement les cibles détectées.
  • Il y a alors DANGER de DESTRUCTION pour le serpent, en cas de collision avec celles-ci.
  • Une fois tirée, la flèche se désactive, et les tirs sans risques redeviennent possibles...jusqu'à l'activation suivante.\n
  • Utilisation du MISSILE\n
  • Après tir par le serpent dans la zone de détection d'une cible, le missile se réoriente pour se diriger vers le centre de la cible.
  • La cible entre en mouvement, sa couleur passe au vert, son cercle de détection se rétracte, puis elle disparait.
  • Lorsqu'une ou plusieurs autres cibles sont aussi détectées, elles deviennent également mobiles; leur couleur passe aussi au vert.
  • Le missile reprend sa place, en queue du serpent, et peut à nouveau être tiré.
  • Mais il y a alors DANGER pour le serpent, puisque ces cibles sont mobiles.\n
  • En fin de partie, l'utilisation des flèches (haut,bas,gauche,droite) du clavier pourra permettre de gagner du temps.
  • Elles modifient la direction de marche du serpent.\n
  • Pour réussir une partie, une combinaison des deux types de tir sera nécessaire pour éviter la destruction du serpent.
  • Avec un peu d'entrainement, on parviendra au niveau 5, le plus intéressant.\n\n''').pack(padx =10, pady =10)
  • def processus():
  • "Fenêtre-message contenant la description du processus de jeu"
  • msg =Toplevel()
  • Message(msg, bg ="dark green", fg ="white", width =450,font ="Arial 10",
  • text='''PROCESSUS à suivre\n\n
  • 1. Choisir le niveau de jeu
  • (cinq valeurs possibles : 1, 2, 3, 4, 5)\n
  • 2. Cliquer sur le bouton < Mise en place ! >\n
  • 3. puis sur le bouton < Lancer le jeu ! >\n
  • 4. Tir avec la flèche rétractable :
  • appuyer sur la touche < Espace > du clavier\n
  • 5. Tir d'un missile :
  • appuyer sur la touche de la lettre < X > du clavier\n
  • 6. Changement de direction du serpent :
  • utiliser les quatre flèches du clavier
  • (haut, bas, gauche, droite)\n
  • 7. Bouton < Stop !>
  • pour arrêter les mouvements\n
  • 8. Bouton < Quitter le jeu !>
  • pour abandonner la partie\n''').pack(padx =10, pady =10)
  • def aPropos():
  • "Fenêtre-message indiquant les versions utilisées"
  • msg =Toplevel()
  • Message(msg, width =200, aspect =100, justify =CENTER,
  • text ='''Serpent PYTHON
  • HCD, Décembre 2005
  • Python version 2.4.2
  • Tk version 8.4''').pack(padx =10, pady =10)
  • ######## Programme principal ############################################
  • root = Tk()
  • root.title('>>>>>>> Serpent PYTHON <<<<<<<')
  • f=1
  • L,H=800*f,800*f
  • flag=0
  • d=10
  • n=1.5
  • V=0
  • tirF,collisionF=0,0
  • tirM,collisionM=0,0
  • activationF=0
  • u,v=0,0
  • GC,DR,HT,BS=0,0,0,0
  • iG,iD,iH,iB=0,0,0,0
  • score_time=0
  • top_end=0
  • J=0
  • activation_cases=1
  • # mise en place des deux canevas
  • can=Canvas(root,bg='dark green',height=H,width=L)
  • can.grid(row=1,column=0,rowspan=2)
  • can2=Canvas(root,bg='brown',highlightbackground='brown')
  • can2.grid(row=1,column=1,sticky=N)
  • # commandes à partir du clavier
  • root.bind("<Left>", left)
  • root.bind("<Right>", right)
  • root.bind("<Up>", up)
  • root.bind("<Down>", down)
  • root.bind('<space>', tirer_fleche)
  • root.bind('x', tirer_missile)
  • root.bind('X', tirer_missile)
  • #Avertissement
  • can.total_destruction=Label(can2,text='0',fg='white',bg='brown')
  • can.total_destruction.pack(side=BOTTOM)
  • Label(can2,text="Nombre de cibles détruites",fg='white',bg='brown').pack(side=BOTTOM)
  • texte3='''ATTENTION !!!
  • La flèche du serpent
  • est passée au BLEU
  • Le prochain tir est risqué !
  • CONSEIL
  • Tirer le missile !
  • (La flèche repasse au BLANC
  • ensuite)'''
  • avertissement=Label(can2,text=texte3,height=13,width=24,relief=GROOVE,font='BOLD',bg="brown",fg="brown",command=None)
  • avertissement.pack(padx=5,pady=5,side=BOTTOM,anchor=SW)
  • # Score (durée de la partie)
  • can.score=Label(can2,text='0',fg='white',bg='brown')
  • can.score.pack(side=BOTTOM)
  • Label(can2,text="Temps écoulé",fg='white',bg='brown').pack(side=BOTTOM)
  • # Menu <Règle du jeu>
  • RdJ = Menubutton(can2, text ='Règle du jeu',height=2,width=35,relief=GROOVE,bg="dark green",fg="white")
  • RdJ.pack(padx=5,pady=5,side=BOTTOM,anchor=SW)
  • me1 = Menu(RdJ)
  • me1.add_command(label='Présentation',underline=0,command=presentation)
  • me1.add_command(label='Processus',underline=0,command=processus)
  • me1.add_command(label='A propos ...',underline=0,command=aPropos)
  • RdJ.configure(menu=me1)
  • # Boutons de commande à partir de la fenêtre Tkinter
  • Button(can2,text='Quitter le jeu !',height=2,width=35,relief=GROOVE,bg="white",command=quitter).pack(padx=5,pady=5,side=BOTTOM,anchor=SW)
  • ST=Button(can2,text='Stop !',height=2,width=35,relief=GROOVE,bg="white",activebackground="dark green",activeforeground="white",command=stop)
  • ST.pack(padx=5,pady=5,side=BOTTOM,anchor=SW)
  • LJ=Button(can2,text='Lancer le jeu !',height=2,width=35,relief=GROOVE,bg="white",activebackground="dark green",activeforeground="white",command=lancer_le_jeu)
  • LJ.pack(padx=5,pady=5,side=BOTTOM,anchor=SW)
  • MP=Button(can2,text='Mise en place !',height=2,width=35,relief=GROOVE,bg="white",activebackground="dark green",activeforeground="white",command=mise_en_place)
  • MP.pack(padx=5,pady=5,side=BOTTOM,anchor=SW)
  • # Niveau de jeu
  • Label(can2,text='''Choisir le niveau de jeu''',fg='white',bg='brown').pack(padx=5,pady=5,side=BOTTOM)
  • niveau=["1","2","3","4","5"]
  • choix_niveau=IntVar()
  • choix_niveau.set(niveau[0])
  • for i in range(0,5):
  • rad=Radiobutton(can2,text=str(i+1),variable=choix_niveau,value=niveau[i],command=niveau_jeu)
  • rad.pack(padx=6,pady=5,side=LEFT)
  • #root.resizable(0,0)
  • root.config(bg="brown")
  • root.mainloop()
  • root.destroy()
#! /usr/bin/env python 
# -*- coding: Latin-1 -*- 
# Python version 2.4.2 
# Tk version 8.4 
# IDLE version 1.1.2 
   
# <<< Serpent PYTHON >>> 
  
############# PRESENTATION ################# 
   
# Ce script est présenté sous la forme d'un JEU. 
  
# Il fait intervenir un SERPENT orientable en direction et "armé" : 
# - d'une FLECHE rétractable 
# (commmande de tir par la touche < Espace > du clavier 
# - d'un MISSILE à autoguidage terminal 
# (commmande de tir par la touche de la lettre < X > du clavier 
# 
# La "FLECHE" est représentée par un cercle blanc ancré au nez du serpent, auquel elle est reliée 
# par un "fil" extensible losqu'elle est projetée. Elle change de couleur, en bleu, lorsqu'elle est 
# "désactivée". 
# Le missile est représenté aussi par un cercle blanc, plus petit.Il est situé à l'extrémité de la queue 
# du serpent et s'en détache quand il est mis en oeuvre. Il revient à sa place après un tir suivi d'une collision. 
# 
# Le but du jeu consiste pour le serpent à détruire le plus rapidement possible plusieurs CIBLES. 
# 
# Les CIBLES, de couleur marron, sont immobiles au départ. 
# Elles peuvent se mettre en mouvement dans le courant de la partie. 
# Elles deviennent alors DANGEREUSES pour le serpent qui risque la DESTRUCTION en cas de collision. 
# Lorsque le serpent tire avec sa flèche rétractable, la cible est normalement détruite immédiatement. 
# Mais cette flèche peut se désactiver; dans ce cas, la cible n'est pas détruite et, surtout, elle devient MOBILE. 
# La flèche se réactive au tir suivant ... si le serpent a survécu. 
# Qand elle est désactivée, un message d'avertissement apparait dans le panneau rouge situé à droite 
# du plan de jeu. 
# Les cibles sont également entourées d'un cercle de détection pour les tirs de missile. 
# Dès que le missile entre en contact avec l'un de ces cercles, il change d'orientation et 
# se dirige automatiquement vers le centre de la cible détectée. 
# La cible se met en mouvement, puis elle est rapidement détruite au contact du missile. 
# Lorsqu'il y a une détection multiple, les autres cibles deviennent aussi mobiles, et donc DANGEREUSES. 
# 
# Dix OBSTACLES fixes sont placés sur le jeu. Ils sont alignés et de couleur bleue. Indestructibles, ils 
# permettent au serpent de rebondir et ainsi de multiplier les changements de trajectoire. 
# Les cibles peuvent s'y cacher. 
# 
# La partie n'est donc pas gagnée d'avance !!! 
# 
# La fenêtre de jeu comprend: 
# - un plan carré à l'intérieur duquel évoluent le serpent et les cibles 
# - un champ de saisie du niveau de jeu choisi (1, 2, 3, 4) 
# - quatre boutons de commande : 
# . < Mise en place ! > 
# . < Lancer le jeu ! > 
# . < Stop ! > 
# . < Quitter le jeu ! > 
# - un bouton donnant la : 
# . < Règle du jeu ! > 
# - un compteur visualisant le temps écoulé 
# - un compteur visualisant le nombre de cibles détruites 
# - un panneau rouge pour le message d'avertissement 
# 
# 
# Commencer -comme il est d'usage- par prendre connaissance de la < Règle du jeu ! >. 
# and "enjoy it !!!" 
  
  
############# COMMENTAIRE ################# 
   
# Le programme fait intervenir l'interface graphique Tkinter, avec quatre modules : 
# math, random, tkMessageBox, time. 
# L'utilisation de LISTES (pour les coordonnées et les diamètres des cercles) et d'une BIBLIOTHEQUE 
# pour leur identification, permet de réduire considérablement le nombre de lignes de code. 
# C'est l'intérêt de ce script. 
# L'algorithme de collision des cercles est celui que j'avais présenté dans les codes intitulés: 
# "BILLARD Français", et "COLLISIONS multiples". 
  
###################################################################################### 
  
from Tkinter import* 
from math import hypot,sqrt,floor,log 
from random import randrange 
from tkMessageBox import askokcancel 
from time import time 
import tkFont 

###################################################################################### 

nS=40# nombre de cercles constituant le serpent 
nC=39# nombre de cibles 
nO=10# nombre d'obstacles 
  
###################################################################################### 

def niveau_jeu(): 
    " choix du niveau de jeu " 
    global V,TD,nS 
    if activation_cases==1: 
        N=choix_niveau.get()# entrée du niveau de jeu choisi (de 1 à 5) 
        # V est un paramètre de réglage de la vitesse du serpent 
        # TD est un paramètre de réglage du nombre total de cibles détruites, pour lequel un tir de flèche 
        # devient dangereux pour le serpent : les cibles détectées deviennent en effet mobiles ...et susceptibles 
        # de le détruire en cas de collision par le travers : 
        if N==1: V=2.0; TD=20;nS=40# correspond à la 20ème cible détruite 
        if N==2: V=2.0; TD= 5;nS=40# correspond aux destructions de rang multiple de 5 : 5ème, 10ème, 15ème,...,35ème 
        if N==3: V=2.0; TD= 4;nS=45# rang multiple de 4 : 4ème, 8ème, 12ème,..., 36ème cible détruite 
        if N==4: V=2.5; TD= 3;nS=40# rang multiple de 3 : 3ème, 6ème, 9ème,..., 39ème cible détruite 
        if N==5: V=3.0; TD= 2;nS=32# rang multiple de 2 : 2ème, 4ème, 6ème,..., 38ème cible détruite 

def mise_en_place(): 
    " commande de mise en place du jeu " 
    global flag,top_start,score_time 
    flag=1 
    ST.configure(state=NORMAL)# activation du bouton de commande < Stop !> 
    LJ.configure(state=NORMAL)# id <Lancer le jeu !> 
    MP.configure(state=DISABLED)# désactivation du bouton de commande < Mise en place !> 
    niveau_jeu()# prise en compte du niveau de jeu choisi, en provenance du module ci-dessus 
    score_time=0# mise à zéro du compteur de temps écoulé 
    can.score.config(text='%s'%score_time)# visualisation de ce compteur 
    top_start=time()# top départ 
    can.delete(ALL)# nettoyage" du plan de jeu 
    serpent()# activation du module (ci-dessous) 
    cibles()# id 
    obstacles()# id 
   
def lancer_le_jeu(): 
    " commandes de lancement des mouvements et de gestion des collisions " 
    global activation_cases 
    LJ.configure(state=DISABLED)# désactivation du bouton de commande <Lancer le jeu !> 
    activation_cases 
    if flag==1: 
        mouvements_serpent()# activation du module (ci-dessous) 
        mouvements_fleche()# id 
        mouvements_cibles()# id 
        collisions_serpent_obstacles()# id 
        collisions_serpent_cibles()# id 
        collisions_missile_cibles()# id 
        if total_destruction == nC:# arrêt lorsque toutes les cibles sont détruites 
            top_end=time()# top fin de partie 
            score_time=int(round(top_end-top_start,0))# calcul de la durée de la partie 
            for i in range(0,nO):can.delete(O[i])# effacement des obstacles fixes 
            for i in range(1,150):sapin();can.delete(ALL)# activation en boucle du module animé "sapin+neige" 
            for i in range(1,150):sapin() 
            can.create_text(L/2,H/3-50,text='Joyeuses fêtes !!!',fill="white",font="Arial 12") 
            root.after(10000,stop)# l'animation finale dure 10 secondes 
        if hypot(x[nS-2]-x[1],y[nS-2]-y[1])>200*V-80:# critère de désintégration du serpent 
            destruction()# destruction du serpent 
        score_time=int(round(time()-top_start,0))# calcul de la durée de la partie 
        can.score.config(text='%s'%score_time)# visualisation du temps écoulé 
        can.total_destruction.config(text='%s'%total_destruction)# visualisation du nombre de cibles détruites 
        activation_cases=0 
        root.after(10,lancer_le_jeu) 
  
###################################################################################### 
  
def serpent(): 
    " création du serpent PYTHON (S) et de sa flèche (F) " 
    global S,LF,x,y,dx,dy,DS 
    x=[L-(i+2)*V*n for i in range(0,nS)]# liste des abscisses des 40 cercles constituant le serpent 
    y=[H-(i+2)*2*V*n for i in range(0,nS)]# liste des ordonnées 
    dx=[-V*n for i in range(0,nS)]# liste des vitesses horizontales 
    dy=[-2*V*n for i in range(0,nS)]# liste des vitesses verticales 
    DS=[7] 
    for i in range(0,nS-1):DS.append(1+d*(1+i)/nS) # liste des diamètres 
    S={}# bibliothèque des cercles 
    LF=can.create_line(x[nS-1],y[nS-1],x[nS-2],y[nS-2],fill="orange")# ligne reliant la flèche à la tête du serpent 
    for i in range(0,nS): 
        S[i]=can.create_oval(x[i]-DS[i]/2,y[i]-DS[i]/2,x[i]+DS[i]/2,y[i]+DS[i]/2,fill="orange",outline="orange") 
    can.itemconfig(S[nS-4],width=9);can.itemconfig(S[nS-3],width=6);can.itemconfig(S[nS-2],width=3)# dessin de la tête du serpent 
    can.itemconfig(S[0],fill="white")# couleur blanche pour le missile (en queue) 
    can.itemconfig(S[nS-1],fill="white",width=1,outline="blue")# dessin de la flèche rétractable (extrémité en forme de cercle) 
     
def cibles(): 
    " création des cibles (C) " 
    global C,Q,xC,yC,dxC,dyC,DC,DQ 
    xC=[randrange(10,780) for i in range(0,25)]# liste des abscisses des 39 cibles (distribution aléatoire) 
    for i in range(25,39):xC.append(randrange(10,520))# pour éviter au départ de placer une cible sur le serpent 
    yC=[10+i*19 for i in range(0,nC)]# liste des ordonnées (régulièrement espacées) 
    dxC=[0 for i in range(0,nC)]# les cibles sont immobiles 
    dyC=[0 for i in range(0,nC)]# id 
    DC=[randrange(10,20) for i in range(0,nC)]# diamètres compris entre 10 et 20 
    DQ=[100 for i in range(0,nC)]# diamètres des cercles de détection des cibles 
    C={}# bibliothèque des cibles 
    Q={}# bibliothèque des cercles de détection 
    for i in range(0,nC): 
        Q[i]=can.create_oval(xC[i]-DQ[i]/2,yC[i]-DQ[i]/2,xC[i]+DQ[i]/2,yC[i]+DQ[i]/2,outline='#007000') 
        C[i]=can.create_oval(xC[i]-DC[i]/2,yC[i]-DC[i]/2,xC[i]+DC[i]/2,yC[i]+DC[i]/2,fill="brown",outline="yellow") 
  
def obstacles(): 
    " création des obstacles fixes (C) " 
    global O,xO,yO,dxO,dyO,DO 
    xO=[L/4+i*50 for i in range(0,nO)]# liste des abscisses des 10 obstacles (distribution régulière) 
    yO=[H/4+i*50 for i in range(0,nO)]# liste des ordonnées (id) 
    dxO=[0 for i in range(0,nO)]# les cibles sont immobiles 
    dyO=[0 for i in range(0,nO)]# id 
    DO=[40 for i in range(0,nO)]# diamètre des obstacles 
    O={}# bibliothèque des obstacles 
    for i in range(0,nO): 
        O[i]=can.create_oval(xO[i]-DO[i]/2,yO[i]-DO[i]/2,xO[i]+DO[i]/2,yO[i]+DO[i]/2,fill="blue",outline="yellow") 
  
###################################################################################### 
  
def mouvements_serpent(): 
    " mouvements du serpent (S) " 
    global x,y,dx,dy,DS 
    global vF,tirF,GC,DR,HT,BS,iG,iD,iH,iB 
    if tirF==1:desactiver_touches()# concerne les flèches du clavier 
    if tirF==0:activer_touches()# id 
    for i in range(0,nS): 
        # commandes de direction 
        if GC==1:# clavier : activation de la flèche gauche 
            desactiver_touches();X,Y=x[i]-u,y[i]-v;Z=hypot(X,Y) 
            if Z==0 :iG+=1;dx[i],dy[i]=-hypot(du,dv),0 
            if iG==nS-1:activer_touches();GC=0;iG=0 
        if DR==1:# clavier : activation de la flèche droite 
            desactiver_touches();X,Y=x[i]-u,y[i]-v;Z=hypot(X,Y) 
            if Z==0 :iD+=1;dx[i],dy[i]=hypot(du,dv),0 
            if iD==nS-1:activer_touches();DR=0;iD=0 
        if HT==1:# clavier : activation de la flèche haute 
            desactiver_touches();X,Y=x[i]-u,y[i]-v;Z=hypot(X,Y) 
            if Z==0 :iH+=1;dx[i],dy[i]=0,-hypot(du,dv) 
            if iH==nS-1:activer_touches();HT=0;iH=0 
        if BS==1:# clavier : activation de la flèche basse 
            desactiver_touches();X,Y=x[i]-u,y[i]-v;Z=hypot(X,Y) 
            if Z==0 :iB+=1;dx[i],dy[i]=0,hypot(du,dv) 
            if iB==nS-1:activer_touches();BS=0;iB=0 
        # mouvements 
        x[i],y[i]=x[i]+(1+collisionF/nC)*dx[i],y[i]+(1+collisionF/nC)*dy[i]# le mouvement du serpent s'accélère avec la destruction des cibles 
        if tirM==0: 
            x[0],y[0]=x[1]-dx[1],y[1]-dy[1]# le missile est maintenu en queue 
        can.coords(S[i],x[i]-DS[i]/2,y[i]-DS[i]/2,x[i]+DS[i]/2,y[i]+DS[i]/2) 
    # collisions avec les bordures 
    for i in range(0,nS-1):# maintien dans les limites du jeu par rebond sur les bords 
        collision_bordures(x[i],y[i],dx[i],dy[i],DS[nS-1]) 
        x[i],y[i],dx[i],dy[i]=pp,qq,rr,ss 
  
def mouvements_fleche(): 
    " mouvements de la flèche (F) " 
    global x,y,dx,dy 
    global vF,tirF,activationF,total_destruction 
    can.coords(LF,x[nS-1],y[nS-1],x[nS-2],y[nS-2]) 
    if tirF==1:# la flèche du serpent est lancée dans l'axe à une vitesse supérieure 
        dx[nS-1],dy[nS-1]=vF*dx[nS-1]/hypot(dx[nS-1],dy[nS-1]),vF*dy[nS-1]/hypot(dx[nS-1],dy[nS-1]) 
        x[nS-1],y[nS-1]=x[nS-1]+dx[nS-1],y[nS-1]+dy[nS-1] 
    if tirF==1 and x[nS-1]>L-d/2 or x[nS-1]<d/2 or y[nS-1]>H-d/2 or y[nS-1]<d/2:# maintien dans les limites du jeu 
        x[nS-1],y[nS-1],dx[nS-1],dy[nS-1]=x[nS-2],y[nS-2],dx[nS-2],dy[nS-2] 
        vF,tirF=0,0 
    if tirF==0 and x[nS-1]>L-d/2 or x[nS-1]<d/2 or y[nS-1]>H-d/2 or y[nS-1]<d/2:# maintien dans les limites du jeu 
        x[nS-1],y[nS-1],dx[nS-1],dy[nS-1]=x[nS-2],y[nS-2],dx[nS-2],dy[nS-2] 
    total_destruction = collisionF + collisionM 
    for i in range(1,13): 
        if total_destruction==TD*i:# si le nombre de cibles détruites est un multiple de TD (voir le module niveau_jeu ci-dessus) 
            activationF=1 
            can.itemconfig(S[nS-1],fill="blue")# la flèche du serpent change de couleur 
            avertissement.config(bg="yellow",fg="red")# un message d'avertissement apparait dans la fenêtre 
        if total_destruction==TD*i+1:# pour les valeurs suivantes 
            activationF=0 
            can.itemconfig(S[nS-1],fill="white")# la flèche reprend sa couleur 
            avertissement.config(bg="brown",fg="brown")# le message disparait 
             
def mouvements_cibles(): 
    " petits mouvements des cibles lors des collisions(O) " 
    global xC,yC,dxC,dyC 
    for i in range(0,nC): 
        # mouvement 
        xC[i],yC[i]=xC[i]+dxC[i],yC[i]+dyC[i] 
        dxC[J],dyC[J]=0.9995*dxC[J],0.9995*dyC[J] 
        can.coords(C[i],xC[i]-DC[i]/2,yC[i]-DC[i]/2,xC[i]+DC[i]/2,yC[i]+DC[i]/2) 
        can.coords(Q[i],xC[i]-DQ[i]/2,yC[i]-DQ[i]/2,xC[i]+DQ[i]/2,yC[i]+DQ[i]/2) 
        # collisions avec les bordures 
        collision_bordures(xC[i],yC[i],dxC[i],dyC[i],DC[i]) 
        xC[i],yC[i],dxC[i],dyC[i]=pp,qq,rr,ss 
  
###################################################################################### 
  
def collisions_serpent_obstacles(): 
    " gestion des collisions Serpent / Obstacles " 
    global x,y,dx,dy,DS 
    global xO,yO 
    for j in range(0,nO): 
        if tirF==1:# après un tir 
            X,Y=xO[j]-x[nS-1],yO[j]-y[nS-1] 
            Z=hypot(X,Y) 
            if Z<=DS[nS-1]/2+DO[j]/2:# s'il y a collision Flèche / Obstacle 
                x[nS-1],y[nS-1],dx[nS-1],dy[nS-1]=x[nS-2],y[nS-2],dx[nS-2],dy[nS-2]# la flèche revient en place 
        for i in range(0,nS):# collisions Serpent / Obstacles 
            collisions(x[i],y[i],xO[j],yO[j],dx[i],dy[i],dxO[j],dyO[j],DS[nS-1],DO[j]) 
            x[i],y[i],xO[j],yO[j]=rxa,rya,rxb,ryb 
            dx[i],dy[i]=rdxa,rdya 
  
def collisions_serpent_cibles(): 
    " gestion des collisions Serpent / Cibles " 
    global x,y,dx,dy 
    global xC,yC 
    global collisionF,tirF,vF,activationF,J 
    for j in range(0,nC): 
        if tirF==1:# après un tir 
            X,Y=xC[j]-x[nS-1],yC[j]-y[nS-1] 
            Z=hypot(X,Y) 
            if Z<=DS[nS-1]/2+(1+collisionF/3)*DC[j]/2:# s'il y a collision Serpent / Cibles 
                J=j# rang (dans la liste) des cibles détectées 
                if activationF==1:# si la flèche est activée (couleur bleue) 
                    xC[J],yC[J]=xC[j],yC[j] 
                    dxC[J],dyC[J]=4*dy[nS-1]/hypot(dx[nS-1],dy[nS-1])/Z,-4*dx[nS-1]/hypot(dx[nS-1],dy[nS-1]/Z)# les cibles touchées se mettent en mouvement 
                    can.itemconfig(C[J],fill="green")# et changent de couleur 
                    collisionF==-1# le tir n'est pas compté 
                else: 
                    xC[j],yC[j],DC[j],DQ[j]=0,0,0,0# la cible est détruite 
                    x[nS-1],y[nS-1],dx[nS-1],dy[nS-1]=x[nS-2],y[nS-2],dx[nS-2],dy[nS-2]# la flèche revient en place 
                    collisionF+=1# le tir est comptabilisé 
                    vF,tirF=0,0 
                    can.create_rectangle(L*(collisionF-1)/nC,H-10,L*collisionF/nC,H,fill="pink",outline="blue") 
                    can.create_text(50,H-15,text='flèche',fill="white") 
                    if collisionM!=0:# s'il y a eu, en outre, destruction d'une cible, une nouvelle cible apparait 
                        dxC[j],dyC[j]=0,0# immobilisation de celle-ci 
        for i in range(0,nS):# collisions Serpent / Cibles 
            collisions(x[i],y[i],xC[j],yC[j],dx[i],dy[i],dxC[j],dyC[j],DS[nS-1],DC[j]) 
            x[i],y[i],xC[j],yC[j]=rxa,rya,rxb,ryb 
            dx[i],dy[i]=rdxa,rdya 
  
def collisions_missile_cibles(): 
    " gestion des collisions Missile de queue / Cibles / Cercle de détection " 
    global x,y,dx,dy,DS 
    global tirM,collisionM 
    global xC,yC,dxC,dyC,DC 
    global DQ 
    if tirM==1:# lorsque le missile est tiré 
        for j in range(0,nC): 
            DQ[j]=DQ[j]+0.05# le diamètre des cercles de détection augmente à chaque tir 
            X,Y=x[0]-xC[j],y[0]-yC[j] 
            Z=hypot(X,Y) 
            if Z<=DQ[j]/2+DS[0]/2:# s'il y a contact du missile avec le cercle de détection 
                dx[0],dy[0]=-X/Z*hypot(dx[0],dy[0]),-Y/Z*hypot(dx[0],dy[0])# le missile s'oriente en direction de la cible 
                DQ[j]=0.97*DQ[j]# le cercle de détection rétrécit lentement 
                can.itemconfig(C[j],fill='#00FF00')# la couleur des cibles détectées passe au vert 
                dxC[j],dyC[j]=0.25*randrange(1,2),0.25*randrange(1,2)# les cibles détectées se mettent en mouvement 
  
                " ATTENTION !!! A partir de ce moment, les cibles mises en mouvement sont DANGEREUSES. " 
                " Le serpent est détruit s'il entre à leur contact : il lui faut donc les détruire en priorité " 
                " et, sinon, les éviter " 
                 
                if DQ[j]<0.97*nC:# collision du missile avec la cible visée 
                    collisionM+=1 
                    tirM=0 
                    xC[j],yC[j],dxC[j],dyC[j],DC[j],DQ[j]=0,0,0,0,0,0# destruction de la cible 
                    x[0],y[0]=x[1]-dx[1],y[1]-dy[1]# le missile revient à sa place (en queue du serpent) 
                    can.create_rectangle(L-L*collisionM/nC,H-10,L-L*(collisionM-1)/nC,H,fill="grey",outline="blue") 
                    can.create_text(L-50,H-15,text='missile',fill="white") 
    if tirM==0 : 
        x[0],y[0]=x[0],y[0] 
                    
###################################################################################### 
  
def collision_bordures(p,q,r,s,D): 
    " algorithme commun de collision avec les bordures " 
    global pp,qq,rr,ss 
    if p>L-D/2:pp,qq,rr,ss=L-D/2,q,-r,s 
    if p<D/2:pp,qq,rr,ss=D/2,q,-r,s 
    if q>H-D/2:pp,qq,rr,ss=p,H-D/2,r,-s 
    if q<D/2:pp,qq,rr,ss=p,D/2,r,-s 
    if p<=L-D/2 and p>=D/2 and q<=H-D/2 and q>=D/2: 
        pp,qq,rr,ss=p,q,r,s 
  
def collisions(xa,ya,xb,yb,dxa,dya,dxb,dyb,da,db): 
    " algorithme commun de collisions entre cercles " 
    global rxa,rya,rxb,ryb 
    global rdxa,rdya 
    X,Y=xb-xa,yb-ya 
    Z=hypot(X,Y) 
    if Z<=(da+db)/2: 
        dX,dY=dxb-dxa,dyb-dya 
        dZ=hypot(dX,dY) 
        if dZ==0:m=0 
        else: 
            k,K=dZ*dZ,X*dX+Y*dY 
            m=(K+sqrt(K*K-k*(Z*Z-(da+db)/2*(da+db)/2)))/k 
        rxa,rya,rxb,ryb=xa-m*dxa,ya-m*dya,xb-m*dxb,yb-m*dyb 
        X,Y=rxb-rxa,ryb-rya 
        Z=hypot(X,Y) 
        if Z<=(da+db)/2: 
            dxb,dyb=0,0 
            dX,dY=dxb-dxa,dyb-dya 
            dZ=hypot(dX,dY) 
            if dZ==0:m=0 
            else: 
                k,K=dZ*dZ,X*dX+Y*dY 
                m=(K+sqrt(K*K-k*(Z*Z-(da+db)/2*(da+db)/2)))/k 
            rxa,rya,rxb,ryb=xa-m*dxa,ya-m*dya,xb-m*dxb,yb-m*dyb 
        xx,xy,yy=X*X/Z/Z,X*Y/Z/Z,Y*Y/Z/Z 
        rdxa,rdya=(yy-xx)*dxa-2*xy*dya,-2*xy*dxa-(yy-xx)*dya 
    else: 
        rxa,rya,rxb,ryb=xa,ya,xb,yb 
        rdxa,rdya=dxa,dya 
  
###################################################################################### 
 
    # Fonctions de déplacement des touches : 
  
def left(event): 
    " S à gauche " 
    global u,v,du,dv,GC 
    GC+=1 
    u,v,du,dv=x[nS-1],y[nS-1],dx[nS-1],dy[nS-1] 
  
def right(event): 
    " S à droite " 
    global u,v,du,dv,DR 
    DR+=1 
    u,v,du,dv=x[nS-1],y[nS-1],dx[nS-1],dy[nS-1] 
  
def up(event): 
    " S vers le haut " 
    global u,v,du,dv,HT 
    HT+=1 
    u,v,du,dv=x[nS-1],y[nS-1],dx[nS-1],dy[nS-1] 
  
def down(event): 
    " S vers le bas " 
    global u,v,du,dv,BS 
    BS+=1 
    u,v,du,dv=x[nS-1],y[nS-1],dx[nS-1],dy[nS-1] 
  
def tirer_fleche(event): 
    " commande touche < Espace > " 
    global vF,tirF 
    tirF=1 
    vF=10 
  
def tirer_missile(event): 
    " commande touche < x > ou < X > " 
    global tirM 
    tirM=1 
  
def activer_touches(): 
    "" 
    root.bind("<Left>",left) 
    root.bind("<Right>",right) 
    root.bind("<Up>",up) 
    root.bind("<Down>",down) 
  
def desactiver_touches(): 
    "" 
    root.unbind("<Left>") 
    root.unbind("<Right>") 
    root.unbind("<Up>") 
    root.unbind("<Down>") 
  
###################################################################################### 
  
def destruction(): 
    " message explicatif " 
    stop() 
    can.delete(texte) 
    texte2=can.create_text(L/2,420,text='''Le serpent a été détruit après collision avec une cible mobile (de couleur verte) !\n\n 
    Lorsque le serpent tire un missile, il peut arriver que plusieurs cibles fixes soient détectées. 
    Dans ce cas, les cibles détectées changent de couleur : elles passent du marron au vert. 
    et, surtout, elles entrent en mouvement. 
    Le missile se dirige vers la première détectée et la détruit. 
    Mais les autres cibles, devenues mobiles, sont dangereuses pour le serpent. 
    Elles doivent être détruites le plus rapidement possible et, surtout, absolument évitées.\n\n 
    Vous pouvez continuer en appuyant sur : Mise en place ! 
    et, sinon, sur : Quitter le jeu !\n''',fill="white",font="Arial 12") 
  
###################################################################################### 
 
def stop(): 
    " arrêt des mouvements et mise à zéro de tous les compteurs " 
    global flag,tirF,collisionF,tirM,collisionM,activationF,GC,DR,HT,BS,texte,arrivée,activation_cases 
  
    ST.configure(state=DISABLED) 
    LJ.configure(state=DISABLED) 
    MP.configure(state=NORMAL) 
    avertissement.configure(bg="brown",fg="brown") 
    flag=0 
    tirF,collisionF=0,0 
    tirM,collisionM=0,0 
    root.bind("<Left>",left) 
    root.bind("<Right>",right) 
    root.bind("<Up>",up) 
    root.bind("<Down>",down) 
    GC,DR,HT,BS=0,0,0,0 
    for i in range(0,nO):can.delete(O[i]) 
    for i in range(0,nC):can.delete(C[i]),can.delete(Q[i]) 
    texte=can.create_text(L/3,100,text='''MERCI\net\nn' hésitez pas à commenter (et à coter...) ce script !''',fill="white",font="Arial 12") 
    top_end=time() 
    activationF=0 
    activation_cases=1 
  
def quitter(): 
    " façon classique de quitter l'application " 
    ans=askokcancel('Serpent PYTHON',"Voulez-vous réellement quitter ?") 
    if ans:root.quit() 
  
def sapin(): 
    " petit dessin en guise de récompense !!!" 
    can.create_polygon(400,400 ,385,455 ,415,455,fill="green") 
    can.create_polygon(400,440 ,375,495 ,425,495,fill="green") 
    can.create_polygon(400,480 ,365,530 ,435,530,fill="green") 
    can.create_polygon(400,510 ,355,570 ,445,570,fill="green") 
    can.create_polygon(400,540 ,345,610 ,455,610,fill="green") 
    can.create_rectangle(392,610 ,408,625 ,fill="green") 
    a,b,c=randrange(0,800),randrange(0,800),randrange(2,8) 
    can.create_oval(a,b,a+c,b+c,fill="white") 
  
###################################################################################### 
  
def presentation(): 
    "Fenêtre-message contenant la description sommaire du principe du jeu" 
    msg =Toplevel() 
    Message(msg, bg ="dark green", fg ="white", width =810,font ="Arial 10", 
        text =''' PRESENTATION\n 
        Au lancement du jeu, le bouton < Mise en place > fait apparaître:\n 
           - le serpent PYTHON constitué de 40 cercles de diamètres décroissants, de la tête vers la queue 
           - la FLECHE (rétractable) du serpent : cercle blanc placé au niveau du nez 
           - le MISSILE (à autoguidage terminal) : petit cercle blanc situé en queue 
           - 10 obstacles fixes indestructibles de couleur bleue et de même diamètre 
             (sur lesquels rebondissent serpent, flèche et missile) 
           - 39 cibles à détruire, de couleur marron et de diamètre variable 
             (leurs abscisses ont des valeurs aléatoires, leurs ordonnées sont échelonnées régulièrement) 
             (ces cibles sont toute entourées d'un cercle de détection dont le diamètre est constant au départ, puis variable ensuite)\n\n 
        Le jeu consiste pour le serpent à détruire les 39 cibles, le plus rapidement possible, sans être lui-même détruit. 
        (la durée de la partie et le nombre de cibles détruites sont affichés à droite de la fenêtre de jeu)\n 
        Les moyens dont le serpent dispose sont: 
           - sa FLECHE, qui peut être tirée par pression rapide ou continue sur la touche < Espace > du clavier 
           - le MISSILE, qui est tirable par pression rapide sur la touche < X > du clavier 
              (la progression des destructions est visualisée en bas du plan de jeu)\n\n 
        Utilisation de la FLECHE\n 
        Au début, les tirs de la flèche doivent être précis pour pouvoir détruire les cibles. 
        Ils deviennent plus faciles ensuite, car la distance d'interception augmente lentement avec le nombre de succès. 
        Mais il ne sont pas sans risques pour le serpent, car à une certaine occurence, fonction du niveau de jeu choisi, cette flèche s'active. 
        Ceci a pour effet, lors du tir suivant, de neutraliser sa capacité de destruction, et surtout de mettre en mouvement les cibles détectées. 
        Il y a alors DANGER de DESTRUCTION pour le serpent, en cas de collision avec celles-ci. 
        Une fois tirée, la flèche se désactive, et les tirs sans risques redeviennent possibles...jusqu'à l'activation suivante.\n 
        Utilisation du MISSILE\n 
        Après tir par le serpent dans la zone de détection d'une cible, le missile se réoriente pour se diriger vers le centre de la cible. 
        La cible entre en mouvement, sa couleur passe au vert, son cercle de détection se rétracte, puis elle disparait. 
        Lorsqu'une ou plusieurs autres cibles sont aussi détectées, elles deviennent également mobiles; leur couleur passe aussi au vert. 
        Le missile reprend sa place, en queue du serpent, et peut à nouveau être tiré. 
        Mais il y a alors DANGER pour le serpent, puisque ces cibles sont mobiles.\n 
        En fin de partie, l'utilisation des flèches (haut,bas,gauche,droite) du clavier pourra permettre de gagner du temps. 
        Elles modifient la direction de marche du serpent.\n 
         
        Pour réussir une partie, une combinaison des deux types de tir sera nécessaire pour éviter la destruction du serpent. 
        Avec un peu d'entrainement, on parviendra au niveau 5, le plus intéressant.\n\n''').pack(padx =10, pady =10) 
  
def processus(): 
    "Fenêtre-message contenant la description du processus de jeu" 
    msg =Toplevel() 
    Message(msg, bg ="dark green", fg ="white", width =450,font ="Arial 10", 
        text='''PROCESSUS à suivre\n\n 
        1. Choisir le niveau de jeu 
             (cinq valeurs possibles : 1, 2, 3, 4, 5)\n 
        2. Cliquer sur le bouton < Mise en place ! >\n 
        3. puis sur le bouton < Lancer le jeu ! >\n 
        4. Tir avec la flèche rétractable : 
             appuyer sur la touche < Espace > du clavier\n 
        5. Tir d'un missile : 
             appuyer sur la touche de la lettre < X > du clavier\n 
        6. Changement de direction du serpent : 
             utiliser les quatre flèches du clavier 
             (haut, bas, gauche, droite)\n 
        7. Bouton < Stop !> 
             pour arrêter les mouvements\n 
        8. Bouton < Quitter le jeu !> 
             pour abandonner la partie\n''').pack(padx =10, pady =10) 
  
def aPropos(): 
    "Fenêtre-message indiquant les versions utilisées" 
    msg =Toplevel() 
    Message(msg, width =200, aspect =100, justify =CENTER, 
        text ='''Serpent PYTHON 
        HCD, Décembre 2005 
        Python version 2.4.2 
        Tk version 8.4''').pack(padx =10, pady =10) 
  
######## Programme principal ############################################ 
   
root = Tk() 
root.title('>>>>>>> Serpent PYTHON <<<<<<<') 
f=1  
L,H=800*f,800*f 
flag=0 
d=10 
n=1.5 
V=0 
tirF,collisionF=0,0 
tirM,collisionM=0,0 
activationF=0 
u,v=0,0 
GC,DR,HT,BS=0,0,0,0 
iG,iD,iH,iB=0,0,0,0 
score_time=0 
top_end=0 
J=0 
activation_cases=1 
# mise en place des deux canevas 
can=Canvas(root,bg='dark green',height=H,width=L) 
can.grid(row=1,column=0,rowspan=2) 
can2=Canvas(root,bg='brown',highlightbackground='brown') 
can2.grid(row=1,column=1,sticky=N) 
  
# commandes à partir du clavier 
root.bind("<Left>", left) 
root.bind("<Right>", right) 
root.bind("<Up>", up) 
root.bind("<Down>", down) 
root.bind('<space>', tirer_fleche) 
root.bind('x', tirer_missile) 
root.bind('X', tirer_missile) 
  
#Avertissement 
can.total_destruction=Label(can2,text='0',fg='white',bg='brown') 
can.total_destruction.pack(side=BOTTOM) 
Label(can2,text="Nombre de cibles détruites",fg='white',bg='brown').pack(side=BOTTOM) 
  
texte3='''ATTENTION !!! 
  
La flèche du serpent 
est passée au BLEU 
  
Le prochain tir est risqué ! 
  
CONSEIL 
  
Tirer le missile ! 
(La flèche repasse au BLANC 
ensuite)''' 
  
avertissement=Label(can2,text=texte3,height=13,width=24,relief=GROOVE,font='BOLD',bg="brown",fg="brown",command=None) 
avertissement.pack(padx=5,pady=5,side=BOTTOM,anchor=SW) 
  
# Score (durée de la partie) 
can.score=Label(can2,text='0',fg='white',bg='brown') 
can.score.pack(side=BOTTOM) 
Label(can2,text="Temps écoulé",fg='white',bg='brown').pack(side=BOTTOM) 
  
# Menu <Règle du jeu> 
RdJ = Menubutton(can2, text ='Règle du jeu',height=2,width=35,relief=GROOVE,bg="dark green",fg="white") 
RdJ.pack(padx=5,pady=5,side=BOTTOM,anchor=SW) 
me1 = Menu(RdJ) 
me1.add_command(label='Présentation',underline=0,command=presentation) 
me1.add_command(label='Processus',underline=0,command=processus) 
me1.add_command(label='A propos ...',underline=0,command=aPropos) 
RdJ.configure(menu=me1) 
  
# Boutons de commande à partir de la fenêtre Tkinter 
Button(can2,text='Quitter le jeu !',height=2,width=35,relief=GROOVE,bg="white",command=quitter).pack(padx=5,pady=5,side=BOTTOM,anchor=SW) 
ST=Button(can2,text='Stop !',height=2,width=35,relief=GROOVE,bg="white",activebackground="dark green",activeforeground="white",command=stop) 
ST.pack(padx=5,pady=5,side=BOTTOM,anchor=SW) 
LJ=Button(can2,text='Lancer le jeu !',height=2,width=35,relief=GROOVE,bg="white",activebackground="dark green",activeforeground="white",command=lancer_le_jeu) 
LJ.pack(padx=5,pady=5,side=BOTTOM,anchor=SW) 
MP=Button(can2,text='Mise en place !',height=2,width=35,relief=GROOVE,bg="white",activebackground="dark green",activeforeground="white",command=mise_en_place) 
MP.pack(padx=5,pady=5,side=BOTTOM,anchor=SW) 

# Niveau de jeu 
Label(can2,text='''Choisir le niveau de jeu''',fg='white',bg='brown').pack(padx=5,pady=5,side=BOTTOM) 
niveau=["1","2","3","4","5"] 
choix_niveau=IntVar() 
choix_niveau.set(niveau[0]) 
for i in range(0,5): 
    rad=Radiobutton(can2,text=str(i+1),variable=choix_niveau,value=niveau[i],command=niveau_jeu) 
    rad.pack(padx=6,pady=5,side=LEFT) 

#root.resizable(0,0) 
root.config(bg="brown") 
root.mainloop() 
root.destroy() 




 Conclusion

Commentaires et cotations seront les bienvenus !

 Fichier Zip

Les Membres Club peuvent télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip


 Historique

19 décembre 2005 23:44:33 :
Une correction est faite pour améliorer le code dans les textes du script : suppression des anti slashs \ de fin de ligne (inutiles), et utilisation des triples quotes.
21 décembre 2005 11:16:26 :
1.Une fonctionnalité nouvelle est ajoutée. Le serpent est maintenant vunérable lorsqu'il tire une flèche. La cible peut en effet se mettre en mouvement et ensuite le détruire. 2.Quatre niveaux de jeu sont créés. 3.La gestion des boutons de commandes et des messages est améliorée
22 décembre 2005 11:10:10 :
1.Introduction de cases à cocher pour les niveaux de jeu (au lieu d'un champ de saisie) 2.Diverses améliorations du code sans incidences sur les algorithmes
23 décembre 2005 01:01:33 :
1.Pendant le jeu, l'activation accidentelle de l'une des cases à cocher n'a plus d'effet (elle "décomposait" le serpent ... et finissait par bloquer le jeu). 2.Correction d'un oubli : le message d'avertissement disparait BIEN à nouveau quand la flèche du serpent redevient blanche. La ligne de code avait disparu lors d'une modification précédente.
11 avril 2006 22:47:35 :
Correction de syntaxe sur les lignes de séparation dans le script : #¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ au lieu de "¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤"
20 juin 2006 08:43:06 :
Ajout d'une capture d'écran

 Sources du même auteur

Source avec Zip MASTERMIND (PAR JULIE ET HCD)
Source avec Zip Source avec une capture RÉSOLUTION DES ÉQUATIONS DU 4ÈME DEGRÉ
Source avec Zip Source avec une capture LE CENTRE DU CERCLE RETROUVÉ PAR NAPOLÉON !
Source avec Zip Source avec une capture CERCLE ET DROITE D' EULER ANIMÉS DANS UN TRIANGLE
Source avec Zip COLLISIONS EN 3D AVEC VISUAL PYTHON

 Sources de la même categorie

Source avec Zip Source avec une capture MORBAK500 : JEU DE MORPION (TIC-TAC-TOE) par Mints
Source avec Zip Source avec une capture ASTRE3.0 : CASSE BRIQUES par Mints
Source avec Zip Source avec une capture SUDOSUDO : SUDOKU EN PYTHON par Mints
Source avec Zip Source avec une capture MODIFICATION SUR UN SNAKE EN PYTHON par zeen1x
Source avec Zip Source avec une capture PRINCIPE TETRIS EN PYTHON 2ÈME VERSION par Mints

 Sources en rapport avec celle ci

Source avec Zip Source avec une capture SUDOKU EN PYTHON AVEC TKINTER ! par karmik
Source avec Zip Source avec une capture MODIFICATION SUR UN SNAKE EN PYTHON par zeen1x
Source avec une capture JEU DU SERPENT (SNAKE) par zarash
Source avec Zip Source avec une capture JEU DU SERPENT ////\\\\ SNAKE par elnabo
Source avec Zip Source avec une capture PETIT JEU DE SERPENT DE BASE par Gulius

Commentaires et avis

Commentaire de tipro75 le 19/12/2005 20:34:50

Ton jeu (si c'est toi qui l'a inventé) est génial ! Même si certain trucs sont a corriger
EXEMPLE :
tu pourrait au bout de 15s de jeu animer(les mettre en vert) une de tes bombes parce que la si j'utilise seulement sa langue (le missile quoi) je peut po perdre...

Maintenant passons au code : impossible pour mon logiciel de lire tes / (ex ligne 443)
il faut les remplacer par des + (je parle pas des \n bien sur mais des trucs après tes " )

Voila je te maitrais 7/10 si je pouvait (ça fonctionne po quant je note)

Commentaire de tipro75 le 20/12/2005 12:55:31

Si tu lance ton logiciel et que tu apuit tout de suite sur stop il y a une ereur... il serait donc utile de verouiller le bouton tant que je n'ai pas appuyer sur 'mise en place'
(tu pourait fair la mm chose avec 'lancer le jeu'

de plus y a une erreur sur ta commande ta oublier de metre le txt en """

def aPropos():
    [...]
        text ="Serpent PYTHON \n\nHCD, Décembre 2005.\n"\
        "Python version 2.4.2\nTk version 8.4").pack(padx =10, pady =10)

j'ai modifier ton programe pour qu'il soit amiliorer (j'ai fait les deux truc au dessus seulement) (j'ai changer le nom de la liste de ron pour l'appeler YX (qui s'appelait S le blèmec que le bouton Stop s'appele aussi S voila pq g fé ca).


#! /usr/bin/env python
# -*- coding: Latin-1 -*-
# Python version 2.4.2
# Tk version 8.4
# IDLE version 1.1.2
  
# <<< Serpent PYTHON >>>
  
############# PRESENTATION #################
  
# Ce script est présenté sous la forme d'un JEU.
  
# Il fait intervenir un SERPENT orientable en direction et "armé" :
# - d'une FLECHE rétractable
# (commmande de tir par la touche < Espace > du clavier
# - d'un MISSILE à autoguidage terminal
# (commmande de tir par la touche de la lettre < X > du clavier
  
# Le but du jeu consiste pour le serpent à détruire le plus rapidement possible plusieurs cibles.
# Les cibles ont un comportement variable en fonction des armes utilisées.
# Elles sont entourées d'un cercle de détection, à l'intérieur duquel le missile se réoriente.
# Il se dirige alors automatiquement vers le centre de la cible détectée.
# La cible est détruite au contact du missile.
# MAIS, les cibles peuvent DETRUIRE le serpent lorsq'un tir de missile les a rendu MOBILES.
# La partie n'est donc pas gagnée d'avance !!!
  
# La fenêtre de jeu comprend:
# - un plan carré à l'intérieur duquel évoluent le serpent et les cibles
# - quatre boutons de commande :
# . < Mise en place ! >
# . < Lancer le jeu ! >
# . < Stop ! >
# . < Quitter le jeu ! >
# - un bouton donnant la :
# . < Règle du jeu ! >
# - un compteur visualisant le temps écoulé
  
# Commencer -comme il est d'usage- par prendre connaissance de la < Règle du jeu ! >.
  
############# COMMENTAIRE #################
  
# Le programme fait intervenir l'interface graphique Tkinter, avec quatre modules :
# math, random, tkMessageBox, time.
# L'utilisation de LISTES (pour les coordonnées et les diamètres des cercles) et d'une BIBLIOTHEQUE
# pour leur identification, permet de réduire considérablement le nombre de lignes de code.
# C'est l'intérêt de ce script.
# L'algorithme de collision est celui que j'avais présenté dans les codes intitulés:
# "BILLARD Français", et "COLLISIONS multiples".
  
"¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤"
  
from Tkinter import*
from math import hypot,sqrt,floor,log
from random import randrange
from tkMessageBox import askokcancel
from time import time
  
"¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤"
  
nS=40# nombre de cercles constituant le serpent
nC=39# nombre de cibles
nO=10# nombre d'obstacles
V=2# paramètre de réglage de la vitesse initiale du serpent
  
"¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤"
  
def mise_en_place():
    " commande de mise en place du jeu "
    global flag,départ
    S.configure(stat=NORMAL)
    T.configure(stat=NORMAL)
    TT.configure(stat=DISABLED)
    flag=1
    départ=time()
    can.delete(ALL)
    serpent()
    cibles()
    obstacles()
  
def lancer_le_jeu():
    " commandes de lancement des mouvements et de gestion des collisions "
    T.configure(stat=DISABLED)
    if flag==1:
        mouvements_serpent()
        mouvements_fleche()
        mouvements_cibles()
        collisions_serpent_obstacles()
        collisions_serpent_cibles()
        collisions_missile_cibles()
        if collisionF + collisionM == nC:# arrêt lorsque toutes les cibles sont détruites
            arrivée=time()
            durée=int(round(arrivée-départ,0))
            for i in range(0,nO):can.delete(O[i])
            for i in range(1,150):sapin();can.delete(ALL)
            for i in range(1,150):sapin()
            can.create_text(L/2,H/3-50,text='Joyeuses fêtes !!!',fill="white",font="Arial 12")
            root.after(10000,stop)
        if hypot(x[nS-2]-x[1],y[nS-2]-y[1])>200*V-80:# destruction du serpent
            destruction()
        durée=int(round(time()-départ,0))
        can.score.config(text='%s'%durée)# visualisation du temps écoulé
        
        root.after(10,lancer_le_jeu)
  
"¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤"
  
def serpent():
    " création du serpent PYTHON (S) et de sa flèche (F) "
    global YX,LF,x,y,dx,dy,DS
    x=[L-(i+2)*V*n for i in range(0,nS)]# liste des abscisses des 40 cercles constituant le serpent
    y=[H-(i+2)*2*V*n for i in range(0,nS)]# liste des ordonnées
    dx=[-V*n for i in range(0,nS)]# liste des vitesses horizontales
    dy=[-2*V*n for i in range(0,nS)]# liste des vitesses verticales
    DS=[7]
    for i in range(0,nS-1):DS.append(1+d*(1+i)/nS) # liste des diamètres
    YX={}# bibliothèque des cercles
    LF=can.create_line(x[nS-1],y[nS-1],x[nS-2],y[nS-2],fill="orange")# ligne reliant la flèche à la tête du serpent
    for i in range(0,nS):
        YX[i]=can.create_oval(x[i]-DS[i]/2,y[i]-DS[i]/2,x[i]+DS[i]/2,y[i]+DS[i]/2,fill="orange",outline="orange")
    can.itemconfig(YX[nS-4],width=9);can.itemconfig(YX[nS-3],width=6);can.itemconfig(YX[nS-2],width=3)# dessin de la tête du serpent
    can.itemconfig(YX[0],fill="white")
    can.itemconfig(YX[nS-1],fill="white",outline="blue")# dessin de la flèche rétractable
    
def cibles():
    " création des cibles (C) "
    global C,Q,xC,yC,dxC,dyC,DC,DQ
    xC=[randrange(10,780) for i in range(0,25)]# liste des abscisses des 39 cibles (distribution aléatoire)
    for i in range(25,39):xC.append(randrange(10,520))# pour éviter au départ de placer une cible sur le serpent
    yC=[10+i*19 for i in range(0,nC)]# liste des ordonnées (régulièrement espacées)
    dxC=[0 for i in range(0,nC)]# les cibles sont immobiles
    dyC=[0 for i in range(0,nC)]
    DC=[randrange(10,20) for i in range(0,nC)]# diamètres compris entre 10 et 20
    DQ=[100 for i in range(0,nC)]# diamètres des cercles de détection des cibles
    C={}# bibliothèque des cibles
    Q={}# bibliothèque des cercles de détection
    for i in range(0,nC):
        Q[i]=can.create_oval(xC[i]-DQ[i]/2,yC[i]-DQ[i]/2,xC[i]+DQ[i]/2,yC[i]+DQ[i]/2,outline='#007000')
        C[i]=can.create_oval(xC[i]-DC[i]/2,yC[i]-DC[i]/2,xC[i]+DC[i]/2,yC[i]+DC[i]/2,fill="brown",outline="yellow")
  
def obstacles():
    " création des obstacles fixes (C) "
    global O,xO,yO,dxO,dyO,DO
    xO=[L/4+i*50 for i in range(0,nO)]# liste des abscisses des 10 obstacles (distribution régulière)
    yO=[H/4+i*50 for i in range(0,nO)]# liste des ordonnées (id)
    dxO=[0 for i in range(0,nO)]# les cibles sont immobiles
    dyO=[0 for i in range(0,nO)]
    DO=[40 for i in range(0,nO)]# diamètre des obstacles
    O={}# bibliothèque des obstacles
    for i in range(0,nO):
        O[i]=can.create_oval(xO[i]-DO[i]/2,yO[i]-DO[i]/2,xO[i]+DO[i]/2,yO[i]+DO[i]/2,fill="blue",outline="yellow")
  
"¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤"
  
def mouvements_serpent():
    " mouvements du serpent (S) "
    global x,y,dx,dy,DS
    global vF,tirF,GC,DR,HT,BS,iG,iD,iH,iB
    if tirF==1:desactiver_touches()
    if tirF==0:activer_touches()
    for i in range(0,nS):
        # commandes de direction
        if GC==1:# clavier : activation de la flèche gauche
            desactiver_touches();X,Y=x[i]-u,y[i]-v;Z=hypot(X,Y)
            if Z==0 :iG+=1;dx[i],dy[i]=-hypot(du,dv),0
            if iG==nS-1:activer_touches();GC=0;iG=0
        if DR==1:# clavier : activation de la flèche droite
            desactiver_touches();X,Y=x[i]-u,y[i]-v;Z=hypot(X,Y)
            if Z==0 :iD+=1;dx[i],dy[i]=hypot(du,dv),0
            if iD==nS-1:activer_touches();DR=0;iD=0
        if HT==1:# clavier : activation de la flèche haute
            desactiver_touches();X,Y=x[i]-u,y[i]-v;Z=hypot(X,Y)
            if Z==0 :iH+=1;dx[i],dy[i]=0,-hypot(du,dv)
            if iH==nS-1:activer_touches();HT=0;iH=0
        if BS==1:# clavier : activation de la flèche basse
            desactiver_touches();X,Y=x[i]-u,y[i]-v;Z=hypot(X,Y)
            if Z==0 :iB+=1;dx[i],dy[i]=0,hypot(du,dv)
            if iB==nS-1:activer_touches();BS=0;iB=0
        # mouvements
        x[i],y[i]=x[i]+(1+collisionF/nC)*dx[i],y[i]+(1+collisionF/nC)*dy[i]# le mouvement du serpent s'accélère avec la destruction des cibles
        if tirM==0:
            x[0],y[0]=x[1]-dx[1],y[1]-dy[1]# le missile est maintenu en queue
        can.coords(YX[i],x[i]-DS[i]/2,y[i]-DS[i]/2,x[i]+DS[i]/2,y[i]+DS[i]/2)
    # collisions avec les bordures
    for i in range(0,nS-1):# maintien dans les limites du jeu par rebond sur les bords
        collision_bordures(x[i],y[i],dx[i],dy[i],DS[nS-1])
        x[i],y[i],dx[i],dy[i]=pp,qq,rr,ss
  
def mouvements_fleche():
    " mouvements de la flèche (F) "
    global x,y,dx,dy
    global vF,tirF
    can.coords(LF,x[nS-1],y[nS-1],x[nS-2],y[nS-2])
    if tirF==1:# la flèche du serpent est lancée dans l'axe à une vitesse supérieure
        dx[nS-1],dy[nS-1]=vF*dx[nS-1]/hypot(dx[nS-1],dy[nS-1]),vF*dy[nS-1]/hypot(dx[nS-1],dy[nS-1])
        x[nS-1],y[nS-1]=x[nS-1]+dx[nS-1],y[nS-1]+dy[nS-1]
    if tirF==1 and x[nS-1]>L-d/2 or x[nS-1]<d/2 or y[nS-1]>H-d/2 or y[nS-1]<d/2:# maintien dans les limites du jeu
        x[nS-1],y[nS-1],dx[nS-1],dy[nS-1]=x[nS-2],y[nS-2],dx[nS-2],dy[nS-2]
        vF,tirF=0,0
    if tirF==0 and x[nS-1]>L-d/2 or x[nS-1]<d/2 or y[nS-1]>H-d/2 or y[nS-1]<d/2:# maintien dans les limites du jeu
        x[nS-1],y[nS-1],dx[nS-1],dy[nS-1]=x[nS-2],y[nS-2],dx[nS-2],dy[nS-2]
  
def mouvements_cibles():
    " petits mouvements des cibles lors des collisions(O) "
    global xC,yC,dxC,dyC
    for i in range(0,nC):
        # mouvement
        xC[i],yC[i]=xC[i]+dxC[i],yC[i]+dyC[i]
        can.coords(C[i],xC[i]-DC[i]/2,yC[i]-DC[i]/2,xC[i]+DC[i]/2,yC[i]+DC[i]/2)
        can.coords(Q[i],xC[i]-DQ[i]/2,yC[i]-DQ[i]/2,xC[i]+DQ[i]/2,yC[i]+DQ[i]/2)
        # collisions avec les bordures
        collision_bordures(xC[i],yC[i],dxC[i],dyC[i],DC[i])
        xC[i],yC[i],dxC[i],dyC[i]=pp,qq,rr,ss
  
"¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤"
  
def collisions_serpent_obstacles():
    " gestion des collisions Serpent / Obstacles "
    global x,y,dx,dy,DS
    global xO,yO
    for j in range(0,nO):
        if tirF==1:# après un tir
            X,Y=xO[j]-x[nS-1],yO[j]-y[nS-1]
            Z=hypot(X,Y)
            if Z<=DS[nS-1]/2+DO[j]/2:# s'il y a collision Flèche / Obstacle
                x[nS-1],y[nS-1],dx[nS-1],dy[nS-1]=x[nS-2],y[nS-2],dx[nS-2],dy[nS-2]# la flèche revient en place
        for i in range(0,nS):# collisions Serpent / Obstacles
            collisions(x[i],y[i],xO[j],yO[j],dx[i],dy[i],dxO[j],dyO[j],DS[nS-1],DO[j])
            x[i],y[i],xO[j],yO[j]=rxa,rya,rxb,ryb
            dx[i],dy[i]=rdxa,rdya
  
def collisions_serpent_cibles():
    " gestion des collisions Serpent / Cibles "
    global x,y,dx,dy
    global xC,yC
    global collisionF,tirF,vF
    for j in range(0,nC):
        if tirF==1:# après un tir
            X,Y=xC[j]-x[nS-1],yC[j]-y[nS-1]
            Z=hypot(X,Y)
            if Z<=DS[nS-1]/2+(1+collisionF/3)*DC[j]/2:# s'il y a collision Serpent / Cibles
                xC[j],yC[j],DC[j],DQ[j]=0,0,0,0# la cible est détruite
                x[nS-1],y[nS-1],dx[nS-1],dy[nS-1]=x[nS-2],y[nS-2],dx[nS-2],dy[nS-2]# la flèche revient en place
                collisionF+=1
                vF,tirF=0,0
                can.create_rectangle(L*(collisionF-1)/nC,H-10,L*collisionF/nC,H,fill="pink",outline="blue")
                can.create_text(50,H-15,text='flèche',fill="white")
                if collisionM!=0:# s'il y a eu, en outre, destruction d'une cible, une nouvelle cible apparait
                    dxC[j],dyC[j]=0,0# immobilisation de celle-ci
        for i in range(0,nS):# collisions Serpent / Cibles
            collisions(x[i],y[i],xC[j],yC[j],dx[i],dy[i],dxC[j],dyC[j],DS[nS-1],DC[j])
            x[i],y[i],xC[j],yC[j]=rxa,rya,rxb,ryb
            dx[i],dy[i]=rdxa,rdya
  
def collisions_missile_cibles():
    " gestion des collisions Missile de queue / Cibles / Cercle de détection "
    global x,y,dx,dy,DS
    global tirM,collisionM
    global xC,yC,dxC,dyC,DC
    global DQ
    if tirM==1:# lorsque le missile est tiré
        for j in range(0,nC):
            DQ[j]=DQ[j]+0.05# le diamètre des cercles de détection augmente à chaque tir
            X,Y=x[0]-xC[j],y[0]-yC[j]
            Z=hypot(X,Y)
            if Z<=DQ[j]/2+DS[0]/2:# s'il y a contact du missile avec le cercle de détection
                dx[0],dy[0]=-X/Z*hypot(dx[0],dy[0]),-Y/Z*hypot(dx[0],dy[0])# le missile s'oriente en direction de la cible
                DQ[j]=0.97*DQ[j]# le cercle de détection rétrécit lentement
                can.itemconfig(C[j],fill='#00FF00')# la couleur des cibles détectées passe au vert
                dxC[j],dyC[j]=0.25*randrange(1,2),0.25*randrange(1,2)# les cibles détectées se mettent en mouvement
  
                " ATTENTION !!! A partir de ce moment, les cibles mises en mouvement sont DANGEREUSES. "
                " Le serpent est détruit s'il entre à leur contact : il lui faut donc les détruire en priorité "
                " et, sinon, les éviter "
                
                if DQ[j]<0.97*nC:# collision du missile avec la cible visée
                    collisionM+=1
                    tirM=0
                    xC[j],yC[j],dxC[j],dyC[j],DC[j],DQ[j]=0,0,0,0,0,0# destruction de la cible
                    x[0],y[0]=x[1]-dx[1],y[1]-dy[1]# le missile revient à sa place (en queue du serpent)
                    can.create_rectangle(L-L*collisionM/nC,H-10,L-L*(collisionM-1)/nC,H,fill="grey",outline="blue")
                    can.create_text(L-50,H-15,text='missile',fill="white")
    if tirM==0 :
        x[0],y[0]=x[0],y[0]
                    
"¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤"
  
def collision_bordures(p,q,r,s,D):
    " algorithme commun de collision avec les bordures "
    global pp,qq,rr,ss
    if p>L-D/2:pp,qq,rr,ss=L-D/2,q,-r,s
    if p<D/2:pp,qq,rr,ss=D/2,q,-r,s
    if q>H-D/2:pp,qq,rr,ss=p,H-D/2,r,-s
    if q<D/2:pp,qq,rr,ss=p,D/2,r,-s
    if p<=L-D/2 and p>=D/2 and q<=H-D/2 and q>=D/2:
        pp,qq,rr,ss=p,q,r,s
  
def collisions(xa,ya,xb,yb,dxa,dya,dxb,dyb,da,db):
    " algorithme commun de collisions entre cercles "
    global rxa,rya,rxb,ryb
    global rdxa,rdya
    X,Y=xb-xa,yb-ya
    Z=hypot(X,Y)
    if Z<=(da+db)/2:
        dX,dY=dxb-dxa,dyb-dya
        dZ=hypot(dX,dY)
        if dZ==0:m=0
        else:
            k,K=dZ*dZ,X*dX+Y*dY
            m=(K+sqrt(K*K-k*(Z*Z-(da+db)/2*(da+db)/2)))/k
        rxa,rya,rxb,ryb=xa-m*dxa,ya-m*dya,xb-m*dxb,yb-m*dyb
        X,Y=rxb-rxa,ryb-rya
        Z=hypot(X,Y)
        if Z<=(da+db)/2:
            dxb,dyb=0,0
            dX,dY=dxb-dxa,dyb-dya
            dZ=hypot(dX,dY)
            if dZ==0:m=0
            else:
                k,K=dZ*dZ,X*dX+Y*dY
                m=(K+sqrt(K*K-k*(Z*Z-(da+db)/2*(da+db)/2)))/k
            rxa,rya,rxb,ryb=xa-m*dxa,ya-m*dya,xb-m*dxb,yb-m*dyb
        xx,xy,yy=X*X/Z/Z,X*Y/Z/Z,Y*Y/Z/Z
        rdxa,rdya=(yy-xx)*dxa-2*xy*dya,-2*xy*dxa-(yy-xx)*dya
    else:
        rxa,rya,rxb,ryb=xa,ya,xb,yb
        rdxa,rdya=dxa,dya
  
"¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤"
  
    # Fonctions de déplacement des touches :
  
def left(event):
    " S à gauche "
    global u,v,du,dv,GC
    GC+=1
    u,v,du,dv=x[nS-1],y[nS-1],dx[nS-1],dy[nS-1]
  
def right(event):
    " S à droite "
    global u,v,du,dv,DR
    DR+=1
    u,v,du,dv=x[nS-1],y[nS-1],dx[nS-1],dy[nS-1]
  
def up(event):
    " S vers le haut "
    global u,v,du,dv,HT
    HT+=1
    u,v,du,dv=x[nS-1],y[nS-1],dx[nS-1],dy[nS-1]
  
def down(event):
    " S vers le bas "
    global u,v,du,dv,BS
    BS+=1
    u,v,du,dv=x[nS-1],y[nS-1],dx[nS-1],dy[nS-1]
  
def tirer_fleche(event):
    " commande touche < Espace > "
    global vF,tirF
    tirF=1
    vF=10
  
def tirer_missile(event):
    " commande touche < x > ou < X > "
    global tirM
    tirM=1
  
def activer_touches():
    ""
    root.bind("<Left>",left)
    root.bind("<Right>",right)
    root.bind("<Up>",up)
    root.bind("<Down>",down)
  
def desactiver_touches():
    ""
    root.unbind("<Left>")
    root.unbind("<Right>")
    root.unbind("<Up>")
    root.unbind("<Down>")
  
"¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤"
  
def destruction():
    " message explicatif "
    stop()
    can.delete(texte)
    texte2=can.create_text(L/2,420,text='''Le serpent a été détruit après collision avec une cible mobile (de couleur verte) !\n\n
    Lorsque le serpent tire un missile, il peut arriver que plusieurs cibles fixes soient détectées.
    Dans ce cas, les cibles détectées changent de couleur : elles passent du marron au vert.
    et, surtout, elles entrent en mouvement.
    Le missile se dirige vers la première détectée et la détruit.
    Mais les autres cibles, devenues mobiles, sont dangereuses pour le serpent.
    Elles doivent être détruites le plus rapidement possible et, surtout, absolument évitées.\n\n
    Vous pouvez continuer en appuyant sur : Mise en place !
    et, sinon, sur : Quitter le jeu !\n''',fill="white",font="Arial 12")
  
"¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤"
  
def stop():
    " arrêt des mouvements et mise à zéro de tous les compteurs "
    global flag,tirF,collisionF,tirM,collisionM,GC,DR,HT,BS,texte,arrivée
    S.configure(stat=DISABLED)
    T.configure(stat=DISABLED)
    TT.configure(stat=NORMAL)
    flag=0
    tirF,collisionF=0,0
    tirM,collisionM=0,0
    root.bind("<Left>",left)
    root.bind("<Right>",right)
    root.bind("<Up>",up)
    root.bind("<Down>",down)
    GC,DR,HT,BS=0,0,0,0
    for i in range(0,nO):can.delete(O[i])
    for i in range(0,nC):can.delete(C[i]),can.delete(Q[i])
    texte=can.create_text(L/2,50,text="MERCI\n\net\n\nn' hésitez pas à commenter (et à coter...) ce script !",fill="white",font="Arial 12")
    arrivée=time()
    
def quitter():
    " façon classique de quitter l'application "
    ans=askokcancel('Serpent PYTHON',"Voulez-vous réellement quitter ?")
    if ans:root.quit()
  
def sapin():
    " petit dessin en guise de récompense !!!"
    can.create_polygon(400,400 ,385,455 ,415,455,fill="green")
    can.create_polygon(400,440 ,375,495 ,425,495,fill="green")
    can.create_polygon(400,480 ,365,530 ,435,530,fill="green")
    can.create_polygon(400,510 ,355,570 ,445,570,fill="green")
    can.create_polygon(400,540 ,345,610 ,455,610,fill="green")
    can.create_rectangle(392,610 ,408,625 ,fill="green")
    a,b,c=randrange(0,800),randrange(0,800),randrange(2,8)
    can.create_oval(a,b,a+c,b+c,fill="white")
  
"¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤"
  
def presentation():
    "Fenêtre-message contenant la description sommaire du principe du jeu"
    msg =Toplevel()
    Message(msg, bg ="dark green", fg ="white", width =700,font ="Arial 10",
        text =''' PRESENTATION\n
        Au lancement du jeu, le bouton < Mise en place > fait apparaître:\n
           - le serpent PYTHON constitué de 40 cercles de diamètres décroissants, de la tête vers la queue
           - la FLECHE (rétractable) du serpent : cercle blanc placé au niveau du nez
           - le MISSILE (à autoguidage terminal) : petit cercle blanc situé en queue
           - 10 obstacles fixes indestructibles de couleur bleue et de même diamètre
             (sur lesquels rebondissent serpent, flèche et missile)
           - 39 cibles à détruire, de couleur marron et de diamètre variable
             (leurs abscisses ont des valeurs aléatoires, leurs ordonnées sont échelonnées régulièrement)
             (ces cibles sont toute entourées d'un cercle de détection dont le diamètre est constant au départ, puis variable ensuite)\n\n
        Le jeu consiste pour le serpent à détruire les 39 cibles, le plus rapidement possible, sans être lui-même détruit.
        (la durée de la partie est affichée en haut et à droite de la fenêtre)\n
        Les \"moyens\" dont il dispose sont:
           - sa FLECHE, qui peut être tirée par pression rapide ou continue sur la touche < Espace > du clavier
              (la progression des destructions avec la flèche est visualisée en bas et à gauche du plan de jeu)
           - le MISSILE, qui est tirable par pression rapide sur la touche < X > du clavier
              (la progression des destructions avec le missile est visualisée en bas et à droite du plan de jeu)\n\n
        Progression du jeu :\n
        Utilisation de la FLECHE
        Au début, les tirs de la flèche doivent être précis pour pouvoir détruire les cibles.
        Ils deviennent plus faciles ensuite, car la distance d'interception augmente lentement avec le nombre de succès.
        Ces tirs étant sans risques pour le serpent, il est recommandé de commencer par eux pour bien progresser.\n
        Utilisation du MISSILE
        Après tir par le serpent dans la zone de détection d'une cible, le missile se réoriente pour se diriger vers le centre de la cible.
        La cible entre en mouvement, sa couleur passe au vert, son cercle de détection se rétracte, puis elle disparait.
        Lorsqu'une ou plusieurs autres cibles sont aussi détectées, elles deviennent également mobiles; leur couleur passe au vert.
        Le missile reprend sa place, en queue du serpent, et peut à nouveau être tiré.
        Mais il y a alors DANGER pour le serpent, qui risque la DESTRUCTION en cas de collision avec ces cibles mobiles.
        Ces tirs de missile sont donc préférables en milieu de partie, quand le risque de multiples détections est moins élevé.
        Avec un peu d'entrainement, on cherchera cependant à les mettre en oeuvre plus tôt, en raison de leur efficacité.
        En fin de partie, l'utilisation des flèches (haut,bas,gauche,droite) du clavier pourra permettre de gagner du temps.\n\n''').pack(padx =10, pady =10)
  
  
def processus():
    "Fenêtre-message contenant la description du processus de jeu"
    msg =Toplevel()
    Message(msg, bg ="dark green", fg ="white", width =450,font ="Arial 10",
        text='''PROCESSUS à suivre\n\n
        1. Cliquer sur le bouton < Mise en place ! >\n
        2. puis sur le bouton < Lancer le jeu ! >\n
        3. Tir avec la flèche rétractable :
             appuyer sur la touche < Espace > du clavier\n
        4. Tir d'un missile :
             appuyer sur la touche de la lettre < X > du clavier\n
        5. Changement de direction du serpent :
             utiliser les quatre flèches du clavier
             (haut, bas, gauche, droite)\n
        6. Bouton < Stop !>
             pour arrêter les mouvements\n
        7. Bouton < Quitter le jeu !>
             pour abandonner la partie\n''').pack(padx =10, pady =10)
  
def aPropos():
    "Fenêtre-message indiquant les versions utilisées"
    msg =Toplevel()
    Message(msg, width =200, aspect =100, justify =CENTER,
        text ="""Serpent PYTHON \n\nHCD, Décembre 2005.
        \nAide de : SK8gis(Tipro75)\n
        Python version 2.4.2\nTk version 8.4""").pack(padx =10, pady =10)
  
######## Programme principal ############################################
  
root = Tk()
root.title('>>>>>>> Serpent PYTHON <<<<<<<')
  
L,H=800,800
flag=0
d=10
n=1.5
tirF,collisionF=0,0
tirM,collisionM=0,0
u,v=0,0
GC,DR,HT,BS=0,0,0,0
iG,iD,iH,iB=0,0,0,0
durée=0
arrivée=0
can=Canvas(root,bg='dark green',height=H,width=L)
can.grid(row=1,column=0,rowspan=2)
can2=Canvas(root,bg='brown',highlightbackground='brown')
can2.grid(row=1,column=1,sticky=N)
  
# commandes à partir du clavier
root.bind("<Left>", left)
root.bind("<Right>", right)
root.bind("<Up>", up)
root.bind("<Down>", down)
root.bind('<space>', tirer_fleche)
root.bind('x', tirer_missile)
root.bind('X', tirer_missile)
  
# Score (durée de la partie)
can.score=Label(can2,text='0',fg='white',bg='brown')
can.score.pack(side=BOTTOM)
Label(can2,text="durée de la partie\n(secondes)",fg='white',bg='brown').pack(side=BOTTOM)
  
# Menu <Règle du jeu>
RdJ = Menubutton(can2, text ='Règle du jeu',height=2,width=25,relief=GROOVE,bg="dark green",fg="white")
RdJ.pack(padx=5,pady=5,side=BOTTOM,anchor=SW)
me1 = Menu(RdJ)
me1.add_command(label='Présentation',underline=0,command=presentation)
me1.add_command(label='Processus',underline=0,command=processus)
me1.add_command(label='A propos ...',underline=0,command=aPropos)
RdJ.configure(menu=me1)
  
# Boutons de commande à partir de la fenêtre Tkinter
Button(can2,text='Quitter le jeu !',height=2,width=25,relief=GROOVE,bg="white",command=quitter).pack(side=BOTTOM)
S=Button(can2,text='Stop !',height=2,width=25,relief=GROOVE,bg="white",activebackground="dark green",activeforeground="white",command=stop,stat=DISABLED)
S.pack(padx=5,pady=5,side=BOTTOM,anchor=SW)
T=Button(can2,text='Lancer le jeu !',height=2,width=25,relief=GROOVE,bg="white",activebackground="dark green",activeforeground="white",command=lancer_le_jeu,stat=DISABLED)
T.pack(padx=5,pady=5,side=BOTTOM,anchor=SW)
TT=Button(can2,text='Mise en place !',height=2,width=25,relief=GROOVE,bg="white",activebackground="dark green",activeforeground="white",command=mise_en_place)
TT.pack(padx=5,pady=5,side=BOTTOM,anchor=SW)
  
root.mainloop()
root.destroy()


Commentaire de HCD le 21/12/2005 12:38:43

Réponses à TIPRO75

au 1er commentaire:

Merci pour ton commentaire si rapide !
J'ai en effet construit moi-même ce petit jeu, qui est dans la lignée de mes scripts précédents sur les algorithmes de collision inélastique (mécanique des solides).
Mais, je débute en PYTHON !!!
Dans une deuxième version que je mets tout de suite sur le site, les problèmes de \ à la fin des lignes de texte sont corrigés. J'ai même simplifié en utilisant les triples quotes '''.
Quand à ton idée de rendre l'extrémité de la flèche vunérable, je la trouve intéressante pour une prochaine version.
Encore merci
et "joyeuses fêtes de fin d'année !"

au 2ème commentaire

J'ai pris en compte toutes tes remarques.
Pour les boutons de commande, c'est en effet beaucoup mieux.
Encore MERCI !
Pour aller plus loin dans le sens que tu m'as  indiqué dans ton premier commentaire, j'ai introduit quelques lignes de code qui rendent le serpent vulnérable quand il tire dans certaines circonstances.
Ajouté aussi 4 niveaux de jeu, en faisant varier certains paramètres.
Cela commence à prendre tournure !
Je relis le script demain matin et le mets sur le site dans la foulée.
Tes commentaires compteront beaucoup pour moi.
Good night and A+

HCD

Commentaire de tipro75 le 21/12/2005 22:40:30

Je suis content du resultat; le jeu est super !!! Bravo a toi...

Sinon ton bouton 'avertissement' tu pourait fair la même chose avec un Label, ce qui empecherait les joeur d'appuyer dessus...
C'est rien mais c un detail, comme les boutons desactivés...

De plus tu pourait utiliser des 'boutons radio' pour choisir le niveau ce qui empecherait le joueur de metre 'a'(par ex.) au compteur ce qui en appuyant sur 'metre en place' fait boeuger et ont est obliger de relancer car ce bouton est verouiller...
C'est rien mais c un detail, comme les boutons desactivés...

Bon voila...

P.S. : Si ta besoin de moi fait moi signe g tout mon temps (mais pas le jour de noël quant même ;) .


A oui mince pour bouger je serpent ca serait bien si on pouvait utiliser les touches du clavier numerique (entre autre le 7,9,1,3 pour les diagonales) et la pour finir ajoute cette ligne à la ligne 652 :
<<   root.config(bg="brown")   >>
ce qui permettera a ta fenetre d'être toute rouge c+ joli...
et :
<<   root.resizable(0,0)   >>
ce qui empechera l'utilisateur de modifier la taille de ta fenetre (c toujours un detail...)

Commentaire de HCD le 22/12/2005 11:00:53

Voici les dernières modifications:

1.'bouton 'avertissement':un Label remplace le bouton
2.'boutons radio': fait, avec 5 niveaux
3.<<root.config(bg="brown")>> : fait; le résultat est superbe !
4<<root.resizable(0,0)>> : j'ai mis l'instruction à la fin du code, mais elle n'est pas activée.
Je trouve dommage qu'elle empêche de passer en plein éran ???
5.Les derniers accents qui restaient dans les noms de variables ont été supprimés, pour ne pas avoir de pb avec les éditeur Scite ou Pythonwin, par exemple.
6.Modifié également les couleurs du panneau "avertissement" : le rouge n'allait pas.

Ta remarque sur la "commmande" du serpent pour le faire bouger : elle existe avec les 4 flèches du clavier.
Je reconnais qu'elle n'est pas terrible, car après un changement de direction, il faut atttendre que le serpent ait complètement fini de tourner avant de pouvoir changer à nouveau. Ce point serait à améliorer.

Voilà pour le moment !

Au fait, il y a un phénomène qui m'intrigue : quand on joue en continu, sans sortir par <<Quitter le jeu>>, j'ai remarqué que les mouvements se ralentissent peu à peu, jusqu'à même se bloquer. Mainloop() tourne, et ça donne l'impression de saturer quelque part dans la mémoire ????
Si tu as des idées sur ce point, elles m'intéressent beaucoup.

Bonne journée et A+

HCD


Commentaire de tipro75 le 22/12/2005 14:25:08

ta oublier un truc : on peur changer de niveau pendant qu'on jou et sa fait tout boeuger !

Voila sinon ton jeu est de mieu en mieu...

Commentaire de HCD le 23/12/2005 01:18:36

Oubli réparé !
J'aurais bien aimé utiliser <<configure()>> pour activer/désactiver le Radiobutton des cases à cocher, mais je n'ai pas trouvé la solution.
Ceci explique la création du paramètre <<activation_case>> (=0 ou 1) qui permet de neutraliser un changement de niveau pendant le jeu.

A+

HCD

Commentaire de xeolin le 02/04/2006 17:48:36


scuse moi mé pourai tu remplacer les :

"¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤"


par des :


#¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

parceque ca fé planter certain interprétateur de pyth

Commentaire de xeolin le 02/04/2006 17:53:54

dsl pur les doublage et pi g pomé mon mot de passe (en tant que tipro75(aussi celle de mon mail (c mon programe qui était censé de proteger mes pass mais il a fait tout le contraire)) donc g changer de psedo...

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

modification de jeu morpion en python [ par apprenti2008 ] salut a tous ! SVP j'ai vraiment besoin d'aide , je suis en première année MASS , le prof nous a demander de créer un jeu morpion en python , le princ [Jeu par navigateur] Miraemos - Projet sérieux [ par jesslaly ] Bonjour,Je suis Jessica, étudiante qui a monté un projet depuis une année maintenant.Je me suis lancée dans un projet assez intéressant de jeu en lign jeu de la vie [ par dia100daly ] je veux poster un code. Mais j'aimerai savoir si c'etait vraiment la peine car c'est la première fois. Pour plus de détail voir sur Wikipédia ( jeu de codage Windows jeu de caractères [ par creaduff ] Bonjour,Avant tout, précisons que je ne suis pas un aigle en Python ! Voici mon problème:J'ai écrit une petit programme permettant d'accéder à ma boit Réalisation d'un plus ou moins sur Tkinter [ par kuritsu ] Bonsoir tout le monde, et je vous souhaite la bonne année à tous par la même occasion. Je viens de me mettre à la programmation sous Python, et j'avo créer une simulation d'un jeu de cartes [ par jimux06 ] # simulation d'un tirage de cartes # dans la version 3.1.x # afficher la date du jour (jj-mm-aaaa) et l'heure (hh:mm:ss), avant chaque jeu # utiliser Création d'un jeu 2D ! [ par Gatax ] Salut [^^clinoeil1] Je suis nouveau ici, et depuis qu'elle que temps j'aimerais crée un jeu 2D avec qu'elle que personne 2 ou 3, Mais c'est un peu dif Créer un petit jeu de simulation politique [ par redstar1504 ] Bonsoir à tous ! Ayant décidé il y a quelque jour d'apprendre à programmer (et cette fois-ci, avec documentation et donc un langage qu'on me recomman Jeux motus python [ par Leeloo91 ] Bonjour à tous!! Nous sommes deux étudiantes et nous devons présenter un produit qui est le jeu de mots Motus, à laide de python qui permettrai à un jeu de l'oie PYTHON [ par poulino ] BONJOUR, JE DOIS CREER UN JEU DE L OIE SUR PYTHON POUR LE 7JANVIER. JE NE SAIS PAS D OU PARTIR ET J AI DES DIFFICULTES EN INFORMATIQUE. EST CE QUE QU


Nos sponsors


Sondage...

CalendriCode

Juin 2013
LMMJVSD
     12
3456789
10111213141516
17181920212223
24252627282930

Consulter la suite du CalendriCode

Photothèque

A découvrir



 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 9,032 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales