See site in english Voir le site en francais
Website skin:
home  download  forum  link  contact

Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length

Author Topic: [tutorial] Posez vos question sur les DLL C++ (no 2)  (Read 40481 times)

0 Members and 1 Guest are viewing this topic.

Offline no matter

  • Legend
  • ******
  • Posts: 2826
  • Karma: 1
Reply #75 - 07 June 2008, 17:18:29
Quote
Mon train rentre et sort seul au décollage et à l'atterrissage en l'asservissant à l'altitude et au sens de la
vitesse de montée et je suis assez content de moi. Il me reste à faire des tests plus complets pour voir qu'il n'y a pas
de blocage possible.
on commence comme çà, on fini avec des réserves d'o2, l'effet plasma pour la rentrée et les boutons des mfd qui
fonctionnent dans le VC.
Ton addon a donc un train d'atterro. A l'affût des infos ^^



Message modifié ( 07-06-2008 17:19 )

------------

no matter.

Offline Papyref

  • Legend
  • ******
  • Posts: 4897
  • Country: France fr
  • Karma: 224
  • Je suis dans la Lune ne pas me déranger
Reply #76 - 07 June 2008, 18:58:47
En fait je refait Hercule que l'on trouve sur le site Mustard et que tu dois connaître.
Je l'avais créé avec Spacecraft et je le reprends en dll.

Mon but est d'apprendre à créer en C++ et ce projet comprend pas mal d'animations: portes, train; RCS et dock
mobiles, un bras animé et un astronaute embarqué.
C'est utopique mais assez complet pour se faire la main.

Le train n'en est pas un a proprement parler car il est constitué par des trappes, des jambes et des patins vu que le
bazar est a décollage vertical et ne posséde pas d'ailes.
L"animation consiste à ouvrir ou fermer les trappes en rotation et déplacer les jambes en translation en même temps
que les patins qui sont enfants par rapport aux jambes et effectuent une petite rotation.

Je profite de la reprise pour faire des asservissements qui n'étaient pas réalisables avec Spacecraft.
Ca prends forme mais j'ai encore du travail et je n'en suis pas au plasma et au VC !

Pas classé Secret !!!

:sage: Papyref


Offline Etudiant spatial

  • Legend
  • ******
  • Posts: 1204
  • Karma: 0
Reply #77 - 07 June 2008, 19:07:19
Bonjour! Je voudrais savoir comment on fait un add-on, j'en ai besoin, comme le disait brainstorm je crois, "oh! Jai
besoin de... et pouf! un add-on!" aidez-moi svp!



Offline Milouse

  • Legend
  • ******
  • Posts: 1401
  • Country: France fr
  • Karma: 125
Reply #78 - 07 June 2008, 21:00:23
Bonsoir,

Pour répondre à Etudiant spatial, et comme ce n'est pas le sujet du topic, je met juste un lien vers un autre topic plus
approprié et très intéressant :
http://orbiter.dansteph.com/forum/index.php?topic=6456.msg98189#msg98189
Après lecture, et si vous vous lancez dans l'aventure, n'hésitez pas un créer un topic pour expliquer précisément les
problèmes rencontrés.

Milouse



Offline DanSteph

  • Administrator
  • Legend
  • *****
  • Posts: 15002
  • Karma: 178
  • Hein, quoi !?
    • FsPassengers
Reply #79 - 08 June 2008, 07:31:25
Quote
Papyref a écrit:
C'est utopique mais assez complet pour se faire la main.

C'est surtout en très bonne voie... lâche pas papy ! ;)

Une grande nouveauté surtout: Spacecraft est vraiment un super outil mais tu étais en "limite haute", tu n'aurais pas pu faire beaucoup plus. Avec le C++ tu n'a pratiquement plus aucune limite à part le temps que tu peux y consacrer.

A++

Dan



Message modifié ( 08-06-2008 09:24 )


Offline Papyref

  • Legend
  • ******
  • Posts: 4897
  • Country: France fr
  • Karma: 224
  • Je suis dans la Lune ne pas me déranger
Reply #80 - 08 June 2008, 11:29:53
Je ne lache pas cher maitre !

