Je me suis fait une petite scéance de "speed-pixels" ce midi. On ouvre the Gimp, on récupère les couleurs de la forêt de Donkey Kong: King of Swing et c'est parti.
L'idée, c'est de faire vite et de mettre les éléments en place: ils seront retravaillés plus tard dans mon sprite editor, mais ce dernier n'est pas encore très pratique quand on veut rapidement entasser quelques gros ronds pour faire une forme de feuillage (à noter pour plus tard, en blanc sur bleu, ça aurait pu faire de beaux nuages) ou les formes étirées du tronc d'arbre.
J'en dirai plus plus tard, mais je crois que c'est un bon début...
Friday, November 16, 2007
Un autre arbre pour Bilou
Thursday, November 15, 2007
2D sur la DS : quelques chiffres ...
Plus de 640K de mémoire vidéo sur la DS -- c'est presqu'autant que la mémoire vive dont on disposait sous DOS sans les extensions. Mais comme je vous le montrait dans un de mes posts précédents, il faut répartir cette mémoire entre les deux écrans, les fonds, les cartes, les sprites et éventuellement, les palettes et les textures. Bref, pas mal de monde.
Pour un jeu de plateforme comme Bilou et Badman, le plus raisonable serait de partir sur 256K pour les décors, 128 à 256K pour les sprites (tout ça sur l'écran principal) et de garder les 128K restant pour gérer l'écran secondaire (map, inventaire ... peu importe). 256K de décors ... avec mes blocs qui font 16x16 pixel, ça veut dire que j'ai droit à un bon millier de blocs différents conservés simultanément en mémoire. Soit près de 5 écran de DS. C'est déjà honnête ...
Bien sûr, rien n'empèche de changer le contenu de la VRAM au fil du jeu. C'est notamment ce que j'ai l'intention de faire pour les blocs animés (pensez à la pièce d'or de SuperMario ou au bloc-question). On leur attribue quelques tiles sur lesquels on ira recopier systématiquement l'étape d'animation suivante au bon moment (depuis nos 4Mo de mémoire de travail, donc). Ainsi on gagne du temps et de la place. On pourrait aussi essayer d'éliminer certains blocs non-affichés pour les remplacer par d'autre en fonction de la progression du joueur dans le niveau, par exemple si l'on voulait faire un traveling continu sur les écrans d'Another World... mais il y a peu de chances que je me serve de quelque-chose de ce genre.
Dans un niveau ou le scrolling est libre dans toutes les directions, on choisira de préférence une map 512x512, de manière à pouvoir toujours modifier les "bords" de la map pour avancer dans le niveau sans que le joueur ne remarque quoi que ce soit. Il y a aussi des map 512x256 et 256x256 que l'on utilisera dans des jeux ou le scrolling suit un seul axe (les shoot'm'up, par exemple, ou des niveaux spéciaux dans un jeu de plate-forme).
Evidemment, on pourrait se dire que c'est du gâchis de prendre une carte de 512x512 alors que 256+16 aurait suffi à un scrolling fluide (réfléchissez un peu: pourquoi le GBA a-t-il un écran de 240 pixels de large, selon vous?). Mais ce serait compter sans le fait que la "carte" des tiles peut aussi nous servir directement pour savoir si notre personnage (et tous ses adversaires) ont affaire à un mur ou à un trou. Chaque "tile" est encodé sur 16 bit dans la carte (cf cet autre post précédent) et on peut choisir parmis 1024 "tiles" différents, les autres bits permettant de "retourner" les blocs horizontalement et verticalement.

Restent 4 bits inutilisés qui pourraient se révéler bien pratiques pour encoder directement le type de bloc: creux, plein, "montée" à 45°, "descente" à 45°, "montée" à 22.5% ...

Dans Rayman Designer, il y a 24 types de blocs différents, y compris le bloc semi-solide (on peut passer à travers en sautant, mais pas en tombant), les blocs glissants (de nouveau 7 inclinaisons différentes), des blocs qui blessent, qui tuent, qui noient, qui font rebondir, escaladable, etc.
<obsolete why= "si les bits "palette" sont actuellement effectivement utilisés, c'est en les combinant par blocs de 4 tiles que l'on étendra le nombre de propriétés disponibles.">
Bien sûr, avec 4 bits de libre, c'est un peu juste pour proposer les 24 types de Rayman, et pourtant, dans Bilou, il nous faudra bien tout ça. Mais dans notre cas, il y a peu de chance que l'on se serve du "retournement" de tiles. Le plus souvent, ça fouterait en l'air tous nos efforts d'éclairage sur les blocs. Résultat, on pourrait s'arranger, par exemple, pour stocker certains blocs "à l'envers" et pour pouvoir se servir du bit "miroir horizontal" pour faire la différence entre les montées et les descentes ... L'alternative, ce serait d'avoir une des combinaisons pour indiquer que le bloc est "spécial", et de se servir à ce moment de son numéro pour choisir le comportement approprié, sachant que ce sera un peu plus compliqué à traiter... L'idéal, ce serait de garder ça pour les interactions que seul le personnage fera (grimper, se blesser, etc.) et d'avoir les effets sensibles égalements pour les monstres directement encodés sur la map...
</obsolete>
Enfin. 'faudra tester tout ça. J'espère que ça ne vous a pas paru trop imbuvable: j'avais besoin de mettre les idées au clair avant de me lancer dans le code de gestion des niveaux ...
Tags: cheat sheet, jump-thru, level design, sidescroller, slopes, tiled, translate me, vram
Wednesday, November 14, 2007
LBM & Linux
Je suis un vieux de la vieille qui a commencé ses pixels sous MS-DOS. Et de temps en temps, j'aime pouvoir récupérer mes vieux dessins tout pixelisés. Mais voilà, bien peu de programmes supportent les fichiers .LBM de mon ancien Deluxe Paint II enhanced :(
Sous ubuntu, pourtant, le package
Reste que imagemagick persiste dans l'idée que mes fichiers Deluxe Paint devraient s'appeler ".ilbm" et pas ".lbm". Comme c'est pénible et que je suis geek, j'édite le fichier /usr/lib/ImageMagick-6.2.4/config/delegates.xml et là ou on voyait une ligne "decode 'ilbm', je passe à
<delegate decode="lbm" command='"ilbmtoppm" "%i" > "%o"' />
<delegate decode="ilbm" command='"ilbmtoppm" "%i" > "%o"' />
Bref, voilà comment mon frère a maintenant mes petits sprites de Kid Paddle pour les envoyer sur le forum de Midam ^_^
(packages à installer: libimlib2, imagemagick et netpbm/libnetpbm10)
Monday, November 12, 2007
Java pas m'énerver ...
Quand il s'agit de manipuler un document XML, moi, mon interface préférée, c'est XPath. Pas besoin de code bien compliqué: on fait comme si tous les éléments étaient des petits fichiers dans une arborescence, et on donne un chemin pour trouver les éléments qui nous intéressent. J'avais déjà pu m'en servir avec succès en PERL, je m'attendais à quelque-chose d'ultra-simple en Java, langage de l'XML par excellence.
J'y vais donc de mon petit test débile:
import java.lang.*;
import java.util.*;
import javax.xml.xpath.*;
import org.xml.sax.InputSource;
public class XpathTest {
public static void main(String[] args) {
try {
System.err.println("creating xpath...");
XPath xpath = XPathFactory.newInstance().newXPath();
String expression = args[0];
InputSource src =
new InputSource(new java.io.FileInputStream(new java.io.File(args[1])));
System.err.println("search for "+args[0]);
String content = xpath.evaluate(expression, src);
System.out.println("here: "+content);
xpath.reset();
src = new InputSource(new java.io.FileInputStream(new java.io.File(args[1])));
Object node = xpath.evaluate(expression, src, XPathConstants.NODESET);
System.out.println("here: ("+node+")");
} catch (javax.xml.xpath.XPathExpressionException ex) {
System.err.println("oops: "+ex);
} catch (java.io.FileNotFoundException ex) {
System.err.println("no file : "+ex);
} catch (java.io.IOException ex) {
System.err.println("doh: "+ex);
}
}
}
Tout ça à l'aide de la première référence que je trouve: la doc de sun bien claire, sauf sur un point "c'est quoi cette 'nodelist' que je suis supposé recevoir mais qui m'est transmise sous la simple forme d'un 'Object' ?". Au bout de quelques minutes de tests, je me rends compte que la seule chose qui marche, c'est le chemin "/" qui reprend tout le texte du document. le reste ("/feed/entry[1]/title" ou "//author", ce genre de choses chouettes et utiles), ne donne aucun résultat. Pas une exception ou un message d'erreur. non. rien, tout simplement. que le chemin corresponde à un noeud existant dans le document ou pas, d'ailleurs.
grmbl.
Puis à force d'essayer, je finis par constater que le fameux objet que je récupère est de la classe com.sun.org.apache.xml.internal.dtm.ref.DTMNodeList.
Et là, je dis: ça pue. pourquoi m'ont-ils renvoyé un objet interne non-documenté et (de plus) qu'est-ce que c'est que ce "sun...apache..." ou bien c'est dans le standard, ou bien ça n'y est pas, non ?
allons bon ...
Xerces does not provide an XPath implementation (it implements only support for the limited expressions allowed by XML Schema constraints). Xalan provides an XPath 1.0 implementation and from the com.sun.org.apache... package name it seems there is the Sun (derived from Xalan) implementation that is included with the JVM.ref
Tout de suite, ça m'étonne moins. Reprenons calmement avec la doc d'apache, donc.
- on installe le package "xalan", un traducteur XSLT qui est sensé fournir XPath pour de vrai
- on redéfini sa variable d'environnement CLASSPATH pour pointer sur /usr/share/java/xalan2.jar
- on google sur "org.apache.xpath example" et pas "xpath java example"
Bref, le code le plus simple auquel j'arrive ressemble à ceci:
mais pour ça, il me faut écrire une horrible fonction capable de passer d'un nom de fichier à un Document, parce que visiblement, les gens qui ont écrit XPathAPI n'ont pas pensé à rendre ce cas-là simple :(import org.apache.xpath.*; // for XPathAPI, obviously!
import org.apache.xpath.objects.*; // for items, nodelists, etc. (XObject)
import org.w3c.dom.*; // for Document and friends
import java.lang.*; // for String and the like.
/** see also:
http://xml.apache.org/xalan-j/apidocs/javax/xml/parsers/DocumentBuilder.html
*/
class xpath2 {
public static void main(String args[]) {
Document doc=FileToDoc(args[0]);
String xpath = args[1];
System.out.println("\nQuerying DOM using xpath string:" + xpath);
try {
XObject o = XPathAPI.eval(doc, xpath);
System.out.println(o.getTypeString()+"> "+o);
} catch (Exception e) {
System.err.println("doh:" +e);
}
}
}
Notez que si vous avez déjà un InputStream prêt sur le contenu (p.ex. une connexion réseau), inutile de passer par un fichier:static Document FileToDoc(String fname) {
/* well, Document is an interface and cannot be built simply */
/* -- grmbl -- */
try {
javax.xml.parsers.DocumentBuilderFactory docBuilderFactory =
javax.xml.parsers.DocumentBuilderFactory.newInstance();
javax.xml.parsers.DocumentBuilder docBuilder =
docBuilderFactory.newDocumentBuilder();
// Parse the XML file and build the Document object in RAM
return docBuilder.parse(new java.io.File(fname));
} catch (Exception e) {
System.err.println("parse error: "+e);
return null;
}
}
docBuilder.parse(InputStream) existe également. Il y a même docBuilder.parse(URL) pour ceux qui ne sont pas occupés à faire un exercice sur l'écriture d'un client HTTP :P(soupir)
Et pour être sûr, ils ont *aussi* rendu la réécriture de documents XML vers un fichier tordue:
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(document);
StreamResult result = new StreamResult(System.out);
transformer.transform(source, result);
Pour la postérité, la javadoc de l'API XPath sur le projet Apache.
Jouons avec netcat ...
Les blogs sont nos amis, mais pour la plupart d'entre nous (même les programmeurs), la simple question "y a-t-il du neuf sur mon blog préféré" paraît trop complexe pour qu'on se donne la peine de la programmer. Pourtant, j'aimerais bien lancer mes étudiants sur un TP basé sur les flux RSS. Alors ?
Alors, bin souvenez-vous du post sur netcat, cet outil unix capable d'ouvrir et de manipuler des sockets en ligne de commande (je simplifie, mais bion). Avec quelques connaissances de HTTP 1.1 on va pouvoir s'amuser un peu. Tout d'abord, il nous faut l'URI d'un flux RSS, en l'occurence, le mien: http://sylvainhb.blogspot.com/feeds/posts/default
Nous avons déjà l'outil wget qui nous permet de récupérer une ressource sans passer par un navigateur, mais netcat va nous permettre de bidouiller un peu notre requête HTTP et de récupérer "en live" la réponse du serveur.
Voyons donc. La manière la plus simple pour récupérer la page avec notre flux RSS en HTTP correspond à
GET http://sylvainhb.blogspot.com/feeds/posts/default HTTP/1.1
Host: sylvainhb.blogspot.com
Auquel le serveur répondra quelque-chose comme
HTTP/1.1 200 OK...
Content-Type: application/atom+xml; charset=UTF-8
Last-Modified: Mon, 12 Nov 2007 11:00:00 GMT
Cache-Control: max-age=0 private
ETag: "8ec946e4-7f26-4280-8dad-30c1e7f20e51"
Transfer-Encoding: chunked
Date: Mon, 12 Nov 2007 11:15:53 GMT
Server: GFE/1.3
Connection: Close
c04
<?xml version='1.0' encoding='UTF-8'?>
<?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?>
<feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/'>
<id>tag:blogger.com,1999:blog-34057821</id>
<updated>2007-11-12T12:07:24.724+01:00</updated>
<title type='text'>Bilou HomeBrew's Blog</title>
La réponse est divisée en deux parties: des en-têtes, qui nous indiquent ce que l'on va recevoir, de quand celà date et comment gérer la suite du transfer et le contenu qui nous intéresse (le flux RSS proprement dit). Ceux qui ont fait un peu de programmation WEB auront tout de suite reconnu le "look HTML" de notre contenu. Il s'agit en fait d'un document XML, qui adopte les conventions d'HTML pour présenter n'importe quel type d'information (ici, un "flux" (
Grâce à la balise
Vous avez remarqué la ligne "Last-Modified" dans les en-tête de la réponse ? Il s'agit de la dernière date de mise à jour (enfin, ce qu'en pense le serveur). Et nous pouvons demander au serveur de ne nous retransmettre le document que s'il a changé depuis cette date avec une petite variante de notre requête:
GET http://sylvainhb.blogspot.com/feeds/posts/default HTTP/1.1
Host: sylvainhb.blogspot.com
If-Modified-Since: Mon, 12 Nov 2007 11:00:00 GMT
Le serveur ne répondra maintenant par un "200 OK" que si la page a changé. Dans le cas contraire, on aura droit à un petit "304", sans contenu. Nettement plus léger, non ^_^ et plus simple que d'extraire à nouveau la balise <updated> pour comparer avec la précédente. Et tout ça avec une seule ligne de commande (à mon avis, bien plus sympa pour les tests que de lancer un "telnet" et d'essayer de taper toute sa requète avant que le serveur WEB n'estime que vous êtes trop lent):echo "GET http://sylvainhb.blogspot.com/feeds/posts/default HTTP/1.1\nHost: sylvainhb.blogspot.com\nIf-Modified-Since: Mon, 12 Nov 2007 09:51:53 GMT\nConnection: close\n\n" | nc sylvainhb.blogspot.com 80
Petit raffinement: sous Unix, on dispose aussi d'un outil "watch" qui appelle la même commande, encore et encore. On pourra donc se faire un "surveilleur de blog ultra-geek" avec
watch 'echo "GET http://sylvainhb.blogspot.com/feeds/posts/default HTTP/1.1\nHost: sylvainhb.blogspot.com\nIf-Modified-Since: Mon, 12 Nov 2007 09:51:53 GMT\nConnection: close\n\n" | nc sylvainhb.blogspot.com 80'
Bon, okay, la date de référence pour laquelle on teste les mises à jour est toujours la même ici, ce qui rend l'exercice assez inutile. C'est que le début, d'accord, d'accord ?
(edit: amusant: non seulement cette méthode m'indique quand il y a un nouveau post, mais aussi si un post a été remanié ou s'il y a un commentaire en attente de modération ;)
Thursday, November 08, 2007
Encore Titus
De temps en temps, je passe faire un tour sur vgmaps.com, un chouette site qui répertorie les niveaux de jeux vidéos comme un "atlas". C'est du boulot, évidemment. Ayant récupéré "the Blues Brothers" sur abandonia, je me suis amusé à photographier le jeu au fur et à mesure.
the Blues Brothers, c'est le jeu où Titus Interactive prépare les ingrédients de ses futurs jeux. Des munitions (caisses à lancer sur les ennemis), pas encore tant de passages secrets, mais une série de "salles secrètes", comme les cavernes de Prehistorik (premier du nom) qu'il faudra explorer pour rassembler les objets nécessaires au concert de Jack et Elwood, mais qui peuvent aussi bien contenir des "bêtes" bonus ou un loubard.
The whole is spiced up with some exploration, as you will need to find a special item in each level to get the "good ending" of the game. By then, I found that mix much more interesting than the usual straightforward, infinite amno, gun-oriented platformer.
Autre détail qui a son importance, si vous êtes touchés alors que vous transportez une caisse, vous la perdez, ce qui veut dire que plus loin dans le jeu, vous serez désarmé face à un autre danger. Bref, le moindre faux-pas est lourd en conséquence. Autre exemple, les designers se sont amusés à s'assurer qu'à deux ou trois endroits, vous risquiez de retomber plus en arrière dans le jeu (de préférence là où vous n'aviez pas la possibilité d'éliminer tous les ennemis).
- niveau 1 : le magasin (guitare dans une des échoppes). On affronte des loubards, des mémés en caddie, des policiers, des serveuses furieuses et des jardiniers toqués. Une fois dans les nuage, c'est le piaf pond-vite qui nous mêne la vie dure
- niveau 2: en construction (lunettes et chapeau que je ne parviens pas à atteindre. Peut-être faut-il un parapluie ...) Sale gosses armés de pulvérisateur d'acide et gros bras maniaques de la clé à molettes, mais gare aux mares d'acides et aux broyeurs.
Autre petit élément sympathique, des objets tels que les parapluies ou les balons du premier niveau, offrent un gameplay plus varié.
Bref, du bon jeu de plateau comme on aimerait en voir à nouveau. Dommage que l'opus "II" (juke box adventure) n'ait pas été une réussite... Bien sûr, les graphismes sont nettement plus beaux, mais ils ont complètement perdu le fil de l'histoire. Tout d'abord, le principe même du jeu n'a plus rien avoir. On le catégorise sur abandonia de "no-brain fun", et en effet, plus la moindre recherche. La progression dans le niveau est devenue ultra-linéaire. Finies les caisses, ici on lance des disques, et il faudra souvent en balancer plusieurs pour venir à bout d'un monstre apparemment inoffensif.
Là aussi, le bât blesse: alors que Blues 1 nous avait fait affronter des personnages parfois déjantés, mais toujours réalistes, on se retrouve ici face à des pièges à loup vivants et géants, et .. euh une sorte de tondeuse à gazon croisée avec une pelleteuse mécanique qui à visiblement des instincts de pit-bull.Bref, les deux premiers niveaux sont beaux, mais franchement insipide une fois leur côté démo/tutoriel passé, et dès le niveau 2, les monstres sont tout simplement pénibles (mouvements trop rapides, impossibilité de les dégommer quand ils sont "au repos", bref, pas impassables, mais pénibles)
Et pour le coup de grâce, je vous laisse contempler, hébétés, nos fameux blueseurs transformés en sur-hommes après avoir mangé une part de gâteau, ce qui semblerait leur permettre de faire des sauts plus longs, et peut-être renforcerait la puissance de leur lancer de disque.Ridicule et pas convaincant pour un sous. Bref, autant Titus Interactive nous a fait de bons jeux dans ses jeunes années, autant il semblerait qu'ils aient été contaminés par la transformation du monde du jeu vidéo en un "marché" et progressivement perdu toute notion du gameplay et de la conception des bons niveaux. Je n'oserais même pas dire qu'ils ont transformé BB en un clône de Megaman: la seule ressemblance viendrait du fait que l'on tire sur des ennemis dans un sidescroller.
Bref, concentrez-vous sur le premier volet à moins d'être un graphiste en manque d'inspiration.
Tags: carry-me, designclass, game, level design, nostalgy, throwable, titus, y91
Monday, November 05, 2007
Pas bien (2)
je ne dois pas blogger au lieu de préparer ma défense de thèse.
je ne dois pas blogger au lieu de préparer ma défense de thèse.
je ne dois pas blogger au lieu de préparer ma défense de thèse.
je ne dois pas blogger au lieu de préparer ma défense de thèse.
je ne dois pas blogger au lieu de préparer ma défense de thèse.
je ne dois pas blogger au lieu de préparer ma défense de thèse.
je ne dois pas blogger au lieu de préparer ma défense de thèse.
je ne dois pas blogger au lieu de préparer ma défense de thèse.
Tags: who am I

Vote for your favourite post
