Crunchez vos adresses URL
|
Rejoignez notre discord
|
Hébergez vos photos
Page 3 sur 5 PremièrePremière 12345 DernièreDernière
Affichage des résultats 61 à 90 sur 123
  1. #61
    Bon, je me suis finalement bougé le cul et j'ai bossé sur le fait que le terrain puisse avoir des "demi-tiles".



    Bon là c'est tout aliasé, mais l'AA c'est pas vraiment ma priorité.


    S'il y a des gens que ça intéresse de savoir comment j'ai fait, voilà mon shader : http://pastebin.com/Hh82jGyX

    En fait je génère sur le CPU un tableau de points et je les mets dans mon vertex buffer. Chaque point correspond au bord bas-gauche de chaque case.
    J'ai une texture 2D (variable "tileStatusTexture") qui contient pour chaque tile quatre nombres. Chaque case est découpée en quatre (en haut, gauche, droite, en bas), et je stocke dans chaque élément de la texture le numéro du type de sol de chacun de ces quatre morceaux.
    Par exemple si la roche c'est 1 et que le cuivre c'est 2, alors une case full roche contiendra quatre fois 1, une case full cuivre contiendra quatre fois 2, une case mi-roche-mi-cuivre avec une pente contiendra deux 1 et deux 2.

    J'ai également un tableau de textures (variable "tileTextures") contenant toutes les textures des différents tiles (texture du sol, texture de la roche, etc.)

    Dans le vertex shader je vais lire dans la texture le type de sol de la case en cours ainsi que des huit cases avoisinantes.
    Dans le geometry shader je construis les quatre triangles représentant les quatre morceaux et je détermine s'il faut dessiner une bordure autour du tile, dans la diagonale, ou dans les coins. Je rajoute également dans la position un petit nombre aléatoire (mais généré aléatoirement à partir d'une seed non aléatoire, sinon ça vibrerait à l'écran) afin de donner le petit effet cartoon.
    Dans le fragment shader je détermine si je suis à l'intérieur d'une bordure (auquel cas je renvois la couleur noir), et si ce n'est pas le cas je lis le tableau de textures au bon offset. Je rajoute un petit bruit aléatoire et le tour est joué.

    C'est un peu compliqué mais je vois pas comment j'aurais pu faire plus simple.
    Reste éventuellement à optimiser un peu le tout, et à remettre les systèmes de "shadow" (par exemple si je veux modifier une case, il faut que la modification soit affichée en surbrillance) et de sélection d'une case (la petite bordure rouge lorsqu'on met la souris dessus).
    Rust fanboy

  2. #62
    Du nouveau !
    Grand maître du lien affilié

  3. #63
    Oui ! On veut des nouvelles !! Viiiiteee Viiiteee !!!
    - Retrouvez la sainte histoire d'Uberwars -


  4. #64
    Euh... euh... ben j'ai pas de nouvelles !

    Techniquement j'ai rencontré un petit soucis avec mon système de composants.
    C'est un peu difficile à expliquer, mais si on prend par exemple les déplacements. Si je veux connaître quelle est la direction de déplacement d'une entité, je suis obligé de connaître tous les autres composants (IA, souffle d'une explosion, etc.), ce qui est contre l'idée du "separation of concerns".

    Par conséquent j'ai un peu changé mon design pour permettre les "liens" entre composants. Par exemple un composant IA va se lier au composant mouvement pour lui indiquer quel est le déplacement à faire.

    Du coup je suis tranquillement en train de transformer mes vieux composants en nouveaux, au rythme de 3 lignes de code par semaine
    Rust fanboy

  5. #65
    Bon, j'ai un peu plus de temps libre à partir de maintenant.
    Je viens de recommencer à bosser dessus sérieusement.

    J'ai entamé quelques changements techniques depuis mes derniers posts.


    Tout d'abord j'ai remplacé le système de callbacks de mon manager par une liste d'événements qui est lue à chaque frame.

    Avant j'avais un simple système de callbacks, c'est à dire que j'appelais une liste de fonctions dès qu'un événement se produisait. Mais ça pose de gros problèmes. En effet si un événement se produit et qu'un callback fait se produire un autre événement, on a les fonctions qui seront appelées dans le mauvais ordre, c'est à dire que certaines fonctions recevront d'abord l'événement B avant l'événement A. Si en plus j'essaye de multithreader tout ça (c'est à dire faire s'exécuter simultanément plusieurs choses), on va rentrer dans un chaos total.

    Maintenant lorsque quelque chose se produit, on a simplement un événement qui se rajoute à la fin d'une liste, sans aucun appel de fonction. La liste d'événements est alors lue à chaque frame. L'avantage c'est que je peux demander à plusieurs parties du programme (l'affichage, le son, les inputs) de lire simultanément la liste d'événements. Et ensuite je commit toutes les modifications (position, mécaniques de jeu, etc.), qui seront affichées à la frame suivante.


    La deuxième modification c'est que j'ai fait hériter tous les composants d'une classe parente Component.
    À la base je voulais profiter de la puissance templatique du C++. Mais le langage manque en fait trop de reflection pour que je puisse aller au bout de mon idée.
    J'ai donc maintenant des fonctions virtuelles "serialize", "unserialize", "getScriptVariablesList", etc.


    Je pense que je vais enchaîner sur l'animation des personnages, ça va pas être une mince affaire.
    Rust fanboy

  6. #66
    J'arrive à un petit résultat niveau animation.

    En fait pour chaque unité dans le jeu, je vais mettre un petit fichier en YAML qui décrit toutes les parties du corps de cette unité et toutes ses animations.

    Par exemple là j'ai un fichier "dwarf.yaml" qui contient les noms des fichiers image qui composent le nain, ainsi que la position, taille et rotation de ces différentes images lors de chaque keyframe de chaque animation.
    Donc pour l'instant j'arrive à enchaîner les keyframes. Je voulais faire un petit gif et le mettre ici, mais pour une raison inconnue Fraps ne fonctionne pas dans mon jeu.

    Il me reste juste à interpoler les positions entre deux keyframes.
    Je vais également rajouter un petit coefficient comme c'est le cas dans Adobe Flash qui permet de rendre l'interpolation plus rapide au début puis ralentit, ou au contraire lente au début puis accélère.
    Je sais pas trop comment ça marche dans flash, mais je pense que c'est tout simplement une courbe de bézier, avec le coefficient qui sert à indiquer où est le point intermédiaire.
    Rust fanboy

  7. #67
    Bon ben j'ai installé la dernière version de Fraps et j'arrive de nouveau à capturer l'écran. Apparemment c'était à cause d'une mise à jour windows.

    Bref, mon petit code d'animation marche du tonnerre.
    Reste à faire les animations. Ouai. Ça va pas être simple.

    En fait le problème c'est qu'il n'y a pas vraiment d'outil gratuit permettant d'animer des images existantes (et encore moins d'exporter les animations), du coup je devoir tout me taper à la main.

    Du coup j'ai inventé mon propre format. Par exemple ce fichier YAML :

    Code:
    body:
      - resource: textures/units/dwarfArmSide
        center: [ 0.5, 0.97 ]
        dimensions: [ 0.17, 0.26 ]
      - resource: textures/units/dwarfFootSide
        center: [ 0.42, 0.97 ]
        dimensions: [ 0.29, 0.16 ]
      - resource: textures/units/dwarfBodySide
        center: [ 0.5, 0.5 ]
        dimensions: [ 0.52, 0.50 ]
      - resource: textures/units/dwarfHeadSide
        center: [ 0.5, 0.5 ]
        dimensions: [ 0.53, 0.60 ]
      - resource: textures/units/dwarfArmSide
        center: [ 0.5, 0.97 ]
        dimensions: [ 0.17, 0.26 ]
    animations:
      walking:
        - duration: 0.5
          acceleration: 0.2
          body:
            - position: [ 0, 0.25 ]
              rotation: 0.79
            - position: [ 0, 0.08 ]
              rotation: -0.05
            - position: [ 0, 0.28 ]
            - position: [ 0, 0.70 ]
            - position: [ 0, 0.25 ]
              rotation: -0.79
        - duration: 0.5
          acceleration: -0.2
          body:
            - position: [ -0.05, 0.25 ]
              rotation: -0.79
            - position: [ 0.01, 0.08 ]
              rotation: 0.05
            - position: [ 0, 0.28 ]
            - position: [ 0, 0.71 ]
            - position: [ 0.05, 0.25 ]
              rotation: 0.79
    Me donne ce résultat :

    Rust fanboy

  8. #68
    on dirait prison architect
    Grand maître du lien affilié

  9. #69
    C'est vrai que ça y ressemble!

    C'est pas mal.
    Et en tout cas, c'est toujours mieux que les animations des personnages dans Gnomoria ou DF

  10. #70
    "Dieu est mort" · "Si le téléchargement c’est du vol, Linux c’est de la prostitution."

  11. #71
    Ah, pas mal ce truc ! Je sais pas comment je suis passé à côté de ça.
    C'est vraiment très complet, et c'est pile ce qu'il me faut.
    Rust fanboy

  12. #72
    C'est payant malheureusement, mais pour 60€ je pense que je vais craquer, surtout que pixi.js que j'utilise le supporte nativement depuis la dernière release !

    Sinon il est classe ton nain ! Mais il est Not amused !!!
    - Retrouvez la sainte histoire d'Uberwars -


  13. #73
    Hop, je me suis payé ce petit soft

    C'est assez simple de créer des trucs avec :



    Reste à faire le code C++ qui lit l'animation.
    Rust fanboy

  14. #74
    manque un petit roulement d'oeil
    Grand maître du lien affilié

  15. #75
    T'as des runtime déjà écrites aussi pour spine : http://esotericsoftware.com/spine-runtimes/
    "Dieu est mort" · "Si le téléchargement c’est du vol, Linux c’est de la prostitution."

  16. #76
    Ouai, j'ai vu, mais v'là le code un peu merdique quoi.

    Là mon code à moi marche à part quelques bugs, et en terme de lignes de code il fait la taille de chacun de ses fichiers pris individuellement.
    Rust fanboy

  17. #77
    Voilà, ça marche en 500 lignes de code :



    http://pastebin.com/k3913U8N
    http://pastebin.com/mmnSethJ

    Faudrait optimiser un peu ça, mais à part la possibilité de changer la couleur des sprites et la possibilité de mettre des gifs animés, tout est implémenté.


    J'ai juste un problème, c'est que les dimensions sont arbitraires puisque ce sont en fait les dimensions en pixels des images qui sont prises. Par exemple si mon buste fait 400px de haut et ma tête 300px, le tout fera à peu près 700 unités de haut in-game, et il n'y a rien qui permet de savoir ça.

    Du coup je ne sais pas de combien réduire la taille pour que ça coincide avec le décor.
    Rust fanboy

  18. #78
    Pourquoi est-ce que tu fais systématiquement des conversions vers std::string lorsque tu accèdes à ta hashtable ? Pourquoi ne pas faire simplement mCharacterInfos["bones"], plus lisible ?
    Je pense aussi que tu peux t'économiser des lignes et des ifs avec des valeurs de fallback du genre : nodeX.as< float >(0).

    Ton calcul de la courbe de bezier est un peu barbare aussi, et ne fonctionne certainement pas si la courbe passe plusieurs fois par le même x, tu devrais retourner la coordonnée d'un point pour t passé en paramètre au lieu d'essayer de le faire pour un x donné.
    "Dieu est mort" · "Si le téléchargement c’est du vol, Linux c’est de la prostitution."

  19. #79
    Pour le mCharacterInfos["bones"] et le nodeX.as<float>(0) c'est parce que j'utilise la librairie YAML.
    Si j'écris mCharacterInfos["bones"], il me met une erreur parce que la lib utilise des templates, et a prévu le cas const char* mais pas le cas const char[N]. Peut être qu'une mise à jour de la lib corrigerait ça, j'ai pas testé.

    Pour nodeX.as<float>(0), c'est pareil, la lib ne supporte pas ça.



    Pour la courbe de bézier, en fait l'axe X représente le temps entre les deux keyframes, et l'axe Y représente la progression de l'animation. Du coup il me faut une méthode pour convertir de X en Y.
    Juste après avoir posté le code j'ai changé l'algorithme pour faire ça par dichotomie. C'est à dire qu'au lieu de faire t=0, puis t=0.01, puis t=0.02, etc. je fais t=0.5, et en fonction de si on trouve un résultat trop grand ou trop petit je pars sur t=0.25 ou t=0.75.

    Mais j'ai eu une autre idée tout à l'heure : je vais tout bêtement garder en mémoire le "t" qui a été trouvé lors du précédent appel de fonction, et chercher à partir de là.



    Je vais encore rien optimiser, mais je pense que je gagnerai beaucoup de temps en gardant en mémoire tout simplement les étapes d'animation actuelles, plutôt que de rechercher l'étape actuelle à chaque frame.
    Rust fanboy

  20. #80
    La version 0.5.1 de yaml-cpp a bien la méthode as(S const& fallback) et je pense que char[N] aussi est supporté.
    http://code.google.com/p/yaml-cpp/so...lease-0.5.1#51
    http://code.google.com/p/yaml-cpp/so...ease-0.5.1#358
    "Dieu est mort" · "Si le téléchargement c’est du vol, Linux c’est de la prostitution."

  21. #81
    Ouaip ça marche, merci.
    En fait pour le char[N], c'était une structure qui s'appelle convert<T>, donc c'est pas ce bout de code là avec to_value_t. Mais ça a l'air d'avoir été corrigé dans la 0.5.1.
    Rust fanboy

  22. #82
    J'ai eu l'idée d'externaliser le code qui génère le terrain.

    Seule couille : ça prend environ une minute pour générer un pauvre terrain de 512x512.
    Après profilage, c'est la partie interface entre le C++ et le Lua qui bouffe 99 % du temps. J'ai à peu près 200 000 appels de fonction de Lua vers C++.
    Du coup va falloir que je passe un peu de temps à optimiser ça.
    Rust fanboy

  23. #83
    Bon, je me suis dit que j'allais créer un petit snapshot de là où j'en suis.
    Je vous préviens tout de suite : c'est pas super intéressant si vous n'êtes pas programmeur, mais ça dévoile l'envers du décor.

    Ça se télécharge ici.
    Attention : je suis passé à Visual C++ 2013, et comme c'est tout neuf il y a de grandes chances que vous ayez besoin d'installer "Redistribuable Visual C++ pour Visual Studio 2013", qui est téléchargeable ici.

    Il y a trois gros bugs connus : au bout d'un certain nombre de clicks à l'écran ça plante (je suspecte un bug dans un code de la STL de Visual C++), parfois il y a un popup "exception while calculating path, blabla, we are inside a solid tile" suivi d'un crash, et on ne peut pas descendre les pentes qui vont vers la droite.



    Fonctionnement

    Donc l'idée, c'est que je suis passé à un système d'entités dynamiques.
    Lorsqu'on démarre le programme, celui-ci charge "resources/game-start.yaml" (qui contient l'état initial du jeu), puis exécute "resources/game-init.lua" (qui se charge pour l'instant juste de créer le terrain de manière aléatoire). J'ai choisi le yaml comme format de sauvegarde de la game, et en chargeant game-start.yaml c'est en fait le même code que si je chargeais une save.

    Tout ce qui existe à l'écran ou dans la mémoire du jeu est décrit dans ces deux fichiers, il n'y a rien de caché.
    Par exemple le personnage que vous voyez à l'écran est décrit dans game-start.yaml :
    Code:
      - name: character
        components:
          position:
            x: 1.5
            y: 0.12
          characterDisplay:
            model: textures/units/dwarf
          colliding:
            collidesWithOthers: false
            collidesWithGround: true
            bumpOnCollision: true
          destination:
            x: 12
            y: 10
          taskAssignment:
            autoAssign: true
            task: ~
          animated:
            animation: walk
            speed: 1
    Par exemple vous pouvez modifier "walk" en "idle" ou bien modifier la valeur de "animated" -> "speed", pour que le personnage s'anime différemment. Vous pouvez mettre "collidesWithGround" à false afin de permettre au personnage de s'enfoncer dans le sol.
    Le model "textures/units/dwarf" désigne le fichier "resources/textures/units/dwarf.json" généré par spine, qui contient quant à lui les noms des images composant le nain.

    La "destination" désigne l'endroit où doit se déplacer le personnage. Mon algo de pathfinding se charge automatiquement de calculer le chemin. Celui-ci est un peu buggé encore, puisque je ne peux par exemple pas descendre les pentes qui vont vers la droite.


    Les interactions

    Vous remarquez que lorsqu'on clique sur une case au niveau du sol, le personnage s'y dirige.
    En fait c'est un morceau de code dans game-init.lua qui fait ça, ligne 83 :
    Code:
    entity:add("interactive")
    entity.interactive.scriptOnClick = [[
    	Entities[2].destination.x = This.position.x
    	Entities[2].destination.y = This.position.y
    
    	local e = Entities:new("digJob")
    	e:add("assignable")
    	e.assignable.maxAssignments = 1
    ]]
    Je suis à l'intérieur d'une boucle for, et "entity" désigne la case de terrain actuellement en cours de création.
    J'ajoute à la case un composant "interactive", et lorsqu'on clique sur la case, le contenu de "entity.interactive.scriptOnClick" sera exécuté. Note : en lua, les [[ ]] permet de faire un bloc de texte multiligne.

    Le bout de code en question modifie la destination de l'entité n°2 (c'est à dire le personnage) pour qu'il vienne sur la case sur laquelle on a cliquée. Les trois lignes suivantes sont simplement là parce que j'ai commencé à refaire le système de jobs, mais c'est pas encore fini, et donc elles ne servent à rien.

    Si vous cliquez sur une case en l'air ou sur une case sous-terraine, la destination est bien modifiée mais le personnage n'arrive pas à s'y diriger et donc ne bouge pas.


    La caméra

    Autre exemple : la caméra.
    La caméra est gérée de façon manuelle. J'ai une entité spéciale nommée "meta-entité" qui se charge de désigner quelle est la caméra actuelle :
    Code:
      - name: meta-entity
        components:
          camera:
            cameraEntity: 1
    La caméra est quant à elle simplement une entité qui possède une position, et qui est dirigée par le joueur uniquement car elle possède un composant "playerControl".
    Code:
      - name: camera
        components:
          ownerMovements:
            x: 0
            y: 0
          position:
            x: 2
            y: 10
          playerControl:
            maxSpeed: 0.2
    Si vous enlevez "playerControl: maxSpeed: 0.2" vous ne pourrez plus diriger la caméra.
    Si vous copiez-coller les composants de la caméra pour les mettre sur le personnage, vous pourrez manuellement diriger celui-ci à l'aide du clavier.
    Dernière modification par Tomaka17 ; 09/07/2013 à 14h07.
    Rust fanboy

  24. #84
    Histoire de donner des nouvelles, je fais toujours mumuse avec mon moteur de jeu.



    (le gif est assez lent, je sais pas pourquoi)

    J'ai rajouté un système d'entités "templates", qui me permet notamment de créer des spawners.
    Vous voyez les personnages à droite apparaître. En fait c'est un spawner invisible qui se déplace vers la droite et fait apparaître des personnages à intervalle régulier.

    Mon GUI fonctionne à nouveau à peu près correctement.
    Les boutons en bas à droite fonctionnent.
    Rust fanboy

  25. #85
    Pour les animations, si je ne dis pas de conneries, la technique usuelle est d'utiliser une planche de ton perso contenant toutes les étapes possibles de chaque animation (pour une question de charge de mémoire, c'est moins gourmand qu'une image par étape d'animation) :


    (Cherche animation sprite sheet sur google).
    Ta méthode est je pense moins gourmande en mémoire (puisque ce n'est pas la totalité de la texture que tu redessines à chaque fois), mais tu ne pourras faire d'animations avancées.

  26. #86
    Ça c'est la méthode classique, que j'exclus car ça prend énormément de temps de dessiner tout ça et que je ne sais de toute façon pas dessiner correctement.

    Au pire des cas je peux toujours utiliser ce principe avec Spine, puisque celui-ci permet de changer de sprite au cours de l'animation. Donc ma méthode ne va absolument pas me limiter en quoi que ce soit.
    Rust fanboy

  27. #87
    Des news cher tomaka ?
    Grand maître du lien affilié

  28. #88
    De nouveau, il y a que ça compile sous Linux et que mon pathfinding est maintenant à peu près niquel. J'ai aussi un GUI qui marche un peu mieux.
    J'ai réglé plein de petits détails avec mon moteur. Il faudrait juste que je remettre ça au propre.

    En gros pour l'instant quand je lance le jeu, je peux donner l'ordre de couper des arbres ou de creuser le sol. Un nain est automatiquement assigné et effectue la tâche.

    Ce qui me bloque un peu c'est l'UI. Il faut que je bosse un peu là dessus si je veux avancer. En fait je pourrais par exemple créer un bouton "poser une échelle" et le faire marcher. Mais le problème c'est que je ne vais pas créer un bouton pour chaque objet constructible. Du coup il me faut un petit système de fenêtres et tout le bordel.
    Rust fanboy

  29. #89
    Est-ce que Survivor of Ragnarok t'as inspiré ? Le pitch de départ semble plutôt similaire :


    C'est aussi du DF-Like, centré sur la gestion des unités, quoique avec peut-être une touche plus importante de gestion des caractéristiques.
    Dernière modification par Aristynax ; 14/10/2013 à 08h12.

  30. #90
    Je connais pas du tout ce jeu, mais il a l'air bien sympa.


    En tout cas même si j'ai pas encore de prototype à montrer (plein de trucs qui marchent pas et de trucs qui marchent mais bien hacky), j'ai eu plein d'idées vis à vis du jeu.

    J'aime beaucoup les jeux "d'exploration" que l'on découvre au fur et à mesure, et je vais faire un jeu de ce genre. C'est à dire concrètement que par exemple au lieu de dire dans un tuto "vous devez récolter du fer pour fabriquer des épées", je laisserai au joueur découvrir le fer et ferai apparaître les recettes à ce moment-là. Et je vais essayer de remplir le jeu de ça.
    Rust fanboy

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •