MadWar

Programmation avancée de jeux en PureBasic
Avatar de l’utilisateur
Cool Dji
Messages : 1126
Inscription : ven. 05/sept./2008 11:42
Localisation : Besançon
Contact :

MadWar

Message par Cool Dji »

Hello,

Je me lance dans la réalisation d'un jeu de guerre en 2D avec gestion de troupes.

Première étape : les troupes se déplacent (pas très bien) sans se chevaucher.

Le principe : je déplace les soldats les uns après les autres (du plus proche au plus éloigné de la cible) s'ils ne sont pas en collision avec un soldat déjà déplacé.
Si c'est le cas, ils attendent que la place soit libre devant eux pour avancer.
Pour éviter que les soldats restent bloqués trop longtemps j'ai posé une variable qui fait varier l'angle de déplacement en fonction du nombre de soldats bloqués

Je suis déjà bien content du premier code produit qui reste néanmoins pas très performant car les déplacements tremblotent un peu (variation aléatoire du déplacement).
Il faut que je corrige en ne faisant varier l'angle de déplacement uniquement aux soldats bloqués...

Code : Tout sélectionner

InitSprite()
InitMouse()
InitKeyboard()



;----- Ouvre un Screen Plein écran
ExamineDesktops()
ScreenWidth=DesktopWidth(0)
ScreenHeight=DesktopHeight(0)
Global DeltaX.f=ScreenWidth/1024
Global DeltaY.f=ScreenHeight/768
Global FSF0, alea,nbcontact
Global Dim Sx.f(100),Dim Sy.f(100), Dim SoldatCalcul(100), Dim SoldatContact(100), Dim soldattris(100), Dim soldatdistance.f(100)
Global mouseX,mouseY

Procedure mousethread(flag.i) ; souris roccat, razer .....
   Static quit.i
   If flag
      Repeat
         If ExamineMouse()
            mouseX=MouseX()
            mouseY=MouseY()
         EndIf
         Delay(1)
      Until quit
      quit=#False
   Else
      If Not flag
         quit=#True
         While quit
            Delay(1)
         Wend
      EndIf
   EndIf
EndProcedure

; Pause les soldats en rang par 5
nbs=0  ; nombre de soldat
Repeat
  x=0
  Repeat
  nbs+1
  Sx(nbs)=x*13+500
  Sy(nbs)=y*13+500
  x+1
Until x=5 Or nbs=100
y+1
Until nbs=100

