Tuto 2: Transformer une ressource (Asset) en centre commercial (première partie).

Willkommen in der Transport Fever Community

Wir begrüßen euch in der Fan-Community zu den Spielen Transport Fever und Train Fever, den Wirtschaftssimulatoren von Urban Games. Die Community steht euch kostenlos zur Verfügung damit ihr euch über das Spiel austauschen und informieren könnt. Wir pflegen hier einen freundlichen und sachlichen Umgang untereinander und unser Team steht euch in allen Fragen gerne beiseite.

 

Die Registrierung und Nutzung ist selbstverständlich kostenlos.

 

Wir wünschen euch viel Spaß und hoffen auf rege Beteiligung.

Das Team der Transport-Fever Community


  • Ce tutoriel est en 3 parties car il m'était impossible de le publier en une seule car il dépasse le nombre de caractères maximum autorisés pour un message.


    Tutoriel 2: Transformer une ressource (Asset) en centre commercial (première partie).


    Pourquoi ?


    Lorsqu'un objet est défini comme "commerce" il attire des clients.
    Donc, si l'on veut gagner facilement de l'argent pour se rendre dans ce commerce dans TF, il suffit de placer un arrêt de bus, de tram ou une gare à proximité de ce bâtiment pour que les usagers utilisent cet arrêt pour se rendre dans ce commerce.
    De façon similaire, on peut faire en sorte que cette construction attire également des marchandises et placer à proximité un dépôt de marchandises afin que nos camions apportent ces marchandises dans ce bâtiment. Ce sera une source supplémentaire de revenus.


    Comment faire?


    Pour attirer des clients, nous devons déclarer cette construction comme étant un immeuble commercial et le relier à la rue où circulent les bus et les piétons.
    Pour attirer des marchandises, nous devons gérer les stocks entrants dans cet immeuble.


    Modèle


    Pour illustrer ce tuto, j'ai utilisé l'immeuble "Lidl" créé par Sir_Bier. Vous pouvez le télécharger à l'adresse suivante:


    https://www.transportfever.net…ase/index.php/Entry/4237/


    J'ai utilisé ce mod car il va me permettre de vous expliquer les points les plus importants de ce tutoriel.
    Si vous installez ce mod tel quel, vous verrez qu'il se situe dans le menu des ressources (Asset) et qu'il est juste un bâtiment de décoration.
    Nous allons le transformer en un véritable immeuble commercial!


    Etudions le fichier lidl.con


    Après avoir téléchargé le mod, sauvegardez-le dans un dossier.
    Toutes les modifications se font dans le fichier lidl.con qui est écrit en language LUA.
    Ce fichier est situé dans \res\construction\assets\buildings\lidl.con
    Ouvrez ce fichier avec votre éditeur de texte favori (moi j'utilise Notepad++).
    Vous remarquez qu'il y a peu de lignes de programmation.
    Nous allons en modifier certaines et en ajouter d'autres.


    Etudions ce script.
    ----------------------


    Lua
    ZPos local = 0




    Il s'agit d'une variable qui est utilisée dans le positionnement vertical du modèle. Vous la retrouvez, plus bas, dans l'appel de la fonction result.models().
    On n'y touche pas pour le moment.

    Lua
    function data ()

    C'est la fonction qui paramétrise la construction et qui se termine, comme toute fonction en langage Lua, par l'instruction END en fin de script.
    C'est dans le corps de cette fonction que nous allons définir ce modèle comme immeuble commercial.

    Lua
    type = "ASSET_DEFAULT"

    Cela indique que la construction est juste un élément de décoration et qui placée dans le menu ressources (ASSET en Anglais).
    Voici les types de constructions possibles dans TF (Toujours en MAJUSCULES):


    Nous laisserons l'immeuble Lidl dans "ASSET_DEFAULT".
    Vous pourrez donc le sélectionner dans ce menu durant le jeu.
    Toutefois, j'ai créé un sous-menu "Commercial". Je vous en parlerai le moment venu.

    Lua
    description = {
    		name = _("Lidl"),			        -- c'est le nom donné à l'immeuble
    		description = _("Lidl_Supermarkt")  -- et sa description dans le menu
    	},

    Le nom et la description de la construction apparaissent dans le menu lorsqu'on laisse le pointeur de la souris sur l'image de cette construction.
    Cette image est au format .tga (non compressé) et est située dans:


    \res\rtextures\ui\constructions\assets\buildings\Lidl.tga


    Remarque
    ------------
    Vous remarquez que le nom et la description de la construction sont écrits avec le format: _("mot")
    Cela est utile si vous voulez que ces mots apparaissent dans le menu dans la langue du joueur qui utilise ce mod.
    Je vous expliquerai, à la fin de ce tuto, en annexe 1, comment vous pouvez faire en sorte que les mots soient traduits dans la langue du joueur.


    Lua
    availability = {},

    C'est ici que l'on indique les dates auxquelles cette construction est disponible. La syntaxe est la suivante:


    Lua
    availability = { yearFrom = année de début,
                     yearTo = année de fin
                   }

    Par exemple, yearFrom = 1900 et YearTo = 1975, qui indique que cette construction est disponible dans le menu de 1900 à 1975.
    Je précise bien "dans le menu" car ce bâtiment, une fois construit, ne disparaît pas de votre carte en 1975! Il y restera tant que vous ne l'aurez pas détruit avec le buldozer.
    En outre, les fichiers qui constituent ce modèle, restent toujours dans leurs répertoires d'origine.


    Cas particuliers:
    Si le contenu de la liste "availability" est vide (comme ici) ou si les deux valeurs sont égales à 0, cette construction est toujours visible dans le menu.
    Si "yearFrom" est omis ou égal à 0, la construction est visible depuis le début du jeu jusqu'à la date "yearTo".
    De-même, si "yearTo" est omis ou égal à 0, la construction reste disponible indéfiniment dans le menu depuis "yearFrom".
    Par exemple:


    Lua
    availability = { yearFrom = 0,
                     yearTo = 1990


    La cosntruction est visible depuis le début du jeu jusqu'en 1990.
    Dans ce tuto, puisque "availability" est vide, la construction est toujours visible dans le menu.


    Lua
    buildMode = "MULTI"

    Ceci indique comment est placé la construction sur la carte:
    MULTI : la construction peut être placée plusieurs fois sans rouvrir le menu
    SINGLE : Lorsque la construction est placée sur la carte, le menu se referme et si on veut placer une autre construction il faut rouvrir le menu contenant cette construction.
    BRUSH : C'est le mode "pulvérisation", c'est-à-dire que si on laisse le bouton gauche de la souris enfoncé pendant que l'on place une construction, celle-ci se dessine plusieurs fois. C'est pratique, par exemple pour placer des arbres sur la carte.


    Vous verrez dans mes modifications que j'ai mis buildmode = "SINGLE", donc on place une construction, puis le menu se referme.


    Lua
    categories = {"buildings"}

    La construction apparaît dans le sous-menu "buildings" du menu "ASSET_DEFAULT".
    J'ai modifié cette valeur par {"commercial"} afin de créer un sous-menu où je place tous mes immeubles commerciaux.
    L'image associée à cette catégorie se trouve dans:


    \res\textures\ui\construction\categories\commercial.tga


    L'original "buildings" défini par le créateur du bâtiment se trouve dans le même répertoire avec, évidemment, le nom "buildings.tga car le fichier .tga doit avoir le même nom que le nom utilisé dans categories sinon, on aura un petit carré bleu dans le sous-menu.


    Lua
    order = 518610905

    C'est une variable que peut prendre la valeur "true" ou "false". Si elle est "true", cela permet que la construction puisse entrer en collision avec un autre objet de la carte.
    Si elle est "false", toute collision est interdite au moment où l'on place cette construction sur la carte.
    Dans la construction modifiée, j'ai placé cette valeur à "false" afin d'éviter toute collision avec un autre objet, comme la rue par exemple.


    Lua
    autoremovable = false,

    Si ce paramètre est mis sur "true", la construction sera automatiquement supprimée en cas de collision avec un autre objet.


    Lua
    params = {},

    C'est ici que l'on écrira la liste dees paramètres qui interviennent dans le reste du script.
    Ces paramètres ouvrent un boîte de dialogue pour que le joueur puisse paramétrer la construction. Par exemple, pour choisir le nombre de voies dans une gare.
    Plus loin dans ce tuto, je vous expliquerai comment faire pour utiliser des paramètres pour choisir, entre autre, le nombre de personnes qui viendront dans le magasin.


    Lua
    update function = function(params)
        local result{}

    C'est cette fonction qui configure la construction en tenant compte des paramètres contenus dans la table "params" ci-dessus.
    Cette fonction retourne une liste de paramètres au programme principal.
    Dans le fichier Lidl.con il n'y a que deux éléments dans cette liste:


    Lua
    result.models =
                {
                    {id = "SB_Lidl.001.mdl", transf = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, zPos, 1 } }
                }

    id est le fichier .mdl qui représente le modèle de la construction. Ce fichier se trouve dans:


    \res\models\model


    Nous ajouterons deux modèles supplémentaires qui viendront compléter cette liste. Il s'agit des objets qui nous permettront de voir les marchandises qui arriveront dans notre commerce.


    "transf" est une liste qui représente une matrice 4x4 permettant de modifier la position du modèle sur la carte par rapport à ses coordonnées d'origine définies par le concepteur dans le fichier .mdl.
    Je vous expliquerai, en annexe 2, en quoi consiste une matrice 4x4 et comment modifier les valeurs contenues pour déplacer, faire tourner et modifier la grandeur d'un modèle.
    En ce qui concerne le modèle du bâtiment principal défini dans le fichier SB_Lidl.001.mdl, nous ne changerons pas ces valeurs. Je remplacerai juste la valeur zPos par 0, puisque je ne désire pas modifier la hauteur à laquelle le bâtiment va se positionner par rapport au sol.
    Mais vous pouvez très bien le laisser tel quel et voir ce qui se passe si vous changez, à la première ligne du script la valeur de la variable zPos.


    L'ordre dans lequel vous agencez la liste des modèles utilisés n'a pas d'importance.


    Lua
    result.terrainAlignmentLists = 
            { 
                {
                 type = "EQUAL",
                 faces = {}
                } 
            }

    type peut accepter les valeurs : "EQUAL", "LESS" ou "GREATER"
    Les valeurs contenues dans cet élément de la liste déterminent la manière dont la construction est alignée par rapport au terrain.
    En principe, on ne modifie pas ces valeurs.


    Lua
    return result

    C'est l'instruction qui retourne au programme principal la liste "result"


    Lua
    end

    Marque la fin de la fonction "updateFn"


    Lua
    {

    Marque la fin de la liste "return"


    Lua
    end

    Marque la fin de la fonction "data()"


    Voyons maintenant comment modifier ce script pour transformer cet élément de décoration "Lidl" en centre commercial


    Téléchargez mon module "ML_tuto2_1" que vous trouverez sur ce site
    Ouvrez dans votre éditeur de texte le fichier:


    \res\construction\ assets\buildings\lidl.con


    Vous voyez pas mal de changements par rapport au fichier .con d'origine.


    1. Comment faire venir des clients dans notre magasin?


    Tout d'abord, dans local result = {}, on ajoute une entrée intitulée:


    Lua
    result.personCapacity = 
            {
                type = "COMMERCIAL", 
                capacity = 1000      
            }

    Il existe 3 type de parcelles dans TF:
    RESIDENTIAL : indique qu'il s'agit d'une maison d'habitation
    COMMERCIAL : indique qu'il s'agit d'un commerce
    INDUSTRIAL : indique qu'il s'agit d'une usine


    Ici, nous définissons la construction comme étant de type commercial et cela suffit pour attirer des clients vers notre commerce, pour autant que cette construction soit placée au bord d'une rue reliée à la ville (max 5 mètres).
    Il faudra attendre un mois avant de voir arriver les premiers clients.
    Les piétons vont s'approcher de l'immeuble commercial et, une fois arrivés à sa hauteur, il vont disparaître pour indiquer qu'ils sont dans l'immeuble. Quelques temps après ils en ressortent et poursuivent leur chemin.
    C'est pareil pour les voitures car certains clients qui habitent plus loin, vont venir visiter notre commerce en voiture.
    Comme pour les piétons, les voitures vont disparaître de la rue une fois en face du commerce puis vont réapparaître au même endroit quelques secondes plus tard.
    Ce n'est pas du plus bel effet, je l'avoue, mais si vous regardez le jeu, vous verrez que c'est ainsi qu'a été conçu le jeu.


    On pourrait donc en rester là, mais nous pouvons faire mieux.


    2. Amener les piétons dans le magasin


    Tout d'abord, amenons les piétons vers la porte d'entrée du bâtiment par laquelle ils entrent et sortent de ce magasin. Ce sera plus réaliste!
    Pour que les clients puissent entrer et sortir du magasin, nous allons relier la construction avec une rue. Mais pas n'importe quelle rue. Je ne veux pas que les voitures puissent l'emprunter et rentrer par la porte du magasin!
    Donc je vais créer une allée réservée aux piétons.
    Cette allée, je l'ai appelée "special_commercial_street".
    Vous la trouverez dans mon module dans le répertoire:
    \res\config\street\special_commercial_street.lua


    Ouvrez ce fichier dans votre éditeur de texte.
    Je n'entre pas dans les détails de la construction d'une rue. Voici ce qui est important:
    Tout d'abord sachez que toutes les mesures de grandeurs dans TF sont exprimées en mètres.


    numLanes = 0, -- indique combien de voies de circulation comporte cette rue. Comme je ne veux aucun véhicule, je mets cette variable à 0
    streetWidth = 0.01, -- c'est la largeur de la rue. Ici je ne veux pas de rue, juste des trottoirs qui feront mon allée. J'aurais pu mettre cette variable à 0, mais, malheureusement, le programme va se planter. Voilà pourquoi j'ai mis 0,01 comme largeur
    sidewalkWidth = 1.0, -- c'est la largeur d'un trottoir (ici 1 mètre)
    sidewalkHeight = .30, -- c'est la hauteur du trottoir par rapport au sol. J'ai mis 0.30 m (soit 30 cm) qui est la mesure générale utilisée dans TF
    yearFrom = 0, -- cette rue est visible depuis le début du jeu
    yearTo = 1900, -- mais on ne la retrouve plus dans le menu des rues après 1900. Si vous souhaitez voir cette rue dans le mu des rues mettez cette valeur à 0, comme je vous l'ai déjà expliqué plus haut.


    Tout le reste concerne les textures des rues, trottoirs et bordures. On peut aussi paramétrer les voies de bus et de tram, ainsi que les objets qui bordent la rue (arbre, réverbères, etc)
    Je vous conseille de regarder les différents fichiers de rues du jeu que vous trouverez dans le répertoire:
    \Transport Fever\res\config\street\


    Cela vous permettra de vous amuser à modifier certains paramètres et voir par vous-même le résultat dans le jeu.
    Mais je ne vous conseille pas de modifier ces fichiers directement dans le jeu, mais bien d'en faire une copie que vous modifierez selon vos goûts et puis les intégrer au jeu en créant un mod.
    Cela fera sans doute l'objet d'un prochain tuto...


    Maintenant que nous avons notre allée, nous allons la relier à notre magasin et à la rue principale afin que les clients puissent entrer dans le magasin.
    Voici le magasin vu de face (Fig.1) et vu de derrière en vue aérienne (Fig.2):
    transportfever.net/wsc/attachment/132460/


    transportfever.net/wsc/attachment/132462/


    Sur la Fig.1 nous voyons l'allée par laquelle les piétons entrent et sortent du magasin. Cette allée se prolonge à l'intérieur du magasin.
    L'allée va donc du point A intérieur (11.8,0.0,0.3) au point B extérieur (11.8,16.0,0.3) où elle se relie à la rue principale.


    Sur la Fig.2 nous voyons que les extrémités du bâtiment principal vont de X= -27.7 (à gauche) à X= 22.3 (à droite) et de Y= -15.0 (arrière) à Y= 10.44 (avant).
    Ces coordonnées sont indiquées dans le fichier situé dans:
    \res\models\model\SB_LIDL.001.mdl


    C'est le fichier qui définit le modèle du bâtiment principal Lidl.
    Vous trouverez les coordonnées, dans ce fichier, dans la liste:
    Transport Fever\res\config\street\


    Lua
    boundingInfo = {
    		bbMax = {22.30238, 10.44462, 10.40048,},
    		bbMin = {-27.69763, -15.04805, 0.0,},
    	},


    Remarquez aussi les coordonnées de l'allée.
    Je l'ai faite rentrer dans le bâtiment pour que les piétons entrent jusque là, ce qui donne un aspect réaliste à la situation.


    Je reviendrai plus tard sur les point R et S de la Fig.2


    Pour relier l'allée à la rue nous créons un nouvel élément dans la liste result:



    Il s'agit d'une liste d'objets qui s'accolent aux bords de la construction principale.
    Je définis donc un objet comme étant un segment de rue avec l'expression:


    type = "STREET",


    On utilise "STREET" pour une rue et "TRACK" pour une voie de chemin de fer.
    Ensuite, je précise de quel modèle de rue il s'agit dans
    params = {type = "special_commercial_street.lua",}


    Puis je donne les coordonnées du segment de rue en définissant les bords avant et arrière de ce segment par rapport au centre de la construction (0,0,0) :
    Après plusieurs essais, j'obtiens les coordonnées correctes de ce segment que je renseigne dans :
    edges = { { { 11.8, 0.0, 0.3}, { 0, 1, 0 } },{ { 11.8, 16.0, 0.3}, { 0, 1, 0 } }},
    coord X,Y,Z bord intérieur coord X,Y,Z bord extérieur
    Noeud 0 Noeud 1


    Mais que représente les triplets { 0, 1, 0 } ?


    En fait, ce sont les vecteurs qui donnent la direction du segment ou, on peut dire aussi les axes d'alignement du segment de route.
    J'ai expliqué dans mon tuto 1 ("Création d'arrêts de bus dans une station") le concept des axes d'alignement et comment les calculer.
    Comme ce segment est rectiligne, on utilise (0, 1, 0) comme axe d'alignement pour les deux bords.
    Si vous voulez plus d'explications concernant les axes d'alignement, revoyez mon tuto 1.


    Enfin, nous devons indiquer de quel côté mon allée va se relier à la rue principale. Cela se fait avec snapNodes = {1}, c'est-à dire le Noeud 1 du segment dans la liste edges.
    Je vous rappelle que puisqu'il s'agit d'une liste, le premier élément possède l'indice 0, le deuxième l'indice 1, etc...


    Si nous nous arrêtons là, les piétons arriveront bien après un mois dans notre magasin. Mais cela ne générera pas d'argent supplémentaire.
    Ce que nous devons faire c'est amener ces clients depuis le centre ville vers le commerce en plaçant un arrêt de bus à proximité de celui-ci et, bien entendu, relier cet arrêt de bus par une ligne de bus.
    Ainsi les clients vont utiliser cette ligne de bus pour aller au magasin et c'est à ce moment que cela va nous faire gagner de l'argent!


    Vous remarquerez que j'ai placé une seconde rue, accolée à notre construction.
    Je l'ai fait pour vous montrer qu'il est possible d'associer plusieurs rues à une construction.
    Il s'agit d'une rue standard du jeu ("new_medium.lua") que je rajoute dans result.edgeLists. Vous la trouverez dans le répertoire:
    \Transport Fever\res\config\street\new_medium.lua
    Nous avons alors:



    Remarquez que snapNodes possède deux valeurs: {1,0}. Cela veut dire que le segment de route peut être relié des deux côtés.
    Ainsi les véhicules (et les piétons) pourront utiliser cette rue pour circuler.


    Suite dans la partie 2 publiée dans ce forum

  • Ceci est la suite du Tuto2 (première partie) publié également dans ce forum


    3. Comment Amener des marchandises dans le magasin ?


    Si nous voulons gager encore plus d'argent, nous pouvons faire en sorte d'attirer des marchandises vers notre construction.
    Je vais maintenant vous expliquer comment amener des produits alimentaires dans notre magasin.
    Quand je dis dans, je devrais dire "à côté", car cela nous permettra de voir si cela fonctionne comme souhaité.


    La procédure est un peu moins facile que dans le cas des clients mais je vais essayer d'être le plus clair possible.


    Donc, je choisis d'amener des produits alimentaires (FOOD en Anglais).
    Pour que cela fonctionne, il est nécessaire que au moins une usine agroalimentaire produise des produits et que ces produits soient amenés avec des camions ou des trains dans un dépôt de marchandises situé dans les environs de notre magasin.


    Rien ne vous empêche de choisir un autre type de marchandise dans cette liste. (Toujours en Majuscule et en Anglais):


    Ceci est la suite du Tuto2 (première partie) publié également dans ce forum




    Pour visualiser ces marchandises, nous utiliserons le fichier "food_small.mdl" qui se trouve avec les autres modèles dans:
    \Transport Fever\res\models\model\industry\cargo\food_small.mdl


    Il s'agit d'un empilement de caisses sur une palette en bois, comme vous pouvez le voir, par exemple, dans l'usine agroalimentaire.
    Bien entendu, si vous utilisez un autre type de marchandise, vous devez utiliser, pour être cohérent, le fichier .mdl adéquat.


    Nous devrons ensuite définir le stock de marchandise, en précisant de quel type il s'agit, si nous souhaitons recevoir ces marchandises(comme c'est le cas d'un magasin) ou au contraire les expédier (comme dans une usine de production) et à quel endroit ces marchandises seront stockées et quelle superficie nous leur accorderons.
    Enfin il faudra aussi préciser quelle quantité annuelle notre magasin va utiliser.


    Allons-y


    Tout d'abord, nous devons définir la surface sur laquelle nous allons recevoir la marchandise. Cela se fait avec le script "constructionutil.lua" qui se trouve dans:
    \Transport Fever\res\scripts\constructionutil.lua
    C'est ce script qui gère les constructions dans le jeu.
    Comme ce script est nécessaire, je déclare, au début de mon fichier .con la variable locale:


    local constructionutil = require "constructionutil"


    Cela indique que le script "constructionutil.lua" sera utilisé.


    Ce qui nous intéresse dans ce script c'est la fonction qui gère le stock de marchandises.
    Cette fonction est:


    function constructionutil.makeStocks(config, result)


    Cette fonction nécessite de définir 3 variables :
    result.stocks = { }
    result.stockRules = { }
    result.groundFaces = { }


    La variable groudFaces est une liste des structures qui définissent le sol où les marchandises vont être entreposées.
    Nous la laisserons vide puisque nous possédons déjà une construction avec un sol défini par le fichier SB_LIDL.001.mdl.
    La fonction constructionutil.makeStocks() la complètera avec un sol délimité dans la zone exacte où nos marchandises seront entreposées avec la texture standard utilisée pour les dépôts de marchandises dans le jeu.
    Mais, vous pouvez très bien rajouter un sol à votre construction. Voici un exemple où le sol est rempli de gravillons comme la plupart des constructions de la ville.
    On utilise la texture "town_concrete" que vous trouverez dans :
    \res\config\groud_texture\town_concrete.lua
    J'ai utilisé les coordonnées du bâtiment principal pour cette illustration. Mais vous pouvez définir d'autres coordonnées.



    Où vont être entreposées les marchandises?


    Ici, j'ai choisi de placer sur la droite du bâtiment l'aire de déchargement des marchandises.
    Je vais la matérialiser avec une texture au sol empruntée de la mine de charbon.
    Je rajoute donc dans la liste des modèles:


    {id = "industry/cargo/coal_small.mdl", transf = {4, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0.2, 0, -31.6, -2.5, 0, 1 } }


    Ce modèle a, comme vous le voyez une largeur de 4 m sur 19 m de long et sera placé à 0.2 m du sol.
    Je le déplace sur le côté gauche de l'immeuble à 31.60 mètres et de 2.5 m vers la rue principale (l'immeuble est regardé depuis l'arrière).
    Vous pouvez voir le résultat dans la Fig 3.



    J'ai aussi envie de voir quel type de marchandise va recevoir mon commerce au moment où l'on placera le bâtiment sur la carte et aussi durant le jeu.
    Plus tard, dans ce tuto, nous paramètrons le type de marchandise qu'attirera le magasin. Mais pour le moment, je vais amener vers mon magasin des denrées alimentaires (FOOD).
    Pour cela je vais ajouter un troisième modèle dans la liste des modèles:


    {id = "industry/cargo/food_small.mdl", transf = { 0, -1.1, 0, 0, 1.1, 0, 0, 0, 0, 0, 1.1, 0, 17, 4, 0.5, 1 } },


    J'ai agrandi de 10% la taille de ce modèle pour qu'il soit mieux visible (valeurs 1.1 dans la matrice 4x4).
    Je place ce modèle près de la porte d'entrée du magasin aux coordonnées (17,4,0.5).
    Si j'avais laissé les coordonnéées (0,0,0), le modèle serait placé dans le bâtiment principal et donc invisible de l'extérieur.
    Et finalement je fais tourner ce modèle de 90 degrés pour bien voir toutes les caisses. C'est pour cela que vous voyez le second élément de la liste transf avec la valeur -1.1 (voir annexe 2 à la fin de ce tuto)
    Vous pouvez voir le résultat sur la fig.1a


    J'ai donc maintenant mes 3 modèles: le bâtiment principal, le sol où les marchandises vont être stockées et le modèle de marchandises situé près de la porte d'entrée du magasin)
    Voici la liste complète des modèles:



    Lua
    result.models =
                {
                    {id = "SB_Lidl.001.mdl", transf = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 } },
                    {id = "industry/cargo/food_small.mdl", transf = { 0, -1.1, 0, 0, 1.1, 0, 0, 0, 0, 0, 1.1, 0, 17, 4, 0.5, 1 } },
                    {id = "industry/cargo/coal_small.mdl", transf = {4, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0.2, 0, -31.6, -2.5, 0, 1 } }
                }

    Nous pouvons enfin définir la gestion du stock en utilisant la fonction:




    La variable capacity = 2000 indique le nombre de marchandises qui transite dans notre construction. Il s'agit d'une quantité annuelle.


    la variable cargotype reprend le type de marchandise (ici "FOOD"), le type de transfert, ici "RECEIVING" puisque le commerce est destiné à recevoir des marchandises.
    On utilisera "SENDING" dans le cas d'une usine qui fabrique des produits qui seront envoyés vers une autre destination.


    x,y,z représentent les coordonnées de l'endroit où l'on veut placer les marchandises reçues ici ( -31.6,-2.0,0.5).


    Petite remarque:
    Une ligne de marchandises se compose de 4 rangées de 4 unités chacunes dont 2 rangées sont disposées de part et d'autre d'une ligne qui s'étire sur une longueur de 8 mètres.
    sizex est le nombre d'unités de longueur de 8 mètres et sizey est le nombre de lignes de marchandises.
    Ici, nous aurons 3 lignes de marchandises disposées de part et d'autre d'une ligne de 8 mètres de longueur.
    Ce qui nous fera 3 * (4 * 4) = 48 unités de marchandises maximales visibles sur l'aire de stockage.
    En fait, on peut avoir 2 hauteurs de marchandises par ligne, représentée par un container à la place des caisses.
    Ceci pour vous dire qu'il ne s'agit que d'une représentation sur la carte pour une question d'esthétique.


    Regardez la Fig 4 qui indique la positions des 3 lignes de marchandises et la Fig 5 qui montre le remplissage de ces lignes par des marchandises (matériaux de construction).



    Comme vous le constatez, la variable stocks est une liste, donc on peut avoir plusieurs types de marchandises.
    Par exemple, on pourrait très bien avoir des matériaux de construction en plus des denrées alimentaires. Mais ici je n'ai utilisé qu'un seul type de marchandises à la fois.


    stockRules définit comment le stock est géré.
    input représente la liste des marchandises entrantes et output la liste des marchandises sortantes.
    La règle d'écriture est la suivante:
    Dans les listes input et output on écrit le nombre de marchandises dans l'ordre de leur définition dans la liste stocks.
    Imaginons que nous ayons défini 3 types de marchandises, nous aurions 3 éléments contenus dans la liste stocks:
    stocks= {
    {cargotype = "FOOD", ...},
    {cargotype = "GOODS", ...},
    {cargotype = "PLANKS", ...},
    }
    Si on veut avoir seulement 1 "GOODS" en entrée, 2 "FOOD" et 1 "PLANKS" en sortie on écrira:
    stockRules = {{input = {{0,1,0}}, output = {{2,0,1}}}, capacity = ... }


    Remarquez bien qu'il faut définir les 3 types de marchandise dans les deux listes (input et output). La première valeur correspond au nombre de marchandise définie à la première ligne de stocks, la seconde à la seconde ligne et la troisième à la troisième ligne.


    Dans notre exemple, il n'y aura qu'une seule marchandise, donc input ne comportera qu'un seul élément {{1}} et output n'aura aussi qu'un seul élément nul {{0}} puisqu'il n'y a pas de marchandise qui sortira de notre construction.
    Donc, 1 unité de "FOOD" en entrée et 0 en sortie.


    Je vous conseille d'aller voir le fichier machines_factory.con dans:
    \res\construction\industry\machines_factory.con


    Ce fichier correspond à l'industrie de fabrication de machines-outils. Vous comprendrez pourquoi il faut 2 planches ou 1 acier pour fabriquer 1 outil et pourquoi il faut 2 planches et 1 acier ou 1 acier et 1 plastique pour fabriquer une machine.


    J'espère avoir été clair concernant la gestion du stock.
    Si tout a bien été programmé, vous devriez voir le résultat de vos efforts quelques minutes après avoir placé votre construction.
    N'oubliez pas:
    - de relier la construction à une rue qui est fréquentée par des piétons et voitures
    - d'avoir une usine agroalimentaire qui fonctionne et que les marchandises arrivent bien par camion ou train dans un dépôt situé à proximité de votre construction.


    Mais, ON PEUT ALLER ENCORE PLUS LOIN !
    C'est ce que nous verrons dans la troisième partie de ce tuto publiée également sur ce forum.



    Michel Lacoste.

    Michel Lacoste
    Belgium

    3 Mal editiert, zuletzt von mich.lacoste ()

  • Ceci est la troisième et dernière partie du tuto publié dans ce même forum


    Je vous rappelle que nous pouvons inclure des paramètres lors de la construction d'un bâtiment sur la carte.
    C'est ce que je vous propose de développer maintenant.


    Les paramètres de construction
    ------------------------------
    Je vous ai dit, au début de ce tuto qu'il était possible d'utiliser des paramètres de construction. Cela se fait avec la liste "params = {}".
    Lorsqu'on programme des paramètres dans cette liste, une boîte de dialogue s'ouvre lorsqu'on place la construction sur la carte et lorsqu'on veut modifier une construction déjà placée.
    Chaque paramètre est lui-même constitué d'une liste comprenant les éléments suivants:
    { key = "xxxx" où xxxx est le nom utilisé pour la variable de ce paramètre
    name = _("nom") où nom est le titre qui apparaîtra dans la boîte de dialogue
    values = {_("val1"),_("val2"),...,_("valn")} est une liste de valeurs qui apparaissent dans la boîte de dialogue et que le joueur peut sélectionner.
    defaultIndex = x où x est le numéro d'ordre de la liste des valeurs et qui sera mis en surbrillance par défaut dans la boîte de dialogue.
    }
    On peut utiliser autant de paramètres que l'on veut, mais sachez que plus il y en a plus cela pourrait devenir confus dans l'esprit du joueur.
    Tout comme pour les noms utilisés dans le jeu, je vous conseille de traduire les mots qui apparaissent dans la boîte de dialogue afin d'en faciliter la compréhension par le joueur.
    Je vous expliquerai en annexe 1 comment procéder pour traduire les mots. Sachez déjà que le principe est d'utiliser la syntaxe : _("mot") pour pouvoir traduire ce mot dans le fichier "strings.lua".


    Dans notre construction, je vais donner la possibilité aux joueurs de pouvoir choisir le nombre de clients qui fréquenteront, par mois, notre commerce.
    Ils pourront également choisir si la rue latérale peut être reliée d'un seul côté ou des deux côtés. Avec un seul côté, les véhicules devront faire demi-tour en haut de la rue alors qu'avec une liaison avant-arrière, ils pourront poursuivre leur route.
    Ils pourront aussi relier le haut de ce segment de route à un dépôt de marchandises.
    Une remarque à ce sujet.
    Si le joueur sélectionne l'option "avant-arrière" le segment de rue restera même si le bâtiment principal est détruit.
    En outre, il faudra détruire ce segment avant d'apporter une modification à une construction existante sinon le programme dira qu'il y a collision.
    Tout se passe donc comme si ce segment de route appartenait au réseau routier et non plus à la construction.
    Cela ne se produit pas si l'option "avant uniquement" est choisie.


    Le joueur pourra aussi choisir entre 3 types de marchandises ou pas de marchandise du tout (Denrées alimentaires, matériaux de construction, outils ou aucune marchandise)
    Enfin, il choisira la quantité annuelle maximale de marchandises pouvant entrer dans ce magasin (très faible, faible, moyenne, élevée, très élevée).


    Voici comment procéder:



    Maintenant que nous avons défini nos paramètres, comment les utiliser?


    Cela se fait dans updateFn:



    Je définis 4 variables locales qui me serviront dans la suite de mon script:


    numpeople = 0 -- variable de type integer qui contiendra le nombre mensuel de clients
    -- cette variable sera utilisée dans result.personCapacity
    numentree = {} -- variable de type list qui contiendra les noeuds (snapNodes) de liaison du segment de route latérale
    -- variable utilisée dans result.edgeLists
    capacount = 0 -- variable de type integer qui définit le nombre annuel de marchandises
    -- variable utilisée dans constructionutil.makeStocks
    idmdl = "" -- variable de type string qui contiendra le chemin d'accès au fichier modèle de la marchandise stockée
    -- variable utilisée dans result.models
    cartype = "NONE" -- variable de type string qui définira le type de marchandise
    -- variable utilisée dans constructionutil.makeStocks


    Vous pouvez voir le script complet dans le fichier lidl.con du module ML_Tuto2_1 que vous avez certainement déjà téléchargé sur ce site.
    Vous pouvez l'utiliser tel quel ou le modifier à votre guise!
    Ici se termine le tuto.
    On pourrait aller encore plus loin, par exemple en ajoutant des arrêts de bus sur le parking de ce magasin. Cela a été développé dans mon tuto 1 ("Création d'arrêts de bus dans une station") que vous retrouverez ici:
    https://www.transportfever.net…?postID=262884#post262884


    On pourrait aussi créer un dépôt de marchandises afin d'éviter de devoir placer un dépôt à proximité. Cela fera l'objet d'un autre tutoriel.


    Annexe 1 : Le fichier strings.lua


    L'avantage de TF c'est de pouvoir traduire les mots importants qui apparaissent dans le jeu, les menus et même dans la descriptions des mods.
    Cela se fait avec un fichier appelé "strings.lua" situé dans la racine du mod.
    Chaque fois que le programme rencontre une valeur de type _("mot"), il regarde d'abord dans sa base de données standard si ce mot existe et le traduit dans la langue du joueur.
    Si ce mot n'existe pas, il regarde dans ce fichier strings.lua et si ce fichier n'existe pas ou que ce mot n'y est pas repris, alors il affiche le "mot" directement.


    Pour ma part, j'utilise toujours un fichier strings.lua qui comporte un dictionnaire de 3 langues:
    le Français (Fr), qui est ma langue maternelle, l'Anglais (En) et l'Allemand (De).
    Rien ne vous empêche d'en utiliser d'autres.
    Ouvrez le fichier "strings.lua" de ce tuto (ML_tuto2_1) que vous pouvez télécharger sur ce site et vous comprendrez aisément comment on procède pour créer des dictionnaires.


    Annexe 2 : Transformation d'un modèle au moyen d'une matrice 4x4


    Je vais vous expliquer comment le jeu TF (et d'autres jeux qui utilisent les objets en 3D) emploie les matrices 4x4 pour effectuer toutes sortes d'opérations sur les objets en 3 dimensions.
    Je vais faire appel à des notions de mathématiques assez pointues, mais si cela vous rebute, retenez uniquement les grandes lignes de ce qui va suivre.


    Un objet en 3 dimensions, comme une construction par exemple, est construit au moyen d'un programme de modélisation 3D (par exemple, Blender).
    Chaque point de l'objet est placé dans un repère orthonormé euclidien à 3 dimensions (x,y,z) qui sont les coordonnées de ce point dans l'espace.
    Dans TF, ce sont les fichiers .mdl qui gèrent ces objets.


    Une fois qu'un objet est réalisé et programmé dans l'un de ces fichiers, il nous est toujours possible de les manipuler: les faire tourner, les déplacer ou encore modifier leurs dimensions.
    Mais vous comprenez bien que s'il fallait modifier chaque point un à un, ce serait trop fastidieux.
    Alors, on utilise une matrice que le programme va exploiter automatiquement pour tous les points de l'objet afin que chaque point soit manipulé de la même façon.
    Par exemple, si on veut faire tourner l'objet sur lui-même de 90 degrés, on crée une matrice qui fait cela et on applique cette matrice sur chacun des points de l'objet.
    Donc une seule programmation pour des miliers de points!


    Mais c'est quoi une matrice?


    C'est un tableau de valeurs que l'on représente entre deux grands crochets (ou parenthèses).
    Exemple de la matrice A comportant 2 lignes et 3 colonnes appelée aussi matrice 2x3:


    A=
    | 1 0 -7 |
    | 2 5 3 |



    Cette matrice comporte donc 6 éléments (3x2) appelés aussi coefficients.
    Chaque élément de la matrice représente une information, par exemple une valeur ou la position d'un objet.
    Ces éléments peuvent alors être traités facilement dans un programme informatique.
    On peut réaliser différentes opérations sur ces éléments (addition, soustraction, multiplication, etc...)


    Puisqu'il faut 3 coordonnées (x,y,z) pour définir un point dans l'espace, on pourrait se dire qu'une matrice 3x3 serait suffisante. Et bien non, car pour pouvoir programmer correctement un objet, nous avons besoin d'une dimension supplémentaire (w) afin de traiter les translations.
    Une translation est le déplacement d'un point vers un autre endroit de l'espace. C'est un vecteur qui possède une direction et une dimension.
    Regardez l'exmple ci-dessous (Fig. 6)


    J'ai représenté l'espace euclidien avec ses 3 axes de coordonnées (x,y,z). Ces axes définissent l'orientation de mon espace avec son origine commune et ses 3 directions.
    Le point "a" se situe aux coordonnées (-3,0,2) et le point "b" aux coordonnées (3,4,0). Le vecteur V qui a son origine au point a et son extrémité au point b possède une direction symbolisée par la flèche et une dimension qui est la longueur du segment entre le point a et le point b.
    Je vais vous expliquer comment on peut utiliser une matrice pour réaliser ce déplacement.


    Avec une quatrième coordonnée (w), on parle de coordonnées homogènes et on obtient une transformation "affine" lorsque cette coordonnée est égale à 1.
    Cela veut dire que les objets qui composent la construction héritent des valeurs de leurs parents. Ainsi, si l'on change la position d'un élément appartenant à un groupe d'objets, on change également la position de toutes les structures qui composent ce groupe.
    Pour passer des coordonnées euclidiennes d'un point P(x,y,z) aux coordonnées homogènes P(x,y,z,w) il suffit de poser w=1. Nous avons donc P(x,y,z,1).
    (Si w = 0 alors les points sont situés à l'infini).


    Voilà pourquoi on utilise une matrice 4x4 c'est-à-dire qui comporte 4 lignes et 4 colonnes.


    Pour manipuler les objets 3D en informatique, on utilise, une matrice 4x4, c'est-à-dire un tableau d'éléments qui comporte 4 lignes et colonnes:


    M=
    | M11 M12 M13 M14 |
    | M21 M22 M23 M24 |
    | M31 M32 M33 M34 |
    | M41 M42 M43 M44 |


    M11 est l'élément M de la ligne 1 et colonne 1
    M12 est l'élément M de la ligne 1 et colonne 2
    ...
    M34 est l'élément M de la ligne 3 et colonne 4
    etc...


    Puisque nous voulons avoir des coordonnées homogènes la dernière ligne doit comporter les éléments 0 0 0 1
    Donc la matrice M devient:


    M=
    | M11 M12 M13 M14 |
    | M21 M22 M23 M24 |
    | M31 M32 M33 M34 |
    | 0 0 0 1 |
    - -
    Dans TF on écrit cette matrice dans une liste:


    transf = {M11,M12,M13,M14,M21,M22,M23,M24,M31,M32,M33,M34,0,0,0,1}


    Lorsque le modèle inscrit dans le fichier .mdl est utilisé tel quel, c'est-à-dire sans transformation, alors la matrice 4x4 a la structure suivante:


    M=
    | 1 0 0 0 |
    | 0 1 0 0 |
    | 0 0 1 0 |
    | 0 0 0 1 |


    ou transf = {1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}


    Vous remarquerez que les éléments de la diagonale allant de M11 à M44 ont pour valeur 1 et les autres 0. Cela veut dire que le modèle est de même taille que son original et est positionné exactement comme il a été défini dans le fichier .mdl.
    Les valeurs contenues dans la première ligne correspondent à l'axe des X, celles de la seconde ligne à l'axe des Y et celles de la troisième ligne à l'axe des Z.
    Les valeurs de la quatrième ligne ne changent pas dans TF de manière à garder les coordonnées homogènes d'une transformation affine.


    On peut effectuer des modifications du modèle original en modifiant la matrice M.
    Par exemple, si on attribue la valeur 2 à M11, l'objet sera 2 fois plus grand dans sa largeur (axe des X). C'est pareil si on change M22, on modifiera la longueur (axe des Y) et si on change M33 (axe des Z), on modifiera la hauteur de cet objet.


    Si on veut déplacer un modèle, on modifiera les valeurs x,y,z de la quatrième colonne (M14,M24,M34)
    Par exemple, si M14 = 5, le modèle se déplacera de 5 unités (5 mètres dans TF) par rapport à son point de départ dans le sens de l'axe des X (puisque nous utilisons une valeur positive).


    On peut aussi faire tourner le modèle autour de n'importe quel axe.
    Dans mon tuto j'ai fait tourner de 90° le modèle "food_small.mdl" de manière à voir l'empilement des caisses de marchandises correctement par rapport au bâtiment principal.
    Donc j'ai fait tourner de 90° le modèle dans le sens des aiguilles d'une montre (signe négatif) par rapport à l'axe vertical Z.
    Pour cela, la valeur M11 est 0 et la valeur M12 est -1.1
    Je vous égargnerai les calculs effectués pour arriver à ce résultat car cela fait appel à la trigonométrie (sinus et cosinus d'angle).
    En plus, comme j'ai agrandi de 10 % le modèle(1.1 pour les valeurs M11,M22,M33), et que le modèle a été déplacé par rapport à son point d'origine (M41=17,M42=4 et M43=0.5), il y a donc 3 transformations qui interviennent dans ce modèle.
    On doit alors faire appel au produit matriciel pour obtenir les valeurs de ces transformations.
    Heureusement, il existe un utilitaire en ligne réalisé par Xanos pour TF qui calcule toutes les transformations à votre place en un clin d'oeil! (merci à lui).


    Voici le lien : http://ftp.train-fever.net/transformation/


    Je reprends, à titre d'illustration, le calcul de la translation d'un point "a" vers le point "b" (comme expliqué plus haut à la Fig 6).


    Sur cette figure, vous voyez que le point a(-3,0,2) est déplacé vers le point b(3,4,0). Quelle est la matrice M qui permet de faire cette translation?


    b = M * a
    b = M * a
    |3| |1 0 0 6 | |-3|
    |4| |0 1 0 4 | | 0|
    |0| |0 0 1-2 | | 2|
    |1| |0 0 0 1 | | 1|


    Pour l'axe des X (M14) nous avons une translation de -3 à + 3, soit +6
    Pour l'axe des Y (M24) nous avons une translation de 0 à +4, soit +4
    Pour l'axe des Z (M34) nous avons une translation de 2 à 0, soit -2
    Comme il n'y a pas de modification de la taille, la diagonale M11,M22,M33 reste avec la valeur 1.
    La dernière ligne reste toujours inchangée afin de respecter la transformation affine et les autres éléments de la matrice restent à 0 puisqu'il n'y a pas de rotation.


    Voilà qui termine ce long tuto.
    J'espère avoir été clair et que vous pourrez, vous aussi, effectuer des modifications de constructions.


    Merci de votre attention.
    Michel Lacoste.

    Michel Lacoste
    Belgium

    Einmal editiert, zuletzt von mich.lacoste ()

BlueBrixx