FANDOM


Nous avons presque un jeu complet ! Mais il manque quand même quelque chose : si avez déjà essayer d'exporter un projet et de le lancer à partir de son .exe, vous avez du vous rendre compte que la fenêtre de débug dans laquelle s'affiche les retours des commandes print() et les messages d'erreurs ne s’affichent pas. Celle-ci ne sert que durant le développement ! Nous allons donc devoir afficher les points de vie restants et le score sur l'écran de jeu : c'est ce qu'on appelle un HUD ( "Heads-up display" ou "affichage tête haute" en français)

Création du HUDModifier

Nous allons créer notre HUD dans une scène à part puis l'instancier dans la scène de jeu. Créez donc une nouvelle scène "HUD", ajoutez un objet avec une caméra (en 0,0,0) et passez-la en mode orthographique. Ainsi, elle ne rendra pas la perspective, notre HUD sera "plat".

Nous allons avoir besoin d'afficher deux choses :

  • Une barre de vie qui indiquera les points de vie restant au joueur


  • Du texte pour afficher le score du joueur

Création d'une barre de vieModifier

Créez un nouveau modèle, ajoutez un bloc de 128*16*1 (vous pouvez lui donner une couleur si vous le souhaitez) puis créer une nouvelle animation pour ce modèle. Nommez la "deplete" (réduire en anglais) et passer sa durée à 100 images.

Sur la première image, placez une image clef sur le décalage pivot et l'étirement sans rien changer.

Sur la dernière image, placez une image clef en changeant le décalage pivot en X à -64 (la moitié de la longueur de la barre) et l'étirement en X à 0

Si tous va bien vous devriez obtenir une animation de votre barre qui réduit petit à petit jusqu’à disparaître. Si vous n'y parvenez pas, allez dans le projet "Doomsday Carrot Rampage" et observez comment est construit le modèle "Healthbar" ou exportez-le et ajoutez-le dans votre projet.

Création de l'objet de texteModifier

CraftStudio ne propose pas encore d'outils pour afficher facilement du texte, on va donc utiliser une petite ruse permettant d'afficher n'importe quel texte très facilement.

Commencez par créer une nouvelle carte nommée "HUDmap" et ajoutez-y un nouveaux TileSet nommé "ASCIItable" de taille 16. 

