Événements liés
  • Démo technique du samedi #4: 26 Mai 2007
Pages: [1]   Bas de page
Imprimer
Auteur Fil de discussion: [Demo] Ouvrez les fenêtres...  (Lu 6083 fois)
0 Membres et 1 Invité sur ce fil de discussion.
Mollusk Hors ligne
Administrateur
*****
Messages: 3537


Voir le profil WWW
Ne vous posez pas de questions, codez !

« 26 Mai 2007, 14:25:51 »

Sur DS, on trouve des entités assez particulières. On a vu l'autre fois comment jour avec le HBL, mais ce n'est pas la seule chose que l'on peut faire...


Fenêtres : les bases

La DS, comme sa petite soeur, possède nativement un système de 'fenêtres', Windows... Celles-ci ont une utilisé bien déterminée : Elles permettent de montrer ou de cacher des choses qui sont à l'écran. Alors ok, dit comme ça, on n'a pas trop envie de jouer avec... Et pourtant on peut obtenir des effets bien sympathiques !

<a href="http://www.palib.info/blog/flvplayer.swf?file=http://www.dev-fr.org/Demos/Ronds/Window.flv" target="_blank">http://www.palib.info/blog/flvplayer.swf?file=http://www.dev-fr.org/Demos/Ronds/Window.flv</a> 
Télécharger la démo

Voilà un effet de transition classique, simple, et efficace Smiley Cet exemple est tiré de PAlib (PAlibExamples/Transitions/WindowFade).


PAlib

Je poste rapidement le code pour PAlib, tout simple, mais pas vraiment intéressant :
Code
(c):
for (i = 32; i >= 0; i--) {
PA_WindowFade(screen, fadetype, i);
PA_WaitForVBL(); // To slow down the fades, we wait a frame...
}
Voilà, c'est simple, on choisit le type de fade, l'écran, et on fait varier la valeur de 0 à 32... 0 pour visible, 32 pour invisible. Rien de bien sorcier.


Libnds

J'invite les PAlibiens à lire aussi cette partie, car elle illustre le fonctionnement sous-jacent et il faut l'avoir intégré pour comprendre les démos qui suivent Wink

Libnds donne quelques définitions pour les registres des fenêtres. Il suffit de rajouter SUB_ pour activer le registre pour l'autre écran...
Pour la fenêtre 0 :
WIN0_X0, WIN0_X1, WIN0_Y0, WIN0_Y1
Pour la fenêtre 1 :
WIN1_X0, WIN1_X1, WIN1_Y0, WIN1_Y1
Mais aussi :
WIN_IN et WIN_OUT


On a en fait plusieurs choses : 2 fenêtres différentes, rectangulaires, numérotées 0 et 1, que l'on change de façon basique en définissant 2 points (coin supérieur gauche et coin inférieur droit, définis par (X0, Y0) et (X1, Y1). Mais on a aussi des fenêtres dites objets, que l'on verra dans la dernière partie Wink
Mais à quoi servent donc les registres WIN_IN et WIN_OUT ?

Ils permettent en fait de contrôler ce que l'on verra dans la fenêtre et en-dehors. Mon exemple n'est pas parfaitement représentatif, car il cache le fond, sans plus. Mais on peut en fait utilisé une fenêtre pour à la fois cacher et afficher : cacher un fond progressivement, tout en remplaçant l'affichage par un autre... Afin de simplifier les choses, j'utilise un jeu de définitions :

Code
(c):
#define WIN_BG0 1
#define WIN_BG1 2
#define WIN_BG2 4
#define WIN_BG3 8
#define WIN_OBJ 16
#define WIN_SFX 32

