Emigmatics

EmileF
Messages : 681
Inscription : 18 Mars 2017 19:39

Re: Emigmatics

Message par EmileF » 08 Mars 2024 12:37

Ha oui, je pensais que donner le lien suffisait. Je viens de vérifier mais il y avait une condition à cocher.
Voilà c'est fait, je pense que ça devrait marcher.
Lien Enigmatics
La différence entre l'intelligence et la stupidité est que l'intelligence est limitée.

EmileF
Messages : 681
Inscription : 18 Mars 2017 19:39

Re: Emigmatics

Message par EmileF » 08 Mars 2024 17:13

Un petit défi supplémentaire.
Ca va un peu vite mais ces défis étaient déjà prêts, il m'a suffit de les adapter seulement.
Voilà le lien Enigmatics

et une petite image, sait-on jamais, ça va peut-être donner envie.
Image
La différence entre l'intelligence et la stupidité est que l'intelligence est limitée.

Avatar de l’utilisateur
boubouk50
ModoGenereux
ModoGenereux
Messages : 6225
Inscription : 28 Avr 2014 11:57
Localisation : Saint-Didier-en-Bresse (71)

Re: Emigmatics

Message par boubouk50 » 08 Mars 2024 19:24

Il y a beaucoup à dire en termes d’ergonomie... L'expérience utilisateur n'est pas agréable.
La navigation :
  • Clics gauche et droit pour avancer et reculer. On est continuellement en train d'appuyer. Je sens bien mon muscle du doigt après 10 minutes de jeu.
  • Clic molette pour sortir du mode navigation et pouvoir cliquer sur l'interface. J'ai mis du temps à trouver... En plus, il faut maintenir le clic jusqu'à ce que la souris soit hors-champs.
  • Cliquer et maintenir pour faire défiler les astuces/textes. Je n'ai jamais atteint la fin d'une phrase, c'est trop lent, ça défile 10 fois moins vite que je ne lis.
  • Sélection des clés. Il faut à chaque fois voir quelle clé on possède (donc toutes les faire défiler une à une) pour savoir quelle porte ouvrir. Ça prend aussi un temps fou.
Bref, on passe autant de temps à chercher son chemin (donc à pas faire grand-chose) qu'à résoudre une énigme. Vu que le décor est unique et répétitif, c'est vite lassant. Certains jeux proposent du gameplay (c'est-à-dire de se balader de partout) mais les graphismes sont souvent contemplatifs, donc c'est se balader dans un décor lécher et agréable.

l'UI:
2/3 de ce qu'on voit est de l'UI, et elle est souvent inutile. C'est pour ça que généralement, elle est limitée aux données utiles en temps réel, et qu'elle est expansible lorsqu'on en a besoin. Ici, elle prend le dessus sur le jeu.
Concernant les énigmes, elles sont sympas, mais elles souffrent aussi du manque d'ergonomie. Il faut cliquer et cliquer et cliquer continuellement. Bon après, si tu limites les interactions à la souris, forcément, il faudra bien cliquer... Mais un glisser-déposer est aussi valide et serait peut-être plus judicieux.

On oublie souvent l'UX (User Experience - l'Expérience Utilisateur) alors qu'il est primordial. Si les déplacements, les interactions, les interfaces, les sons ne sont pas agréables lors du jeu, alors quel que soit le jeu derrière, on ne va pas avoir envie d'y jouer. A contrario, l'UX est réussi, même si le jeu derrière n'est pas fou, alors on a eu une bonne sensation tout de même.
Tout le monde préférera conduire une vieille twingo sympa à poste cassette qu'une superbe lamborghini qui t'envoie une décharge électrique toutes les dix secondes.

Évidemment, c'est un métier à part entière et c'est ton jeu, et tu es libre de faire ce que tu veux.
Si tu veux qu'on discute ergonomie de jeu et UX pour rendre ton jeu plus agréable (en tout cas pour moi :D ), n'hésite pas à poser toutes les questions, on est là pour ça.

Désolé si le rapport est abrupt, j'espère que tu vois ça comme de la critique constructive, ce que c'est.
La création d'un jeu demande des compétences en beaucoup de domaines, et beaucoup de références. C'est déjà super que tu aies déjà développé tout ça. Ce n'est pas évident, je sais ce que c'est. Ça prend du temps, des nerfs, et beaucoup de refaisage (un mot qui ne se dit pas).
"Ce n'est pas en améliorant la bougie, que l'on a inventé l'ampoule, c'est en marchant longtemps."
Nétiquette du forum
Savoir faire une recherche
Apprendre la programmation

EmileF
Messages : 681
Inscription : 18 Mars 2017 19:39

Re: Emigmatics

Message par EmileF » 08 Mars 2024 21:19

Merci Boubouk d'avoir testé mon jeu.

Merci aussi pour ton appréciation bien qu'à t'écouter il me reste que tout mettre à la poubelle et recommencer :nonon:
Mais c'est ce que je souhaitais. Un avis professionnel pour me guider vers une réalisation plus réussie et agréable.

Donc oui, je souhaiterais quelques conseils.

Tu me dis que les clics sur la souris c'est lassant, mais je voulais éviter le clavier car personnellement être toujours à la recherche du bouton à presser, je trouve ça désagréable, et en fait au lieu d'appuyer sur un bouton de la souris tu appuis sur un bouton du clavier. Au niveau musculaire je ne vois pas grande différence par contre avec la souris tu n'as pas de bouton à chercher. Mais je pense qu'il doit être possible de combiner les deux pour au moins le déplacement du joueur.

Quand à la pression sur la touche centrale de la souris c'est pour pouvoir débloquer le curseur et lui permettre d'atteindre les boutons de l'UI.

Pour l'UI je voulais apporter une note originale à mon jeu. C'est vrai que ça prend beaucoup de place inutilement.

Pour le décor c'est pour ça que je proposais deux décors différents dans mon premier message et je crois que le décor du château était moins lassant que les corridors et escaliers. Maintenant le fait de rechercher son chemin aurait pu ajouter un point à l'énigme.

Pour les défis, je ne vois pas ce que tu entends par l'ergonomie, j'ai essayé de les rendre plus facile à l'emploi en cliquant :langue2: sur le panneau afin de bien se positionner et libérer le curseur pour avoir accès à tous les objets du panneau et cliquer :amen: à l'extérieur du panneau pour libérer le joueur. Il faut savoir que j'avais prévu pour récupérer les clés de passer par ce système à chaque fois, mais adopter d'autres méthodes pour des énigmes plus ouvertes dans les salles des trophées.

Voilà ou j'en suis pour le moment. Je pense commencer par proposer un autre environnement, un autre design, mais je préfère rester dans un bâtiment plutôt qu'un environnement extérieur qui offrirait peut-être plus de choix au niveau décor mais plus de difficultés au niveau ressources de l'ordi.

Ca fait plus d'une vingtaine de fois que je recommence sans arriver à être vraiment satisfait du résultat. C'est pour ça que je suis venu chercher des conseils ici et je ne suis pas à un refaisage :mdr3: près

Encore merci.
La différence entre l'intelligence et la stupidité est que l'intelligence est limitée.

EmileF
Messages : 681
Inscription : 18 Mars 2017 19:39

Re: Emigmatics

Message par EmileF » 25 Avr 2024 16:34

Voilà,
J'ai tout repris, la déco, les commandes et le gameplay.

Pour les commandes j'ai essayé de regrouper les commandes clavier chère à Boubouk :amen: et celles que je préfère.
Soit les touches du clavier pour déplacer le player et le déplacement de la souris pour l'orienter, ça c'est pour Boubouk,
et la touche gauche de la souris pour avancer et la droite pour reculer, c'est ce que je préfère.
La touche Ctrl gauche ou le bouton central de la souris permettent de libérer le curseur pour avoir accès aux UI ou autre.
Il faut réutiliser le ctrl ou la souris pour revenir au mode normal du jeu.

Voici le lien pour essayer : Enigmatics

help!!! c'est loin d'être terminé, ce n'est juste qu'un aperçu pour la déco et les commandes.

Mais si vous l'avez essayé vous aurez peut-être constaté qu'il y a un problème pour le drag and drop des pièces du puzzle.
Ce problème me bloque depuis plusieurs jours. On arrive à sélectionner et déplacer sans problèmes certaines pièces et d'autres pas. Et ce n'est pas toujours les mêmes qui ont le problème.

Ci joint les scripts qui me semblent concernés. Je les ai commenté pour essayer d'être le plus clair possible.
A savoir que le script "Btn" je l'ai conçu pour qu'il puisse convenir à toutes les éventualités des objets sur lesquels le joueur peut avoir une action. C'est pour ça qu'il est un peu long et complexe. Mais je n'arrive pas à comprendre pourquoi ça fonctionne très bien dans certains cas et pas dans d'autres.

Si quelqu'un pouvait avoir la patience et la gentillesse d'y jeter un oeil, peut-être trouvera-t-il un idée de solution.

Code : Tout sélectionner

using System;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;

[ExecuteInEditMode]
public class Btn : MonoBehaviour
{
    [Foldout("Apparence", true)]
    [Tooltip("La couleur par défaut de l'objet")]
    [SerializeField] Color col_Defaut = Colors.Yellow;
    [Tooltip("La couleur quand le curseur entre dans l'objet")]
    [SerializeField] Color col_Enter = Colors.Orange;
    [Tooltip("La couleur quand il y a clic l'objet")]
    [SerializeField] Color col_Press = Colors.Red;
    [Tooltip("La couleur quand l'objet est désactivé")]
    [SerializeField] Color col_Inactif = Colors.Gray;
    [Tooltip("La couleur imposée à l'objet")]
    [SerializeField] Color color = Color.clear;
    [Tooltip("sorting order")]
    [SerializeField] int order = 1;

    [Foldout("Mesh", true)]
    [Tooltip("l'ID du matériel du mesh à colorer")]
    public int id_mat = 0;

    [Foldout("Sprite", true)]
    [Tooltip("le sprite à appliquer au SpriteRenderer")]
    [SerializeField] Sprite sprite;

    [Foldout("Symbole", true)]
    [Tooltip("le sprite à appliquer au Symbole")]
    [SerializeField] Sprite symbole;
    [Tooltip("la dimension du sprite du Symbole")]
    [SerializeField] Color col_Symb = Color.clear;
    [Tooltip("la dimension du sprite du Symbole")]
    [SerializeField] Vector2 size_symb = new Vector2(0.025f, 0.025f);
    [Tooltip("la rotation du sprite du Symbole")]
    [SerializeField] float rot_symb;

    [Foldout("Texte", true)]
    [Tooltip("le texte du Tmp_Text")]
    [SerializeField] string text;
    [Tooltip("la couleur du texte du Tmp_Text")]
    [SerializeField] Color col_text = Color.yellow;

    [Foldout("Les Events", true)]
    [Tooltip("L'objet à appeler")]
    public GameObject target;
    [Tooltip("la distance maximum de la caméra ver l'objet pour déclencher les actions")]
    [SerializeField] float distance = 5f;
    [Tooltip("Le mode à utiliser quand le curseur entre dans le bouton")]
    public Mode mode_enter = Mode.Vise;
    [Tooltip("Le mode à utiliser quand le curseur sort du bouton")]
    public Mode mode_exit = Mode.Normal;
    [Tooltip("Si le bouton est actif ou non")]
    [SerializeField] bool actif = true;
    [Tooltip("Pour appeler la fonction 'Btn_Active' dans 'Objet'")]
    [SerializeField] bool active = false;
    [Tooltip("Pour appeler la fonction 'Btn_Desactive' dans 'Objet'")]
    public bool desactive = false;
    [Tooltip("S'il faut appeler la fonction Btn_Enter")]
    public bool enter = false;
    [Tooltip("S'il faut appeler la fonction Btn_Left_Down")]
    public bool leftDown = false;
    [Tooltip("S'il faut appeler la fonction Btn_Center_Down")]
    public bool centerDown = false;
    [Tooltip("S'il faut appeler la fonction Btn_Right_Down")]
    public bool rightDown = false;
    [Tooltip("S'il faut appeler la fonction Btn_Left_Up")]
    public bool leftUp = false;
    [Tooltip("S'il faut appeler la fonction Btn_Center_Up")]
    public bool centerUp = false;
    [Tooltip("S'il faut appeler la fonction Btn_Right_Up")]
    public bool rightUp = false;
    [Tooltip("S'il faut appeler la fonction Btn_Exit")]
    public bool exit = false;
    [Tooltip("S'il faut appeler la fonction Btn_Dragging")]
    public bool drag = false;
    [Tooltip("S'il faut appeler la fonction Btn_Drag_Start")]
    public bool dragStart = false;
    [Tooltip("S'il faut appeler la fonction Btn_Dragging")]
    public bool dragDragging = false;
    [Tooltip("S'il faut appeler la fonction Btn_Drag_End")]
    public bool dragEnd = false;
    [Tooltip("Les boutons à désactiver en cas de drag (Se met à jour automatiquement si vide)")]
    [SerializeField] List<Btn> voisins;
    internal bool pose;

    bool _actif;
    public bool Actif
    {
        get { return _actif; }
        set
        {
            _actif = value;
            actif = value;
            GetComponent<Collider>().enabled = value;
            Colore_Btn(col_Defaut);
            if (value)
            {
                if (active) target.SendMessage("Btn_Active", this);
            }
            else
            {
                if (desactive) target.SendMessage("Btn_Desactive", this);
            }
        }
    }

    Color _color;
    //Pour imposer une couleur. Tant que Color est différent de Clear c'est cette couleur qui sera utilisée
    public Color Color
    {
        get { return _color; }
        set
        {
            _color = value;
            if (value == Color.clear)
                Colore_Btn(col_Defaut);
            else
                Colore_Btn(value);
        }
    }

    Sprite _sprite;
    //Pour appliquer un sprite si le bouton est un sprite renderer
    public Sprite Sprite
    {
        get { return _sprite; }
        set
        {
            _sprite = value;
            if (transform.GetComponent<SpriteRenderer>())
            {
                transform.GetComponent<SpriteRenderer>().sprite = value;
                transform.GetComponent<SpriteRenderer>().color = col_Defaut;
            }
        }
    }

    //Pour appliquer un sprite au symbole affiché au dessus du bouton s'il existe
    public void Symbole(Sprite sprite, Color? color = null, Vector2? size = null, float rot = 0)
    {
        if (transform.Find("Symbole"))
        {
            if (color == null) color = Color.white;
            if (size == null) size = new Vector2(0.025f, 0.025f);
            SpriteRenderer render = transform.Find("Symbole").GetComponent<SpriteRenderer>();
            render.sprite = sprite;
            render.color = (Color)color;
            render.size = (Vector2)size;
            render.transform.localEulerAngles = new Vector3(0, 0, rot);
        }
    }

    //Pour appliquer un texte sur le bouton s'il y a lieu
    public string txt
    {
        get { return _txt; }
        set
        {
            _txt = value;
            foreach (Transform item in transform)
            {
                if (item.name == "Tmp_Text")
                {
                    item.GetComponent<TextMeshPro>().color = _colTxt;
                    item.GetComponent<TextMeshPro>().text = value;
                }
            }
        }
    }

    Color _colTxt;
    //La couleur du texte
    public Color Col_Txt
    {
        get { return _colTxt; }
        set
        {
            _colTxt = value;
            foreach (Transform item in transform)
            {
                if (item.name == "Tmp_Text")
                {
                    item.GetComponent<TextMeshPro>().color = value;
                }
            }
        }
    }

    string _txt;
    //Pour appliquer un texte sur le bouton s'il y a lieu et sa couleur
    public void Texte(string texte, Color? color = null)
    {
        if (color == null) color = _colTxt;
        _txt = texte;
        _colTxt = (Color)color;
        foreach (Transform item in transform)
        {
            if (item.name == "Tmp_Text")
            {
                item.GetComponent<TextMeshPro>().color = _colTxt;
                item.GetComponent<TextMeshPro>().text = texte;
            }
        }
    }

    int _order;
    //Pour régler le sorting order des sprites du bouton
    public int Order
    {
        get { return _order; }
        set
        {
            _order = value;
            if (transform.Find("Fond"))
                transform.Find("Fond").GetComponent<SpriteRenderer>().sortingOrder = value;
            if (transform.GetComponent<SpriteRenderer>())
                transform.GetComponent<SpriteRenderer>().sortingOrder = value + 1;
            if (transform.Find("Symbole"))
                transform.Find("Symbole").GetComponent<SpriteRenderer>().sortingOrder = value + 2;
            if (transform.Find("Tmp_Text"))
                transform.Find("Tmp_Text").GetComponent<TextMeshPro>().sortingOrder = value + 2;

        }
    }

    //Initialisation du bouton en mode édition
    private void Initialise_Btn()     //Corrigé en public au lieu de private
    {
        Actif = actif;
        Order = order;
        if (color != Color.clear) Color = color;
        Sprite = sprite;
        Colore_Btn(col_Defaut);
        Symbole(symbole, col_Symb, size_symb, rot_symb);
        Texte(text, col_text);
        if (drag)
        {
            if (voisins == null || voisins.Count == 0)
            {
                voisins = new List<Btn>();
                foreach (Transform item in transform.parent)
                {
                    if (item.GetComponent<Btn>())
                    {
                        if (item != transform)
                            voisins.Add(item.GetComponent<Btn>());
                    }
                }
            }
        }
        else
            voisins = null;
    }

    //Pour appliquer la couleur courante
    private void Colore_Btn(Color col)
    {
        if (transform.GetComponent<SpriteRenderer>())
        {
            if (_color != Color.clear)
                transform.GetComponent<SpriteRenderer>().color = _color;
            else
                transform.GetComponent<SpriteRenderer>().color = !_actif? col_Inactif: col;
        }
        if (transform.GetComponent<MeshRenderer>())
        {
            if (_color != Color.clear)
                transform.Color(_color, id_mat);
            else
                transform.Color(!_actif ? col_Inactif : col, id_mat);
        }
    }

    //A la création du bouton
    private void Awake()
    {
        Initialise_Btn();
    }

    bool dans;      //true quand le curseur est dans le bouton
    bool ok;        //true quand le player est assez proche du bouton        
    bool dragging;  //true quand le bouton est en cours de drag
    Vector3 start;  //la position d'origine du bouton au départ du drag
    Vector3 offset; //la différence de position du curseur et du centre du bouton

    //Quand le curseur entre dans le bouton
    void OnMouseEnter()
    {
        //s'il n'est pas actif ou s'il est en pose ou si c'est le mode UI : on sort
        if (!_actif || pose || Manager.Instance.mode == Mode.UI) return;
        //sinon on signale que le curseur est dans le bouton
        dans = true;
    }

    //Quand le curseur sort du bouton
    void OnMouseExit()
    {
        //s'il n'est pas actif ou s'il est en pose ou si c'est le mode UI : on sort
        if (!_actif || pose || Manager.Instance.mode == Mode.UI) return;
        //si on est en cours d'un drag : on sort
        if (dragging) return;
        //on signale que le curseur n'est plus dans le bouton
        dans = false;
        //qu'il n'est plus à la bonne distance
        ok = false;
        //on remet le couleur par défaut
        Colore_Btn(col_Defaut);
        //on reinitialise le mode 
        Manager.Instance.mode = mode_exit ;
        //et on appelle la fonction "Btn_Exit" dans l'objet target si exit est à true
        if (exit) target.SendMessage("Btn_Exit", this);
    }

