KeyListener & déplacement de sprite

Résolu
Jyhem2000 Messages postés 9 Date d'inscription dimanche 21 mai 2006 Statut Membre Dernière intervention 1 juillet 2009 - 19 juin 2009 à 13:49
Jyhem2000 Messages postés 9 Date d'inscription dimanche 21 mai 2006 Statut Membre Dernière intervention 1 juillet 2009 - 1 juil. 2009 à 16:48
Bonjour,

J'ai un probleme de déplacement de sprite dans un jeu, problème que je retrouve cependant dans bcp de jeu java que je trouve sur le net en open source...

Voici le code du jeu que j'ai essayé d'alléger au maximum.
J'ai gardé les missiles car le problème est flagrant : quand on tire un missile en mouvement (avec la barre espace), le vaisseau s'arrête de bouger. On voit dans les logs que la touche de déplacement a été relâchée alors que ce n'est pas le cas. Niveau gameplay c'est pas terrible

Image vaisseau : [url]http://zepload.com/images/1245316524_craft.png/url
Image missile : [url]http://zepload.com/images/1245316548_missile.png/url

Classe RType :
import java.awt.Color;
import javax.swing.JFrame;

public class RType extends JFrame {
    
    // Constructeur
    // -------------------------------------------
    public RType() {
        add(new Board());
        
        setSize(400,300);
        setTitle("R-Type");
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true); }
    
    
    
    // Méthode main()
    // -------------------------------------------
    public static void main(String[] arg) {
        new RType(); }

}

Classe Crat :
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import javax.swing.ImageIcon;

public class Craft {
    
        private String craft = "craft.png";
        private Image image;
        private int dx,    dy,    x, y, craftHeight, craftWidth, speed;
        private ArrayList missiles;
        private Boolean
            depLeft = false,
            depRight = false,
            depUp = false,
            depDown = false;

                
        // Constructeur
        // -------------------------------------------
        public Craft() {
            // Récupération de l'image du vaisseau
            image = new ImageIcon(getClass().getResource(craft)).getImage();
            // Récupération de tailles
            craftWidth = image.getWidth(null);
            craftHeight = image.getHeight(null);
            
            // Tableau des missiles
            missiles = new ArrayList();
            
            // Position de départ et vitesse
            speed = 1;
            x = 40;
            y = 60; }
            
                
        // Méthode move()
        // -------------------------------------------
        public void move() {
            // Déplacement
            x += dx;
            y += dy;
            
            // Ne pas dépasser les bords
            if (x < 1) x = 1;
            if (y <1 ) y = 1;
            if (x > 370) x = 370;
            if (y > 250) y = 250; }
        
        
        // Touches appuyées
        // -------------------------------------------
        public void keyPressed(KeyEvent e) {
            // Récupération de la touche enfoncée
            int key = e.getKeyCode();
            
            // Actions
            switch (key) {
                case KeyEvent.VK_LEFT :
                    depLeft = true;
                    break;
                case KeyEvent.VK_RIGHT :
                    depRight = true;
                    break;
                case KeyEvent.VK_UP :
                    depUp = true;
                    break;
                case KeyEvent.VK_DOWN :
                    depDown = true;
                    break; }
            
            // MAJ
            update(); }
        
        
        // Touches relâchées
        // -------------------------------------------
        public void keyReleased(KeyEvent e) {
            // Récupération de la touche relâchée
            int key = e.getKeyCode();
            
            // Actions & MAJ
            switch (key) {
                case KeyEvent.VK_SPACE :
                    fire();
                    break;
                case KeyEvent.VK_LEFT :
                    depLeft = false;
                    System.out.println("Left released");
                    break;
                case KeyEvent.VK_RIGHT :
                    depRight = false;
                    System.out.println("Right released");
                    break;
                case KeyEvent.VK_UP :
                    depUp = false;
                    System.out.println("Up released");
                    break;
                case KeyEvent.VK_DOWN :
                    depDown = false;
                    System.out.println("Down released");
                    break; }
            
            // MAJ
            update(); }

    
        // Méthode update()
        // -------------------------------------------
        public void update() {
            // Initialisation du déplacement à 0
            dx = 0;
            dy = 0;
            
            // Déplacement
            if (depLeft) dx = -speed;
            if (depRight) dx = speed;
            if (depDown) dy = speed;
            if (depUp) dy = -speed; }
        
        
        // Méthode fire()
        // -------------------------------------------
        public void fire() {
            missiles.add(new Missile(x + craftWidth, y + craftHeight/2)); }
                    
        
        // Accesseurs
        // -------------------------------------------
        public int getX() { return x; }
        public int getY() { return y; }
        public Image getImage() { return image; }
        public ArrayList getMissiles() { return missiles; }
        
}

