Le site probablement pas pour toi, qui vient de passer à Vanilla 2 à l'arrache, et qui va mettre un certain temps avant d'être à nouveau opérationnel (ou du moins Über avec un Ü).
Pingu's Code bLog
  • pingupingu novembre 2006

    Bon voilà, je vais commencer à écrire mon petit journal de dév, en essayant de maintenir un rythme régulier.

    Donc j'ai commencé la programmation du projet X il y a peu, après une phase de préprod et de début de prod graphique ces derniers mois. Je dois pour cela reprendre une maquette pré-existante et développer de nouveaux modules.

    Le projet est développé sous Blitz3D, et va durer jusqu'à fin mars 2007. Le "logiciel" sera distribué sous forme de CD-ROM et rentre dans la catégorie du serious gaming (utilisation des techniques du JV pour d'autres secteurs : industriel, santé, formation, etc...)

    Voilà, j'espère être resté assez vague mais pas trop pour pouvoir quand même situer le genre de projet.

    Les posts qui suivront seront un poil plus techniques, mais bon ça me fera une trace écrite des problèmes rencontrés et de l'avancée du projet.

    Voilou.

  • pingupingu novembre 2006

    Yo.

    Alors, le premier truc de ouf malade que j'ai à dire ici, c'est que Blitz3D, c'est pas Flash... Et que c'est quand on développe plus sous flash, qu'on se rend compte comment qu'il était bien en fait ce soft (un peu comme avec une ex).

    Parceque là, toutes ces belles animations et effets de scale et de mouvement qu'on fait faire par le graphiste en 2 temps 3 mouvements en flash, hé bin quand on passe par un outil "only code", hé bin faut tout se taper à la main. C'est super laborieux, et pour le coup ça fait réviser un peu les maths...

    Alors, comment qu'on interpole une valeur de départ à une valeur d'arrivée, grand père ? Le tout suivant une progression plus ou moins longue ?

    En exclusivité, voici la réponse (retrouvée par bibi en se creusant la tête...) :

    [b]valeurCourante = valeurDépart + (valeurFinale - valeurDépart)*(tempsCourant-tempsDépart)/(tempsFinal-tempsDépart)[/b]

    Houuuu, c'est beauuuuuu ! Ca doit certainement avoir un ptit nom cette bête là, mais je vous avouerais que j'en ais strictement rien à secouer. Mais en gros, en flash, ça équivaut au calcul de chaque position intermédiare dans un tween (=interpolation in english).

    Bon, donc passé le cap de la formule à retrouver, il faut ensuite organiser le système pour enchaîner les animations, à la manière de gotoAndPlay() dans flash. Bing, faut tout refaire à la main, et c'est forcément à un moment ou un autre le bordel. Heureusement, j'ai fini par organiser mon code très rapidement, en découpant par fonction les différentes interpolations possibles (en l'occurence, le scale, la position, l'alpha, et une pour la frame d'animation)

    Ca s'est plutôt bien goupillé je dois dire, d'après mon expérience passée, j'ai privilégié la clarté au détriment de l'ultra-performance algorithmique, et ça marche bien.

    Le problème vient aussi du fait que flash est totalement objet, et que mine de rien c'est quand même bien pratique. Alors quand tu retournes sur Blitz3D, où tu peux faire un 'semblant' d'objet, bin les réflexes pratiques sont tous faussés. Et même avec un langage objet, le temps de déclarer tous ses petites classes, c'est assez décourageant avant de voir venir se pointer le nez du sprite que tu veux afficher.

    Bref, un truc qui m'a super bien aidé, et qui je pense sera généralisé pour les prochains projets : pour des raisons de retour client, on a dû réaliser une mini démo animée des graphs issus de la préprod, donc réalisée vite fait en flash par nos graphistes. Et donc, pour faire mon programme, je me suis basé là-dessus. Et là, c'est le bonheur... Plutôt qu'un pauvre fichier texte avec toutes les étapes d'animation à recréer en code, j'avais directement le résultat à obtenir sous les yeux, avec les bonnes valeurs et tout directement dans le .fla. Génial, d'autant plus que le graphiste peut bien contrôler son animation avant de me la faire intégrer.

    C'est un système utile pour les animations un peu complexes, là on avait par exemple un sprite ayant deux animations : une boucle de marche, et une boucle d'attente (pour économiser du poids mémoire). Donc en code est recréé la trajectoire du sprite (2-3 points en ligne droite, pour les courbes c'est moins rigolo), son apparition en alpha, et son scale pour simuler l'effet de profondeur (hé oui, les joies de la 2D).

    Bon, deuxième point que je voulais soulever : le debug. Sachant que débugger/tester son programme occuppe 80% du temps de développement, ça devient très rapidement un point critique dans l'organisation du travail. Pour mes précédents programmes, en flash notamment, fol ingénu que j'étais, je n'avais pas mis en place de système de hack pour pouvoir tester le jeu, à part vraiment des gros trucs pour le level design. Mais pour mes tests, c'était vraiment à l'improviste. Alors, quand t'es au début de prod, que le jeu se lance super rapidement, ok c'est cool, tu te sens bien, frais, heureux de vivre... mais au bout de quelques temps, quand t'as intégré les jolis graphismes et que ton jeu mets 4m50 (chrono en main, world record) à se lancer, et qu'en moyenne tu le compiles toutes les 3 lignes de code (débug avancé dans la prod)... ça a valu la phrase mythique de Yabai "ah ouais, en fait Youtube c'est fait pour attendre pendant les temps de compilation !".

    Donc, il faut éviter ça. Oooooh oui. Et comment ? Hé bien, quand on peut, en découpant le programme en plusieurs petits bouts (qu'il faudra bien assembler un jour...). Ou alors, en faisant ce que j'ai fait là : hacker son propre code, et ne charger que ce dont on a vraiment besoin de tester. Ca semble évident, mais trop souvent par paresse ou par le syndrôme du "boah ça va marcher tout de suite", je me suis retrouvé à lancer le programme du début à la fin, passer pour la 10000ième fois par le menu principal, cliquer sur les boutons, etc,etc... AU SECOURS ! Non, il faut hacker.

    Et hop, un petit code aux endroits critiques du programme, et hop, au lieu de charger toutes les ressources (190 sprites * 5 pour ce cas là), hé bin tu ne charges qu'une seule série, et tu testes sur celui-là. Et quand t'es sûr que ça marche sur 1, tu testes avec tous. Et si ça marche, tu repasses à 1 pour la suite du développement. Ô bonheur, ô joie. C'est fastidieux, car à peine tu as commencé à programmer ton bout de jeu (qui fait juste apparaître un bout de cube qqpart à l'écran), que déjà tu dois penser à mettre en place ce genre d'astuce, qui viennent te perturber le moment où tu es sensé prendre le plus de plaisir à penser, à concevoir ton programme. Mais il faut.

    Allez, pour conclure dans la joie et la bonne humeur ce premier post-blog, un ptit bout de code tout frais tout beau, la fonction qui me permet de gérer l'interpolation de position de mes petits sprites. Vous noterez mon petit système de hack en début de fonction.

    [code]Function checkPos()

    If(Not debug) Then
    max = 4
    Else
    max = 0
    EndIf

    For i=0 To max

    If(aTab(i)\i_frame = 0) Then
    ;nothing
    posXD = -1000
    posYD = -1000
    posXP = -1000
    posYP = -1000
    frameD = 50
    frameP = 1

    ElseIf(aTab(i)\i_frame < 50) Then

    posXD = 492.4
    posYD = 252
    posXP = 507
    posYP = 252.2
    frameD = 50
    frameP = 1

    ElseIf(aTab(i)\i_frame < 450) Then

    posXD = 373.9
    posYD = 250.4
    posXP = 492.4
    posYP = 252
    frameD = 450
    frameP = 50

    ElseIf(aTab(i)\i_frame < 550) Then

    posXD = 373.9
    posYD = 250.4
    posXP = 373.9
    posYP = 250.4
    frameD = 550
    frameP = 450

    ElseIf(aTab(i)\i_frame < 950) Then

    posXD = 492.4
    posYD = 252
    posXP = 373.9
    posYP = 250.4
    frameD = 950
    frameP = 550

    ElseIf(aTab(i)\i_frame <= 1000) Then<br />
    posXD = 507
    posYD = 252.2
    posXP = 492.4
    posYP = 252
    frameD = 1000
    frameP = 950

    EndIf

    posXC1 = posXP + (posXD-posXP)*(aTab(i)\i_frame-frameP)/(frameD-frameP)
    posYC1 = posYP + (posYD-posYP)*(aTab(i)\i_frame-frameP)/(frameD-frameP)

    Select (i)
    Case 0
    DrawImage3D(AnimalTab1(aTab(i)\i_anim),posXC1,posYC1)
    Case 1
    DrawImage3D(AnimalTab2(aTab(i)\i_anim),posXC1-50,posYC1)
    Case 2
    DrawImage3D(AnimalTab3(aTab(i)\i_anim),posXC1+50,posYC1)
    Case 3
    DrawImage3D(AnimalTab4(aTab(i)\i_anim),posXC1+100,posYC1)
    Case 4
    DrawImage3D(AnimalTab5(aTab(i)\i_anim),posXC1-100,posYC1)
    End Select


    Next

    End Function[/code]

  • EnsembleVideEnsembleVide décembre 2006

    Ca a l'air fatiguant les trucs de vrais codeurs...

    Histoire que vous puissiez comparer avec le travail harassant du webdesigner, moi, le dernier hack que j'ai découvert pour faire bouffer le CSS que je veux à cette merde de Internet Explorer 6 (et uniquement à lui, d'où l'intérêt de la chose), il se résume à ça après un sélecteur de classe :
    [code],[/code]
    Ouais, c'est court. Enfin bon, j'en parlerai peut-être un de ces jours dans mon blög (quand je l'aurai créé, déjà...)

  • p2mp2m décembre 2006

    J'ai compris 67,32% de ton post.
    Je me hais.

    Soit dit en passant c'était instructif. Ca me servira peut'être si je vais au bout de mon DUT.

  • pingupingu décembre 2006

    Allez hop, deuxième post (code), soyons fous.

    Hé oui, quand on est une ptite boîte qui démarre, il faut savoir jongler entre les casquettes. Après la tenue d'un salon avec la casquette "vendeur de supermarché", back to code avec la casquette "codeur ActionScript" qui me va quand même un peu mieux.

    Donc pause Blitz pour le moment, à priori jusqu'à nowell, ou moins selon mon efficacité.

    Ici, le but est donc de faire une maquette jouable rapidos d'un concept, et ce pour en éprouver la funnabilité et la gameplairisation. La question du "je le fais en Blitz ou en Flash ?" s'est posée, mais pour des raisons de rapidité j'ai retenu Flash pour la maquette. Rien n'empêche de développer ensuite sous Blitz pour la version finale.

    Pourquoi ce choix tout d'abord ? Hé bin, l'air de rien, flash avec ses boutons déjà tout faits où il n'y a plus qu'à mettre le code dedans, c'est quand même vachement pratique. Rien que pour pouvoir faire un bouton triangulaire (la zone de click hein), hé bin en passant par du vectoriel c'est quand même beaucoup plus simple. Je pense qu'en bidoullant la formule de calcul d'aire d'un triangle, et en la repositionnant dans l'espace, il y aurait eu moyen de moyenner, mais ça donne mal au crâne rien que d'y penser.

    Surtout que le défi sur ce concept n'était pas là. Il est surtout à arriver à insuffler une mini-IA à des petits personnages, aussi cons soient-ils dans la réalité. Et ça mine de rien, j'avais toujours réussi à esquiver (jeu multijoueur, jeu à tableau, etc...).

    Donc voilà, après deux jours d'actionscriptage en tout genre, j'arrive à peu près à un résultat : 1 petit perso bouge à l'écran de façon spontannée (lol), j'ai ma base de gameplay. Consiste ensuite à multiplier ces actions dynamiquement (pas trop dur), à intégrer le gameplay (ça devrait aller), et à intégrer les "ennemis" (et là... ça va être plus chaud).

    Mon code pour faire avancer mon ptit perso, c'est un peu du débrouillage, mais au final ça fonctionne grâce aux spécificités du jeu (peu de solutions de déplacement à chaque étape). En gros, il y a au maximum 3 déplacements possibles pour le perso à chaque "case" du plateau. Hé oui, c'est un tableau triangulaire. (ça aussi, à éviter quand on débute... il m'a fallu au moins 4 heures pour m'en sortir, alors qu'un bête damier carré... mais bon, c'est moins fun)

    Donc avec 3 déplacements possibles, j'ai réussi en bricolant à m'en sortir : selon la position par laquelle arrive le perso (l'orientation est importante, pour pas que le perso ne fasse des allers-retours sur les deux même cases continuellement), on checke dans tel ordre les chemins possibles de la case courante, puis les chemins possibles de la case d'arrivée, et si ça matche, c'est good, envoyez le déplacement (sans anchois svp).

    Auparavant, il y a un "petit" système qui détecte l'ordre dans lequel il faut checker les chemins. En gros, c'est une sâle imbriquation de ifs et de switchs, et c'est moche.

    Je pense qu'en prenant le problème d'un abord plus "objet", ça aurait été plus propre. Mais moi je préfère tout contrôler de ma timeline principale, et éviter d'avoir du code qui se balade un peu partout dans mes MovieClips (sous flash. Avec un autre langage, y a pas ce problème).

    Enfin bon, d'ici le dév, ça peut encore changer, il suffirait d'adapter ce bout de code à mon objet, mais quand on a peu d'expérience de l'objet, on perd quand même beaucoup de temps à s'organiser et coder "pour rien", alors que justement l'intérêt de ce genre d'outils (flash, blitz et autres), c'est de pouvoir speeder à voir un truc se balader à l'écran, pour pouvoir valider avec le game design "ça c'est bon, mais le gameplay manque un peu sur telle partie, etc..."

    Allez, je pense que je vais institutionnaliser cela, un ptit bout de code pour la fin :

    Ca, c'est un niveau :

    [code]var arrLevel:Array = new Array(5);
    arrLevel[0] = new Array(3,1,3,3,3,3,3,3,3,1,3,3,3,3,3,3,0,0,0,0);
    arrLevel[1] = new Array(1,1,3,1,1,1,3,1,3,3,3,3,3,3,3,3,1,0,0,0);
    arrLevel[2] = new Array(0,1,3,3,1,3,1,1,3,1,3,3,3,3,3,3,3,3,0,0);
    arrLevel[3] = new Array(0,0,0,1,1,3,1,3,1,0,1,3,3,3,3,3,3,1,0,0);
    arrLevel[4] = new Array(0,0,0,0,0,0,0,1,3,3,3,1,3,3,3,1,3,0,0,0);[/code]

    Bon courage le level designer ^^

    Et ça, c'est une portion du code pour checker les chemins possibles sur la case de départ. Le même bout de code est appliqué à la case de sortie, et si ok1 et ok2 sont égales à "true", alors on envoie le déplacement.

    [code] var ok1 = false; //départ
    var ok2 = false; //arrivée
    var indi = obj.tx+obj.ty*100;
    var blio = eval("block"+indi).io;

    if(arrLevel[obj.ty][obj.tx] == 3){
    //3 sorties
    ok1 = true;
    }else if(arrLevel[obj.ty][obj.tx] == 2){
    //2 sorties
    if(dir == 0){
    //gauche
    if(blio == 1 or blio == 0){
    ok1 = true;
    }
    }else if(dir == 1){
    //droite
    if(blio == 2 or blio == 1){
    ok1 = true;
    }
    }else if(dir == 2){
    //bas
    if(blio == 0 or blio == 2){
    ok1 = true;
    }
    }else if(dir == 3){
    //haut
    if(blio == 0 or blio == 2){
    ok1 = true;
    }
    }
    }else if(arrLevel[obj.ty][obj.tx] == 1){
    // 1 sortie
    if(obj.tx % 2 == 0){
    //pair
    if(dir == 0){
    //gauche
    if(blio == 1){
    ok1 = true;
    }
    }else if(dir == 1){
    //droite
    if(blio == 2){
    ok1 = true;
    }
    }else if(dir == 2){
    //bas
    if(blio == 0){
    ok1 = true;
    }
    }else if(dir == 3){
    //haut
    if(blio == 0){
    ok1 = true;
    }
    }
    }else{
    //impair
    if(dir == 0){
    //gauche
    if(blio == 2){
    ok1 = true;
    }
    }else if(dir == 1){
    //droite
    if(blio == 1){
    ok1 = true;
    }
    }else if(dir == 2){
    //bas
    if(blio == 0){
    ok1 = true;
    }
    }else if(dir == 3){
    //haut
    if(blio == 0){
    ok1 = true;
    }
    }
    }

    }else{
    ok1 = false;
    }[/code]

  • EnsembleVideEnsembleVide décembre 2006

    [quote]Bon courage le level designer ^^[/quote]Déjà que j'ai un pur mal de crâne et toute l'efficacité intellectuelle d'un bel état grippal, là, ouais, j'ai besoin de courage. Ceci dit, c'est exactement ce à quoi je m'attendais, donc ça va. Chaque chiffre correspond au type du bloc, et son degré de rotation est géré ailleurs, c'est bien ça ?

  • pingupingu décembre 2006

    Ouaip, le type de block. Son degré de rotation, j'avais pas prévu. Oups -_-'

    Je pensais à du random, mais si tu veux pouvoir les régler tous individuellement, bin ça sera le même tableau dupliqué, avec les chiffres pour les orientations (de 0 à 2).

    Après avoir trifouillé un peu avec, la méthode la plus simple sera je pense de faire le niveau graphiquement, sous flash au toshop selon la facilité, puis de le coder et le tester. Je vais garder une version de test niveau qui se lance rapidement pour que tu puisses checker.

    En plus, rien n'empêche de créer les niveaux en chaîne, puis de passer la main à quelqu'un d'autre pour l'encodage. Un bon boulot de stagiaire ça ^_^

    Au fait, j'ai fini la maquette... elle attend plus qu'à être testée et re-gamedesignée (j'ai noté quelques idées d'ailleurs).

Bien le bonjour, visiteur.

On dirait que vous êtes quelqu'un d'intéressant. Pour le prouver à la face du monde, cliquez sur l'un des boutons ci-dessous.

Connexion Postuler

Dans cette discussion