<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[C]]></title><description><![CDATA[C]]></description><link>https://melinyel.net/category/43</link><generator>RSS for Node</generator><lastBuildDate>Wed, 02 Sep 2026 04:05:51 GMT</lastBuildDate><atom:link href="https://melinyel.net/category/43.rss" rel="self" type="application/rss+xml"/><pubDate>Tue, 26 Dec 2017 17:27:16 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Formation Vidéo le projet de Jason Champagne]]></title><description><![CDATA[&lt;p&gt;
&lt;span style="font-family:Verdana, Geneva, sans-serif;"&gt;&lt;span style="color:#ff8c00;"&gt;&lt;span style="font-size:24px;"&gt;PRESENTATION DE LA FORMATION &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-size:20px;"&gt;La formation en langage C, est une formation d'un langage de programmation nommé le C, cette formation est entièrement gratuite, fait par un "amis" a moi, qui est un couteaux suisse dans le domaine de l'informatique, la formation abordera tout les sujet ou presque tout elle est vaste voici une petite liste de ce qui s'aura appris .&lt;/span&gt;
&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;
&lt;span style="font-size:20px;"&gt;Les base du langage &lt;/span&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;span style="font-size:20px;"&gt;Les structure de données :&lt;/span&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;span style="font-size:20px;"&gt;La SDL 2.0 &lt;/span&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;span style="font-size:20px;"&gt;La programmation système &lt;/span&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;span style="font-size:20px;"&gt;Le réseaux  &lt;/span&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;
&lt;span style="font-size:20px;"&gt;Tout ceci entièrement gratuit, et accessible a tous jeune est moins jeune . Bien sur des complément de cours seront aussi posté et sera mis a jour .&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Verdana, Geneva, sans-serif;"&gt;&lt;span style="color:#ff8c00;"&gt;&lt;span style="font-size:24px;"&gt;QUI EST VOTRE FORMATEUR &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-size:20px;"&gt;Il s'appelle &lt;a href="https://jasonchampagne.fr/" rel="external nofollow"&gt;Jason Champagne&lt;/a&gt; c'est formation son gratuites en ligne sur YouTube les formation sont vaste encore une fois, Programmation Informatique avec les langage C, python, C++, java qui a promis de faire, bien sur le développement web n'est pas laisser de coter les langage abordé seront PHP, HTML et CSS et JavaScript et dans un futur ruby etc... ;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-size:20px;"&gt;Il n' y a aussi le hacking éthique qui est abordé, mais comme je l'est dit les formation sont vaste, il y' a commencer une formation en Japonais, pour les amateur de manga vous voilla content j'imagine, mais pas que de dessins, de Français oui de Français, de musique il fait aussi des reprise de chant &lt;a href="https://www.youtube.com/watch?v=z4vGqar4ThM&amp;amp;list=PLd2ajeT6F5fkUrXViPJBOVT6X6szrmE0P" rel="external nofollow"&gt;clic ici&lt;/a&gt; pour allez voir ; &lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-size:20px;"&gt;Les moteur de jeu aussi seront abordé dans un futur, unity, unreal engine notamment .&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="color:#ff8c00;"&gt;&lt;span style="font-family:Verdana, Geneva, sans-serif;"&gt;&lt;span style="font-size:24px;"&gt;OU REGARDER LES FORMATION PROPOSE &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Arial, Helvetica, sans-serif;"&gt;&lt;span style="font-size:20px;"&gt;Et bien sur YouTube les formation sont comme déjà dit gratuite, accessible pour tout le monde .&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:Arial, Helvetica, sans-serif;"&gt;&lt;span style="font-size:20px;"&gt;Voici la chaine qui se nomment &lt;a href="https://www.youtube.com/channel/UCS2e0hEJMhwd6bNscS60xTg" rel="external nofollow"&gt;Formation Vidéo&lt;/a&gt; , il faut allez voir dans la playlist tout les vidéo sont bien rangé par thème.&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="color:#ff8c00;"&gt;&lt;span style="font-family:Verdana, Geneva, sans-serif;"&gt;&lt;span style="font-size:24px;"&gt;INTRODUCTION &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Arial, Helvetica, sans-serif;"&gt;&lt;span style="font-size:20px;"&gt;&lt;span style="color:#ff8c00;"&gt;&lt;span style="font-family:Verdana, Geneva, sans-serif;"&gt;&lt;span style="font-size:24px;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="float:none;background-color:transparent;color:rgb(17,17,17);font-family:Roboto, Arial, sans-serif;font-size:18px;font-style:normal;font-variant:normal;font-weight:400;letter-spacing:normal;line-height:24px;text-align:left;text-decoration:none;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;"&gt;Langage C #1 - introduction &lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;span style="float:none;background-color:transparent;color:rgb(17,17,17);font-family:Roboto, Arial, sans-serif;font-size:18px;font-style:normal;font-variant:normal;font-weight:400;letter-spacing:normal;line-height:24px;text-align:left;text-decoration:none;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;"&gt;Description : &lt;/span&gt;
&lt;/p&gt;
&lt;div style="background-attachment:scroll;background-color:transparent;background-image:none;background-repeat:repeat;border-bottom-color:rgb(0,0,0);border-bottom-style:none;border-bottom-width:0px;border-left-color:rgb(0,0,0);border-left-style:none;border-left-width:0px;border-right-color:rgb(0,0,0);border-right-style:none;border-right-width:0px;border-top-color:rgb(0,0,0);border-top-style:none;border-top-width:0px;color:rgb(0,0,0);font-family:Roboto, Arial, sans-serif;font-size:14px;font-style:normal;font-variant:normal;font-weight:400;letter-spacing:normal;margin-bottom:0px;margin-left:0px;margin-right:0px;margin-top:0px;padding-bottom:0px;padding-left:0px;padding-right:0px;padding-top:0px;text-align:left;text-decoration:none;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;"&gt;
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬&lt;br/&gt;
● SITE PERSO : &lt;a href="https://www.youtube.com/redirect?v=90hGCMC3Chc&amp;amp;redir_token=onVFdsc1hehfkl1SjPqRzlhTVjd8MTUxNDM5NTUzMkAxNTE0MzA5MTMy&amp;amp;event=video_description&amp;amp;q=https%3A%2F%2Fjasonchampagne.fr" rel="external nofollow" style="color:rgb(39,147,230);font-size:14px;font-weight:400;line-height:normal;text-decoration:none;"&gt;https://jasonchampagne.fr&lt;/a&gt;&lt;br/&gt;
▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬&lt;br/&gt;&lt;br/&gt;
► Première séance sur le langage C.&lt;br/&gt;
Faisons ensemble une petite présentation du langage, de son histoire, et ce à quoi il peut vous servir.&lt;br/&gt;&lt;br/&gt;
██▄&lt;br/&gt;
Je n'utilise plus Skype, vous pouvez à la place utiliser Discord et m'ajouter en ami sur ce logiciel (tutoriel ici : &lt;a href="https://www.youtube.com/redirect?v=90hGCMC3Chc&amp;amp;redir_token=onVFdsc1hehfkl1SjPqRzlhTVjd8MTUxNDM5NTUzMkAxNTE0MzA5MTMy&amp;amp;event=video_description&amp;amp;q=https%3A%2F%2Fgoo.gl%2FqXADCa" rel="external nofollow" style="color:rgb(39,147,230);font-size:14px;font-weight:400;line-height:normal;text-decoration:none;"&gt;https://goo.gl/qXADCa&lt;/a&gt;).&lt;br/&gt;
Pour me contacter en privé, utilisez donc de préférence Discord (si vous n'aimez pas les réseaux sociaux), sinon vous pouvez me retrouver sur Twitter, Facebook, Google+ et directement par e-mail.&lt;br/&gt;
██▄&lt;br/&gt;&lt;br/&gt;
MERCI DE VOTRE FIDÉLITÉ (◕_◕) !
&lt;/div&gt;
&lt;div style="background-attachment:scroll;background-color:transparent;background-image:none;background-repeat:repeat;border-bottom-color:rgb(0,0,0);border-bottom-style:none;border-bottom-width:0px;border-left-color:rgb(0,0,0);border-left-style:none;border-left-width:0px;border-right-color:rgb(0,0,0);border-right-style:none;border-right-width:0px;border-top-color:rgb(0,0,0);border-top-style:none;border-top-width:0px;color:rgb(0,0,0);font-family:Roboto, Arial, sans-serif;font-size:14px;font-style:normal;font-variant:normal;font-weight:400;letter-spacing:normal;margin-bottom:0px;margin-left:0px;margin-right:0px;margin-top:0px;padding-bottom:0px;padding-left:0px;padding-right:0px;padding-top:0px;text-align:left;text-decoration:none;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;"&gt;
&lt;div class="ipsEmbeddedVideo"&gt;
&lt;div&gt;
&lt;iframe allowfullscreen="true" data-embed-src="https://www.youtube.com/embed/videoseries?list=PLrSOXFDHBtfEh6PCE39HERGgbbaIHhy4j" frameborder="0" height="270" src="//melinyel.net/applications/core/interface/js/spacer.png" width="480"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div style="background-attachment:scroll;background-color:transparent;background-image:none;background-repeat:repeat;border-bottom-color:rgb(0,0,0);border-bottom-style:none;border-bottom-width:0px;border-left-color:rgb(0,0,0);border-left-style:none;border-left-width:0px;border-right-color:rgb(0,0,0);border-right-style:none;border-right-width:0px;border-top-color:rgb(0,0,0);border-top-style:none;border-top-width:0px;color:rgb(0,0,0);font-family:Roboto, Arial, sans-serif;font-size:14px;font-style:normal;font-variant:normal;font-weight:400;letter-spacing:normal;margin-bottom:0px;margin-left:0px;margin-right:0px;margin-top:0px;padding-bottom:0px;padding-left:0px;padding-right:0px;padding-top:0px;text-align:left;text-decoration:none;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;"&gt;
 
&lt;/div&gt;
&lt;div style="background-attachment:scroll;background-color:transparent;background-image:none;background-repeat:repeat;border-bottom-color:rgb(0,0,0);border-bottom-style:none;border-bottom-width:0px;border-left-color:rgb(0,0,0);border-left-style:none;border-left-width:0px;border-right-color:rgb(0,0,0);border-right-style:none;border-right-width:0px;border-top-color:rgb(0,0,0);border-top-style:none;border-top-width:0px;color:rgb(0,0,0);font-family:Roboto, Arial, sans-serif;font-size:14px;font-style:normal;font-variant:normal;font-weight:400;letter-spacing:normal;margin-bottom:0px;margin-left:0px;margin-right:0px;margin-top:0px;padding-bottom:0px;padding-left:0px;padding-right:0px;padding-top:0px;text-align:left;text-decoration:none;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;"&gt;
&lt;div class="ipsSpoiler" data-ipsspoiler=""&gt;
&lt;div class="ipsSpoiler_header"&gt;
&lt;span&gt;Révélation&lt;/span&gt;
&lt;/div&gt;
&lt;div class="ipsSpoiler_contents"&gt;
&lt;p&gt;
ABONNEZ VOUS SVP POUR QUE LA CHAINE SOIT CONNUES !
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
 
&lt;/p&gt;
&lt;/div&gt;
&lt;div style="background-attachment:scroll;background-color:transparent;background-image:none;background-repeat:repeat;border-bottom-color:rgb(0,0,0);border-bottom-style:none;border-bottom-width:0px;border-left-color:rgb(0,0,0);border-left-style:none;border-left-width:0px;border-right-color:rgb(0,0,0);border-right-style:none;border-right-width:0px;border-top-color:rgb(0,0,0);border-top-style:none;border-top-width:0px;margin-bottom:0px;margin-left:0px;margin-right:0px;margin-top:0px;padding-bottom:0px;padding-left:0px;padding-right:0px;padding-top:0px;"&gt;
 
&lt;/div&gt;
&lt;div style="background-attachment:scroll;background-color:transparent;background-image:none;background-repeat:repeat;border-bottom-color:rgb(0,0,0);border-bottom-style:none;border-bottom-width:0px;border-left-color:rgb(0,0,0);border-left-style:none;border-left-width:0px;border-right-color:rgb(0,0,0);border-right-style:none;border-right-width:0px;border-top-color:rgb(0,0,0);border-top-style:none;border-top-width:0px;margin-bottom:0px;margin-left:0px;margin-right:0px;margin-top:0px;padding-bottom:0px;padding-left:0px;padding-right:0px;padding-top:0px;"&gt;
&lt;h4 style="background-attachment:scroll;background-color:transparent;background-image:none;background-repeat:repeat;border-bottom-color:rgb(136,136,136);border-bottom-style:none;border-bottom-width:0px;border-left-color:rgb(136,136,136);border-left-style:none;border-left-width:0px;border-right-color:rgb(136,136,136);border-right-style:none;border-right-width:0px;border-top-color:rgb(136,136,136);border-top-style:none;border-top-width:0px;color:rgb(136,136,136);font-size:14px;font-weight:400;line-height:21px;margin-bottom:0px;margin-left:0px;margin-right:16px;margin-top:0px;padding-bottom:0px;padding-left:0px;padding-right:0px;padding-top:0px;width:110px;"&gt;
Catégorie
&lt;/h4&gt;
&lt;div style="background-attachment:scroll;background-color:transparent;background-image:none;background-repeat:repeat;border-bottom-color:rgb(0,0,0);border-bottom-style:none;border-bottom-width:0px;border-left-color:rgb(0,0,0);border-left-style:none;border-left-width:0px;border-right-color:rgb(0,0,0);border-right-style:none;border-right-width:0px;border-top-color:rgb(0,0,0);border-top-style:none;border-top-width:0px;margin-bottom:0px;margin-left:0px;margin-right:0px;margin-top:0px;padding-bottom:0px;padding-left:0px;padding-right:0px;padding-top:0px;"&gt;
&lt;a href="https://www.youtube.com/channel/UCiDF_uaU1V00dAc8ddKvNxA" rel="external nofollow" style="color:rgb(17,17,17);font-size:14px;font-weight:500;line-height:normal;text-decoration:none;"&gt;Science et technologie&lt;/a&gt;
&lt;/div&gt;
&lt;h4 style="background-attachment:scroll;background-color:transparent;background-image:none;background-repeat:repeat;border-bottom-color:rgb(136,136,136);border-bottom-style:none;border-bottom-width:0px;border-left-color:rgb(136,136,136);border-left-style:none;border-left-width:0px;border-right-color:rgb(136,136,136);border-right-style:none;border-right-width:0px;border-top-color:rgb(136,136,136);border-top-style:none;border-top-width:0px;color:rgb(136,136,136);font-size:14px;font-weight:400;line-height:21px;margin-bottom:0px;margin-left:0px;margin-right:16px;margin-top:0px;padding-bottom:0px;padding-left:0px;padding-right:0px;padding-top:0px;width:110px;"&gt;
Licence
&lt;/h4&gt;
&lt;div style="background-attachment:scroll;background-color:transparent;background-image:none;background-repeat:repeat;border-bottom-color:rgb(0,0,0);border-bottom-style:none;border-bottom-width:0px;border-left-color:rgb(0,0,0);border-left-style:none;border-left-width:0px;border-right-color:rgb(0,0,0);border-right-style:none;border-right-width:0px;border-top-color:rgb(0,0,0);border-top-style:none;border-top-width:0px;margin-bottom:0px;margin-left:0px;margin-right:0px;margin-top:0px;padding-bottom:0px;padding-left:0px;padding-right:0px;padding-top:0px;"&gt;
Licence YouTube standard
&lt;/div&gt;
&lt;/div&gt;
]]></description><link>https://melinyel.net/topic/1897/formation-vidéo-le-projet-de-jason-champagne</link><guid isPermaLink="true">https://melinyel.net/topic/1897/formation-vidéo-le-projet-de-jason-champagne</guid><dc:creator><![CDATA[Madzcore]]></dc:creator><pubDate>Tue, 26 Dec 2017 17:27:16 GMT</pubDate></item><item><title><![CDATA[[console/c] Todolist]]></title><description><![CDATA[&lt;p&gt;Bonjour, j'ai réalisé un petit projet qui a pour objectif de permettre à quelqu'un de réaliser une todolist.&lt;/p&gt;&lt;p&gt; Le lien de l'exécutable :  &lt;a class="attach-link" href="&lt;base_url&gt;/applications/core/interface/file/attachment.php?id=281"&gt;todolist.tar.gz&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Avec ce petit soft en console, vous pouvez :&lt;/p&gt;&lt;p&gt;*créer une todolist&lt;/p&gt;&lt;p&gt;*visualiser votre todolist&lt;/p&gt;&lt;p&gt;*supprimer votre todolist&lt;/p&gt;&lt;p&gt;*modifier votre todo list, en passant l'état de la tâche de 0 à 1, vous indiquez que vous avez finis cette tache.&lt;/p&gt;&lt;p&gt;A vous de tester :), le logiciel devrait être portable logiquement!&lt;/p&gt;&lt;p&gt;--&lt;/p&gt;&lt;p&gt;Execution : ./agenda&lt;/p&gt;
]]></description><link>https://melinyel.net/topic/1828/consolec-todolist</link><guid isPermaLink="true">https://melinyel.net/topic/1828/consolec-todolist</guid><dc:creator><![CDATA[Alemort]]></dc:creator><pubDate>Mon, 07 Mar 2016 06:24:42 GMT</pubDate></item><item><title><![CDATA[déclaration de structure dans un appel de fonction]]></title><description><![CDATA[&lt;p&gt;hey tout le monde !!!&lt;/p&gt;
&lt;p&gt;
petite question:&lt;/p&gt;
&lt;p&gt;
est-il possible en C, de déclaré et d'initialiser a la volée une structure dans un appel de fonction ?&lt;br/&gt;&lt;br/&gt;
exemple:&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
DrawText(SDL_Rect{500; 500; 500; 500}, score, BLANC, systeme);
&lt;/pre&gt;
&lt;p&gt;je suis presque sûr que oui, mais je dois mal m'y prendre ^^&lt;/p&gt;
]]></description><link>https://melinyel.net/topic/1475/déclaration-de-structure-dans-un-appel-de-fonction</link><guid isPermaLink="true">https://melinyel.net/topic/1475/déclaration-de-structure-dans-un-appel-de-fonction</guid><dc:creator><![CDATA[cegdd]]></dc:creator><pubDate>Wed, 21 Jan 2015 22:01:48 GMT</pubDate></item><item><title><![CDATA[[Question] Un FILE* en argument de fonction]]></title><description><![CDATA[&lt;p&gt;Hey, je commence un projet en C et j'ai un problème avec une fonction&lt;/p&gt;
&lt;p&gt;Je résume rapidement la fonction:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Un fichier texte est composé de plusieurs lignes, chaque ligne contient 3 chiffres, une coordonnnée x, une coordonnée y et une valeur à mettre à ces coordonnées dans la grille. La fonction remplie d'abord la grille avec des 0, puis récupères les valeurs du fichiers pour les insérer dans la grille aux bonnes coordonnées.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Ma fonction ne marche pas et fait planter le programme et j'ai vraiment du mal à la corriger, vous auriez une solution? (J'ai des doutes sur la syntaxe des arguments de la fonction...)&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
void lire_Grille(FILE* nomFichier[400],int grille[][9])
{
    int i, j;
    for (i=0; i&lt;9;i++)
    {
        for (j=0;j&lt;9;j++)
        {
            grille[i][j]=0;
        };
 
    };
    i = fgetc(nomFichier);
    do
    {
        j = fgetc(nomFichier);
        grille[i][j] = fgetc(nomFichier);
        k = fgetc(nomFichier);
        while (k==" " || k=="\n")
        {
            k=fgetc(nomFichier);
        };
        i = k;
    } while (i!=EOF);
}
&lt;/pre&gt;
]]></description><link>https://melinyel.net/topic/1446/question-un-file-en-argument-de-fonction</link><guid isPermaLink="true">https://melinyel.net/topic/1446/question-un-file-en-argument-de-fonction</guid><dc:creator><![CDATA[nell]]></dc:creator><pubDate>Sat, 10 Jan 2015 21:16:32 GMT</pubDate></item><item><title><![CDATA[[Cours] La programmation réseau]]></title><description><![CDATA[&lt;p&gt;Bonjour à tous,&lt;/p&gt;
&lt;p&gt;C'est un sujet aussi intéressent que difficile que nous allons voir aujourd'hui: Le réseau.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Nous allons découvrir le réseau de manière théorique et pratique, via ce cours.&lt;/p&gt;
&lt;p&gt;Nous allons voir tout ça via diverses parties. Tenez-vous bien, après la gestion mémoire, le réseau est la &lt;strong&gt;deuxième plus grosse difficulté&lt;/strong&gt; au niveau de la programmation (ce qui le rends très intéressent!), ce sera un cours principalement théorique (oui, je sais, j'en fais très TRES rarement), et du coup, vous y verrez que très peu de code.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Index:&lt;/p&gt;
&lt;p&gt;1- Le réseau, en théorie, c'est quoi?&lt;/p&gt;
&lt;p&gt;2- En pratique?&lt;/p&gt;
&lt;p&gt;3- Différence entre TCP, UDP et UDT (oui oui, ça existe).&lt;/p&gt;
&lt;p&gt;4- Quel type de données on peux envoyer en réseau?&lt;/p&gt;
&lt;p&gt;5- Synchrone? Asynchrone? Kesako?&lt;/p&gt;
&lt;p&gt;6- Un serveur de tchat synchrone (théorique).&lt;/p&gt;
&lt;p&gt;7- Notre tchat en version Asynchrone (théorique).&lt;/p&gt;
&lt;p&gt;8- Index des fonctions utiles en C (RTFM  ).&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:18px;"&gt;&lt;strong&gt;1- Le réseau, en théorie, c'est quoi?&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Le réseau définit un moyen pour deux programmes de pouvoir communiquer. Il existe deux définitions du réseau existantes: LAN et INET. De manière générale, le réseau LAN représente le réseau local (nous ne parlerons pas des réseaux VPN qui sont des exceptions à ce niveau là, puisqu'elles créent un réseau LAN virtuel), et les réseaux dis INET représentent les réseaux passant par internet. WOUHOUUUU!&lt;/p&gt;
&lt;p&gt;La partie théorique a l'aire plutôt bien simple! MAIS, et c'est là que le réseau deviens très cool à connaitre, c'est ULTRA-COMPLEXE à comprendre et en même temps pas si compliqué à mettre en place. Je vais donc essayer de ne pas vous perdre durant ce cours.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:18px;"&gt;&lt;strong&gt;2- En pratique?&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Eh oui, la description ci-dessus simplifie pas mal le fonctionnement du réseau au final. Si nous voulons mettre les mains dans le cambouis, il faut savoir pas mal de choses sur le réseau (bien que pas très importantes dans la programmation en elle même, ça vous permettra au moins de comprendre comment fonctionne le réseau de l’intérieur.&lt;/p&gt;
&lt;p&gt;Il faut savoir que la couche réseau est la 3ième couche du &lt;a href="http://fr.wikipedia.org/wiki/Modèle_OSI" rel="external nofollow"&gt;modèle OSI&lt;/a&gt; voyons un peu, pour avoir de la culture info, les 7 couches du modèle OSI:&lt;/p&gt;
&lt;p&gt;1- Physique (Le matériel de liaison, carte wifi, blutooth, etc...)&lt;/p&gt;
&lt;p&gt;2- Liaison (Gestion de la liaison et de la communication)&lt;/p&gt;
&lt;p&gt;3- Réseau (Gestion des couches réseau, IPv4, IPv6, etc...)&lt;/p&gt;
&lt;p&gt;4- Transport (Gère la communication en bout des processus, UDP, TCP, etc...)&lt;/p&gt;
&lt;p&gt;5- Session (Gère la synchronisation des communications et la gestion des "transactions")&lt;/p&gt;
&lt;p&gt;6- Présentation (Code les données applicatives)&lt;/p&gt;
&lt;p&gt;7- Application (Définit les points d'accès au service, Nous sommes ICI!)&lt;/p&gt;
&lt;p&gt;(je vous conseille de jeter un petit coup d’œil sur Wiki, c'est toujours un plus de savoir ce genre de choses  , pour vous donner une idée, nous les apprenons par cœur à Epitech (3ième année))&lt;/p&gt;
&lt;p&gt;La couche applicative est celle ou nous sommes lorsque nous développons un programme. Toutes les autres couches sont gérées par notre OS, qui fait tout le travail à notre place!&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Enfin, il faut retenir une chose TRES importante, et qui va beaucoup vous aider: les SOCKETS (système qui permet la communication en réseau) sont des &lt;a href="http://fr.wikipedia.org/wiki/Descripteur_de_fichier" rel="external nofollow"&gt;FD&lt;/a&gt;s (File descriptors), il sera donc géré comme un fichier, et il faudra toujours penser à FERMER LES SOCKETS! (laisser des FDs ouverts, c'moche! Pauvre kernel  )&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:18px;"&gt;&lt;strong&gt;3- Différence entre TCP, UDP et UDT (oui oui, ça existe).&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Ahhh, les protocoles de communication réseau (à ne pas confondre avec les protocoles applicatifs), beaucoup de choix, avec beaucoup de différences.&lt;/p&gt;
&lt;p&gt;Nous allons voir ça tout de suite:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1- Le TCP&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Le protocole &lt;strong&gt;TCP &lt;/strong&gt;est actuellement le plus stable et certainement le plus utilisé dans le domaine applicatif (ATTENTION: pas dans le jeu-vidéo). Le &lt;strong&gt;TCP &lt;/strong&gt;comporte 3 grand principes:&lt;/p&gt;
&lt;p&gt;- Les packets sont certains d'arriver.&lt;/p&gt;
&lt;p&gt;- Les packets arrivent dans l'ordre.&lt;/p&gt;
&lt;p&gt;- On a une réponse de la réception du packet par le client.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Et tout ça, grâce à un header implémenté dans le packet (oui, le packet est un peu plus lourd). Pour résumer, voici ce qui se passe lorsque vous envoyez un packet &lt;strong&gt;TCP&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;serveur = Envois du packet =&gt; client&lt;/p&gt;
&lt;p&gt;client = J'ai bien reçu le packet! =&gt; serveur&lt;/p&gt;
&lt;p&gt;serveur = Ok merci, j'ai bien reçu la réponse! =&gt; client&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Nous voyons donc qu'il y a &lt;strong&gt;3&lt;/strong&gt; envois réseau pour chaque packets, ce qui peux ralentir le réseau pour tout ce qui est temps-réel. ATTENTION NEANMOINS, au vue des connexions internet de nos jours, la différence ne se fait pratiquement pas ressentir.&lt;/p&gt;
&lt;p&gt;Néanmoins, dans la plupart des jeux, le &lt;strong&gt;TCP &lt;/strong&gt;permet de faire les actions importantes (envois de sorts, pop de monstres, etc...) et l'&lt;strong&gt;UDP &lt;/strong&gt;permet de gérer les actions moins importantes (Déplacements, etc...) pour éviter de surcharger la couche réseau. Même si certains jeux nous montrent bien que le Full &lt;strong&gt;TCP&lt;/strong&gt;, ça peux marcher aussi (RPZ World Of Warcraft).&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2- L'UDP&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;L'UDP de manière générale est plus simple, c'est un simple envois de packet ANONYME à un serveur.&lt;/p&gt;
&lt;p&gt;Cela offre une vitesse&lt;strong&gt; 3 fois plus rapide que le TCP&lt;/strong&gt; mais néanmoins, on ne sais absolument pas sur le packet est bien arrivé au destinataire.&lt;/p&gt;
&lt;p&gt;Il faut donc apprendre à manier le &lt;strong&gt;TCP &lt;/strong&gt;aussi bien que l'&lt;strong&gt;UDP &lt;/strong&gt;en fonction de ce qu'on veux faire.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2- L'UDT&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Le cas de l'&lt;strong&gt;UDT &lt;/strong&gt;est totalement différent, car c'est un protocole plutôt jeune qui a été créé pour pouvoir transporter un grand nombre de données (on parle ici de Téraoctets) sur un réseau généralement &lt;strong&gt;LAN&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Nous n'allons pas en parler ici, mais si vous souhaiter vous renseigner dessus, je vous conseille Wikipedia  .&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:18px;"&gt;&lt;strong&gt;4- Quel type de données on peux envoyer en réseau?&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Là est la question. Pour faire simple, qu'est-ce qui passe par du réseau, en soite? Eh bien, des données en &lt;strong&gt;BINAIRE&lt;/strong&gt;! Eh oui, c'est des 1 et des 0 qui passent dans nos câbles! On s'y attendais pas, hein? Pour résumer, tant que les données peuvent être stockées en mémoire (soite presque toutes), il est possible de les envoyer en réseau (eh oui, c'est pour ça que le réseau est considéré très proche de la gestion mémoire  ). D'une manière générale, faut pas faire l'imbécile, n'envoyez pas des pointeurs en réseau, puisque l'autre machine, n'aura pas allouée ce pointeur  . Il faut envoyer des données dites "flat", donc des données et non pas des adresses!&lt;/p&gt;
&lt;p&gt;Ce qui est très souvent fait, c'est d'envoyer des structures en réseau. ça permet pas mal de chose, mais c'est très peu modulable.&lt;/p&gt;
&lt;p&gt;Une autre technique, c'est de créer un &lt;strong&gt;packet&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Voici un exemple du contenu d'un packet:&lt;/p&gt;
&lt;p&gt;| taille des données dans le packet (4 octets) | données du packet.... |&lt;/p&gt;
&lt;p&gt;du coup, lorsqu'on reçois ce packet, on lit d'abord les 4 premiers octets pour savoir quelle est la taille du packet complet, et on lit le packet  .&lt;/p&gt;
&lt;p&gt;Bref, de la théorie tout ça! On verra dans un autre cours sur le réseau du code à proprement parlé!&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:18px;"&gt;&lt;strong&gt;5- Synchrone? Asynchrone? Kesako?&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Le principe de l'Asynchrone et du Synchrone se retrouve souvent dans les applications ayant plusieurs &lt;strong&gt;threads&lt;/strong&gt; (sous processus).&lt;/p&gt;
&lt;p&gt;Le principe du Synchrone, c'est d'avoir un thread qui exécute tout de manière Linéaire.&lt;/p&gt;
&lt;p&gt;Le principe de l'Asynchrone, c'est d'avoir plusieurs threads, ayant chacun un rôle et communicant entre eux.&lt;/p&gt;
&lt;p&gt;Dans notre cas, le Synchrone en réseau est nommé &lt;strong&gt;bloquant &lt;/strong&gt;alors que l'Asynchrone est nommé &lt;strong&gt;non bloquant&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Pour faire simple, dans un réseau &lt;strong&gt;bloquant&lt;/strong&gt;, nous attendrons que le client ait bien reçu les informations, alors que dans l'autre cas, nous envoyons les informations en NOWAIT (voir les mans des sockets) et du coup, nous n'attendons pas la réponse TCP. Ce qui nous renvois la taille des données envoyées, et dans le cas ou des données n'ont pas été envoyées, on les renvois.&lt;/p&gt;
&lt;p&gt;D'une manière générale, le côté &lt;strong&gt;bloquant &lt;/strong&gt;est utilisé dans les clients, alors que le côté &lt;strong&gt;non bloquant &lt;/strong&gt;est utilisé pour les serveurs (eh oui jamie! Si on est bloquant et qu'un client lag, on fait laguer tout le monde! Exemple concret: Starcraft II, mais là encore l'exemple est spécial, puisque SCII, c'est du P2P via servering).&lt;/p&gt;
&lt;p&gt;Pour l'&lt;strong&gt;UDP&lt;/strong&gt;, il n'est pas question d'être &lt;strong&gt;bloquant&lt;/strong&gt;, puisque nous ne savons pas quand le client reçoit l'information.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-size:18px;"&gt;6- Un serveur de tchat synchrone (théorique).&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A VENIR.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-size:18px;"&gt;7- Notre tchat en version Asynchrone (théorique).&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A VENIR.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:18px;"&gt;&lt;strong&gt;8- Index des fonctions utiles en C (RTFM  ).&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://man7.org/linux/man-pages/man2/socket.2.html" rel="external nofollow"&gt;- man 2 socket&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://man7.org/linux/man-pages/man2/select.2.html" rel="external nofollow"&gt;- man 2 select &lt;/a&gt;(une de mes fonctions préférées en C &lt;3)&lt;/p&gt;
&lt;p&gt;&lt;a href="http://man7.org/linux/man-pages/man2/accept.2.html" rel="external nofollow"&gt;- man 2 accept&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://man7.org/linux/man-pages/man2/bind.2.html" rel="external nofollow"&gt;- man 2 bind&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://man7.org/linux/man-pages/man2/connect.2.html" rel="external nofollow"&gt;- man 2 connect&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://man7.org/linux/man-pages/man2/listen.2.html" rel="external nofollow"&gt;- man 2 listen&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://man7.org/linux/man-pages/man2/read.2.html" rel="external nofollow"&gt;- man 2 read&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://man7.org/linux/man-pages/man2/write.2.html" rel="external nofollow"&gt;- man 2 write&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://man7.org/linux/man-pages/man2/recv.2.html" rel="external nofollow"&gt;- man 2 recv&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://man7.org/linux/man-pages/man2/send.2.html" rel="external nofollow"&gt;- man 2 send&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://man7.org/linux/man-pages/man7/ip.7.html" rel="external nofollow"&gt;- man 7 ip&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://man7.org/linux/man-pages/man7/socket.7.html" rel="external nofollow"&gt;- man 7 socket&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://man7.org/linux/man-pages/man7/tcp.7.html" rel="external nofollow"&gt;- man 7 tcp&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://man7.org/linux/man-pages/man7/udp.7.html" rel="external nofollow"&gt;- man 7 udp&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;A bientôt pour un prochain cours!&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;p&gt;AlexMog.&lt;/p&gt;
]]></description><link>https://melinyel.net/topic/1225/cours-la-programmation-réseau</link><guid isPermaLink="true">https://melinyel.net/topic/1225/cours-la-programmation-réseau</guid><dc:creator><![CDATA[AlexMog]]></dc:creator><pubDate>Tue, 28 Oct 2014 14:03:57 GMT</pubDate></item><item><title><![CDATA[Moteur physique #3]]></title><description><![CDATA[&lt;p&gt;Et voila la fin de la création d'un moteur physique !&lt;br/&gt;
Il ne nous restent plus qu'a détecter les collisions et les corriger, et le moteur est finit. :lol:  :lol:&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style="color:#ff0000;"&gt;&lt;span style="font-size:18px;"&gt;&lt;u&gt;&lt;strong&gt;Détection des collisions :&lt;/strong&gt;&lt;/u&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color:#008000;"&gt;&lt;u&gt;La théorie :&lt;/u&gt;&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;
Pour que deux rectangles soit en collisions, il faut qu'ils se "rentrent" dedans.&lt;br/&gt;
Pour cela, la distance (sur un seul axe pour l'instant) entre les deux points doit être inférieur&lt;br/&gt;
à la somme de la moitié de leur largueur (dans le cas de l'axe x, la hauteur pour l'axe y).&lt;br/&gt;
C'est pour cela que dans le précédent tuto (&lt;iframe data-embed-src="&lt;base_url&gt;/topic/1043-moteur-physique-2/?do=embed&amp;embedDo=findComment%3Fcomment%3D11169%2C" data-embedcontent="" frameborder="0" src="//melinyel.net/applications/core/interface/js/spacer.png"&gt;&lt;/iframe&gt; lors de la création de corps, on ne gardait que la moitié de la largueur et de la hauteur.&lt;br/&gt;
Ont peut ainsi tester chaque axe pour voir s'il y a une collision sur celui-ci.&lt;br/&gt;
S'il n'y a une collision que sur un seul axe, alors l'objet n'est pas en collision avec l'autre, il est simplement à coté.&lt;br/&gt;&lt;br/&gt;
Une magnifique image qui résume cela :&lt;/p&gt;
&lt;p&gt;&lt;img alt="carre.png" src="&lt;base_url&gt;/applications/sslimageproxy/interface/image.php?url=http://www.turboconnard.com/b/wp-content/uploads/2010/11/carre.png"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color:#008000;"&gt;&lt;u&gt;La pratique :&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;En code, on teste chaque axe l'un après l'autre. Si sur le premier axe il n'y a pas de collision, alors on a pas besoin de tester le deuxième.&lt;br/&gt;
 &lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
float mlb_abs(float number)
{
if (number &lt; 0)
{
number *= -1;
}
return (number);
}
float penetration_x(t_body *f_body, t_body *s_body)
{
return (mlb_abs(f_body-&gt;box.x - s_body-&gt;box.x) - (f_body-&gt;box.w + s_body-&gt;box.w));
}
float penetration_y(t_body *f_body, t_body *s_body)
{
return (mlb_abs(f_body-&gt;box.y - s_body-&gt;box.y) - (f_body-&gt;box.h + s_body-&gt;box.h));
}
char is_collide(t_body *f_body, t_body *s_body)
{
if (penetration_x(f_body, s_body) &lt;= 0.
&amp;&amp; penetration_y(f_body, s_body) &lt;= 0.)
{
return (1);
}
return (0);
}
&lt;/pre&gt;
&lt;p&gt;La fonction mlb_abs est strictement équivalente a abs() de math.h, mais à chaque fois que le moteur serait inclus dans un projet, il faudrait linker la biblio, et c'est pas pratique, donc créer la fonction est pour moi plus simple. Vous pouvez évidement la remplacer par celle de math.h si cela vous arrange.&lt;br/&gt;
On calcule donc les collisions sur chaque axe, et la fonction renvoie 1 en cas de collision.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style="color:#ff0000;"&gt;&lt;span style="font-size:18px;"&gt;&lt;u&gt;&lt;strong&gt;Correction des collisions :&lt;/strong&gt;&lt;/u&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Il faut tester tout les corps entre eux pour savoir s'il y a une collision. Je vous rappelle que deux corps statiques ne seront jamais en collisions, donc on ne vas pas les tester entre eux.&lt;br/&gt;
 &lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
void check_collision(t_physic_world *world)
{
t_body *update = world-&gt;dynamic_body;
t_body *collide_with = world-&gt;static_body;;
update = world-&gt;dynamic_body;
while (update != NULL)
{
/collide with static body/
while (collide_with != NULL)
{
if (is_collide(update, collide_with))
{
correct_collision(update, collide_with);
}
collide_with = collide_with-&gt;next;
}
/collide with dynamic body/
collide_with = update-&gt;next;
while (collide_with != NULL)
{
if (is_collide(update, collide_with))
{
correct_collision(update, collide_with);
}
collide_with = collide_with-&gt;next;
}
    update = update-&amp;gt;next;
}

}
&lt;/pre&gt;
&lt;p&gt;On teste d'abord les collisions avec les corps statiques, car cela permet d'éviter que le corps soit repoussé a travers un mur s'il est poussé par un corps dynamique, ce qu'il ne faut surtout pas.&lt;br/&gt;&lt;br/&gt;
Et maintenant, il faut pouvoir corriger ces collisions une fois quelle sont détectées !&lt;br/&gt;
Tout d'abord, les corrections ne seront pas les mêmes en cas de collisions dynamique / statique que des collisions dynamique / dynamique.&lt;br/&gt;
Les première collisions pousseront le corps dynamique hors du corps statique alors que les deuxième collisions, les deux corps se pousseront mutuellement, et celui avec la plus grande force l'emportera.&lt;br/&gt;
Il faut d'abord dispatcher les corps dans les bonnes collisions :&lt;br/&gt;
 &lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
void correct_collision(t_body *f_body, t_body *s_body)
{
if (f_body-&gt;dynamic &amp;&amp; !s_body-&gt;dynamic)
{
correct_static_collision(s_body, f_body);
}
else if (!f_body-&gt;dynamic &amp;&amp; s_body-&gt;dynamic)
{
correct_static_collision(f_body, s_body);
}
else if (f_body-&gt;dynamic &amp;&amp; s_body-&gt;dynamic)
{
correct_dynamic_collision(f_body, s_body);
}
}
&lt;/pre&gt;
&lt;p&gt;Normalement, les collisions entre corps statique et dynamique se font dans cette ordre dans la fonction, mais cela permet de tester les collisions entre un corps qui n'appartient pas a la structure physic_world avec ce que vous voulez, sans vous souciez de l'ordre dans lequel les corps doivent être mis.&lt;br/&gt;
On va commencer avec les collisions avec des corps statiques :&lt;br/&gt;
 &lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
void correct_static_collision(t_body *static_body, t_body *dynamic_body)
{
if (penetration_x(static_body, dynamic_body) &gt; penetration_y(static_body, dynamic_body))
{
/x axis penetration/
float direction = dynamic_body-&gt;force.total_force.x / mlb_abs(dynamic_body-&gt;force.total_force.x);
dynamic_body-&gt;box.x = static_body-&gt;box.x - (dynamic_body-&gt;box.w + static_body-&gt;box.w) * direction;
    add_contact_force(&amp;amp;(dynamic_body-&amp;gt;force), -dynamic_body-&amp;gt;force.total_force.x, static_body-&amp;gt;force.contact_force.y);
}
else
{
    /*y axis penetration*/
    float direction = dynamic_body-&amp;gt;force.total_force.y / mlb_abs(dynamic_body-&amp;gt;force.total_force.y);
    dynamic_body-&amp;gt;box.y = static_body-&amp;gt;box.y - ((dynamic_body-&amp;gt;box.h + static_body-&amp;gt;box.h) * direction);

    add_contact_force(&amp;amp;(dynamic_body-&amp;gt;force), static_body-&amp;gt;force.contact_force.x, -dynamic_body-&amp;gt;force.total_force.y);
}

}
&lt;/pre&gt;
&lt;p&gt;On corrige la collision en fonction de l'axe ou le corps est le moins en collision, afin de ne pas voir un corps se faire repousser violemment alors que l'on peut faire une chose moins visible.&lt;br/&gt;
La fonction est simple : 1ere ligne ont calcule la direction de la collision, deuxième ligne, on la corrige, et troisième ligne, on met la force contraire de l'axe ou il y a eut la collisions dans le corps dynamique afin de l’empêcher de passer a travers. Mais pourquoi le faire, si on corrige simplement, il ne passera pas non plus non ?&lt;br/&gt;
Ce qu'il faut savoir, c'est que le moteur physique ne peut pas être sur qu'il va être appelé suffisamment pour éviter l’effet "tunnel", le corps passe alors a travers alors qu'il aurait du y avoir une collisions. Si l'ont ajoute une force contraire mais de contact, elle ne disparaîtra que lorsque le moteur physique sera remis a jour, donc on pourra alors recorriger la collision.&lt;/p&gt;
&lt;p&gt;De plus on peut voir que dans l'axe ou il n'y a pas de colliisons, on rajoute un force. Mais qu'est ce que c'est ?&lt;br/&gt;
C'est le méga truc de la mort qui tue du deuxième tuto ! Grâce a cela, on peut rajouter facilement des tapis roulant et des plate-formes mobiles, alors que sinon, dans les autres moteurs physique, ont doit tricher en rajoutant une force lorsque le personnage se trouve sur celui-ci.&lt;br/&gt;
Evidemment, la force de contact n'est là que si vous l'ajouter, elle est de base à 0.&lt;br/&gt;&lt;br/&gt;
Et maintenant, la correction la plus difficile : les collisions dynamiques / dynamiques dont voici la fonction :&lt;br/&gt;
 &lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
void correct_dynamic_collision(t_body *f_body, t_body *s_body)
{
t_force common_force;
t_force total_force;
float weight;
if (penetration_x(f_body, s_body) &amp;gt; penetration_y(f_body, s_body))
{
    /*x axis penetration*/
    /*calculate the total force for the total body and divise it*/
    calc_total_force(&amp;amp;(f_body-&amp;gt;force));
    calc_total_force(&amp;amp;(s_body-&amp;gt;force));
    total_force.x = f_body-&amp;gt;force.total_force.x;
    total_force.y = s_body-&amp;gt;force.total_force.x;
    
    common_force.x = total_force.x + total_force.y;
    weight = f_body-&amp;gt;weight + s_body-&amp;gt;weight;
    common_force.y = common_force.x / weight * s_body-&amp;gt;weight;
    common_force.x = common_force.x / weight * f_body-&amp;gt;weight;
    
    add_contact_force(&amp;amp;(f_body-&amp;gt;force), common_force.x - total_force.x, 0);
    add_contact_force(&amp;amp;(s_body-&amp;gt;force), common_force.y - total_force.y, 0);

    /*correct collision*/
    float average_x = (f_body-&amp;gt;box.y * s_body-&amp;gt;weight + s_body-&amp;gt;box.y * f_body-&amp;gt;weight) / weight;
    float direction = average_x - f_body-&amp;gt;box.x;
    if (direction &amp;lt; 0)
    {
        direction = -1;
    }
    else
    {
        direction = 1;
    }
    f_body-&amp;gt;box.x = average_x - (f_body-&amp;gt;box.w * direction);
    s_body-&amp;gt;box.x = average_x + (s_body-&amp;gt;box.w * direction);
}
else
{
    /*y axis penetration*/
    /*calculate the total force for the total body and divise it*/
    calc_total_force(&amp;amp;(f_body-&amp;gt;force));
    calc_total_force(&amp;amp;(s_body-&amp;gt;force));
    total_force.x = f_body-&amp;gt;force.total_force.y;
    total_force.y = s_body-&amp;gt;force.total_force.y;
    
    common_force.y = total_force.x + total_force.y;
    weight = f_body-&amp;gt;weight + s_body-&amp;gt;weight;
    common_force.x = common_force.y / weight * f_body-&amp;gt;weight;
    common_force.y = common_force.y / weight * s_body-&amp;gt;weight;

    add_contact_force(&amp;amp;(f_body-&amp;gt;force), 0, common_force.x - total_force.x);
    add_contact_force(&amp;amp;(s_body-&amp;gt;force), 0, common_force.y - total_force.y);

    /*correct collision*/
    float average_y = (f_body-&amp;gt;box.y * s_body-&amp;gt;weight + s_body-&amp;gt;box.y * f_body-&amp;gt;weight) / weight;
    float direction = average_y - f_body-&amp;gt;box.y;
    if (direction &amp;lt; 0)
    {
        direction = -1;
    }
    else
    {
        direction = 1;
    }
    f_body-&amp;gt;box.y = average_y - (f_body-&amp;gt;box.h * direction);
    s_body-&amp;gt;box.y = average_y + (s_body-&amp;gt;box.h * direction);
}

}
&lt;/pre&gt;
&lt;p&gt;Les fonctions sont exactement les mêmes sur les deux axes, il n'y a que des ajustement au niveau des axes a faire.&lt;br/&gt;
La fonction marche comme cela : elle calcule les forces des deux corps, calcule la moyenne de l'endroit de leur collisions en fonctions de la force de l'autre corps (car plus un corps aura de force, moins il devra être bougé car c'est lui le plus fort).&lt;br/&gt;
On transfère les forces dans les deux corps afin qu'ils aient la même vitesse en sortie, le tout dans des forces de contact, cela permet de faire des caisses que l'ont pourra pousser !&lt;br/&gt;
Et ont corrige a la fin la collision, et c'est bon.&lt;br/&gt;
Malgré que la fonction soit longue, elle reste relativement simple.&lt;br/&gt;&lt;br/&gt;
Et voila, le moteur physique est fini !&lt;br/&gt;
J'espère qu'il vous aura plus, et que vous vous en servirez  &lt;/p&gt;
]]></description><link>https://melinyel.net/topic/1065/moteur-physique-3</link><guid isPermaLink="true">https://melinyel.net/topic/1065/moteur-physique-3</guid><dc:creator><![CDATA[daemondragon]]></dc:creator><pubDate>Sat, 06 Sep 2014 09:10:39 GMT</pubDate></item><item><title><![CDATA[Moteur physique #2]]></title><description><![CDATA[&lt;p&gt;Maintenant que l'on peut appliquer une force, il faut pouvoir la rattacher à un corps   .&lt;br/&gt;
On peut distinguer, là encore, deux types de corps : les dynamiques et les statiques.&lt;br/&gt;
Les corps dynamiques seront les seuls qu'il est possible de bouger via des forces, les statiques seront considérés comme des élément du décors, il seront tout le temps immobiles (sauf si  vous modifier leur position manuellement bien sur).&lt;br/&gt;
Ainsi, les personnages, les caisses... seront dynamiques, et les élément du décors seront statiques.&lt;br/&gt;
Voici donc la structure d'un corps :&lt;br/&gt;
 &lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
typedef struct s_body
{
char dynamic;
float weight;
t_collision_box box;
t_force_container force;
struct s_body *next;
}t_body;
&lt;/pre&gt;
&lt;p&gt;Le poids (weight) sert à savoir à quel point l'objet sera dur a bouger. Ainsi, un objet de 40 kg sera deux fois plus facile&lt;br/&gt;
à bouger qu'un objet de 80 kg. il faudra donc deux fois moins de force. Et voici donc l'unité des forces : Mètre par secondes par kilogrammes.&lt;br/&gt;
(40 de force pour bouger un corps de 40 kg à 1m/s)&lt;br/&gt;
la collision box, servira plus tard pour déterminer les collisions entre les corps, et le tout en liste chainnée, afin de pouvoir les stoker facilement dans une structure world :&lt;br/&gt;
 &lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
typedef struct s_physic_world
{
t_body *static_body;
t_body *dynamic_body;
}t_physic_world;
&lt;/pre&gt;
&lt;p&gt;Il faut faire la différence entre les corps afin d'éviter de faire des tests qui ne servent à rien (par définition, deux corps statiques ne sont jamais en collisions)&lt;br/&gt;
Tout d'abord, la fonction de création de corps :&lt;br/&gt;
 &lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
t_body *create_static_body(float x, float y, float w, float h)
{
t_body *body = malloc(sizeof(*body));
if (body != NULL)
{
body-&gt;box.x = x;
body-&gt;box.y = y;
body-&gt;box.w = w / 2;
body-&gt;box.h = h / 2;
    body-&amp;gt;dynamic = 0;
    body-&amp;gt;weight = 1;
    
    body-&amp;gt;force.permanent_force = NULL;
    set_contact_force(&amp;amp;(body-&amp;gt;force), 0, 0);
    body-&amp;gt;force.total_force.x = 0;
    body-&amp;gt;force.total_force.y = 0;
    body-&amp;gt;next = NULL;
}
return (body);

}
t_body *create_dynamic_body(float x, float y, float w, float h)
{
t_body *body = malloc(sizeof(*body));
if (body != NULL)
{
body-&gt;box.x = x;
body-&gt;box.y = y;
body-&gt;box.w = w / 2;
body-&gt;box.h = h / 2;
    body-&amp;gt;dynamic = 1;
    body-&amp;gt;weight = 1;
    
    body-&amp;gt;force.permanent_force = NULL;
    set_contact_force(&amp;amp;(body-&amp;gt;force), 0, 0);
    body-&amp;gt;force.total_force.x = 0;
    body-&amp;gt;force.total_force.y = 0;
    body-&amp;gt;next = NULL;
}
return (body);

}
&lt;/pre&gt;
&lt;p&gt;les deux fonctions sont strictement les mêmes, sauf une initialisation d'une variable. Vous pouvez facilement réunir le tout en une fonction, mais j'ai garder cette présentation car plus claire à utiliser. La fonction retourne un pointeur sur la structure afin de pouvoir la modifier et de l'ajouter à la structure physic_world (la fonction va venir, ne vous inquiétez pas).&lt;br/&gt;
Il faut initialiser toutes les forces à 0, ont met le poids à 1 par défaut (ne jamais mettre le poids à 0, sinon il va y avoir un problème de division par 0)&lt;br/&gt;
Il faut aussi savoir que pour déterminer les collisions, on à besoin du centre du corps, pas un de ces coins. On à aussi besoin que de la moitié de la hauteur et de la largeur, mais la conversion est faites dans la fonction, pour plus de simplicité.&lt;br/&gt;&lt;br/&gt;
Et surtout pour ceux qui veulent la structure collision box :&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
typedef struct s_collision_box
{
float x;
float y;
float w;
float h;
}t_collision_box;
&lt;/pre&gt;
&lt;p&gt;il faut maintenant aussi, pouvoir détruire une entité :&lt;br/&gt;
 &lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
void delete_body(t_body *body)
{
if (body != NULL)
{
t_force *remove = body-&gt;force.permanent_force;
while (remove != NULL)
{
body-&gt;force.permanent_force = remove-&gt;next;
free(remove);
remove = body-&gt;force.permanent_force;
}
free(body);
}
}
&lt;/pre&gt;
&lt;p&gt;On doit enlever toutes les forces permanentes afin d'éviter les fuites de mémoires !&lt;br/&gt;
De plus, l'objet doit aussi avoir le poids que vous voulez :&lt;br/&gt;
 &lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
void add_weight(t_body *body, float weight)
{
if (body != NULL)
{
if (weight &lt;= 0)
{
weight = 1;
}
body-&gt;weight = weight;
}
}
&lt;/pre&gt;
&lt;p&gt;Mais ce n'est pas finit ! Il faut aussi pouvoir ajouter le corps à la structure world. La fonction pour mettre a jour tout les corps ne va pas attendre qu'on lui passe tout les objets 1 par 1 ! Cela possède plusieurs avantages : On n'envoie qu'une grande structure au lieu de plein de petites, et vous pourrez bénéficier de la détection de collisions sans que l'objet soit présent physiquement : cela permet de faire des capteurs, de savoir si on est dans de l'eau sans autant repousser le personnage etc...&lt;br/&gt;&lt;br/&gt;
Bref suit les fonctions d'initialisation, de suppression du monde physique et d'ajout de corps, rien de bien complexe, presque un copier coller des forces :&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
t_physic_world *create_physic_world()
{
t_physic_world *world = malloc(sizeof(*world));
if (world != NULL)
{
world-&gt;static_body = NULL;
world-&gt;dynamic_body = NULL;
}
return (world);
}
void delete_physic_world(t_physic_world *world)
{
if (world != NULL)
{
t_body *remove = world-&gt;static_body;
while (remove != NULL)
{
world-&gt;static_body = remove-&gt;next;
delete_body(remove);
remove = world-&gt;static_body;
}
remove = world-&gt;dynamic_body;
while (remove != NULL)
{
world-&gt;dynamic_body = remove-&gt;next;
delete_body(remove);
remove = world-&gt;dynamic_body;
}
free(world);
}
}
char add_to_physic_world(t_physic_world *world, t_body *body)
{
if (world != NULL &amp;&amp; body != NULL)
{
if (body-&gt;dynamic)
{
body-&gt;next = world-&gt;dynamic_body;
world-&gt;dynamic_body = body;
}
else
{
body-&gt;next = world-&gt;static_body;
world-&gt;static_body = body;
}
return (1);
}
else
{
return (0);
}
}
&lt;/pre&gt;
&lt;p&gt;Les corps sont encore empilés, car c'est toujours plus simple à faire  &lt;br/&gt;
Et maintenant, on peut mettre a jour touts les corps :&lt;br/&gt;
 &lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
void update_physic_world(t_physic_world *world, int millisecond_time)
{
t_body *update = world-&gt;dynamic_body;
while (update != NULL)
{
update_force(update, millisecond_time);
update = update-&gt;next;
}
}
void update_force(t_body *body, int millisecond_time)
{
calc_total_force(&amp;(body-&gt;force));
body-&gt;force.total_force.x *= (millisecond_time / 1000.0) / body-&gt;weight;
body-&gt;force.total_force.y *= (millisecond_time / 1000.0) / body-&gt;weight;
body-&gt;box.x += body-&gt;force.total_force.x;
body-&gt;box.y += body-&gt;force.total_force.y;
set_contact_force(&amp;(body-&gt;force), 0, 0);
}
&lt;/pre&gt;
&lt;p&gt;Je vous rappelle que seuls les corps dynamiques peuvent être en mouvement, donc il n'y a pas de raison de mettre a jours les corps statiques.&lt;/p&gt;
&lt;p&gt;La fonction attend un temps en millisecondes car la SDL utilise cette unité, mais vous pouvez changer l'unité de temps, il faudra juste adapter en conséquence.&lt;br/&gt;
Mais vous avez sûrement remarquer la présence de la structure force_container, même chez les corps statiques, alors pourquoi ne pas l'enlever chez eux ?&lt;br/&gt;
Tous simplement parce que sinon on doit dupliquer le code en deux : corps statiques et corps dynamiques, que c'est plus complexe à faire, que les risque de bug sont multiplier par deux, et surtout ça empêche le méga truc de la mort qui tue, mais que vous ne saurez pas dans ce tutos.&lt;br/&gt;
Les forces de contacts sont remisent à 0 a chaque fois car on les recréer aussi à chaque fois.&lt;/p&gt;
&lt;p&gt;Et voilà, vous pouvez bouger vos personnages comme vous voulez, mais il n'y a toujours pas de collisions !&lt;/p&gt;
]]></description><link>https://melinyel.net/topic/1043/moteur-physique-2</link><guid isPermaLink="true">https://melinyel.net/topic/1043/moteur-physique-2</guid><dc:creator><![CDATA[daemondragon]]></dc:creator><pubDate>Sat, 30 Aug 2014 09:24:43 GMT</pubDate></item><item><title><![CDATA[Moteur physique #1]]></title><description><![CDATA[&lt;p&gt;Je vais faire dans cette série de tutoriels, une construction suivit d'un moteur physique.&lt;br/&gt;&lt;br/&gt;
Tout d'abord : Qu'est ce qu'un moteur physique ?&lt;br/&gt;
Un moteur physique, est un programme qui permet de gerer la physique correctement, et qui déplace les personnages, tout en gérant les collisions.&lt;br/&gt;
(tout les problèmes de collisions d'un jeu viennent du moteur physique).&lt;br/&gt;&lt;br/&gt;
Ce qu'il faut savoir avant de commencer à le faire :&lt;br/&gt;
Le moteur physique, que je vais vous apprendre à faire, ne gérera que des rectangles, il est donc parfait pour les jeux de plate-formes, de type mario, mais aussi d'autre styles de jeu avec que des blocs (les jeux en tiles quoi) comme zelda. Et oui le moteur ne sera qu'en 2d !&lt;br/&gt;
De plus, le principe majeur d'un moteur physique est la réutilisabilité de celui-ci, ce qui veut dire pas de : IF MUR THEN ...  &lt;br/&gt;&lt;br/&gt;
L'architecture que nous allons utilisé est celle dite "à posteriori" :&lt;br/&gt;
-première étape, on génère des forces, comme la gravité, les forces de mouvement...&lt;br/&gt;
-deuxième étape, on applique ces forces.&lt;br/&gt;
-troisième étape, on détecte les collisions.&lt;br/&gt;
-dernière étape, on les corrige.&lt;br/&gt;&lt;br/&gt;
L'autre architecture, aussi appelé "à priori", utilise des matrices de résolution, afin de détecter l'instant exact de la collision.&lt;br/&gt;
Cette architecture est plus précise, mais elle est aussi beaucoup plus lente, c'est pourquoi AUCUN moteur physique de jeu vidéo ne l'utilise, l'architecture "à posteriori" offrant des résultats satisfaisants.&lt;br/&gt;
(Ce n'est qu'en cas extrêmes que l'ont remarque des problèmes, mais on ne les vois pas souvent).&lt;br/&gt;&lt;br/&gt;
Et on va donc commencer par créer un générateur de force, et qui va les stoker dans une structure, afin de les garder en mémoire.&lt;br/&gt;
(On attachera ensuite cette structure à un corps, afin de le déplacer)&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
typedef struct s_force_container
{
t_force *permanent_force;
t_force contact_force;
t_force total_force;
}t_force_container;
&lt;/pre&gt;
&lt;p&gt;
Tout d'abord, j'ai distingué deux type de forces : les permanentes (la gravité, les mouvements...), et les forces de contact. celle là seront régénérées à chaque fois que le moteur se mettra à jour, donc on ne va pas créer de listes chaînées pour ça, car le risque qu'un malloc échoue devient très vite important, donc on va uniquement se contenter d'additionner les valeurs entre elles.&lt;br/&gt;
Les forces permanentes, elles, seront stockées dans la liste chaînées, afin de pouvoir en modifier une sans impacter les autres.&lt;br/&gt;
La force total_force, elle sert uniquement a connaître le total des forces permanentes et de contact, afin de bouger le corps en conséquences.&lt;br/&gt;
Les forces sont représentées par la structure suivantes :&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
typedef struct s_force
{
float x;
float y;
struct s_force *next;
}t_force;
&lt;/pre&gt;
&lt;p&gt;Les forces en x représente normalement l'axe horizontal et l'axe x, vertical. Il n'y a pas de sens ou de direction pour les axes, vous pouvez prendre&lt;br/&gt;
celui que vous voulez, il faudra juste adapter les forces en conséquence.&lt;br/&gt;&lt;br/&gt;
il nous faut maintenant une fonction afin d'ajouter ou d'enlever une force permanente.&lt;br/&gt;
La fonction d'ajout :&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
t_force *create_permanent_force(t_force_container *container, float x, float y)
{
t_force *add = malloc(sizeof(*add));
if (add != NULL)
{
add-&gt;x = x;
add-&gt;y = y;
    add-&amp;gt;next = container-&amp;gt;permanent_force;
    container-&amp;gt;permanent_force = add;
}
return (add);

}
&lt;/pre&gt;
&lt;p&gt;la fonction retourne un pointeur vers la force, afin de la modifier quand vous voulez.&lt;br/&gt;
Les forces sont empiler les une à la suite des autres (l'ordre d'empilage n'a absolument aucune importance, c'est juste plus simple à programmer   )&lt;br/&gt;
Et maintenant la fonction "d'enlevage" :&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
void delete_permanent_force(t_force_container *container, t_force *remove)
{
if (container != NULL)
{
if (container-&gt;permanent_force != NULL)
{
t_force *search = container-&gt;permanent_force;
char finish = 0;
if (search == remove)
{
container-&gt;permanent_force = remove-&gt;next;
free(remove);
finish = 1;
}
while (search-&gt;next != NULL &amp;&amp; !finish)
{
if (search-&gt;next == remove)
{
search-&gt;next = search-&gt;next-&gt;next;
free(remove);
finish = 1;
}
}
}
}
}
&lt;/pre&gt;
&lt;p&gt;Le seul truc dur a faire ici, c'est de penser a enlever la force, tout ne perdant aucun pointeur vers les prochaines forces, tout en ne faisant pas de segfault.&lt;br/&gt;&lt;br/&gt;
On s’occupe maintenant des forces de contact, les plus faciles   .&lt;br/&gt;
pour en ajouter :&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
void add_contact_force(t_force_container *container, float x, float y)
{
if (container != NULL)
{
container-&gt;contact_force.x += x;
container-&gt;contact_force.y += y;
}
}
&lt;/pre&gt;
&lt;p&gt;il n'y a pas de fonction pour retirer une force, car pour retirer les forces directement additionner, il suffit juste d'ajouter son contraire.&lt;br/&gt;
Mais en revanche, il faut une fonction pour remettre à un certain nombre cette force, car je vous rappelle, il faut réinitialiser les forces de contacts a chaque mise à jour (bah oui sinon vous imaginez, il faudrait retenir a cause de quoi cette force de contact a été créer, vérifier si elle a toujours raison d’exister, le tout avec beaucoup de corps en mouvement, et le moteur va ramer très vite.&lt;br/&gt;
Bref la fonction :&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
void set_contact_force(t_force_container *container, float x, float y)
{
if (container != NULL)
{
container-&gt;contact_force.x = x;
container-&gt;contact_force.y = y;
}
}
&lt;/pre&gt;
&lt;p&gt;Toujours aussi simple, normalement pas de difficulté a comprendre   .&lt;br/&gt;
Et enfin, il nous reste une dernière fonction a voir : celle qui calcule la somme de toutes les forces, afin de savoir la force finale pour bouger le corps.&lt;br/&gt;
Elle parcours la liste chaînées des forces permanentes, les additionnent, puis ajoute les forces de contacts et met le résultat dans total_force :&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
void calc_total_force(t_force_container *container)
{
if (container != NULL)
{
float x = 0;
float y = 0;
t_force *force = container-&gt;permanent_force;
while (force != NULL)
{
x += force-&gt;x;
y += force-&gt;y;
force = force-&gt;next;
}
x += container-&gt;contact_force.x;
y += container-&gt;contact_force.y;
    container-&amp;gt;total_force.x = x;
    container-&amp;gt;total_force.y = y;
}

}
&lt;/pre&gt;
&lt;p&gt;Et voilà ! on peut maintenant ajouter ou enlever facilement des forces, permanentes où de contact.&lt;br/&gt;
Évidement, le code comme cela ne sert absolument a rien, il faut ajouter la notion de corps pour comprendre à quoi cela va servir.&lt;/p&gt;
]]></description><link>https://melinyel.net/topic/1040/moteur-physique-1</link><guid isPermaLink="true">https://melinyel.net/topic/1040/moteur-physique-1</guid><dc:creator><![CDATA[daemondragon]]></dc:creator><pubDate>Fri, 29 Aug 2014 08:46:32 GMT</pubDate></item><item><title><![CDATA[[ALGO] algorithme de collision en fromage]]></title><description><![CDATA[&lt;p&gt;bonjour bonjour !&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;pour &lt;iframe data-embed-src="&lt;base_url&gt;/topic/545-reconqu%C3%AAte-salvatrice/,?do=embed" data-embedcontent="" frameborder="0" src="//melinyel.net/applications/core/interface/js/spacer.png"&gt;&lt;/iframe&gt; j'ai codé un petit algorithme qui me permet de tester si notre personnage fait face à une image ou non.&lt;/p&gt;
&lt;p&gt;le tout avec une marge dynamique  &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;u&gt;pour les non-initié à la SDL, la structure SDL_Rect contient les coordonnées : x, y, w et h d'une image.&lt;/u&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;j'ai crois donc qu'il est important de vous le faire partager  &lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
bool colisionfromage(SDL_Rect lanceur, SDL_Rect recepteur, SDL_Rect curseur, double marge)
{
double degre, degre2, diff;
int difx, dify;
difx = (lanceur.x + lanceur.w/2) - (curseur.x + curseur.w/2); //calcul de la difference en pixel
dify = (lanceur.y + lanceur.h/2) - (curseur.y + curseur.h/2); //entre le lanceur et le pointeur de la souris
degre = atan2(dify, difx);//obtention de l'angle en radian

difx = (lanceur.x + lanceur.w/2) - (recepteur.x + recepteur.w/2); //calcul de la difference en pixel entre
dify = (lanceur.y + lanceur.h/2) - (recepteur.y + recepteur.h/2); //le lanceur et l'objectif
degre2 = atan2(dify, difx);//obtention de l'angle en radian

degre  *= 57.296;//conversion en degre
degre2 *= 57.296;

degre   += 180; //ajustement pour passer d'un systeme (-180/180) à un systeme (0/360)
degre2  += 180;

diff = degre-degre2;//calcul de la différence

if (diff &amp;lt; 0) //si diff est négatif, on le passe en positif
{
    diff *= -1;
}

if (diff &amp;lt;= 0 || diff &amp;gt;= marge/2) //si la différence est plus grande que la marge, nous retournons FAUX
{
    return FALSE;
}
return TRUE;

}
&lt;/pre&gt;
&lt;p&gt;si vous avez des questions / remarques, comme d'habitude, je vous écoute !&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;edit : je sais que ce code a un défaut, le calcul de la différence ne marche pas si l'un est &lt;360 et l'autre &gt;0. mais je ne sais pas comment gérer ça simplement. des idées ?&lt;/p&gt;
]]></description><link>https://melinyel.net/topic/1031/algo-algorithme-de-collision-en-fromage</link><guid isPermaLink="true">https://melinyel.net/topic/1031/algo-algorithme-de-collision-en-fromage</guid><dc:creator><![CDATA[cegdd]]></dc:creator><pubDate>Wed, 27 Aug 2014 00:48:24 GMT</pubDate></item><item><title><![CDATA[[TUTO] installation SDL 2.0]]></title><description><![CDATA[&lt;p&gt;&lt;span style="font-family:'comic sans ms', cursive;"&gt;Salut tout le monde !&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:'comic sans ms', cursive;"&gt;en exclusivité pour mes chers Melinyens ... comment installer la bibliothèque SDL2 et ses filles sur code::blocks (windows x32 / x64) !&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:'comic sans ms', cursive;"&gt;j'avais dis que je n'expliquerais pas cela pour plusieurs raisons :&lt;/span&gt;&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;&lt;span style="font-family:'comic sans ms', cursive;"&gt;je ne suis pas un professionnel des installations de bibliothèques je ne vous garanti donc pas la propreté de l'installation.&lt;/span&gt;
&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:'comic sans ms', cursive;"&gt;il existe déjà des tutoriels qui traitent ce sujet. (et même des templates tout fait sur develloppez.com !)&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;&lt;span style="font-family:'comic sans ms', cursive;"&gt;mais ... je vois beaucoup trop de personnes qui me demandent des conseils là dessus ^_^  donc je me lance !&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#008000;"&gt;&lt;span style="font-size:24px;"&gt;&lt;strong&gt;&lt;u&gt;1) le téléchargement :&lt;/u&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:24px;"&gt;&lt;span style="font-size:14px;"&gt;&lt;span style="font-family:'comic sans ms', cursive;"&gt;pour être complet vous allez avoir besoin des bibliothèque cité ci-dessous :&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;La SDL : &lt;a href="https://www.libsdl.org/download-2.0.php" rel="external nofollow"&gt;https://www.libsdl.org/download-2.0.php&lt;/a&gt;
&lt;/li&gt;&lt;li&gt;La SDL_image : &lt;a href="https://www.libsdl.org/projects/SDL_image/" rel="external nofollow"&gt;https://www.libsdl.org/projects/SDL_image/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;La SDL_ttf : &lt;a href="https://www.libsdl.org/projects/SDL_ttf/" rel="external nofollow"&gt;https://www.libsdl.org/projects/SDL_ttf/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;La SDL_mixer : &lt;a href="http://www.libsdl.org/projects/SDL_mixer/" rel="external nofollow"&gt;http://www.libsdl.org/projects/SDL_mixer/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:'comic sans ms', cursive;"&gt;sur chaque pages, vous prendrez ce lien :&lt;/span&gt;&lt;img alt="185360sdldl.jpg" src="&lt;base_url&gt;/applications/sslimageproxy/interface/image.php?url=http://img11.hostingpics.net/pics/185360sdldl.jpg"/&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style="color:#008000;"&gt;&lt;span style="font-size:24px;"&gt;&lt;strong&gt;&lt;u&gt;2) le positionnement des fichiers :&lt;/u&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:'comic sans ms', cursive;"&gt;maintenant que vous avez tout téléchargé, vous devriez avoir des fichiers en ".tar.gz", décompressez les avec votre logiciel de compression/décompression habituel.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:'comic sans ms', cursive;"&gt;les dossiers ainsi obtenu devrais ressembler a ça : ouvrez le dossier entouré en rouge.&lt;/span&gt;&lt;img alt="121091files.jpg" src="&lt;base_url&gt;/applications/sslimageproxy/interface/image.php?url=http://img11.hostingpics.net/pics/121091files.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:'comic sans ms', cursive;"&gt;&lt;strong&gt;&lt;u&gt;ne prenez pas les dossiers en x64 même si votre ordinateur est en x64 !&lt;/u&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:'comic sans ms', cursive;"&gt;&lt;span style="font-size:10px;"&gt;(bien entendu je m’adresse ici a un public tout aussi amateur que moi. si vous savez ce que vous faites et que votre compilateur est en x64, faites ce qu'il vous plait   )&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:'comic sans ms', cursive;"&gt;copiez maintenant dans chacune des bibliothèque précédemment téléchargées le dossier "include", "bin" et "lib"&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:'comic sans ms', cursive;"&gt;et fusionnez les avec ceux du compilateur que vous devriez trouver à l'emplacement montré ci-dessous :&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;img alt="253684mingw.jpg" src="&lt;base_url&gt;/applications/sslimageproxy/interface/image.php?url=http://img11.hostingpics.net/pics/253684mingw.jpg"/&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style="color:#008000;"&gt;&lt;span style="font-size:24px;"&gt;&lt;strong&gt;&lt;u&gt;3) la configuration :&lt;/u&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:'comic sans ms', cursive;"&gt;et maintenant ... CODE::BLOCKS !!!&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:'comic sans ms', cursive;"&gt;créez un nouveau projet vierge "empty project",&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:'comic sans ms', cursive;"&gt;puis allez dans :&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="696488uicRSinDEVCodeBlocks1312.jpg" src="&lt;base_url&gt;/applications/sslimageproxy/interface/image.php?url=http://img11.hostingpics.net/pics/696488uicRSinDEVCodeBlocks1312.jpg"/&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:'comic sans ms', cursive;"&gt;vous devriez avoir cette fenêtre&lt;/span&gt;        ----------------------------------|&lt;/p&gt;
&lt;p&gt;                                                                                                        |&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:'comic sans ms', cursive;"&gt;assurez vous d'être bien dans la racine ici !&lt;/span&gt;          |                       |&lt;/p&gt;
&lt;p&gt;             v-----------------------------------------------------                      v&lt;/p&gt;
&lt;p&gt;&lt;img alt="192892kijhg.jpg" src="&lt;base_url&gt;/applications/sslimageproxy/interface/image.php?url=http://img11.hostingpics.net/pics/192892kijhg.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:'comic sans ms', cursive;"&gt;vous devez maintenant en premier, cliquer sur "add" et écrire "mingw32",&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:'comic sans ms', cursive;"&gt;puis parcourir vos fichiers pour lui indiquer tout les fichiers ".a" que vous voyez ci-dessus. &lt;u&gt;&lt;strong&gt;Dans le même ordre !&lt;/strong&gt;&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:'comic sans ms', cursive;"&gt;mais ce n'est pas fini !  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:'comic sans ms', cursive;"&gt;vous devez ensuite ajouter les dossiers "lib" et "include" de votre compilateur, comme montré ci-dessous !&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="351599jyhgt.jpg" src="&lt;base_url&gt;/applications/sslimageproxy/interface/image.php?url=http://img11.hostingpics.net/pics/351599jyhgt.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;et enfin :&lt;/p&gt;
&lt;p&gt;&lt;img alt="551051PrtScrcapture.jpg" src="&lt;base_url&gt;/applications/sslimageproxy/interface/image.php?url=http://img11.hostingpics.net/pics/551051PrtScrcapture.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:'comic sans ms', cursive;"&gt;&lt;strong&gt;&lt;span style="color:rgb(255,0,0);"&gt;TADAM&lt;/span&gt;&lt;/strong&gt; &lt;span style="color:rgb(255,0,0);"&gt;! ! !&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:'comic sans ms', cursive;"&gt;votre projet est maintenant configuré ! :wub: &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:'comic sans ms', cursive;"&gt;&lt;strong&gt;&lt;u&gt;il reste cependant un toouuuuuuut petit détail, :rolleyes: &lt;/u&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:'comic sans ms', cursive;"&gt;pour pouvoir lancer votre ".exe", vous devez copier à coté du .exe toutes les ".dll" que vous trouverez dans le dossier "bin" de chaque bibliothèque ajoutée.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:'comic sans ms', cursive;"&gt;et voila !  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:'comic sans ms', cursive;"&gt;n'hésitez pas à poser des questions ou à me dire si vous trouvez une erreur.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:'comic sans ms', cursive;"&gt;pour essayer la configuration, je vous invite à lire le premier tutoriel sur la SDL2 &lt;iframe data-embed-src="&lt;base_url&gt;/topic/595-tuto-sdl-20/?do=embed" data-embedcontent="" frameborder="0" src="//melinyel.net/applications/core/interface/js/spacer.png"&gt;&lt;/iframe&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:'comic sans ms', cursive;"&gt;&lt;iframe data-embed-src="&lt;base_url&gt;/topic/595-tuto-sdl-20/?do=embed" data-embedcontent="" frameborder="0" src="//melinyel.net/applications/core/interface/js/spacer.png"&gt;&lt;/iframe&gt;&lt;/span&gt;&lt;/p&gt;
]]></description><link>https://melinyel.net/topic/922/tuto-installation-sdl-20</link><guid isPermaLink="true">https://melinyel.net/topic/922/tuto-installation-sdl-20</guid><dc:creator><![CDATA[cegdd]]></dc:creator><pubDate>Wed, 23 Jul 2014 15:05:38 GMT</pubDate></item><item><title><![CDATA[[Recensement] Les templates]]></title><description><![CDATA[&lt;p&gt;&lt;span style="font-size:24px;"&gt;Les templates, c'est quoi?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;    C'est un projet qui inclut des bibliothèques externes pré-configurés, pour faire simple par exemple vous n'arrivez pas à installer la SDL en C, vous pouvez trouver un projet ou la SDL est installée directement.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:18px;"&gt;SDL1.2:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;u&gt; Avec SDL TTF et SDL IMAGE:&lt;/u&gt;&lt;/p&gt;
&lt;p&gt;                   &lt;a href="http://jeux.developpez.com/telecharger/detail/id/3420/SDL-1-2-plus-SDL-Image-plus-SDL-TTF-Template-pour-Code-Blocks" rel="external nofollow"&gt;http://jeux.developpez.com/telecharger/detail/id/3420/SDL-1-2-plus-SDL-Image-plus-SDL-TTF-Template-pour-Code-Blocks&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:18px;"&gt; SDL2:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;                   &lt;a href="http://jeux.developpez.com/telecharger/detail/id/3538/SDL-2-0-Template-pour-Code-Blocks" rel="external nofollow"&gt;http://jeux.developpez.com/telecharger/detail/id/3538/SDL-2-0-Template-pour-Code-Blocks&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;u&gt; Avec SDL TTF et SDL IMAGE:&lt;/u&gt;&lt;/p&gt;
&lt;p&gt;                   &lt;a href="http://jeux.developpez.com/telecharger/detail/id/4036/SDL-2-0-3-plus-SDL2-Image-plus-SDL2-TTF-Template-pour-Code-Blocks" rel="external nofollow"&gt;http://jeux.developpez.com/telecharger/detail/id/4036/SDL-2-0-3-plus-SDL2-Image-plus-SDL2-TTF-Template-pour-Code-Blocks&lt;/a&gt;&lt;/p&gt;
]]></description><link>https://melinyel.net/topic/827/recensement-les-templates</link><guid isPermaLink="true">https://melinyel.net/topic/827/recensement-les-templates</guid><dc:creator><![CDATA[Alemort]]></dc:creator><pubDate>Fri, 27 Jun 2014 12:31:44 GMT</pubDate></item><item><title><![CDATA[[Cours complémentaires] Les bonnes pratiques en C]]></title><description><![CDATA[&lt;p&gt;Bonjour à tous,&lt;/p&gt;
&lt;p&gt;Dans ce cours un peu spécial, nous allons voir ensemble les bonnes pratiques à prendre en C, nous allons aussi voir dans quels cas certaines choses sont plus optimisées que d'autres.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Nous allons donc voir d'une manière générale la propreté du code, et l'optimisation de celui-ci en passant par des exemples d'erreures que tout le monde fait.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I- Propreté du code.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Pour un code lisible en C, il est impératif de bien construire son code. Les fichiers .h (headers) sont là pour les prototypes des fonctions, ainsi, le .c ne contiendra QUE le code des dites fonctions (et non pas des prototypes ou autres structures qui trainent dans des .c... BUARK!).&lt;/p&gt;
&lt;p&gt;DECOUPEZ VOTRE CODE! Plus votre code sera découpé, et mieu il sera, plus vous ferez en sorte d'avoir un certain nombre de fonctions (en évitant les fonctions "poubelles" quand même...), plus votre code sera lisible et propre! Prensez donc bien à découper votre code!&lt;/p&gt;
&lt;p&gt;Evtez les fonctions de 300 lignes! (ce qui rejoint le paragraphe précédent), effectivement, vous vous en sortez mieu en découpant le tout  .&lt;/p&gt;
&lt;p&gt;Essayez de respecter la taille d'un terminal (hé oui, les programmeurs Linux programment souvent sur le terminal, il faut penser à eux!) qui est de 80 caractères. Ainsi, évitez de dépasser les 80 caractères par lignes de code  .&lt;/p&gt;
&lt;p&gt;Les includes se font EN HAUT du code, je ne veux plus jamais voir des includes en plein milieu d'un code source... BRRRRR!&lt;/p&gt;
&lt;p&gt;Vous pouvez, en plus, respecter un certain format d'include, certains trient par ordre alphabétique, d'autres par longueur, le but étant de mettre tout de même les includes System AVANT les includes perso.&lt;/p&gt;
&lt;p&gt;ex:&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
// Ca c'est bon
#include &lt;stdio.h&gt;
#include "mon_include.h"
// CA C'EST BOF!
#include "mon_include.h"
#include &lt;stdio.h&gt;
&lt;/pre&gt;
&lt;p&gt;Evitez les includes inutiles! Cela ralentiera votre compilation si vous gardez des includes qui n'ont rien à faire là!&lt;/p&gt;
&lt;p&gt;Pensez à sauter des lignes, éviter le multi-exécution sur une ligne... c'est pas très propre.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Bref, rendez votre code LISIBLE! Un code source, c'est comme un livre, si tout est en bordel, on a pas envie de le lire  .&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;II- Optimisations et bonnes pratiques!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Passons à la partie la plus intéressente! L'optimisation et les bonnes pratiques. D'une manière générale les deux sont proches.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Au niveau des optimisations, nous allons d'abord commencer par un cas très spécial:&lt;/p&gt;
&lt;p&gt;Doit-on passer par copie ou pas? (ceci ne s'applique pas aux typpages de base, mais plutôt aux tableaux et aux structures).&lt;/p&gt;
&lt;p&gt;La réponse est simple: TOUT DEPENDS DE VOTRE CODE!&lt;/p&gt;
&lt;p&gt;Si vous souhaitez utiliser la variable que vous passez dans une fonction de manière locale à ladite fonction, passez la par copie.&lt;/p&gt;
&lt;p&gt;Dans le cas contraire, si vous voulez modifier une structure ou les cases d'un tableau par exemple, NE LA PASSEZ PAS PAR COPIE! Laissez votre stack tranquile non de dieu!&lt;/p&gt;
&lt;p&gt;Pour bien vous faire différencier ce qui est une copie et ce qui ne l'est pas, vouci des exemples concrets.&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
// Ceci est une copie (buark)
void mafonction(int tab[10]);
// Ceci n'est pas une copie
void mafonction(int *tab);
void mafonction(int tab[]);
// Ceci est une copie
void mafonction(struct mastruct s);
//Ceci n'est pas une copie
void mafonction(struct mastruct *s);
&lt;/pre&gt;
&lt;p&gt;Nous avons aussi le cas de l'allocation, quand faut-il allouer de la mémoire? Déjà, il faut savoir que l'allocation dynamique est la chose la plus LOURDE dans le monde de la programmation.&lt;/p&gt;
&lt;p&gt;Il est donc conseillé d'allouer tout l'espace naisséssaire au chargement de son programme, pour éviter d'allouer en plein milieu.&lt;/p&gt;
&lt;p&gt;Si les allocations sont rares, on peut tout de même les utiliser de manière dynamique. Mais il ne faut surtout pas en abuser! (c'est pour cela qu'un tableau à une dimension (au niveau de l'alloc) sera moins lourd qu'un tableau à double dimensions).&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Une autre pratique qui est plutôt bonne à connaitre pour l'optimisation: les calculs à base d'INT.&lt;/p&gt;
&lt;p&gt;Pourquoi utiliser le typpage int plutôt que float? Il faut savoir que les int sont stockés sur un seul registre, alors qu'un float (chiffre à virgule) est stocké sur 4 registres (merci l'ASM de nous le démontrer), il est donc conseillé d'utiliser des int plutôt que des float pour optimiser les calculs. N'oubliez pas que le calcul sur 4 registres sera TOUJOURS plus long que le calcul sur 1 registre (4x plus long), et cela, peut importe la valeur stockée dans les registres.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Enfin, la meilleure pratique pour bien optimiser son programme, c'est savoir de quoi est composé le dit programme!&lt;/p&gt;
&lt;p&gt;Je m'explique, utiliser des fonctions préfaites par la LibC, c'est bien, mais quand on ne sait pas comment elles fonctionnent, c'est MAL!&lt;/p&gt;
&lt;p&gt;En effet, vous êtes plusieurs à ne pas savoir que dans certains cas, printf n'est pas du tout optimisé (en effet, printf passe par 3 boucles ET une bufferisation des données AVANT affichage, alors qu'un simple puts ou write aurait fait l'affaire!), je vous conseille donc de vous renseigner sur les fonctions que vous utilisez, ou encore mieu! RECODEZ LES! Vous apprendrez beaucoup plus ainsi que de n'importe qu'elle autre manière!&lt;/p&gt;
&lt;p&gt;Je vous invites à lire mes cours dans la section C, qui utilisent le principe de l'utilisation de Fonctions System au lieu de passer par des fonctions de la LibC, pour vous apprendre à bien comprendre la différence entre les deux, et avoir de bonnes habitudes (qui sait, vous comprendrez peut être comment ça marche  )&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Si vous désirez d'autres informations, n'hésitez pas à laisser un commentaire ci-dessous!&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;A très bientôt pour un prochain cours!&lt;/p&gt;
&lt;p&gt;AlexMog.&lt;/p&gt;
]]></description><link>https://melinyel.net/topic/808/cours-complémentaires-les-bonnes-pratiques-en-c</link><guid isPermaLink="true">https://melinyel.net/topic/808/cours-complémentaires-les-bonnes-pratiques-en-c</guid><dc:creator><![CDATA[AlexMog]]></dc:creator><pubDate>Thu, 12 Jun 2014 16:52:20 GMT</pubDate></item><item><title><![CDATA[Apprendre l'optimisation en C?]]></title><description><![CDATA[&lt;div&gt;Comme-vous le savez lorsque l'on fait de la programmation, un point important auquel n'ont accordé aucune attention lorsque l'on commence, c'est bien l'optimisation.&lt;/div&gt;
&lt;div&gt;Donc pour aller vers l'optimisation en language C, vers où se tourner?&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;u&gt;&lt;span style="font-size:18px;"&gt;&lt;strong&gt;Pour améliorer ses algorithmes de calcul:&lt;/strong&gt;&lt;/span&gt;&lt;/u&gt;&lt;/div&gt;
&lt;div&gt;-vers l'assembleur pour optimiser les différents calculs&lt;/div&gt;
&lt;div&gt;-Utiliser des types de variables moins gourmandes&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:18px;"&gt;&lt;strong&gt;&lt;u&gt;Optimisation générale:&lt;/u&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;-éviter la copie de variable ou de tableaux dans des fonctions.&lt;/div&gt;
&lt;div&gt;-Recoder les fonctions que l'on utilise pour mieux les comprendre et en créer de moins gourmandes pour nôtres utilisations.&lt;/div&gt;
&lt;div&gt;Mais bon, les cours sur internet né détail pas trop ces points généralement.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;span style="font-size:18px;"&gt;&lt;u&gt;&lt;strong&gt;Quelques questions:&lt;/strong&gt;&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;em&gt;            Pour recoder une fonction par exemple prin, on se dirige vers quel type de fonction? Les fonctions que l'on utilisera il serait bien de les recoder mais il arrivera un point ou on pourra plus continuer, non?&lt;/em&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;em&gt;           Y a-t-il de bons sites qui donnent des conseils sur ce genre de sujet?&lt;/em&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;em&gt;           Y a-t-il d'autres voix pour optimiser son programme?&lt;/em&gt;&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;em&gt;           Est-il préférable d'optimiser son programme en codant les fonctions, ou bien coder un programme qui marche et ensuite l'optimiser?&lt;/em&gt;&lt;/div&gt;
]]></description><link>https://melinyel.net/topic/801/apprendre-loptimisation-en-c</link><guid isPermaLink="true">https://melinyel.net/topic/801/apprendre-loptimisation-en-c</guid><dc:creator><![CDATA[Alemort]]></dc:creator><pubDate>Sun, 08 Jun 2014 16:03:14 GMT</pubDate></item><item><title><![CDATA[[TUTO] SDL2.0 #2]]></title><description><![CDATA[&lt;p&gt;Bonjour à tous !&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;ça fait un moment que j'en parle, voici la suite du premier cours sur la SDL2 !&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;malheureusement le temps me manque, le peu de temps dont je dispose,  je n'ais pas de connexion internet.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;la solution la plus simple est donc d'écrire le code source du cours en le SURcommentant  &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;le code source qui vas suivre vous montre étape par étape comment animer le personnage de rayman&lt;span style="font-size:12px;"&gt;&lt;span style="font-family:arial, helvetica, sans-serif;"&gt;&lt;/span&gt;&lt;/span&gt; grâce a la SDL2.&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
//pour le type bool
#include &lt;stdbool.h&gt;
//pour les atexit
#include &lt;stdlib.h&gt;
//pour les printf
#include &lt;stdio.h&gt;
//les includes SDL
#include &lt;SDL2/SDL.h&gt;
#include &lt;SDL2/SDL_image.h&gt;
int main ()
{
//initialisation de la sdl
if (SDL_Init (SDL_INIT_VIDEO) &lt; 0)
{   printf("erreur SDL_Init: %s\n", SDL_GetError());
return EXIT_FAILURE;
}
atexit(SDL_Quit);
//initialisation de la sdl_image
if (IMG_Init(IMG_INIT_PNG) &lt; 0)
{   printf("erreur IMG_Init: %s\n", SDL_GetError());
return EXIT_FAILURE;
}
atexit(IMG_Quit);
//contexte d'affichage
SDL_Window *screen;
//tampon de rendu
SDL_Renderer *renderer;
//position de l'écran, de rayman et des différents sprites de rayman
SDL_Rect pecran, prayman;
SDL_Rect raymantiles[16];

unsigned int temps, tempsbride = 0, tempsanim = 0, index, anim = 0;
bool droite = true;


//initialisation des positions
pecran.x = 0;
pecran.y = 0;
prayman.w = 120;
prayman.h = 136;
for(index = 0 ; index &amp;lt; 6 ; index++)
{
	raymantiles[index].x = index*60;
	raymantiles[index].y = 1100;
	raymantiles[index].w = 60;
	raymantiles[index].h = 68;
}
for(index = 0 ; index &amp;lt; 6 ; index++)
{
	raymantiles[index+6].x = index*60;
	raymantiles[index+6].y = 68+1100;
	raymantiles[index+6].w = 60;
	raymantiles[index+6].h = 68;
}
for(index = 0 ; index &amp;lt; 4 ; index++)
{
	raymantiles[index+12].x = index*60;
	raymantiles[index+12].y = 136+1100;
	raymantiles[index+12].w = 60;
	raymantiles[index+12].h = 68;
}

//suppression du curseur de souris
SDL_ShowCursor(SDL_DISABLE);
//création de la fenêtre
screen = SDL_CreateWindow("Rayman_like", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 0, 0, SDL_WINDOW_FULLSCREEN_DESKTOP);
//création du tampon de rendu
renderer = SDL_CreateRenderer(screen, -1, SDL_RENDERER_ACCELERATED);
//récupération de la taille de l'écran
SDL_GetWindowSize(screen , &amp;amp;pecran.w , &amp;amp;pecran.h);

//mise en position de rayman
prayman.x = (pecran.w/2)-(prayman.w/2);
prayman.y = (pecran.h*0.65)-(prayman.w/2);

// chargement des images
SDL_Texture *fond = IMG_LoadTexture(renderer, "fond.jpg");
SDL_Texture *rayman = IMG_LoadTexture(renderer, "rayman.png");

//test d'erreur a la création de la fenêtre, du tampon de rendu et des images. (fonction critiques qui peuvent rencontrer des erreurs
if (screen == NULL || renderer == NULL || fond == NULL || rayman == NULL)
{
	printf("erreur: %s\n", SDL_GetError());
	return EXIT_FAILURE;
}

//entrée en boucle principale
while(1)
{
	//récupération du temps
	temps = SDL_GetTicks();
	
	//si le programme tourne depuis "x" ms, on quitte;
	if (temps &amp;gt;= 7000) { break; }
	
	
	//test pour changer le sprite d'animation si "x" ms sont écoulées
	if (temps - tempsanim &amp;gt;= 60)
	{
		//sauvegarde du temps actuel pour la prochaine itération
		tempsanim = temps;
		//sprite suivant
		anim++;
		//si le dernier sprite est atteint, on reviens au premier
		if(anim == 16){anim = 0;}
	}
	
	//bride pour sinchro ecran ~60fps
	if (temps - tempsbride &amp;gt;= 16)
	{
		//assignation du temps actuel pour la prochaine itération
		tempsbride = temps;
		
		//si rayman touche la bordure d'écran a droite, il fait demi tour !
		if (prayman.x + prayman.w &amp;gt;= pecran.w) { droite = false; }
		//si il touche la bordure gauche, il fait de même.
		else if (prayman.x &amp;lt;= 0) {droite = true;}
		
		
		//vidage du tampon de rendu
		SDL_RenderClear(renderer);
		
		//copie du fond sur le tampon
		SDL_RenderCopy(renderer, fond, NULL, &amp;amp;pecran);
		
		//si rayman vas à gauche
		if (!droite)
		{
			//décrémentation horizontale de la position de rayman.
			prayman.x -= 5;
			//copie de rayman (en inversant le sens de l'image) sur le tampon
			SDL_RenderCopyEx(renderer, rayman, &amp;amp;raymantiles[anim], &amp;amp;prayman, 0,NULL, SDL_FLIP_HORIZONTAL);
		}
		//sinon
		else
		{
			//incrémentation horizontale de la position de rayman.
			prayman.x += 5;
			//copie de rayman sur le tampon
			SDL_RenderCopy(renderer, rayman, &amp;amp;raymantiles[anim], &amp;amp;prayman);
		}
		
		//affichage du tampon de rendu sur l'écran.
		SDL_RenderPresent(renderer);
	}
	else
	{
		// si l'écran ne suis pas, ont fait une pause.
		// cela permet de grandement libérer le CPU.
		SDL_Delay(5);
	}
}

//programme terminé
return EXIT_SUCCESS;

}
&lt;/pre&gt;
&lt;p&gt;si vous compilez chez vous, vous devriez avoir un résultat s'approchant de ça:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=fTFRiKdBPec" rel="external nofollow"&gt;https://www.youtube.com/watch?v=fTFRiKdBPec  (a noter qu'ici le déplacement était au clavier et non automatique)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;pour tout commentaire ou question, je suis présent pour vous répondre  &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;voici les fichiers pour ceux qui voudrais le compiler et le modifier pour s’entraîner ----&gt; &lt;a href="https://drive.google.com/file/d/0BwiU5yPF-jlWdHJERFhwZnFycjg/edit?usp=sharing" rel="external nofollow"&gt;ICI&lt;/a&gt;&lt;/p&gt;
]]></description><link>https://melinyel.net/topic/795/tuto-sdl20-2</link><guid isPermaLink="true">https://melinyel.net/topic/795/tuto-sdl20-2</guid><dc:creator><![CDATA[cegdd]]></dc:creator><pubDate>Fri, 06 Jun 2014 19:51:39 GMT</pubDate></item><item><title><![CDATA[IA #4 - le GOAP]]></title><description><![CDATA[&lt;p&gt;Bonjour a tous !&lt;br/&gt;&lt;br/&gt;
Tous d'abord qu'est ce que le GOAP ?&lt;br/&gt;&lt;br/&gt;
C'est l'abréviation de Goal Oriented Action Planning, ce qui pour les non anglophone, veut dire la&lt;/p&gt;
&lt;p&gt;planification des actions en fonction de tes buts, ou de tes souhaits.&lt;br/&gt;&lt;br/&gt;
C'est un type d'IA qui a pour but de remplacer les FSMs (Finite State Machine), les automates a états&lt;/p&gt;
&lt;p&gt;finis en gros. (Le mot anglais est plus classe et plus court a écrire donc c'est celui là que je vais utiliser maintenant).&lt;br/&gt;
En effet, les FSMs sont bêtes et méchantes, bien que facile a réaliser. Mais dès qu'il s'agit d'un comportement où il faut que l'IA ai l'air de réfléchir, les FSMs sont inadaptées. Ainsi les GOAPs sont utilisés principalement dans les FPS,&lt;br/&gt;
et aussi dans le mondialement connu Starcraft.&lt;br/&gt;
Cette IA a pour but d'offrir plus de challenge au joueur.&lt;br/&gt;
Mais rien ne vous empêche de faire une IA bien plus intelligente dans les autres types de jeu comme les RPG, ou les rogues like.&lt;br/&gt;&lt;br/&gt;
Le principe des GOAP maintenant :&lt;br/&gt;
Un pnj a différents but, comme manger, dormir, travailler etc...&lt;br/&gt;
chaque but a un niveau d'importance plus ou moins grand.&lt;br/&gt;&lt;br/&gt;
schéma :&lt;br/&gt;&lt;br/&gt;
but           : importance&lt;br/&gt;
dormir      : 4&lt;br/&gt;
manger    : 2&lt;br/&gt;
travailler   : 1&lt;br/&gt;&lt;br/&gt;
Ici par exemple le pnj a très envie de dormir.&lt;br/&gt;
Les niveaux d'importance sont mis a jour au fil du temps et les actions les plus importantes&lt;br/&gt;
sont exécutées en premier.&lt;br/&gt;&lt;br/&gt;
En code :&lt;br/&gt;
 &lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
typedef struct t_state
{
unsigned char id;
unsigned char importance;
}t_state;
t_state but[nombre_de_but_different];
/* on initialise le tout
int i;
for( i = 0 ; i &lt; nombre_de_but_different ; i++ )
{
but[i].id = i;
but[i].importance = 0;
}
&lt;/pre&gt;
&lt;p&gt;
L'id sert a savoir le but ( par exemple dormir c'est 0, manger c'est 1 et travailler c'est 3) parce qu’à chaque fois que l'importance d'un but change, il faut retrier le tableau.&lt;br/&gt;
Regardez du coté des algorithme de tri, et n'oubliez pas que le tableau est presque trier, seul un élément est a sa mauvaise place.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Une fonction de tri en exemple (oui c'est utile de faire cela)&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
void tri(t_state but[], int nb_but)
{
/* Il s'agit ici d'un tri à bulle qui marche, mais qui est le plus lent possible
c'est pour vous forcer à regarder du côté des algo de tri*/
int changement = 1;
int i;
t_state transition;
while(changement)
{
        changement = 0;
	for(i = 0 ; i &amp;lt; nb_but - 1 ; i++)
	{
		if(but[i].importance &amp;lt; but[i+1].importance)
		{
			transition.importance = but[i].importance;
			transition.id = but[i].id;
			
			but[i].importance = but[i+1].importance;
			but[i].id = but[i+1].id;
			
			but[i+1].importance = transition.importance;
			but[i+1].id = transition.id;
			
			changement = 1;
		}
	}
}

}
&lt;/pre&gt;
&lt;p&gt;&lt;br/&gt;
On regarde donc le premier élément du tableau, qui est le plus important, et on exécute l'action associé.&lt;br/&gt;&lt;br/&gt;
Et la vous allez me dire : "mais alors c'est la même chose que les FSMs non ?"&lt;br/&gt;
Et bah non : les état ne sont plus reliés entre eux, donc l’insertion d'un nouveau but ne nécessite pas de tout revoir, mais en contre partie, cela nécessite plus de temps de processeur pour faire cela.&lt;br/&gt;
Et aussi, une grande nouveauté : pourquoi ce contenter d'UNE action par but ?&lt;br/&gt;
Si vous avez faim, vous pouvez vous faire vous même à manger, aller chez quelqu'un, ou encore aller dans un fast-food. il y a donc plusieurs solutions possibles.&lt;br/&gt;&lt;br/&gt;
Pour chaque action, il suffit de déterminer son poids :&lt;br/&gt;
Celui-ci peut varier en fonction de plusieurs facteurs, comme le temps mis à faire l'action,&lt;br/&gt;
le prix que cela va nous coûter etc...&lt;br/&gt;
Et il faut aussi déterminer l'importance que vont perdre les but. Par exemple :&lt;br/&gt;
fastfood : manger - 2&lt;br/&gt;
maison   : manger - 4&lt;br/&gt;&lt;br/&gt;
On peut aussi choisir une des deux actions en fonction du poids en utilisant le principe des algorithmes de Dijkstra (parcours de graphe), qui est le même principe que le pathfinding. L'avantage, c'est de pouvoir avoir une plus grande flexibilité. Il faut alors voir les actions comme un enchaînement d'actions, et plusieurs actions peuvent menées a la même suivante.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Th_gra36.gif" src="&lt;base_url&gt;/applications/sslimageproxy/interface/image.php?url=http://serge.mehl.free.fr/anx/anx_gif/Th_gra36.gif"/&gt;&lt;br/&gt;
Le poid peut être en fonction de plusieurs choses, comme le temps, et l'importance que cela va perdre.&lt;br/&gt;
Par exemple, si l'on a très peu de temps et on est juste à coté du fast-food, alors on va y allez, et si on a tous notre temps, et juste à coté de chez soi, autant allez à sa maison. Le poid peut aussi être influencer par l'argent dépensé etc...&lt;br/&gt;&lt;br/&gt;
exemple :&lt;br/&gt;
 &lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
/on calcule le poid de chaque action/
poid[nb_action_differentes];
int i;
for ( i = 0 ; i &lt; nb_action_differente ; i++)
{
poid[i] = (temps * 0,5) /* plus le temps est court, mieux c'est. 50% d'importance pour le temps*/
+ (diminution_de_l_importance * 0,5);
}
&lt;/pre&gt;
&lt;p&gt;
je suis parfaitement conscient que le temps a un poid totalement aléatoire en fonction de l'unité&lt;br/&gt;
utilisé. C'est à vous de calibrer correctement le calcul du poid. il ne s'agit ici que du principe général.&lt;br/&gt;
Dans ce cas, plus le poid est grand, plus le temps pris est long.&lt;br/&gt;
Attention, la variable diminution_de_l'importance est négative (-2, -4 etc...) !&lt;br/&gt;
 &lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
int meilleur_poid;
int meilleur_poid = poid[0];/C'est très important d'initialiser !/
int meilleure_action;
for ( i = 0 ; i &lt; nb_action_differente ; i++)
{
if(poid[i] &lt; meilleur_poid)
{
meilleur_poid = poid[i];
meilleure_action = i;
}
}
&lt;/pre&gt;
&lt;p&gt;et on fait l'action :&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
actionmeilleure_action;
&lt;/pre&gt;
&lt;p&gt;Je considère ici, que l'on envoie rien a la fonction, mais vous pouvez facilement le faire.&lt;br/&gt;
Le tableau est un tableau de pointeur de fonctions (voir le tutoriel d'AlexMog à ce sujet).&lt;/p&gt;
&lt;p&gt;Pensez à updater ce tableau régulièrement tout les X secondes ou millisecondes, car une action peut à un moment&lt;/p&gt;
&lt;p&gt;être plus utile que celle que vous voulez faire, alors qu'avant, elle ne servait à rien.&lt;br/&gt;&lt;br/&gt;
Vous avez donc maintenant réussi a faire un pnj qui pourra avoir des buts et faire des actions&lt;br/&gt;
en conséquence.&lt;br/&gt;
N'oubliez pas pas que plus vous augmenter le nombres de buts et d'actions, plus le pnj sera réaliste,&lt;br/&gt;
et plus cela prendra de temps pour "réfléchir"(pas beaucoup non plus mais sur des milliers de pnjs, cela se ressent).&lt;br/&gt;
Par exemple, le FPS  F.E.A.R (j’insiste sur le mot FPS là !) possède 67 buts différents (pas un seul où&lt;br/&gt;
il le but est de tuer l’ennemi   ) et 197 actions différentes.&lt;/p&gt;
]]></description><link>https://melinyel.net/topic/785/ia-4-le-goap</link><guid isPermaLink="true">https://melinyel.net/topic/785/ia-4-le-goap</guid><dc:creator><![CDATA[daemondragon]]></dc:creator><pubDate>Wed, 04 Jun 2014 06:44:19 GMT</pubDate></item><item><title><![CDATA[[Cours #8] Listes chainées]]></title><description><![CDATA[&lt;p&gt;Bonjour à tous,&lt;/p&gt;
&lt;p&gt;Dans ce cours, nous allons voir ce qu'est une liste chainées, et comment elle fonctionne.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I- Liste chainée? WTF?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;D'après Wikipedia: "Une liste chaînée désigne en informatique une structure de données représentant une collection ordonnée et de taille arbitraire d'éléments de même type".&lt;/p&gt;
&lt;p&gt;Pour résumer, il s'agit d'une collection de données (comme un tableau, sisi), qui a une taille variable, donc on a pas besoin de connaitre la taille de la liste à l'avance (un peu comme dans le cours sur les allocations dynamiques  ). Les éléments sont enregistrés les uns après les autres.&lt;/p&gt;
&lt;p&gt;C'est donc une grosse liste de données. Le premier élément pointe vers le second, le second vers le troisième, le troisième vers le quatrième etc...&lt;/p&gt;
&lt;p&gt;Comme le montre le schéma ci-dessous:&lt;/p&gt;
&lt;p&gt;(Source: Openclassroom)&lt;/p&gt;
&lt;p&gt;&lt;img alt="39595.jpg" src="http://uploads.siteduzero.com/files/39001_40000/39595.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;C'est une liste chainée simple, et nous ne verrons que celle-ci. Pour la liste chainée circulaire, ou encore double, je vous laisse chercher par vous mêmes  &lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;II- Créons notre structure de données!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Une liste chainées à pour but de contenir des données (c'est logique...), il faut donc créer une structure pour stocker lesdites données.&lt;/p&gt;
&lt;p&gt;Pour ma part de vais créer une liste pour stocker l'age et la taille d'un certain nombre d'utilisateurs.&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
typedef struct s_list
{
int taille;
int age;
struct s_list *next;
}t_list;
&lt;/pre&gt;
&lt;p&gt;Oh! c'est étrange, qu'est-ce que la variable "next" vient faire ici? Comme je l'ai dit plus haut, il s'agit du pointeur sur le prochain élément de notre liste chainée. Il va falloir penser à le mettre à NULL pour connaitre la fin de notre liste chainée! En effet, lorsqu'on sera au dernier élément, on le sera grâce au NULL.&lt;/p&gt;
&lt;p&gt;Dans ce cours, je vais uniquement vous apprendre à ajouter des éléments à votre liste, à parcourir votre liste, et enfin à supprimer votre liste. C'est à vous d'utiliser votre tête pour la suite!&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;III- Ajouter un élément à la liste.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Maintenant que notre structure est crée, nous allons créer plusieurs fonctions, pour gérer notre liste chainée.&lt;/p&gt;
&lt;p&gt;Créons tout d'abord une fonction pour ajouter un élément à la liste:&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
int add_to_list(t_list **list, t_list *datas)
{
t_list *next;
next = NULL;
if (*list != NULL)
next = *list;
if ((*list = malloc(sizeof(t_list))) == NULL)
return (1);
(*list)-&gt;taille = datas-&gt;taille;
(*list)-&gt;age = datas-&gt;age;
(*list)-&gt;next =next;
return (0);
}
&lt;/pre&gt;
&lt;p&gt;Voici un exemple d'utilisation de la fonciton:&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
int main(void)
{
t_list *list;
t_list datas;
*list = NULL;
datas.age = 10;
datas.taille = 180;
// On ajoute à notre liste
if (add_to_list(&amp;list, &amp;datas))
return (1);
// On récupère le premier noeud pour voir ce qu'il contient
printf("Age: %d, Taille: %d\n", list-&gt;age, list-&gt;taille);
return (0);
}
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;III- Parcourons notre liste!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Nous allons à présent parcourir notre liste.&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
int main(void)
{
t_list *list;
t_list datas;
int i;
i = -1;
// On remplis notre liste avec 10 éléments
while (++i &lt; 10)
{
datas.age = i;
datas.taille = 180 + i;
if (add_to_list(&amp;list, &amp;datas))
return (1);
}
// On parcours et on affiche notre liste!
while (list != NULL)
{
printf("Age: %d, Taille: %d\n", list-&gt;age, list-&gt;taille);
list = list-&gt;next;
}
return (0);
}
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;IV- Vidons notre liste! (C'est important de vider la mémoire!)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Pour cela, créons une fonction de vidage.&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
void clear_list(t_list **list)
{
t_list *elem;
t_list *next;
elem = *list;
while (elem)
{
next = elem-&gt;next;
free(elem);
elem = next;
}
*list = NULL;
}
&lt;/pre&gt;
&lt;p&gt;Exemple d'utilisation:&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
int main(void)
{
t_list *list;
t_list datas;
int i;
i = -1;
// On remplis notre liste avec 10 éléments
while (++i &lt; 10)
{
datas.age = i;
datas.taille = 180 + i;
if (add_to_list(&amp;list, &amp;datas))
return (1);
}
// On parcours et on affiche notre liste! (on utilise un pointeur annexe pour ne pas perdre le noeud mère)
list *elem = list;
while (elem != NULL)
{
printf("Age: %d, Taille: %d\n", elem-&gt;age, elem-&gt;taille);
elem = elem-&gt;next;
}
clear_list(&amp;list);
return (0);
}
&lt;/pre&gt;
&lt;p&gt;Je vous laisse la joie d'analyser le code, à ce stade des cours (et si vous avez bien tout suivi) vous savez analyser le code, je vous laisse donc le comprendre par vous mêmes! Je reste disponible pour répondre à vos questions!&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;A bientôt pour un prochain cours!&lt;/p&gt;
]]></description><link>https://melinyel.net/topic/783/cours-8-listes-chainées</link><guid isPermaLink="true">https://melinyel.net/topic/783/cours-8-listes-chainées</guid><dc:creator><![CDATA[AlexMog]]></dc:creator><pubDate>Tue, 03 Jun 2014 17:04:34 GMT</pubDate></item><item><title><![CDATA[IA #3 - les mécanismes de groupes]]></title><description><![CDATA[&lt;p&gt;Qu'est ce que les mécanismes de groupe ?&lt;br/&gt;&lt;br/&gt;
Ce sont les actions qui se passent lorsque vous êtes avec un nombre&lt;br/&gt;
important de personnes.&lt;br/&gt;
Ce tutoriel va mettre en place l'algorithme flack and swarm.&lt;br/&gt;
Cet algorithme est issue de l'observation des "essaims" de poissons :&lt;br/&gt;
Lorsqu'un poissons voit un prédateur, il fuit. Le poisson a coté voit celui&lt;br/&gt;
qui fuit et fuit a son tour, etc... Ce mécanisme est tellement rapide&lt;br/&gt;
qu'un observateur à l'impression que ceci se fait directement.&lt;br/&gt;
C'est ça les mécanismes de groupe.&lt;br/&gt;&lt;br/&gt;
Ces mécanismes sont souvent utilisés dans des jeu de type total war,&lt;br/&gt;
ou un groupe de personnes n'a en fait qu'une vrai personnes qui va&lt;br/&gt;
"réfléchir", le reste va copier les mouvement de celui qui réfléchit.&lt;br/&gt;&lt;br/&gt;
Mais quels sont les avantages d'utiliser cette technique ?&lt;br/&gt;&lt;br/&gt;
Tout d'abord, cela consomme moins de processeur car une seule personne&lt;br/&gt;
réfléchit, fait son action, et tout le monde copie son action. Du coup,&lt;br/&gt;
personnes d'autre ne réfléchit. (vous faites aussi cela en cours, tout&lt;br/&gt;
le monde copie sur une unique personne, cela prend moins de temps aux&lt;br/&gt;
autre cerveaux pour réfléchir, donc c'est bien   )&lt;br/&gt;
Cela permet aussi d'assurer une cohérence dans le groupe&lt;br/&gt;
vous imaginer une armée où chacun peut faire ce qu'il veut ?&lt;br/&gt;
limiter le nombre de personnes qui réfléchit permet donc de limiter les incohérences&lt;br/&gt;
dans le jeu pour le joueur.&lt;br/&gt;&lt;br/&gt;
Donc pour le code, il faut faire cela :&lt;br/&gt;
"l'entité" leader fait cela :&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
typedef struct t_leader
{
char etat;
void(*p_fonction)(t_info *);
}t_leader;
&lt;/pre&gt;
&lt;p&gt;
Si vous ne savez pas se que signifie etat, aller voir le tutoriel précédent.&lt;br/&gt;
p_fonction est un pointeur de fonction.&lt;br/&gt;
Allez voir le tutoriel d'AlexMog qui est très bien fait.&lt;/p&gt;
&lt;p&gt;&lt;iframe data-embed-src="&lt;base_url&gt;/topic/746-cours-7-les-pointeurs-sur-fonction/?do=embed" data-embedcontent="" frameborder="0" src="//melinyel.net/applications/core/interface/js/spacer.png"&gt;&lt;/iframe&gt;&lt;/p&gt;
&lt;p&gt;
Utiliser les pointeur sur fonction permet d'exécuter très rapidement la fonction,&lt;br/&gt;
au lieu de mettre un ID de fonction et faire un immense switch ou if, else if ...&lt;br/&gt;&lt;br/&gt;
Dès lors, afin que les sbires, où ceux qui suivent le leader fassent les même actions,&lt;br/&gt;
il suffit de faire :&lt;br/&gt;
 &lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