    private void Update()
    {
        //si on est en mode editeur
        if (!Application.isPlaying)
        {
            //on initialise le bouton pour le mettre à jour lors des changements
            Initialise_Btn();
        }
        else
        {
            //s'il n'est pas actif ou s'il est en pose ou si c'est le mode UI : on sort
            if (!_actif || pose || Manager.Instance.mode == Mode.UI) return;
            //Si on est en cours de drag
            if (dragging)
            {
                //Tant que le bouton gauche de la souris est pressé
                if (Input.GetMouseButton(0))
                {//Envoie un rayon vers le curseur
                    Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
                    RaycastHit hit;
                    //si le rayon rencontre quelque chose
                    if (Physics.Raycast(ray, out hit))
                    {
                        //on récupère la local position z du bouton
                        float z = transform.localPosition.z;
                        //on repositionne le bouton
                        transform.position = hit.point - offset;
                        //on rectifie la position z
                        Vector3 p = transform.localPosition;
                        p.z = z;
                        transform.localPosition = p;
                        //on appelle le fonction "Btn_Dragging" du target si dragDragging est à true
                        if (dragDragging) target.SendMessage("Btn_Dragging", hit.point);
                    }
                }
                //si le bouton gauche de la souris est relaché
                else
                {
                    //on active le mode_enter
                    Manager.Instance.mode = mode_enter;
                    //on corrige le sorting order des sprites
                    Order = order;
                    //on arrete le drag
                    dragging = false;
                    //on sort du curseur
                    dans = false;
                    //on desactive les voisins en cas de drag
                    foreach (Btn item in voisins)
                        item.pose = false;
                    //on appelle la fonction "Btn_Drag_End" du target si dragEnd est activé
                    if (dragEnd)
                        target.SendMessage("Btn_Drag_End", this);
                    //si dragEnd n'est pas activé
                    else
                    {
                        //on replace le le bouton au départ
                        transform.position = start;
                        //et on sort du bouton
                        OnMouseExit();
                   }

                }
            }
            //si on n'est pas en cours de drag
            else
            {
                //si le curseur est dans le bouton
                if (dans)
                {
                    //si le bouton est actif et qu'il n'est pas en pose
                    if (_actif && !pose)
                    {
                        //on calcule la distance horizontale avec la caméra
                        float dist = Camera.main.transform.Distance(transform, 0);
                        //si on n'était pas à bonne distance
                        if (!ok)
                        {
                            //et que la distance actuelle est plus petite que la distance maxi
                            if (dist < distance)
                            {
                                //on signale que la distance c'est ok
                                ok = true;
                                //on colore le bouton avec la couleur enter
                                Colore_Btn(col_Enter);
                                //on passe au mode enter 
                                Manager.Instance.mode = mode_enter;
                                //On appelle la fonction "Btn_Enter" de l'objet target si enter est activé
                                if (enter) target.SendMessage("Btn_Enter", this);
                            }
                        }
                        //si on est assez prêt du bouton
                        else
                        { 
                            //si le player s'est trop éloigné
                            if (dist > distance)
                            {
                                //on signale que la distance n'est pas ok
                                ok = false;
                                //on remet la couleur par défaut
                                Colore_Btn(col_Defaut);
                                //on passe au mode exit 
                                Manager.Instance.mode = mode_exit;
                                //On appelle la fonction "Btn_Exit" de l'objet target si exit est activé
                                if (exit) target.SendMessage("Btn_Exit", this);
                            }
                            //si le player est assez prêt
                            else
                            {
                                //si le player avance on sort
                                if (Player.Instance.avance) return;

                                //si drag est active, si on n'est pas en mode dragging et si on appuye sur le bouton gauche de la souris
                                if (drag && !dragging && Input.GetMouseButtonDown(0))
                                {
                                    //on met en pose tous les voisins
                                    foreach (Btn item in voisins)
                                        item.pose = true;
                                    //on applique le mode stop
                                    Manager.Instance.mode = Mode.Stop;
                                    //on augmentre le sortig order pour passer afficher le le bouton devant les autres
                                    Order = order + 3;
                                    //on récupère la position d'origine du bouton
                                    start = transform.position;
                                    //et on calcule la différence de position entre la position du curseur et du bouton
                                    Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
                                    RaycastHit hit;
                                    if (Physics.Raycast(ray, out hit))
                                        offset = hit.point - start;
                                    //on active le dragging
                                    dragging = true;
                                    //si dragStart est activé on appelle la fonction "Btn_Drag_Start" de l'objet cible
                                    if (dragStart) target.SendMessage("Btn_Drag_Start", this);
                                }
                                //si on n'est pas en mode drag
                                else
                                    //on active le mode_enter choisi
                                    Manager.Instance.mode = mode_enter;
                                //on appelle la fonction "Btn_Left_Down" si leftDown est actif et on appuye sur le btn gauche de la souris 
                                if (leftDown && Input.GetMouseButtonDown(0)) target.SendMessage("Btn_Left_Down", this);
                                //on appelle la fonction "Btn_Right_Down" si rightDown est actif et on appuye sur le btn droit de la souris 
                                if (rightDown && Input.GetMouseButtonDown(1)) target.SendMessage("Btn_Right_Down", this);
                                //on appelle la fonction "Btn_Center_Down" si centertDown est actif et on appuye sur le btn central de la souris 
                                if (centerDown && Input.GetMouseButtonDown(2)) target.SendMessage("Btn_Center_Down", this);
                                //on appelle la fonction "Btn_Left_Up" si leftUp est actif et on relache le btn gauche de la souris 
                                if (leftUp && Input.GetMouseButtonUp(0)) target.SendMessage("Btn_Left_Up", this);
                                //on appelle la fonction "Btn_Right_Up" si rightUp est actif et on relache le btn droit de la souris 
                                if (rightUp && Input.GetMouseButtonUp(1)) target.SendMessage("Btn_Right_Up", this);
                                //on appelle la fonction "Btn_Center_Up" si centerUp est actif et on relache le btn central de la souris 
                                if (centerUp && Input.GetMouseButtonUp(2)) target.SendMessage("Btn_Center_Up", this);
                            }
                        }
                    }
                    //si le bouton n'est pas actif ou en pose
                    else
                    {
                        //on applique le mode exit spécifié
                        Manager.Instance.mode = mode_exit;

                    }
                }
            }
        }
    }
}