OpenScreen(ScreenWidth, ScreenHeight, 32, "")
thread=CreateThread(@mousethread(),#True)

; Sprite des soldats
CreateSprite(0,10,10,#PB_Sprite_AlphaBlending | #PB_Sprite_PixelCollision)
StartDrawing(SpriteOutput(0))
Circle(5,5,5,RGB(255,0,0))
StopDrawing()
TransparentSpriteColor(0,RGB(0,0,0))

; sprite de la cible
CreateSprite(1,2,2)
StartDrawing(SpriteOutput(1))
Box(0,0,2,2,RGB(255,255,0))
StopDrawing()


Repeat
  ExamineKeyboard()
  ;ExamineMouse()
  ClearScreen(RGB(0,0,0))

  ; etabli le déplacement pour rejoindre un point de contact
  ; procede de proche en proche
  ; recherche déjà le soldat le plus proche et déplace-le dans la bonne direction
  ; puis le suivant sans qu'il touche les soldats déjà déplacés...


  For j=1 To nbs
    SoldatCalcul(j)=0  ; les soldats n'ont pas été déplacés
    soldattris(j)=0
  ; soldatdistance(j)=Sqr((sx(j)-MouseX())*(sx(j)-MouseX()) + (sy(j)-MouseY())*(sy(j)-MouseY()))  ; calcul les distances
   soldatdistance(j)=Sqr((sx(j)-MouseX)*(sx(j)-MouseX) + (sy(j)-MouseY)*(sy(j)-MouseY))  ; calcul les distances
 
  Next
 
  ; trie les soldats du plus grand au proche au plus éloigné
  nbsoldattris=0
    Repeat
    nbsoldattris+1
  distance.f=9999  
  For j=1 To nbs
      If soldattris(j)=0 And soldatdistance(j)<distance
        distance=soldatdistance(j)
        proche=j  
      EndIf  
    Next
    soldattris(proche)=nbsoldattris
 Until nbsoldattris=nbs  
  
 nbsoldat=0
 alea=nbcontact  ; ajoute un alea directionnel proportionnel au nombre de soldats bloqués
 nbcontact=0
 Repeat
   nbsoldat+1
   
   soldatproche=0
   Repeat
     soldatproche+1
   Until soldattris(soldatproche)=nbsoldat
   
  ; calcul la trajectoire en ligne droite entre le soldat et la cible
  x2=MouseX
  y2=MouseY
  x1=sx(soldatproche)
  y1=sy(soldatproche)
  soldatcalcul(soldatproche)=1

  A.f = x1-x2
  b.f = y1-y2
  c.f = -Sqr(A*A+b*b)
  If Abs(c)>5
  If SoldatContact(soldatproche)=1
 
    Angle.f = ACos(A/c)*180/#PI+Random(alea)-alea/2   ; Determine l'angle directionnel du déplacement et ajoute un alea si les troupes sont bloquées
  Else
Angle.f = ACos(A/c)*180/#PI   ; Determine l'angle directionnel du déplacement et ajoute un alea si les troupes sont bloquées
  EndIf 
  SoldatContact(soldatproche)=0 
  If y1 < y2 : Angle=360-Angle : EndIf
  ; test si la place est prise
  sx(soldatproche)+2*Cos(Radian(angle))   ; calcul les nouvelles positions x et y du soldat
  sy(soldatproche)-2*Sin(Radian(angle))

  ; test si la place est libre
  ; => possibilité d'optimiser en mettant tous les soldats déjà déplacés dans un seul sprite pour faire 1 seul test de collision global
  contact=0
  For i=1 To nbs
    If  soldatcalcul(i)=1 And i<> soldatproche
      If SpritePixelCollision(0,sx(i),sy(i),0,sx(soldatproche),sy(soldatproche))<>0
        contact=1
        SoldatContact(soldatproche)=1
         nbcontact+1
      EndIf
    EndIf
  Next


  If contact=1             ; la place n'est pas libre, le soldat reprend sa place d'avant
    sx(soldatproche)=x1
    sy(soldatproche)=y1
  EndIf

  ;=> à creuser pour que le soldat cherche une autre place (variation d'angle pour contourner celui qui le gene...)

EndIf

  DisplayTransparentSprite(0,sx(soldatproche)-5,sy(soldatproche)-5)


Until nbsoldat=nbs


   DisplaySprite(1,MouseX-1,MouseY-1)


  FlipBuffers()

Until KeyboardPushed(#PB_Key_Escape)

KillThread(thread)
Dernière modification par Cool Dji le dim. 29/nov./2015 15:05, modifié 2 fois.
Only PureBasic makes it possible
Avatar de l’utilisateur
Ar-S
Messages : 9477
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: MadWar

Message par Ar-S »

Excepté que ma souris rame à mort surement due à l'éternel bug de la gestion de certaines souris haut dpi (RAT5), j'adore comme les sprites se déplacent.
Comme tu l'as dit ils saccadent un poil mais c'est déjà excellent, ça fait banc de poissons.
~~~~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
Huitbit
Messages : 939
Inscription : jeu. 08/déc./2005 5:19
Localisation : Guadeloupe

Re: MadWar

Message par Huitbit »

Hello,

Ar-S, je te rassure, ce n'est pas ta souris !

@Cool Dji
Très intéressant, mais si tu prends 500 sprites (voir 1000), ça va ramer encore plus.

J'avais fait quelques tests(il y avait RotateSprite() pour chaque sprite en plus) , il y a longtemps, la meilleure solution que j'avais trouvée, c'était sans SpriteCollision() et sans calculs de distances (beaucoup trop gourmand).

D'ailleurs pour la distance, tu peux te contenter du carré (la racine carré bouffe encore des ressources)

Voilà la méthode essayée:
Le décor correspondait avec un tableau dont les cases étaient de la taille des sprites (ou un peu plus petites), si les coordonnées (arrondies à la valeur entière la plus proche)correspondaient à celles d'une case, la case était dite "occupée" et le déplacement dessus était impossible tant que le sprite n'était pas parti.
Pour déplacer les sprites, il suffisait de contrôler l'état de la case dans la direction souhaitée.

J'avais lu que pour les jeux où il y a beaucoup de troupes en mouvement, ils "trichent" en remplaçant des paquets de sprites (20 soldats par exemple ou plus) par un seul animé.

Bref en résumé, à mon avis, les calculs de distances et les collisions, ça sera toujours trop gourmand à moins que tu trouves des astuces (ce qui est tout à fait envisageable).

En tout cas, ce genre de jeu fait partie de mes projets (peut-être un futur Punch :roll: !)


Hasta la vista !
Elevé au MSX !
Patrick88
Messages : 1564
Inscription : mer. 21/janv./2004 18:24

Re: MadWar

Message par Patrick88 »

"cannon fodder" like ? :mrgreen:
Avatar de l’utilisateur
Cool Dji
Messages : 1126
Inscription : ven. 05/sept./2008 11:42
Localisation : Besançon
Contact :

Re: MadWar

Message par Cool Dji »

Merci les gars,

Ar-s : pour la souris, ce n'est pas la première fois que j'entends ce genre de pb. C'est lié à PureBasic ? On peut faire quelque chose pour améliorer ?

Huitbit : pas mal, l'idée du tableau, ça devrait être tout aussi efficace..

Patrick88 : Cannon Folder, je ne connaissais pas mais oui, un truc du genre avec peut-être les sprites de StarCraft...
Only PureBasic makes it possible
Avatar de l’utilisateur
Cool Dji
Messages : 1126
Inscription : ven. 05/sept./2008 11:42
Localisation : Besançon
Contact :

Re: MadWar

Message par Cool Dji »

Hop,

Première modification : seuls les soldats bloqués peuvent changer de direction. Il me semble que ça ne tremblote plus mais par contre je viens de tester sur l'ordi du boulot et c'est hyper saccadé...à la maison ça coulait comme de l'huile !
Only PureBasic makes it possible
Avatar de l’utilisateur
Ar-S
Messages : 9477
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: MadWar

Message par Ar-S »

Voilà un lien vers le soucis des souris. ça peut toujours servir.
http://www.purebasic.fr/french/viewtopi ... URIS+RAZER
~~~~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
venom
Messages : 3072
Inscription : jeu. 29/juil./2004 16:33
Localisation : Klyntar
Contact :

Re: MadWar

Message par venom »

Génial, bravo pour ce code fonctionnel Cool Dji 8)





@++
Windows 10 x64, PureBasic 5.73 x86 & x64
GPU : radeon HD6370M, CPU : p6200 2.13Ghz
Avatar de l’utilisateur
Cool Dji
Messages : 1126
Inscription : ven. 05/sept./2008 11:42
Localisation : Besançon
Contact :

Re: MadWar

Message par Cool Dji »

Merci pour tout,

J'ai modifié en intégrant un thread sur la souris : ça marche mieux ?

J'ai commencé à optimiser les calculs de déplacements.
Par la suite, je ne vais pas calculer l'orientation à chaque frame. Pour chaque soldat, son angle de déplacement sera mis à jour que quelques fois par seconde.

Pour le test de collision, je vais créer un sprite spécial qui sera l'agglomération de tous les soldats déjà déplacés : je n'aurai qu'un seul test de collision par soldat au lieu de factoriel(nombre de soldat)
Only PureBasic makes it possible
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: MadWar

Message par blendman »

sympa ce code :)

ça fonctionne pas mal, mais tu as oublié ça dans ta boucle principale : le double repeat

Code : Tout sélectionner

Repeat
    
    Repeat
        event = WaitWindowEvent(1)
    Until event = 0
        
  ExamineKeyboard()

; etc... le reste de ton code


Until KeyboardPushed(#PB_Key_Escape)
Avatar de l’utilisateur
Cool Dji
Messages : 1126
Inscription : ven. 05/sept./2008 11:42
Localisation : Besançon
Contact :

Re: MadWar

Message par Cool Dji »

Hello,

@BlendMan ; ça fait planter, j'ai du rater un truc, je regarde ce soir.

Sinon, ça commence à rendre un peu mieux avec des sprites de StarCraft...

http://www.jeuxvideobesancon.fr/Telecha ... MadWar.zip

Ce soir, je bosse sur les animations et sur le tir en approche de cible
Only PureBasic makes it possible
Avatar de l’utilisateur
Ar-S
Messages : 9477
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: MadWar

Message par Ar-S »

ça fonctionne nickel avec ma razer comme ça.
Par contre pense à stopper l'anim des sprites lorsqu'ils se regroupent contre le dot
~~~~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
Cool Dji
Messages : 1126
Inscription : ven. 05/sept./2008 11:42
Localisation : Besançon
Contact :

Re: MadWar

Message par Cool Dji »

Hello,

Merci Ar-S pour le retour souris :D

Stopage des soldtats activé...
http://www.jeuxvideobesancon.fr/Telecha ... oldier.zip

Le code est brouillon, je mets au propre par la suite
Only PureBasic makes it possible
Avatar de l’utilisateur
Cool Dji
Messages : 1126
Inscription : ven. 05/sept./2008 11:42
Localisation : Besançon
Contact :

Re: MadWar

Message par Cool Dji »

Hop,

Avec un fond de StarCraft.

Image

Le cheminement des soldats est un peu light. J'ai rentré un chemin vite fait (succession de points à suivre).
Pour un pathFinding réaliste, je vais creuser un peu. je vais mixer entre topologie pré-établie et calcul temps-réel.
Le cheminement doit pouvoir s'adapter aux évolutions de la Map...
Only PureBasic makes it possible
Répondre