IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 Java Discussion :

Construire une grille de jeu


Sujet :

Java

  1. #1
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2013
    Messages
    77
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2013
    Messages : 77
    Points : 49
    Points
    49
    Par défaut Construire une grille de jeu
    Salut,

    je suis en train de programmer un jeu qui nécessite un plateau de jeu (une grille quoi). Cependant je ne sais pas quelle est la manière la plus judicieuse de coder ça.
    J'ai une classe Plateau qui étend JPanel , ainsi qu'une classe Case et Pion qui étendent aussi de JPanel. J'ai alors opté pour un tableau de Case à deux dimensions que j'ai mis dans un GridLayout dans Plateau. Cependant je trouve cette méthode lourde car beaucoup de JPanel sont crées (le plateau peut avoir une taille max de 20x20) ... sachant aussi que j'aimerai pouvoir déplacer mes objets Pions sur le plateau avec une animation de déplacement.

    J'ai aussi pensé a dessiner un grillage en redefinissant paintComponent(Graphics g), cependant cette méthode me semble un peu "abstraite" vu que c'est finalement juste visuel , on ne peut pas vraiment interagir avec..

    Quelle serait finalement la meilleur méthode pour mes besoins ?
    merci.

  2. #2
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Salut,

    On peut coder l'affichage en SWING d'un plateur de type tableau de cases (damier, échiquier, etc...) avec des composants SWING (tes que des JPanel, des JLabel, des Canvas, etc...), placés dans un JPanel. Le nombre ne pose pas vraiment de problème tant qu'on reste dans certaines limites. Aucun problème pour faire 10x10 cases. J'ai jamais vraiment fait de tests avec beaucoup plus, mais pour avoir fait des interfaces graphiques d'applications professionelles ent SWT avec des centaines de composants, voire des milliers, je ne pense pas que ça soit vraiment un problème de le faire en SWING. C'est sûr qu'il y a toujours une limite.

    Ensuite, personnellement, je trouve que pour faire des jeux, il devient souvent très vite intéressant d'abandonner cette méthode pour faire un système qui dessine directement dans un Canvas, ou un JPanel, donc en redéfinissant paintComponent() (ou paint() pour Canvas). Bien sûr cela oblige à redéfinir un minimum de choses pour reproduire l'interaction (rien de très complexe) qu'on peut avoir avec un système à la composants SWING, mais la gestion de l'emplacement des éléments, les possiblités graphiques étendues, sont beaucoup plus pratiques dès qu'on veut des graphismes un peu évolués (en particulier grâce aux Composites les transformées affines, le cliping, les Shape (et en particulier les Path2D ou les Area), etc.), ou des animations.

    Les possibilités d'agencement avec les LayoutManagers sont souvent très formatées pour faire des UI qui ne sont pas vraiment celles des jeux. On se retrouve donc, lorsqu'on fait des jeux, à devoir faire plein de code supplémentaire pour que les graphismes soient satisfaisants, et on peut même être très restreint et ne pas pouvoir faire tout ce qu'on veut, ou le faire avec moins de facilités que par dessin direct. Au final, autant refaire son propre système, car on a tellement de code à soi, et on utilise finalement que très peu de code des composants SWING : en faisant ses propres composants, on a des composants plus légers qui font exactement ce qu'on veut. Il y a probablement des bibliothèques de base qui permettent de le faire. Je n'en connais pas spécifiquement pour faire des jeux, mais j'en utilise une pour faire une ZUI dans une application professionelle (Piccolo2D) qui est infiniment plus pratique que SWING, et permet de faire des zooms, des rotations, des animations et pleins d'autres choses, qui demanderaient beaucoup de travail en SWING. Cette bibliothèque pourrait être utilisée sans problème pour faire des jeux de type plateaux.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  3. #3
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2013
    Messages
    77
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2013
    Messages : 77
    Points : 49
    Points
    49
    Par défaut
    Merci pour cette réponse enrichissante.
    Je pense me diriger vers la premiere solution qui me semble etre la plus adaptée car le jeu est assez basique.

    Cependant si je redefinissais la méthode paintComponent(), je me demandais comment je pourrai gérer la taille des cases de la grille quand la fenetre du jeu change de taille vu qu'il ny'a plus de layout, et aussi comment faire pour avoir un système de coordonnées plus "simple" (par exemple la premiere case serait (0,0), celle de droite (0,1) au lieu d'utiliser les coordonnées absolues, ce qui me semble compliquer pour gérer le placement des objets)
    ?

  4. #4
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par tamerla Voir le message
    Merci pour cette réponse enrichissante.
    Je pense me diriger vers la premiere solution qui me semble etre la plus adaptée car le jeu est assez basique.

    Cependant si je redefinissais la méthode paintComponent(), je me demandais comment je pourrai gérer la taille des cases de la grille quand la fenetre du jeu change de taille vu qu'il ny'a plus de layout,
    Le fait qu'il y ait plus de layout implique juste qu'on a le gérer soi-même : ensuite ça dépend de ce qu'on veut faire :

    • On peut avoir un plateau dont la taille s'ajuste à taille de la fenêtre : l'échelle d'affichage dépend de la taille de la fenêtre,
    • ou on verra plus ou moins de cases selon la taille de la fenêtre
    • Ou c'est les éléments autour du plateau qui varient en fonction de la taille de la fenêtre, affichant plus ou moins d'informations, à différents endroits, selon la place disponible
    • un combinaison des trois précédents, avec une échelle maximum,




    Citation Envoyé par tamerla Voir le message
    et aussi comment faire pour avoir un système de coordonnées plus "simple" (par exemple la premiere case serait (0,0), celle de droite (0,1) au lieu d'utiliser les coordonnées absolues, ce qui me semble compliquer pour gérer le placement des objets)
    ?
    Là, je pense ne pas comprendre ce que tu veux dire, parce que je comprends que tu veux parler de passer d'un système de coordonnées dans le tableau 2D à un système de coordonnées graphiques 2D.

    Pour un nombre de cases fixes : Or, ça se fait pas division entière tout simplement. Pour un plateau plus grand que l'écran (et scrolling), on prendra une base de taille (par exemple une échelle nominal qui dit à l'échelle 1, on doit voir tant de cases (ou une case a telle taille métrique), quelque soit la taille et la résolution de l'écran, ce qui permet de définir une échelle standard.

    A moins que tu parles de passer de coordonnées linéaires 1D à un système de coordonnées 2D et vice versa :
    • y = index / nb en largeur (division entière)
      x = index reste de la division entière y / nb en largeur (modulo)
    • index = y * nb en largeur + x
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  5. #5
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2013
    Messages
    77
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2013
    Messages : 77
    Points : 49
    Points
    49
    Par défaut
    Merci pour ces infos , elles me seront surement utiles bientot .

    Par contre j'ai une question par rapport à mon projet, j'utilise donc un tableau[][] de JPanel qui se trouvent dans un JPanel et un GridLayout pour agencer tout ça.
    J'imagine bien que c'est pas la meilleure idée mais c'est celle qui me paraissait le plus simple pour faire une grille pour un jeu simple. Cependant je suis confronté à un problème car j'aimerai pouvoir réaliser une sorte d'animation de déplacement, pour cela j'ai essayé de déplacer mes Pions JPanel sur le tableau mais rien à faire ca ne fonctionne pas en modifiant les coordonnées absolues.

    J'ai laissé tomber cette idée et j'ai essayé de dessiner mes Pions avec paintComponent() (en ajoutant une image), là j'arrive a déplacer mes pions en modifiant leurs attributs x, y dans une boucle et avec repaint() pour les redessiner, cependant mes pions n'apparaissent plus dans les cases du tableau mais derrière le tableau ...(je sais pas si je suis clair).
    Je m'y prends mal surement mais j'aimerai pouvoir concilier mon tableau de JPanel dans un gridLayout avec mes Pions qui sont aussi des JPanel et que j'aimerai pouvoir déplacer par une animation et pas seulement les supprimer pour les ajouter dans une autre case.
    merci (je peux mettre du code si jamais ce n'est pas clair).

  6. #6
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par tamerla Voir le message
    Cependant je suis confronté à un problème car j'aimerai pouvoir réaliser une sorte d'animation de déplacement, pour cela j'ai essayé de déplacer mes Pions JPanel sur le tableau mais rien à faire ca ne fonctionne pas en modifiant les coordonnées absolues.
    C'est tout-à-fait normal : un LayoutManager contrôle les bounds (position et dimensions) de chaque composant. Donc tout ce que tu peux faire en modifiant toi-même la position ou les dimensions sera "annulé" par le LayoutManager.

    Citation Envoyé par tamerla Voir le message
    J'ai laissé tomber cette idée et j'ai essayé de dessiner mes Pions avec paintComponent() (en ajoutant une image), là j'arrive a déplacer mes pions en modifiant leurs attributs x, y dans une boucle et avec repaint() pour les redessiner, cependant mes pions n'apparaissent plus dans les cases du tableau mais derrière le tableau ...(je sais pas si je suis clair).
    Il faut redéfinir paintChildren() au lieu de paintComponent()

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    public class Dammier extends JPanel {
     
    	public Dammier() {
    		super(new GridLayout(0, 10));
    		for (int i = 0; i < 10; i++) {
    			for (int j = 0; j < 10; j++) {
    				JPanel panel = new JPanel();
    				if (j % 2 == (i % 2 == 0 ? 0 : 1)) {
    					panel.setBackground(Color.WHITE);
    				} else {
    					panel.setOpaque(false);
    				}
    				add(panel);
    			}
    		}
    	}
     
    	@Override
    	protected void paintComponent(Graphics g) {
    		super.paintComponent(g);
    		int w = getWidth() / 2;
    		int h = getHeight() / 2;
    		g.setColor(Color.RED);
    		g.fillRect(0, 0, w, h);
    	}
     
    	@Override
    	protected void paintChildren(Graphics g) {
    		super.paintChildren(g);
    		int w = getWidth() / 2;
    		int h = getHeight() / 2;
    		g.setColor(Color.GREEN);
    		g.fillRect(w, h, w, h);
    	}
     
    	public static void main(String[] args) {
    		SwingUtilities.invokeLater(() -> run());
    	}
     
    	private static void run() {
    		JFrame frame = new JFrame("Démo");
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
    		JPanel mainPanel = new Dammier();
     
    		frame.getContentPane().add(mainPanel);
     
    		frame.setSize(300, 300);
    		frame.setLocationRelativeTo(null);
    		frame.setVisible(true);
    	}
     
    }


    Citation Envoyé par tamerla Voir le message
    Je m'y prends mal surement mais j'aimerai pouvoir concilier mon tableau de JPanel dans un gridLayout avec mes Pions qui sont aussi des JPanel et que j'aimerai pouvoir déplacer par une animation et pas seulement les supprimer pour les ajouter dans une autre case.
    merci (je peux mettre du code si jamais ce n'est pas clair).
    Tu peux aussi utiliser les GlassPane, ou les JLayer.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  7. #7
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2013
    Messages
    77
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2013
    Messages : 77
    Points : 49
    Points
    49
    Par défaut
    Ahh merci je connaissais pas l'existence de paintChildren().. ca a réglé mon problème d'affichage .

    J'aurai une dernière (normalement) question par rapport au déplacement dans la grille :

    J'ai par exemple un pion dans la case (0,1) et j'aimerai qu'il se déplace progressivement à l'endroit où la personne a cliqué. Voilà ce que j'ai fait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
     
    public double calculDistance(int a, int b) {
    	          return Math.sqrt(((a-this.x)*(a-this.x))+((b-this.y)*(b-this.y)));
    }
     
    public void move(int a, int b) {
    		 double distance = calculDistance(a, b);
    		 while(distance > 0) {
    			double directionX = a-this.x;
    			double directionY = b-this.y;	
    			double longueurDirection = Math.sqrt(directionX*directionX+directionY*directionY);
    			double normalizeX = directionX/longueurDirection;
    			double normalizeY = directionY/longueurDirection;
    			double translationX = normalizeX;
    			double translationY = normalizeY;
    			this.x += normalizeX;
    			this.y += normalizeY;
    			repaint();
    			distance = distance-(Math.sqrt(translationX*translationX+translationY*translationY));
    			System.out.println(distance);
    			try {
    				Thread.sleep(50);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		}
    }
    En gros je calcule la distance entre les deux points (entre l'objet a deplacer et le clique de souris) , je calcule la direction et je la normalise et j'incrémente avec ça le this.x et this.y . Cela marche a peu près, cependant comment faire pour que, si je clique sur n'importe quel endroit à l'intérieur d'une case (JPanel) de mon tableau[][] de JPanels , le pion se place au centre de celui - ci , est ce possible ?

  8. #8
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Si tu peux déplacer un pion depuis un point (x0, y0) vers un point (x,y) qui correspond au point cliqué par la souris, tu peux déplacer de (x0, y0) à un point (x1, y1) où x1 et y1 sont calculés.

    Il te suffit donc de calculer les coordonnées du centre de la case cliqué :

    Code pseudocode : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    (x,y) = coordonnées du point cliqué
    convertir (x,y) en (i, j) coordonnées de la case
    convertir (i,j) en (x1, y1) le centre de la case, donc le centre du rectangle de pixels correspondant à la case (i, j)

    Pour faire ça, il te faut connaitre les bounds de la case : on peut les obtenir directement sur le JPanel, avec getBounds(), qui te renvoit un Rectangle. Les bounds sont relatif au container.

    Ensuite, le (x,y) de la souris est toujours relatif au composant source du clic. Si le MouseListener est sur la JPanel de la case, tu sais directement quel JPanel est cliqué, donc ses bounds. Pour déterminer son centre, on peut le calculer simplement ( xcentre = x + width/2, ycentre = y + height/2, avec x et y les coordonnées du point haut gauche du panel), ou utiliser directement les méthodes getCenterX() et getCenterY() de Rectangle.

    Si le MouseListener est sur le container, le (x,y) de la souris est relatif au container, et on peut retrouver la case par division entière : le i de la case est x / largeur d'une case, et le j de la case y / hauteur d'une case. Comme toutes ces coordonnées sont des entiers, la division est entière directement.

    On retrouve les coordonnées d'une case i1,j1, par multiplication par la largeur et la hauteur.

    Sur l'aspect animation, je te conseille de procéder par calcul direct de ce qui reste à faire sur la distance, plutôt que d'incrémenter, parce que tu ne peux être sûr du temps d'exécution de chaque pas, donc tu peux être décalé dans le temps. Ce décalage peut être minime, voir non remarquable sur une animation, mais si tu en as plusieurs, tu peux avoir des écarts entre différents éléments qui devraient être synchrones.

    Le principe est de calculer la distance actuelle par rapport au départ, de faire la distance avec la distance à parcourir, de détermine le temps passé depuis le départ et de déterminer de combien il faut se déplacer ensuite en fonction de la période de pas de déplacement. Cette période sera d'autant plus facile à déterminer si tu utilises un Timer, plutôt qu'un thread avec sleep(). Pour la dernière étape (temps écoulé>temps d'animation), il est intéressant de ne plus procéder par calcul, mais par affectation directe, ce qui évite les décalages dus aux décalages dans le temps : tu es sûr, ainsi, que ton élément est bien à position exacte d'arrivée voulu, et pas un peu à côté (trop loin, ou trop près). Il y a même une vieille bibliothèque fondée sur ce principe si tu veux (TimingFramework).
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  9. #9
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2013
    Messages
    77
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2013
    Messages : 77
    Points : 49
    Points
    49
    Par défaut
    Merci , j'ai enfin réussi a faire ce que je voulais, mais il reste un petit soucis :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    		public int calculCentreCaseX(int a) {
    			int i = (int) (a / pan.tab[0][0].getWidth());
                            int x = i * pan.tab[0][0].getWidth() + (pan.tab[0][0].getWidth() / 2);
    			return x;
     
    		}
     
    		public int calculCentreCaseY(int b) {
    			int j = (int) (b / pan.tab[0][0].getHeight());
                            int y = j * pan.tab[0][0].getHeight() + (pan.tab[0][0].getHeight() / 2);
    			return y;
    		}
     
    		public void move(int a, int b) {
    			int x = calculCentreCaseX(a);
    			int y = calculCentreCaseY(b);
    			double distance = calculDistance(x, y);
     
    			while (distance > 0) {
    				double directionx = x - (this.x + (im.getIconWidth() / 2)); 
    				double directiony = y - (this.y + (im.getIconHeight() / 2));
    				double longueurDirection = Math.sqrt(directionx * directionx
    						+ directiony * directiony);
    				double normalizex = directionx / longueurDirection;
    				double normalizey = directiony / longueurDirection;
    				double translationx = normalizex;
    				double translationy = normalizey;
    				this.x += translationx;
    				this.y += translationy;
    				MoveJLabel.this.repaint();
    				distance = distance - (Math.sqrt(translationx * translationx + translationy
    								* translationy));
    				// System.out.println(distance);
    				try {
    					Thread.sleep(5);
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			}
    J'ai du ajouté à la ligne 20 et 21 (this.x + (im.getIconWidth() / 2)) et (this.y + (im.getIconHeight() / 2)) pour faire en sorte que le this.x et this.y correspondent au centre de l'image, car normalement ils correspondent au top left corner de l'image, or quand j'avance de la case (0,0) a (0,1) le pion va bien se centrer, mais quand je veux retourner a la case (0,0) il ne va pas arriver à ce centrer parfaitement , je ne vois pas pour quelle raison..

    Sur l'aspect animation, je te conseille de procéder par calcul direct de ce qui reste à faire sur la distance, plutôt que d'incrémenter, parce que tu ne peux être sûr du temps d'exécution de chaque pas, donc tu peux être décalé dans le temps. Ce décalage peut être minime, voir non remarquable sur une animation, mais si tu en as plusieurs, tu peux avoir des écarts entre différents éléments qui devraient être synchrones.

    Le principe est de calculer la distance actuelle par rapport au départ, de faire la distance avec la distance à parcourir, de détermine le temps passé depuis le départ et de déterminer de combien il faut se déplacer ensuite en fonction de la période de pas de déplacement. Cette période sera d'autant plus facile à déterminer si tu utilises un Timer, plutôt qu'un thread avec sleep(). Pour la dernière étape (temps écoulé>temps d'animation), il est intéressant de ne plus procéder par calcul, mais par affectation directe, ce qui évite les décalages dus aux décalages dans le temps : tu es sûr, ainsi, que ton élément est bien à position exacte d'arrivée voulu, et pas un peu à côté (trop loin, ou trop près). Il y a même une vieille bibliothèque fondée sur ce principe si tu veux (TimingFramework).
    Je t'avoue que je n'ai pas tout compris à ce passage.. pour l'instant je me suis un peu renseigné sur la classe Timer et je suis déjà perdu !
    J'ai vu qu'il y avait util.Timer et swing.Timer ?? Quelle est la différence (la javadoc ne m'aide pas beaucoup) ?
    Serait-il possible d'avoir un peu plus d'explications ?
    merci

  10. #10
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par tamerla Voir le message
    J'ai du ajouté à la ligne 20 et 21 (this.x + (im.getIconWidth() / 2)) et (this.y + (im.getIconHeight() / 2)) pour faire en sorte que le this.x et this.y correspondent au centre de l'image, car normalement ils correspondent au top left corner de l'image, or quand j'avance de la case (0,0) a (0,1) le pion va bien se centrer, mais quand je veux retourner a la case (0,0) il ne va pas arriver à ce centrer parfaitement , je ne vois pas pour quelle raison..
    C'est-à-dire pas "pas parfaitement" ? Quel est le décalage ? Si c'est de 1 pixel, c'est probablement à cause des approximations de calculs en double : même si mathématiquement, le total des pas de déplacement est égale à la distance totale à l'origine, ce n'est pas forcément le cas informatiquement parlant. C'est pour ça que je parlais de forcer la position au dernier pas, pour compenser le décalage dû aux approximations.

    Citation Envoyé par tamerla Voir le message
    Je t'avoue que je n'ai pas tout compris à ce passage.. pour l'instant je me suis un peu renseigné sur la classe Timer et je suis déjà perdu !
    J'ai vu qu'il y avait util.Timer et swing.Timer ?? Quelle est la différence (la javadoc ne m'aide pas beaucoup) ?
    Serait-il possible d'avoir un peu plus d'explications ?
    merci
    Un timer SWING exécute une action SWING sur le thread SWING (Event Dispatch Thread) : ça te simplifie tout l'aspect accès concurrents (gestion d'états partagés entre le thread d'animation et le thread d'affichage, puisque c'est le même thread). Par contre, ça t'oblige à faire tes calculs dans le thread SWING ce qui va bloquer SWING (donc le rafraichissement de l'affichage entre autre) pendant un petit laps de temps : tout dépend du temps de calcul. Avec un time java.util, le calcul sera fait dans son propre thread, mais il faudra veille à l'aspect concurrence (éviter de modifier l'état partiellement (par exemple en gérant le x et y via la classe Point), ou synchroniser sur la modification de l'éat, et veiller à ce que l'état soit mis à jour le plus rapidement possible pour le thread graphique (voir la notion de volatile)).
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  11. #11
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2013
    Messages
    77
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2013
    Messages : 77
    Points : 49
    Points
    49
    Par défaut
    D'accord merci pour les explications , je connais pas énormément de choses sur les thread donc je vais m'y interesser.

    C'est-à-dire pas "pas parfaitement" ? Quel est le décalage ? Si c'est de 1 pixel, c'est probablement à cause des approximations de calculs en double : même si mathématiquement, le total des pas de déplacement est égale à la distance totale à l'origine, ce n'est pas forcément le cas informatiquement parlant. C'est pour ça que je parlais de forcer la position au dernier pas, pour compenser le décalage dû aux approximations.
    Pas parfaitement dans le sens où quand je "recule" le pion (de la case [0][1] à [0][0] par exemple) , la boucle est déjà terminée avant que le pion ne soit arrivé au centre de la case, je dois cliquer plusieurs fois sur la case pour qu'il arrive enfin au milieu... je ne trouve pas la source du problème.
    De plus parfois le pion se met a trembler une fois arrivé sur la case je sais pas trop pourquoi non plus ......ma méthode move(x,y) n'est pas la plus optimal j'ai l'impression.

  12. #12
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Salut,

    As-tu réglé ton problème ? Vu tes formules un peu compliquées à calculer de tête et fastidieuses à le faire sur papier, tu n'as plus que le debug et les traces pour comprendre pourquoi on atteint la condition de fin de boucle trop tôt.

    Sinon, voici ci-après l'illustration des mes propos précédents :

    • déplacement temps fixe : le temps est en ms. quelque soit la destination, le carré y va en ce temps
    • pas fixe : en 100ème de pixels : quelques soit la case cible, le carré y va en se déplaçant de ce pas à chaque tick


    Le déplacement est adaptable aux modifications de taille de la fenêtre pour avoir un système complet (bien qu'en pratique, personnellement je ne ferais pas comme ça, comme je te l'ai dit, mais par dessin direct dans le contexte graphiques, ce qui me permettrait d'avoir un mouvement dans un repère fixe, en utilisant les transformées affines pour adapter à la taille de la fenêtre.

    J'ai fait ça un peu vite fait et les spinner ont l'air un peu revêche en SWING (et j'ai plutôt l'habitude de travailler en SWT, où ils fonctionnent nettement mieux) : j'ai pas le temps de fignoler cet aspect, donc il faut bien penser à faire entrée pour valider si tu n'utilises pas les flèches, et comme on peut saisir n'importe quoi en dehors des bornes et le spinner continue de l'afficher sans vergogne, attention à ces bornes donc... (15-300 000 pour le time, 1-3 000 pour le pas en 100ème de pixels)

    Les imports à part, au cas où
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    import java.awt.GridLayout;
    import java.awt.Insets;
    import java.awt.Point;
    import java.awt.event.ComponentAdapter;
    import java.awt.event.ComponentEvent;
    import java.awt.event.ComponentListener;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.awt.geom.Point2D;
    import java.awt.geom.Rectangle2D;
    import java.util.Timer;
    import java.util.TimerTask;
     
    import javax.swing.ButtonGroup;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JRadioButton;
    import javax.swing.JSpinner;
    import javax.swing.SpinnerNumberModel;
    import javax.swing.SwingUtilities;


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    public class Dammier extends JPanel {
     
    	public enum AnimType {
    		NO, FIXED_TIME, FIXED_STEP
    	}
     
    	private static final int NBCASES = 10;
     
    	protected static final long DURATION = 500;
    	protected static final long STEPS = 300;
     
    	private static final long RATE = 5;
     
    	private volatile Rectangle2D shape;
     
    	// TODO : on devrait mettre ça dans un objet à part (si on veut pouvoir en bouger plusieurs, il vaudrait mieux)
    	private volatile int currentcase;
    	private volatile boolean move;
     
    	private final Timer timer;
     
    	private volatile TimerTask timerTask;
     
    	private AnimType animType;
    	private long duration;
    	private long step;
     
    	public Dammier() {
    		super(new GridLayout(0, NBCASES,0, 0), true);
    		animType = AnimType.NO;
    		duration=DURATION;
    		step=STEPS;
    		timer=new Timer();
    		setBorder(null);
    		for (int i = 0; i < NBCASES; i++) {
    			for (int j = 0; j < NBCASES; j++) {
    				JPanel panel = new JPanel();
    				if (j % 2 == (i % 2 == 0 ? 0 : 1)) {
    					panel.setBackground(Color.WHITE);
    				} else {
    					panel.setOpaque(false);
    				}
    				final int icase = i*NBCASES+j;
    				panel.setEnabled(true);
    				panel.addMouseListener(new MouseAdapter() {
     
    					@Override
    					public void mouseClicked(MouseEvent e) {
    						if ( e.getButton()== MouseEvent.BUTTON1 ) {
    							switch (animType) {
    							case NO:
    								moveShape(icase);
    								break;
    							case FIXED_TIME:
    								moveShapeFixedTime(icase, duration);
    								break;
    							case FIXED_STEP:
    								moveShapeFixedSpeed(icase, step);
    								break;
    							default:
    								break;
    							}
    						}
    					}
    				});
    				add(panel);
    			}
    		}
    		addComponentListener(new ComponentAdapter() {
    			@Override
    			public void componentResized(ComponentEvent e) {
    				if ( timerTask==null ) {
    					shape = getComponent(currentcase).getBounds().getBounds2D();
    				}
    			}
    		});
    		shape = new Rectangle2D.Double();
    		currentcase=0;
    	}
     
    	public void setAnimType(AnimType animType) {
    		this.animType=animType;
    	}
     
    	public AnimType getAnimType() {
    		return animType;
    	}
     
    	public void setDuration(long duration) {
    		this.duration = duration;
    	}
     
    	public long getDuration() {
    		return duration;
    	}
     
    	public void setStep(long step) {
    		this.step = step;
    	}
     
    	public long getStep() {
    		return step;
    	}
     
    	protected void moveShapeFixedTime(final int target, final long duration) {
    		if ( timerTask==null && target!=currentcase ) {
    			timerTask = new AdaptableTimerTask() {
     
    				private volatile FixedTimeMove fixedTimeMove = new FixedTimeMove(
    						getComponent(currentcase).getBounds().getBounds2D(), 
    						getComponent(target).getBounds().getBounds2D(), 
    						duration,
    						target);
     
    				protected void recompute() {
    					Rectangle2D currentBounds = fixedTimeMove.getCurrentBounds();
    					Rectangle2D bounds = getComponent(currentcase).getBounds().getBounds2D();
    					double sx = bounds.getWidth()/currentBounds.getWidth();
    					double sy = bounds.getHeight()/currentBounds.getHeight();
    					fixedTimeMove = new FixedTimeMove(
    							new Rectangle2D.Double(currentBounds.getCenterX()*sx-bounds.getWidth()/2,
    									currentBounds.getCenterY()*sy-bounds.getHeight()/2,
    									bounds.getWidth(),
    									bounds.getHeight()),
    							getComponent(target).getBounds().getBounds2D(), 
    							fixedTimeMove.getRemainingTime(), 
    							target);
    				}
     
    				@Override
    				public void run() {
    					fixedTimeMove.run();
    				}
     
    			};
    			timer.scheduleAtFixedRate(timerTask, 0, RATE);
    		}
    	}
     
    	protected void moveShapeFixedSpeed(final int target, final long step) {
    		if ( timerTask==null && target!=currentcase ) {
     
    			timerTask = new AdaptableTimerTask() {
     
    				private volatile FixedStepMove fixedStepMove = new FixedStepMove(
    						getComponent(currentcase).getBounds().getBounds2D(), 
    						getComponent(target).getBounds().getBounds2D(), 
    						step,
    						Double.MAX_VALUE,
    						target);
     
    				protected void recompute() {
    					Rectangle2D currentBounds = fixedStepMove.getCurrentBounds();
    					Rectangle2D bounds = getComponent(currentcase).getBounds().getBounds2D();
    					double sx = bounds.getWidth()/currentBounds.getWidth();
    					double sy = bounds.getHeight()/currentBounds.getHeight();
    					fixedStepMove = new FixedStepMove(
    							new Rectangle2D.Double(currentBounds.getCenterX()*sx-bounds.getWidth()/2,
    									currentBounds.getCenterY()*sy-bounds.getHeight()/2,
    									bounds.getWidth(),
    									bounds.getHeight()),
    							getComponent(target).getBounds().getBounds2D(), 
    							step, 
    							fixedStepMove.getRemainingDistance(),
    							target
    							);
    				}
     
    				@Override
    				public void run() {
    					fixedStepMove.run();
    				}
     
    			}; 
     
    			timer.scheduleAtFixedRate(timerTask, 0, RATE);
    		}
    	}
     
    	protected void moveShape(int dest) {
    		cancelPreviousMove();
    		currentcase=dest;
    		shape=getComponent(currentcase).getBounds().getBounds2D();
    		repaint();
    	}
     
    	private void cancelPreviousMove() {
    		if (timerTask!=null) {
    			timerTask.cancel();
    			timerTask=null;
    		}
    	}
     
    	@Override
    	protected void paintChildren(Graphics g) {
    		super.paintChildren(g);
    		g.setColor(Color.GREEN);
    		((Graphics2D)g).fill(shape);
    	}
     
    	private abstract class AdaptableTimerTask extends TimerTask implements ComponentListener {
     
    		public AdaptableTimerTask() {
    			addComponentListener(this);
    		} 
     
    		@Override
    		public boolean cancel() {
    			if( super.cancel() ) {
    				removeComponentListener(this);
    				return true;
    			}
    			else {
    				return false;
    			}
    		}
     
    		@Override
    		public void componentResized(ComponentEvent e) {
    			recompute();
    		}
     
    		@Override
    		public void componentMoved(ComponentEvent e) { 
    		}
     
    		@Override
    		public void componentShown(ComponentEvent e) { 
    		}
     
    		@Override
    		public void componentHidden(ComponentEvent e) { 
    		} 
     
    		protected abstract void recompute();
     
    	}
     
    	private class FixedTimeMove {
     
    		private final long startTime = System.currentTimeMillis();
     
    		private final Point2D.Double startPoint;
    		private final Point2D.Double endPoint;
    		private final long duration;
    		private final Rectangle2D targetBounds;
    		private final int target;
     
    		private final double dx;
    		private final double dy;
     
    		private Rectangle2D currentBounds;
    		private long remainingTime;
     
    		public FixedTimeMove(Rectangle2D startBounds, Rectangle2D endBounds, long duration, int target) {
    			this.duration = duration;
    			this.remainingTime = duration;
    			this.startPoint = new Point2D.Double(startBounds.getCenterX(), startBounds.getCenterY());
    			this.endPoint = new Point2D.Double(endBounds.getCenterX(), endBounds.getCenterY()); 
    			double timeStep = duration/RATE;
    			dx = computePixelStep(endPoint.getX()-startPoint.getX(), timeStep);
    			dy = computePixelStep(endPoint.getY()-startPoint.getY(), timeStep);
    			currentBounds = startBounds;
    			targetBounds = endBounds;
    			this.target = target;
    		}
     
    		 public final Rectangle2D getCurrentBounds() {
    			return currentBounds;
    		}
     
    		public final long getRemainingTime() {
    			return remainingTime;
    		}
     
    		public void run() {
    			final long time = System.currentTimeMillis();
    			long elapsedTime = time-startTime;
    			if ( elapsedTime<=duration) {
    				remainingTime = duration - elapsedTime;
    				currentBounds= new Rectangle2D.Double(currentBounds.getX()+dx, currentBounds.getY()+dy, currentBounds.getWidth(), currentBounds.getHeight());
    				shape=currentBounds;
    			}
    			else {
    				remainingTime = 0;
    				cancelPreviousMove();
    				currentcase = target;
    				shape=targetBounds;
    			}
    			repaint();
    		}
     
    		private double computePixelStep(double distance, double step) {
    			distance /= step;
    			if ( distance==java.lang.Double.NaN ) {
    				distance=0;
    			}
    			return distance;
    		}
     
    	}
     
    	private class FixedStepMove {
     
    		private final Point2D.Double startPoint;
    		private final Point2D.Double endPoint;
    		private final double step;
    		private final Rectangle2D targetBounds;
    		private final int target;
     
    		private final double dx;
    		private final double dy;
     
    		private final double distance;
     
    		private volatile double remainingDistance;
    		private volatile Rectangle2D currentBounds;
     
    		public FixedStepMove(Rectangle2D startBounds, Rectangle2D endBounds, long step, double remainingDistance, int target) {
    			this.step = step/100.0; // 100ème pixels
    			this.startPoint = new Point2D.Double(startBounds.getCenterX(), startBounds.getCenterY());
    			this.endPoint = new Point2D.Double(endBounds.getCenterX(), endBounds.getCenterY());
    			distance = startPoint.distance(endPoint);
    			dx = computePixelStep(endPoint.getX()-startPoint.getX(), distance, this.step);
    			dy = computePixelStep(endPoint.getY()-startPoint.getY(), distance, this.step);
    			currentBounds = startBounds;
    			targetBounds = endBounds;
    			this.target = target;
    			this.remainingDistance = Math.min(remainingDistance, distance);
    		}
     
    		public Rectangle2D getCurrentBounds() {
    			return currentBounds;
    		}
     
    		public double getRemainingDistance() {
    			return remainingDistance;
    		}
     
    		private double computePixelStep(double dist, double distance, double step) {
    			return step * (dist/distance); // Thales
    		}
     
    		public void run() {
     
    			double nextX = currentBounds.getX()+dx;
    			double nextY = currentBounds.getY()+dy;
    			double distance = Point.distance(currentBounds.getX(), currentBounds.getY(), nextX, nextY);
    			remainingDistance -= distance;
     
    			if ( remainingDistance>0 ) {
    				currentBounds= new Rectangle2D.Double(nextX, nextY, currentBounds.getWidth(), currentBounds.getHeight());
    				shape=currentBounds;
    			}
    			else {
    				cancelPreviousMove();
    				currentcase = target;
    				shape=targetBounds;
    			}
    			repaint();
     
    		}
     
    	} 
     
    	public static void main(String[] args) {
    		SwingUtilities.invokeLater(() -> run());
    	}
     
    	private static void run() {
    		JFrame frame = new JFrame("Démo");
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
    		JPanel mainPanel = new JPanel(new BorderLayout());
     
    		JPanel configPanel = new JPanel(new GridBagLayout());
     
    		JRadioButton buttonNoAnim = new JRadioButton("Pas d'animation");
    		configPanel.add(buttonNoAnim, new GridBagConstraints(0, 0, 2, 1, 1, 0, GridBagConstraints.BASELINE_LEADING, GridBagConstraints.BOTH, new Insets(1,1,1,1), 0, 0));
     
    		JRadioButton buttonFixedTime = new JRadioButton("Temps fixe (ms)");
    		configPanel.add(buttonFixedTime, new GridBagConstraints(0, 1, 1, 1, 0, 0, GridBagConstraints.BASELINE_LEADING, GridBagConstraints.BOTH, new Insets(1,1,1,1), 0, 0));
            JSpinner timeSpinner = new JSpinner(new SpinnerNumberModel(DURATION, 15, 300000, 100));
    		configPanel.add(timeSpinner, new GridBagConstraints(1, 1, 1, 1, 1, 0, GridBagConstraints.BASELINE_TRAILING, GridBagConstraints.BOTH, new Insets(1,1,1,1), 0, 0));
     
    		JRadioButton buttonFixedStep = new JRadioButton("Pas fixe (100ème px)");
    		configPanel.add(buttonFixedStep, new GridBagConstraints(0, 2, 1, 1, 0, 0, GridBagConstraints.BASELINE_LEADING, GridBagConstraints.BOTH, new Insets(1,1,1,1), 0, 0));
            JSpinner stepSpinner = new JSpinner(new SpinnerNumberModel(STEPS, 1, 300, 1));
    		configPanel.add(stepSpinner, new GridBagConstraints(1, 2, 1, 1, 1, 0, GridBagConstraints.BASELINE_TRAILING, GridBagConstraints.BOTH, new Insets(1,1,1,1), 0, 0));
     
    		ButtonGroup group = new ButtonGroup();
    		group.add(buttonNoAnim);
    		group.add(buttonFixedTime);
    		group.add(buttonFixedStep);
     
    		Dammier dammier = new Dammier();
     
    		buttonNoAnim.addActionListener(e-> dammier.setAnimType(AnimType.NO));
    		buttonFixedTime.addActionListener(e-> dammier.setAnimType(AnimType.FIXED_TIME));
    		buttonFixedStep.addActionListener(e-> dammier.setAnimType(AnimType.FIXED_STEP));
     
    		timeSpinner.addChangeListener(e-> dammier.setDuration(((java.lang.Double)timeSpinner.getValue()).longValue()));
    		stepSpinner.addChangeListener(e-> dammier.setStep(((java.lang.Double)stepSpinner.getValue()).longValue()));
     
    		switch (dammier.getAnimType()) {
    		case NO:
    			buttonNoAnim.setSelected(true);
    			break;
    		case FIXED_TIME:
    			buttonFixedTime.setSelected(true);
    			break;
    		case FIXED_STEP:
    			buttonFixedStep.setSelected(true);
    			break;
    		default:
    			break;
    		}
     
     
    		mainPanel.add(dammier, BorderLayout.CENTER);
    		mainPanel.add(configPanel, BorderLayout.SOUTH);
     
    		frame.getContentPane().add(mainPanel);
     
    		frame.setSize(300, 300);
    		frame.setLocationRelativeTo(null);
    		frame.setVisible(true);
    	}
     
    }
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  13. #13
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2013
    Messages
    77
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2013
    Messages : 77
    Points : 49
    Points
    49
    Par défaut
    Salut,

    Je n'ai pas réussi à régler le problème, mais de toute façon c'était assez mauvais alors j'ai simplement utilisé une fonction affine pour représenter la droite qui passe par le pion et le clique pour pouvoir déplacer le pion meme si ce n'est pas encore parfait.
    En tout cas merci de ton aide j'ai appris pleins de trucs , je mets en résolu.

    ps: je n'ai pas réussi a compiler ta solution car il y a des symboles que mon eclipse ne connait pas (qu 'est ce que " -> " ?)

  14. #14
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par tamerla Voir le message
    ps: je n'ai pas réussi a compiler ta solution car il y a des symboles que mon eclipse ne connait pas (qu 'est ce que " -> " ?)
    C'est parce qu'elle est en Java8 : le -> c'est l'opérateur d'expression lambda (une nouveauté de Java8).

    Tu peux convertir facilement le code en Java7 (mais je te conseille plutôt d'installer Java8) :

    1. partout où tu vois un truc du genre : buttonNoAnim.addActionListener(e-> dammier.setAnimType(AnimType.NO));, tu le remplace par

      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      buttonNoAnim.addActionListener(
      new ActionListener() {
       
          public void actionPerformed(ActionEvent e ) {
             dammier.setAnimType(AnimType.NO);
          }
      }
      );
      Donc en gros : tu regardes la classe de l'argument attendu à la place de l'expression du type machin -> truc (par la complétion, c'est facile). Tu coupes l'expression, tu tapes new et par la complétion tu devrais avoir automatiquement le nom de la classe, puis tu demandes la création automatique de la classe dans l'IDE. Tu copier la partie après la flêche dans la méthode qui se créé, et tu veille à ce que les arguments de la méthode ait le bon nom.
    2. quand tu auras traité toutes les expressions lambdas, tu auras encore (peut-être) des erreurs de compilation : ce sont les effectively finals. On est plus obligé en Java8 de mettre systématique final pour utiliser une variable du scope local dans une classe anonyme, tant que la valeur de la variable n'est jamais modifiée. Il suffit d'ajouter final devant chaque variable
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Génération d'une grille puzzle pour un jeu vidéo avec gestion de difficulté
    Par CaNiBaLe dans le forum Algorithmes et structures de données
    Réponses: 1
    Dernier message: 04/07/2014, 16h49
  2. Utilisation de gtkada pour une grille de jeu
    Par Anastasia dans le forum Ada
    Réponses: 0
    Dernier message: 08/05/2009, 11h14
  3. Reseter une grille de jeu
    Par olihya dans le forum Débuter avec Java
    Réponses: 1
    Dernier message: 26/01/2009, 14h40
  4. Construire graphiquement une grille
    Par benoth08 dans le forum AWT/Swing
    Réponses: 10
    Dernier message: 21/01/2007, 23h30

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo