<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Intégration | Magazine Jeux</title>
	<atom:link href="https://www.magazine-jeux.com/category/developpement/integration/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.magazine-jeux.com</link>
	<description>Le magazine des jeux en ligne</description>
	<lastBuildDate>Mon, 14 May 2007 05:00:00 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.4.8</generator>
	<item>
		<title>La spécificité</title>
		<link>https://www.magazine-jeux.com/la-specificite/</link>
		
		<dc:creator><![CDATA[Jean-François Renauld]]></dc:creator>
		<pubDate>Mon, 14 May 2007 05:00:00 +0000</pubDate>
				<category><![CDATA[Intégration]]></category>
		<guid isPermaLink="false">https://www.magazine-jeux.com/la-specificite/</guid>

					<description><![CDATA[Entre les deux déclarations ci-dessous, à votre avis, laquelle sera appliquée sur l&#8217;élément de liste < li> ? .page .menu li color: red; body div.menu ul li color: blue; Si les deux déclarations désignent bien le même élément, l&#8217;une est prioritaire sur l&#8217;autre et du style de la première déclaration dont va hériter l&#8217;élément de [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Entre les deux déclarations ci-dessous, à votre avis, laquelle sera appliquée sur l&rsquo;élément de liste < li> ?</p>
<p><code>.page .menu li <em>color: red;</em></p>
<p>body div.menu ul li <em>color: blue;</em><br />
</code></p>
<p>Si les deux déclarations désignent bien le même élément, l&rsquo;une est prioritaire sur l&rsquo;autre et du style de la première déclaration dont va hériter l&rsquo;élément de liste. La couleur bleue de la deuxième déclaration ne sera pas appliquée.<br />
<br />Si la première déclaration (.page .menu li) prend le pas sur la deuxième (body div.menu ul li) c&rsquo;est que le calcul de spécificité lui donne plus d&rsquo;importance.</p>
<p>La spécificité d&rsquo;une déclaration est un calcul qui indique le « poids » d&rsquo;une déclaration.<br />
<br />Ce « poids » est alors utilisé pour comparer les différentes déclarations entre-elles et savoir laquelle est prioritaire sur l&rsquo;autre, laquelle a le plus de « poids ».</p>
<p>Le calcul se fait :<br />
&#8211; en fonction de 3 types d&rsquo;éléments qui composent une déclaration (ID, class, élément balise)<br />
&#8211; sur 3 chiffres concaténés</p>
<p>Pour connaitre le premier des trois chiffres concaténés, il faut compter le nombre d&rsquo;ID dans la déclaration (a).<br />
Pour le deuxième chiffre, il faut compter le nombre de class (b).<br />
<br />Enfin, le troisième chiffre est donné par le nombre d&rsquo;élément balise (c).</p>
<p>Le poids d&rsquo;une déclaration est le nombre donné par ces trois résultats mis côte à côte (abc).</p>
<p>Dans notre exemple :</p>
<p><code>.page .menu li <em>color: red;</em><br />
Nombre d'ID : 0 (donc a=0)<br />
Nombre de class : 2 (donc b=2)<br />
Nombre d'élément : 1 (donc C=1)<br />
</code><br />
Le poids de cette déclaration est donc de 21 (021).</p>
<p><code>body div.menu ul li <em>color: blue;</em><br />
Nombre d'ID : 0 (donc a=0)<br />
Nombre de class : 1 (donc b=1)<br />
Nombre d'élément : 4 (donc C=4)<br />
</code><br />
Le poids de cette déclaration est donc de 14 (014).</p>
<p>La première déclaration est donc bien prioritaire sur la deuxième.</p>
<p>Quelques exemples :<br />
<code>#contenu #contenu-principal<br />
</code><br />
La spécificité est de 200 (a=2 ; b=0 ; c=0)</p>
<p><code>div.informations #mentions p.important span<br />
</code><br />
La spécificité est de 123 (a=1 ; b=2 ; c=3)</p>
<p>Et comme une image (ludique) vaut toujours mieux qu&rsquo;un long discours :</p>
<p><a href="http://www.stuffandnonsense.co.uk/archives/images/specificitywars-05v2.jpg">http://www.stuffandnonsense.co.uk/&#8230;/specificitywars-05v2.jpg</a></p>
<p>Cela nous permet de comprendre pourquoi, dans certains cas « inexplicable » notre déclaration ne s&rsquo;applique pas alors qu&rsquo;elle ne contient aucune erreur. L&rsquo;élément cible hérite en fait d&rsquo;une déclaration ayant une spécificité plus forte.<br />
Parfois, ces problèmes peuvent simplement se régler en « surchargeant » la déclaration afin de lui donner plus de poids. Attention néanmoins à ne pas avoir le reflexe de trop charger ses déclarations (pour éviter ce type de désagrément) au point d&rsquo;avoir des déclarations très fortes et peu souples.</p>
<p><strong>Aller plus loin :</strong></p>
<p>Spécification CSS2 (traduction française) > Le calcul de la spécificité d&rsquo;un sélecteur &#8211; <a href="http://www.yoyodesign.org/doc/w3c/css2/cascade.html#specificity">http://www.yoyodesign.org/doc/w3c/css2/cascade.html#specificity</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Jouer avec AJAX II/III</title>
		<link>https://www.magazine-jeux.com/jouer-avec-ajax-ii-iii/</link>
		
		<dc:creator><![CDATA[Jean-François Renauld]]></dc:creator>
		<pubDate>Mon, 25 Sep 2006 05:00:00 +0000</pubDate>
				<category><![CDATA[Intégration]]></category>
		<guid isPermaLink="false">https://www.magazine-jeux.com/jouer-avec-ajax-ii-iii/</guid>

					<description><![CDATA[Dans le dernier article nous avons discuté de ce qu&#8217;Ajax pouvait apporter en terme d&#8217;ergonomie pour le joueur. Nous sommes finalement arrivé à la conclusion qu&#8217;Ajax est très riche &#8211; quel surprise &#8211; mais aussi que cette technique peut s&#8217;avérer assez complexe à mettre en place. Notre but cette fois et de parcourir une implémentation [&#8230;]]]></description>
										<content:encoded><![CDATA[<p class="post_excerpt">Dans le dernier article nous avons discuté de ce qu&rsquo;Ajax pouvait apporter en terme d&rsquo;ergonomie pour le joueur. Nous sommes finalement arrivé à la conclusion qu&rsquo;Ajax est très riche &#8211; quel surprise &#8211; mais aussi que cette technique peut s&rsquo;avérer assez complexe à mettre en place.</p>
<p>Notre but cette fois et de parcourir une implémentation (parmi tant d&rsquo;autres) d&rsquo;un moteur de gestion de carte. Notre moteur tentera de tirer parti d&rsquo;Ajax en évitant au joueur de devoir supporter une période de loading.</p>
<p>Notre carte est volontairement simple : pas de support de layers, nous n&rsquo;afficherons que le sol. Le but ici est de démontrer qu&rsquo;Ajax peut être un outil fort intéressant dans le cadre du pré-loading d&rsquo;une carte, rien d&rsquo;autre. Evidemment si cette structure peut vous donner des idées c&rsquo;est tant mieux&#8230;
</p>
<p><span id="more-137"></span></p>
<h2> <strong>Concept</strong> </h2>
<p>Notre carte est composée de cases, toutes placées fort judicieusement les unes à côté des autres. Jusque là rien de bien nouveau.</p>
<div id="attachment_135" style="width: 272px" class="wp-caption aligncenter"><img fetchpriority="high" decoding="async" aria-describedby="caption-attachment-135" class=" aligncenter size-full wp-image-135" src="https://www.magazine-jeux.com/wp-content/uploads/2006/09/map_concept_3D_petit.gif" alt="Concept de la carte" title="Concept de la carte" class="caption" align="center" width="262" height="247" /><p id="caption-attachment-135" class="wp-caption-text">Concept de la carte</p></div>
<p>Nous ne voulons pas de loading, il nous faudra donc :</p>
<ol>
<li> Pouvoir faire le rendu de la carte de façon modulaire</li>
<li> Pouvoir gérer un ou plusieurs buffers, dont le rendu sera assuré par les méthodes du point 1.</li>
</ol>
<p>Dans notre cas nous prendrons 4 buffers, en haut, en bas, à droite et à gauche. La dimension des buffers dépends de vous et de vos tests, ici je les prendrai de 1&#215;5 (1 case de large sur 5 cases de long). </p>
<h2> <strong>Base de données</strong> </h2>
<p><div id="attachment_136" style="width: 144px" class="wp-caption alignleft"><img decoding="async" aria-describedby="caption-attachment-136" class=" alignleft size-full wp-image-136" src="https://www.magazine-jeux.com/wp-content/uploads/2006/09/DB_map_petit.gif" alt="Structure de la DB" title="Structure de la DB" class="caption" align="left" width="134" height="243" /><p id="caption-attachment-136" class="wp-caption-text">Structure de la DB</p></div>Voici la structure de la DB. Très classiquement nous allons retrouver des zones (les carrés de la carte) qui permettrons de construire la carte (on parle de tiles ou de tuiles).</p>
<p>Notre carte sera découpée en lignes et colonnes, ce qui nous permettra plus facilement de gérer un buffer de cases. </p>
<p>Chaque case dispose d&rsquo;une image qui lui est propre, cette image peut être NULL. Si ce champ est NULL nous utiliserons l&rsquo;image par défaut du type de terrain (type_terrain.type_img)</p>
<p>Pour le principe ajoutons une table joueur minimaliste. Elle ne retient qu&rsquo;une chose : la position du joueur.</p>
<p>Dans la réalité le schéma de votre DB sera nettement plus complexe, on est tous d&rsquo;accord, mais ça nous suffira pour l&rsquo;instant.</p>
<p>Ecrire des queries pour cette structure est très simple : prenons un exemple : comment trouver le buffer de gauche de notre carte ?</p>
<p><code><br />
SELECT C.case_id, C.type_terrain_id, C.case_ligne, C.case_col, C.case_img, T.type_img<br />
FROM 	type_terrain T, cases C<br />
WHERE T.type_terrain_id=C.type_terrain_id<br />
AND C.case_col = 4<br />
AND C.case_ligne BETWEEN 11 AND 15<br />
</code></p>
<p>Ce select renvoie donc le buffer gauche de notre carte. C&rsquo;est à dire une colonne composée de 5 cases. Pour obtenir les autres buffers nous jouerons sur les deux dernières conditions, faisant varier soit les colonnes soit les lignes. Par exemple, pour trouver le buffer du bas</p>
<p><code><br />
AND C.case_col BETWEEN 5 AND 9<br />
AND C.case_ligne = 16<br />
</code></p>
<p><strong> </p>
<h2>Structure du code</h2>
<p> </strong><br />
Nous allons essayer de faire aussi générique que possible. De quoi avons-nous besoin ? Tout d&rsquo;abord d&rsquo;un script capable de nous renvoyer le XML proprement dit. Nous appellerons ce script un module. </p>
<p>Notre structure, en sus de la carte, devra être capable d&rsquo;accueillir bien d&rsquo;autres modules, pour à peu près n&rsquo;importe quoi. Puisque nous risquons d&rsquo;avoir un nombre de modules importants il ne serait pas opportun de lier chaque appel Ajax à un module en particulier, ça nous obligerait à connaître à chaque fois l&rsquo;URL de ce module, ce qui peut être contraignant (et ennuyeux niveau sécurité).</p>
<p>Pour éviter de coupler module et code côté client nous allons définir un point d&rsquo;entrée. Ce script particulier sera chargé de dispatcher l&rsquo;appel Ajax vers le module ad-hoc puis d&rsquo;en renvoyer le code XML. Avantage supplémentaire, nous pourrons valider ce que le client nous envoi directement au niveau du point d&rsquo;entrée.</p>
<p>Le code en dessous vous donne un aperçu de l&rsquo;implémentation du point d&rsquo;entrée et d&rsquo;un module.</p>
<h2>
<h2>Le point d&rsquo;entrée</h2>
</h2>
<p><code><br />
<?
//A ne pas oublier si vous utilisez des sessions
session_start();


/***********************************
      	GLOBAL
***********************************/
//Contient les infos génériques (passwords, etc)


   include_once("../globals.php");


/***********************************
      	DATABASE
************************************/
/** Fonctions d'accès à la DB. Notez qu'il peut être utile de les découper aussi en fonction des modules, ce qui évite d'inclure des centaines de lignes inutiles.**/


   require_once("../includes/database/db_interface.php");


/***********************************
      	DEFINITION MODULES
************************************/
/**
Contient la liste des modules devant être supportés. Il est plus simple de rassembler tous les requires des modules dans un seul fichier


Pour plus d'efficacité on peut également faire le require du module nécéssaire juste avant d'apeller son code.
**/


   require_once("module_definition.php");


/***********************************
      	OPERATIONS
************************************/


//! Fermer la connexion  *AVANT* de renvoyer le code XML.
   db_open_connection();


   $str_xml ="";


      if (!isset($_REQUEST['action']) )
      <em><br />
      	die "action non définie!";<br />
      	/**<br />
      		Erreur mal gérée! Idéalement il faut logger les détails de la requête.<br />
      		Il peut également être intéressant de renvoyer un XML contenant les détails de l'erreur<br />
      		Ca simplifiera d'autant le debugging.<br />
      	**/<br />
      </em><br />
      else<br />
      <em><br />
      	switch($_REQUEST['action'])<br />
      	<em></p>
<p>      		/** SUPPORT MODULE CARTE **/<br />
      		case $_REQUEST['action']=='map':<br />
      			$str_xml .= get_default_view(/*params*/);<br />
      			if ($SYS_DEBUG==1) raw_log(1, "list_mail ok");<br />
      			break;</p>
<p>      		// Pour créer un nouveau mode il suffira d'ajouter un case ici</p>
<p>      		/** AUTRE / DEFAULT **/<br />
      		default:<br />
      			$str_xml .= "DEFAULT";<br />
      			if ($SYS_DEBUG==1) detailled_log(1, "action vide");<br />
      	</em></p>
<p>      </em>	  	   </p>
<p>	  //Fin de la génération du XML --> fermeture de la connexion devenue inutile<br />
	  db_close_connection();</p>
<p>	  // Renvoie le code XML généré<br />
	  echo $str_xml;<br />
?><br />
</code></p>
<h2>
<h2>Un module</h2>
</h2>
<p> (ici la carte, donc)<br />
<code><br />
<?


/****************************
/*		DEFAULT				*
/***************************/


//fonction appelée par le mode lié à ce module, c'est à daire par le site "standard", pas par un appel AJAX.
//Elle affiche la version de base du module


function map_mod_default()
<em><br />
//Cette fonction renvoie du HTML, pas du XML, ce n'est pas un appel AJAX</p>
<p>  $str_html="";</p>
<p>  //scripts necessaires à l'application --> AJAX<br />
  $str_html .= init_map_script();<br />
  $str_html .= /* rendu de base */;</p>
<p>  return $str_html;</p>
<p></em>	 </p>
<p>/****************************<br />
/*		 Script JS			*<br />
/***************************/</p>
<p>function init_map_script()<br />
<em><br />
    /**<br />
    N'importe quel script dont vous pourriez avoir besoin est à ajouter ici.<br />
    Notez que dans le cas des scripts génériques utilisés régulièrements il sera plus sage de les<br />
    inclure dans votre index.php une fois pour toute.<br />
    **/<br />
    return "";<br />
</em></p>
<p>/****************************<br />
/*		Actions				*<br />
/****************************/<br />
function get_default_view()<br />
<em><br />
	$str_xml = ... /* Renvoie vos infos sous forme de XML */</p>
<p>	/**<br />
		C'est ici qu'il faudra insérer l'accès à la DB et la création du XML,<br />
		autrement dit c'est le coeur de votre moteur de carte, pas niveau rendu,<br />
		mais bien niveau data<br />
	**/</p>
<p>	return $str_xml<br />
</em></p>
<p>?><br />
</code></p>
<h2> <strong>Côté client</strong> </h2>
<p>Mais qu&rsquo;en est-il côté client ? Très simple : du javascript à foison ! Dans le chapitre précédent nous avions un simple « Moteur javascript », et bien c&rsquo;est lui qui va se charger de tout :</p>
<ol>
<li>Des appels pour récupérer le code XML</li>
<li>Des buffers</li>
<li>De l&rsquo;affichage des informations recueillies</li>
</ol>
<p>La solution la plus propre pour gérer l&rsquo;affichage est d&rsquo;utiliser des feuilles de style XSL. Mais ce n&rsquo;est pas forcément la solution la plus simple. XSL fait appel à des technologies telles que XPath, qui ne sont pas toujours accessibles aux moins expérimentés.</p>
<p>En pseudo-code, voilà ce que donne notre moteur JS :<br />
<code><br />
Vérifier si le buffer contient ce dont on a besoin<br />
Si il ne le contient pas<br />
Recupérer le handler (l'objet XMLHttpRequest)<br />
Construire la requête en fonction de ce qu'on désire obtenir<br />
Envoyer la requête et récupérer la réponse</p>
<p>Tant que la réponse n'est pas reçue entièrement on attend cette réponse</p>
<p>Si la réponse qui est reçue est une erreur (ex: une page 404) on gère l'erreur<br />
Sinon on met à jour le buffer</p>
<p>On sélectionne le nœud que l'on veut afficher</p>
<p>On récupère la feuille de style XSL</p>
<p>Si on a à la fois les données et la feuille de style on effectue le rendu<br />
Sinon on gère une erreur</p>
<p>On identifie la cible dans laquelle il faut insérer le contenu (avec son attribut ID)<br />
On insère le code HTML obtenu grâce à la transformation XSL<br />
</code></p>
<p>Il existe des tas de très bon tutoriaux pour découvrir quelles sont les fonctions qui vont bien en JavaScript. Allez jeter un œil <a href="http://web.developpez.com/tutoriel/javascript/#ajax">du côté de developpez.com</a> par exemple pour un très bon papier dessus.</p>
<p><strong> </p>
<h2>Conclusions</h2>
<p> </strong><br />
Avec ce que nous avons vu ici vous devriez être capable de construire une structure simple de gestion d&rsquo;appels Ajax. Pour augmenter les possibilités de cette structure il ne vous reste qu&rsquo;à développer de nouveaux modules, à choisir l&rsquo;action qui y est liée (mod) et à effectuer l&rsquo;appel javascript qui va bien.</p>
<p>Dans le cas qui nous intéresse, une carte, il est clair que nous gagnons en ergonomie ce qui nous perdons en complexité. Le joueur ne doit plus reloader la page à chaque mouvement de son personnage, mais seulement quand le besoin d&rsquo;un scroll se fait sentir. </p>
<p>Implémenter le support du scrolling manuel (le joueur qui déplace la vue) est également un jeu d&rsquo;enfant : c&rsquo;est déjà supporté.</p>
<p>Soyons clair, la méthode décrite n&rsquo;est pas parfaite et peut-être améliorée. Le code présenté n&rsquo;est pas orienté objet, ce qui est très dommage. Point de vue performance, le switch sur l&rsquo;action n&rsquo;est sûrement pas la panacée. Avec de nombreuses actions différentes vous aurez vite un code horrible. Mais cet exemple a le mérite de montrer qu&rsquo;il n&rsquo;est pas forcément si complexe de concevoir « from scratch » le support d&rsquo;une carte en Ajax.</p>
<p>Dans le prochain épisode nous verrons qu&rsquo;il existe aussi des frameworks qui supportent déjà toutes ces fonctions, vous évitant donc de réinventer la roue à chaque fois. Stay tuned, et rendez-vous dans un petit mois!</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>La sécurité dans un jeu PHP/MySQL</title>
		<link>https://www.magazine-jeux.com/la-securite-dans-un-jeu-php-mysql/</link>
		
		<dc:creator><![CDATA[Jean-François Renauld]]></dc:creator>
		<pubDate>Fri, 15 Sep 2006 15:11:46 +0000</pubDate>
				<category><![CDATA[Intégration]]></category>
		<guid isPermaLink="false">https://www.magazine-jeux.com/la-securite-dans-un-jeu-php-mysql/</guid>

					<description><![CDATA[La sécurité dans un jeu en PHP/MySQL est un élément primordial. Si votre site n&#8217;est pas sécurisé, c&#8217;est la porte ouverte à toutes sortes de tricheries de la part de joueurs moins honnêtes que les autres&#8230; Et qui dit triche, dit plaisir de jeu perdu pour les victimes ! Il est également primordial de penser [&#8230;]]]></description>
										<content:encoded><![CDATA[<p class="post_excerpt">La <strong>sécurité</strong> dans un jeu en PHP/MySQL est un élément <strong>primordial</strong>. Si votre site n&rsquo;est pas sécurisé, c&rsquo;est la porte ouverte à toutes sortes de <strong>tricheries</strong> de la part de joueurs moins honnêtes que les autres&#8230; Et qui dit triche, dit plaisir de jeu perdu pour les victimes !<br />
Il est également primordial de penser à la sécurité avant même de commencer à programmer. Plus tard, vous aurez bien d&rsquo;autres préoccupations, et il risque d&rsquo;être difficile de revenir en arrière. Par contre, quelques <strong>bonnes pratiques</strong> respectées tout au long du développement vous éviterons bien des soucis par la suite !</p>
<p>Il n&rsquo;est pas question dans cet article de faire l&rsquo;inventaire de toutes les failles possibles de sécurité pour un site en PHP. Je conseille à ce sujet le très bon <a href="http://phpsec.org/projects/guide/fr/">Guide Sécurité PHP du PHP Security Consortium</a>, après avoir bien sûr parcouru la <a href="http://www.php.net/manual/fr/security.php">rubrique sécurité du manuel PHP</a>.<br />
Cet article a pour but de vous donner les <strong>bases</strong> qui vous permettront de développer l&rsquo;esprit tranquille, le tout illustré d&rsquo;exemples concrets applicables aux jeux web.</p>
<p><span id="more-138"></span></p>
<h2>Configuration et utilisation des variables</h2>
<p>La configuration de php, stockée dans le <em>php.ini</em> est importante puisqu&rsquo;elle conditionne le comportement des variables prédéfinies. Utilisez une configuration par défaut, elle est le fruit de l&rsquo;expérience de la communauté PHP. Evitez d&rsquo;utiliser des fonctionnalités spécifiques, qui pourraient ne pas être disponibles sur n&rsquo;importe quel serveur ! On peut citer <em>register_globals</em>, <em>magic_quotes_gpc</em>, <em>short_open_tags</em>, &#8230;<br />
Et bien sûr, si vous êtes plusieurs à développer, utilisez tous la même configuration.</p>
<p>Voici les points vraiment très importants :</p>
<ul>
<li> <em>register_globals</em> doit être positionné à <em>Off</em>. Lorsque vous utilisez des variables de session, utilisez toujours $_SESSION, idem pour les cookies, variables passées en GET et POST :  $_COOKIE, $_GET et $_POST.</li>
</ul>
<ul>
<li> Positionnez <em>error_reporting</em> à <em>E_ALL</em>, afin d&rsquo;afficher toutes les erreurs, warnings et notice. Un bon moyen est d&rsquo;appeler <em>error_reporting(E_ALL)</em> au début de chaque script. Si vous avez le moindre avertissement, c&rsquo;est potentiellement une faille de sécurité !</li>
</ul>
<ul>
<li> Evitez d&rsquo;utiliser le <em>include($page)</em>, même si vous contrôlez avec une liste de pages autorisées.</li>
</ul>
<ul>
<li> Si vous avez un espace d&rsquo;administration, contrôlez son accès avec un mot de passe (.htaccess)</li>
</ul>
<ul>
<li> Si vous offrez la possibilité d&rsquo;uploader un fichier, contrôlez son contenu, cela pourrait être&#8230; un script php, qui pourrait être exécuté par le serveur !</li>
</ul>
<ul>
<li> De manière générale, évitez de re-développer des fonctionnalités déjà existantes, comme la gestion des sessions. Sauf si vous êtes un véritable expert, il y a de fortes chances pour que vous laissiez passer certains aspects importants (la sécurité en est un), et cela pour un gain pas forcément réel.</li>
</ul>
<ul>
<li> Sur la même note, si vous utilisez des outils externes (forum phpBB, punBB, &#8230;) assurez-vous de le maintenir à jour régulièrement afin de combler les failles de sécurité. Si vous décidez de gérer vous-même votre hébergement (serveur dédié), sachez que c&rsquo;est un métier à part entière, et un métier complexe. Là encore, agissez prudemment, n&rsquo;utilisez que des outils stables et sécurisés, et entourez-vous de personnes compétentes sur le sujet.</li>
</ul>
<ul>
<li> Pour éviter les injections SQL, assurez-vous de toujours échapper les variables utilisées dans les requêtes, surtout si elles proviennent de l&rsquo;utilisateur. La fonction addslashes est généralement utilisée, mais il est préférable d&rsquo;utiliser celle correspondant à votre base de données : <em>mysql_real_escape_string</em> pour MySQL (qui échappe en plus le caractère 0)<br />
Attention aux <em>magic quotes</em> : les variables peuvent être déjà échappées ou non selon la configuration php.<br />
Le manuel PHP fournit une <a href="http://fr2.php.net/manual/fr/function.mysql-real-escape-string.php)">solution sécurisée</a> les prenant en compte :<br />
<code><br />
<?php
// Protège la variable
function quote_smart($value)
<em><br />
   // Stripslashes<br />
   if (get_magic_quotes_gpc()) <em><br />
     $value = stripslashes($value);<br />
   </em><br />
   // Protection si ce n'est pas une valeur numérique ou une chaîne numérique<br />
   if (!is_numeric($value)) <em><br />
     $value = "'" . mysql_real_escape_string($value) . "'";<br />
   </em><br />
   return $value;<br />
</em></li>
</ul>
<p>// Connexion<br />
$link = mysql_connect('mysql_host', 'mysql_user', 'mysql_password')<br />
OR die(mysql_error());</p>
<p>// Fabrication d'une requête sécurisée<br />
$query = sprintf("SELECT * FROM users WHERE user=%s AND password=%s",<br />
quote_smart($_POST['username']),<br />
quote_smart($_POST['password']));</p>
<p>mysql_query($query);<br />
?><br />
</code></p>
<p>Il est généralement recommandé de désactiver les <em>magic quotes</em>, et de systématiquement<br />
échapper les variables utilisées dans une requête SQL (cela simplifie également<br />
leur sortie sur la page html). Pour désactiver les magic quotes quelle que soit<br />
la configuration, on peut placer ce bout de code au début de chaque page :</p>
<p><code><br />
set_magic_quotes_runtime(FALSE);<br />
if(get_magic_quotes_gpc())<em><br />
	function remove_magic_quotes(&$var) <em><br />
		if(is_array($var))<em><br />
			array_walk($var, "remove_magic_quotes");<br />
		</em> else if (is_string($var)) <em><br />
			$var=stripslashes($var);<br />
		</em><br />
	</em></p>
<p>	remove_magic_quotes($_POST);<br />
	remove_magic_quotes($_GET);<br />
	remove_magic_quotes($_REQUEST);<br />
	remove_magic_quotes($_COOKIE);<br />
</em><br />
</code></p>
<p>Pour éviter les problèmes d&rsquo;injection SQL, on peut aussi se tourner vers les requêtes préparées, supportées entre autres dans la nouvelle <a href="http://www.php.net/manual/fr/ref.pdo.php">extension PDO</a> inclue dans PHP 5.1.</p>
<h2>Contrôle des données fournies par l&rsquo;utilisateur</h2>
<p>Si vous n&rsquo;en avez jamais entendu parler, c&rsquo;est que vous n&rsquo;avez lu aucun article sur la sécurité.<br />
Les données fournies en provenance de l&rsquo;utilisateur, qu&rsquo;elle proviennent d&rsquo;un formulaire de saisie (variable $_POST), ou qu&rsquo;elles soient passées en paramètre de la requête HTTP ($_GET), peuvent aisément être falsifiées. Il faut donc impérativement contrôler TOUTE valeur que vous récupérez du navigateur web, et vérifier que ces valeurs sont bien fournies !</p>
<p>Une bonne pratique est de lister, pour chaque action, les variables nécessaires, ainsi que des contraintes sur leur contenu (ceux qui ont suivi des cours se remémoreront la notion de « pré-condition »). Si une valeur est facultative pour l&rsquo;utilisateur, mais que vous en avez besoin pour un traitement, pensez à l&rsquo;initialiser avec une valeur par défaut.</p>
<p>Exemple pour l&rsquo;action « inscription d&rsquo;un joueur » :</p>
<p>$_POST[&lsquo;nom_perso&rsquo;] : texte, min 1 caractère, max 100 caractères, obligatoire<br />
$_POST[&lsquo;description&rsquo;] : texte, min 0 caractère, max 1000 caractères, obligatoire<br />
$_POST[&lsquo;force&rsquo;] : nombre, min 1, max 20, obligatoire<br />
$_POST[&lsquo;endurance&rsquo;] : nombre, min 1, max 20, obligatoire<br />
force + endurance = 20</p>
<p>Toutes ces contraintes devront être vérifiées avant de pouvoir effectuer l&rsquo;inscription. Si une contrainte n&rsquo;est pas respectée, à vous de décider de renvoyer une erreur à l&rsquo;utilisateur (« Nom du perso obligatoire ») ou bien de considérer cela comme une tentative de tricherie ! S&rsquo;il n&rsquo;est pas possible en navigant normalement de fournir une certaine valeur, alors c&rsquo;est très probablement une tentative de triche. Exemple, vous avez sur une page 3 liens :</p>
<ul>
<li> avancer.php?direction=1</li>
<li> avancer.php?direction=2</li>
<li> avancer.php?direction=3</li>
</ul>
<p>Il n&rsquo;y a que 3 directions possibles, et il n&rsquo;existe nulle part sur le site de lien avec une direction différente de 1, 2 ou 3. Si l&rsquo;on vous fournit une valeur différente, alors c&rsquo;est que l&rsquo;utilisateur a modifié le lien manuellement !</p>
<p>Les contraintes listées précedemment pourraient se traduire ainsi :</p>
<p><code><br />
function valider_inscription($variables) <em><br />
	if (!isset($variables['nom_perso'])) return array('TRICHE', 'nom_perso non défini');<br />
	if (!is_string($variables['nom_perso'])) return array('TRICHE', 'nom_perso non textuel');<br />
	if (strlen($variables['nom_perso'])<1 || strlen($variables['nom_perso'])>100) return array('VALID', 'Le nom du perso doit comprendre entre 1 et 100 caractères');</p>
<p>	if (!isset($variables['description'])) return array('TRICHE', 'description non défini');<br />
	if (!is_string($variables[' description '])) return array('TRICHE', ' description non textuel');<br />
	if (strlen($variables[' description '])>1000) return array('VALID', 'La description du perso ne doit pas excéder 1000 caractères');</p>
<p>	if (!isset($variables['force'])) return array('TRICHE', 'force non défini');<br />
if (!is_numeric(($variables['force'])) return array('VALID', 'La force doit être un nombre');<br />
if ($variables['force']<1 || $variables['force']>20) return array('VALID', 'La force doit être comprise entre 1 et 20');</p>
<p>	if (!isset($variables['endurance'])) return array('TRICHE', 'endurance non défini');<br />
if (!is_numeric(($variables['endurance'])) return array('VALID', 'L'endurance doit être un nombre');<br />
if ($variables['endurance']<1 || $variables['endurance']>20) return array('VALID', 'L'endurance doit être comprise entre 1 et 20');</p>
<p>if ($variables['force']+$variables['endurance']!=20) return array('VALID', 'Le cumul de la force et de l'endurance doit valoir 20');</p>
<p>return array('OK', '');<br />
</em><br />
</code></p>
<p>Cette fonction pourra être utilisée ainsi :</p>
<p><code><br />
list($erreur, $message)=valider_inscription($_POST);<br />
if ($erreur=="TRICHE") <em><br />
	//selon votre politique, logger la tentative, afficher un message à l'utilisateur, etc<br />
</em> else if ($erreur=="VALID") <em><br />
	//Renvoyer le formulaire avec le message d'erreur $message à l'utilisateur<br />
</em> else <em><br />
	//OK, effectuer l'inscription en utilisant $_POST['nom_perso'], $_POST['force'], etc<br />
</em><br />
</code></p>
<p>A propos de la politique concernant la triche, il est utile d&rsquo;enregistrer quelque part toutes les tentatives de triche. Lorsqu&rsquo;une entrée ne correspond pas à ce qu&rsquo;elle devrait être, on peut enregistrer cela sur le disque, avec la requête lancée, la page appelée, l&rsquo;IP, ainsi que toutes les variables de session (numéro de compte). Ce fichier peut même entre envoyé à un administrateur par mail régulièrement. Cela permet de voir immédiatement une tentative de piratage, son auteur, et de prendre immédiatement les mesures qui s&rsquo;imposent.<br />
On peut faire la même chose pour les requêtes SQL ayant échoué. A chaque requête lancée, on va vérifier que l&rsquo;exécution s&rsquo;est déroulée correctement (mysql_query() renvoit false en cas d&rsquo;échec). Si ce n&rsquo;est pas le cas, alors on va envoyer un mail à l&rsquo;administrateur avec toutes les infos citées précédemment. En plus de permettre de contrôler que toutes les requêtes sont bonnes, cela permet quelquefois de détecter une tentative de hack par injection SQL.</p>
<p>Voici deux exemples qui vous convaincront de la nécessité de bien contrôler ses variables.</p>
<p>1) Imaginons que vous ayez une fonctionnalité de don d&rsquo;argent à un autre personnage.<br />
L&rsquo;utilisateur choisit un destinataire, puis saisit la somme qu&rsquo;il veut lui céder dans un formulaire. Imaginez d&rsquo;abord que vous contrôliez bien que la somme soit un nombre, mais que vous ne testiez pas les bornes. Votre traitement ressemble à :</p>
<p><code><br />
UPDATE Perso set argent=argent-somme where id_perso=$donneur<br />
UPDATE Perso set argent=argent+somme where id_perso=$destinataire<br />
</code></p>
<p>Imaginez qu&rsquo;un joueur malin saisisse une somme négative&#8230; cela aura pour effet de retirer de l&rsquo;argent au destinataire, et d&rsquo;en ajouter au donneur !</p>
<p>2) Votre jeu se déroule sur une carte, chaque personnage se trouvant une case. Votre script d&rsquo;attaque, attaquer.php, prend en paramètre un nombre correspondant au personnage visé, id_perso_vise. Lorsque l&rsquo;utilisateur choisit d&rsquo;attaquer, le site lui présente une liste de personnages qui sont à sa portée, c&rsquo;est-à-dire à moins de 3 cases, accompagné d&rsquo;un lien attaquer.php?id_perso_vise=xxxx<br />
Si vous ne contrôlez pas que le personnage visé est bien à moins de 3 cases dans le script attaquer.php, alors un joueur pourrait modifier l&rsquo;url, et attaquer n&rsquo;importe quel perso où qu&rsquo;il soit !</p>
<p>Il existe des cas très subtils, par exemple prenons si une variable $force contient la chaîne « 15+250 » (saisie par l&rsquo;utilisateur) :</p>
<ul>
<li> Dans un calcul PHP, $force sera converti en nombre, la conversion récupère tous les chiffres jusqu&rsquo;au premier caractère non numérique è if ($force<20) renverra true</li>
<li> Si alors vous faites une requête : UPDATE Perso set force=$force, alors la valeur 265 sera insérée dans la table !<br />
è il faut vérifier l&rsquo;utilisateur a bien saisi un nombre (<em>is_numeric</em>). Il est aussi possible de systématiquement convertir le nombre en entier avec <em>intval()</em> par exemple, mais cela ne permet pas de détecter la tentative de triche.</li>
</ul>
<h2>Concurrence d&rsquo;accès aux données</h2>
<p>Maintenant que les données en entrées des traitement sont bien contrôlées, nous allons nous intéresser aux traitements aux-mêmes.</p>
<p>Reprenons notre exemple de don d&rsquo;argent. Cette action est effectuée par un script donner.php qui prend en paramètre le destinataire du don, ainsi que la somme &#8211; entier positif, qui doit être inférieur au montant disponible sur le compte bancaire du joueur. Le numéro du donateur (joueur connecté) est bien entendu conservé dans une variable de session.</p>
<p>La structure générale du script est la suivante :</p>
<p><code><br />
//Validation : on vérifie que le joueur possède assez d'argent<br />
$r=mysql_query("SELECT argent from Perso where id_perso=".$_SESSION["id_perso']);<br />
list($argent_dispo)=mysql_fetch_row($r);<br />
if ($somme > $argent_dispo) <em><br />
	// renvoyer un message d'erreur à l'utilisateur indiquant qu'il n'a pas assez d'argent<br />
</em><br />
...</p>
<p>//Traitement : on transfert l'argent d'un perso à l'autre<br />
mysql_query("UPDATE Perso set argent=argent-".$_POST['somme']." where id_perso=".$_SESSION['id_perso']);<br />
mysql_query("UPDATE Perso set argent=argent+".$_POST['somme']." where id_perso=$destinataire");<br />
</code></p>
<p>Tout va bien jusqu&rsquo;à présent, notre code fonctionne. Maintenant, imaginons qu&rsquo;il survienne un délai notable entre la validation et le traitement. Les serveurs web gèrent plusieurs processus ou requêtes simultanément. Un script peut donc être interrompu provisoirement, avant de reprendre son exécution plus tard. Vous pourriez également avoir à effectuer des calculs longs et compliquées entre la validation et la mise à jour de la base de données.</p>
<p>Si un joueur envoie alors plusieurs fois de suite la même requête http (avec le même contenu), ce qui peut aisément être effectué en cliquant plusieurs fois de suite, très rapidement, sur le bouton de validation, alors nous avons plusieurs requêtes qui arrivent simultanément au serveur web. Notre serveur web sait exécuter plusieurs scripts (processus) simultanément, et leur exécution peut être effectuée simultanément &#8211; surtout si par exemple, le serveur dispose de plusieurs CPU ; mais aussi parce que le système peut décider de suspendre un processus pour en démarrer un autre.</p>
<p>Considérons donc le cas où 2 appels identiques (mêmes paramètres) à donner.php sont arrivés au serveur web simultanément. Nous allons les appeler A et B. Le donateur (joueur n°42) dispose de 50 pièces sur son compte. Il souhaite en donner 30 au joueur n°123, qui en possède initialement 20.<br />
Le séquencement des opérations peut être le suivant :</p>
<p>Le système démarre l&rsquo;appel A au script<br />
A effectue la phase de validation è ok, le joueur veut donner 30 et dispose de 50<br />
Le système interromps l&rsquo;appel A et démarre l&rsquo;appel B au script.<br />
B effectue la phase de validation è ok, le joueur veut donner 30 et dispose de 50<br />
B effectue le traitement, il retire 30 à A et les verse à B è joueur 42 dispose de 20, joueur 123 dispose de 50<br />
B se termine<br />
A reprend son exécution<br />
B effectue le traitement, il retire 30 à A et les verse à B è joueur 42 dispose de -10, joueur 123 dispose de 80 !</p>
<p>C&rsquo;est ce genre de problème qui a conduit des informaticiens, il y a quelques dizaines d&rsquo;années, à inventer les bases de données et la notion de transaction. Je ne vais pas rentrer dans les détails ici (internet fournit une large documentation sur le sujet), sachez juste que les transactions ne sont pas supportées par le format de table par défaut de MySQL, MyISAM, mais qu&rsquo;elles le sont avec InnoDB.<br />
Les transactions permettent de verrouiller les données manipulées, et de s&rsquo;assurer qu&rsquo;elles n&rsquo;ont pas été modifiées entre le début et la fin de la transaction. Si nous avions encapsulé toutes nos requêtes SQL dans une même transaction, nous aurions eu l&rsquo;assurance que le 2ème appel n&rsquo;aurait pas abouti.</p>
<p>Outre ce cas d&rsquo;école, il existe de nombreuses situations où vous pourriez avoir des problèmes.</p>
<p>Prenons l&rsquo;exemple d&rsquo;une gestion des points d&rsquo;action (PA). Le joueur gagne 1 PA par heure. Pour gérer ce système, on stocke la date/heure (timestamp) de dernière connexion pour chaque joueur. Lorsqu&rsquo;il se connecte, on calcule le temps écoulé depuis le dernier gain de PA, et on lui redonne autant de PA que d&rsquo;heures écoulées. Notre script pourrait ressembler à :</p>
<p><code><br />
$r=mysql_query("SELECT timestamp_gain from Perso where id_perso=".$_SESSION['id_perso']);<br />
list($timestamp_gain)=mysql_fetch_row($r));<br />
if (time()-$timestamp_gain>3600) <em> //si plus de 3600 secondes (1h) se sont écoulées depuis la dernière connexion<br />
	$gain = floor((time()-$timestamp_gain)/3600); //calculer le nombre d'heures écoulées<br />
	mysql_query("UPDATE Perso set PA=PA+$gain, timestamp_gain= timestamp_gain+3600*$gain_timestamp where id_perso=$id_perso");<br />
</em><br />
</code></p>
<p>Maintenant, imaginez si deux appels à ce script arrivent simultanément au serveur web&#8230; Quel est le risque ? Que le joueur perçoive 2 fois trop de PA !</p>
<p>Pour éviter cette situation délicate, il n&rsquo;existe guère de salut en dehors des transactions. Vous pourriez effectuer toute l&rsquo;opération en une seule requête (la requête est compliquée mais c&rsquo;est parfaitement faisable), mais ce n&rsquo;est valable que pour ce cas précis. Vous pourriez aussi gérer vous-même une section critique à l&rsquo;aide de sémaphores UNIX, de la fonction <em>flock()</em> ou la fonction <em>GET_LOCK()</em> de MySQL. Oubliez tout de suite, c&rsquo;est une très mauvaise idée. D&rsquo;une part, parce que (hormis avec <em>flock</em>), vous devenez dépendant de fonctions qui ne seront pas forcément disponibles sur toute plate-forme, mais surtout parce que vous êtes en train de réinventer la roue ! La gestion des transactions est un problème compliqué, fiez-vous plutôt aux implémentations fiables et éprouvées qui existent déjà, vous gagnerez du temps et de la sueur ! 🙂</p>
<p>Pour clôre ce chapitre (et vous faire des frayeurs :p), appliquez le comportement que l&rsquo;on vient de voir à une action d&rsquo;attaque d&rsquo;un adversaire : le joueur inflige des dommages à un adversaire. Si le nombre de Points de Vie de l&rsquo;adversaire bascule en dessous de zéro, l&rsquo;adversaire meurt. Plusieurs joueurs peuvent même attaquer un même adversaire simultanément. Que peut-il se passer en cas d&rsquo;attaques simultanées sur un même perso ?</p>
<h2>Multi-comptes</h2>
<p>Vous avez maintenant toutes les cartes en main pour sécuriser votre site. Il reste cependant un problème potentiel : le multi-comptes. En effet, dans un jeu traditionnel, comme un jeu de carte, une personne ne peut jouer qu&rsquo;un seul joueur. Dans un jeu sur internet, il en va autrement. Une même personne peut très facilement se créer plusieurs comptes sur votre jeu !<br />
Selon le type de jeu, cela aura un impact plus ou moins important. Dans un jeu de guerre, où le nombre de joueurs influence les chances de victoire, cela peut être catastrophique. A moindre échelle, un autre compte peut être utiliser pour affaiblir l&rsquo;ennemi avant de l&rsquo;attaquer avec son vrai personnage, pour espionner ou même infiltrer son ennemi.</p>
<p>Il faut savoir qu&rsquo;il est presque impossible, au niveau technique, d&#8217;empêcher le multi-comptes. Les principales techniques de détection, basées sur l&rsquo;e-mail, l&rsquo;adresse IP ou les cookies, peuvent être contournées par une personne suffisamment expérimentée. De même, il peut arriver que plusieurs personnes jouent réellement à partir du même poste (familles, écoles, cyber-cafés, &#8230;). Aucune technique de détection n&rsquo;est donc véritablement fiable.</p>
<p>En conséquence, il est important d&rsquo;évaluer les impacts et les risques provoqués par une personne gérant plusieurs comptes sur votre jeu. De là, vous devrez en déduire une politique à adapter face à ce problème.<br />
Selon le type et les règles du jeu, cela pourrait être :</p>
<ul>
<li> autorisation explicite de faire du multi-comptes (aucun d&rsquo;impact)</li>
<li> autorisation implicite (très faible impact)</li>
<li> interdiction explicite sans répression.</li>
<li> interdiction explicite avec répression, ce qui suppose la mise en place d&rsquo;un système de détection. On peut joueur sur le niveau de tolérance, sur l&rsquo;éducation plutôt que la répression, s&rsquo;aider de la dénonciation, etc. Le système de détection n&rsquo;étant pas fiable, certains jeux mettent même en place des équipes chargées d&rsquo;enquêter et juger les cas litigieux.</li>
</ul>
<p>Le meilleur moyen de limiter le multi-comptes reste sans aucun doute de faire en sorte qu&rsquo;il n&rsquo;ait aucun impact sur le jeu&#8230; Ce qui n&rsquo;est pas toujours forcément évident. C&rsquo;est donc un aspect qui devrait être pris en compte dès la conception du jeu !</p>
<p>Pour conclure, retenez surtout qu&rsquo;il n&rsquo;y a pas de solution toute faite. Il faudra la choisir en fonction de votre jeu, de votre public et&#8230; de votre intuition ! 😉</p>
<hr />
<p><em>Je remercie <a href="http://www.jdr-delain.net">Merrick</a>, <a href="http://www.mountyhall.com">VYS</a> et <a href="http://www.nainwak.com">DT</a> pour leurs remarques et relecture de cet article 🙂</em></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Astuces pour une feuille de style pour l&#8217;impression</title>
		<link>https://www.magazine-jeux.com/astuces-pour-une-feuille-de-style-pour-limpression/</link>
		
		<dc:creator><![CDATA[Jean-François Renauld]]></dc:creator>
		<pubDate>Mon, 04 Sep 2006 05:00:00 +0000</pubDate>
				<category><![CDATA[Intégration]]></category>
		<guid isPermaLink="false">https://www.magazine-jeux.com/astuces-pour-une-feuille-de-style-pour-limpression/</guid>

					<description><![CDATA[Les CSS permettent d&#8217;utiliser une feuille de style différente en fonction du média utilisé : écran, imprimante, etc. On peut appliquer à une page web un style spécifique pour l&#8217;impression. Voici quelques astuces et reflexes à avoir au moment de préparer ses pages et ses feuilles de style pour bien profiter des possibilité des styles [&#8230;]]]></description>
										<content:encoded><![CDATA[<p class="post_excerpt">Les CSS permettent d&rsquo;utiliser une feuille de style différente en fonction du média utilisé : écran, imprimante, etc.<br />
On peut appliquer à une page web un style spécifique pour l&rsquo;impression.</p>
<p>Voici quelques astuces et reflexes à avoir au moment de préparer ses pages et ses feuilles de style pour bien profiter des possibilité des styles d&rsquo;impression.</p>
<p><span id="more-129"></span><br />
<strong>L&rsquo;appel à la feuille de style</strong></p>
<p>De la même manière que vous appelez votre ou vos feuilles de style habituellement, vous pouvez ajouter des appels à d&rsquo;autres feuilles en spécifiant bien le média auquel elles se destinent.</p>
<p>Exemple :<br />
<code>
<link rel="stylesheet" type="text/css" href="style-ecran.css" media="screen" />
<link rel="stylesheet" type="text/css" href="style-imprimante.css" media="print" />
</code></p>
<p><strong>La typo</strong></p>
<p>Certaines polices de caractères sont plus agréables à l&rsquo;écran que d&rsquo;autres. De la même manière, une police de caractère peut être désagréable ou moins « jolie » une fois imprimée. On peut donc utiliser la feuille de style d&rsquo;impression pour changer de typo.<br />
Les typo à empâtement, par exemple, sont très fréquentes sur support papier alors qu&rsquo;elles le sont moins sur écran.<br />
Il faut aussi penser à adapter la taille des caractères.</p>
<p>Exemple :<br />
<code>body <em><br />
font: 10pt Times New Roman, serif;<br />
</em></code></p>
<p><strong>Les liens</strong></p>
<p>Les liens de navigation interne n&rsquo;ont plus d&rsquo;intérêt sur une feuille imprimée. On peut donc, dès le début, prévoir une classe spécifique à appliquer sur tous ces liens. Ainsi, on peut faire disparaître, par exemple, le sousligné sur les liens type « &#8230;que vous trouverez sur la page Recherche ».</p>
<p>Les liens externes, eux, sont certainement des liens qui continuent à avoir un sens hors du site.</p>
<p>CSS2 permet d&rsquo;afficher l&rsquo;adresse d&rsquo;un lien après celui-ci. C&rsquo;est très intéressant pour une feuille de style d&rsquo;impression puisque, sur papier, impossible de cliquer. Sans cette possibilité, l&rsquo;information principale du lien (l&rsquo;adresse) est perdue.<br />
Ne soyez pas déçus, néanmoins, si vous imprimez avec Internet Explorer : cette fonction n&rsquo;est pas encore implémentée. Cela ne générera pas d&rsquo;erreur &#8230; mais cela n&rsquo;affichera pas l&rsquo;adresse internet non plus !</p>
<p>Exemple :<br />
<code>a.navigationInterne <em><br />
text-decoration: none;<br />
</em><br />
a:after <em><br />
content: " (" attr(href) ") ";<br />
font-size: 0.9em;<br />
</em><br />
a.navigationInterne:after <em><br />
content: "";<br />
</em></code></p>
<p><strong>Les couleurs et les images de fond</strong></p>
<p>Les couleurs de fond peuvent avoir de gros inconvénients, une fois sur papier.<br />
Elles peuvent, dans certains cas, gêner la lisibilité (plus que sur écran où le contraste n&rsquo;est pas le même).</p>
<p>C&rsquo;est encore plus vrai pour les images de fond qui peuvent être jolies et sans effet gênant sur un écran mais poser des problèmes de contraste à la lecture sur papier.</p>
<p>Couleurs de fond et images de fond peuvent aussi utiliser beaucoup d&rsquo;encre pour un effet graphique mineur. L&rsquo;internaute apprécierait qu&rsquo;un site ait pensé à lui éviter le problème.<br />
Cette fonctionnalité est d&rsquo;ailleurs déjà implémentée par défaut dans certains navigateurs.</p>
<p>Attention, en enlevant les couleurs de fond, à ne pas se retrouver avec un texte illisible. Si un texte jaune, par exemple, était très lisible sur son fond noir, une fois la couleur de fond enlevée, le jaune sur le blanc de la feuille sera très difficile à lire. Il convient d&rsquo;adapter la couleur du texte à tout changement de couleur de fond.</p>
<p>Exemple :<br />
<code>p <em><br />
background: none;<br />
color: #000;<br />
</em></code></p>
<p><strong>Les marges, les espacements</strong></p>
<p>L&rsquo;aération d&rsquo;une page imprimée n&rsquo;est pas la même que pour une page web.<br />
Il sera alors peut-être nécéssaire de revoir les marges, notamment horizontale, sur votre feuille d&rsquo;impression.<br />
Pensez que l&rsquo;internaute sera déçu s&rsquo;il doit imprimer sur 2 pages avec une marge de 4 cm un texte qui tiendrait sur 1 en utilisant simplement toute la largeur de la feuille.</p>
<p>Adaptez les espacements entre les éléments au média. Les titres n&rsquo;ont pas forcément besoin d&rsquo;être autant espacés de leur texte sur une version papier qu&rsquo;à l&rsquo;écran.</p>
<p><strong>Les sauts de page</strong></p>
<p>Rien de plus désagréable pour un internaute qu&rsquo;une page sur laquelle n&rsquo;a été imprimée qu&rsquo;une seule ligne, qu&rsquo;un paragraphe dont les derniers mots sont sur la page suivante, qu&rsquo;un titre qui n&rsquo;est pas immédiatement suivi par, au moins, la première ligne de son paragraphe, ou qu&rsquo;une image dont la légende a été imprimée sur la page suivante, etc.<br />
Les styles d&rsquo;impression permettent de gérer tout ça. Analysez bien vos pages pour voir quels sont les coupures à éviter. Attention à ne pas tomber dans l&rsquo;excès inverse et de faire des coupures partout : l&rsquo;internaute n&rsquo;appréciera pas non plus de devoir imprimer trop de pages.</p>
<p>Les propriétés à utiliser :<br />
&#8211; page-break-before (gestion du saut de page avant l&rsquo;élément)<br />
&#8211; page-break-after  (gestion du saut de page après l&rsquo;élément)<br />
&#8211; orphans (gestion des lignes seules en bas de page)<br />
&#8211; widows (gestion des lignes seules en haut de page)</p>
<p>Exemple :<br />
<code>h1, h2, h3, h4, h5, h6 <em><br />
page-break-after:avoid;<br />
</em><br />
p <em><br />
orphans: 2;<br />
</em></code></p>
<p>Dans l&rsquo;exemple ci-dessus, aucun saut de page ne sera fait après un titre hn et aucun début de paragraphe ne sera imprimé avec moins de deux lignes en bas de page.</p>
<p><strong>Les zones inutiles</strong></p>
<p>Certaines zones très courantes sur un site web sont néanmoins inutiles sur une version imprimée.<br />
C&rsquo;est le cas par exemple du menu. L&rsquo;internaute qui imprime une page n&rsquo;a plus besoin, quand il voudra relire sa page, d&rsquo;avoir dans sa lecture tous les items du menu imprimés.</p>
<p>Un formulaire n&rsquo;a également plus de sens sur une feuille imprimée (sauf, bien-sûr, les formulaires fait pour l&rsquo;impression).<br />
Il n&rsquo;est pas forcément utile que le formulaire soit encore visible sur une page contact, par exemple, qui aurait été imprimée pour garder une trace du numéro de téléphone, de l&rsquo;adresse, etc.</p>
<p>Les liens tels que « Retour à l&rsquo;accueil » peuvent aussi être évité sur une feuille d&rsquo;impression. Il faut identifier ces liens et leur assigner une classe particulière pour pouvoir les retirer lors de l&rsquo;impression.</p>
<p>Exemple :<br />
<code>#menu, #piedDePage, form, #retourHautPage <em><br />
display: none;<br />
</em><br />
.lienNonImprime <em><br />
display: none;<br />
</em><br />
</code></p>
<p><strong>Les informations perdues</strong></p>
<p>En supprimant le menu, en ayant pas la barre d&rsquo;adresse imprimée, certaines informations se retrouvent « hors de la page web ».<br />
L&rsquo;internaute retrouve souvent ce type d&rsquo;information imprimée en en-tête et pied-de-page (avec la date, parfois le titre&#8230;) en fonction de son navigateur et de sa configuration.<br />
Mais le webmaster n&rsquo;a pas la main sur ces informations.</p>
<p>Pour palier à cela, on peut concevoir, sur chacune des pages, une zone qui ne sera pas visible pour les écrans mais qui le sera à l&rsquo;impression.<br />
Cette zone reprendrait des informations telles que le titre du site, son URL, des informations importantes qui pourrait manquer au lecteur de la page imprimée (l&#8217;email du webmaster, par exemple).</p>
<p>Exemple :<br />
Sur la feuille de style pour écran :<br />
<code><br />
#infosImpression <em><br />
display: none;<br />
</em><br />
</code></p>
<p>Sur la feuille de style pour imprimante:<br />
<code><br />
#infosImpression <em><br />
display: block;<br />
</em><br />
</code></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Jouer avec AJAX I/III</title>
		<link>https://www.magazine-jeux.com/jouer-avec-ajax-i-iii/</link>
		
		<dc:creator><![CDATA[Jean-François Renauld]]></dc:creator>
		<pubDate>Mon, 28 Aug 2006 05:02:00 +0000</pubDate>
				<category><![CDATA[Intégration]]></category>
		<guid isPermaLink="false">https://www.magazine-jeux.com/jouer-avec-ajax-i-iii/</guid>

					<description><![CDATA[Le but de cette série de trois articles est de vous permettre d&#8217;introduire une pincée d&#8217;Ajax dans vos jeux. Nous commencerons par voir quels sont les avantages que l&#8217;on peut espérer de cette technique. Nous passerons ensuite en revue une (parmi d&#8217;autres) vision de l&#8217;implémentation d&#8217;Ajax. Enfin, le dernier article se penchera sur les frameworks [&#8230;]]]></description>
										<content:encoded><![CDATA[<p class="post_excerpt">Le but de cette série de trois articles est de vous permettre d&rsquo;introduire une pincée d&rsquo;Ajax dans vos jeux. Nous commencerons par voir quels sont les avantages que l&rsquo;on peut espérer de cette technique. Nous passerons ensuite en revue une (parmi d&rsquo;autres) vision de l&rsquo;implémentation d&rsquo;Ajax. Enfin, le dernier article se penchera sur les frameworks disponibles actuellement sur le net.</p>
<p><span id="more-130"></span></p>
<h2> <strong>Intro</strong> </h2>
<p>Ajax, Web 2.0, la mode est à l&rsquo;asynchrone &#8230; Ajax est-il incontournable ? Est-il véritablement intéressant d&rsquo;utiliser Ajax comme méthode d&rsquo;échange d&rsquo;information dans le cadre du développement d&rsquo;un jeu ?</p>
<h2> <strong>Petits rappels</strong> </h2>
<p>AJAX, pour Asynchronous JavaScript and XML est une technique de développement web qui vise à rendre les pages plus ergonomiques. L&rsquo;objectif est de donner une sensation de réponse instantanée à l&rsquo;utilisateur. Le principe de base est terriblement simple : échanger de faibles quantités d&rsquo;information via un appel asynchrone &#8211; et en général grâce à du code XML, entre le client et le serveur.</p>
<p>Quand on parle d&rsquo;Ajax, on entend trois choses:</p>
<ol>
<li>L&rsquo;utilisation intensive de JavaScript</li>
<li>L&rsquo;utilisation de l&rsquo;objet XMLHttpRequest</li>
<li>L&rsquo;utilisation du langage XML pour le transfert des informations</li>
</ol>
<p>Les puristes ajouteront un soupçon de XSLT pour le rendu, mais ce sont des puristes 😉</p>
<p>Vous l&rsquo;aurez tous compris, Ajax, comme le DHTML, n&rsquo;est pas une technologie en soi, c&rsquo;est le fait d&rsquo;utiliser un groupe de technologie ensemble dans un but précis.</p>
<p>Utiliser Ajax a des avantages : meilleure gestion de la bande passante, interactivité améliorée, hype pour n&rsquo;en citer que quelque uns. Cette technique a aussi des inconvénients : diminution de l&rsquo;accessibilité, mise en péril de l&rsquo;ergonomie à laquelle l&rsquo;utilisateur est habitué, temps de réponses non maîtrisés et principe de l&rsquo;asynchronisme généralement mal assimilés par les programmeurs débutants. </p>
<h2> <strong>Mise en situation</strong> </h2>
<p>Mettons-nous dans la peau d&rsquo;un webmaster lambda. Il développe son premier jeu. Pour simplifier notre propos considérons que son jeu ne compte que trois éléments: des pages plutôt statiques, comme des news, un classement, ou une FAQ. Des pages plutôt dynamiques, comme une carte. Et des pages composées presque exclusivement de formulaires, comme l&rsquo;administration de compte ou le passage d&rsquo;ordres.</p>
<p>Comment juger de l&rsquo;intérêt d&rsquo;une technologie ? En dehors de l&rsquo;aspect subjectif « j&rsquo;implémente parce que j&rsquo;en ai envie » ou « parce que ça m&rsquo;amuse », mesurons le degré d&rsquo;intérêt en fonction de trois critères : l&rsquo;ergonomie, les performances et la simplicité.</p>
<p><strong>Valeur ajoutée à l&rsquo;ergonomie générale</strong><br />
Comment l&rsquo;utilisateur va t-il percevoir ce changement ? Va-t-il avoir la sensation que les « performances » de l&rsquo;interface sont améliorées ? Va-t-il disposer de nouvelles fonctionnalités qui s&rsquo;intègrent harmonieusement avec le reste, avec les fonctions par défaut de son navigateur (par exemple avec le bouton Back) ?</p>
<p>Supposons que notre webmaster n&rsquo;affiche que 5 news. Il pourrait vouloir proposer un lien « Voir les news suivantes », ou un accès aux « archive » avec un calendrier. Sans Ajax le principe est simple, on ajoute un paramètre au script qui affiche la page et on rafraichi la totalité de la page. Avec Ajax on économise l&rsquo;appel à ce script. On ne rafraichi que le contenu que l&rsquo;utilisateur demande : les news. Il reçoit sa réponse plus vite, sans le « clignotement » de la page qui se rafraîchi. Attention néanmoins à ne pas le dérouter. Il faut que le changement sur la page soit clair,  bien visible. </p>
<p>En ce qui concerne la carte, il est nécessaire de supporter un minimum de scrolling. La solution du rafraîchissement de la page à chaque déplacement est possible, bien sur, mais fort limité tout de même. Sans parler que son jeu aura l&rsquo;air à la traîne techniquement. Quand on parle de scrolling on pense forcement à maintenir un (ou des) buffer(s). Techniquement, Ajax est bien adapté à ce type d&rsquo;utilisation. A tout moment il est possible de déclencher le pré chargement d&rsquo;une partie de la carte de façon invisible. Maintenir le buffer devient plus simple. Le XML se prête aussi à ce type d&rsquo;utilisation. Le buffer deviendra un ou plusieurs node(s) dont on assurera le rendu via une fonction JS qui va bien.</p>
<p>Reste les pages dotées de formulaires. Nous étions habitués à devoir les valider d&rsquo;abord côté client, puis à éventuellement demander une correction à l&rsquo;utilisateur. Depuis fort longtemps nous sommes tous habitué à vérifier nos formulaires une seconde fois côté serveur. Ajax apporte ici deux avantages majeurs : </p>
<ol>
<li>la possibilité de proposer des informations contextuelles (pensez au système d&rsquo;auto-completion de gmail par exemple). </li>
<li>la possibilité de valider le formulaire au fur et à mesure, donnant un feedback plus rapide à l&rsquo;utilisateur, évitant ainsi la frustration du formulaire refusé.</li>
</ol>
<p>Bien sur, ça n&rsquo;exclu pas la vérification côté serveur, mais ici l&rsquo;intérêt en terme d&rsquo;ergonomie est énorme, puisque les formulaires sont partout dans nos jeux.</p>
<p><strong>Gain de performances côté serveur</strong><br />
Que va-t-on gagner en définitive ? On peut estimer le gain en fonction du temps d&rsquo;exécution des scripts. De la répartition des requêtes SQL. Du taux d&rsquo;utilisation moyen des ressources. Mais globalement ce qui nous intéresse c&rsquo;est surtout le temps de réponse du site.</p>
<p>Le serveur n&rsquo;a pas besoin de calculer le rendu de toute la page. Il n&rsquo;effectue le plus souvent qu&rsquo;un seul SELECT, pour récupérer les informations demandées par l&rsquo;utilisateur. L&rsquo;économie ici est triple :</p>
<ol>
<li>On économise sur les SELECT qu&rsquo;aurait effectué le serveur si il avait du rafraîchir toute la page, puisque seules les infos demandées sont rafraîchies</li>
<li>On économise la bande passante : pas besoin de renvoyer tout le code HTML, mais seulement un petit bout de code XML.</li>
<li>On économise sur le rendu : raffinement supplémentaire, le rendu peut-être délégué à une fonction JS, autant d&rsquo;économie en temps d&rsquo;exécution PHP.</li>
</ol>
<p>Ceci dit Ajax peut avoir un effet pervers : la multiplication des requêtes. Il est tentant par exemple d&rsquo;effectuer un rafraîchissement automatique par polling. Une aide contextuelle dans un formulaire utilisé pour chaque passage d&rsquo;ordre signifie une requête au serveur web (et potentiellement une requête SQL) à chaque fois. Si la solution peut-être envisageable attention aux ressources qu&rsquo;elle requiert.</p>
<p><strong>Simplicité de mise en œuvre</strong><br />
Est-il aisé d&rsquo;implémenter cette solution ? Est-il plus aisé de continuer à utiliser les techniques habituelles de DHTML ? Pourra-t-on la maintenir facilement ? Pourra-t-on facilement l&rsquo;améliorer ? Considérons pour le moment que notre MJ ne se base pas sur un framework existant.</p>
<p>Soyons réaliste, non Ajax n&rsquo;est pas simple à mettre en œuvre. Il demande une certaine expérience du développement web, sans doute plus que le DHTML à son époque. Il demande également une grande rigueur dans le code. Il est souvent nécessaire de jongler avec les éléments via leur id&rsquo;s, de pouvoir modifier le contenu à la volée, en respectant le look&#038;feel du site, d&rsquo;où le besoin intensif de CSS. Ajax nécessite aussi de bien comprendre le concept d&rsquo;asynchronisme, d&rsquo;en connaître les limites et les risques.</p>
<h2> <strong>Conclusions</strong> </h2>
<p>Nous approfondirons les points abordés dans la suite, mais d&rsquo;ores et déjà une réponse s&rsquo;impose : oui, Ajax peut nous être utile. Le gain d&rsquo;ergonomie peut-être énorme : assistance au remplissage des formulaire, aide contextuelle, réactivité accrue, meilleure gestion des cartes, autant de domaine ou Ajax excelle. La mise en place demande tout de même un minimum de réflexion. Où l&rsquo;appliquer, tout d&rsquo;abord. Quel sera l&rsquo;impact sur les performances du serveur ? Enfin, la conception même du jeu devra évoluer, on pourra dans un premier temps se contenter d&rsquo;intégrer Ajax à l&rsquo;existant, mais pour en tirer vraiment partit il faudra souvent repasser par la case développement. Stay tuned et rendez vous dans le numéro 2&#8230;</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Réussir ses liens</title>
		<link>https://www.magazine-jeux.com/reussir-ses-liens/</link>
		
		<dc:creator><![CDATA[Jean-François Renauld]]></dc:creator>
		<pubDate>Mon, 10 Apr 2006 03:37:00 +0000</pubDate>
				<category><![CDATA[Intégration]]></category>
		<guid isPermaLink="false">https://www.magazine-jeux.com/reussir-ses-liens/</guid>

					<description><![CDATA[Que ce soit en matière d&#8217;ergonomie, d&#8217;accessibilité ou de référencement, il y a une manière de réussir ses liens, internes ou venant de l&#8217;exterieur, pour qu&#8217;ils soient efficaces. L&#8217;apparence Pour que votre site soit fonctionnel, les liens doivent être immédiatement reconnus comme tels. Ils doivent donc impérativement se différencier du texte normal. L&#8217;usage veut que [&#8230;]]]></description>
										<content:encoded><![CDATA[<p class="post_excerpt">Que ce soit en matière d&rsquo;ergonomie, d&rsquo;accessibilité ou de référencement, il y a une manière de réussir ses liens, internes ou venant de l&rsquo;exterieur, pour qu&rsquo;ils soient efficaces.</p>
<p><span id="more-97"></span></p>
<h2>L&rsquo;apparence</h2>
<p>Pour que votre site soit fonctionnel, les liens doivent être immédiatement reconnus comme tels. Ils doivent donc impérativement se différencier du texte normal.<br />
L&rsquo;usage veut que le lien soit souligné et bleu. Si la majorité des sites s&rsquo;affranchissent du bleu (créant ainsi un apprentissage de l&rsquo;internaute), le soulignement reste encore un repère utile.<br />
Il est d&rsquo;ailleurs fortement déconseillé d&rsquo;utiliser le soulignement pour autre chose que les liens hypertextes. L&rsquo;effet en est TRES perturbateur.</p>
<p>Si on décide de se passer du soulignement, il faut lui substituer un autre repère visuel.<br />
C&rsquo;est le cas, par exemple, des menus qui sotn souvent présentés de telle sorte qu&rsquo;ils n&rsquo;ont pas besoin d&rsquo;être souligné. C&rsquo;est aussi le cas des boutons dans lesquels on reconnaît immédiatement une action à faire.</p>
<p>Pour plus de fonctionnalité, les CSS peuvent vous aider à donner des repères supplémentaires en fonction des actions (survol du lien, liens déjà vus, etc).</p>
<h2>Le libellé</h2>
<p>Il faut le soigner à plusieurs niveaux. D&rsquo;abord, parce que c&rsquo;est ce qui va -ou non- insciter l&rsquo;internaut à cliqurer. Vos liens mis en valeur comme vu dans le paragraphe « L&rsquo;apparence », il est possible que l&rsquo;oeil de l&rsquo;internaute ballaye le page, entre autres, de liens en liens.</p>
<p>Le libelé doit donc être clair et explicite. Evitez les liens trop génériques et, si vous optez quand même pour un lien type « En savoir plus », n&rsquo;oubliez pas de préciser de quoi vous parler : « En savoir plus sur le livre L&rsquo;ignorance de Milan Kundera ».</p>
<p>Les moteurs d&rsquo;indexation sont également très sensibles aux libelés des liens. Si vous pensez à rédiger un lien parlant, il auta de grandes chances de contenir des mots-clé, très utiles pour votre référencement naturel.</p>
<p>Pour un lien d&rsquo;action, utilisez un berbe à l&rsquo;infinitif qui décrit bien l&rsquo;effet induit par le clic. Exemple : « Valider mon choix ».</p>
<p>Attention, par contre, à éviter les libelés trop longs. Le lien doit être explicite en lui-même. Pour qu&rsquo;il puisse être un bon repère pour l&rsquo;internaute, il est préférable qu&rsquo;il ne fasse que quelques mots.</p>
<p>De plus, les règles d&rsquo;accessibilité préconisent moins de 80 caractères par liens.</p>
<h2>L&rsquo;attribut « title »</h2>
<p>Il n&rsquo;est pas un élément obligatoire, mais il apporte plusieurs avantages.</p>
<p>En premier lieu, il vous permet de (et il doit) donner des information supplémentaires à l&rsquo;internaute. Sur le type d&rsquo;ouverture (« Nouvelle fenêtre »), sur le poid à charger (« format .pdf &#8211; 53k) ou des renseignements plus précis (« Lire la fiche de lecture : Le Petit Prince d&rsquo;Antoine de Saint-Exupéry » sur un lien « Le Petit Prince »), etc.</p>
<p>Cela peut être l&rsquo;occasion de renforcer votre référencement naturel : densité des mots-clé ou couverture du champ lexical.</p>
<p>Pour finir, ces informations supplémentaires sont également très utiles en terme d&rsquo;accessibilité. Là aussi, il ne faut pas dépasser 80 caractères.</p>
<h2>Le lien entrant</h2>
<p>Avoir d&rsquo;autres sites qui font un lien vers le votre est une très bonne chose (surtout si la page qui vous cite traîte d&rsquo;un sujet connexe). Cela augmente, bien sûr, vos chances d&rsquo;être trouvé par l&rsquo;internaute et c&rsquo;est bon pour le référencement naturel.<br />
Si vous ne pouvez agir que rarement sur l&rsquo;apparence des liens chez un site partenaire qui fait un lien vers vous, veille par contre à la qualité du libelé et à la présence de l&rsquo;attribut « title ».</p>
<p>Dans le cas d&rsquo;un partenariat rémunéré, un repère modifie l&rsquo;URL afin de savoir que le lien a été cliqué. Certaines méthodes sont mauvaises pour le référencement car elles empêchent les robots d&rsquo;indexation d&rsquo;enregistrer correctement le lien. C&rsquo;est donc également un aspect à surveiller lors d&rsquo;un partenariat.</p>
<p>Les liens, par leur rôle spécifiques au web &#8211; et par leur importance dans le référencement naturel &#8211; méritent la plus grande attention. pour un Internet plus riche et plus pertinent.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Les différentes unités de mesure</title>
		<link>https://www.magazine-jeux.com/les-differentes-unites-de-mesure/</link>
		
		<dc:creator><![CDATA[Jean-François Renauld]]></dc:creator>
		<pubDate>Mon, 13 Feb 2006 06:00:00 +0000</pubDate>
				<category><![CDATA[Intégration]]></category>
		<guid isPermaLink="false">https://www.magazine-jeux.com/les-differentes-unites-de-mesure/</guid>

					<description><![CDATA[Il est bon de faire un petit rappel concernant les différentes unités de mesures qui existent lors de la création d&#8217;une page web. Même si vous utilisez souvent, voir tout le temps, le pixel comme unité de mesure dans vos feuilles de styles, sachez qu&#8217;il en existe d&#8217;autres et que le pixel n&#8217;est pas la [&#8230;]]]></description>
										<content:encoded><![CDATA[<p class="post_excerpt">Il est bon de faire un petit rappel concernant les différentes unités de mesures qui existent lors de la création d&rsquo;une page web.</p>
<p><span id="more-68"></span><br />
Même si vous utilisez souvent, voir tout le temps, le pixel comme unité de mesure dans vos feuilles de styles, sachez qu&rsquo;il en existe d&rsquo;autres et que le pixel n&rsquo;est pas la mesure forcément la plus recommandée.<br />
&#8211; Et nous allons voir pourquoi.</p>
<h2>Deux sortes d&rsquo;unités</h2>
<p>Il existe en fait deux sortes d&rsquo;unités :</p>
<p><strong>les unités dites absolues</strong></p>
<p>Les unités absolues sont données en fonction d&rsquo;un axe imaginaire situé en haut et à gauche de l&rsquo;objet parent, par exemple la fenêtre de navigation.</p>
<table>
<tbody>
<tr class='row_even'>
<td> <strong>Unité</strong> </td>
<td> <strong>Informations</strong> </td>
</tr>
<tr class='row_odd'>
<td> cm </td>
<td> Centimètres. </td>
</tr>
<tr class='row_even'>
<td> mm </td>
<td> Millimètres </td>
</tr>
<tr class='row_odd'>
<td> in </td>
<td> Inches (pouces en français, soit 2.54cm) </td>
</tr>
<tr class='row_even'>
<td> pt </td>
<td> Point. Ne pas confondre avec les pixels. C&rsquo;est la valeur que l&rsquo;on retrouve dans les « point par pouce » ou « dot per inch » (dpi). Utilisé en imprimerie </td>
</tr>
<tr class='row_odd'>
<td> pc </td>
<td> picas. Utilisé également en imprimerie </td>
</tr>
</tbody>
</table>
<p>Attention : ces unités ne permettent pas d&rsquo;obtenir un résultat similaire sur plusieurs écran. En effet, 1 centimètre sur un écran de 14 pouces n&rsquo;a rien à voir avec le « même » centimètre sur un écran de 21 pouces.</p>
<p>En revanche, vous pouvez (devez) les utiliser dans vos feuilles de styles réservées à l&rsquo;impression.</p>
<p><strong>les unités dites relatives</strong></p>
<p>Les unités relatives peuvent être négatives puisqu&rsquo;elles expriment une mesure en rapport à une valeur de référence.</p>
<table>
<tbody>
<tr class='row_even'>
<td> <strong>Unité</strong> </td>
<td> <strong>Informations</strong> </td>
</tr>
<tr class='row_odd'>
<td> px </td>
<td> Pixels. On défini sa taille par 72 ou 96 pixels par pouce pour un écran </td>
</tr>
<tr class='row_even'>
<td> em </td>
<td> Par rapport à la hauteur d&rsquo;une police. 1em = 100% de la taille en cours, 1.4 = 140%, 0.6 = 60% </td>
</tr>
<tr class='row_odd'>
<td> ex </td>
<td> Idem à em, mais pas suffisament implémenté pour être utilisé </td>
</tr>
<tr class='row_even'>
<td> % </td>
<td> Pourcentage. Par rapport à l&rsquo;objet parent </td>
</tr>
</tbody>
</table>
<p>L&rsquo;unité « ex » exprime une mesure dont le point de référence est la hauteur des minuscules de la police courante.</p>
<h2>Et maintenant, je fais quoi ?</h2>
<p>Il est donc fortement conseillé d&rsquo;utiliser l&rsquo;unité <strong>em</strong> pour les tailles de textes.</p>
<p>Pour les élements graphiques, le pourcentage est fortement conseillé. Et les pixels pour positionner des éléments précisément sur un écran.</p>
<p>Les unités <strong>cm</strong> et <strong>mm</strong> sont à proscrire pour l&rsquo;écran, mais à utiliser pour l&rsquo;imprimante.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>HTML Validator</title>
		<link>https://www.magazine-jeux.com/html-validator/</link>
		
		<dc:creator><![CDATA[Jean-François Renauld]]></dc:creator>
		<pubDate>Mon, 06 Feb 2006 06:16:00 +0000</pubDate>
				<category><![CDATA[Intégration]]></category>
		<guid isPermaLink="false">https://www.magazine-jeux.com/html-validator/</guid>

					<description><![CDATA[Les normes Vous connaissez sans aucun doute le W3C et toute les normes qui en sort. Et vous savez très certainement que nos pages internet doivent répondrent à certains critères afin qu&#8217;elles s&#8217;affichent correctement quelque soit le navigateur utilisé. Pour tester vos pages, vous avez évidement les outils proposés par le W3C. Vous pouvez notament [&#8230;]]]></description>
										<content:encoded><![CDATA[<h2>Les normes</h2>
<p>Vous connaissez sans aucun doute le W3C et toute les normes qui en sort. Et vous savez très certainement que nos pages internet doivent répondrent à certains critères afin qu&rsquo;elles s&rsquo;affichent correctement quelque soit le navigateur utilisé.</p>
<p>Pour tester vos pages, vous avez évidement les outils proposés par le W3C. Vous pouvez notament contrôler vos pages ici : <a href="http://validator.w3.org/">http://validator.w3.org/</a></p>
<p>Vous indiquez l&rsquo;URL de la page à contrôler et vous aurez le résultat aussitôt. En vert, c&rsquo;est ok. En rouge : il va falloir revoir certaines choses.<br />
<br />Si vous avez testé ce validateur, vous aurez remarqué comme il est très compliqué de mettre au point des pages valident. Les erreur annoncées ne sont pas toujours très claires et sont, bien souvent, dépendantes d&rsquo;autres erreurs.</p>
<p>Au passage, vous pouvez placer ce lien sur vos pages : <a href="http://validator.w3.org/check?uri=referer">http://validator.w3.org/check?uri=referer</a><br />
<br />Ceci vous permet de tester directement la qualité de vos pages.</p>
<h2>Encore plus simple !</h2>
<p>Firefox arrive comme un grand dans le monde des navigateurs en proposant tout plein de petites extensions permettant d&rsquo;améliorer la navigation, mais également le développement de pages en ajoutant des outils d&rsquo;aide aux développeurs.</p>
<p><img loading="lazy" decoding="async" class=" aligncenter size-full wp-image-76" src="https://www.magazine-jeux.com/wp-content/uploads/2006/02/non-valide.gif" alt="non-valide.gif" align="center" width="339" height="162" /></p>
<p>HTML Validator est donc une extension de Firefox qui vous permet d&rsquo;un simple coup d&rsquo;oeil de contrôler la validité de vos pages en indiquant (en bas à droite)</p>
<p>Une extension vraiment pratique qui vous fera gagner un temps précieux. En cliquant sur l&rsquo;icône en bas à droite de Firefox, vous aurez alors une page avec le code source et l&rsquo;explication (plus ou moins claire) de l&rsquo;erreur.</p>
<p><img loading="lazy" decoding="async" class=" aligncenter size-full wp-image-77" src="https://www.magazine-jeux.com/wp-content/uploads/2006/02/valide.gif" alt="valide.gif" align="center" width="264" height="146" /></p>
<p>Malheureusement, vous constaterez amèrement que certaines régies publicitaires ne respectent pas toujours les standards et génèrent de ce fait des erreurs que vous ne pourrez pas corriger (cas de <a href="article 22">Google AdSense</a> par exemple).</p>
<p>HTML Validator pour Firefox est <a href="https://addons.mozilla.org/extensions/moreinfo.php?application=firefox&#038;category=Developer%20Tools&#038;numpg=10&#038;id=249">disponible ici</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Ne confondons plus alt et title</title>
		<link>https://www.magazine-jeux.com/ne-confondons-plus-alt-et-title/</link>
		
		<dc:creator><![CDATA[Jean-François Renauld]]></dc:creator>
		<pubDate>Mon, 26 Dec 2005 06:00:00 +0000</pubDate>
				<category><![CDATA[Intégration]]></category>
		<guid isPermaLink="false">https://www.magazine-jeux.com/ne-confondons-plus-alt-et-title/</guid>

					<description><![CDATA[De nombreux intégrateurs -y compris parmi les professionnels- n&#8217;utilisent pas correctement les attributs alt et title. La confusion vient aussi certainement du fait que Internet Explorer ne les interprête pas correctement. L&#8217;attribut alt L&#8217;attribut alt est fait pour accueillir un contenu alternatif. Il sera utilisé par le navigateur, par l&#8217;agent utilisateur en général, au cas [&#8230;]]]></description>
										<content:encoded><![CDATA[<p class="post_excerpt">De nombreux intégrateurs -y compris parmi les professionnels- n&rsquo;utilisent pas correctement les attributs alt et title.<br />
La confusion vient aussi certainement du fait que Internet Explorer ne les interprête pas correctement.</p>
<p><span id="more-33"></span></p>
<h2>L&rsquo;attribut alt</h2>
<p>L&rsquo;attribut alt est fait pour accueillir un contenu alternatif. Il sera utilisé par le navigateur, par l&rsquo;agent utilisateur en général, au cas où il ne pourrait pas lire l&rsquo;élément, une image par exemple.</p>
<p>Dans une page web, un certains nombre d&rsquo;éléments peuvent ne pas être accessible au navigateur, à l&rsquo;agent utilisateur. Les images, par exemple, ne sont bien évidement pas « lues » par un navigateur vocal ou si un internaute, en bas débit par exemple, a décidé de désactiver les images.<br />
Cela peut-être le cas des applets, des objets, des images ; en fait, de tous les éléments graphiques.</p>
<p>Pour que les internautes ne perdent pas pour autant l&rsquo;information, on fournit à l&rsquo;agent utilisateur une alternative textuelle. Elle a pour but d&rsquo;indiquer à l&rsquo;internaute le contenu de l&rsquo;applet, de l&rsquo;objet, de l&rsquo;image.</p>
<p>Exemple [[Les exemples sont donnés en XHTML]] :<br />
<code><img decoding="async" src="images/logo.gif" alt="Logo de Game On Net" /></code></p>
<p>Tous les objets graphiques doivent fournir une information alternative.<br />
Dans le cas d&rsquo;une image purement décorative, l&rsquo;attribut alt peut être laissé vide, mais doit être présent.</p>
<p>Exemple :<br />
<code><img decoding="async" src="images/decor-rubrique.jpg" alt="" /></code></p>
<p>Le contenu du alt doit faire 60 caractères maximum (un caractère encodé vaut pour un).</p>
<p>Si l&rsquo;objet, par contre, fournit de nombreuses informations, qu&rsquo;il est impossible ou réducteur de le résumer dans un alt, on utilise alors en complément l&rsquo;attribut longdesc qui fait appel à un fichier de description plus complet.</p>
<p>Exemple :<br />
<code><img decoding="async" src="images/graphique.gif" alt="Statistiques du site" longdesc="graphique.txt" /></code></p>
<h2>L&rsquo;attribut title</h2>
<p>L&rsquo;attribut title (non la balise title contenue dans le head et qui apparaît dans la barre de titre du navigateur) est le titre d&rsquo;un élément.</p>
<p>Il peut être présent pour une image.</p>
<p>Exemple :<br />
<code><img decoding="async" src="images/ventes-2005.jpg" alt="Graphique" title="Evolution des ventes de 2005" longdesc="ventes2005.txt" /></code></p>
<p>Il est également attendu sur les liens pour fournir une information en plus de celles du libellé.</p>
<p>Exemple :<br />
<code><a href="http://www.site.com/accessibilite.html" title="Lire l'article sur l'accessibilité sur Site">L'accessibilité</a><br />
</code></p>
<p>Si nous reprennons  l&rsquo;exemple du logo, nous pourrions avoir :<br />
<code><a href="index.html" title="Game On Net - Accueil"><img decoding="async" src="images/logo.gif" alt="Logo Game On Net" /></a></code></p>
<p>L&rsquo;information données par l&rsquo;attribut title est destinée à tous les types de navigateurs et fournis dons un texte visible par tous.<br />
Le texte d&rsquo;un title apparaît donc dans les navigateurs classiques dans une petite info-bulle, au survol de l&rsquo;élément.</p>
<p>En cas d&rsquo;absence de title mais de présence de alt, Internet Explorer affiche le contenu du alt dans l&rsquo;info-bulle. Et c&rsquo;est probablement de là qu&rsquo;est née une partie de la confusion entre ces deux éléments et qui a fait que l&rsquo;on trouve encore beaucoup de alt dans des balises a (ce qui n&rsquo;a pas de sens au vu de la fonction du alt).<br />
Si les deux attributs sont présents, Internet Explorer utilise le title en priorité pour son info-bulle.</p>
<p>L&rsquo;attribut title autorise 80 carctères maximum (un caractère encodé vaut pour un).</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Optimiser le poids de sa feuille de style</title>
		<link>https://www.magazine-jeux.com/optimiser-le-poids-de-sa-feuille-de-style/</link>
		
		<dc:creator><![CDATA[Jean-François Renauld]]></dc:creator>
		<pubDate>Fri, 21 Oct 2005 17:44:49 +0000</pubDate>
				<category><![CDATA[Intégration]]></category>
		<guid isPermaLink="false">https://www.magazine-jeux.com/optimiser-le-poids-de-sa-feuille-de-style/</guid>

					<description><![CDATA[La feuille de style externe Plutôt que de mettre tout votre style en interne, dans une page, il faut privilégier la feuille de style externe. plutôt que Le séparteur A la fin d&#8217;une déclaration, on met un « ; ». Le point-virgule est un séparateur, entre deux déclarations, il n&#8217;est donc pas nécessaire de le mettre à [&#8230;]]]></description>
										<content:encoded><![CDATA[<h2>La feuille de style externe</h2>
<p>Plutôt que de mettre tout votre style en interne, dans une page, il faut privilégier la feuille de style externe.</p>
<p><code><link rel="stylesheet" type="text/css" href="votre_feuille_de_style.css" /></code></p>
<p>plutôt que</p>
<p><code></p>
<style>
* <em>font-family: Arial, Helvetica, sans-serif; font-size: medium; color: #ABC</em>
body <em>background: url(images/fond.jpg)</em>
h1 <em>border: solid #DEF; border-width: 0 2px 2px 0; background: #FFFFF0</em>
#footer, #footer a, #footer span <em>font-size: smaller</em>
#footer <em>color: #BDB76B</em>
#footer a <em>color: #562</em>
#footer span <em>margin: 0 5px</em>
</style>
<p></code></p>
<h2>Le séparteur</h2>
<p>A la fin d&rsquo;une déclaration, on met un « ; ».<br />
<br />Le point-virgule est un séparateur, entre deux déclarations, il n&rsquo;est donc pas nécessaire de le mettre à la fin de la dernière déclaration.<br />
<br />Le gain peut parraître minime, mais sur Internet, chaque octet compte.</p>
<p><code>h2 <em>margin-top:20px</em><br />
h3 <em>text-indent:10%</em><br />
p <em>text-align: justify</em></code></p>
<p>plutôt que</p>
<p><code>h2 <em>margin-top:20px;</em><br />
h3 <em>text-indent:10%;</em><br />
p <em>text-align: justify;</em></code></p>
<h2>Les couleurs</h2>
<p>La notation hexadécimale des couleurs peut être passée sur 4 caractères au lieu de 7 lorque chacune des trois couleurs est décrite par deux caractères identiques.</p>
<p><code>color:#ABC</code></p>
<p>plutôt que</p>
<p><code>color:#AABBCC</code></p>
<h2>Les unités</h2>
<p>Lorsqu&rsquo;une valeur est à 0, il est inutile de préciser son unité, quelle qu&rsquo;elle soit.</p>
<p><code>margin:0 5em</code></p>
<p>plutôt que</p>
<p><code>margin:0px 5em</code></p>
<h2>Les valeurs par défaut</h2>
<p>Chaque propriété à une valeur par défaut initiale. Inutile, donc, de déclarer le comportement d&rsquo;un élément si celui-ci est déjà par défaut.</p>
<p><code>div <em>border:1px solid #A1F5C3</em></code></p>
<p>plutôt que</p>
<p><code>div <em>position:static; border:1px solid #A1F5C3</em></code></p>
<h2>Les propriétés raccourcies</h2>
<p>(Voir <a href="14">14</a>)</p>
<p>Une même propriété peut, à elle seule, déclarer plusieurs propriétés. Elles sont donc à privilégier fortement ; en plus du gain de poids, elles sont aussi bien plus agréable au développement et à la relecture car elles permettent un code moins verbeux.<a href="http://www.ilovejackdaniels.com/css_cheat_sheet.pdf">[Pour en savoir plus : [CSS Cheat Sheet (pdf &#8211; 379k)</a> de <a href="http://www.ilovejackdaniels.com/">Dave Child</a> ou sa traduction française par <a href="http://goetzilla.info/index.php/">goetzilla</a>: <a href="http://goetzilla.info/ressources/aide-memoire_css.pdf">Aide-mémoire CSS (pdf &#8211; 43k)</a> ]]</p>
<p><code>border: solid #DEF; border-width: 0 2px 2px 0;</code>	</p>
<p>plutôt que </p>
<p><code>border-color: #DDEEFF; border-style: solid; border-left-width: 0px; border-right-width: 2px; border-top-width: 0px; border-bottom-width: 2px;</code></p>
<h2>Les déclarations communes</h2>
<p>Lorsque qu&rsquo;une ou plusieurs déclarations s&rsquo;appliquent à plusieurs éléments, les declarations communes apportent, elles aussi, plusieurs avantages.<br />
Celui du gain de poids, un code moins verbeux, mais aussi une maintenance plus agréable puisqu&rsquo;une même propriété pourra être modifier sur plusieurs éléments, même différents mais tous concernés, d&rsquo;un coup.[[<1>]]</p>
<p><code>#footer, #footer a, #footer span <em>font-size: smaller</em></code></p>
<p>plutôt que</p>
<p><code>#footer <em>font-size: smaller</em><br />
#footer a <em>font-size: smaller</em><br />
#footer span <em>font-size: smaller</em></code></p>
<h2>Les propriétés qui héritent</h2>
<p>Les CSS sont basées sur le système d&rsquo;héritage et un certain nombres de propriétés héritant, il n&rsquo;est pas nécessaire de les re-déclarer dans les éléments enfants.[[<1>]]</p>
<p><code>* <em>font-family: Arial, Helvetica, sans-serif</em></code></p>
<p>plutôt que</p>
<p><code>* <em>font-family: Arial, Helvetica, sans-serif</em><br />
p <em>font-family: Arial, Helvetica, sans-serif</em><br />
a <em>font-family: Arial, Helvetica, sans-serif</em></code></p>
<h2>Les selecteurs qui appartiennent déjà à une classe</h2>
<p>Pour un même groupe, il est parfois inutile de créer une classe pour chaque élément du groupe. Il suffit de faire appel à la classe (ou à l&rsquo;id) du groupe et de préciser quel élément sera touché par la règle.<br />
<br />Si le poids de la feuille de style y gagne, le poids du code HTML en tire également le même bénéfice.</p>
<p><code>#footer <em>color: #BDB76B</em><br />
#footer a <em>color: #562</em><br />
#footer span <em>margin: 0 5px</em></code><br />
et<br />
<code></p>
<div id="footer"><span>Réalisation&nbsp;:</span><a href="ma_page.htm" title="Le site du webmaster">Ma page</a></div>
<p></code></p>
<p>plutôt que </p>
<p><code>#footer <em>color: #BDB76B</em><br />
.footerLiens <em>color: #562</em><br />
.footerTexte <em>margin: 0 5px</em></code><br />
et<br />
<code></p>
<div id="footer"><span class="footerTexte">Réalisation&nbsp;:</span><a class="footerLiens" href="ma_page.htm" title="Le site du webmaster">Ma page</a></div>
<p></code></p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