Pour le prouver voilà deux images.
Une d'Hercule posé toutes issues ouvertes et une après début de montée ou les automatismes ont fermés la soute
si on ne l'a pas fait manuellement (j'ajouterai peut être un bip d'alarme), rentré le train, le dock, les rétros et fermé la
salle pour être prêt à affronter la montée en atmosphère.
Si il n'y a pas d'atmosphère, seuls le train et la soute sont maneuvrés.

Il est vrai qu'avec C++ on s'épanouit...

Avant décollage


Tout se ferme en montée


Je vais attaquer le bras robotique et ça sera peut être un peu plus délicat !

:sage: Papyref


Offline no matter

  • Legend
  • ******
  • Posts: 2826
  • Karma: 1
Reply #81 - 08 June 2008, 12:24:14
Quote
(j'ajouterai peut être un bip d'alarme)
peut-être un peu hors sujet mais on peut trouver plein de sons ici (alrme avions, gpws etc...):
http://www.simphonics.com/library/WaveFiles/


------------

no matter.

Offline DanSteph

  • Administrator
  • Legend
  • *****
  • Posts: 15002
  • Karma: 178
  • Hein, quoi !?
    • FsPassengers
Reply #82 - 09 June 2008, 03:01:19
Quote
Papyref a écrit:
Je vais attaquer le bras robotique et ça sera peut être un peu plus délicat !

C'est sur ! Mais comme dis le proverbe: "plus on peste plus on a de... euh.. vestes" !?

...Attend non c'est pas ça ! :sick:

Je réessaie: "Plus on peste... plus on fait... la sieste ?"

Ah non je hais les proverbes !!!.... :rant:

Enfin bref ! on est super content quand ça marche quoi. :badsmile:

Bras robotique ? mhhhh dans le principe c'est pas *trop* compliqué faut bien être stricte et propre avec les
parents/enfants, plus difficile est de rendre la chose conviviale et aisée à utiliser.

De loins le plus dur/long en prog en fait c'est souvent l'interface pour que les gens utilisent nos "routines".

A++

Dan



Message modifié ( 10-06-2008 14:55 )


Offline DanSteph

  • Administrator
  • Legend
  • *****
  • Posts: 15002
  • Karma: 178
  • Hein, quoi !?
    • FsPassengers
Reply #83 - 09 June 2008, 03:10:05
mhhh petit conseil:

Souvent il y a un moment "chaud" ou on doit trouver les principes, "comment faire" pour cela on essaie et test pas
mal de choses et ca fini en total désordre, code mal et vite fait mélangé avec des essais infructueux. Ne pas hésiter à
faire donc du code temporaire "bordelique" et une fois que ca marche et qu'on sait "comment", penser le truc avec les
nouvelles connaissances acquise et réecrire au propre.

J'utilise souvent dans ces cas des routines avec des noms "test" ou "temp" (ie: "temp_altitude") facile à enlever après coup.  Sinon c'est comme une maison: à force de batir sur du fragile ça fini par s'écrouler sous le poids des bugs ou du fouilli incompréhensible.

Après chacun à son style j'imagine, certain sont hyper clean et posé depuis le début ?

Dan



Message modifié ( 09-06-2008 03:25 )


Offline Papyref

  • Legend
  • ******
  • Posts: 4897
  • Country: France fr
  • Karma: 224
  • Je suis dans la Lune ne pas me déranger
Reply #84 - 09 June 2008, 07:41:52
Exact le b... est latent avec ce genre de choses.
Je mets au point sur deux éléments pour commencer et ensuite ce sera plus facile.


J'avance pas à pas et je suis en train de me gratter la tête pour réaliser un arrêt en cours du mouvement et une
inversion.
Ensuite je cogiterai sur le graping puis l'interface.


Quand j'aurais fini je prendrai des vacances :)

:sage: Papyref


Offline Papyref

  • Legend
  • ******
  • Posts: 4897
  • Country: France fr
  • Karma: 224
  • Je suis dans la Lune ne pas me déranger
Reply #85 - 09 June 2008, 09:59:36
On peut définir la commande d'ouverture ou de fermeture d'une porte de deux façons comme par exemple:

Quote
void Hercule::RevertPorte ()
{
   if (Porte_status == DOOR_CLOSED|| Porte_status == DOOR_CLOSING)
   {
      Porte_status = DOOR_OPENING;
   }
   else if (Porte_status == DOOR_OPENING|| Porte_status == DOOR_OPEN)
   {
      Porte_status = DOOR_CLOSING;
   }
}

ou

Quote
void Hercule::RevertPorte ()
{
   Porte_status = ((Porte_status == DOOR_CLOSED|| Porte_status == DOOR_CLOSING)?
   DOOR_OPENING:DOOR_CLOSING);
}

L'une des définitions est elle préférable ?

Papyref


Offline DanSteph

  • Administrator
  • Legend
  • *****
  • Posts: 15002
  • Karma: 178
  • Hein, quoi !?
    • FsPassengers
Reply #86 - 09 June 2008, 12:02:31
Ca revient strictement au même, la deuxième c'est "luxe le savon des stars", c'est une notation courte, "pro".
Si tu a des problèmes à la comprendre utilise la première. (Perso c'est celle que j'utilise, très verbeuse et visuelle
donc compréhensible en un éclair, c'est important) A la compilation ca revient au même de toute façon.

Question optimisation le C++ est incroyablement rapide, tu pourrais mettre 20'000 fois ces lignes
dans la fonction sans constater aucune différence de FPS.  

C'est une question d'endroit aussi, cette fonction n'est utilisée qu'une fois tout les milliers de frames,
il faut être plus précautioneux dans clbkPostStep (je veux dire, ne pas mettre 20'000 fois ces lignes ;) )

Une chose importante c'est d'être capable "d'executer" le code dans sa tête comme le ferait l'ordi.
Il faut être capable de voir le bug dans celle la par exemple en "l'executant" avec différents cas:

Code: [Select]
void Hercule::RevertPorte ()
{
     if (Porte_status == DOOR_CLOSED|| Porte_status == DOOR_OPEN)
     {
          Porte_status = DOOR_OPENING;
     }
     else if (Porte_status == DOOR_OPENING|| Porte_status == DOOR_OPEN)
     {
          Porte_status = DOOR_CLOSING;
     }
}


Réponse du Bug: Une fois la porte ouverte elle resterais bloquée dans cette position

A++

Dan



Message modifié ( 09-06-2008 12:04 )


Offline orbiter28

  • Legend
  • ******
  • Posts: 2680
  • Karma: 15
Reply #87 - 09 June 2008, 13:45:38
Je suis étonné de voir que j'ai compris toute ta première partie, et absolument rien à la seconde :damn:, alors que les deux
parties fond la même chose.


Offline DanSteph

  • Administrator
  • Legend
  • *****
  • Posts: 15002
  • Karma: 178
  • Hein, quoi !?
    • FsPassengers
Reply #88 - 09 June 2008, 14:40:46
Pour le bras robotique:

Oublie pas une chose non plus, les DOOR_CLOSING et tout ca ce ne sont que des "flags" une methode qu'à "inventé"
martin pour controller la seule variable qui active l'animation la variable ***_proc qui est passée a "SetAnimation",
ces flags permettent grace au petit bloc dans clbkPostStep de faire passer la variable ***_proc de 0 a 1 et
inversement.

On aurais pu utiliser d'autre methodes mais celle à martin est élégante *dans ce cas précis*.

Par contre pour un bras ou tu veux le controle sur toute la course et pas seulement passer d'un etat a l'autre
automatiquement (ferme/ouvert)  cette methode n'est plus adéquate. (les DOOR_CLOSING etc etc j'entend)

Tu va devoir controller précisement les variables ***_proc pour bouger l'animation au millimetres.

Pour garder la souplesse d'animation il va donc te falloir une variable qui contient quel position tu *demande* et dans
clbkPostStep un petit block sera en charge de faire bouger la variable ***_proc jusqu'à quelle "rejoigne" la valeur
demandée en douceur et un SetAnimation pour bouger le bras.

Exemple, variables requises: (a sauver dans le scenario)

Code: [Select]
dAvantBras_proc            // de 0 a 1, variable passée à SetAnimation, position de l'avant bras
dAvantBras_request      // de 0 a 1, variable qui demande une position de l'avant bras.


Le but donc c'est pas exemple si tu demande une position au millieux de l'avant bras "dAvantBras_request=0.5f;" il
existe une routine dans clbkPostStep qui fera passer automatiquement la variable "dAvantBras_proc" de sa position
actuelle à celle demandée (0.5), le tout en douceur en tenant compte de la vitesse/fps.

On peut utiliser plusieurs methodes donct certaines plus avancées qui tiendrais compte de l'amortissement (inertie
demarrage/arret, vitesse +rapide quand on est loin de la position)

Autre contrainte: une fois en bonne position la routine Setanimation ne doit plus etre activée, le block doit
etre "inerte" à ce moment. (pour éviter que martin ne declenche des calculs 3d complexe juste pour remettre le mesh
animé au meme endroit)

Pour bien comprendre le principe la methode la plus basique (pourrie) serait celle la:

Code: [Select]
// Bouge l'avant bras d'après la valeur demandée "dAvantBras_request"
if(dAvantBras_proc<dAvantBras_request)
{
     dAvantBras_proc+=0.1f;
}
else
{
     dAvantBras_proc-=0.1f;
}
SetAnimation(bidule,dAvantBras_proc);

La valeur effective proc va "rejoindre" toujours celle demandée par "request". Mais cette methode est inepte car on
ne tient pas compte du FPS, le bras va sauter continuellement de +-0.1 autour de la bonne valeur et Setanimation
sera appellée chaque frame même quand le bras sera quasi à la bonne position.

A vue de groins celle la est encore basique mais marche parfaitement sans les défauts précédents:

Code: [Select]
// Bouge l'avant bras d'après la valeur demandée "dAvantBras_request"
if(dAvantBras_Request!=dAvantBras_Proc)
{
double dg =simdt*0.02f; // vitesse en fonction du FPS
if(dAvantBras_Proc<dAvantBras_Request-dg)
{
dAvantBras_Proc+=dg;
}
else if(dAvantBras_Proc>dAvantBras_Request+dg)
{
dAvantBras_Proc-=dg;
}
else
{
// la valeur est très proche, met la egale donc
// désactive ce bloque d'animation la prochaine boucle
dAvantBras_Proc=dAvantBras_Request;
}
SetAnimation (uAnim_AvantBras , dAvantBras_Proc);
}


Maintenant ce qui serais sympa c'est de pouvoir faire nos demande de 0° a 360° plutot que de 0 à 1. C'est plus
parlant pour un humain. Donc on pourrait utiliser des variables "proc et request" dans ces limites la et simplement
diviser la valeur proc par 360 juste avant de la passer à SetAnimation.

Voila qui est parfaitement fonctionnel, grace aux touche clavier ou a un panel on met la valeur "dAvantBras_Request"
à une position de 0° a 360° et le bras rejoindra doucement cet angle la:

Code: [Select]
// Bouge l'avant bras d'après la valeur demandée "dAvantBras_request"
// demande de 0° a 360°
if(dAvantBras_Request!=dAvantBras_Proc)
{
// protection contre une valeur request "out of range"
// limite a 0-360 la valeur.
dAvantBras_Request=min(360,max(0,dAvantBras_Request));
double dg =simdt*5.0f; // vitesse en fonction du FPS
if(dAvantBras_Proc<dAvantBras_Request-dg)
{
dAvantBras_Proc+=dg;
}
else if(dAvantBras_Proc>dAvantBras_Request+dg)
{
dAvantBras_Proc-=dg;
}
else
{
// la valeur est très proche, met la egale donc
// désactive ce bloque d'animation la prochaine boucle
dAvantBras_Proc=dAvantBras_Request;
}
SetAnimation (uAnim_AvantBras , dAvantBras_Proc/360.0f);
}

Avec ca tu peux permettre à l'utilisateur de controller la valeur dAvantBras_Request de 5° ou 1° par les touches clavier, l'avant bras rejoindra doucement la position demandée.

Après on peut rentrer dans la complexité avec inertie demarrage/arret, gestion "intelligente" de la vitesse en  millieu
de course voir "vitesse variable" définie par utilisateur (rapide/lent) mais ca sort du cadre d'un post "introduction"
La vitesse étant faible par définition ca peut marcher comme cela sans choquer vraiment. (mais avec un bras de 10m
ca pourrait donner pas mal de l'inertie)

Mais je suis pret a plancher sur un truc plus complexe dans un prochain post :badsmile:

A++

Dan



Message modifié ( 09-06-2008 15:20 )


Offline DanSteph

  • Administrator
  • Legend
  • *****
  • Posts: 15002
  • Karma: 178
  • Hein, quoi !?
    • FsPassengers
Reply #89 - 09 June 2008, 16:37:23
Bon j'ai fais une routine "à inertie" juste par interet si jamais c'est dispo.

Remarque sur la routine "Bras Robotique":

Comme on a pleins d'éléments du bras a bouger on va ce retrouver avec des dizaines de lignes
qui vont faire la même chose juste avec des variables différentes. Ca fait un gros paquet de lignes
répétitive donc dur a modifier et à lire. Typiquement le truc à remplacer par une fonction.

Le code plus haut n'a besoin que de trois variables, deux variables anim et le numéro de l'animation
pour "SetAnimation".

Dès lors on pourrait creer une fonction "animation" dans le genre:

Code: [Select]
ProcessBrasAnimation(UINT NoAnimation,double * dProc,double *dRequest)
Avec un seul "corp" de fonction générique pour toutes les parties du bras.

Dans clbkPostStep au lieu d'une centaines de lignes indigeste on aurait un truc dans le genre:

Code: [Select]
ProcessBrasAnimation(uAnim_AvantBras,&dAvantBras_Proc,&dAvantBras_Request);
ProcessBrasAnimation(uAnim_Bras, &Bras_Proc,  &Bras_Request);
ProcessBrasAnimation(uAnim_Epaule, &dEpaule_Proc,  &dEpaule_Request);
ProcessBrasAnimation(uAnim_Poignet, &dPoignet_Proc,  &dPoignet_Request);

Beaucoup plus lisible, en plus si on veut changer la routine d'animation elle même on a qu'un
seul bloc à modifier et c'est beaucoup plus lisible.

Mon coeur de programmeur 3d s'indigne de ces 5 calls inutiles dans la boucle principale, mais le gain en lisibilité du projet est conséquent. Pour pallier le defaut on peut "proteger" les fonction de l'execution. comme ceci:

Code: [Select]
if(dAvantBras_Request!=dAvantBras_Proc)
        ProcessBrasAnimation(uAnim_AvantBras,&dAvantBras_Proc,&dAvantBras_Request);
if(Bras_Request!=Bras_Proc)
        ProcessBrasAnimation(uAnim_Bras, &Bras_Proc,  &Bras_Request);
if(dEpaule_Proc!=dEpaule_Request)
        ProcessBrasAnimation(uAnim_Epaule, &dEpaule_Proc,  &dEpaule_Request);
if(dPoignet_Request!=dPoignet_Proc)
        ProcessBrasAnimation(uAnim_Poignet, &dPoignet_Proc,  &dPoignet_Request);

Ou déclarer la fonction inline, (pour ceux qui connaissent).

Voila, rien que des avantages. je déteste lire la section "animation" dans le DGIV, 3km de lignes pareilles qui font la même chose avec juste des variables différentes, j'aurais du faire comme ci-dessus (mais j'était jeune ;) )

A++

Dan



Message modifié ( 09-06-2008 17:43 )


Offline Papyref

  • Legend
  • ******
  • Posts: 4897
  • Country: France fr
  • Karma: 224
  • Je suis dans la Lune ne pas me déranger
Reply #90 - 09 June 2008, 18:43:25
Merci pour ces renseignements.

Moi aussi je trouve que j'écris trop de lignes mais il faut d'abord que ça marche et ensuite on peut envisager de faire
plus sioux avec l'expérience.

Je vais 3 jours à Carnac pour me laver le citron et je ne ferai pas de robotique mais de la bouffe-balade.
Il faut s'oxygener les méninges C++sûr sinon mon vieux cerveau va perdre beaucoup trop de neurones :)