typedef struct t_sbire
{
void(*p_fonction)(t_info );
}t_sbire;
&lt;/pre&gt;
&lt;p&gt;la structure t_info contient toutes les infos utiles pour exécuter les actions&lt;br/&gt;
Aller encore regarder mon tutoriel précédent pour comprendre se que c'est&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
t_leader leader;
t_info info;
/ vous mettez le pointeur sur fonction en fonction de l'état du pnj
par exemple : */
leader.p_fonction = &amp;attack_near_enemy;
t_sbire sbire[16]; /* 16 est un exemple */
int i;
for(i = 0 ; i &lt; 16 ; i++)
{
sbire[i].p_fonction = leader.p_fonction;
}
/* tout les sbires vont maintenant pouvoir faire la même action que le leader /
&lt;/pre&gt;
&lt;p&gt;et on exécute le tout&lt;br/&gt;
 &lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
leader.p_fonction(&amp;info); / on envoie la structure d'info a la fonction (un pointeur)*/
for(i = 0 ; i &lt; 16 ; i++)
{
sbire[i].p_fonction(&amp;info);
}
&lt;/pre&gt;
&lt;p&gt;&lt;br/&gt;
Et voila, vous pouvez maintenant créer facilement des mécaniques de groupe, afin de créer&lt;br/&gt;
des immense batailles, ou encore une joli danse (chacun fait la même chose que son voisin)  .&lt;/p&gt;
]]></description><link>https://melinyel.net/topic/776/ia-3-les-mécanismes-de-groupes</link><guid isPermaLink="true">https://melinyel.net/topic/776/ia-3-les-mécanismes-de-groupes</guid><dc:creator><![CDATA[daemondragon]]></dc:creator><pubDate>Sat, 31 May 2014 07:31:22 GMT</pubDate></item><item><title><![CDATA[IA #2 - le pnj : un automate à états finis]]></title><description><![CDATA[&lt;p&gt;Bonjour à tous !&lt;br/&gt;&lt;br/&gt;
En regardant le titre, vous avez sans doute penser : "kesako ?"&lt;br/&gt;
Et bah c'est très simple : un automate, c'est une machine qui fait ce qu'on lui dit,&lt;br/&gt;
et pourquoi a états finis ?&lt;/p&gt;
&lt;p&gt;C'est parce que cet automate peut avoir plusieurs états différents, mais il ne&lt;br/&gt;
peut pas prendre les états que l'on n'a pas coder pour lui. Il ne peut aussi&lt;/p&gt;
&lt;p&gt;prendre qu'un seul état à la fois.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Les automate à état fini sont très utilisés dans les jeux vidéos car ils sont&lt;br/&gt;
très simples à mettre en place et à débuggés. Le majeur inconvénients, c'est&lt;br/&gt;
qu'il sont prédictible, ce qui peut briser l'illusion qu'un véritable joueur,&lt;br/&gt;
est devant le joueur. Pour éviter la prédictibilité, une des solutions possibles&lt;br/&gt;
est d'augmenter le nombre d'états, ce qui permet plus de variations dans le pnj&lt;br/&gt;&lt;br/&gt;
Concrètement, prenons exemple sur un soldat dans un jeu qui protège un village par exemple :&lt;br/&gt;
On peut lui mettre deux états différents :&lt;br/&gt;
État 1 : patrouille&lt;br/&gt;
État 2 : attaque&lt;br/&gt;&lt;br/&gt;
Il faut maintenant dire ce qu'il faut pour changer d'état (c'est mieux non ?)&lt;br/&gt;
Par exemple, pour aller de l'état 1 à l'état 2, il faut que le soldat ai vu un intrus&lt;br/&gt;
et de l'état 2 au 1, il faut que le garde ai tuer l'intrus.&lt;br/&gt;&lt;br/&gt;
Pour reprendre l'exemple du soldats, on peut créer d'autre états :&lt;br/&gt;&lt;br/&gt;
État 3 : suivit d'un intrus qui veut s'enfuir.&lt;br/&gt;
État 4 : fuite car l'intrus est trop fort.&lt;br/&gt;
État 5 : va dormir (il a le droit de dormir non ?)&lt;br/&gt;&lt;br/&gt;
Bref vous l'avez compris, plus il y a d'états, plus le pnj sera réaliste.&lt;br/&gt;&lt;br/&gt;
Et maintenant le code :&lt;br/&gt;
 &lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
/*
la structure qui va servir pour votre pnj
*/
typedef struct t_perso t_perso;
struct t_perso
{
char etat;
char type;
t_info info;
}
&lt;/pre&gt;
&lt;p&gt;
l'état correspond a l'état actuel du pnj. par exemple, pour le soldat,&lt;br/&gt;
si l’état est égal a 1, alors le soldat patrouille, etc...&lt;br/&gt;
le type correspond au type de pnj que vous avez.&lt;/p&gt;
&lt;p&gt;et la structure t_info, contient tout ce que le pnj a besoin de savoir pour changer&lt;br/&gt;
d'état. (il a besoin de savoir si un ennemi est proche de lui etc...)&lt;br/&gt;
 &lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
void change_etat(t_perso pnj)
{
/
Je suppose que toutes les infos utiles sont dans la structure t_perso
touts les mot en majuscules sont soit des define, soit des énumérations;
faites ce qu'il vous plaît le plus
*/

if(pnj-&amp;gt;etat == PATROUILLE)
{
    if(test_attaque(pnj))
    {
        pnj-&amp;gt;etat = ATTAQUE;
    }
    else if(test_sommeil(pnj))
    {
        pnj-&amp;gt;etat = DODO;
    }
}
if(pnj-&amp;gt;etat == ATTAQUE)
{
    if(test_intrus_mort(pnj))
    {
        pnj-&amp;gt;etat = PATROUILLE;
    }
    else if(test_intrus_trop_fort(pnj))
    {
        pnj-&amp;gt;etat = FUITE;
    }    
}
if(pnj-&amp;gt;etat == DODO)
{
    if(test_sommeil_fini(pnj))
    {
        pnj-&amp;gt;etat = PATROUILLE;
    }    
}
if(pnj-&amp;gt;etat == FUITE)
{
    if(test_intrus_loin(pnj))
    {
        pnj-&amp;gt;etat = PATROUILLE;
    }
}

}
&lt;/pre&gt;
&lt;p&gt;&lt;br/&gt;
les fonctions test_quelquechose(), sont des fonctions booléenne : si la condition est vrai, alors on retourne&lt;br/&gt;
1, et on change d'état associé a la fonction, si la fonction retourne 0, la condition est fausse,&lt;br/&gt;
alors on ne change pas d'état. ces fonction nécessite une structure t_perso pour tester&lt;br/&gt;
les conditions, mais rien ne vous oblige à les utiliser.&lt;br/&gt;
Faites vos propres test avec ce qu'il faut pour changer d’état, il faut juste modifier un peu&lt;br/&gt;
le code.&lt;br/&gt;&lt;br/&gt;
Comme vous le voyez, ce code est simple, et est très facilement lisible, donc facilement modifiable et&lt;br/&gt;
débuggable.&lt;br/&gt;
Chaque type de personnage nécessite sa propre fonction de changement d'état(un fermier qui fabrique ses&lt;br/&gt;
propres vêtements n'est pas crédible, réservez cela au tailleur).&lt;br/&gt;&lt;br/&gt;
Afin de vous retrouver plus facilement dans la création de changement d'état, n'hésitez pas&lt;br/&gt;
à faire un graphique des différents état possible :&lt;/p&gt;
&lt;p&gt;&lt;img alt="9.jpg?w=300&amp;h=232" src="http://jakemissing.files.wordpress.com/2012/11/9.jpg?w=300&amp;amp;h=232"/&gt;&lt;/p&gt;
&lt;p&gt;pour info, flee veut dire s'enfuir.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Et voila, vous avez maintenant un pnj qui peut réagir en fonction des événement&lt;/p&gt;
&lt;p&gt;qu'il l'entoure  &lt;/p&gt;
]]></description><link>https://melinyel.net/topic/759/ia-2-le-pnj-un-automate-à-états-finis</link><guid isPermaLink="true">https://melinyel.net/topic/759/ia-2-le-pnj-un-automate-à-états-finis</guid><dc:creator><![CDATA[daemondragon]]></dc:creator><pubDate>Sun, 25 May 2014 10:33:19 GMT</pubDate></item><item><title><![CDATA[[Cours #7] Les pointeurs sur fonction]]></title><description><![CDATA[&lt;p&gt;Bonjour à tous,&lt;br/&gt;
Ce cours va être très court (oh ce jeu de mot!). En effet, je vais juste vous montrer comment faire un pointeur sur fonction.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I- Pointeur sur fonction? Kesako?&lt;/strong&gt;&lt;br/&gt;
Un pointeur sur fonction, c'est simplement une manière d'appeler une fonction, en passant par un pointeur.&lt;br/&gt;
Par exemple:&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
void (*function_pointer)(char);
function_pointer = &amp;my_putchar; // Vous pouvez retrouver la fonction my_putchar sur
le cours #1.
function_pointer('A');&lt;/pre&gt;
&lt;p&gt;
Le programme ci-dessus crée le pointeur sur fonction function_pointer, et lui définit l'adresse de my_putchar (qui permet d'afficher un caractère).&lt;br/&gt;
Il affiche 'A'.&lt;/p&gt;
&lt;p&gt;
II- Utilité?&lt;br/&gt;
Un pointeur sur fonction permet d'appeler une fonction via un pointeur. Il est très souvent utilisé pour les tableaux de pointeurs sur fonction. Ce qui permet, par exemple, d'appeler une fonction en fonction d'une condition, sans avoir 40 000 if/else.&lt;br/&gt;
Exemple de tableau de pointeurs sur fonction:&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
#include &lt;unistd.h&gt;
void my_putchar(char c)
{
write(1, &amp;c, 1);
}
void my_putstr(char *str)
{
while(str)
my_putchar((str++));
}
void aff_help()
{
my_putstr("Commandes:\ncoucou: affiche salut\ndada: affiche dadi\npopo affiche caca");
}
void aff_coucou()
{
my_putstr("salut\n");
}
void aff_dada()
{
my_putstr("dadi\n");
}
void aff_popo()
{
my_putstr("caca\n");
}
void do_cmd(char *cmd)
{
void (*fptr[])() = {&amp;aff_popo, &amp;aff_dada, &amp;aff_coucou};
char cmds[] = {"popo", "dada", "coucou"};
int i = -1;
while (++i &lt; 3)
{
if (!strcmp(cmds[i], cmd))
{
fptr(i)();
return ;
}
}
my_putstr("Commande introuvable.");
}
int main(int ac, char **av)
{
int readed;
char buffer[4096];
my_putstr("Entrez votre commande. Utilisez CTRL+D pour quitter\n");
while ((readed = read(0, buffer, 4095)) != -1)
{
buffer[readed] = '\0';
do_cmd(buffer);
}
return (0);
}
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;III- Déclaration et appel.&lt;/strong&gt;&lt;br/&gt;
Enfin, voyons comment déclarer un pointeur sur fonction, puis comment lui définir une fonction.&lt;br/&gt;
Déclarons notre pointeur. Forme de déclaration:&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
typage_renvoyé_par_la_fonction (*nom_pointeur)(arguments_pris_par_la_fonction);&lt;/pre&gt;
&lt;p&gt;
Par exemple, pour printf:&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
int (*myptr)(char *, ...); // oui, les ... sont un type. Il existe une fonction qui permet de récupérer une infinité d'args dans une fonction, mais je vousl’expliquerais dans un prochain cours!
// Assignation
myptr = &amp;printf;
// Utilisation
myptr("Salut tout le %s", "monde!\n");
&lt;/pre&gt;
&lt;p&gt;Voilà.&lt;br/&gt;
Vous l'aurez compris, les pointeurs sur fonctions sont très, TRES utilisés dans le monde du développement. Il est donc important de savoir les utiliser, pour apprendre à gagner des lignes.&lt;br/&gt;
Je vous dis a bientôt pour un prochain cours!&lt;br/&gt;
Cours écrit par AlexMog. Contact: alexmog [at] live [point] fr&lt;/p&gt;
]]></description><link>https://melinyel.net/topic/746/cours-7-les-pointeurs-sur-fonction</link><guid isPermaLink="true">https://melinyel.net/topic/746/cours-7-les-pointeurs-sur-fonction</guid><dc:creator><![CDATA[AlexMog]]></dc:creator><pubDate>Thu, 22 May 2014 14:47:21 GMT</pubDate></item><item><title><![CDATA[[Cours #6] Librairies (statiques) et fichiers Headers (.h)]]></title><description><![CDATA[&lt;p&gt;Bonjour à vous,&lt;br/&gt;
Dans ce cours, nous allons voir à quoi corresponds un fichier header, ainsi que comment créer une  librairie, et enfin, les structures!&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I- Qu'est-ce qu'une lib?&lt;/strong&gt;&lt;br/&gt;
Une lib, aussi nommée librairie (dynamique ou statique) est un fichier binaire contenant une liste de fonctions prédéfinies.&lt;br/&gt;
Je vais vous donner un exemple de son utilisation, et pourquoi il est bon de créer une lib!&lt;br/&gt;
Imaginons que vous avez créé plusieurs fonctions, il vous serait pratique de les ré-utiliser dans un autre programme! Malheureusement, la compilation est très longue si il y a beaucoup de fonctions.&lt;br/&gt;
La lib est donc là pour deux choses: partager des fonctions sur diverses programmes, et éviter une  compilation inutile sur des fonctions déjà près compilées.&lt;br/&gt;
Pour mieux vous faire comprendre tout cela, créons trois fichiers distincts:&lt;br/&gt;
main.c:&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
int main(void)
{
my_putstr("coucou\n");
return (0);
}
my_putchar.c:
void my_putchar(char c)
{
write(1, &amp;c, 1);
}
my_putstr.c:
void my_putstr(char *str)
{
while(str)
my_putchar((str++));
}&lt;/pre&gt;
&lt;p&gt;
Tentons à présent de compiler main.c:&lt;/p&gt;
&lt;blockquote class="ipsQuote" data-ipsquote=""&gt;&lt;div&gt;cc main.c
&lt;p&gt; &lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;
Hum.. notre linker nous gueule dessus en nous disant qu'il est impossible de trouver la fonction "my_putstr". C'est normal! my_putstr n'a pas été compilée avec notre main. Elle ne fais donc pas partie du programme.&lt;br/&gt;
Maintenant, tentons de compiler tous nos fichiers en même temps:&lt;/p&gt;
&lt;blockquote class="ipsQuote" data-ipsquote=""&gt;&lt;div&gt;cc main.c my_putchar.c my_putstr.c
&lt;p&gt; &lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Ah! Là ça marche! On a notre a.out qui est bien créé, et qui affiche bien "coucou".C'est un bon point, mais nous ne sommes pas avancés, j'ai envie de réutiliser my_putchar et my_putstr dans mes autres programmes, je vais tenter des les compiler pour voir si je peux les ré-utiliser sans avoir à les recompiler!&lt;/p&gt;
&lt;blockquote class="ipsQuote" data-ipsquote=""&gt;&lt;div&gt;cc my_putchar.c&lt;br/&gt;
cc my_putstr.c
&lt;p&gt; &lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;
Hum... Mon linker me dit cette fois-ci qu'aucun main n'a été trouvé... Je ne peux donc pas compiler mes fonctions séparément?&lt;br/&gt;
Eh bien si! Il a une solution, les transformer en fichiers binaires non exécutables (aussi appelées lib), leur extentions est généralement .a pour un rassemblement de mini-libs, et .o pour les fichiers de fonctions de cette lib (pour résumer, les .o sont les briques, et .a est une partie du mur ! On utilise les briques pour construire cette partie).&lt;br/&gt;
Créons donc nos .o!&lt;/p&gt;
&lt;blockquote class="ipsQuote" data-ipsquote=""&gt;&lt;div&gt;cc -c my_putchar.c&lt;br/&gt;
cc -c my_putstr.c
&lt;p&gt; &lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;
(man cc pour plus d'informations)&lt;br/&gt;
Voila! Je découvre my_putchar.o et my_putstr.o, tentez la commande "file my_putchar.o" pour voir qu'il s'agit bien d'un fichier binaire non exécutable.&lt;br/&gt;
C'est cool, mais pour l'instant mes fichiers sont séparés, j'aimerais bien tous les avoir dans un même  "packetage" pour éviter de me trimballer 40 fichiers par programmes.&lt;br/&gt;
Eh bien, nous allons utiliser notre linker (et non plus notre compilateur) pour tous les liés dans un même  package, un véritable fichier lib: un fichier .a.&lt;br/&gt;
Nous l'appellerons libmy.a:&lt;br/&gt;
Pour créer notre lib, voici la commande linker (je vous laisse le soin de lire le man de celle-ci):&lt;/p&gt;
&lt;blockquote class="ipsQuote" data-ipsquote=""&gt;&lt;div&gt;ar rc libmy.a my_putstr.o my_putchar.o
&lt;p&gt; &lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;On peux en faite considérer les .o comme des briques, et les .a comme le ciment qui va maintenir ces briques sur le programme.&lt;br/&gt;
Nous avons enfin notre lib! Tentons à présent de compiler main.c avec notre lib (je vous laisse, encore une fois, le soin de lire le man de gcc):&lt;/p&gt;
&lt;blockquote class="ipsQuote" data-ipsquote=""&gt;&lt;div&gt;cc main.c -L./ -lmy
&lt;p&gt; &lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Hop! Nous avons notre a.out fonctionnel!&lt;br/&gt;
Vous savez à présent créer vos propres librairies!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;II- Les fichiers Header&lt;/strong&gt;&lt;br/&gt;
Nous avons vu précédemment comment créer notre propre librairie, mais néanmoins, nous avons, de temps à autres, des warnings qui apparaissent lors de notre compilation, voir même des erreurs car notre compilateur ne connaît pas les fonctions qu'il utilise.Les fichiers Headers ont plusieurs particularités. Il s'agit avant tout de fichiers d'"entête" chargés de fournir des informations au compilateur pour qu'il sache où chercher les fonctions, et leur utilité dans le programme.&lt;br/&gt;
Il permet aussi de rendre le code plus propre: nous pourrions faire nos headers directement dans notre .c, mais c'est plus moche, et la compilation d'un .h diffère de celle d'un .c (tentez cc *.h vous verrez bien).&lt;br/&gt;
Un header, c'est donc un fichier de préparation à la compilation. Il contiendra ainsi les prototypes des fonctions utilisées dans notre programme.&lt;br/&gt;
Vous pouvez trouver des exemples de headers dans les librairies que nous avions déjà utilisé!&lt;br/&gt;
Souvenez-vous:&lt;br/&gt;
Nous avions utilisé:&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
#include &lt;unistd.h&gt;
&lt;/pre&gt;
&lt;p&gt;qui corresponds à inclure le fichier .h de la libraire unistd. les &lt;&gt; signifient que le header se trouve dans le dossier include de notre compilateur.&lt;br/&gt;
Pour inclure un fichier local, il suffit de faire&lt;/p&gt;
&lt;blockquote class="ipsQuote" data-ipsquote=""&gt;&lt;div&gt;#include "fichierlocal"
&lt;p&gt; &lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;
tout simplement!&lt;br/&gt;
Donc revenons sur notre histoire de warnings, nous allons créer un .h pour la lib précédente que nous avons créé:&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
#ifndef MY_H
#define MY_H
void my_putchar(char);
void my_putstr(char );
#endif / MY_H */&lt;/pre&gt;
&lt;p&gt;
Je vais vous expliquer le fichier lignes par lignes.&lt;br/&gt;
Mais avant cela, je vais vous expliquer ce qu'est un define.&lt;br/&gt;
Un define est une sorte de variable statique et constante. Elle permet de remplacer la valeur du define par la valeur associée à celui-ci.&lt;br/&gt;
Voici un exemple simple:&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
#define VERSION "1.0.0"&lt;/pre&gt;
&lt;p&gt;
J'ai définit VERSION comme ayant comme value 1.0.0&lt;br/&gt;
Je peux le ré-utiliser dans mon code, si j'inclus le fichier .h qui contient ce define, comme ceci:&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
int main(void)
{
my_putstr(VERSION);
return (0);
}&lt;/pre&gt;
&lt;p&gt;
ATTENTION: il ne s'agit pas d'une variable. Un define est remplacé par le compilateur par la valeurqui lui est destinée!&lt;br/&gt;
J'espère que vous m'aurez compris...&lt;br/&gt;
Passons donc à la définition de notre fichier .h:&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
#ifndef MY_H&lt;/pre&gt;
&lt;p&gt;
Notre première ligne de code permet d'éviter ce qu'on appelle une "double inclusion", en effet, si on inclue notre fichier .h dans plusieurs autres fichiers du même programme, nous pouvons créer de multiples inclusions, ce qui ne sert à rien, et ralentit la compilation.&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
#define MY_H&lt;/pre&gt;
&lt;p&gt;
Si notre fichier n'a jamais été inclus, nous définissons qu'il l'a à présent été void my_putchar(char);&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
void my_putstr(char );&lt;/pre&gt;
&lt;p&gt;
On y ajoute ensuite les prototypes des fonctions utilisées...&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
#endif / MY_H */&lt;/pre&gt;
&lt;p&gt;
Enfin, on ferme notre "#ifndef" (if not defined).&lt;br/&gt;
Nous y sommes, revoyons notre main à présent:&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
#include "my.h"
int main(void)
{
my_putstr("coucou\n");
return (0);
}&lt;/pre&gt;
&lt;p&gt;
Compilons le:&lt;/p&gt;
&lt;blockquote class="ipsQuote" data-ipsquote=""&gt;&lt;div&gt;cc main.c -lmy -L./
&lt;p&gt; &lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;
Et voilà! Plus aucun warnings ou erreurs! Nous pouvons passer à la suite!&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;III- Les Structures.&lt;/strong&gt;&lt;br/&gt;
Une structure est un ensemble de données. Il permet de stocker plusieurs données sous un même typpage. (nous verrons en même temps la déclaration de typpages, grâce à typedef).&lt;br/&gt;
Construction d'une structure:&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
struct s_nom_de_ma_struct
{
int valeur_numerique;
char valeur_caractere;
typpage valeur_n'importe_quel_typpage;
};&lt;/pre&gt;
&lt;p&gt;
C'est aussi simple que cela.&lt;br/&gt;
A savoir : Une structure doit être déclarée dans un .h!Nous allons créer une structure, qui contiendra une  chaine de caractères "pseudo" et une autre&lt;br/&gt;
chaine de caractère "texte":&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
struct s_mastruct
{
char *pseudo;
char *texte;
};&lt;/pre&gt;
&lt;p&gt;
Nous allons afficher les données de notre structure:&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
void set_structure(struct s_mastruct mastruct)
{
/ (*mastruct).pseudo = "AlexMog" est la même chose que mastruct-&gt;pseudo = "AlexMog" */
mastruct-&gt;pseudo = "AlexMog";
mastruct-&gt;texte = "Coucou! :)";
}
int main(void)
{
struct s_mastruct mastruct;
set_structure(&amp;mastruct);
my_putstr("Pseudo: ");
my_putstr(mastruct.pseudo);
my_putchar('\n');
my_putstr("Texte: ");
my_putstr(mastruct.texte);
my_putchar('\n');
return (0);
}&lt;/pre&gt;
&lt;p&gt;
Ce code nous affichera:&lt;/p&gt;
&lt;blockquote class="ipsQuote" data-ipsquote=""&gt;&lt;div&gt;Pseudo: AlexMog&lt;br/&gt;
Texte: Coucou!  &lt;p&gt; &lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;A SAVOIR: lorsque vous utilisez un pointeur sur structure (comme dans la fonction set_structure) les "." sont remplacés par "-&gt;".&lt;br/&gt;
Voilà, vous savez à présent vous servir des structures. Mais vous avez remarqué que taper "struct s_mastruct mastruct" est tout de même long pour la ré-utilisation de cette structure... Nous allons donc créer notre propre typage!&lt;br/&gt;
Rendez-vous dans le .h:&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
struct s_mastruct
{
char *pseudo;
char *texte;
};
&lt;/pre&gt;
&lt;p&gt;et créons notre nouveau typage:&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
typedef struct s_mastruct
{
char *pseudo;char *texte;
} t_mastruct;&lt;/pre&gt;
&lt;p&gt;
Nous pouvons à présent déclarer nos structures comme ceci:&lt;/p&gt;
&lt;blockquote class="ipsQuote" data-ipsquote=""&gt;&lt;div&gt;t_mastruct mastruct;
&lt;p&gt; &lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;
Cool n'est-ce pas ?&lt;br/&gt;
Vous remarquerez, pour ceux qui font de la programmation orientée objet, qu'une structure ressemble énormément à un objet, il s'agit en faite de la maman de l'objet connu actuellement! Nous verrons cela plus en détails, lorsque j'aborderais les notions sur la programmation en C Modulaire dans un prochain cours (dans longtemps donc, puisque nous devons voir les pointeurs sur fonctions avant (un objet = une structure contenant un ensemble de données et de pointeurs sur fonctions allouée dans la mémoire)).&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Voilà!&lt;br/&gt;
A très bientôt pour un prochain cours!&lt;br/&gt;
Cours écrit par AlexMog. Contact: alexmog [at] live [point] fr&lt;/p&gt;
]]></description><link>https://melinyel.net/topic/745/cours-6-librairies-statiques-et-fichiers-headers-h</link><guid isPermaLink="true">https://melinyel.net/topic/745/cours-6-librairies-statiques-et-fichiers-headers-h</guid><dc:creator><![CDATA[AlexMog]]></dc:creator><pubDate>Thu, 22 May 2014 14:37:44 GMT</pubDate></item><item><title><![CDATA[[Cours #5] ArgC, ArgV et allocations Dynamiques]]></title><description><![CDATA[&lt;p&gt;Bonjour à tous,&lt;br/&gt;
Bienvenue dans ce 4ième cours sur la programmation en C.&lt;br/&gt;
Aujourd'hui, nous allons voir un point intéréssent de notre programme, et un point clé en  les&lt;br/&gt;
Arguments de lancement, et les allocations dynamiques.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I- Qu'est-ce qu'un argument de lancement?&lt;/strong&gt;&lt;br/&gt;
Un argument de lancement est une string ajoutée au lancement du programme permettant de faire passer ladite string au programme (string = chaine de caractères).&lt;br/&gt;
Ainsi, si je lance le programme avec cette ligne de commande:&lt;/p&gt;
&lt;blockquote class="ipsQuote" data-ipsquote=""&gt;&lt;div&gt;mon_programme mon_argument
&lt;p&gt; &lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;mon programme recevra comme argument 1 : "mon_argument".&lt;br/&gt;
(En faite, d'une façon générale, les arguments sont gérés par les shells qui lancent le programme. C'est une convention de programmation).&lt;br/&gt;
Quelques exemples d'utilisations d'arguments:&lt;br/&gt;
Les commandes unix utilisent très souvent les arguments:&lt;/p&gt;
&lt;blockquote class="ipsQuote" data-ipsquote=""&gt;&lt;div&gt;ls --help&lt;br/&gt;
cd --&lt;br/&gt;
cd /home&lt;br/&gt;
cd ~&lt;br/&gt;
mkdir test&lt;br/&gt;
...
&lt;p&gt; &lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;et peuvent donc permettre de faire passer une valeur, ou même un chemin à son programme (bah oui, c'est des Strings (tableaux de caractères). Bon, passons à la pratique:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;II- Récupérer des arguments de lancement&lt;/strong&gt;&lt;br/&gt;
Nous avions vu la structure basique d'un main en C:&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
int main(void)
{
}&lt;/pre&gt;
&lt;p&gt;
Eh bien, je ne vous ai pas dit la vérité sur cette fonction!&lt;br/&gt;
En effet, main peut prendre un void pour argument (et donc ne prendre aucun arguments), ou bien prendre un int, et un char **.&lt;br/&gt;
Le véritable prototypage de la fonction main est donc:&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
int main(int argc, char *argv)
{
}&lt;/pre&gt;
&lt;p&gt;
En voyant ça, vous allez me dire "dis donc, j'ai mal à la tête, y'a un ** dans ton code!" Eh bien ne&lt;br/&gt;
vous inquiétez pas, il s'agit d'un tableau de chaines de caractères.Prenons pour exemple ce programme lancé comme ceci:&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
coucou arg1 arg2 arg3 je suis fou
&lt;/pre&gt;
&lt;p&gt;Eh bien, nous pouvons récupérer les arguments de ce programme de la façon suivante:&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
/
** Je re-crée les fonctions d'affichage. Voir cours #1 et #2
*/
void my_putchar(char c)
{
write(1, &amp;c, 1);
}
void my_putstr(char *str)
{
while(str)
my_putchar((str++));
}
int main(int argc, char **argv)
{
my_putstr(argv[0]); // Affichera
my_putstr(argv[1]); // Affichera
my_putstr(argv[2]); // Affichera
my_putstr(argv[3]); // Affichera
my_putstr(argv[4]); // Affichera
my_putstr(argv[5]); // Affichera
my_putstr(argv[6]); // Affichera
return (0);
}
&lt;/pre&gt;
&lt;blockquote class="ipsQuote" data-ipsquote=""&gt;&lt;div&gt;"cocuou"&lt;br/&gt;
"arg1"&lt;br/&gt;
"arg2"&lt;br/&gt;
"arg3"&lt;br/&gt;
"je"&lt;br/&gt;
"suis"&lt;br/&gt;
"foud"
&lt;p&gt; &lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;Nous butons à présent sur un problème, ré-utilisons le programme précédent, mais supprimons tous,&lt;br/&gt;
ou un des arguments:&lt;/p&gt;
&lt;blockquote class="ipsQuote" data-ipsquote=""&gt;&lt;div&gt;Segmentation Fault
&lt;p&gt; &lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;
Eh oui, comme vous le voyez, nous essayons d'accéder à la valeur d'un tableau qui n'existe pas, ce qui provoque une erreur d'accès en mémoire.&lt;br/&gt;
Pour remédier à cela, les développeurs nous ont rajoutés "argc".&lt;br/&gt;
Pour mieux vous faire comprendre, je vais vous définir exactement ce que signifie argc et argv:&lt;br/&gt;
ArgC est un couplage entre les mots: Argument et Count, il s'agit donc du nombre d'arguments qui ont été passés en paramètres.&lt;br/&gt;
ArgV est un couplage entre les mots: Argument et Value, il s'agit donc des valeurs de ces dits arguments.&lt;/p&gt;
&lt;p&gt;
Maintenant que vous avez le nombre d'arguments, vous pouvez vérifier que le nombre d'arguments est correcte avant de l'afficher:&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
int main(int argc, char **argv)
{
if (argc &gt; 1)
my_putstr(argv[1]);
return (0);
}&lt;/pre&gt;
&lt;p&gt;argv[0] sera toujours présent, puisqu'il s'agit du tout premier argument, qui est vital pour lancer le programme (il s'agit plus exactement de la commande utilisée pour lancer le programme).&lt;br/&gt;
Passons à présent à la partie complexe de ce cours: les allocations dynamiques.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;III- Les allocations dynamiques&lt;/strong&gt;&lt;br/&gt;
L'allocation dynamique, c'est l'art de savoir utiliser sa RAM et les répercussions de l'alloc sur celle-ci.&lt;br/&gt;
Nous avions vu précédemment que pour pouvoir avoir une chaine de caractère avec une certaine taille, nous devions définir un tableau de caractères, avec une taille FIXE.&lt;br/&gt;
Comme ceci:&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
char mon_tableau[talle_de_mon_tableau];
&lt;/pre&gt;
&lt;p&gt;Là est le problème, imaginons que nous devions modifier notre chaine, en lui imposant une taille plus grande: SegFault.&lt;br/&gt;
Eh bien, la solution, c'est d'utiliser l'allocation dynamique: Au lieu de stocker notre chaine dans la stack, stockons la dans la RAM! (ce qui nous permet d'avoir plus d'espace, d'ailleurs! (généralement, la stack est limitée à quelques Ko, alors que la RAM non))&lt;br/&gt;
Vous comprenez donc qu'il est dangereux d'utiliser malloc de façon idiote: dans une boucle infinie par exemple... Puisque vous allez remplir votre RAM!&lt;/p&gt;
&lt;p&gt;
Prenons un exemple simple:&lt;br/&gt;
J'ai un programme qui connaît la taille d'une chaine de caractère, et je dois la stocker dans une variable:&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
int main(void)
{
int lenght = 300000; // Oui, notre chaine est très longue
}&lt;/pre&gt;
&lt;p&gt;
Si je tentais de déclarer un tableau statique de char de taille 300 000, il y aura énormément de chances pour que mon programme segfault dès le lancement.&lt;br/&gt;
C'est problématique, en effet.&lt;br/&gt;
Tentons donc d’allouer un emplacement dans la ram pour cette chaine:&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
int main(void)
{
char *ptr;
ptr = malloc(300000 * sizeof(char));
}&lt;/pre&gt;
&lt;p&gt;
Tiens, ça marche!&lt;br/&gt;
Lisons un peu mieux le man de malloc: en cas d'erreur, malloc retourne NULL.&lt;br/&gt;
Nous allons donc vérifier si il y a eu une erreur (pour éviter le segfault):&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
int main(void)
{
char ptr;
ptr = malloc(300000 * sizeof(char));
if (ptr == NULL)
{
my_putstr("Erreur malloc\n");
return ;
}
}&lt;/pre&gt;
&lt;p&gt;
Bon, nous avons donc alloué un emplacement de type char (donc tableau de caractères) dans notre ram, avec une taille de 300 000 cases! Cool!&lt;br/&gt;
Nous pouvons donc remplire "ptr" exactement comme un tableau (case par case, voir cours sur les chaines de caractères).&lt;br/&gt;
ATTENTION: ptr est un POINTEUR. Si vous modifiez son adresse, vous perdez l'ancienne adresse allouée! Donc ceci:&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
int main(void)
{
char *ptr;
ptr = malloc(300000 * sizeof(char));
if (ptr == NULL)
{
my_putstr("Erreur malloc\n");
return ;
}
ptr = "coucou";
}
&lt;/pre&gt;
&lt;p&gt;est interdit et stupide (ne rigolez pas, les profs de programmation font souvent l'erreur!).&lt;br/&gt;
Bon, c'est bien, nous avons alloué de la mémoire, mais bon, c 'est pas cool pour la RAM, on ne la vide jamais, il va falloir la vider!&lt;br/&gt;
Pour la vider, la fonction "free" est là pour nous aider!&lt;br/&gt;
Voilà mon programme une fois la fonction "free" utilisée:&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
int main(void)
{
char *ptr;
ptr = malloc(300000 * sizeof(char));
if (ptr == NULL)
{
my_putstr("Erreur malloc\n");
return ;
}
free(ptr);
}
&lt;/pre&gt;
&lt;p&gt;Tout marche! Cool!&lt;br/&gt;
ATTENTION: pour bien vous montrer que modifier un pointeur est une mauvaise idée, tentez de faire ceci:&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
int main(void)
{
char *ptr;
ptr = malloc(300000 * sizeof(char));
if (ptr == NULL)
{
my_putstr("Erreur malloc\n");
return ;
}
ptr = "coucou";
free(ptr);
}&lt;/pre&gt;
&lt;p&gt;
Hop, vous tomberez sur une erreur qui se nomme "glibC" et qui corresponds à une erreur de pointage, la fonction "free" vous hurle dessus comme quoi votre pointeur ne pointe pas sur une zone&lt;br/&gt;
allouée.&lt;br/&gt;
Pour vous montrer que mon code fonctionne, je vais afficher ma chaine de caractère, qui fera&lt;br/&gt;
l'alphabet avec 300 000 lettres!&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
int main(void)
{
char *ptr;
int i;
i = 0;
j = 0;
ptr = malloc(300000 * sizeof(char));
if (ptr == NULL)
{
my_putstr("Erreur malloc\n");
return ;
}
while(i &lt; 300000)
{
ptr[i] = j + 'a';
i = i + 1;
j = j + 1;
if (j + 'a' &gt;= 'z')
j = 0;
}
ptr[i] = '\0'; // NE PAS OUBLIER LA FIN DE LA CHAINE (voir cours sur les chaines de caractères)
my_putstr(ptr);
free(ptr);
}&lt;/pre&gt;
&lt;p&gt;
Et voilà, vous savez à présent utiliser les allocations dynamiques!&lt;br/&gt;
A bientôt pour le prochain cours!&lt;br/&gt;
Cours écrit par AlexMog. Contact: alexmog [at] live [point] fr&lt;/p&gt;
]]></description><link>https://melinyel.net/topic/744/cours-5-argc-argv-et-allocations-dynamiques</link><guid isPermaLink="true">https://melinyel.net/topic/744/cours-5-argc-argv-et-allocations-dynamiques</guid><dc:creator><![CDATA[AlexMog]]></dc:creator><pubDate>Thu, 22 May 2014 14:08:36 GMT</pubDate></item><item><title><![CDATA[IA #1 - le pathfinding (2/2)]]></title><description><![CDATA[&lt;p&gt;Et voila le deuxieme tutoriel où je vais vous expliquer tout le code&lt;br/&gt;
du pathfinding ( et oui enfin !   )&lt;br/&gt;&lt;br/&gt;
Tout d'abord n'hésitez pas a télécharger les sources en bas du post afin&lt;br/&gt;
de les lire en même temps, c'est plus pratique pour comprendre de&lt;br/&gt;
quoi je parle.&lt;br/&gt;&lt;br/&gt;
On va commencer par le prototype de la fonction :&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
path_direction* create_path(const int largueur, const int hauteur, int map[][hauteur],
const path_pos debut, const path_pos fin, int pivot)
&lt;/pre&gt;
&lt;p&gt;Cette fonction retourne un pointeur vers une structure, je vais vous expliquer a quoi&lt;br/&gt;
elle sert vers la fin. Il faut donc en paramètre la largueur et la hauteur de la map&lt;/p&gt;
&lt;p&gt;(attention, la map doit être de format map[largueur][hauteur] et non, map[hauteur][largueur]&lt;br/&gt;
la map qui contient des nombres afin de représenter votre terrain, et maintenant les trucs&lt;br/&gt;
intéressant : la structure path_pos ne contient que deux int, x et y, pour connaître la position&lt;br/&gt;
du début et celle de la fin.&lt;br/&gt;&lt;br/&gt;
Attention, le début de la map commence a (0, 0), il faut faire attention !&lt;br/&gt;
Et enfin le pivot, mais qu'est ce que c'est ?&lt;br/&gt;
C'est tout simplement tout les nombres qui sont supérieur ou égal a lui sont traversables,&lt;br/&gt;
tout ceux inférieur sont des murs par exemples. cela nécessite par contre de penser a&lt;br/&gt;
cela dès le début e la conception du jeu mais c'est pas très difficile. personnellement,&lt;br/&gt;
j'utilise souvent des énumération pour définir les différentes tiles (blocs) de la map.&lt;br/&gt;&lt;br/&gt;
ensuite :&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
if(debut.x == fin.x &amp;&amp; debut.y == fin.y)
{
return NULL;
}
&lt;/pre&gt;
&lt;p&gt;assez explicite je crois, on retourne NULL afin de savoir qu'il n'y a pas de chemin.&lt;br/&gt;&lt;br/&gt;
On doit créer ensuite une grille de coût , de la taille qui faut exactement, et on initialise&lt;br/&gt;
le tout a 0, c'est très important !&lt;br/&gt;
on met a jour a grille de coût, en mettant a 1 le début.&lt;/p&gt;
&lt;p&gt;Ainsi, on sait que tout les blocs avec un coût égal a zéro sont non explorés&lt;br/&gt;&lt;br/&gt;
Il faut ensuite créer une file, les positions actuelle et les suivantes, ce qui donne :&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
path_pos actuel;
path_pos suivant;
control control_list;
&lt;/pre&gt;
&lt;p&gt;la structure control et donc se qui va nous servir a contrôler la file, on va mettre les donnée&lt;br/&gt;
en file a partir de cette structure là.&lt;br/&gt;
Elle contient un pointeur vers la première donnée, pour la récupérer. (n'hésitez pas a regarder&lt;br/&gt;
le précédent tutoriel pour voir de quoi je veux parler) Et aussi un pointeur vers la dernière&lt;br/&gt;
données, afin de mettre les données dans la file plus rapidement. S'il n'y en avait pas, on&lt;br/&gt;
aurait du parcourir TOUTES les données de la file une par une afin de trouver la fin.&lt;br/&gt;
Vous imaginez sur une énorme file de 1000 données ?&lt;br/&gt;
Il faut initialiser la file avec la position de début et on commence les choses sérieuse.&lt;br/&gt;&lt;br/&gt;
Il faut ensuite créer une boucle qui s’arrête quand on a trouvé la fin ou que la file est vide.&lt;br/&gt;
dedans, on met a jour la position actuelle qui erre égale a la valeur du début de file.&lt;br/&gt;
si la position actuelle est égale a celle de fin on sort de la boucle, sinon on regarde sur le coté.&lt;br/&gt;
Cela donne en code:&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
while(control_list.premier != NULL &amp;&amp; fini)
{
actuel.x = control_list.premier-&gt;actuel.x;
actuel.y = control_list.premier-&gt;actuel.y;
        if(actuel.x == fin.x &amp;amp;&amp;amp; actuel.y == fin.y)
        {
            fini = 0;
        }

        if(actuel.x != 0)
        {
            if(map[actuel.x-1][actuel.y] &amp;gt;= pivot &amp;amp;&amp;amp; poid[actuel.x-1][actuel.y] == 0)
            {
                suivant.x = actuel.x-1;
                suivant.y = actuel.y;
                poid[suivant.x][suivant.y] = poid[actuel.x][actuel.y] + 1;

                add_to_file(&amp;amp;control_list, suivant);                    
            }
        }
        if(actuel.x != largueur -1)
        {
            if(map[actuel.x+1][actuel.y] &amp;gt;= pivot &amp;amp;&amp;amp; poid[actuel.x+1][actuel.y] == 0)
            {
                suivant.x = actuel.x+1;
                suivant.y = actuel.y;
                poid[suivant.x][suivant.y] = poid[actuel.x][actuel.y] + 1;

                add_to_file(&amp;amp;control_list, suivant);
            }
        }
        if(actuel.y != 0)
        {
            if(map[actuel.x][actuel.y-1] &amp;gt;= pivot &amp;amp;&amp;amp; poid[actuel.x][actuel.y-1] == 0)
            {                
                suivant.x = actuel.x;
                suivant.y = actuel.y-1;
                poid[suivant.x][suivant.y] = poid[actuel.x][actuel.y] + 1;
                
                add_to_file(&amp;amp;control_list, suivant);
            }
        }
        if(actuel.y != hauteur - 1)
        {
            if(map[actuel.x][actuel.y+1] &amp;gt;= pivot &amp;amp;&amp;amp; poid[actuel.x][actuel.y+1] == 0)
            {                
                suivant.x = actuel.x;
                suivant.y = actuel.y+1;
                poid[suivant.x][suivant.y] = poid[actuel.x][actuel.y] + 1;

                add_to_file(&amp;amp;control_list, suivant);
            }
        }
        remove_to_file(&amp;amp;control_list);
    }

&lt;/pre&gt;
&lt;p&gt;Il faut bien entendu éviter de partir sur les coté de la map, sinon on risque d'avoir des problèmes de mémoires.&lt;br/&gt;
Vous vous dites aussi sûrement : "mais c'est quoi add_to_file et remove to file" non ?&lt;br/&gt;
Ce sont les structure qui servent a mettre les données dans la file, ou a les enlever.&lt;br/&gt;
(regardez dans le code source fournit, elle y sont au début.)&lt;br/&gt;
A partir de là, la grille de coût est fini, on peut vider totalement la file, on&lt;br/&gt;
n'en a plus besoin. ( il faut éviter les fuites mémoires) :&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
while(control_list.premier != NULL)
{
remove_to_file(&amp;control_list);
}
&lt;/pre&gt;
&lt;p&gt;Et non ce n'est toujours pas fini :&lt;br/&gt;
Il faut regarder la variables fini, qui si elle est égale a zéro, signifie qu'on a trouvé la&lt;br/&gt;
fin ,sinon, il faut encore retourner NULL.&lt;br/&gt;
si le chemin est trouvé, on se place sur la position de fin et regarde a coté.&lt;br/&gt;
On va dans la direction on le coût est égal au coût - 1 de la case.&lt;br/&gt;
Il ne faut surtout PAS prendre la case qui a un coût inférieur a celle autour, car a ce&lt;br/&gt;
stade la, certaine case n'ont pas encore été explorer ( se n'était pas la peine, on&lt;br/&gt;
avait trouver le plus court chemin jusqu’à la fin) et sont donc encore égale a 0.&lt;br/&gt;
On risque alors de se trompé totalement de chemin.&lt;br/&gt;
On met ensuite dans la pile les directions contraire ou on va aller.&lt;br/&gt;
(on part de la fin je vous rappelle) et on retourne a la fin cette pile.&lt;br/&gt;
En code :&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
if (fini == 0)
{
fini = 1;
actuel.x = fin.x;
actuel.y = fin.y;
path_direction *control = NULL;
char direction;
        while((actuel.x != debut.x &amp;amp;&amp;amp; fini) || (actuel.y != debut.y &amp;amp;&amp;amp; fini))
        {
            //les directions sont inversé car le png va aller dans l'autre sens
            if(poid[actuel.x][actuel.y+1] == poid[actuel.x][actuel.y] - 1)
            {
                direction = NORD;
                actuel.y++;    
            }
            else if(poid[actuel.x][actuel.y-1] == poid[actuel.x][actuel.y] - 1)
            {
                direction = SUD;
                actuel.y--;
            }
            else if(poid[actuel.x+1][actuel.y] == poid[actuel.x][actuel.y] - 1)
            {
                direction = OUEST;
                actuel.x++;
            }
            else
            {
                direction = EST;
                actuel.x--;
            }
            empile(&amp;amp;control, direction);
        }
        return (control);
    }

