"Compilation" niveau
Posté le 29/01/2016 20:35
Bonjour,
Ayant envie de passer à la vitesse supérieure niveau prog, je suis actuellement en train de travailler sur un jeu de plateforme fonctionnant par tableaux successifs (d'ailleurs si quelqu'un sait comment gérer du scrolling en basic, je suis preneur x), et pour me faciliter la tâcher, j'ai créé un éditeur dans lequel je peux modifier un des tableaux assez facilement avec le test et tout le bazar.
Le plan étant d'ensuite proposer une sorte de "compilation" rudimentaire où la calculatrice me condenserait toute la matrice de travail (de 21*7) dans une seule ligne que j'ajouterais dans un programme stockant les niveaux que le programme chargerait ensuite quand le joueur se déplace de tableau en tableau. Oui je suis flemmard et j'ai moyennement envie de recopier tout ça à la main vu que je prévois une centaine de tableaux xD (en espérant que les 60ko de la puce tiennent le coup)
Du coup là où survient le problème, c'est que j'aimerais que le compilateur "lise" la matrice case par case (ça c'est facile) mais qu'il me transfère le résultat dans le presse-papier afin que je puisse le coller ensuite avec le reste des niveaux, ce qui revient à renvoyer ce genre de texte : [[1,2,3,..,21][[1,2,3,..,21]...]
Est-ce que c'est possible, où y'aurait moyen de contourner le problème ?
Merci par avance !
(je mets le prog d'édition et de test en pièce-jointe, si vous avez envie de vous crever les yeux c'est par là
: les progs marchent avec les matrices C et D dimensionnées à 7*21)
Fichier joint
Citer : Posté le 01/02/2016 22:48 | #
Ca marche pas vu que tes 3 vecteurs propres comportent chacun 3 coordonnée
Oui oui oui, ça c'est indéniable, la matrice n'est pas chouette en dur, c'est bien ce que je dis aussi.
En effet ton calcul est juste Ne0tux De ce point de vu, les matrices sont moins lourdes que les Str, je ne m'y attendais pas.
Et d'ailleurs on peut rajouter des chiffres dans la puissance de 10, c'est ça ton 20 chiffre bonus ?
Bien vu Dark Storm. Comme vous dites, chaque compression va s'adapter au cas par cas.
Citer : Posté le 01/02/2016 22:50 | #
J'avoue qu'on a bien dérivé, mais de manière constructive pour une fois.
Citer : Posté le 01/02/2016 22:54 | #
J'ai repensé au fait de monter en base, je pensais que c'est ce que je proposais initialement sur ce topic mais c'est encore plus puissant ! Car en base 100 par exemple, avec deux caractères on peut stocker des nombres entre 0 et 9999, donc 4 chiffres avec seulement deux caractères !
Les bases au delà de 100 ne me paraissent pas intéressantes car il faut attendre la base 317 pour pouvoir avoir 5 digits...
Au fait Epicmario, je suis vraiment désolé d'avoir lancé ça ici.
Et d'ailleurs on peut rajouter des chiffres dans la puissance de 10, c'est ça ton 20 chiffre bonus ?
Les 20 chiffres bonus viennent du fait que 19 cases fois 28 chiffres = 532 donc tu as 20 chiffres de plus par rapport aux 2 Str qui ne peuvent n'en comporter que 512. Par contre c'est quoi cette histoire de puissance ?
Quelqu'un ne voudrait pas vérifier aussi si c'est 14 ou 15 chiffres dans une variable avant troncature svp (j'aurais dû la prendre ) ?
Nickel Dark' ton système pour la redondance !
La Planète Casio est accueillante : n'hésite pas à t'inscrire pour laisser un message ou partager tes créations !
Citer : Posté le 01/02/2016 23:01 | #
15 chiffres
Citer : Posté le 01/02/2016 23:29 | #
Ah merci beaucoup Dark' !
Du coup c'est encore mieux ! A partir de 108 chiffres il devient plus intéressant d'utiliser une matrice plutôt qu'une Str (je viens de le résoudre avec un peu de LP et GLPK ), toujours sous réserve de ne pas le coder en dur dans le programme. Voilà c'était juste pour l'exercice, mais c'est bon à savoir pour ceux qui veulent manipuler beaucoup de données.
Sinon la base 100 sera la meilleure solution pour ce qui est du stockage en dur je pense. Elle apporte exactement les mêmes gains mémoire que la méthode que je préconisais au tout début dans ce topic MAIS la base est plus "petite "que le "dictionnaire" de 256 caractères, on gagne 156 octets.
La Planète Casio est accueillante : n'hésite pas à t'inscrire pour laisser un message ou partager tes créations !
Citer : Posté le 01/02/2016 23:43 | #
@Ninestar : les ID sont tout simplement les valeurs à stocker
Bah vous savez quoi les gars me s'en va créee un défi intéressant
Pourras-tu survivre plus de 20 secondes dans ce fameux tunnel appelé Graviton
Rebondis entre les murs en évitant les piques dans SpikeBird
Pourras-tu éviter de te faire écraser dans FallBlocs (élu Jeu Du Mois)
La version 2048 tactile amélioré au plus haut point : 2048 Delux !
Pars à la recherche des morceaux d'étoile dans Lumyce (élu Jeu Du Mois)
Citer : Posté le 01/02/2016 23:47 | #
Exactement ! L'astuce vient de remiweb
Ah c'est moi qui t'ai appris ça ? Cool
Il me semble que Remiweb avec Calcraft travaille directement sur les Str, donne nous ton avis si tu passes par là
Bien entendu, c'est juste pour le stockage des données, ces méthodes sont bien trop lentes pour le jeu en temps réèl.
Après, soit on utilise les strings (comme dans Calcraft), soit les matrices, au choix et selon les besoins du jeu.
Je n'utilise plus directement les Str pour la version 2.0 de Calcraft car c'était trop lent
Et j'ai justement à la fois des matrices et des chaines, et ce pour deux raisons :
- Ça me permet de donner une information en plus sur chaque bloc, en plus que son apparence (par exemple de quel bloc il s'agit quand c'est un bloc encore non découvert qui est noir dans la chaine)
- La matrice est le moyen le plus rapide que j'ai trouvé pour tester la hitbox
Pour ce qui est de l'affichage :
J'utilise effectivement StrRotate au moment d'afficher une ligne, même chose : c'est ce qui s'est avéré être le plus rapide.
Pour les lignes où le personnage se trouve je fais :
StrLeft permet de prendre les blocs à gauche du joueur, θ le sprite du joueur et StrRight les blocs à droite du joueur.
Ça évite d'avoir un rajouter un Locate pour le joueur, ce qui est plus rapide...
Pour le scrolling vertical c'est bien plus compliqué alors je ne vais pas entrer dans les détails...
En gros j’intervertis les chaînes mais dans un ordre atroce à l'aide de modulos
Le but étant de ne pas toutes les intervertir à chaque déplacement. J'ai du faire un schéma sur une feuille pour me repérer
Pour ce qui est de la mémoire :
J'utilise en gros ce que Ne0tux a dit page 2.
J'ai une matrice dont chaque case correspond à 10 valeurs différentes pour gagner de la place.
Mais il m'a donné une idée pour la manière dont je récupère ou écrit ces valeurs, il faudra que je regarde ça.
Mais effectivement avoir à la fois des matrices et des chaines ce n'est pas forcément l'idéal. C'était juste que ça s'y prêtait plutôt bien pour mon jeu en particulier.
générer des niveaux qui sont compilés puis ajoutés au presse-papier pour enfin être collés directement dans le bon sous-programme.
Je ne comprend pas trop le principe. Une fois que l'utilisateur a créer son niveau il est compressé et mit dans une fn et c'est à l’utilisateur d'aller coller ça dans un sous programme ?
En tout cas tout ce qui est dit ici m'intéresse énormément. J'ai lu entre les lignes mais je regarderai ça précisément ce week-end
Citer : Posté le 02/02/2016 00:11 | #
Je ne comprend pas trop le principe. Ene fois que l'utilisateur a créer son niveau il est compressé et mit dans une fn et c'est à l’utilisateur d'aller coller ça dans un sous programme ?
Oui exactement ! Pour rendre les choses encore plus simple dans Arkenstone le programme bug volontairement à la bonne ligne, comme ça l'utilisateur se retrouve directement au bon endroit dans le code pour coller le niveau qu'il vient de créer.
J'utilise en gros ce que Ne0tux a dit page 2.
J'ai une matrice dont chaque case correspond à 10 valeurs différentes pour gagner de la place.
Mais il m'a donné une idée pour la manière dont je récupère ou écrit ces valeurs, il faudra que je regarde ça.
Je me doutais que d'autres utilisaient ça. Tu nous tiens au courant de tes avancées ?
La Planète Casio est accueillante : n'hésite pas à t'inscrire pour laisser un message ou partager tes créations !
Citer : Posté le 02/02/2016 17:55 | #
Toutes ces techniques de compression sont vraiment superbes c'est impressionnant les possibilités qu'il y a
Mais pour que ce soit utilisable, il faut tout décompresser, ce qui prend un temps monstrueux.
Mais expert en Basic Casio que vous êtes avez surement une technique pour limiter au maximum ce temps. Car dans un jeu si les temps de chargement sont trop long, le joueur va vite se lasser
Personnellement, je n'utilise aucune "technique de compression" pour mes niveaux, je les stock comme ceci :
1 2 3 4
5 6 7 8
9 0 1 2
3 4 5 6
"01020304"→Str 1 //Pourquoi 01 et pas 1, c'est pour gérer les chiffres entre 10 et 99 inclus ;)
"05060708"→Str 2
"09000102"→Str 3
"03040506"→Str 4
ClrMat AÙ
{4,4}ãDim Mat AÙ
For 1ãB To 4Ù
For 1ãA To 4Ù
Ax2ãDÙ
D=1×2ãDÙ
B=1×Exp(StrRight(StrLeft(Str 1,D),2))ãCÙ
B=2×Exp(StrRight(StrLeft(Str 2,D),2))ãCÙ
B=3×Exp(StrRight(StrLeft(Str 3,D),2))ãCÙ
B=4×Exp(StrRight(StrLeft(Str 4,D),2))ãCÙ
CãMat A[B,A]Ù
NextÙ
Next
Y a-t-il plus rapide ?
Un beat them all pour les CPC 19
Un jeu de Tank multijoueur en version graphique
Un jeu de boxe rigolo
Le moteur de combat épique d'un RPG
soccer physics : Un jeu de foot totalement wtf !
Survie 1 & 2 te laisseras-tu attraper par la méchante IA ?
Séquestrez les tous avec Catch'em all !
Joué à la calcultarice et pécher ? Facile !
Battle un système de combat dément !!
Débombe pas tout à fait un démineur
Mon mario pour le concours des 10 ans de PC
Casio jump un doodle jump pas comme les autres !
Rush four your life : tu cours ou tu meurs
Cookie clicker ! More cookies MOOORE !
Move et esquive : bouge pour esquiver les ennemis !
Guitar Hero !! Let's rock !
INVASION : Au secours on se fait envahir !
Un devine nombre entièrement customisable (mon 1er jeu)
Un outil pour dessiner des sprites en super drawstat et qui vous le compile pour vous donner un code utilisable dans vos programmes
Un super programme de dessin bourré de trucs funcs
Sortir une version finale de Tankasio
Bien m'améliorer en C parce que pour l'instant c'est pas jojo
Une ou plusieurs idées qui mûrissent petit à petit
Citer : Posté le 02/02/2016 20:59 | # | Fichier joint
GNA GNA GNIA ! Je m'absente un jour sans PC, et le topic part en live xD
Bref, j'ai beaucoup, beaucoup BEAUCOUP avancé sur la compression du niveau (j'ai sacrifié ma soirée dessus et 2 heures de français pour ça, la dissertation sur des œuvres du 20ème c'est chiant) . A présent, j'ai créé un algorithme capable de reproduire la matrice de manière procédurale, je vais vous expliquer le concept car c'est du moi tout craché ce système farfelu.
Pour commencer, ce système est d'une simplicité dingue mais aussi d'une grande efficacité : les temps de chargement au début d'un niveau sont entre 6 et 8 secondes, et ce pour charger une matrice de 200*7.
Le concept, c'est de compter combien de blocs qui ont la même entité se succèdent, puis quand on tombe sur un bloc différent, on va passer sur le nombre de répétitions de ce nouveau bloc. En gros, si sur la ligne 4 j'ai 5 blocs d'air puis deux blocs ?, il va enregistrer dans une fonction :{0,4,3,2}->List 4
Mais pour me faciliter la tâche, j'ai créé deux listes distinctes gérant pour une l'entité du bloc et l'autre son nombre de répétitions, comme cela pour reprendre mon exemple :{0,2,-9}->List 1 {4,2}->List 2
Quand il a répété le nombre de blocs indiqué dans la liste 2, il passe à la ligne suivante et il recommence. Lorsqu'il rencontre l'entité "-9", il change de ligne sur la matrice et avance donc de 2 listes en avant.
Et là, vous allez vous rendre compte du génie total du truc. En fait, je me suis rendu compte qu'il y avait 80%/85% de vide dans un niveau, donc l'idée, ça serait de compter le nombre de blocs d'air qui se succèdent avec le reste (comme d'hab), mais lorsqu'il va tout décompresser, si il doit répéter un nombre X de fois un bloc d'air, au lieu de tous les placer il va simplement avancer le "curseur d'écriture de la matrice" de X et passer au bloc suivant qu'il va rencontrer. Ben oui, la matrice est remplie de 0 à la base, pourquoi s'embêter à placer des 0 qui existent déjà ? :3 Donc, j'ai une décompression 5 fois plus rapide avec cette petite ligne de code.
Du coup, ma fameuse matrice de 200*7 ne prend à présent pas plus de 1000 octets, impliquant en retour un temps de chargement de 6 à 8 secondes comme je l'ai déjà dit. Matt, t'as pas le droit de me voler mon système, même si c'est très tentant il est beaucoup trop puissant pour toi et j'hésite à le breveter ! (#TheFineBros)
A présent, je vais voir pour déduire efficacement les strings de la matrice, (réduisant donc la taille d'un niveau à 1000 octets à peine pour 200 blocs max) donc j'aimerais vous demander si y'avait moyen de remplacer un caractère random par un autre en plein milieu d'un string. En effet, j'aimerais qu'il génère la "VRAM" (au point où on en est c'est littéralement ça) en même temps qu'il décompresse la matrice, si c'est bien géré, ça peut être très rapide également !
J'ai testé la génération des strings au fur et à mesure qu'on avance dans le niveau, mais ça divise les FPS par deux lorsqu'on avance vers la droite, même en admettant que le jeu continue à tout générer lorsque le joueur ne touche à aucune touche, ça reste moyen moyen...
Pour ceux qui veulent le code du jeu : pièce-jointe, pas d'éditeur parce que j'ai la flemme ! Au passage, j'avais deux heures de perm, alors pour tuer le temps j'ai fait selon mes vagues souvenirs le niveau 2, assez court mais bon il est là
Citer : Posté le 02/02/2016 22:30 | #
C'est très ingénieux ! Je sais plus qui avait dit quelque chose de semblable mais tu y es arrivé sans lire ce commentaire
J'ai très envie de te piquer ton idée mais ça ne collerait pas avec mon programme, je vais juste optimiser les répétitions
Oui il y a moyen regarde tes tous premiers commentaires
En tout cas bien joué !
Ajouté le 02/02/2016 à 22:38 :
Ah bah non je l'ai pas dit
Alors c'est
Pour changer le bloc ou se trouve le perso ;
StrLeft(Str 1,X-1) // Tu prends la partie gauche de ta Str jusqu'à la position du personnage -1. Le -1 c'est pour ne pas inclure le bloc ou se trouve le perso
+ "O" // Tu rajoutes donc le caractère que tu veux
+ "StrRight(Str 1,StrLen(Str 1)-X) // et tu finis en rajoutant la partie droite de la Str tout en excluant le bloc ou se trouve le perso
C'est aussi simple que ça (merci encore à Remiweb qui m'avait expliqué ça il y loooongtemps)
Un beat them all pour les CPC 19
Un jeu de Tank multijoueur en version graphique
Un jeu de boxe rigolo
Le moteur de combat épique d'un RPG
soccer physics : Un jeu de foot totalement wtf !
Survie 1 & 2 te laisseras-tu attraper par la méchante IA ?
Séquestrez les tous avec Catch'em all !
Joué à la calcultarice et pécher ? Facile !
Battle un système de combat dément !!
Débombe pas tout à fait un démineur
Mon mario pour le concours des 10 ans de PC
Casio jump un doodle jump pas comme les autres !
Rush four your life : tu cours ou tu meurs
Cookie clicker ! More cookies MOOORE !
Move et esquive : bouge pour esquiver les ennemis !
Guitar Hero !! Let's rock !
INVASION : Au secours on se fait envahir !
Un devine nombre entièrement customisable (mon 1er jeu)
Un outil pour dessiner des sprites en super drawstat et qui vous le compile pour vous donner un code utilisable dans vos programmes
Un super programme de dessin bourré de trucs funcs
Sortir une version finale de Tankasio
Bien m'améliorer en C parce que pour l'instant c'est pas jojo
Une ou plusieurs idées qui mûrissent petit à petit
Citer : Posté le 02/02/2016 23:30 | #
OHHHHHHH MG !!! (lel)
Merci mon gros, c'est tout bête mais ça me sauve la vie ! Avec ça, je vais enfin pouvoir gérer les destructions de bloc, toute forme de modification sur la map et en + (et surtout ) la compilation totale et absolue du niveau dès le début, ça sera basé sur le même système que pour générer la matrice, il ne me suffira que d'instancier des chaînes de caractères pleines de vides et les remplir de caractères ! (le turfu dans cette phrase...)
En regardant tout ce que vous vous êtes racontés pendant ma courte absence, en effet Ne0tux avait déjà fait allusion à ma technique dans le plus grand des calmes, ça me met le seum quand on sait qu'il a écrit ça en même temps que lorsque j'en ai eu l'idée
Enfin bref, merci beaucoup je pense que là j'ai à peu près tout pour aller loin dans mon projet, je ne peux que te souhaiter bonne courage pour le tien mon ami !
Je publierais toujours les avancées ici néanmoins, y'a des gens qui débattent sans pression sur mon topic, ben moi je vois pas pourquoi je déplacerais mon projet dans la bonne section nan mais oh ! (au passage, un petit coucou + big up à l'admin qui le fera en me lisant x')
Citer : Posté le 02/02/2016 23:46 | #
@Matt : Avec plaisir
Une idée rapide pour gagner de la place et peut-être de la vitesse avec ton système :
Tu choisis un caractère pour chaque nombre de 1 à 99.
Par exemple :
2 pour 2
...
9 pour 9
A pour 10
B pour 11
...
Z pour 34
θ pour 35
π pour 36
Etc ...
Pour décoder tu as juste à remplacer les lignes en :
Par :
Déjà "StrMid(Str 1,D,1)" remplace ton "StrRight(StrLeft(Str 1,D),2)". Il permet de récupérer 1 caractères dans la Str 1 à la position D.
Ensuite pour "StrSrc" :
Il sert à obtenir la position d'un caractère dans une chaîne, et c'est là que notre codage juste au dessus devient sympa !
Par exemple pour 35 on avait choisit le caractère "θ".
Donc au moment du décodage si on tombe sur "θ" StrSrc va chercher où il se trouve dans la chaine "123456789ABCDEF (...) XYZθπ".
Et d'après l'ordre qu'on a choisit il se trouve à la 35e position, on récupère donc immédiatement la valeur à laquelle il correspond.
Un dernière astuce pour éviter d'avoir 4 chaines avec des conditions pour savoir laquelle utiliser :
Tu devrais tout mettre à la suite dans une seule et simplement rajouter une petite étape pour extraire les morceaux que tu veux à chaque fois que B augmente.
Pour une matrice 4x4 ça donne quelque-chose comme ça :
Quand B vaut 1, 4B-3 vaut 1, donc StrMid va récupérer 4 caractères à partir du 1er de la chaine. Donc les 4 premiers.
Quand B vaut 2, 4B-3 vaut 5, donc StrMid va récupérer 4 caractères à partir du 5e. Donc les 4 suivants.
Etc...
Je pourrai expliquer ça plus en détail si tu veux, mais là il se fait tard et j'ai DS demain
Ajouté le 03/02/2016 à 07:06 :
Quelqu'un ne voudrait pas vérifier aussi si c'est 14 ou 15 chiffres dans une variable avant troncature svp (j'aurais dû la prendre ) ?
15 chiffres
J'ai toujours pensé que c'était 10...
En fait c'est l'affichage qui passe en puissance de 10, mais la variable peut effectivement contenir 15 chiffres.
Je vais adapter mon système du coup