[jeu]ennemis et sorts de magie (collision)

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

[jeu]ennemis et sorts de magie (collision)

Message par blendman »

Salut

Dans Mon jeu Arkeos chronicle, j'ai :
- des ennemis que je peux combattre (en leur envoyant des sorts de magie (boule de feu, cercle de feu..)
- des sorts que j'envoie pour combattre les monstres.

Je dispose de plusieurs types de sorts et parmi ceux-ci, j'ai des sorts dit "de groupe", autrement dit qui peuvent attaquer plusieurs ennemis en même temps.

J'ai donc une question pour ceux que cela intéressent :D :
- comment pensez-vous que je doive gérer les monstres et les sorts

Je vérifie déjà plusieurs le tableau des monstres (avec une boucle) et je me dis que faire encore une boucle sur le même tableau est un peu une perte de performance j'ai l'impression.



Pour le moment, j'ai créé un tableau pour les monstres, et une liste pour les sorts.
Lorsque je clique droit, j'ajoute un élément à cette liste (avec plein de paramètres).

J'ai donc le choix entre :
1) commencer une boucle sur les sorts, puis tester la collision avec chaque monstre
- faire une boucle pour chaque sorts
- vérifier le type de sort
- si c'est un sort de groupe, faire une boucle pour chaque ennemi
- vérifier la collision : sort/ennemi
- si collision => action du sort
2) commencer une boucle sur les monstres, puis tester la collision avec chaque sort
- faire une boucle pour chaque monstre
- faire une boucle pour chaque sorts
- vérifier la collision : sort/ennemi
- vérifier le type de sort
- si c'est un sort de groupe
- si collision => action du sort sur le monstre

Le problème est que je dois mettre un délai sur ce sort sinon, ça enlève trop de vie d'un coup sur les mobs.
Autre problème : j'effectue déjà une boucle sur les monstres pour tester d'autres choses (déplacement, perte de vie, combat..).

En gros, voici un code (incomplet, mais je peux le compléter si besoin, c'est juste pour que vous voyez l'idée) :

Code : Tout sélectionner

;{ structures
Structure stSort
  sprite.w
  type.a ; sort d'attaque, de soin, téléportation...
  cible.a ; mobile, fixe, cible ennemi, cible player.; + = seul, - = de groupe.
  vie.w; durée de vie du sort
  degat.w
  ; position
  cible_pos.point
  x.w : y.w
EndStructure
Global NewList sort.stSort()

Structure stMonstre
  sprite.w
  ; caractéristique
  vie.w
  vie_max.w
  degat.w
  armure.w
  type.a ; 0 = normal, 1 = agressif, 10 = se retourne contre les autres mobs
  ; position
  cible.point
  x.w : y.w
  ; event
  eventId.w
EndStructure
Global Dim monstre.stMonstre(50); je crée 50 monstres

Structure StDrop
  id.w
  pos.point
  nb.a
EndStructure
Global NewList drop.StDrop()
;}

;{ procedures

Procedure.a Collision(Array monstre.stMonstre(1),i.a,List sort.stSort())
  If SpriteCollision(monstre(i)\sprite,monstre(i)\x,monstre(i)\y,sort()\sprite,sort()\x,sort()\y)    
    ProcedureReturn #True
  Else 
    ProcedureReturn #False
  EndIf  
EndProcedure

Procedure CheckSort(List sort.stSort(), Array monstre.stMonstre(1))
ForEach sort()
  Select sort()\type
      
    Case 1; attaque
      Select sort()\cible
        Case 1 ;mobile - boule de feu
          
        Case 2 ; fixe (cercle de feu, sort de groupe)
          For i =0 To 50
            If collision(monstre(),i, sort())
              monstre(i)\vie - sort()\degat
              ; if monstre(i)\vie <=0 etc...
            EndIf        
          Next i
      EndSelect
      
      
    Case 2 ; soin, ajout vie
      
    Case 3 ; ajout mana
      
    Case 4; invocation
      
    Case 5 ; téléportation
      
  EndSelect 
Next
EndProcedure

Procedure.w rnd(i.w)
  ProcedureReturn Random(i)-Random(i)
EndProcedure
 
Macro DropMob()
  AddElement(drop())  
  drop()\id =1
  drop()\nb = 1
  drop()\pos\x = monstre(i)+rnd(50)
EndMacro

Procedure AddEvent(id)
  ; on créé l'évènement si besoin
EndProcedure

Procedure MobDead(Array monstre.stMonstre(1),i.a)
  If monstre(i)\vie <=0
    Select monstre(i)\type
      Case 0,1,10 ; normal, agressif, retourné
        DropMob()
        monstre(i)\x = Random(1000)
        monstre(i)\y = Random(1000)
        monstre(i)\vie = monstre(i)\vie_max
        monstre(i)\type = 0
      Case 11 ; mob de quête
        AddEvent(monstre(i)\eventId)
    EndSelect    
  EndIf
EndProcedure

Macro SortType()
  Select sort()\type       
    Case 1; attaque
      monstre(i)\vie - sort()\degat
      MobDead(monstre(),i)
            
    Case 8; on retourne le monstre contre les autres monstres
      monstre(i)\type = 10
  EndSelect
EndMacro

Procedure CheckMob(List sort.stSort(),Array monstre.stMonstre(1))
  For i=0 To 50
    ;{ deplacement
    
    ;}
    ;{ cible sur la mob (clic droit dessus par exemple)
    
    ;}
    ;{ Combat
    If monstre(i)\vie <= 0    
      ;{ le mob meurt
      MobDead(monstre(),i)
      ;}      
    Else    
      ;{ on attaque le mob    
      If monstre(i)\vie < monstre(i)\vie_max Or monstre(i)\type =1
        ; combat, attaque joueur, etc..
        Select monstre(i)\type 
          Case 0 ; normal
            
          Case 1 ; agressif
            
          Case 10 ; attaque les autres mobs
            
        EndSelect        
      EndIf
      ;}     
      ;{ collision sort/mob
      ForEach sort()
        Select sort()\cible
            
          Case 1 ; mobile - boule de feu            
            If collision(monstre(),i, sort())              
              SortType()
              DeleteElement(sort(),1)
            EndIf
            
          Case 2 ; fixe (cercle de feu, sort de groupe)             
            If collision(monstre(),i, sort())               
              SortType()
            EndIf          
        EndSelect
      Next 
    EndIf;}
    ;}
  Next i  
EndProcedure
;}

