Changer le curseur de la souris



  • Bonjour à tous !

    Je vais vous présenter une petite astuce exclusive qui saura embellir vos mods/serveur !

    La possibilité de changer la texture du curseur de la souris quand on est dans Minecraft !

    Il y a deux trois éléments techniques que je détaillerais au maximum, même si je ne les maîtrisent pas très bien.

    Pour ce faire, rendez vous dans la classe de votre ClientProxy, si vous ne l'avez pas, suivez le tutoriel sur "La base de votre mod"

    Vous devriez avoir quelque chose comme ça:

    ClientProxy.java

    package fr.minecraftforgefrance.tutoriel.proxy;
    
    public class ClientProxy extends CommonProxy
    {
         @Override
         public void registerRender()
         {
              System.out.println("méthode côté client");
         }
    }
    

    Nous allons créer une fonction qui nous servira à set le curseur avec comme paramètres, l'id de votre mod, le chemin de la texture, la taille XY de votre image et un double permettant la **rotation **de votre texture.

    private void setCursor(String modid, String path, int width, int height, double rotation)
    {
    }
    

    Ajoutons ensuite un "try multi catch" dans la fonction ci-dessus,

    Le premier "catch" servira à gérer les exceptions LWJGL, liées au(x) changement(s) sur le curseur de la souris.
    Le second est lié au(x) exception(s) possible(s) lors de la lecture de l'image.

    try {
    }
    catch (LWJGLException e) {
         e.printStackTrace();
    }
    catch (IOException e) {
         e.printStackTrace();
    }
    

    Juste avant le try ajoutons une méthode permettant de gérer la rotation de la texture (pourquoi une rotation ? J'y viens plus tard)

    AffineTransform transform = new AffineTransform();
    

    Dans le try ajoutons maintenant une "buffered image" (pour set le chemin vers la texture de votre nouveau curseur)

    BufferedImage cursorTexture = ImageIO.read(getClass().getResource("/assets/" + modid + path));
    

    Explications:
    modid: est le dossier dans lequel ce trouve les différents fichiers/images de votre mod, il est donc lié au "/assets/"
    path: est le chemin final vers votre curseur au format png

    Ajoutons ensuite le reste de la fonction permettant de **rotate **et de **draw ** le nouveau curseur:

    transform.rotate(rotation, cursorTexture.getWidth()/2, cursorTexture.getHeight()/2);
    
    AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
    cursorTexture = op.filter(cursorTexture, null);
    
    int[] rgbs = new int[cursorTexture.getWidth() * cursorTexture.getHeight()];
    
    IntBuffer buffer = IntBuffer.wrap(cursorTexture.getRGB(0, 0, cursorTexture.getWidth(), cursorTexture.getHeight(), rgbs, 0, cursorTexture.getHeight()));          
    
    buffer.rewind();
    

    Explications:

    transform.rotate: Permet la rotation de votre texture, car vous rencontrerez un "problème" qui vous obligera de changer, via un éditeur d'images, la rotation de votre texture, or c'est tout sauf optimisé que d'avoir deux fois la même image avec juste la rotation qui diffère !

    rotation: cette rotation là n'est pas en degrés, mais en radian ! (Nous y reviendrons tout à l'heure)

    int[] rgbs: est lié quand à lui à la fonction présente dans l'IntBuffer, cursorTexture.getRGB() pour pouvoir draw les couleurs de notre futur curseur.

    rewind(): permet de rendre possible la lecture et l'application de notre nouveau curseur

    Pour finir et rendre possible le changement du curseur ajoutez simplement en dessous de rewind():

    Cursor newCursor = new Cursor(width, height, 1, cursorTexture.getHeight() - 1, 1, buffer, null);
    
    Mouse.setNativeCursor(newCursor);
    

    Explications:

    newCursor: permet d'enregister les paramètre de notre nouveau curseur:

    width/height: taille de l'image largeur/hauteur (32x semble être une bonne taille pour un curseur visible 😉 )

    1, cursorTexture.getHeight() - 1: le premier integer permet de set le point X pour que le clic prenne effet.
    cursorTexture.getHeight() - 1 permet quand à lui de set le point Y pour que le clic prenne effet.

    Note:
    Pour les deux paramètres ci-dessus, ils doivent être supérieurs à 0 et inférieurs à la taille de l'image, d'où le "cursorTexture.getHeight() - 1"

    Vous pourriez alors rencontrer ce genre de crash:

    java.lang.IllegalArgumentException: yHotspot > height || yHotspot < 0
    

    Vous saurez d'où ça vient.

    Mouse.setNativeCursor(newCursor); Permet quand à elle de set le nouveau curseur !

    Mais ce n'est pas fini, il faut maintenant appeler notre fonction setCursor() nous l'appellerons dans la fonction registerRender()

    Dans l'exemple qui va suivre j'ai fait en sorte d'afficher l'épée en diamants comme nouveau curseur (en l’occurrence la texture est en 16x)

    this.setCursor("minecraft", "/textures/items/diamond_sword.png", 16, 16, 3.1415926536);
    

    Explications:

    "minecraft": est le premier String et donc le modid de votre mod (ici pour les test j'ai mis minecraft pour avoir la texture de l'épée en diamant)

    "/textures/items/diamond_sword.png": est le second String et donc le chemin final de votre texture pour le curseur

    16 , 16: sont les deux integer de la taille X/Y de l'image (vu que la texture de l'item est en 16 x 16 veillez à bien mettre 16 en X/Y ici aussi, sinon vous aurez un crash)

    3.1415926536: est donc le double qui permet la rotation de la texture…

    Explications sur la rotation de la texture:

    La texture de base de l'item est dans ce sens:

    Mais pour avoir un curseur dans le bon sens, la texture devra être comme ça:

    Or si on n'ajoute pas les quelques lignes permettant la rotation (et donc le double) de la texture le curseur se retrouve dans ce sens:

    Il faut donc ajouter un angle de 180°, non pas en degré mais en radian ce qui nous donne 3.1415926536

    Je vous conseille le site rapidtables.com (en anglais) pour pouvoir convertir un angle en degré vers une angle radian.

    Après libre à vous de jouer avec les point de clic X/Y et la rotation de la texture pour avoir une curseur dans le sens que vous voulez !

    Vous devriez donc avoir la classe ClientProxy qui ressemble à ça au final:

    import java.awt.geom.AffineTransform;
    import java.awt.image.AffineTransformOp;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.nio.IntBuffer;
    
    import javax.imageio.ImageIO;
    
    import org.lwjgl.LWJGLException;
    import org.lwjgl.input.Cursor;
    import org.lwjgl.input.Mouse;
    
    import fr.zeamateis.tuto_ic.common.proxy.CommonProxy;
    
    public class ClientProxy extends CommonProxy
    {
        @Override
        public void registerRender()
        {
            this.setCursor("minecraft", "/textures/items/diamond_sword.png", 16, 16, 3.1415926536);
        }
    
        private void setCursor(String modid, String path, int width, int height, double rotation)
        {  
            AffineTransform transform = new AffineTransform();
    
            try
            {
                BufferedImage cursorTexture = ImageIO.read(getClass().getResource("/assets/" + modid + path));
                transform.rotate(rotation, cursorTexture.getWidth()/2, cursorTexture.getHeight()/2);
    
                AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
                cursorTexture = op.filter(cursorTexture, null);
    
                int[] rgbs = new int[cursorTexture.getWidth() * cursorTexture.getHeight()];
    
                IntBuffer buffer = IntBuffer.wrap(cursorTexture.getRGB(0, 0, cursorTexture.getWidth(), cursorTexture.getHeight(), rgbs, 0, cursorTexture.getHeight()));          
    
                buffer.rewind();
    
                Cursor newCursor = new Cursor(width, height, 1, cursorTexture.getHeight() - 1, 1, buffer, null);
                Mouse.setNativeCursor(newCursor);
            }
            catch (LWJGLException e) {
                e.printStackTrace();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

    Rendu In-Game:

    Zoom sur le curseur car une texture en 16x16 ne ce vois pas trop:

    Et voilà qui conclu cette astuce pour changer le curseur de votre souris ! Vous voilà avec une belle épée en diam's comme curseur !



  • Vraiment cool, çà servira surement !


  • Correcteurs

    Très bon tuto, je ne m'en servirai pas pour l'instant mais je crois avoir une petite idée. 🙂


  • Correcteurs

    Il est passé où l'ancien tuto sur du 1.7? T.T


  • Correcteurs

    What?


  • Correcteurs

    Eh bien il y a quelques jours je suis sûr être tombé sur un tuto de Ama sur les curseurs en 1.7 (un tuto écrit avec beaucoup d'humour et d'aparte)

    Et je dois le retrouver si je veux rattraper du travail perdu.


  • Correcteurs

    Je ne le trouve pas moi non plus, peut-être qu'il l'a réécrit?


  • Correcteurs

    Ok!…
    Alors au final, ce tuto marche aussi en 1.7 :dodgy:

    Du coup j'arrête de psychoter et merci pour ce super tuto