Classe Board :
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Board extends JPanel implements ActionListener {
    
    
        private Timer timer;
        private Craft craft;
    
    
        // Constructeur
        // -------------------------------------------
        public Board() {
            addKeyListener(new TAdapter());
            
            setSize(400, 300);
            setBackground(Color.BLACK);
            setDoubleBuffered(true);
            setFocusable(true);
            
            craft = new Craft();
            
            timer = new Timer(5, this);
            timer.start(); }
            
                
    
        // Méthode paintComponent
        // -------------------------------------------
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            
            Graphics2D g2d = (Graphics2D) g;
            
            // Vaisseau
            g2d.drawImage(craft.getImage(), craft.getX(), craft.getY(), this);
            // Missiles
            ArrayList ms = craft.getMissiles();
            for (int i=0; i<ms.size(); i++) {
                    Missile m = (Missile) ms.get(i);
                    g2d.drawImage(m.getImage(), m.getX(), m.getY(), this); }

            
            // Synchro Linux et libération objet g            
            Toolkit.getDefaultToolkit().sync();
            g.dispose(); }
        
        
        // Méthode actionPerformed
        // -------------------------------------------
        public void actionPerformed(ActionEvent e) {
            // Missiles
            ArrayList ms = craft.getMissiles();
            for (int i=0; i <ms.size(); i++) {
                Missile m = (Missile) ms.get(i);
                if (m.isVisible()) m.move();
                else ms.remove(i); }

            // Mouvement vaisseau
            craft.move();

            // Rafraîchissement
            repaint(); }
    

        // Classe interne TAdapter
        // -------------------------------------------
        class TAdapter extends KeyAdapter {
            public void keyReleased(KeyEvent e) {
                craft.keyReleased(e); }
            
            public void keyPressed(KeyEvent e) {
                craft.keyPressed(e); }}    
}

Classe Missile :
import java.awt.Image;
import java.awt.Rectangle;
import javax.swing.ImageIcon;

public class Missile {
    
    
        private int x, y;
        private Image image;
        private Boolean visible;
        private int height, width;
        
        private final int BOARD_WIDTH = 390;
        private final int MISSILE_SPEED = 2;
        
        
        // Constructeur
        // -------------------------------------------
        public Missile(int x, int y) {
            image = new ImageIcon(getClass().getResource("missile.png")).getImage();
            this.x = x;
            this.y = y;

            width = image.getWidth(null);
            height = image.getHeight(null);
            
            visible = true; }
            
        
        // Méthode isVisible()
        // -------------------------------------------
        public Boolean isVisible() {
            return visible; }
        
                
        // Méthode de déplacement du missile
        // -------------------------------------------
        public void move() {
            x += MISSILE_SPEED;
            if (x > BOARD_WIDTH) visible = false; }

        // Accesseurs
        // -------------------------------------------
        public int getX() { return x; }
        public int getY() { return y; }
        public Image getImage() { return image; }
        public void setVisible(boolean visible) { this.visible = visible; }
        public Rectangle getBounds() { return new Rectangle(x, y, width, height); }

}

Merci d'avance pour votre aide

10 réponses

Utilisateur anonyme
19 juin 2009 à 18:23
Comme tu ne connais pas ce langage, avant de dire que c'est lui qui a un bogue, demande-toi d'abord si c'est pas plutôt toi qui as fait une connerie. Je ne connais aucun jeu open source en Java qui souffre du symptome dont tu parles donc je maintiens que tu parles sans savoir. D'ailleurs, je n'ai pas ce problème dans mon jeu en 3D, j'avance avec les flèches du haut et je peux tirer en même temps avec espace ou avec le clic gauche.

Essaie avec une version de la JVM moins récente, par exemple le JDK 1.6 update 10.

