Tirer un laser vers le haut d'un jpanel

Jadorelinfo Messages postés 51 Date d'inscription   Statut Membre Dernière intervention   -  
KX Messages postés 16761 Date d'inscription   Statut Modérateur Dernière intervention   -
Bonjour a toutes et a tous,

J'essaye de coder un petit jeu du genre bataille spatiale, je dois degommer un max d'aliens.
Faire descendre les aliens vers le bas j'ai réussis, mais moi je dois envoyer des laser(imageIcon) vers le haut(d'un jpanel) et la je beug mais grave!



 JLabel vaisseau= new JLabel(imgVaisseau);
JLabel laser= new JLabel(imgLaser);

public void keyPressed(KeyEvent e)

{ //des que j'appuis sur espace, ça lance le laser.
if(e.getKeyCode()==KeyEvent.VK_SPACE)
{
//la position initiale du laser est au point getY() du vaisseau.
// le point final est le y==0 du bounds du container
for(int i=vaisseau.getY(); i<=(container.getBounds().y); i--)
{

laser.setBounds(vaisseau.getX()-20, vaisseau.getY()+20, 10, 20);
try {
Thread.sleep(300);
} catch (InterruptedException ex) {

}
}
}
}

A partir du for avec son i, je n'y arrive vraiment pas.Merçi d'avance.
A voir également:

3 réponses

Reivax962 Messages postés 3672 Date d'inscription   Statut Membre Dernière intervention   1 011
 
Bonjour,

Le problème, c'est que les paramètres que tu passes à SetBounds ne bougent pas !
Il faut utiliser le i de ta boucle.
De plus, ton test <= est mauvais puisqu'au contraire, le i décroit. Le pire c'est que tu donnes la bonne réponse dans ton commentaire :)
    int posX = vaisseau.getX() - 20;
    for(int i=vaisseau.getY(); i >= 0; i--)
    {
        laser.setBounds(posX, i, 10, 20);
        try {
            Thread.sleep(300);
        } catch (InterruptedException ex) {
        }
    }


Xavier
1
Jadorelinfo Messages postés 51 Date d'inscription   Statut Membre Dernière intervention   1
 
merçi Xavier, ça marche nickel!

Maintenant je dois juste remanier le Thread car ça me fais bugger mon pc antique :).
0
Srg2 Messages postés 214 Date d'inscription   Statut Membre Dernière intervention   42
 
désolé je vais risquer d'être hors sujet ...

mais tu essaies de refaire un Space Invaders ???
0
Jadorelinfo Messages postés 51 Date d'inscription   Statut Membre Dernière intervention   1
 
oui, les aliens debarquent sur terre et nous les humains avons le devoir de proteger notre terre :)

Tout ça pour dire, que grace au laser je dois decalque tous les aliens qui viennent d'en haut (jpanel).
0
Srg2 Messages postés 214 Date d'inscription   Statut Membre Dernière intervention   42
 
1
Jadorelinfo Messages postés 51 Date d'inscription   Statut Membre Dernière intervention   1
 
merçi pour le lien, faut toujours revenir aux sources wiki :)

Sinon, j'ai une question: la methode keyListener utilise un thread (de base) et j'ai besoin d'un thread.sleep() pour actualiser l'emplacent du laser, quelqu'un aurait une idée svp??

Merçi.
0
KX Messages postés 16761 Date d'inscription   Statut Modérateur Dernière intervention   3 020
 
0
Jadorelinfo Messages postés 51 Date d'inscription   Statut Membre Dernière intervention   1
 
bonsoir,

merçi KX, avec un timer pourquoi pas?!
Par contre, existe t'il un moyen de n'avoir qu'un seul
Public static void main

celui du jeu de base, car avec 2, je risque de m'emmeler les pinceaux??
Et concretement mon Thread.sleep() je l'insere dans la methode run ou bien je raconte une enormité??

Merçi pour cette aide.

PS: J'ai oublié de dire: ALLER LES BLEUS!! :)
0
KX Messages postés 16761 Date d'inscription   Statut Modérateur Dernière intervention   3 020
 
"existe t'il un moyen de n'avoir qu'un seul Public static void main celui du jeu de base"
Le main que j'ai mis dans mon code c'était pour tester, il faut bien évidemment l'enlever et mettre son contenu au bon endroit dans ton code.

