Vulture repellent doesn’t work !!!

Edit 2015-11-27 : en réalité, les DirtySprites de pygame fonctionnent. La taille de la zone à nettoyer est définie par la taille de l’attribut rect, et non pas par la taille de l’image du sprite. Ce n’est pas le même comportement qu’avec les RenderUpdates, et c’est documenté nul part. D’où ma non-compréhension. Tout est expliqué plus en détail dans une question que j’ai posée sur le site IndexError (http:// indexerror.net/79/pygame-groupe-sprite-layereddirty-renvoie-bons-rects-refresh).

Maintenant, il ne vous reste plus qu’à lire cet article devenu obsolète !

 

Haha, ouais ! « Vulture repellent doesn’t work ». Ça kille, no ? C’est une private joke rien que pour moi.

Durant mes folles années, je jouais au jeu-fusion « Might and Magic 4 & 5 : World of Xeen ». Je l’ai terminé. Je vous en parlerais un jour.

Comme dans tout bon jeu de rôles, on peut discuter avec des gens dans des tavernes. Enfin disons qu’on les écoute déblatérer leurs conneries d’ivrognes, sans rien pouvoir répondre. Le jeu n’est pas non plus un modèle d’interactivité. (Hey ! Depuis quand les ivrognes sont interactifs ?)

hé, Yörgl ! Un ch'ti canon ?

hé, Yörgl ! Un ch’ti canon ?

Bref, à un moment, y’en a un qui beugle « Vulture repellent doesn’t work !! » Ah c’était quelque chose. J’avais la version CD-collector du jeu, avec les voies digitalisées de tous les dialogues. Elles étaient très bien faite, beaucoup d’accents variés et prononcés, des phrasés super bizarres : « Ayt’s alwèïze eu plésure teu see you, Ghôôsslayèrze », « The MejjjaDragon » … On sentait bien qu’ils s’étaient lachés sur les voix, et ça faisait chaud à la partie de mon cerveau « esthète du jeu vidéo ».

dans les RPG, on sauve des princesses

dans les RPG, on sauve des princesses.

Bref-bref, un ivrogne générique me gueule ça à la gueule, et je comprends pas du tout. Ça c’est éclairci un peu plus tard, quand je suis tombé sur des monstres appelés « Vulture Roc ». Pas évident à tuer ces saletés, du moins au niveau où j’étais. Or, dans la même ville que l’ivrogne, résidait un clampin vendant du « vulture repellent », à only 250,000 gold. Et il doesn’t workait, bien entendu.

Mais, euh.. Osef complètement ?

Stupidement, cette phrase m’a marqué. Le cri du cœur de ce personnage, sa sentence complètement insolite, l’intonation de sa voie… J’ai décidé d’en faire mon « internet meme » personnel. Maintenant, à chaque fois que je tombe sur un truc quelconque qui fonctionne pas, ce meme fait dzoing dans ma tête.

might and magic gardian tower schtroumpfs

Donc, acte :

pygame

dirty

sprites

doesn’t

work !!!

Comme vous ne le savez pas, en ce moment je fais joujou avec la libraire pygame, qui permet de faire des jeux rigolos en python. On y trouve une classe, fort adéquatement appelée pygame.sprite.Sprite. Celle-ci contient un attribut « rect », pour les coordonnées, et un attribut « image », pour haha l’image.

On peut mettre ces sprites dans des classes « Group », pour les afficher/rafraîchir en un seul appel de fonction. La classe RenderUpdates est un type de Group particulier, et est trop cool. Comment ça marche ?

  • Tu fous tes sprites dans ton RenderUpdates.
  • Quand il faut les effacer, tu lances RenderUpdates.clear(), en spécifiant l’image de background pour l’effaçage. Hop, à ce moment là, le RenderUpdates, il enregistre les positions et tailles de tes sprites. Où stocke-t-il ça ? J’en sais rien. Mais ça marche tout seul, c’est magique.
  • Tu fais toutes les conneries que tu veux avec tes sprites. (déplacement, changement d’image, sexe avec des écureuils…)
  • Quand faut les réafficher, tu lances RenderUpdates.draw().
  • Arrivée à cette étape, si t’es un bourrin de plâtrier, tu prends toute la grosse image que tu viens de créer (background + sprites) et tu blit le tout à l’écran. Plaf !!
  • Mais ne serait-ce pas plus économique et plus subtil de ne remettre à jour que les zones qui ont changées ? C’est à dire, les zones où se trouvaient les sprites avant, ainsi que les zones où ils se trouvent maintenant ? Oh si alors !
  • Noël !! Noël !! Cet opération est automatisée par le RenderUpdates. Quand tu fais un draw, il te renvoie une liste de rectangles sales (dirtyRects), indiquant les zones à réafficher.
  • Plus qu’à faire un petit display.update(), en filant directos la liste de dirtyRects. (Surtout pas de display.flip() de plâtrier bourrin). Et le tour est jouay !!! Ça marche, c’est simple, c’est optimisé, on est content.

Petit exemple de RenderUpdates

Le script python est à récupérer ici : dirtyno.py

Le fond de l’écran est vert. Il n’y a qu’un sprite : un carré rouge. Au début il est immobile, puis il se déplace vers la droite. C’est moche et saccadé. Et j’ai même l’impression que ça clignote, (ou alors c’est mes yeux). Mais on s’en fout.

Ca nous y fait ceci :

Là vous le voyez pas bouger, car c’est qu’une image. Pour avoir une émulation à peu près fiable du logiciel, Faites de petits mouvement de tête, comme un pigeon.

Comme je suis d’un naturel curieux…

Haha, quelle titre de merde !! J’ai toujours rêvé de dire ça un jour, en restant stoïque et avec un petit sourire en coin. Comme les gars qui se la pètent, mais sans en avoir l’air. Genre « hu-hu-hu je suis un type normal et tout à fait modeste, mais je suis d’un naturel curieux. Oooohhh, aimez-moi, regardez-moi comme je suis un mec bien, je suis un gentleman avec une petite moustache fine, je ne veux pas donner l’impression de me vanter mais je le fais quand même avec mes gros sabots dégueulasse pleins de boue. Je brâme ma vacuité dans vos oreilles. Brâââââhhhâââââ. Mon sperme est à vendre ! Une occasion unique de faire quelque chose de bien de votre vie ! Fabriquez un enfant ayant mon patrimoine génétique et admirez-le !! Pââââmez-vous, pââââmez-vous !! »

Et merde, encore raté.

Bref, moi et ma curiosité, on voulait juste voir le contenu de ces fameux dirtyRects. J’ai mis un print dans mon programme d’exemple, ça me donne ceci :

coucou !!!
mode normal. liste des rect a repeinturer :
[<rect(10, 100, 50, 50)>]
mode normal. liste des rect a repeinturer :
[<rect(10, 100, 50, 50)>]
mode normal. liste des rect a repeinturer :
[<rect(10, 100, 80, 50)>]
mode normal. liste des rect a repeinturer :
[<rect(40, 100, 80, 50)>]
mode normal. liste des rect a repeinturer :
[<rect(70, 100, 80, 50)>]
mode normal. liste des rect a repeinturer :
[<rect(100, 100, 80, 50)>]
mode normal. liste des rect a repeinturer :
[<rect(130, 100, 80, 50)>]

Le coucou du début, faites y pas gaffe. C’est mon init.

A chaque fois, la liste contient un seul dirty rect. Les valeurs numériques indiquent (coord_X, coord_Y, largeur, hauteur). Au début, le sprite ne bouge pas, donc le dirtyrect à rafraîchir lui correspond exactement. C’est normal.

Ensuite, la coordonnée X du dirtyRect augmente de 30 en 30. Normal, c’est la distance de déplacement de mon sprite, à chaque cycle.

On remarque aussi que la largeur du dirty rect passe à 80. Normal aussi. Le sprite a une largeur de 50. Le RenderUpdates a fusionné la position initiale (le sprite à effacer), avec la position finale (le sprite à afficher). 50 + 30 = 80. Toute la zone nécessaire est rafraîchie (toute ? oui). Ça se gère automatiquement, c’est super.

Donc ça marche.

Dirty Sprite. Ce n’est pas sale.

Quand on est un gars bien, avec une moustache fine, on sait qu’un niveau d’optimisation supplémentaire est possible. En effet, tous les sprites n’ont pas toujours besoin d’être rafraîchis à chaque cycle : si ils ne bougent pas et ne changent pas, pas la peine de les redessiner. C’est là qu’interviennent les dirtySprites ! Tadzam !

C’est comme les sprites normaux, sauf qu’un attribut supplémentaire est ajouté : « dirty ».

  • dirty = 0. Le sprite n’est jamais redessiné.
  • dirty = 1. Le sprite est redessiné une seule fois, puis l’attribut est automatiquement fixé à 0.
  • dirty = 2. Le sprite est toujours redessiné.

Pour avoir ce fonctionnement, il faut utiliser le Group « LayeredDirty », au lieu de « RenderUpdates ». OK c’est cool.

Comme je suis d’un naturel essayiste, j’ai repris mon programme tout moche, j’ai remplacé le group et le sprite, et j’ai fixé dirty à 2. Concrètement, quel est l’intérêt ? Aucun. Le sprite sera redessiné à chaque cycle, comme avant. Mais c’est juste pour tester.

Petit exemple de LayeredDirty

Voici le programme modifié : dirtyyes.py
Et à l’écran, ça donne quoi ?

But ! But !! It’s all fucked up !!! THIS IS AN OUTRAGE !!!

Quand au résultat du print, c’est pas mieux :

coucou !!!
mode dirty. liste des rect a repeinturer :
[<rect(0, 0, 400, 300)>]
mode dirty. liste des rect a repeinturer :
[<rect(10, 100, 50, 50)>]
mode dirty. liste des rect a repeinturer :
[<rect(10, 100, 50, 50)>]
mode dirty. liste des rect a repeinturer :
[<rect(40, 100, 50, 50)>]
mode dirty. liste des rect a repeinturer :
[<rect(70, 100, 50, 50)>]
mode dirty. liste des rect a repeinturer :
[<rect(100, 100, 50, 50)>]
mode dirty. liste des rect a repeinturer :
[<rect(130, 100, 50, 50)>]

Le premier dirty rect fait tout l’écran. Ça a l’air normal, car au début il faut tout rafraîchir. En vertu de quelle lubie pygame se décide à gérer ça maintenant, alors qu’il le faisait pas avant ? De toutes façons m’en fout, je fais un flip global à l’init. Pas besoin de leur connerie. Passons.

On retrouve les deux premiers dirtyRects du début, qui ne bougent pas. Jusque là OK. Ensuite, on se déplace de 30 pixels vers la droite. Mais la largeur reste toujours 50 ! What the fuck ?

Je ne vois que deux explications possibles : soit je suis idiot, et j’ai pas compris comment ça fonctionnait. Soit leur truc est buggé.

J’ai cherché de l’aide par-ci-par-là-lulé sur internet. Que d’alle. Et comme j’ai pas le courage de traduire tout mon blabla en anglais pour poser la question sur un forum ou sur leur IRC-mailing-list, je me contente de râler dans mon coin et d’en faire un article. Voilà.

Je terminerais avec bonnet-de-nuit-man, qui n’est pas très très content de toute cette gabegie :

bonnet de nuit man

M’en fout, je vais continuer de coder mes trucs sans utiliser cette connerie de dirtySprite. Bien fait. Et pour finir, une dernière image de notre plumpprincess :

plump princess

3 réponses à “Vulture repellent doesn’t work !!!

  1. Source des images.

    La taverne du début, dans Might and Magic.
    http://cur.lv/1enxz
    http:// i.ytimg.com/vi/zdwzpS4cHIQ/0.jpg

    Haaa !! Might and Magic !! J’y ai dépensé (à très bonne escient) une bonne partie du temps de mon lycée et de mes études. Ouais. J’avais presque fini le jeu en mode Adventurer (taffiole). Puis j’ai laissé tomber et suis parti vers d’autres horizons. Mais ça me titillait continuellement de ne pas être allé jusqu’au bout. Je m’y remettais un peu de temps en temps. J’ai aussi usé ma souris sur l’épisode 6 (jamais terminé, super long). Et lorsque je me suis senti prêt dans ma tête, j’ai tout recommencé du début, en mode Warrior. Et je l’ai fini !! J’ai juste pas réussi à buter le MegaDragon (le MejjjjaDragon comme le dit si bien Orothin). Mais il et super bourrin, et facultatif. Il fait même pas partie d’une quête. Ptêtre qu’un jour je rerecommencerais en mode Adventurer, juste pour lui niquer la gueule et voir les objets qu’on gagne.

    Plump Princess habillée.
    http://cur.lv/1eny0
    http:// plumpprincess.skyrock.com/2.html

    Bien joli damoiselle. Comme quoi, y’a pas que de la merdouille sur skyblog !! Ah je vous rassure, c’est pas une petite adolescente qui met des photos d’elle juste comme ça et qui irait le regretter après. Elle a quand même un site payant. C’est un peu son métier. D’ailleurs, si vous voulez me filer votre membership avec votre mot de passe, je suis preneur.

    Un schtroumpf dans Might and Magic.
    http://cur.lv/1eny1
    http:// forum.canardpc.com/threads/23076-Le-TOPIC-des-screenshoots-Tranches-de-jeux-et-instants-tann%C3%A9s-sur-fond-d-Clayderman?s=e5e41f9ca1efcb252f9c4a1db6d4b783&p=2680757&viewfull=1#post2680757

    Haaa!! Might and Magic !! J’y ai dépensé (à très bon…) Woups, pardon. Bon, le schtroumpf, c’est le gardien des tours côté « Clouds of Xeen ». Il dit, d’une voix veloutée et sépulcrale : « I seeee youuu haaaave the keeeyyy tooouu ziiisssss tooowweerrr !! You maaayyy paaasss moooorttaaaalze ». Excellent vraiment. Mais je préfère encore plus la gardienne côté « Darkside of Xeen », car on voit le début de ses nichons. Ouais, les dessins de ces petites scènes cinématiques étaient vraiment … soignés, mais kitsch. Y’en avait pas énormément, mais chacun d’eux valaient le coup. Je finirais forcément par faire un article détaillé sur ce jeu. Dans le magazine 42, ou ici-même. Stay tuning !

    Plump Princess moins habillée.
    http://cur.lv/1eny2
    http:// fr.bebo.com/c/photos/view?MemberId=6341696783&PhotoNbr=1&PhotoAlbumId=7497525702#photoId=7497540172

    Re plump-princess. Mais cette fois-ci en blonde et bleus. Ce qui fait deux fois de suite la séquence de consonne « bl ». Tiens ça me fait penser aux UV de biologie de l’UTBM. Y’a toutes les petites minettes qui se précipitaient dedans. Moi non, car ça m’intéressait pas du tout. La bio je trouve ça super chiant. Zut, faut que j’y aille. La cloche interne de mon cerveau sonne. A+

    Les screenshot moches et carrés sont de moi, donc pas vraiment de source.

    Bonnet-de-nuit-man, c’est moi dans le monde réel, donc pas de source non plus, si ce n’est mon génôme personnel. Y’a pas longtemps, j’ais joué le bourgeois gentilhomme dans « Le Bourgeois Gentilhomme ». C’était vraiment chouette. Mais j’évite de faire trop de « my life » sur ce blog. Donc vous en saurez pas plus. Appréciez mon regard de braise et mon visage d’airin, cela devrait amplement vous suffire, n’est-ce pas ?

  2. Pingback: Introduction à une introduction à la karmagraphie « Réchèr : le Grand Tout

  3. Pingback: Blarg pour tout le monde | Réchèr : le Grand Tout

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s