:sage::sage::sage: Papyref


Offline DanSteph

  • Administrator
  • Legend
  • *****
  • Posts: 15002
  • Karma: 178
  • Hein, quoi !?
    • FsPassengers
Reply #91 - 09 June 2008, 21:34:01
Quote
Papyref a écrit:
Moi aussi je trouve que j'écris trop de lignes mais il faut d'abord que ça marche et ensuite on peut envisager de faire
plus sioux avec l'expérience.

Ben c'est la ou c'est malin: si ca marche pour une section ca marchera aussi pour toutes les autres
sans ecrire en plus une centaines de lignes. Suffit de trois variables et de rajouter la fonction.
En plus si t'est pas satisfait de la routine au lieu d'en modifier 5 tu modifie juste la générique.

Quote
Papyref a écrit:
Il faut s'oxygener les méninges C++sûr sinon mon vieux cerveau va perdre beaucoup trop de neurones :)

Bah il "parait" qu'on utilise 1/3 du cerveau seulement donc t'a de quoi voir venir :badsmile:

A++

Dan

PS publique: c'est une légende urbaine les 1/3, les seul qui font ca sont les cadavres de fraiche date.


Offline brainstorm

  • Legend
  • ******
  • Posts: 2694
  • Karma: 0
Reply #92 - 09 June 2008, 21:49:48
hum moins de 10 % parait il .... ;)



Offline DanSteph

  • Administrator
  • Legend
  • *****
  • Posts: 15002
  • Karma: 178
  • Hein, quoi !?
    • FsPassengers
Reply #93 - 10 June 2008, 02:01:39
Quote
brainstorm a écrit:
hum moins de 10 % parait il .... ;)

Après réflexion c'est certainement vrai pour ceux qui ont inventés cette légende ;)

Dan



Message modifié ( 10-06-2008 02:55 )


Offline Papyref

  • Legend
  • ******
  • Posts: 4897
  • Country: France fr
  • Karma: 224
  • Je suis dans la Lune ne pas me déranger
Reply #94 - 14 June 2008, 17:03:26
Pour déplacer la rotule de mon bras vers l'avant ou l'arrière de la soute d'Hercule, j'écris dans clbkConsumeBufferKey
pour ajuster ma dShiftZ_proc avec dShiftZ_request (voir méthode Dan):

Quote
case OAPI_KEY_LEFT:  // Deplacement longitudinal avant de la rotule
      if (dShiftZ_request <= 0.95) dShiftZ_request = dShiftZ_request + 0.05;
      return 1;

case OAPI_KEY_RIGHT:  // Deplacement longitudinal arrière de la rotule
      if (dShiftZ_request >= 0.05) dShiftZ_request = dShiftZ_request - 0.05;
      return 1;

Ce n'est pas terrible mais ça marche et ça permet de mouvoir le bras par incréments de 0.05 de 0 à 1 et vice versa.
L'ennui est bien sûr qu'il faut une impulsion sur flèche gauche ou droite chaque fois que l'on veut faire un petit
déplacement supplémentaire et ce n'est pas continu.

Mon idée serait de faire un déplacement dans un sens ou dans l'autre en faisant une incrémentation automatique
tant qu'on tient le bouton enfoncé (on pourrait afficher en même temps la valeur de consigne à atteindre) et en
relachant on attendrait que le déplacement soit terminé ou alors on pourrait rectifier la consigne avant la fin du
déplacement.
 
A ma grande honte je ne trouve pas de solution adéquate faute de savoir tester correctement l'enfoncement
temporaire de la touche et de plus si je crée une boucle pour incrémenter j'ai peur que le déplacement de la consigne
soit trop rapide.

Quelqu'un peut-il m'aider ?
Merci

:sage::sage: Pauvre vieux Papy épuisé !


Offline DanSteph

  • Administrator
  • Legend
  • *****
  • Posts: 15002
  • Karma: 178
  • Hein, quoi !?
    • FsPassengers
Reply #95 - 14 June 2008, 17:46:41
Deux methodes à mon avis:


clbkConsumeBufferKey recoit tout les événements clavier ceux ci sont de deux natures:

