Bon, je vais commencer par recoller ce que j'ai déjà marqué à droite à gauche, j'éditerai pour faire plus joli plus tard
Génération de grilles : Pour la génération des grilles, la méthode actuelle est simple, efficace, mais très imparfaite :
Tu prends une grille côtée 'facile' dans un journal. Tu te fais des fonctions qui inversent des lignes, colonnes, ou des numéros (genre si tu remplaces tous les 2 par des 8 et les 8 par des 2, c'est pas la même grille mais ca revient au même, etc...). Enfin en gros, tu peux modifier la grille de façon simple pour donner l'illusion d'une nouvelle grille alors qu'en réalité c'est la même (IE, ce sera la même 'logique' pour la résoudre).
J'ai codé un solveur de sudoku, et j'ai fait des essais rapides. Les grilles faciles il les finit en 3 à 5 passes, les grilles moyennes en 6 à 8, etc... Donc à partir de là, je peux coter une grille... Pour quoi faire ? Et bien en fait j'ai une grille plein (avec les chiffres dans l'ordre, ca fait bizarre

), j'applique mon algo de permutations dessus (et personne ne sera capable de voir que ca vient d'une grille triée), puis je retire des chiffres au hasard (et de façon symétrique). A chaque retrait, je test avec le solveur. Si ca passe de facile à moyen, je sais que la grille d'avant était la grille la plus juste à mettre en tant que facile, j'ai donc trouvé ma grille

A noter que je prépare un long post (peut-être pour demain du coup) où j'explique ce que je fais (pour tous les aspects du jeu)
Le solveur de grille : De mémoire, au démarrage ca mets pour chaque grille que tous les chiffres sont possibles. A chaque chiffre ajouté (quand on remplit la grille au début...), ça scan la ligne, colonne, et le 'bloc' de ce chiffre pour enlever cette possibilité aux autres emplacements... Si on n'a plus qu'une possibilité, on sait que c'est ce chiffre (logique...).
Ca suffit pour remplir les grilles très faciles, pour les faciles ca peut échouer avant la fin

Du coup, si pendant une boucle ca ne trouve aucun chiffre à rajouter, je passe dans la seconde routine : même genre mais en plus lent. Ca regarde pour chaque possibilité de l'emplacement si dans la ligne/colonne/bloc la possibilité y est aussi. Si elle n'y est pas, on sait donc que seul cet emplacement peut avoir ce chiffre, il faut donc lui mettre... Et de là on retourne dans la première routine, bien plus rapide

Ceci permet de réussir les grilles faciles, moyennes, et difficiles que je lui ai fait manger (tirées du 20 minutes).
Pour aller plus loin, il faudra que je rajoute des vérifications encore plus raffinées, et/ou une gestion du plottage aléatoire, mais pour l'instant je n'en ai pas encore besoin et j'ai la flemme
A terme, quand le solveur marchera pour toutes les grilles, il sera disponible au démarrage pour avoir une application 'solveur de sudoku' sous le coude avec soi

.
Affichage du bas L'écran du bas set constitué de plusieurs couches. Comme fond, un 16bitBg tout simple, sur lequel j'affiche la grille tirée telle qu'elle de la skin... Quand on clique sur une case pour zoomerçapplique une simple division à la position du stylet pour savoir quelle case c'est. Si la case n'est pas une préremplie, on passe en mode écriture...
Pour se faire, je fais un zoom purement software, je recopie les pixels 8 par 8 autour du centre de la case, rien de particulier, et j'utilise ensuite PA_16bitDraw pour écrire dessus
En ce qui concerne les numéros, ils sont affichés sous la forme de 3DSprites/textures. Les sprites 0 à 81 sont pour les gros numéros, et 100 à 100+9*81 pour les petits numéros (9 par case, 81 cases...). Le numéro fait 32x32 à la base, est dézoomé à genre 16x16 pour faire la vue globale, et zoomé à 112x112 pour la vue rapprochée...
Afin d'économiser en mémoire, toutes les textures sont chargées au moment du chargement de la skin, et ensuite je ne fais qu'utiliser des PA_3DCreateSpriteFromTex...
Affichage du hautPas de grande différence... Le plus gros est sur un fond 16bit, chargé tel quel depuis la skin... Les numéros de la grille sont en sprites 16bit, tous les Gfx étant préchargés à la décompression de la skin, puis PA_Create16bitSpriteFromGfx relancé à chaque mise à jour de la grille... Numérotés de 1 à 90, le sprite 0 étant pris pour faire le petit curseur rouge qui indique la position dans la grille

Pour afficher le temps qui passe et être sur de rien rater, j'ai une fonction qui tourne automatiquement pendant le VBL :
void VBLFunc(void){
[...]
time++;
UpdateTimer();
}
void UpdateTimer(void){
PA_SetSpriteGfx(1, SPRITE_TIMER, timer_Gfx[(time/36000)%6]);
PA_SetSpriteGfx(1, SPRITE_TIMER+1, timer_Gfx[(time/3600)%10]);
PA_SetSpriteGfx(1, SPRITE_TIMER+2, timer_Gfx[(time/600)%6]);
PA_SetSpriteGfx(1, SPRITE_TIMER+3, timer_Gfx[(time/60)%10]);
}
Voilà, les Gfx sont créés au début, puis je ne fais que mettre à jour le numéro à utiliser, ce qui est rapide. Notez que ce n'est pas optimal, dans l'idéal il ne faut mettre à jour que si les chiffres ont changés, là je refais les divisions et modulos pour rien 59 frames sur 60...

Et pour que ça tourne tout seul, il suffit de mettre "PA_VBLFunctionInit(VBLFunc);" vers le début du code
Reconnaissance de caractèresJe me base intégralement sur le code de PAlib... (le truc Graffiti). Au démarrage, je charge des chaines persos à reconnaitre pour les chiffres :
void InitNumbers(void){
PA_UsePAGraffiti(0); // Do not use the provided Graffiti shapes...
PA_RecoAddShape('1', "999999999999999");
PA_RecoAddShape('1', "FFF;99999999999");
PA_RecoAddShape('1', "GFGHJ7899999988");
PA_RecoAddShape('1', "EEED97777777779");
PA_RecoAddShape('1', "DDDCDDDCCC=9999");
PA_RecoAddShape('2', "@?755436@AAAAAA");
PA_RecoAddShape('2', "E@=;;998632;AAA");
[...]
PA_RecoAddShape('9', "36;AFH;9::98632");
PA_RecoAddShape('9', "357;@DGGF999999");
PA_RecoAddShape('9', "0258<?CFH999998");
}
Alors, pourquoi avoir plusieurs chaines pour un même chiffre ? Et bien on peut avoir plusieurs façon d'écrire un même chiffre, donc il faut pour chacune de ces façon avoir le tracé correspondant... Plus on a de chaines, plus la probabilité de bien reconnaitre est élevée

Ca permet en plus de rajouter des chiffres non reconnus en se faisant donner une simple chaine de 15 caractères... Simple et efficace

La méthode utilisée par PAlib est différente de celle que l'on voit le plus souvent dans le jeux officiels. En général, le 'plus simple' est de laisser dessiner, puis de reconnaitre la forme dessinée. Dans le cas de PAlib, j'ai opté pour la lecture des entrées du stylet, puis l'extrapolation de 16 points, ce qui donne 15 segments de même longueurs avec un angle variable (d'où les 15 caratères dans la chaine, pour chaque angle...). A partir de là, on compare chaque dessin fait (= une chaine) à toutes les autres chaines en mémoire, et on garde celle qui est la plus proche... Ca marche plutôt bien, même si la faille principale est qu'on ne peut pas reconnaitre une chaine non rentrée... Si on dessine en partant de la fin, ça ne marchera pas.
Afin de savoir si on a dessiné un petit ou un grand chiffre, je me base sur les infos gardées en mémoire par le système de reconnaissance, en l'occurrence la taille :
if(PA_RecoInfo.maxY-PA_RecoInfo.minY > 48)...
Les skinsLe format des skins est visible dans le premier topic... C'est simple, on un fichier png, il est ajouté à la compilation, et la libpng se charge de le décompresser dans un buffer... Après l'avoir copié dans le buffer, je peux afficher la partie de l'écran du haut directement, pareil pour celui du bas.
Pour les textures, c'est un poil plus compliqué... Il faut déjà remplacer le magenta par du transparent, avec pare exemple une simple boucle for et
if (img[n] == PA_RGB(31, 0, 31)) img[n] = 0;
Une fois cela réglé, il faut découper correctement. J'ai donc des tableaux pour chaque texture, que l'on va remplir. Voici un exemple :
u16 *timerpng = (u16*)(png+32+256*(192+96))
for(i = 0; i < 10; i++){
startx = 16*i;
for(y = 0; y < 32; y++){
for(x = 0; x < 16; x++){
timer[i][x+(y<<4)] = timerpng[startx + x + (y<<8)];
}
}
timer_Gfx[i] = PA_CreateGfx(1, (void*)timer[i], OBJ_SIZE_16X32, 2);
}
Techniquement, on pourrait en fait utiliser un petit tableau au lieu d'un grand qui peut accueillir les 10 numéros (0 à 9), mais bon, j'ai préféré gardé pour si jamais je veux faire des animations ou modifier les numéros, etc...
Voilà, c'est tout simple du coup

Je charge mes Gfx/Tex, et après dans mon code je ne fais pas une seule fois PA_DeleteSprite, puisque je peux me permettre de recharger directement par-dessus sans soucis (je n'utilise que des CreateFromGfx...).
Voilà, j'ai fait un survol rapide, si vous voulez en savoir plus, avoir des détails, etc, n'hésitez pas
A noter que pour les boutons de l'écran du bas, j'ai fait une technique de Sioux : dans ma fonction VBL je regarde si on les touches. Si oui, je change l'image pour afficher la version 'appuyée', et je passe Pad.Held.Start (ou autre) à 1... Comme ça, pour valider on appuyer sur Start ou toucher le Sprite, et dans mon code je n'ai qu'à tester Pad.Newpress.Start... Pour effacer, j'ai calqué sur Pad.Held.B
Le spash screen Mollusk/SpriteAttack...Bon allez, je vais rajouter la petite description sur le splash screen...
L'effet de transition de base est tout simple, c'est l'effet PA_BgTrans en diagonale avec comme type TRANS_CROSS

Rien de particulier donc, n'oubliez pas que ce vous bouffre un fond quand même...
Pour la spirale du logo 'Mollusk', de l'écran du haut, j'ai hésité sur plusieurs façon de faire

. En fait, j'avais fait l'écran du bas en premier, donc je voulais absolument faire partir le logo, une fois affiché, par scrolling horizontal... Et on doit avoir derrière un fond 8bit qui affiche le titre du jeu, donc ca réserve déjà le fond 8bit et ainsi une partie de la mémoire

. Donc, si je résume, je voulais avoir un fond tout simple (EasyBg pour les PAistes) avec le logo "Mollusk Games" pour le faire scroller...
En fait, je me suis dit que ce serait du gachi de ne pas me servir du fond 8bit de dessous. Donc, au lancement de la rom, je charge sur le fond 8bit l'image du logo SANS la spirale (juste le carré bleu), et je le mets devant le fond avec le logo plein... Puis, une fois le premier effet de transition passé, il est temps de faire dessiner la spirale. Je suis un flemmard, je ne supporte donc pas de devoir rentrer les points à changer 'à la main', il me fallait donc une méthode automatique

.
Et bien c'est simple ! Je me suis inspiré d'une routine que j'ai faite pour une app de dessin, afin de remplir une zone d'une même couleur... Sauf que là, j'allais changer les pixels non pas de la même couleur que celle du départ, mais dont la couleur est différente entre le fond 8bit (Mollusk sans spirale) et le fond normal (Mollusk avec spirale). J'ai donc un tableau qui répertorie les pixels à changer, vide au démarrage. On part du centre de l'écran (qui est le centre de la spirale en fait), et on ajoute ce pixel au tableau... Pour chaque pixel ajouté, on le passe à la bonne couleur (PA_EasyBgGetPixel, pour lire la couleur du fond plein

), et on regarde les 4 pixels autour (haut/bas/gauche/droite). Pour chacun de ces pixels, s'il n'a pas la même couleur sur le fond 8bit et sur le fond normal, on l'ajoute à la liste, etc... Et on fout ca en boucle ! Et là, oh magie, la spirale commence au centre, et le changement des pixels se fait de proche en proche