Pour WIN_IN, les 8 premiers bits concernent la fenêtre 0, et les 8 suivants la fenêtre 1... (donc ajouter par exemple (WIN_BG0<<Cool, etc...).
Pour WIN_OUT, c'est un peu différent. On ne peut pas définir séparément pour les 2 fenêtre, on n'a que 8 bit pour les 2. Tant pis !
Mais à quoi servent donc les 8 derniers ?? Tout simplement à définir le WIN_IN pour les OBJWIN (fenêtres objets, que nous verrons après...)

Mais tout cela ne marchera que si l'on active les fenêtres :
DISPLAY_CR => DISPLAY_WIN0_ON, DISPLAY_WIN1_ON, et DISPLAY_SPR_WIN_ON, au choix Smiley

Voilà, je pense qu'il n'est pas nécessaire de donner plus de code que ça, tout est relativement clair et simple, on définit la position du rectangle et ça marche tout seul Smiley

Pour les utilisateurs de PAlib, toutes les fonctions sont listées et expliquées ici : Doc PAlib...
Pour résumer l'utilisation avec un exemple tout con :
Activation de la fenêtre 0 : PA_EnableWin0(screen, WIN_BG0|WIN_BG1)  (pour les fonds 0 et 1, ajout |WIN_TRUC pour avoir d'autres choses...)
Puis : PA_SetWin0XY (u8 screen, u8 x1, u8 y1, u8 x2, u8 y2) pour le positionnement... (valeurs de 0 à 155)


Fenêtres : HBL powered

Imaginons à présent que nous changions les positions de la fenêtre dans le HBL, comme nous faisions pour le scrolling dans l'une des démos précédentes... Quel serait le résultat ? Langue

<a href="http://www.palib.info/blog/flvplayer.swf?file=http://www.dev-fr.org/Demos/Ronds/HBLWindow.flv" target="_blank">http://www.palib.info/blog/flvplayer.swf?file=http://www.dev-fr.org/Demos/Ronds/HBLWindow.flv</a> 
Télécharger la démo
Télécharger les sources

Et oui, on peut ainsi outrepasser la limite des fenêtres (à savoir la forme rectangulaire) et obtenir un peu tout et n'importe quoi comme forme. Dans cet exemple, j'ai utilisé la fonction Sinus pour faire un effet de vague, je trouve ça sympa, mais on pourrait imaginer d'autres fonctions pour avoir des effets différentes, comme un losange, etc... Le principe reste alors le même, changer les positions de la fenêtre pendant le HBL...

Bon, on to the code !

Commençons par la fonction à mettre en HBL :
Code
(c):
s8 width = 8;
 
s8 height = 16;
 
u16 add = 0;
s16 pos = 0;
 
 
 
s16 x, x0, x1; // Pour calculer...
 
 
 
void HBL_function(void){
 
  s16 vcount = PA_GetVcount();
 
  vcount++;
 
  if(vcount > 192) vcount = 0; // Get correct vcount
 
  x0 = ((PA_Sin((vcount)*height+add)*width)>>8);
  x1 = x0+255-pos; // Autre bout de l'écran
  x0 += pos;
  if(x0 < 0) x0 = 0; // Ne pas tomber plus bas...
  if(x1 > 255) x1 = 255;
 
 
  PA_SetWin0XY(0, x0, 0, x1, 191); // Position de la fenêtre...
 
}

Rien de particulier, je n'ai fait que copier/coller la fonction de l'autre jour Azn  Dans cette démo, 'add' reste toujours à 0 parce que je ne voulais pas faire la variation verticale de la vague, il suffit de faire changer la valeur à chaque VBL pour l'activer Smiley
On part d'une valeur qui oscille entre -8 et 8 (x0). Pour la valeur de gauche, on ajoute 'pos', qui permet de faire l'effet d'ouverture/fermeture (varie entre 0 et 127), tandis que pour la valeur de droite (x1), on part de l'autre côté... Afin d'éviter d'injecter de mauvaises valeurs dans les registres, on limite la position à 0-255.

Et c'est tout ! Le reste du code, dans main, est tout simple :
Code
(c):
for(i = -8; i <= 127; i+=2){
// add+=8; add&= 511; // Move wave...
 
pos= i;
 
PA_WaitForVBL();
}
for(i = 127; i >= -8; i-=2){
// add+=8; add&= 511; // Move wave...
 
pos = i;
 
PA_WaitForVBL();
}
Voilà, on fait juste varier la valeur de 'pos' pour obtenir l'effet voulu... J'ai mis en commentaire la variation de 'add', comme je ne m'en sers pas, mais vous pouvez décommenter dans les sources et voir ce que cela fait Smiley

Bon, si à l'occasion on me le demande je ferais des exemples avec d'autres formes, mais pour l'instant j'ai un peu la flemme Wink Passons donc à la troisième partie de la démo, qui est la plus originale...


Fenêtres : les sprites !

Je vous laisse regarder et je vous explique...
http://www.dev-fr.org/Demos/Ronds/Ronds.png<a href="http://www.palib.info/blog/flvplayer.swf?file=http://www.dev-fr.org/Demos/Ronds/Ronds.flv" target="_blank">http://www.palib.info/blog/flvplayer.swf?file=http://www.dev-fr.org/Demos/Ronds/Ronds.flv</a> 
Télécharger la démo
Télécharger les sources

Notez qu'il est préférable d'utiliser la DS ou No$GBA pour cette rom, les autres ont un peu du mal :/ Donc, la question qui se pose, est comment fait-on pour avoir un tel effet... C'est simple : les fenêtres objets ! On peut en fait appliquer le système de fenêtre en utilisant des sprites au lieu des rectangles... Ainsi, on a un système plus flexible, mais qui utilise des slots de sprite et de la VRAM, par contre. Je ne vais pas faire un topo sur comment charger des sprites, etc... Ni sur comment les déplacer, ce n'est pas la question Azn

Cette démo combine plusieurs choses : des sprites noirs, pleins, dont on ne voit que le contour ici. Et des sprites légèrement plus petits, qui eux sont en mode 'Window' et exactement à la même position que les autres sprites. Voici le code initialisé pour les fenêtres :
Code
(c):
PA_EnableWinObj(0, WIN_BG3);
 
PA_SetOutWin(0, WIN_SFX|WIN_OBJ);

Donc, on voit qu'on fait afficher le fond 3 (celui avec DEV-FR dessus) à travers les fenêtres (mais pas dehors Langue), et juste les sprites en dehors (mais pas dedans...). Conséquence... On ne verra JAMAIS le centre des ronds noirs, toute cette partie est devenue invisible... et donc, par extension, quand 2 ronds se rapprochent, si une partie visible passe dans une partie invisible, elle disparait, ce qui donne un joli petit effet de 'fusion'. Cheesy

Je ne code pas tout le code, il est relativement clair. C'est un code tout bête de balles qui rebondissent sur les côtés, au détail près que j'affiche 2 sprites au lieu d'un seul (sprites 0 à 63 pour les sprites fenêtres, sprites 64 à 127 pour les sprites visibles).

Pour passer un sprite en mode fenêtre avec PAlib : PA_SetSpriteMode(0, i, 2);  // Mode WINDOW !   
Pour passer un sprite en mode fenêtre avec libnds : utiliser ATTR0_TYPE_WINDOWED Smiley

Voilà, je vous souhaite un bon week-end, et à bientôt !

Journalisée

Pitt Hors ligne
Administrateur
*****
Messages: 575


Voir le profil WWW
« Réponse #1 : 26 Mai 2007, 15:21:39 »

C'est moi ou les rendez-vous sont de plus en plus complets ? Azn
En tout cas vraiment intéressant, j'ai appris des trucs. Smiley
Journalisée
mikegba Hors ligne
VIP
****
Messages: 35


Voir le profil
« Réponse #2 : 26 Mai 2007, 17:52:04 »

 Smiley ouaip, et dans la démo des balles on peut même s'amuser à capturer une balle au stylet et à la ballader n'importe où !!    ( petit cachotier......  laugh )
Journalisée
Remi59 Hors ligne
Jr. Member
**
Messages: 56


Voir le profil
« Réponse #3 : 27 Mai 2007, 16:07:17 »

Effet vraiment sympatique! Smiley franchement j'adore le samedi Azn sa donne trop envi de programmer!
Merci!!!
Journalisée

Phoenix DataBase v1.0 : www.phoenixdb.fr
Logiciel de gestion de collection video!

Mon site de dev. regroupant mes projets :
http://bennyrebirth.palib.info
Tiwaz Hors ligne
Full Member
***
Messages: 125


Voir le profil
« Réponse #4 : 27 Mai 2007, 18:13:33 »

Merci pour ces Demos du Samedi. Très instructif.

Un grand bravo.
Journalisée

"Le jeu est la forme la plus élevée d'apprentissage"
Mony Hors ligne
Hero Member
*****
Messages: 551


Voir le profil WWW
zOMG !!!1

« Réponse #5 : 16 Avril 2008, 01:09:17 »

Pas mal les effets Cheesy
Journalisée

Membre du club des joyeux guitaristes pas aidés et codeurs avec les pieds de Dev-Fr et pas du club des pieds pas guitaristes aidés de joyeux codeurs Dev-fr...

Mollusk Hors ligne
Administrateur
*****
Messages: 3537


Voir le profil WWW
Ne vous posez pas de questions, codez !

« Réponse #6 : 16 Avril 2008, 07:33:36 »

Merci Azn
Journalisée

Schyzophrenic Hors ligne
Sr. Member
****
Messages: 425


Voir le profil WWW
Crappy Koder

« Réponse #7 : 21 Avril 2008, 00:02:53 »

Je viens compléter un peu cette petite démo avec ma petite touche personnelle Azn

Quand Mollusk dit qu'on peut déformer les fenêtres, on peut faire des petites transitions en forme de cercle... On pourrait aussi utiliser ce système pour faire une sorte de torche... Enfin voila l'idée Smiley

Donc voici la vidéo :


Et, bien entendu, le code qui va avec :

Code
(c):
// Includes
#include <PA9.h>       // Include for PA_Lib
#include "gfx/all_gfx.c"
#include "gfx/all_gfx.h"
 
///////////////////////////////////////////////////////////////
#define RMAX 200 // Rayon maximum du cercle
void HBL_function(void);
u16 getSQRT (u32 carre);
///////////////////////////////////////////////////////////////
u16 r = 300; // Rayon du cercle
u8 xFen1, xFen2; // Coordonnées x de la fenetre
u8 vcount; // numéro de la ligne courante
u8 centrex=0, centrey=0; // Coordonnées du centre du cercle
 
// Function: main()
int main(int argc, char ** argv)
{
PA_Init();    // Initializes PA_Lib
PA_InitVBL(); // Initializes a standard VBL
 
PA_InitText(1,0); // Initialisation du texte sur l'écran du haut pour suivre les variables
 
PA_EasyBgLoad(0, 0, bg0); // Chargement du bg sur l'écran du bas
 
// Initialisation des fenetres
PA_EnableWin0(0,//screen
WIN_BG0); //bg qui sera affiché
PA_SetWin0XY(0, 40,10, 150, 80); // On initialise la fenetre a une petite partie en mode "carrée"
PA_WaitForVBL();
PA_WaitFor(Stylus.Newpress); // Prêt pour la démo ?
// Initialisation HBL
irqSet(IRQ_HBLANK, HBL_function);
irqEnable(IRQ_HBLANK);
 
s8 offset = -1;
while (1)
{
r+=offset;
if (r==0) {offset=1;}
else if (r==RMAX) {offset=-1;}
PA_OutputText(1,0,0,"r : %d   ",r);
PA_OutputText(1,0,1,"xFen1 : %d   ",xFen1);
PA_OutputText(1,0,2,"xFen2 : %d   ",xFen2);
// On récupère le centre du cercle
centrex = Stylus.X;
centrey = Stylus.Y;
PA_WaitForVBL();
} // End Infinite loop
return 0;
} // End of main()
 
void HBL_function(void) {
vcount = PA_GetVcount(); // On récupère la ligne courante (y)
vcount++;
if(vcount >=192) vcount = 0; // Après 192 on affiche plus, donc on peut revenir au début
 
// y représente le numéro de la ligne sur laquelle on se trouve.
// Il faut convertir ce numéro de ligne en distance par rapport au centre du cercle
u8 y; // Coordonnée y
if(vcount<centrey) y=centrey-vcount;
else y=vcount-centrey;
 
// Une equation de base du cercle est : x2 + y2 = r2
// On cherche x, on en deduit que : x=SQRT(r*r-y*y)
 
u16 x = getSQRT(r*r-y*y);
  // On calcule les coordonées de la "bande de fenetre"
if (centrex-x<0) {xFen1=0;}
else {xFen1 = centrex-x;}
 
if (centrex+x>255) {xFen2=255;}
else {xFen2=centrex+x;}
 
PA_SetWin0XY(0, xFen1, vcount, // X1, Y1
xFen2, vcount+1);
 
}
 
// Calcul de la racine carrée par approximation successives
u16 getSQRT (u32 carre) {
// Calcul de la racine carree (algorithme de Heron d'Alexandrie)
u32 x=carre;
s32 precision;
do
{
precision=x;
x=(x+carre/x)>>1; // Note : on n'utilise pas INVERSE_TABLE[x] car x peut etre superieur a INVNB...
precision-=x;
}
while(precision>1);
return (u16) x;
}
 

Bien entendu, ce code est pas parfait, je ne suis ni Mollusk ni un bon codeur, mais il fonctionne Azn Si vous avez des remarques, n'hésitez pas !

Encore merci à Batman et Copper pour leur aide sur le sujet, sans eux j'y arrivais pas Wink

Journalisée

Montspy Hors ligne
Jr. Member
**
Messages: 64


Voir le profil
What You Want Is What You Will Get

« Réponse #8 : 21 Avril 2008, 10:55:41 »

Excellent ton effet Schyzo Cheesy
Sa rend super bien je trouve !
Journalisée

Ultra-FastReflexes  v 0.3 ... Vite !!! WYWIWYWG is better than WYSIWYG !
Schyzophrenic Hors ligne
Sr. Member
****
Messages: 425


Voir le profil WWW
Crappy Koder

« Réponse #9 : 24 Avril 2008, 14:45:17 »

Petite note : (c'est ptet moi qui suit mauvais faudra me le dire Azn), j'ai découvert un petit bug je crois dans la lib
Code
(c):
#define PA_EnableWin1(screen, bg_sprites) {DISPCNTL(screen) |= WINDOW1; WININ(screen) &= 255; WININ(screen) |= (bg_sprites << 8);}
 

est à remplacer par
Code
(c):
#define PA_EnableWin1(screen, bg_sprites) {DISPCNTL(screen) |= WINDOW1; WININ(screen) &= 255; WININ(screen) |= ((bg_sprites) << 8);}
 
En effet, lorsque l'on combine les BG et autres obj cela ne fonctionne pas sans les parenthèses autour de bg_sprites Azn
Journalisée

Mollusk Hors ligne
Administrateur
*****
Messages: 3537


Voir le profil WWW
Ne vous posez pas de questions, codez !

« Réponse #10 : 01 Mai 2008, 14:07:15 »

Super classe le cercle, j'avais eu la flemme de le faire Azn
Journalisée

morukutsu Hors ligne
Sr. Member
****
Messages: 499


Voir le profil
Noctambule

« Réponse #11 : 10 Juillet 2008, 17:02:19 »

Désolé pour l'up Langue
Je me demande, en utilisant la technique de l'HBL pour faire une transition avec un cercle, peut on faire la même chose plusieurs cercles en même temps ?
J'aurai bien voulu me servir des sprites mais je ne peux pas m'en servir en mode 3D Sad
Journalisée
Copper Hors ligne
Mega Member
***
Messages: 1296


Voir le profil
« Réponse #12 : 10 Juillet 2008, 20:04:08 »

On doit pouvoir faire 2 cercles "par lignes" vu qu'il y a 2 fenêtres...
Journalisée
Mollusk Hors ligne
Administrateur
*****
Messages: 3537


Voir le profil WWW
Ne vous posez pas de questions, codez !

« Réponse #13 : 10 Juillet 2008, 20:11:49 »

On doit pouvoir faire plusieurs cercles par colonne vu qu'il y a plusieurs lignes indépendantes
Journalisée

Pages: [1]   Haut de page
Imprimer

Aller à: