FANDOM


Ajouter des ennemisModifier

Maintenant que nous pouvons bouger, tourner et tirer, nous allons ajouter des ennemis sur qui tirer !

L'ajout des ennemis dans le jeux se fera de la même façon que pour nos projectiles : nous allons définir notre ennemi et son comportement dans une scène préfabriquée puis instancier cette scène dans notre scène principale au besoin.

Création de notre ennemi préfabriqué :Modifier

Commencer par créer une nouvelle scène nommée "Prefab_ennemi", ajouter un objet en (0,0,0), associez-y un modèle (encore un cube dans mon cas, avec une texture différente) et pour finir associez-y un nouveau script nommé « ennemi_IA ». Ce sera l'intelligence artificielle de notre ennemi.

A défaut de véritable intelligence, notre ennemi se déplacera toujours droit vers le joueur.

Dans le script ennemi_IA, commençons par récupérer notre objet joueur dans le Awake():

self.target = CraftStudio.FindGameObject( "Cube" )

On définit une vitesse de déplacement :

self.speed = 0.3

Puis dans le update on a juste à orienter et à faire avancer notre ennemi vers sa cible :

local targetPos = self.target.transform:GetPosition()

self.gameObject.transform:LookAt( targetPos )
self.gameObject.transform:MoveOriented( Vector3:Forward()*self.speed )


Créations des ennemis :Modifier

Il nous reste à faire apparaître nos ennemis: Dans dans la scène principale « jeu », sur l'objet « map » ajouter un nouveau script « gestion_ennemis » Dans le Awake() on va commencer par créer un nouvel objet "Ennemies" (notez bien le "s" à la fin ! ) qui contiendra tout les ennemis que nous allons créer par la suite. Ceci nous permettra de les retrouver facilement par la suite.

self.ennemiesRoot = CraftStudio.CreateGameObject( "Ennemies" )

Puis dans le Update on ajoute notre nouvel ennemi avec comme parent l'objet créé précédemment :

CraftStudio.AppendScene( CraftStudio.FindAsset( "Prefab_ennemi" ), self.ennemiesRoot )

Ceci va donc créer un nouvel ennemi ... à chaque cycle. Ça risque de faire beaucoup ! On va ajouter un délai pour créer un ennemi toute les 5 secondes :

function Behavior:Awake()
   self.ennemiesRoot = CraftStudio.CreateGameObject( "Ennemies" )
   self.spawntimer = 0
end

function Behavior:Update()
   self.spawntimer = self.spawntimer+1
   
   if self.spawntimer == 60*5 then  
       CraftStudio.AppendScene( CraftStudio.FindAsset( "Prefab_ennemi" ), self.ennemiesRoot )
       self.spawntimer = 0
   end

end

Lancer votre jeu et testez. Au bout de 5 seconde, un ennemi doit apparaître.... dans le sol, puis se diriger vers le joueur et le suivre.

Nous allons modifier la création de nos ennemis pour qu'ils apparaissent toujours à une certaine distance du joueur. Dans le awake() on commence par définir une distance où apparaître :

self.spawnDist = 10

Puis dans le Update(), on récupère la positon du joueur :

  local targetPos = self.target.transform:GetPosition()

Et on définit la position où apparaître en décalant la position du joueur vers le nord. Puis on repositionne notre ennemi :

  self.spawPos = targetPos + Vector3:Forward()*self.spawnDist
  self.gameObject.transform:SetPosition( self.spawPos )

Lancez, testez.