"mon Thread.sleep() je l'insere dans la methode run ou bien je raconte une enormité??"
Effectivement c'est une énormité. Si tu regardes mon code, nul part je n'ai de Thread.Sleep, et pourtant il y a bien 1 seconde entre chaque tâche. Pourquoi ? Parce que la tâche est ordonnancée pour s'exécuter régulièrement
timer.schedule(task, 0, 1000)
avec 1000ms=1s

Concrètement tu devrais donc avoir un Timer qui gère toutes tes actions, en particulier le rafraîchissement de la fenêtre, ou alors plusieurs Timer qui gère indépendamment chaque action mais ça semble être la fausse bonne idée, car plus il y aura d'actions à gérer, plus il y aura de threads en concurrence et l'ordonnanceur risque de figer certains threads, alors qu'avec un seul Timer tu es sûr que toutes les actions auront lieu en même temps.
0
Jadorelinfo Messages postés 51 Date d'inscription   Statut Membre Dernière intervention   1
 
merçi mais j'ai vraiment du mal sur ce coup la, j'essaye mais je n'y arrive pas.
  public void keyPressed(KeyEvent e)
{
if(e.getKeyCode()==KeyEvent.VK_SPACE)
{
System.out.println("e");
//cont.getSize().setSize(500, 0);
//System.out.println(cont.getBounds().y);
for(int i=vaisseau.getY(); i>=0; i--)
{

laser.setBounds(vaisseau.getX()+5, i, 10, 20);
Task t1= new Task();
Timer time= new Timer();
time.schedule(t1, 0, 1000);


}
}
}

Est ce que tu pourrais encore m'aider stp??

Merçi.
0
KX Messages postés 16761 Date d'inscription   Statut Modérateur Dernière intervention   3 020
 
Déjà tu es partie sur le principe où chaque laser va avoir son propre Thread/Task, je ne pense pas que ce soit la meilleure méthode, mais admettons.

Avant toute chose il faut créer le TimerTask, moi j'avais une classe Task qui disait HelloWorld, toi ce qu'il te faudra c'est une classe LaserTask qui gère ton laser.

Un TimerTask s'exécute automatiquement régulièrement, c'est définit lors de son ordonnancement avec le Timer. Il n'y a donc pas à gérer de boucles, uniquement ce que fera chaque occurrence.

Par exemple :

public class LaserTask extends TimerTask
{
    private final Component laser;
    
    private final int dx;
    private final int dy;
    private final int xMin;
    private final int yMin;
    private final int xMax;
    private final int yMax;
    
    private int x;
    private int y;
    
    public LaserTask(Component laser, int x0, int y0, int dx, int dy, int xMin, int yMin, int xMax, int yMax)
    {
        this.laser = laser;
        this.x = x0;
        this.y = y0;
        this.dx = dx;
        this.dy = dy;
        this.xMax = xMax;
        this.yMax = yMax;
        this.xMin = xMin;
        this.yMin = yMin;
    }
    
    @Override
    public void run()
    {
        if (x < xMin || y < yMin || x > xMax || y > yMax)
            cancel();
        
        x += dx;
        y += dy;
        
        laser.setLocation(x, y);
    }
}

Ce qui donnerait :

private static final Timer timer = new Timer();

public void keyPressed(KeyEvent e)
{
    if (e.getKeyCode() == KeyEvent.VK_SPACE)
    {
        // j'ai mis 1000 comme max, il faut adapter à la taille de la fenêtre ou d'éventuels obstacles
        LaserTask task = new LaserTask(laser, vaisseau.getX(), vaisseau.getY(), 0, -1, 0, 0, 1000, 1000);
        timer.scheduleAtFixedRate(task, 0, 300);
    }
}

Remarque technique : une tâche annulée est conservée dans le Timer, dans ton cas cela va utiliser de la mémoire car tu as une tâche par laser, il faut donc rajouter une tâche qui va purger régulièrement le Timer.

public class AutoPurgeTimer extends Timer
{
    public AutoPurgeTimer(long delay, long period)
    {
        schedule(new PurgeTask(), delay, period);
    }
    
    private class PurgeTask extends TimerTask
    {
        @Override
        public void run()
        {
            purge();
        }
    }
}

Dans ce cas on aurait par exemple :

private static final Timer timer = new AutoPurgeTimer(1000,1000);

Autre remarque : quand tu as terminé le jeu, fait un
timer.cancel();
, on pourrait aussi définir le Timer comme un démon... ça dépend du reste de l'application.
0