Code : Tout sélectionner

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Hexa_Puzzle : MonoBehaviour
{
    public List<Transform> pos_exter;   //les positions des pièces à l'extérieur de la grille
    public List<Transform> pos;         //les positions des pièces dans la grille
    public List<Btn> pieces;            //les pièces du puzzle
    public List<Sprite> sprites;        //les sprites pour l'affichage UI
    public List<Transform> niches;      //les transform parent pour les pièces du puzzle dans les niches du labyrinthe
    public List<Image> images;          //les images UI de l'inventaire
    public List<int> id_piece;          //l'index des pièces pour les niches et l'inventaire
    public List<int> id_image;          //l'index des images
    public Porte porte;                 //la porte à ouvrir
    public bool reussi;                 //si le défi est reussi

    //pour initialise le puzlle au départ quand le labyrinthe est construit
    public void Initialise(List<Transform> niches)
    {
        //on recupère les niches du labyrinthe
        this.niches = niches;
        //on initialise la liste des pièces qui vont aller dans les niches
        id_piece = new List<int>();
        for (int i = 0; i < 3; i++)
        {
            recommence:
            //un index de pièce au hazard
            int v = UnityEngine.Random.Range(0, pieces.Count);
            //si on à déjà tiré cette pièce au sort on recommence
            if (id_piece.Contains(v)) goto recommence;
            //on positionne la pièce dans la niche
            pieces[v].transform.parent = niches[i];
            pieces[v].transform.localPosition = new Vector3(0, 0, 0);
            pieces[v].transform.localEulerAngles = Vector3.zero;
            //on change les propriété de la pièce pour qu'elle réagisse au clic et pas au drag
            pieces[v].leftUp = true;
            pieces[v].drag = false;
            pieces[v].dragEnd = false;
            pieces[v].Initialise_Btn(); //Correction apportée pour régler les problèmes
            //on ajoute l'index de la pièce à la liste
            id_piece.Add(v);
        }
    }

    //quand on clique sur une pièce
    public void Btn_Left_Up(Btn btn)
    {
        //on récupère l'index de la pièce
        int v = pieces.IndexOf(btn);
        int i = id_piece.IndexOf(v);
        //on affiche l'image de l'inventaire en fonction de la pièce cliquée
        images[i].sprite = sprites[v];
        images[i].gameObject.SetActive(true);
        //on repositionne la pièce dans le puzzle
        pieces[v].transform.parent = transform;
        pieces[v].transform.localPosition = pos_exter[v].transform.localPosition;
        pieces[v].transform.localEulerAngles = new Vector3(-90, 0, 0);
        //on restaure les actions de drag et clic
        pieces[v].leftUp = false;
        pieces[v].drag = true;
        pieces[v].dragEnd = true;
        pieces[v].Initialise_Btn(); //Correction apportée pour régler les problèmes
        //et on rend la pièce inactive pour que le joueur les sélectionne dans l'inventaire pour les réactiver
        pieces[v].gameObject.SetActive(false);
        //et on passe au mode normal car ça ne se fait pas automatiquement car désactivé
        Manager.Instance.mode = Mode.Normal;
    }

    //Quand le joueur clique sur une image de l'inventaire
    public void Clic_Image(int i)
    {
        //on récupère l'index de la pièce
        int v = id_piece[i];
        //on active la pièce
        pieces[v].gameObject.SetActive(true);
        //on désactive l'image
        images[i].gameObject.SetActive(false);
    }

    //quand le joueur termine le drag d'une pièce
    public void Btn_Drag_End(Btn btn)
    {
        //pour une grande distance au départ
        float d = 1000;
        //l'index de la "pos" le plus proche
        int p = -1;
        //l'index de la "pos_exter" la plus proche
        int e = -1;
        //recherche la pos_exter la plus proche
        for (int i = 0; i < pos_exter.Count; i++)
        {
            float dist = Vector3.Distance(btn.transform.localPosition, pos_exter[i].localPosition);
            if (dist < d)
            {
                d = dist;
                e = i;
            }
        }
        //recherche la pos piece la plus proche
        for (int i = 0; i < pos.Count; i++)
        {
            float dist = Vector3.Distance(btn.transform.localPosition, pos[i].localPosition);
            if (dist < d)
            {
                d = dist;
                p = i;
                e = -1;
            }
        }
        //s'il n'y a pas de pos pièces plus pr0che on ramène la piece sur la pos_exter la plus proche
        if (e > -1)
            btn.transform.localPosition = pos_exter[e].transform.localPosition;
        //sinon positionne la pièce sur la pos_pièce la plus proche
        else if (p > -1)
            btn.transform.localPosition = pos[p].transform.localPosition;

        Controle();
    }

    private void Controle()
    {
        reussi = false;
        //on parcours toutes les pièces
        for (int i = 0; i < pos.Count; i++)
        {
            //si une pièce n'est pas à sa place : on sort
            if (pieces[i].transform.localPosition != pos[i].transform.localPosition)
                return;
        }
        //puzzle réussi
        reussi = true;
        //on débloque et ouvre la porte
        porte.Bloque = false;
        porte.Ouvre();
        //on désactive toutes les pièces
        foreach (Btn item in pieces)
        {
            item.Actif = false;
        }
        //et on active le mode normal
        Manager.Instance.mode = Mode.Normal;
    }
}
Edité quelques minutes après le premier envoi : Il semblerai que le simple fait de poser la question ici m'éclaire pour trouver la solution. J'ai modifié les scripts et ajouté un petit commentaire pour montrer mes erreurs.