Les ennemis apparaissent maintenant toujours à la même position par rapport au joueur (vers le haut puisque que l'on a utilisé Vector3:Forward(). )

On va donc ajouter un peu de hasard à l'aide d'un générateur de nombres aléatoire.

Le générateur fait partie de l'objet "math" et a besoin d’être initialisé par la méthode math.randomseed( seed ). La seed (graine en anglais) est une valeur à partir de laquelle les prochains nombres seront générés. Une même seed donne toujours la même séquence de nombres (notre générateur est en réalité "pseudo-aléatoire") Afin d'avoir une partie différente à chaque fois, nous allons utiliser l'heure comme seed :

math.randomseed(os.time())

On va utiliser notre générateur pour choisir un angle au hasard entre 0 et 360 degrés :

local angle = math.random( 0, 359 )

Ensuite on fait tourner notre vecteur Foward de l'angle trouvé avec : Vector3.Transform( Vector3:Forward(), quaternion de rotation)

Notre quaternion de rotation est un objet mathématique qui décrit la rotation. On le définit à partir de l'angle de rotation et de l'axe autour duquel tourner (axe Y vers le haut): Quaternion:FromAxisAngle( Vector3:Up(), angle ) La position de départ devient :

self.spawPos = targetPos + Vector3.Transform( Vector3:Forward(), Quaternion:FromAxisAngle( Vector3:Up(), angle ) ) * SPAWN_DISTANCE

Script complet :Modifier

Gest_ennemies :

function Behavior:Awake()
    math.randomseed(os.time())
    self.enemiesRoot = CraftStudio.CreateGameObject( "Enemies" )
    self.spawntimer = 0
end

function Behavior:Update()
    self.spawntimer = self.spawntimer+1

    if self.spawntimer == 60*5 then  
        CraftStudio.AppendScene( CraftStudio.FindAsset( "prefab_ennemis1" ), self.enemiesRoot )
        self.spawntimer = 0
    end
end


Ennemi_AI :

function Behavior:Awake()
   self.speed = 0.03
   self.target = CraftStudio.FindGameObject( "Cube" ) --cible à suivre

   --gestion de l'apparition   
   self.spawnDist = 10 --distance d'apparition

   local angle = math.random( 0, 359 )
   local targetPos = self.target.transform:GetPosition()

   self.spawPos = targetPos + Vector3.Transform( Vector3:Forward(), Quaternion:FromAxisAngle( Vector3:Up(), angle ) ) * self.spawnDist

   self.gameObject.transform:SetPosition( self.spawPos )
end

function Behavior:Update()
   --gestion du mouvement
   local targetPos = self.target.transform:GetPosition()
   self.gameObject.transform:LookAt( targetPos )
   self.gameObject.transform:MoveOriented( Vector3:Forward()*self.speed )
end

Tuer les ennemis...Modifier

Maintenant que nos ennemis sont la, il va falloir leur tirer dessus !

Pour ça on va devoir déterminer quand un projectile percute un ennemi puis détruire le projectile et l'ennemi.

Ici, nous allons faire en sorte que ce soit le projectile qui détecte sa collision avec un ennemis, mais notez que l'on pourrais tous à fait faire l'inverse. Il existe plusieurs techniques plus ou moins compliquées pour détecter les collisions entre deux objets. Ici nous allons utiliser la plus simple et la moins précise : la détection de distance.

Dans notre script "bullet" qui gère notre projectile, nous allons donc passer en revue tous les ennemis existants. Pour chaque ennemi, on va vérifier à quel distance il se trouve du projectile. Dans le Update(), on commence d'abord par récupérer la liste des ennemis présents ,souvenez vous que nous les avons délibérément tous placés dans le même objet parent "Ennemies". On récupère donc les enfants de l'objet "Ennemies" :

local enemies = CraftStudio.FindGameObject( "Enemies" ):GetChildren()

On récupére aussi la position actuelle de notre projectile :


local pos = self.gameObject.transform:GetPosition()

Ensuite, on utilise une boucle "for" pour parcourir la liste des ennemis :


for i=1,#enemies do 

    local enemy = enemies[i] 

end

Puis, dans notre boucle for, on va déterminer la distance entre la position du projectile et celle de l'ennemi (enemy.transform:GetPosition()) en utilisant la fonction :


[Number] Vector3.Distance( [Vector3] v1, [Vector3] v2 )


qui nous donne la distance entre deux points. Si cette distance est inférieur au rayon de notre ennemi, alors c'est qu'il est touché. Ici notre ennemi est un cube de 1 de coté, je vais donc considérer son rayon égal à 0.5. (Evidemment les collisions obtenues ne serons pas parfaites, mais c'est un début) On test donc notre collision avec :


if Vector3.Distance( enemy.transform:GetPosition(), pos ) < 0.5 then 


end

Et si il y à collision on détruit notre projectile :


CraftStudio.Destroy( self.gameObject )

Il ne nous reste plus qu'a détruire l'ennemis touché. On pourrais tout fait le faire depuis le script attaché au projectile, mais par principe, il vaux mieux modifier un objet uniquement depuis un script attaché a celui-ci. Cette règle n'est évidement pas absolue, mais elle vous permettra de mieux vous y retrouver lorsque votre projet grossira.

Dans le script attaché à notre ennemi "Ennemi_IA", on va donc crée une nouvelle fonction (une "méthode" pour être exacte):

function Behavior:Damage( )

end

Cette fonction définira ce qui se passe lorsque notre ennemi est touché. Nous allons pour le moment simplement la remplir avec :


CraftStudio.Destroy( self.gameObject )


Pour détruire notre ennemi dés qu'il est touché.

Notre méthode Damage() peu être appelée depuis le script "Ennemi_IA" par self:Damage() ou depuis un autre script a l'aide de la fonction :


GameObject:SendMessage( [string] nom de la méthode, [table] données )

Ici, l'objet concerné sera l'ennemi touché (la variable local "enemy"), la méthode sera "Damage" et les données serons ce que nous voulons passer en paramètre à notre méthode (rien pour le moment, mais cela pourrais nous servir à définir les dommages de notre arme par exemple). On obtient donc :


enemy:SendMessage( "Damage",nil)

On obtient le script complet de notre ennemi :

function Behavior:Awake()

  self.speed = 0.03
  self.target = CraftStudio.FindGameObject( "Cube" ) --cible à suivre

  --gestion de l'apparition   
  self.spawnDist = 10 --distance d'apparition
 
  math.randomseed(os.time())
  local angle = math.random( 0, 359 )
  local targetPos = self.target.transform:GetPosition()

  self.spawPos = targetPos + Vector3.Transform( Vector3:Forward(), Quaternion:FromAxisAngle( Vector3:Up(), angle ) ) * self.spawnDist
   
  self.gameObject.transform:SetPosition( self.spawPos )

end

function Behavior:Update()

  --gestion du mouvement
  local targetPos = self.target.transform:GetPosition()

  self.gameObject.transform:LookAt( targetPos )
  self.gameObject.transform:MoveOriented( Vector3:Forward()*self.speed ) 

end


--Fonction appelée lors d'une colision avec une bullet
function Behavior:Damage( )
   print ("ai")
   CraftStudio.Destroy( self.gameObject ) 
end

Et celui de "bullet" :

function Behavior:Awake()

   self.speed = 0.5
   self.MaxLife = 20
   self.source = CraftStudio.FindGameObject( "Cube" )
   
   --initialiser la position
   self.gameObject.transform:SetPosition (self.source.transform:GetPosition())
   self.gameObject.transform:SetOrientation (self.source.transform:GetOrientation())
   
   --initialiser durée de vie
   self.life = 0

end

function Behavior:Update()

  --gestion déplacement
  self.gameObject.transform:MoveOriented( Vector3:Forward()*self.speed ) 
  
  --gestion durée de vie
  self.life = self.life +1
  if self.life > self.MaxLife then
       CraftStudio.Destroy( self.gameObject ) 
  end
  
  --gestion colisions
  local enemies = CraftStudio.FindGameObject( "Enemies" ):GetChildren()
  local pos = self.gameObject.transform:GetPosition()
  
  for i=1,#enemies do
      local enemy = enemies[i]
                        
      if Vector3.Distance( enemy.transform:GetPosition(), pos ) < 0.5 then
           enemy:SendMessage( "Damage",nil)
           CraftStudio.Destroy( self.gameObject ) 
      end
  end

end

Gagner des points Modifier

Maintenant que nous pouvons détruire les ennemis, nous allons ajouter une gestion du score : Dans le script de gestion du personnage, on commence par ajouter une variable qui stockera notre score : self.score = 0

On va également crée un méthode pour ajouter des points. Celle-ci prend en paramètre le nombre de point à ajouter et se contente d'ajouter celui-ci au score actuel puis de l'afficher dans la fenêtre de debug :

function Behavior:AddPoint(point)
   self.score = self.score + point
   print ("Vous avez "..self.score.." points")
end

Il nous reste a définir le moment ou les points serons ajoutés. Ce sera nos ennemis au moment de mourir qui accorderons les points au joueur. Donc dans le script "Ennemi_AI" on ajoute une propriété de script (dans le bandeau en haut du script) afin de pouvoir définir le nombre point donné au joueur lors de sa mort. Appelons la "ScoreWhenKilled", défini comme un nombre avec 1 comme valeur par défaut. Ensuite dans la fonction Damage() de "Ennemi_AI" on ajoute la ligne :


self.target:SendMessage( "AddPoint",self.ScoreWhenKilled)

Ainsi le contenu de la propriété ScoreWhenKill, sera passé en paramètre à la fonction "AddPoint" et donc ajouté au score du joueur.

Et se faire tuerModifier

Maintenant que l'on peu tuer les ennemis, on va faire en sorte de pouvoir se faire tuer. On va utiliser le même principe que pour les collisions entre projectiles et ennemis. Dans le Update() du script "ennemi_AI" on ajoute un test de collisions similaire à celui des projectiles.:

local direction = targetPos - self.gameObject.transform:GetPosition()
local distance = direction:Length()
 
if distance < 1 then
       self.target:SendMessage( "Damage",nil)
       CraftStudio.Destroy( self.gameObject )
end


Puis on crée un méthode "Damage" dans le script attaché au joueur pour gérer se qui se passe lorsque q'un ennemi touche le joueur:

function Behavior:Damage( ) 

    CraftStudio.LoadScene (CraftStudio.FindAsset("menu")) 

end

Lancez votre jeux et vérifier que si le l'ennemi vous touche, le jeu reviens au menu principal.

C'est un peu brutal non ? On va ajouter une barre de vie à notre personnage : dans le script attaché au personnage principal ajoutez dans le awake() :


self.life = 10


Dans le script "ennemi_AI" on va définir combien de points de vie fait perdre cet ennemi s'il touche le joueur. Afin de pouvoir modifier cette valeur facilement si on crée plusieurs type d'ennemis différent, on va le crée en tant que propriété de script . On joute donc une propriété au script "ennemi_AI" nommé "power", ce sera un nombre avec 1 comme valeur par défaut.

Dans ce même script modifiez la partie appelée lors d'une collision avec le joueur pour avoir : 

self.target:SendMessage( "Damage",self.power)

On va maintenant modifier notre méthode "Damage()" du script du joueur pour faire baisser ce niveau de vie à chaque contact avec un ennemi. Au début de la fonction on ajoute donc :


self.life = self.life -damage

On va également ajouter un ligne afin d'afficher les points de vie restants dans la fenêtre de debug :


print ("il vous reste "..self.life.."points de vie")

Et finalement on ajoute pour retourner au menu:

if self.life <= 0 then

   CraftStudio.LoadScene (CraftStudio.FindAsset("menu"))

end

Script complet : Joueur :

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()

   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)

   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
    
   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 

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")

end


Ennemi :

function Behavior:Awake()

  self.speed = 0.03
  self.radius = 1
  self.target = CraftStudio.FindGameObject( "Cube" ) --cible à suivre

  --gestion de l'apparition   
  self.spawnDist = 10 --distance d'apparition
 
  math.randomseed(os.time())
  local angle = math.random( 0, 359 )
  local targetPos = self.target.transform:GetPosition()

  self.spawPos = targetPos + Vector3.Transform( Vector3:Forward(), Quaternion:FromAxisAngle( Vector3:Up(), angle ) ) * self.spawnDist
   
  self.gameObject.transform:SetPosition( self.spawPos )

end

function Behavior:Update()

  --gestion du mouvement
  local targetPos = self.target.transform:GetPosition()

  self.gameObject.transform:LookAt( targetPos )
  self.gameObject.transform:MoveOriented( Vector3:Forward()*self.speed )
  
  --gestion collisions avec le joueur
  local direction = targetPos - self.gameObject.transform:GetPosition()
       
  local distance = direction:Length()
  if distance < 1 then
       self.target:SendMessage( "Damage",self.power)
       CraftStudio.Destroy( self.gameObject ) 
  end

end

--Fonction appelée lors d'une colision avec une bullet
function Behavior:Damage( )

   self.target:SendMessage( "AddPoint",self.ScoreWhenKill)
   CraftStudio.Destroy( self.gameObject )

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