[RESOLU] (& meme + :))un sprite qui se déplace vers un autre

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

[RESOLU] (& meme + :))un sprite qui se déplace vers un autre

Message par blendman »

salut

Je cherche la technique pour faire qu'un sprite se déplace en ligne vers un autre.

Un exemple :
- un magicien lance une boule de feu vers un ennemi.

Je ne sais pas trop comment faire ça. J'ai réussi si ce n'est pas une ligne droite.

Merci
Dernière modification par blendman le mer. 23/mars/2011 9:27, modifié 1 fois.
G-Rom
Messages : 3641
Inscription : dim. 10/janv./2010 5:29

Re: un sprite qui se déplace vers un autre

Message par G-Rom »

Code : Tout sélectionner

; Cpl.Bator
; PureBasic 4.10
CompilerIf #PB_Compiler_OS = #PB_OS_Linux
  Structure point
    x.f
    y.f
  EndStructure
CompilerEndIf

#SW=800
#SH=600

InitSprite() : InitKeyboard() : InitMouse()
OpenScreen(#SW,#SH,32,"")



;-Structures
Structure VECTOR2
  x.f
  y.f
EndStructure

Structure ENTITY
  Position.VECTOR2
  Angle.f
EndStructure


;-Declarations des fonctions
Declare DrawArrow(Lenght.l , x.f , y.f , Angle.f)
Declare.f curveangle(newangle.f,oldangle.f,increments.f)
Declare.f ReturnDegAngle(x1.f,y1.f,x2.f,y2.f)
Declare track_SmoothPoint(*A.ENTITY,*B.ENTITY, turnspeed.f=1.0)



; ************************************************************************************
#NB_ARROW = 3
Dim Arrow.ENTITY(#NB_ARROW)

For i = 1 To #NB_ARROW
  Arrow(i)\Position\x = Random(#SW)
  Arrow(i)\Position\y = Random(#SH)
  Arrow(i)\Angle      = 0
Next
; ************************************************************************************


; Cible des "arrow" , coordonées de la souris pour la position
Target.ENTITY



CompilerIf #PB_Compiler_OS = #PB_OS_Linux
  KeyboardMode(#PB_Keyboard_International)
CompilerEndIf


Repeat
  
ExamineMouse()
ExamineKeyboard()
ClearScreen(0)

Target\Position\x = MouseX()
Target\Position\y = MouseY()

            StartDrawing(ScreenOutput())
                Circle(Target\Position\x,Target\Position\y,2,255)
            StopDrawing()


                For i = 1 To #NB_ARROW
                    DrawArrow(50 , Arrow(i)\Position\x , Arrow(i)\Position\y , Arrow(i)\Angle)
                    track_SmoothPoint(Arrow(i),Target,20)
                   
                    Arrow(i)\Position\x + 1 *Cos(Arrow(i)\Angle*#PI/180)
                    Arrow(i)\Position\y + 1 *Sin(Arrow(i)\Angle*#PI/180)
                Next



If KeyboardPushed(#PB_Key_Escape)<>#Null : Quit=1 : EndIf
FlipBuffers()
Until Quit=1
End




Procedure.f curveangle(newangle.f,oldangle.f,increments.f)
  If increments>1
    If (oldangle+360)-newangle<newangle-oldangle
      oldangle=360+oldangle
    EndIf
    If (newangle+360)-oldangle<oldangle-newangle
      newangle=360+newangle
    EndIf
    oldangle=oldangle-(oldangle-newangle)/increments
  EndIf
 
  If increments<=1
    ProcedureReturn newangle
  EndIf
  ProcedureReturn oldangle
EndProcedure


Procedure.f ReturnDegAngle(x1.f,y1.f,x2.f,y2.f) ; DEGREE
  A.f = x1-x2
  b.f = y1-y2
  c.f = -Sqr(A*A+b*b)
  Angle.f = ACos(A/c)*180/#PI
  If y1 < y2 : Angle=360-Angle : EndIf
  ProcedureReturn Abs(Angle - 360)
EndProcedure


Procedure track_SmoothPoint(*A.ENTITY,*B.ENTITY, turnspeed.f=1.0)
    AngDif = ReturnDegAngle(*A\position\x,*A\position\y,*B\position\x,*B\position\y)
    temp_yaw.f = curveangle(AngDif,*A\Angle,turnspeed)
    *A\Angle = temp_yaw
EndProcedure



Procedure DrawArrow(Lenght.l , x.f , y.f , Angle.f)

          Protected ArrowA.Point,ArrowB.Point
          Protected ArrowBranchA.Point,ArrowBranchB.Point
         
         
         
          ArrowA\x = x + (Lenght/2) * Cos(Angle*#PI/180)
          ArrowA\y = y + (Lenght/2) * Sin(Angle*#PI/180)
         
          ArrowB\x = x - (Lenght/2) * Cos(Angle*#PI/180)
          ArrowB\y = y - (Lenght/2) * Sin(Angle*#PI/180)
         
         
          ArrowBranchA\x = ArrowA\x - (Lenght/3) * Cos((Angle+45)*#PI/180)
          ArrowBranchA\y = ArrowA\y - (Lenght/3) * Sin((Angle+45)*#PI/180)
         
          ArrowBranchB\x = ArrowA\x - (Lenght/3) * Cos((Angle-45)*#PI/180)
          ArrowBranchB\y = ArrowA\y - (Lenght/3) * Sin((Angle-45)*#PI/180)
         
         
            StartDrawing(ScreenOutput())
                LineXY(ArrowA\x,ArrowA\y,ArrowB\x,ArrowB\y,255)
                LineXY(ArrowA\x,ArrowA\y,ArrowBranchA\x,ArrowBranchA\y,255)
                LineXY(ArrowA\x,ArrowA\y,ArrowBranchB\x,ArrowBranchB\y,255)
                Circle(x+1,y+1,2,255)
            StopDrawing()
EndProcedure
jbernard13
Messages : 1501
Inscription : dim. 18/avr./2004 15:04
Localisation : sud de la france

Re: un sprite qui se déplace vers un autre

Message par jbernard13 »

G-rom donne Moi des cours pour crée un jeux ... tu es trop fort .
Jbernard13
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: un sprite qui se déplace vers un autre

Message par blendman »

G-rom : merci pour ce code, il est très intéressant ;).
Maintenant, je vais le simplifier pour que lorsque l'objet arrive sur la cible, il disparaisse, et aussi pour qu'il se déplace uniquement en ligne droite :)
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: un sprite qui se déplace vers un autre

Message par djes »

Sinon le principe est celui de l'équation de droite, pour laquelle il existe trente six algos.
Le plus simple à mon avis (donc mon préféré, celui dont je me sers pour les tests, et avant optim) : si tu as une variable u.f qui va de 0 à 1, et deux points A et B, tu obtiens ta trajectoire comme ça...

Code : Tout sélectionner

x = u * (xB - xA)
y = u * (yB - yA)
Enfantin, non ? :mrgreen:
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: un sprite qui se déplace vers un autre

Message par blendman »

djes a écrit :Sinon le principe est celui de l'équation de droite, pour laquelle il existe trente six algos.
Le plus simple à mon avis (donc mon préféré, celui dont je me sers pour les tests, et avant optim) : si tu as une variable u.f qui va de 0 à 1, et deux points A et B, tu obtiens ta trajectoire comme ça...

Code : Tout sélectionner

x = u * (xB - xA)
y = u * (yB - yA)
Enfantin, non ? :mrgreen:
c'est quoi cette variable u ? la vitesse ?

Que dois-je faire si je veux que le sprite aille de A à B en ligne droite ? (en s'arrêtant à B) :D

EDIT : bon, j'ai testé ce code, normalement, ça devrait marcher :
(block() est une liste)
\vitese = 0 à la création de l'élément de la liste.

Code : Tout sélectionner

With block()      
      If \vitesse <=1
        \position\x  + \vitesse * (\cible\x - \position\x)
        \position\y  + \vitesse * (\cible\y - \position\y)
        \vitesse +0.1
      EndIf
endif     
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: un sprite qui se déplace vers un autre

Message par djes »

La vitesse, non, c'est plutôt la position entre A et B. À 0, tu es sur A, à 1, tu es sur B, à 0.5, tu es au milieu. Dans ton exemple, la vitesse est conditionnée par le 0.1, et elle varie suivant la distance entre A et B ; c'est pour ça que tu ne peux simplement utiliser cette formule si tu veux que la vitesse soit constante quels que soient les points de départ et d'arrivée.
G-Rom
Messages : 3641
Inscription : dim. 10/janv./2010 5:29

Re: un sprite qui se déplace vers un autre

Message par G-Rom »

il te manque quelques notions sur les vecteurs.
voici un petit code commenté de quoi t'éclairer sur le sujet , c'est la base.

@+

Code : Tout sélectionner

Structure Vector2
  x.f
  y.f
EndStructure


A.Vector2
B.Vector2


; Départ
A\x = 100
A\y = 100

;Arrivé
B\x = 650
B\y = 1450

;Direction
Direction.Vector2
; La direction se calcul entre soustrayant l'arrivé du départ
Direction\x = B\x - A\x
Direction\y = B\y - A\y

; Calcul de la longueur du vecteur Direction
Longueur.f = Sqr( Direction\x * Direction\x    +    Direction\y * Direction\y )
; Normalise le vecteur Direction ( Vecteur entre 0 & 1 )
If Longueur > 0
  Direction\x = Direction\x / Longueur
  Direction\y = Direction\y / Longueur
EndIf 

; Calcul de la nouvelle position :

vitesse.f = 3.5 ; Amuse toi à changer la valeur

NouvellePosition.Vector2
NouvellePosition\x = A\x + (Direction\x * vitesse)
NouvellePosition\y = A\y + (Direction\y * vitesse)

Debug "Depart en 100x100"
Debug ""
Debug "Vitesse = "+StrF(vitesse)
Debug ""
Debug "Nouveau X = " +StrF(NouvellePosition\x)
Debug "Nouveau Y = " +StrF(NouvellePosition\y)

Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: un sprite qui se déplace vers un autre

Message par blendman »

G-Rom a écrit :il te manque quelques notions sur les vecteurs. voici un petit code commenté de quoi t'éclairer sur le sujet , c'est la base.
salut G-rom

Effectivement, il me manque beaucoup de notions sur les vecteurs (disons que je les ai oublié).
Merci pour ton exemple, je vais le regarder et l'étudier de prêt, histoire de voir comment cela fonctionne ;).

djes a écrit :La vitesse, non, c'est plutôt la position entre A et B. À 0, tu es sur A, à 1, tu es sur B, à 0.5, tu es au milieu. Dans ton exemple, la vitesse est conditionnée par le 0.1, et elle varie suivant la distance entre A et B ; c'est pour ça que tu ne peux simplement utiliser cette formule si tu veux que la vitesse soit constante quels que soient les points de départ et d'arrivée.
j'ai enlevé la vitesse qui augmente et j'ai changé un paramètre (le previous\x et \y) et maintenant la vitesse est constante :).

Finalement, je suis moins une quiche que je ne le pensais lol.

Le code (ce qui a changé):

Code : Tout sélectionner

If ListSize(block()) <> 0 
    For i =0 To ListSize(block())-1
    If SelectElement(block(), i)   
        block()\position\x  + (block()\vitesse * (block()\cible\x - block()\previous\x))/100
        block()\position\y  + (block()\vitesse * (block()\cible\y - block()\previous\y))/100
      EndIf
    EndIf
    ChangeCurrentElement(block(),i)
et l'exemple complet :

Code : Tout sélectionner

;{******************** infos ******************
; code release mouse : netmaestro
;  le reste : ben, moi :)
; pb : 4.51
; déplacement de personnage (un clic and go de base) et lançage de sorts à la volée :)
;}


;{ ************************enumeration ***********************
Enumeration
#window
#player 
#block
EndEnumeration
#ScreenW = 800
#ScreenH = 600
;}

;{ ************************ variables ************************
Global vitesse= 3
Global inscreen = 1
Global mouseClic = 0
ShowCursor_(1)
;}

;{ ************************ Structures ************************

Structure s_block
  name.s
  position.Point
  previous.Point
  vitesse.f 
  cible.Point
  cible_ok.i
  sprite.i
EndStructure

Global NewList block.s_block()

Global Dim player.s_block(0)

player(0)\name = "player"
player(0)\position\x = 15
player(0)\position\y = 15
player(0)\previous\x = 15 
player(0)\previous\y = 15 
player(0)\vitesse = 3
player(0)\cible\x=15
player(0)\cible\y=15
player(0)\sprite = #player
player(0)\cible_ok=0
;}

;{ ************************ declare ***************************
Declare gestion_souris()
Declare evenementClavier()
Declare Player_move()
Declare affichage()
Declare instance_create()
Declare Sort_move()
;}

;{ ************************ inititialisation *****************
InitKeyboard () 
InitSprite()
InitSprite3D()
InitMouse()
UsePNGImageDecoder()
;}

;{ ************************ open window *********************

OpenWindow(#window, 0, 0,#ScreenW, #ScreenH, "Collision" , #PB_Window_SystemMenu|#PB_Window_BorderLess |#PB_Window_ScreenCentered )
OpenWindowedScreen( WindowID (#window),0,0, 800,600, 1, 0,0)

;}

;{ ************************ sprite et loading ***************

LoadSprite(#player,"col.png")
LoadSprite(#block,"blockCollision.png")

TransparentSpriteColor(#player,RGB(255,0,0))
TransparentSpriteColor(#block,RGB(255,0,0))
;}

;{ ************************ boucle principale ***************

Repeat

Event= WindowEvent ()

ExamineKeyboard ()
ExamineMouse()
gestion_souris()

affichage()
evenementClavier()
Player_move()

instance_create()
Sort_move()

; With block()
;       If SpritePixelCollision(#player,player(0)\position\x,player(0)\position\y,#block,\position\x,\position\y)
;             player(0)\vitesse =0
;             player(0)\position\x = \previous\x 
;             player(0)\position\y = \previous\y   
;           Else
;             player(0)\vitesse = 3
;       EndIf
; EndWith



FlipBuffers ()
ClearScreen (RGB (125,125,125)) 

Until Event= #PB_Event_CloseWindow Or KeyboardPushed ( #PB_Key_Escape ) 
;}

Procedure evenementClavier()
  If KeyboardPushed ( #PB_Key_Up )
     ForEach block()
         With block() 
           If \name = "player"
             \previous\y = \position\y
             \position\y - \vitesse
           EndIf
        EndWith 
      Next
  EndIf


If KeyboardPushed ( #PB_Key_Down )
     ForEach block()
         With block() 
           If \name = "player"
             \previous\y = \position\y
              \position\y + \vitesse
           EndIf
        EndWith 
      Next
EndIf


 If KeyboardPushed ( #PB_Key_Left )
     ForEach block()
   With block() 
     If \name = "player"
       \previous\x = \position\x
        \position\x - \vitesse
         EndIf
  EndWith 
Next
EndIf

If KeyboardPushed ( #PB_Key_Right )
    ForEach block()
      With block() 
           If \name = "player"
              \previous\x = \position\x
              \position\x +\vitesse       
          EndIf
      EndWith  
    Next
EndIf
EndProcedure

Procedure Player_move()
  If MouseButton(#PB_MouseButton_Left) =1 
        player(0)\cible_ok = 1
        player(0)\cible\x = MouseX()
        player(0)\cible\y = MouseY()
  EndIf

  With player(0)
    If \cible_ok = 1 And \name = "player"
      If \position\x < \cible\x
        \position\x + \vitesse
       ElseIf \position\x > \cible\x
         \position\x - \vitesse
      EndIf
      If \position\y < \cible\y
        \position\y + \vitesse/2
       ElseIf \position\y > \cible\y
         \position\y - \vitesse/2
       EndIf
     EndIf
   EndWith
EndProcedure

Procedure instance_create()  
  If MouseButton(#PB_MouseButton_Right) =1 And  mouseClic = 0
    mouseClic = 1
    vitesseSort = 0
    ;ClearList(block())
    AddElement(block())
      With block()
        \name = "block"
        \cible\x = MouseX()
        \cible\y = MouseY()
        \position\x = player(0)\position\x
        \position\y = player(0)\position\y
        \previous\x = player(0)\position\x
        \previous\y = player(0)\position\y
        \sprite = #block
        \vitesse = 2
      EndWith 
      nbre_element = ListSize(block())
     
ElseIf MouseButton(#PB_MouseButton_Right) =0
  mouseClic = 0
EndIf 
EndProcedure

Procedure gestion_souris() 
  mx = WindowMouseX(#window):my = WindowMouseY(#window)
  If inscreen = 1
        If mx> #ScreenW-2 Or my> #ScreenH-2 Or mx<1 Or my<1
          inscreen = 0
          ReleaseMouse(1)             
        EndIf     
  ElseIf mx <#ScreenW-1 And my < #ScreenH-1 And mx > 0 And my > 0 
      ReleaseMouse(0)
      MouseLocate(mx,my)
      inscreen = 1
  EndIf
EndProcedure

Procedure Sort_move()
   
  If ListSize(block()) <> 0 
    For i =0 To ListSize(block())-1
    If SelectElement(block(), i)    
        block()\position\x  + (block()\vitesse * (block()\cible\x - block()\previous\x))/100
        block()\position\y  + (block()\vitesse * (block()\cible\y - block()\previous\y))/100
    EndIf
    ChangeCurrentElement(block(),i)
    Next
 EndIf 
  EndProcedure


Procedure affichage()
  DisplayTransparentSprite(player(0)\sprite, player(0)\position\x, player(0)\position\y) 
  ForEach block()
    DisplayTransparentSprite(block()\sprite, block()\position\x, block()\position\y)  
  Next
EndProcedure
Avatar de l’utilisateur
Cool Dji
Messages : 1126
Inscription : ven. 05/sept./2008 11:42
Localisation : Besançon
Contact :

Re: un sprite qui se déplace vers un autre

Message par Cool Dji »

Manque juste un lien sur les fichiers de sprite et ça pourra compiler... :lol:
Only PureBasic makes it possible
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: un sprite qui se déplace vers un autre

Message par blendman »

Cool Dji a écrit :Manque juste un lien sur les fichiers de sprite et ça pourra compiler... :lol:
les 2 sprites, c'est juste 2 bêtes losanges (n'importe quel sprite irait en fait :))
mais les voici :
Image
Image
Avatar de l’utilisateur
Cool Dji
Messages : 1126
Inscription : ven. 05/sept./2008 11:42
Localisation : Besançon
Contact :

Re: un sprite qui se déplace vers un autre

Message par Cool Dji »

Ben kektafoutu ?
ça se déplace pas en ligne droite !!
C'est plus compliqué en ligne droite :mrgreen:

Faut reprendre le code de G-Rom.

A moins que tu souhaites garder ce type de déplacement, mais les déplacements vont pas être réalistes, surtout quand tu vas introduire des obstacles à éviter...
Only PureBasic makes it possible
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: un sprite qui se déplace vers un autre

Message par blendman »

Cool Dji a écrit :Ben kektafoutu ?
ça se déplace pas en ligne droite !!
C'est plus compliqué en ligne droite :mrgreen:

Faut reprendre le code de G-Rom.

A moins que tu souhaites garder ce type de déplacement, mais les déplacements vont pas être réalistes, surtout quand tu vas introduire des obstacles à éviter...
heu, c'est le sort qu'il faut regarder (clic droit, le losange rouge) pas le le losange bleu :D
Avatar de l’utilisateur
Cool Dji
Messages : 1126
Inscription : ven. 05/sept./2008 11:42
Localisation : Besançon
Contact :

Re: un sprite qui se déplace vers un autre

Message par Cool Dji »

Wouai, bon ça va :mrgreen: :mrgreen:

En revanche, ya un truc à améliorer : la vitesse de déplacement du sort est proportionnelle à l'éloignement de la cible par rapport au lancer => c'est pas bon, ça !!
Only PureBasic makes it possible
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: un sprite qui se déplace vers un autre

Message par blendman »

Cool Dji a écrit :Wouai, bon ça va :mrgreen: :mrgreen:

En revanche, ya un truc à améliorer : la vitesse de déplacement du sort est proportionnelle à l'éloignement de la cible par rapport au lancer => c'est pas bon, ça !!
oui, je sais c'est ce que j'essaie de corriger :) (en faisant en sorte que ce soit le plus simple possible) :)

Si tu as une idée, je suis preneur ;).

EDIT : je suis en train d'essayer d'intégrer l'exemple de G-rom pour voir si j'ai bien tout compris :D
Répondre