Nous allons remplir notre tileset avec la table ASCII. La norme ASCII attribue à chaque caractère un nombre de 0 à 255 (http://www.ascii.cl/ ) ça tombe bien notre tileset peut contenir 256 blocs différent. Chaque bloc (numéroté de 0 à 255) correspondra à un caractère. Par exemple, le caractère "1" à pour code ASCII 49

Anno 16x16.png

Table ASCII pour un tileset de 16*16

. Donc le bloc d'ID 49 devra représenter un "1". On pourrait le faire à la main mais ce serais un peu fastidieux. Il est 

possible de trouver des tilseset avec la table ASCII toute prête. Vous pouvez utiliser la table ci contre, ou en récupérer une ici par exemple : http://dwarffortresswiki.org/index.php/Tileset_repository.

Il ne vous reste donc qu'a copier votre texture dans Craftsutio pour créer votre tileset. Enfin, ajoutez une ligne de bloc horizontal partant du bloc en (0,0,0) pour pouvoir vous repérer plus facilement.

MapAscii.png

Notre carte prête à afficher du texte.

Retournez dans votre scéne "HUD", ajoutez un nouvel objet , nommé "healthbar", avec votre modéle de barre de vie, placez la en bas à droite par exemple. Créez un autre objet nommé "score", associez

ResultHUD.png

Mon HUD prêt à l'emploi

-y votre carte "HUDmap" et placez le en haut à gauche. Définissez votre scène comme scène principale pour pouvoir la lancer, visualisez le résultat et réglez la position et la taille des objets jusqu’à ce que cela vous plaise.


Intégrer le HUDModifier

Il nous faut maintenant intégrer notre scène "HUD" dans le jeu. Comme pour les ennemis et les projectiles, nous allons instancier notre nouvelle scène préfabriquée, mais cette fois-ci une seule fois et dés le lancement de notre jeu. 

Dans votre scène principale, associez un nouveau script à votre objet "Camera" et appelez le "init_HUD". Dans le Awake() on va instancier notre HUD avec :

CraftStudio.Instantiate( "HUD", CraftStudio.FindAsset( "HUD" ) )

Si vous lancez la scène vous devriez vous rendre compte qu'il y a un problème. En effet, la scène HUD contient une camera, donc lorsque qu'on l'instancie dans la scène "jeu" (qui en comporte également une), le jeu comporte alors deux caméras différente qui vont afficher des choses différente sur l'écran du jeu (on plutôt les même choses mais vus sous des angles différent). Pour remédier à cela nous allons simplement déplacer la scène HUD afin que les deux caméras ne "filment" pas la même chose. Le script "init_HUD" devient :

function Behavior:Awake()
   local HUD = CraftStudio.Instantiate( "HUD", CraftStudio.FindAsset( "HUD" ) )
   HUD.transform:SetPosition( Vector3:New( 10000, 10000, 10000 ) )
end


Mettre à jour les éléments du HUDModifier

Il ne nous reste plus qu'a faire en sorte que les éléments de notre HUD soient mis à jour en fonction des variables "self.life" et "self.score" de notre personnage. Nous allons une fois encore définir des méthodes propre aux objets du HUD et appeler ces méthodes depuis le script du joueur a l'aide de sendMessage().

Mettre à jour la barre de vieModifier

Retournez dans votre scène "HUD" et associez un nouveau script à votre barre de vie ("gest_heathbar").

Pour maîtriser l'état de notre barre de vie il va falloir gérer son animation. Toute les fonctions qui gère les animations d'un modèle s'applique à un composant de rendue de modèle. Dans le awake() du script de notre barre, on va donc commencer par récupérer ce composant :

self.model = self.gameObject:GetComponent( "ModelRenderer" )

Ensuite nous allons définir quelle sera l'animation à utiliser. Nous n'en avons crée qu'une seule "deplete", on la récupère donc avec CraftStudio.FindAsset( "deplete" ) et on la définie comme animation courante avec :

self.model:SetAnimation( CraftStudio.FindAsset( "deplete" ) )

Par défaut notre animation va tourner en boucle, nous voulons plutôt que celle ci soit bloquée sur une image fixe. Il nous suffit d'ajouter :

self.model:StopAnimationPlayback()

Notre animation sera donc bloquée sur la première image: celle ou la barre est pleine. Pour afficher notre barre plus ou moins vide, il nous suffit de changer le point ou l'animation est arrêtée. On va donc créer la méthode qui va mettre à jour notre barre :

function Behavior:Show(value) 

end

La fonction pour changer l'image que l'animation doit afficher est 'ModelRenderer:SetAnimationTime( [number] temps )'  ou la valeur à passer en paramètre correspond au moment de l'animation voulu. Ici notre animation est composée de 100 images, avec 30 images par secondes. Pour afficher la 50eme image d'une animation on utilisera donc : SetAnimationTime( 50 / 30 ). 

Ici notre niveau de vie varie entre 0 et 10, on va donc simplement la multiplier par 10 pour avoir une valeur entre 0 et 100. Si le niveau de vie est à 3 (30%) on doit afficher la 70eme image (la barre au deux tiers vide) : 100 - 3*10. On obtient donc : 

self.model:SetAnimationTime( (100- value*10) / 30 )

Il nous reste juste à compléter la méthode Damage() de notre joueur pour appeler notre nouvelle méthode "Show()" :

self.bar = CraftStudio.FindGameObject( "healthbar" )
self.bar:SendMessage( "Show",self.life)


Mettre à jour le scoreModifier

De la même façon, associez un nouveau script "gest_score" à votre objet "score".

Ce script va manipuler le composant "carte" de notre objet. On peut le récupérer simplement avec la fonction GetMap() du composant "MapRenderer" :

self.map = self.gameObject:GetComponent("MapRenderer"):GetMap()

On crée notre fonction de mise à jour :

function Behavior:Show(value)


end

Il va falloir afficher le contenu de la variable "value" en modifiant les blocs affichés dans la carte. On peut modifier les blocs d'une carte avec la fonction Map:SetBlockAt( [number] x, [number] y, [number] z, [number] block id, [BlockOrientation] orientation ).

On va traiter les caractères de notre variable un à un grâce à une boucle for :

for i=1,string.len(value) do

end

"i" sera donc l'index du caractère en cours de traitement. L'ID du bloc à placer dans la carte corresponds au caractère ASCII de ce caractère. On va utiliser la fonction LUA "string.byte(value,i) " qui renvoit le code ASCII du "i-éme" caractère de la chaîne "value". L'orientation des blocs sera celle par défaut (Map.BlockOrientation.North). On obtient donc :

for i=1,string.len(value) do
    local char = string.byte(value,i) 
    self.map:SetBlockAt( i, 0, 0, char, Map.BlockOrientation.North )
end

On va ajouter un peu de texte avant notre score. Ajoutez dans le Awake()

self.texte = "Score :"
self:Show (0)

Et modifiez la méthode Show pour obtenir : 

function Behavior:Show(value)
    self.output = self.texte..value

    for i=1,string.len(self.output) do
        local char = string.byte(self.output,i) 
        self.map:SetBlockAt( i, 0, 0, char, Map.BlockOrientation.North )
    end   
end

Ainsi le score du joueur sera toujours précédé du texte :"Score :" Il ne nous reste plus qu'a compléter la méthode AddPiont de notre joueur pour appeler la méthode Show de l'objet "score" :

self.TextScore = CraftStudio.FindGameObject( "score" )
self.TextScore:SendMessage( "Show",self.score)

(Il se peut que le texte ne s'affiche pas correctement si vos blocs de repère dans votre carte "HUDmap" sont mal placés...) Et voila ! Vous avez déjà un bon point de départ pour créer vos propre jeux. Nous n'avons pas utilisé toute les fonctions de l'API de Crafstudio, n'hésitez pas à consulter la référence de scripting pour compléter vos connaissances.   Script complet :

gest_perso

function Behavior:Awake()
    self.vitesse = 0.05
    self.life = 10
    self.score = 0

    self.groundPlane = Plane:New( Vector3:Up(), -1 )
    self.viseur = CraftStudio.FindGameObject( "viseur" )
    self.cameraComponent = CraftStudio.FindGameObject( "Camera" ):GetComponent( "Camera" )
    self.bulletPrefab = CraftStudio.FindAsset( "prefab_bullet" )
end

function Behavior:Update()
    --gestion des déplacements
    local horizontal = CraftStudio.Input.GetAxisValue( "Horizontal" )
    local vertical = CraftStudio.Input.GetAxisValue( "Vertical" )

    local mouvement = Vector3:New( horizontal, 0, -vertical )
    mouvement = mouvement * self.vitesse

    self.gameObject.transform:Move (mouvement)

    --gestion de l'orientation
    local mousePos = CraftStudio.Input.GetMousePosition()
    local mouseRay = self.cameraComponent:CreateRay( mousePos )
    local distance = mouseRay:IntersectsPlane( self.groundPlane )

    if distance ~= nil then
            local targetPos = mouseRay.position + mouseRay.direction * distance
            self.viseur.transform:SetPosition( targetPos )
            self.gameObject.transform:LookAt( targetPos )
    end
    
    --gestion des tirs
    if CraftStudio.Input.IsButtonDown( "Fire" ) then
        CraftStudio.Instantiate("bullet",self.bulletPrefab)
    end
end


--Fonction appelée lors d'une colision avec un ennemi
function Behavior:Damage(damage)
    self.life = self.life -damage
    print ("il vous reste "..self.life.."points de vie")

    if self.life <= 0 then
        CraftStudio.LoadScene (CraftStudio.FindAsset("menu"))
    end 

    --gestion affichage vie
    self.bar = CraftStudio.FindGameObject( "healthbar" )
    self.bar:SendMessage( "Show",self.life)
end

--Fonction appelée lorsque le joueur tu un ennemi
function Behavior:AddPoint(point)
    self.score = self.score + point
    print ("Vous avez "..self.score.." points")
    
    self.TextScore = CraftStudio.FindGameObject( "score" )
    self.TextScore:SendMessage( "Show",self.score)
end


gest_heathbar

function Behavior:Awake()
    self.model = self.gameObject:GetComponent( "ModelRenderer" )
    self.model:SetAnimation( CraftStudio.FindAsset( "deplete" ) )
    self.model:StopAnimationPlayback()
end

function Behavior:Update()

end

function Behavior:Show(value) 
   self.model:SetAnimationTime( (100- value*10) / 30 )
end


gest_score

function Behavior:Awake()
    self.map = self.gameObject:GetComponent("MapRenderer"):GetMap()
    self.texte = "Score :"
    self:Show (0)
end

function Behavior:Update()

end

function Behavior:Show(value)
    self.output = self.texte..value

    for i=1,string.len(self.output) do
        local char = string.byte(self.output,i) 
        self.map:SetBlockAt( i, 0, 0, char, Map.BlockOrientation.North )
    end   
end

Interférence d'un bloqueur de publicité détectée !


Wikia est un site gratuit qui compte sur les revenus de la publicité. L'expérience des lecteurs utilisant des bloqueurs de publicité est différente

Wikia n'est pas accessible si vous avez fait d'autres modifications. Supprimez les règles personnalisées de votre bloqueur de publicité, et la page se chargera comme prévu.

Sur le réseau FANDOM

Wiki au hasard