Demande d'aide à l'optimisation [Résolu]

Messages postés
28
Date d'inscription
vendredi 7 août 2009
Statut
Membre
Dernière intervention
2 mai 2016
- - Dernière réponse : elnabo
Messages postés
28
Date d'inscription
vendredi 7 août 2009
Statut
Membre
Dernière intervention
2 mai 2016
- 27 janv. 2010 à 10:57
Bonjour, ayant réaliser un petit code permettant de déplacer un petit rond d'avant en arrière et lui permettant des rotations, à l'aide du clavier en me servant de classe,je me décide à le poster ici pour demander une aide à son optimisation.

#
from Tkinter import *
from math import *
class move:
    ""
    def __init__(self):
        self.x=100
        self.y=100
        self.x1=120
        self.y1=120
        self.ang=0
        fen = Tk()
        self.can Canvas(fen,width 300,height = 300,bg='dark grey')
        self.can.bind_all("<Right>",self.droite)
        self.can.bind_all("<Left>",self.gauche)
        self.can.bind_all("",self.haut)
        self.can.bind_all("<Down>",self.bas)
        self.can.pack()
        self.joueur self.can.create_oval(self.x-10,self.y-10,self.x+10,self.y+10,fill 'yellow')
        self.t = self.can.create_line(self.x,self.y,self.x1,self.y1,fill='red')
        fen.mainloop()
        
    
    def gauche(self,event):
        if self.ang==0:
            self.x1+=-5
        else:
            self.x1+=5
        self.eg()
        self.can.coords(self.t,self.x,self.y,self.x1,self.y1)

    def droite(self,event):
        if self.ang==0:
            self.x1+=5
        else:
            self.x1+=-5
        self.ed()
        self.can.coords(self.t,self.x,self.y,self.x1,self.y1)

    def eg(self):
        try:
            self.y1=self.y-sqrt(20**2-(self.x1-self.x)**2)
        except:
            if self.ang != 1:
                self.ang=1
                self.x1+=10
            else:
                self.ang=0
                self.x1+=-10
        if self.ang==1:
            self.y1=self.y+sqrt(20**2-(self.x1-self.x)**2)
        else:
            self.y1=self.y-sqrt(20**2-(self.x1-self.x)**2)

    def ed(self):
        try:
            self.y1=self.y+sqrt(20**2-(self.x1-self.x)**2)
        except:
            if self.ang==0:
                self.ang=1
                self.x1+=-10
            else:
                self.ang=0
                self.x1+=10
        if self.ang==1:
            self.y1=self.y+sqrt(20**2-(self.x1-self.x)**2)
        else:
            self.y1=self.y-sqrt(20**2-(self.x1-self.x)**2)


    def haut(self,event):
        self.x2,self.y2=self.x,self.y
        if self.x1<280 and self.y1<280 and self.x1>20 and self.y1>20 :
            self.can.coords(self.joueur,self.x1-10,self.y1-10,self.x1+10,self.y1+10)
            self.x,self.y=self.x1,self.y1
            self.x1,self.y1=2*self.x-self.x2,2*self.y-self.y2
            self.can.coords(self.t,self.x,self.y,self.x1,self.y1)


    def bas(self,event):
        self.x2,self.y2=2*self.x-self.x1,2*self.y-self.y1
        if self.x<280 and self.y<280 and self.x>20 and self.y>20 :
            self.can.coords(self.joueur,self.x2-10,self.y2-10,self.x2+10,self.y2+10)
            self.x1,self.y1=self.x,self.y
            self.x,self.y= self.x2,self.y2
            self.can.coords(self.t,self.x,self.y,self.x1,self.y1)
        
        

Move = move()


De plus, je me demandais comment je pourrais faire pour permettre la rotation du cercle en même temps que le déplacement de celui ci

Merci d'avance elnabo
Afficher la suite 

5 réponses

Meilleure réponse
Messages postés
6
Date d'inscription
vendredi 8 septembre 2006
Statut
Membre
Dernière intervention
29 janvier 2010
3
Merci
Bonjour,
Je viens de jeter un coup d'œil à ton code, j'ai trouvé ton idée assez marrante.
Voici quelques idée en vrac:

-En général j'essaye d'éviter le from truk import *. ça va bien pour les petits programme, mais c'est vite le bordel dans des projet plus conséquent.
-Il n'y a aucun commentaire dans ton code, c'est parfois bien utile.
-Je remarque qu'il y a beaucoup de valeurs numériques. Le jours ou t'as envies de mettre un canvas de 500*350 il faut aller bidouiller un peu partout dans ton code. Je pense que tu peux mettre les valeurs taille du canvas, déplacement de l'angle et longueur du déplacement dans le __init__(), (tu peux bien sûr en rajouter, taille du cercle...). Après t'as plus qu'à choisir tes valeurs lorsque tu instancies t'as classe, c'est quand même le bute de POO.
-Je remarque beaucoup de redondance dans ton code, notamment dans les méthodes haut, bas et droite, gauche. Il doit y avoir moyen de les combiner en une seule méthode en passant un argument lors du bind grâce à une fonction lambda, ou tout simplement en "bindant" uniquement <KeyPress>.
-Il est plutôt d'usage de mettre une majuscule pour les noms de classes
-Tu peux remplacer
if self.x1<280 and self.y1<280 and self.x1>20 and self.y1>20 :

par
if 20<self.x1<280 and 20<self.y1<280:

-Je ne suis pas très fort en math, mais il m'a semblé que la trigonométrie était plus approprié pour ce genre de chose.
-Je ne suis pas sûr qu'il soit nécessaire de stoker les coordonnées du joueur, il vaut mieux les récupérer avec .coords().
-tu peux utiliser la méthode .move pour déplacer ton joueur. Tu peux même mettre un tags identique au rond et au trait pour les déplacer en même temps.
-j'ai remarquer deux petits problème dans le fonctionnement de ton applications: le trait est plus long au départ, puisque tu démarres à -20, -20, d'après pythagore ça fait 28.28 alors qu'il fait 20 par la suite. Il y a également un problème dans le changement des angles, le trait ce déplace parfois de 45° et parfois de 15°. J'ai pas regardé la cause du problème.

Bon trève de bacardage, je me suis amusé à mettre en œuvre mes conseils:
# -*- coding: utf-8 -*-
import Tkinter as tk
from math import cos, sin, pi


class Move:
def __init__(self, width=300, height=300, precisionAngle=12, moveBy=5, rayonJoueur=10, directionLen=20, xDepart=100, yDepart=100):
fen = tk.Tk()
#La valeur avec laquelle on incrémentera l'angle
self.incrAng = (2*pi) / precisionAngle
#le "pas" de déplacement
self.moveBy = moveBy
#longueur du trait
self.directionLen = directionLen
#la valeur de l'angle en cours
self.ang = 0
#le x et y maximum du joueur pour ne pas sotir du canevas
self.maxX = width - self.directionLen
self.maxY = height - self.directionLen

self.can = tk.Canvas(fen, width=width, height=height, bg='dark grey')
self.can.pack()
self.joueur = self.can.create_oval(xDepart-rayonJoueur, 
yDepart-rayonJoueur, xDepart+rayonJoueur, yDepart+rayonJoueur, fill='yellow', tags="joueur")
self.direction = self.can.create_line(xDepart, yDepart, xDepart+self.directionLen, yDepart, fill='red', tags="joueur")
self.can.bind_all("<KeyPress>", self.onKeyPress)
fen.mainloop()


def onKeyPress(self, event):
key = event.keysym
if key == "Right":
self.moveDirection(1)
elif key == "Left":
self.moveDirection(-1)
elif key == "Up":
self.moveJoueur(1)
elif key == "Down":
self.moveJoueur(-1)