1-Enfoncement de la touche: événement "down"
2-Relachement de la touche: événement "up"

Au début de la fonction "clbkConsumeBufferedKey" un petit bout de code rejette les événements "up" pour ne garder
que les enfoncements "down". (sinon chaque appui déclencherait l'action voulue deux fois, une à l'appui, une au
relachement)

Code: [Select]
// ne traite que quand la touche est enfoncée pas quand elle remonte
if (!down)
return 0;

Tout ce qui est après ne sera executé qu'après un enfoncement de la touche.

En utilisant ce savoir tu pourrais faire un flag, à l'enfoncement il déclencherais l'animation et au relachement
arreterais l'animation. Un peu compliqué mais valable.



L'autre méthode plus simple à mon avis utilise les fonctions que j'ai posté plus haut avec des variables "request" et
un callback spécial d'orbiter qui s'execute à chaque "PostStep" et permet de tester l'appui ou non d'une touche:

clbkConsumeDirectKey
Keyboard handler. Called at each simulation time step. This callback function allows
the installation of a custom keyboard interface for the vessel.


Dans cette fonction une macro "KEYDOWN" permet de tester si une touche est enfoncée ou non à chaque "image"

Code: [Select]
int Hercule::clbkConsumeDirectKey(char *kstate)
{
                   if(KEYDOWN(kstate,OAPI_KEY_T)
                   {
                           // si ici, touche T appuyée en ce moment
                   
                   }
}


Le but serais le suivant: incrémenter la variable "Request" si la touche est enfoncée pour qu'elle soit toujours un chouia devant la valeur actuelle (carotte devant le nez), mais attention comme cette incrémentation serais faite à chaque image en une secondes tu atteindrais une valeur "request" limite. (1.0 ou 0.0) Il faut donc l'incrémenter mais que de la "valeur actuelle de position du bras" + "un petit chiffre" "0.05" par exemple. pour que la "carotte" reste bien juste "devant le nez"

Un peu dans le genre:

Code: [Select]
int Hercule::clbkConsumeDirectKey(char *kstate)
{
                   if(KEYDOWN(kstate,OAPI_KEY_LEFT)
                   {
                           dAvantBras_Request=dAvantBras_Proc+0.05;
                           dAvantBras_Request=min(1.0,max(0.0,dAvantBras_Request)); // limite
                   }
                   else if(KEYDOWN(kstate,OAPI_KEY_RIGHT)
                   {
                           dAvantBras_Request=dAvantBras_Proc-0.05;
                           dAvantBras_Request=min(1.0,max(0.0,dAvantBras_Request)); // limite
                   }
}

-Oublie pas de limiter "dAvantBras_Request" dans cette fonction pour pas qu'il n'excede 0.0 ou 1.0 (utilise min/max)

C'est bon ? (sinon je te fais plus de code) ;)

A++

Dan



Message modifié ( 14-06-2008 17:55 )


Offline Papyref

  • Legend
  • ******
  • Posts: 4897
  • Country: France fr
  • Karma: 224
  • Je suis dans la Lune ne pas me déranger
Reply #96 - 14 June 2008, 18:11:19
Merci Speedy Dan,

Je vais essayer de me débrouiller avec ces éléments.
Si je coince je referai appel à ta grande sagesse !

Papy


Offline Papyref

  • Legend
  • ******
  • Posts: 4897
  • Country: France fr
  • Karma: 224
  • Je suis dans la Lune ne pas me déranger
Reply #97 - 15 June 2008, 18:07:05
Question bête !

Je crée une variable iControle bras qui va me servir à controler la prise de commande du bras et une variable
iControlPartBras qui va désigner ensuite en cyclant par la touche fléche UP quelle partie du bras va être déplacée en
agissant sur les touches flêches LEFT et RIGHT

J'écris (probablement pas génialement mais ça marche) dans clbkConsumeBufferKey à l'endroit adéquat et avec les
initialisations iControlBras=0;  iControlPartBras=1;

Quote
case OAPI_KEY_SPACE:

         // Controle du bras demandé ou non par CTRL + SPACEBAR
         // La variable iControlBras va servir d'inverseur
         // A 1 le bras est sous controle, a 0 il ne l'est pas

         iControlBras = iControlBras + 1;
           if (iControlBras >1)
         {
            iControlBras =0 ;
         }
         return 1;
      }   

case OAPI_KEY_UP:

         // On cycle avec la fléche UP pour choisir quelle partie du bras
         // sera controlée par les fléches LEFT et RIGHT

         if (iControlBras == 1)
         {
         iControlPartBras = iControlPartBras + 1;
           if (iControlPartBras >7)
         {
            iControlPartBras =1 ;   
         }
         }
      }   

et toujours dans clbkConsumeBufferKey dans le handler traitant l'appui fugitif

Quote
int Hercule::clbkConsumeDirectKey (char*kstate)
{
if (iControlBras == 1) // Le bras est sous controle pour la translation longitudinale
{
   if(KEYDOWN (kstate,OAPI_KEY_LEFT) && iControlPartBras == 1) // La partie 1 est choisie
   {
      dShiftZ_request = dShiftZ_proc + 0.01;
      dShiftZ_request = min(1.0,max(0.0,dShiftZ_request));
   }
   else if(KEYDOWN (kstate,OAPI_KEY_RIGHT)&& iControlPartBras == 1)
   {
      dShiftZ_request = dShiftZ_proc - 0.01;
      dShiftZ_request = min(1.0,max(0.0,dShiftZ_request));
   }

Une chose me surprend.
Les variables iControlBras et iControlPartBras sont des entiers mais je dois écrire iControlBras ==1 et
iControlPartBras  ==1 pour que ça marche.
Pourquoi une équivalence et pas une égalité ?

:sage: Papyref rêveur


Offline MartySpaceLines

  • Legend
  • ******
  • Posts: 1096
  • Karma: 0
Reply #98 - 15 June 2008, 19:41:14
Ben je crois que dans les structures en if, il faut demander == (égal à), != (différent de), < (+ petit que), > (+ grand
que), <= (+ petit ou égal à), >= (+ grand ou égal à), || (ou), && (et).
C'est comme ça ;).

Mais ta variables iControlBras doit contenir deux valeurs, non??
Si tel est le cas, c'est mieux de prendre une variable de type "booléenes", qui peut soit être TRUE, soit FALSE.
Dans ton code, ça donnerait ça:

Code: [Select]

bool bControlBras = false;

   if (bControlBras) //Si bControlBras est true
   {
      ...
   }

   if (!bControlBras) //Si bControlBras est false
   {
      ...
   }

Ensuite, petit truc pour ajouter un à une variable (indentation):

Au lieu d'écrire
Code: [Select]
iControlBras = iControlBras + 1; //Très long...

On peut aussi mettre
Code: [Select]
iControlBras++;

Cela marche aussi avec les moins:
Code: [Select]
iControlBras--;



Message modifié ( 15-06-2008 19:49 )

@++

MSL  


Offline DanSteph

  • Administrator
  • Legend
  • *****
  • Posts: 15002
  • Karma: 178
  • Hein, quoi !?
    • FsPassengers
Reply #99 - 15 June 2008, 19:45:47
Quote
Les variables iControlBras et iControlPartBras sont des entiers mais je dois écrire iControlBras ==1 et
iControlPartBras ==1 pour que ça marche.

Tu veux dire dans le "if" ? les conditions prennent toujours un double "==" c'est une convention d'écriture.

Si tu fait "if(iControlPartBras =1)" Tu assigne la valeur 1 au lieu de comparer. Depuis la version 2005 le
compilateur grogne si on ecrit comme cela mais avant ce n'était pas le cas et c'était une source d'erreur la condition
étant toujours vraie et la variable prenant la valeur au lieu de comparer.

Donc "egal" s'ecrit toujours "==" Le "non egal" s'ecrit "!=" plus grand et plus petit eux s'écrivent "<" et ">"

Par contre en lisant je me dis que ce serait logique d'augmenter la valeur iControlPartBras avec "UP" et la descendre
avec "DOWN". Si le gars controle le "poignet 7" et qu'il veut controller "l'avant bras 6" il devra presser 7 fois sur UP.
Pas très pratique.

A++

Dan