InitSprite() : InitKeyboard() : InitSprite3D() :
OpenWindow(0, 0,0,1024,768, "", #PB_Window_SystemMenu|#PB_Window_MaximizeGadget|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0),0,0,1024,768,0,0,0)

Repeat
  ExamineKeyboard()
  event =WaitWindowEvent(10)
Until KeyboardPushed(#PB_Key_Escape) Or event = #PB_Event_CloseWindow
End


j'ai donc le choix de 2 techniques :
- CheckSort(List sort.stSort(), Array monstre.stMonstre(1))
- CheckMob(List sort.stSort(),Array monstre.stMonstre(1)))

- Soit je vérifie chaque sort, puis la collision avec chaque mob
- soit je vérifie chaque mob puis la collision avec chaque sort., en sachant que ce serait compris dans une boucle qui s'occupe déjà de vérfier certains paramètre de mob.

n'hésitez pas si vous une idée de la meilleure technique à adopter pour ça :D.
Avatar de l’utilisateur
Ar-S
Messages : 9540
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: [jeu]ennemis et sorts de magie (collision)

Message par Ar-S »

Pour un sort de "groupe" censé toucher plusieurs mobs, je ne pense pas que tu ais à utiliser plein de fois les collisions.
J'utiliserai plutôt la position des sprites par rapport à la position d'impact et l'air d'effet de ton sort.
Ainsi tout ennemi dans l'air d'impact recevrait des dégâts (avec possibilité de décrémenté le dégât en fonction de la distance de l'ennemi).
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: [jeu]ennemis et sorts de magie (collision)

Message par blendman »

c'est vrai que ça semble une meilleure idée, je vais tester ça :D

EDIT :

voici un petit code qui marche pas mal j'ai l'impression, si vous voulez tester, vous pourrez me dire ce que vous en pensez ;)

Code : Tout sélectionner

;{ structures
Structure stSort
  sprite.w
  type.a ; sort d'attaque, de soin, téléportation...
  cible.a ; mobile, fixe, cible ennemi, cible player.; + = seul, - = de groupe.
  vie.w; durée de vie du sort
  degat.w
  ; position
  cible_pos.point
  x.w : y.w
  timer.w
EndStructure


Structure stMonstre
  sprite.w
  ; caractéristique
  vie.w
  vie_max.w
  degat.w
  armure.w
  type.a ; 0 = normal, 1 = agressif, 10 = se retourne contre les autres mobs
  ; position
  cible.point
  x.w : y.w
  ; event
  eventId.w
EndStructure

Structure StDrop
  id.w
  pos.point
  nb.a
EndStructure

;}

;{ enumeration & variables
 #window = 0
Enumeration ; sprite 
  #mob
  #sort
  #sort2
  #drop
EndEnumeration

Global Gbmouse.a
;}


;{ procedures

;{ init
Procedure InitGame()
  ; init drawing mob
  CreateSprite(#mob,16,16,#PB_Sprite_Texture)
  CreateSprite3D(#mob,#mob)
  StartDrawing(SpriteOutput(#mob))
  Box(0,0,16,16,#Red)
  StopDrawing()
 ; init drawing sort
  CreateSprite(#sort,16,16,#PB_Sprite_Texture)
  CreateSprite3D(#sort,#sort)
  StartDrawing(SpriteOutput(#sort))
  Box(0,0,16,16,#White)
  StopDrawing()
; init drawing sort
  CreateSprite(#sort2,16,16,#PB_Sprite_Texture)
  CreateSprite3D(#sort2,#sort2)
  StartDrawing(SpriteOutput(#sort2))
  Box(0,0,16,16,#Blue)
  StopDrawing()
  
  Global Dim monstre.stMonstre(49); je crée 50 monstres
  For i =0 To 49
    With monstre(i)
      \sprite = #mob
      \x = Random(1000)
      \y = Random(768)
      \vie_max = 50
      \vie = \vie_max
    EndWith    
  Next i
  
  Global NewList drop.StDrop()
  Global NewList sort.stSort()
EndProcedure
;}

;{ event

;{ collision
Macro distance(mob,sort)   
   Sqr((sort\x - mob\x)*  (sort\x-mob\x) +  (sort\y-mob\y)* (sort\y-mob\y))         
EndMacro

Procedure.a Collision(Array monstre.stMonstre(1),i.a,List sort.stSort())
  If SpriteCollision(monstre(i)\sprite,monstre(i)\x,monstre(i)\y,sort()\sprite,sort()\x,sort()\y)  
    Debug "collision"
    ProcedureReturn #True
  Else 
    ProcedureReturn #False
  EndIf  
EndProcedure
;}


Procedure CheckSort(List sort.stSort(), Array monstre.stMonstre(1))
ForEach sort()
  Select sort()\type
      
    Case 1; attaque
      Select sort()\cible
        Case 1 ;mobile - boule de feu
          
        Case 2 ; fixe (cercle de feu, sort de groupe)
          For i =0 To 49
            If collision(monstre(),i, sort())
              monstre(i)\vie - sort()\degat
              ; if monstre(i)\vie <=0 etc...
            EndIf        
          Next i
      EndSelect
      
      
    Case 2 ; soin, ajout vie
      
    Case 3 ; ajout mana
      
    Case 4; invocation
      
    Case 5 ; téléportation
      
  EndSelect 
Next
EndProcedure

Procedure.w rnd(i.w)
  ProcedureReturn Random(i)-Random(i)
EndProcedure
 
Macro DropMob()
  AddElement(drop())  
  drop()\id =1
  drop()\nb = 1
  drop()\pos\x = monstre(i)+rnd(50)
EndMacro

Procedure AddEvent(id)
  ; on créé l'évènement si besoin
EndProcedure

Procedure MobDead(Array monstre.stMonstre(1),i.a)
  If monstre(i)\vie <=0
    Select monstre(i)\type
      Case 0,1,10 ; normal, agressif, retourné
        DropMob()
        monstre(i)\x = Random(1000)
        monstre(i)\y = Random(1000)
        monstre(i)\vie = monstre(i)\vie_max
        monstre(i)\type = 0
      Case 11 ; mob de quête
        AddEvent(monstre(i)\eventId)
    EndSelect    
  EndIf
EndProcedure

Macro SortType()
  Select sort()\type       
    Case 1; attaque
      If sort()\timer <=0 Or sort()\cible =1
        sort()\timer = 200
        monstre(i)\vie - sort()\degat
        Debug monstre(i)\vie
        MobDead(monstre(),i)
      Else
        sort()\timer -1
      EndIf
            
    Case 8; on retourne le monstre contre les autres monstres
      monstre(i)\type = 10
  EndSelect
EndMacro

Procedure CheckMob(List sort.stSort(),Array monstre.stMonstre(1))
  For i=0 To 49
    ;{ deplacement
    
    ;}
    ;{ cible sur la mob (clic droit dessus par exemple)
    
    ;}
    ;{ Combat
    If monstre(i)\vie <= 0    
      ;{ le mob meurt
      MobDead(monstre(),i)
      ;}      
    Else    
      ;{ on attaque le mob    
      If monstre(i)\vie < monstre(i)\vie_max Or monstre(i)\type =1
        ; combat, attaque joueur, etc..
        Select monstre(i)\type 
          Case 0 ; normal
            
          Case 1 ; agressif
            
          Case 10 ; attaque les autres mobs
            
        EndSelect        
      EndIf
      ;}     
      ;{ collision sort/mob
      ForEach sort()
        Select sort()\cible
            
          Case 1 ; mobile - boule de feu            
            If collision(monstre(),i, sort())         
              SortType()
              DeleteElement(sort(),1)            
            EndIf
            
          Case 2 ; fixe (cercle de feu, sort de groupe)             
            If distance(monstre(i),sort())<200    
              SortType()
            EndIf          
        EndSelect
      Next 
    EndIf;}
    ;}
  Next i  
EndProcedure


Procedure AddSpell(List sort.stSort(),cible=1, sp=0)
  AddElement(sort())
  sort()\sprite =#sort+sp
  sort()\x = MouseX()
  sort()\y = MouseY()
  sort()\type = 1
  sort()\cible = cible
  sort()\degat = (cible-1) + 60*(2-cible)
  Debug sort()\degat
  sort()\timer = 100
EndProcedure

Procedure EventGame()
  ExamineMouse()
  If MouseButton(#PB_MouseButton_Left) 
    If Gbmouse= 0
      Gbmouse =1
      AddSpell(sort())
    EndIf
  Else
    Gbmouse = 0
  EndIf  
  If MouseButton(#PB_MouseButton_Right) 
    If Gbmouse= 0
      Gbmouse =1
      AddSpell(sort(),2,1)
    EndIf
  Else
    Gbmouse = 0
  EndIf  
 CheckMob(sort(),monstre())
EndProcedure

;}

;{ draw
Procedure Affichage()
  ClearScreen(0)
  Start3D()
  For i =0 To 49
    DisplaySprite3D(#mob,monstre(i)\x,monstre(i)\y)
  Next i
  ForEach sort()
    DisplaySprite3D(sort()\sprite,sort()\x,sort()\y)
  Next  
  Stop3D()
  
  StartDrawing(ScreenOutput())
  DrawingMode(#PB_2DDrawing_Transparent)
  For i =0 To 49
    DrawText(monstre(i)\x,monstre(i)\y,Str(monstre(i)\vie),#White)
  Next i
  StopDrawing()
  FlipBuffers()
EndProcedure
;}
;}

InitSprite() : InitKeyboard() : InitSprite3D() : InitMouse()
OpenWindow(#window, 0,0,1024,768, "", #PB_Window_SystemMenu|#PB_Window_MaximizeGadget|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(#window),0,0,1024,768,0,0,0)
ShowCursor_(1)
InitGame()

Repeat
  ExamineKeyboard()
  event =WindowEvent()
  Delay(1) 
  EventGame()
  Affichage()
Until KeyboardPushed(#PB_Key_Escape) Or event = #PB_Event_CloseWindow
End
Avatar de l’utilisateur
Cool Dji
Messages : 1126
Inscription : ven. 05/sept./2008 11:42
Localisation : Besançon
Contact :

Re: [jeu]ennemis et sorts de magie (collision)

Message par Cool Dji »

Yep, d'ac avec Ar-S, c'est une bonne idée qu'elle est bonne !

Tu peux même faire diminuer l'efficacité du sort :
- avec la distance entre ton héros et l'ennemi
- le nombre d'ennemis déjà atteint par le sort (tu réparti la puissance du sort entre les ennemis qui seront touchés)

ex : pour un sort niveau 100, il n'y a qu'un seul ennemi
L'ennemi se prend toute la puissance du sort (proportionnement à la distance au héros)

ex : pour un sort niveau 100, il n'y a 3 ennemis
Tu répartis la puissance 100 entre les 3 ennemis en fonction de leur distance respective au héros
le plus proche s'en prendra plus dans la tête que le plus éloigné...mais chacun s'en prendra un peu

Ou sinon tu donnes tout le sort au plus proche et rien pour les autres
ou, comme à l'école des fans, tout le monde attrape le même niveau de sort

Amuses-toi bien !!
Only PureBasic makes it possible
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: [jeu]ennemis et sorts de magie (collision)

Message par blendman »

oui, ça ouvre plein de possibilités c'est clair :).
Je suis en train de tester ingame et ça me semble prometteur
Avatar de l’utilisateur
Ar-S
Messages : 9540
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: [jeu]ennemis et sorts de magie (collision)

Message par Ar-S »

:mrgreen: :mrgreen: :mrgreen: :mrgreen: Nous aussi on veut tester ingame :mrgreen: :mrgreen: :mrgreen: :mrgreen:

ton type.a ; 0 = normal, 1 = agressif, 10 = se retourne contre les autres mobs
Un type 11 pour mode folie :?: (se retournerait contre amis/ennemis, genre de mode bersek)
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: [jeu]ennemis et sorts de magie (collision)

Message par blendman »

Ar-S a écrit :Nous aussi on veut tester ingame
ton type.a ; 0 = normal, 1 = agressif, 10 = se retourne contre les autres mobs
Un type 11 pour mode folie :?: (se retournerait contre amis/ennemis, genre de mode bersek)
en gros, il attaquerait au hasard un personnage ou un autre ennemi ?
Faut voir comment faire ça.

J'ai déjà pensé à ces types-ci :
0 : normal
1 : agressif (attaque le joueur tout seul, sans qu'on l'ait attaqué)
2 : chef : il a des bonus (degats, armure..°
3 : protecteur : protège les autres si on les attaque
4 : peureux : fuit quand on l'attaque

10 : se retourne contre les autres mobs (avec un de nos sorts)
Avatar de l’utilisateur
Ar-S
Messages : 9540
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: [jeu]ennemis et sorts de magie (collision)

Message par Ar-S »

blendman a écrit :en gros, il attaquerait au hasard un personnage ou un autre ennemi ?

Je dirai un mélange du 1 et du 4
un mode "survivor" ou le plus important pour le mob est que personne ne s'approche de lui, il attaquerait tout ce qui est à moins de x pixels
Ce comportement pourrait être déclenché par un assaut qui dure ou une blessure grave mélé à un sort de "peur" (si tu en prévois un)
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Répondre