def moveDirection(self, sens):
"""Appelé lorsque que l'utilisateur appuie sur gauche ou droite"""
#calcul le nouvel angle
self.ang = self.ang + self.incrAng * sens
#récupère les coordonnées du début du trait de direction
x, y = self.getCoord()
#calcul les coordonnées de la fin du trait de direction
x1 = x + cos(self.ang) * self.directionLen
y1 = y + sin(self.ang) * self.directionLen
#affiche le nouveau trait de direction
self.can.coords(self.direction, x, y, x1, y1)

def moveJoueur(self, sens):
"""Appelé lorsque que l'utilisateur appuie sur haut ou bas"""
#calcul le vecteur de déplacement
xMove = cos(self.ang) * self.moveBy
yMove = sin(self.ang) * self.moveBy
#si je joueur ne sort pas du canvas, déplace le joueur
if self.verifZone(xMove*sens, yMove*sens):
self.can.move("joueur", xMove*sens, yMove*sens)

def verifZone(self, xMove, yMove):
"""vérifie si le joueur sort de la zone"""
#récupère les coordonnées du joueur
x, y = self.getCoord()
#coordonnée du joueur après déplacement
newX, newY = x + xMove, y + yMove
#si le joueur ne sort pas du canevas après déplacement
if self.directionLen<newX<self.maxX and self.directionLen<newY<self.maxY:
return True
else:
return False

def getCoord(self):
"""retourne les coordonnées du centre du joueur"""
return self.can.coords(self.direction)[:2]


Move(300, 200, 24, 3)


Pour changer l'angle en même temps que le joueur se déplace ça semble plus compliqué, il faudrait pouvoir désactiver la répétition des touches.Je me pencherai dessus une autre fois.

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources 188 internautes nous ont dit merci ce mois-ci

Commenter la réponse de nyko77
Messages postés
6
Date d'inscription
vendredi 8 septembre 2006
Statut
Membre
Dernière intervention
29 janvier 2010
3
Merci
La méthode .move() n'assigne pas des coordonnées, mais déplace un objet de x et y.
Prenons un exemple:
Ton joueur est situé aux coordonnées x=50 et y=100.
puis tu exécutes self.can.move("joueur", 10, 20),
ton joueur se situe alors aux coordonnées x=60 et y=120.
Puisque le cercle et le trait on le tag "joueur", les 2 se déplacent en même temps.

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources 188 internautes nous ont dit merci ce mois-ci

Commenter la réponse de nyko77
Messages postés
28
Date d'inscription
vendredi 7 août 2009
Statut
Membre
Dernière intervention
2 mai 2016
0
Merci
Et bien merci pour cette réponse structuré. Visiblement ça m'a l'air plus pratique.

En fait pour la rotation , je ne me servais uniquement de l'équation d'un cercle pour calculer les coordonnées du point y en fonction du point x que j'incrémentais. Et de ce fait la rotation n'était pas forcement régulière.

Je vais regarder grossièrement tes idées et conseils ce soir, mais je regarderais le plus gros à tête reposée ce Week-End

Encore merci Elnabo
Commenter la réponse de elnabo
Messages postés
28
Date d'inscription
vendredi 7 août 2009
Statut
Membre
Dernière intervention
2 mai 2016
0
Merci
Voila, j'ai tout bien regardé et j'avoue que c'est plus pratique, plus simple et plus régulier que ma première version.

En plus j'ai compris l'usage de Tkinter sans avoir à charger toutes ces fonctions.

Par contre, j'aurais une question à propos de l'utilisation des tags.
J'ai cru comprendre qu'ils permettaient d'effectuer une/des opération(s) sur plusieurs objet en même temps. Par contre je ne comprends pas pourquoi cette ligne de code permet de modifier quatre coordonnées:
self.can.move("joueur", xMove*sens, yMove*sens)
Commenter la réponse de elnabo
Messages postés
28
Date d'inscription
vendredi 7 août 2009
Statut
Membre
Dernière intervention
2 mai 2016
0
Merci
D'accord merci bien
Commenter la réponse de elnabo