tag:blogger.com,1999:blog-340578212024-03-19T09:04:11.644+01:00Bilou HomeBrew's BlogFrom Bits to GameplayPypeBroshttp://www.blogger.com/profile/10564522267743689261noreply@blogger.comBlogger1572125tag:blogger.com,1999:blog-34057821.post-58793142654775688362024-03-06T13:13:00.002+01:002024-03-06T13:49:11.169+01:00Reprendre les vieilles maps ?<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZbWqB1vZXBtwycvsP17oeSug9cnMBE1kYQ4YktSAKmJ0VJzN1GZ9csSa1SQN7YGpns-yUpc56ZWXHia9_5Z_r0qm8oXAojhDccy4WBqdMXfc5iv4FRYIsyoO5DO8eVAFBZODwtUoqo5tbi2AcfrFGJ1Kw0SPxwSvGgNhwnJiP_BOPOUidP0ZdCQ/s363/Screenshot%202024-03-04%20at%2013-01-41%20Bilou%20HomeBrew's%20Blog.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="190" data-original-width="363" height="167" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZbWqB1vZXBtwycvsP17oeSug9cnMBE1kYQ4YktSAKmJ0VJzN1GZ9csSa1SQN7YGpns-yUpc56ZWXHia9_5Z_r0qm8oXAojhDccy4WBqdMXfc5iv4FRYIsyoO5DO8eVAFBZODwtUoqo5tbi2AcfrFGJ1Kw0SPxwSvGgNhwnJiP_BOPOUidP0ZdCQ/s320/Screenshot%202024-03-04%20at%2013-01-41%20Bilou%20HomeBrew's%20Blog.png" width="320" /></a></div>Surprise quand j'avais <a href="http://sylvainhb.blogspot.com/2024/01/how-long-before-we-play.html">fait le tour</a> de mon cahier "level design", je n'ai en fait que 2 niveaux et demi candidats pour la Green Zone. Alors que <a href="http://sylvainhb.blogspot.com/2006/03/souvenirs-souvenirs.html">le jeu en BASIC</a> donne l'impression qu'il en comptait 5. Mais certains niveaux (dont celui baptisé "les grands arbres") ont vraiment mal vieilli.<p>Alors pourquoi ne pas inviter à la fête les maps de <a href="http://sylvainhb.blogspot.com/2009/09/un-bilou-tout-neuf.html">la démo 9/9/9</a> ? Elles auraient besoin d'un peu de vernis, mais elles pourraient faire l'office d'écran pour apprivoiser les mécaniques du jeu avant d'être lancé dans l'historique niveau 1 de la forêt ... </p><p><en><i>The goal for the Green Zone of Bilou's Dreamland should be around 26 screens (that's Kirby's Dreamland world 1 size). I have only 2 levels of Bilou's Adventure that seem mature enough to be included ... A bit light if you ask me. But I do have 2 small levels drawn for the earliest GEDS demo back in 2009 that might be welcome, either in the 'dreamland' game, or in the 3-rooms demo.</i></en></p><p><en><i></i></en></p><div class="separator" style="clear: both; text-align: center;"><i><a href="https://2.bp.blogspot.com/-Y4lkVtEH704/W5Q1B6fiq0I/AAAAAAAAIQU/flijXg1pAmMxQTuZY-y675FQbTvV0ZjjgCLcBGAs/s256/testing3.png" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="209" data-original-width="256" height="209" src="https://2.bp.blogspot.com/-Y4lkVtEH704/W5Q1B6fiq0I/AAAAAAAAIQU/flijXg1pAmMxQTuZY-y675FQbTvV0ZjjgCLcBGAs/s1600/testing3.png" width="256" /></a></i></div><i><en>They might feature a bit too much of Funky Funghi, but some of them are in interesting settings, like in that 2nd level with chunks of dirt here and there that are only waiting for <a href="http://sylvainhb.blogspot.com/2023/05/funky-21-bridge-to-fun.html">bridges to be tested</a>... So I went for a poll, and 3/4 responders picked "go for inclusion" while the last person would prefer those maps to be exclusive to the 3-rooms demo.</en></i><p></p>Et le 2eme niveau de la démo, avec ses petites plate-formes et ses funghi partout serait le terrain rêvé pour introduire <a href="http://sylvainhb.blogspot.com/2023/05/funky-21-bridge-to-fun.html">les ponts</a> et jouer un peu avec. Et si la question n'a pas suscité de débat remarquable sur<a href="https://twitter.com/pypebros/status/1762056436903813497"> twitter</a>/<a href="https://mastodon.social/@PypeBros/111996657121433216">mastodon</a>, il y a au moins unanimité sur le fait que les faire intervenir au moins comme terrain d'exploration supplémentaire depuis la démo "three rooms" est une bonne idée.<br />PypeBroshttp://www.blogger.com/profile/10564522267743689261noreply@blogger.com1tag:blogger.com,1999:blog-34057821.post-29501436235186663732024-03-02T10:21:00.007+01:002024-03-18T16:26:30.033+01:00Let's have more musics!<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2d_0y89AN5hd4RpknqFQw3Zbe1E61YuNnXbK38beebmtf4q9AibJ1MslCJKklV74BTCyYsYEPbH3zcjptOAbhZzMsPFn23iF4GUriLGSam6mIyU5Ibm26tTputrpfxh4zxGzvkTeoYiKCql2GunYDkLgWHmhH-YFKnv5OhvBkdTy3QobJ6lFpIA/s428/Screenshot%202024-03-01%20at%2010-08-03%20Mastodon.png" style="float: right; padding: 0px 0px 0px 4px; text-align: center;"><img alt="" border="0" data-original-height="384" data-original-width="428" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2d_0y89AN5hd4RpknqFQw3Zbe1E61YuNnXbK38beebmtf4q9AibJ1MslCJKklV74BTCyYsYEPbH3zcjptOAbhZzMsPFn23iF4GUriLGSam6mIyU5Ibm26tTputrpfxh4zxGzvkTeoYiKCql2GunYDkLgWHmhH-YFKnv5OhvBkdTy3QobJ6lFpIA/s400/Screenshot%202024-03-01%20at%2010-08-03%20Mastodon.png" width="400" /></a></div><p><en><i>If you have tried <a href="http://sylvainhb.blogspot.com/2024/02/apple-water-and-sand.html">the last demo</a>, you most certainly noted that there are only 2 soundtracks for 3 rooms. And moreover, that there is a different set of sound effects depending on the room you're in. This is a drawback of the current sound engine, where everything is in one data file: main in-game tune, <a href="http://sylvainhb.blogspot.com/2010/09/bxx-jump-to-order-xx-dec.html">side tunes</a> for menu and such, <a href="http://sylvainhb.blogspot.com/2010/10/tracksequence-public-animator.html">single-pattern</a> for level clear, <a href="http://sylvainhb.blogspot.com/2016/05/sound-effects.html">mini-patterns</a> for 1-UPs and notable pick-ups, samples to play them all and samples to be used as <a href="http://sylvainhb.blogspot.com/2009/09/sound-effects.html">standalone sound effects</a>.</i></en></p>
<p>Bon, un des gros morceaux de programmation qu'il me reste à faire sur le moteur de jeu, c'est de faire en sorte qu'on puisse plus librement passer d'une musique à l'autre. Pas charger une autre musique en changeant de monde, ça c'est déjà fait. Non. Je veux dire décider que "string tracking" n'est pas la musique idéale pour la green zone et que "4U2" donnera mieux. Ou "little flower on the grass". Pour l'instant, ça pose un soucis parce que les fichiers musique contiennent aussi la palette sonore pour les différents personnages. Je voudrais donc pouvoir faire avec les <i>samples</i> et autres <i>patterns</i> ce que j'ai fait avec les images : charger un deuxième jeu de sons par-dessus la musique destinée au monde. <a href="https://sylvainhb.blogspot.com/2023/10/zikmore-bilouxm.html">ça fait un moment </a>que ça me trotte en tête.</p><p>Et cette semaine, j'ai pu passer un premier cap: importer les samples. ça a l'air de marcher, mais ne nous leurrons pas: vu le type de programmation auquel on a affaire, il faudra rajouter quelques tests automatiques sous scruteur de mémoire pour garantir qu'on n'a pas ajouté une bombe à retardement dans le jeu. Et il y aura une repasse pour mettre ça au net avec des classes une fois que j'aurai validé le concept, parce que pour l'instant, ça part dans tous les sens, aucune des classes du moteur de jeu n'ayant été prévues pour ça.<br /></p>
<p><en><i>So among the objectives I sketched in my 2024 notebook, there was some ideas <a href="http://sylvainhb.blogspot.com/2023/10/zikmore-bilouxm.html">to overlay .xm files</a> the way I overlay .spr files... Or rather the other way'round. Here the generic "bilou.xm" containing mostly sound effects would see its samples and patterns imported over the world-specific song.</i></en></p>
<quote><a href="https://mastodon.social/@PypeBros/112005618785860011" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="48" data-original-width="48" height="48" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjm-4KeCmfOhmQ4hcQ8UGmJN_viW5w0VhsPPnePJgYxWF0hIfBduZFwUzXSb714u7ohEJvCwXXBbN99FZ0mzUK0dUBdyg-OclWiWpqO462sGLJQ1X4G49L0-stgXNjqhRExaq9_2CVair8sFnaZaZb1VbOX3IlhGoyOnKvgVM-ziuq4JIgFa03f0A/s1600/mastoquote.png" width="48" /></a><i>#ndsdev status last night: I could allow 2 instances of NTXM::Song to exist together.<br />
#ndsdev status tonight: I can import instruments from one NTXM::Song so that different environment can share some sound effects.<br />
little step for #gamedev, giant leap for game #MadeWithMyEngine.</i></quote>
<p><en><i>I admit it might sound weird to add the common part over the world-custom part. After all <a href="https://sylvainhb.blogspot.com/2021/01/sprload.html">video does the opposite</a>. The reason here is that odds of adding common sounds over the course of the development feels higher than odds of adding new samples to an existing song. It shouldn't be too hard to tell my brother that patterns 50-60 should be kept free for sound effects, same for samples 50+, no matter what song we're using than to remap all samples of the per-world-songs to other slots because we've got one extra ooch-that-is-electric sample added in the shared bilou.xm</i></en></p><p><en><i>But yeah, I still make sure that bilou.xm is only loaded once, when the game initializes, and we don't pay extra wait time for overlaying it from the SD card. Instead, samples and patterns from the shared song got "borrowed" from the shared song and marked as such so that they aren't freed when we swap songs. Did I mention I read a bit about RUST programming language earlier this week ;) ?</i></en></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyDlcIAivKaKqS4M80ryEcdOEi8xxAfJg-4n9hU0LoQq-_c1EO10oJRSr9R6kzNuAq0RXqpDxEqk-FvJdNZs-8Ck0czKESNjJN4Sthzn6adjmzZpRCadN21OmPwZS9v52cNxPEGWy9j64zsjwNobLdwl6mQV0xLjq9JMkPtdto_onKqOGYeNJxig/s575/ddd-2b68de759ba12ae6.png" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="416" data-original-width="575" height="232" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyDlcIAivKaKqS4M80ryEcdOEi8xxAfJg-4n9hU0LoQq-_c1EO10oJRSr9R6kzNuAq0RXqpDxEqk-FvJdNZs-8Ck0czKESNjJN4Sthzn6adjmzZpRCadN21OmPwZS9v52cNxPEGWy9j64zsjwNobLdwl6mQV0xLjq9JMkPtdto_onKqOGYeNJxig/s320/ddd-2b68de759ba12ae6.png" width="320" /></a></div><en><i><b>edit: </b><a href="https://sourceforge.net/p/dsgametools/hg/ci/2aa8cf0ef83c353511822c994a456da26c04bc0a/">now</a> also imports mini-pattern ^_^</i></en><p></p><p><en><i><b>edit:</b> tried new songs ... some things worked, but some things look broken</i></en></p><p><en><i><b>edit</b>: ow. <a href="https://mastodon.social/@PypeBros">turns out</a> when you encounter pattern break on a mini-pattern, only the channel with the break command is discarded ^^". Seems like it was only a matter of luck that SchoolRush did work fine, and possibly explain why playing / leaving it idle long enough started producing super-fast trash sounds. Now, you'd have hard time dumping the ROM with that ... not as "easy" as with <a href="https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&cad=rja&uact=8&ved=2ahUKEwjvmImItt-EAxXwSKQEHU-9BCYQtwJ6BAgXEAI&url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D0-7PSmYYHF0&usg=AOvVaw2NhCR6sOWzbqSdpKvWY4mT&opi=89978449">a runaway audio channel</a> on a GBA.</i></en></p><p><en><i><b>edit</b>: <a href="https://sourceforge.net/p/dsgametools/hg/ci/18fb0dca2419/">fixed</a></i></en></p>PypeBroshttp://www.blogger.com/profile/10564522267743689261noreply@blogger.com0tag:blogger.com,1999:blog-34057821.post-42771002711095861082024-02-21T22:21:00.004+01:002024-02-22T21:28:15.826+01:00Demo: Scorpeye, Apple, Water and Sand<p>A new demo appeared. At last, my checklist is complete (and sure, there are still many more things to write for a next list). The demo is still based on the "three rooms". Don't expect much more land to explore. I still have a few concepts to prove before I can do that.</p><p></p><table><tbody><tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhY5_HZcfQrSBTrZn80JOrkv2UHBmmhT5SjUW25obw8MRa24tNNAzpINrb8FWvnEkdcJuDVN2Bkm62x1mgsVf5bHJjFSutkTxCv8tXBcu7AYpYJ-7JLQwf1lirYec6BxEt_oktxD_3EQLJs0xVy1kQCMf3FcWDio9tQ2qKhm94TZqWkdTM5Yl5Apw/s101/swim-fixb.gif" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="93" data-original-width="101" height="93" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhY5_HZcfQrSBTrZn80JOrkv2UHBmmhT5SjUW25obw8MRa24tNNAzpINrb8FWvnEkdcJuDVN2Bkm62x1mgsVf5bHJjFSutkTxCv8tXBcu7AYpYJ-7JLQwf1lirYec6BxEt_oktxD_3EQLJs0xVy1kQCMf3FcWDio9tQ2qKhm94TZqWkdTM5Yl5Apw/s1600/swim-fixb.gif" width="101" /></a></td><td><a href="https://sourceforge.net/projects/dsgametools/files/demo%20games/Dreams-sand.zip/download" style="display: block; padding: 1em 0px; text-align: center;"><img alt="" border="0" data-original-height="71" data-original-width="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUwnAbFMY3kuVHKArXhLZ_9MlESthtadOx49Kg1BQpMkDV8IOxnb7BLym5CEV6ShCkbMDR9xSqGfKiqLuAZJ3ysTieRQGeY6Ay2GE4eqsGCU4tgPz_6o9iTEXCmtYV16HagPuOtm4Ya4SoGhXGPCDwTJu-KqB0TyOrGpbyrqwSO_s8QAbARVHbIA/s1600/Screenshot%202024-02-21%20at%2022-03-23%20GamEditorDS.png" /></a></td><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpcXjHvk4E0HdXJLH6AniAztCinPP17c1nwu5rs1Q_H59gbI3M7Kl0KoOvgjEApdncbo7sY-qheIcqsIVo92qzz8kCb10UfCY61abpkJrxi8Vn2VYr6WeIpWWFtIv42rOvS3kdjLjtYI3JLu-V16e0Zg_MY0qiD1PUjVKFbPwsb7d-t6On8-XfMA/s134/sandslope-timedc.gif" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="95" data-original-width="134" height="95" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpcXjHvk4E0HdXJLH6AniAztCinPP17c1nwu5rs1Q_H59gbI3M7Kl0KoOvgjEApdncbo7sY-qheIcqsIVo92qzz8kCb10UfCY61abpkJrxi8Vn2VYr6WeIpWWFtIv42rOvS3kdjLjtYI3JLu-V16e0Zg_MY0qiD1PUjVKFbPwsb7d-t6On8-XfMA/s1600/sandslope-timedc.gif" width="134" /></a></td></tr></tbody></table><p><fr><i>Enfin direz vous, et je ne vous contredirai pas. Voici la nouvelle démo de mes travaux en cours sur Bilou's Dreamland. Toujours limitée à 3 salles à peine de 2x2 écrans qui servent pour expérimenter les nouvelles mécaniques sans passer trop de temps à courir jusqu'à la nouvelle fonction à tester. Mais pour la première fois, vous allez pouvoir nager, affronter les sables mouvants, lancer des carapaces. Et puis il y a toujours le rodéo d'éponge et le saut en encrier. Allez, quoi. Sortez votre linker et faites-vous plaisir :)<br /></i></fr></p><p>Compared to <a href="https://sylvainhb.blogspot.com/2022/03/les-piles-momies-animees.html">the previous demo</a>, you can try</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicdenT7QhGuOEAJCSAODpUdOmABvRLIcTS8Ytj3-BUb73vYRzlg9RMVlHP42Ko8WmLAGlSBu7pZS016cPRU8tb68Fc-gQKRT9m8AWERrey0bj-ODXzKnBkiipte97-JyUc6Qfs2UifRARLu16QClqbFFFI5Ub255DPhK5Na4xGPy2_ecpxBElx2A/s140/school-roomc.gif" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="109" data-original-width="140" height="109" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicdenT7QhGuOEAJCSAODpUdOmABvRLIcTS8Ytj3-BUb73vYRzlg9RMVlHP42Ko8WmLAGlSBu7pZS016cPRU8tb68Fc-gQKRT9m8AWERrey0bj-ODXzKnBkiipte97-JyUc6Qfs2UifRARLu16QClqbFFFI5Ub255DPhK5Na4xGPy2_ecpxBElx2A/s1600/school-roomc.gif" width="140" /></a></div><p></p><ul style="text-align: left;"><li>the new appleman animations</li><li>the collapsing platform (pyramid)</li><li>the scorpeye shell (jump on the scorpeye, then grab it like you'd do with a blador)</li><li>flowing sand, pushing you down the slopes</li><li>improved swim mechanics, waterflow<br /></li></ul>
tested on NDS Lite, desmume 0.9.11 and desmume 0.9.6
<p>Feel like playing a real game ? Try my <a href="http://sylvainhb.blogspot.com/p/blog-page.html">previous titles</a> ;)</p>PypeBroshttp://www.blogger.com/profile/10564522267743689261noreply@blogger.com2tag:blogger.com,1999:blog-34057821.post-90720823089718060732024-02-20T10:14:00.006+01:002024-02-20T11:14:37.136+01:00Tools update<div class="separator" style="clear: both; text-align: center;"><a href="https://sourceforge.net/projects/dsgametools/files/dsgametools/dsgametools-nova24.zip/download" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="109" data-original-width="540" height="65" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8Hb1H_sv6yJZMjB7S5alHXxkay1iAFqb3iP927Tp-sN9sY_v_7Bhunf7nY5DglVTD0MkaK2KbuwaRl8KYll-cUVU44VtCsSC1MSgsUfXm4ocbdEn2mwrkEyhEhQHG2Ri5YZCiCFjgsp_bjT7iCf3Djw5EFCBnERejVvIzwDxwq9rJ-JNMXhJvWQ/s320/Screenshot%202024-02-18%20at%2017-26-55%20GamEditorDS%20-%20Browse%20_dsgametools%20at%20SourceForge.net.png" width="320" /></a></div><blockquote><div class="separator" style="clear: both; text-align: center;"><a href="https://novasquirrel.com/" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="96" data-original-width="76" height="96" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3IAF5aVPMM_ZKyl-kfjjXEN6pSlDGpw4KflmgSGe4h6jGWXkFlBDs4rZIFss7mVmqzibHeIRC5kWwJUUsV0Z1u5EXMog2W-QBMUXPOf5ga3cmqlpoUbZf5gIMSq0Z2qrbkavODmK92-SqrFHTkrVJuaFTovHudT62lcUwMpFUA8mECyxRhgsHqg/s1600/PetalNova.gif" width="76" /></a></div><br /><i>It'd be fun to try your editors! I'd probably do any serious development
on a computer, but it's still cool to have an opportunity to try
something I would've loved to have as a kid.<br /><p>(<a href="https://mastodon.social/@NovaSquirrel@chitter.xyz/111891608985023986">Nova Storm, 7 February 2024</a>)</i></p></blockquote><p>I <a href="http://sylvainhb.blogspot.com/2022/06/nova-squirrel.html">told you about Nova's work</a> on NES and SNES already. Earlier this year, she shown interest into NDS homebrew and linkers, so I proposed her to try the dsgametools, and she replied with the heartwarming sentence above. My last tools release dates <a href="http://sylvainhb.blogspot.com/2021/12/xmas21zip.html">back from 2021</a>, and while there are not that many things that have changed since, some annoying bugs were fixed nonetheless. So I went for<a href="https://sourceforge.net/projects/dsgametools/files/dsgametools/dsgametools-nova24.zip/download"> a new package </a>with some README, example files and PERL tools in addition to the .nds files proper. <b> <br /></b></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjqvoAL3xO7DT-B4ZfJ8Emny2m0ifdmceIobUD0u2F1ijW3L2vWpVoGoDQ9B1PB5mK02YY0hK9ctwUUFW8EVr9maLPhOoHd58gafwDcaF3vjtOEkiHcboqsxxC0QE81IMjMBcKSTQzXYz1mKD_okC8HW4mlTAXK7TzTTc6UOzZVd4V6wVgl-V5KQ/s259/tile4-leds.png" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="204" data-original-width="259" height="204" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjqvoAL3xO7DT-B4ZfJ8Emny2m0ifdmceIobUD0u2F1ijW3L2vWpVoGoDQ9B1PB5mK02YY0hK9ctwUUFW8EVr9maLPhOoHd58gafwDcaF3vjtOEkiHcboqsxxC0QE81IMjMBcKSTQzXYz1mKD_okC8HW4mlTAXK7TzTTc6UOzZVd4V6wVgl-V5KQ/s1600/tile4-leds.png" width="259" /></a></div><b>Level Editor</b>: <br /><p></p><ul style="text-align: left;"><li>fixing bugs with meta buttons;</li><li>add support for special tiles used in conveyer belts and flowing water</li><li>cosmetics: buttons with shadow and show when they are pushed <br /></li></ul><p><b>AnimEditor</b>: </p><ul style="text-align: left;"><li>fixing 'apply to all previous frames' and 'apply to all future frames' buttons.</li><li>only store thumbnails when the animation is used. </li></ul><p><b>runME:</b></p><ul style="text-align: left;"><li>cosmetics: <a href="https://sylvainhb.blogspot.com/2023/05/a-bit-of-shadow.html">buttons with shadow and show when they are pushed</a><b> </b> </li></ul><blockquote><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDGp1IBaQIp2H_oUCowc7gHMA5xDHAGVgEKusFo3lxohf6eG8XfgTMyVgEDMIZLRNv6eCyq0z23v1V8RoK-kYKrClHCLFzUI9j9w3tV_Gd4aWdsrfbjwW2DVT6CSvi7O05u9F88YPkfA_y2v-iSeWxDtPZ_2mOhWsrIvlLqLNQfUsWBtWf5jCxfw/s96/nova3.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="96" data-original-width="76" height="96" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDGp1IBaQIp2H_oUCowc7gHMA5xDHAGVgEKusFo3lxohf6eG8XfgTMyVgEDMIZLRNv6eCyq0z23v1V8RoK-kYKrClHCLFzUI9j9w3tV_Gd4aWdsrfbjwW2DVT6CSvi7O05u9F88YPkfA_y2v-iSeWxDtPZ_2mOhWsrIvlLqLNQfUsWBtWf5jCxfw/s1600/nova3.png" width="76" /></a></div><i>These tools seem like they're very compact and full of features, maybe
to the point of feeling a little bit cramped or unintuitive, though it's
tricky to do something about that with this sort of screen resolution. I
do appreciate the manual that you can access whenever to find out how
to do stuff, and I'd rather have all the features than have a simplified
tool. I liked the "scan" button in the sprite editor; that's not
something I've really seen in pixel art programs.</i><p></p></blockquote><p>I can certainly agree with that. It isn't rare that I have to dig my own blog -- or worse, the source code -- of AnimEDS when I want to do something a bit less frequent like copy a frame to a given position, create a new skeletton or adjust hit boxes. I'll have to complete the "L+R to get hint on how to use things" but it's good news that someone noticed it and appreciated it. Maybe it could be completed by a "please explain that control" mode where you can touch something on screen and learn about it rather than use it ... <br /></p><blockquote><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKdpfhvq1ZXN8knEbVutHwxeNEwx9lN0yC3aL7fE1c7DQvo3lZmS0Hy4hz8X9_yxgYS3dGknS-NZ6xX3i-LJceY2vMTRWN3kbiY74YlNHIoem4IJF-mczSn9W2bMH0aH2icB_Sqczl8Y7dM2HoJzzNpK_Op3GpGjXNMKQdA-w-IDMjZ_BSD7Y-mQ/s96/nova2.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="96" data-original-width="76" height="96" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKdpfhvq1ZXN8knEbVutHwxeNEwx9lN0yC3aL7fE1c7DQvo3lZmS0Hy4hz8X9_yxgYS3dGknS-NZ6xX3i-LJceY2vMTRWN3kbiY74YlNHIoem4IJF-mczSn9W2bMH0aH2icB_Sqczl8Y7dM2HoJzzNpK_Op3GpGjXNMKQdA-w-IDMjZ_BSD7Y-mQ/s1600/nova2.png" width="76" /></a></div><i>I feel like it would help a lot to have buttons that bring up menus
(especially on the animation editor, which needs more explanation than
sprite editors do), where you'd have more room to make it clear what
each option does or avoid needing button combos so you can fit more
options on-screen, but that has to be weighed against how much it would
slow down a user who knows what they're doing. You *could* have quick
shortcuts with small icons alongside a button that brings up a menu
that's less compact, though.</i></blockquote>
<p>I have started something along these lines for 'monsters edition' in LEDS... That will be motivating to push it further</p>
<p>As you may have guessed, that lovely avatar for Nova comes straight from <a href="https://novasquirrel.com/">her website</a> ;)</p>PypeBroshttp://www.blogger.com/profile/10564522267743689261noreply@blogger.com0tag:blogger.com,1999:blog-34057821.post-55786056731720049012024-02-16T18:00:00.002+01:002024-02-21T22:00:38.894+01:00Sand "waves" completed.<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpcXjHvk4E0HdXJLH6AniAztCinPP17c1nwu5rs1Q_H59gbI3M7Kl0KoOvgjEApdncbo7sY-qheIcqsIVo92qzz8kCb10UfCY61abpkJrxi8Vn2VYr6WeIpWWFtIv42rOvS3kdjLjtYI3JLu-V16e0Zg_MY0qiD1PUjVKFbPwsb7d-t6On8-XfMA/s134/sandslope-timedc.gif" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="95" data-original-width="134" height="190" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpcXjHvk4E0HdXJLH6AniAztCinPP17c1nwu5rs1Q_H59gbI3M7Kl0KoOvgjEApdncbo7sY-qheIcqsIVo92qzz8kCb10UfCY61abpkJrxi8Vn2VYr6WeIpWWFtIv42rOvS3kdjLjtYI3JLu-V16e0Zg_MY0qiD1PUjVKFbPwsb7d-t6On8-XfMA/s1600/sandslope-timedc.gif" width="268" /></a></div><p>Bien. Ce coup-ci, je pense qu'on y est enfin. Le sable tombe, il fait un petit tas, le tas croule le long de la pente, puis se "dissout" au moment d'arriver à la chute suivante. ça reste "mode démo", celà dit: le code pour la pente à contresens n'a pas été testé et la longueur de la pente est hard-codée dans la "l'animation" de la vague qui descend. Mais ça fera l'affaire.</p><p><en><i>At last. Sands falls down, piles up, flows down slope and then falls again. The illusion is complete. The code is partly production-grade, partly demoshow-grade. Just what I need for a new release of the 3-rooms demo ... if only there wasn't that<a href="https://mastodon.social/@PypeBros/111937264608923953"> just-popping-up bug</a> in the School room >_<</i></en></p><p></p>PypeBroshttp://www.blogger.com/profile/10564522267743689261noreply@blogger.com1tag:blogger.com,1999:blog-34057821.post-39709331440409018822024-02-13T22:00:00.006+01:002024-02-16T10:39:00.595+01:00Ciao, Lime ?<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNPjaVNz6AWcLzhs6s3S9SgEEzSLbNrahshpCw8sd0z3yVRk36n_sncVJwruqEs6QaJxtR7AI33lEwmd8PxbQpzopomLTWKle6xcyZld1XWDaDyhiq1r3xu9anxN0R0pZ0-My4_Vk1r7-7N4hYJenh70Pf5hyphenhyphenwo_r3Zw6oK8_g4-D5oFokoW2V2Q/s2560/20240213_185603.jpg" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="1920" data-original-width="2560" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNPjaVNz6AWcLzhs6s3S9SgEEzSLbNrahshpCw8sd0z3yVRk36n_sncVJwruqEs6QaJxtR7AI33lEwmd8PxbQpzopomLTWKle6xcyZld1XWDaDyhiq1r3xu9anxN0R0pZ0-My4_Vk1r7-7N4hYJenh70Pf5hyphenhyphenwo_r3Zw6oK8_g4-D5oFokoW2V2Q/s320/20240213_185603.jpg" width="320" /></a><p><a href="https://sylvainhb.blogspot.com/2013/09/ca-fait-du-bien-jai-reussi-mener-bien.html">Depuis plus de 10 ans</a>, c'est surtout ma DS colorée "Lime" que vous voyez. C'est elle qui sert à dessiner des nouveaux pixels avec Sprite Editor, c'est elle qui a l'<a href="https://sylvainhb.blogspot.com/2020/08/reality-check.html">éditeur de niveau</a> à jour <a href="https://sylvainhb.blogspot.com/2021/12/greentmap.html">pour 3-rooms</a>. C'est encore elle qui va m'aider à faire des animations pour <a href="https://sylvainhb.blogspot.com/2023/01/how-it-is-bashing.html">les nouveaux personnages</a>.</p><p>Mais là, pour les derniers ajouts pour avoir du sable fluide, Lime me lâche. Son trigger gauche ne répond plus qu'occasionnellement, or il est absolument critique pour tous mes outils. C'est lui qui fait la différence entre "CTRL+C" et "CTRL+V" dans l'éditeur, la différence entre "pipette" et "pinceau" dans SEDS. La différence entre "charge en mémoire" et "enregistre sur ma carte SD" dans runme. Le bouton "L", c'est mon clic droit.</p><p><en><i>Hold the L trigger in one of my homebrews, and you're swapping between "pull mode" and "push mode". You pull a colour out of the SpriteEditor grid. You push a sprite into a sprite page. You push a colour into the palette, etc. Hold the L trigger on that Lime DS I've been using as gamedev unit for about 10 years and ... nothing happens. I want to pull the colour of a pixel and I push the current colour to that pixel instead. I want to push something to the sheet and I pull the older contents instead. Same if I try to pull the current tile of some spot of a level: I end up pushing the last used block instead. No need to say that this made the last step of "fixing the sand falls" super exasparatingly tedious.</i></en></p><p>Ce n'est pas la seule, bien sûr. Il y a aussi DarkneSs, qui était numéro 1 <a href="https://sylvainhb.blogspot.com/2010/06/hop-une-arene-yeah.html">pendant AppleAssault</a> mais qui <a href="https://sylvainhb.blogspot.com/2013/04/startra.html">depuis sa chute</a> a pris plus le rôle de <a href="https://sylvainhb.blogspot.com/2021/08/djlncmd.html">distracteur d'enfants</a> mais <a href="https://sylvainhb.blogspot.com/2019/08/starting-new-worldlevel.html">pouvait parfois ressortir</a> quand un test un peu plus audacieux (nouveau devkit, p.ex.). Un petit swap de linkers, un changement d'adresse IP dans mes commandes de transfers par WiFi et la voici prête à prendre le relai et poursuivre le marathon.</p><p>Les réparateurs de DS sont plus rares que dans les années 201x, évidemment, mais <a href="https://www.studio-quena.be/cyborgjeff/blog/2024/01/22/projet-la-game-boy-parfaite/">mon frère a pris pas mal de galon</a> dans ce genre d'entreprise. Je garde espoir qu'on puisse remettre cette console photogénique en selle d'une manière ou d'une autre. Ses écrans et sa batterie étaient encore parfaitement opérationnels. Ou a défaut lui trouver une remplaçante.<br /></p><p><en><i>Hopefully, that does not kill all hopes of seeing more homebrew contents from me. I still have my DarkneSs unit and its triggers seem all fine. Just swapping the linker cards, changing an entry in my IP addresses list and it's ready to take over the tasks. I have hope that the faulty trigger of Lime can be fixed, and my brother even offered a third option just in case (I'll have to find a name for a grey device, if we pick that up. Mithrandir might do)... Wait and see.</i></en></p><p>(Et pour faire bonne mesure, voilà la coque de protection de ma liseuse boox qui tombe en morceaux :/ )</p>PypeBroshttp://www.blogger.com/profile/10564522267743689261noreply@blogger.com1tag:blogger.com,1999:blog-34057821.post-6954864000023271632024-02-09T22:26:00.009+01:002024-02-21T08:20:34.064+01:00Sand falls<div style="background-attachment: scroll; background-clip: border-box; background-color: rgba(0, 0, 0, 0); background-origin: padding-box; background-position: 0% 0%; background-repeat: repeat; background-size: auto; background: url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_BLNnuAdODr1tL4y65dPtq2xIf4g-z2o_LQE8LijWL5DUgaOS16I5ktKasjTQJfx5v9yKRthCMfNRVq8pH3Abvvsl1C717sWt5ra0Q1KNOKW-0hFtesuF1-_3qylospq3kA9q56V7BhqAh2jHBmOTb3h40zf1rMYht1zfQPGuii3M6ihZ1Z1Agw/s320/Screenshot%202024-02-09%20at%2022-09-00%20Mastodon.png); float: right;"><iframe allowfullscreen="allowfullscreen" class="mastodon-embed" src="https://mastodon.social/@PypeBros/111903518047126936/embed" style="border: 0; max-width: 100%;" width="640"></iframe><script async="async" src="https://mastodon.social/embed.js"></script></div><div class="separator" style="clear: both;"><!--a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_BLNnuAdODr1tL4y65dPtq2xIf4g-z2o_LQE8LijWL5DUgaOS16I5ktKasjTQJfx5v9yKRthCMfNRVq8pH3Abvvsl1C717sWt5ra0Q1KNOKW-0hFtesuF1-_3qylospq3kA9q56V7BhqAh2jHBmOTb3h40zf1rMYht1zfQPGuii3M6ihZ1Z1Agw/s335/Screenshot%202024-02-09%20at%2022-09-00%20Mastodon.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="274" data-original-width="335" src=""/></a--></div><p>Il faut bien l'admettre, dans toutes ces animations de Bilou qui est <a href="http://sylvainhb.blogspot.com/2023/12/tapis-roulant.html">repoussé par les chutes de sables</a> et de décor en pseudo-3D réalisé <a href="http://sylvainhb.blogspot.com/2024/01/raycasting.html">à grand coup de HDMA</a>, la chute de sable tout en pixels statiques, ça ne rendait pas particulièrement convainquant. C'est donc maintenant ma dernière étape avant une petite riliize de ma démo 3-écrans. <br /></p><table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 6px;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgI36f1ebw4iTiZ4cRrSAvjINVhGGEQVX3tlYsLmWnFtYpqm2tMILuKJx5jLqHw-gCob7YH919ZvXPbYymRaIvbtJHW5FkSqoT6N4YBTToKvAu3QYdcjO48kSPg3F3l8nXq0j5HrVE1TyRS0eEZjE6Ty7LLQ8_0qR6qSrJ-JMF6a-AkIqemSgZEfg/s1344/FW_3MHMWYAAAzav.png" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" data-original-height="768" data-original-width="1344" height="183" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgI36f1ebw4iTiZ4cRrSAvjINVhGGEQVX3tlYsLmWnFtYpqm2tMILuKJx5jLqHw-gCob7YH919ZvXPbYymRaIvbtJHW5FkSqoT6N4YBTToKvAu3QYdcjO48kSPg3F3l8nXq0j5HrVE1TyRS0eEZjE6Ty7LLQ8_0qR6qSrJ-JMF6a-AkIqemSgZEfg/s320/FW_3MHMWYAAAzav.png" width="320" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Anokolisa mock up, <a href="https://twitter.com/Anokolisa/status/1544725227300601856">initial reference</a><br /></td></tr></tbody></table><p><en><i>Almost every time I posted a video about Bilou being pushed by sandy slopes or about the pyramid background 3D scrolling, I couldn't help being sorry for the flat, uninspired, unanimated sands fall that are present since the first release of the '<a href="http://sylvainhb.blogspot.com/2021/12/3-rooms-release-early.html">three rooms</a>' demo. That's the last thing I want to fix before I release a new one.<br /></i></en></p><p>ça fait un moment que j'avais <a href="https://anokolisa.itch.io/high-forest-assets-pack">ce mockup d'Anokolisa</a> parmi mes images à étudier et j'avais même quelques <a href="https://twitter.com/pypebros/status/1624873190538285057">gribouilles assez réussies</a> de comment ils étaient construits ... mais vous en conviendrez, du miel et du sable, ça ne s'écoule pas granchement de la même manière.</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhi9u6Z5JAE0jVBQCVoNvctBlpkrdO1sW5aaM3z0z-XAoUjtexlHxDL6vMi-4ikID_5p8TW-v7JkELSUBi56KiNFXES9vDuQDeP3ebZvj7CYB4g5hgw82h5UOuzNUWZRFzcN3KhfpgFEJrrtw7ORqzctX08YbgzAX1SLJbF1HiG1fGpEQeWb_3Vzg/s128/sandfall-sonic.png" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="127" data-original-width="128" height="127" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhi9u6Z5JAE0jVBQCVoNvctBlpkrdO1sW5aaM3z0z-XAoUjtexlHxDL6vMi-4ikID_5p8TW-v7JkELSUBi56KiNFXES9vDuQDeP3ebZvj7CYB4g5hgw82h5UOuzNUWZRFzcN3KhfpgFEJrrtw7ORqzctX08YbgzAX1SLJbF1HiG1fGpEQeWb_3Vzg/s1600/sandfall-sonic.png" width="128" /></a></div>J'ai fini par retourner regarder les graphismes de la <a href="https://www.spriters-resource.com/genesis_32x_scd/snk/">Sandopolis Zone dans Sonic</a> & Knuckles ... qui au final étaient assez simples de ce côté-là: un cycle de 4 couleurs dans la palette, un tramage par-ci, une rangée de pixels transparents par là ... j'ai essayé de m'en inspirer et ça rend assez correctement pour une première démo, je trouve. Il me reste encore à animer 'le sable qui descend le long de la pente'. Voyons si le week-end m'offre le temps de faire ça ;)<br /><p></p><p><en><i>But it is a bit tricky to find good pixelart reference for such item. For quite some time, I thought I could use something inspired by Anokolisa's Hive tileset, until I realised that it would never flow like sand, no matter how close I could get from that brilliant design. Neither <a href="http://sylvainhb.blogspot.com/2023/02/souldiers-pyramid.html">Souldiers</a> nor <a href="http://sylvainhb.blogspot.com/2023/01/megaman-bass-ground-man-pixel-art-and.html">Megaman</a> could help, but I finally remembered about <a href="http://sylvainhb.blogspot.com/2019/02/sandopolis-zone-and-mega-tiles.html">Sonic's Sandopolis Zone</a>, burried in early reference hunts. A quick check on youtube convinced me that, once in motion, they are good looking. Their design is quite simple, though: wavy patterns of 4 colours that will be palette-cycled. When they have to become half-transparent, non-solid tiles, they are alternated with empty columns or dithered with transparent pixels. That's enough for a CRT screen, but I will likely require something a bit more subtle for the LCD screen of the Nintendo DS. Well, my pattern is more angled, but it seems to be good-looking enough, given mastodon reaction.<br /></i></en></p><p><en><i></i></en></p><div class="separator" style="clear: both; text-align: center;"><i><a href="https://twitter.com/pypebros/status/1624873190538285057" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="261" data-original-width="527" height="158" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj79GSZJpAnC-L-8r_SpgLWTMSs0LURkKb-L3pZkFxL4pJ3RLQglNAeQuKDJIwHBmBw7brSbVCikAYWe9FjFTmeJUzr1n5EnhK1SkAUkJLWCNrnCWqwsI4HxyRdgmoTB8ClLAUo5uaWQJASIF-LwrISrS53IwJAr5WUhFiBupAN9AGJjH5DBmvQ0Q/s320/Screenshot%202024-02-11%20at%2008-59-06%20Pype%20on%20X%20Finally%20done%20those%20sands%20%23pixelstudy%20https%20__t.co_PsHTT45io0%20_%20X.png" width="320" /></a></i></div><i>Now I have to aslo animate the slope itself, but checking Souldiers again, I believe I might better <a href="https://sylvainhb.blogspot.com/2024/02/sand-waves-completed.html">spawn waves periodically</a> and let them roll down a static ground than trying to animate it all as I did for the sand falls (scoop: I'm not using palette cycling this time)<br /></i><p></p><br />PypeBroshttp://www.blogger.com/profile/10564522267743689261noreply@blogger.com0tag:blogger.com,1999:blog-34057821.post-81486640931894409792024-02-07T09:06:00.001+01:002024-02-07T10:26:21.590+01:00Appleman 2.0<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhLpUfIJwVvvyIEshCOQ7Gd2QKm_96t0zE6iPgVnONVqKZjwuGo0mkTH5x-W02_mXouKh8uwVY5HE-znSg-gndAK3o9LPp5a2ZER2oJwagtZWHBhR5_wjR57-Z7kTVecL059y5yuJ1cotrXzs7Dd7Qik-vTG8WUuWaPhLqUPEEAEpf41RE9s3Qaw/s384/page11.png" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="384" data-original-width="254" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhLpUfIJwVvvyIEshCOQ7Gd2QKm_96t0zE6iPgVnONVqKZjwuGo0mkTH5x-W02_mXouKh8uwVY5HE-znSg-gndAK3o9LPp5a2ZER2oJwagtZWHBhR5_wjR57-Z7kTVecL059y5yuJ1cotrXzs7Dd7Qik-vTG8WUuWaPhLqUPEEAEpf41RE9s3Qaw/s16000/page11.png" /></a></div>Bon, je me suis enfin refait les animations de l'Appleman dans l'éditeur d'animation modulaire. C'est que déjà avant que je ne m'attaque à Apple Assault, j'avais dans l'idée que Bilou puisse ramasser <a href="http://sylvainhb.blogspot.com/2009/11/grab-me-shoot-me.html">le corps de l'Appleman</a> pour s'en servir ensuite de projectile. Puis c'est plus cohérent avec le comportement de dumblador qui joue le même rôle dans la School Zone.<p></p><p>Sauf que, vous vous en doutez, ça ne s'est pas passé sans mal. D'abord quelques plantages de MEDS (oui, encore) qui m'ont obligé à tout refaire, puis le niveau qui ne voulait plus rien charger le temps que je lui réexplique où se trouvent les animations demandées et que je corrige celles qui étaient lues en boucle alors que la machine d'état prévoit une transition "à la fin de l'animation".</p><p><en><i>You could easily claim that this was a cursed sprite and I would almost believe you. See, I've had applemen pixels from over 15 years now, and yet I wanted to upgrade its motion into a compound sprite. The idea would be to make it more <a href="http://sylvainhb.blogspot.com/2012/12/games-of-thrown.html">like the dumblador</a>, losing its feet when stomped, staying stunned until feet are recovered etc. I expect that it would feel fun...</i></en></p><p><en><i>Then the curse started, with blue screens in the editor as I tried to "clean up" some animations, despite I fixed <a href="http://sylvainhb.blogspot.com/2023/09/un-ptit-coup-de-marteau.html">something similar</a> in September. Then the level would no longer load because some of the newly defined animations were looping and <a href="http://sylvainhb.blogspot.com/search/label/apple%20assault">AppleAssault</a> assumed it could wait for them to be <code>done</code> for some transition. And when all that was fixed, with WiFi transfers over RunMe through <a href="https://sylvainhb.blogspot.com/2019/03/nohup-nuc.html">the NUC</a>, the appleman did not have feet but huge, purple fists instead.</i></en></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiM15AyzKJSf-RYHbqKPxTPxw1gUiZIdudN8B4dJUr9-tdwwY34JJCeZjCgIdtCYH2ieI8kG1L75cjOaPyZA8YUla0xVv0cxPCgnH2dvB8N_zSwVI2oB3Q_v3Pshldr0xg9bH5S-XAOsq_6O6PkCf3rEh-QrEGx0BJ8XDgyj5Qe-IvPQkX1pi0wWA/s120/weirdo.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="120" data-original-width="120" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiM15AyzKJSf-RYHbqKPxTPxw1gUiZIdudN8B4dJUr9-tdwwY34JJCeZjCgIdtCYH2ieI8kG1L75cjOaPyZA8YUla0xVv0cxPCgnH2dvB8N_zSwVI2oB3Q_v3Pshldr0xg9bH5S-XAOsq_6O6PkCf3rEh-QrEGx0BJ8XDgyj5Qe-IvPQkX1pi0wWA/s16000/weirdo.png" /></a></div>Ensuite, voilà que les pieds de l'appleman sont <a href="https://mastodon.social/@PypeBros/111863772431107059">remplacés par des gros poings mauve</a> alors qu'il devrait réutiliser les pieds de Bilou relookés en brun. La faute à un code encore un peu trop jeune dans le chargement d'un 2eme fichier de graphismes. Les couleurs erronées, ça, ça m'aura pris plus de temps. Je me replonge dans le <a href="http://sylvainhb.blogspot.com/2022/01/ca-boume-vieille-branche.html">code d'il y a 2 ans</a>, je vérifie qu'on a bien assez de mémoire vidéo pour charger tout ce petit monde (scoop: oui. On a 16KiB, assez pour 8192 couleurs alors que les 16 palettes accessibles par les sprites n'en consommeraient que 4096)<p><en><i>To get proper images, the first thing is to ensure <a href="http://sylvainhb.blogspot.com/2023/10/done-transition-on-looping-animation.html">SpritePages are properly remapped</a> when loading the additional set. For the school zone, that was done with <code>spr.more "school.spr" <u>page8,82</u> meds+4</code>. Yeah, I know. That's not the most self-documenting line of script in the world ^^". What's important here is <code>page8,82</code>. That is controlling the remapping. </i></en></p><ul><li><i>The first number (8) indicates that we expect Bilou.spr to feature 8 sprite pages, and that pages for "school.spr" are to be numbered 8, 9, 10, ...</i></li><li><i>The second is not a number: it is a series of digits each identifying a page, and each telling where each page is starting with the 8th slot. Page 8 remains unchanged (since the series starts with an 8), but page 9 will use page 2 instead (where Bilou hands and feet are)</i></li></ul><p></p><p><en><i>That was for the school zone, but the green zone spriteset did not have hand and feet. Instead, they had to be added as the 11th page within the set ... almost page 20 for the level. <a href="https://sourceforge.net/p/dsgametools/hg/ci/0690fee758ceaa0fc17bf26481c673da8437687d/">Code parsing that was a bit crude too</a> and was never meant for things identifying page number higher than 10. Oh, you could do it, but you might have to identify page 11 in the whole set with <code>;</code>. I tried to simplify that a bit so that we can actually use <code>spr.more "green.spr" page8,-..---.----2 meds+4</code> instead. Here,</i></en></p><ul><li><i> every <code>-</code> in the sequence means "that page holds no sprites. It shouldn't be used by animations".</i></li><li><i> <code>.</code> means "don't touch: that page is perfect as it is". Any sprite page in green.spr has such a dot.</i></li><li><i> And you know about the final <code>2</code> already: it identifies one page within bilou.spr that must appear instead of a "draft" page of green.spr and be used by Appleman animations</i></li></ul><p></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj256VVebuxhTip2Iu2kHFnp0lMUvzqnqM3b40bRrVlhs7nGEfEXZfbAxwyHI1ZxHtfghI19bwpLpkD7sjITnaPy441C1wp68dBGQ5cOcfD6uKm34DrY6noXp59x1l0yi5VF7zCyKhTX2c0XUOxn-zwi4GW1cOW-daZnDuICG4ubjvLD6FnbdG0kA/s433/bad-apple-colors-2024-02-07%20082847.png" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="367" data-original-width="433" height="271" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj256VVebuxhTip2Iu2kHFnp0lMUvzqnqM3b40bRrVlhs7nGEfEXZfbAxwyHI1ZxHtfghI19bwpLpkD7sjITnaPy441C1wp68dBGQ5cOcfD6uKm34DrY6noXp59x1l0yi5VF7zCyKhTX2c0XUOxn-zwi4GW1cOW-daZnDuICG4ubjvLD6FnbdG0kA/s320/bad-apple-colors-2024-02-07%20082847.png" width="320" /></a></div><p><en><i>Definitely, some colors from green.spr were loaded here. We wouldn't have the sprite-branch with colours that close to those of the trunk otherwise. But the yellow worm now has weird blueish outlines and the appleman feet are both light-Bilou-green rather than having one dark brown and the other darker brown. </i></en></p><p>Et là, la raison était plus ... exotique, on va dire. Le code C++, rien à redire. C'est presque limpide: ça *doit* ajuster les commandes qui définissent les images et palettes utilisées par les personnages, à condition que le décalage soit correct. Et le décalage, je fournis à la main dans le script du niveau. Mais manque de bol: le compilateur (gcc 8.1.0 ajouté à devkitARM 49 en 2018) produit du code machine qui ne correspond pas à ce qu'il me faut (<a href="https://sylvainhb.blogspot.com/2021/01/only-6-releases-and-25-years-behind.html">une fois encore</a>). Vérification faite, le gcc 10.1.0 du devkitARM 54 ne fait pas mieux. Pour avoir enfin mes bonnes couleurs, il faudra que je réexprime mon code différemment pour contourner ce qui semble être un bug dans le générateur de code ou dans l'optimiseur ...<br /></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOF7ammbU4g5OFAymvhjTa86Vb1yMREUkSh3JpN-kpDtXZfO0luZTAAym3I4huFtJdcqjOzdDeU7tLjgjyS6Zt49EwhXeQk8ZNEpyYlRnjecDCvRcOP16QBf1Yo2WzrVuS-hNv82UxJMav8nVDJXJkjZAN_S9NF71WJ9ZnL73SbfPCd6FnH613hA/s517/cb99af10c7cd7e5a.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="286" data-original-width="517" height="177" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOF7ammbU4g5OFAymvhjTa86Vb1yMREUkSh3JpN-kpDtXZfO0luZTAAym3I4huFtJdcqjOzdDeU7tLjgjyS6Zt49EwhXeQk8ZNEpyYlRnjecDCvRcOP16QBf1Yo2WzrVuS-hNv82UxJMav8nVDJXJkjZAN_S9NF71WJ9ZnL73SbfPCd6FnH613hA/s320/cb99af10c7cd7e5a.png" width="320" /></a></div><p><en><i>There's a line in the remapPages() function that should deal with that: find "change sprite" instructions in the animation code, isolate the current palette value and add the "adjust palette" computed by the caller. It should work, really, but single stepping through the code with all the optimized-away locals left me puzzled. So I dug deeper, taking notes of the machine code, tracking what register meant what and ... 0_0</i></en></p><p><en><i>and there was no add instruction to be found. Nowhere in the loop. The machine code generated by gcc 8.1.0 would just assign the same green_palette[0] to every sprite no matter what palette they were using. That seemed to happen with gcc 10.1.0 as well... it wasn't <a href="https://sourceforge.net/p/dsgametools/hg/ci/3dc7100419840a42783eee9c22f78c1ae158553b/">too hard to work around</a>, but yet. Troublesome.</i></en></p>PypeBroshttp://www.blogger.com/profile/10564522267743689261noreply@blogger.com1tag:blogger.com,1999:blog-34057821.post-35291286063258672592024-01-31T23:00:00.001+01:002024-02-01T09:37:14.170+01:00Hello 2024<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkKPAxTwf8dg46LVV39sEsWiHuMQStT_Tamf_5N5bJsF9GtAgnB_hU34x60srHvbumtgJMfRJZ18sWMQQhqbWxEJ9aU9ZpmOIGCBVVWow5u4BFP2n3rcsv8gwdeW36W7UbXH9XNHvClAGheSN3vMdD-SyOvstagB-jhYAv2X1Crq1wRXg25rWi2g/s1014/blog2024.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="600" data-original-height="417" data-original-width="1014" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkKPAxTwf8dg46LVV39sEsWiHuMQStT_Tamf_5N5bJsF9GtAgnB_hU34x60srHvbumtgJMfRJZ18sWMQQhqbWxEJ9aU9ZpmOIGCBVVWow5u4BFP2n3rcsv8gwdeW36W7UbXH9XNHvClAGheSN3vMdD-SyOvstagB-jhYAv2X1Crq1wRXg25rWi2g/s600/blog2024.png"/></a></div>
<p><en><i>Hey! The blog has finally reached over 1M views before it turned 20 years old! Not that it means much since most of the hits are likely scans from automated tools like the Internet Archive (or search engines Google doesn't know about). But yet, it is nice. I totally missed the opportunity to release something significant for the 30th anniversary of Bilou, but it has been an inspiring year and I haven't dropped the dream of a more elaborate game. So Happy new year ;)</i></en></p>PypeBroshttp://www.blogger.com/profile/10564522267743689261noreply@blogger.com0tag:blogger.com,1999:blog-34057821.post-24599325902094342502024-01-29T22:09:00.005+01:002024-02-09T22:00:28.029+01:00Over-engineered ?<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikPkM10uVKTJJZ3Qr3LeYNgvXWYkb2Q-GG_rWA4Wo3JP84us7o1hBhlSgXokWWsG4myvDtKy12sOyM0f3wpmWV6Wp-zf80o8jaBZTp2ju0w8BIHZY7YE8SKi_0WnwU7G93aUh1fqYoBLI38MZrmA3B3GQCyfGq0RTDbvG4jdpCPC5tiFfgxpJ-bQ/s1600/Screenshot%202024-01-28%20at%2022-53-38%20PypeBros%20%28@PypeBros@mastodon.social%29.png" style="clear: right; display: block; float: right; margin-left: 1em; text-align: center;"><img alt="" border="0" data-original-height="140" data-original-width="424" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikPkM10uVKTJJZ3Qr3LeYNgvXWYkb2Q-GG_rWA4Wo3JP84us7o1hBhlSgXokWWsG4myvDtKy12sOyM0f3wpmWV6Wp-zf80o8jaBZTp2ju0w8BIHZY7YE8SKi_0WnwU7G93aUh1fqYoBLI38MZrmA3B3GQCyfGq0RTDbvG4jdpCPC5tiFfgxpJ-bQ/s1600/Screenshot%202024-01-28%20at%2022-53-38%20PypeBros%20%28@PypeBros@mastodon.social%29.png" /></a><p><en><i>Maybe I'm starting that "<a href="http://sylvainhb.blogspot.com/2024/01/nager-mieux.html">swim made fun</a>" thing by the wrong end. What I really need is to be able to move Bilou through water and to get him out of the water. Sure it is fun to swim in Rayman Origins, it was pleasant in DKC and a nightmare in TNMT on NES. But unlike all these games, I have no "water level" planned in Bilou: Dreamlands. The reason why I started working on dash-in-water is not because travelling through water would feel empty without it. It isn't even because I have level sketches where jumping out of water is a key mechanics. It is solely because in the current demo, you can't reach the green room exit unless you trigger an unintended double-jump with precise button mashing that should be left to speedrunners.</i></en></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZgrBtwyCCzP8JIyJ4YCfs55zI5ddEl2L21QCx6y9PYm-UOFFH4Ta8UpCvC4KdxmU4ClKrSjt75jFzJXtBNVAs96dGeNVYtgbL8QH5H_X6nHGJI4USxVaer7YmocBUTi-ZLQADOQ8KXHkaLIVfbPRZ00DnyQsveRFADRQIMjzlrRokO37ugr1vTg/s568/Screenshot%202024-02-09%20at%2021-59-29%20Mastodon.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="408" data-original-width="568" height="230" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZgrBtwyCCzP8JIyJ4YCfs55zI5ddEl2L21QCx6y9PYm-UOFFH4Ta8UpCvC4KdxmU4ClKrSjt75jFzJXtBNVAs96dGeNVYtgbL8QH5H_X6nHGJI4USxVaer7YmocBUTi-ZLQADOQ8KXHkaLIVfbPRZ00DnyQsveRFADRQIMjzlrRokO37ugr1vTg/s320/Screenshot%202024-02-09%20at%2021-59-29%20Mastodon.png" width="320" /></a></div>J'avais donc un <a href="http://sylvainhb.blogspot.com/2024/01/nager-mieux.html">beau projet</a> pour les mouvements dans l'eau. Je venais de commencer à ajouter "on accélère si on appuie sur JUMP" et J.L.N a pris "la manette" en main. Il a nagé à droite. Il a nagé à gauche, puis il a voulu sortir de l'eau. Et bien sûr, lui n'a pas attendu que Bilou revienne à l'état "je patauge en attendant" avant de presser le bouton de saut: il l'a fait depuis l'état "bilou nage à gauche", là où j'avais prévu un "fonce dans l'eau vers la gauche" en réaction au bouton "pied"... Bilou n'a donc même pas tenté de s'élever d'un pixel. J'avais échoué le test n°1 de Miyamoto: "the JUMP button makes Jumpman jump". Et donc je me suis enfin posé la bonne question: "Est-ce que j'ai vraiment besoin de tout ça, moi?"<p></p><p>Parce que dans mon cahier bleu, avec les <a href="http://sylvainhb.blogspot.com/search/label/level%20design">croquis de level design</a> que j'ai l'intention d'utiliser pour <a href="http://sylvainhb.blogspot.com/2020/02/bilou-dream-land-codename.html">Bilou's Dreamland</a>, l'eau est bien présente, mais je n'ai jamais un "niveau aquatique" à proprement parler. Ce qui motive cette recherche sur les mouvements dans l'eau, c'est juste le fait que la berge est trop haute <i>dans la démo</i>. Et donc, garder une mécanique simple <i>"JUMP" à la surface = sauter hors de l'eau</i> et <i>sauter hors de l'eau près de la berge = sortir de l'eau</i> serait impeccable si j'éditais un rien l'écran-démo pour que sa berge soit un tile plus bas ^^" (et éventuellement que j'augmente de 15% la hauteur du saut depuis l'eau, actuellement défini au doigt mouillé) <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhY5_HZcfQrSBTrZn80JOrkv2UHBmmhT5SjUW25obw8MRa24tNNAzpINrb8FWvnEkdcJuDVN2Bkm62x1mgsVf5bHJjFSutkTxCv8tXBcu7AYpYJ-7JLQwf1lirYec6BxEt_oktxD_3EQLJs0xVy1kQCMf3FcWDio9tQ2qKhm94TZqWkdTM5Yl5Apw/s1600/swim-fixb.gif" style="clear: right; display: block; float: right; margin-left: 1em; text-align: center;"><img alt="" border="0" data-original-height="93" data-original-width="101" height="186" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhY5_HZcfQrSBTrZn80JOrkv2UHBmmhT5SjUW25obw8MRa24tNNAzpINrb8FWvnEkdcJuDVN2Bkm62x1mgsVf5bHJjFSutkTxCv8tXBcu7AYpYJ-7JLQwf1lirYec6BxEt_oktxD_3EQLJs0xVy1kQCMf3FcWDio9tQ2qKhm94TZqWkdTM5Yl5Apw/s1600/swim-fixb.gif" width="202" /></a> </p><p><en><i>I wanted to use the opportunity of changing the level map to also fix an issue I had with the interaction of <a href="http://sylvainhb.blogspot.com/2024/01/de-leau-par-ci-de-leau-par-la.html">surface-swimming</a> and <a href="http://sylvainhb.blogspot.com/2023/11/tile-4-swimflow-2560.html">following the water flow</a>. I presume that the core of the issue is that the *middle* of the character's bounding box is used to determine whether there's a flow to follow. But "stay at the surface" code maintains Bilou above the flowing tiles. As soon as one pixel of the box enters the "full water, flowing downwards" tile, it starts pushing Bilou upwards.</i></en></p><p><en><i>I made a few bad moves, like trying to have full-water-flow-downwards tiles higher (closer to the surface), but that <a href="https://mastodon.social/@PypeBros/111829779324436776">didn't work</a> at all. Instructing the level that "water-flowing-downwards" can be felt through did work pretty well, I think.</i></en></p><p>Pendant que je testais cette nouvelle map avec sa nouvelle "berge" moins haute, je me suis rendu compte que <a href="http://sylvainhb.blogspot.com/2024/01/de-leau-par-ci-de-leau-par-la.html">depuis qu'on sait nager à gauche et à droite</a>, les remous de la cascade <a href="http://sylvainhb.blogspot.com/2023/11/tile-4-swimflow-2560.html">ne nous entrainent plus vers le fond</a>. La flottaison est trop efficace et le centre de Bilou n'entre plus dans la zone qui le tire vers le bas. J'ai un peu chipoté, mais heureusement, il suffisait de permettre à Bilou de "tomber" aussi dans cette zone pour que tout rentre dans l'ordre (enfin, je pense)<br /></p>PypeBroshttp://www.blogger.com/profile/10564522267743689261noreply@blogger.com0tag:blogger.com,1999:blog-34057821.post-22859350512897395252024-01-23T17:50:00.000+01:002024-01-23T17:50:42.057+01:00Input Buffering.<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_dqR6j7AUKzafBdHcCq3RWvXbx5Ibrnph3_I-TKWJJ09NWLRJXdLu_d0CwtgQVAO8XEVfL36RNNS45j6umJFa7vccn1L9lee-MPup6W_pq2nWbD9PP9tP0JU5Gy4wqUJ-PVZmX0I-oa_eMePX9QpEU3dIi6oyvYSa1rKOvEUxvTXbo0AkV22I4Q/s435/Screenshot%202024-01-12%20at%2018-24-12%20Mastodon.png" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="217" data-original-width="435" height="160" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_dqR6j7AUKzafBdHcCq3RWvXbx5Ibrnph3_I-TKWJJ09NWLRJXdLu_d0CwtgQVAO8XEVfL36RNNS45j6umJFa7vccn1L9lee-MPup6W_pq2nWbD9PP9tP0JU5Gy4wqUJ-PVZmX0I-oa_eMePX9QpEU3dIi6oyvYSa1rKOvEUxvTXbo0AkV22I4Q/s320/Screenshot%202024-01-12%20at%2018-24-12%20Mastodon.png" width="320" /></a></div><p>Tout est parti d'un tweet de <a href="https://caseportman.itch.io/">Case Portman</a>, auteur du jeu "<a href="https://t.co/pwTdznhEdc">Flynn, Son of Crismon</a>" dont je suivais le développement dans lequel il nous expliquait en quoi le <a href="https://twitter.com/Case_Portman/status/1610951512456404992">"jump buffering" est fondamental</a> dans tout jeu de plate-forme. Un nom un peu barbare pour les francophones qui consiste plus ou moins à faire du voyage temporel avec votre manette de jeu.</p><p>Quand le joueur est au sol et qu'il fait sauter son personnage, on s'attend à ce que le saut soit pris en compte à la frame exacte où le bouton est enfoncé. Pas trop difficile. Supposons que le joueur veuille rebondir sur le sol en finissant un saut. Il sera assez fréquent qu'il appuie sur le bouton de saut <i>légèrement avant</i> de toucher véritablement le sol. Son intention est de rebondir. Le code peut faire deux choses: soit ignorer la demande de saut vu qu'on est en l'air, soit effectuer un saut dès que l'on atteint le sol. Et clairement, les jeux qui suivent la première approche sont <a href="https://sylvainhb.blogspot.com/2019/11/rayman-sur-super-nes-vs-fantasia-sur.html">désagréables pour les joueurs</a>.</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://twitter.com/Case_Portman/status/1183067181480890368" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="382" data-original-width="517" height="236" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8TrtY83AntTaPsDtHzI__xGSFutmse8-0Kz0CBVcnetcIPzVIvGnnGilN-8OwP-6o-wVTyYG0i6KeltT3cTS_1hTTo-Urp-6ocdQm3D4W7An85XTczxpWjKU1vDf6h8EjMNcv7U8Ibsk6XB9UPT8NLgkcNmPMcPtAm7R49K5a3sBMUi4OKQZ8Dw/s320/Capture%20d%E2%80%99%C3%A9cran%202024-01-23%20171704.png" width="320" /></a></div><p><en><i>In my notebook for 2022-2023, I had a small page about <a href="https://twitter.com/Case_Portman/status/1183067181480890368">Case Portman's post on Jump Buffering</a> (link recovered, thanks, search Engine :P), where the author of "Flynn, Son of Crismon" explains:</i></en></p><p></p><blockquote><p><i><span class="css-1qaijid r-bcqeeo r-qvutc0 r-poiln3" style="text-overflow: unset;"> It's a nifty little feature that will add *a lot* more flow to your game. This can also be applied to almost any action! Shooting, melee attacks, dodge rolls, even menu selection.</span></i></p></blockquote><p><i>Don't let the name frighten you: what it truly means is that you're time-traveling with your DPAD, pretending than your jump button presses did not happen when they did. If time was a photoshop/gimp layer, then jump buffering would be something like "snap to guide". He went on with a detailed and beautiful gif animation showing how to achieve that and make the game more tolerant on the case where player is about to land on ground and press the jump button in one of the last few frames mid-air. Many 8-bit games failed to do so and feel unfair when played.</i></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4LMmNAeJ-Bt3eWa5cv2yhUHuJmuPUH4bdR8-eVWgc9l5fQ9f_q04rme33D2A_YsNNTYOrNvUnFJuO7Z_-iDOg68dQoNi-d4hszqeUUaf9A_m6bXUeJN232jPsBY0dzV12m0wE-Y_2Fbb8larTohTOO_EJTR1oM5sRfpGQObYeG75lmljZIwaYTw/s392/Screenshot%202024-01-12%20at%2018-25-13%20Mastodon.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="284" data-original-width="392" height="232" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4LMmNAeJ-Bt3eWa5cv2yhUHuJmuPUH4bdR8-eVWgc9l5fQ9f_q04rme33D2A_YsNNTYOrNvUnFJuO7Z_-iDOg68dQoNi-d4hszqeUUaf9A_m6bXUeJN232jPsBY0dzV12m0wE-Y_2Fbb8larTohTOO_EJTR1oM5sRfpGQObYeG75lmljZIwaYTw/s320/Screenshot%202024-01-12%20at%2018-25-13%20Mastodon.png" width="320" /></a></div><p>Dans mon moteur de jeu, tout celà est pris en compte par le contrôleur "<code>dpad</code>". Pour chacun des boutons, ce contrôleur retient si le bouton était déjà enfoncé lors de la frame précédente, et pendant combien de temps encore il doit être considéré enfoncé. La fenêtre de temps autorisée (6 frames, soit 1/10eme de seconde) sera la même pour tous les boutons. Je me suis refait un petit schéma de la manière dont c'était géré parce que je l'avais complètement perdu de vue. "<code>to[i]</code>" sur ce schéma, c'est le timeout associé à un bouton donné.</p><p><en><i>I realised then that how my engine does this slipped out of my brain: it was about time to document it and blog it. It all happens in the DPAD controller, where a counter will be started if a "new press" is detected and reset if the button is released. The counter is decremented every frame while you're holding the button. But earlier tests in SchoolRush shown that this is not enough. In some part of the character behaviour, we actually *must* indicate directly whether the button is still pressed. Without that, there's no such thing as "<a href="https://sylvainhb.blogspot.com/2013/06/dpadcontrollertimeout.html">keep jumping higher as long as player holds JUMP button</a>" or "keep floating as long as player holds JUMP button". My engine handles that with a bitmask that indicates which button should report "pressed" instead of "held".<br /></i></en></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigozEZQR8c2H7WM-H77t-xoZkD-in2AjbhUxY9LcX23g6odw5GHSTF3xKmXLr1MLWzp8EplTwHnM-k00bMQkEEo6VktmXpDRhTJda9M3L9ca0YSIgF2WfS40NVLsAN65GXOZmoLjS7TCU2cxZm4Ejus3v81CKpk2XAzc43UUqPJ-ziNiDppzXWeA/s536/Screenshot%202024-01-12%20at%2018-25-00%20Mastodon.png" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="350" data-original-width="536" height="209" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigozEZQR8c2H7WM-H77t-xoZkD-in2AjbhUxY9LcX23g6odw5GHSTF3xKmXLr1MLWzp8EplTwHnM-k00bMQkEEo6VktmXpDRhTJda9M3L9ca0YSIgF2WfS40NVLsAN65GXOZmoLjS7TCU2cxZm4Ejus3v81CKpk2XAzc43UUqPJ-ziNiDppzXWeA/s320/Screenshot%202024-01-12%20at%2018-25-00%20Mastodon.png" width="320" /></a></div>Par contre, on peut définir état par état quels sont les boutons pour lesquels on veut un mécanisme du type "enfoncé il y a au plus 1/10eme de seconde" et ceux pour lesquels on veut "maintenu enfoncé depuis aussi longtemps qu'on veut. <p></p><p>Quand on définit "<code>MOVE + FOOT</code>" pour l'état "flotter" (dans les airs, façon super-cape de SMW), ça signifie que le DPAD et les boutons de sauts ne passeront jamais par "decrease timeout". l'état "chevauchée d'éponge" évitera quand à lui de faire expirer "<code>MOVE + HANDS</code>". Et pour tous les états où on a rien précisé, c'est le DPAD et la gâchette droite (qui sert de déclencheur pour la course) qui seront maintenus.<br /></p><p><en><i>But watch the catch: while the controller code defaults to 'held', the script <a href="https://sourceforge.net/p/dsgametools/hg/ci/default/tree/libplugins/source/dpad.cpp#l63">instead</a> </i></en><en><i>indicates which inputs are expected to be "held", and defautls to "press" ... that's why you see '<code>using dpad(MOVE|FOOT)</code>' for the FLOAT state, where it prevents the press to expire while floating.<br /></i></en></p>PypeBroshttp://www.blogger.com/profile/10564522267743689261noreply@blogger.com0tag:blogger.com,1999:blog-34057821.post-2257176735297728872024-01-22T21:09:00.007+01:002024-03-02T10:00:04.376+01:00How long before we play ?<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIzPO3P8yAHX4CnhYR0YygjPgpCkHGnGgBSU-nnPFdhKJxsUA4JO0LyCp5VH-Bz6S606mjzPkKTbjQlCvURA3gQNnGHTcgU-nI3Cv1ya7U54QPicyMGduv4F7xPALaMIxboDzxzB7amDi8UYBkNvIBINXY1Nl08bkdKBbWXLq96Ad8AkrKdEHRmQ/s2448/howlong-798e4e4c8a4c3924.jpg" style="display: block; padding: 1em 0px; text-align: center;"><img alt="" border="0" data-original-height="2448" data-original-width="2396" height="600" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIzPO3P8yAHX4CnhYR0YygjPgpCkHGnGgBSU-nnPFdhKJxsUA4JO0LyCp5VH-Bz6S606mjzPkKTbjQlCvURA3gQNnGHTcgU-nI3Cv1ya7U54QPicyMGduv4F7xPALaMIxboDzxzB7amDi8UYBkNvIBINXY1Nl08bkdKBbWXLq96Ad8AkrKdEHRmQ/s600/howlong-798e4e4c8a4c3924.jpg" /></a></div>
<p><en><i>Somebody asked The Question: how long before we can play the game (presumably Dreamland). So I picked my secret blue notebook and for every level, I tried to identify what I'm still missing to let you play it. Each of the checkboxes cost about 1 month of hobby time. maybe. I won't try being a project manager here. Not during hobby time. Oh, and blue boxes cost more. Possibly up to 3 months.<br /></i></en></p>
<p>Je n'ai pas vraiment envie de jouer au gestionnaire de projet pendant mes temps libres. Mais voilà, la question a été posée: "dans combien de temps est-ce qu'on pourra jouer" (à Bilou Dreamland, je présume). Alors j'ai repris mon cahier bleu, celui des secrets, des niveaux et des idées de gamedesign. Et pour chaque niveau déjà esquissé, j'ai fait l'inventaire de ce qui me manquait déjà. Pour les 3 premiers mondes prévus pour le jeu. Je n'ai encore aucun niveau pour le 4eme (ni aucun pixel, d'ailleurs). Chaque case à cocher sur cette map géante, c'est probablement 1 mois de hobby. Probablement 3 pour les cases rehaussées de bleu. Faites le compte ;-)<br /></p>
<b>edit</b>: avant <a href="http://sylvainhb.blogspot.com/2024/02/apple-water-and-sand.html">la prochaine démo</a>,
<ul><li> [<a href="http://sylvainhb.blogspot.com/2024/01/over-engineered.html">done</a>] faliciter la sortie de l'eau </li>
<li> [<a href="http://sylvainhb.blogspot.com/2024/02/sand-waves-completed.html">done</a>] animer les chutes et les pentes de sable</li>
<li> [<a href="http://sylvainhb.blogspot.com/2024/02/appleman-20.html">done</a>] Appleman en CompoundGob</li></ul><p>Mais la bonne nouvelle, c'est que certaines de ces cases ne sont pas indispensables pour avoir une version "jouable", c'est à dire où on puisse atteindre la fin des niveaux. Les PNJ, par exemple, sont supposés être optionnels tout comme Yoshi était optionnel. Parfois, une substitution par un élément déjà existant pourrait s'envisager. Certains niveaux de la school zone seraient mieux avec des lattes en guise de tremplin, mais déjà jouables en utilisant les gommes rebondissantes de School Rush, etc. <br /></p><ul>
</ul>PypeBroshttp://www.blogger.com/profile/10564522267743689261noreply@blogger.com1tag:blogger.com,1999:blog-34057821.post-65029371058129393022024-01-21T12:42:00.006+01:002024-01-21T22:54:18.344+01:00De l'eau par ci, de l'eau par là ...<p>Tentons donc de nager. La première chose serait de pouvoir stabiliser Bilou à la surface sans l'immobiliser pour autant. Ce n'est pas impossible parce que j'ai une bande de 2 tiles à la surface qui est à la fois de l'air et de l'eau. Une ruse pour que Bilou-qui-coule puisse succéder à Bilou-qui-tombait et que la dernière position valide pour l'un soit aussi une position valide pour l'autre. Bilou-qui-flotte à la surface devrait donc éviter d'entrer dans une zone qui n'est que de l'eau ou dans une zone qui n'est que de l'air ? Il lui faudrait pour ça un contrôleur dédié ?<br /></p>
<center><table><tbody><tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEho0fFqrIEBl_RBzhPknPJlpDYNYGiVW6DM_1i2Xx69NPioWLwuiuFjOEhoQI81_D4vX2dmzmv0ywQ3hBFL-J5gSyElsLLcEpxGaTOVkXXcFWbqCmoPvbJjTePW_MJIRHPOfaf4nE-PzuuuAh_uPPBOXuhp2QO52f5OjjePCDPHOwuDDcuKa1DWEg/s1600/3a1e7634e7b240d6.png" style="display: block; padding: 1em 0px; text-align: center;"><img alt="" border="0" data-original-height="173" data-original-width="135" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEho0fFqrIEBl_RBzhPknPJlpDYNYGiVW6DM_1i2Xx69NPioWLwuiuFjOEhoQI81_D4vX2dmzmv0ywQ3hBFL-J5gSyElsLLcEpxGaTOVkXXcFWbqCmoPvbJjTePW_MJIRHPOfaf4nE-PzuuuAh_uPPBOXuhp2QO52f5OjjePCDPHOwuDDcuKa1DWEg/s1600/3a1e7634e7b240d6.png" /></a></td><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEP37a1-04HKhJ0cxvxAHGwW8ysCMPiSQabaxjgQ2JOvfxYk7lHff20oOqStQhk8LXAE9a8d0Uiy8LwBjBH9PMPNRu8PjYtcMABlkI4s0Odk_8N44wYgGN1XEU9f3BoxcO-nyJ1QgyAzX52Gw8dUIWeK_BY_jbGBsp3knuKQdqawRTEtAwZ5VGrg/s1600/370e354802844321.png" style="display: block; padding: 1em 0px; text-align: center;"><img alt="" border="0" data-original-height="189" data-original-width="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEP37a1-04HKhJ0cxvxAHGwW8ysCMPiSQabaxjgQ2JOvfxYk7lHff20oOqStQhk8LXAE9a8d0Uiy8LwBjBH9PMPNRu8PjYtcMABlkI4s0Odk_8N44wYgGN1XEU9f3BoxcO-nyJ1QgyAzX52Gw8dUIWeK_BY_jbGBsp3knuKQdqawRTEtAwZ5VGrg/s1600/370e354802844321.png" /></a></td><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1-3xn1b6rATf5Ejhyphenhyphen653UhyphenhyphenK87EqlbEv_zAdXQDuvGwYxHJPVBGuuVTGxIzFefntmTwZqjRVQSISC9dbxfWDjMPvU_cjwkok1u-w83-pXVAAZTHB5QUdO5qpDTK_d8gocA8Om21j0J8dpNDFyy1dhp9YGxBa9c1hyTrAwL0A8R9ojfI0Im3_Kpg/s1600/cd6d672faf72ac35.png" style="display: block; padding: 1em 0px; text-align: center;"><img alt="" border="0" data-original-height="178" data-original-width="136" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1-3xn1b6rATf5Ejhyphenhyphen653UhyphenhyphenK87EqlbEv_zAdXQDuvGwYxHJPVBGuuVTGxIzFefntmTwZqjRVQSISC9dbxfWDjMPvU_cjwkok1u-w83-pXVAAZTHB5QUdO5qpDTK_d8gocA8Om21j0J8dpNDFyy1dhp9YGxBa9c1hyTrAwL0A8R9ojfI0Im3_Kpg/s1600/cd6d672faf72ac35.png" /></a></td><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJTsdEjyMSB3Aao8wQvo2vUDzpmexyATSpIbtG1JjrQnCghyZVZR2Qz2HifN6IgifDTgjJABs2nxrDXe3KnjNGTMQAUY4F6zYnXt3yun0YI7_jngkQ0C7kR6V60igrgzAR4n7WUibjJ4VyJiTSadv2ogOmCrARbDPUT3u-grpbV5KrrmuQHDPeGg/s1600/b9837e9da446bdf8.png" style="display: block; padding: 1em 0px; text-align: center;"><img alt="" border="0" data-original-height="189" data-original-width="137" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJTsdEjyMSB3Aao8wQvo2vUDzpmexyATSpIbtG1JjrQnCghyZVZR2Qz2HifN6IgifDTgjJABs2nxrDXe3KnjNGTMQAUY4F6zYnXt3yun0YI7_jngkQ0C7kR6V60igrgzAR4n7WUibjJ4VyJiTSadv2ogOmCrARbDPUT3u-grpbV5KrrmuQHDPeGg/s1600/b9837e9da446bdf8.png" /></a></td></tr>
<tr><td>props: 0fc<b>8</b><br /></td><td>props: 8fc<b>4</b><br /></td><td>props: 8fc<b>c</b><br /></td><td>props: 8fc<b>c</b></td></tr><tr><td>using <b>swim</b><br /></td><td>using <b>gravity</b><br /></td><td>using <b>gravity</b><br /></td><td>using <b>float</b> (?)<br /></td></tr></tbody></table></center>
<p><en><i>So, switching between "fall down" and "pushed up by the water" is not quite satisfying to emulate "floating at the surface". Partly because that means every transition between the two resets the animation. Mostly because how leaving water is notified and how that prevents DPAD events to be notified, making things like 'jump out' or 'switch to swim-left' impossible. So I spent time now and then during the week to figure out what I should do to get the desired effect. I do have a row of tiles that are <a href="http://sylvainhb.blogspot.com/2020/10/direct-flags.html">both air and water</a>... could it be enough to try and confine Bilou there when he's floating ? That wouldn't be impossible, but Bilou is 13 pixels high and the row only 16. Not much headroom ...<br /></i></en></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAD8HLCYp0FmwdFmwcMViXLN7SmM14BAgKvW97qQQp7BK6_7M7nzDQoro2_KmBqs9sArIBv4hP8UUs6uvYBzfxpDiMivuvjcEp034PpVqudtdKSb85oRdGqYhLpR1WRGR_dhd4ePKWoZ-iM1_WeIOG0X5se3MCLn-2KOiQncNxCJiFsKRiJU8AaA/s352/surface2.png" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="334" data-original-width="352" height="304" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAD8HLCYp0FmwdFmwcMViXLN7SmM14BAgKvW97qQQp7BK6_7M7nzDQoro2_KmBqs9sArIBv4hP8UUs6uvYBzfxpDiMivuvjcEp034PpVqudtdKSb85oRdGqYhLpR1WRGR_dhd4ePKWoZ-iM1_WeIOG0X5se3MCLn-2KOiQncNxCJiFsKRiJU8AaA/s320/surface2.png" width="320" /></a></div>Mais en fait, ça s'est avéré <a href="https://sourceforge.net/p/dsgametools/hg/ci/ddf1e315d5bdc137a8bdf955722dd35b53f3cfc3/">encore plus simple que ça</a>. J'avais entre-temps réalisé qu'il serait peut-être suffisant de faire tomber bilou-qui-flotte s'il est tout entier dans la bande de surface et de le faire monter s'il est bas dans cette bande ou s'il a commencé à s'enfoncer dans l'eau. Mais en testant, il s'avère que juste "tirer vers le bas dans la bande-surface, pousser vers le haut si on est ne serait-ce que d'un pixel dans la partie que-de-l'eau" <a href="https://mastodon.social/@PypeBros/111788397546696124">donne le résultat qui me convient</a>. Les mouvements de Bilou sont souples et amples, son animation n'est pas interrompue inutilement et sa position est pertinente par rapport aux graphismes.<br /><p></p><p><en><i>Hopefully, it turns out that I only need that area for the 'pull down' part of the move. Pushing up can happen anywhere in water because this is the default behaviour in water. I had plan for an extra "surface position" parameter in swim controller instead of a new float controller, but it turned out that was useless as well because the default position (where Bilou is completely in the 'both' row) is <a href="https://mastodon.social/@PypeBros/111788397546696124">just what I need given current graphics</a>.</i></en></p><p><en><i></i></en></p><div class="separator" style="clear: both; text-align: center;"><i><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDp0khRVmCkdjVJi2SeaUCJsH854dV8IKeBTe5jbvVC9oXGQl9aqqWZM5_4OfoznPeTPyBJoCfFGrfKCFe_rpM5mmaVar25Fvnu0iH8gOXdtsvoslmnWmrHzWuuEcvLMyEo7CUTlx3Xn_nE7xKu_p46i13Ge0F_7En5O0wzxc5XhdyEnxj_93wNQ/s256/swimfloat.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="192" data-original-width="256" height="384" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDp0khRVmCkdjVJi2SeaUCJsH854dV8IKeBTe5jbvVC9oXGQl9aqqWZM5_4OfoznPeTPyBJoCfFGrfKCFe_rpM5mmaVar25Fvnu0iH8gOXdtsvoslmnWmrHzWuuEcvLMyEo7CUTlx3Xn_nE7xKu_p46i13Ge0F_7En5O0wzxc5XhdyEnxj_93wNQ/s1600/swimfloat.gif" width="512" /></a></i></div><i><br /> </i><p></p><p><en><i>That seemed proper time to try the new 'swim right' and 'swim left' animations inspired by Fury of the Furries. But there I got annoyed again by how other controllers "steal" the focus of an earlier event. This time, the DPAD event notifying that I've pressed LEFT got replaced by an event mentioning that speed changed direction. It did not happen when pressing RIGHT because positive speed to the right and null speed at rest appear to have the same sign.</i></en></p><p>
<iframe allowfullscreen="allowfullscreen" class="mastodon-embed" src="https://mastodon.social/@PypeBros/111788925695133307/embed" style="border: 0; max-width: 100%;" width="400"></iframe></p><p><script async="async" src="https://mastodon.social/embed.js"></script></p><p><en><i>I cannot possibly express how satisfying it is for me to see that little animation coming to life and respond to my left/right/left/right keypresses. I guess I'm glad I kept up with gamedev so far ^_^</i></en></p>PypeBroshttp://www.blogger.com/profile/10564522267743689261noreply@blogger.com0tag:blogger.com,1999:blog-34057821.post-34589011567874649722024-01-10T22:27:00.007+01:002024-01-15T18:06:11.680+01:00Nager mieux<p><en><i>I like to release a demo on special occasions like new year or my birthday. It is twice unfortunate that I had none to show by the end of 2023 since it was the <a href="http://sylvainhb.blogspot.com/search/label/y93">30th anniversary</a> of <a href="http://sylvainhb.blogspot.com/2012/01/symbol-240601262552542551266062.html">Bilou's original design</a>. But there was something still lagging behind: for an untrained player, it takes countless trials to get out of the water in<a href="http://sylvainhb.blogspot.com/2021/12/3-rooms-release-early.html"> the green room</a>. When the season holidays started, I thought I could just change the state machine a little bit so that Bilou would jump out of water if we hold the FOOT button.</i></en></p><div class="separator" style="clear: both; text-align: center;"><a href="https://mastodon.social/@PypeBros/111669824901091487" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="320" data-original-width="457" height="224" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8zgmnfamXgJvEVzPA-lCECkq-sBazgW91zRSxBsZfbd1mN9TtBMFyL3_1zOYRUkiS0XWjc-GF2Nq96Tlm_p1iNNvOTxDfF6FDu0GBpH3-tFCyOcKmKx0rvH3N-re3vW3izsIRxubX5P-VX5Kob1GSEjTNvsfGelblRAyaTyH3gvM74n8d5v4W_w/s320/Screenshot%202024-01-09%20at%2009-23-18%20PypeBros%20(@PypeBros@mastodon.social).png" width="320" /></a></div><p>Il y a un élément qui m'empêche encore de faire une nouvelle démo avec les améliorations de l'an dernier: c'est difficile de sortir de l'eau. Je m'en suis rendu véritablement compte en laissant un peu la démo actuelle entre les doigts de J.L.N ... Je m'étais donc donné la mission d'essayer de faire fonctionner ça pendant le congé, mais avant même le premier essai, j'ai compris que ça n'irais pas <a href="http://sylvainhb.blogspot.com/2023/11/making-swim-fun.html">comme je voudrais</a>. Parce que pour qu'on puisse "jaillir de l'eau si on a appuyé sur le bouton de saut près de la surface", j'ai besoin de pouvoir mémoriser que ce bouton a été enfoncé. </p><p><en><i>It didn't work as I expected though. Maybe it could be adjusted with some <a href="https://mastodon.social/@PypeBros/111727398220541775">cleaner input buffering</a>, but since I intend to use some <a href="http://sylvainhb.blogspot.com/2023/11/making-swim-fun.html">different SWIM mechanics</a> to help the game being fun, it seems silly to hack something else first. So I went on, picked my animation editor and started crafting swim left, right and up animations, each split so that they player would have to chain button pressing to reach full speed and Bilou could come back to some "rest position" otherwise.</i></en></p><div class="separator" style="clear: both; text-align: center;"><a href="https://mastodon.social/@PypeBros/111671593164078762" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="224" data-original-width="333" height="215" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuOtwWd_oFaAtIBBUQ8HI3oGXjZmZF2CXFptfjo_saXGstxaNvCYCoHNkuDnN-AvI9nMM8G6gtVyd7EZkqeMOEWURCLHiT1aCDdik3WFnLU4EyCrga4lU4kHeC0QjjdNu66SajroQKytcVm-JfOkg-qTwVGP4ADXSS5J5usXdxlYUkCPrelpVi9Q/s320/Screenshot%202024-01-09%20at%2009-23-02%20PypeBros%20(@PypeBros@mastodon.social).png" width="320" /></a></div><p>ça pourrait être réglé avec une peu de tuning sur l'input buffering, j'imagine. Mais comme j'ai aussi prévu de passer à un autre système de nage dans lequel Bilou reste dans l'équivalent d'un dash sous-marin pendant quelques frames quand on a appuyé sur "pieds", ce serait naturel que l'on jaillisse automatiquement si on est dans cette phase de dash. J'ai donc passé deux petites soirées à faire des animations dans MEDS pour que notre brave Bilou brasse mieux.</p><p>Manque de pot, une animation supplémentaire s'est invitée dans le fichier. J'ai prévu 4 "pages" d'animations pour bilou.spr, mais cette nouvelle animation <a href="https://mastodon.social/@PypeBros/111675462938573554">est sur la page 7</a>, décalant toutes les nouvelles animations </p><p>- code avant la nage avec les sprites avant la nage: <br /> - démarrer la pyramide: ok<br /> - passer de la pyramide à l'école: ok<br /> - sortie de l'école: <a href="https://mastodon.social/@PypeBros/111728196263372742">gros crash</a>.</p><p><a href="https://sourceforge.net/p/dsgametools/hg/ci/4e7787df748f47fd70634725d03637b44886eab4/">Une petite modif' plus tard</a> (là, ce soir) pour éviter que l'animation excédentaire soit à la fois sous le contrôle du jeu et sous le contrôle du reste (sinon, ça fout un chaos digne de Jurassic Park dans le gestionnaire de mémoire) et j'ai de quoi commencer à utiliser toutes ces jolies nouvelles animations. Sauf que ça fait bizarre de voir Bilou essayer de rejoindre la surface la bouche grande ouverte (animation "super jump" recyclée) puis fermer la bouche une fois qu'il arrive à l'air libre :-P <b>Edit</b> et il va falloir que j'en fasse une ou deux de plus pour permettre au joueur de quand-même avancer. Sur base des animations de Fury ? Pourquoi pas ...<br /></p><p><en><i></i></en></p><div class="separator" style="clear: both; text-align: center;"><i><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-90K_44aonuY2kboNkxZ039HRCMV8I4heXBVBcz8h1rI8Xu3Ezt1HTz_eDyPSQmCz91Xw5yjS7M4Bm5HB3foh9WuChIAr3TuD5HTZZtYm7NZh3FE0jFAi1zOJFNxMAdqv1KcATPAZAAcpFLctwiNhyUkHgEGJa5kmyd2kBgQdknmofANzMcK41Q/s144/fury-swim.png" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="112" data-original-width="144" height="224" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-90K_44aonuY2kboNkxZ039HRCMV8I4heXBVBcz8h1rI8Xu3Ezt1HTz_eDyPSQmCz91Xw5yjS7M4Bm5HB3foh9WuChIAr3TuD5HTZZtYm7NZh3FE0jFAi1zOJFNxMAdqv1KcATPAZAAcpFLctwiNhyUkHgEGJa5kmyd2kBgQdknmofANzMcK41Q/w400-h311/fury-swim.png" width="288" /></a></i></div><p><en><i>But unfortunately, some bits got twisted, and I ended up with an undesired 'temporary' animation stuck in the bilou.spr file. Then I picked the wrong decision of ignoring it while loading rather than fixing the editor and saving the file again. It worked when I tried the animations in the green room, but when I tried to 'move' between rooms later on, everything blew up. I had HDMA experiments catching my attention, so I was all out of holidays when I finally understood why it broke and how to fix it. Sounds like you'll see the swimming another time ^^"<br /><b>Edit: </b>one more thing ... Dash-swimming might be fun, but I also need something to use when player just navigates with the DPAD. Maybe Fury's swim sheet will be the template I need for that ... </i></en></p>PypeBroshttp://www.blogger.com/profile/10564522267743689261noreply@blogger.com0tag:blogger.com,1999:blog-34057821.post-89581633963424933202024-01-06T00:37:00.003+01:002024-01-06T19:56:15.983+01:00Raycasting ?<p></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnieliZmjb8PH8sicFM60rx5sBamQoGJ6-Bw4uxdJn0PKNzu1faTiAcyhlLL2kihZRh_gqI4pmtqOooD8Tw7cSQ2O31XCOJOb5kOhmB4bu6Rpo9Epr-Mb4Bu8-PCot9QXau3EvzoyQg-kK0GaRevJpuFz2xLAPyIluGfJVMQxFvN006Lk0zMLSTg/s584/3Dbackground.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="434" data-original-width="584" height="238" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnieliZmjb8PH8sicFM60rx5sBamQoGJ6-Bw4uxdJn0PKNzu1faTiAcyhlLL2kihZRh_gqI4pmtqOooD8Tw7cSQ2O31XCOJOb5kOhmB4bu6Rpo9Epr-Mb4Bu8-PCot9QXau3EvzoyQg-kK0GaRevJpuFz2xLAPyIluGfJVMQxFvN006Lk0zMLSTg/s320/3Dbackground.png" width="320" /></a></div>There's an awesome effect one can achieve once you have <a href="https://sylvainhb.blogspot.com/2023/12/petite-pause-hdma.html">HDMA</a> in a platformer: add depth to your background with "floors" like in<a href="https://youtu.be/OJooJmrddeY?feature=shared&t=657"> DKC2 Lava lagoon</a>. There will be complete occlusion of the 'far' background plane (wall) by the 'near' background plane (floor side), so having them scroll at different speed is 'just' a matter of updating X scrolling register at the right time. Having the floor positioned above or below the "seam line" between two walls is 'just' a matter of adjusting Y scrolling register earlier or later so that they 'skip' part of the far background art to show front background art.<p></p><p>The awesome part is that depth effect added with the horizontal planes, of course. That is about adjusting <a href="https://mastodon.social/@PypeBros/111704670124205992">both X and Y scrolling registers</a> and that will <a href="https://mastodon.social/@PypeBros/111691640837855127">need maths</a> to explain properly, using some pre-slanted texture as shown in the <a href="https://www.spriters-resource.com/snes/dkc2/sheet/84066/">ripped contents of DKC2</a>.</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWCzhhxyro4qT2c66nvl_SY6W56bBECuJfGM-FKaThDv2HhVoJMp_AxBizoFznZ5x5N2gaPGayc5dz8wxY-j5pDeiwhOjBWaUlB9CYluO0vLuUBrmzinJyLdzVqT_JaZIHfKU0RmkbES1B2IyDhuYsyEvinjpUIORFYaVGAPK2pqJUxlpIk3_aEg/s679/raycasting.png" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="579" data-original-width="679" height="273" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWCzhhxyro4qT2c66nvl_SY6W56bBECuJfGM-FKaThDv2HhVoJMp_AxBizoFznZ5x5N2gaPGayc5dz8wxY-j5pDeiwhOjBWaUlB9CYluO0vLuUBrmzinJyLdzVqT_JaZIHfKU0RmkbES1B2IyDhuYsyEvinjpUIORFYaVGAPK2pqJUxlpIk3_aEg/s320/raycasting.png" width="320" /></a></div>First immediate thought after I realised that it could be more than welcome in the <a href="http://sylvainhb.blogspot.com/2021/04/pyramtmap.html">pyramid level</a> of <a href="http://sylvainhb.blogspot.com/search/label/dreamland#1852537865726465129">Bilou's Dreamland</a> was that it is actually an instance of the raycasting algorithm. Yeah, that infamous thing that turned ID software away from my beloved Commander Keen and sent them trashing the whole era of 2D platformers with first-person shooters. No wonder why, despite my affinty for maths and software optimization, I never ever felt tempted to code one myself. But hey, do it vertically instead of horizontally, and this is precisely what we need to decide whether to show floor, ceiling, wall or cut-through floor-to-ceiling structure.<p></p><div class="separator" style="clear: both; text-align: left;"><a href="https://www.youtube.com/watch?v=NbSee-XM7WA&t=840s" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="390" data-original-width="535" height="233" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvvh8q9tIVcfUF2_5JvpB6eSE7_E3V-tj_CETwQ7uNU_o8aY9oxU4YJT3h2nQ936EDw54JIxed7y3UGInsXMQ-5yJmo-cnZSPVBbcqXfL0t3FZG5KTTjP8UMaT546z7ncfW5s6kd9SLhE5Ozh9LsyRkQ3eaiH1cfyRbrTUb1ytjTEbliY9Q31rJg/s320/Screenshot%202024-01-03%20at%2011-26-05%20Super%20Fast%20Ray%20Casting%20in%20Tiled%20Worlds%20using%20DDA.png" width="320" /></a>So before trying to reconstruct the algorihtm that might have been used on SNES, let's see what it would cost us.</div><ul style="text-align: left;"><li>the background scene must be structured along a 2D grid. I'd say 64x64 pixels would be fine by me</li><li>For every scanline , we will have to step through the grid, one tile at a time, essentially checking whether one more "depth" step takes us farther than one "height" step in our case.</li><li>We need a direction vector associated with every scanline. That implies 192 square roots per frame, but hopefully, those computations are the same for every frame: they depend on the
camera-to-screen distance and define angle used to trace through each
pixel. They could be pre-computed even at compile time and stored in a
look-up table.</li></ul><p>So for every scanline Ys of the screen, (DDA) raycasting will give us a pair of (Zw, Yw) coordinates in the world that is shown on that scanline. Most likely, we don't want to compute the distance to Zw, Yw nor use that distance to adjust scrolling speed. Instead, Zw should directly be used to decide the scrolling speed. Well, unless we're on a horizontal surface, that is. Well, I can't help thinking this is overgeneral and overkill, despite übercool.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibdX0ypZAymhxZvbe-M5TeqS5UJpzVA10nqhseAR6E2kh_haZNba6rEsfxgDfG2eboTTZL2nTermx8yYBNd8JYsGpz4m0ajl2A3J468PNx7jmorXbJTMMzr1kxuw_t7g-tJMoPtfFzK5vdLUvK_y-98Jpe21KyJZc_Bnt1H7ot00g6muLe06Fh3A/s548/dkc2-depth.png" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="483" data-original-width="548" height="353" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibdX0ypZAymhxZvbe-M5TeqS5UJpzVA10nqhseAR6E2kh_haZNba6rEsfxgDfG2eboTTZL2nTermx8yYBNd8JYsGpz4m0ajl2A3J468PNx7jmorXbJTMMzr1kxuw_t7g-tJMoPtfFzK5vdLUvK_y-98Jpe21KyJZc_Bnt1H7ot00g6muLe06Fh3A/w400-h353/dkc2-depth.png" width="400" /></a></div><p>The trick in the SNES DKC2 implementation is that we have pre-rendered floors and ceilings. They already feature some depth-of-field effect. if you use them as-is. And being 440px wide, they're significantly larger than the screen (256 pixels iirc). Where does that 440 value come from ? Well, I guess this is screen_width + pattern_width, as the flat stripe shows a repeating pattern of 184 pixels. So whereever you are in the pattern, you can always have at least one full scanline ahead. The most distant line of the ceiling has only 96 pixels between two patterns, matching exactly the size of the tiled background wall. That means if the 'front' part is moving exactly at 1 pixel / frame, the tiled part should be moving at 0.52 pixel/frame so that Thales theorem is satisfied.</p><p>That size difference also tell us how far away the tiled parallax layer should be from the 184x32 parallax layer (and thus how deep the floor/ceiling objects are): they're as far from each other as the 184x32 layer is from the "camera"</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEius4qWkW2000laKUUSM08aBUDF2XbA-juUcZsQBYgx1Vtc5AwVXyeArEZFu-cJimXZ76GPe6h7Pe15uNZrt7SXBraZWHL9-zF_3F6rQ21GgPimFMbSrHUQnBV7J5wewymHyhlYUyNP8YqbNTC5jeXdlwDCFOy0YyHEJS1QK3yAoqIfZa3wXXH4TA/s256/hdma-synchro-parallax.gif" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="192" data-original-width="256" height="192" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEius4qWkW2000laKUUSM08aBUDF2XbA-juUcZsQBYgx1Vtc5AwVXyeArEZFu-cJimXZ76GPe6h7Pe15uNZrt7SXBraZWHL9-zF_3F6rQ21GgPimFMbSrHUQnBV7J5wewymHyhlYUyNP8YqbNTC5jeXdlwDCFOy0YyHEJS1QK3yAoqIfZa3wXXH4TA/s1600/hdma-synchro-parallax.gif" width="256" /></a></div><pre><code> s16 xref = REG_BG1HOFS;
s16 yref = (offset >> 2) % 192;
s16 xamp = xref + xref / 2;
s16 yamp = yref + yref / 2;
int ytrigger = 224 - yamp;
int btrigger = 192 - yref;
int i, j;
for (i = 0, j = 0; j < N; j++, i += 2) {
if (j > ytrigger && j < ytrigger + 64 <br /> || j > ytrigger + 256) {
data[i] = xamp;
data[i+1] = yamp + 30;
} else {
data[i] = xref;
data[i+1] = yref + (j >= btrigger ? 128 : 64);
}
}</code></pre><p>That doesn't make the 3D-effect of DKC yet, but at least it gets me <a href="https://mastodon.social/@PypeBros/111705366635260675">synchronous</a> <a href="https://mastodon.social/@PypeBros/111704871315282127">parallax</a> with a single hardware layer.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivxPnC5zoPW8VW0gxzkkk2GnRS5MsgEWNvcD1YAdOfLvQOFKAwiX4u7wG_dvWRJOwtGwGqVl_1Pt4evMxIUdei0JmEQEitqsAbb000LWwq8xu90oNmojS3qLnpupWtRLOvtgL0HBBU855DLrvs6OHvfjd_MqoKp_nffb2a2ovMQdKxinXf_GSnlg/s503/analyzed-18deabb9e44d792a.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="503" data-original-width="458" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivxPnC5zoPW8VW0gxzkkk2GnRS5MsgEWNvcD1YAdOfLvQOFKAwiX4u7wG_dvWRJOwtGwGqVl_1Pt4evMxIUdei0JmEQEitqsAbb000LWwq8xu90oNmojS3qLnpupWtRLOvtgL0HBBU855DLrvs6OHvfjd_MqoKp_nffb2a2ovMQdKxinXf_GSnlg/s320/analyzed-18deabb9e44d792a.jpg" width="291" /></a></div>Next step: find the zones where ceiling and floor should be shown. And there, trials and errors became too complicated to figure out. Hopefully, I found a way to <i>analyze</i> the problem with maths. Most of what's computed is derived from that "yref" value, which is normally the input from camera position. What I need to do is use that yref as horizontal axis and study how "triggers" that define top or bottom of areas evolve, cross and areas overlap appear or disappear. And once the (simple) maths were written, it took only half an hour to <a href="https://sourceforge.net/p/dsgametools/hg/ci/6422a91f2898b5f3e8745f041261afad2c49398b/">write the code</a> <a href="https://mastodon.social/@PypeBros/111710476065314856">to do it right</a>.<br /><p>With this graphics, that's the best I can do... let's see how it follows up once I have dedicated background.<br /></p><p></p><p></p>Oh, and while I'm at it, there's a stunning online tool out there, to visit every map of every DKC SNES game: the <a href="http://www.dkc-atlas.com/maps/dkc2/2-3">DKC-atlas</a>. <br /><p></p><p></p><br /><p></p><br /><br />PypeBroshttp://www.blogger.com/profile/10564522267743689261noreply@blogger.com0tag:blogger.com,1999:blog-34057821.post-31652536219743474692023-12-25T16:24:00.002+01:002024-03-11T11:19:04.896+01:00Petite pause HDMA<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQjgpCvb9L2pTv470chC2Cx_WF-8vPu7EV3zASrs9O0qIBnFwAByAyA4-SwJ2gI8b57mJ0JoYYVqUNOcZARB6wjd2BhWj8Hw5OGo0Ad9UczhEWgj7PtHefgc_jwiudAEk5D46QuexdlFW013nQYd5BK84dzeOqHD1nH4rAZMmo4v-F798Ne9rrzg/s1600/hdma-yes2.gif" style="clear: right; display: block; float: right; margin-bottom: 1em; margin-left: 1em; padding: 1em 0px; text-align: center;"><img alt="" border="0" data-original-height="192" data-original-width="256" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQjgpCvb9L2pTv470chC2Cx_WF-8vPu7EV3zASrs9O0qIBnFwAByAyA4-SwJ2gI8b57mJ0JoYYVqUNOcZARB6wjd2BhWj8Hw5OGo0Ad9UczhEWgj7PtHefgc_jwiudAEk5D46QuexdlFW013nQYd5BK84dzeOqHD1nH4rAZMmo4v-F798Ne9rrzg/s1600/hdma-yes2.gif" /></a><p><en><i>Yes! I managed to get some <a href="https://sylvainhb.blogspot.com/2022/01/le-hdma.html">HDMA effect</a> applied on my 3-rooms demo. It has absolutely no use in that particular scenery, but it did work. Yet, at first, I couldn't get anything, up to the point where I suspected that my emulator simply had no support for HDMA at all. But then I remembered seeing something very HDMA-esque in WarhawkDS (<a href="https://github.com/benbaker76/WarhawkDS/commit/e8bdf81f283e282c25366298ffe71d4327acc202">recently open-sourced</a>). And then before I could even try whether the .nds would work in my emulator, Asie <a href="https://mastodon.social/@asie@mk.asie.pl/111634986693579616">confirmed</a> that she knew another open-source homebrew using HDMA: <a href="https://github.com/asiekierka/megazeux/blob/7dad36e942f0865e2f5ec93ed564c094acc7a1f4/arch/nds/render.c#L278">MegaZeux.</a></i></en></p><p><en></en>Hahaa! Nous y voilà! J'ai réussi à appliquer un effet "HDMA" dans ma démo de Bilou Dreamland! ça ne sert à rien, c'est d'une esthétique discutable, mais voilà: il y a <a href="https://sylvainhb.blogspot.com/2022/01/le-hdma.html">presque 2 ans</a> que j'ai des notes sur comment faire ce genre de chose dans mon carnet-agenda et que je passe par-dessus en me disant que "ouais, je tenterai ça un de ces 4. C'est complètement le genre de technique qui fait que je suis sur NDS et pas sur playdate ou androïd. Mais c'est McMartin avec <a href="https://mastodon.social/@mcmartin@mastodon.gamedev.place/111592132775379128">son post sur le HDMA de la SNES</a> qui m'a donné envie de bousculer un peu mon absence-de-planning de hobby-coding pour le mettre en oeuvre. Sauf que vous vous en doutez, au premier essai, rien ne marchait. J'avais pourtant quelque chose de quasi-identique à ce setup dans MegaZeux DS ou même warhawk DS.<br /></p>
<pre><code> DMA1_CR = 0;
REG_BG0VOFS_SUB = scroll_table[0];
DMA1_SRC = (u32)(scroll_table + 1);
DMA1_DEST = (u32)&REG_BG0VOFS_SUB;
DMA1_CR = DMA_DST_FIX | DMA_SRC_INC | DMA_REPEAT | DMA_16_BIT |
DMA_START_HBL | DMA_ENABLE | 1;</code></pre>
<p><en><i>The registers configuration is almost identical to the one I tried in my demo: 16-bit transfer with proper start and repeat setup, and a transfer size of 1 word per line. At that point I started suspecting that something else in my code would break the setup of the DMA transfer. After all we already have channel 0 used for 3D pipeline and channel 3 used by dmaCopy macros. So I picked up devkitpro simplest graphics demo and tried to bring it there instead.</i></en></p>Un petit passage dans les programmes d'exemple de devkitpro. Aucune ne fait du HDMA alors j'essaie d'injecter mon code dedans. Sauf que la première victime n'a aucun plan de décor (donc rien à faire onduler) et est écrit en C (contre du C++ pour mon code). Je m'adapte et je fais la bonne vieille rasterbar (impossible dans le code de Bilou parce que je travaille en mode 4096 couleurs par plan, ce qui veut dire que la palette est hors de la mémoire adressable). Et là, ça marche presque nickel. Il faut juste veiller à programmer la couleur pour la ligne 0 "à la main" avant de commencer la configuration du HDMA qui fera toute les autres lignes parce qu'il se déclenche *à la fin* de chaque ligne, mais pas pendant les lignes virtuelles du délai entre 2 images.<br /><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEF-QjF06mfJ2PXI4psZ52gFSWhzWHrVNibCsZBuQUM7BE2fMYfI4bscqHkYxv-CNW_Or__ivzxTWWQX4ZImHfz7ee_Wh7KHzpV4Zv7sMrV-XgIDI7a_G00cXhdy6bzxsRjm-HoQ9hj_XwwZ2Qa0sQWGSiosVP_91NS8hOa4XddgY7rM0bQp24YA/s553/hblank-ebe43587353dd23e.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="331" data-original-width="553" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEF-QjF06mfJ2PXI4psZ52gFSWhzWHrVNibCsZBuQUM7BE2fMYfI4bscqHkYxv-CNW_Or__ivzxTWWQX4ZImHfz7ee_Wh7KHzpV4Zv7sMrV-XgIDI7a_G00cXhdy6bzxsRjm-HoQ9hj_XwwZ2Qa0sQWGSiosVP_91NS8hOa4XddgY7rM0bQp24YA/s16000/hblank-ebe43587353dd23e.png" /></a></div><p><en><i>The first one (simple sprite) had no background to wave but it had single palette, so there (unlike with my demo), I could beam values into palette slot 0 and see it draw raster bars on screen. A bit of translation was needed because it was a C example rather than a C++ one, but there it is. changing the background colour like I was driving an Atari 2600 except the DMA does the waits and syncs, and not the CPU.</i></en></p>
<pre><code>class HdmaEffect {
static const size_t N=256;
static const unsigned CHN = 1;
s16 data[N];
size_t offset;
public:
HdmaEffect(); // intialize data[]
~HdmaEffect() {
DMA_CR(CHN) = 0;
}
void Frame() {
DMA_CR(CHN) = 0; // disable channel
DMA_SRC(CHN) = (uint32)(data + offset);
DMA_DEST(CHN) = (uint32) &REG_BG0HOFS_SUB; // mind the & to get register *address*
DMA_DEST(CHN) = (uint32) BG_PALETTE_SUB;
DMA_CR(CHN) = DMA_REPEAT | DMA_START_HBL | DMA_SRC_INC | DMA_ENABLE | DMA_DST_FIX | 1;
offset = (offset + 1) & ((N / 4) - 1);
}
};
void mainLoop() {
HdmaEffect hdma;
while(1) {
swiWaitForVBlank();
hdma.Frame();
scanKeys();
if (keysDown()&KEY_START) break;
}
}
</code></pre>
<p>Mais mon code C++, lui, toujours rien. Il n'est pourtant pas si différent. Je continue à passer d'un exemple à l'autre et je tombe sur un avec un décor (qui refusera mordicus de bouger) et en C++. Toujours rien. Par contre, en reprenant et adaptant le code C, là, je parviendrai à faire onduler le texte de l'écran du bas. Moins sexy, mais c'est un début. Il m'aura fallu un bon réveillon familial et une petite nuit de sommeil pour comprendre la différence fondamentale entre les deux implémentations.<br /></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuWw_9OVwC3uzfQD1kOJ7pcR6b6Doi-UDZpYmEEGT2nqTt4m0cFDJ5nRdK3j3dyU78yvwwgqgahpVeLFbhTfqmOFxmACow4IPw5vBcfDRh_62sPefbaFzFYMjldwjqKGrZsIM65vkUtn3XLqAsW5w_6Gb5RFadnPpBLOnif4zAmQ_aq0153aXULw/s256/hdma-why.gif" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="192" data-original-width="256" height="192" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuWw_9OVwC3uzfQD1kOJ7pcR6b6Doi-UDZpYmEEGT2nqTt4m0cFDJ5nRdK3j3dyU78yvwwgqgahpVeLFbhTfqmOFxmACow4IPw5vBcfDRh_62sPefbaFzFYMjldwjqKGrZsIM65vkUtn3XLqAsW5w_6Gb5RFadnPpBLOnif4zAmQ_aq0153aXULw/s1600/hdma-why.gif" width="256" /></a></div><en><i>I picked another example featuring a background, this time in C++. I couldn't get any color changed with my C++ code, and I couldn't get the picture waving. But with the adapted C code, it could change colors and I could make the text on the bottom screen waving (although somehow weirdly). We were 24th of December, I had errands to run and a party to attend, so I accidentally shut down the computer and went doing something completely different. It's only when I woke up this morning that I got struck by the difference between the C++ class and the C code. The C++ class will have the source array in a member and it allocates the HdmaEffect object on the stack. But <b>the stack is invisible to DMA operations</b>. I've <a href="https://sylvainhb.blogspot.com/2011/04/almost-done.html">been tricked by that</a> a good number of times in the past already. One more alloc/free pair was all I needed to get the working screen-waving effect you've seen above. Huzzah! Merry Christmas! May the source be with you all ;-)<br /></i></en><p></p><p>La conversion rapide en C utilisait une grosse variable globale pour le tableau contenant les différentes valeurs à streamer dans le registre de scrolling. La version C++, plus propre sur elle, encapsulait ce tableau au sein de l'objet HdmaEffect, lequel pouvait être construit dans une variable locale pour gérer ses ressources (le canal DMA) Rabi-style. Sauf que "local", ça veut dire "sur la pile" et que la pile de la DS est 1) petite et 2) mappée sur de la mémoire plus rapide (type cache L1) logée au coeur du chip ARM ... et donc inaccessible depuis le bus système avec lequel travaille le contrôleur DMA. Eh oui. <a href="https://sourceforge.net/p/dsgametools/hg/ci/0ddd4229a151e3b938ead41e0fadca2a4871665c/">Un malloc plus tard</a>, j'étais prêt à faire une démo qui marche ^^"<br /></p>PypeBroshttp://www.blogger.com/profile/10564522267743689261noreply@blogger.com3tag:blogger.com,1999:blog-34057821.post-56365796189452265072023-12-17T17:10:00.004+01:002024-01-24T11:09:48.000+01:00tapis roulant!<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZIA6tZJ3IhXHdodrbYkWbOK8crnpRbqgNz0-rXII6xPxEy4lZtdVpEtL6RJpp_Yd_weTK0yqX3tGFaD6mr4xbsLl1eGQILgP8HfFglazocJWuSts-mfNYxe87EE5k3zb16Ag3U3usBA_aMtGNyOcWX1nc-GvwIyL40yct0LuHf-N0Vl-4SPDyXw/s256/specialground2.gif" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="192" data-original-width="256" height="192" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZIA6tZJ3IhXHdodrbYkWbOK8crnpRbqgNz0-rXII6xPxEy4lZtdVpEtL6RJpp_Yd_weTK0yqX3tGFaD6mr4xbsLl1eGQILgP8HfFglazocJWuSts-mfNYxe87EE5k3zb16Ag3U3usBA_aMtGNyOcWX1nc-GvwIyL40yct0LuHf-N0Vl-4SPDyXw/s1600/specialground2.gif" width="256" /></a></div>Nous y voilà <a href="https://sourceforge.net/p/dsgametools/hg/ci/3f544d710c942b7455e8ee56813b249d9545c808/">enfin</a>! Après l'eau-qui-pousse, je peux vous présenter le sol-qui-pousse. Le point délicat, vous vous en doutez, ça aura été de mélanger ça avec des sols pentus. Ce à quoi je ne m'attendais pas franchement, par contre, c'est que être poussé pendant qu'on est immobile sur le sol se révèle plus compliqué à gérer qu'être poussé pendant qu'on avance.<p><en><i>The natural step after <a href="https://sylvainhb.blogspot.com/2023/11/tile-4-swimflow-2560.html">water-that-push-Bilou</a> was ground-that-push-Bilou. It started quite nicely and it is finally working, but to reach that nice behaviour, there has been significant ups and downs, and especially to get it working on sloped ground. But hey, sloped conveyor ground was <a href="https://sylvainhb.blogspot.com/2019/08/a-b-idea.html">my trick</a> to have one-way halls without getting too mechanical. <br /></i></en></p><p>C'est que pendant qu'on avance, on appelle régulièrement <a href="http://sylvainhb.blogspot.com/2020/02/doslopes.html">la fonction do_slopes</a>, voyez-vous. Et même si le sol annonce "je te pousse de deux pixels sur la gauche" alors qu'on est sur une pente, on finira bien 2 pixel à gauche et 1 pixel plus bas si nécessaire. Mais rien de ce genre dans l'état "immobile sur le sol". Et notre fonction <code>do_slopes</code> est prévue pour aller directement corriger la vitesse et les déplacement retardés du personnage, or l'idée du "sol qui pousse", c'est justement de manipuler la position dans un premier temps et de laisser le code qui traite la vitesse tranquille. Sans ça, sur un tapis roulant trop rapide, vous verrez Bilou se retourner pour marcher tout seul vers la gauche plutôt que de le voir s'échiner à avancer vers la droite tout en reculant malgré tout vers la gauche. Pas terrible.</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhc2VQAKehak_1Ja4o5axtd4-ltMbRWKsqiSQhgyXT1rLju6aFuwOqX5m81hgaPkUCgSQ0VdVY_fwRP0v8s_tsP3AS_UiD4P6IecUJ9M3GE0nFv2yAczFTyxSExRiBgaZmb6f3k6VzHtCwPekOOj2olNq6hfqd33JimBZClATuhuF1nkzQODrrsgQ/s283/Screenshot%202023-12-17%20at%2013-43-07%20PypeBros%20(@PypeBros@mastodon.social).png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="183" data-original-width="283" height="183" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhc2VQAKehak_1Ja4o5axtd4-ltMbRWKsqiSQhgyXT1rLju6aFuwOqX5m81hgaPkUCgSQ0VdVY_fwRP0v8s_tsP3AS_UiD4P6IecUJ9M3GE0nFv2yAczFTyxSExRiBgaZmb6f3k6VzHtCwPekOOj2olNq6hfqd33JimBZClATuhuF1nkzQODrrsgQ/s1600/Screenshot%202023-12-17%20at%2013-43-07%20PypeBros%20(@PypeBros@mastodon.social).png" width="283" /></a></div><a href="https://sylvainhb.blogspot.com/2007/11/2d-sur-la-ds-quelques-chiffres.html">Dans Rayman</a>, j'avais pu voir qu'on avait deux types de pentes: des normales et des glissantes. Chaque angle et chaque offset est dédoublé avec un second type pour gérer les deux types de physiques. J'avoue que je souhaite plus de souplesse pour Bilou. Pas tant que j'ambitionne de faire un jeu plus complexe que Michel Ancel, mais surtout parce que je n'ai pas l'occasion de <a href="https://sylvainhb.blogspot.com/2014/11/lhistoire-de-rayman.html">planifier l'ensemble du jeu</a>. Je suis incapable actuellement de garantir qu'il n'y aura jamais plus de 2 types de sol dans un niveau ni 2 types de pentes. <a href="http://sylvainhb.blogspot.com/2019/03/level-editor-vs-new-engine.html">Le projet</a> était donc d'utiliser des emplacements séparés pour encoder la pente et les propriétés du sol. Et quand je me suis mis à coder, c'était encore plus simple que prévu: quelque soit la position de Bilou sur une pente, il est toujours à l'intérieur du tile "pentu". Et donc pour trouver le tile avec le type du sol, il suffit toujours de regarder 8 pixels plus bas. Enfin ... presque toujours. <br /><p><en><i>And that was the final test for my "neat idea" to "simplify" the level editor: use separate tiles to indicate the slope (if any) and the ground properties. Ground properties are always on the 'plain' part of the ground and the slope types sit on top of it. A new <code>getGroundType</code> function <a href="https://sourceforge.net/p/dsgametools/hg/ci/6aabb3fd676b9f3e27742b90565a5577eb1cf5c2/">can probe through that slope</a> layer to find the actual ground and return its numerical type. Then, each controller use that to index to retrieve relevant parameters, such as push vector, friction, or whatever needed. It mostly worked except on one spot: the precise location where Bilou's <a href="https://sylvainhb.blogspot.com/2013/05/un-grand-pas-en-avant.html">hotspot</a> has just been shifted out of the lowest 'sloped' tile of a slopes stripe. It is now mid-air, with one 'slope' tile below it and the ground properties one more below. Then Bilou stops because it is no longer pushed but doesn't fall either. And if I try to hack that around, I end up with Bilou moved horizontally instead of following the slope because there's no slope to follow.<br /></i></en></p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiu63ONjSDYNpu9mEEE8ikmgb7VkZTgSyDS-P75npGo1NGJw5VTbMdUEP5f0uAiLUVwpW1CHURNGaGS5v7f2bcWtpu-PrxwHDCdidyJsCgA2SshetqmVTJoFUKSIuFaQspafZaekUSl5e063aGrDmkEeYwIEdz38kXUUfB1Xx_zqWDVij9HofMy7Q/s465/Screenshot%202023-12-17%20at%2013-43-28%20PypeBros%20(@PypeBros@mastodon.social).png" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="294" data-original-width="465" height="202" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiu63ONjSDYNpu9mEEE8ikmgb7VkZTgSyDS-P75npGo1NGJw5VTbMdUEP5f0uAiLUVwpW1CHURNGaGS5v7f2bcWtpu-PrxwHDCdidyJsCgA2SshetqmVTJoFUKSIuFaQspafZaekUSl5e063aGrDmkEeYwIEdz38kXUUfB1Xx_zqWDVij9HofMy7Q/s320/Screenshot%202023-12-17%20at%2013-43-28%20PypeBros%20(@PypeBros@mastodon.social).png" width="320" /></a><p>Comme toujours avec les pentes, les problèmes commencent quand le sol n'est plus dans le prolongement horizontal de celui utilisé une frame plus tôt. On se retrouve dans ce cas-là soit avec Bilou qui s'arrête au milieu de la pente, soit continuant à se faire pousser, <a href="https://mastodon.social/@PypeBros/111507054926803048">mais à l'horizontale</a>. </p><p><en><i>Yet, when you walked on the sloped ground rather than letting yourself pushed by flowing sands, you wouldn't get any issues. The trick is that walking state already has a call to the do_slope function that keeps Bilou in contact with sloped ground despites of motion. The extra shift happened prior that call, so it would still re-align when Bilou's own velocity is applied. But there was no such call in "idle, standing" state so far. And the do_slopes function wasn't meant to affect anything but character's speed, while it should now sometimes affect temporary variables used to immediately apply a coordinates update.</i></en></p><p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh51A3DLaL3opl6Vdq3aQLGCMAzO8SpXw0nUFPmTOpMlfzk2vFlWnoXVMxHG41Gzu4kgcuNg65_FLneieSBGgYudSKOxtLZi8ke4klAELLDTiBC2YOBzR3ebkGq6uaN_LOnvOQLXxI2KWM6li_xPydGDcDp2i11PxfyVJLUGsOCpxvQ1EVeb4-hRQ/s320/slope-tooted-5cbe46a8d5bd07b3.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="320" data-original-width="257" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh51A3DLaL3opl6Vdq3aQLGCMAzO8SpXw0nUFPmTOpMlfzk2vFlWnoXVMxHG41Gzu4kgcuNg65_FLneieSBGgYudSKOxtLZi8ke4klAELLDTiBC2YOBzR3ebkGq6uaN_LOnvOQLXxI2KWM6li_xPydGDcDp2i11PxfyVJLUGsOCpxvQ1EVeb4-hRQ/s1600/slope-tooted-5cbe46a8d5bd07b3.png" width="257" /></a><en><i>And just in case that seemed too easy, a typo in the first coding sprint made me change accumulated step instead of actual speed, ruining the whole thing with Bilou digging into the ground. Then a <a href="https://mastodon.social/@PypeBros/111563810816709388">bug introduced in the level editor</a> broke some part of the level without me realizing it and I started suspecting wrong properties for the ground here or there.</i></en></p><p><en><i>But there we are. It's working, even though it cost me hopping back in time with Mercurial and re-doing the sprint one dash at a time, checking, committing, re-importing maps and the like. And <a href="https://mastodon.social/@PypeBros/111524147284344431">about one week later</a>, I finally shot a decent .gif of the behaviour so I could post it and write this stuff. It's been planned for so long. It has been through so many preliminary work and so that I'm gonna call it a milestone. <br /></i></en></p><p>Bref, inspector widget, ddd, j'ai pu sortir toute la panoplie. Presque (pas les unit-tests, cette fois). Mais l'éditeur de niveau m'aura bien cassé le rythme.</p><p>(wow. Le soir est tombé, j'ai encore une machine à faire tourner et je n'aurai pas fait plus de homebrew de cet aprèm' libre que de vous raconter tout ça :-P)<br /></p><br /><p></p>PypeBroshttp://www.blogger.com/profile/10564522267743689261noreply@blogger.com0tag:blogger.com,1999:blog-34057821.post-11159463624722606162023-11-23T22:25:00.015+01:002023-12-09T15:12:54.620+01:00Making swim fun<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKFNZmBlTtNqLWmxfQ4Z7GpJ44qjKCjpHcEnvWBN8OCEt9cxP3KB76wxjDQROwhvV-OJdMVsErmZz4XFE1IGfW68cXw7G102HXypZjOsNrV04gC0LIY99zUD-dcoBqDbQF5I-kiRWpI9O8OIrHUnfamtOKR0ZnALaEKp0k5Yk9hy1vfmPve978Yg/s927/water-splash.png" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="837" data-original-width="927" height="289" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKFNZmBlTtNqLWmxfQ4Z7GpJ44qjKCjpHcEnvWBN8OCEt9cxP3KB76wxjDQROwhvV-OJdMVsErmZz4XFE1IGfW68cXw7G102HXypZjOsNrV04gC0LIY99zUD-dcoBqDbQF5I-kiRWpI9O8OIrHUnfamtOKR0ZnALaEKp0k5Yk9hy1vfmPve978Yg/s320/water-splash.png" width="320" /></a></div><p><strike>Somewhere last year</strike> April 2023, I had been reading <strike>something </strike><a href="https://www.neogaf.com/threads/platformers-that-do-swimming-right.907088/#post-133012718">a neogaf thread</a> about water levels in platformers and whether it might be possible for them to be actually fun. Because, well, I don't think I'll manage to copy the awe DKC sharks may produce and <a href="https://www.youtube.com/watch?v=q64iQWslc9c">I can't ask my brother</a> to come up with something like David Wise's Aquatic Ambience for my Nintendo DS title.Yet there will be water.</p><p>There have been some platformer titles over the last years that came with fun-to-play water levels. I think about "20000 lums undersea" level in Rayman Legends and some level of DKC: Tropical Freeze. Swimming in Ori and the Will of the Wisps was pretty pleasing as well. All these games share something: they benefit from analog stick and they depart completely from their 8-bit and 16-bit counterparts by letting you target any direction freely. Your character will typically need some time to turn himself towards the direction you want though, which works fairly well.</p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjoHJuNm5jcHOE4ESoGpFB1f3wbFxVNMHBW39-uUBs2nhuFjczBo6hirqRxiQvJhUfhlObK0tF2aAVmbYY7Ai8ZWUi2vcZc9eQpLjNk3Bt9Ot9VuCwB25tPF2AdxPmHgUzZIbCl2DbUmcm0a9BsDDqcEKyCNinGwtuNTDnsiATB7nT3N0QqA96Jw/s70/chomps.gif" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="68" data-original-width="70" height="68" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjoHJuNm5jcHOE4ESoGpFB1f3wbFxVNMHBW39-uUBs2nhuFjczBo6hirqRxiQvJhUfhlObK0tF2aAVmbYY7Ai8ZWUi2vcZc9eQpLjNk3Bt9Ot9VuCwB25tPF2AdxPmHgUzZIbCl2DbUmcm0a9BsDDqcEKyCNinGwtuNTDnsiATB7nT3N0QqA96Jw/s1600/chomps.gif" width="70" /></a><p><fr><i>Les niveaux aquatiques dans les platformers, ça a mauvaise réputation. Vu le nombre d'échecs que <a href="https://www.youtube.com/watch?v=797cYuTdZ6s"><strike>Vanilla Lake</strike></a> <a href="https://www.youtube.com/watch?v=mNuFMMXH9s8">Forest of Illusion 2</a> m'a infligé, je ne peux pas franchement leur donner tort. ça a commencé à aller un peu mieux avec Donkey Kong Country, d'abord parce que la musique de David Wise était aussi époustouflante que l'animation des requins, mais surtout <a href="https://www.youtube.com/watch?v=CHXYoytIYOo">grâce à Enguarde</a> qui permet de cesser de se battre continuellement avec la gravité... Et d'avoir une chance contre la poiscaille.<br /></i></fr></p><div class="separator" style="clear: both; text-align: center;"><i><a href="https://www.youtube.com/live/ozIMtLn8lIw?feature=shared&t=1088" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="331" data-original-width="292" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEVxv_jPBk7ckCoQGKF0rYXg9tkJm-DOZ2E7vjy2ncfCjlP0SXSVcK6HVefZSoYT2N3CZaJSLSDfus8hmWJ58T-VfUNv6yysCtnc5kHW05bIrKqmRFuRKezTvYx5BoQfjWYxlHAdnUur_3Px_SIriuWmFv0vPZH9vnKXOEvZ_DTIgrjMNfFbzVvw/s320/raynage.png" width="282" /></a></i></div><p><fr><i>Plus proche de nous, Tropical Freeze et <strike>20000 Lums sous la mer</strike> l'Océan des Songes de Rayman Origins nous ont donné un nouveau mode de fonctionnement d'un personnage de jeu de plate-forme qui tombe dans l'eau. Ils sont maintenant capables de se diriger dans n'importe quelle direction (indiquée par le stick analogique), accélèrent dans la direction correspondante si on appuie sur un bouton. C'est souple. On voit son perso se tortiller pour faire un demi-tour ce qui donne l'impression d'être dans l'eau ... On peut chercher une certaine forme d'élégance dans les trajectoires qu'on prend ... d'une certaine façon, ça se contrôle un peu comme un jeu de micromachines avec beaucoup de dérapages. Ou un avion qui fait des loopings.</i></fr></p><p><fr><i>Dans chacun de ces cas, exit la "<a href="https://sylvainhb.blogspot.com/2009/12/slopes-contd.html">blind box fonctionelle</a>" d'Enguarde: on peut attaquer dans n'importe quelle direction, à n'importe quel moment.<br /></i></fr></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://twitter.com/pypebros/status/1729600075582824845" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="272" data-original-width="473" height="184" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwxwHgWFaSijyNoFDD7-Va6WC59obHalschHEoioSl0nAodDTMCc-bplNMxDvuziT30qyffDZ8BB5yFbrpqnCXz72Q2o0BJ7gO-AnvgD9uz9Xo9jcJd4sdiIyOMWy8pA9Azj9ER5iutjsM1M8wsq9l3ZKLeuAT8CW1xeGDa-eOhJWncODlOGLEIw/s320/Screenshot%202023-11-29%20at%2009-28-26%20Pype%20(@pypebros)%20_%20X.png" width="320" /></a></div>But the part I prefer is how you get a speed boost into the direction of choice with the JUMP button, and especially how you jump out of water in Ori and the Will of the Wisp like you were a true dolphino. I could certainly do something alike in Bilou Dreamlands. (at first, I wanted to make it an unlockable move so that you could discover secrets later on when you've unlocked some ability ... but that's something for Bilou's Adventure instead).<p></p><p>Of course, with the NDS DPAD, I can't truly have free aiming like in the switch/wiiu titles, but maybe I can find something approaching:</p><ul style="text-align: left;"><li>when you hit FOOT, you get a speed boost in the one-of-eight direction you're aiming with the DPAD.</li><li>during that move, you can modulate your direction (say, +/-15°) around that main direction with the DPAD</li><li>the swim animation eventually comes to a slow down step where you can chose a new main direction and hit FOOT again to keep speeding.<br /></li></ul><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxDG3g9ztP1YEW2CU1guN7SPZZSbSGj2WKALLzwHr1gBPzG-6r-G0rajBN53WB3IZ1uhl1scNa0Z_aw94Hg3piTB9vUPx5DxqJHwLqw7mk1Gxc20g6zlysz8uKvstvNEwPnHqm6pFqPTtAslMnDdMYufIy-tMei_VUNRmF5wJ1uhVcgOPzXIw7Ng/s1203/water-fsm.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="825" data-original-width="1203" height="219" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxDG3g9ztP1YEW2CU1guN7SPZZSbSGj2WKALLzwHr1gBPzG-6r-G0rajBN53WB3IZ1uhl1scNa0Z_aw94Hg3piTB9vUPx5DxqJHwLqw7mk1Gxc20g6zlysz8uKvstvNEwPnHqm6pFqPTtAslMnDdMYufIy-tMei_VUNRmF5wJ1uhVcgOPzXIw7Ng/s320/water-fsm.png" width="320" /></a></div><p><fr><i>Une des choses que j'ai préférées dans ces jeux plus modernes, c'est la manière dont notre personnage peut jaillir hors de l'eau si on fait une "attaque" près de la surface. J'avoue qu'au départ je pensais utiliser quelque-chose inspiré de la physique de nage de Fury of the Furries, où on ne sait sortir de l'eau que s'il y a une berge suffisament "à niveau". Puis offrir le "mode dauphin" avec un level-up, comme le fait Ori and the Will of the Wisps. Mais bon, l'objectif ici, c'est un "dreamland", pas un castlevania. Pouvoir bondir hors de l'eau dès le début du jeu, pour le fun, c'est l'objectif. Première chose à tenter, donc: permettre à Bilou de jaillir de l'eau si on tente de sauter près de la surface.</i></fr></p><p><fr><i>Deuxio, prévoir un dash-swim qui propulse Bilou dans une direction indiquée par le DPAD si je tente de sauter dans l'eau. ça pourrait être intéressant d'en profiter pour essayer de faire l'équivalent aquatique d'un wall-jump parce que j'ai toujours trouvé plus simple de se propulser en utilisant le bord de la piscine que de nager à proprement parler.</i></fr></p><p><fr><i></i></fr></p><div class="separator" style="clear: both; text-align: center;"><i><a href="https://twitter.com/pypebros/status/1729759954968682504" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="231" data-original-width="402" height="184" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBEBfiMcXI9ltYUGj6lPk_bAEJ4zODjSi6ZEvvI8WnaqWXhYK6fipXAopipO8FCYHPuDSwnMhjo6hOCssy_zp8Bahoijci-mlEgkaHOTMFf9ZPWrtO73AYJBC1MGYKGAh74MgaoG1XYMk712CLgv5ycPw8do3ZEHVtOWO_ZLMZu4ywbuE6Dy7rkQ/s320/Screenshot%202023-12-01%20at%2012-50-16%20Pype%20(@pypebros)%20_%20X.png" width="320" /></a></i></div><i>Tertio, le dash sera normalement suivi par une période de "retour au repos" pendant laquelle le bouton saut n'aura aucun effet, mais ça pourrait être intéressant de prévoir d'enchaîner sur un dash si on utilise plutôt le bouton "ramasser". On nagerait alors à la vitesse maximale en enchainant pied - main - pied - main avec le bon tempo... Pas d'attaque aquatique prévue pour l'instant, mais je n'ai pas non plus un bestiaire aquatique débordant ... </i><p></p><p><fr><i>Quarto(?): permettre d'infléchir la trajectoire vers le haut ou le bas avec des petits coups de DPAD pendant un dash horizontal. Et vice versa ... et diagonalement. Ce sera l'équivalent à la croix directionelle des mouvements libres au stick analogique.<br /></i></fr></p><p><fr><i></i></fr></p><p>One other fun thing that might be worth experimenting is doing the equivalent of wall-bounce underwater. At least, it might be the easiest way to get a first experience with wall jumps in my engine.<br /></p><p>And finally, one possibly terrible (or fun) idea would be to keep moving fast underwater with properly timed FOOT / HAND / FOOT / HAND button pressing<br /> </p><p></p>PypeBroshttp://www.blogger.com/profile/10564522267743689261noreply@blogger.com0tag:blogger.com,1999:blog-34057821.post-7003846857883970072023-11-18T15:33:00.005+01:002023-11-18T15:50:39.486+01:00tile 4 { swim.flow = (256,0) }<p><br />Enfin! Je m'attaque enfin à la dernière face de mon 'newmeta/newmap': les tiles spéciaux. Il y avait déjà les blocs spéciaux, auxquels on peut attacher des zones de collision et des actions. Il y a les pentes qui se passent de commentaires et les <a href="http://sylvainhb.blogspot.com/2020/10/direct-flags.html">tiles aux propriétés "directes"</a> qui permettent de combiner jusqu'à 6 propriété distincte (eau, sol, air, lianes, ...) librement. </p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjqvoAL3xO7DT-B4ZfJ8Emny2m0ifdmceIobUD0u2F1ijW3L2vWpVoGoDQ9B1PB5mK02YY0hK9ctwUUFW8EVr9maLPhOoHd58gafwDcaF3vjtOEkiHcboqsxxC0QE81IMjMBcKSTQzXYz1mKD_okC8HW4mlTAXK7TzTTc6UOzZVd4V6wVgl-V5KQ/s259/tile4-leds.png" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="204" data-original-width="259" height="204" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjqvoAL3xO7DT-B4ZfJ8Emny2m0ifdmceIobUD0u2F1ijW3L2vWpVoGoDQ9B1PB5mK02YY0hK9ctwUUFW8EVr9maLPhOoHd58gafwDcaF3vjtOEkiHcboqsxxC0QE81IMjMBcKSTQzXYz1mKD_okC8HW4mlTAXK7TzTTc6UOzZVd4V6wVgl-V5KQ/s1600/tile4-leds.png" width="259" /></a></div><p>Dans le cas des "nouveaux" tiles, le script définissant le jeu va pouvoir encoder librement les propriétés voulues pour chaque type de tile. J'aime y penser comme à un accès indirect, mais c'est probablement parce que j'ai fait trop d'assembleur :-P. Et ça ne s'arrête pas là: je veux les utiliser pour les tapis roulants, le sol qui glisse, et ce genre de choses. Chaque type permet donc aussi d'aller paramétrer des valeurs le concernant auprès des différents contrôleurs.</p><p>En pratique, on va définir <a href="https://sourceforge.net/p/dsgametools/hg/ci/b642a3487b3ad94a5559b3c2d7a6ee8726885266/">dans un fichier script.gam</a></p><pre><code>tile 8 {
is flowdn "0055220000552200"
props fc8 # WATER
swim.flow = (0,512)
}</code></pre><p>La première commande dans le block, <code>is</code> est utilisée dans l'éditeur de niveau, pour fixer le graphisme représentant le type de tile. La commande <code>props</code> donne les fameuses propriétés indirectes. Ces deux-là existent aussi pour les blocs interactifs. La dernière sera passée à une nouvelle fonction <a href="https://sourceforge.net/p/dsgametools/hg/ci/b58b9571a7d42fc19cf77cde9f24003b3b0dcfb8/#diff-5"><code>SwimControllerFactory::setTileVariable()</code></a> qui s'occupera de tout ce qu'il y a derrière le signe <code>=</code> et enregistrera le "mouvement forcé" à appliquer dans <code>GobSwimController::think()</code> quand on se trouve sur ce genre de tile.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcsYvH_sTbVDlI4HlIpDyIVZb5SFL5RkKuSxmUzEO4_yFbdTDdLDyqelZT1aEg3jpbdwBd1FF7oQLYxdHynsKZCcf1owQtY6DeUGhcVjQuktIN6nJkXXYJv78-0Q65w7V1PBApFweg2FtoFJzS93X8qrAkIJi8A2V26OhffKGeBa20ensIETtVtQ/s1644/tile4-sketch83916c498d58bdc9.jpg" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="1288" data-original-width="1644" height="251" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcsYvH_sTbVDlI4HlIpDyIVZb5SFL5RkKuSxmUzEO4_yFbdTDdLDyqelZT1aEg3jpbdwBd1FF7oQLYxdHynsKZCcf1owQtY6DeUGhcVjQuktIN6nJkXXYJv78-0Q65w7V1PBApFweg2FtoFJzS93X8qrAkIJi8A2V26OhffKGeBa20ensIETtVtQ/s320/tile4-sketch83916c498d58bdc9.jpg" width="320" /></a></div><p><en><i>Hello. I've been writing notes about how to have conveyers and flow-in-water since<strike> <a href="http://sylvainhb.blogspot.com/2020/01/lencodage-de-la-physique-du-sol.html">at least 2020</a></strike> <a href="http://sylvainhb.blogspot.com/2019/01/tile-engine-revision.html">2019</a>. Now is the time<a href="https://mastodon.social/@PypeBros/111392189759432901"> to get it done</a>. At last. The syntax of the new "tile" description will look as much as possible to that of the "block" description, used for collectibles and more. Like them, it can describe the <a href="http://sylvainhb.blogspot.com/2019/12/rush-to-flatworld.html">value of cando() flags</a> to be used by controllers with a props statement.</i></en></p><p><en><i>What only they can do is set values for 'controllers variable'. Say that we want water to be able to push Bilou in some direction while he's swimming, we need a table of swim::flowx and swim::flowy that indicate how much Bilou should be moved at each frame if he stays on the given tile.</i></en></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiR_MFXukb8D-NBX0R6DDXeGclevxngZGhagqz3J3cs__2Y8zWRafef_g4Iag28Raoy3zdjVRiaSbj0oYOzOBrpnKkf9GtyHxXy2aaleo9t2K2alYYFx-eJ2k6vC_WN5C_7P0kaEKBVvTRBvXuEaIFa1LqhC2LfuZ0HSfuVxZNtMDEMRg_pgyiJtg/s257/flowblog.gif" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="192" data-original-width="257" height="192" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiR_MFXukb8D-NBX0R6DDXeGclevxngZGhagqz3J3cs__2Y8zWRafef_g4Iag28Raoy3zdjVRiaSbj0oYOzOBrpnKkf9GtyHxXy2aaleo9t2K2alYYFx-eJ2k6vC_WN5C_7P0kaEKBVvTRBvXuEaIFa1LqhC2LfuZ0HSfuVxZNtMDEMRg_pgyiJtg/s1600/flowblog.gif" width="257" /></a></div><p><en><i>After some refactoring of the iWorld class and <a href="https://sourceforge.net/p/dsgametools/hg/ci/b58b9571a7d42fc19cf77cde9f24003b3b0dcfb8/#diff-5">some more code in the script parser</a>, this is finally possible. And with some bugfixes on the level editor, I've got a test case coded for the "three rooms" demo where Bilou is moved away from the waterfall because tiles say so.</i></en></p><p>Quelque jours plus tard, j'ai enfin ajouté le code qu'il faut au contrôleur utilisé pour la nage, téléchargé une nouvelle map avec des tiles "pousseurs" sous la cascade, et voilà: une première mise en application du concept où Bilou, tel un Fury, se fait embarquer vers le fond, puis un poil sur le côté avant d'être recraché vers le haut par les remous...</p>PypeBroshttp://www.blogger.com/profile/10564522267743689261noreply@blogger.com3tag:blogger.com,1999:blog-34057821.post-22809823178326511052023-11-10T13:31:00.000+01:002023-11-10T13:31:01.887+01:00Neocities<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRiq-iT3oY8QJp2jUwyBzyBFrWdDLCbkqcb-fEvRBNesipNArdcLJ_Lqo4IJnrDKuPuENHVCHpVOnyM2wBYeCFq3AgIdgplrPxV7jQ6W-llojxcA3ZE7jt6NcnzbGhLKcjzUnuFnZ2DbVSZj5PZNqanFfZyhGEu0EDxWykKW3TizJkzLgQwxr8zQ/s1033/neocities-scene-downloads.png" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="1033" data-original-width="916" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRiq-iT3oY8QJp2jUwyBzyBFrWdDLCbkqcb-fEvRBNesipNArdcLJ_Lqo4IJnrDKuPuENHVCHpVOnyM2wBYeCFq3AgIdgplrPxV7jQ6W-llojxcA3ZE7jt6NcnzbGhLKcjzUnuFnZ2DbVSZj5PZNqanFfZyhGEu0EDxWykKW3TizJkzLgQwxr8zQ/w285-h320/neocities-scene-downloads.png" width="285" /></a></div><p>Pendant des années, j'ai eu un site présentant mon projet d'OS et mon activité sur la démoscène... et quelques-uns des jeux qu'on avait réalisés avec des amis. Le point commun entre eux, c'était le nom de l'équipe: "PPP Team (Software)". Il a migré de mon compte étudiant à mon compte de chercheur, puis il a fini par disparaître <strike>corps</strike> <code><body></code> z'et bien quand j'ai quitté l'unif.</p><p>Dommage parce qu'il n'y a plus rien pour parler de notre passage sur la Inscene ou des concepts originels du Clicker32 sans lui.<br /></p><p>Mais<a href="https://twitter.com/pypebros/status/1372168384637509635"> entre deux tweet</a>, j'entends parler d'un nouveau service d'hébergement orienté "bon vieil HTML", sans lourderie en php: neocities. Vu que mon premier hébergeur était geocities, ça fait mouche, bien sûr.</p><p>Je transfère donc mes derniers backups sur https://pppteam.neocities.org/ pour voir ce que ça donne ...<br /></p><p><en><i>Somebody on twitter mentioned neocities ... Since I have old (pre-php) web contents that has turned unavailable lately, I decided to re-upload it on brand new <a href="https://pppteam.neocities.org/">https://pppteam.neocities.org/</a> ... So you can visit my old demoscene archives and operating system development manifesto and I don't have to wonder how I could convert that into wordpress</i></en></p><div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;">
<table><tbody><tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzWXrpl2lqWTb1Iu2RIvkus8LFgiClqvmyTboZo5IcWHZWeLQoGZDkLcQk2wrRdXpd0YZ4-aXZhF57wooYtgCRDbKJQYyGoGPR1k75BKQ8c6nJE5nEcQYlAG370BVz7R06ukVhHUP9UujX3LlTi9GIMGrz3VDWPdUC25jASD1JLDN8PQzG4AzQ_g/s756/neocities-os-fs.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="521" data-original-width="756" height="138" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzWXrpl2lqWTb1Iu2RIvkus8LFgiClqvmyTboZo5IcWHZWeLQoGZDkLcQk2wrRdXpd0YZ4-aXZhF57wooYtgCRDbKJQYyGoGPR1k75BKQ8c6nJE5nEcQYlAG370BVz7R06ukVhHUP9UujX3LlTi9GIMGrz3VDWPdUC25jASD1JLDN8PQzG4AzQ_g/w200-h138/neocities-os-fs.png" width="200" /></a></td><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiG0jbLoYdPms6dKuqwWh37c667v_AMUQ1-Q85npUIjtUEuHusrw6eSB3o2XWb_bfp4qH7xbM7ZreAgx-sEQPpvneWAznQ07oFljYfXr58Ev3bra2u3Q77we9U220bVWObS-TaESVIdYR-N_WVeNdpbIjF0Y8LvBaVWWzZARq_vqNI8zAtpeVeCpw/s929/neocities-games-outmup.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="706" data-original-width="929" height="152" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiG0jbLoYdPms6dKuqwWh37c667v_AMUQ1-Q85npUIjtUEuHusrw6eSB3o2XWb_bfp4qH7xbM7ZreAgx-sEQPpvneWAznQ07oFljYfXr58Ev3bra2u3Q77we9U220bVWObS-TaESVIdYR-N_WVeNdpbIjF0Y8LvBaVWWzZARq_vqNI8zAtpeVeCpw/w200-h152/neocities-games-outmup.png" width="200" /></a></td></tr><tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj76ONyf-Pjz0Lh3f4xPtsmj1lwydtvBZwT4UE402Ec-wPkEbiFPrwqgzH82vm9PElcHp-u1X1ejVYXqcX8jfoyoWObrcgTYsanluvE8X8QSpqdsIP_kZI0MI0OVsrU70afkHwGj59k1ljtTs5q_ASELDiNlu0GdsjucvQgYPsv-vI1Y85pMHuqJQ/s926/neocities-games-crazybrix.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="555" data-original-width="926" height="120" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj76ONyf-Pjz0Lh3f4xPtsmj1lwydtvBZwT4UE402Ec-wPkEbiFPrwqgzH82vm9PElcHp-u1X1ejVYXqcX8jfoyoWObrcgTYsanluvE8X8QSpqdsIP_kZI0MI0OVsrU70afkHwGj59k1ljtTs5q_ASELDiNlu0GdsjucvQgYPsv-vI1Y85pMHuqJQ/w200-h120/neocities-games-crazybrix.png" width="200" /></a></td><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnhzvkjiNX55QYeYYX6Brggs-SuP-N9yPczQ6MLL4gWz6QllwlVMINc2aMldzmQoM0dvr09-CZsvT9Ya7ELx1Kh2oZfN_44IfLRFOcwIj82VkEBtG16XTkrYAh1hH4C0OHoijpLkK9QNvUkBAH9UjyVI-j1fxPtDGqKjNB8Hcp-qsbe3I5JPER0Q/s767/Screenshot%202023-10-16%20at%2012-24-48%20PPP%20Team%20obsolete%20homepage.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="767" data-original-width="758" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnhzvkjiNX55QYeYYX6Brggs-SuP-N9yPczQ6MLL4gWz6QllwlVMINc2aMldzmQoM0dvr09-CZsvT9Ya7ELx1Kh2oZfN_44IfLRFOcwIj82VkEBtG16XTkrYAh1hH4C0OHoijpLkK9QNvUkBAH9UjyVI-j1fxPtDGqKjNB8Hcp-qsbe3I5JPER0Q/w198-h200/Screenshot%202023-10-16%20at%2012-24-48%20PPP%20Team%20obsolete%20homepage.png" width="198" /></a></td></tr></tbody></table>
<p>bin ça donne plutôt sympa ^_^</p></div>PypeBroshttp://www.blogger.com/profile/10564522267743689261noreply@blogger.com0tag:blogger.com,1999:blog-34057821.post-70113633504535202092023-10-31T10:16:00.004+01:002024-03-01T13:47:47.397+01:00zik.more "bilou.xm"<p>Bon, après avoir peiné à permettre de mélanger deux jeux d'images dans la mémoire vidéo, il est probablement temps que je regarde à faire la même chose <a href="http://sylvainhb.blogspot.com/2021/11/three-tunes.html">au niveau des sons</a>. En particulier parce que pour l'instant <a href="http://sylvainhb.blogspot.com/search/label/ThreeRooms">ma démo "three rooms"</a> est obligé de partager la même musique pour l'école et la pyramide. Et si CJ ou Piek me débarquait là tout de suite avec une musique plus pyramidale, je serais obligé d'aller copier-coller les samples <a href="http://sylvainhb.blogspot.com/2016/05/sound-effects.html">et les pistes</a> de 'bilousch16.it' par-dessus, sans quoi je risquerais d'avoir des effets bizarres.</p><p>La manière la plus simple de procéder serait de charger d'abord "pyramid.xm" puis d'aller piocher dans "bilou.xm" les pistes et les samples que je veux importer. ça a par contre l'inconvénient qu'à chaque fois que le jeu va charger un nouveau monde, il doit commencer par oublier tous les sons, charger les sons spécifiques au nouveau monde puis enfin remettre les sons communs par-dessus. Avouez que c'est un peu idiot.</p><p>Une alternative à creuser, ce serait de faire en sorte que les sons et pistes d'effets de Bilou.xm restent en mémoire, et que la musique "pour le monde en cours" sache y faire référence sans essayer d'en gérer directement le contenu. En somme, que ces samples aient un statut "d'invités" et que supprimer le morceau en cours n'ait aucun effet sur eux.</p><ul style="text-align: left;"><li>bonne nouvelle: XmTransport, la classe chargée d'ouvrir les fichiers XM, est déjà capable de travailler avec un NTXM::Song& donné.</li><li>[<a href="https://mastodon.social/@PypeBros/112005618785860011">done</a>] vérifier qu'il n'y a pas "d'effet Singleton" dans ::Song</li><li>[<a href="https://mastodon.social/@PypeBros/111983138495608729">done</a>] extraire le bilou.xm hors de la musique de SchoolRush<br /></li></ul>PypeBroshttp://www.blogger.com/profile/10564522267743689261noreply@blogger.com0tag:blogger.com,1999:blog-34057821.post-16011648883809078742023-10-22T18:42:00.001+02:002023-10-25T16:36:26.648+02:00done transition on looping animation<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBcsDlzyNtFCXdmsdOZcUH3_gyUhash5-PYl1R6HplYbgS-rrOsLLtnbJR_jHBpqYzXYraOEWKotXO7ce4e-V3rl6FrDpgIJBj7JjeI1rEyaReJAOEXMHpUvqPzviqDSDcOoXhQNfEvNzW8d8SGBw7ssLopAas-8yOw9Hzu7av3K0Dy3PwdsPzzw/s680/buggy-inkjets-HM18iR2m.jpg" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="640" data-original-width="680" height="301" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBcsDlzyNtFCXdmsdOZcUH3_gyUhash5-PYl1R6HplYbgS-rrOsLLtnbJR_jHBpqYzXYraOEWKotXO7ce4e-V3rl6FrDpgIJBj7JjeI1rEyaReJAOEXMHpUvqPzviqDSDcOoXhQNfEvNzW8d8SGBw7ssLopAas-8yOw9Hzu7av3K0Dy3PwdsPzzw/s320/buggy-inkjets-HM18iR2m.jpg" width="320" /></a></div><p>I've been crawling on the dark side of hobby game development lately. Dark because it mostly involved <a href="https://mastodon.social/@PypeBros/111211662977247096">too much hex numbers</a> and too little pixels to feed enjoyment while doing it. Dark because it implied admitting that I have not been paying enough attention to things like "whether unit test still pass" and "whether it might be the right time to merge that into default". Things that make the difference between coding and coding as a job. Now I have to repay that attention debt, right after the <a href="http://sylvainhb.blogspot.com/2023/09/un-ptit-coup-de-marteau.html">buggy-tool debt</a> and even before I can look at that<a href="http://sylvainhb.blogspot.com/2023/07/ds-ram-leakage-in-testnscripts.html"> memory leakage debt</a>. Given how long it took, how little motivation I had to do it more than 1h per day, I wonder whether I shouldn't have opted for something less useful but more enjoyable first...</p><p>Anyway, I went on with <a href="https://sourceforge.net/p/dsgametools/hg/ci/b7238ae75b878a9741b2ce6558b8c5e81518c00a/">cherry-picking</a> bits of the 'newmap' branch that ought to have been on independent branches and merged into default long ago until I finally <a href="https://mastodon.social/@PypeBros/111262941833958909">identified the fix</a> that stabilizes on what pages animations are actually loaded.</p><p><fr><i>Y'a les jours où le développement de jeux, c'est fun. Puis il y a les jours où le programme supposé anticiper les défauts du moteur de jeu vous crache de l'hexadécimal à la figure. Tout ça parce que j'avais espéré pouvoir remonter dans le temps avant la décision "allez, on va faire évoluer le moteur de jeu pour qu'il puisse supporter plus de pentes, <a href="http://sylvainhb.blogspot.com/2020/01/lencodage-de-la-physique-du-sol.html">plus de types de sol</a> et encore plus de folies!" ... parce que je n'avais pas pris la peine de vérifier que la modification juste avant ("allez, on va autoriser la fuuusiooon de fichiers graphiques au moment du chargement pour permettre d'avoir un monde 2") ne cassait rien de ces fameux tests automatiques.</i></fr></p><p><fr><i>Et encore: l'hexadécimal, il a presque fallu aller le chercher dans les boyaux de la bête qui se contentait sinon de nous roter un "transition sur fin d'animation en boucle". Eh oui. Et j'avais beau reprendre les fichiers dans mon éditeur, vérifier à coup de MD5 que j'utilisais les bons, vérifier l'état du GobTransition dans le débuggeur, rien ne parvenait à expliquer comment l'animation d'inkjet se retrouvait tout à coup avec une boucle.<br /></i></fr></p><p>I have small scribbled characters and notes about it all over my yearly notebook, but I thought it might be worth another "big picture" sketch page to summarize all the things I had forgotten about my own code and re-discovered while working on this specific bug.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzsTnPKJss-RGb-cW0_wbpmCMSjQ3XBmZZSVjME-EXpjbNvIMZMMPTKvfFt6bG8bw7R9gg8i1mun_pdWxmnu5YDOxyHyuF7gZwOHR3jWX_ouQ05VCEWJmWo5fam1o357x7aQIgpUvxRcZqEYA8rJBCbe8Rcvoh8h6KLPO1j_NbdhvA2oEi3BbDiw/s1707/animspr-bugfix.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1215" data-original-width="1707" height="456" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzsTnPKJss-RGb-cW0_wbpmCMSjQ3XBmZZSVjME-EXpjbNvIMZMMPTKvfFt6bG8bw7R9gg8i1mun_pdWxmnu5YDOxyHyuF7gZwOHR3jWX_ouQ05VCEWJmWo5fam1o357x7aQIgpUvxRcZqEYA8rJBCbe8Rcvoh8h6KLPO1j_NbdhvA2oEi3BbDiw/w640-h456/animspr-bugfix.png" width="640" /></a></div><p></p><p>Like how you can load two files in the <code>sprdo</code> helper tool to see which animation #543 truly is ... I should have remembered that earlier on. As soon as I noticed that the the commands I could see in the debugger were not matching what they should (they were ending with a 'LOOP' command, just to start with. I tried comparing them with the line above, the room above, but I should really have just compared them with the next page ^^". Then I've been distracted by that "meds+4" extra token on some files, but it was just a hint for Level Editor. I guess that would have been obvious if I had refreshed memories of "world 2" by reading my own blog posts again. But for some reason, I only thought about that tag now, when blogging about how I eventually figured out that I was missing some fix written long ago, but not merged on "default" ^^".<br /></p><p><fr><i>Au final, ce que j'aurais du faire, c'est comparer cette animation incompréhensible à celle se trouvant au même emplacement, mais sur la page *suivante* dans mon fichier school.spr ... parce qu'il me manquait sur la branche que je cherchais à corriger un malheureux patch corrigeant un décalage d'une position au moment d'enregistrer les animations du fichier supplémentaire à côté du fichier de base :P<br /></i></fr></p>PypeBroshttp://www.blogger.com/profile/10564522267743689261noreply@blogger.com0tag:blogger.com,1999:blog-34057821.post-26002390522718944542023-09-30T17:51:00.004+02:002023-10-02T14:01:29.363+02:00Un p'tit coup de marteau ...<p></p><div class="separator"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdKwu7v8sERrwCXhSaVinzrMMgVkGbU7SLFFGt3P4VH1YyLbnaKXMPDifyDwaqG_3HeoFhFWhua_WUpsc4ZKgXtqC9NsHaRReATDBu6A8QXidsV95H0MhbSSJJK4mOxAcmBBnXfQBOb5Yc2AyyJN7gLKtUg1C5zZL59hSNcaFskp4LPhYDRYlhHw/s1174/Photo0188-AnimEDS-guru.jpg" style="clear: right; display: block; float: right; margin-bottom: 1em; margin-left: 1em; padding: 1em 0px; text-align: center;"><img alt="" border="0" data-original-height="958" data-original-width="1174" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdKwu7v8sERrwCXhSaVinzrMMgVkGbU7SLFFGt3P4VH1YyLbnaKXMPDifyDwaqG_3HeoFhFWhua_WUpsc4ZKgXtqC9NsHaRReATDBu6A8QXidsV95H0MhbSSJJK4mOxAcmBBnXfQBOb5Yc2AyyJN7gLKtUg1C5zZL59hSNcaFskp4LPhYDRYlhHw/s400/Photo0188-AnimEDS-guru.jpg" width="400" /></a></div>Mes <a href="http://sylvainhb.blogspot.com/2023/01/how-it-is-bashing.html">dernières</a> <a href="http://sylvainhb.blogspot.com/2022/03/animating-undead-cell.html">sessions</a> avec <a href="http://sylvainhb.blogspot.com/2020/08/animeds-cru-2020.html">AnimEDS</a> s'étaient toutes soldées par des "guru meditation". Peu de travail perdu, heureusement, le problème se produisant généralement soit juste au début, soit juste après une sauvegarde. L'impact sur ma motivation à continuer à animer mes p'tits persos en prenait quand-même chaque fois un coup: j'aurais pu effectivement perdre un travail précieux.<p></p>
<p>Alors j'ai noté de faire du debugging de tout ça. Il y a un bail. D'abord refaire une version précise de l'animateur (rH2021) et garder le .nds et son .elf à côté des fichiers re-générés à tout bout de champ quand je bricole du homebrew, histoire que quand le problème se présente console en main, je puisse effectivement utiliser la valeur du registre PC pour retrouver un numéro de ligne dans le code. C'est le cas depuis Juin.</p><p><en><i>I can't help wondering whether this is worth translating. It's another epic (?) showdown between me and my code to see who's got the StrongARM. But well, it has been bugging me since January, crashing the animation editor almost every time I used it. I'm just lucky I never lost anything important but motivation to work on some cute things over the evening. The "guru meditation" screens I got during the first half of the year were almost useless: the AnimEDS build on my 'lime' DS was so old I did not have the matching .ELF file for my debugger anymore. Believe it or not, the RealLife (tm) has turned so intense that I even had to write down an agenda check list with "rebuild ; keep .elf apart ; upload .nds to lime" to actually get it done.<br /></i></en></p><p>Pas de chance: c'est un de ces bugs où l'adresse ne dit pas grand-chose parce qu'on est a suivi des pointeurs de fonctions qui ne voulaient rien dire. Mais! Bonne nouvelle, avec les nouvelles animations pour l'Appleman, le bug est plus facile à reproduire: il suffit d'essayer de copier une frame d'animation juste après avoir chargé la première animation du fichier dans l'éditeur.</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh93SItyrBcaak0ixtgyzoe0KkfTDHXDAuZiUbCdDs7UD3BcGhefKYQplr_28XxUI0G8gK_atvAdce7QVELAMMqGgziy3MLyslnLuJMXcA319EL7Vlhjo6EtpFLASkGERgCPBX6lb77uQjb2OasHi36Z6ImPGne64tRXyW4KL_ikP6ExMKiKr3imQ/s776/Animeds-7f84dbf04b2bdccc.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="708" data-original-width="776" height="292" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh93SItyrBcaak0ixtgyzoe0KkfTDHXDAuZiUbCdDs7UD3BcGhefKYQplr_28XxUI0G8gK_atvAdce7QVELAMMqGgziy3MLyslnLuJMXcA319EL7Vlhjo6EtpFLASkGERgCPBX6lb77uQjb2OasHi36Z6ImPGne64tRXyW4KL_ikP6ExMKiKr3imQ/s320/Animeds-7f84dbf04b2bdccc.png" width="320" /></a></div><p>Alors j'ai ressorti mon émulateur et mon débuggeur et là, bonne nouvelle, ça foire aussi dans l'émulateur. Différemment, mais ça foire, donc c'est débuggable. Et là,<a href="https://mastodon.social/@PypeBros/111138810701650771"> j'ai galéré pendant des heures</a> ... Des structures qui ne veulent rien dire, des vptr complètement à l'ouest ... Il faut dire que pour encoder la ligne du temps utilisée par l'éditeur, j'ai pris une std::list de std::pair de classe dérivées. Bref, on se perd sous les couches de templates, de membres dépendant de l'implémentation et d'optimisation du compilateur qui prend un malin plaisir à rendre inaccessible les variables dont on aurait besoin.</p><p><en><i>With that done, I wasn't much more lucky. It's one of those bugs where you try doing a virtual function call on something that isn't truly an object and thus end up in the middle of nowhere, especially where memory contents doesn't match any valid opcode. Hopefully, while trying to get the crash to write down registers values, I realised that the bug was actually easy to reproduce (just open one animation and try to copy the frame before selecting any frame) and a bit later, that it also happened with the same file in my emulator. At least I could save the evening where I navigate DS memory to reconstruct objects on paper this time.</i></en><br /></p><p></p><p>J'allais jeter le gant puis un soir j'ai noté dans mon calepin "fait du débugging indirect en surveillant les constructeurs". Bah oui: la variable aura beau avoir été optimisée, il faut bien qu'il soit construit à un moment où à un autre, le TIFrame qui explique pourquoi j'ai du n'importe quoi dans les registres au moment de copier cette première frame.</p><p>Sauf que ... non. Les "TIFrames" sont construites vides, puis au fur et à mesure que l'AnimationParser traite la liste de commandes destinées à GEDS -- le moteur de jeu -- il complète les coordonnées, les numéros d'images, etc. J'étais sur le point de laisser tomber (traduire: réécrire tout avec ma propre classe 'liste' plus propice au debugging) quand je réalise que je peux "figer" l'afficher d'une ou de TIFrame dont je capture l'adresse à la construction, et suivre leur évolution jusqu'au bug (l'animation en question ne contient en réalité qu'une frame et une commande de contrôle). Et là, surprise, tout va très bien (Mme la Marquise :)</p><p> <en><i>It did not save navigating memory altogether though. The way gdb handles std::list and std::pair combined to the amount of variables that were actually "optimized away" when they would be critical to have around still turned that debugging session into some guru meditation. I first thought that it was because of some incoherent animation instructions into the animation itself, but inspecting how the animationParser processed them shown everything should be fine. Yet, if I tried to see what frame was triggering the bug, all I'd get was garbage non-sense. I was about to replace all that std::* by some pype::* when I realised that I could just break on constructors of the contained TimeItems to see what the list contained.</i></en></p><p><en><i>That did not work either, unfortunately, because when TimeItems are added to the list, they are "blank" items that will be modified by the yet-to-come UPDATE animation commands. What did help, was creating some static watches at addresses discovered in a constructor-breakpoints so that I could look at the state of my list just before the offending call. That and realising that the list was just fine, thanks, but that I was using an iterator that might not have been updated since the previous list had been trashed and replaced by the new one :P<br /></i></en></p><p>Une seule explication restante: <a href="https://sourceforge.net/p/dsgametools/hg/ci/1aee3987aa31d448aed99aec73203c7974efd474/">c'est l'itérateur qui devient invalide</a> au bout d'un moment. Je sors mon cahier A4 histoire de me faire une map UML de tous les bouts de code impliqués et c'est bien ça: quand on choisit une animation à éditer, la liste est vidée, mais l'itérateur reste inchangé, <a href="https://stackoverflow.com/questions/759274/what-is-the-lifetime-and-validity-of-c-iterators">ce qui est invalide</a>.<br /></p><p>Ah oui. Vous vous demandez "pourquoi le marteau" ... et vous n'avez pas Thor. C'est à cause de cette blague d'ingénieur où un consultant rentre une facture de $100000 pour une intervention et ça rouspète chez le client parce que "vous avez juste donné un coup de marteau!". Et le consultant de reconnaître qu'il a fait une erreur et de préparer la facture suivante</p><ul style="text-align: left;"><li>1 hammer hit: $10</li><li>knowing where to hit $99990</li></ul><p>(bon, c'était vraiment une grosse machine très chère qu'il fallait dépanner). Bin c'est un peu la sensation que ça me fait sur ce bug-ci. Sauf que je ne vais pas recevoir des cents et des mille et que je ne devrai pas les débourser non plus :P <br /></p><p> </p>PypeBroshttp://www.blogger.com/profile/10564522267743689261noreply@blogger.com2tag:blogger.com,1999:blog-34057821.post-58907729063002502062023-09-20T15:05:00.004+02:002023-09-20T15:09:03.638+02:00Tiny Thor, at last!<p><en><i></i></en></p><div class="separator" style="clear: both; text-align: center;"><i><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyTkqZsHthpbWLbsSeLFYgoqaHZjjCkZrSe6FM-ePrQLeIdyc-fpVvUbw-xx4TiAN3tUSqbehikWeK-ZKfwT89JXgz-M4lcOx9yqmLPay29Ea8CcC2Blf797xDhA3WYD6HEAKFsgdXdHibYnVdK5G0n_x9fTWhPTMcAI8ikfdHdzUV385zBrFwjA/s680/tinythor.jpg" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="383" data-original-width="680" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyTkqZsHthpbWLbsSeLFYgoqaHZjjCkZrSe6FM-ePrQLeIdyc-fpVvUbw-xx4TiAN3tUSqbehikWeK-ZKfwT89JXgz-M4lcOx9yqmLPay29Ea8CcC2Blf797xDhA3WYD6HEAKFsgdXdHibYnVdK5G0n_x9fTWhPTMcAI8ikfdHdzUV385zBrFwjA/s320/tinythor.jpg" width="320" /></a></i></div><i>I have records of tracking <a href="https://twitter.com/joemanaco">Joe Manaco</a>'s "Tiny Thor" title for as long as <a href="https://twitter.com/pypebros/status/1350002725153615872">January 2021</a>. With gorgeous art from Henk Neiborg and brilliant <a href="https://chrishuelsbeck.bandcamp.com/album/tiny-thor-soundtrack">soundtrack by Chris Huelsbeck</a>, the game's author even revised his project to match the level of those invited developers. I've been waiting for it to be released on the Nintendo Switch, and yeah! Huzzah! it did!</i><p></p><p><en><i>Most of the game is amazing. Gorgeous art, (very) challenging levels and smooth action. I hope I will manage to get far enough in the game, but it is already pointing out that my skills are not on par with those of the intended audience. Holding a trigger to freeze while aiming a shot in a platformer is not a bad idea, but I struggle to explain that to my fingers ^^". As a result, I end up in spikes or with my hammer flying the wrong direction more often than I should. Note that I had the same issue with that-space-pirate-game<br /></i></en></p><p>Rho, ce que je l'ai attendu, ce jeu! Rien que savoir qu'il y avait Henk Nieborg aux pixels ... D'autant que contrairement à d'autres projets esthétiquement attractifs (comme CyberShadow ou Flynn, son of Crismon), ici on est sur un mode de jeu qui fait véritablement partie de mes styles de prédilection au niveau du gameplay. Mais le voilà! il est sorti sur Switch et il a été rejoint par Chris Hülsbeck aux platines.</p><p>Niveau game design, c'est bien rôdé. Niveau difficulté, c'est une autre histoire. Non pas que le jeu soit injouable ou infogramesque, mais le peu d'habileté dont je dispose est mis à rude épreuve. Une des opérations de base est de maintenir une gachette enfoncée pendant que le stick directionnel indique la trajectoire que Mjolnir le marteau devra suivre une fois lancé ... manipulation qui m'avait déjà un peu donné de fil à retordre dans FlintHook et que j'ai du mal à faire entrer dans mes doigts.<br /></p><p><en><i>Levels in Tiny Thor are quite long, as I'm approaching the second boss. It took me no less than 30 minutes for the last level I played (it took about 10 minutes to a <a href="https://youtu.be/n1Eu_zfRBws?t=721">fairly trained player</a>). Should I leave the game on pause at one of the numerous checkpoints in the game, I will take the risk that one of my kids pick the controller to play a game of Kirby in the Lost World and zap my progress. That definitely reminds me of the level design of Donkey Kong Returns and <a href="http://sylvainhb.blogspot.com/2017/04/de-plus-en-plus-long.html">Giana Sisters: Twisted Dreams</a>. </i></en></p><table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em;"><tbody><tr><td style="text-align: center;"><a href="https://twitter.com/pypebros/status/1696603271933329469/video/1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" data-original-height="359" data-original-width="373" height="308" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTX4KJsHnLmipoDgIPmxnA9lKBlAAp6gqhxJpOweR4ISN9oP9_QEuLfh0ZOYwWUJk2H1A-U-eImmu8Hajn6etWiYt6hyPM9QCnty96jNcLkCyT5zY86nSM9leAhWlZVGtjbzVb2R4RSFFgyYTHkXdBpMynvmIcS9UP_zCri54Pns2Hd6o2PDVIsg/s320/Screenshot%202023-09-06%20at%2017-39-54%20Pype%20(@pypebros)%20_%20X.png" width="320" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Spiders... One of my favourite monsters</td></tr></tbody></table><p><en><i>The game also share one major skill barrier with those two other platformer: when you respawn, you start with just one hit point. Should you hit anything while you're trying to reach the location where you died, you'll die again. There are extra hitpoints to be found, and a fairly nice gameplay mechanic where you can recover your lost hitpoint à la Sonic, except it has a variable time à la Yoshi Island. That means one obstacle you could have passed in a few attempts will now take you over 10 tries just because you're super-fragile as soon as your second attempt, unless Joe granted you a health pick-up just next to your respawn point (which hopefully happens from time to time).</i></en></p><p>Une fois que cette manoeuvre est devenue un peu moins laborieuse, on arrive dans des niveaux dont la longueur elle-même devient un challenge. Pas loin de 30 minutes dans le niveau contenant le 1er boss (qu'un joueur un peu mieux entrainé atteint en 10 minutes). Il y a un bon nombre de checkpoints dans un niveau mais je ne peux m'y "arrêter" qu'à condition que mes enfants ne cherchent pas à utiliser la switch pendant l'après-midi ^^". Au moins, la console (contrairement à une PlayStation) est prévue pour des veilles prolongées, mais <a href="https://sylvainhb.blogspot.com/2017/04/de-plus-en-plus-long.html">ça a tout de même un petit goût de Giana Sisters: Twisted Dreams</a>. D'autant que, comme dans ce dernier, si j'échoue entre deux checkpoints, je reviens extrêmement vulnérable pour réessayer le passage délicat. J'entends par là "un-coup-t'es-mort". Comme dans Super Mario Bros direz vous. Oui, sauf qu'on voit rarement autant de pics et d'ennemis en vrac dans SMB qu'on en voit dans Tiny Thor. Et de toutes façons, SMB1 est toujours trop dur pour moi :P</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDs8sS4XWMcN_M2LFQGDNf2TeWsLFPQiCLhgwacqtx4f4F6gKutooHPwsY5rAOuijbc84MGkBFo-s2cTgtF3VbfPa-6wEO5NiDGmBzKNDarQ-oKEuvAMTTSo9PJ1cJm6CdtoHJYUpXkjS8nt70J3JeqqY0eaqMSVG5jsUmy9_e_iu87v5frm7NKQ/s446/tiny-thor-heart.png" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="399" data-original-width="446" height="286" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDs8sS4XWMcN_M2LFQGDNf2TeWsLFPQiCLhgwacqtx4f4F6gKutooHPwsY5rAOuijbc84MGkBFo-s2cTgtF3VbfPa-6wEO5NiDGmBzKNDarQ-oKEuvAMTTSo9PJ1cJm6CdtoHJYUpXkjS8nt70J3JeqqY0eaqMSVG5jsUmy9_e_iu87v5frm7NKQ/s320/tiny-thor-heart.png" width="320" /></a></div>Il y a tout de même moyen de ramasser un coeur-pour-un-coup-en-plus. On en a même de temps en temps un dans un bloc à côté du checkpoint. Là je pourrai encaisser un coup sans défaillir. Le coeur s'enfuit alors en rebondissant un peu comme un Yoshi dans SMW, et j'ai un temps limité pour le récupérer. Une mécanique que l'auteur avoue avoir emprunté à Yoshi's Island, les pleurs de bébé en moins. ça m'aura certainement sauvé la mise à pas mal de reprises, récupérant un coeur au bout de quelques secondes, puis me faisant à nouveau toucher un peu plus tard, le coeur se sauvant à nouveau mais me laissant cette fois moins de temps pour le récupérer jusqu'à ce que je tombe sur un bloc-coeur où je pourrai rajouter des secondes à ce précieux compteur. Mais une petite noyade, et toute cette jolie chaîne s'interrompt: on repart aussi fragile qu'un Rick Dangerous depuis le dernier point de sauvegarde. Les vies sont infinies, et ce n'est pas un hasard.<br /><p></p><p><en><i>You sure have guessed now: the game is hard. It doesn't feature any 1-UP or lives counter and there's a reason for that. The developer was aware of that and provides a menu with a set of "game genie" options, like how much you stick to walls, how high you jump (yes, truly), whether your heart bounces much or not when you lose it, etc. A good idea, well executed, but if you ask me, it lacks one critical option: to swim out to safety. I'm glad<a href="http://sylvainhb.blogspot.com/search/label/deep%20ink%20pit"> I did this in School Rush</a>, despite it might not be perfect and might not completely save "your" lives, but <a href="https://twitter.com/pypebros/status/1697962094686277651/video/1">given</a> <a href="https://twitter.com/pypebros/status/1697961168109973950/video/1">the</a> <a href="https://twitter.com/pypebros/status/1694814642445688971/video/1">number</a> <a href="https://twitter.com/pypebros/status/1694814033915093354/video/1">of</a> <a href="https://twitter.com/pypebros/status/1694813623250829445/video/1">times</a> <a href="https://twitter.com/pypebros/status/1694813023146549591/video/1">I've</a> drown that Tiny Thor, I now know it was good.<br /></i></en></p><p><en><i></i></en></p><div class="separator" style="clear: both; text-align: center;"><i><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcgtM_UECCx2ww_QpanyL1SPvY-uC5qtjOOxL7KX1MV4C2bPTnmO813o4yx8rY0vUT-o9d4cPrxK6D00KxXzFiNV3qICdSDLBUK3xbTG1TDxqZ7PecXhfDc0NJIHKCIFcYy7POjd4nw016CQjdkC4pRSyhdfZKLk6l6Dcpd7VGI6LPmjYEqD5Svw/s429/thor-times.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="245" data-original-width="429" height="183" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcgtM_UECCx2ww_QpanyL1SPvY-uC5qtjOOxL7KX1MV4C2bPTnmO813o4yx8rY0vUT-o9d4cPrxK6D00KxXzFiNV3qICdSDLBUK3xbTG1TDxqZ7PecXhfDc0NJIHKCIFcYy7POjd4nw016CQjdkC4pRSyhdfZKLk6l6Dcpd7VGI6LPmjYEqD5Svw/s320/thor-times.png" width="320" /></a></i></div><i>Just for the record, I re-played levels 1-2, 2-2 and 3-2 using the in-game time counter to measure how long I spent between two check points. The duration is comparable to the average 1:30 minutes per School rush *level*. Yes, the question of whether the game <a href="https://sylvainhb.blogspot.com/2015/02/checkpoint.html">should have offered mid-level checkpoints</a> is still itching me.<br /></i><p></p>PypeBroshttp://www.blogger.com/profile/10564522267743689261noreply@blogger.com2tag:blogger.com,1999:blog-34057821.post-56525105363007789532023-09-08T18:00:00.001+02:002023-09-08T18:00:00.134+02:00operator sockaddr*()<p>J'ai passé un peu de temps cet été dans du code third-party qui avait un autre dialecte c++ que moi. En particulier, ils aimaient bien faire des objets-wrappers métamorphes. Prenons par exemple une adresse réseau. C'est pénible: on peut l'avoir sous forme ASCII ou dans un entier 32-bit (ou un gros blob si on est en IPv6). Et de toutes façons, pour s'en servir il faudra qu'elle soit emballée dans un sockaddr, seule connue de l'API socket, qui reprend un identifiant de 'famille de protocole' et un numéro de port.</p><p>Tout ça semble justifier une classe <code>NetAddress</code> qui aurait des constructeurs <code>NetAddress(std::string fromUserInterface)</code> et <code>NetAddress(uint32_t fromProtocolMessage)</code>. Très bien. On peut aussi en faire en réalité un wrapper de `struct sockaddr_storage`, et remplir les différents champs au moment de l'appel. Avec éventuellement un <code>NetAddress.setPort()</code> pour faire bonne mesure.</p><p>Mais ce n'est pas ça qui va changer le fait que <code>connect()</code> et <code>bind()</code> travaillent exclusivement avec des <code>sockaddr</code>. Là où j'ai été surpris, c'est qu'au lieu d'un <code>NetAddress.getSockAddr()</code>, j'ai eu droit à</p>
<pre><code>operator sockaddr*() {
return reinterpret_cast<const sockaddr*>(&address);
}</code></pre><p>Séduisant a priori. Elégant, même. Mais à l'usage (et surtout à la lecture), ça s'est avéré être un fiasco. Je tombais sur du code du genre <code>connect(toServer, myServerAddress, options)</code> suffisament loin de la définition de myServerAddress et je zappais qu'il ne s'agissait pas d'un sockaddr classique, mais de l'objet emballant. Particulièrement piégeux quand on essaie de découvrir d'où provient l'exception InvalidArgument que rien dans le code de connect ne semble pouvoir générer.</p><p>Et ç'aurait pu être encore pire si myServerAddress avait été un pointeur vers une NetAddress ... Là, on aurait dû écrire <code>connect(toServer, *myServerAddress, options)</code>, parce que c'est un NetAddress-même que le compilateur a appris à "traduire" en sockaddr* à l'aide de l'opérateur. Pas un pointeur de NetAddress. Perturbant au possible quand on se souvient qu'en C on aurait écrit <code>connect(toServer, &server_address, opts)</code>;<br /></p>
<p>...</p>
<p>Sinon, vous, l'été, ça a été ?</p>PypeBroshttp://www.blogger.com/profile/10564522267743689261noreply@blogger.com0