J'attends quand même vos commentaires en ce qui concerne la déco et les commandes
Merci
La différence entre l'intelligence et la stupidité est que l'intelligence est limitée.

Avatar de l’utilisateur
boubouk50
ModoGenereux
ModoGenereux
Messages : 6225
Inscription : 28 Avr 2014 11:57
Localisation : Saint-Didier-en-Bresse (71)

Re: Emigmatics

Message par boubouk50 » 25 Avr 2024 17:35

EmileF a écrit :
25 Avr 2024 16:34
Pour les commandes, j'ai essayé de regrouper les commandes clavier chères à Boubouk :amen:
Quel soulagement déjà ! Et pas que pour moi. Depuis que les PCs ont des jeux, l'énorme majorité des jeux utilise ces commandes, à juste titre de confort et rapidité.
Bon du coup, il y a la double commande avec la souris, et c'est parfois déroutant.
Le pb quand on veut tout faire à la souris, c'est que les commandes se chevauchent, ou alors, il faut toujours faire une action avant pour décider d'un type de commande.
Ici, typiquement, pour passer à l'UI (ou en sortir), il faut un clic molette.
Aussi, quand on doit cliquer ou glisser-déposer un objet, si tu rates ton clic, tu avances alors que ce n'est pas ce que tu veux. Donc après, il faut se repositionner.
Ce sont pleins de petits détails qui peuvent lasser les joueurs.
Bon après, pour les (rares) adeptes de la souris comme toi, ce sont des contraintes avec lesquelles tu devras composer.
Aussi, je le répète, c'est ton jeu, si tu veux un pur point & clic contrôlé que par la souris, fais-le. Au diable le clavier !

Pour le graphisme, le décor est déjà plus agréable, je trouve.
Mais cette manie de devoir cliquer partout, tout le temps, à tout prix, on se croirait en 1995 quand on était très limité et qu'il n'y avait que ça à faire. :pleur4: ← Ça, c'est un commentaire perso de ressenti. Si tu aimes cliquer, c'est mon problème.
L'UI sur le côté qui peut se déplier/replier. Ok. C'est pas foufou, mais ça a le mérite de pas bloquer toute la vue comme la précédente.
"Ce n'est pas en améliorant la bougie, que l'on a inventé l'ampoule, c'est en marchant longtemps."
Nétiquette du forum
Savoir faire une recherche
Apprendre la programmation

EmileF
Messages : 681
Inscription : 18 Mars 2017 19:39

Re: Emigmatics

Message par EmileF » 25 Avr 2024 17:45