Voilà qui permet d'avoir un code d'à peine quelques lignes pour faire apparaitre la spirale

A noter que cela marcherait donc pour d'autres formes, du moment qu'il y a une forme continue... (genre une courbe, une écriture avec lettres attachées, etc...)
Ensuite (ralala), une fois que le fond 8bit correspond enfin au fond normal, on fait quoi ? Et bien il parait évident que l'un des 2 est devenu superflu... On peut donc repasser le fond 8bit derrière l'autre fond, et afficher dessus (en furtif/caché pour l'instant, donc), l'écran de titre du jeu ! C'est très rapide à charger (à partir d'un gif par exemple), l'utilisateur ne voit rien

Ensuite, pour faire scroller hors de l'écran j'ai choisi de faire lire les tiles et de les recopier 1 cran plus loin, plutôt que d'utiliser un vrai scroll, ca me permet de rester avec un fond de 256 pixels de large et c'était plus pratique pour l'écran du bas...
Place à l'écran du bas, c'est plus simple, ne vous en faites pas

L'astuce pour ce dernier réside dans le fait que l'image que l'on voit une fois le premier effet de transition terminé n'est pas une seule image, mais un fond tout simple avec le logo SpriteAttack qui est en fait un sprite... Et un sprite, on eut en faire plein de choses, comme le zoomer et le rendre plus ou moins transparent

En combinant les 2, on a le sprite qui devient gros et disparait, tout simplement.
Pour faire virer cet écran, c'est ensuite le même principe qu'en haut. Le fond étant en tiles, je peux avoir derrière un fond 8bit sur lequel je charge l'écran titre/menu de mon jeu pendant qu'il est caché... Ensuite, pour faire scroller, j'ai choisi, comme dit avant, d'utiliser les tiles... Je fais bouger les tiles du bas vers la gauche, celle du haut vers la droite, et le tour est joué ! Ca découvre le fond du dessous, et on peut alors partir dans le code du jeu pour continuer

Bon, ce code je l'avais fait pour Weeds, j'ai voulu le réutiliser pour Skinz Sudoku mais j'ai eu un petit soucis : mes fonds étaient en 16bit, et les boutons du menu en 3DSprites... Hors, je n'ai pas la place en mémoire pour le 16bit pendant mon flash (et il faut charger les images pendant que le splash tourne...), donc j'ai du migrer mes fonds en 8bit... De plus, comme j'utilise la transparence et que ça marchait bien pour l'écran du bas, j'ai eu la flemme et je n'ai pas voulu changer ce bout de code, donc je ne pouvais pas avoir les 3DSprites au moment de l'affichage du menu :s Donc je les ai viré, ca fait le splash sans les boutons, et apres les boutons scrollent vers le centre comme si c'était fait exprès, alors que c'était pour m'arranger

(en fait je pourrais refaire le code du bas pour n'utiliser que le GPU 3D, ca serait mieux mais ça marche et j'ai la flemme

)
Voilà, merci de votre attention, je rajoute tout ça dans mon post précédent
