Return false

Un blog IT de plus le blog de Hubebert.

Articles taggés avec ‘dev’

gpc

Présentation

Tout pareil que le_poulet j’ai participé à une compète de création de jeu vidéo en une semaine. La mienne, c’était la Game Prototype Challenge. Une compétition sans vainqueur (le défi est juste personnel) à laquelle j’ai participé par pure frustration d’avoir loupé la Global Game Jam à Paris. Les deux thèmes (parce que oui, il y en a deux obligatoires) de la 16° édition étaient :

FOUR COLOURS & ABSORBTION

L'écran artistique

L'écran artistique

Dev

Après une bonne nuit de réflexion je décide de faire un jeu de plateforme avec LÖVE, parce que j’ai vraiment pas d’idées. Un kirby simpliste en 3 couleurs Red Green et Blue. Je décide de ne pas utiliser la librairie physique Box2d,  je trouve ça un peu lourd pour de la collision de plateforme tout conne.

Red Green et Blue, ça fait que 3 couleurs, j’ajoute donc une 4° couleur: le joueur. En avalant des bouboules de couleurs, il modifie sa propre couleur, ce qui donne un côté un peu plus imprévu au graphisme, la dernière couleur évoluant sans cesse.

Je passe le weekend à  procrastiner parce que la réalisation du niveau ne me fait pas envie de tout. Au lieu de faire un level potable j’ajoute 3 mécaniques de jeu: plus on est vert, plus on court vite, plus on est bleu, plus on saute haut, et plus on est rouge, plus on est mort. J’ajoute à ça un paramètre pour que le perso rougisse -meure- à petit feu, et une capacité à “geler” la couleur des plateformes rencontrées pour faire joli.

Rectangle kid

Rectangle kid et ses boules

Résultat: un jeu qui pourrait être sympa s’il n’avait pas un niveau composé que de 4 platformes et une gestion des collisions scandaleuse.

Comme je suis un vilain tricheur j’ai débordé de la semaine du concours pour me construire un éditeur de niveaux et faire un niveau a peu près potable. Rien de bien folichon, mais c’est histoire de faire en sorte qu’une partie dure plus de 25 secondes.

Post-Mortem

Ce que je retiens de ces 25~30H (plus 10 hors compèt’) passées sur ce prototype.

Les bon côtés:

  • ça fonctionne…
  • meh…

Les points à revoir:

  • Finalement, utiliser box2d aurait surement rendu le jeu plus fun, en jouant avec une rotation des plateformes par exemple
  • Penser au level design plus tôt, et s’en préoccuper tout court
  • Prévoir l’intégration des sons dès le départ (je n’ai pas eu le temps d’en mettre du coup)

Download

Si vous voulez tester j’ai mis en ligne différentes versions.

La version portable pour windows (sans installation: unzip, click, play)

La version en .love (pour Linux/MacOS - nécessite LÖVE)

Le code source pour les curieux.

Seed - jeu de gestion végétal

Samedi 2 février 2013

Pas de nouvelle sur le développement depuis un bail, mais le projet est loin d’être mort.

Suite à la suggestion de MrHelmut,  en commentaire de mon article précédent, le jeu s’appellera Seed (et pas Weed, désolé).

Concept du menu

Concept du menu

Team up !

Avec mon appel à l’aide, deux nofragés m’ont proposé leur talents, on va donc avoir une belle production labellisée 100% wefrag. Et 100% pas FPS, cherchez l’erreur… Voici la liste des participants:

- Solentis au graphisme

- Khelben au son

- Moi même au code

C’est fait sur notre temps libre a chacun, donc ça avance à un rythme erratique, selon l’emploi du temps et la motivation, mais ça avance !

On a déjà une version présentable du menu principal et quelques mécaniques de jeu fonctionnelles, que je vais présenter succinctement ici.

Menu

On a commencé par intégrer le menu. Ça laisse libre cours à l’inspiration des artistes pendant que j’ai le temps de débuter le code gameplay. Pour rester dans l’ambiance, le menu prends la forme d’un arbre dont les branches sont les boutons. On en profite pour donner une idée du style graphique du jeu:

YouTube Preview Image

Gameplay

Je vais vous présenter ici le fonctionnement global de l’aspect ressources du jeu. Un arbre nécessite trois choses pour pousser, de l’eau de la terre et de la lumière. On aura donc trois ressources récupérables : eau, lumière et nutriment.

Chaque segment d’un arbre (racine, feuille, branche), consomme des ressources, et la branche est le seul élément à ne pas en récolter. Son rôle est uniquement utilitaire, et sert à atteindre des zones de récolte de lumière plus distantes du sol.

Les nutriments sont une ressource finie  à récolte constante. Plus on connecte de racines aux sources de nutriment, plus on en récolte rapidement. Une fois une zone épuisée, il faut creuser plus profond pour retrouver des nutriments. C’est la ressource qui pousse le joueur à s’étendre pour pouvoir se maintenir en vie.

L’eau est une ressource infinie, à collecte variable. On part du principe que le sol dispose d’un humidité générale, qui varie selon la saison. Elle aura l’occasion de changer à l’occasion de différents évènements, mais j’y reviendrais quand on parlera des évènements. On y ajoute des petites nappes phréatiques (ou waterspots) qui permettent de donner un

La lumière est une ressource infinie à collecte variable, on ne peut en collecter que le jour, et qu’avec les feuilles qui ne sont pas a l’ombre. Pour les espèces a feuilles non persistantes, l’hiver réduira drastiquement la collecte de lumière, de façon à encourager le joueur.

Pistes de réflexion

Pour l’instant il n’y a rien de définitif en terme de gameplay, même si le système de ressources commence à me sembler cohérent. Voici néanmoins quelques pistes de réflexion que je nourris en ce moment, libre a vous lecteur de commenter et de donner votre avis ou vos idées sur les sujet suivants.

  • Utiliser la branche comme stockage. Chaque branche peut contenir des ressources et augmente la quantité maximum qu’on peut conserver.
  • Les nappes phréatiques: les remplir après chaque pluie? Ne jamais les remplir?
  • Faire en sorte que plus une branche a de “filles” plus les feuilles consomment de resources. Ceci afin de forcer le joueur à se débarrasser des feuilles proches du tronc, et de donner à l’arbre un aspect plus réaliste.
  • Trouver un moyen simple et efficace de montrer comment évoluent les ressources. (Augmentation ou diminution) et d’identifier leur source (quelle racine rapporte le plus, et quelle feuille consomme le plus).

Comme toujours, remarques et retours sont appréciés, soit en commentaire, soit par email: hubebert_at_wefrag.com.

Tu as un serveur hébergé chez toi? Une box qui change d’IP quand ça lui chante? Voici une solution pour y pallier.

Cet article fait suite à celui d’ecaheti du 16 Août concernant la configuration de son Raspberry Pi le changement d’IP de sa box.  Il a lui même réalisé une solution expliquée dans son article, mais celle-ci nécessite qu’un moteur PHP tourne sur le Rasp. Bien qu’il éxiste des outils pour gérer ça de façon automatique, il peut être préférable de le faire soi même, c’est pourquoi je propose ici une autre approche, moins gourmande pour le serveur local et plus simple à mettre en place à mon goût.

Voici la configuration d'origine

La configuration d'origine

Ingrédients:

  • Un serveur chez soi (Raspberry ou autre, peu importe)
  • Un serveur web avec PHP (free.fr en fournit gracieusement, ça fait parfaitement l’affaire)
  • Une box permettant le NAT (la redirection des ports)

L'objectif final: mise à jour de l'IP et redirection automatique

L'objectif final: mise à jour de l'IP et redirection automatique

Sur la box:

Rediriger les ports auquels ont veut accéder depuis l’extérieur vers l’adresse IP locale du serveur. Je ne rentrerais pas dans les détails, on trouve de très bons tutos un peu partout pour ça.

Espace Web 1/2 :

Comment connaître l’ip de ma box/mon serveur local?

La meilleure façon de connaître l’IP de mon serveur local est encore de regarder l’adresse d’origine d’une requête allant de mon serveur local à mon espace web.

Pour différencier une requête qui provient d’un visiteur “normal” de celles servant a mettre à jour l’adresse de ma box on va utiliser des variables POST. On va même “sécuriser” ça sous la forme d’un ensemble clé-valeur pour éviter que n’importe qui puisse changer l’IP de référence.
On va ensuite stocker l’IP d’ou provient la requête valide dans un fichier texte. Pour récupérer l’ip d’origine d’une requête en PHP, on utilise la variable $_SERVER["REMOTE_ADDR"]. C’est pratique d’autant plus qu’en ouvrant le fichier avec l’attribut "w+" on ne se préoccupe même pas de l’effacer, le nouveau contenu remplacera toujours l’ancien contenu du dit fichier.

$KEY      =    "le_serveur";
$VALEUR =    "c'est moi!";
$FICHIER =    "ip.txt";

if (isset($_POST[$KEY]) && $_POST[$KEY] === $VALEUR) {
$file = fopen($FICHIER, "w+");
fwrite($file, $_SERVER["REMOTE_ADDR"]);
fclose($file);
}

Voilà pour la partie mise à jour de l’IP côté PHP. Rien de bien méchant. Chaque fois qu’une requête contenant “le serveur=c’est moi” sera envoyée sur ce fichier, le fichier “ip.txt” sera mis à jour avec l’adresse d’origine. Il ne reste plus qu’a le faire régulièrement…

Serveur personnel:

La partie la plus facile. On va demander l’envoi de l’ensemble clé-valeur vers le serveur web. Pour gérer les tâches répétitives on utilise le cron, auquel on ajoute la ligne suivante:

user$: crontab -e #edition du fichier crontab avec votre editeur par défaut

#Ajout d'une ligne pour envoyer la requête toutes les 5 minutes
*/5 * * * * curl --silent -F le_serveur="c'est moi!" http://addresse/de/mon/fichier.php

Espace Web 2/2 :

Revenons à l’espace Web. Pour l’instant, le fichier PHP permet de mettre à jour l’IP de notre auto-hébergement automatiquement, mais si un visiteur arrive sur la page, il ne se passe rien (page blanche). À mon goût, il y a deux trucs sympas a faire pour un visiteur:

  • Une redirection transparente et instantanée vers le serveur local
  • Une liste des services proposés par le serveur local

Option 1: Redirection transparente

Sur le fichier côté serveur on va tout simplement… rediriger le navigateur, d’où le titre ! Pour cela il existe une fonction PHP: header(). Sans rentrer dans les détails, celle-ci ne fonctionnera si elle est utilisée en tête de fichier. Si on veut rediriger, il est important de l’appeler le plus tôt possible. (Typiquement: avant le code HTML s’il y en a). La fonction header prends comme paramètre une chaîne de caractères. Si elle content “location: http://uneurl“, elle va nous rediriger vers une adresse du type: http://uneurl. On déclare donc deux variables en tête de fichier: $PORT et $PROTOCOL.

Port étant le port sur lequel rediriger (par défaut :80 pour le web), et le protocole a utiliser (http://, https:// …). À nouveau je ne vais pas rentrer dans les détails, le port 80 et le http couvrant la majorité des cas.

<?php
$KEY        =    "le_serveur";
$VALEUR     =    "c'est moi!";
$FICHIER    =    "ip.txt";
$PORT       =    ":80";
$PROTOCOL   =    "http://";

if (isset($_POST[$KEY]) && $_POST[$KEY] === $VALEUR) {//Mise à jour de l'ip
$file = fopen($FICHIER, "w+");
fwrite($file, $_SERVER["REMOTE_ADDR"]);
fclose($file);
}else{//Redirection du client
$addresse   =   file_get_contents($FICHIER);
$addresse   =   $PROTOCOL . $addresse . $PORT;
header("location: $addresse");
}
?>

Protip: En PHP, lorsqu’on utilise des guillements doubles, on peut mettre nos variables directement entre les guillements. (Comme dans la ligne 15)

Option 2: Liste des services

Exemple de rendu de la liste de services

Exemple de rendu de la liste de services

On peut tout à fait s’arrêter ici et faire une page d’accueil sur le serveur local, permettant de lister les services dispos. Cependant, dans certains cas, il peut être utile de faire cela directement sur le serveur distant : pour économiser les (maigres) ressources d’un Raspberry Pi par exemple, et éviter d’y faire tourner un PHP juste pour afficher une page.

Pour lister les différents services, on va faire ça “en dur” ou de façon statique, pour éviter de scanner systématiquement tous les ports de votre serveur local à chaque visite. On va donc faire une liste des différents services que procure notre serveur. Cette liste va prendre la  forme d’un tableau associatif contenant le nom du service, et le port sur lequel il est publié.

Voici un exemple pour mon serveur.

$SERVICES    =    Array(
"Pages Web"=>":80",
"Streaming Video"=>":1234",
"Interface web qBittorrent"=>":8112",
"Interface web Transmission"=>":9091"
);

On va ensuite réaliser une boucle qui parcours ce tableau pour nous réaliser une liste au format HTML qu’il nous suffira ensuite d’afficher dans le corps d’une page HTML.

$IP = file_get_contents($FICHIER);
$listeHTML = "<ul>";
foreach($SERVICES as $nom => $port){
$URL = $PROTOCOL . $IP . $port;
$listeHTML .= "<li><a href='$URL'>$nom</a></li>";
}
$listeHTML .= "</ul>";

Pour les fénants, le code de la page HTML entière:


<?php
$KEY        =    "le_serveur";
$VALEUR     =    "c'est moi!";
$FICHIER    =    "ip.txt";
$PORT       =    ":80";
$PROTOCOL   =    "http://";
$SERVICES    =    Array(
"Web"=>":80",
"Streaming"=>":1234",
"qBittorrent"=>":8112",
"Transmission"=>":9091"
);

if (isset($_POST[$KEY]) && $_POST[$KEY] === $VALEUR) {
$file = fopen($FICHIER, "w+");
fwrite($file, $_SERVER["REMOTE_ADDR"]);
fclose($file);
}else{
$IP = file_get_contents($FICHIER);
$listeHTML = "<ul>";
foreach($SERVICES as $nom => $port){
$URL = $PROTOCOL . $IP . $port;
$listeHTML .= "<li><a href='$URL'>$nom</a></li>";
}
$listeHTML .= "</ul>";
}
?>
<!DOCTYPE HTML>
<html lang="en">
<head>
<link href='http://fonts.googleapis.com/css?family=Ubuntu' rel='stylesheet' type='text/css'>
<title>Mon chouette serveur Perso!</title>
<style type="text/css" media="screen">
*{
text-align:center;
}
h1{
font-family:'Ubuntu';
}
ul{
list-style-type:none;
}
</style>
</head>

<body>
<h1>Mon chouette serveur Perso...</h1>
<p>...est à votre disposition, et fournit les services suivants:</p>
<?php echo $listeHTML;?>
</body>
</html>
Voilà, en espérant avoir été clair et que cela resserve à d’autres.
Avec la démocratisation du Raspbery Pi, ce genre de petit script peut éviter des déboires à certains d’entre vous et vous permettre de vous concentrer sur des problèmes plus intérressants.

“Tiens, je me suis fait 0.50€ pendant que j’étais aux toilettes, et déjà 1,54€ depuis mon premier café!”

Regis essayant myTwoCents

Écran de détail d'un compteur

Écran de détail d'un compteur

Après deux ans d’étude et d’inactivité bloguistique je retrouve le courage d’écrire quelque chose.

J’ai découvert récemment le framework jQueryMobile qui m’a paru franchement sympa et m’a donné envie de (re) jouer un peu avec le web mobile. J’ai donc réalisé une petite “webapp” pour l’occasion.

J’ai décidé réécrire un truc que j’adore: le module iGlande sur faineant.com: Une petite appli flash qui remplace le comptage de mouches par le comptage de brouzoufs quand on fout rien au boulot. Le but étant de se réjouir toute la journée en comptant combien on gagne chaque seconde.

Comme c’est du flash, et que mon téléphone n’aime pas ça, c’était l’occasion.

Pour ceux qui veulent essayer et s’amuser 5 minutes c’est par ici, pour les apprentis magiciens qui veulent des détails sur la réalisation, bonne lecture.

Je présente ici la partie stockage des données et calcul des compteurs. Pour plus de lisibilité la partie purement jQueryMobile fera l’objet d’un autre article.



TL;DR: scanne ça pour tester.

TL;DR: scanne ça pour tester.

Cahier des charges

Je veux :

  • savoir combien je gagne en temps réel
  • garder en mémoire les paramètres (compteurs, options…)
  • que mon salaire soit compté même quand je ne suis pas sur le site
  • pouvoir suivre plusieurs compteurs en parallèle (celui de ma femme, de ma dernière sieste et de mon dernier café)

Je ne veux pas:

  • de base de donnée (pas envie de me casser les pieds)
  • que les utilisateur puissent voir les compteurs des autres
  • de login  / mdp

Petite nuance par rapport au module iGlande: je ne compte pas le salaire au 35H, mais en heures réelles, afin que le compteur puisse continuer a tourner la nuit. Ça fait à peu près du 720H/Mois.

Au final, on code que dans 2 fichiers, le reste, c'est des frameworks et des plugins

Au final, on code que dans 2 fichiers, le reste, c'est le framework et les plugins

Les outils

Pour réaliser l’appli je vais utiliser:

  • du jQueryMobile (c’était le but après tout)
  • un plugin jQuery pour gérer les cookies
  • du jQuery tout court
  • un bon IDE et du café

Le stockage des données

Pour ne pas avoir à gérer de base de données et de login/mdp j’ai décidé de stocker les données côté client, dans son navigateur. En me réunissant avec moi même j’ai pensé a deux solutions:

les cookies

Les cookies sont ces sales petits trucs qui se stockent dans votre navigateur lorsque vous visitez des sites. Ça sert aussi bien a cibler la publicité qu’a connaître vos habitudes de surf nocturnes. Typiquement la case “se rappeller de moi” quand vous vous loguez sur un site,  utilise un cookie.

Les plus:

  • Tous les navigateurs les prennent en charge

Les moins:

Tous les navigateurs s’en méfient. Le stockage d’un cookie est effectué pour une durée donnée. Le problème c’est que l’abus de beaucoup de sites a conduit les navigateurs à êtres drastiques avec les cookies. Aucun moyen de savoir si la durée de stockage sera respectée, ou même si le navigateur acceptera de garder les cookies ne serais-ce que 20 secondes après la fermeture de la page.

le localStorage

Le localStorage c’est l’évolution logique du cookie, qui est apparu avec la norme HTML5. C’est encore peu utilisé et peu pris en charge, c’est à la fois un avantage et un inconvénient, les navigateurs et autres logiciels “nettoyeurs de trace” ont moins tendance a supprimer sauvagement le localStorage que les cookies.

Plus:

  • Plus rapide que les cookies
  • Pas de limitation de durée

Moins:

  • Pas géré par tous les navigateurs (notamment mobiles)

Écran principal

L'écran d'accueil

Comme souvent quand il faut choisir, j’ai décidé de prendre les deux solutions. Mon site devra donc regarder si le local Storage est disponible, et si ce n’est pas le cas, utiliser les cookies. Pour cela c’est très simple, le test suivant va nous dire pour le navigateur courant, si le localStorage est utilisable:

if (localStorage) {
debug("J'ai le localStorage");
}else{
debug("Je vais devoir utiliser les cookies...");
}

Maintenant la question des compteurs: comment faire compter un compteur côté client, lorsque que le client n’est pas sur la page?

C’est très simple: on ne peut pas.

On va donc fonctionner différemment. On stocke l’heure de démarrage du compteur, lorsqu’on voudra connaître l’argent gagné depuis, on fera la différence avec l’heure actuelle. En pratique ça donne ça:

On déclare des variables globales en tête de fichier

/**
* Global vars
*/
var debugConsole    =   true;//TODO: affiche les infos dans la console quand vrai, passer a false en prod
//Paramètres
var CURRENCY        =   "&euro;";
var LOCAL_STORAGE   =   false;
var TICK            =   false;
var DISPLAY_BUTTON  =   false;
var NOTIF           =   false;
var NOTIF_CAPABLE   =   false;
var TIMERLAP        =   10;
//Données compteurs
var counterNames    =   Array();
var counterDates    =   Array();
var counterIncomes  =   Array();

Puis on les attribue en fonction de la détection du navigateur:

La dernière ligne de chaque bloc, écrit un texte dans l’écran de config afin d’informer l’utilisateur de la technique de stockage utilisée.

if (localStorage) {
LOCAL_STORAGE   =   true;
CURRENCY        =   localStorage.getItem("CURRENCY")==="true"       ?true:CURRENCY;
TICK            =   localStorage.getItem("TICK")==="true"           ?true:TICK;
DISPLAY_BUTTON  =   localStorage.getItem("DISPLAY_BUTTON")==="true" ?true:DISPLAY_BUTTON;
NOTIF           =   localStorage.getItem("NOTIF")==="true"          ?true:NOTIF;
$("#localStorageStatus").html("Great! Your browser can use localStorage. You maybe won't see the difference, but I will!");
debug(TIMERLAP);
} else {
LOCAL_STORAGE   =   false;
CURRENCY        =   $.cookie("CURRENCY")==="true"       ?true:CURRENCY;
TICK            =   $.cookie("TICK")==="true"           ?true:TICK;
DISPLAY_BUTTON  =   $.cookie("DISPLAY_BUTTON")==="true" ?true:DISPLAY_BUTTON;
NOTIF           =   $.cookie("NOTIF")==="true"          ?true:NOTIF;
$("#localStorageStatus").html("Your browser doens't have a localStorage. Data will be stored in cookies. If they get erased, you'll loose your data");

Du coup, chaque ajout de compteur prendra simplement la forme :

//Lecture des données
var name = $("#counterName").val();
var income = $("#monthIncome").val();
var startDate = new Date().getTime();
//Reset des champs de saisie
$("#counterName").val("");
$("#monthIncome").val("");

//Intégration dans les tableaux de compteurs
counterNames.push(name);
counterDates.push(startDate);
counterIncomes.push(income);
saveCounterValue();

La fonction saveCounterValue() se chargeant simplement de sauvegarder les tableaux au bon endroit selon la valeur de la variable LOCAL_STORAGE vue plus haut.

Ajout d'un compteur

Ajout d'un compteur

Le Calcul

Pour calculer combien d’argent on a gagné on boucle sur chaque compteur. On va alors déterminer la différence entre la date de départ de celui-ci et la date actuelle.

//Calcul de la différence entre maintenant et le début
delta = new Date().getTime() - counterDates[i];
//Conversion du revenu mensuel en revenu milliseconduel

Puis on va réduire un salaire mensuel, à un salaire par milliseconde. On commence par se demander combien vous gagnez par an (pour pouvoir gérer un revenu moyen indépendamment du fait que l’année soit bissextile ou non), pour le diviser ensuite par le nombre de milliseconde d’une année.

function monthlyToMillisecIncome(income){
var DAYS_PER_YEAR       =   365.25;
var MONTH_PER_YEAR      =   12;
var HOURS_PER_DAY       =   24;
var MINUTES_PER_HOUR    =   60;
var SEC_PER_MINUTE      =   60;
var MILLISEC_PER_MINUTE =   1000;
return income * MONTH_PER_YEAR / DAYS_PER_YEAR / HOURS_PER_DAY / MINUTES_PER_HOUR / SEC_PER_MINUTE / MILLISEC_PER_MINUTE;
}

On n’a plus qu’a appeler la fonction et à formater la chaîne à afficher…

millisecIncome = monthlyToMillisecIncome(thatIncome);
sofar = delta * millisecIncome;
sofar = Math.round(sofar * 100) / 100;//Arrondi a 2 décimales

//Formattage pour l'affichage du temps écoulé
tmpDate = new Date(delta);
elapsed = tmpDate.getUTCHours() +":"+tmpDate.getUTCMinutes()+ ":"+tmpDate.getUTCSeconds();

Voilà pour la partie backoffice de l’application. C’est loin d’être parfait, mais c’est fonctionnel et testable en ligne. Je compte encore passer quelques jours dessus si je trouve des choses intéressantes à y faire.

La partie jQueryMobile fera l’objet d’un prochain article.

Fun fact: j’ai gagné 1,87€ en rédigeant ce post.

TODOLIST:

  • Des notifications compatibles avec les  mobiles?
  • Une animation de l’icône lors d’une notification?
  • Une version multilingue?
  • Des supers idées proposées par les nofragés?

Avec un icône dédié pour mettre sur son menu iPhone...

Avec un icône dédié pour mettre sur son menu iPhone...

Ayant enfin, après un cursus plus qu’aléatoire commencé mes études en informatique. Du coup j’ai développé par un après midi de temps libre deux pages PHP pour stocker mes ebooks en ligne, afin que mes amis lisant sur iPhone puisse se servir dans ma petite collection. C’est un tout petit truc sans ambition, mais étant donné la rareté de la documentation pour iui sur internet, cela ne fera de mal a personne.

Un simple répertoire ftp aurait suffit, mais ça n’a rien de convivial ni de pratique. Lorsque l’on utilise Stanza (l’application gratuite la plus répandue pour lire sur iPhone), cela nécessite de cliquer sur ajouter un catalogue, choisir l’option web, taper l’adresse et galérer un peu avec le zoom pour sélectionner le livre que l’ont veut télécharger.

J’ai donc été chercher du coté des librairies iui de Joe Hewitt. En l’absence de documentation j’ai vraiment fait un truc balbutiant et non fini, mais qui à le mérite de fonctionner et de faire ce que j’attends de lui.

But : lister les fichiers d’un répertoire et de ses sous répertoires et faire un lien vers ceux-ci permettant un import direct dans Stanza. Le contenu des sous répertoires apparaîtra dans une sous-liste.

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Berru2 - iPhone</title>
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/>
<link rel="apple-touch-icon" href="../err/iui/iui-logo-touch-icon.png" />
<meta name="apple-touch-fullscreen" content="YES" />
<style type="text/css" media="screen">@import "../err/iui/iui.css";</style>
<script type="application/x-javascript" src="../err/iui/iui.js"></script>
</head>

Dans le header on inclue les fichiers de la librairie iui préalablement installée  sur le ftp, ici dans ../err/iui. Le fichier iui.css qui permet d’utiliser les class qui donneront le look iPhone et le iui.js qui permet de faire des transitions animées entre les liens : le petit effet de glissement que l’on à lorsque l’on passe d’un menu à un sous menu dans l’iphone OS.  On donne le lien vers l’icône qui sera utilisé quand l’utilisateur crée un lien vers le site, au format PNG et en 57px par 57px.

Les fichiers .epub sont des fichiers ebooks faciles à lire sur iPhone, de plus lorsqu’un iPhone/iPod Touch à le logiciel Stanza d’installé les liens utilisant le protocole epub:// permettent de dire à l’iPhone de lancer Stanza et de commencer l’importation du fichier vers lequel le lien pointe.

<ul id="home" title="eBooks" selected="true">

<? //----Boucle d'affichage des FOLDER
$folder = "./";
$dossier = opendir($folder);
while ($Fichier = readdir($dossier)) {
if(is_dir($Fichier) && $Fichier != '.' && $Fichier != '..' ){
$nomFichier = $folder.$Fichier;
$nomFichier2 = substr(str_replace('./','',$nomFichier),0,20);
echo '<li><a href="#_'.$nomFichier2.'" target="_self">'.$nomFichier2.'</a></li></br>';

}
}
closedir($dossier);
?>

<li> <a href='#root'> Local </a></li>
</ul>

On débute le contenu de la page lui même : la classe toolbar permet d’afficher le haut de la page d’une appli iPhone, et à lui intégrer un bouton retour lorsque l’on est dans une sous liste. La première boucle en PHP permet de regarder dans le dossier actuel et d’y trouver tous les répertoires. Pour chaque répertoire trouvé, un lien relatif vers une ancre (#_nom_du_répertoire) est créé. Le tout est placé dans des balises <ul> </ul> afin d’apparaître dans une même page, la page home qui sert de page d’accueil. Remarquez la présence du lien vers l’ancre #_root appellélocal“. C’est le lien qui servira à entrer dans le sous menu qui liste les fichiers à la racine du répertoire.

<?php //Affichage du contenu EPUB des sous répertoires
$folder = "./";
$dossier = opendir($folder);
while ($Fichier = readdir($dossier)) {
if(is_dir($Fichier) && $Fichier != '.' && $Fichier != '..' ){
$nomFichier = $folder.$Fichier;
$nomFichier2 = substr(str_replace('./','',$nomFichier),0,20);
echo '<ul id="'.$nomFichier2.'" title="'.$nomFichier2.'">';
$sdossier = opendir($nomFichier.'/');
while ($sFichier = readdir($sdossier)) {
if (substr($sFichier,-4,4)== 'epub') {
$nomsFichier = $folder.$sFichier; // Attention $nomFichier != $nomsFichier
$nomRep = opendir('../');
$nomsFichier2 = str_replace('./', 'epub://berru2.free.fr/', $nomsFichier);
$nomsFichier3 = str_replace('./','',$nomsFichier);
$urlFichier = $nomFichier2.'/'.$nomsFichier3;
$urlFichierStanza = 'epub://berru2.free.fr/ebooks/'.$urlFichier;
echo '<li><a href="'.$urlFichierStanza.'" target="_self">'.str_replace('_',' ',substr($nomsFichier3,0,30)).'</a></li></br>';
}
}
echo '</ul>';

}
}
?>

<ul id="root" title="Racine">

Ici on exécute une boucle qui ouvre les sous répertoires du répertoire courant à la recherche des fichiers .epub
Tous ces fichiers seront donc listés entre deux balises <ul></ul> pour apparaître à chaque fois dans un sous menu portant le nom du répertoire dans lequel on les à trouvés.
Enfin, on remplace le protocole http:// du lien vers le fichier par le protocole epub://.

</pre>
<ul id="root" title="Racine">
<?php
//-------Boucle d'affichage des fichiers EPUB
$folder = "./";
$dossier = opendir($folder);
while ($Fichier = readdir($dossier)) {
if (substr($Fichier,-4,4)== 'epub') {
$nomFichier = $folder.$Fichier;
$nomFichier2 = str_replace('./', 'epub://berru2.free.fr/', $nomFichier);
$nomFichier3 = substr(str_replace('./','',$nomFichier),0,20);
echo '<li><a href="'.$nomFichier2.'" target="_self">'.$nomFichier3.'</a></li></br>';
}
}
closedir($dossier);
?>
</ul>

</body>

La dernière boucle parcours les fichiers du répertoire courant à la recherche des fichiers .epub. Même principe que plus haut, on remplace le protocole http:// par epub:// et on stocke tous les liens relatifs dans le sous menu appelé “Local”.

Pour finir, une petite redirection, en javascript sur ma home afin de rediriger les possesseurs d’iPhone/iPod touch vers la page que l’on viens de voir, sinon vers une page pour permettre d’uploader des fichiers .epub.


<script type="text/javascript">
if (navigator.userAgent.indexOf('iPhone') != -1)
{
if(confirm('Vous êtes sur un iPhone/iTouch, voulez vous accèder au catalogue ebook?'))
window.location="http://berru2.free.fr/ebooks/iphone.php";
}
else if (navigator.userAgent.indexOf('iPod') != -1)
{
if(confirm('Vous êtes sur un iPhone/iTouch, voulez vous accèder au catalogue ebook?'))
window.location="http://berru2.free.fr/ebooks/iphone.php";
}
</script>

Vous pourrez tester la page en vous rendant à l’adresse suivante si vous avez un iPhone : http://berru2.free.fr/

Et si vous n’avez pas d’iPhone vous pourrez essayer la page (dont la mise en forme sera proche de ce qu’on voit sur iPhone sans être identique) ici. Par contre les liens vers le ebooks ne seront du coup pas fonctionnel à moins que vous n’ayez associé un programme au protocole epub:// sur votre machine.

Si vous avez des suggestions concernant le code ou les fonctionnalités, elles sont les bienvenues, c’est toujours formateur d’avoir un retour.

L'aspect final en version iPhone.

L'aspect final en version iPhone.

Edit: Les bugs remontés par Caroline sont corrigés, et les underscore dans les menus sont désormais masqués. Le code ci dessus est mis à jour.