Merci boubouk,
Tu dis qu'il faut cliquer tout le temps, mais comment faire autrement pour commander des actions dans un jeu du genre du miens.
Même dans les jeux de combats, (je crois, je les fuis,) il faut cliquer pour tirer ou sortir un épée.
Quand tu fait un drag and drop tu cliques aussi pour commencer ton déplacement.
Donc je crois que de toute façon il faut cliquer. C'est vrai que je suis plutôt des années 1995, je n'ai pas bien suivi l'évolution mais je ne vois pas comment faire pour éviter les clics dans un jeu.

J'ai bien peur de ne pas arriver à comprendre. Veux-tu me donner un exemple de jeu gratuit qui utilise ton mode de commande ?

Je viens de me renseigner sur chatGPT et apparemment les touches ZQSD et la barre espace sont préférées. Donc au lieu de cliquer on préfère la barre espace. Et pour orienter le joueur les touches QD je parle bien sûr sur un clavier azerty
et délaisser complètement la souris pour toutes les actions du jeu sauf UI ?
La différence entre l'intelligence et la stupidité est que l'intelligence est limitée.

Avatar de l’utilisateur
boubouk50
ModoGenereux
ModoGenereux
Messages : 6225
Inscription : 28 Avr 2014 11:57
Localisation : Saint-Didier-en-Bresse (71)

Re: Emigmatics

Message par boubouk50 » 26 Avr 2024 09:31

Oui, c'est ça.
La souris ne possède que 4 actions : 3 clics (droit, molette, gauche) et le défilement roulette. Cela limite donc les possibilités. Il faut donc jouer d'astuces pour multiplier les interactions.
Le clavier possède tellement de touches que tu n'auras jamais assez d'interactions pour toutes les utiliser. En plus, il est complémentaire de la souris, chacun n'utilisant qu'une seule main.
Évidemment, pour les générations qui sont nées avec l'ordinateur, cette prise en main est évidente. On ne regarde même plus où sont les touches, parce que ce sont toujours les mêmes qui sont utilisées.
Comme la plupart des personnes sont droitières, les touches à gauche du clavier sont utilisées :
  • ZSQD pour le déplacement (avant, arrière, gauche et droite)
  • Ctrl - Shift - Espace pour les actions
Pose ta main gauche sur le clavier, tu comprendras l'ergonomie de ces touches. Le petit doigt sur Shift - Ctrl, les 3 suivants sur QZD (le majeur glisse entre Z et S, mais comme dans les jeux, on avance plus qu'on en recule, Z est plus utilisé) et le pouce sur la touche Espace. Le pouce (Espace) est l'action principale, celle qui permet de rapidement faire quelque chose. Ici, je dirai ouvrir / fermer le menu d'UI et donc passer en mode UI / Jeu. Appuyer sur Espace avec le pouce est un mouvement simple et rapide, souvent associé au saut dans les jeux de plateformes.
La main droite tient la souris pour toutes les actions de clic et son déplacement pour la rotation de la caméra (comme tu l'as fait actuellement).
"Ce n'est pas en améliorant la bougie, que l'on a inventé l'ampoule, c'est en marchant longtemps."
Nétiquette du forum
Savoir faire une recherche
Apprendre la programmation

EmileF
Messages : 681
Inscription : 18 Mars 2017 19:39

Re: Emigmatics

Message par EmileF » 26 Avr 2024 10:28

Donc si je comprends bien le clic de la souris est utilisé quand même pour agir sur les objets du jeu.
Selon tes commentaires je comprenais qu'il fallait exclure complètement la souris.

Donc, je déplace le player avec les touches ZQSD et je l'oriente avec la souris ainsi que la caméra et la roulette pour monter ou descendre la caméra
Je peux utiliser le clic gauche ou droit de la souris pour les diverses actions.
Et la touche space pour libérer le curseur pour l'accès au UI et de nouveau le Space pour revenir au jeu normal.

Je vais tenir compte de tes remarques. Personnellement je m'efforçais à tout regrouper sur la souris pensant qu'elle était préférée comme une manette de jeu en quelque sorte.

Merci Boubouk
La différence entre l'intelligence et la stupidité est que l'intelligence est limitée.

Avatar de l’utilisateur
boubouk50
ModoGenereux
ModoGenereux
Messages : 6225
Inscription : 28 Avr 2014 11:57
Localisation : Saint-Didier-en-Bresse (71)

Re: Emigmatics

Message par boubouk50 » 26 Avr 2024 11:32

Oui, c'est une bonne analyse, le gameplay sera plus agréable avec ce système.
Une manette de jeu possède bien plus de boutons qu'une souris, même les anciennes.
Une manette de Super Nintendo (1990) possède une croix directionnelle (Haut, Bas, Gauche, Droite), 4 boutons d'action (saut, courir, freiner, etc.), 2 boutons de menu (start/select) et 2 boutons gachettes (L et R).
C'est bien plus proche du clavier tout compte fait que de la souris.
"Ce n'est pas en améliorant la bougie, que l'on a inventé l'ampoule, c'est en marchant longtemps."
Nétiquette du forum
Savoir faire une recherche
Apprendre la programmation

Répondre

Revenir vers « Vos créations, jeux, démos... »