Chez moi, quand j'utilise ton exemple, en pressant UP, ça affiche une succession de "up" et de "Lache up" tant que je ne relâche pas comme avec l'exemple du site de Sun :
http://java.sun.com/docs/books/tutorial/uiswing/events/keylistener.html

3
Jyhem2000 Messages postés 9 Date d'inscription dimanche 21 mai 2006 Statut Membre Dernière intervention 1 juillet 2009
1 juil. 2009 à 16:48
Problème résolu...
3 petits points car maintenant que je sais d'où ça vient j'ai les nerfs mm si je suis satisfait de voir que ca fonctionne :)

Mon portable est relié à un switch qui me permet d'avoir un PC fixe et
PC portable relié au même écran, au même clavier, et à la même souris.

Quand je passe par le clavier du portable, ça fonctionne, quand je
passe par le clavier USB relié au switch, ca bug, de même que l'appui
sur 3 touches ne fonctionne pas du tout via la switch, mais très bien
directement sur le portable.


ENFIN !
C'est souvent quand c'est bête que l'on reste bloqué des heures j'ai l'impression...
3
Utilisateur anonyme
19 juin 2009 à 15:34
Bonjour

Je ne suis pas d'accord avec toi, pas mal de jeux vidéo open source écrits en Java ne souffrent pas de ce symptome, merci de ne pas dire n'importe quoi.

De plus, c'est sûr que si tu crées une instance d'ImageIcon pour chaque missile, ça ne va pas le faire. Le constructeur agit de façon synchrone, il va bloquer le processus léger sur lequel il s'exécute tant que l'image n'est pas complètement chargée (du coup, l'Event Dispatch Thread ne peut rien faire d'autre). Crée une seule instance d'ImageIcon pour tous les missiles, stocke-là comme attribut de classe et non d'instance. Bon courage et surtout, évite de cracher sur les jeux vidéo Java open source car ce n'est vraiment pas le meilleur moyen d'obtenir de l'aide.

De la part d'un programmeur de jeux vidéo open source depuis maintenant presque 10 ans.

0
Jyhem2000 Messages postés 9 Date d'inscription dimanche 21 mai 2006 Statut Membre Dernière intervention 1 juillet 2009
19 juin 2009 à 17:35
Oula excuse-moi je crache pas du tout sur les projets / jeux open-source, loin de là, c'est grâce a eux que j'apprends.
Le problème tel que je le rencontre n'est pas que sur les jeux open-source d'ailleurs. Ne le prends donc pas mal, il s'agit d'un malentendu.

Je disais cela parce ce que je commençais a penser que c'était une limitation de JAVA, et comme je viens de commencer ce langage, ca me faisait un peu peur pour la suite.

Merci du conseil pour mon code :)
Cependant, j'ai le mm probleme avec la classe suivante (donc sans image) :
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
 
import javax.swing.JFrame;
 
 
publicclass ToucheFleche implements KeyListener
{
publicstaticvoid main( String[] arg )
{
new ToucheFleche();
}

private JFrame frame;
boolean up, down, left, right;

public ToucheFleche()
{
frame = new JFrame();
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 400);
frame.addKeyListener(this);
frame.setVisible(true);up down left = right = false;
}

@Override
publicvoid keyPressed( KeyEvent e )
{
switch( e.getKeyCode())
{
case KeyEvent.VK_UP:
if( ! up )
{
System.out.println("up");
}
up = true;
break;
case KeyEvent.VK_DOWN:
if( ! down )
{
System.out.println("down");
}
down = true;
break;
case KeyEvent.VK_LEFT:
if( ! left )
{
System.out.println("left");
}
left = true;
break;
case KeyEvent.VK_RIGHT:
if( ! right )
{
System.out.println("right");
}
right = true;
break;
default:
}
}
 
@Override
publicvoid keyReleased( KeyEvent e )
{
switch( e.getKeyCode())
{
case KeyEvent.VK_UP:
System.out.println("lache up");
up = false;
break;
case KeyEvent.VK_DOWN:
System.out.println("lache down");
down = false;
break;
case KeyEvent.VK_LEFT:
System.out.println("lache left");
left = false;
break;
case KeyEvent.VK_RIGHT:
System.out.println("lache right");
right = false;
break;
default:
}
}
 
@Override
publicvoid keyTyped( KeyEvent e ){}
}
 

