Page 1 sur 3
[RESOLU] (& meme + :))un sprite qui se déplace vers un autre
Publié : mar. 08/mars/2011 23:33
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
Re: un sprite qui se déplace vers un autre
Publié : mer. 09/mars/2011 0:14
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
Re: un sprite qui se déplace vers un autre
Publié : mer. 09/mars/2011 7:23
par jbernard13
G-rom donne Moi des cours pour crée un jeux ... tu es trop fort .
Re: un sprite qui se déplace vers un autre
Publié : mer. 09/mars/2011 8:39
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

Re: un sprite qui se déplace vers un autre
Publié : mer. 09/mars/2011 12:26
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...
Enfantin, non ?

Re: un sprite qui se déplace vers un autre
Publié : mer. 09/mars/2011 12:41
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...
Enfantin, non ?

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)
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
Re: un sprite qui se déplace vers un autre
Publié : mer. 09/mars/2011 13:52
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.
Re: un sprite qui se déplace vers un autre
Publié : mer. 09/mars/2011 14:01
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)
Re: un sprite qui se déplace vers un autre
Publié : mer. 09/mars/2011 15:04
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
Re: un sprite qui se déplace vers un autre
Publié : mer. 09/mars/2011 16:07
par Cool Dji
Manque juste un lien sur les fichiers de sprite et ça pourra compiler...

Re: un sprite qui se déplace vers un autre
Publié : mer. 09/mars/2011 16:17
par blendman
Cool Dji a écrit :Manque juste un lien sur les fichiers de sprite et ça pourra compiler...

les 2 sprites, c'est juste 2 bêtes losanges (n'importe quel sprite irait en fait

)
mais les voici :

Re: un sprite qui se déplace vers un autre
Publié : mer. 09/mars/2011 16:26
par Cool Dji
Ben kektafoutu ?
ça se déplace pas en ligne droite !!
C'est plus compliqué en ligne droite
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...
Re: un sprite qui se déplace vers un autre
Publié : mer. 09/mars/2011 16:43
par blendman
Cool Dji a écrit :Ben kektafoutu ?
ça se déplace pas en ligne droite !!
C'est plus compliqué en ligne droite
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

Re: un sprite qui se déplace vers un autre
Publié : mer. 09/mars/2011 16:49
par Cool Dji
Wouai, bon ça va
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 !!
Re: un sprite qui se déplace vers un autre
Publié : mer. 09/mars/2011 16:55
par blendman
Cool Dji a écrit :Wouai, bon ça va
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