&lt;/pre&gt;
&lt;p&gt;La structure path_direction comporte, une direction sous forme de point cardinaux (NORD, SUD...)&lt;br/&gt;
et un pointeur vers la donnée suivante (c'est une pile je vous rappelle).&lt;br/&gt;
la fonction empile sert a empiler la direction dans la pile (elle va tout au début).&lt;br/&gt;
A la fin, on retourne la pile, qu'il faut récupérer avec un pointeur sur une structure path_direction&lt;/p&gt;
&lt;p&gt;Le seul problème de ce path_finding actuel, c'est qu'il faut éviter que le chemin, se trouve sur les bord,&lt;/p&gt;
&lt;p&gt;sinon on peut passer de l'autre coté de la map dans certain cas, ce qu'il faut a tout prix empêcher.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Dans le cas de situation différentes a celle d'un labyrinthe, (quand les chemins ont une grande&lt;/p&gt;
&lt;p&gt;chance d'être droit, vous pouvez dirigez le path_finding en lui faisant allez dans la direction vers la&lt;/p&gt;
&lt;p&gt;fin et en transformant la file de départ en pile. Il faut alors pouvoir réécrire un coût d'une bloc si la&lt;/p&gt;
&lt;p&gt;deuxième fois, le coût est plus faible.&lt;/p&gt;
&lt;p&gt;Bref, il est facilement améliorable et il ne tiens qu'à vous de le récréer totalement.  &lt;/p&gt;
&lt;p&gt;Et voila le tour est joué, vous avez maintenant un path_finding qui marche&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/daemondragon/pathfinding.git" rel="external nofollow"&gt;https://github.com/daemondragon/pathfinding.git&lt;/a&gt;&lt;/p&gt;
]]></description><link>https://melinyel.net/topic/743/ia-1-le-pathfinding-22</link><guid isPermaLink="true">https://melinyel.net/topic/743/ia-1-le-pathfinding-22</guid><dc:creator><![CDATA[daemondragon]]></dc:creator><pubDate>Thu, 22 May 2014 13:24:02 GMT</pubDate></item><item><title><![CDATA[IA #1 - le pathfinding (1/2)]]></title><description><![CDATA[&lt;p&gt;Bonjour a tous !&lt;br/&gt;&lt;br/&gt;
Cette suite de tutoriel va vous expliquez comment faire une IA basique pour des pnj&lt;br/&gt;
que vous pourrez adapter pour des jeux simples(non ce n'est pas une super grosse IA&lt;br/&gt;
de la mort qui tue qui va faire vos problèmes de math toute seule).&lt;br/&gt;&lt;br/&gt;
Dans la première partie du tutoriel, nous allons voir une partie fondamentale&lt;br/&gt;
des IA dans les jeux vidéos : le pathfinding.&lt;br/&gt;
Le code du pathfinding était trop long pour être expliqué dans un seul tutoriel,&lt;br/&gt;
le premier traitera de la théorie et le deuxième de la pratique.&lt;br/&gt;&lt;br/&gt;
Le pathfinding, qu'est ce que c'est ?&lt;br/&gt;&lt;br/&gt;
Le pathfinding c'est le fait de dire a une personne :&lt;br/&gt;
tu vas du point A au point B en évitant les obstacles.&lt;br/&gt;
(c'est mieux que de se prendre les murs non ?   )&lt;br/&gt;&lt;br/&gt;
Pour le pathfinding, nous allons mettre en place un algorithme A*, qui est&lt;br/&gt;
très célèbre et qui peut être utilisé un peu partout, surtout dans le jeu&lt;br/&gt;
utilisant un système de grille(starcraft, zelda etc...)&lt;br/&gt;&lt;br/&gt;
A* tiens son nom de la recherche "en étoile" qu'il fait :&lt;br/&gt;
pour chaque case, il va regarder celles d'autour qui n'ont pas été déjà exploré et va dire :&lt;br/&gt;
celle la elle est plus loin de la case de départ que la précédente.&lt;br/&gt;&lt;br/&gt;
petite image :&lt;/p&gt;
&lt;p&gt;&lt;img alt="ExplicationAStar.png" src="&lt;base_url&gt;/applications/sslimageproxy/interface/image.php?url=http://www.nicolas-texier.net/fr/system/files/ExplicationAStar.png"/&gt;&lt;br/&gt;&lt;br/&gt;
Le 0 correspond au début.&lt;br/&gt;
Plus on s'éloigne du 0, plus le coût (ou le poids, c'est la même chose) augmente.&lt;br/&gt;
Le but, c'est de prendre le chemin, qui possède le plus faible coût.&lt;br/&gt;&lt;br/&gt;
Par exemple, si vous voulez partir du point (0, 3) -&gt; le 4eme point&lt;br/&gt;
tout en haut a gauche, vous n'allez pas partir carrément a gauche, faire X fois&lt;br/&gt;
le tour du gros truc noir, non ?&lt;br/&gt;
Vous allez simplement prendre le chemin le plus court.&lt;br/&gt;&lt;br/&gt;
Pour réaliser donc ce merveilleux pathfinding, vous allez donc partir du début&lt;br/&gt;
(le point (7, 6)) et regarder autour, si ce bloc n'est pas un mur. Vous augmenter&lt;br/&gt;
alors le coût du déplacement pour cette case, puis on refait cela jusqu’à ce qu'on&lt;br/&gt;
trouve la fin voulu ou jusqu’à ce qu'il n'y ai plus de possibilité&lt;br/&gt;
de passer car tous les blocs ont été explorés, il n'y a donc pas de possibilité&lt;br/&gt;
d'aller du point A au point B.&lt;br/&gt;
Puis on part de la fin et on passe par les blocs qui ont le plus faible coût.&lt;br/&gt;&lt;br/&gt;
Pour réaliser cela, on commence par créer une file (oui je parle enfin de code).&lt;br/&gt;
Une file est une structure de données qui permet de mettre des variables l'une après l'autre.&lt;br/&gt;
La première donnée qui rentre dans la file est la première à sortir.&lt;br/&gt;&lt;br/&gt;
Pour ceux qui ne savent pas ce que c'est :&lt;br/&gt;&lt;iframe data-embed-src="&lt;base_url&gt;/topic/783-cours-8-listes-chain%C3%A9es/?do=embed" data-embedcontent="" frameborder="0" src="//melinyel.net/applications/core/interface/js/spacer.png"&gt;&lt;/iframe&gt;&lt;br/&gt;&lt;br/&gt;
Donc ont la créer, cette file et on met, si ce n'est pas des murs, et s'il n'ont pas&lt;br/&gt;
été déjà explorés,la position des blocs d’à coté, tout a la fin.&lt;br/&gt;
A chaque tour de boucle, ont prend la première position et on refait la même chose.&lt;br/&gt;
Pour les minecraftien, c'est comme l'eau qui coule déjà sur la case la plus proche, puis sur celles&lt;br/&gt;
plus éloignées.&lt;br/&gt;&lt;br/&gt;
Quand on a trouvé la fin, la où le pnj par exemple veut aller, on arrête, ou alors quand il n'y a plus&lt;br/&gt;
de blocs a explorer, alors le pnj est triste car il ne peut pas y aller.&lt;br/&gt;&lt;br/&gt;
Si on a trouvé la fin, on met alors dans une pile, (les dernières données qui arrivent dedans&lt;br/&gt;
seront les premières à sortir), car le chemin doit être pris dans le sens contraire où l'on va.&lt;br/&gt;
On cherche alors, a partir de la fin, la case autour d'elle qui a le plus faible coût,&lt;br/&gt;
puis on enregistre sa position et on mets la direction contraire (n'oublier pas que le&lt;br/&gt;
pnj va parcourir le chemin dans l'autre sens) dans la pile et on refait ça&lt;br/&gt;
jusqu’à ce qu'on trouve le début.&lt;br/&gt;&lt;br/&gt;
Et voila vous pouvez maintenant, grâce à ces explication créer vous même votre pathfinding, ou alors&lt;br/&gt;
attendre le prochain tutoriel qui ne devrait pas tarder a suivre.&lt;br/&gt;
En utilisant uniquement le pathfinding et intelligemment vous pouvez déjà créer un planning pour chaque pnj,&lt;br/&gt;
ce qui va permettre de rendre une ville plus vivante (je pense surtout au village pnj de zelda qui sont&lt;br/&gt;
toujours au même endroit, c'est un peu triste non ?).&lt;/p&gt;
]]></description><link>https://melinyel.net/topic/741/ia-1-le-pathfinding-12</link><guid isPermaLink="true">https://melinyel.net/topic/741/ia-1-le-pathfinding-12</guid><dc:creator><![CDATA[daemondragon]]></dc:creator><pubDate>Wed, 21 May 2014 17:34:50 GMT</pubDate></item><item><title><![CDATA["else if" dans une boucle]]></title><description><![CDATA[&lt;p&gt;&lt;/p&gt;&lt;pre class="ipsCode prettyprint"&gt;
if (variable &gt;= 0)
{
}
for (index = 0 ; index &lt; 150 ; index++)
{
else if (untableau[index] == 0)
{
}
}
else
{
}
&lt;/pre&gt;
&lt;p&gt;bonjour à tous,&lt;/p&gt;
&lt;p&gt;voici un exemple pour illlustrer mon cas.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;dans l'exemple ci-dessus, le compilateur n'est pas content.&lt;/p&gt;
&lt;p&gt;mais comment éviter une cascade de "else if" ?&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;
des avis ?  &lt;/p&gt;
]]></description><link>https://melinyel.net/topic/618/else-if-dans-une-boucle</link><guid isPermaLink="true">https://melinyel.net/topic/618/else-if-dans-une-boucle</guid><dc:creator><![CDATA[cegdd]]></dc:creator><pubDate>Tue, 29 Apr 2014 19:09:16 GMT</pubDate></item><item><title><![CDATA[[TUTO] SDL 2.0]]></title><description><![CDATA[&lt;p&gt;&lt;span style="font-size:18px;"&gt;Bonjour à tous,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Ce tuto a pour but de vous apprendre les bases de la bibliotheque SDL,&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;et plus précisément la &lt;strong&gt;2.0&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Les exemples de codes seront rédigés en C car c'est le language dans lequel est écris la SDL,&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;bien que la SDL suporte le C++ et dispose de bindings pour le C#, &lt;span style="font-size:14px;"&gt;le Pascal et le Python.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;u&gt;j'imagine donc que vous maitrisez votre langage pour la suite.&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="color:#0000cd;"&gt;&lt;u&gt;&lt;span style="font-size:24px;"&gt;Code minimal&lt;/span&gt;&lt;/u&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Pour tester l'installation et expliquer les premières fonctions voici un code de base.&lt;/p&gt;
&lt;pre class="ipsCode prettyprint"&gt;
int main (int argc, char *argv[])
{
SDL_Init (SDL_INIT_VIDEO);
SDL_Window *screen;
SDL_Renderer *renderer;

screen = SDL_CreateWindow("tuto", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_RESIZABLE);
renderer = SDL_CreateRenderer(screen, -1, SDL_RENDERER_ACCELERATED);

SDL_RenderPresent(renderer);
SDL_Delay(2000);

SDL_Quit();
return 0;

}
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="color:#ff0000;"&gt;SDL_Init (SDL_INIT_VIDEO);&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Fonction initialisant la sdl.&lt;/p&gt;
&lt;blockquote class="ipsQuote" data-ipsquote=""&gt;&lt;div&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;int&lt;/span&gt; &lt;span&gt;SDL_Init&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;Uint32&lt;/span&gt; &lt;span&gt;flags&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;u&gt;retour :&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;retourne une valeur négative en cas d'erreur.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;u&gt;&lt;strong&gt;paramètres :&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SDL_INIT_TIMER&lt;/strong&gt;                           sous-système temps&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SDL_INIT_AUDIO&lt;/strong&gt;                          sous-système audio&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SDL_INIT_VIDEO&lt;/strong&gt;                          sous-système video&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SDL_INIT_JOYSTICK&lt;/strong&gt;                    sous-système pour joystick&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SDL_INIT_HAPTIC&lt;/strong&gt;                        sous-système pour le tactile&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SDL_INIT_GAMECONTROLLER&lt;/strong&gt;    sous-système mannette de jeu&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SDL_INIT_EVENTS&lt;/strong&gt;                       sous-système pour les évènement&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SDL_INIT_EVERYTHING&lt;/strong&gt;               tout les sous-système au dessus&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SDL_INIT_NOPARACHUTE&lt;/strong&gt;           ne prend pas en compte les signaux comme SIGSEGV SIGPIPE etc &lt;strong&gt;&lt;span style="color:#000000;"&gt;DANGEREUX &lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="color:#ff0000;"&gt;SDL_CreateWindow("tuto", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_RESIZABLE);&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;fonction créant la fenêtre de notre programme.&lt;/p&gt;
&lt;blockquote class="ipsQuote" data-ipsquote=""&gt;&lt;div&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;SDL_Window&lt;/span&gt;&lt;span&gt;&lt;/span&gt; &lt;span&gt;SDL_CreateWindow&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt; &lt;span&gt;char&lt;/span&gt;&lt;span&gt;&lt;/span&gt; &lt;span&gt;title&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;int&lt;/span&gt; &lt;span&gt;x&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt; int&lt;/span&gt; &lt;span&gt;y&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;int&lt;/span&gt; &lt;span&gt;w&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;int&lt;/span&gt; &lt;span&gt;h&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt; Uint32&lt;/span&gt; &lt;span&gt;flags&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;u&gt;retour :&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;retourne un pointeur vers la structure &lt;span&gt;&lt;span&gt;"SDL_Window&lt;/span&gt;&lt;/span&gt;" nouvellement créée.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;u&gt;&lt;strong&gt;paramètres :&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;le titre de la fenêtre&lt;/li&gt;
&lt;li&gt;le point x de la fenêtre ou "SDL_WINDOWPOS_CENTERED" et "SDL_WINDOWPOS_UNDEFINED"&lt;/li&gt;
&lt;li&gt;le point y de la fenêtre ou "SDL_WINDOWPOS_CENTERED" et "SDL_WINDOWPOS_UNDEFINED"&lt;/li&gt;
&lt;li&gt;la taille horizontale de la fenêtre&lt;/li&gt;
&lt;li&gt;la taille verticale de la fenêtre&lt;/li&gt;
&lt;li&gt;encore des flags que voici :&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;&lt;span&gt; &lt;/span&gt;&lt;strong&gt;SDL_WINDOW_FULLSCREEN&lt;/strong&gt;&lt;span&gt;                      &lt;/span&gt;plein écran&lt;/p&gt;
&lt;p&gt;&lt;span&gt; &lt;/span&gt;&lt;strong&gt;SDL_WINDOW_FULLSCREEN_DESKTOP&lt;/strong&gt;&lt;span&gt;     &lt;/span&gt;plein écran a la résolution du bureau&lt;/p&gt;
&lt;p&gt;&lt;span&gt; &lt;/span&gt;&lt;strong&gt;SDL_WINDOW_OPENGL&lt;/strong&gt;&lt;span&gt;                               fenêtre de contexte pour OpenGL&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt; &lt;/span&gt;&lt;strong&gt;SDL_WINDOW_SHOWN&lt;/strong&gt;&lt;span&gt;                                fenêtre visible&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt; &lt;/span&gt;&lt;strong&gt;SDL_WINDOW_HIDDEN&lt;/strong&gt;&lt;span&gt;                                fenêtre invisible&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt; &lt;/span&gt;&lt;strong&gt;SDL_WINDOW_BORDERLESS&lt;/strong&gt;&lt;span&gt;                      &lt;/span&gt;fenêtre sans contour&lt;/p&gt;
&lt;p&gt;&lt;span&gt; &lt;/span&gt;&lt;strong&gt;SDL_WINDOW_RESIZABLE&lt;/strong&gt;&lt;span&gt;                           fenêtre redimensionnable&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt; &lt;/span&gt;&lt;strong&gt;SDL_WINDOW_MINIMIZED&lt;/strong&gt;&lt;span&gt;                             &lt;/span&gt;&lt;span&gt;fenêtre minimisée&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt; &lt;/span&gt;&lt;strong&gt;SDL_WINDOW_MAXIMIZED&lt;/strong&gt;&lt;span&gt;                            &lt;/span&gt;&lt;span&gt;fenêtre agrandie&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt; &lt;/span&gt;&lt;strong&gt;SDL_WINDOW_INPUT_GRABBED&lt;/strong&gt;&lt;span&gt;       &lt;/span&gt;window has grabbed input focus  :huh: &lt;/p&gt;
&lt;p&gt;&lt;span&gt; &lt;/span&gt;&lt;strong&gt;SDL_WINDOW_INPUT_FOCUS&lt;/strong&gt;&lt;span&gt;            &lt;/span&gt;window has input focus :huh: &lt;/p&gt;
&lt;p&gt;&lt;span&gt; &lt;/span&gt;&lt;strong&gt;SDL_WINDOW_MOUSE_FOCUS&lt;/strong&gt;&lt;span&gt;          &lt;/span&gt;window has mouse focus :huh: &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SDL_WINDOW_FOREIGN&lt;/strong&gt;                               pas de fenêtre&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SDL_WINDOW_ALLOW_HIGHDPI&lt;/strong&gt;                  fenêtre en mode High-DPI (SDL2.0.1 ou plus)&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="color:#ff0000;"&gt;SDL_CreateRenderer(screen, -1, SDL_RENDERER_ACCELERATED);&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Créer un renderer (le renderer est la vue, la surface que l'on va afficher à l'écran).&lt;/p&gt;
&lt;blockquote class="ipsQuote" data-ipsquote=""&gt;&lt;div&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;SDL_Renderer&lt;/span&gt;&lt;span&gt;&lt;/span&gt; &lt;span&gt;SDL_CreateRenderer&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;SDL_Window&lt;/span&gt;&lt;span&gt;&lt;/span&gt; &lt;span&gt;window&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt; int&lt;/span&gt; &lt;span&gt;index&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt; Uint32&lt;/span&gt; &lt;span&gt;flags&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;u&gt;retour :&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;retourne un pointeur vers la structure &lt;span&gt;&lt;span&gt;"SDL_Renderer&lt;/span&gt;&lt;/span&gt;" nouvellement créée.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;u&gt;paramètres:&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;le pointeur vers la structure SDL_Window créée précédemment.&lt;/li&gt;
&lt;li&gt;j'aurais aimé vous expliquer mais malheureusement aucune doc ou tuto n'est clair là dessus du coup, ne vous en occupez pas et donnez -1 comme argument.&lt;/li&gt;
&lt;li&gt;ce sont encore des flags, vous pouvez en mettre plusieurs.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;&lt;strong&gt;SDL_RENDERER_SOFTWARE     &lt;/strong&gt;      rendu calculé par le CPU&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SDL_RENDERER_ACCELERATED  &lt;/strong&gt;    rendu calculé par le GPU &lt;strong&gt;(grosse nouveauté de la SDL2.0)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SDL_RENDERER_PRESENTVSYNC&lt;/strong&gt;    rendu synchronisé avec le taux de rafraichissement de votre écran&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SDL_RENDERER_TARGETTEXTURE&lt;/strong&gt;  rendu pour texture&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;span style="color:#ff0000;"&gt;&lt;strong&gt;SDL_RenderPresent(renderer);&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;fonction affichant le rendu sur l'écran&lt;/p&gt;
&lt;blockquote class="ipsQuote" data-ipsquote=""&gt;&lt;div&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;void&lt;/span&gt; &lt;span&gt;SDL_RenderPresent&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;SDL_Renderer&lt;/span&gt;&lt;span&gt;*&lt;/span&gt; &lt;span&gt;renderer&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;u&gt;paramètre :&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;le pointeur vers la structure SDL_Renderer créée précédemment.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="color:#ff0000;"&gt;SDL_Delay(2000);&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;fonction qui met le programme en pause pendant x milisecondes&lt;/p&gt;
&lt;blockquote class="ipsQuote" data-ipsquote=""&gt;&lt;div&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;void&lt;/span&gt; &lt;span&gt;SDL_Delay&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;Uint32&lt;/span&gt; &lt;span&gt;ms&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;u&gt;&lt;strong&gt;paramètre:&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;le nombre de milisecondes&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;&lt;span style="color:#ff0000;"&gt;&lt;strong&gt;SDL_Quit();&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;fonction qui ferme la sdl&lt;/p&gt;
&lt;blockquote class="ipsQuote" data-ipsquote=""&gt;&lt;div&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;void&lt;/span&gt; &lt;span&gt;SDL_Quit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style="color:#0000cd;"&gt;&lt;span style="font-size:24px;"&gt;&lt;u&gt;explication :&lt;/u&gt;&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;si vous lancez ce code, vous devriez avoir une fenêtre noire pendant 2 secondes.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;c'est tout à fait normal.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;à bientôt  &lt;strong&gt; &lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;
]]></description><link>https://melinyel.net/topic/595/tuto-sdl-20</link><guid isPermaLink="true">https://melinyel.net/topic/595/tuto-sdl-20</guid><dc:creator><![CDATA[cegdd]]></dc:creator><pubDate>Fri, 25 Apr 2014 22:03:26 GMT</pubDate></item></channel></rss>