jeudi, avril 08, 2010

ATTR0_ROTSCALE : partie I

Tout comme le GBA et la SNES, la DS est capable de zoom et "rotations" sur un sprite. Une fonction quelque peu obscure, sans doute parce que liée à une implémentation hardware alors qu'on serait tenté de penser "transformations géométriques" (comme dans le cas d'OpenGL) ou "programme de rendu". Eh bin non. Puisque je projette de me servir de sprites aussi pour la visualisation des zones de collisions pour mon InspectorWidget, voilà un peu de bidouille pour identifier les quelques points importants à prendre en compte. Mon "sprite de base" est une sorte de grille/radiateur noir dans une zone de 16x16.

Engine::sprites[oam].attribute[0]=ATTR0_ROTSCALE|ATTR0_ROTSCALE_DOUBLE|
ATTR0_TYPE_BLENDED|ATTR0_SQUARE|y;
Engine::sprites[oam].attribute[1]=ATTR1_ROTDATA(oarot)|ATTR1_SIZE_16|x;
pSpriteRotation sr = Engine::spriteRotations + oarot;
sr->hdx=0x100; sr->hdy=0x0; // 8.8 fixed point : 0x100 is 1.00 here
sr->vdx=0x0; sr->vdy=0x100;
ROTSCALE_DOUBLE affecte la manière dont les coordonnées sont interprétées. C'est la zone de visualisation -- de 32x32 ici, matérialisée par les # blancs -- qui aura ses coordonnées en (x,y). Le sprite proprement dit, lui, verra son centre coïncider avec le centre de cette zone.
Si je donne les paramètres (hdx,hdy,vdx,vdy) = (1,0,0,1) -- ce qui correspond à un affichage sans aucune transformation -- mon sprite apparaîtra donc w/2 pixels plus à droite et h/2 pixels plus bas que les coordonnées (x,y) que je lui fixe.

A noter que [hv]d[xy] indique "de combien avancer (en X et Y) dans la "texture" du sprite lorsqu'on avance d'1 pixel Horizontalement ou Verticalement sur l'écran. Du coup, un zoom grossissant s'obtient avec des valeurs de hdx plus petites que 1.

Si je zoome (0.5,0,0,0.5) puis (0.25,0,0,0.25), le centre de mon sprite continue effectivement à coïncider avec le centre du "viseur". En revanche, impossible de sortir de la "zone de visibilité" de 32x32, même avec un facteur de zoom (4x) qui devrait m'afficher un sprite de 64x64, je ne vois plus que le centre de l'image.

En clair, le hardware permettra sans problème de légère déformations, comme celles subies par Morton Koopa Jr., et n'importe qu'elle réduction de taille (jusqu'à 256 fois plus petit ;), mais pour un zoom prend-toi-ça-dans-les-dents tels qu'on en a vu dans le combat contre Bowser dans SMW ou dans Turtles in Time, il faut ruser...
  • soit en utilisant plus de sprites,
  • soit en prenant des sprites plus gros que ce qui est nécessaire (p.ex. 64x64), zoomés de manière logicielle et rapetissés artificiellement par le hardware -- probablement la solution pour mes zones de collision,
  • soit (à mon avis plus plausible) en utilisant un fond plutôt qu'un sprite pour le boss. Ca s'est régulièrement vu sur NES où les sprites avait des tailles ridicule (8x8 ou 8x16 :P)
PS: tests réalisés sous Desmume 0.9.4 (linux) et confirmés par le hardware.

3 commentaires:

lint a dit…

There is no such things as sprite rotation on SNES. It's always done with mode7 tricks.

sylvainulg a dit…

@Lint: thanks for the correction. I take your word for it, as far as the SNES is concerned. Is there sprite scaling anyway ?

cyborgjeff a dit…

vachement ingénieux ton systeme de débogging ;)