Donc j'appuie sur UP par exemple (jai bien le message "up" dans la console).

Tout en maintenant UP, j'appuie sur ESPACE Pour simuler un shoot, et
quand je relâche ESPACE, le "lache up" apparait dans la console alors
que la touche est toujours maintenue enfoncée...
En gros quand je "relache" une touche, le prog les "relache" toutes.

Cependant, a priori d'autres ne rencontrent pas ce probleme, alors peut etre que le souci vient de ma bécane...
J'utilise Eclipse Version: 3.4.1 et ma JVM est la 1.6.0_14-b08.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Jyhem2000 Messages postés 9 Date d'inscription dimanche 21 mai 2006 Statut Membre Dernière intervention 1 juillet 2009
19 juin 2009 à 20:01
Oui je parle sans savoir, je débute.
J'ai cherché avant de venir poster ici, j'ai changé mes méthodes de déplacement, cherché sur le net, mis à jour ma JRE, mais rien n'y faisait.
Comme je rencontrais aussi le problème sur d'autre jeu, je ne remettais pas mon code en cause.
Je finissais donc par penser que le langage était fait comme ca, qu'il fallait s'y adapter avec des méthodes plus complexes.

Mais j'ai suivi ton conseil, et effectivement, le problème venait de ma bécane...
J'ai désinstallé le jre1.6.14 et ne trouvant pas de version plus ancienne, j'ai réinstallé la jre1.6.14, et là, tout marche nickel... Donc pour info, ne pas faire les mise a jour JAVA de manière automatique, d'abord désinstallé l'ancienne version, puis installer la nouvelle

1 semaine que je cherche d'autres méthodes de déplacement, des jeux open source java pour voir s'ils ont le mm prob, que je parcourt les forums,  etc...

Bref, voila qui m'enlève une belle épine du pied :)
Encore merci !
0
Utilisateur anonyme
20 juin 2009 à 08:46
Bonjour

Désolé si j'ai été un peu dur mais je pense vraiment qu'il faut d'abord se remettre en question. Ton problème est quand même curieux, je te conseille de configurer Java de façon à ce qu'il affiche la console pour que, quand un programme se lance, on puisse voir quelle JVM il utilise, entre "javaws -viewer" dans ton invite de commande sous Windows ou dans ton terminal sous Linux et va dans l'onglet "Avancé", il y a une rubrique qui traite du débogage, active les logs et la console. Bon courage.

0
Jyhem2000 Messages postés 9 Date d'inscription dimanche 21 mai 2006 Statut Membre Dernière intervention 1 juillet 2009
22 juin 2009 à 12:00
Ok je vais faire ca.
Mais ce qui m'a "perturbé" c'est que j'avais le problème aussi bien sur mon portable pro que sur mon PC perso...
0
Jyhem2000 Messages postés 9 Date d'inscription dimanche 21 mai 2006 Statut Membre Dernière intervention 1 juillet 2009
29 juin 2009 à 15:16
Bon, je remonte le sujet, car le lendemain, le bug est revenu.

Depuis, j'ai désinstallé, réinstallé toutes les versions des JRE 1.6 les unes après les autres  (a savoir l'update 11, 12, 13, 14), c'est pareil.


J'ai formaté mon système, tout réinstallé vendredi dernier : ça marche

Ce matin, j'essaie, ça ne marche plus.

Changement entre vendredi et aujourd'hui : install FlashPlayer + Firefox + forcément un redémarrage

Aujourd'hui, j'ai de nouveau testé plusieurs versions de JRE, idem.


Bref le prob vient du PC je pense, mais je vois vraiment pas d'où.
Qq a t'il une idée ?
0
Utilisateur anonyme
29 juin 2009 à 23:18
Bonsoir

Je te conseille de venir en parler à des spécialistes de la création de jeux Java sur www.javagaming.org (n'aies pas peur d'utiliser la langue de Shakespeare). Je ne reproduis pas ton bogue sinon j'aurais essayé de le corriger. Bon courage.

0
Jyhem2000 Messages postés 9 Date d'inscription dimanche 21 mai 2006 Statut Membre Dernière intervention 1 juillet 2009
30 juin 2009 à 13:25
Merci, j'y vais de ce pas.
0
Rejoignez-nous